security/nss/cmd/addbuiltin/addbuiltin.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

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 * Tool for converting builtin CA certs.
michael@0 7 */
michael@0 8
michael@0 9 #include "nssrenam.h"
michael@0 10 #include "nss.h"
michael@0 11 #include "cert.h"
michael@0 12 #include "certdb.h"
michael@0 13 #include "secutil.h"
michael@0 14 #include "pk11func.h"
michael@0 15
michael@0 16 #if defined(WIN32)
michael@0 17 #include <fcntl.h>
michael@0 18 #include <io.h>
michael@0 19 #endif
michael@0 20
michael@0 21 void dumpbytes(unsigned char *buf, int len)
michael@0 22 {
michael@0 23 int i;
michael@0 24 for (i=0; i < len; i++) {
michael@0 25 if ((i !=0) && ((i & 0xf) == 0)) {
michael@0 26 printf("\n");
michael@0 27 }
michael@0 28 printf("\\%03o",buf[i]);
michael@0 29 }
michael@0 30 printf("\n");
michael@0 31 }
michael@0 32
michael@0 33 char *getTrustString(unsigned int trust)
michael@0 34 {
michael@0 35 if (trust & CERTDB_TRUSTED) {
michael@0 36 if (trust & CERTDB_TRUSTED_CA) {
michael@0 37 return "CKT_NSS_TRUSTED_DELEGATOR";
michael@0 38 } else {
michael@0 39 return "CKT_NSS_TRUSTED";
michael@0 40 }
michael@0 41 } else {
michael@0 42 if (trust & CERTDB_TRUSTED_CA) {
michael@0 43 return "CKT_NSS_TRUSTED_DELEGATOR";
michael@0 44 } else if (trust & CERTDB_VALID_CA) {
michael@0 45 return "CKT_NSS_VALID_DELEGATOR";
michael@0 46 } else if (trust & CERTDB_TERMINAL_RECORD) {
michael@0 47 return "CKT_NSS_NOT_TRUSTED";
michael@0 48 } else {
michael@0 49 return "CKT_NSS_MUST_VERIFY_TRUST";
michael@0 50 }
michael@0 51 }
michael@0 52 return "CKT_NSS_TRUST_UNKNOWN"; /* not reached */
michael@0 53 }
michael@0 54
michael@0 55 static const SEC_ASN1Template serialTemplate[] = {
michael@0 56 { SEC_ASN1_INTEGER, offsetof(CERTCertificate,serialNumber) },
michael@0 57 { 0 }
michael@0 58 };
michael@0 59
michael@0 60 void print_crl_info(CERTName *name, SECItem *serial)
michael@0 61 {
michael@0 62 PRBool saveWrapeState = SECU_GetWrapEnabled();
michael@0 63 SECU_EnableWrap(PR_FALSE);
michael@0 64
michael@0 65 SECU_PrintNameQuotesOptional(stdout, name, "# Issuer", 0, PR_FALSE);
michael@0 66 printf("\n");
michael@0 67
michael@0 68 SECU_PrintInteger(stdout, serial, "# Serial Number", 0);
michael@0 69
michael@0 70 SECU_EnableWrap(saveWrapeState);
michael@0 71 }
michael@0 72
michael@0 73 static SECStatus
michael@0 74 ConvertCRLEntry(SECItem *sdder, PRInt32 crlentry, char *nickname)
michael@0 75 {
michael@0 76 int rv;
michael@0 77 PLArenaPool *arena = NULL;
michael@0 78 CERTSignedCrl *newCrl = NULL;
michael@0 79 CERTCrlEntry *entry;
michael@0 80
michael@0 81 CERTName *name = NULL;
michael@0 82 SECItem *derName = NULL;
michael@0 83 SECItem *serial = NULL;
michael@0 84
michael@0 85 rv = SEC_ERROR_NO_MEMORY;
michael@0 86 arena = PORT_NewArena(DER_DEFAULT_CHUNKSIZE);
michael@0 87 if (!arena)
michael@0 88 return rv;
michael@0 89
michael@0 90 newCrl = CERT_DecodeDERCrlWithFlags(arena, sdder, SEC_CRL_TYPE,
michael@0 91 CRL_DECODE_DEFAULT_OPTIONS);
michael@0 92 if (!newCrl)
michael@0 93 return SECFailure;
michael@0 94
michael@0 95 name = &newCrl->crl.name;
michael@0 96 derName = &newCrl->crl.derName;
michael@0 97
michael@0 98 if (newCrl->crl.entries != NULL) {
michael@0 99 PRInt32 iv = 0;
michael@0 100 while ((entry = newCrl->crl.entries[iv++]) != NULL) {
michael@0 101 if (crlentry == iv) {
michael@0 102 serial = &entry->serialNumber;
michael@0 103 break;
michael@0 104 }
michael@0 105 }
michael@0 106 }
michael@0 107
michael@0 108 if (!name || !derName || !serial)
michael@0 109 return SECFailure;
michael@0 110
michael@0 111 printf("\n# Distrust \"%s\"\n",nickname);
michael@0 112 print_crl_info(name, serial);
michael@0 113
michael@0 114 printf("CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST\n");
michael@0 115 printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
michael@0 116 printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
michael@0 117 printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
michael@0 118 printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
michael@0 119
michael@0 120 printf("CKA_ISSUER MULTILINE_OCTAL\n");
michael@0 121 dumpbytes(derName->data,derName->len);
michael@0 122 printf("END\n");
michael@0 123 printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
michael@0 124 printf("\\002\\%03o", serial->len); /* 002: type integer; len >=3 digits */
michael@0 125 dumpbytes(serial->data,serial->len);
michael@0 126 printf("END\n");
michael@0 127
michael@0 128 printf("CKA_TRUST_SERVER_AUTH CK_TRUST CKT_NSS_NOT_TRUSTED\n");
michael@0 129 printf("CKA_TRUST_EMAIL_PROTECTION CK_TRUST CKT_NSS_NOT_TRUSTED\n");
michael@0 130 printf("CKA_TRUST_CODE_SIGNING CK_TRUST CKT_NSS_NOT_TRUSTED\n");
michael@0 131 printf("CKA_TRUST_STEP_UP_APPROVED CK_BBOOL CK_FALSE\n");
michael@0 132
michael@0 133 PORT_FreeArena (arena, PR_FALSE);
michael@0 134 return rv;
michael@0 135 }
michael@0 136
michael@0 137 void print_info(SECItem *sdder, CERTCertificate *c)
michael@0 138 {
michael@0 139 PRBool saveWrapeState = SECU_GetWrapEnabled();
michael@0 140 SECU_EnableWrap(PR_FALSE);
michael@0 141
michael@0 142 SECU_PrintNameQuotesOptional(stdout, &c->issuer, "# Issuer", 0, PR_FALSE);
michael@0 143 printf("\n");
michael@0 144
michael@0 145 SECU_PrintInteger(stdout, &c->serialNumber, "# Serial Number", 0);
michael@0 146
michael@0 147 SECU_PrintNameQuotesOptional(stdout, &c->subject, "# Subject", 0, PR_FALSE);
michael@0 148 printf("\n");
michael@0 149
michael@0 150 SECU_PrintTimeChoice(stdout, &c->validity.notBefore, "# Not Valid Before", 0);
michael@0 151 SECU_PrintTimeChoice(stdout, &c->validity.notAfter, "# Not Valid After ", 0);
michael@0 152
michael@0 153 SECU_PrintFingerprints(stdout, sdder, "# Fingerprint", 0);
michael@0 154
michael@0 155 SECU_EnableWrap(saveWrapeState);
michael@0 156 }
michael@0 157
michael@0 158 static SECStatus
michael@0 159 ConvertCertificate(SECItem *sdder, char *nickname, CERTCertTrust *trust,
michael@0 160 PRBool excludeCert, PRBool excludeHash)
michael@0 161 {
michael@0 162 SECStatus rv = SECSuccess;
michael@0 163 CERTCertificate *cert;
michael@0 164 unsigned char sha1_hash[SHA1_LENGTH];
michael@0 165 unsigned char md5_hash[MD5_LENGTH];
michael@0 166 SECItem *serial = NULL;
michael@0 167 PRBool step_up = PR_FALSE;
michael@0 168 const char *trust_info;
michael@0 169
michael@0 170 cert = CERT_DecodeDERCertificate(sdder, PR_FALSE, nickname);
michael@0 171 if (!cert) {
michael@0 172 return SECFailure;
michael@0 173 }
michael@0 174 serial = SEC_ASN1EncodeItem(NULL,NULL,cert,serialTemplate);
michael@0 175 if (!serial) {
michael@0 176 return SECFailure;
michael@0 177 }
michael@0 178
michael@0 179 if (!excludeCert) {
michael@0 180 printf("\n#\n# Certificate \"%s\"\n#\n",nickname);
michael@0 181 print_info(sdder, cert);
michael@0 182 printf("CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n");
michael@0 183 printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
michael@0 184 printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
michael@0 185 printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
michael@0 186 printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
michael@0 187 printf("CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n");
michael@0 188 printf("CKA_SUBJECT MULTILINE_OCTAL\n");
michael@0 189 dumpbytes(cert->derSubject.data,cert->derSubject.len);
michael@0 190 printf("END\n");
michael@0 191 printf("CKA_ID UTF8 \"0\"\n");
michael@0 192 printf("CKA_ISSUER MULTILINE_OCTAL\n");
michael@0 193 dumpbytes(cert->derIssuer.data,cert->derIssuer.len);
michael@0 194 printf("END\n");
michael@0 195 printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
michael@0 196 dumpbytes(serial->data,serial->len);
michael@0 197 printf("END\n");
michael@0 198 printf("CKA_VALUE MULTILINE_OCTAL\n");
michael@0 199 dumpbytes(sdder->data,sdder->len);
michael@0 200 printf("END\n");
michael@0 201 }
michael@0 202
michael@0 203 if ((trust->sslFlags | trust->emailFlags | trust->objectSigningFlags)
michael@0 204 == CERTDB_TERMINAL_RECORD)
michael@0 205 trust_info = "Distrust";
michael@0 206 else
michael@0 207 trust_info = "Trust for";
michael@0 208
michael@0 209 printf("\n# %s \"%s\"\n", trust_info, nickname);
michael@0 210 print_info(sdder, cert);
michael@0 211
michael@0 212 printf("CKA_CLASS CK_OBJECT_CLASS CKO_NSS_TRUST\n");
michael@0 213 printf("CKA_TOKEN CK_BBOOL CK_TRUE\n");
michael@0 214 printf("CKA_PRIVATE CK_BBOOL CK_FALSE\n");
michael@0 215 printf("CKA_MODIFIABLE CK_BBOOL CK_FALSE\n");
michael@0 216 printf("CKA_LABEL UTF8 \"%s\"\n",nickname);
michael@0 217
michael@0 218 if (!excludeHash) {
michael@0 219 PK11_HashBuf(SEC_OID_SHA1, sha1_hash, sdder->data, sdder->len);
michael@0 220 printf("CKA_CERT_SHA1_HASH MULTILINE_OCTAL\n");
michael@0 221 dumpbytes(sha1_hash,SHA1_LENGTH);
michael@0 222 printf("END\n");
michael@0 223 PK11_HashBuf(SEC_OID_MD5, md5_hash, sdder->data, sdder->len);
michael@0 224 printf("CKA_CERT_MD5_HASH MULTILINE_OCTAL\n");
michael@0 225 dumpbytes(md5_hash,MD5_LENGTH);
michael@0 226 printf("END\n");
michael@0 227 }
michael@0 228
michael@0 229 printf("CKA_ISSUER MULTILINE_OCTAL\n");
michael@0 230 dumpbytes(cert->derIssuer.data,cert->derIssuer.len);
michael@0 231 printf("END\n");
michael@0 232 printf("CKA_SERIAL_NUMBER MULTILINE_OCTAL\n");
michael@0 233 dumpbytes(serial->data,serial->len);
michael@0 234 printf("END\n");
michael@0 235
michael@0 236 printf("CKA_TRUST_SERVER_AUTH CK_TRUST %s\n",
michael@0 237 getTrustString(trust->sslFlags));
michael@0 238 printf("CKA_TRUST_EMAIL_PROTECTION CK_TRUST %s\n",
michael@0 239 getTrustString(trust->emailFlags));
michael@0 240 printf("CKA_TRUST_CODE_SIGNING CK_TRUST %s\n",
michael@0 241 getTrustString(trust->objectSigningFlags));
michael@0 242 #ifdef notdef
michael@0 243 printf("CKA_TRUST_CLIENT_AUTH CK_TRUST CKT_NSS_TRUSTED\n");
michael@0 244 printf("CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
michael@0 245 printf("CKA_TRUST_NON_REPUDIATION CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
michael@0 246 printf("CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
michael@0 247 printf("CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
michael@0 248 printf("CKA_TRUST_KEY_AGREEMENT CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
michael@0 249 printf("CKA_TRUST_KEY_CERT_SIGN CK_TRUST CKT_NSS_TRUSTED_DELEGATOR\n");
michael@0 250 #endif
michael@0 251
michael@0 252 step_up = (trust->sslFlags & CERTDB_GOVT_APPROVED_CA);
michael@0 253 printf("CKA_TRUST_STEP_UP_APPROVED CK_BBOOL %s\n",
michael@0 254 step_up ? "CK_TRUE" : "CK_FALSE");
michael@0 255
michael@0 256 PORT_Free(sdder->data);
michael@0 257 return(rv);
michael@0 258
michael@0 259 }
michael@0 260
michael@0 261 void printheader() {
michael@0 262 printf("# \n"
michael@0 263 "# This Source Code Form is subject to the terms of the Mozilla Public\n"
michael@0 264 "# License, v. 2.0. If a copy of the MPL was not distributed with this\n"
michael@0 265 "# file, You can obtain one at http://mozilla.org/MPL/2.0/.\n"
michael@0 266 "#\n"
michael@0 267 "CVS_ID \"@(#) $RCSfile$ $Revision$ $Date$\"\n"
michael@0 268 "\n"
michael@0 269 "#\n"
michael@0 270 "# certdata.txt\n"
michael@0 271 "#\n"
michael@0 272 "# This file contains the object definitions for the certs and other\n"
michael@0 273 "# information \"built into\" NSS.\n"
michael@0 274 "#\n"
michael@0 275 "# Object definitions:\n"
michael@0 276 "#\n"
michael@0 277 "# Certificates\n"
michael@0 278 "#\n"
michael@0 279 "# -- Attribute -- -- type -- -- value --\n"
michael@0 280 "# CKA_CLASS CK_OBJECT_CLASS CKO_CERTIFICATE\n"
michael@0 281 "# CKA_TOKEN CK_BBOOL CK_TRUE\n"
michael@0 282 "# CKA_PRIVATE CK_BBOOL CK_FALSE\n"
michael@0 283 "# CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
michael@0 284 "# CKA_LABEL UTF8 (varies)\n"
michael@0 285 "# CKA_CERTIFICATE_TYPE CK_CERTIFICATE_TYPE CKC_X_509\n"
michael@0 286 "# CKA_SUBJECT DER+base64 (varies)\n"
michael@0 287 "# CKA_ID byte array (varies)\n"
michael@0 288 "# CKA_ISSUER DER+base64 (varies)\n"
michael@0 289 "# CKA_SERIAL_NUMBER DER+base64 (varies)\n"
michael@0 290 "# CKA_VALUE DER+base64 (varies)\n"
michael@0 291 "# CKA_NSS_EMAIL ASCII7 (unused here)\n"
michael@0 292 "#\n"
michael@0 293 "# Trust\n"
michael@0 294 "#\n"
michael@0 295 "# -- Attribute -- -- type -- -- value --\n"
michael@0 296 "# CKA_CLASS CK_OBJECT_CLASS CKO_TRUST\n"
michael@0 297 "# CKA_TOKEN CK_BBOOL CK_TRUE\n"
michael@0 298 "# CKA_PRIVATE CK_BBOOL CK_FALSE\n"
michael@0 299 "# CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
michael@0 300 "# CKA_LABEL UTF8 (varies)\n"
michael@0 301 "# CKA_ISSUER DER+base64 (varies)\n"
michael@0 302 "# CKA_SERIAL_NUMBER DER+base64 (varies)\n"
michael@0 303 "# CKA_CERT_HASH binary+base64 (varies)\n"
michael@0 304 "# CKA_EXPIRES CK_DATE (not used here)\n"
michael@0 305 "# CKA_TRUST_DIGITAL_SIGNATURE CK_TRUST (varies)\n"
michael@0 306 "# CKA_TRUST_NON_REPUDIATION CK_TRUST (varies)\n"
michael@0 307 "# CKA_TRUST_KEY_ENCIPHERMENT CK_TRUST (varies)\n"
michael@0 308 "# CKA_TRUST_DATA_ENCIPHERMENT CK_TRUST (varies)\n"
michael@0 309 "# CKA_TRUST_KEY_AGREEMENT CK_TRUST (varies)\n"
michael@0 310 "# CKA_TRUST_KEY_CERT_SIGN CK_TRUST (varies)\n"
michael@0 311 "# CKA_TRUST_CRL_SIGN CK_TRUST (varies)\n"
michael@0 312 "# CKA_TRUST_SERVER_AUTH CK_TRUST (varies)\n"
michael@0 313 "# CKA_TRUST_CLIENT_AUTH CK_TRUST (varies)\n"
michael@0 314 "# CKA_TRUST_CODE_SIGNING CK_TRUST (varies)\n"
michael@0 315 "# CKA_TRUST_EMAIL_PROTECTION CK_TRUST (varies)\n"
michael@0 316 "# CKA_TRUST_IPSEC_END_SYSTEM CK_TRUST (varies)\n"
michael@0 317 "# CKA_TRUST_IPSEC_TUNNEL CK_TRUST (varies)\n"
michael@0 318 "# CKA_TRUST_IPSEC_USER CK_TRUST (varies)\n"
michael@0 319 "# CKA_TRUST_TIME_STAMPING CK_TRUST (varies)\n"
michael@0 320 "# (other trust attributes can be defined)\n"
michael@0 321 "#\n"
michael@0 322 "\n"
michael@0 323 "#\n"
michael@0 324 "# The object to tell NSS that this is a root list and we don't\n"
michael@0 325 "# have to go looking for others.\n"
michael@0 326 "#\n"
michael@0 327 "BEGINDATA\n"
michael@0 328 "CKA_CLASS CK_OBJECT_CLASS CKO_NSS_BUILTIN_ROOT_LIST\n"
michael@0 329 "CKA_TOKEN CK_BBOOL CK_TRUE\n"
michael@0 330 "CKA_PRIVATE CK_BBOOL CK_FALSE\n"
michael@0 331 "CKA_MODIFIABLE CK_BBOOL CK_FALSE\n"
michael@0 332 "CKA_LABEL UTF8 \"Mozilla Builtin Roots\"\n");
michael@0 333 }
michael@0 334
michael@0 335 static void Usage(char *progName)
michael@0 336 {
michael@0 337 fprintf(stderr, "%s -t trust -n nickname [-i certfile] [-c] [-h]\n", progName);
michael@0 338 fprintf(stderr,
michael@0 339 "\tRead a der-encoded cert from certfile or stdin, and output\n"
michael@0 340 "\tit to stdout in a format suitable for the builtin root module.\n"
michael@0 341 "\tExample: %s -n MyCA -t \"C,C,C\" -i myca.der >> certdata.txt\n",
michael@0 342 progName);
michael@0 343 fprintf(stderr, "%s -D -n label [-i certfile]\n", progName);
michael@0 344 fprintf(stderr,
michael@0 345 "\tRead a der-encoded cert from certfile or stdin, and output\n"
michael@0 346 "\ta distrust record.\n"
michael@0 347 "\t(-D is equivalent to -t p,p,p -c -h)\n");
michael@0 348 fprintf(stderr, "%s -C -e crl-entry-number -n label [-i crlfile]\n", progName);
michael@0 349 fprintf(stderr,
michael@0 350 "\tRead a CRL from crlfile or stdin, and output\n"
michael@0 351 "\ta distrust record (issuer+serial).\n"
michael@0 352 "\t(-C implies -c -h)\n");
michael@0 353 fprintf(stderr, "%-15s trust flags (cCTpPuw).\n", "-t trust");
michael@0 354 fprintf(stderr, "%-15s nickname to assign to builtin cert, or\n",
michael@0 355 "-n nickname");
michael@0 356 fprintf(stderr, "%-15s a label for the distrust record.\n", "");
michael@0 357 fprintf(stderr, "%-15s exclude the certificate (only add a trust record)\n", "-c");
michael@0 358 fprintf(stderr, "%-15s exclude hash from trust record\n", "-h");
michael@0 359 fprintf(stderr, "%-15s (useful to distrust any matching issuer/serial)\n", "");
michael@0 360 fprintf(stderr, "%-15s (not allowed when adding positive trust)\n", "");
michael@0 361 fprintf(stderr, "%-15s a CRL entry number, as shown by \"crlutil -S\"\n", "-e");
michael@0 362 fprintf(stderr, "%-15s input file to read (default stdin)\n", "-i file");
michael@0 363 fprintf(stderr, "%-15s (pipe through atob if the cert is b64-encoded)\n", "");
michael@0 364 exit(-1);
michael@0 365 }
michael@0 366
michael@0 367 enum {
michael@0 368 opt_Input = 0,
michael@0 369 opt_Nickname,
michael@0 370 opt_Trust,
michael@0 371 opt_Distrust,
michael@0 372 opt_ExcludeCert,
michael@0 373 opt_ExcludeHash,
michael@0 374 opt_DistrustCRL,
michael@0 375 opt_CRLEnry
michael@0 376 };
michael@0 377
michael@0 378 static secuCommandFlag addbuiltin_options[] =
michael@0 379 {
michael@0 380 { /* opt_Input */ 'i', PR_TRUE, 0, PR_FALSE },
michael@0 381 { /* opt_Nickname */ 'n', PR_TRUE, 0, PR_FALSE },
michael@0 382 { /* opt_Trust */ 't', PR_TRUE, 0, PR_FALSE },
michael@0 383 { /* opt_Distrust */ 'D', PR_FALSE, 0, PR_FALSE },
michael@0 384 { /* opt_ExcludeCert */ 'c', PR_FALSE, 0, PR_FALSE },
michael@0 385 { /* opt_ExcludeHash */ 'h', PR_FALSE, 0, PR_FALSE },
michael@0 386 { /* opt_DistrustCRL */ 'C', PR_FALSE, 0, PR_FALSE },
michael@0 387 { /* opt_CRLEnry */ 'e', PR_TRUE, 0, PR_FALSE },
michael@0 388 };
michael@0 389
michael@0 390 int main(int argc, char **argv)
michael@0 391 {
michael@0 392 SECStatus rv;
michael@0 393 char *nickname = NULL;
michael@0 394 char *trusts = NULL;
michael@0 395 char *progName;
michael@0 396 PRFileDesc *infile;
michael@0 397 CERTCertTrust trust = { 0 };
michael@0 398 SECItem derItem = { 0 };
michael@0 399 PRInt32 crlentry = 0;
michael@0 400 PRInt32 mutuallyExclusiveOpts = 0;
michael@0 401 PRBool decodeTrust = PR_FALSE;
michael@0 402
michael@0 403 secuCommand addbuiltin = { 0 };
michael@0 404 addbuiltin.numOptions = sizeof(addbuiltin_options)/sizeof(secuCommandFlag);
michael@0 405 addbuiltin.options = addbuiltin_options;
michael@0 406
michael@0 407 progName = strrchr(argv[0], '/');
michael@0 408 progName = progName ? progName+1 : argv[0];
michael@0 409
michael@0 410 rv = SECU_ParseCommandLine(argc, argv, progName, &addbuiltin);
michael@0 411
michael@0 412 if (rv != SECSuccess)
michael@0 413 Usage(progName);
michael@0 414
michael@0 415 if (addbuiltin.options[opt_Trust].activated)
michael@0 416 ++mutuallyExclusiveOpts;
michael@0 417 if (addbuiltin.options[opt_Distrust].activated)
michael@0 418 ++mutuallyExclusiveOpts;
michael@0 419 if (addbuiltin.options[opt_DistrustCRL].activated)
michael@0 420 ++mutuallyExclusiveOpts;
michael@0 421
michael@0 422 if (mutuallyExclusiveOpts != 1) {
michael@0 423 fprintf(stderr, "%s: you must specify exactly one of -t or -D or -C\n",
michael@0 424 progName);
michael@0 425 Usage(progName);
michael@0 426 }
michael@0 427
michael@0 428 if (addbuiltin.options[opt_DistrustCRL].activated) {
michael@0 429 if (!addbuiltin.options[opt_CRLEnry].activated) {
michael@0 430 fprintf(stderr, "%s: you must specify the CRL entry number.\n",
michael@0 431 progName);
michael@0 432 Usage(progName);
michael@0 433 }
michael@0 434 else {
michael@0 435 crlentry = atoi(addbuiltin.options[opt_CRLEnry].arg);
michael@0 436 if (crlentry < 1) {
michael@0 437 fprintf(stderr, "%s: The CRL entry number must be > 0.\n",
michael@0 438 progName);
michael@0 439 Usage(progName);
michael@0 440 }
michael@0 441 }
michael@0 442 }
michael@0 443
michael@0 444 if (!addbuiltin.options[opt_Nickname].activated) {
michael@0 445 fprintf(stderr, "%s: you must specify parameter -n (a nickname or a label).\n",
michael@0 446 progName);
michael@0 447 Usage(progName);
michael@0 448 }
michael@0 449
michael@0 450 if (addbuiltin.options[opt_Input].activated) {
michael@0 451 infile = PR_Open(addbuiltin.options[opt_Input].arg, PR_RDONLY, 00660);
michael@0 452 if (!infile) {
michael@0 453 fprintf(stderr, "%s: failed to open input file.\n", progName);
michael@0 454 exit(1);
michael@0 455 }
michael@0 456 } else {
michael@0 457 #if defined(WIN32)
michael@0 458 /* If we're going to read binary data from stdin, we must put stdin
michael@0 459 ** into O_BINARY mode or else incoming \r\n's will become \n's,
michael@0 460 ** and latin-1 characters will be altered.
michael@0 461 */
michael@0 462
michael@0 463 int smrv = _setmode(_fileno(stdin), _O_BINARY);
michael@0 464 if (smrv == -1) {
michael@0 465 fprintf(stderr,
michael@0 466 "%s: Cannot change stdin to binary mode. Use -i option instead.\n",
michael@0 467 progName);
michael@0 468 exit(1);
michael@0 469 }
michael@0 470 #endif
michael@0 471 infile = PR_STDIN;
michael@0 472 }
michael@0 473
michael@0 474 #if defined(WIN32)
michael@0 475 /* We must put stdout into O_BINARY mode or else the output will include
michael@0 476 ** carriage returns.
michael@0 477 */
michael@0 478 {
michael@0 479 int smrv = _setmode(_fileno(stdout), _O_BINARY);
michael@0 480 if (smrv == -1) {
michael@0 481 fprintf(stderr, "%s: Cannot change stdout to binary mode.\n", progName);
michael@0 482 exit(1);
michael@0 483 }
michael@0 484 }
michael@0 485 #endif
michael@0 486
michael@0 487 nickname = strdup(addbuiltin.options[opt_Nickname].arg);
michael@0 488
michael@0 489 NSS_NoDB_Init(NULL);
michael@0 490
michael@0 491 if (addbuiltin.options[opt_Distrust].activated ||
michael@0 492 addbuiltin.options[opt_DistrustCRL].activated) {
michael@0 493 addbuiltin.options[opt_ExcludeCert].activated = PR_TRUE;
michael@0 494 addbuiltin.options[opt_ExcludeHash].activated = PR_TRUE;
michael@0 495 }
michael@0 496
michael@0 497 if (addbuiltin.options[opt_Distrust].activated) {
michael@0 498 trusts = strdup("p,p,p");
michael@0 499 decodeTrust = PR_TRUE;
michael@0 500 }
michael@0 501 else if (addbuiltin.options[opt_Trust].activated) {
michael@0 502 trusts = strdup(addbuiltin.options[opt_Trust].arg);
michael@0 503 decodeTrust = PR_TRUE;
michael@0 504 }
michael@0 505
michael@0 506 if (decodeTrust) {
michael@0 507 rv = CERT_DecodeTrustString(&trust, trusts);
michael@0 508 if (rv) {
michael@0 509 fprintf(stderr, "%s: incorrectly formatted trust string.\n", progName);
michael@0 510 Usage(progName);
michael@0 511 }
michael@0 512 }
michael@0 513
michael@0 514 if (addbuiltin.options[opt_Trust].activated &&
michael@0 515 addbuiltin.options[opt_ExcludeHash].activated) {
michael@0 516 if ((trust.sslFlags | trust.emailFlags | trust.objectSigningFlags)
michael@0 517 != CERTDB_TERMINAL_RECORD) {
michael@0 518 fprintf(stderr, "%s: Excluding the hash only allowed with distrust.\n", progName);
michael@0 519 Usage(progName);
michael@0 520 }
michael@0 521 }
michael@0 522
michael@0 523 SECU_FileToItem(&derItem, infile);
michael@0 524
michael@0 525 /*printheader();*/
michael@0 526
michael@0 527 if (addbuiltin.options[opt_DistrustCRL].activated) {
michael@0 528 rv = ConvertCRLEntry(&derItem, crlentry, nickname);
michael@0 529 }
michael@0 530 else {
michael@0 531 rv = ConvertCertificate(&derItem, nickname, &trust,
michael@0 532 addbuiltin.options[opt_ExcludeCert].activated,
michael@0 533 addbuiltin.options[opt_ExcludeHash].activated);
michael@0 534 if (rv) {
michael@0 535 fprintf(stderr, "%s: failed to convert certificate.\n", progName);
michael@0 536 exit(1);
michael@0 537 }
michael@0 538 }
michael@0 539
michael@0 540 if (NSS_Shutdown() != SECSuccess) {
michael@0 541 exit(1);
michael@0 542 }
michael@0 543
michael@0 544 return(SECSuccess);
michael@0 545 }

mercurial