|
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/. */ |
|
4 |
|
5 /* |
|
6 ** certutil.c |
|
7 ** |
|
8 ** utility for managing certificates and the cert database |
|
9 ** |
|
10 */ |
|
11 #include <stdio.h> |
|
12 #include <string.h> |
|
13 #include <stdlib.h> |
|
14 |
|
15 #if defined(WIN32) |
|
16 #include "fcntl.h" |
|
17 #include "io.h" |
|
18 #endif |
|
19 |
|
20 #include "secutil.h" |
|
21 |
|
22 #if defined(XP_UNIX) |
|
23 #include <unistd.h> |
|
24 #endif |
|
25 |
|
26 #include "nspr.h" |
|
27 #include "prtypes.h" |
|
28 #include "prtime.h" |
|
29 #include "prlong.h" |
|
30 |
|
31 #include "pk11func.h" |
|
32 #include "secasn1.h" |
|
33 #include "cert.h" |
|
34 #include "cryptohi.h" |
|
35 #include "secoid.h" |
|
36 #include "certdb.h" |
|
37 #include "nss.h" |
|
38 #include "certutil.h" |
|
39 |
|
40 #define MIN_KEY_BITS 512 |
|
41 /* MAX_KEY_BITS should agree with MAX_RSA_MODULUS in freebl */ |
|
42 #define MAX_KEY_BITS 8192 |
|
43 #define DEFAULT_KEY_BITS 1024 |
|
44 |
|
45 #define GEN_BREAK(e) rv=e; break; |
|
46 |
|
47 char *progName; |
|
48 |
|
49 static CERTCertificateRequest * |
|
50 GetCertRequest(const SECItem *reqDER) |
|
51 { |
|
52 CERTCertificateRequest *certReq = NULL; |
|
53 CERTSignedData signedData; |
|
54 PLArenaPool *arena = NULL; |
|
55 SECStatus rv; |
|
56 |
|
57 do { |
|
58 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
59 if (arena == NULL) { |
|
60 GEN_BREAK (SECFailure); |
|
61 } |
|
62 |
|
63 certReq = (CERTCertificateRequest*) PORT_ArenaZAlloc |
|
64 (arena, sizeof(CERTCertificateRequest)); |
|
65 if (!certReq) { |
|
66 GEN_BREAK(SECFailure); |
|
67 } |
|
68 certReq->arena = arena; |
|
69 |
|
70 /* Since cert request is a signed data, must decode to get the inner |
|
71 data |
|
72 */ |
|
73 PORT_Memset(&signedData, 0, sizeof(signedData)); |
|
74 rv = SEC_ASN1DecodeItem(arena, &signedData, |
|
75 SEC_ASN1_GET(CERT_SignedDataTemplate), reqDER); |
|
76 if (rv) { |
|
77 break; |
|
78 } |
|
79 rv = SEC_ASN1DecodeItem(arena, certReq, |
|
80 SEC_ASN1_GET(CERT_CertificateRequestTemplate), &signedData.data); |
|
81 if (rv) { |
|
82 break; |
|
83 } |
|
84 rv = CERT_VerifySignedDataWithPublicKeyInfo(&signedData, |
|
85 &certReq->subjectPublicKeyInfo, NULL /* wincx */); |
|
86 } while (0); |
|
87 |
|
88 if (rv) { |
|
89 SECU_PrintError(progName, "bad certificate request\n"); |
|
90 if (arena) { |
|
91 PORT_FreeArena(arena, PR_FALSE); |
|
92 } |
|
93 certReq = NULL; |
|
94 } |
|
95 |
|
96 return certReq; |
|
97 } |
|
98 |
|
99 static SECStatus |
|
100 AddCert(PK11SlotInfo *slot, CERTCertDBHandle *handle, char *name, char *trusts, |
|
101 const SECItem *certDER, PRBool emailcert, void *pwdata) |
|
102 { |
|
103 CERTCertTrust *trust = NULL; |
|
104 CERTCertificate *cert = NULL; |
|
105 SECStatus rv; |
|
106 |
|
107 do { |
|
108 /* Read in an ASCII cert and return a CERTCertificate */ |
|
109 cert = CERT_DecodeCertFromPackage((char *)certDER->data, certDER->len); |
|
110 if (!cert) { |
|
111 SECU_PrintError(progName, "could not decode certificate"); |
|
112 GEN_BREAK(SECFailure); |
|
113 } |
|
114 |
|
115 /* Create a cert trust */ |
|
116 trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust)); |
|
117 if (!trust) { |
|
118 SECU_PrintError(progName, "unable to allocate cert trust"); |
|
119 GEN_BREAK(SECFailure); |
|
120 } |
|
121 |
|
122 rv = CERT_DecodeTrustString(trust, trusts); |
|
123 if (rv) { |
|
124 SECU_PrintError(progName, "unable to decode trust string"); |
|
125 GEN_BREAK(SECFailure); |
|
126 } |
|
127 |
|
128 rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, name, PR_FALSE); |
|
129 if (rv != SECSuccess) { |
|
130 /* sigh, PK11_Import Cert and CERT_ChangeCertTrust should have |
|
131 * been coded to take a password arg. */ |
|
132 if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { |
|
133 rv = PK11_Authenticate(slot, PR_TRUE, pwdata); |
|
134 if (rv != SECSuccess) { |
|
135 SECU_PrintError(progName, |
|
136 "could not authenticate to token %s.", |
|
137 PK11_GetTokenName(slot)); |
|
138 GEN_BREAK(SECFailure); |
|
139 } |
|
140 rv = PK11_ImportCert(slot, cert, CK_INVALID_HANDLE, |
|
141 name, PR_FALSE); |
|
142 } |
|
143 if (rv != SECSuccess) { |
|
144 SECU_PrintError(progName, |
|
145 "could not add certificate to token or database"); |
|
146 GEN_BREAK(SECFailure); |
|
147 } |
|
148 } |
|
149 |
|
150 rv = CERT_ChangeCertTrust(handle, cert, trust); |
|
151 if (rv != SECSuccess) { |
|
152 if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { |
|
153 rv = PK11_Authenticate(slot, PR_TRUE, pwdata); |
|
154 if (rv != SECSuccess) { |
|
155 SECU_PrintError(progName, |
|
156 "could not authenticate to token %s.", |
|
157 PK11_GetTokenName(slot)); |
|
158 GEN_BREAK(SECFailure); |
|
159 } |
|
160 rv = CERT_ChangeCertTrust(handle, cert, trust); |
|
161 } |
|
162 if (rv != SECSuccess) { |
|
163 SECU_PrintError(progName, |
|
164 "could not change trust on certificate"); |
|
165 GEN_BREAK(SECFailure); |
|
166 } |
|
167 } |
|
168 |
|
169 if ( emailcert ) { |
|
170 CERT_SaveSMimeProfile(cert, NULL, pwdata); |
|
171 } |
|
172 |
|
173 } while (0); |
|
174 |
|
175 CERT_DestroyCertificate (cert); |
|
176 PORT_Free(trust); |
|
177 |
|
178 return rv; |
|
179 } |
|
180 |
|
181 static SECStatus |
|
182 CertReq(SECKEYPrivateKey *privk, SECKEYPublicKey *pubk, KeyType keyType, |
|
183 SECOidTag hashAlgTag, CERTName *subject, char *phone, int ascii, |
|
184 const char *emailAddrs, const char *dnsNames, |
|
185 certutilExtnList extnList, const char *extGeneric, |
|
186 /*out*/ SECItem *result) |
|
187 { |
|
188 CERTSubjectPublicKeyInfo *spki; |
|
189 CERTCertificateRequest *cr; |
|
190 SECItem *encoding; |
|
191 SECOidTag signAlgTag; |
|
192 SECStatus rv; |
|
193 PLArenaPool *arena; |
|
194 void *extHandle; |
|
195 SECItem signedReq = { siBuffer, NULL, 0 }; |
|
196 |
|
197 /* Create info about public key */ |
|
198 spki = SECKEY_CreateSubjectPublicKeyInfo(pubk); |
|
199 if (!spki) { |
|
200 SECU_PrintError(progName, "unable to create subject public key"); |
|
201 return SECFailure; |
|
202 } |
|
203 |
|
204 /* Generate certificate request */ |
|
205 cr = CERT_CreateCertificateRequest(subject, spki, NULL); |
|
206 SECKEY_DestroySubjectPublicKeyInfo(spki); |
|
207 if (!cr) { |
|
208 SECU_PrintError(progName, "unable to make certificate request"); |
|
209 return SECFailure; |
|
210 } |
|
211 |
|
212 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
213 if ( !arena ) { |
|
214 SECU_PrintError(progName, "out of memory"); |
|
215 return SECFailure; |
|
216 } |
|
217 |
|
218 extHandle = CERT_StartCertificateRequestAttributes(cr); |
|
219 if (extHandle == NULL) { |
|
220 PORT_FreeArena (arena, PR_FALSE); |
|
221 return SECFailure; |
|
222 } |
|
223 if (AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric) |
|
224 != SECSuccess) { |
|
225 PORT_FreeArena (arena, PR_FALSE); |
|
226 return SECFailure; |
|
227 } |
|
228 CERT_FinishExtensions(extHandle); |
|
229 CERT_FinishCertificateRequestAttributes(cr); |
|
230 |
|
231 /* Der encode the request */ |
|
232 encoding = SEC_ASN1EncodeItem(arena, NULL, cr, |
|
233 SEC_ASN1_GET(CERT_CertificateRequestTemplate)); |
|
234 CERT_DestroyCertificateRequest(cr); |
|
235 if (encoding == NULL) { |
|
236 PORT_FreeArena (arena, PR_FALSE); |
|
237 SECU_PrintError(progName, "der encoding of request failed"); |
|
238 return SECFailure; |
|
239 } |
|
240 |
|
241 /* Sign the request */ |
|
242 signAlgTag = SEC_GetSignatureAlgorithmOidTag(keyType, hashAlgTag); |
|
243 if (signAlgTag == SEC_OID_UNKNOWN) { |
|
244 PORT_FreeArena (arena, PR_FALSE); |
|
245 SECU_PrintError(progName, "unknown Key or Hash type"); |
|
246 return SECFailure; |
|
247 } |
|
248 |
|
249 rv = SEC_DerSignData(arena, &signedReq, encoding->data, encoding->len, |
|
250 privk, signAlgTag); |
|
251 if (rv) { |
|
252 PORT_FreeArena (arena, PR_FALSE); |
|
253 SECU_PrintError(progName, "signing of data failed"); |
|
254 return SECFailure; |
|
255 } |
|
256 |
|
257 /* Encode request in specified format */ |
|
258 if (ascii) { |
|
259 char *obuf; |
|
260 char *header, *name, *email, *org, *state, *country; |
|
261 |
|
262 obuf = BTOA_ConvertItemToAscii(&signedReq); |
|
263 if (!obuf) { |
|
264 goto oom; |
|
265 } |
|
266 |
|
267 name = CERT_GetCommonName(subject); |
|
268 if (!name) { |
|
269 name = PORT_Strdup("(not specified)"); |
|
270 } |
|
271 |
|
272 if (!phone) |
|
273 phone = strdup("(not specified)"); |
|
274 |
|
275 email = CERT_GetCertEmailAddress(subject); |
|
276 if (!email) |
|
277 email = PORT_Strdup("(not specified)"); |
|
278 |
|
279 org = CERT_GetOrgName(subject); |
|
280 if (!org) |
|
281 org = PORT_Strdup("(not specified)"); |
|
282 |
|
283 state = CERT_GetStateName(subject); |
|
284 if (!state) |
|
285 state = PORT_Strdup("(not specified)"); |
|
286 |
|
287 country = CERT_GetCountryName(subject); |
|
288 if (!country) |
|
289 country = PORT_Strdup("(not specified)"); |
|
290 |
|
291 header = PR_smprintf( |
|
292 "\nCertificate request generated by Netscape certutil\n" |
|
293 "Phone: %s\n\n" |
|
294 "Common Name: %s\n" |
|
295 "Email: %s\n" |
|
296 "Organization: %s\n" |
|
297 "State: %s\n" |
|
298 "Country: %s\n\n" |
|
299 "%s\n", |
|
300 phone, name, email, org, state, country, NS_CERTREQ_HEADER); |
|
301 |
|
302 PORT_Free(name); |
|
303 PORT_Free(email); |
|
304 PORT_Free(org); |
|
305 PORT_Free(state); |
|
306 PORT_Free(country); |
|
307 |
|
308 if (header) { |
|
309 char * trailer = PR_smprintf("\n%s\n", NS_CERTREQ_TRAILER); |
|
310 if (trailer) { |
|
311 PRUint32 headerLen = PL_strlen(header); |
|
312 PRUint32 obufLen = PL_strlen(obuf); |
|
313 PRUint32 trailerLen = PL_strlen(trailer); |
|
314 SECITEM_AllocItem(NULL, result, |
|
315 headerLen + obufLen + trailerLen); |
|
316 if (result->data) { |
|
317 PORT_Memcpy(result->data, header, headerLen); |
|
318 PORT_Memcpy(result->data + headerLen, obuf, obufLen); |
|
319 PORT_Memcpy(result->data + headerLen + obufLen, |
|
320 trailer, trailerLen); |
|
321 } |
|
322 PR_smprintf_free(trailer); |
|
323 } |
|
324 PR_smprintf_free(header); |
|
325 } |
|
326 } else { |
|
327 (void) SECITEM_CopyItem(NULL, result, &signedReq); |
|
328 } |
|
329 |
|
330 if (!result->data) { |
|
331 oom: SECU_PrintError(progName, "out of memory"); |
|
332 PORT_SetError(SEC_ERROR_NO_MEMORY); |
|
333 rv = SECFailure; |
|
334 } |
|
335 |
|
336 PORT_FreeArena (arena, PR_FALSE); |
|
337 return rv; |
|
338 } |
|
339 |
|
340 static SECStatus |
|
341 ChangeTrustAttributes(CERTCertDBHandle *handle, PK11SlotInfo *slot, |
|
342 char *name, char *trusts, void *pwdata) |
|
343 { |
|
344 SECStatus rv; |
|
345 CERTCertificate *cert; |
|
346 CERTCertTrust *trust; |
|
347 |
|
348 cert = CERT_FindCertByNicknameOrEmailAddr(handle, name); |
|
349 if (!cert) { |
|
350 SECU_PrintError(progName, "could not find certificate named \"%s\"", |
|
351 name); |
|
352 return SECFailure; |
|
353 } |
|
354 |
|
355 trust = (CERTCertTrust *)PORT_ZAlloc(sizeof(CERTCertTrust)); |
|
356 if (!trust) { |
|
357 SECU_PrintError(progName, "unable to allocate cert trust"); |
|
358 return SECFailure; |
|
359 } |
|
360 |
|
361 /* This function only decodes these characters: pPwcTCu, */ |
|
362 rv = CERT_DecodeTrustString(trust, trusts); |
|
363 if (rv) { |
|
364 SECU_PrintError(progName, "unable to decode trust string"); |
|
365 return SECFailure; |
|
366 } |
|
367 |
|
368 /* CERT_ChangeCertTrust API does not have a way to pass in |
|
369 * a context, so NSS can't prompt for the password if it needs to. |
|
370 * check to see if the failure was token not logged in and |
|
371 * log in if need be. */ |
|
372 rv = CERT_ChangeCertTrust(handle, cert, trust); |
|
373 if (rv != SECSuccess) { |
|
374 if (PORT_GetError() == SEC_ERROR_TOKEN_NOT_LOGGED_IN) { |
|
375 rv = PK11_Authenticate(slot, PR_TRUE, pwdata); |
|
376 if (rv != SECSuccess) { |
|
377 SECU_PrintError(progName, "could not authenticate to token %s.", |
|
378 PK11_GetTokenName(slot)); |
|
379 return SECFailure; |
|
380 } |
|
381 rv = CERT_ChangeCertTrust(handle, cert, trust); |
|
382 } |
|
383 if (rv != SECSuccess) { |
|
384 SECU_PrintError(progName, "unable to modify trust attributes"); |
|
385 return SECFailure; |
|
386 } |
|
387 } |
|
388 CERT_DestroyCertificate(cert); |
|
389 |
|
390 return SECSuccess; |
|
391 } |
|
392 |
|
393 static SECStatus |
|
394 DumpChain(CERTCertDBHandle *handle, char *name, PRBool ascii) |
|
395 { |
|
396 CERTCertificate *the_cert; |
|
397 CERTCertificateList *chain; |
|
398 int i, j; |
|
399 the_cert = SECU_FindCertByNicknameOrFilename(handle, name, |
|
400 ascii, NULL); |
|
401 if (!the_cert) { |
|
402 SECU_PrintError(progName, "Could not find: %s\n", name); |
|
403 return SECFailure; |
|
404 } |
|
405 chain = CERT_CertChainFromCert(the_cert, 0, PR_TRUE); |
|
406 CERT_DestroyCertificate(the_cert); |
|
407 if (!chain) { |
|
408 SECU_PrintError(progName, "Could not obtain chain for: %s\n", name); |
|
409 return SECFailure; |
|
410 } |
|
411 for (i=chain->len-1; i>=0; i--) { |
|
412 CERTCertificate *c; |
|
413 c = CERT_FindCertByDERCert(handle, &chain->certs[i]); |
|
414 for (j=i; j<chain->len-1; j++) printf(" "); |
|
415 printf("\"%s\" [%s]\n\n", c->nickname, c->subjectName); |
|
416 CERT_DestroyCertificate(c); |
|
417 } |
|
418 CERT_DestroyCertificateList(chain); |
|
419 return SECSuccess; |
|
420 } |
|
421 |
|
422 static SECStatus |
|
423 outputCertOrExtension(CERTCertificate *the_cert, PRBool raw, PRBool ascii, |
|
424 SECItem *extensionOID, PRFileDesc *outfile) |
|
425 { |
|
426 SECItem data; |
|
427 PRInt32 numBytes; |
|
428 SECStatus rv = SECFailure; |
|
429 if (extensionOID) { |
|
430 int i; |
|
431 PRBool found = PR_FALSE; |
|
432 for (i=0; the_cert->extensions[i] != NULL; i++) { |
|
433 CERTCertExtension *extension = the_cert->extensions[i]; |
|
434 if (SECITEM_CompareItem(&extension->id, extensionOID) == SECEqual) { |
|
435 found = PR_TRUE; |
|
436 numBytes = PR_Write(outfile, extension->value.data, |
|
437 extension->value.len); |
|
438 rv = SECSuccess; |
|
439 if (numBytes != (PRInt32) extension->value.len) { |
|
440 SECU_PrintSystemError(progName, "error writing extension"); |
|
441 rv = SECFailure; |
|
442 } |
|
443 rv = SECSuccess; |
|
444 break; |
|
445 } |
|
446 } |
|
447 if (!found) { |
|
448 SECU_PrintSystemError(progName, "extension not found"); |
|
449 rv = SECFailure; |
|
450 } |
|
451 } else { |
|
452 data.data = the_cert->derCert.data; |
|
453 data.len = the_cert->derCert.len; |
|
454 if (ascii) { |
|
455 PR_fprintf(outfile, "%s\n%s\n%s\n", NS_CERT_HEADER, |
|
456 BTOA_DataToAscii(data.data, data.len), NS_CERT_TRAILER); |
|
457 rv = SECSuccess; |
|
458 } else if (raw) { |
|
459 numBytes = PR_Write(outfile, data.data, data.len); |
|
460 rv = SECSuccess; |
|
461 if (numBytes != (PRInt32) data.len) { |
|
462 SECU_PrintSystemError(progName, "error writing raw cert"); |
|
463 rv = SECFailure; |
|
464 } |
|
465 } else { |
|
466 rv = SEC_PrintCertificateAndTrust(the_cert, "Certificate", NULL); |
|
467 if (rv != SECSuccess) { |
|
468 SECU_PrintError(progName, "problem printing certificate"); |
|
469 } |
|
470 } |
|
471 } |
|
472 return rv; |
|
473 } |
|
474 |
|
475 static SECStatus |
|
476 listCerts(CERTCertDBHandle *handle, char *name, char *email, |
|
477 PK11SlotInfo *slot, PRBool raw, PRBool ascii, |
|
478 SECItem *extensionOID, |
|
479 PRFileDesc *outfile, void *pwarg) |
|
480 { |
|
481 SECStatus rv = SECFailure; |
|
482 CERTCertList *certs; |
|
483 CERTCertListNode *node; |
|
484 |
|
485 /* List certs on a non-internal slot. */ |
|
486 if (!PK11_IsFriendly(slot) && PK11_NeedLogin(slot)) { |
|
487 SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, pwarg); |
|
488 if (newrv != SECSuccess) { |
|
489 SECU_PrintError(progName, "could not authenticate to token %s.", |
|
490 PK11_GetTokenName(slot)); |
|
491 return SECFailure; |
|
492 } |
|
493 } |
|
494 if (name) { |
|
495 CERTCertificate *the_cert = |
|
496 SECU_FindCertByNicknameOrFilename(handle, name, ascii, NULL); |
|
497 if (!the_cert) { |
|
498 SECU_PrintError(progName, "Could not find cert: %s\n", name); |
|
499 return SECFailure; |
|
500 } |
|
501 /* Here, we have one cert with the desired nickname or email |
|
502 * address. Now, we will attempt to get a list of ALL certs |
|
503 * with the same subject name as the cert we have. That list |
|
504 * should contain, at a minimum, the one cert we have already found. |
|
505 * If the list of certs is empty (NULL), the libraries have failed. |
|
506 */ |
|
507 certs = CERT_CreateSubjectCertList(NULL, handle, &the_cert->derSubject, |
|
508 PR_Now(), PR_FALSE); |
|
509 CERT_DestroyCertificate(the_cert); |
|
510 if (!certs) { |
|
511 PORT_SetError(SEC_ERROR_LIBRARY_FAILURE); |
|
512 SECU_PrintError(progName, "problem printing certificates"); |
|
513 return SECFailure; |
|
514 } |
|
515 for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs); |
|
516 node = CERT_LIST_NEXT(node)) { |
|
517 rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID, |
|
518 outfile); |
|
519 if (rv != SECSuccess) { |
|
520 break; |
|
521 } |
|
522 } |
|
523 } else if (email) { |
|
524 certs = PK11_FindCertsFromEmailAddress(email, NULL); |
|
525 if (!certs) { |
|
526 SECU_PrintError(progName, |
|
527 "Could not find certificates for email address: %s\n", |
|
528 email); |
|
529 return SECFailure; |
|
530 } |
|
531 for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs); |
|
532 node = CERT_LIST_NEXT(node)) { |
|
533 rv = outputCertOrExtension(node->cert, raw, ascii, extensionOID, |
|
534 outfile); |
|
535 if (rv != SECSuccess) { |
|
536 break; |
|
537 } |
|
538 } |
|
539 } else { |
|
540 certs = PK11_ListCertsInSlot(slot); |
|
541 if (certs) { |
|
542 for (node = CERT_LIST_HEAD(certs); !CERT_LIST_END(node,certs); |
|
543 node = CERT_LIST_NEXT(node)) { |
|
544 SECU_PrintCertNickname(node,stdout); |
|
545 } |
|
546 rv = SECSuccess; |
|
547 } |
|
548 } |
|
549 if (certs) { |
|
550 CERT_DestroyCertList(certs); |
|
551 } |
|
552 if (rv) { |
|
553 SECU_PrintError(progName, "problem printing certificate nicknames"); |
|
554 return SECFailure; |
|
555 } |
|
556 |
|
557 return SECSuccess; /* not rv ?? */ |
|
558 } |
|
559 |
|
560 static SECStatus |
|
561 ListCerts(CERTCertDBHandle *handle, char *nickname, char *email, |
|
562 PK11SlotInfo *slot, PRBool raw, PRBool ascii, |
|
563 SECItem *extensionOID, |
|
564 PRFileDesc *outfile, secuPWData *pwdata) |
|
565 { |
|
566 SECStatus rv; |
|
567 |
|
568 if (!ascii && !raw && !nickname && !email) { |
|
569 PR_fprintf(outfile, "\n%-60s %-5s\n%-60s %-5s\n\n", |
|
570 "Certificate Nickname", "Trust Attributes", "", |
|
571 "SSL,S/MIME,JAR/XPI"); |
|
572 } |
|
573 if (slot == NULL) { |
|
574 CERTCertList *list; |
|
575 CERTCertListNode *node; |
|
576 |
|
577 list = PK11_ListCerts(PK11CertListAll, pwdata); |
|
578 for (node = CERT_LIST_HEAD(list); !CERT_LIST_END(node, list); |
|
579 node = CERT_LIST_NEXT(node)) { |
|
580 SECU_PrintCertNickname(node, stdout); |
|
581 } |
|
582 CERT_DestroyCertList(list); |
|
583 return SECSuccess; |
|
584 } |
|
585 rv = listCerts(handle, nickname, email, slot, raw, ascii, |
|
586 extensionOID, outfile, pwdata); |
|
587 return rv; |
|
588 } |
|
589 |
|
590 static SECStatus |
|
591 DeleteCert(CERTCertDBHandle *handle, char *name) |
|
592 { |
|
593 SECStatus rv; |
|
594 CERTCertificate *cert; |
|
595 |
|
596 cert = CERT_FindCertByNicknameOrEmailAddr(handle, name); |
|
597 if (!cert) { |
|
598 SECU_PrintError(progName, "could not find certificate named \"%s\"", |
|
599 name); |
|
600 return SECFailure; |
|
601 } |
|
602 |
|
603 rv = SEC_DeletePermCertificate(cert); |
|
604 CERT_DestroyCertificate(cert); |
|
605 if (rv) { |
|
606 SECU_PrintError(progName, "unable to delete certificate"); |
|
607 } |
|
608 return rv; |
|
609 } |
|
610 |
|
611 static SECStatus |
|
612 ValidateCert(CERTCertDBHandle *handle, char *name, char *date, |
|
613 char *certUsage, PRBool checkSig, PRBool logit, |
|
614 PRBool ascii, secuPWData *pwdata) |
|
615 { |
|
616 SECStatus rv; |
|
617 CERTCertificate *cert = NULL; |
|
618 PRTime timeBoundary; |
|
619 SECCertificateUsage usage; |
|
620 CERTVerifyLog reallog; |
|
621 CERTVerifyLog *log = NULL; |
|
622 |
|
623 if (!certUsage) { |
|
624 PORT_SetError (SEC_ERROR_INVALID_ARGS); |
|
625 return (SECFailure); |
|
626 } |
|
627 |
|
628 switch (*certUsage) { |
|
629 case 'O': |
|
630 usage = certificateUsageStatusResponder; |
|
631 break; |
|
632 case 'L': |
|
633 usage = certificateUsageSSLCA; |
|
634 break; |
|
635 case 'A': |
|
636 usage = certificateUsageAnyCA; |
|
637 break; |
|
638 case 'Y': |
|
639 usage = certificateUsageVerifyCA; |
|
640 break; |
|
641 case 'C': |
|
642 usage = certificateUsageSSLClient; |
|
643 break; |
|
644 case 'V': |
|
645 usage = certificateUsageSSLServer; |
|
646 break; |
|
647 case 'S': |
|
648 usage = certificateUsageEmailSigner; |
|
649 break; |
|
650 case 'R': |
|
651 usage = certificateUsageEmailRecipient; |
|
652 break; |
|
653 case 'J': |
|
654 usage = certificateUsageObjectSigner; |
|
655 break; |
|
656 default: |
|
657 PORT_SetError (SEC_ERROR_INVALID_ARGS); |
|
658 return (SECFailure); |
|
659 } |
|
660 do { |
|
661 cert = SECU_FindCertByNicknameOrFilename(handle, name, ascii, |
|
662 NULL); |
|
663 if (!cert) { |
|
664 SECU_PrintError(progName, "could not find certificate named \"%s\"", |
|
665 name); |
|
666 GEN_BREAK (SECFailure) |
|
667 } |
|
668 |
|
669 if (date != NULL) { |
|
670 rv = DER_AsciiToTime(&timeBoundary, date); |
|
671 if (rv) { |
|
672 SECU_PrintError(progName, "invalid input date"); |
|
673 GEN_BREAK (SECFailure) |
|
674 } |
|
675 } else { |
|
676 timeBoundary = PR_Now(); |
|
677 } |
|
678 |
|
679 if ( logit ) { |
|
680 log = &reallog; |
|
681 |
|
682 log->count = 0; |
|
683 log->head = NULL; |
|
684 log->tail = NULL; |
|
685 log->arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); |
|
686 if ( log->arena == NULL ) { |
|
687 SECU_PrintError(progName, "out of memory"); |
|
688 GEN_BREAK (SECFailure) |
|
689 } |
|
690 } |
|
691 |
|
692 rv = CERT_VerifyCertificate(handle, cert, checkSig, usage, |
|
693 timeBoundary, pwdata, log, &usage); |
|
694 if ( log ) { |
|
695 if ( log->head == NULL ) { |
|
696 fprintf(stdout, "%s: certificate is valid\n", progName); |
|
697 GEN_BREAK (SECSuccess) |
|
698 } else { |
|
699 char *name; |
|
700 CERTVerifyLogNode *node; |
|
701 |
|
702 node = log->head; |
|
703 while ( node ) { |
|
704 if ( node->cert->nickname != NULL ) { |
|
705 name = node->cert->nickname; |
|
706 } else { |
|
707 name = node->cert->subjectName; |
|
708 } |
|
709 fprintf(stderr, "%s : %s\n", name, |
|
710 SECU_Strerror(node->error)); |
|
711 CERT_DestroyCertificate(node->cert); |
|
712 node = node->next; |
|
713 } |
|
714 } |
|
715 } else { |
|
716 if (rv != SECSuccess) { |
|
717 PRErrorCode perr = PORT_GetError(); |
|
718 fprintf(stdout, "%s: certificate is invalid: %s\n", |
|
719 progName, SECU_Strerror(perr)); |
|
720 GEN_BREAK (SECFailure) |
|
721 } |
|
722 fprintf(stdout, "%s: certificate is valid\n", progName); |
|
723 GEN_BREAK (SECSuccess) |
|
724 } |
|
725 } while (0); |
|
726 |
|
727 if (cert) { |
|
728 CERT_DestroyCertificate(cert); |
|
729 } |
|
730 |
|
731 return (rv); |
|
732 } |
|
733 |
|
734 static PRBool |
|
735 ItemIsPrintableASCII(const SECItem * item) |
|
736 { |
|
737 unsigned char *src = item->data; |
|
738 unsigned int len = item->len; |
|
739 while (len-- > 0) { |
|
740 unsigned char uc = *src++; |
|
741 if (uc < 0x20 || uc > 0x7e) |
|
742 return PR_FALSE; |
|
743 } |
|
744 return PR_TRUE; |
|
745 } |
|
746 |
|
747 /* Caller ensures that dst is at least item->len*2+1 bytes long */ |
|
748 static void |
|
749 SECItemToHex(const SECItem * item, char * dst) |
|
750 { |
|
751 if (dst && item && item->data) { |
|
752 unsigned char * src = item->data; |
|
753 unsigned int len = item->len; |
|
754 for (; len > 0; --len, dst += 2) { |
|
755 sprintf(dst, "%02x", *src++); |
|
756 } |
|
757 *dst = '\0'; |
|
758 } |
|
759 } |
|
760 |
|
761 static const char * const keyTypeName[] = { |
|
762 "null", "rsa", "dsa", "fortezza", "dh", "kea", "ec" }; |
|
763 |
|
764 #define MAX_CKA_ID_BIN_LEN 20 |
|
765 #define MAX_CKA_ID_STR_LEN 40 |
|
766 |
|
767 /* print key number, key ID (in hex or ASCII), key label (nickname) */ |
|
768 static SECStatus |
|
769 PrintKey(PRFileDesc *out, const char *nickName, int count, |
|
770 SECKEYPrivateKey *key, void *pwarg) |
|
771 { |
|
772 SECItem * ckaID; |
|
773 char ckaIDbuf[MAX_CKA_ID_STR_LEN + 4]; |
|
774 |
|
775 pwarg = NULL; |
|
776 ckaID = PK11_GetLowLevelKeyIDForPrivateKey(key); |
|
777 if (!ckaID) { |
|
778 strcpy(ckaIDbuf, "(no CKA_ID)"); |
|
779 } else if (ItemIsPrintableASCII(ckaID)) { |
|
780 int len = PR_MIN(MAX_CKA_ID_STR_LEN, ckaID->len); |
|
781 ckaIDbuf[0] = '"'; |
|
782 memcpy(ckaIDbuf + 1, ckaID->data, len); |
|
783 ckaIDbuf[1 + len] = '"'; |
|
784 ckaIDbuf[2 + len] = '\0'; |
|
785 } else { |
|
786 /* print ckaid in hex */ |
|
787 SECItem idItem = *ckaID; |
|
788 if (idItem.len > MAX_CKA_ID_BIN_LEN) |
|
789 idItem.len = MAX_CKA_ID_BIN_LEN; |
|
790 SECItemToHex(&idItem, ckaIDbuf); |
|
791 } |
|
792 |
|
793 PR_fprintf(out, "<%2d> %-8.8s %-42.42s %s\n", count, |
|
794 keyTypeName[key->keyType], ckaIDbuf, nickName); |
|
795 SECITEM_ZfreeItem(ckaID, PR_TRUE); |
|
796 |
|
797 return SECSuccess; |
|
798 } |
|
799 |
|
800 /* returns SECSuccess if ANY keys are found, SECFailure otherwise. */ |
|
801 static SECStatus |
|
802 ListKeysInSlot(PK11SlotInfo *slot, const char *nickName, KeyType keyType, |
|
803 void *pwarg) |
|
804 { |
|
805 SECKEYPrivateKeyList *list; |
|
806 SECKEYPrivateKeyListNode *node; |
|
807 int count = 0; |
|
808 |
|
809 if (PK11_NeedLogin(slot)) { |
|
810 SECStatus rv = PK11_Authenticate(slot, PR_TRUE, pwarg); |
|
811 if (rv != SECSuccess) { |
|
812 SECU_PrintError(progName, "could not authenticate to token %s.", |
|
813 PK11_GetTokenName(slot)); |
|
814 return SECFailure; |
|
815 } |
|
816 } |
|
817 |
|
818 if (nickName && nickName[0]) |
|
819 list = PK11_ListPrivKeysInSlot(slot, (char *)nickName, pwarg); |
|
820 else |
|
821 list = PK11_ListPrivateKeysInSlot(slot); |
|
822 if (list == NULL) { |
|
823 SECU_PrintError(progName, "problem listing keys"); |
|
824 return SECFailure; |
|
825 } |
|
826 for (node=PRIVKEY_LIST_HEAD(list); |
|
827 !PRIVKEY_LIST_END(node,list); |
|
828 node=PRIVKEY_LIST_NEXT(node)) { |
|
829 char * keyName; |
|
830 static const char orphan[] = { "(orphan)" }; |
|
831 |
|
832 if (keyType != nullKey && keyType != node->key->keyType) |
|
833 continue; |
|
834 keyName = PK11_GetPrivateKeyNickname(node->key); |
|
835 if (!keyName || !keyName[0]) { |
|
836 /* Try extra hard to find nicknames for keys that lack them. */ |
|
837 CERTCertificate * cert; |
|
838 PORT_Free((void *)keyName); |
|
839 keyName = NULL; |
|
840 cert = PK11_GetCertFromPrivateKey(node->key); |
|
841 if (cert) { |
|
842 if (cert->nickname && cert->nickname[0]) { |
|
843 keyName = PORT_Strdup(cert->nickname); |
|
844 } else if (cert->emailAddr && cert->emailAddr[0]) { |
|
845 keyName = PORT_Strdup(cert->emailAddr); |
|
846 } |
|
847 CERT_DestroyCertificate(cert); |
|
848 } |
|
849 } |
|
850 if (nickName) { |
|
851 if (!keyName || PL_strcmp(keyName,nickName)) { |
|
852 /* PKCS#11 module returned unwanted keys */ |
|
853 PORT_Free((void *)keyName); |
|
854 continue; |
|
855 } |
|
856 } |
|
857 if (!keyName) |
|
858 keyName = (char *)orphan; |
|
859 |
|
860 PrintKey(PR_STDOUT, keyName, count, node->key, pwarg); |
|
861 |
|
862 if (keyName != (char *)orphan) |
|
863 PORT_Free((void *)keyName); |
|
864 count++; |
|
865 } |
|
866 SECKEY_DestroyPrivateKeyList(list); |
|
867 |
|
868 if (count == 0) { |
|
869 PR_fprintf(PR_STDOUT, "%s: no keys found\n", progName); |
|
870 return SECFailure; |
|
871 } |
|
872 return SECSuccess; |
|
873 } |
|
874 |
|
875 /* returns SECSuccess if ANY keys are found, SECFailure otherwise. */ |
|
876 static SECStatus |
|
877 ListKeys(PK11SlotInfo *slot, const char *nickName, int index, |
|
878 KeyType keyType, PRBool dopriv, secuPWData *pwdata) |
|
879 { |
|
880 SECStatus rv = SECFailure; |
|
881 static const char fmt[] = \ |
|
882 "%s: Checking token \"%.33s\" in slot \"%.65s\"\n"; |
|
883 |
|
884 if (slot == NULL) { |
|
885 PK11SlotList *list; |
|
886 PK11SlotListElement *le; |
|
887 |
|
888 list= PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,pwdata); |
|
889 if (list) { |
|
890 for (le = list->head; le; le = le->next) { |
|
891 PR_fprintf(PR_STDOUT, fmt, progName, |
|
892 PK11_GetTokenName(le->slot), |
|
893 PK11_GetSlotName(le->slot)); |
|
894 rv &= ListKeysInSlot(le->slot,nickName,keyType,pwdata); |
|
895 } |
|
896 PK11_FreeSlotList(list); |
|
897 } |
|
898 } else { |
|
899 PR_fprintf(PR_STDOUT, fmt, progName, PK11_GetTokenName(slot), |
|
900 PK11_GetSlotName(slot)); |
|
901 rv = ListKeysInSlot(slot,nickName,keyType,pwdata); |
|
902 } |
|
903 return rv; |
|
904 } |
|
905 |
|
906 static SECStatus |
|
907 DeleteKey(char *nickname, secuPWData *pwdata) |
|
908 { |
|
909 SECStatus rv; |
|
910 CERTCertificate *cert; |
|
911 PK11SlotInfo *slot; |
|
912 |
|
913 slot = PK11_GetInternalKeySlot(); |
|
914 if (PK11_NeedLogin(slot)) { |
|
915 SECStatus rv = PK11_Authenticate(slot, PR_TRUE, pwdata); |
|
916 if (rv != SECSuccess) { |
|
917 SECU_PrintError(progName, "could not authenticate to token %s.", |
|
918 PK11_GetTokenName(slot)); |
|
919 return SECFailure; |
|
920 } |
|
921 } |
|
922 cert = PK11_FindCertFromNickname(nickname, pwdata); |
|
923 if (!cert) { |
|
924 PK11_FreeSlot(slot); |
|
925 return SECFailure; |
|
926 } |
|
927 rv = PK11_DeleteTokenCertAndKey(cert, pwdata); |
|
928 if (rv != SECSuccess) { |
|
929 SECU_PrintError("problem deleting private key \"%s\"\n", nickname); |
|
930 } |
|
931 CERT_DestroyCertificate(cert); |
|
932 PK11_FreeSlot(slot); |
|
933 return rv; |
|
934 } |
|
935 |
|
936 |
|
937 /* |
|
938 * L i s t M o d u l e s |
|
939 * |
|
940 * Print a list of the PKCS11 modules that are |
|
941 * available. This is useful for smartcard people to |
|
942 * make sure they have the drivers loaded. |
|
943 * |
|
944 */ |
|
945 static SECStatus |
|
946 ListModules(void) |
|
947 { |
|
948 PK11SlotList *list; |
|
949 PK11SlotListElement *le; |
|
950 |
|
951 /* get them all! */ |
|
952 list = PK11_GetAllTokens(CKM_INVALID_MECHANISM,PR_FALSE,PR_FALSE,NULL); |
|
953 if (list == NULL) return SECFailure; |
|
954 |
|
955 /* look at each slot*/ |
|
956 for (le = list->head ; le; le = le->next) { |
|
957 printf ("\n"); |
|
958 printf (" slot: %s\n", PK11_GetSlotName(le->slot)); |
|
959 printf (" token: %s\n", PK11_GetTokenName(le->slot)); |
|
960 } |
|
961 PK11_FreeSlotList(list); |
|
962 |
|
963 return SECSuccess; |
|
964 } |
|
965 |
|
966 static void |
|
967 PrintSyntax(char *progName) |
|
968 { |
|
969 #define FPS fprintf(stderr, |
|
970 FPS "Type %s -H for more detailed descriptions\n", progName); |
|
971 FPS "Usage: %s -N [-d certdir] [-P dbprefix] [-f pwfile] [--empty-password]\n", progName); |
|
972 FPS "Usage: %s -T [-d certdir] [-P dbprefix] [-h token-name]\n" |
|
973 "\t\t [-f pwfile] [-0 SSO-password]\n", progName); |
|
974 FPS "\t%s -A -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n", |
|
975 progName); |
|
976 FPS "\t%s -B -i batch-file\n", progName); |
|
977 FPS "\t%s -C [-c issuer-name | -x] -i cert-request-file -o cert-file\n" |
|
978 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n" |
|
979 "\t\t [-f pwfile] [-d certdir] [-P dbprefix]\n" |
|
980 "\t\t [-1 | --keyUsage [keyUsageKeyword,..]] [-2] [-3] [-4]\n" |
|
981 "\t\t [-5 | --nsCertType [nsCertTypeKeyword,...]]\n" |
|
982 "\t\t [-6 | --extKeyUsage [extKeyUsageKeyword,...]] [-7 emailAddrs]\n" |
|
983 "\t\t [-8 dns-names] [-a]\n", |
|
984 progName); |
|
985 FPS "\t%s -D -n cert-name [-d certdir] [-P dbprefix]\n", progName); |
|
986 FPS "\t%s -E -n cert-name -t trustargs [-d certdir] [-P dbprefix] [-a] [-i input]\n", |
|
987 progName); |
|
988 FPS "\t%s -F -n nickname [-d certdir] [-P dbprefix]\n", |
|
989 progName); |
|
990 FPS "\t%s -G -n key-name [-h token-name] [-k rsa] [-g key-size] [-y exp]\n" |
|
991 "\t\t [-f pwfile] [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); |
|
992 FPS "\t%s -G [-h token-name] -k dsa [-q pqgfile -g key-size] [-f pwfile]\n" |
|
993 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); |
|
994 #ifndef NSS_DISABLE_ECC |
|
995 FPS "\t%s -G [-h token-name] -k ec -q curve [-f pwfile]\n" |
|
996 "\t\t [-z noisefile] [-d certdir] [-P dbprefix]\n", progName); |
|
997 FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|ec|rsa|all]\n", |
|
998 progName); |
|
999 #else |
|
1000 FPS "\t%s -K [-n key-name] [-h token-name] [-k dsa|rsa|all]\n", |
|
1001 progName); |
|
1002 #endif /* NSS_DISABLE_ECC */ |
|
1003 FPS "\t\t [-f pwfile] [-X] [-d certdir] [-P dbprefix]\n"); |
|
1004 FPS "\t%s --upgrade-merge --source-dir upgradeDir --upgrade-id uniqueID\n", |
|
1005 progName); |
|
1006 FPS "\t\t [--upgrade-token-name tokenName] [-d targetDBDir]\n"); |
|
1007 FPS "\t\t [-P targetDBPrefix] [--source-prefix upgradeDBPrefix]\n"); |
|
1008 FPS "\t\t [-f targetPWfile] [-@ upgradePWFile]\n"); |
|
1009 FPS "\t%s --merge --source-dir sourceDBDir [-d targetDBdir]\n", |
|
1010 progName); |
|
1011 FPS "\t\t [-P targetDBPrefix] [--source-prefix sourceDBPrefix]\n"); |
|
1012 FPS "\t\t [-f targetPWfile] [-@ sourcePWFile]\n"); |
|
1013 FPS "\t%s -L [-n cert-name] [--email email-address] [-X] [-r] [-a]\n", |
|
1014 progName); |
|
1015 FPS "\t\t [--dump-ext-val OID] [-d certdir] [-P dbprefix]\n"); |
|
1016 FPS "\t%s -M -n cert-name -t trustargs [-d certdir] [-P dbprefix]\n", |
|
1017 progName); |
|
1018 FPS "\t%s -O -n cert-name [-X] [-d certdir] [-a] [-P dbprefix]\n", progName); |
|
1019 FPS "\t%s -R -s subj -o cert-request-file [-d certdir] [-P dbprefix] [-p phone] [-a]\n" |
|
1020 "\t\t [-7 emailAddrs] [-k key-type-or-id] [-h token-name] [-f pwfile] [-g key-size]\n", |
|
1021 progName); |
|
1022 FPS "\t%s -V -n cert-name -u usage [-b time] [-e] [-a]\n" |
|
1023 "\t\t[-X] [-d certdir] [-P dbprefix]\n", |
|
1024 progName); |
|
1025 FPS "Usage: %s -W [-d certdir] [-f pwfile] [-@newpwfile]\n", |
|
1026 progName); |
|
1027 FPS "\t%s -S -n cert-name -s subj [-c issuer-name | -x] -t trustargs\n" |
|
1028 "\t\t [-k key-type-or-id] [-q key-params] [-h token-name] [-g key-size]\n" |
|
1029 "\t\t [-m serial-number] [-w warp-months] [-v months-valid]\n" |
|
1030 "\t\t [-f pwfile] [-d certdir] [-P dbprefix]\n" |
|
1031 "\t\t [-p phone] [-1] [-2] [-3] [-4] [-5] [-6] [-7 emailAddrs]\n" |
|
1032 "\t\t [-8 DNS-names]\n" |
|
1033 "\t\t [--extAIA] [--extSIA] [--extCP] [--extPM] [--extPC] [--extIA]\n" |
|
1034 "\t\t [--extSKID] [--extNC] [--extSAN type:name[,type:name]...]\n" |
|
1035 "\t\t [--extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...]\n", progName); |
|
1036 FPS "\t%s -U [-X] [-d certdir] [-P dbprefix]\n", progName); |
|
1037 exit(1); |
|
1038 } |
|
1039 |
|
1040 enum usage_level { |
|
1041 usage_all = 0, usage_selected = 1 |
|
1042 }; |
|
1043 |
|
1044 static void luCommonDetailsAE(); |
|
1045 |
|
1046 static void luA(enum usage_level ul, const char *command) |
|
1047 { |
|
1048 int is_my_command = (command && 0 == strcmp(command, "A")); |
|
1049 if (ul == usage_all || !command || is_my_command) |
|
1050 FPS "%-15s Add a certificate to the database (create if needed)\n", |
|
1051 "-A"); |
|
1052 if (ul == usage_selected && !is_my_command) |
|
1053 return; |
|
1054 if (ul == usage_all) { |
|
1055 FPS "%-20s\n", " All options under -E apply"); |
|
1056 } |
|
1057 else { |
|
1058 luCommonDetailsAE(); |
|
1059 } |
|
1060 } |
|
1061 |
|
1062 static void luB(enum usage_level ul, const char *command) |
|
1063 { |
|
1064 int is_my_command = (command && 0 == strcmp(command, "B")); |
|
1065 if (ul == usage_all || !command || is_my_command) |
|
1066 FPS "%-15s Run a series of certutil commands from a batch file\n", "-B"); |
|
1067 if (ul == usage_selected && !is_my_command) |
|
1068 return; |
|
1069 FPS "%-20s Specify the batch file\n", " -i batch-file"); |
|
1070 } |
|
1071 |
|
1072 static void luE(enum usage_level ul, const char *command) |
|
1073 { |
|
1074 int is_my_command = (command && 0 == strcmp(command, "E")); |
|
1075 if (ul == usage_all || !command || is_my_command) |
|
1076 FPS "%-15s Add an Email certificate to the database (create if needed)\n", |
|
1077 "-E"); |
|
1078 if (ul == usage_selected && !is_my_command) |
|
1079 return; |
|
1080 luCommonDetailsAE(); |
|
1081 } |
|
1082 |
|
1083 static void luCommonDetailsAE() |
|
1084 { |
|
1085 FPS "%-20s Specify the nickname of the certificate to add\n", |
|
1086 " -n cert-name"); |
|
1087 FPS "%-20s Set the certificate trust attributes:\n", |
|
1088 " -t trustargs"); |
|
1089 FPS "%-25s trustargs is of the form x,y,z where x is for SSL, y is for S/MIME,\n", ""); |
|
1090 FPS "%-25s and z is for code signing. Use ,, for no explicit trust.\n", ""); |
|
1091 FPS "%-25s p \t prohibited (explicitly distrusted)\n", ""); |
|
1092 FPS "%-25s P \t trusted peer\n", ""); |
|
1093 FPS "%-25s c \t valid CA\n", ""); |
|
1094 FPS "%-25s T \t trusted CA to issue client certs (implies c)\n", ""); |
|
1095 FPS "%-25s C \t trusted CA to issue server certs (implies c)\n", ""); |
|
1096 FPS "%-25s u \t user cert\n", ""); |
|
1097 FPS "%-25s w \t send warning\n", ""); |
|
1098 FPS "%-25s g \t make step-up cert\n", ""); |
|
1099 FPS "%-20s Specify the password file\n", |
|
1100 " -f pwfile"); |
|
1101 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1102 " -d certdir"); |
|
1103 FPS "%-20s Cert & Key database prefix\n", |
|
1104 " -P dbprefix"); |
|
1105 FPS "%-20s The input certificate is encoded in ASCII (RFC1113)\n", |
|
1106 " -a"); |
|
1107 FPS "%-20s Specify the certificate file (default is stdin)\n", |
|
1108 " -i input"); |
|
1109 FPS "\n"); |
|
1110 } |
|
1111 |
|
1112 static void luC(enum usage_level ul, const char *command) |
|
1113 { |
|
1114 int is_my_command = (command && 0 == strcmp(command, "C")); |
|
1115 if (ul == usage_all || !command || is_my_command) |
|
1116 FPS "%-15s Create a new binary certificate from a BINARY cert request\n", |
|
1117 "-C"); |
|
1118 if (ul == usage_selected && !is_my_command) |
|
1119 return; |
|
1120 FPS "%-20s The nickname of the issuer cert\n", |
|
1121 " -c issuer-name"); |
|
1122 FPS "%-20s The BINARY certificate request file\n", |
|
1123 " -i cert-request "); |
|
1124 FPS "%-20s Output binary cert to this file (default is stdout)\n", |
|
1125 " -o output-cert"); |
|
1126 FPS "%-20s Self sign\n", |
|
1127 " -x"); |
|
1128 FPS "%-20s Cert serial number\n", |
|
1129 " -m serial-number"); |
|
1130 FPS "%-20s Time Warp\n", |
|
1131 " -w warp-months"); |
|
1132 FPS "%-20s Months valid (default is 3)\n", |
|
1133 " -v months-valid"); |
|
1134 FPS "%-20s Specify the password file\n", |
|
1135 " -f pwfile"); |
|
1136 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1137 " -d certdir"); |
|
1138 FPS "%-20s Cert & Key database prefix\n", |
|
1139 " -P dbprefix"); |
|
1140 FPS "%-20s \n" |
|
1141 "%-20s Create key usage extension. Possible keywords:\n" |
|
1142 "%-20s \"digitalSignature\", \"nonRepudiation\", \"keyEncipherment\",\n" |
|
1143 "%-20s \"dataEncipherment\", \"keyAgreement\", \"certSigning\",\n" |
|
1144 "%-20s \"crlSigning\", \"critical\"\n", |
|
1145 " -1 | --keyUsage keyword,keyword,...", "", "", "", ""); |
|
1146 FPS "%-20s Create basic constraint extension\n", |
|
1147 " -2 "); |
|
1148 FPS "%-20s Create authority key ID extension\n", |
|
1149 " -3 "); |
|
1150 FPS "%-20s Create crl distribution point extension\n", |
|
1151 " -4 "); |
|
1152 FPS "%-20s \n" |
|
1153 "%-20s Create netscape cert type extension. Possible keywords:\n" |
|
1154 "%-20s \"sslClient\", \"sslServer\", \"smime\", \"objectSigning\",\n" |
|
1155 "%-20s \"sslCA\", \"smimeCA\", \"objectSigningCA\", \"critical\".\n", |
|
1156 " -5 | --nsCertType keyword,keyword,... ", "", "", ""); |
|
1157 FPS "%-20s \n" |
|
1158 "%-20s Create extended key usage extension. Possible keywords:\n" |
|
1159 "%-20s \"serverAuth\", \"clientAuth\",\"codeSigning\",\n" |
|
1160 "%-20s \"emailProtection\", \"timeStamp\",\"ocspResponder\",\n" |
|
1161 "%-20s \"stepUp\", \"msTrustListSign\", \"critical\"\n", |
|
1162 " -6 | --extKeyUsage keyword,keyword,...", "", "", "", ""); |
|
1163 FPS "%-20s Create an email subject alt name extension\n", |
|
1164 " -7 emailAddrs"); |
|
1165 FPS "%-20s Create an dns subject alt name extension\n", |
|
1166 " -8 dnsNames"); |
|
1167 FPS "%-20s The input certificate request is encoded in ASCII (RFC1113)\n", |
|
1168 " -a"); |
|
1169 FPS "\n"); |
|
1170 } |
|
1171 |
|
1172 static void luG(enum usage_level ul, const char *command) |
|
1173 { |
|
1174 int is_my_command = (command && 0 == strcmp(command, "G")); |
|
1175 if (ul == usage_all || !command || is_my_command) |
|
1176 FPS "%-15s Generate a new key pair\n", |
|
1177 "-G"); |
|
1178 if (ul == usage_selected && !is_my_command) |
|
1179 return; |
|
1180 FPS "%-20s Name of token in which to generate key (default is internal)\n", |
|
1181 " -h token-name"); |
|
1182 #ifndef NSS_DISABLE_ECC |
|
1183 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", |
|
1184 " -k key-type"); |
|
1185 FPS "%-20s Key size in bits, (min %d, max %d, default %d) (not for ec)\n", |
|
1186 " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); |
|
1187 #else |
|
1188 FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", |
|
1189 " -k key-type"); |
|
1190 FPS "%-20s Key size in bits, (min %d, max %d, default %d)\n", |
|
1191 " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); |
|
1192 #endif /* NSS_DISABLE_ECC */ |
|
1193 FPS "%-20s Set the public exponent value (3, 17, 65537) (rsa only)\n", |
|
1194 " -y exp"); |
|
1195 FPS "%-20s Specify the password file\n", |
|
1196 " -f password-file"); |
|
1197 FPS "%-20s Specify the noise file to be used\n", |
|
1198 " -z noisefile"); |
|
1199 FPS "%-20s read PQG value from pqgfile (dsa only)\n", |
|
1200 " -q pqgfile"); |
|
1201 #ifndef NSS_DISABLE_ECC |
|
1202 FPS "%-20s Elliptic curve name (ec only)\n", |
|
1203 " -q curve-name"); |
|
1204 FPS "%-20s One of nistp256, nistp384, nistp521\n", ""); |
|
1205 #ifdef NSS_ECC_MORE_THAN_SUITE_B |
|
1206 FPS "%-20s sect163k1, nistk163, sect163r1, sect163r2,\n", ""); |
|
1207 FPS "%-20s nistb163, sect193r1, sect193r2, sect233k1, nistk233,\n", ""); |
|
1208 FPS "%-20s sect233r1, nistb233, sect239k1, sect283k1, nistk283,\n", ""); |
|
1209 FPS "%-20s sect283r1, nistb283, sect409k1, nistk409, sect409r1,\n", ""); |
|
1210 FPS "%-20s nistb409, sect571k1, nistk571, sect571r1, nistb571,\n", ""); |
|
1211 FPS "%-20s secp160k1, secp160r1, secp160r2, secp192k1, secp192r1,\n", ""); |
|
1212 FPS "%-20s nistp192, secp224k1, secp224r1, nistp224, secp256k1,\n", ""); |
|
1213 FPS "%-20s secp256r1, secp384r1, secp521r1,\n", ""); |
|
1214 FPS "%-20s prime192v1, prime192v2, prime192v3, \n", ""); |
|
1215 FPS "%-20s prime239v1, prime239v2, prime239v3, c2pnb163v1, \n", ""); |
|
1216 FPS "%-20s c2pnb163v2, c2pnb163v3, c2pnb176v1, c2tnb191v1, \n", ""); |
|
1217 FPS "%-20s c2tnb191v2, c2tnb191v3, \n", ""); |
|
1218 FPS "%-20s c2pnb208w1, c2tnb239v1, c2tnb239v2, c2tnb239v3, \n", ""); |
|
1219 FPS "%-20s c2pnb272w1, c2pnb304w1, \n", ""); |
|
1220 FPS "%-20s c2tnb359w1, c2pnb368w1, c2tnb431r1, secp112r1, \n", ""); |
|
1221 FPS "%-20s secp112r2, secp128r1, secp128r2, sect113r1, sect113r2\n", ""); |
|
1222 FPS "%-20s sect131r1, sect131r2\n", ""); |
|
1223 #endif /* NSS_ECC_MORE_THAN_SUITE_B */ |
|
1224 #endif |
|
1225 FPS "%-20s Key database directory (default is ~/.netscape)\n", |
|
1226 " -d keydir"); |
|
1227 FPS "%-20s Cert & Key database prefix\n", |
|
1228 " -P dbprefix"); |
|
1229 FPS "%-20s\n" |
|
1230 "%-20s PKCS #11 key Attributes.\n", |
|
1231 " --keyAttrFlags attrflags", ""); |
|
1232 FPS "%-20s Comma separated list of key attribute attribute flags,\n", ""); |
|
1233 FPS "%-20s selected from the following list of choices:\n", ""); |
|
1234 FPS "%-20s {token | session} {public | private} {sensitive | insensitive}\n", ""); |
|
1235 FPS "%-20s {modifiable | unmodifiable} {extractable | unextractable}\n", ""); |
|
1236 FPS "%-20s\n", |
|
1237 " --keyOpFlagsOn opflags"); |
|
1238 FPS "%-20s\n" |
|
1239 "%-20s PKCS #11 key Operation Flags.\n", |
|
1240 " --keyOpFlagsOff opflags", ""); |
|
1241 FPS "%-20s Comma separated list of one or more of the following:\n", ""); |
|
1242 FPS "%-20s encrypt, decrypt, sign, sign_recover, verify,\n", ""); |
|
1243 FPS "%-20s verify_recover, wrap, unwrap, derive\n", ""); |
|
1244 FPS "\n"); |
|
1245 } |
|
1246 |
|
1247 static void luD(enum usage_level ul, const char *command) |
|
1248 { |
|
1249 int is_my_command = (command && 0 == strcmp(command, "D")); |
|
1250 if (ul == usage_all || !command || is_my_command) |
|
1251 FPS "%-15s Delete a certificate from the database\n", |
|
1252 "-D"); |
|
1253 if (ul == usage_selected && !is_my_command) |
|
1254 return; |
|
1255 FPS "%-20s The nickname of the cert to delete\n", |
|
1256 " -n cert-name"); |
|
1257 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1258 " -d certdir"); |
|
1259 FPS "%-20s Cert & Key database prefix\n", |
|
1260 " -P dbprefix"); |
|
1261 FPS "\n"); |
|
1262 |
|
1263 } |
|
1264 |
|
1265 static void luF(enum usage_level ul, const char *command) |
|
1266 { |
|
1267 int is_my_command = (command && 0 == strcmp(command, "F")); |
|
1268 if (ul == usage_all || !command || is_my_command) |
|
1269 FPS "%-15s Delete a key from the database\n", |
|
1270 "-F"); |
|
1271 if (ul == usage_selected && !is_my_command) |
|
1272 return; |
|
1273 FPS "%-20s The nickname of the key to delete\n", |
|
1274 " -n cert-name"); |
|
1275 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1276 " -d certdir"); |
|
1277 FPS "%-20s Cert & Key database prefix\n", |
|
1278 " -P dbprefix"); |
|
1279 FPS "\n"); |
|
1280 |
|
1281 } |
|
1282 |
|
1283 static void luU(enum usage_level ul, const char *command) |
|
1284 { |
|
1285 int is_my_command = (command && 0 == strcmp(command, "U")); |
|
1286 if (ul == usage_all || !command || is_my_command) |
|
1287 FPS "%-15s List all modules\n", /*, or print out a single named module\n",*/ |
|
1288 "-U"); |
|
1289 if (ul == usage_selected && !is_my_command) |
|
1290 return; |
|
1291 FPS "%-20s Module database directory (default is '~/.netscape')\n", |
|
1292 " -d moddir"); |
|
1293 FPS "%-20s Cert & Key database prefix\n", |
|
1294 " -P dbprefix"); |
|
1295 FPS "%-20s force the database to open R/W\n", |
|
1296 " -X"); |
|
1297 FPS "\n"); |
|
1298 |
|
1299 } |
|
1300 |
|
1301 static void luK(enum usage_level ul, const char *command) |
|
1302 { |
|
1303 int is_my_command = (command && 0 == strcmp(command, "K")); |
|
1304 if (ul == usage_all || !command || is_my_command) |
|
1305 FPS "%-15s List all private keys\n", |
|
1306 "-K"); |
|
1307 if (ul == usage_selected && !is_my_command) |
|
1308 return; |
|
1309 FPS "%-20s Name of token to search (\"all\" for all tokens)\n", |
|
1310 " -h token-name "); |
|
1311 |
|
1312 FPS "%-20s Key type (\"all\" (default), \"dsa\"," |
|
1313 #ifndef NSS_DISABLE_ECC |
|
1314 " \"ec\"," |
|
1315 #endif |
|
1316 " \"rsa\")\n", |
|
1317 " -k key-type"); |
|
1318 FPS "%-20s The nickname of the key or associated certificate\n", |
|
1319 " -n name"); |
|
1320 FPS "%-20s Specify the password file\n", |
|
1321 " -f password-file"); |
|
1322 FPS "%-20s Key database directory (default is ~/.netscape)\n", |
|
1323 " -d keydir"); |
|
1324 FPS "%-20s Cert & Key database prefix\n", |
|
1325 " -P dbprefix"); |
|
1326 FPS "%-20s force the database to open R/W\n", |
|
1327 " -X"); |
|
1328 FPS "\n"); |
|
1329 } |
|
1330 |
|
1331 static void luL(enum usage_level ul, const char *command) |
|
1332 { |
|
1333 int is_my_command = (command && 0 == strcmp(command, "L")); |
|
1334 if (ul == usage_all || !command || is_my_command) |
|
1335 FPS "%-15s List all certs, or print out a single named cert (or a subset)\n", |
|
1336 "-L"); |
|
1337 if (ul == usage_selected && !is_my_command) |
|
1338 return; |
|
1339 FPS "%-20s Pretty print named cert (list all if unspecified)\n", |
|
1340 " -n cert-name"); |
|
1341 FPS "%-20s \n" |
|
1342 "%-20s Pretty print cert with email address (list all if unspecified)\n", |
|
1343 " --email email-address", ""); |
|
1344 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1345 " -d certdir"); |
|
1346 FPS "%-20s Cert & Key database prefix\n", |
|
1347 " -P dbprefix"); |
|
1348 FPS "%-20s force the database to open R/W\n", |
|
1349 " -X"); |
|
1350 FPS "%-20s For single cert, print binary DER encoding\n", |
|
1351 " -r"); |
|
1352 FPS "%-20s For single cert, print ASCII encoding (RFC1113)\n", |
|
1353 " -a"); |
|
1354 FPS "%-20s \n" |
|
1355 "%-20s For single cert, print binary DER encoding of extension OID\n", |
|
1356 " --dump-ext-val OID", ""); |
|
1357 FPS "\n"); |
|
1358 } |
|
1359 |
|
1360 static void luM(enum usage_level ul, const char *command) |
|
1361 { |
|
1362 int is_my_command = (command && 0 == strcmp(command, "M")); |
|
1363 if (ul == usage_all || !command || is_my_command) |
|
1364 FPS "%-15s Modify trust attributes of certificate\n", |
|
1365 "-M"); |
|
1366 if (ul == usage_selected && !is_my_command) |
|
1367 return; |
|
1368 FPS "%-20s The nickname of the cert to modify\n", |
|
1369 " -n cert-name"); |
|
1370 FPS "%-20s Set the certificate trust attributes (see -A above)\n", |
|
1371 " -t trustargs"); |
|
1372 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1373 " -d certdir"); |
|
1374 FPS "%-20s Cert & Key database prefix\n", |
|
1375 " -P dbprefix"); |
|
1376 FPS "\n"); |
|
1377 } |
|
1378 |
|
1379 static void luN(enum usage_level ul, const char *command) |
|
1380 { |
|
1381 int is_my_command = (command && 0 == strcmp(command, "N")); |
|
1382 if (ul == usage_all || !command || is_my_command) |
|
1383 FPS "%-15s Create a new certificate database\n", |
|
1384 "-N"); |
|
1385 if (ul == usage_selected && !is_my_command) |
|
1386 return; |
|
1387 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1388 " -d certdir"); |
|
1389 FPS "%-20s Cert & Key database prefix\n", |
|
1390 " -P dbprefix"); |
|
1391 FPS "%-20s use empty password when creating a new database\n", |
|
1392 " --empty-password"); |
|
1393 FPS "\n"); |
|
1394 } |
|
1395 |
|
1396 static void luT(enum usage_level ul, const char *command) |
|
1397 { |
|
1398 int is_my_command = (command && 0 == strcmp(command, "T")); |
|
1399 if (ul == usage_all || !command || is_my_command) |
|
1400 FPS "%-15s Reset the Key database or token\n", |
|
1401 "-T"); |
|
1402 if (ul == usage_selected && !is_my_command) |
|
1403 return; |
|
1404 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1405 " -d certdir"); |
|
1406 FPS "%-20s Cert & Key database prefix\n", |
|
1407 " -P dbprefix"); |
|
1408 FPS "%-20s Token to reset (default is internal)\n", |
|
1409 " -h token-name"); |
|
1410 FPS "%-20s Set token's Site Security Officer password\n", |
|
1411 " -0 SSO-password"); |
|
1412 FPS "\n"); |
|
1413 } |
|
1414 |
|
1415 static void luO(enum usage_level ul, const char *command) |
|
1416 { |
|
1417 int is_my_command = (command && 0 == strcmp(command, "O")); |
|
1418 if (ul == usage_all || !command || is_my_command) |
|
1419 FPS "%-15s Print the chain of a certificate\n", |
|
1420 "-O"); |
|
1421 if (ul == usage_selected && !is_my_command) |
|
1422 return; |
|
1423 FPS "%-20s The nickname of the cert to modify\n", |
|
1424 " -n cert-name"); |
|
1425 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1426 " -d certdir"); |
|
1427 FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n", |
|
1428 " -a"); |
|
1429 FPS "%-20s Cert & Key database prefix\n", |
|
1430 " -P dbprefix"); |
|
1431 FPS "%-20s force the database to open R/W\n", |
|
1432 " -X"); |
|
1433 FPS "\n"); |
|
1434 } |
|
1435 |
|
1436 static void luR(enum usage_level ul, const char *command) |
|
1437 { |
|
1438 int is_my_command = (command && 0 == strcmp(command, "R")); |
|
1439 if (ul == usage_all || !command || is_my_command) |
|
1440 FPS "%-15s Generate a certificate request (stdout)\n", |
|
1441 "-R"); |
|
1442 if (ul == usage_selected && !is_my_command) |
|
1443 return; |
|
1444 FPS "%-20s Specify the subject name (using RFC1485)\n", |
|
1445 " -s subject"); |
|
1446 FPS "%-20s Output the cert request to this file\n", |
|
1447 " -o output-req"); |
|
1448 #ifndef NSS_DISABLE_ECC |
|
1449 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", |
|
1450 #else |
|
1451 FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", |
|
1452 #endif /* NSS_DISABLE_ECC */ |
|
1453 " -k key-type-or-id"); |
|
1454 FPS "%-20s or nickname of the cert key to use \n", |
|
1455 ""); |
|
1456 FPS "%-20s Name of token in which to generate key (default is internal)\n", |
|
1457 " -h token-name"); |
|
1458 FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n", |
|
1459 " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); |
|
1460 FPS "%-20s Name of file containing PQG parameters (dsa only)\n", |
|
1461 " -q pqgfile"); |
|
1462 #ifndef NSS_DISABLE_ECC |
|
1463 FPS "%-20s Elliptic curve name (ec only)\n", |
|
1464 " -q curve-name"); |
|
1465 FPS "%-20s See the \"-G\" option for a full list of supported names.\n", |
|
1466 ""); |
|
1467 #endif /* NSS_DISABLE_ECC */ |
|
1468 FPS "%-20s Specify the password file\n", |
|
1469 " -f pwfile"); |
|
1470 FPS "%-20s Key database directory (default is ~/.netscape)\n", |
|
1471 " -d keydir"); |
|
1472 FPS "%-20s Cert & Key database prefix\n", |
|
1473 " -P dbprefix"); |
|
1474 FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n", |
|
1475 " -p phone"); |
|
1476 FPS "%-20s Output the cert request in ASCII (RFC1113); default is binary\n", |
|
1477 " -a"); |
|
1478 FPS "%-20s \n", |
|
1479 " See -S for available extension options"); |
|
1480 FPS "%-20s \n", |
|
1481 " See -G for available key flag options"); |
|
1482 FPS "\n"); |
|
1483 } |
|
1484 |
|
1485 static void luV(enum usage_level ul, const char *command) |
|
1486 { |
|
1487 int is_my_command = (command && 0 == strcmp(command, "V")); |
|
1488 if (ul == usage_all || !command || is_my_command) |
|
1489 FPS "%-15s Validate a certificate\n", |
|
1490 "-V"); |
|
1491 if (ul == usage_selected && !is_my_command) |
|
1492 return; |
|
1493 FPS "%-20s The nickname of the cert to Validate\n", |
|
1494 " -n cert-name"); |
|
1495 FPS "%-20s validity time (\"YYMMDDHHMMSS[+HHMM|-HHMM|Z]\")\n", |
|
1496 " -b time"); |
|
1497 FPS "%-20s Check certificate signature \n", |
|
1498 " -e "); |
|
1499 FPS "%-20s Specify certificate usage:\n", " -u certusage"); |
|
1500 FPS "%-25s C \t SSL Client\n", ""); |
|
1501 FPS "%-25s V \t SSL Server\n", ""); |
|
1502 FPS "%-25s L \t SSL CA\n", ""); |
|
1503 FPS "%-25s A \t Any CA\n", ""); |
|
1504 FPS "%-25s Y \t Verify CA\n", ""); |
|
1505 FPS "%-25s S \t Email signer\n", ""); |
|
1506 FPS "%-25s R \t Email Recipient\n", ""); |
|
1507 FPS "%-25s O \t OCSP status responder\n", ""); |
|
1508 FPS "%-25s J \t Object signer\n", ""); |
|
1509 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1510 " -d certdir"); |
|
1511 FPS "%-20s Input the certificate in ASCII (RFC1113); default is binary\n", |
|
1512 " -a"); |
|
1513 FPS "%-20s Cert & Key database prefix\n", |
|
1514 " -P dbprefix"); |
|
1515 FPS "%-20s force the database to open R/W\n", |
|
1516 " -X"); |
|
1517 FPS "\n"); |
|
1518 } |
|
1519 |
|
1520 static void luW(enum usage_level ul, const char *command) |
|
1521 { |
|
1522 int is_my_command = (command && 0 == strcmp(command, "W")); |
|
1523 if (ul == usage_all || !command || is_my_command) |
|
1524 FPS "%-15s Change the key database password\n", |
|
1525 "-W"); |
|
1526 if (ul == usage_selected && !is_my_command) |
|
1527 return; |
|
1528 FPS "%-20s cert and key database directory\n", |
|
1529 " -d certdir"); |
|
1530 FPS "%-20s Specify a file with the current password\n", |
|
1531 " -f pwfile"); |
|
1532 FPS "%-20s Specify a file with the new password in two lines\n", |
|
1533 " -@ newpwfile"); |
|
1534 FPS "\n"); |
|
1535 } |
|
1536 |
|
1537 static void luUpgradeMerge(enum usage_level ul, const char *command) |
|
1538 { |
|
1539 int is_my_command = (command && 0 == strcmp(command, "upgrade-merge")); |
|
1540 if (ul == usage_all || !command || is_my_command) |
|
1541 FPS "%-15s Upgrade an old database and merge it into a new one\n", |
|
1542 "--upgrade-merge"); |
|
1543 if (ul == usage_selected && !is_my_command) |
|
1544 return; |
|
1545 FPS "%-20s Cert database directory to merge into (default is ~/.netscape)\n", |
|
1546 " -d certdir"); |
|
1547 FPS "%-20s Cert & Key database prefix of the target database\n", |
|
1548 " -P dbprefix"); |
|
1549 FPS "%-20s Specify the password file for the target database\n", |
|
1550 " -f pwfile"); |
|
1551 FPS "%-20s \n%-20s Cert database directory to upgrade from\n", |
|
1552 " --source-dir certdir", ""); |
|
1553 FPS "%-20s \n%-20s Cert & Key database prefix of the upgrade database\n", |
|
1554 " --source-prefix dbprefix", ""); |
|
1555 FPS "%-20s \n%-20s Unique identifier for the upgrade database\n", |
|
1556 " --upgrade-id uniqueID", ""); |
|
1557 FPS "%-20s \n%-20s Name of the token while it is in upgrade state\n", |
|
1558 " --upgrade-token-name name", ""); |
|
1559 FPS "%-20s Specify the password file for the upgrade database\n", |
|
1560 " -@ pwfile"); |
|
1561 FPS "\n"); |
|
1562 } |
|
1563 |
|
1564 static void luMerge(enum usage_level ul, const char *command) |
|
1565 { |
|
1566 int is_my_command = (command && 0 == strcmp(command, "merge")); |
|
1567 if (ul == usage_all || !command || is_my_command) |
|
1568 FPS "%-15s Merge source database into the target database\n", |
|
1569 "--merge"); |
|
1570 if (ul == usage_selected && !is_my_command) |
|
1571 return; |
|
1572 FPS "%-20s Cert database directory of target (default is ~/.netscape)\n", |
|
1573 " -d certdir"); |
|
1574 FPS "%-20s Cert & Key database prefix of the target database\n", |
|
1575 " -P dbprefix"); |
|
1576 FPS "%-20s Specify the password file for the target database\n", |
|
1577 " -f pwfile"); |
|
1578 FPS "%-20s \n%-20s Cert database directory of the source database\n", |
|
1579 " --source-dir certdir", ""); |
|
1580 FPS "%-20s \n%-20s Cert & Key database prefix of the source database\n", |
|
1581 " --source-prefix dbprefix", ""); |
|
1582 FPS "%-20s Specify the password file for the source database\n", |
|
1583 " -@ pwfile"); |
|
1584 FPS "\n"); |
|
1585 } |
|
1586 |
|
1587 static void luS(enum usage_level ul, const char *command) |
|
1588 { |
|
1589 int is_my_command = (command && 0 == strcmp(command, "S")); |
|
1590 if (ul == usage_all || !command || is_my_command) |
|
1591 FPS "%-15s Make a certificate and add to database\n", |
|
1592 "-S"); |
|
1593 if (ul == usage_selected && !is_my_command) |
|
1594 return; |
|
1595 FPS "%-20s Specify the nickname of the cert\n", |
|
1596 " -n key-name"); |
|
1597 FPS "%-20s Specify the subject name (using RFC1485)\n", |
|
1598 " -s subject"); |
|
1599 FPS "%-20s The nickname of the issuer cert\n", |
|
1600 " -c issuer-name"); |
|
1601 FPS "%-20s Set the certificate trust attributes (see -A above)\n", |
|
1602 " -t trustargs"); |
|
1603 #ifndef NSS_DISABLE_ECC |
|
1604 FPS "%-20s Type of key pair to generate (\"dsa\", \"ec\", \"rsa\" (default))\n", |
|
1605 #else |
|
1606 FPS "%-20s Type of key pair to generate (\"dsa\", \"rsa\" (default))\n", |
|
1607 #endif /* NSS_DISABLE_ECC */ |
|
1608 " -k key-type-or-id"); |
|
1609 FPS "%-20s Name of token in which to generate key (default is internal)\n", |
|
1610 " -h token-name"); |
|
1611 FPS "%-20s Key size in bits, RSA keys only (min %d, max %d, default %d)\n", |
|
1612 " -g key-size", MIN_KEY_BITS, MAX_KEY_BITS, DEFAULT_KEY_BITS); |
|
1613 FPS "%-20s Name of file containing PQG parameters (dsa only)\n", |
|
1614 " -q pqgfile"); |
|
1615 #ifndef NSS_DISABLE_ECC |
|
1616 FPS "%-20s Elliptic curve name (ec only)\n", |
|
1617 " -q curve-name"); |
|
1618 FPS "%-20s See the \"-G\" option for a full list of supported names.\n", |
|
1619 ""); |
|
1620 #endif /* NSS_DISABLE_ECC */ |
|
1621 FPS "%-20s Self sign\n", |
|
1622 " -x"); |
|
1623 FPS "%-20s Cert serial number\n", |
|
1624 " -m serial-number"); |
|
1625 FPS "%-20s Time Warp\n", |
|
1626 " -w warp-months"); |
|
1627 FPS "%-20s Months valid (default is 3)\n", |
|
1628 " -v months-valid"); |
|
1629 FPS "%-20s Specify the password file\n", |
|
1630 " -f pwfile"); |
|
1631 FPS "%-20s Cert database directory (default is ~/.netscape)\n", |
|
1632 " -d certdir"); |
|
1633 FPS "%-20s Cert & Key database prefix\n", |
|
1634 " -P dbprefix"); |
|
1635 FPS "%-20s Specify the contact phone number (\"123-456-7890\")\n", |
|
1636 " -p phone"); |
|
1637 FPS "%-20s Create key usage extension\n", |
|
1638 " -1 "); |
|
1639 FPS "%-20s Create basic constraint extension\n", |
|
1640 " -2 "); |
|
1641 FPS "%-20s Create authority key ID extension\n", |
|
1642 " -3 "); |
|
1643 FPS "%-20s Create crl distribution point extension\n", |
|
1644 " -4 "); |
|
1645 FPS "%-20s Create netscape cert type extension\n", |
|
1646 " -5 "); |
|
1647 FPS "%-20s Create extended key usage extension\n", |
|
1648 " -6 "); |
|
1649 FPS "%-20s Create an email subject alt name extension\n", |
|
1650 " -7 emailAddrs "); |
|
1651 FPS "%-20s Create a DNS subject alt name extension\n", |
|
1652 " -8 DNS-names"); |
|
1653 FPS "%-20s Create an Authority Information Access extension\n", |
|
1654 " --extAIA "); |
|
1655 FPS "%-20s Create a Subject Information Access extension\n", |
|
1656 " --extSIA "); |
|
1657 FPS "%-20s Create a Certificate Policies extension\n", |
|
1658 " --extCP "); |
|
1659 FPS "%-20s Create a Policy Mappings extension\n", |
|
1660 " --extPM "); |
|
1661 FPS "%-20s Create a Policy Constraints extension\n", |
|
1662 " --extPC "); |
|
1663 FPS "%-20s Create an Inhibit Any Policy extension\n", |
|
1664 " --extIA "); |
|
1665 FPS "%-20s Create a subject key ID extension\n", |
|
1666 " --extSKID "); |
|
1667 FPS "%-20s \n", |
|
1668 " See -G for available key flag options"); |
|
1669 FPS "%-20s Create a name constraints extension\n", |
|
1670 " --extNC "); |
|
1671 FPS "%-20s \n" |
|
1672 "%-20s Create a Subject Alt Name extension with one or multiple names\n", |
|
1673 " --extSAN type:name[,type:name]...", ""); |
|
1674 FPS "%-20s - type: directory, dn, dns, edi, ediparty, email, ip, ipaddr,\n", ""); |
|
1675 FPS "%-20s other, registerid, rfc822, uri, x400, x400addr\n", ""); |
|
1676 FPS "%-20s \n" |
|
1677 "%-20s Add one or multiple extensions that certutil cannot encode yet,\n" |
|
1678 "%-20s by loading their encodings from external files.\n", |
|
1679 " --extGeneric OID:critical-flag:filename[,OID:critical-flag:filename]...", "", ""); |
|
1680 FPS "%-20s - OID (example): 1.2.3.4\n", ""); |
|
1681 FPS "%-20s - critical-flag: critical or not-critical\n", ""); |
|
1682 FPS "%-20s - filename: full path to a file containing an encoded extension\n", ""); |
|
1683 FPS "\n"); |
|
1684 } |
|
1685 |
|
1686 static void LongUsage(char *progName, enum usage_level ul, const char *command) |
|
1687 { |
|
1688 luA(ul, command); |
|
1689 luB(ul, command); |
|
1690 luE(ul, command); |
|
1691 luC(ul, command); |
|
1692 luG(ul, command); |
|
1693 luD(ul, command); |
|
1694 luF(ul, command); |
|
1695 luU(ul, command); |
|
1696 luK(ul, command); |
|
1697 luL(ul, command); |
|
1698 luM(ul, command); |
|
1699 luN(ul, command); |
|
1700 luT(ul, command); |
|
1701 luO(ul, command); |
|
1702 luR(ul, command); |
|
1703 luV(ul, command); |
|
1704 luW(ul, command); |
|
1705 luUpgradeMerge(ul, command); |
|
1706 luMerge(ul, command); |
|
1707 luS(ul, command); |
|
1708 #undef FPS |
|
1709 } |
|
1710 |
|
1711 static void |
|
1712 Usage(char *progName) |
|
1713 { |
|
1714 PR_fprintf(PR_STDERR, |
|
1715 "%s - Utility to manipulate NSS certificate databases\n\n" |
|
1716 "Usage: %s <command> -d <database-directory> <options>\n\n" |
|
1717 "Valid commands:\n", progName, progName); |
|
1718 LongUsage(progName, usage_selected, NULL); |
|
1719 PR_fprintf(PR_STDERR, "\n" |
|
1720 "%s -H <command> : Print available options for the given command\n" |
|
1721 "%s -H : Print complete help output of all commands and options\n" |
|
1722 "%s --syntax : Print a short summary of all commands and options\n", |
|
1723 progName, progName, progName); |
|
1724 exit(1); |
|
1725 } |
|
1726 |
|
1727 static CERTCertificate * |
|
1728 MakeV1Cert( CERTCertDBHandle * handle, |
|
1729 CERTCertificateRequest *req, |
|
1730 char * issuerNickName, |
|
1731 PRBool selfsign, |
|
1732 unsigned int serialNumber, |
|
1733 int warpmonths, |
|
1734 int validityMonths) |
|
1735 { |
|
1736 CERTCertificate *issuerCert = NULL; |
|
1737 CERTValidity *validity; |
|
1738 CERTCertificate *cert = NULL; |
|
1739 PRExplodedTime printableTime; |
|
1740 PRTime now, after; |
|
1741 |
|
1742 if ( !selfsign ) { |
|
1743 issuerCert = CERT_FindCertByNicknameOrEmailAddr(handle, issuerNickName); |
|
1744 if (!issuerCert) { |
|
1745 SECU_PrintError(progName, "could not find certificate named \"%s\"", |
|
1746 issuerNickName); |
|
1747 return NULL; |
|
1748 } |
|
1749 } |
|
1750 |
|
1751 now = PR_Now(); |
|
1752 PR_ExplodeTime (now, PR_GMTParameters, &printableTime); |
|
1753 if ( warpmonths ) { |
|
1754 printableTime.tm_month += warpmonths; |
|
1755 now = PR_ImplodeTime (&printableTime); |
|
1756 PR_ExplodeTime (now, PR_GMTParameters, &printableTime); |
|
1757 } |
|
1758 printableTime.tm_month += validityMonths; |
|
1759 after = PR_ImplodeTime (&printableTime); |
|
1760 |
|
1761 /* note that the time is now in micro-second unit */ |
|
1762 validity = CERT_CreateValidity (now, after); |
|
1763 if (validity) { |
|
1764 cert = CERT_CreateCertificate(serialNumber, |
|
1765 (selfsign ? &req->subject |
|
1766 : &issuerCert->subject), |
|
1767 validity, req); |
|
1768 |
|
1769 CERT_DestroyValidity(validity); |
|
1770 } |
|
1771 if ( issuerCert ) { |
|
1772 CERT_DestroyCertificate (issuerCert); |
|
1773 } |
|
1774 |
|
1775 return(cert); |
|
1776 } |
|
1777 |
|
1778 static SECStatus |
|
1779 SignCert(CERTCertDBHandle *handle, CERTCertificate *cert, PRBool selfsign, |
|
1780 SECOidTag hashAlgTag, |
|
1781 SECKEYPrivateKey *privKey, char *issuerNickName, |
|
1782 int certVersion, void *pwarg) |
|
1783 { |
|
1784 SECItem der; |
|
1785 SECKEYPrivateKey *caPrivateKey = NULL; |
|
1786 SECStatus rv; |
|
1787 PLArenaPool *arena; |
|
1788 SECOidTag algID; |
|
1789 void *dummy; |
|
1790 |
|
1791 if( !selfsign ) { |
|
1792 CERTCertificate *issuer = PK11_FindCertFromNickname(issuerNickName, pwarg); |
|
1793 if( (CERTCertificate *)NULL == issuer ) { |
|
1794 SECU_PrintError(progName, "unable to find issuer with nickname %s", |
|
1795 issuerNickName); |
|
1796 return SECFailure; |
|
1797 } |
|
1798 |
|
1799 privKey = caPrivateKey = PK11_FindKeyByAnyCert(issuer, pwarg); |
|
1800 CERT_DestroyCertificate(issuer); |
|
1801 if (caPrivateKey == NULL) { |
|
1802 SECU_PrintError(progName, "unable to retrieve key %s", issuerNickName); |
|
1803 return SECFailure; |
|
1804 } |
|
1805 } |
|
1806 |
|
1807 arena = cert->arena; |
|
1808 |
|
1809 algID = SEC_GetSignatureAlgorithmOidTag(privKey->keyType, hashAlgTag); |
|
1810 if (algID == SEC_OID_UNKNOWN) { |
|
1811 fprintf(stderr, "Unknown key or hash type for issuer."); |
|
1812 rv = SECFailure; |
|
1813 goto done; |
|
1814 } |
|
1815 |
|
1816 rv = SECOID_SetAlgorithmID(arena, &cert->signature, algID, 0); |
|
1817 if (rv != SECSuccess) { |
|
1818 fprintf(stderr, "Could not set signature algorithm id."); |
|
1819 goto done; |
|
1820 } |
|
1821 |
|
1822 switch(certVersion) { |
|
1823 case (SEC_CERTIFICATE_VERSION_1): |
|
1824 /* The initial version for x509 certificates is version one |
|
1825 * and this default value must be an implicit DER encoding. */ |
|
1826 cert->version.data = NULL; |
|
1827 cert->version.len = 0; |
|
1828 break; |
|
1829 case (SEC_CERTIFICATE_VERSION_2): |
|
1830 case (SEC_CERTIFICATE_VERSION_3): |
|
1831 case 3: /* unspecified format (would be version 4 certificate). */ |
|
1832 *(cert->version.data) = certVersion; |
|
1833 cert->version.len = 1; |
|
1834 break; |
|
1835 default: |
|
1836 PORT_SetError(SEC_ERROR_INVALID_ARGS); |
|
1837 return SECFailure; |
|
1838 } |
|
1839 |
|
1840 der.len = 0; |
|
1841 der.data = NULL; |
|
1842 dummy = SEC_ASN1EncodeItem (arena, &der, cert, |
|
1843 SEC_ASN1_GET(CERT_CertificateTemplate)); |
|
1844 if (!dummy) { |
|
1845 fprintf (stderr, "Could not encode certificate.\n"); |
|
1846 rv = SECFailure; |
|
1847 goto done; |
|
1848 } |
|
1849 |
|
1850 rv = SEC_DerSignData(arena, &cert->derCert, der.data, der.len, privKey, algID); |
|
1851 if (rv != SECSuccess) { |
|
1852 fprintf (stderr, "Could not sign encoded certificate data.\n"); |
|
1853 /* result allocated out of the arena, it will be freed |
|
1854 * when the arena is freed */ |
|
1855 goto done; |
|
1856 } |
|
1857 done: |
|
1858 if (caPrivateKey) { |
|
1859 SECKEY_DestroyPrivateKey(caPrivateKey); |
|
1860 } |
|
1861 return rv; |
|
1862 } |
|
1863 |
|
1864 static SECStatus |
|
1865 CreateCert( |
|
1866 CERTCertDBHandle *handle, |
|
1867 PK11SlotInfo *slot, |
|
1868 char * issuerNickName, |
|
1869 const SECItem * certReqDER, |
|
1870 SECKEYPrivateKey **selfsignprivkey, |
|
1871 void *pwarg, |
|
1872 SECOidTag hashAlgTag, |
|
1873 unsigned int serialNumber, |
|
1874 int warpmonths, |
|
1875 int validityMonths, |
|
1876 const char *emailAddrs, |
|
1877 const char *dnsNames, |
|
1878 PRBool ascii, |
|
1879 PRBool selfsign, |
|
1880 certutilExtnList extnList, |
|
1881 const char *extGeneric, |
|
1882 int certVersion, |
|
1883 SECItem * certDER) |
|
1884 { |
|
1885 void * extHandle; |
|
1886 CERTCertificate *subjectCert = NULL; |
|
1887 CERTCertificateRequest *certReq = NULL; |
|
1888 SECStatus rv = SECSuccess; |
|
1889 CERTCertExtension **CRexts; |
|
1890 |
|
1891 do { |
|
1892 /* Create a certrequest object from the input cert request der */ |
|
1893 certReq = GetCertRequest(certReqDER); |
|
1894 if (certReq == NULL) { |
|
1895 GEN_BREAK (SECFailure) |
|
1896 } |
|
1897 |
|
1898 subjectCert = MakeV1Cert (handle, certReq, issuerNickName, selfsign, |
|
1899 serialNumber, warpmonths, validityMonths); |
|
1900 if (subjectCert == NULL) { |
|
1901 GEN_BREAK (SECFailure) |
|
1902 } |
|
1903 |
|
1904 |
|
1905 extHandle = CERT_StartCertExtensions (subjectCert); |
|
1906 if (extHandle == NULL) { |
|
1907 GEN_BREAK (SECFailure) |
|
1908 } |
|
1909 |
|
1910 rv = AddExtensions(extHandle, emailAddrs, dnsNames, extnList, extGeneric); |
|
1911 if (rv != SECSuccess) { |
|
1912 GEN_BREAK (SECFailure) |
|
1913 } |
|
1914 |
|
1915 if (certReq->attributes != NULL && |
|
1916 certReq->attributes[0] != NULL && |
|
1917 certReq->attributes[0]->attrType.data != NULL && |
|
1918 certReq->attributes[0]->attrType.len > 0 && |
|
1919 SECOID_FindOIDTag(&certReq->attributes[0]->attrType) |
|
1920 == SEC_OID_PKCS9_EXTENSION_REQUEST) { |
|
1921 rv = CERT_GetCertificateRequestExtensions(certReq, &CRexts); |
|
1922 if (rv != SECSuccess) |
|
1923 break; |
|
1924 rv = CERT_MergeExtensions(extHandle, CRexts); |
|
1925 if (rv != SECSuccess) |
|
1926 break; |
|
1927 } |
|
1928 |
|
1929 CERT_FinishExtensions(extHandle); |
|
1930 |
|
1931 /* self-signing a cert request, find the private key */ |
|
1932 if (selfsign && *selfsignprivkey == NULL) { |
|
1933 *selfsignprivkey = PK11_FindKeyByDERCert(slot, subjectCert, pwarg); |
|
1934 if (!*selfsignprivkey) { |
|
1935 fprintf(stderr, "Failed to locate private key.\n"); |
|
1936 rv = SECFailure; |
|
1937 break; |
|
1938 } |
|
1939 } |
|
1940 |
|
1941 rv = SignCert(handle, subjectCert, selfsign, hashAlgTag, |
|
1942 *selfsignprivkey, issuerNickName, |
|
1943 certVersion, pwarg); |
|
1944 if (rv != SECSuccess) |
|
1945 break; |
|
1946 |
|
1947 rv = SECFailure; |
|
1948 if (ascii) { |
|
1949 char * asciiDER = BTOA_DataToAscii(subjectCert->derCert.data, |
|
1950 subjectCert->derCert.len); |
|
1951 if (asciiDER) { |
|
1952 char * wrapped = PR_smprintf("%s\n%s\n%s\n", |
|
1953 NS_CERT_HEADER, |
|
1954 asciiDER, |
|
1955 NS_CERT_TRAILER); |
|
1956 if (wrapped) { |
|
1957 PRUint32 wrappedLen = PL_strlen(wrapped); |
|
1958 if (SECITEM_AllocItem(NULL, certDER, wrappedLen)) { |
|
1959 PORT_Memcpy(certDER->data, wrapped, wrappedLen); |
|
1960 rv = SECSuccess; |
|
1961 } |
|
1962 PR_smprintf_free(wrapped); |
|
1963 } |
|
1964 PORT_Free(asciiDER); |
|
1965 } |
|
1966 } else { |
|
1967 rv = SECITEM_CopyItem(NULL, certDER, &subjectCert->derCert); |
|
1968 } |
|
1969 } while (0); |
|
1970 CERT_DestroyCertificateRequest (certReq); |
|
1971 CERT_DestroyCertificate (subjectCert); |
|
1972 if (rv != SECSuccess) { |
|
1973 PRErrorCode perr = PR_GetError(); |
|
1974 fprintf(stderr, "%s: unable to create cert (%s)\n", progName, |
|
1975 SECU_Strerror(perr)); |
|
1976 } |
|
1977 return (rv); |
|
1978 } |
|
1979 |
|
1980 |
|
1981 /* |
|
1982 * map a class to a user presentable string |
|
1983 */ |
|
1984 static const char *objClassArray[] = { |
|
1985 "Data", |
|
1986 "Certificate", |
|
1987 "Public Key", |
|
1988 "Private Key", |
|
1989 "Secret Key", |
|
1990 "Hardware Feature", |
|
1991 "Domain Parameters", |
|
1992 "Mechanism" |
|
1993 }; |
|
1994 |
|
1995 static const char *objNSSClassArray[] = { |
|
1996 "CKO_NSS", |
|
1997 "Crl", |
|
1998 "SMIME Record", |
|
1999 "Trust", |
|
2000 "Builtin Root List" |
|
2001 }; |
|
2002 |
|
2003 |
|
2004 const char * |
|
2005 getObjectClass(CK_ULONG classType) |
|
2006 { |
|
2007 static char buf[sizeof(CK_ULONG)*2+3]; |
|
2008 |
|
2009 if (classType <= CKO_MECHANISM) { |
|
2010 return objClassArray[classType]; |
|
2011 } |
|
2012 if (classType >= CKO_NSS && classType <= CKO_NSS_BUILTIN_ROOT_LIST) { |
|
2013 return objNSSClassArray[classType - CKO_NSS]; |
|
2014 } |
|
2015 sprintf(buf, "0x%lx", classType); |
|
2016 return buf; |
|
2017 } |
|
2018 |
|
2019 typedef struct { |
|
2020 char *name; |
|
2021 int nameSize; |
|
2022 CK_ULONG value; |
|
2023 } flagArray; |
|
2024 |
|
2025 #define NAME_SIZE(x) #x,sizeof(#x)-1 |
|
2026 |
|
2027 flagArray opFlagsArray[] = |
|
2028 { |
|
2029 {NAME_SIZE(encrypt), CKF_ENCRYPT}, |
|
2030 {NAME_SIZE(decrypt), CKF_DECRYPT}, |
|
2031 {NAME_SIZE(sign), CKF_SIGN}, |
|
2032 {NAME_SIZE(sign_recover), CKF_SIGN_RECOVER}, |
|
2033 {NAME_SIZE(verify), CKF_VERIFY}, |
|
2034 {NAME_SIZE(verify_recover), CKF_VERIFY_RECOVER}, |
|
2035 {NAME_SIZE(wrap), CKF_WRAP}, |
|
2036 {NAME_SIZE(unwrap), CKF_UNWRAP}, |
|
2037 {NAME_SIZE(derive), CKF_DERIVE}, |
|
2038 }; |
|
2039 |
|
2040 int opFlagsCount = sizeof(opFlagsArray)/sizeof(flagArray); |
|
2041 |
|
2042 flagArray attrFlagsArray[] = |
|
2043 { |
|
2044 {NAME_SIZE(token), PK11_ATTR_TOKEN}, |
|
2045 {NAME_SIZE(session), PK11_ATTR_SESSION}, |
|
2046 {NAME_SIZE(private), PK11_ATTR_PRIVATE}, |
|
2047 {NAME_SIZE(public), PK11_ATTR_PUBLIC}, |
|
2048 {NAME_SIZE(modifiable), PK11_ATTR_MODIFIABLE}, |
|
2049 {NAME_SIZE(unmodifiable), PK11_ATTR_UNMODIFIABLE}, |
|
2050 {NAME_SIZE(sensitive), PK11_ATTR_SENSITIVE}, |
|
2051 {NAME_SIZE(insensitive), PK11_ATTR_INSENSITIVE}, |
|
2052 {NAME_SIZE(extractable), PK11_ATTR_EXTRACTABLE}, |
|
2053 {NAME_SIZE(unextractable), PK11_ATTR_UNEXTRACTABLE} |
|
2054 |
|
2055 }; |
|
2056 |
|
2057 int attrFlagsCount = sizeof(attrFlagsArray)/sizeof(flagArray); |
|
2058 |
|
2059 #define MAX_STRING 30 |
|
2060 CK_ULONG |
|
2061 GetFlags(char *flagsString, flagArray *flagArray, int count) |
|
2062 { |
|
2063 CK_ULONG flagsValue = strtol(flagsString, NULL, 0); |
|
2064 int i; |
|
2065 |
|
2066 if ((flagsValue != 0) || (*flagsString == 0)) { |
|
2067 return flagsValue; |
|
2068 } |
|
2069 while (*flagsString) { |
|
2070 for (i=0; i < count; i++) { |
|
2071 if (strncmp(flagsString, flagArray[i].name, flagArray[i].nameSize) |
|
2072 == 0) { |
|
2073 flagsValue |= flagArray[i].value; |
|
2074 flagsString += flagArray[i].nameSize; |
|
2075 if (*flagsString != 0) { |
|
2076 flagsString++; |
|
2077 } |
|
2078 break; |
|
2079 } |
|
2080 } |
|
2081 if (i == count) { |
|
2082 char name[MAX_STRING]; |
|
2083 char *tok; |
|
2084 |
|
2085 strncpy(name,flagsString, MAX_STRING); |
|
2086 name[MAX_STRING-1] = 0; |
|
2087 tok = strchr(name, ','); |
|
2088 if (tok) { |
|
2089 *tok = 0; |
|
2090 } |
|
2091 fprintf(stderr,"Unknown flag (%s)\n",name); |
|
2092 tok = strchr(flagsString, ','); |
|
2093 if (tok == NULL) { |
|
2094 break; |
|
2095 } |
|
2096 flagsString = tok+1; |
|
2097 } |
|
2098 } |
|
2099 return flagsValue; |
|
2100 } |
|
2101 |
|
2102 CK_FLAGS |
|
2103 GetOpFlags(char *flags) |
|
2104 { |
|
2105 return GetFlags(flags, opFlagsArray, opFlagsCount); |
|
2106 } |
|
2107 |
|
2108 PK11AttrFlags |
|
2109 GetAttrFlags(char *flags) |
|
2110 { |
|
2111 return GetFlags(flags, attrFlagsArray, attrFlagsCount); |
|
2112 } |
|
2113 |
|
2114 char *mkNickname(unsigned char *data, int len) |
|
2115 { |
|
2116 char *nick = PORT_Alloc(len+1); |
|
2117 if (!nick) { |
|
2118 return nick; |
|
2119 } |
|
2120 PORT_Memcpy(nick, data, len); |
|
2121 nick[len] = 0; |
|
2122 return nick; |
|
2123 } |
|
2124 |
|
2125 /* |
|
2126 * dump a PK11_MergeTokens error log to the console |
|
2127 */ |
|
2128 void |
|
2129 DumpMergeLog(const char *progname, PK11MergeLog *log) |
|
2130 { |
|
2131 PK11MergeLogNode *node; |
|
2132 |
|
2133 for (node = log->head; node; node = node->next) { |
|
2134 SECItem attrItem; |
|
2135 char *nickname = NULL; |
|
2136 const char *objectClass = NULL; |
|
2137 SECStatus rv; |
|
2138 |
|
2139 attrItem.data = NULL; |
|
2140 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object, |
|
2141 CKA_LABEL, &attrItem); |
|
2142 if (rv == SECSuccess) { |
|
2143 nickname = mkNickname(attrItem.data, attrItem.len); |
|
2144 PORT_Free(attrItem.data); |
|
2145 } |
|
2146 attrItem.data = NULL; |
|
2147 rv = PK11_ReadRawAttribute(PK11_TypeGeneric, node->object, |
|
2148 CKA_CLASS, &attrItem); |
|
2149 if (rv == SECSuccess) { |
|
2150 if (attrItem.len == sizeof(CK_ULONG)) { |
|
2151 objectClass = getObjectClass(*(CK_ULONG *)attrItem.data); |
|
2152 } |
|
2153 PORT_Free(attrItem.data); |
|
2154 } |
|
2155 |
|
2156 fprintf(stderr, "%s: Could not merge object %s (type %s): %s\n", |
|
2157 progName, |
|
2158 nickname ? nickname : "unnamed", |
|
2159 objectClass ? objectClass : "unknown", |
|
2160 SECU_Strerror(node->error)); |
|
2161 |
|
2162 if (nickname) { |
|
2163 PORT_Free(nickname); |
|
2164 } |
|
2165 } |
|
2166 } |
|
2167 |
|
2168 /* Certutil commands */ |
|
2169 enum { |
|
2170 cmd_AddCert = 0, |
|
2171 cmd_CreateNewCert, |
|
2172 cmd_DeleteCert, |
|
2173 cmd_AddEmailCert, |
|
2174 cmd_DeleteKey, |
|
2175 cmd_GenKeyPair, |
|
2176 cmd_PrintHelp, |
|
2177 cmd_PrintSyntax, |
|
2178 cmd_ListKeys, |
|
2179 cmd_ListCerts, |
|
2180 cmd_ModifyCertTrust, |
|
2181 cmd_NewDBs, |
|
2182 cmd_DumpChain, |
|
2183 cmd_CertReq, |
|
2184 cmd_CreateAndAddCert, |
|
2185 cmd_TokenReset, |
|
2186 cmd_ListModules, |
|
2187 cmd_CheckCertValidity, |
|
2188 cmd_ChangePassword, |
|
2189 cmd_Version, |
|
2190 cmd_Batch, |
|
2191 cmd_Merge, |
|
2192 cmd_UpgradeMerge, /* test only */ |
|
2193 max_cmd |
|
2194 }; |
|
2195 |
|
2196 /* Certutil options */ |
|
2197 enum certutilOpts { |
|
2198 opt_SSOPass = 0, |
|
2199 opt_AddKeyUsageExt, |
|
2200 opt_AddBasicConstraintExt, |
|
2201 opt_AddAuthorityKeyIDExt, |
|
2202 opt_AddCRLDistPtsExt, |
|
2203 opt_AddNSCertTypeExt, |
|
2204 opt_AddExtKeyUsageExt, |
|
2205 opt_ExtendedEmailAddrs, |
|
2206 opt_ExtendedDNSNames, |
|
2207 opt_ASCIIForIO, |
|
2208 opt_ValidityTime, |
|
2209 opt_IssuerName, |
|
2210 opt_CertDir, |
|
2211 opt_VerifySig, |
|
2212 opt_PasswordFile, |
|
2213 opt_KeySize, |
|
2214 opt_TokenName, |
|
2215 opt_InputFile, |
|
2216 opt_Emailaddress, |
|
2217 opt_KeyIndex, |
|
2218 opt_KeyType, |
|
2219 opt_DetailedInfo, |
|
2220 opt_SerialNumber, |
|
2221 opt_Nickname, |
|
2222 opt_OutputFile, |
|
2223 opt_PhoneNumber, |
|
2224 opt_DBPrefix, |
|
2225 opt_PQGFile, |
|
2226 opt_BinaryDER, |
|
2227 opt_Subject, |
|
2228 opt_Trust, |
|
2229 opt_Usage, |
|
2230 opt_Validity, |
|
2231 opt_OffsetMonths, |
|
2232 opt_SelfSign, |
|
2233 opt_RW, |
|
2234 opt_Exponent, |
|
2235 opt_NoiseFile, |
|
2236 opt_Hash, |
|
2237 opt_NewPasswordFile, |
|
2238 opt_AddAuthInfoAccExt, |
|
2239 opt_AddSubjInfoAccExt, |
|
2240 opt_AddCertPoliciesExt, |
|
2241 opt_AddPolicyMapExt, |
|
2242 opt_AddPolicyConstrExt, |
|
2243 opt_AddInhibAnyExt, |
|
2244 opt_AddNameConstraintsExt, |
|
2245 opt_AddSubjectKeyIDExt, |
|
2246 opt_AddCmdKeyUsageExt, |
|
2247 opt_AddCmdNSCertTypeExt, |
|
2248 opt_AddCmdExtKeyUsageExt, |
|
2249 opt_SourceDir, |
|
2250 opt_SourcePrefix, |
|
2251 opt_UpgradeID, |
|
2252 opt_UpgradeTokenName, |
|
2253 opt_KeyOpFlagsOn, |
|
2254 opt_KeyOpFlagsOff, |
|
2255 opt_KeyAttrFlags, |
|
2256 opt_EmptyPassword, |
|
2257 opt_CertVersion, |
|
2258 opt_AddSubjectAltNameExt, |
|
2259 opt_DumpExtensionValue, |
|
2260 opt_GenericExtensions, |
|
2261 opt_Help |
|
2262 }; |
|
2263 |
|
2264 static const |
|
2265 secuCommandFlag commands_init[] = |
|
2266 { |
|
2267 { /* cmd_AddCert */ 'A', PR_FALSE, 0, PR_FALSE }, |
|
2268 { /* cmd_CreateNewCert */ 'C', PR_FALSE, 0, PR_FALSE }, |
|
2269 { /* cmd_DeleteCert */ 'D', PR_FALSE, 0, PR_FALSE }, |
|
2270 { /* cmd_AddEmailCert */ 'E', PR_FALSE, 0, PR_FALSE }, |
|
2271 { /* cmd_DeleteKey */ 'F', PR_FALSE, 0, PR_FALSE }, |
|
2272 { /* cmd_GenKeyPair */ 'G', PR_FALSE, 0, PR_FALSE }, |
|
2273 { /* cmd_PrintHelp */ 'H', PR_FALSE, 0, PR_FALSE, "help" }, |
|
2274 { /* cmd_PrintSyntax */ 0, PR_FALSE, 0, PR_FALSE, |
|
2275 "syntax" }, |
|
2276 { /* cmd_ListKeys */ 'K', PR_FALSE, 0, PR_FALSE }, |
|
2277 { /* cmd_ListCerts */ 'L', PR_FALSE, 0, PR_FALSE }, |
|
2278 { /* cmd_ModifyCertTrust */ 'M', PR_FALSE, 0, PR_FALSE }, |
|
2279 { /* cmd_NewDBs */ 'N', PR_FALSE, 0, PR_FALSE }, |
|
2280 { /* cmd_DumpChain */ 'O', PR_FALSE, 0, PR_FALSE }, |
|
2281 { /* cmd_CertReq */ 'R', PR_FALSE, 0, PR_FALSE }, |
|
2282 { /* cmd_CreateAndAddCert */ 'S', PR_FALSE, 0, PR_FALSE }, |
|
2283 { /* cmd_TokenReset */ 'T', PR_FALSE, 0, PR_FALSE }, |
|
2284 { /* cmd_ListModules */ 'U', PR_FALSE, 0, PR_FALSE }, |
|
2285 { /* cmd_CheckCertValidity */ 'V', PR_FALSE, 0, PR_FALSE }, |
|
2286 { /* cmd_ChangePassword */ 'W', PR_FALSE, 0, PR_FALSE }, |
|
2287 { /* cmd_Version */ 'Y', PR_FALSE, 0, PR_FALSE }, |
|
2288 { /* cmd_Batch */ 'B', PR_FALSE, 0, PR_FALSE }, |
|
2289 { /* cmd_Merge */ 0, PR_FALSE, 0, PR_FALSE, "merge" }, |
|
2290 { /* cmd_UpgradeMerge */ 0, PR_FALSE, 0, PR_FALSE, |
|
2291 "upgrade-merge" } |
|
2292 }; |
|
2293 #define NUM_COMMANDS ((sizeof commands_init) / (sizeof commands_init[0])) |
|
2294 |
|
2295 static const |
|
2296 secuCommandFlag options_init[] = |
|
2297 { |
|
2298 { /* opt_SSOPass */ '0', PR_TRUE, 0, PR_FALSE }, |
|
2299 { /* opt_AddKeyUsageExt */ '1', PR_FALSE, 0, PR_FALSE }, |
|
2300 { /* opt_AddBasicConstraintExt*/ '2', PR_FALSE, 0, PR_FALSE }, |
|
2301 { /* opt_AddAuthorityKeyIDExt*/ '3', PR_FALSE, 0, PR_FALSE }, |
|
2302 { /* opt_AddCRLDistPtsExt */ '4', PR_FALSE, 0, PR_FALSE }, |
|
2303 { /* opt_AddNSCertTypeExt */ '5', PR_FALSE, 0, PR_FALSE }, |
|
2304 { /* opt_AddExtKeyUsageExt */ '6', PR_FALSE, 0, PR_FALSE }, |
|
2305 { /* opt_ExtendedEmailAddrs */ '7', PR_TRUE, 0, PR_FALSE }, |
|
2306 { /* opt_ExtendedDNSNames */ '8', PR_TRUE, 0, PR_FALSE }, |
|
2307 { /* opt_ASCIIForIO */ 'a', PR_FALSE, 0, PR_FALSE }, |
|
2308 { /* opt_ValidityTime */ 'b', PR_TRUE, 0, PR_FALSE }, |
|
2309 { /* opt_IssuerName */ 'c', PR_TRUE, 0, PR_FALSE }, |
|
2310 { /* opt_CertDir */ 'd', PR_TRUE, 0, PR_FALSE }, |
|
2311 { /* opt_VerifySig */ 'e', PR_FALSE, 0, PR_FALSE }, |
|
2312 { /* opt_PasswordFile */ 'f', PR_TRUE, 0, PR_FALSE }, |
|
2313 { /* opt_KeySize */ 'g', PR_TRUE, 0, PR_FALSE }, |
|
2314 { /* opt_TokenName */ 'h', PR_TRUE, 0, PR_FALSE }, |
|
2315 { /* opt_InputFile */ 'i', PR_TRUE, 0, PR_FALSE }, |
|
2316 { /* opt_Emailaddress */ 0, PR_TRUE, 0, PR_FALSE, "email" }, |
|
2317 { /* opt_KeyIndex */ 'j', PR_TRUE, 0, PR_FALSE }, |
|
2318 { /* opt_KeyType */ 'k', PR_TRUE, 0, PR_FALSE }, |
|
2319 { /* opt_DetailedInfo */ 'l', PR_FALSE, 0, PR_FALSE }, |
|
2320 { /* opt_SerialNumber */ 'm', PR_TRUE, 0, PR_FALSE }, |
|
2321 { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE }, |
|
2322 { /* opt_OutputFile */ 'o', PR_TRUE, 0, PR_FALSE }, |
|
2323 { /* opt_PhoneNumber */ 'p', PR_TRUE, 0, PR_FALSE }, |
|
2324 { /* opt_DBPrefix */ 'P', PR_TRUE, 0, PR_FALSE }, |
|
2325 { /* opt_PQGFile */ 'q', PR_TRUE, 0, PR_FALSE }, |
|
2326 { /* opt_BinaryDER */ 'r', PR_FALSE, 0, PR_FALSE }, |
|
2327 { /* opt_Subject */ 's', PR_TRUE, 0, PR_FALSE }, |
|
2328 { /* opt_Trust */ 't', PR_TRUE, 0, PR_FALSE }, |
|
2329 { /* opt_Usage */ 'u', PR_TRUE, 0, PR_FALSE }, |
|
2330 { /* opt_Validity */ 'v', PR_TRUE, 0, PR_FALSE }, |
|
2331 { /* opt_OffsetMonths */ 'w', PR_TRUE, 0, PR_FALSE }, |
|
2332 { /* opt_SelfSign */ 'x', PR_FALSE, 0, PR_FALSE }, |
|
2333 { /* opt_RW */ 'X', PR_FALSE, 0, PR_FALSE }, |
|
2334 { /* opt_Exponent */ 'y', PR_TRUE, 0, PR_FALSE }, |
|
2335 { /* opt_NoiseFile */ 'z', PR_TRUE, 0, PR_FALSE }, |
|
2336 { /* opt_Hash */ 'Z', PR_TRUE, 0, PR_FALSE }, |
|
2337 { /* opt_NewPasswordFile */ '@', PR_TRUE, 0, PR_FALSE }, |
|
2338 { /* opt_AddAuthInfoAccExt */ 0, PR_FALSE, 0, PR_FALSE, "extAIA" }, |
|
2339 { /* opt_AddSubjInfoAccExt */ 0, PR_FALSE, 0, PR_FALSE, "extSIA" }, |
|
2340 { /* opt_AddCertPoliciesExt */ 0, PR_FALSE, 0, PR_FALSE, "extCP" }, |
|
2341 { /* opt_AddPolicyMapExt */ 0, PR_FALSE, 0, PR_FALSE, "extPM" }, |
|
2342 { /* opt_AddPolicyConstrExt */ 0, PR_FALSE, 0, PR_FALSE, "extPC" }, |
|
2343 { /* opt_AddInhibAnyExt */ 0, PR_FALSE, 0, PR_FALSE, "extIA" }, |
|
2344 { /* opt_AddNameConstraintsExt*/ 0, PR_FALSE, 0, PR_FALSE, "extNC" }, |
|
2345 { /* opt_AddSubjectKeyIDExt */ 0, PR_FALSE, 0, PR_FALSE, |
|
2346 "extSKID" }, |
|
2347 { /* opt_AddCmdKeyUsageExt */ 0, PR_TRUE, 0, PR_FALSE, |
|
2348 "keyUsage" }, |
|
2349 { /* opt_AddCmdNSCertTypeExt */ 0, PR_TRUE, 0, PR_FALSE, |
|
2350 "nsCertType" }, |
|
2351 { /* opt_AddCmdExtKeyUsageExt*/ 0, PR_TRUE, 0, PR_FALSE, |
|
2352 "extKeyUsage" }, |
|
2353 |
|
2354 { /* opt_SourceDir */ 0, PR_TRUE, 0, PR_FALSE, |
|
2355 "source-dir"}, |
|
2356 { /* opt_SourcePrefix */ 0, PR_TRUE, 0, PR_FALSE, |
|
2357 "source-prefix"}, |
|
2358 { /* opt_UpgradeID */ 0, PR_TRUE, 0, PR_FALSE, |
|
2359 "upgrade-id"}, |
|
2360 { /* opt_UpgradeTokenName */ 0, PR_TRUE, 0, PR_FALSE, |
|
2361 "upgrade-token-name"}, |
|
2362 { /* opt_KeyOpFlagsOn */ 0, PR_TRUE, 0, PR_FALSE, |
|
2363 "keyOpFlagsOn"}, |
|
2364 { /* opt_KeyOpFlagsOff */ 0, PR_TRUE, 0, PR_FALSE, |
|
2365 "keyOpFlagsOff"}, |
|
2366 { /* opt_KeyAttrFlags */ 0, PR_TRUE, 0, PR_FALSE, |
|
2367 "keyAttrFlags"}, |
|
2368 { /* opt_EmptyPassword */ 0, PR_FALSE, 0, PR_FALSE, |
|
2369 "empty-password"}, |
|
2370 { /* opt_CertVersion */ 0, PR_FALSE, 0, PR_FALSE, |
|
2371 "certVersion"}, |
|
2372 { /* opt_AddSubjectAltExt */ 0, PR_TRUE, 0, PR_FALSE, "extSAN"}, |
|
2373 { /* opt_DumpExtensionValue */ 0, PR_TRUE, 0, PR_FALSE, |
|
2374 "dump-ext-val"}, |
|
2375 { /* opt_GenericExtensions */ 0, PR_TRUE, 0, PR_FALSE, |
|
2376 "extGeneric"}, |
|
2377 }; |
|
2378 #define NUM_OPTIONS ((sizeof options_init) / (sizeof options_init[0])) |
|
2379 |
|
2380 static secuCommandFlag certutil_commands[NUM_COMMANDS]; |
|
2381 static secuCommandFlag certutil_options [NUM_OPTIONS ]; |
|
2382 |
|
2383 static const secuCommand certutil = { |
|
2384 NUM_COMMANDS, |
|
2385 NUM_OPTIONS, |
|
2386 certutil_commands, |
|
2387 certutil_options |
|
2388 }; |
|
2389 |
|
2390 static certutilExtnList certutil_extns; |
|
2391 |
|
2392 static int |
|
2393 certutil_main(int argc, char **argv, PRBool initialize) |
|
2394 { |
|
2395 CERTCertDBHandle *certHandle; |
|
2396 PK11SlotInfo *slot = NULL; |
|
2397 CERTName * subject = 0; |
|
2398 PRFileDesc *inFile = PR_STDIN; |
|
2399 PRFileDesc *outFile = PR_STDOUT; |
|
2400 SECItem certReqDER = { siBuffer, NULL, 0 }; |
|
2401 SECItem certDER = { siBuffer, NULL, 0 }; |
|
2402 char * slotname = "internal"; |
|
2403 char * certPrefix = ""; |
|
2404 char * sourceDir = ""; |
|
2405 char * srcCertPrefix = ""; |
|
2406 char * upgradeID = ""; |
|
2407 char * upgradeTokenName = ""; |
|
2408 KeyType keytype = rsaKey; |
|
2409 char * name = NULL; |
|
2410 char * email = NULL; |
|
2411 char * keysource = NULL; |
|
2412 SECOidTag hashAlgTag = SEC_OID_UNKNOWN; |
|
2413 int keysize = DEFAULT_KEY_BITS; |
|
2414 int publicExponent = 0x010001; |
|
2415 int certVersion = SEC_CERTIFICATE_VERSION_3; |
|
2416 unsigned int serialNumber = 0; |
|
2417 int warpmonths = 0; |
|
2418 int validityMonths = 3; |
|
2419 int commandsEntered = 0; |
|
2420 char commandToRun = '\0'; |
|
2421 secuPWData pwdata = { PW_NONE, 0 }; |
|
2422 secuPWData pwdata2 = { PW_NONE, 0 }; |
|
2423 PRBool readOnly = PR_FALSE; |
|
2424 PRBool initialized = PR_FALSE; |
|
2425 CK_FLAGS keyOpFlagsOn = 0; |
|
2426 CK_FLAGS keyOpFlagsOff = 0; |
|
2427 PK11AttrFlags keyAttrFlags = |
|
2428 PK11_ATTR_TOKEN | PK11_ATTR_SENSITIVE | PK11_ATTR_PRIVATE; |
|
2429 |
|
2430 SECKEYPrivateKey *privkey = NULL; |
|
2431 SECKEYPublicKey *pubkey = NULL; |
|
2432 |
|
2433 int i; |
|
2434 SECStatus rv; |
|
2435 |
|
2436 progName = PORT_Strrchr(argv[0], '/'); |
|
2437 progName = progName ? progName+1 : argv[0]; |
|
2438 memcpy(certutil_commands, commands_init, sizeof commands_init); |
|
2439 memcpy(certutil_options, options_init, sizeof options_init); |
|
2440 |
|
2441 rv = SECU_ParseCommandLine(argc, argv, progName, &certutil); |
|
2442 |
|
2443 if (rv != SECSuccess) |
|
2444 Usage(progName); |
|
2445 |
|
2446 if (certutil.commands[cmd_PrintSyntax].activated) { |
|
2447 PrintSyntax(progName); |
|
2448 } |
|
2449 |
|
2450 if (certutil.commands[cmd_PrintHelp].activated) { |
|
2451 int i; |
|
2452 char buf[2]; |
|
2453 const char *command = NULL; |
|
2454 for (i = 0; i < max_cmd; i++) { |
|
2455 if (i == cmd_PrintHelp) |
|
2456 continue; |
|
2457 if (certutil.commands[i].activated) { |
|
2458 if (certutil.commands[i].flag) { |
|
2459 buf[0] = certutil.commands[i].flag; |
|
2460 buf[1] = 0; |
|
2461 command = buf; |
|
2462 } |
|
2463 else { |
|
2464 command = certutil.commands[i].longform; |
|
2465 } |
|
2466 break; |
|
2467 } |
|
2468 } |
|
2469 LongUsage(progName, (command ? usage_selected : usage_all), command); |
|
2470 exit(1); |
|
2471 } |
|
2472 |
|
2473 if (certutil.options[opt_PasswordFile].arg) { |
|
2474 pwdata.source = PW_FROMFILE; |
|
2475 pwdata.data = certutil.options[opt_PasswordFile].arg; |
|
2476 } |
|
2477 if (certutil.options[opt_NewPasswordFile].arg) { |
|
2478 pwdata2.source = PW_FROMFILE; |
|
2479 pwdata2.data = certutil.options[opt_NewPasswordFile].arg; |
|
2480 } |
|
2481 |
|
2482 if (certutil.options[opt_CertDir].activated) |
|
2483 SECU_ConfigDirectory(certutil.options[opt_CertDir].arg); |
|
2484 |
|
2485 if (certutil.options[opt_SourceDir].activated) |
|
2486 sourceDir = certutil.options[opt_SourceDir].arg; |
|
2487 |
|
2488 if (certutil.options[opt_UpgradeID].activated) |
|
2489 upgradeID = certutil.options[opt_UpgradeID].arg; |
|
2490 |
|
2491 if (certutil.options[opt_UpgradeTokenName].activated) |
|
2492 upgradeTokenName = certutil.options[opt_UpgradeTokenName].arg; |
|
2493 |
|
2494 if (certutil.options[opt_KeySize].activated) { |
|
2495 keysize = PORT_Atoi(certutil.options[opt_KeySize].arg); |
|
2496 if ((keysize < MIN_KEY_BITS) || (keysize > MAX_KEY_BITS)) { |
|
2497 PR_fprintf(PR_STDERR, |
|
2498 "%s -g: Keysize must be between %d and %d.\n", |
|
2499 progName, MIN_KEY_BITS, MAX_KEY_BITS); |
|
2500 return 255; |
|
2501 } |
|
2502 #ifndef NSS_DISABLE_ECC |
|
2503 if (keytype == ecKey) { |
|
2504 PR_fprintf(PR_STDERR, "%s -g: Not for ec keys.\n", progName); |
|
2505 return 255; |
|
2506 } |
|
2507 #endif /* NSS_DISABLE_ECC */ |
|
2508 |
|
2509 } |
|
2510 |
|
2511 /* -h specify token name */ |
|
2512 if (certutil.options[opt_TokenName].activated) { |
|
2513 if (PL_strcmp(certutil.options[opt_TokenName].arg, "all") == 0) |
|
2514 slotname = NULL; |
|
2515 else |
|
2516 slotname = PL_strdup(certutil.options[opt_TokenName].arg); |
|
2517 } |
|
2518 |
|
2519 /* -Z hash type */ |
|
2520 if (certutil.options[opt_Hash].activated) { |
|
2521 char * arg = certutil.options[opt_Hash].arg; |
|
2522 hashAlgTag = SECU_StringToSignatureAlgTag(arg); |
|
2523 if (hashAlgTag == SEC_OID_UNKNOWN) { |
|
2524 PR_fprintf(PR_STDERR, "%s -Z: %s is not a recognized type.\n", |
|
2525 progName, arg); |
|
2526 return 255; |
|
2527 } |
|
2528 } |
|
2529 |
|
2530 /* -k key type */ |
|
2531 if (certutil.options[opt_KeyType].activated) { |
|
2532 char * arg = certutil.options[opt_KeyType].arg; |
|
2533 if (PL_strcmp(arg, "rsa") == 0) { |
|
2534 keytype = rsaKey; |
|
2535 } else if (PL_strcmp(arg, "dsa") == 0) { |
|
2536 keytype = dsaKey; |
|
2537 #ifndef NSS_DISABLE_ECC |
|
2538 } else if (PL_strcmp(arg, "ec") == 0) { |
|
2539 keytype = ecKey; |
|
2540 #endif /* NSS_DISABLE_ECC */ |
|
2541 } else if (PL_strcmp(arg, "all") == 0) { |
|
2542 keytype = nullKey; |
|
2543 } else { |
|
2544 /* use an existing private/public key pair */ |
|
2545 keysource = arg; |
|
2546 } |
|
2547 } else if (certutil.commands[cmd_ListKeys].activated) { |
|
2548 keytype = nullKey; |
|
2549 } |
|
2550 |
|
2551 if (certutil.options[opt_KeyOpFlagsOn].activated) { |
|
2552 keyOpFlagsOn = GetOpFlags(certutil.options[opt_KeyOpFlagsOn].arg); |
|
2553 } |
|
2554 if (certutil.options[opt_KeyOpFlagsOff].activated) { |
|
2555 keyOpFlagsOff = GetOpFlags(certutil.options[opt_KeyOpFlagsOff].arg); |
|
2556 keyOpFlagsOn &=~keyOpFlagsOff; /* make off override on */ |
|
2557 } |
|
2558 if (certutil.options[opt_KeyAttrFlags].activated) { |
|
2559 keyAttrFlags = GetAttrFlags(certutil.options[opt_KeyAttrFlags].arg); |
|
2560 } |
|
2561 |
|
2562 /* -m serial number */ |
|
2563 if (certutil.options[opt_SerialNumber].activated) { |
|
2564 int sn = PORT_Atoi(certutil.options[opt_SerialNumber].arg); |
|
2565 if (sn < 0) { |
|
2566 PR_fprintf(PR_STDERR, "%s -m: %s is not a valid serial number.\n", |
|
2567 progName, certutil.options[opt_SerialNumber].arg); |
|
2568 return 255; |
|
2569 } |
|
2570 serialNumber = sn; |
|
2571 } |
|
2572 |
|
2573 /* -P certdb name prefix */ |
|
2574 if (certutil.options[opt_DBPrefix].activated) { |
|
2575 if (certutil.options[opt_DBPrefix].arg) { |
|
2576 certPrefix = strdup(certutil.options[opt_DBPrefix].arg); |
|
2577 } else { |
|
2578 Usage(progName); |
|
2579 } |
|
2580 } |
|
2581 |
|
2582 /* --source-prefix certdb name prefix */ |
|
2583 if (certutil.options[opt_SourcePrefix].activated) { |
|
2584 if (certutil.options[opt_SourcePrefix].arg) { |
|
2585 srcCertPrefix = strdup(certutil.options[opt_SourcePrefix].arg); |
|
2586 } else { |
|
2587 Usage(progName); |
|
2588 } |
|
2589 } |
|
2590 |
|
2591 /* -q PQG file or curve name */ |
|
2592 if (certutil.options[opt_PQGFile].activated) { |
|
2593 #ifndef NSS_DISABLE_ECC |
|
2594 if ((keytype != dsaKey) && (keytype != ecKey)) { |
|
2595 PR_fprintf(PR_STDERR, "%s -q: specifies a PQG file for DSA keys" \ |
|
2596 " (-k dsa) or a named curve for EC keys (-k ec)\n)", |
|
2597 progName); |
|
2598 #else /* } */ |
|
2599 if (keytype != dsaKey) { |
|
2600 PR_fprintf(PR_STDERR, "%s -q: PQG file is for DSA key (-k dsa).\n)", |
|
2601 progName); |
|
2602 #endif /* NSS_DISABLE_ECC */ |
|
2603 return 255; |
|
2604 } |
|
2605 } |
|
2606 |
|
2607 /* -s subject name */ |
|
2608 if (certutil.options[opt_Subject].activated) { |
|
2609 subject = CERT_AsciiToName(certutil.options[opt_Subject].arg); |
|
2610 if (!subject) { |
|
2611 PR_fprintf(PR_STDERR, "%s -s: improperly formatted name: \"%s\"\n", |
|
2612 progName, certutil.options[opt_Subject].arg); |
|
2613 return 255; |
|
2614 } |
|
2615 } |
|
2616 |
|
2617 /* -v validity period */ |
|
2618 if (certutil.options[opt_Validity].activated) { |
|
2619 validityMonths = PORT_Atoi(certutil.options[opt_Validity].arg); |
|
2620 if (validityMonths < 0) { |
|
2621 PR_fprintf(PR_STDERR, "%s -v: incorrect validity period: \"%s\"\n", |
|
2622 progName, certutil.options[opt_Validity].arg); |
|
2623 return 255; |
|
2624 } |
|
2625 } |
|
2626 |
|
2627 /* -w warp months */ |
|
2628 if (certutil.options[opt_OffsetMonths].activated) |
|
2629 warpmonths = PORT_Atoi(certutil.options[opt_OffsetMonths].arg); |
|
2630 |
|
2631 /* -y public exponent (for RSA) */ |
|
2632 if (certutil.options[opt_Exponent].activated) { |
|
2633 publicExponent = PORT_Atoi(certutil.options[opt_Exponent].arg); |
|
2634 if ((publicExponent != 3) && |
|
2635 (publicExponent != 17) && |
|
2636 (publicExponent != 65537)) { |
|
2637 PR_fprintf(PR_STDERR, "%s -y: incorrect public exponent %d.", |
|
2638 progName, publicExponent); |
|
2639 PR_fprintf(PR_STDERR, "Must be 3, 17, or 65537.\n"); |
|
2640 return 255; |
|
2641 } |
|
2642 } |
|
2643 |
|
2644 /* --certVersion */ |
|
2645 if (certutil.options[opt_CertVersion].activated) { |
|
2646 certVersion = PORT_Atoi(certutil.options[opt_CertVersion].arg); |
|
2647 if (certVersion < 1 || certVersion > 4) { |
|
2648 PR_fprintf(PR_STDERR, "%s -certVersion: incorrect certificate version %d.", |
|
2649 progName, certVersion); |
|
2650 PR_fprintf(PR_STDERR, "Must be 1, 2, 3 or 4.\n"); |
|
2651 return 255; |
|
2652 } |
|
2653 certVersion = certVersion - 1; |
|
2654 } |
|
2655 |
|
2656 |
|
2657 /* Check number of commands entered. */ |
|
2658 commandsEntered = 0; |
|
2659 for (i=0; i< certutil.numCommands; i++) { |
|
2660 if (certutil.commands[i].activated) { |
|
2661 commandToRun = certutil.commands[i].flag; |
|
2662 commandsEntered++; |
|
2663 } |
|
2664 if (commandsEntered > 1) |
|
2665 break; |
|
2666 } |
|
2667 if (commandsEntered > 1) { |
|
2668 PR_fprintf(PR_STDERR, "%s: only one command at a time!\n", progName); |
|
2669 PR_fprintf(PR_STDERR, "You entered: "); |
|
2670 for (i=0; i< certutil.numCommands; i++) { |
|
2671 if (certutil.commands[i].activated) |
|
2672 PR_fprintf(PR_STDERR, " -%c", certutil.commands[i].flag); |
|
2673 } |
|
2674 PR_fprintf(PR_STDERR, "\n"); |
|
2675 return 255; |
|
2676 } |
|
2677 if (commandsEntered == 0) { |
|
2678 Usage(progName); |
|
2679 } |
|
2680 |
|
2681 if (certutil.commands[cmd_ListCerts].activated || |
|
2682 certutil.commands[cmd_PrintHelp].activated || |
|
2683 certutil.commands[cmd_ListKeys].activated || |
|
2684 certutil.commands[cmd_ListModules].activated || |
|
2685 certutil.commands[cmd_CheckCertValidity].activated || |
|
2686 certutil.commands[cmd_Version].activated ) { |
|
2687 readOnly = !certutil.options[opt_RW].activated; |
|
2688 } |
|
2689 |
|
2690 /* -A, -D, -F, -M, -S, -V, and all require -n */ |
|
2691 if ((certutil.commands[cmd_AddCert].activated || |
|
2692 certutil.commands[cmd_DeleteCert].activated || |
|
2693 certutil.commands[cmd_DeleteKey].activated || |
|
2694 certutil.commands[cmd_DumpChain].activated || |
|
2695 certutil.commands[cmd_ModifyCertTrust].activated || |
|
2696 certutil.commands[cmd_CreateAndAddCert].activated || |
|
2697 certutil.commands[cmd_CheckCertValidity].activated) && |
|
2698 !certutil.options[opt_Nickname].activated) { |
|
2699 PR_fprintf(PR_STDERR, |
|
2700 "%s -%c: nickname is required for this command (-n).\n", |
|
2701 progName, commandToRun); |
|
2702 return 255; |
|
2703 } |
|
2704 |
|
2705 /* -A, -E, -M, -S require trust */ |
|
2706 if ((certutil.commands[cmd_AddCert].activated || |
|
2707 certutil.commands[cmd_AddEmailCert].activated || |
|
2708 certutil.commands[cmd_ModifyCertTrust].activated || |
|
2709 certutil.commands[cmd_CreateAndAddCert].activated) && |
|
2710 !certutil.options[opt_Trust].activated) { |
|
2711 PR_fprintf(PR_STDERR, |
|
2712 "%s -%c: trust is required for this command (-t).\n", |
|
2713 progName, commandToRun); |
|
2714 return 255; |
|
2715 } |
|
2716 |
|
2717 /* if -L is given raw, ascii or dump mode, it must be for only one cert. */ |
|
2718 if (certutil.commands[cmd_ListCerts].activated && |
|
2719 (certutil.options[opt_ASCIIForIO].activated || |
|
2720 certutil.options[opt_DumpExtensionValue].activated || |
|
2721 certutil.options[opt_BinaryDER].activated) && |
|
2722 !certutil.options[opt_Nickname].activated) { |
|
2723 PR_fprintf(PR_STDERR, |
|
2724 "%s: nickname is required to dump cert in raw or ascii mode.\n", |
|
2725 progName); |
|
2726 return 255; |
|
2727 } |
|
2728 |
|
2729 /* -L can only be in (raw || ascii). */ |
|
2730 if (certutil.commands[cmd_ListCerts].activated && |
|
2731 certutil.options[opt_ASCIIForIO].activated && |
|
2732 certutil.options[opt_BinaryDER].activated) { |
|
2733 PR_fprintf(PR_STDERR, |
|
2734 "%s: cannot specify both -r and -a when dumping cert.\n", |
|
2735 progName); |
|
2736 return 255; |
|
2737 } |
|
2738 |
|
2739 /* If making a cert request, need a subject. */ |
|
2740 if ((certutil.commands[cmd_CertReq].activated || |
|
2741 certutil.commands[cmd_CreateAndAddCert].activated) && |
|
2742 !(certutil.options[opt_Subject].activated || keysource)) { |
|
2743 PR_fprintf(PR_STDERR, |
|
2744 "%s -%c: subject is required to create a cert request.\n", |
|
2745 progName, commandToRun); |
|
2746 return 255; |
|
2747 } |
|
2748 |
|
2749 /* If making a cert, need a serial number. */ |
|
2750 if ((certutil.commands[cmd_CreateNewCert].activated || |
|
2751 certutil.commands[cmd_CreateAndAddCert].activated) && |
|
2752 !certutil.options[opt_SerialNumber].activated) { |
|
2753 /* Make a default serial number from the current time. */ |
|
2754 PRTime now = PR_Now(); |
|
2755 LL_USHR(now, now, 19); |
|
2756 LL_L2UI(serialNumber, now); |
|
2757 } |
|
2758 |
|
2759 /* Validation needs the usage to validate for. */ |
|
2760 if (certutil.commands[cmd_CheckCertValidity].activated && |
|
2761 !certutil.options[opt_Usage].activated) { |
|
2762 PR_fprintf(PR_STDERR, |
|
2763 "%s -V: specify a usage to validate the cert for (-u).\n", |
|
2764 progName); |
|
2765 return 255; |
|
2766 } |
|
2767 |
|
2768 /* Upgrade/Merge needs a source database and a upgrade id. */ |
|
2769 if (certutil.commands[cmd_UpgradeMerge].activated && |
|
2770 !(certutil.options[opt_SourceDir].activated && |
|
2771 certutil.options[opt_UpgradeID].activated)) { |
|
2772 |
|
2773 PR_fprintf(PR_STDERR, |
|
2774 "%s --upgrade-merge: specify an upgrade database directory " |
|
2775 "(--source-dir) and\n" |
|
2776 " an upgrade ID (--upgrade-id).\n", |
|
2777 progName); |
|
2778 return 255; |
|
2779 } |
|
2780 |
|
2781 /* Merge needs a source database */ |
|
2782 if (certutil.commands[cmd_Merge].activated && |
|
2783 !certutil.options[opt_SourceDir].activated) { |
|
2784 |
|
2785 |
|
2786 PR_fprintf(PR_STDERR, |
|
2787 "%s --merge: specify an source database directory " |
|
2788 "(--source-dir)\n", |
|
2789 progName); |
|
2790 return 255; |
|
2791 } |
|
2792 |
|
2793 |
|
2794 /* To make a cert, need either a issuer or to self-sign it. */ |
|
2795 if (certutil.commands[cmd_CreateAndAddCert].activated && |
|
2796 !(certutil.options[opt_IssuerName].activated || |
|
2797 certutil.options[opt_SelfSign].activated)) { |
|
2798 PR_fprintf(PR_STDERR, |
|
2799 "%s -S: must specify issuer (-c) or self-sign (-x).\n", |
|
2800 progName); |
|
2801 return 255; |
|
2802 } |
|
2803 |
|
2804 /* Using slotname == NULL for listing keys and certs on all slots, |
|
2805 * but only that. */ |
|
2806 if (!(certutil.commands[cmd_ListKeys].activated || |
|
2807 certutil.commands[cmd_DumpChain].activated || |
|
2808 certutil.commands[cmd_ListCerts].activated) && slotname == NULL) { |
|
2809 PR_fprintf(PR_STDERR, |
|
2810 "%s -%c: cannot use \"-h all\" for this command.\n", |
|
2811 progName, commandToRun); |
|
2812 return 255; |
|
2813 } |
|
2814 |
|
2815 /* Using keytype == nullKey for list all key types, but only that. */ |
|
2816 if (!certutil.commands[cmd_ListKeys].activated && keytype == nullKey) { |
|
2817 PR_fprintf(PR_STDERR, |
|
2818 "%s -%c: cannot use \"-k all\" for this command.\n", |
|
2819 progName, commandToRun); |
|
2820 return 255; |
|
2821 } |
|
2822 |
|
2823 /* Open the input file. */ |
|
2824 if (certutil.options[opt_InputFile].activated) { |
|
2825 inFile = PR_Open(certutil.options[opt_InputFile].arg, PR_RDONLY, 0); |
|
2826 if (!inFile) { |
|
2827 PR_fprintf(PR_STDERR, |
|
2828 "%s: unable to open \"%s\" for reading (%ld, %ld).\n", |
|
2829 progName, certutil.options[opt_InputFile].arg, |
|
2830 PR_GetError(), PR_GetOSError()); |
|
2831 return 255; |
|
2832 } |
|
2833 } |
|
2834 |
|
2835 /* Open the output file. */ |
|
2836 if (certutil.options[opt_OutputFile].activated) { |
|
2837 outFile = PR_Open(certutil.options[opt_OutputFile].arg, |
|
2838 PR_CREATE_FILE | PR_RDWR | PR_TRUNCATE, 00660); |
|
2839 if (!outFile) { |
|
2840 PR_fprintf(PR_STDERR, |
|
2841 "%s: unable to open \"%s\" for writing (%ld, %ld).\n", |
|
2842 progName, certutil.options[opt_OutputFile].arg, |
|
2843 PR_GetError(), PR_GetOSError()); |
|
2844 return 255; |
|
2845 } |
|
2846 } |
|
2847 |
|
2848 name = SECU_GetOptionArg(&certutil, opt_Nickname); |
|
2849 email = SECU_GetOptionArg(&certutil, opt_Emailaddress); |
|
2850 |
|
2851 PK11_SetPasswordFunc(SECU_GetModulePassword); |
|
2852 |
|
2853 if (PR_TRUE == initialize) { |
|
2854 /* Initialize NSPR and NSS. */ |
|
2855 PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); |
|
2856 if (!certutil.commands[cmd_UpgradeMerge].activated) { |
|
2857 rv = NSS_Initialize(SECU_ConfigDirectory(NULL), |
|
2858 certPrefix, certPrefix, |
|
2859 "secmod.db", readOnly ? NSS_INIT_READONLY: 0); |
|
2860 } else { |
|
2861 rv = NSS_InitWithMerge(SECU_ConfigDirectory(NULL), |
|
2862 certPrefix, certPrefix, "secmod.db", |
|
2863 sourceDir, srcCertPrefix, srcCertPrefix, |
|
2864 upgradeID, upgradeTokenName, |
|
2865 readOnly ? NSS_INIT_READONLY: 0); |
|
2866 } |
|
2867 if (rv != SECSuccess) { |
|
2868 SECU_PrintPRandOSError(progName); |
|
2869 rv = SECFailure; |
|
2870 goto shutdown; |
|
2871 } |
|
2872 initialized = PR_TRUE; |
|
2873 SECU_RegisterDynamicOids(); |
|
2874 } |
|
2875 certHandle = CERT_GetDefaultCertDB(); |
|
2876 |
|
2877 if (certutil.commands[cmd_Version].activated) { |
|
2878 printf("Certificate database content version: command not implemented.\n"); |
|
2879 } |
|
2880 |
|
2881 if (PL_strcmp(slotname, "internal") == 0) |
|
2882 slot = PK11_GetInternalKeySlot(); |
|
2883 else if (slotname != NULL) |
|
2884 slot = PK11_FindSlotByName(slotname); |
|
2885 |
|
2886 if ( !slot && (certutil.commands[cmd_NewDBs].activated || |
|
2887 certutil.commands[cmd_ModifyCertTrust].activated || |
|
2888 certutil.commands[cmd_ChangePassword].activated || |
|
2889 certutil.commands[cmd_TokenReset].activated || |
|
2890 certutil.commands[cmd_CreateAndAddCert].activated || |
|
2891 certutil.commands[cmd_AddCert].activated || |
|
2892 certutil.commands[cmd_Merge].activated || |
|
2893 certutil.commands[cmd_UpgradeMerge].activated || |
|
2894 certutil.commands[cmd_AddEmailCert].activated)) { |
|
2895 |
|
2896 SECU_PrintError(progName, "could not find the slot %s",slotname); |
|
2897 rv = SECFailure; |
|
2898 goto shutdown; |
|
2899 } |
|
2900 |
|
2901 /* If creating new database, initialize the password. */ |
|
2902 if (certutil.commands[cmd_NewDBs].activated) { |
|
2903 if(certutil.options[opt_EmptyPassword].activated && (PK11_NeedUserInit(slot))) |
|
2904 PK11_InitPin(slot, (char*)NULL, ""); |
|
2905 else |
|
2906 SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg, |
|
2907 certutil.options[opt_NewPasswordFile].arg); |
|
2908 } |
|
2909 |
|
2910 /* walk through the upgrade merge if necessary. |
|
2911 * This option is more to test what some applications will want to do |
|
2912 * to do an automatic upgrade. The --merge command is more useful for |
|
2913 * the general case where 2 database need to be merged together. |
|
2914 */ |
|
2915 if (certutil.commands[cmd_UpgradeMerge].activated) { |
|
2916 if (*upgradeTokenName == 0) { |
|
2917 upgradeTokenName = upgradeID; |
|
2918 } |
|
2919 if (!PK11_IsInternal(slot)) { |
|
2920 fprintf(stderr, "Only internal DB's can be upgraded\n"); |
|
2921 rv = SECSuccess; |
|
2922 goto shutdown; |
|
2923 } |
|
2924 if (!PK11_IsRemovable(slot)) { |
|
2925 printf("database already upgraded.\n"); |
|
2926 rv = SECSuccess; |
|
2927 goto shutdown; |
|
2928 } |
|
2929 if (!PK11_NeedLogin(slot)) { |
|
2930 printf("upgrade complete!\n"); |
|
2931 rv = SECSuccess; |
|
2932 goto shutdown; |
|
2933 } |
|
2934 /* authenticate to the old DB if necessary */ |
|
2935 if (PORT_Strcmp(PK11_GetTokenName(slot), upgradeTokenName) == 0) { |
|
2936 /* if we need a password, supply it. This will be the password |
|
2937 * for the old database */ |
|
2938 rv = PK11_Authenticate(slot, PR_FALSE, &pwdata2); |
|
2939 if (rv != SECSuccess) { |
|
2940 SECU_PrintError(progName, "Could not get password for %s", |
|
2941 upgradeTokenName); |
|
2942 goto shutdown; |
|
2943 } |
|
2944 /* |
|
2945 * if we succeeded above, but still aren't logged in, that means |
|
2946 * we just supplied the password for the old database. We may |
|
2947 * need the password for the new database. NSS will automatically |
|
2948 * change the token names at this point |
|
2949 */ |
|
2950 if (PK11_IsLoggedIn(slot, &pwdata)) { |
|
2951 printf("upgrade complete!\n"); |
|
2952 rv = SECSuccess; |
|
2953 goto shutdown; |
|
2954 } |
|
2955 } |
|
2956 |
|
2957 /* call PK11_IsPresent to update our cached token information */ |
|
2958 if (!PK11_IsPresent(slot)) { |
|
2959 /* this shouldn't happen. We call isPresent to force a token |
|
2960 * info update */ |
|
2961 fprintf(stderr, "upgrade/merge internal error\n"); |
|
2962 rv = SECFailure; |
|
2963 goto shutdown; |
|
2964 } |
|
2965 |
|
2966 /* the token is now set to the state of the source database, |
|
2967 * if we need a password for it, PK11_Authenticate will |
|
2968 * automatically prompt us */ |
|
2969 rv = PK11_Authenticate(slot, PR_FALSE, &pwdata); |
|
2970 if (rv == SECSuccess) { |
|
2971 printf("upgrade complete!\n"); |
|
2972 } else { |
|
2973 SECU_PrintError(progName, "Could not get password for %s", |
|
2974 PK11_GetTokenName(slot)); |
|
2975 } |
|
2976 goto shutdown; |
|
2977 } |
|
2978 |
|
2979 /* |
|
2980 * merge 2 databases. |
|
2981 */ |
|
2982 if (certutil.commands[cmd_Merge].activated) { |
|
2983 PK11SlotInfo *sourceSlot = NULL; |
|
2984 PK11MergeLog *log; |
|
2985 char *modspec = PR_smprintf( |
|
2986 "configDir='%s' certPrefix='%s' tokenDescription='%s'", |
|
2987 sourceDir, srcCertPrefix, |
|
2988 *upgradeTokenName ? upgradeTokenName : "Source Database"); |
|
2989 |
|
2990 if (!modspec) { |
|
2991 rv = SECFailure; |
|
2992 goto shutdown; |
|
2993 } |
|
2994 |
|
2995 sourceSlot = SECMOD_OpenUserDB(modspec); |
|
2996 PR_smprintf_free(modspec); |
|
2997 if (!sourceSlot) { |
|
2998 SECU_PrintError(progName, "couldn't open source database"); |
|
2999 rv = SECFailure; |
|
3000 goto shutdown; |
|
3001 } |
|
3002 |
|
3003 rv = PK11_Authenticate(slot, PR_FALSE, &pwdata); |
|
3004 if (rv != SECSuccess) { |
|
3005 SECU_PrintError(progName, "Couldn't get password for %s", |
|
3006 PK11_GetTokenName(slot)); |
|
3007 goto merge_fail; |
|
3008 } |
|
3009 |
|
3010 rv = PK11_Authenticate(sourceSlot, PR_FALSE, &pwdata2); |
|
3011 if (rv != SECSuccess) { |
|
3012 SECU_PrintError(progName, "Couldn't get password for %s", |
|
3013 PK11_GetTokenName(sourceSlot)); |
|
3014 goto merge_fail; |
|
3015 } |
|
3016 |
|
3017 log = PK11_CreateMergeLog(); |
|
3018 if (!log) { |
|
3019 rv = SECFailure; |
|
3020 SECU_PrintError(progName, "couldn't create error log"); |
|
3021 goto merge_fail; |
|
3022 } |
|
3023 |
|
3024 rv = PK11_MergeTokens(slot, sourceSlot, log, &pwdata, &pwdata2); |
|
3025 if (rv != SECSuccess) { |
|
3026 DumpMergeLog(progName, log); |
|
3027 } |
|
3028 PK11_DestroyMergeLog(log); |
|
3029 |
|
3030 merge_fail: |
|
3031 SECMOD_CloseUserDB(sourceSlot); |
|
3032 PK11_FreeSlot(sourceSlot); |
|
3033 goto shutdown; |
|
3034 } |
|
3035 |
|
3036 /* The following 8 options are mutually exclusive with all others. */ |
|
3037 |
|
3038 /* List certs (-L) */ |
|
3039 if (certutil.commands[cmd_ListCerts].activated) { |
|
3040 if (certutil.options[opt_DumpExtensionValue].activated) { |
|
3041 const char *oid_str; |
|
3042 SECItem oid_item; |
|
3043 SECStatus srv; |
|
3044 oid_item.data = NULL; |
|
3045 oid_item.len = 0; |
|
3046 oid_str = certutil.options[opt_DumpExtensionValue].arg; |
|
3047 srv = GetOidFromString(NULL, &oid_item, oid_str, strlen(oid_str)); |
|
3048 if (srv != SECSuccess) { |
|
3049 SECU_PrintError(progName, "malformed extension OID %s", |
|
3050 oid_str); |
|
3051 goto shutdown; |
|
3052 } |
|
3053 rv = ListCerts(certHandle, name, email, slot, |
|
3054 PR_TRUE /*binary*/, PR_FALSE /*ascii*/, |
|
3055 &oid_item, |
|
3056 outFile, &pwdata); |
|
3057 } else { |
|
3058 rv = ListCerts(certHandle, name, email, slot, |
|
3059 certutil.options[opt_BinaryDER].activated, |
|
3060 certutil.options[opt_ASCIIForIO].activated, |
|
3061 NULL, outFile, &pwdata); |
|
3062 } |
|
3063 goto shutdown; |
|
3064 } |
|
3065 if (certutil.commands[cmd_DumpChain].activated) { |
|
3066 rv = DumpChain(certHandle, name, |
|
3067 certutil.options[opt_ASCIIForIO].activated); |
|
3068 goto shutdown; |
|
3069 } |
|
3070 /* XXX needs work */ |
|
3071 /* List keys (-K) */ |
|
3072 if (certutil.commands[cmd_ListKeys].activated) { |
|
3073 rv = ListKeys(slot, name, 0 /*keyindex*/, keytype, PR_FALSE /*dopriv*/, |
|
3074 &pwdata); |
|
3075 goto shutdown; |
|
3076 } |
|
3077 /* List modules (-U) */ |
|
3078 if (certutil.commands[cmd_ListModules].activated) { |
|
3079 rv = ListModules(); |
|
3080 goto shutdown; |
|
3081 } |
|
3082 /* Delete cert (-D) */ |
|
3083 if (certutil.commands[cmd_DeleteCert].activated) { |
|
3084 rv = DeleteCert(certHandle, name); |
|
3085 goto shutdown; |
|
3086 } |
|
3087 /* Delete key (-F) */ |
|
3088 if (certutil.commands[cmd_DeleteKey].activated) { |
|
3089 rv = DeleteKey(name, &pwdata); |
|
3090 goto shutdown; |
|
3091 } |
|
3092 /* Modify trust attribute for cert (-M) */ |
|
3093 if (certutil.commands[cmd_ModifyCertTrust].activated) { |
|
3094 rv = ChangeTrustAttributes(certHandle, slot, name, |
|
3095 certutil.options[opt_Trust].arg, &pwdata); |
|
3096 goto shutdown; |
|
3097 } |
|
3098 /* Change key db password (-W) (future - change pw to slot?) */ |
|
3099 if (certutil.commands[cmd_ChangePassword].activated) { |
|
3100 rv = SECU_ChangePW2(slot, 0, 0, certutil.options[opt_PasswordFile].arg, |
|
3101 certutil.options[opt_NewPasswordFile].arg); |
|
3102 goto shutdown; |
|
3103 } |
|
3104 /* Reset the a token */ |
|
3105 if (certutil.commands[cmd_TokenReset].activated) { |
|
3106 char *sso_pass = ""; |
|
3107 |
|
3108 if (certutil.options[opt_SSOPass].activated) { |
|
3109 sso_pass = certutil.options[opt_SSOPass].arg; |
|
3110 } |
|
3111 rv = PK11_ResetToken(slot,sso_pass); |
|
3112 |
|
3113 goto shutdown; |
|
3114 } |
|
3115 /* Check cert validity against current time (-V) */ |
|
3116 if (certutil.commands[cmd_CheckCertValidity].activated) { |
|
3117 /* XXX temporary hack for fips - must log in to get priv key */ |
|
3118 if (certutil.options[opt_VerifySig].activated) { |
|
3119 if (slot && PK11_NeedLogin(slot)) { |
|
3120 SECStatus newrv = PK11_Authenticate(slot, PR_TRUE, &pwdata); |
|
3121 if (newrv != SECSuccess) { |
|
3122 SECU_PrintError(progName, "could not authenticate to token %s.", |
|
3123 PK11_GetTokenName(slot)); |
|
3124 goto shutdown; |
|
3125 } |
|
3126 } |
|
3127 } |
|
3128 rv = ValidateCert(certHandle, name, |
|
3129 certutil.options[opt_ValidityTime].arg, |
|
3130 certutil.options[opt_Usage].arg, |
|
3131 certutil.options[opt_VerifySig].activated, |
|
3132 certutil.options[opt_DetailedInfo].activated, |
|
3133 certutil.options[opt_ASCIIForIO].activated, |
|
3134 &pwdata); |
|
3135 if (rv != SECSuccess && PR_GetError() == SEC_ERROR_INVALID_ARGS) |
|
3136 SECU_PrintError(progName, "validation failed"); |
|
3137 goto shutdown; |
|
3138 } |
|
3139 |
|
3140 /* |
|
3141 * Key generation |
|
3142 */ |
|
3143 |
|
3144 /* These commands may require keygen. */ |
|
3145 if (certutil.commands[cmd_CertReq].activated || |
|
3146 certutil.commands[cmd_CreateAndAddCert].activated || |
|
3147 certutil.commands[cmd_GenKeyPair].activated) { |
|
3148 if (keysource) { |
|
3149 CERTCertificate *keycert; |
|
3150 keycert = CERT_FindCertByNicknameOrEmailAddr(certHandle, keysource); |
|
3151 if (!keycert) { |
|
3152 keycert = PK11_FindCertFromNickname(keysource, NULL); |
|
3153 if (!keycert) { |
|
3154 SECU_PrintError(progName, |
|
3155 "%s is neither a key-type nor a nickname", keysource); |
|
3156 return SECFailure; |
|
3157 } |
|
3158 } |
|
3159 privkey = PK11_FindKeyByDERCert(slot, keycert, &pwdata); |
|
3160 if (privkey) |
|
3161 pubkey = CERT_ExtractPublicKey(keycert); |
|
3162 if (!pubkey) { |
|
3163 SECU_PrintError(progName, |
|
3164 "Could not get keys from cert %s", keysource); |
|
3165 rv = SECFailure; |
|
3166 CERT_DestroyCertificate(keycert); |
|
3167 goto shutdown; |
|
3168 } |
|
3169 keytype = privkey->keyType; |
|
3170 /* On CertReq for renewal if no subject has been |
|
3171 * specified obtain it from the certificate. |
|
3172 */ |
|
3173 if (certutil.commands[cmd_CertReq].activated && !subject) { |
|
3174 subject = CERT_AsciiToName(keycert->subjectName); |
|
3175 if (!subject) { |
|
3176 SECU_PrintError(progName, |
|
3177 "Could not get subject from certificate %s", keysource); |
|
3178 CERT_DestroyCertificate(keycert); |
|
3179 rv = SECFailure; |
|
3180 goto shutdown; |
|
3181 } |
|
3182 } |
|
3183 CERT_DestroyCertificate(keycert); |
|
3184 } else { |
|
3185 privkey = |
|
3186 CERTUTIL_GeneratePrivateKey(keytype, slot, keysize, |
|
3187 publicExponent, |
|
3188 certutil.options[opt_NoiseFile].arg, |
|
3189 &pubkey, |
|
3190 certutil.options[opt_PQGFile].arg, |
|
3191 keyAttrFlags, |
|
3192 keyOpFlagsOn, |
|
3193 keyOpFlagsOff, |
|
3194 &pwdata); |
|
3195 if (privkey == NULL) { |
|
3196 SECU_PrintError(progName, "unable to generate key(s)\n"); |
|
3197 rv = SECFailure; |
|
3198 goto shutdown; |
|
3199 } |
|
3200 } |
|
3201 privkey->wincx = &pwdata; |
|
3202 PORT_Assert(pubkey != NULL); |
|
3203 |
|
3204 /* If all that was needed was keygen, exit. */ |
|
3205 if (certutil.commands[cmd_GenKeyPair].activated) { |
|
3206 rv = SECSuccess; |
|
3207 goto shutdown; |
|
3208 } |
|
3209 } |
|
3210 |
|
3211 /* If we need a list of extensions convert the flags into list format */ |
|
3212 if (certutil.commands[cmd_CertReq].activated || |
|
3213 certutil.commands[cmd_CreateAndAddCert].activated || |
|
3214 certutil.commands[cmd_CreateNewCert].activated) { |
|
3215 certutil_extns[ext_keyUsage].activated = |
|
3216 certutil.options[opt_AddCmdKeyUsageExt].activated; |
|
3217 if (!certutil_extns[ext_keyUsage].activated) { |
|
3218 certutil_extns[ext_keyUsage].activated = |
|
3219 certutil.options[opt_AddKeyUsageExt].activated; |
|
3220 } else { |
|
3221 certutil_extns[ext_keyUsage].arg = |
|
3222 certutil.options[opt_AddCmdKeyUsageExt].arg; |
|
3223 } |
|
3224 certutil_extns[ext_basicConstraint].activated = |
|
3225 certutil.options[opt_AddBasicConstraintExt].activated; |
|
3226 certutil_extns[ext_nameConstraints].activated = |
|
3227 certutil.options[opt_AddNameConstraintsExt].activated; |
|
3228 certutil_extns[ext_authorityKeyID].activated = |
|
3229 certutil.options[opt_AddAuthorityKeyIDExt].activated; |
|
3230 certutil_extns[ext_subjectKeyID].activated = |
|
3231 certutil.options[opt_AddSubjectKeyIDExt].activated; |
|
3232 certutil_extns[ext_CRLDistPts].activated = |
|
3233 certutil.options[opt_AddCRLDistPtsExt].activated; |
|
3234 certutil_extns[ext_NSCertType].activated = |
|
3235 certutil.options[opt_AddCmdNSCertTypeExt].activated; |
|
3236 if (!certutil_extns[ext_NSCertType].activated) { |
|
3237 certutil_extns[ext_NSCertType].activated = |
|
3238 certutil.options[opt_AddNSCertTypeExt].activated; |
|
3239 } else { |
|
3240 certutil_extns[ext_NSCertType].arg = |
|
3241 certutil.options[opt_AddCmdNSCertTypeExt].arg; |
|
3242 } |
|
3243 |
|
3244 certutil_extns[ext_extKeyUsage].activated = |
|
3245 certutil.options[opt_AddCmdExtKeyUsageExt].activated; |
|
3246 if (!certutil_extns[ext_extKeyUsage].activated) { |
|
3247 certutil_extns[ext_extKeyUsage].activated = |
|
3248 certutil.options[opt_AddExtKeyUsageExt].activated; |
|
3249 } else { |
|
3250 certutil_extns[ext_extKeyUsage].arg = |
|
3251 certutil.options[opt_AddCmdExtKeyUsageExt].arg; |
|
3252 } |
|
3253 certutil_extns[ext_subjectAltName].activated = |
|
3254 certutil.options[opt_AddSubjectAltNameExt].activated; |
|
3255 if (certutil_extns[ext_subjectAltName].activated) { |
|
3256 certutil_extns[ext_subjectAltName].arg = |
|
3257 certutil.options[opt_AddSubjectAltNameExt].arg; |
|
3258 } |
|
3259 |
|
3260 certutil_extns[ext_authInfoAcc].activated = |
|
3261 certutil.options[opt_AddAuthInfoAccExt].activated; |
|
3262 certutil_extns[ext_subjInfoAcc].activated = |
|
3263 certutil.options[opt_AddSubjInfoAccExt].activated; |
|
3264 certutil_extns[ext_certPolicies].activated = |
|
3265 certutil.options[opt_AddCertPoliciesExt].activated; |
|
3266 certutil_extns[ext_policyMappings].activated = |
|
3267 certutil.options[opt_AddPolicyMapExt].activated; |
|
3268 certutil_extns[ext_policyConstr].activated = |
|
3269 certutil.options[opt_AddPolicyConstrExt].activated; |
|
3270 certutil_extns[ext_inhibitAnyPolicy].activated = |
|
3271 certutil.options[opt_AddInhibAnyExt].activated; |
|
3272 } |
|
3273 |
|
3274 /* -A -C or -E Read inFile */ |
|
3275 if (certutil.commands[cmd_CreateNewCert].activated || |
|
3276 certutil.commands[cmd_AddCert].activated || |
|
3277 certutil.commands[cmd_AddEmailCert].activated) { |
|
3278 PRBool isCreate = certutil.commands[cmd_CreateNewCert].activated; |
|
3279 rv = SECU_ReadDERFromFile(isCreate ? &certReqDER : &certDER, inFile, |
|
3280 certutil.options[opt_ASCIIForIO].activated, |
|
3281 PR_TRUE); |
|
3282 if (rv) |
|
3283 goto shutdown; |
|
3284 } |
|
3285 |
|
3286 /* |
|
3287 * Certificate request |
|
3288 */ |
|
3289 |
|
3290 /* Make a cert request (-R). */ |
|
3291 if (certutil.commands[cmd_CertReq].activated) { |
|
3292 rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject, |
|
3293 certutil.options[opt_PhoneNumber].arg, |
|
3294 certutil.options[opt_ASCIIForIO].activated, |
|
3295 certutil.options[opt_ExtendedEmailAddrs].arg, |
|
3296 certutil.options[opt_ExtendedDNSNames].arg, |
|
3297 certutil_extns, |
|
3298 (certutil.options[opt_GenericExtensions].activated ? |
|
3299 certutil.options[opt_GenericExtensions].arg : NULL), |
|
3300 &certReqDER); |
|
3301 if (rv) |
|
3302 goto shutdown; |
|
3303 privkey->wincx = &pwdata; |
|
3304 } |
|
3305 |
|
3306 /* |
|
3307 * Certificate creation |
|
3308 */ |
|
3309 |
|
3310 /* If making and adding a cert, create a cert request file first without |
|
3311 * any extensions, then load it with the command line extensions |
|
3312 * and output the cert to another file. |
|
3313 */ |
|
3314 if (certutil.commands[cmd_CreateAndAddCert].activated) { |
|
3315 static certutilExtnList nullextnlist = {{PR_FALSE, NULL}}; |
|
3316 rv = CertReq(privkey, pubkey, keytype, hashAlgTag, subject, |
|
3317 certutil.options[opt_PhoneNumber].arg, |
|
3318 PR_FALSE, /* do not BASE64-encode regardless of -a option */ |
|
3319 NULL, |
|
3320 NULL, |
|
3321 nullextnlist, |
|
3322 (certutil.options[opt_GenericExtensions].activated ? |
|
3323 certutil.options[opt_GenericExtensions].arg : NULL), |
|
3324 &certReqDER); |
|
3325 if (rv) |
|
3326 goto shutdown; |
|
3327 privkey->wincx = &pwdata; |
|
3328 } |
|
3329 |
|
3330 /* Create a certificate (-C or -S). */ |
|
3331 if (certutil.commands[cmd_CreateAndAddCert].activated || |
|
3332 certutil.commands[cmd_CreateNewCert].activated) { |
|
3333 rv = CreateCert(certHandle, slot, |
|
3334 certutil.options[opt_IssuerName].arg, |
|
3335 &certReqDER, &privkey, &pwdata, hashAlgTag, |
|
3336 serialNumber, warpmonths, validityMonths, |
|
3337 certutil.options[opt_ExtendedEmailAddrs].arg, |
|
3338 certutil.options[opt_ExtendedDNSNames].arg, |
|
3339 certutil.options[opt_ASCIIForIO].activated && |
|
3340 certutil.commands[cmd_CreateNewCert].activated, |
|
3341 certutil.options[opt_SelfSign].activated, |
|
3342 certutil_extns, |
|
3343 (certutil.options[opt_GenericExtensions].activated ? |
|
3344 certutil.options[opt_GenericExtensions].arg : NULL), |
|
3345 certVersion, |
|
3346 &certDER); |
|
3347 if (rv) |
|
3348 goto shutdown; |
|
3349 } |
|
3350 |
|
3351 /* |
|
3352 * Adding a cert to the database (or slot) |
|
3353 */ |
|
3354 |
|
3355 /* -A -E or -S Add the cert to the DB */ |
|
3356 if (certutil.commands[cmd_CreateAndAddCert].activated || |
|
3357 certutil.commands[cmd_AddCert].activated || |
|
3358 certutil.commands[cmd_AddEmailCert].activated) { |
|
3359 if (strstr(certutil.options[opt_Trust].arg, "u")) { |
|
3360 fprintf(stderr, "Notice: Trust flag u is set automatically if the " |
|
3361 "private key is present.\n"); |
|
3362 } |
|
3363 rv = AddCert(slot, certHandle, name, |
|
3364 certutil.options[opt_Trust].arg, |
|
3365 &certDER, |
|
3366 certutil.commands[cmd_AddEmailCert].activated,&pwdata); |
|
3367 if (rv) |
|
3368 goto shutdown; |
|
3369 } |
|
3370 |
|
3371 if (certutil.commands[cmd_CertReq].activated || |
|
3372 certutil.commands[cmd_CreateNewCert].activated) { |
|
3373 SECItem * item = certutil.commands[cmd_CertReq].activated ? &certReqDER |
|
3374 : &certDER; |
|
3375 PRInt32 written = PR_Write(outFile, item->data, item->len); |
|
3376 if (written < 0 || (PRUint32) written != item->len) { |
|
3377 rv = SECFailure; |
|
3378 } |
|
3379 } |
|
3380 |
|
3381 shutdown: |
|
3382 if (slot) { |
|
3383 PK11_FreeSlot(slot); |
|
3384 } |
|
3385 if (privkey) { |
|
3386 SECKEY_DestroyPrivateKey(privkey); |
|
3387 } |
|
3388 if (pubkey) { |
|
3389 SECKEY_DestroyPublicKey(pubkey); |
|
3390 } |
|
3391 if (subject) { |
|
3392 CERT_DestroyName(subject); |
|
3393 } |
|
3394 if (name) { |
|
3395 PL_strfree(name); |
|
3396 } |
|
3397 if (inFile && inFile != PR_STDIN) { |
|
3398 PR_Close(inFile); |
|
3399 } |
|
3400 if (outFile && outFile != PR_STDOUT) { |
|
3401 PR_Close(outFile); |
|
3402 } |
|
3403 SECITEM_FreeItem(&certReqDER, PR_FALSE); |
|
3404 SECITEM_FreeItem(&certDER, PR_FALSE); |
|
3405 if (pwdata.data && pwdata.source == PW_PLAINTEXT) { |
|
3406 /* Allocated by a PL_strdup call in SECU_GetModulePassword. */ |
|
3407 PL_strfree(pwdata.data); |
|
3408 } |
|
3409 |
|
3410 /* Open the batch command file. |
|
3411 * |
|
3412 * - If -B <command line> option is specified, the contents in the |
|
3413 * command file will be interpreted as subsequent certutil |
|
3414 * commands to be executed in the current certutil process |
|
3415 * context after the current certutil command has been executed. |
|
3416 * - Each line in the command file consists of the command |
|
3417 * line arguments for certutil. |
|
3418 * - The -d <configdir> option will be ignored if specified in the |
|
3419 * command file. |
|
3420 * - Quoting with double quote characters ("...") is supported |
|
3421 * to allow white space in a command line argument. The |
|
3422 * double quote character cannot be escaped and quoting cannot |
|
3423 * be nested in this version. |
|
3424 * - each line in the batch file is limited to 512 characters |
|
3425 */ |
|
3426 |
|
3427 if ((SECSuccess == rv) && certutil.commands[cmd_Batch].activated) { |
|
3428 FILE* batchFile = NULL; |
|
3429 char *nextcommand = NULL; |
|
3430 PRInt32 cmd_len = 0, buf_size = 0; |
|
3431 static const int increment = 512; |
|
3432 |
|
3433 if (!certutil.options[opt_InputFile].activated || |
|
3434 !certutil.options[opt_InputFile].arg) { |
|
3435 PR_fprintf(PR_STDERR, |
|
3436 "%s: no batch input file specified.\n", |
|
3437 progName); |
|
3438 return 255; |
|
3439 } |
|
3440 batchFile = fopen(certutil.options[opt_InputFile].arg, "r"); |
|
3441 if (!batchFile) { |
|
3442 PR_fprintf(PR_STDERR, |
|
3443 "%s: unable to open \"%s\" for reading (%ld, %ld).\n", |
|
3444 progName, certutil.options[opt_InputFile].arg, |
|
3445 PR_GetError(), PR_GetOSError()); |
|
3446 return 255; |
|
3447 } |
|
3448 /* read and execute command-lines in a loop */ |
|
3449 while ( SECSuccess == rv ) { |
|
3450 PRBool invalid = PR_FALSE; |
|
3451 int newargc = 2; |
|
3452 char* space = NULL; |
|
3453 char* nextarg = NULL; |
|
3454 char** newargv = NULL; |
|
3455 char* crlf; |
|
3456 |
|
3457 if (cmd_len + increment > buf_size) { |
|
3458 char * new_buf; |
|
3459 buf_size += increment; |
|
3460 new_buf = PORT_Realloc(nextcommand, buf_size); |
|
3461 if (!new_buf) { |
|
3462 PR_fprintf(PR_STDERR, "%s: PORT_Realloc(%ld) failed\n", |
|
3463 progName, buf_size); |
|
3464 break; |
|
3465 } |
|
3466 nextcommand = new_buf; |
|
3467 nextcommand[cmd_len] = '\0'; |
|
3468 } |
|
3469 if (!fgets(nextcommand + cmd_len, buf_size - cmd_len, batchFile)) { |
|
3470 break; |
|
3471 } |
|
3472 crlf = PORT_Strrchr(nextcommand, '\n'); |
|
3473 if (crlf) { |
|
3474 *crlf = '\0'; |
|
3475 } |
|
3476 cmd_len = strlen(nextcommand); |
|
3477 if (cmd_len && nextcommand[cmd_len - 1] == '\\') { |
|
3478 nextcommand[--cmd_len] = '\0'; |
|
3479 continue; |
|
3480 } |
|
3481 |
|
3482 /* we now need to split the command into argc / argv format */ |
|
3483 |
|
3484 newargv = PORT_Alloc(sizeof(char*)*(newargc+1)); |
|
3485 newargv[0] = progName; |
|
3486 newargv[1] = nextcommand; |
|
3487 nextarg = nextcommand; |
|
3488 while ((space = PORT_Strpbrk(nextarg, " \f\n\r\t\v")) ) { |
|
3489 while (isspace(*space) ) { |
|
3490 *space = '\0'; |
|
3491 space ++; |
|
3492 } |
|
3493 if (*space == '\0') { |
|
3494 break; |
|
3495 } else if (*space != '\"') { |
|
3496 nextarg = space; |
|
3497 } else { |
|
3498 char* closingquote = strchr(space+1, '\"'); |
|
3499 if (closingquote) { |
|
3500 *closingquote = '\0'; |
|
3501 space++; |
|
3502 nextarg = closingquote+1; |
|
3503 } else { |
|
3504 invalid = PR_TRUE; |
|
3505 nextarg = space; |
|
3506 } |
|
3507 } |
|
3508 newargc++; |
|
3509 newargv = PORT_Realloc(newargv, sizeof(char*)*(newargc+1)); |
|
3510 newargv[newargc-1] = space; |
|
3511 } |
|
3512 newargv[newargc] = NULL; |
|
3513 |
|
3514 /* invoke next command */ |
|
3515 if (PR_TRUE == invalid) { |
|
3516 PR_fprintf(PR_STDERR, "Missing closing quote in batch command :\n%s\nNot executed.\n", |
|
3517 nextcommand); |
|
3518 rv = SECFailure; |
|
3519 } else { |
|
3520 if (0 != certutil_main(newargc, newargv, PR_FALSE) ) |
|
3521 rv = SECFailure; |
|
3522 } |
|
3523 PORT_Free(newargv); |
|
3524 cmd_len = 0; |
|
3525 nextcommand[0] = '\0'; |
|
3526 } |
|
3527 PORT_Free(nextcommand); |
|
3528 fclose(batchFile); |
|
3529 } |
|
3530 |
|
3531 if ((initialized == PR_TRUE) && NSS_Shutdown() != SECSuccess) { |
|
3532 exit(1); |
|
3533 } |
|
3534 if (rv == SECSuccess) { |
|
3535 return 0; |
|
3536 } else { |
|
3537 return 255; |
|
3538 } |
|
3539 } |
|
3540 |
|
3541 int |
|
3542 main(int argc, char **argv) |
|
3543 { |
|
3544 int rv = certutil_main(argc, argv, PR_TRUE); |
|
3545 PL_ArenaFinish(); |
|
3546 PR_Cleanup(); |
|
3547 return rv; |
|
3548 } |
|
3549 |