security/nss/cmd/signtool/verify.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

michael@0 1 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 2 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 3 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 4
michael@0 5 #include "signtool.h"
michael@0 6
michael@0 7
michael@0 8 static int jar_cb(int status, JAR *jar, const char *metafile,
michael@0 9 char *pathname, char *errortext);
michael@0 10 static int verify_global (JAR *jar);
michael@0 11
michael@0 12 /*************************************************************************
michael@0 13 *
michael@0 14 * V e r i f y J a r
michael@0 15 */
michael@0 16 int
michael@0 17 VerifyJar(char *filename)
michael@0 18 {
michael@0 19 FILE * fp;
michael@0 20
michael@0 21 int ret;
michael@0 22 int status;
michael@0 23 int failed = 0;
michael@0 24 char *err;
michael@0 25
michael@0 26 JAR * jar;
michael@0 27 JAR_Context * ctx;
michael@0 28
michael@0 29 JAR_Item * it;
michael@0 30
michael@0 31 jar = JAR_new();
michael@0 32
michael@0 33 if ((fp = fopen (filename, "r")) == NULL) {
michael@0 34 perror (filename);
michael@0 35 exit (ERRX);
michael@0 36 } else
michael@0 37 fclose (fp);
michael@0 38
michael@0 39 JAR_set_callback (JAR_CB_SIGNAL, jar, jar_cb);
michael@0 40
michael@0 41
michael@0 42 status = JAR_pass_archive (jar, jarArchGuess, filename, "some-url");
michael@0 43
michael@0 44 if (status < 0 || jar->valid < 0) {
michael@0 45 failed = 1;
michael@0 46 PR_fprintf(outputFD,
michael@0 47 "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
michael@0 48 filename);
michael@0 49 if (status < 0) {
michael@0 50 const char *errtext;
michael@0 51
michael@0 52 if (status >= JAR_BASE && status <= JAR_BASE_END) {
michael@0 53 errtext = JAR_get_error (status);
michael@0 54 } else {
michael@0 55 errtext = SECU_Strerror(PORT_GetError());
michael@0 56 }
michael@0 57
michael@0 58 PR_fprintf(outputFD, " (reported reason: %s)\n\n",
michael@0 59 errtext);
michael@0 60
michael@0 61 /* corrupt files should not have their contents listed */
michael@0 62
michael@0 63 if (status == JAR_ERR_CORRUPT)
michael@0 64 return - 1;
michael@0 65 }
michael@0 66 PR_fprintf(outputFD,
michael@0 67 "entries shown below will have their digests checked only.\n");
michael@0 68 jar->valid = 0;
michael@0 69 } else
michael@0 70 PR_fprintf(outputFD,
michael@0 71 "archive \"%s\" has passed crypto verification.\n", filename);
michael@0 72
michael@0 73 if (verify_global (jar))
michael@0 74 failed = 1;
michael@0 75
michael@0 76 PR_fprintf(outputFD, "\n");
michael@0 77 PR_fprintf(outputFD, "%16s %s\n", "status", "path");
michael@0 78 PR_fprintf(outputFD, "%16s %s\n", "------------", "-------------------");
michael@0 79
michael@0 80 ctx = JAR_find (jar, NULL, jarTypeMF);
michael@0 81
michael@0 82 while (JAR_find_next (ctx, &it) >= 0) {
michael@0 83 if (it && it->pathname) {
michael@0 84 rm_dash_r(TMP_OUTPUT);
michael@0 85 ret = JAR_verified_extract (jar, it->pathname, TMP_OUTPUT);
michael@0 86 /* if (ret < 0) printf ("error %d on %s\n", ret, it->pathname); */
michael@0 87 if (ret < 0)
michael@0 88 failed = 1;
michael@0 89
michael@0 90 if (ret == JAR_ERR_PNF)
michael@0 91 err = "NOT PRESENT";
michael@0 92 else if (ret == JAR_ERR_HASH)
michael@0 93 err = "HASH FAILED";
michael@0 94 else
michael@0 95 err = "NOT VERIFIED";
michael@0 96
michael@0 97 PR_fprintf(outputFD, "%16s %s\n",
michael@0 98 ret >= 0 ? "verified" : err, it->pathname);
michael@0 99
michael@0 100 if (ret != 0 && ret != JAR_ERR_PNF && ret != JAR_ERR_HASH)
michael@0 101 PR_fprintf(outputFD, " (reason: %s)\n",
michael@0 102 JAR_get_error (ret));
michael@0 103 }
michael@0 104 }
michael@0 105
michael@0 106 JAR_find_end (ctx);
michael@0 107
michael@0 108 if (status < 0 || jar->valid < 0) {
michael@0 109 failed = 1;
michael@0 110 PR_fprintf(outputFD,
michael@0 111 "\nNOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
michael@0 112 filename);
michael@0 113 give_help (status);
michael@0 114 }
michael@0 115
michael@0 116 JAR_destroy (jar);
michael@0 117
michael@0 118 if (failed)
michael@0 119 return - 1;
michael@0 120 return 0;
michael@0 121 }
michael@0 122
michael@0 123
michael@0 124 /***************************************************************************
michael@0 125 *
michael@0 126 * v e r i f y _ g l o b a l
michael@0 127 */
michael@0 128 static int
michael@0 129 verify_global (JAR *jar)
michael@0 130 {
michael@0 131 FILE * fp;
michael@0 132 JAR_Context * ctx;
michael@0 133 JAR_Item * it;
michael@0 134 JAR_Digest * globaldig;
michael@0 135 char * ext;
michael@0 136 unsigned char *md5_digest, *sha1_digest;
michael@0 137 unsigned int sha1_length, md5_length;
michael@0 138 int retval = 0;
michael@0 139 char buf [BUFSIZ];
michael@0 140
michael@0 141 ctx = JAR_find (jar, "*", jarTypePhy);
michael@0 142
michael@0 143 while (JAR_find_next (ctx, &it) >= 0) {
michael@0 144 if (!PORT_Strncmp (it->pathname, "META-INF", 8)) {
michael@0 145 for (ext = it->pathname; *ext; ext++)
michael@0 146 ;
michael@0 147 while (ext > it->pathname && *ext != '.')
michael@0 148 ext--;
michael@0 149
michael@0 150 if (verbosity >= 0) {
michael@0 151 if (!PORT_Strcasecmp (ext, ".rsa")) {
michael@0 152 PR_fprintf(outputFD, "found a RSA signature file: %s\n",
michael@0 153 it->pathname);
michael@0 154 }
michael@0 155
michael@0 156 if (!PORT_Strcasecmp (ext, ".dsa")) {
michael@0 157 PR_fprintf(outputFD, "found a DSA signature file: %s\n",
michael@0 158 it->pathname);
michael@0 159 }
michael@0 160
michael@0 161 if (!PORT_Strcasecmp (ext, ".mf")) {
michael@0 162 PR_fprintf(outputFD,
michael@0 163 "found a MF master manifest file: %s\n",
michael@0 164 it->pathname);
michael@0 165 }
michael@0 166 }
michael@0 167
michael@0 168 if (!PORT_Strcasecmp (ext, ".sf")) {
michael@0 169 if (verbosity >= 0) {
michael@0 170 PR_fprintf(outputFD,
michael@0 171 "found a SF signature manifest file: %s\n",
michael@0 172 it->pathname);
michael@0 173 }
michael@0 174
michael@0 175 rm_dash_r(TMP_OUTPUT);
michael@0 176 if (JAR_extract (jar, it->pathname, TMP_OUTPUT) < 0) {
michael@0 177 PR_fprintf(errorFD, "%s: error extracting %s\n",
michael@0 178 PROGRAM_NAME, it->pathname);
michael@0 179 errorCount++;
michael@0 180 retval = -1;
michael@0 181 continue;
michael@0 182 }
michael@0 183
michael@0 184 md5_digest = NULL;
michael@0 185 sha1_digest = NULL;
michael@0 186
michael@0 187 if ((fp = fopen (TMP_OUTPUT, "rb")) != NULL) {
michael@0 188 while (fgets (buf, BUFSIZ, fp)) {
michael@0 189 char *s;
michael@0 190
michael@0 191 if (*buf == 0 || *buf == '\n' || *buf == '\r')
michael@0 192 break;
michael@0 193
michael@0 194 for (s = buf; *s && *s != '\n' && *s != '\r'; s++)
michael@0 195 ;
michael@0 196 *s = 0;
michael@0 197
michael@0 198 if (!PORT_Strncmp (buf, "MD5-Digest: ", 12)) {
michael@0 199 md5_digest =
michael@0 200 ATOB_AsciiToData (buf + 12, &md5_length);
michael@0 201 }
michael@0 202 if (!PORT_Strncmp (buf, "SHA1-Digest: ", 13)) {
michael@0 203 sha1_digest =
michael@0 204 ATOB_AsciiToData (buf + 13, &sha1_length);
michael@0 205 }
michael@0 206 if (!PORT_Strncmp (buf, "SHA-Digest: ", 12)) {
michael@0 207 sha1_digest =
michael@0 208 ATOB_AsciiToData (buf + 12, &sha1_length);
michael@0 209 }
michael@0 210 }
michael@0 211
michael@0 212 globaldig = jar->globalmeta;
michael@0 213
michael@0 214 if (globaldig && md5_digest && verbosity >= 0) {
michael@0 215 PR_fprintf(outputFD,
michael@0 216 " md5 digest on global metainfo: %s\n",
michael@0 217 PORT_Memcmp(md5_digest, globaldig->md5, MD5_LENGTH)
michael@0 218 ? "no match" : "match");
michael@0 219 }
michael@0 220
michael@0 221 if (globaldig && sha1_digest && verbosity >= 0) {
michael@0 222 PR_fprintf(outputFD,
michael@0 223 " sha digest on global metainfo: %s\n",
michael@0 224 PORT_Memcmp(sha1_digest, globaldig->sha1, SHA1_LENGTH)
michael@0 225 ? "no match" : "match");
michael@0 226 }
michael@0 227
michael@0 228 if (globaldig == NULL && verbosity >= 0) {
michael@0 229 PR_fprintf(outputFD,
michael@0 230 "global metadigest is not available, strange.\n");
michael@0 231 }
michael@0 232
michael@0 233 fclose (fp);
michael@0 234 }
michael@0 235 }
michael@0 236 }
michael@0 237 }
michael@0 238
michael@0 239 JAR_find_end (ctx);
michael@0 240
michael@0 241 return retval;
michael@0 242 }
michael@0 243
michael@0 244
michael@0 245 /************************************************************************
michael@0 246 *
michael@0 247 * J a r W h o
michael@0 248 */
michael@0 249 int
michael@0 250 JarWho(char *filename)
michael@0 251 {
michael@0 252 FILE * fp;
michael@0 253
michael@0 254 JAR * jar;
michael@0 255 JAR_Context * ctx;
michael@0 256
michael@0 257 int status;
michael@0 258 int retval = 0;
michael@0 259
michael@0 260 JAR_Item * it;
michael@0 261 JAR_Cert * fing;
michael@0 262
michael@0 263 CERTCertificate * cert, *prev = NULL;
michael@0 264
michael@0 265 jar = JAR_new();
michael@0 266
michael@0 267 if ((fp = fopen (filename, "r")) == NULL) {
michael@0 268 perror (filename);
michael@0 269 exit (ERRX);
michael@0 270 }
michael@0 271 fclose (fp);
michael@0 272
michael@0 273 status = JAR_pass_archive (jar, jarArchGuess, filename, "some-url");
michael@0 274
michael@0 275 if (status < 0 || jar->valid < 0) {
michael@0 276 PR_fprintf(outputFD,
michael@0 277 "NOTE -- \"%s\" archive DID NOT PASS crypto verification.\n",
michael@0 278 filename);
michael@0 279 retval = -1;
michael@0 280 if (jar->valid < 0 || status != -1) {
michael@0 281 const char *errtext;
michael@0 282
michael@0 283 if (status >= JAR_BASE && status <= JAR_BASE_END) {
michael@0 284 errtext = JAR_get_error (status);
michael@0 285 } else {
michael@0 286 errtext = SECU_Strerror(PORT_GetError());
michael@0 287 }
michael@0 288
michael@0 289 PR_fprintf(outputFD, " (reported reason: %s)\n\n", errtext);
michael@0 290 }
michael@0 291 }
michael@0 292
michael@0 293 PR_fprintf(outputFD, "\nSigner information:\n\n");
michael@0 294
michael@0 295 ctx = JAR_find (jar, NULL, jarTypeSign);
michael@0 296
michael@0 297 while (JAR_find_next (ctx, &it) >= 0) {
michael@0 298 fing = (JAR_Cert * ) it->data;
michael@0 299 cert = fing->cert;
michael@0 300
michael@0 301 if (cert) {
michael@0 302 if (prev == cert)
michael@0 303 break;
michael@0 304
michael@0 305 if (cert->nickname)
michael@0 306 PR_fprintf(outputFD, "nickname: %s\n", cert->nickname);
michael@0 307 if (cert->subjectName)
michael@0 308 PR_fprintf(outputFD, "subject name: %s\n",
michael@0 309 cert->subjectName);
michael@0 310 if (cert->issuerName)
michael@0 311 PR_fprintf(outputFD, "issuer name: %s\n", cert->issuerName);
michael@0 312 } else {
michael@0 313 PR_fprintf(outputFD, "no certificate could be found\n");
michael@0 314 retval = -1;
michael@0 315 }
michael@0 316
michael@0 317 prev = cert;
michael@0 318 }
michael@0 319
michael@0 320 JAR_find_end (ctx);
michael@0 321
michael@0 322 JAR_destroy (jar);
michael@0 323 return retval;
michael@0 324 }
michael@0 325
michael@0 326
michael@0 327 /************************************************************************
michael@0 328 * j a r _ c b
michael@0 329 */
michael@0 330 static int jar_cb(int status, JAR *jar, const char *metafile,
michael@0 331 char *pathname, char *errortext)
michael@0 332 {
michael@0 333 PR_fprintf(errorFD, "error %d: %s IN FILE %s\n", status, errortext,
michael@0 334 pathname);
michael@0 335 errorCount++;
michael@0 336 return 0;
michael@0 337 }
michael@0 338
michael@0 339

mercurial