Back to index

lightning-sunbird  0.9+nobinonly
pk11.c
Go to the documentation of this file.
00001 /* ***** BEGIN LICENSE BLOCK *****
00002  * Version: MPL 1.1/GPL 2.0/LGPL 2.1
00003  *
00004  * The contents of this file are subject to the Mozilla Public License Version
00005  * 1.1 (the "License"); you may not use this file except in compliance with
00006  * the License. You may obtain a copy of the License at
00007  * http://www.mozilla.org/MPL/
00008  *
00009  * Software distributed under the License is distributed on an "AS IS" basis,
00010  * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License
00011  * for the specific language governing rights and limitations under the
00012  * License.
00013  *
00014  * The Original Code is the Netscape security libraries.
00015  *
00016  * The Initial Developer of the Original Code is
00017  * Netscape Communications Corporation.
00018  * Portions created by the Initial Developer are Copyright (C) 1994-2000
00019  * the Initial Developer. All Rights Reserved.
00020  *
00021  * Contributor(s):
00022  *
00023  * Alternatively, the contents of this file may be used under the terms of
00024  * either the GNU General Public License Version 2 or later (the "GPL"), or
00025  * the GNU Lesser General Public License Version 2.1 or later (the "LGPL"),
00026  * in which case the provisions of the GPL or the LGPL are applicable instead
00027  * of those above. If you wish to allow use of your version of this file only
00028  * under the terms of either the GPL or the LGPL, and not to allow others to
00029  * use your version of this file under the terms of the MPL, indicate your
00030  * decision by deleting the provisions above and replace them with the notice
00031  * and other provisions required by the GPL or the LGPL. If you do not delete
00032  * the provisions above, a recipient may use your version of this file under
00033  * the terms of any one of the MPL, the GPL or the LGPL.
00034  *
00035  * ***** END LICENSE BLOCK ***** */
00036 
00037 /* To edit this file, set TABSTOPS to 4 spaces. 
00038  * This is not the normal NSS convention. 
00039  */
00040 
00041 #include "modutil.h"
00042 /* #include "secmodti.h"  */
00043 #include "pk11func.h"
00044 
00045 static PK11DefaultArrayEntry *pk11_DefaultArray = NULL;
00046 static int pk11_DefaultArraySize = 0;
00047 
00048 /*************************************************************************
00049  *
00050  * F i p s M o d e
00051  * If arg=="true", enable FIPS mode on the internal module.  If arg=="false",
00052  * disable FIPS mode on the internal module.
00053  */
00054 Error
00055 FipsMode(char *arg)
00056 {
00057     char *internal_name;
00058 
00059     if(!PORT_Strcasecmp(arg, "true")) {
00060        if(!PK11_IsFIPS()) {
00061            internal_name = PR_smprintf("%s",
00062               SECMOD_GetInternalModule()->commonName);
00063            if(SECMOD_DeleteInternalModule(internal_name) != SECSuccess) {
00064               PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError()));
00065               PR_smprintf_free(internal_name);
00066               PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
00067               return FIPS_SWITCH_FAILED_ERR;
00068            }
00069            PR_smprintf_free(internal_name);
00070            if (!PK11_IsFIPS()) {
00071               PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
00072               return FIPS_SWITCH_FAILED_ERR;
00073            }
00074            PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
00075        } else {
00076            PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_ON_ERR]);
00077            return FIPS_ALREADY_ON_ERR;
00078        }
00079     } else if(!PORT_Strcasecmp(arg, "false")) {
00080        if(PK11_IsFIPS()) {
00081            internal_name = PR_smprintf("%s",
00082               SECMOD_GetInternalModule()->commonName);
00083            if(SECMOD_DeleteInternalModule(internal_name) != SECSuccess) {
00084               PR_fprintf(PR_STDERR, "%s\n", SECU_Strerror(PORT_GetError()));
00085               PR_smprintf_free(internal_name);
00086               PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
00087               return FIPS_SWITCH_FAILED_ERR;
00088            }
00089            PR_smprintf_free(internal_name);
00090            if (PK11_IsFIPS()) {
00091               PR_fprintf(PR_STDERR, errStrings[FIPS_SWITCH_FAILED_ERR]);
00092               return FIPS_SWITCH_FAILED_ERR;
00093            }
00094            PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
00095        } else {
00096            PR_fprintf(PR_STDERR, errStrings[FIPS_ALREADY_OFF_ERR]);
00097            return FIPS_ALREADY_OFF_ERR;
00098        }
00099     } else {
00100        PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
00101        return INVALID_FIPS_ARG;
00102     }
00103 
00104     return SUCCESS;
00105 }
00106 
00107 /*************************************************************************
00108  *
00109  * C h k F i p s M o d e
00110  * If arg=="true", verify FIPS mode is enabled on the internal module.  
00111  * If arg=="false", verify FIPS mode is disabled on the internal module.
00112  */
00113 Error
00114 ChkFipsMode(char *arg)
00115 {
00116     if(!PORT_Strcasecmp(arg, "true")) {
00117        if (PK11_IsFIPS()) {
00118            PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
00119        } else {
00120            PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
00121            return FIPS_SWITCH_FAILED_ERR;
00122        }
00123 
00124     } else if(!PORT_Strcasecmp(arg, "false")) {
00125        if(!PK11_IsFIPS()) {
00126            PR_fprintf(PR_STDOUT, msgStrings[FIPS_DISABLED_MSG]);
00127        } else {
00128            PR_fprintf(PR_STDOUT, msgStrings[FIPS_ENABLED_MSG]);
00129            return FIPS_SWITCH_FAILED_ERR;
00130        }
00131     } else {
00132        PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
00133        return INVALID_FIPS_ARG;
00134     }
00135 
00136     return SUCCESS;
00137 }
00138 
00139 /************************************************************************
00140  * Cipher and Mechanism name-bitmask translation tables
00141  */
00142 
00143 typedef struct {
00144     const char *name;
00145     const unsigned long mask;
00146 } MaskString;
00147 
00148 static const MaskString mechanismStrings[] = {
00149     {"RSA", PUBLIC_MECH_RSA_FLAG},
00150     {"DSA", PUBLIC_MECH_DSA_FLAG},
00151     {"RC2", PUBLIC_MECH_RC2_FLAG},
00152     {"RC4", PUBLIC_MECH_RC4_FLAG},
00153     {"RC5", PUBLIC_MECH_RC5_FLAG},
00154     {"DES", PUBLIC_MECH_DES_FLAG},
00155     {"DH", PUBLIC_MECH_DH_FLAG},
00156     {"FORTEZZA", PUBLIC_MECH_FORTEZZA_FLAG},
00157     {"SHA1", PUBLIC_MECH_SHA1_FLAG},
00158     {"MD5", PUBLIC_MECH_MD5_FLAG},
00159     {"MD2", PUBLIC_MECH_MD2_FLAG},
00160     {"SSL", PUBLIC_MECH_SSL_FLAG},
00161     {"TLS", PUBLIC_MECH_TLS_FLAG},
00162     {"AES", PUBLIC_MECH_AES_FLAG},
00163     {"SHA256", PUBLIC_MECH_SHA256_FLAG},
00164     {"SHA512", PUBLIC_MECH_SHA512_FLAG},
00165     {"RANDOM", PUBLIC_MECH_RANDOM_FLAG},
00166     {"FRIENDLY", PUBLIC_MECH_FRIENDLY_FLAG}
00167 };
00168 static const int numMechanismStrings =
00169     sizeof(mechanismStrings) / sizeof(mechanismStrings[0]);
00170 
00171 static const MaskString cipherStrings[] = {
00172     {"FORTEZZA", PUBLIC_CIPHER_FORTEZZA_FLAG}
00173 };
00174 static const int numCipherStrings =
00175     sizeof(cipherStrings) / sizeof(cipherStrings[0]);
00176 
00177 /* Maximum length of a colon-separated list of all the strings in an 
00178  * array. */
00179 #define MAX_STRING_LIST_LEN 240    /* or less */
00180 
00181 /************************************************************************
00182  * 
00183  * g e t F l a g s F r o m S t r i n g
00184  *
00185  * Parses a mechanism list passed on the command line and converts it
00186  * to an unsigned long bitmask.
00187  * string is a colon-separated string of constants
00188  * array is an array of MaskStrings.
00189  * elements is the number of elements in array.
00190  */
00191 static unsigned long
00192 getFlagsFromString(char *string, const MaskString array[], int elements)
00193 {
00194     unsigned long ret = 0;
00195     short i = 0;
00196     char *cp;
00197     char *buf;
00198     char *end;
00199 
00200     if(!string || !string[0]) {
00201        return ret;
00202     }
00203 
00204     /* Make a temporary copy of the string */
00205     buf = PR_Malloc(strlen(string)+1);
00206     if(!buf) {
00207        out_of_memory();
00208     }
00209     strcpy(buf, string);
00210 
00211     /* Look at each element of the list passed in */
00212     for(cp=buf; cp && *cp; cp = (end ? end+1 : NULL) ) {
00213        /* Look at the string up to the next colon */
00214        end = strchr(cp, ':');
00215        if(end) {
00216            *end = '\0';
00217        }
00218 
00219        /* Find which element this is */
00220        for(i=0; i < elements; i++) {
00221            if( !PORT_Strcasecmp(cp, array[i].name) ) {
00222               break;
00223            }
00224        }
00225        if(i == elements) {
00226            /* Skip a bogus string, but print a warning message */
00227            PR_fprintf(PR_STDERR, errStrings[INVALID_CONSTANT_ERR], cp);
00228            continue;
00229        }
00230        ret |= array[i].mask;
00231     }
00232 
00233     PR_Free(buf);
00234     return ret;
00235 }
00236 
00237 /**********************************************************************
00238  *
00239  * g e t S t r i n g F r o m F l a g s
00240  * 
00241  * The return string's memory is owned by this function.  Copy it
00242  * if you need it permanently or you want to change it.
00243  */
00244 static char *
00245 getStringFromFlags(unsigned long flags, const MaskString array[], int elements)
00246 {
00247     static char buf[MAX_STRING_LIST_LEN];
00248     int i;
00249     int count=0;
00250 
00251     buf[0] = '\0';
00252     for(i=0; i<elements; i++) {
00253        if( flags & array[i].mask ) {
00254            ++count;
00255            if(count!=1) {
00256               strcat(buf, ":");
00257            }
00258            strcat(buf, array[i].name);
00259        }
00260     }
00261     return buf;
00262 }
00263 
00264 /**********************************************************************
00265  *
00266  * A d d M o d u l e
00267  *
00268  * Add the named module, with the given library file, ciphers, and
00269  * default mechanism flags
00270  */
00271 Error
00272 AddModule(char *moduleName, char *libFile, char *cipherString,
00273     char *mechanismString, char* modparms)
00274 {
00275     unsigned long ciphers;
00276     unsigned long mechanisms;
00277     SECStatus status;
00278 
00279     mechanisms =
00280        getFlagsFromString(mechanismString, mechanismStrings,
00281                         numMechanismStrings);
00282     ciphers =
00283        getFlagsFromString(cipherString, cipherStrings, numCipherStrings);
00284 
00285     status =
00286        SECMOD_AddNewModuleEx(moduleName, libFile,
00287                 SECMOD_PubMechFlagstoInternal(mechanisms),
00288                 SECMOD_PubCipherFlagstoInternal(ciphers),
00289                 modparms, NULL );
00290 
00291     if(status != SECSuccess) {
00292        char* errtxt=NULL;
00293        PRInt32 copied = 0;
00294        if (PR_GetErrorTextLength()) {
00295            errtxt = PR_Malloc(PR_GetErrorTextLength());
00296            copied = PR_GetErrorText(errtxt);
00297        }
00298        if (copied && errtxt) {
00299            PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_STATUS_ERR], 
00300                      moduleName, errtxt);
00301            PR_Free(errtxt);
00302        } else {
00303            PR_fprintf(PR_STDERR, errStrings[ADD_MODULE_FAILED_ERR], 
00304                      moduleName);
00305        }
00306        return ADD_MODULE_FAILED_ERR;
00307     } else {
00308        PR_fprintf(PR_STDOUT, msgStrings[ADD_MODULE_SUCCESS_MSG], moduleName);
00309        return SUCCESS;
00310     }
00311 }
00312 
00313 /***********************************************************************
00314  *
00315  * D e l e t e M o d u l e
00316  *
00317  * Deletes the named module from the database.
00318  */
00319 Error
00320 DeleteModule(char *moduleName)
00321 {
00322     SECStatus status;
00323     int type;
00324     
00325     status = SECMOD_DeleteModule(moduleName, &type);
00326 
00327     if(status != SECSuccess) {
00328        if(type == SECMOD_FIPS || type == SECMOD_INTERNAL) {
00329            PR_fprintf(PR_STDERR, errStrings[DELETE_INTERNAL_ERR]);
00330            return DELETE_INTERNAL_ERR;
00331        } else {
00332            PR_fprintf(PR_STDERR, errStrings[DELETE_FAILED_ERR], moduleName);
00333            return DELETE_FAILED_ERR;
00334        }
00335     }
00336 
00337     PR_fprintf(PR_STDOUT, msgStrings[DELETE_SUCCESS_MSG], moduleName);
00338     return SUCCESS;
00339 }
00340 
00341 /************************************************************************
00342  *
00343  * R a w L i s t M o d u l e s
00344  *
00345  * Lists all the modules in the database, along with their slots and tokens.
00346  */
00347 Error
00348 RawListModule(char *modulespec)
00349 {
00350     SECMODModule *module;
00351     char **moduleSpecList;
00352 
00353     module = SECMOD_LoadModule(modulespec,NULL,PR_FALSE);
00354     if (module == NULL) {
00355        /* handle error */
00356        return NO_SUCH_MODULE_ERR;
00357     }
00358 
00359     moduleSpecList = SECMOD_GetModuleSpecList(module);
00360     if (!moduleSpecList || !moduleSpecList[0]) {
00361        SECU_PrintError("modutil",
00362                          "no specs in secmod DB");
00363        return NO_SUCH_MODULE_ERR;
00364     }
00365 
00366     for ( ;*moduleSpecList; moduleSpecList++) {
00367        printf("%s\n\n",*moduleSpecList);
00368     }
00369 
00370     return SUCCESS;
00371 }
00372 
00373 Error
00374 RawAddModule(char *dbmodulespec, char *modulespec)
00375 {
00376     SECMODModule *module;
00377     SECMODModule *dbmodule;
00378 
00379 
00380     dbmodule = SECMOD_LoadModule(dbmodulespec,NULL,PR_TRUE);
00381     if (dbmodule == NULL) {
00382        /* handle error */
00383        return NO_SUCH_MODULE_ERR;
00384     }
00385 
00386     module = SECMOD_LoadModule(modulespec,dbmodule,PR_FALSE);
00387     if (module == NULL) {
00388        /* handle error */
00389        return NO_SUCH_MODULE_ERR;
00390     }
00391 
00392     if( SECMOD_UpdateModule(module) != SECSuccess ) {
00393        PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], modulespec);
00394        return UPDATE_MOD_FAILED_ERR;
00395     }
00396     return SUCCESS;
00397 }
00398 
00399 static void
00400 printModule(SECMODModule *module, int *count) 
00401 {
00402     int slotCount = module->loaded ? module->slotCount : 0;
00403     int i;
00404 
00405     if ((*count)++) {
00406         PR_fprintf(PR_STDOUT,"\n");
00407     }
00408         PR_fprintf(PR_STDOUT, "%3d. %s\n", *count, module->commonName);
00409 
00410     if (module->dllName) {
00411         PR_fprintf(PR_STDOUT, "\tlibrary name: %s\n", module->dllName);
00412     }
00413 
00414     if (slotCount == 0) {
00415         PR_fprintf(PR_STDOUT,
00416        "\t slots: There are no slots attached to this module\n");
00417     } else {
00418         PR_fprintf(PR_STDOUT, "\t slots: %d slot%s attached\n",
00419               slotCount, (slotCount==1 ? "" : "s") );
00420     }
00421 
00422     if (module->loaded == 0) {
00423         PR_fprintf(PR_STDOUT, "\tstatus: Not loaded\n");
00424     } else {
00425         PR_fprintf(PR_STDOUT, "\tstatus: loaded\n");
00426     }
00427 
00428     /* Print slot and token names */
00429     for (i = 0; i < slotCount; i++) {
00430         PK11SlotInfo *slot = module->slots[i];
00431 
00432         PR_fprintf(PR_STDOUT, "\n");
00433         PR_fprintf(PR_STDOUT, "\t slot: %s\n", PK11_GetSlotName(slot));
00434         PR_fprintf(PR_STDOUT, "\ttoken: %s\n", PK11_GetTokenName(slot));
00435     }
00436     return;
00437 }
00438 
00439 /************************************************************************
00440  *
00441  * L i s t M o d u l e s
00442  *
00443  * Lists all the modules in the database, along with their slots and tokens.
00444  */
00445 Error
00446 ListModules()
00447 {
00448     SECMODListLock *lock;
00449     SECMODModuleList *list;
00450     SECMODModuleList *deadlist;
00451     SECMODModuleList *mlp;
00452     Error ret=UNSPECIFIED_ERR;
00453     int count = 0;
00454 
00455     lock = SECMOD_GetDefaultModuleListLock();
00456     if(!lock) {
00457        PR_fprintf(PR_STDERR, errStrings[NO_LIST_LOCK_ERR]);
00458        return NO_LIST_LOCK_ERR;
00459     }
00460 
00461     SECMOD_GetReadLock(lock);
00462 
00463     list = SECMOD_GetDefaultModuleList();
00464     deadlist = SECMOD_GetDeadModuleList();
00465     if (!list && !deadlist) {
00466        PR_fprintf(PR_STDERR, errStrings[NO_MODULE_LIST_ERR]);
00467        ret = NO_MODULE_LIST_ERR;
00468        goto loser;
00469     }
00470 
00471     PR_fprintf(PR_STDOUT,
00472        "\nListing of PKCS #11 Modules\n"
00473        "-----------------------------------------------------------\n");
00474     
00475     for(mlp=list; mlp != NULL; mlp = mlp->next) {
00476        printModule(mlp->module, &count);
00477     }
00478     for (mlp=deadlist; mlp != NULL; mlp = mlp->next) {
00479        printModule(mlp->module, &count);
00480     }
00481 
00482 
00483     PR_fprintf(PR_STDOUT,
00484        "-----------------------------------------------------------\n");
00485 
00486     ret = SUCCESS;
00487 
00488 loser:
00489     SECMOD_ReleaseReadLock(lock);
00490     return ret;
00491 }
00492 
00493 /* Strings describing PK11DisableReasons */
00494 static char *disableReasonStr[] = {
00495     "no reason",
00496     "user disabled",
00497     "could not initialize token",
00498     "could not verify token",
00499     "token not present"
00500 };
00501 static int numDisableReasonStr =
00502     sizeof(disableReasonStr) / sizeof(disableReasonStr[0]);
00503 
00504 /***********************************************************************
00505  *
00506  * L i s t M o d u l e
00507  *
00508  * Lists detailed information about the named module.
00509  */
00510 Error
00511 ListModule(char *moduleName)
00512 {
00513     SECMODModule *module;
00514     PK11SlotInfo *slot;
00515     int slotnum;
00516     CK_INFO modinfo;
00517     CK_SLOT_INFO slotinfo;
00518     CK_TOKEN_INFO tokeninfo;
00519     char *ciphers, *mechanisms;
00520     PK11DisableReasons reason;
00521     Error  rv = SUCCESS;
00522 
00523     if(!moduleName) {
00524        return SUCCESS;
00525     }
00526 
00527     module = SECMOD_FindModule(moduleName);
00528     if(!module) {
00529        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
00530        return NO_SUCH_MODULE_ERR;
00531     }
00532 
00533     if ((module->loaded) && 
00534                      (PK11_GetModInfo(module, &modinfo) != SECSuccess)) {
00535        PR_fprintf(PR_STDERR, errStrings[MOD_INFO_ERR], moduleName);
00536        return MOD_INFO_ERR;
00537     }
00538 
00539     /* Module info */
00540     PR_fprintf(PR_STDOUT, 
00541        "\n-----------------------------------------------------------\n");
00542     PR_fprintf(PR_STDOUT, "Name: %s\n", module->commonName);
00543     if(module->internal || !module->dllName) {
00544        PR_fprintf(PR_STDOUT, "Library file: **Internal ONLY module**\n");
00545     } else {
00546        PR_fprintf(PR_STDOUT, "Library file: %s\n", module->dllName);
00547     }
00548 
00549     if (module->loaded) {
00550        PR_fprintf(PR_STDOUT, "Manufacturer: %.32s\n", modinfo.manufacturerID);
00551        PR_fprintf(PR_STDOUT, "Description: %.32s\n", modinfo.libraryDescription);
00552        PR_fprintf(PR_STDOUT, "PKCS #11 Version %d.%d\n",
00553        modinfo.cryptokiVersion.major, modinfo.cryptokiVersion.minor);
00554        PR_fprintf(PR_STDOUT, "Library Version: %d.%d\n",
00555        modinfo.libraryVersion.major, modinfo.libraryVersion.minor);
00556     } else {
00557        PR_fprintf(PR_STDOUT, "* Module not loaded\n");
00558     }
00559     /* Get cipher and mechanism flags */
00560     ciphers = getStringFromFlags(module->ssl[0], cipherStrings,
00561       numCipherStrings);
00562     if(ciphers[0] == '\0') {
00563        ciphers = "None";
00564     }
00565     PR_fprintf(PR_STDOUT, "Cipher Enable Flags: %s\n", ciphers);
00566     mechanisms = NULL;
00567     if (module->slotCount > 0) {
00568        mechanisms = getStringFromFlags(
00569            PK11_GetDefaultFlags(module->slots[0]),
00570            mechanismStrings, numMechanismStrings);
00571     }
00572     if ((mechanisms==NULL) || (mechanisms[0] =='\0')) {
00573        mechanisms = "None";
00574     }
00575     PR_fprintf(PR_STDOUT, "Default Mechanism Flags: %s\n", mechanisms);
00576 
00577 #define PAD "  "
00578 
00579     /* Loop over each slot */
00580     for (slotnum=0; slotnum < module->slotCount; slotnum++) {
00581        slot = module->slots[slotnum];
00582        if (PK11_GetSlotInfo(slot, &slotinfo) != SECSuccess) {
00583            PR_fprintf(PR_STDERR, errStrings[SLOT_INFO_ERR],
00584               PK11_GetSlotName(slot));
00585            rv = SLOT_INFO_ERR;
00586            continue;
00587        }
00588 
00589        /* Slot Info */
00590        PR_fprintf(PR_STDOUT, "\n"PAD"Slot: %s\n", PK11_GetSlotName(slot));
00591        mechanisms = getStringFromFlags(PK11_GetDefaultFlags(slot),
00592            mechanismStrings, numMechanismStrings);
00593        if(mechanisms[0] =='\0') {
00594             mechanisms = "None";
00595        }
00596        PR_fprintf(PR_STDOUT, PAD"Slot Mechanism Flags: %s\n", mechanisms);
00597        PR_fprintf(PR_STDOUT, PAD"Manufacturer: %.32s\n",
00598            slotinfo.manufacturerID);
00599        if (PK11_IsHW(slot)) {
00600            PR_fprintf(PR_STDOUT, PAD"Type: Hardware\n");
00601        } else {
00602            PR_fprintf(PR_STDOUT, PAD"Type: Software\n");
00603        }
00604        PR_fprintf(PR_STDOUT, PAD"Version Number: %d.%d\n",
00605            slotinfo.hardwareVersion.major, slotinfo.hardwareVersion.minor);
00606        PR_fprintf(PR_STDOUT, PAD"Firmware Version: %d.%d\n",
00607            slotinfo.firmwareVersion.major, slotinfo.firmwareVersion.minor);
00608        if (PK11_IsDisabled(slot)) {
00609            reason  = PK11_GetDisabledReason(slot);
00610            if(reason < numDisableReasonStr) {
00611               PR_fprintf(PR_STDOUT, PAD"Status: DISABLED (%s)\n",
00612                 disableReasonStr[reason]);
00613            } else {
00614               PR_fprintf(PR_STDOUT, PAD"Status: DISABLED\n");
00615            }
00616        } else {
00617            PR_fprintf(PR_STDOUT, PAD"Status: Enabled\n");
00618        }
00619 
00620        if(PK11_GetTokenInfo(slot, &tokeninfo) != SECSuccess) {
00621            PR_fprintf(PR_STDERR, errStrings[TOKEN_INFO_ERR],
00622              PK11_GetTokenName(slot));
00623            rv = TOKEN_INFO_ERR;
00624            continue;
00625        }
00626 
00627        /* Token Info */
00628        PR_fprintf(PR_STDOUT, PAD"Token Name: %.32s\n",
00629            tokeninfo.label);
00630        PR_fprintf(PR_STDOUT, PAD"Token Manufacturer: %.32s\n",
00631            tokeninfo.manufacturerID);
00632        PR_fprintf(PR_STDOUT, PAD"Token Model: %.16s\n", tokeninfo.model);
00633        PR_fprintf(PR_STDOUT, PAD"Token Serial Number: %.16s\n",
00634            tokeninfo.serialNumber);
00635        PR_fprintf(PR_STDOUT, PAD"Token Version: %d.%d\n",
00636            tokeninfo.hardwareVersion.major, tokeninfo.hardwareVersion.minor);
00637        PR_fprintf(PR_STDOUT, PAD"Token Firmware Version: %d.%d\n",
00638            tokeninfo.firmwareVersion.major, tokeninfo.firmwareVersion.minor);
00639        if(tokeninfo.flags & CKF_WRITE_PROTECTED) {
00640            PR_fprintf(PR_STDOUT, PAD"Access: Write Protected\n");
00641        } else {
00642            PR_fprintf(PR_STDOUT, PAD"Access: NOT Write Protected\n");
00643        }
00644        if(tokeninfo.flags & CKF_LOGIN_REQUIRED) {
00645            PR_fprintf(PR_STDOUT, PAD"Login Type: Login required\n");
00646        } else {
00647            PR_fprintf(PR_STDOUT, PAD
00648              "Login Type: Public (no login required)\n");
00649        }
00650        if(tokeninfo.flags & CKF_USER_PIN_INITIALIZED) {
00651            PR_fprintf(PR_STDOUT, PAD"User Pin: Initialized\n");
00652        } else {
00653            PR_fprintf(PR_STDOUT, PAD"User Pin: NOT Initialized\n");
00654        }
00655     }
00656     PR_fprintf(PR_STDOUT, 
00657        "\n-----------------------------------------------------------\n");
00658     return rv;
00659 }
00660 
00661 /************************************************************************
00662  *
00663  * C h a n g e P W
00664  */
00665 Error
00666 ChangePW(char *tokenName, char *pwFile, char *newpwFile)
00667 {
00668     char *oldpw=NULL, *newpw=NULL, *newpw2=NULL;
00669     PK11SlotInfo *slot;
00670     Error ret=UNSPECIFIED_ERR;
00671     PRBool matching;
00672 
00673     slot = PK11_FindSlotByName(tokenName);
00674     if(!slot) {
00675        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_TOKEN_ERR], tokenName);
00676        return NO_SUCH_TOKEN_ERR;
00677     }
00678 
00679     PK11_SetPasswordFunc(SECU_GetModulePassword);
00680 
00681     /* Get old password */
00682     if(! PK11_NeedUserInit(slot)) {
00683        if(pwFile) {
00684            oldpw = SECU_FilePasswd(NULL, PR_FALSE, pwFile);
00685            if(PK11_CheckUserPassword(slot, oldpw) != SECSuccess) {
00686               PR_fprintf(PR_STDERR, errStrings[BAD_PW_ERR]);
00687               ret=BAD_PW_ERR;
00688               goto loser;
00689            }
00690        } else {
00691            for(matching=PR_FALSE; !matching; ) {
00692               oldpw = SECU_GetPasswordString(NULL, "Enter old password: ");
00693               if(PK11_CheckUserPassword(slot, oldpw) == SECSuccess) {
00694                   matching = PR_TRUE;
00695               } else {
00696                   PR_fprintf(PR_STDOUT, msgStrings[BAD_PW_MSG]);
00697               }
00698            }
00699        }
00700     }
00701 
00702     /* Get new password */
00703     if(newpwFile) {
00704        newpw = SECU_FilePasswd(NULL, PR_FALSE, newpwFile);
00705     } else {
00706        for(matching=PR_FALSE; !matching; ) {
00707            newpw = SECU_GetPasswordString(NULL, "Enter new password: ");
00708            newpw2 = SECU_GetPasswordString(NULL, "Re-enter new password: ");
00709            if(strcmp(newpw, newpw2)) {
00710               PR_fprintf(PR_STDOUT, msgStrings[PW_MATCH_MSG]);
00711            } else {
00712               matching = PR_TRUE;
00713            }
00714        }
00715     }
00716 
00717     /* Change the password */
00718     if(PK11_NeedUserInit(slot)) {
00719        if(PK11_InitPin(slot, NULL /*ssopw*/, newpw) != SECSuccess) {
00720            PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
00721            ret = CHANGEPW_FAILED_ERR;
00722            goto loser;
00723        }
00724     } else {
00725        if(PK11_ChangePW(slot, oldpw, newpw) != SECSuccess) {
00726            PR_fprintf(PR_STDERR, errStrings[CHANGEPW_FAILED_ERR], tokenName);
00727            ret = CHANGEPW_FAILED_ERR;
00728            goto loser;
00729        }
00730     }
00731 
00732     PR_fprintf(PR_STDOUT, msgStrings[CHANGEPW_SUCCESS_MSG], tokenName);
00733     ret = SUCCESS;
00734 
00735 loser:
00736     if(oldpw) {
00737        memset(oldpw, 0, strlen(oldpw));
00738        PORT_Free(oldpw);
00739     }
00740     if(newpw) {
00741        memset(newpw, 0, strlen(newpw));
00742        PORT_Free(newpw);
00743     }
00744     if(newpw2) {
00745        memset(newpw2, 0, strlen(newpw2));
00746        PORT_Free(newpw2);
00747     }
00748     return ret;
00749 }
00750 
00751 /***********************************************************************
00752  *
00753  * E n a b l e M o d u l e
00754  *
00755  * If enable==PR_TRUE, enables the module or slot.
00756  * If enable==PR_FALSE, disables the module or slot.
00757  * moduleName is the name of the module.
00758  * slotName is the name of the slot.  It is optional.
00759  */
00760 Error
00761 EnableModule(char *moduleName, char *slotName, PRBool enable)
00762 {
00763     int i;
00764     SECMODModule *module;
00765     PK11SlotInfo *slot = NULL;
00766     PRBool found = PR_FALSE;
00767 
00768     module = SECMOD_FindModule(moduleName);
00769     if(!module) {
00770        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
00771        return NO_SUCH_MODULE_ERR;
00772     }
00773 
00774     for(i=0; i < module->slotCount; i++) {
00775        slot = module->slots[i];
00776        if(slotName && strcmp(PK11_GetSlotName(slot), slotName)) {
00777               /* Not the right slot */
00778               continue;
00779        }
00780        if(enable) {
00781            if(! PK11_UserEnableSlot(slot)) {
00782               PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR],
00783                   "enable", PK11_GetSlotName(slot));
00784               return ENABLE_FAILED_ERR;
00785            } else {
00786               found = PR_TRUE;
00787               PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG],
00788                   PK11_GetSlotName(slot), "enabled");
00789            }
00790        } else {
00791            if(! PK11_UserDisableSlot(slot)) {
00792               PR_fprintf(PR_STDERR, errStrings[ENABLE_FAILED_ERR],
00793                   "disable", PK11_GetSlotName(slot));
00794               return ENABLE_FAILED_ERR;
00795            } else {
00796               found = PR_TRUE;
00797               PR_fprintf(PR_STDOUT, msgStrings[ENABLE_SUCCESS_MSG],
00798                   PK11_GetSlotName(slot), "disabled");
00799            }
00800        }
00801     }
00802 
00803     if(slotName && !found) {
00804        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
00805        return NO_SUCH_SLOT_ERR;
00806     }
00807 
00808     /* Delete and re-add module to save changes */
00809     if( SECMOD_UpdateModule(module) != SECSuccess ) {
00810        PR_fprintf(PR_STDERR, errStrings[UPDATE_MOD_FAILED_ERR], moduleName);
00811        return UPDATE_MOD_FAILED_ERR;
00812     }
00813 
00814     return SUCCESS;
00815 }
00816 
00817 /*************************************************************************
00818  *
00819  * S e t D e f a u l t M o d u l e
00820  *
00821  */
00822 Error
00823 SetDefaultModule(char *moduleName, char *slotName, char *mechanisms)
00824 {
00825     SECMODModule *module;
00826     PK11SlotInfo *slot;
00827     int s, i;
00828     unsigned long mechFlags = getFlagsFromString(mechanisms, mechanismStrings,
00829        numMechanismStrings);
00830     PRBool found = PR_FALSE;
00831     Error errcode = UNSPECIFIED_ERR;
00832 
00833     if (pk11_DefaultArray == NULL) {
00834        pk11_DefaultArray = PK11_GetDefaultArray(&pk11_DefaultArraySize);
00835        if (pk11_DefaultArray == NULL) {
00836            /* should assert. This shouldn't happen */
00837            goto loser;
00838        }
00839     }
00840 
00841     mechFlags =  SECMOD_PubMechFlagstoInternal(mechFlags);
00842 
00843     module = SECMOD_FindModule(moduleName);
00844     if(!module) {
00845        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
00846        errcode = NO_SUCH_MODULE_ERR;
00847        goto loser;
00848     }
00849 
00850     /* Go through each slot */
00851     for(s=0; s < module->slotCount; s++) {
00852        slot = module->slots[s];
00853 
00854        if ((slotName != NULL) &&
00855            !((strcmp(PK11_GetSlotName(slot),slotName) == 0) ||
00856            (strcmp(PK11_GetTokenName(slot),slotName) == 0)) ) {
00857            /* we are only interested in changing the one slot */
00858            continue;
00859        }
00860 
00861        found = PR_TRUE;
00862 
00863        /* Go through each mechanism */
00864        for(i=0; i < pk11_DefaultArraySize; i++) {
00865            if(pk11_DefaultArray[i].flag & mechFlags) {
00866               /* Enable this default mechanism */
00867               PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]),
00868                   PR_TRUE);
00869            }
00870        }
00871     }
00872     if (slotName && !found) {
00873        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
00874        errcode = NO_SUCH_SLOT_ERR;
00875        goto loser;
00876     }
00877 
00878     /* Delete and re-add module to save changes */
00879     if( SECMOD_UpdateModule(module) != SECSuccess ) {
00880        PR_fprintf(PR_STDERR, errStrings[DEFAULT_FAILED_ERR],
00881          moduleName);
00882        errcode = DEFAULT_FAILED_ERR;
00883        goto loser;
00884     }
00885 
00886     PR_fprintf(PR_STDOUT, msgStrings[DEFAULT_SUCCESS_MSG]);
00887 
00888     errcode = SUCCESS;
00889 loser:
00890     return errcode;
00891 }
00892 
00893 /************************************************************************
00894  *
00895  * U n s e t D e f a u l t M o d u l e
00896  */
00897 Error
00898 UnsetDefaultModule(char *moduleName, char *slotName, char *mechanisms)
00899 {
00900     SECMODModule * module;
00901     PK11SlotInfo *slot;
00902     int s, i;
00903     unsigned long mechFlags = getFlagsFromString(mechanisms,
00904        mechanismStrings, numMechanismStrings);
00905     PRBool found = PR_FALSE;
00906 
00907     if (pk11_DefaultArray == NULL) {
00908        pk11_DefaultArray = PK11_GetDefaultArray(&pk11_DefaultArraySize);
00909        if (pk11_DefaultArray == NULL) {
00910            /* should assert. This shouldn't happen */
00911            return UNSPECIFIED_ERR;
00912        }
00913     }
00914 
00915     mechFlags =  SECMOD_PubMechFlagstoInternal(mechFlags);
00916 
00917     module = SECMOD_FindModule(moduleName);
00918     if(!module) {
00919        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_MODULE_ERR], moduleName);
00920        return NO_SUCH_MODULE_ERR;
00921     }
00922 
00923     for(s=0; s < module->slotCount; s++) {
00924        slot = module->slots[s];
00925        if ((slotName != NULL) &&
00926            !((strcmp(PK11_GetSlotName(slot),slotName) == 0) ||
00927            (strcmp(PK11_GetTokenName(slot),slotName) == 0)) ) {
00928            /* we are only interested in changing the one slot */
00929            continue;
00930        }
00931        for(i=0; i < pk11_DefaultArraySize ; i++) {
00932            if(pk11_DefaultArray[i].flag & mechFlags) {
00933               PK11_UpdateSlotAttribute(slot, &(pk11_DefaultArray[i]),
00934                   PR_FALSE);
00935            }
00936        }
00937     }
00938     if (slotName && !found) {
00939        PR_fprintf(PR_STDERR, errStrings[NO_SUCH_SLOT_ERR], slotName);
00940        return NO_SUCH_SLOT_ERR;
00941     }
00942 
00943     /* Delete and re-add module to save changes */
00944     if( SECMOD_UpdateModule(module) != SECSuccess ) {
00945        PR_fprintf(PR_STDERR, errStrings[UNDEFAULT_FAILED_ERR],
00946          moduleName);
00947        return UNDEFAULT_FAILED_ERR;
00948     }
00949 
00950     PR_fprintf(PR_STDOUT, msgStrings[UNDEFAULT_SUCCESS_MSG]);
00951     return SUCCESS;
00952 }