Wed, 31 Dec 2014 07:16:47 +0100
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 | } |