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