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