tor-browser

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

pk11.c (32169B)


      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 /* To edit this file, set TABSTOPS to 4 spaces.
      6 * This is not the normal NSS convention.
      7 */
      8 
      9 #include "modutil.h"
     10 #include "pk11func.h"
     11 
     12 /*************************************************************************
     13 *
     14 * F i p s M o d e
     15 * If arg=="true", enable FIPS mode on the internal module.  If arg=="false",
     16 * disable FIPS mode on the internal module.
     17 */
     18 Error
     19 FipsMode(char *arg)
     20 {
     21    char *internal_name;
     22 
     23    if (!PORT_Strcasecmp(arg, "true")) {
     24        if (!PK11_IsFIPS()) {
     25            internal_name = PR_smprintf("%s",
     26                                        SECMOD_GetInternalModule()->commonName);
     27            if (SECMOD_DeleteInternalModule(internal_name) != SECSuccess) {
     28                PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError()));
     29                PR_smprintf_free(internal_name);
     30                PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
     31                return FIPS_SWITCH_FAILED_ERR;
     32            }
     33            PR_smprintf_free(internal_name);
     34            if (!PK11_IsFIPS()) {
     35                PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
     36                return FIPS_SWITCH_FAILED_ERR;
     37            }
     38            PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
     39        } else {
     40            PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_ON_ERR]);
     41            return FIPS_ALREADY_ON_ERR;
     42        }
     43    } else if (!PORT_Strcasecmp(arg, "false")) {
     44        if (PK11_IsFIPS()) {
     45            internal_name = PR_smprintf("%s",
     46                                        SECMOD_GetInternalModule()->commonName);
     47            if (SECMOD_DeleteInternalModule(internal_name) != SECSuccess) {
     48                PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError()));
     49                PR_smprintf_free(internal_name);
     50                PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
     51                return FIPS_SWITCH_FAILED_ERR;
     52            }
     53            PR_smprintf_free(internal_name);
     54            if (PK11_IsFIPS()) {
     55                PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
     56                return FIPS_SWITCH_FAILED_ERR;
     57            }
     58            PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
     59        } else {
     60            PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_OFF_ERR]);
     61            return FIPS_ALREADY_OFF_ERR;
     62        }
     63    } else {
     64        PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
     65        return INVALID_FIPS_ARG;
     66    }
     67 
     68    return SUCCESS;
     69 }
     70 
     71 /*************************************************************************
     72 *
     73 * C h k F i p s M o d e
     74 * If arg=="true", verify FIPS mode is enabled on the internal module.
     75 * If arg=="false", verify FIPS mode is disabled on the internal module.
     76 */
     77 Error
     78 ChkFipsMode(char *arg)
     79 {
     80    if (!PORT_Strcasecmp(arg, "true")) {
     81        if (PK11_IsFIPS()) {
     82            PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
     83        } else {
     84            PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
     85            return FIPS_SWITCH_FAILED_ERR;
     86        }
     87 
     88    } else if (!PORT_Strcasecmp(arg, "false")) {
     89        if (!PK11_IsFIPS()) {
     90            PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
     91        } else {
     92            PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
     93            return FIPS_SWITCH_FAILED_ERR;
     94        }
     95    } else {
     96        PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
     97        return INVALID_FIPS_ARG;
     98    }
     99 
    100    return SUCCESS;
    101 }
    102 
    103 /************************************************************************
    104 * Cipher and Mechanism name-bitmask translation tables
    105 */
    106 
    107 typedef struct {
    108    const char *name;
    109    unsigned long mask;
    110 } MaskString;
    111 
    112 static const MaskString cipherStrings[] = {
    113    { "FORTEZZA", PUBLIC_CIPHER_FORTEZZA_FLAG }
    114 };
    115 static const int numCipherStrings =
    116    sizeof(cipherStrings) / sizeof(cipherStrings[0]);
    117 
    118 /* Initialized by LoadMechanismList */
    119 static MaskString *mechanismStrings = NULL;
    120 static int numMechanismStrings = 0;
    121 const static PK11DefaultArrayEntry *pk11_DefaultArray = NULL;
    122 static int pk11_DefaultArraySize = 0;
    123 
    124 /* Maximum length of a colon-separated list of all the strings in an
    125 * array. */
    126 #define MAX_STRING_LIST_LEN 240 /* or less */
    127 
    128 Error
    129 LoadMechanismList(void)
    130 {
    131    int i;
    132 
    133    if (pk11_DefaultArray == NULL) {
    134        pk11_DefaultArray = PK11_GetDefaultArray(&pk11_DefaultArraySize);
    135        if (pk11_DefaultArray == NULL) {
    136            /* should assert. This shouldn't happen */
    137            return UNSPECIFIED_ERR;
    138        }
    139    }
    140    if (mechanismStrings != NULL) {
    141        return SUCCESS;
    142    }
    143 
    144    /* build the mechanismStrings array */
    145    mechanismStrings = PORT_NewArray(MaskString, pk11_DefaultArraySize);
    146    if (mechanismStrings == NULL) {
    147        return OUT_OF_MEM_ERR;
    148    }
    149    numMechanismStrings = pk11_DefaultArraySize;
    150    for (i = 0; i < numMechanismStrings; i++) {
    151        const char *name = pk11_DefaultArray[i].name;
    152        unsigned long flag = pk11_DefaultArray[i].flag;
    153        /* map new name to old */
    154        switch (flag) {
    155            case SECMOD_FORTEZZA_FLAG:
    156                name = "FORTEZZA";
    157                break;
    158            case SECMOD_SHA1_FLAG:
    159                name = "SHA1";
    160                break;
    161            case SECMOD_CAMELLIA_FLAG:
    162                name = "CAMELLIA";
    163                break;
    164            case SECMOD_RANDOM_FLAG:
    165                name = "RANDOM";
    166                break;
    167            case SECMOD_FRIENDLY_FLAG:
    168                name = "FRIENDLY";
    169                break;
    170            default:
    171                break;
    172        }
    173        mechanismStrings[i].name = name;
    174        mechanismStrings[i].mask = SECMOD_InternaltoPubMechFlags(flag);
    175    }
    176    return SUCCESS;
    177 }
    178 
    179 /************************************************************************
    180 *
    181 * g e t F l a g s F r o m S t r i n g
    182 *
    183 * Parses a mechanism list passed on the command line and converts it
    184 * to an unsigned long bitmask.
    185 * string is a colon-separated string of constants
    186 * array is an array of MaskStrings.
    187 * elements is the number of elements in array.
    188 */
    189 static unsigned long
    190 getFlagsFromString(char *string, const MaskString array[], int elements)
    191 {
    192    unsigned long ret = 0;
    193    short i = 0;
    194    char *cp;
    195    char *buf;
    196    char *end;
    197 
    198    if (!string || !string[0]) {
    199        return ret;
    200    }
    201 
    202    /* Make a temporary copy of the string */
    203    buf = PR_Malloc(strlen(string) + 1);
    204    if (!buf) {
    205        out_of_memory();
    206    }
    207    strcpy(buf, string);
    208 
    209    /* Look at each element of the list passed in */
    210    for (cp = buf; cp && *cp; cp = (end ? end + 1 : NULL)) {
    211        /* Look at the string up to the next colon */
    212        end = strchr(cp, ':');
    213        if (end) {
    214            *end = '\0';
    215        }
    216 
    217        /* Find which element this is */
    218        for (i = 0; i < elements; i++) {
    219            if (!PORT_Strcasecmp(cp, array[i].name)) {
    220                break;
    221            }
    222        }
    223        if (i == elements) {
    224            /* Skip a bogus string, but print a warning message */
    225            PR_fprintf(PR_STDERR, errStrings[INVALID_CONSTANT_ERR], cp);
    226            continue;
    227        }
    228        ret |= array[i].mask;
    229    }
    230 
    231    PR_Free(buf);
    232    return ret;
    233 }
    234 
    235 /**********************************************************************
    236 *
    237 * g e t S t r i n g F r o m F l a g s
    238 *
    239 * The return string's memory is owned by this function.  Copy it
    240 * if you need it permanently or you want to change it.
    241 */
    242 static char *
    243 getStringFromFlags(unsigned long flags, const MaskString array[], int elements)
    244 {
    245    static char buf[MAX_STRING_LIST_LEN];
    246    int i;
    247    int count = 0;
    248 
    249    buf[0] = '\0';
    250    for (i = 0; i < elements; i++) {
    251        if (flags & array[i].mask) {
    252            ++count;
    253            if (count != 1) {
    254                strcat(buf, ":");
    255            }
    256            strcat(buf, array[i].name);
    257        }
    258    }
    259    return buf;
    260 }
    261 
    262 static PRBool
    263 IsP11KitProxyModule(SECMODModule *module)
    264 {
    265    CK_INFO modinfo;
    266    static const char p11KitManufacturerID[33] =
    267        "PKCS#11 Kit                     ";
    268    static const char p11KitLibraryDescription[33] =
    269        "PKCS#11 Kit Proxy Module        ";
    270 
    271    if (PK11_GetModInfo(module, &modinfo) == SECSuccess &&
    272        PORT_Memcmp(modinfo.manufacturerID,
    273                    p11KitManufacturerID,
    274                    sizeof(modinfo.manufacturerID)) == 0 &&
    275        PORT_Memcmp(modinfo.libraryDescription,
    276                    p11KitLibraryDescription,
    277                    sizeof(modinfo.libraryDescription)) == 0) {
    278        return PR_TRUE;
    279    }
    280 
    281    return PR_FALSE;
    282 }
    283 
    284 PRBool
    285 IsP11KitEnabled(void)
    286 {
    287    SECMODListLock *lock;
    288    SECMODModuleList *mlp;
    289    PRBool found = PR_FALSE;
    290 
    291    lock = SECMOD_GetDefaultModuleListLock();
    292    if (!lock) {
    293        PR_fprintf(PR_STDERR, errStrings[NO_LIST_LOCK_ERR]);
    294        return found;
    295    }
    296 
    297    SECMOD_GetReadLock(lock);
    298 
    299    mlp = SECMOD_GetDefaultModuleList();
    300    for (; mlp != NULL; mlp = mlp->next) {
    301        if (IsP11KitProxyModule(mlp->module)) {
    302            found = PR_TRUE;
    303            break;
    304        }
    305    }
    306 
    307    SECMOD_ReleaseReadLock(lock);
    308    return found;
    309 }
    310 
    311 /**********************************************************************
    312 *
    313 * A d d M o d u l e
    314 *
    315 * Add the named module, with the given library file, ciphers, and
    316 * default mechanism flags
    317 */
    318 Error
    319 AddModule(char *moduleName, char *libFile, char *cipherString,
    320          char *mechanismString, char *modparms)
    321 {
    322    unsigned long ciphers;
    323    unsigned long mechanisms;
    324    SECStatus status;
    325 
    326    mechanisms =
    327        getFlagsFromString(mechanismString, mechanismStrings,
    328                           numMechanismStrings);
    329    ciphers =
    330        getFlagsFromString(cipherString, cipherStrings, numCipherStrings);
    331 
    332    status =
    333        SECMOD_AddNewModuleEx(moduleName, libFile,
    334                              SECMOD_PubMechFlagstoInternal(mechanisms),
    335                              SECMOD_PubCipherFlagstoInternal(ciphers),
    336                              modparms, NULL);
    337 
    338    if (status != SECSuccess) {
    339        char *errtxt = NULL;
    340        PRInt32 copied = 0;
    341        if (PR_GetErrorTextLength()) {
    342            errtxt = PR_Malloc(PR_GetErrorTextLength() + 1);
    343            copied = PR_GetErrorText(errtxt);
    344        }
    345        if (copied && errtxt) {
    346            PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_ERR],
    347                       moduleName, errtxt);
    348            PR_Free(errtxt);
    349        } else {
    350            PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_ERR],
    351                       moduleName, SECU_Strerror(PORT_GetError()));
    352        }
    353        return ADD_MODULE_FAILED_ERR;
    354    } else {
    355        PR_fprintf(PR_STDOUT, msgStrings[ADD_MODULE_SUCCESS_MSG], moduleName);
    356        return SUCCESS;
    357    }
    358 }
    359 
    360 /***********************************************************************
    361 *
    362 * D e l e t e M o d u l e
    363 *
    364 * Deletes the named module from the database.
    365 */
    366 Error
    367 DeleteModule(char *moduleName)
    368 {
    369    SECStatus status;
    370    int type;
    371 
    372    status = SECMOD_DeleteModule(moduleName, &type);
    373 
    374    if (status != SECSuccess) {
    375        if (type == SECMOD_FIPS || type == SECMOD_INTERNAL) {
    376            PR_fprintf(PR_STDERR, errStrings[DELETE_INTERNAL_ERR]);
    377            return DELETE_INTERNAL_ERR;
    378        } else {
    379            PR_fprintf(PR_STDERR, errStrings[DELETE_FAILED_ERR], moduleName);
    380            return DELETE_FAILED_ERR;
    381        }
    382    }
    383 
    384    PR_fprintf(PR_STDOUT, msgStrings[DELETE_SUCCESS_MSG], moduleName);
    385    return SUCCESS;
    386 }
    387 
    388 /************************************************************************
    389 *
    390 * R a w L i s t M o d u l e s
    391 *
    392 * Lists all the modules in the database, along with their slots and tokens.
    393 */
    394 Error
    395 RawListModule(char *modulespec)
    396 {
    397    SECMODModule *module;
    398    char **moduleSpecList;
    399 
    400    module = SECMOD_LoadModule(modulespec, NULL, PR_FALSE);
    401    if (module == NULL) {
    402        /* handle error */
    403        return NO_SUCH_MODULE_ERR;
    404    }
    405 
    406    moduleSpecList = SECMOD_GetModuleSpecList(module);
    407    if (!moduleSpecList || !moduleSpecList[0]) {
    408        SECU_PrintError("modutil",
    409                        "no specs in secmod DB");
    410        return NO_SUCH_MODULE_ERR;
    411    }
    412 
    413    for (; *moduleSpecList; moduleSpecList++) {
    414        printf("%s\n\n", *moduleSpecList);
    415    }
    416 
    417    return SUCCESS;
    418 }
    419 
    420 Error
    421 RawAddModule(char *dbmodulespec, char *modulespec)
    422 {
    423    SECMODModule *module;
    424    SECMODModule *dbmodule;
    425 
    426    dbmodule = SECMOD_LoadModule(dbmodulespec, NULL, PR_TRUE);
    427    if (dbmodule == NULL) {
    428        /* handle error */
    429        return NO_SUCH_MODULE_ERR;
    430    }
    431 
    432    module = SECMOD_LoadModule(modulespec, dbmodule, PR_FALSE);
    433    if (module == NULL) {
    434        /* handle error */
    435        return NO_SUCH_MODULE_ERR;
    436    }
    437 
    438    if (SECMOD_UpdateModule(module) != SECSuccess) {
    439        PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], modulespec);
    440        return UPDATE_MOD_FAILED_ERR;
    441    }
    442    return SUCCESS;
    443 }
    444 
    445 static void
    446 printModule(SECMODModule *module, int *count)
    447 {
    448    int slotCount = module->loaded ? module->slotCount : 0;
    449    char *modUri;
    450    int i;
    451 
    452    if ((*count)++) {
    453        PR_fprintf(PR_STDOUT, "\n");
    454    }
    455    PR_fprintf(PR_STDOUT, "%3d. %s\n", *count, module->commonName);
    456 
    457    if (module->dllName) {
    458        PR_fprintf(PR_STDOUT, "\tlibrary name: %s\n", module->dllName);
    459    }
    460 
    461    modUri = PK11_GetModuleURI(module);
    462    if (modUri) {
    463        PR_fprintf(PR_STDOUT, "\t   uri: %s\n", modUri);
    464        PORT_Free(modUri);
    465    }
    466    if (slotCount == 0) {
    467        PR_fprintf(PR_STDOUT,
    468                   "\t slots: There are no slots attached to this module\n");
    469    } else {
    470        PR_fprintf(PR_STDOUT, "\t slots: %d slot%s attached\n",
    471                   slotCount, (slotCount == 1 ? "" : "s"));
    472    }
    473 
    474    if (module->loaded == 0) {
    475        PR_fprintf(PR_STDOUT, "\tstatus: Not loaded\n");
    476    } else {
    477        PR_fprintf(PR_STDOUT, "\tstatus: loaded\n");
    478    }
    479 
    480    /* Print slot and token names */
    481    for (i = 0; i < slotCount; i++) {
    482        PK11SlotInfo *slot = module->slots[i];
    483        char *tokenUri = PK11_GetTokenURI(slot);
    484        PR_fprintf(PR_STDOUT, "\n");
    485        PR_fprintf(PR_STDOUT, "\t slot: %s\n", PK11_GetSlotName(slot));
    486        PR_fprintf(PR_STDOUT, "\ttoken: %s\n", PK11_GetTokenName(slot));
    487        PR_fprintf(PR_STDOUT, "\t  uri: %s\n", tokenUri);
    488        PORT_Free(tokenUri);
    489    }
    490    return;
    491 }
    492 
    493 /************************************************************************
    494 *
    495 * L i s t M o d u l e s
    496 *
    497 * Lists all the modules in the database, along with their slots and tokens.
    498 */
    499 Error
    500 ListModules()
    501 {
    502    SECMODListLock *lock;
    503    SECMODModuleList *list;
    504    SECMODModuleList *deadlist;
    505    SECMODModuleList *mlp;
    506    Error ret = UNSPECIFIED_ERR;
    507    int count = 0;
    508 
    509    lock = SECMOD_GetDefaultModuleListLock();
    510    if (!lock) {
    511        PR_fprintf(PR_STDERR, errStrings[NO_LIST_LOCK_ERR]);
    512        return NO_LIST_LOCK_ERR;
    513    }
    514 
    515    SECMOD_GetReadLock(lock);
    516 
    517    list = SECMOD_GetDefaultModuleList();
    518    deadlist = SECMOD_GetDeadModuleList();
    519    if (!list && !deadlist) {
    520        PR_fprintf(PR_STDERR, errStrings[NO_MODULE_LIST_ERR]);
    521        ret = NO_MODULE_LIST_ERR;
    522        goto loser;
    523    }
    524 
    525    PR_fprintf(PR_STDOUT,
    526               "\nListing of PKCS #11 Modules\n"
    527               "-----------------------------------------------------------\n");
    528 
    529    for (mlp = list; mlp != NULL; mlp = mlp->next) {
    530        printModule(mlp->module, &count);
    531    }
    532    for (mlp = deadlist; mlp != NULL; mlp = mlp->next) {
    533        printModule(mlp->module, &count);
    534    }
    535 
    536    PR_fprintf(PR_STDOUT,
    537               "-----------------------------------------------------------\n");
    538 
    539    ret = SUCCESS;
    540 
    541 loser:
    542    SECMOD_ReleaseReadLock(lock);
    543    return ret;
    544 }
    545 
    546 /* Strings describing PK11DisableReasons */
    547 static char *disableReasonStr[] = {
    548    "no reason",
    549    "user disabled",
    550    "could not initialize token",
    551    "could not verify token",
    552    "token not present"
    553 };
    554 static size_t numDisableReasonStr =
    555    sizeof(disableReasonStr) / sizeof(disableReasonStr[0]);
    556 
    557 /***********************************************************************
    558 *
    559 * L i s t M o d u l e
    560 *
    561 * Lists detailed information about the named module.
    562 */
    563 Error
    564 ListModule(char *moduleName)
    565 {
    566    SECMODModule *module = NULL;
    567    PK11SlotInfo *slot;
    568    int slotnum;
    569    CK_INFO modinfo;
    570    CK_SLOT_INFO slotinfo;
    571    CK_TOKEN_INFO tokeninfo;
    572    char *ciphers, *mechanisms;
    573    size_t reasonIdx;
    574    Error rv = SUCCESS;
    575 
    576    if (!moduleName) {
    577        return SUCCESS;
    578    }
    579 
    580    module = SECMOD_FindModule(moduleName);
    581    if (!module) {
    582        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
    583        rv = NO_SUCH_MODULE_ERR;
    584        goto loser;
    585    }
    586 
    587    if ((module->loaded) &&
    588        (PK11_GetModInfo(module, &modinfo) != SECSuccess)) {
    589        PR_fprintf(PR_STDERR, errStrings[MOD_INFO_ERR], moduleName);
    590        rv = MOD_INFO_ERR;
    591        goto loser;
    592    }
    593 
    594    /* Module info */
    595    PR_fprintf(PR_STDOUT,
    596               "\n-----------------------------------------------------------\n");
    597    PR_fprintf(PR_STDOUT, "Name: %s\n", module->commonName);
    598    if (module->internal || !module->dllName) {
    599        PR_fprintf(PR_STDOUT, "Library file: **Internal ONLY module**\n");
    600    } else {
    601        PR_fprintf(PR_STDOUT, "Library file: %s\n", module->dllName);
    602    }
    603 
    604    if (module->loaded) {
    605        PR_fprintf(PR_STDOUT, "Manufacturer: %.32s\n", modinfo.manufacturerID);
    606        PR_fprintf(PR_STDOUT, "Description: %.32s\n", modinfo.libraryDescription);
    607        PR_fprintf(PR_STDOUT, "PKCS #11 Version %d.%d\n",
    608                   modinfo.cryptokiVersion.major, modinfo.cryptokiVersion.minor);
    609        PR_fprintf(PR_STDOUT, "Library Version: %d.%d\n",
    610                   modinfo.libraryVersion.major, modinfo.libraryVersion.minor);
    611    } else {
    612        PR_fprintf(PR_STDOUT, "* Module not loaded\n");
    613    }
    614    /* Get cipher and mechanism flags */
    615    ciphers = getStringFromFlags(module->ssl[0], cipherStrings,
    616                                 numCipherStrings);
    617    if (ciphers[0] == '\0') {
    618        ciphers = "None";
    619    }
    620    PR_fprintf(PR_STDOUT, "Cipher Enable Flags: %s\n", ciphers);
    621    mechanisms = NULL;
    622    if (module->slotCount > 0) {
    623        mechanisms = getStringFromFlags(
    624            PK11_GetDefaultFlags(module->slots[0]),
    625            mechanismStrings, numMechanismStrings);
    626    }
    627    if ((mechanisms == NULL) || (mechanisms[0] == '\0')) {
    628        mechanisms = "None";
    629    }
    630    PR_fprintf(PR_STDOUT, "Default Mechanism Flags: %s\n", mechanisms);
    631 
    632 #define PAD "  "
    633 
    634    /* Loop over each slot */
    635    for (slotnum = 0; slotnum < module->slotCount; slotnum++) {
    636        slot = module->slots[slotnum];
    637        if (PK11_GetSlotInfo(slot, &slotinfo) != SECSuccess) {
    638            PR_fprintf(PR_STDERR, errStrings[SLOT_INFO_ERR],
    639                       PK11_GetSlotName(slot));
    640            rv = SLOT_INFO_ERR;
    641            continue;
    642        }
    643 
    644        /* Slot Info */
    645        PR_fprintf(PR_STDOUT, "\n" PAD "Slot: %s\n", PK11_GetSlotName(slot));
    646        mechanisms = getStringFromFlags(PK11_GetDefaultFlags(slot),
    647                                        mechanismStrings, numMechanismStrings);
    648        if (mechanisms[0] == '\0') {
    649            mechanisms = "None";
    650        }
    651        PR_fprintf(PR_STDOUT, PAD "Slot Mechanism Flags: %s\n", mechanisms);
    652        PR_fprintf(PR_STDOUT, PAD "Manufacturer: %.32s\n",
    653                   slotinfo.manufacturerID);
    654        if (PK11_IsHW(slot)) {
    655            PR_fprintf(PR_STDOUT, PAD "Type: Hardware\n");
    656        } else {
    657            PR_fprintf(PR_STDOUT, PAD "Type: Software\n");
    658        }
    659        PR_fprintf(PR_STDOUT, PAD "Version Number: %d.%d\n",
    660                   slotinfo.hardwareVersion.major, slotinfo.hardwareVersion.minor);
    661        PR_fprintf(PR_STDOUT, PAD "Firmware Version: %d.%d\n",
    662                   slotinfo.firmwareVersion.major, slotinfo.firmwareVersion.minor);
    663        if (PK11_IsDisabled(slot)) {
    664            reasonIdx = PK11_GetDisabledReason(slot);
    665            if (reasonIdx < numDisableReasonStr) {
    666                PR_fprintf(PR_STDOUT, PAD "Status: DISABLED (%s)\n",
    667                           disableReasonStr[reasonIdx]);
    668            } else {
    669                PR_fprintf(PR_STDOUT, PAD "Status: DISABLED\n");
    670            }
    671        } else {
    672            PR_fprintf(PR_STDOUT, PAD "Status: Enabled\n");
    673        }
    674 
    675        if (PK11_GetTokenInfo(slot, &tokeninfo) != SECSuccess) {
    676            PR_fprintf(PR_STDERR, errStrings[TOKEN_INFO_ERR],
    677                       PK11_GetTokenName(slot));
    678            rv = TOKEN_INFO_ERR;
    679            continue;
    680        }
    681 
    682        /* Token Info */
    683        PR_fprintf(PR_STDOUT, PAD "Token Name: %.32s\n",
    684                   tokeninfo.label);
    685        PR_fprintf(PR_STDOUT, PAD "Token Manufacturer: %.32s\n",
    686                   tokeninfo.manufacturerID);
    687        PR_fprintf(PR_STDOUT, PAD "Token Model: %.16s\n", tokeninfo.model);
    688        PR_fprintf(PR_STDOUT, PAD "Token Serial Number: %.16s\n",
    689                   tokeninfo.serialNumber);
    690        PR_fprintf(PR_STDOUT, PAD "Token Version: %d.%d\n",
    691                   tokeninfo.hardwareVersion.major, tokeninfo.hardwareVersion.minor);
    692        PR_fprintf(PR_STDOUT, PAD "Token Firmware Version: %d.%d\n",
    693                   tokeninfo.firmwareVersion.major, tokeninfo.firmwareVersion.minor);
    694        if (tokeninfo.flags & CKF_WRITE_PROTECTED) {
    695            PR_fprintf(PR_STDOUT, PAD "Access: Write Protected\n");
    696        } else {
    697            PR_fprintf(PR_STDOUT, PAD "Access: NOT Write Protected\n");
    698        }
    699        if (tokeninfo.flags & CKF_LOGIN_REQUIRED) {
    700            PR_fprintf(PR_STDOUT, PAD "Login Type: Login required\n");
    701        } else {
    702            PR_fprintf(PR_STDOUT, PAD
    703                       "Login Type: Public (no login required)\n");
    704        }
    705        if (tokeninfo.flags & CKF_USER_PIN_INITIALIZED) {
    706            PR_fprintf(PR_STDOUT, PAD "User Pin: Initialized\n");
    707        } else {
    708            PR_fprintf(PR_STDOUT, PAD "User Pin: NOT Initialized\n");
    709        }
    710    }
    711    PR_fprintf(PR_STDOUT,
    712               "\n-----------------------------------------------------------\n");
    713 loser:
    714    if (module) {
    715        SECMOD_DestroyModule(module);
    716    }
    717    return rv;
    718 }
    719 
    720 /************************************************************************
    721 *
    722 * I n i t P W
    723 */
    724 Error
    725 InitPW(void)
    726 {
    727    PK11SlotInfo *slot;
    728    Error ret = UNSPECIFIED_ERR;
    729 
    730    slot = PK11_GetInternalKeySlot();
    731    if (!slot) {
    732        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], "internal");
    733        return NO_SUCH_TOKEN_ERR;
    734    }
    735 
    736    /* Set the initial password to empty */
    737    if (PK11_NeedUserInit(slot)) {
    738        if (PK11_InitPin(slot, NULL, "") != SECSuccess) {
    739            PR_fprintf(PR_STDERR, errStrings[INITPW_FAILED_ERR]);
    740            ret = INITPW_FAILED_ERR;
    741            goto loser;
    742        }
    743    }
    744 
    745    ret = SUCCESS;
    746 
    747 loser:
    748    PK11_FreeSlot(slot);
    749 
    750    return ret;
    751 }
    752 
    753 /************************************************************************
    754 *
    755 * C h a n g e P W
    756 */
    757 Error
    758 ChangePW(char *tokenName, char *pwFile, char *newpwFile)
    759 {
    760    char *oldpw = NULL, *newpw = NULL, *newpw2 = NULL;
    761    PK11SlotInfo *slot;
    762    Error ret = UNSPECIFIED_ERR;
    763    PRBool matching;
    764 
    765    slot = PK11_FindSlotByName(tokenName);
    766    if (!slot) {
    767        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], tokenName);
    768        return NO_SUCH_TOKEN_ERR;
    769    }
    770 
    771    /* Get old password */
    772    if (!PK11_NeedUserInit(slot)) {
    773        if (pwFile) {
    774            oldpw = SECU_FilePasswd(NULL, PR_FALSE, pwFile);
    775            if (PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
    776                PR_fprintf(PR_STDERR, errStrings[BAD_PW_ERR]);
    777                ret = BAD_PW_ERR;
    778                goto loser;
    779            }
    780        } else if (PK11_NeedLogin(slot)) {
    781            for (matching = PR_FALSE; !matching;) {
    782                oldpw = SECU_GetPasswordString(NULL, "Enter old password: ");
    783                if (PK11_CheckUserPassword(slot, oldpw) == SECSuccess) {
    784                    matching = PR_TRUE;
    785                } else {
    786                    PR_fprintf(PR_STDOUT, msgStrings[BAD_PW_MSG]);
    787                }
    788            }
    789        }
    790    }
    791 
    792    /* Get new password */
    793    if (newpwFile) {
    794        newpw = SECU_FilePasswd(NULL, PR_FALSE, newpwFile);
    795    } else {
    796        for (matching = PR_FALSE; !matching;) {
    797            newpw = SECU_GetPasswordString(NULL, "Enter new password: ");
    798            newpw2 = SECU_GetPasswordString(NULL, "Re-enter new password: ");
    799            if (strcmp(newpw, newpw2)) {
    800                PR_fprintf(PR_STDOUT, msgStrings[PW_MATCH_MSG]);
    801                PORT_ZFree(newpw, strlen(newpw));
    802                PORT_ZFree(newpw2, strlen(newpw2));
    803            } else {
    804                matching = PR_TRUE;
    805            }
    806        }
    807    }
    808 
    809    /* Change the password */
    810    if (PK11_NeedUserInit(slot)) {
    811        if (PK11_InitPin(slot, NULL /*ssopw*/, newpw) != SECSuccess) {
    812            PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
    813            ret = CHANGEPW_FAILED_ERR;
    814            goto loser;
    815        }
    816    } else {
    817        if (PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
    818            PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
    819            ret = CHANGEPW_FAILED_ERR;
    820            goto loser;
    821        }
    822    }
    823 
    824    PR_fprintf(PR_STDOUT, msgStrings[CHANGEPW_SUCCESS_MSG], tokenName);
    825    ret = SUCCESS;
    826 
    827 loser:
    828    if (oldpw) {
    829        PORT_ZFree(oldpw, strlen(oldpw));
    830    }
    831    if (newpw) {
    832        PORT_ZFree(newpw, strlen(newpw));
    833    }
    834    if (newpw2) {
    835        PORT_ZFree(newpw2, strlen(newpw2));
    836    }
    837    PK11_FreeSlot(slot);
    838 
    839    return ret;
    840 }
    841 
    842 /***********************************************************************
    843 *
    844 * E n a b l e M o d u l e
    845 *
    846 * If enable==PR_TRUE, enables the module or slot.
    847 * If enable==PR_FALSE, disables the module or slot.
    848 * moduleName is the name of the module.
    849 * slotName is the name of the slot.  It is optional.
    850 */
    851 Error
    852 EnableModule(char *moduleName, char *slotName, PRBool enable)
    853 {
    854    int i;
    855    SECMODModule *module = NULL;
    856    PK11SlotInfo *slot = NULL;
    857    PRBool found = PR_FALSE;
    858    Error rv;
    859 
    860    module = SECMOD_FindModule(moduleName);
    861    if (!module) {
    862        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
    863        rv = NO_SUCH_MODULE_ERR;
    864        goto loser;
    865    }
    866 
    867    for (i = 0; i < module->slotCount; i++) {
    868        slot = module->slots[i];
    869        if (slotName && strcmp(PK11_GetSlotName(slot), slotName)) {
    870            /* Not the right slot */
    871            continue;
    872        }
    873        if (enable) {
    874            if (!PK11_UserEnableSlot(slot)) {
    875                PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR],
    876                           "enable", PK11_GetSlotName(slot));
    877                rv = ENABLE_FAILED_ERR;
    878                goto loser;
    879            } else {
    880                found = PR_TRUE;
    881                PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG],
    882                           PK11_GetSlotName(slot), "enabled");
    883            }
    884        } else {
    885            if (!PK11_UserDisableSlot(slot)) {
    886                PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR],
    887                           "disable", PK11_GetSlotName(slot));
    888                rv = ENABLE_FAILED_ERR;
    889                goto loser;
    890            } else {
    891                found = PR_TRUE;
    892                PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG],
    893                           PK11_GetSlotName(slot), "disabled");
    894            }
    895        }
    896    }
    897 
    898    if (slotName && !found) {
    899        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
    900        rv = NO_SUCH_SLOT_ERR;
    901        goto loser;
    902    }
    903 
    904    /* Delete and re-add module to save changes */
    905    if (SECMOD_UpdateModule(module) != SECSuccess) {
    906        PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], moduleName);
    907        rv = UPDATE_MOD_FAILED_ERR;
    908        goto loser;
    909    }
    910 
    911    rv = SUCCESS;
    912 loser:
    913    if (module) {
    914        SECMOD_DestroyModule(module);
    915    }
    916    return rv;
    917 }
    918 
    919 /*************************************************************************
    920 *
    921 * S e t D e f a u l t M o d u l e
    922 *
    923 */
    924 Error
    925 SetDefaultModule(char *moduleName, char *slotName, char *mechanisms)
    926 {
    927    SECMODModule *module = NULL;
    928    PK11SlotInfo *slot;
    929    int s, i;
    930    unsigned long mechFlags = getFlagsFromString(mechanisms, mechanismStrings,
    931                                                 numMechanismStrings);
    932    PRBool found = PR_FALSE;
    933    Error errcode = UNSPECIFIED_ERR;
    934 
    935    mechFlags = SECMOD_PubMechFlagstoInternal(mechFlags);
    936 
    937    module = SECMOD_FindModule(moduleName);
    938    if (!module) {
    939        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
    940        errcode = NO_SUCH_MODULE_ERR;
    941        goto loser;
    942    }
    943 
    944    /* Go through each slot */
    945    for (s = 0; s < module->slotCount; s++) {
    946        slot = module->slots[s];
    947 
    948        if ((slotName != NULL) &&
    949            !((strcmp(PK11_GetSlotName(slot), slotName) == 0) ||
    950              (strcmp(PK11_GetTokenName(slot), slotName) == 0))) {
    951            /* we are only interested in changing the one slot */
    952            continue;
    953        }
    954 
    955        found = PR_TRUE;
    956 
    957        /* Go through each mechanism */
    958        for (i = 0; i < pk11_DefaultArraySize; i++) {
    959            if (pk11_DefaultArray[i].flag & mechFlags) {
    960                /* Enable this default mechanism */
    961                PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]),
    962                                         PR_TRUE);
    963            }
    964        }
    965    }
    966    if (slotName && !found) {
    967        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
    968        errcode = NO_SUCH_SLOT_ERR;
    969        goto loser;
    970    }
    971 
    972    /* Delete and re-add module to save changes */
    973    if (SECMOD_UpdateModule(module) != SECSuccess) {
    974        PR_fprintf(PR_STDERR, errStrings[DEFAULT_FAILED_ERR],
    975                   moduleName);
    976        errcode = DEFAULT_FAILED_ERR;
    977        goto loser;
    978    }
    979 
    980    PR_fprintf(PR_STDOUT, msgStrings[DEFAULT_SUCCESS_MSG]);
    981 
    982    errcode = SUCCESS;
    983 loser:
    984    if (module) {
    985        SECMOD_DestroyModule(module);
    986    }
    987    return errcode;
    988 }
    989 
    990 /************************************************************************
    991 *
    992 * U n s e t D e f a u l t M o d u l e
    993 */
    994 Error
    995 UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms)
    996 {
    997    SECMODModule *module = NULL;
    998    PK11SlotInfo *slot;
    999    int s, i;
   1000    unsigned long mechFlags = getFlagsFromString(mechanisms,
   1001                                                 mechanismStrings, numMechanismStrings);
   1002    PRBool found = PR_FALSE;
   1003    Error rv;
   1004 
   1005    mechFlags = SECMOD_PubMechFlagstoInternal(mechFlags);
   1006 
   1007    module = SECMOD_FindModule(moduleName);
   1008    if (!module) {
   1009        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
   1010        rv = NO_SUCH_MODULE_ERR;
   1011        goto loser;
   1012    }
   1013 
   1014    for (s = 0; s < module->slotCount; s++) {
   1015        slot = module->slots[s];
   1016        if ((slotName != NULL) &&
   1017            !((strcmp(PK11_GetSlotName(slot), slotName) == 0) ||
   1018              (strcmp(PK11_GetTokenName(slot), slotName) == 0))) {
   1019            /* we are only interested in changing the one slot */
   1020            continue;
   1021        }
   1022        for (i = 0; i < pk11_DefaultArraySize; i++) {
   1023            if (pk11_DefaultArray[i].flag & mechFlags) {
   1024                PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]),
   1025                                         PR_FALSE);
   1026            }
   1027        }
   1028    }
   1029    if (slotName && !found) {
   1030        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
   1031        rv = NO_SUCH_SLOT_ERR;
   1032        goto loser;
   1033    }
   1034 
   1035    /* Delete and re-add module to save changes */
   1036    if (SECMOD_UpdateModule(module) != SECSuccess) {
   1037        PR_fprintf(PR_STDERR, errStrings[UNDEFAULT_FAILED_ERR],
   1038                   moduleName);
   1039        rv = UNDEFAULT_FAILED_ERR;
   1040        goto loser;
   1041    }
   1042 
   1043    PR_fprintf(PR_STDOUT, msgStrings[UNDEFAULT_SUCCESS_MSG]);
   1044    rv = SUCCESS;
   1045 loser:
   1046    if (module) {
   1047        SECMOD_DestroyModule(module);
   1048    }
   1049    return rv;
   1050 }