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