1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/crlutil/crlutil.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,1109 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 +** certutil.c 1.10 +** 1.11 +** utility for managing certificates and the cert database 1.12 +** 1.13 +*/ 1.14 +/* test only */ 1.15 + 1.16 +#include "nspr.h" 1.17 +#include "plgetopt.h" 1.18 +#include "secutil.h" 1.19 +#include "cert.h" 1.20 +#include "certi.h" 1.21 +#include "certdb.h" 1.22 +#include "nss.h" 1.23 +#include "pk11func.h" 1.24 +#include "crlgen.h" 1.25 + 1.26 +#define SEC_CERT_DB_EXISTS 0 1.27 +#define SEC_CREATE_CERT_DB 1 1.28 + 1.29 +static char *progName; 1.30 + 1.31 +static CERTSignedCrl *FindCRL 1.32 + (CERTCertDBHandle *certHandle, char *name, int type) 1.33 +{ 1.34 + CERTSignedCrl *crl = NULL; 1.35 + CERTCertificate *cert = NULL; 1.36 + SECItem derName; 1.37 + 1.38 + derName.data = NULL; 1.39 + derName.len = 0; 1.40 + 1.41 + cert = CERT_FindCertByNicknameOrEmailAddr(certHandle, name); 1.42 + if (!cert) { 1.43 + CERTName *certName = NULL; 1.44 + PLArenaPool *arena = NULL; 1.45 + 1.46 + certName = CERT_AsciiToName(name); 1.47 + if (certName) { 1.48 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.49 + if (arena) { 1.50 + SECItem *nameItem = 1.51 + SEC_ASN1EncodeItem (arena, NULL, (void *)certName, 1.52 + SEC_ASN1_GET(CERT_NameTemplate)); 1.53 + if (nameItem) { 1.54 + SECITEM_CopyItem(NULL, &derName, nameItem); 1.55 + } 1.56 + PORT_FreeArena(arena, PR_FALSE); 1.57 + } 1.58 + CERT_DestroyName(certName); 1.59 + } 1.60 + 1.61 + if (!derName.len || !derName.data) { 1.62 + SECU_PrintError(progName, "could not find certificate named '%s'", name); 1.63 + return ((CERTSignedCrl *)NULL); 1.64 + } 1.65 + } else { 1.66 + SECITEM_CopyItem(NULL, &derName, &cert->derSubject); 1.67 + CERT_DestroyCertificate (cert); 1.68 + } 1.69 + 1.70 + crl = SEC_FindCrlByName(certHandle, &derName, type); 1.71 + if (crl ==NULL) 1.72 + SECU_PrintError 1.73 + (progName, "could not find %s's CRL", name); 1.74 + if (derName.data) { 1.75 + SECITEM_FreeItem(&derName, PR_FALSE); 1.76 + } 1.77 + return (crl); 1.78 +} 1.79 + 1.80 +static SECStatus DisplayCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType) 1.81 +{ 1.82 + CERTSignedCrl *crl = NULL; 1.83 + 1.84 + crl = FindCRL (certHandle, nickName, crlType); 1.85 + 1.86 + if (crl) { 1.87 + SECU_PrintCRLInfo (stdout, &crl->crl, "CRL Info:\n", 0); 1.88 + SEC_DestroyCrl (crl); 1.89 + return SECSuccess; 1.90 + } 1.91 + return SECFailure; 1.92 +} 1.93 + 1.94 +static void ListCRLNames (CERTCertDBHandle *certHandle, int crlType, PRBool deletecrls) 1.95 +{ 1.96 + CERTCrlHeadNode *crlList = NULL; 1.97 + CERTCrlNode *crlNode = NULL; 1.98 + CERTName *name = NULL; 1.99 + PLArenaPool *arena = NULL; 1.100 + SECStatus rv; 1.101 + 1.102 + do { 1.103 + arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); 1.104 + if (arena == NULL) { 1.105 + fprintf(stderr, "%s: fail to allocate memory\n", progName); 1.106 + break; 1.107 + } 1.108 + 1.109 + name = PORT_ArenaZAlloc (arena, sizeof(*name)); 1.110 + if (name == NULL) { 1.111 + fprintf(stderr, "%s: fail to allocate memory\n", progName); 1.112 + break; 1.113 + } 1.114 + name->arena = arena; 1.115 + 1.116 + rv = SEC_LookupCrls (certHandle, &crlList, crlType); 1.117 + if (rv != SECSuccess) { 1.118 + fprintf(stderr, "%s: fail to look up CRLs (%s)\n", progName, 1.119 + SECU_Strerror(PORT_GetError())); 1.120 + break; 1.121 + } 1.122 + 1.123 + /* just in case */ 1.124 + if (!crlList) 1.125 + break; 1.126 + 1.127 + crlNode = crlList->first; 1.128 + 1.129 + fprintf (stdout, "\n"); 1.130 + fprintf (stdout, "\n%-40s %-5s\n\n", "CRL names", "CRL Type"); 1.131 + while (crlNode) { 1.132 + char* asciiname = NULL; 1.133 + CERTCertificate *cert = NULL; 1.134 + if (crlNode->crl && &crlNode->crl->crl.derName) { 1.135 + cert = CERT_FindCertByName(certHandle, 1.136 + &crlNode->crl->crl.derName); 1.137 + if (!cert) { 1.138 + SECU_PrintError(progName, "could not find signing " 1.139 + "certificate in database"); 1.140 + } 1.141 + } 1.142 + if (cert) { 1.143 + char* certName = NULL; 1.144 + if (cert->nickname && PORT_Strlen(cert->nickname) > 0) { 1.145 + certName = cert->nickname; 1.146 + } else if (cert->emailAddr && PORT_Strlen(cert->emailAddr) > 0) { 1.147 + certName = cert->emailAddr; 1.148 + } 1.149 + if (certName) { 1.150 + asciiname = PORT_Strdup(certName); 1.151 + } 1.152 + CERT_DestroyCertificate(cert); 1.153 + } 1.154 + 1.155 + if (!asciiname) { 1.156 + name = &crlNode->crl->crl.name; 1.157 + if (!name){ 1.158 + SECU_PrintError(progName, "fail to get the CRL " 1.159 + "issuer name"); 1.160 + continue; 1.161 + } 1.162 + asciiname = CERT_NameToAscii(name); 1.163 + } 1.164 + fprintf (stdout, "%-40s %-5s\n", asciiname, "CRL"); 1.165 + if (asciiname) { 1.166 + PORT_Free(asciiname); 1.167 + } 1.168 + if ( PR_TRUE == deletecrls) { 1.169 + CERTSignedCrl* acrl = NULL; 1.170 + SECItem* issuer = &crlNode->crl->crl.derName; 1.171 + acrl = SEC_FindCrlByName(certHandle, issuer, crlType); 1.172 + if (acrl) 1.173 + { 1.174 + SEC_DeletePermCRL(acrl); 1.175 + SEC_DestroyCrl(acrl); 1.176 + } 1.177 + } 1.178 + crlNode = crlNode->next; 1.179 + } 1.180 + 1.181 + } while (0); 1.182 + if (crlList) 1.183 + PORT_FreeArena (crlList->arena, PR_FALSE); 1.184 + PORT_FreeArena (arena, PR_FALSE); 1.185 +} 1.186 + 1.187 +static SECStatus ListCRL (CERTCertDBHandle *certHandle, char *nickName, int crlType) 1.188 +{ 1.189 + if (nickName == NULL) { 1.190 + ListCRLNames (certHandle, crlType, PR_FALSE); 1.191 + return SECSuccess; 1.192 + } 1.193 + 1.194 + return DisplayCRL (certHandle, nickName, crlType); 1.195 +} 1.196 + 1.197 + 1.198 + 1.199 +static SECStatus DeleteCRL (CERTCertDBHandle *certHandle, char *name, int type) 1.200 +{ 1.201 + CERTSignedCrl *crl = NULL; 1.202 + SECStatus rv = SECFailure; 1.203 + 1.204 + crl = FindCRL (certHandle, name, type); 1.205 + if (!crl) { 1.206 + SECU_PrintError 1.207 + (progName, "could not find the issuer %s's CRL", name); 1.208 + return SECFailure; 1.209 + } 1.210 + rv = SEC_DeletePermCRL (crl); 1.211 + SEC_DestroyCrl(crl); 1.212 + if (rv != SECSuccess) { 1.213 + SECU_PrintError(progName, "fail to delete the issuer %s's CRL " 1.214 + "from the perm database (reason: %s)", 1.215 + name, SECU_Strerror(PORT_GetError())); 1.216 + return SECFailure; 1.217 + } 1.218 + return (rv); 1.219 +} 1.220 + 1.221 +SECStatus ImportCRL (CERTCertDBHandle *certHandle, char *url, int type, 1.222 + PRFileDesc *inFile, PRInt32 importOptions, PRInt32 decodeOptions, 1.223 + secuPWData *pwdata) 1.224 +{ 1.225 + CERTSignedCrl *crl = NULL; 1.226 + SECItem crlDER; 1.227 + PK11SlotInfo* slot = NULL; 1.228 + int rv; 1.229 +#if defined(DEBUG_jp96085) 1.230 + PRIntervalTime starttime, endtime, elapsed; 1.231 + PRUint32 mins, secs, msecs; 1.232 +#endif 1.233 + 1.234 + crlDER.data = NULL; 1.235 + 1.236 + 1.237 + /* Read in the entire file specified with the -f argument */ 1.238 + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); 1.239 + if (rv != SECSuccess) { 1.240 + SECU_PrintError(progName, "unable to read input file"); 1.241 + return (SECFailure); 1.242 + } 1.243 + 1.244 + decodeOptions |= CRL_DECODE_DONT_COPY_DER; 1.245 + 1.246 + slot = PK11_GetInternalKeySlot(); 1.247 + 1.248 + if (PK11_NeedLogin(slot)) { 1.249 + rv = PK11_Authenticate(slot, PR_TRUE, pwdata); 1.250 + if (rv != SECSuccess) 1.251 + goto loser; 1.252 + } 1.253 + 1.254 +#if defined(DEBUG_jp96085) 1.255 + starttime = PR_IntervalNow(); 1.256 +#endif 1.257 + crl = PK11_ImportCRL(slot, &crlDER, url, type, 1.258 + NULL, importOptions, NULL, decodeOptions); 1.259 +#if defined(DEBUG_jp96085) 1.260 + endtime = PR_IntervalNow(); 1.261 + elapsed = endtime - starttime; 1.262 + mins = PR_IntervalToSeconds(elapsed) / 60; 1.263 + secs = PR_IntervalToSeconds(elapsed) % 60; 1.264 + msecs = PR_IntervalToMilliseconds(elapsed) % 1000; 1.265 + printf("Elapsed : %2d:%2d.%3d\n", mins, secs, msecs); 1.266 +#endif 1.267 + if (!crl) { 1.268 + const char *errString; 1.269 + 1.270 + rv = SECFailure; 1.271 + errString = SECU_Strerror(PORT_GetError()); 1.272 + if ( errString && PORT_Strlen (errString) == 0) 1.273 + SECU_PrintError (progName, 1.274 + "CRL is not imported (error: input CRL is not up to date.)"); 1.275 + else 1.276 + SECU_PrintError (progName, "unable to import CRL"); 1.277 + } else { 1.278 + SEC_DestroyCrl (crl); 1.279 + } 1.280 + loser: 1.281 + if (slot) { 1.282 + PK11_FreeSlot(slot); 1.283 + } 1.284 + return (rv); 1.285 +} 1.286 + 1.287 +SECStatus DumpCRL(PRFileDesc *inFile) 1.288 +{ 1.289 + int rv; 1.290 + PLArenaPool *arena = NULL; 1.291 + CERTSignedCrl *newCrl = NULL; 1.292 + 1.293 + SECItem crlDER; 1.294 + crlDER.data = NULL; 1.295 + 1.296 + /* Read in the entire file specified with the -f argument */ 1.297 + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); 1.298 + if (rv != SECSuccess) { 1.299 + SECU_PrintError(progName, "unable to read input file"); 1.300 + return (SECFailure); 1.301 + } 1.302 + 1.303 + rv = SEC_ERROR_NO_MEMORY; 1.304 + arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE); 1.305 + if (!arena) 1.306 + return rv; 1.307 + 1.308 + newCrl = CERT_DecodeDERCrlWithFlags(arena, &crlDER, SEC_CRL_TYPE, 1.309 + CRL_DECODE_DEFAULT_OPTIONS); 1.310 + if (!newCrl) 1.311 + return SECFailure; 1.312 + 1.313 + SECU_PrintCRLInfo (stdout, &newCrl->crl, "CRL file contents", 0); 1.314 + 1.315 + PORT_FreeArena (arena, PR_FALSE); 1.316 + return rv; 1.317 +} 1.318 + 1.319 +static CERTCertificate* 1.320 +FindSigningCert(CERTCertDBHandle *certHandle, CERTSignedCrl *signCrl, 1.321 + char *certNickName) 1.322 +{ 1.323 + CERTCertificate *cert = NULL, *certTemp = NULL; 1.324 + SECStatus rv = SECFailure; 1.325 + CERTAuthKeyID* authorityKeyID = NULL; 1.326 + SECItem* subject = NULL; 1.327 + 1.328 + PORT_Assert(certHandle != NULL); 1.329 + if (!certHandle || (!signCrl && !certNickName)) { 1.330 + SECU_PrintError(progName, "invalid args for function " 1.331 + "FindSigningCert \n"); 1.332 + return NULL; 1.333 + } 1.334 + 1.335 + if (signCrl) { 1.336 +#if 0 1.337 + authorityKeyID = SECU_FindCRLAuthKeyIDExten(tmpArena, scrl); 1.338 +#endif 1.339 + subject = &signCrl->crl.derName; 1.340 + } else { 1.341 + certTemp = CERT_FindCertByNickname(certHandle, certNickName); 1.342 + if (!certTemp) { 1.343 + SECU_PrintError(progName, "could not find certificate \"%s\" " 1.344 + "in database", certNickName); 1.345 + goto loser; 1.346 + } 1.347 + subject = &certTemp->derSubject; 1.348 + } 1.349 + 1.350 + cert = SECU_FindCrlIssuer(certHandle, subject, authorityKeyID, PR_Now()); 1.351 + if (!cert) { 1.352 + SECU_PrintError(progName, "could not find signing certificate " 1.353 + "in database"); 1.354 + goto loser; 1.355 + } else { 1.356 + rv = SECSuccess; 1.357 + } 1.358 + 1.359 + loser: 1.360 + if (certTemp) 1.361 + CERT_DestroyCertificate(certTemp); 1.362 + if (cert && rv != SECSuccess) 1.363 + CERT_DestroyCertificate(cert); 1.364 + return cert; 1.365 +} 1.366 + 1.367 +static CERTSignedCrl* 1.368 +CreateModifiedCRLCopy(PLArenaPool *arena, CERTCertDBHandle *certHandle, 1.369 + CERTCertificate **cert, char *certNickName, 1.370 + PRFileDesc *inFile, PRInt32 decodeOptions, 1.371 + PRInt32 importOptions) 1.372 +{ 1.373 + SECItem crlDER = {0, NULL, 0}; 1.374 + CERTSignedCrl *signCrl = NULL; 1.375 + CERTSignedCrl *modCrl = NULL; 1.376 + PLArenaPool *modArena = NULL; 1.377 + SECStatus rv = SECSuccess; 1.378 + 1.379 + if (!arena || !certHandle || !certNickName) { 1.380 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.381 + SECU_PrintError(progName, "CreateModifiedCRLCopy: invalid args\n"); 1.382 + return NULL; 1.383 + } 1.384 + 1.385 + modArena = PORT_NewArena(SEC_ASN1_DEFAULT_ARENA_SIZE); 1.386 + if (!modArena) { 1.387 + SECU_PrintError(progName, "fail to allocate memory\n"); 1.388 + return NULL; 1.389 + } 1.390 + 1.391 + if (inFile != NULL) { 1.392 + rv = SECU_ReadDERFromFile(&crlDER, inFile, PR_FALSE, PR_FALSE); 1.393 + if (rv != SECSuccess) { 1.394 + SECU_PrintError(progName, "unable to read input file"); 1.395 + PORT_FreeArena(modArena, PR_FALSE); 1.396 + goto loser; 1.397 + } 1.398 + 1.399 + decodeOptions |= CRL_DECODE_DONT_COPY_DER; 1.400 + 1.401 + modCrl = CERT_DecodeDERCrlWithFlags(modArena, &crlDER, SEC_CRL_TYPE, 1.402 + decodeOptions); 1.403 + if (!modCrl) { 1.404 + SECU_PrintError(progName, "fail to decode CRL"); 1.405 + goto loser; 1.406 + } 1.407 + 1.408 + if (0 == (importOptions & CRL_IMPORT_BYPASS_CHECKS)){ 1.409 + /* If caCert is a v2 certificate, make sure that it 1.410 + * can be used for crl signing purpose */ 1.411 + *cert = FindSigningCert(certHandle, modCrl, NULL); 1.412 + if (!*cert) { 1.413 + goto loser; 1.414 + } 1.415 + 1.416 + rv = CERT_VerifySignedData(&modCrl->signatureWrap, *cert, 1.417 + PR_Now(), NULL); 1.418 + if (rv != SECSuccess) { 1.419 + SECU_PrintError(progName, "fail to verify signed data\n"); 1.420 + goto loser; 1.421 + } 1.422 + } 1.423 + } else { 1.424 + modCrl = FindCRL(certHandle, certNickName, SEC_CRL_TYPE); 1.425 + if (!modCrl) { 1.426 + SECU_PrintError(progName, "fail to find crl %s in database\n", 1.427 + certNickName); 1.428 + goto loser; 1.429 + } 1.430 + } 1.431 + 1.432 + signCrl = PORT_ArenaZNew(arena, CERTSignedCrl); 1.433 + if (signCrl == NULL) { 1.434 + SECU_PrintError(progName, "fail to allocate memory\n"); 1.435 + goto loser; 1.436 + } 1.437 + 1.438 + rv = SECU_CopyCRL(arena, &signCrl->crl, &modCrl->crl); 1.439 + if (rv != SECSuccess) { 1.440 + SECU_PrintError(progName, "unable to dublicate crl for " 1.441 + "modification."); 1.442 + goto loser; 1.443 + } 1.444 + 1.445 + /* Make sure the update time is current. It can be modified later 1.446 + * by "update <time>" command from crl generation script */ 1.447 + rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now()); 1.448 + if (rv != SECSuccess) { 1.449 + SECU_PrintError(progName, "fail to encode current time\n"); 1.450 + goto loser; 1.451 + } 1.452 + 1.453 + signCrl->arena = arena; 1.454 + 1.455 + loser: 1.456 + if (crlDER.data) { 1.457 + SECITEM_FreeItem(&crlDER, PR_FALSE); 1.458 + } 1.459 + if (modCrl) 1.460 + SEC_DestroyCrl(modCrl); 1.461 + if (rv != SECSuccess && signCrl) { 1.462 + SEC_DestroyCrl(signCrl); 1.463 + signCrl = NULL; 1.464 + } 1.465 + return signCrl; 1.466 +} 1.467 + 1.468 + 1.469 +static CERTSignedCrl* 1.470 +CreateNewCrl(PLArenaPool *arena, CERTCertDBHandle *certHandle, 1.471 + CERTCertificate *cert) 1.472 +{ 1.473 + CERTSignedCrl *signCrl = NULL; 1.474 + void *dummy = NULL; 1.475 + SECStatus rv; 1.476 + void* mark = NULL; 1.477 + 1.478 + /* if the CERTSignedCrl structure changes, this function will need to be 1.479 + updated as well */ 1.480 + if (!cert || !arena) { 1.481 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.482 + SECU_PrintError(progName, "invalid args for function " 1.483 + "CreateNewCrl\n"); 1.484 + return NULL; 1.485 + } 1.486 + 1.487 + mark = PORT_ArenaMark(arena); 1.488 + 1.489 + signCrl = PORT_ArenaZNew(arena, CERTSignedCrl); 1.490 + if (signCrl == NULL) { 1.491 + SECU_PrintError(progName, "fail to allocate memory\n"); 1.492 + return NULL; 1.493 + } 1.494 + 1.495 + dummy = SEC_ASN1EncodeInteger(arena, &signCrl->crl.version, 1.496 + SEC_CRL_VERSION_2); 1.497 + /* set crl->version */ 1.498 + if (!dummy) { 1.499 + SECU_PrintError(progName, "fail to create crl version data " 1.500 + "container\n"); 1.501 + goto loser; 1.502 + } 1.503 + 1.504 + /* copy SECItem name from cert */ 1.505 + rv = SECITEM_CopyItem(arena, &signCrl->crl.derName, &cert->derSubject); 1.506 + if (rv != SECSuccess) { 1.507 + SECU_PrintError(progName, "fail to duplicate der name from " 1.508 + "certificate.\n"); 1.509 + goto loser; 1.510 + } 1.511 + 1.512 + /* copy CERTName name structure from cert issuer */ 1.513 + rv = CERT_CopyName (arena, &signCrl->crl.name, &cert->subject); 1.514 + if (rv != SECSuccess) { 1.515 + SECU_PrintError(progName, "fail to duplicate RD name from " 1.516 + "certificate.\n"); 1.517 + goto loser; 1.518 + } 1.519 + 1.520 + rv = DER_EncodeTimeChoice(arena, &signCrl->crl.lastUpdate, PR_Now()); 1.521 + if (rv != SECSuccess) { 1.522 + SECU_PrintError(progName, "fail to encode current time\n"); 1.523 + goto loser; 1.524 + } 1.525 + 1.526 + /* set fields */ 1.527 + signCrl->arena = arena; 1.528 + signCrl->dbhandle = certHandle; 1.529 + signCrl->crl.arena = arena; 1.530 + 1.531 + return signCrl; 1.532 + 1.533 + loser: 1.534 + PORT_ArenaRelease(arena, mark); 1.535 + return NULL; 1.536 +} 1.537 + 1.538 + 1.539 +static SECStatus 1.540 +UpdateCrl(CERTSignedCrl *signCrl, PRFileDesc *inCrlInitFile) 1.541 +{ 1.542 + CRLGENGeneratorData *crlGenData = NULL; 1.543 + SECStatus rv; 1.544 + 1.545 + if (!signCrl || !inCrlInitFile) { 1.546 + PORT_SetError(SEC_ERROR_INVALID_ARGS); 1.547 + SECU_PrintError(progName, "invalid args for function " 1.548 + "CreateNewCrl\n"); 1.549 + return SECFailure; 1.550 + } 1.551 + 1.552 + crlGenData = CRLGEN_InitCrlGeneration(signCrl, inCrlInitFile); 1.553 + if (!crlGenData) { 1.554 + SECU_PrintError(progName, "can not initialize parser structure.\n"); 1.555 + return SECFailure; 1.556 + } 1.557 + 1.558 + rv = CRLGEN_ExtHandleInit(crlGenData); 1.559 + if (rv == SECFailure) { 1.560 + SECU_PrintError(progName, "can not initialize entries handle.\n"); 1.561 + goto loser; 1.562 + } 1.563 + 1.564 + rv = CRLGEN_StartCrlGen(crlGenData); 1.565 + if (rv != SECSuccess) { 1.566 + SECU_PrintError(progName, "crl generation failed"); 1.567 + goto loser; 1.568 + } 1.569 + 1.570 + loser: 1.571 + /* CommitExtensionsAndEntries is partially responsible for freeing 1.572 + * up memory that was used for CRL generation. Should be called regardless 1.573 + * of previouse call status, but only after initialization of 1.574 + * crlGenData was done. It will commit all changes that was done before 1.575 + * an error has occurred. 1.576 + */ 1.577 + if (SECSuccess != CRLGEN_CommitExtensionsAndEntries(crlGenData)) { 1.578 + SECU_PrintError(progName, "crl generation failed"); 1.579 + rv = SECFailure; 1.580 + } 1.581 + CRLGEN_FinalizeCrlGeneration(crlGenData); 1.582 + return rv; 1.583 +} 1.584 + 1.585 +static SECStatus 1.586 +SignAndStoreCrl(CERTSignedCrl *signCrl, CERTCertificate *cert, 1.587 + char *outFileName, SECOidTag hashAlgTag, int ascii, 1.588 + char *slotName, char *url, secuPWData *pwdata) 1.589 +{ 1.590 + PK11SlotInfo *slot = NULL; 1.591 + PRFileDesc *outFile = NULL; 1.592 + SECStatus rv; 1.593 + SignAndEncodeFuncExitStat errCode; 1.594 + 1.595 + PORT_Assert(signCrl && (!ascii || outFileName)); 1.596 + if (!signCrl || (ascii && !outFileName)) { 1.597 + SECU_PrintError(progName, "invalid args for function " 1.598 + "SignAndStoreCrl\n"); 1.599 + return SECFailure; 1.600 + } 1.601 + 1.602 + if (!slotName || !PL_strcmp(slotName, "internal")) 1.603 + slot = PK11_GetInternalKeySlot(); 1.604 + else 1.605 + slot = PK11_FindSlotByName(slotName); 1.606 + if (!slot) { 1.607 + SECU_PrintError(progName, "can not find requested slot"); 1.608 + return SECFailure; 1.609 + } 1.610 + 1.611 + if (PK11_NeedLogin(slot)) { 1.612 + rv = PK11_Authenticate(slot, PR_TRUE, pwdata); 1.613 + if (rv != SECSuccess) 1.614 + goto loser; 1.615 + } 1.616 + 1.617 + rv = SECU_SignAndEncodeCRL(cert, signCrl, hashAlgTag, &errCode); 1.618 + if (rv != SECSuccess) { 1.619 + char* errMsg = NULL; 1.620 + switch (errCode) 1.621 + { 1.622 + case noKeyFound: 1.623 + errMsg = "No private key found of signing cert"; 1.624 + break; 1.625 + 1.626 + case noSignatureMatch: 1.627 + errMsg = "Key and Algorithm OId are do not match"; 1.628 + break; 1.629 + 1.630 + default: 1.631 + case failToEncode: 1.632 + errMsg = "Failed to encode crl structure"; 1.633 + break; 1.634 + 1.635 + case failToSign: 1.636 + errMsg = "Failed to sign crl structure"; 1.637 + break; 1.638 + 1.639 + case noMem: 1.640 + errMsg = "Can not allocate memory"; 1.641 + break; 1.642 + } 1.643 + SECU_PrintError(progName, "%s\n", errMsg); 1.644 + goto loser; 1.645 + } 1.646 + 1.647 + if (outFileName) { 1.648 + outFile = PR_Open(outFileName, PR_WRONLY|PR_CREATE_FILE, PR_IRUSR | PR_IWUSR); 1.649 + if (!outFile) { 1.650 + SECU_PrintError(progName, "unable to open \"%s\" for writing\n", 1.651 + outFileName); 1.652 + goto loser; 1.653 + } 1.654 + } 1.655 + 1.656 + rv = SECU_StoreCRL(slot, signCrl->derCrl, outFile, ascii, url); 1.657 + if (rv != SECSuccess) { 1.658 + SECU_PrintError(progName, "fail to save CRL\n"); 1.659 + } 1.660 + 1.661 + loser: 1.662 + if (outFile) 1.663 + PR_Close(outFile); 1.664 + if (slot) 1.665 + PK11_FreeSlot(slot); 1.666 + return rv; 1.667 +} 1.668 + 1.669 +static SECStatus 1.670 +GenerateCRL (CERTCertDBHandle *certHandle, char *certNickName, 1.671 + PRFileDesc *inCrlInitFile, PRFileDesc *inFile, 1.672 + char *outFileName, int ascii, char *slotName, 1.673 + PRInt32 importOptions, char *alg, PRBool quiet, 1.674 + PRInt32 decodeOptions, char *url, secuPWData *pwdata, 1.675 + int modifyFlag) 1.676 +{ 1.677 + CERTCertificate *cert = NULL; 1.678 + CERTSignedCrl *signCrl = NULL; 1.679 + PLArenaPool *arena = NULL; 1.680 + SECStatus rv; 1.681 + SECOidTag hashAlgTag = SEC_OID_UNKNOWN; 1.682 + 1.683 + if (alg) { 1.684 + hashAlgTag = SECU_StringToSignatureAlgTag(alg); 1.685 + if (hashAlgTag == SEC_OID_UNKNOWN) { 1.686 + SECU_PrintError(progName, "%s -Z: %s is not a recognized type.\n", 1.687 + progName, alg); 1.688 + return SECFailure; 1.689 + } 1.690 + } else { 1.691 + hashAlgTag = SEC_OID_UNKNOWN; 1.692 + } 1.693 + 1.694 + arena = PORT_NewArena (SEC_ASN1_DEFAULT_ARENA_SIZE); 1.695 + if (!arena) { 1.696 + SECU_PrintError(progName, "fail to allocate memory\n"); 1.697 + return SECFailure; 1.698 + } 1.699 + 1.700 + if (modifyFlag == PR_TRUE) { 1.701 + signCrl = CreateModifiedCRLCopy(arena, certHandle, &cert, certNickName, 1.702 + inFile, decodeOptions, importOptions); 1.703 + if (signCrl == NULL) { 1.704 + goto loser; 1.705 + } 1.706 + } 1.707 + 1.708 + if (!cert) { 1.709 + cert = FindSigningCert(certHandle, signCrl, certNickName); 1.710 + if (cert == NULL) { 1.711 + goto loser; 1.712 + } 1.713 + } 1.714 + 1.715 + if (!signCrl) { 1.716 + if (modifyFlag == PR_TRUE) { 1.717 + if (!outFileName) { 1.718 + int len = strlen(certNickName) + 5; 1.719 + outFileName = PORT_ArenaAlloc(arena, len); 1.720 + PR_snprintf(outFileName, len, "%s.crl", certNickName); 1.721 + } 1.722 + SECU_PrintError(progName, "Will try to generate crl. " 1.723 + "It will be saved in file: %s", 1.724 + outFileName); 1.725 + } 1.726 + signCrl = CreateNewCrl(arena, certHandle, cert); 1.727 + if (!signCrl) 1.728 + goto loser; 1.729 + } 1.730 + 1.731 + rv = UpdateCrl(signCrl, inCrlInitFile); 1.732 + if (rv != SECSuccess) { 1.733 + goto loser; 1.734 + } 1.735 + 1.736 + rv = SignAndStoreCrl(signCrl, cert, outFileName, hashAlgTag, ascii, 1.737 + slotName, url, pwdata); 1.738 + if (rv != SECSuccess) { 1.739 + goto loser; 1.740 + } 1.741 + 1.742 + if (signCrl && !quiet) { 1.743 + SECU_PrintCRLInfo (stdout, &signCrl->crl, "CRL Info:\n", 0); 1.744 + } 1.745 + 1.746 + loser: 1.747 + if (arena && (!signCrl || !signCrl->arena)) 1.748 + PORT_FreeArena (arena, PR_FALSE); 1.749 + if (signCrl) 1.750 + SEC_DestroyCrl (signCrl); 1.751 + if (cert) 1.752 + CERT_DestroyCertificate (cert); 1.753 + return (rv); 1.754 +} 1.755 + 1.756 +static void Usage(char *progName) 1.757 +{ 1.758 + fprintf(stderr, 1.759 + "Usage: %s -L [-n nickname] [-d keydir] [-P dbprefix] [-t crlType]\n" 1.760 + " %s -D -n nickname [-d keydir] [-P dbprefix]\n" 1.761 + " %s -S -i crl\n" 1.762 + " %s -I -i crl -t crlType [-u url] [-d keydir] [-P dbprefix] [-B] " 1.763 + "[-p pwd-file] -w [pwd-string]\n" 1.764 + " %s -E -t crlType [-d keydir] [-P dbprefix]\n" 1.765 + " %s -T\n" 1.766 + " %s -G|-M -c crl-init-file -n nickname [-i crl] [-u url] " 1.767 + "[-d keydir] [-P dbprefix] [-Z alg] ] [-p pwd-file] -w [pwd-string] " 1.768 + "[-a] [-B]\n", 1.769 + progName, progName, progName, progName, progName, progName, progName); 1.770 + 1.771 + fprintf (stderr, "%-15s List CRL\n", "-L"); 1.772 + fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n", 1.773 + "-n nickname"); 1.774 + fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 1.775 + "-d keydir"); 1.776 + fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 1.777 + "-P dbprefix"); 1.778 + 1.779 + fprintf (stderr, "%-15s Delete a CRL from the cert database\n", "-D"); 1.780 + fprintf(stderr, "%-20s Specify the nickname for the CA certificate\n", 1.781 + "-n nickname"); 1.782 + fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType"); 1.783 + fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 1.784 + "-d keydir"); 1.785 + fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 1.786 + "-P dbprefix"); 1.787 + 1.788 + fprintf (stderr, "%-15s Erase all CRLs of specified type from hte cert database\n", "-E"); 1.789 + fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType"); 1.790 + fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 1.791 + "-d keydir"); 1.792 + fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 1.793 + "-P dbprefix"); 1.794 + 1.795 + fprintf (stderr, "%-15s Show contents of a CRL file (without database)\n", "-S"); 1.796 + fprintf(stderr, "%-20s Specify the file which contains the CRL to show\n", 1.797 + "-i crl"); 1.798 + 1.799 + fprintf (stderr, "%-15s Import a CRL to the cert database\n", "-I"); 1.800 + fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n", 1.801 + "-i crl"); 1.802 + fprintf(stderr, "%-20s Specify the url.\n", "-u url"); 1.803 + fprintf(stderr, "%-20s Specify the crl type.\n", "-t crlType"); 1.804 + fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 1.805 + "-d keydir"); 1.806 + fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 1.807 + "-P dbprefix"); 1.808 +#ifdef DEBUG 1.809 + fprintf (stderr, "%-15s Test . Only for debugging purposes. See source code\n", "-T"); 1.810 +#endif 1.811 + fprintf(stderr, "%-20s CRL Types (default is SEC_CRL_TYPE):\n", " "); 1.812 + fprintf(stderr, "%-20s \t 0 - SEC_KRL_TYPE\n", " "); 1.813 + fprintf(stderr, "%-20s \t 1 - SEC_CRL_TYPE\n", " "); 1.814 + fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B"); 1.815 + fprintf(stderr, "\n%-20s Partial decode for faster operation.\n", "-p"); 1.816 + fprintf(stderr, "%-20s Repeat the operation.\n", "-r <iterations>"); 1.817 + fprintf(stderr, "\n%-15s Create CRL\n", "-G"); 1.818 + fprintf(stderr, "%-15s Modify CRL\n", "-M"); 1.819 + fprintf(stderr, "%-20s Specify crl initialization file\n", 1.820 + "-c crl-conf-file"); 1.821 + fprintf(stderr, "%-20s Specify the nickname of the CA certificate\n", 1.822 + "-n nickname"); 1.823 + fprintf(stderr, "%-20s Specify the file which contains the CRL to import\n", 1.824 + "-i crl"); 1.825 + fprintf(stderr, "%-20s Specify a CRL output file\n", 1.826 + "-o crl-output-file"); 1.827 + fprintf(stderr, "%-20s Specify to use base64 encoded CRL output format\n", 1.828 + "-a"); 1.829 + fprintf(stderr, "%-20s Key database directory (default is ~/.netscape)\n", 1.830 + "-d keydir"); 1.831 + fprintf(stderr, "%-20s Provide path to a default pwd file\n", 1.832 + "-f pwd-file"); 1.833 + fprintf(stderr, "%-20s Provide db password in command line\n", 1.834 + "-w pwd-string"); 1.835 + fprintf(stderr, "%-20s Cert & Key database prefix (default is \"\")\n", 1.836 + "-P dbprefix"); 1.837 + fprintf(stderr, "%-20s Specify the url.\n", "-u url"); 1.838 + fprintf(stderr, "\n%-20s Bypass CA certificate checks.\n", "-B"); 1.839 + 1.840 + exit(-1); 1.841 +} 1.842 + 1.843 +int main(int argc, char **argv) 1.844 +{ 1.845 + CERTCertDBHandle *certHandle; 1.846 + PRFileDesc *inFile; 1.847 + PRFileDesc *inCrlInitFile = NULL; 1.848 + int generateCRL; 1.849 + int modifyCRL; 1.850 + int listCRL; 1.851 + int importCRL; 1.852 + int showFileCRL; 1.853 + int deleteCRL; 1.854 + int rv; 1.855 + char *nickName; 1.856 + char *url; 1.857 + char *dbPrefix = ""; 1.858 + char *alg = NULL; 1.859 + char *outFile = NULL; 1.860 + char *slotName = NULL; 1.861 + int ascii = 0; 1.862 + int crlType; 1.863 + PLOptState *optstate; 1.864 + PLOptStatus status; 1.865 + SECStatus secstatus; 1.866 + PRInt32 decodeOptions = CRL_DECODE_DEFAULT_OPTIONS; 1.867 + PRInt32 importOptions = CRL_IMPORT_DEFAULT_OPTIONS; 1.868 + PRBool quiet = PR_FALSE; 1.869 + PRBool test = PR_FALSE; 1.870 + PRBool erase = PR_FALSE; 1.871 + PRInt32 i = 0; 1.872 + PRInt32 iterations = 1; 1.873 + PRBool readonly = PR_FALSE; 1.874 + 1.875 + secuPWData pwdata = { PW_NONE, 0 }; 1.876 + 1.877 + progName = strrchr(argv[0], '/'); 1.878 + progName = progName ? progName+1 : argv[0]; 1.879 + 1.880 + rv = 0; 1.881 + deleteCRL = importCRL = listCRL = generateCRL = modifyCRL = showFileCRL = 0; 1.882 + inFile = NULL; 1.883 + nickName = url = NULL; 1.884 + certHandle = NULL; 1.885 + crlType = SEC_CRL_TYPE; 1.886 + /* 1.887 + * Parse command line arguments 1.888 + */ 1.889 + optstate = PL_CreateOptState(argc, argv, "sqBCDGILMSTEP:f:d:i:h:n:p:t:u:r:aZ:o:c:"); 1.890 + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.891 + switch (optstate->option) { 1.892 + case '?': 1.893 + Usage(progName); 1.894 + break; 1.895 + 1.896 + case 'T': 1.897 + test = PR_TRUE; 1.898 + break; 1.899 + 1.900 + case 'E': 1.901 + erase = PR_TRUE; 1.902 + break; 1.903 + 1.904 + case 'B': 1.905 + importOptions |= CRL_IMPORT_BYPASS_CHECKS; 1.906 + break; 1.907 + 1.908 + case 'G': 1.909 + generateCRL = 1; 1.910 + break; 1.911 + 1.912 + case 'M': 1.913 + modifyCRL = 1; 1.914 + break; 1.915 + 1.916 + case 'D': 1.917 + deleteCRL = 1; 1.918 + break; 1.919 + 1.920 + case 'I': 1.921 + importCRL = 1; 1.922 + break; 1.923 + 1.924 + case 'S': 1.925 + showFileCRL = 1; 1.926 + break; 1.927 + 1.928 + case 'C': 1.929 + case 'L': 1.930 + listCRL = 1; 1.931 + break; 1.932 + 1.933 + case 'P': 1.934 + dbPrefix = strdup(optstate->value); 1.935 + break; 1.936 + 1.937 + case 'Z': 1.938 + alg = strdup(optstate->value); 1.939 + break; 1.940 + 1.941 + case 'a': 1.942 + ascii = 1; 1.943 + break; 1.944 + 1.945 + case 'c': 1.946 + inCrlInitFile = PR_Open(optstate->value, PR_RDONLY, 0); 1.947 + if (!inCrlInitFile) { 1.948 + PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading\n", 1.949 + progName, optstate->value); 1.950 + PL_DestroyOptState(optstate); 1.951 + return -1; 1.952 + } 1.953 + break; 1.954 + 1.955 + case 'd': 1.956 + SECU_ConfigDirectory(optstate->value); 1.957 + break; 1.958 + 1.959 + case 'f': 1.960 + pwdata.source = PW_FROMFILE; 1.961 + pwdata.data = strdup(optstate->value); 1.962 + break; 1.963 + 1.964 + case 'h': 1.965 + slotName = strdup(optstate->value); 1.966 + break; 1.967 + 1.968 + case 'i': 1.969 + inFile = PR_Open(optstate->value, PR_RDONLY, 0); 1.970 + if (!inFile) { 1.971 + PR_fprintf(PR_STDERR, "%s: unable to open \"%s\" for reading\n", 1.972 + progName, optstate->value); 1.973 + PL_DestroyOptState(optstate); 1.974 + return -1; 1.975 + } 1.976 + break; 1.977 + 1.978 + case 'n': 1.979 + nickName = strdup(optstate->value); 1.980 + break; 1.981 + 1.982 + case 'o': 1.983 + outFile = strdup(optstate->value); 1.984 + break; 1.985 + 1.986 + case 'p': 1.987 + decodeOptions |= CRL_DECODE_SKIP_ENTRIES; 1.988 + break; 1.989 + 1.990 + case 'r': { 1.991 + const char* str = optstate->value; 1.992 + if (str && atoi(str)>0) 1.993 + iterations = atoi(str); 1.994 + } 1.995 + break; 1.996 + 1.997 + case 't': { 1.998 + crlType = atoi(optstate->value); 1.999 + if (crlType != SEC_CRL_TYPE && crlType != SEC_KRL_TYPE) { 1.1000 + PR_fprintf(PR_STDERR, "%s: invalid crl type\n", progName); 1.1001 + PL_DestroyOptState(optstate); 1.1002 + return -1; 1.1003 + } 1.1004 + break; 1.1005 + 1.1006 + case 'q': 1.1007 + quiet = PR_TRUE; 1.1008 + break; 1.1009 + 1.1010 + case 'w': 1.1011 + pwdata.source = PW_PLAINTEXT; 1.1012 + pwdata.data = strdup(optstate->value); 1.1013 + break; 1.1014 + 1.1015 + case 'u': 1.1016 + url = strdup(optstate->value); 1.1017 + break; 1.1018 + 1.1019 + } 1.1020 + } 1.1021 + } 1.1022 + PL_DestroyOptState(optstate); 1.1023 + 1.1024 + if (deleteCRL && !nickName) Usage (progName); 1.1025 + if (importCRL && !inFile) Usage (progName); 1.1026 + if (showFileCRL && !inFile) Usage (progName); 1.1027 + if ((generateCRL && !nickName) || 1.1028 + (modifyCRL && !inFile && !nickName)) Usage (progName); 1.1029 + if (!(listCRL || deleteCRL || importCRL || showFileCRL || generateCRL || 1.1030 + modifyCRL || test || erase)) Usage (progName); 1.1031 + 1.1032 + if (listCRL || showFileCRL) { 1.1033 + readonly = PR_TRUE; 1.1034 + } 1.1035 + 1.1036 + PR_Init( PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 1.1037 + 1.1038 + PK11_SetPasswordFunc(SECU_GetModulePassword); 1.1039 + 1.1040 + if (showFileCRL) { 1.1041 + NSS_NoDB_Init(NULL); 1.1042 + } 1.1043 + else { 1.1044 + secstatus = NSS_Initialize(SECU_ConfigDirectory(NULL), dbPrefix, dbPrefix, 1.1045 + "secmod.db", readonly ? NSS_INIT_READONLY : 0); 1.1046 + if (secstatus != SECSuccess) { 1.1047 + SECU_PrintPRandOSError(progName); 1.1048 + return -1; 1.1049 + } 1.1050 + } 1.1051 + 1.1052 + SECU_RegisterDynamicOids(); 1.1053 + 1.1054 + certHandle = CERT_GetDefaultCertDB(); 1.1055 + if (certHandle == NULL) { 1.1056 + SECU_PrintError(progName, "unable to open the cert db"); 1.1057 + /*ignoring return value of NSS_Shutdown() as code returns -1*/ 1.1058 + (void) NSS_Shutdown(); 1.1059 + return (-1); 1.1060 + } 1.1061 + 1.1062 + CRLGEN_InitCrlGenParserLock(); 1.1063 + 1.1064 + for (i=0; i<iterations; i++) { 1.1065 + /* Read in the private key info */ 1.1066 + if (deleteCRL) 1.1067 + DeleteCRL (certHandle, nickName, crlType); 1.1068 + else if (listCRL) { 1.1069 + rv = ListCRL (certHandle, nickName, crlType); 1.1070 + } 1.1071 + else if (importCRL) { 1.1072 + rv = ImportCRL (certHandle, url, crlType, inFile, importOptions, 1.1073 + decodeOptions, &pwdata); 1.1074 + } 1.1075 + else if (showFileCRL) { 1.1076 + rv = DumpCRL (inFile); 1.1077 + } else if (generateCRL || modifyCRL) { 1.1078 + if (!inCrlInitFile) 1.1079 + inCrlInitFile = PR_STDIN; 1.1080 + rv = GenerateCRL (certHandle, nickName, inCrlInitFile, 1.1081 + inFile, outFile, ascii, slotName, 1.1082 + importOptions, alg, quiet, 1.1083 + decodeOptions, url, &pwdata, 1.1084 + modifyCRL); 1.1085 + } 1.1086 + else if (erase) { 1.1087 + /* list and delete all CRLs */ 1.1088 + ListCRLNames (certHandle, crlType, PR_TRUE); 1.1089 + } 1.1090 +#ifdef DEBUG 1.1091 + else if (test) { 1.1092 + /* list and delete all CRLs */ 1.1093 + ListCRLNames (certHandle, crlType, PR_TRUE); 1.1094 + /* list CRLs */ 1.1095 + ListCRLNames (certHandle, crlType, PR_FALSE); 1.1096 + /* import CRL as a blob */ 1.1097 + rv = ImportCRL (certHandle, url, crlType, inFile, importOptions, 1.1098 + decodeOptions, &pwdata); 1.1099 + /* list CRLs */ 1.1100 + ListCRLNames (certHandle, crlType, PR_FALSE); 1.1101 + } 1.1102 +#endif 1.1103 + } 1.1104 + 1.1105 + CRLGEN_DestroyCrlGenParserLock(); 1.1106 + 1.1107 + if (NSS_Shutdown() != SECSuccess) { 1.1108 + rv = SECFailure; 1.1109 + } 1.1110 + 1.1111 + return (rv != SECSuccess); 1.1112 +}