1 /* ***** BEGIN LICENSE BLOCK *****
2 * Version: MPL 1.1/GPL 2.0/LGPL 2.1
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/
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
14 * The Original Code is the Netscape security libraries.
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.
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.
35 * ***** END LICENSE BLOCK ***** */
37 /****************************************************************************
38 * Read in a cert chain from one or more files, and verify the chain for
41 * This code was modified from other code also kept in the NSS directory.
42 ****************************************************************************/
62 /* #include <stdlib.h> */
63 /* #include <errno.h> */
64 /* #include <fcntl.h> */
65 /* #include <stdarg.h> */
72 /* #include "vfyutil.h" */
74 #define RD_BUF_SIZE (60 * 1024)
78 char *password
= NULL
;
80 /* Function: char * myPasswd()
82 * Purpose: This function is our custom password handler that is called by
83 * SSL when retreiving private certs and keys from the database. Returns a
84 * pointer to a string that with a password for the database. Password pointer
85 * should point to dynamically allocated memory that will be freed later.
88 myPasswd(PK11SlotInfo
*info
, PRBool retry
, void *arg
)
92 if ( (!retry
) && arg
) {
93 passwd
= PORT_Strdup((char *)arg
);
99 Usage(const char *progName
)
102 "Usage: %s [options] certfile [[options] certfile] ...\n"
103 "\twhere options are:\n"
104 "\t-a\t\t following certfile is base64 encoded\n"
105 "\t-b YYMMDDHHMMZ\t Validate date (default: now)\n"
106 "\t-d directory\t Database directory\n"
107 "\t-r\t\t following certfile is raw binary DER (default)\n"
108 "\t-u usage \t 0=SSL client, 1=SSL server, 2=SSL StepUp, 3=SSL CA,\n"
109 "\t\t\t 4=Email signer, 5=Email recipient, 6=Object signer,\n"
110 "\t\t\t 9=ProtectedObjectSigner, 10=OCSP responder, 11=Any CA\n"
111 "\t-v\t\t verbose mode\n"
112 "\t-w password\t Database password\n",
117 /**************************************************************************
119 ** Error and information routines.
121 **************************************************************************/
124 errWarn(char *function
)
126 PRErrorCode errorNumber
= PR_GetError();
127 const char * errorString
= SECU_Strerror(errorNumber
);
129 fprintf(stderr
, "Error in function %s: %d\n - %s\n",
130 function
, errorNumber
, errorString
);
134 exitErr(char *function
)
137 /* Exit gracefully. */
138 /* ignoring return value of NSS_Shutdown as code exits with 1 anyway*/
139 (void) NSS_Shutdown();
144 typedef struct certMemStr
{
145 struct certMemStr
* next
;
146 CERTCertificate
* cert
;
152 rememberCert(CERTCertificate
* cert
)
154 certMem
* newCertMem
= PORT_ZNew(certMem
);
156 newCertMem
->next
= theCerts
;
157 newCertMem
->cert
= cert
;
158 theCerts
= newCertMem
;
165 certMem
* oldCertMem
;
166 while (oldCertMem
= theCerts
) {
167 theCerts
= oldCertMem
->next
;
168 CERT_DestroyCertificate(oldCertMem
->cert
);
169 PORT_Free(oldCertMem
);
176 readCertFile(const char * fileName
, PRBool isAscii
)
179 CERTCertificate
* cert
= NULL
;
180 CERTCertDBHandle
*defaultDB
= NULL
;
186 static unsigned char certBuf
[RD_BUF_SIZE
];
188 fd
= PR_Open(fileName
, PR_RDONLY
, 0777);
190 PRIntn err
= PR_GetError();
191 fprintf(stderr
, "open of %s failed, %d = %s\n",
192 fileName
, err
, SECU_Strerror(err
));
195 /* read until EOF or buffer is full */
197 while (0 < (remaining
= (sizeof certBuf
) - (pb
- certBuf
))) {
198 cc
= PR_Read(fd
, pb
, remaining
);
202 PRIntn err
= PR_GetError();
203 fprintf(stderr
, "read of %s failed, %d = %s\n",
204 fileName
, err
, SECU_Strerror(err
));
213 if (!remaining
|| cc
> 0) { /* file was too big. */
214 fprintf(stderr
, "cert file %s was too big.\n", fileName
);
217 total
= pb
- certBuf
;
218 if (!total
) { /* file was empty */
219 fprintf(stderr
, "cert file %s was empty.\n", fileName
);
223 /* convert from Base64 to binary here ... someday */
225 item
.type
= siBuffer
;
228 defaultDB
= CERT_GetDefaultCertDB();
229 cert
= CERT_NewTempCertificate(defaultDB
, &item
,
231 PR_FALSE
/* isPerm */,
232 PR_TRUE
/* copyDER */);
234 PRIntn err
= PR_GetError();
235 fprintf(stderr
, "couldn't import %s, %d = %s\n",
236 fileName
, err
, SECU_Strerror(err
));
242 main(int argc
, char *argv
[], char *envp
[])
244 char * certDir
= NULL
;
245 char * progName
= NULL
;
246 CERTCertificate
* cert
;
247 CERTCertificate
* firstCert
= NULL
;
248 CERTCertDBHandle
* defaultDB
= NULL
;
249 PRBool isAscii
= PR_FALSE
;
251 SECCertificateUsage certUsage
= certificateUsageSSLServer
;
252 PLOptState
* optstate
;
258 PR_Init( PR_SYSTEM_THREAD
, PR_PRIORITY_NORMAL
, 1);
260 progName
= PL_strdup(argv
[0]);
262 optstate
= PL_CreateOptState(argc
, argv
, "ab:d:ru:w:v");
263 while ((status
= PL_GetNextOpt(optstate
)) == PL_OPT_OK
) {
264 switch(optstate
->option
) {
265 case 0 : /* positional parameter */ goto breakout
;
266 case 'a' : isAscii
= PR_TRUE
; break;
267 case 'b' : secStatus
= DER_AsciiToTime(&time
, optstate
->value
);
268 if (secStatus
!= SECSuccess
) Usage(progName
); break;
269 case 'd' : certDir
= PL_strdup(optstate
->value
); break;
270 case 'r' : isAscii
= PR_FALSE
; break;
271 case 'u' : usage
= PORT_Atoi(optstate
->value
);
272 if (usage
< 0 || usage
> 62) Usage(progName
);
273 certUsage
= ((SECCertificateUsage
)1) << usage
;
274 if (certUsage
> certificateUsageHighest
) Usage(progName
);
276 case 'w' : password
= PL_strdup(optstate
->value
); break;
277 case 'v' : verbose
++; break;
278 default : Usage(progName
); break;
282 if (status
!= PL_OPT_OK
)
285 /* Set our password function callback. */
286 PK11_SetPasswordFunc(myPasswd
);
288 /* Initialize the NSS libraries. */
290 secStatus
= NSS_Init(certDir
);
292 secStatus
= NSS_NoDB_Init(NULL
);
294 /* load the builtins */
295 SECMOD_AddNewModule("Builtins", DLL_PREFIX
"nssckbi."DLL_SUFFIX
, 0, 0);
297 if (secStatus
!= SECSuccess
) {
300 SECU_RegisterDynamicOids();
302 while (status
== PL_OPT_OK
) {
303 switch(optstate
->option
) {
304 default : Usage(progName
); break;
305 case 'a' : isAscii
= PR_TRUE
; break;
306 case 'r' : isAscii
= PR_FALSE
; break;
307 case 0 : /* positional parameter */
308 cert
= readCertFile(optstate
->value
, isAscii
);
316 status
= PL_GetNextOpt(optstate
);
318 PL_DestroyOptState(optstate
);
319 if (status
== PL_OPT_BAD
|| !firstCert
)
325 /* NOW, verify the cert chain. */
326 defaultDB
= CERT_GetDefaultCertDB();
327 secStatus
= CERT_VerifyCertificate(defaultDB
, firstCert
,
328 PR_TRUE
/* check sig */,
332 NULL
, /* error log */
333 NULL
); /* returned usages */
335 if (secStatus
!= SECSuccess
) {
336 PRIntn err
= PR_GetError();
337 fprintf(stderr
, "Chain is bad, %d = %s\n", err
, SECU_Strerror(err
));
338 SECU_printCertProblemsOnDate(stderr
, defaultDB
, firstCert
,
339 PR_TRUE
, certUsage
, NULL
, verbose
, time
);
342 fprintf(stderr
, "Chain is good!\n");
348 if (NSS_Shutdown() != SECSuccess
) {
349 SECU_PrintError(progName
, "NSS_Shutdown");