tor-browser

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

util.c (30205B)


      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 #include "signtool.h"
      6 #include "prio.h"
      7 #include "prmem.h"
      8 #include "prenv.h"
      9 #include "nss.h"
     10 
     11 static int is_dir(char *filename);
     12 
     13 /***********************************************************
     14 * Nasty hackish function definitions
     15 */
     16 
     17 long *mozilla_event_queue = 0;
     18 
     19 #ifndef XP_WIN
     20 char *
     21 XP_GetString(int i)
     22 {
     23    /* nasty hackish cast to avoid changing the signature of
     24     * JAR_init_callbacks() */
     25    return (char *)SECU_Strerror(i);
     26 }
     27 #endif
     28 
     29 void
     30 FE_SetPasswordEnabled()
     31 {
     32 }
     33 
     34 void /*MWContext*/ *
     35 FE_GetInitContext(void)
     36 {
     37    return 0;
     38 }
     39 
     40 void /*MWContext*/ *
     41 XP_FindSomeContext()
     42 {
     43    /* No windows context in command tools */
     44    return NULL;
     45 }
     46 
     47 void
     48 ET_moz_CallFunction()
     49 {
     50 }
     51 
     52 /*
     53 *  R e m o v e A l l A r c
     54 *
     55 *  Remove .arc directories that are lingering
     56 *  from a previous run of signtool.
     57 *
     58 */
     59 int
     60 RemoveAllArc(char *tree)
     61 {
     62    PRDir *dir;
     63    PRDirEntry *entry;
     64    char *archive = NULL;
     65    int retval = 0;
     66 
     67    dir = PR_OpenDir(tree);
     68    if (!dir)
     69        return -1;
     70 
     71    for (entry = PR_ReadDir(dir, 0); entry; entry = PR_ReadDir(dir,
     72                                                               0)) {
     73 
     74        if (entry->name[0] == '.') {
     75            continue;
     76        }
     77 
     78        if (archive)
     79            PR_Free(archive);
     80        archive = PR_smprintf("%s/%s", tree, entry->name);
     81 
     82        if (PL_strcaserstr(entry->name, ".arc") ==
     83            (entry->name + strlen(entry->name) - 4)) {
     84 
     85            if (verbosity >= 0) {
     86                PR_fprintf(outputFD, "removing: %s\n", archive);
     87            }
     88 
     89            if (rm_dash_r(archive)) {
     90                PR_fprintf(errorFD, "Error removing %s\n", archive);
     91                errorCount++;
     92                retval = -1;
     93                goto finish;
     94            }
     95        } else if (is_dir(archive)) {
     96            if (RemoveAllArc(archive)) {
     97                retval = -1;
     98                goto finish;
     99            }
    100        }
    101    }
    102 
    103 finish:
    104    PR_CloseDir(dir);
    105    if (archive)
    106        PR_Free(archive);
    107 
    108    return retval;
    109 }
    110 
    111 /*
    112 *  r m _ d a s h _ r
    113 *
    114 *  Remove a file, or a directory recursively.
    115 *
    116 */
    117 int
    118 rm_dash_r(char *path)
    119 {
    120    PRDir *dir;
    121    PRDirEntry *entry;
    122    PRFileInfo fileinfo;
    123    char filename[FNSIZE];
    124 
    125    if (PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
    126        /*fprintf(stderr, "Error: Unable to access %s\n", filename);*/
    127        return -1;
    128    }
    129    if (fileinfo.type == PR_FILE_DIRECTORY) {
    130 
    131        dir = PR_OpenDir(path);
    132        if (!dir) {
    133            PR_fprintf(errorFD, "Error: Unable to open directory %s.\n", path);
    134            errorCount++;
    135            return -1;
    136        }
    137 
    138        /* Recursively delete all entries in the directory */
    139        while ((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
    140            snprintf(filename, sizeof(filename), "%s/%s", path, entry->name);
    141            if (rm_dash_r(filename)) {
    142                PR_CloseDir(dir);
    143                return -1;
    144            }
    145        }
    146 
    147        if (PR_CloseDir(dir) != PR_SUCCESS) {
    148            PR_fprintf(errorFD, "Error: Could not close %s.\n", path);
    149            errorCount++;
    150            return -1;
    151        }
    152 
    153        /* Delete the directory itself */
    154        if (PR_RmDir(path) != PR_SUCCESS) {
    155            PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
    156            errorCount++;
    157            return -1;
    158        }
    159    } else {
    160        if (PR_Delete(path) != PR_SUCCESS) {
    161            PR_fprintf(errorFD, "Error: Unable to delete %s\n", path);
    162            errorCount++;
    163            return -1;
    164        }
    165    }
    166    return 0;
    167 }
    168 
    169 /*
    170 *  u s a g e
    171 *
    172 *  Print some useful help information
    173 *
    174 */
    175 
    176 void
    177 Usage(void)
    178 {
    179 #define FPS PR_fprintf(outputFD,
    180    FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
    181    FPS "\n\nType %s -H for more detailed descriptions\n", PROGRAM_NAME);
    182    FPS "\nUsage:  %s -k keyName [-b basename] [-c Compression Level]\n"
    183        "\t\t [-d cert-dir] [-i installer script] [-m metafile] [-x name]\n"
    184        "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
    185        "\t\t [--norecurse] [--leavearc] [-j directory] [-Z jarfile] [-O]\n"
    186        "\t\t [-p password] directory-tree\n", PROGRAM_NAME);
    187    FPS "\t%s -J -k keyName [-b basename] [-c Compression Level]\n"
    188        "\t\t [-d cert-dir][-i installer script] [-m metafile] [-x name]\n"
    189        "\t\t [-e extension] [-o] [-z] [-X] [--outfile] [--verbose value]\n"
    190        "\t\t [--norecurse] [--leavearc] [-j directory] [-p password] [-O] \n"
    191        "\t\t directory-tree\n", PROGRAM_NAME);
    192    FPS "\t%s -h \n", PROGRAM_NAME);
    193    FPS "\t%s -H \n", PROGRAM_NAME);
    194    FPS "\t%s -l [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
    195    FPS "\t%s -L [-k keyName] [-d cert-dir] [--outfile] [-O] \n", PROGRAM_NAME);
    196    FPS "\t%s -M [--outfile] [-O] \n", PROGRAM_NAME);
    197    FPS "\t%s -v [-d cert-dir] [--outfile] [-O] archive\n", PROGRAM_NAME);
    198    FPS "\t%s -w [--outfile] [-O] archive\n" , PROGRAM_NAME);
    199    FPS "\t%s -G nickname [--keysize|-s size] [-t |--token tokenname]\n"
    200        "\t\t [--outfile] [-O] \n", PROGRAM_NAME);
    201    FPS "\t%s -f filename\n" , PROGRAM_NAME);
    202    exit(ERRX);
    203 }
    204 
    205 void
    206 LongUsage(void)
    207 {
    208    FPS "%s %s -a signing tool for jar files\n", LONG_PROGRAM_NAME,NSS_VERSION);
    209    FPS "\n%-20s  Signs the directory-tree\n",
    210        "signtool directory-tree");
    211    FPS "%-30s Nickname (key) of the certificate to sign with\n",
    212        "   -k keyname");
    213    FPS "%-30s Base filename for the .rsa and.sf files in the\n",
    214        "   -b basename");
    215    FPS "%-30s META-INF directory\n"," ");
    216    FPS "%-30s Set the compression level. 0-9, 0=none\n",
    217    "   -c CompressionLevel");
    218    FPS "%-30s Certificate database directory containing cert*db\n",
    219    "   -d certificate directory");
    220    FPS "%-30s and key*db\n"," ");
    221    FPS "%-30s Name of the installer script for SmartUpdate\n",
    222    "   -i installer script");
    223    FPS "%-30s Name of a metadata control file\n",
    224    "   -m metafile");
    225    FPS "%-30s For optimizing the archive for size.\n",
    226    "   -o");
    227    FPS "%-30s Omit Optional Headers\n"," ");
    228    FPS "%-30s Excludes the specified directory or file from\n",
    229    "   -x  directory or file name");
    230    FPS "%-30s signing\n"," ");
    231    FPS "%-30s To not store the signing time in digital\n",
    232    "   -z  directory or file name");
    233    FPS "%-30s signature\n"," ");
    234    FPS "%-30s Create XPI Compatible Archive. It requires -Z\n",
    235    "   -X  directory or file name");
    236    FPS "%-30s option\n"," ");
    237    FPS "%-30s Sign only files with the given extension\n",
    238    "   -e");
    239    FPS "%-30s Causes the specified directory to be signed and\n",
    240    "   -j");
    241    FPS "%-30s tags its entries as inline JavaScript\n"," ");
    242    FPS "%-30s Creates a JAR file with the specified name.\n",
    243    "   -Z");
    244    FPS "%-30s -Z option cannot be used with -J option\n"," ");
    245    FPS "%-30s Specifies a password for the private-key database\n",
    246    "   -p");
    247    FPS "%-30s (insecure)\n"," ");
    248    FPS "%-30s File to receive redirected output\n",
    249        "   --outfile filename");
    250    FPS "%-30s Sets the quantity of information generated in\n",
    251    "   --verbosity value");
    252    FPS "%-30s operation\n"," ");
    253    FPS "%-30s Blocks recursion into subdirectories\n",
    254    "   --norecurse");
    255    FPS "%-30s Retains the temporary .arc (archive) directories\n",
    256    "   --leavearc");
    257    FPS "%-30s -J option creates\n"," ");
    258 
    259    FPS "\n%-20s Signs a directory of HTML files containing JavaScript and\n",
    260    "-J" );
    261    FPS "%-20s creates as many archive files as are in the HTML tags.\n"," ");
    262 
    263    FPS "%-20s The options are same as without any command option given\n"," ");
    264    FPS "%-20s above. -Z and -J options are not allowed together\n"," ");
    265 
    266    FPS "\n%-20s Generates a new private-public key pair and corresponding\n",
    267    "-G nickname");
    268    FPS "%-20s object-signing certificates with the given nickname\n"," ");
    269    FPS "%-30s Specifies the size of the key for generated \n",
    270    "   --keysize|-s keysize");
    271    FPS "%-30s certificate\n"," ");
    272    FPS "%-30s Specifies which available token should generate\n",
    273    "   --token|-t token name ");
    274    FPS "%-30s the key and receive the certificate\n"," ");
    275    FPS "%-30s Specifies a file to receive redirected output\n",
    276    "   --outfile filename ");
    277 
    278    FPS "\n%-20s Display signtool help\n",
    279    "-h ");
    280 
    281    FPS "\n%-20s Display signtool help(Detailed)\n",
    282    "-H ");
    283 
    284    FPS "\n%-20s Lists signing certificates, including issuing CAs\n",
    285    "-l ");
    286    FPS "%-30s Certificate database directory containing cert*db\n",
    287    "   -d certificate directory");
    288    FPS "%-30s and key*db\n"," ");
    289 
    290    FPS "%-30s Specifies a file to receive redirected output\n",
    291    "   --outfile filename ");
    292    FPS "%-30s Specifies the nickname (key) of the certificate\n",
    293    "   -k keyname");
    294 
    295    FPS "\n%-20s Lists the certificates in your database\n",
    296    "-L ");
    297    FPS "%-30s Certificate database directory containing cert*db\n",
    298    "   -d certificate directory");
    299    FPS "%-30s and key*db\n"," ");
    300 
    301    FPS "%-30s Specifies a file to receive redirected output\n",
    302    "   --outfile filename ");
    303    FPS "%-30s Specifies the nickname (key) of the certificate\n",
    304    "   -k keyname");
    305 
    306    FPS "\n%-20s Lists the PKCS #11 modules available to signtool\n",
    307    "-M ");
    308 
    309    FPS "\n%-20s Displays the contents of an archive and verifies\n",
    310    "-v archive");
    311    FPS "%-20s cryptographic integrity\n"," ");
    312    FPS "%-30s Certificate database directory containing cert*db\n",
    313    "   -d certificate directory");
    314    FPS "%-30s and key*db\n"," ");
    315    FPS "%-30s Specifies a file to receive redirected output\n",
    316    "   --outfile filename ");
    317 
    318    FPS "\n%-20s Displays the names of signers in the archive\n",
    319    "-w archive");
    320    FPS "%-30s Specifies a file to receive redirected output\n",
    321    "   --outfile filename ");
    322 
    323    FPS "\n%-30s Common option to all the above.\n",
    324    "   -O");
    325    FPS "%-30s Enable OCSP checking\n"," ");
    326 
    327    FPS "\n%-20s Specifies a text file containing options and arguments in\n",
    328    "-f command-file");
    329    FPS "%-20s keyword=value format. Commands are taken from this file\n"," ");
    330 
    331    FPS  "\n\n\n");
    332    FPS  "Example:\n");
    333    FPS  "%-10s -d \"certificate directory\" -k \"certnickname\" \\",
    334         PROGRAM_NAME);
    335    FPS  "\n%-10s -p \"password\"  -X -Z \"file.xpi\" directory-tree\n"," " );
    336    FPS  "Common syntax to create an XPInstall compatible"
    337         " signed archive\n\n"," ");
    338    FPS  "\nCommand File Keywords and Example:\n");
    339    FPS "\nKeyword\t\tValue\n");
    340    FPS "basename\tSame as -b option\n");
    341    FPS "compression\tSame as -c option\n");
    342    FPS "certdir\t\tSame as -d option\n");
    343    FPS "extension\tSame as -e option\n");
    344    FPS "generate\tSame as -G option\n");
    345    FPS "installscript\tSame as -i option\n");
    346    FPS "javascriptdir\tSame as -j option\n");
    347    FPS "htmldir\t\tSame as -J option\n");
    348    FPS "certname\tNickname of certificate, as with -k  option\n");
    349    FPS "signdir\t\tThe directory to be signed, as with -k option\n");
    350    FPS "list\t\tSame as -l option. Value is ignored,\n"
    351        "    \t\tbut = sign must be present\n");
    352    FPS "listall\t\tSame as -L option. Value is ignored\n"
    353        "       \t\tbut = sign must be present\n");
    354    FPS "metafile\tSame as -m option\n");
    355    FPS "modules\t\tSame as -M option. Value is ignored,\n"
    356        "       \t\tbut = sign must be present\n");
    357    FPS "optimize\tSame as -o option. Value is ignored,\n"
    358        "        \tbut = sign must be present\n");
    359    FPS "ocsp\t\tSame as -O option\n");
    360    FPS "password\tSame as -p option\n");
    361    FPS "verify\t\tSame as -v option\n");
    362    FPS "who\t\tSame as -w option\n");
    363    FPS "exclude\t\tSame as -x option\n");
    364    FPS "notime\t\tSame as -z option. Value is ignored,\n"
    365        "      \t\tbut = sign must be present\n");
    366    FPS "jarfile\t\tSame as -Z option\n");
    367    FPS "outfile\t\tSame as --outfile option. The argument\n");
    368    FPS "       \t\tis the name of a file to which output\n");
    369    FPS "       \t\tof a file and error messages will be  \n");
    370    FPS "       \t\tredirected\n");
    371    FPS "leavearc\tSame as --leavearc option\n");
    372    FPS "verbosity\tSame as --verbosity option\n");
    373    FPS "keysize\t\tSame as -s option\n");
    374    FPS "token\t\tSame as -t option\n");
    375    FPS "xpi\t\tSame as -X option\n");
    376    FPS "\n\n");
    377    FPS "Here's an example of the use of the command file. The command\n\n");
    378    FPS "   signtool -d c:\\netscape\\users\\james -k mycert -Z myjar.jar \\\n"
    379        "   signdir > output.txt\n\n");
    380    FPS "becomes\n\n");
    381    FPS "   signtool -f somefile\n\n");
    382    FPS "where somefile contains the following lines:\n\n");
    383    FPS "   certdir=c:\\netscape\\users\\james\n"," ");
    384    FPS "   certname=mycert\n"," ");
    385    FPS "   jarfile=myjar.jar\n"," ");
    386    FPS "   signdir=signdir\n"," ");
    387    FPS "   outfile=output.txt\n"," ");
    388    exit(ERRX);
    389 #undef FPS
    390 }
    391 
    392 /*
    393 *  p r i n t _ e r r o r
    394 *
    395 *  For the undocumented -E function. If an older version
    396 *  of communicator gives you a numeric error, we can see what
    397 *  really happened without doing hex math.
    398 *
    399 */
    400 
    401 void
    402 print_error(int err)
    403 {
    404    PR_fprintf(errorFD, "Error %d: %s\n", err, JAR_get_error(err));
    405    errorCount++;
    406    give_help(err);
    407 }
    408 
    409 /*
    410 *  o u t _ o f _ m e m o r y
    411 *
    412 *  Out of memory, exit Signtool.
    413 *
    414 */
    415 void
    416 out_of_memory(void)
    417 {
    418    PR_fprintf(errorFD, "%s: out of memory\n", PROGRAM_NAME);
    419    errorCount++;
    420    exit(ERRX);
    421 }
    422 
    423 /*
    424 *  V e r i f y C e r t D i r
    425 *
    426 *  Validate that the specified directory
    427 *  contains a certificate database
    428 *
    429 */
    430 void
    431 VerifyCertDir(char *dir, char *keyName)
    432 {
    433    /* this function is truly evil. Tools and applications should not have
    434     * any knowledge of actual cert databases! */
    435    return;
    436 }
    437 
    438 /*
    439 *  f o r e a c h
    440 *
    441 *  A recursive function to loop through all names in
    442 *  the specified directory, as well as all subdirectories.
    443 *
    444 *  FIX: Need to see if all platforms allow multiple
    445 *  opendir's to be called.
    446 *
    447 */
    448 
    449 int foreach (char *dirname, char *prefix,
    450             int (*fn)(char *relpath, char *basedir, char *reldir, char *filename,
    451                       void *arg),
    452             PRBool recurse, PRBool includeDirs, void *arg)
    453 {
    454    char newdir[FNSIZE];
    455    int retval = 0;
    456 
    457    PRDir *dir;
    458    PRDirEntry *entry;
    459 
    460    strcpy(newdir, dirname);
    461    if (*prefix) {
    462        strcat(newdir, "/");
    463        strcat(newdir, prefix);
    464    }
    465 
    466    dir = PR_OpenDir(newdir);
    467    if (!dir)
    468        return -1;
    469 
    470    for (entry = PR_ReadDir(dir, 0); entry; entry = PR_ReadDir(dir, 0)) {
    471        if (strcmp(entry->name, ".") == 0 ||
    472            strcmp(entry->name, "..") == 0) {
    473            /* no infinite recursion, please */
    474            continue;
    475        }
    476 
    477        /* can't sign self */
    478        if (!strcmp(entry->name, "META-INF"))
    479            continue;
    480 
    481        /* -x option */
    482        if (PL_HashTableLookup(excludeDirs, entry->name))
    483            continue;
    484 
    485        strcpy(newdir, dirname);
    486        if (*dirname)
    487            strcat(newdir, "/");
    488 
    489        if (*prefix) {
    490            strcat(newdir, prefix);
    491            strcat(newdir, "/");
    492        }
    493        strcat(newdir, entry->name);
    494 
    495        if (!is_dir(newdir) || includeDirs) {
    496            char newpath[FNSIZE];
    497 
    498            strcpy(newpath, prefix);
    499            if (*newpath)
    500                strcat(newpath, "/");
    501            strcat(newpath, entry->name);
    502 
    503            if ((*fn)(newpath, dirname, prefix, (char *)entry->name,
    504                      arg)) {
    505                retval = -1;
    506                break;
    507            }
    508        }
    509 
    510        if (is_dir(newdir)) {
    511            if (recurse) {
    512                char newprefix[FNSIZE];
    513 
    514                strcpy(newprefix, prefix);
    515                if (*newprefix) {
    516                    strcat(newprefix, "/");
    517                }
    518                strcat(newprefix, entry->name);
    519 
    520                if (foreach (dirname, newprefix, fn, recurse,
    521                             includeDirs, arg)) {
    522                    retval = -1;
    523                    break;
    524                }
    525            }
    526        }
    527    }
    528 
    529    PR_CloseDir(dir);
    530 
    531    return retval;
    532 }
    533 
    534 /*
    535 *  i s _ d i r
    536 *
    537 *  Return 1 if file is a directory.
    538 *  Wonder if this runs on a mac, trust not.
    539 *
    540 */
    541 static int
    542 is_dir(char *filename)
    543 {
    544    PRFileInfo finfo;
    545 
    546    if (PR_GetFileInfo(filename, &finfo) != PR_SUCCESS) {
    547        printf("Unable to get information about %s\n", filename);
    548        return 0;
    549    }
    550 
    551    return (finfo.type == PR_FILE_DIRECTORY);
    552 }
    553 
    554 /***************************************************************
    555 *
    556 * s e c E r r o r S t r i n g
    557 *
    558 * Returns an error string corresponding to the given error code.
    559 * Doesn't cover all errors; returns a default for many.
    560 * Returned string is only valid until the next call of this function.
    561 */
    562 const char *
    563 secErrorString(long code)
    564 {
    565    static char errstring[80]; /* dynamically constructed error string */
    566    char *c;                   /* the returned string */
    567 
    568    switch (code) {
    569        case SEC_ERROR_IO:
    570            c = "io error";
    571            break;
    572        case SEC_ERROR_LIBRARY_FAILURE:
    573            c = "security library failure";
    574            break;
    575        case SEC_ERROR_BAD_DATA:
    576            c = "bad data";
    577            break;
    578        case SEC_ERROR_OUTPUT_LEN:
    579            c = "output length";
    580            break;
    581        case SEC_ERROR_INPUT_LEN:
    582            c = "input length";
    583            break;
    584        case SEC_ERROR_INVALID_ARGS:
    585            c = "invalid args";
    586            break;
    587        case SEC_ERROR_EXPIRED_CERTIFICATE:
    588            c = "expired certificate";
    589            break;
    590        case SEC_ERROR_REVOKED_CERTIFICATE:
    591            c = "revoked certificate";
    592            break;
    593        case SEC_ERROR_INADEQUATE_KEY_USAGE:
    594            c = "inadequate key usage";
    595            break;
    596        case SEC_ERROR_INADEQUATE_CERT_TYPE:
    597            c = "inadequate certificate type";
    598            break;
    599        case SEC_ERROR_UNTRUSTED_CERT:
    600            c = "untrusted cert";
    601            break;
    602        case SEC_ERROR_NO_KRL:
    603            c = "no key revocation list";
    604            break;
    605        case SEC_ERROR_KRL_BAD_SIGNATURE:
    606            c = "key revocation list: bad signature";
    607            break;
    608        case SEC_ERROR_KRL_EXPIRED:
    609            c = "key revocation list expired";
    610            break;
    611        case SEC_ERROR_REVOKED_KEY:
    612            c = "revoked key";
    613            break;
    614        case SEC_ERROR_CRL_BAD_SIGNATURE:
    615            c = "certificate revocation list: bad signature";
    616            break;
    617        case SEC_ERROR_CRL_EXPIRED:
    618            c = "certificate revocation list expired";
    619            break;
    620        case SEC_ERROR_CRL_NOT_YET_VALID:
    621            c = "certificate revocation list not yet valid";
    622            break;
    623        case SEC_ERROR_UNKNOWN_ISSUER:
    624            c = "unknown issuer";
    625            break;
    626        case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE:
    627            c = "expired issuer certificate";
    628            break;
    629        case SEC_ERROR_BAD_SIGNATURE:
    630            c = "bad signature";
    631            break;
    632        case SEC_ERROR_BAD_KEY:
    633            c = "bad key";
    634            break;
    635        case SEC_ERROR_NOT_FORTEZZA_ISSUER:
    636            c = "not fortezza issuer";
    637            break;
    638        case SEC_ERROR_CA_CERT_INVALID:
    639            c = "Certificate Authority certificate invalid";
    640            break;
    641        case SEC_ERROR_EXTENSION_NOT_FOUND:
    642            c = "extension not found";
    643            break;
    644        case SEC_ERROR_CERT_NOT_IN_NAME_SPACE:
    645            c = "certificate not in name space";
    646            break;
    647        case SEC_ERROR_UNTRUSTED_ISSUER:
    648            c = "untrusted issuer";
    649            break;
    650        default:
    651            snprintf(errstring, sizeof(errstring), "security error %ld", code);
    652            c = errstring;
    653            break;
    654    }
    655 
    656    return c;
    657 }
    658 
    659 /***************************************************************
    660 *
    661 * d i s p l a y V e r i f y L o g
    662 *
    663 * Prints the log of a cert verification.
    664 */
    665 void
    666 displayVerifyLog(CERTVerifyLog *log)
    667 {
    668    CERTVerifyLogNode *node;
    669    CERTCertificate *cert;
    670    char *name;
    671 
    672    if (!log || (log->count <= 0)) {
    673        return;
    674    }
    675 
    676    for (node = log->head; node != NULL; node = node->next) {
    677 
    678        if (!(cert = node->cert)) {
    679            continue;
    680        }
    681 
    682        /* Get a name for this cert */
    683        if (cert->nickname != NULL) {
    684            name = cert->nickname;
    685        } else if (cert->emailAddr && cert->emailAddr[0]) {
    686            name = cert->emailAddr;
    687        } else {
    688            name = cert->subjectName;
    689        }
    690 
    691        printf("%s%s:\n", name,
    692               (node->depth > 0) ? " [Certificate Authority]" : "");
    693 
    694        printf("\t%s\n", secErrorString(node->error));
    695    }
    696 }
    697 
    698 /*
    699 *  J a r L i s t M o d u l e s
    700 *
    701 *  Print a list of the PKCS11 modules that are
    702 *  available. This is useful for smartcard people to
    703 *  make sure they have the drivers loaded.
    704 *
    705 */
    706 void
    707 JarListModules(void)
    708 {
    709    int i;
    710    int count = 0;
    711 
    712    SECMODModuleList *modules = NULL;
    713    static SECMODListLock *moduleLock = NULL;
    714 
    715    SECMODModuleList *mlp;
    716 
    717    if ((moduleLock = SECMOD_GetDefaultModuleListLock()) == NULL) {
    718        /* this is the wrong text */
    719        PR_fprintf(errorFD, "%s: unable to acquire lock on module list\n",
    720                   PROGRAM_NAME);
    721        errorCount++;
    722        exit(ERRX);
    723    }
    724 
    725    SECMOD_GetReadLock(moduleLock);
    726 
    727    modules = SECMOD_GetDefaultModuleList();
    728 
    729    if (modules == NULL) {
    730        SECMOD_ReleaseReadLock(moduleLock);
    731        PR_fprintf(errorFD, "%s: Can't get module list\n", PROGRAM_NAME);
    732        errorCount++;
    733        exit(ERRX);
    734    }
    735 
    736    PR_fprintf(outputFD, "\nListing of PKCS11 modules\n");
    737    PR_fprintf(outputFD, "-----------------------------------------------\n");
    738 
    739    for (mlp = modules; mlp != NULL; mlp = mlp->next) {
    740        count++;
    741        PR_fprintf(outputFD, "%3d. %s\n", count, mlp->module->commonName);
    742 
    743        if (mlp->module->internal)
    744            PR_fprintf(outputFD, "          (this module is internally loaded)\n");
    745        else
    746            PR_fprintf(outputFD, "          (this is an external module)\n");
    747 
    748        if (mlp->module->dllName)
    749            PR_fprintf(outputFD, "          DLL name: %s\n",
    750                       mlp->module->dllName);
    751 
    752        if (mlp->module->slotCount == 0)
    753            PR_fprintf(outputFD, "          slots: There are no slots attached to this module\n");
    754        else
    755            PR_fprintf(outputFD, "          slots: %d slots attached\n",
    756                       mlp->module->slotCount);
    757 
    758        if (mlp->module->loaded == 0)
    759            PR_fprintf(outputFD, "          status: Not loaded\n");
    760        else
    761            PR_fprintf(outputFD, "          status: loaded\n");
    762 
    763        for (i = 0; i < mlp->module->slotCount; i++) {
    764            PK11SlotInfo *slot = mlp->module->slots[i];
    765 
    766            PR_fprintf(outputFD, "\n");
    767            PR_fprintf(outputFD, "    slot: %s\n", PK11_GetSlotName(slot));
    768            PR_fprintf(outputFD, "   token: %s\n", PK11_GetTokenName(slot));
    769        }
    770    }
    771 
    772    PR_fprintf(outputFD, "-----------------------------------------------\n");
    773 
    774    if (count == 0)
    775        PR_fprintf(outputFD,
    776                   "Warning: no modules were found (should have at least one)\n");
    777 
    778    SECMOD_ReleaseReadLock(moduleLock);
    779 }
    780 
    781 /**********************************************************************
    782 * c h o p
    783 *
    784 * Eliminates leading and trailing whitespace.  Returns a pointer to the
    785 * beginning of non-whitespace, or an empty string if it's all whitespace.
    786 */
    787 char *
    788 chop(char *str)
    789 {
    790    char *start, *end;
    791 
    792    if (str) {
    793        start = str;
    794 
    795        /* Nip leading whitespace */
    796        while (isspace((unsigned char)*start)) {
    797            start++;
    798        }
    799 
    800        /* Nip trailing whitespace */
    801        if (*start) {
    802            end = start + strlen(start) - 1;
    803            while (isspace((unsigned char)*end) && end > start) {
    804                end--;
    805            }
    806            *(end + 1) = '\0';
    807        }
    808 
    809        return start;
    810    } else {
    811        return NULL;
    812    }
    813 }
    814 
    815 /***********************************************************************
    816 *
    817 * F a t a l E r r o r
    818 *
    819 * Outputs an error message and bails out of the program.
    820 */
    821 void
    822 FatalError(char *msg)
    823 {
    824    if (!msg)
    825        msg = "";
    826 
    827    PR_fprintf(errorFD, "FATAL ERROR: %s\n", msg);
    828    errorCount++;
    829    exit(ERRX);
    830 }
    831 
    832 /*************************************************************************
    833 *
    834 * I n i t C r y p t o
    835 */
    836 int
    837 InitCrypto(char *cert_dir, PRBool readOnly)
    838 {
    839    SECStatus rv;
    840    static int prior = 0;
    841    PK11SlotInfo *slotinfo;
    842 
    843    if (prior == 0) {
    844        /* some functions such as OpenKeyDB expect this path to be
    845         * implicitly set prior to calling */
    846        if (readOnly) {
    847            rv = NSS_Init(cert_dir);
    848        } else {
    849            rv = NSS_InitReadWrite(cert_dir);
    850        }
    851        if (rv != SECSuccess) {
    852            SECU_PrintPRandOSError(PROGRAM_NAME);
    853            exit(-1);
    854        }
    855 
    856        SECU_ConfigDirectory(cert_dir);
    857 
    858        /* Been there done that */
    859        prior++;
    860 
    861        PK11_SetPasswordFunc(SECU_GetModulePassword);
    862 
    863        /* Must login to FIPS before you do anything else */
    864        if (PK11_IsFIPS()) {
    865            slotinfo = PK11_GetInternalSlot();
    866            if (!slotinfo) {
    867                fprintf(stderr, "%s: Unable to get PKCS #11 Internal Slot."
    868                                "\n",
    869                        PROGRAM_NAME);
    870                return -1;
    871            }
    872            if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
    873                                  &pwdata) != SECSuccess) {
    874                fprintf(stderr, "%s: Unable to authenticate to %s.\n",
    875                        PROGRAM_NAME, PK11_GetSlotName(slotinfo));
    876                PK11_FreeSlot(slotinfo);
    877                return -1;
    878            }
    879            PK11_FreeSlot(slotinfo);
    880        }
    881 
    882        /* Make sure there is a password set on the internal key slot */
    883        slotinfo = PK11_GetInternalKeySlot();
    884        if (!slotinfo) {
    885            fprintf(stderr, "%s: Unable to get PKCS #11 Internal Key Slot."
    886                            "\n",
    887                    PROGRAM_NAME);
    888            return -1;
    889        }
    890        if (PK11_NeedUserInit(slotinfo)) {
    891            PR_fprintf(errorFD,
    892                       "\nWARNING: No password set on internal key database.  Most operations will fail."
    893                       "\nYou must create a password.\n");
    894            warningCount++;
    895        }
    896 
    897        /* Make sure we can authenticate to the key slot in FIPS mode */
    898        if (PK11_IsFIPS()) {
    899            if (PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
    900                                  &pwdata) != SECSuccess) {
    901                fprintf(stderr, "%s: Unable to authenticate to %s.\n",
    902                        PROGRAM_NAME, PK11_GetSlotName(slotinfo));
    903                PK11_FreeSlot(slotinfo);
    904                return -1;
    905            }
    906        }
    907        PK11_FreeSlot(slotinfo);
    908    }
    909 
    910    return 0;
    911 }
    912 
    913 /* Windows foolishness is now in the secutil lib */
    914 
    915 /*****************************************************************
    916 *  g e t _ d e f a u l t _ c e r t _ d i r
    917 *
    918 *  Attempt to locate a certificate directory.
    919 *  Failing that, complain that the user needs to
    920 *  use the -d(irectory) parameter.
    921 *
    922 */
    923 char *
    924 get_default_cert_dir(void)
    925 {
    926    char *home;
    927 
    928    char *cd = NULL;
    929    static char db[FNSIZE];
    930 
    931 #ifdef XP_UNIX
    932    home = PR_GetEnvSecure("HOME");
    933 
    934    if (home && *home) {
    935        snprintf(db, sizeof(db), "%s/.netscape", home);
    936        cd = db;
    937    }
    938 #endif
    939 
    940 #ifdef XP_PC
    941    FILE *fp;
    942 
    943    /* first check the environment override */
    944 
    945    home = PR_GetEnvSecure("JAR_HOME");
    946 
    947    if (home && *home) {
    948        snprintf(db, sizeof(db), "%s/cert7.db", home);
    949 
    950        if ((fp = fopen(db, "r")) != NULL) {
    951            fclose(fp);
    952            cd = home;
    953        }
    954    }
    955 
    956    /* try the old navigator directory */
    957 
    958    if (cd == NULL) {
    959        home = "c:/Program Files/Netscape/Navigator";
    960 
    961        snprintf(db, sizeof(db), "%s/cert7.db", home);
    962 
    963        if ((fp = fopen(db, "r")) != NULL) {
    964            fclose(fp);
    965            cd = home;
    966        }
    967    }
    968 
    969    /* Try the current directory, I wonder if this
    970     is really a good idea. Remember, Windows only.. */
    971 
    972    if (cd == NULL) {
    973        home = ".";
    974 
    975        snprintf(db, sizeof(db), "%s/cert7.db", home);
    976 
    977        if ((fp = fopen(db, "r")) != NULL) {
    978            fclose(fp);
    979            cd = home;
    980        }
    981    }
    982 
    983 #endif
    984 
    985    if (!cd) {
    986        PR_fprintf(errorFD,
    987                   "You must specify the location of your certificate directory\n");
    988        PR_fprintf(errorFD,
    989                   "with the -d option. Example: -d ~/.netscape in many cases with Unix.\n");
    990        errorCount++;
    991        exit(ERRX);
    992    }
    993 
    994    return cd;
    995 }
    996 
    997 /************************************************************************
    998 * g i v e _ h e l p
    999 */
   1000 void
   1001 give_help(int status)
   1002 {
   1003    if (status == SEC_ERROR_UNKNOWN_ISSUER) {
   1004        PR_fprintf(errorFD,
   1005                   "The Certificate Authority (CA) for this certificate\n");
   1006        PR_fprintf(errorFD,
   1007                   "does not appear to be in your database. You should contact\n");
   1008        PR_fprintf(errorFD,
   1009                   "the organization which issued this certificate to obtain\n");
   1010        PR_fprintf(errorFD, "a copy of its CA Certificate.\n");
   1011    }
   1012 }
   1013 
   1014 /**************************************************************************
   1015 *
   1016 * p r _ f g e t s
   1017 *
   1018 * fgets implemented with NSPR.
   1019 */
   1020 char *
   1021 pr_fgets(char *buf, int size, PRFileDesc *file)
   1022 {
   1023    int i;
   1024    int status;
   1025    char c;
   1026 
   1027    i = 0;
   1028    while (i < size - 1) {
   1029        status = PR_Read(file, &c, 1);
   1030        if (status == -1) {
   1031            return NULL;
   1032        } else if (status == 0) {
   1033            if (i == 0) {
   1034                return NULL;
   1035            }
   1036            break;
   1037        }
   1038        buf[i++] = c;
   1039        if (c == '\n') {
   1040            break;
   1041        }
   1042    }
   1043    buf[i] = '\0';
   1044 
   1045    return buf;
   1046 }