tor-browser

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

dbtest.c (7497B)


      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 ** dbtest.c
      7 **
      8 ** QA test for cert and key databases, especially to open
      9 ** database readonly (NSS_INIT_READONLY) and force initializations
     10 ** even if the databases cannot be opened (NSS_INIT_FORCEOPEN)
     11 **
     12 */
     13 #include <stdio.h>
     14 #include <string.h>
     15 
     16 #if defined(WIN32)
     17 #include "fcntl.h"
     18 #include "io.h"
     19 #endif
     20 
     21 #include "secutil.h"
     22 #include "pk11pub.h"
     23 
     24 #if defined(XP_UNIX)
     25 #include <unistd.h>
     26 #endif
     27 
     28 #include "nspr.h"
     29 #include "prtypes.h"
     30 #include "certdb.h"
     31 #include "nss.h"
     32 #include "../modutil/modutil.h"
     33 
     34 #include "plgetopt.h"
     35 
     36 static char *progName;
     37 
     38 char *dbDir = NULL;
     39 
     40 static char *dbName[] = { "secmod.db", "cert8.db", "key3.db" };
     41 static char *dbprefix = "";
     42 static char *secmodName = "secmod.db";
     43 static char *userPassword = "";
     44 PRBool verbose;
     45 
     46 static char *
     47 getPassword(PK11SlotInfo *slot, PRBool retry, void *arg)
     48 {
     49    int *success = (int *)arg;
     50 
     51    if (retry) {
     52        *success = 0;
     53        return NULL;
     54    }
     55 
     56    *success = 1;
     57    return PORT_Strdup(userPassword);
     58 }
     59 
     60 static void
     61 Usage()
     62 {
     63    printf("Usage:  %s [-r] [-f] [-i] [-d dbdir ] \n",
     64           progName);
     65    printf("%-20s open database readonly (NSS_INIT_READONLY)\n", "-r");
     66    printf("%-20s Continue to force initializations even if the\n", "-f");
     67    printf("%-20s databases cannot be opened (NSS_INIT_FORCEOPEN)\n", " ");
     68    printf("%-20s Try to initialize the database\n", "-i");
     69    printf("%-20s Supply a password with which to initialize the db\n", "-p");
     70    printf("%-20s Directory with cert database (default is .\n",
     71           "-d certdir");
     72    exit(1);
     73 }
     74 
     75 int
     76 main(int argc, char **argv)
     77 {
     78    PLOptState *optstate;
     79    PLOptStatus optstatus;
     80 
     81    PRUint32 flags = 0;
     82    Error ret;
     83    SECStatus rv;
     84    char *dbString = NULL;
     85    PRBool doInitTest = PR_FALSE;
     86    int i;
     87 
     88    progName = strrchr(argv[0], '/');
     89    if (!progName)
     90        progName = strrchr(argv[0], '\\');
     91    progName = progName ? progName + 1 : argv[0];
     92 
     93    optstate = PL_CreateOptState(argc, argv, "rfip:d:h");
     94 
     95    while ((optstatus = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
     96        switch (optstate->option) {
     97            case 'h':
     98            default:
     99                Usage();
    100                break;
    101 
    102            case 'r':
    103                flags |= NSS_INIT_READONLY;
    104                break;
    105 
    106            case 'f':
    107                flags |= NSS_INIT_FORCEOPEN;
    108                break;
    109 
    110            case 'i':
    111                doInitTest = PR_TRUE;
    112                break;
    113 
    114            case 'p':
    115                userPassword = PORT_Strdup(optstate->value);
    116                break;
    117 
    118            case 'd':
    119                dbDir = PORT_Strdup(optstate->value);
    120                break;
    121        }
    122    }
    123    PL_DestroyOptState(optstate);
    124    if (optstatus == PL_OPT_BAD)
    125        Usage();
    126 
    127    if (dbDir) {
    128        char *tmp = dbDir;
    129        dbDir = SECU_ConfigDirectory(tmp);
    130        PORT_Free(tmp);
    131    } else {
    132        /* Look in $SSL_DIR */
    133        dbDir = SECU_ConfigDirectory(SECU_DefaultSSLDir());
    134    }
    135    PR_fprintf(PR_STDERR, "dbdir selected is %s\n\n", dbDir);
    136 
    137    if (dbDir[0] == '\0') {
    138        PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
    139        ret = DIR_DOESNT_EXIST_ERR;
    140        goto loser;
    141    }
    142 
    143    PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
    144 
    145    /* get the status of the directory and databases and output message */
    146    if (PR_Access(dbDir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
    147        PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dbDir);
    148    } else if (PR_Access(dbDir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
    149        PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dbDir);
    150    } else {
    151        if (!(flags & NSS_INIT_READONLY) &&
    152            PR_Access(dbDir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
    153            PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dbDir);
    154        }
    155        if (!doInitTest) {
    156            for (i = 0; i < 3; i++) {
    157                dbString = PR_smprintf("%s/%s", dbDir, dbName[i]);
    158                PR_fprintf(PR_STDOUT, "database checked is %s\n", dbString);
    159                if (PR_Access(dbString, PR_ACCESS_EXISTS) != PR_SUCCESS) {
    160                    PR_fprintf(PR_STDERR, errStrings[FILE_DOESNT_EXIST_ERR],
    161                               dbString);
    162                } else if (PR_Access(dbString, PR_ACCESS_READ_OK) != PR_SUCCESS) {
    163                    PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
    164                               dbString);
    165                } else if (!(flags & NSS_INIT_READONLY) &&
    166                           PR_Access(dbString, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
    167                    PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
    168                               dbString);
    169                }
    170                PR_smprintf_free(dbString);
    171            }
    172        }
    173    }
    174 
    175    rv = NSS_Initialize(SECU_ConfigDirectory(dbDir), dbprefix, dbprefix,
    176                        secmodName, flags);
    177    if (rv != SECSuccess) {
    178        SECU_PrintPRandOSError(progName);
    179        ret = NSS_INITIALIZE_FAILED_ERR;
    180    } else {
    181        ret = SUCCESS;
    182        if (doInitTest) {
    183            PK11SlotInfo *slot = PK11_GetInternalKeySlot();
    184            int passwordSuccess = 0;
    185            int type = CKM_DES3_CBC;
    186            SECItem keyid = { 0, NULL, 0 };
    187            unsigned char keyIdData[] = { 0xff, 0xfe };
    188            PK11SymKey *key = NULL;
    189 
    190            keyid.data = keyIdData;
    191            keyid.len = sizeof(keyIdData);
    192 
    193            PK11_SetPasswordFunc(getPassword);
    194            rv = PK11_InitPin(slot, (char *)NULL, userPassword);
    195            if (rv != SECSuccess) {
    196                PR_fprintf(PR_STDERR, "Failed to Init DB: %s\n",
    197                           SECU_Strerror(PORT_GetError()));
    198                ret = CHANGEPW_FAILED_ERR;
    199            }
    200            if (*userPassword && !PK11_IsLoggedIn(slot, &passwordSuccess)) {
    201                PR_fprintf(PR_STDERR, "New DB did not log in after init\n");
    202                ret = AUTHENTICATION_FAILED_ERR;
    203            }
    204            /* generate a symetric key */
    205            key = PK11_TokenKeyGen(slot, type, NULL, 0, &keyid,
    206                                   PR_TRUE, &passwordSuccess);
    207 
    208            if (!key) {
    209                PR_fprintf(PR_STDERR, "Could not generated symetric key: %s\n",
    210                           SECU_Strerror(PORT_GetError()));
    211                exit(UNSPECIFIED_ERR);
    212            }
    213            PK11_FreeSymKey(key);
    214            PK11_Logout(slot);
    215 
    216            PK11_Authenticate(slot, PR_TRUE, &passwordSuccess);
    217 
    218            if (*userPassword && !passwordSuccess) {
    219                PR_fprintf(PR_STDERR, "New DB Did not initalize\n");
    220                ret = AUTHENTICATION_FAILED_ERR;
    221            }
    222            key = PK11_FindFixedKey(slot, type, &keyid, &passwordSuccess);
    223 
    224            if (!key) {
    225                PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
    226                           SECU_Strerror(PORT_GetError()));
    227                ret = UNSPECIFIED_ERR;
    228            } else {
    229                PK11_FreeSymKey(key);
    230            }
    231            PK11_FreeSlot(slot);
    232        }
    233 
    234        if (NSS_Shutdown() != SECSuccess) {
    235            PR_fprintf(PR_STDERR, "Could not find generated key: %s\n",
    236                       SECU_Strerror(PORT_GetError()));
    237            exit(1);
    238        }
    239    }
    240 
    241 loser:
    242    return ret;
    243 }