tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

addbuiltin.c (22456B)


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