Back to index

lightning-sunbird  0.9+nobinonly
modutil.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 "install.h"
00043 #include <plstr.h>
00044 #include "certdb.h" /* for CERT_DB_FILE_VERSION */
00045 #include "nss.h"
00046 
00047 static void install_error(char *message);
00048 static char* PR_fgets(char *buf, int size, PRFileDesc *file);
00049 static char *progName;
00050 
00051 
00052 /* This enum must be kept in sync with the commandNames list */
00053 typedef enum {
00054        NO_COMMAND,
00055        ADD_COMMAND,
00056        CHANGEPW_COMMAND,
00057        CREATE_COMMAND,
00058        DEFAULT_COMMAND,
00059        DELETE_COMMAND,
00060        DISABLE_COMMAND,
00061        ENABLE_COMMAND,
00062        FIPS_COMMAND,
00063        JAR_COMMAND,
00064        LIST_COMMAND,
00065        RAW_LIST_COMMAND,
00066        RAW_ADD_COMMAND,
00067        CHKFIPS_COMMAND,
00068        UNDEFAULT_COMMAND
00069 } Command;
00070 
00071 /* This list must be kept in sync with the Command enum */
00072 static char *commandNames[] = {
00073        "(no command)",
00074        "-add",
00075        "-changepw",
00076        "-create",
00077        "-default",
00078        "-delete",
00079        "-disable",
00080        "-enable",
00081        "-fips",
00082        "-jar",
00083        "-list",
00084        "-rawlist",
00085        "-rawadd",
00086        "-chkfips",
00087        "-undefault"
00088 };
00089 
00090 
00091 /* this enum must be kept in sync with the optionStrings list */
00092 typedef enum {
00093        ADD_ARG=0,
00094        RAW_ADD_ARG,
00095        CHANGEPW_ARG,
00096        CIPHERS_ARG,
00097        CREATE_ARG,
00098        DBDIR_ARG,
00099        DBPREFIX_ARG,
00100        DEFAULT_ARG,
00101        DELETE_ARG,
00102        DISABLE_ARG,
00103        ENABLE_ARG,
00104        FIPS_ARG,
00105        FORCE_ARG,
00106        JAR_ARG,
00107        LIBFILE_ARG,
00108        LIST_ARG,
00109        RAW_LIST_ARG,
00110        MECHANISMS_ARG,
00111        NEWPWFILE_ARG,
00112        PWFILE_ARG,
00113        SLOT_ARG,
00114        UNDEFAULT_ARG,
00115        INSTALLDIR_ARG,
00116        TEMPDIR_ARG,
00117        SECMOD_ARG,
00118        NOCERTDB_ARG,
00119        STRING_ARG,
00120        CHKFIPS_ARG,
00121 
00122        NUM_ARGS      /* must be last */
00123 } Arg;
00124 
00125 /* This list must be kept in sync with the Arg enum */
00126 static char *optionStrings[] = {
00127        "-add",
00128        "-rawadd",
00129        "-changepw",
00130        "-ciphers",
00131        "-create",
00132        "-dbdir",
00133        "-dbprefix",
00134        "-default",
00135        "-delete",
00136        "-disable",
00137        "-enable",
00138        "-fips",
00139        "-force",
00140        "-jar",
00141        "-libfile",
00142        "-list",
00143        "-rawlist",
00144        "-mechanisms",
00145        "-newpwfile",
00146        "-pwfile",
00147        "-slot",
00148        "-undefault",
00149        "-installdir",
00150        "-tempdir",
00151        "-secmod",
00152        "-nocertdb",
00153        "-string",
00154        "-chkfips",
00155 };
00156 
00157 /* Increment i if doing so would have i still be less than j.  If you
00158    are able to do this, return 0.  Otherwise return 1. */
00159 #define TRY_INC(i,j)  ( ((i+1)<j) ? (++i, 0) : 1 )
00160 
00161 /********************************************************************
00162  *
00163  * file-wide variables obtained from the command line
00164  */
00165 static Command command = NO_COMMAND;
00166 static char* pwFile = NULL;
00167 static char* newpwFile = NULL;
00168 static char* moduleName = NULL;
00169 static char* moduleSpec = NULL;
00170 static char* slotName = NULL;
00171 static char* secmodName = NULL;
00172 static char* tokenName = NULL;
00173 static char* libFile = NULL;
00174 static char* dbdir = NULL;
00175 static char* dbprefix = "";
00176 static char* secmodString = NULL;
00177 static char* mechanisms = NULL;
00178 static char* ciphers = NULL;
00179 static char* fipsArg = NULL;
00180 static char* jarFile = NULL;
00181 static char* installDir = NULL;
00182 static char* tempDir = NULL;
00183 static short force = 0;
00184 static PRBool nocertdb = PR_FALSE;
00185 
00186 /*******************************************************************
00187  *
00188  * p a r s e _ a r g s
00189  */
00190 static Error
00191 parse_args(int argc, char *argv[])
00192 {
00193        int i;
00194        char *arg;
00195        int optionType;
00196 
00197        /* Loop over all arguments */
00198        for(i=1; i < argc; i++) {
00199               arg = argv[i];
00200 
00201               /* Make sure this is an option and not some floating argument */
00202               if(arg[0] != '-') {
00203                      PR_fprintf(PR_STDERR, errStrings[UNEXPECTED_ARG_ERR], argv[i]);
00204                      return UNEXPECTED_ARG_ERR;
00205               }
00206 
00207               /* Find which option this is */
00208               for(optionType=0; optionType < NUM_ARGS; optionType++) {
00209                      if(! strcmp(arg, optionStrings[optionType])) {
00210                             break;
00211                      }
00212               }
00213               
00214               /* Deal with this specific option */
00215               switch(optionType) {
00216               case NUM_ARGS:
00217               default:
00218                      PR_fprintf(PR_STDERR, errStrings[UNKNOWN_OPTION_ERR], arg);
00219                      return UNKNOWN_OPTION_ERR;
00220                      break;
00221               case ADD_ARG:
00222                      if(command != NO_COMMAND) {
00223                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00224                             return MULTIPLE_COMMAND_ERR;
00225                      }
00226                      command = ADD_COMMAND;
00227                      if(TRY_INC(i, argc)) {
00228                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00229                             return OPTION_NEEDS_ARG_ERR;
00230                      }
00231                      moduleName = argv[i];
00232                      break;
00233               case CHANGEPW_ARG:
00234                      if(command != NO_COMMAND) {
00235                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00236                             return MULTIPLE_COMMAND_ERR;
00237                      }
00238                      command = CHANGEPW_COMMAND;
00239                      if(TRY_INC(i, argc)) {
00240                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00241                             return OPTION_NEEDS_ARG_ERR;
00242                      }
00243                      tokenName = argv[i];
00244                      break;
00245               case CIPHERS_ARG:
00246                      if(ciphers != NULL) {
00247                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00248                             return DUPLICATE_OPTION_ERR;
00249                      }
00250                      if(TRY_INC(i, argc)) {
00251                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00252                             return OPTION_NEEDS_ARG_ERR;
00253                      }
00254                      ciphers = argv[i];
00255                      break;
00256               case CREATE_ARG:
00257                      if(command != NO_COMMAND) {
00258                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00259                             return MULTIPLE_COMMAND_ERR;
00260                      }
00261                      command = CREATE_COMMAND;
00262                      break;
00263               case DBDIR_ARG:
00264                      if(dbdir != NULL) {
00265                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00266                             return DUPLICATE_OPTION_ERR;
00267                      }
00268                      if(TRY_INC(i, argc)) {
00269                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00270                             return OPTION_NEEDS_ARG_ERR;
00271                      }
00272                      dbdir = argv[i];
00273                      break;
00274               case DBPREFIX_ARG:
00275                      if(TRY_INC(i, argc)) {
00276                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00277                             return OPTION_NEEDS_ARG_ERR;
00278                      }
00279                      dbprefix = argv[i];
00280                      break;
00281               case UNDEFAULT_ARG:
00282               case DEFAULT_ARG:
00283                      if(command != NO_COMMAND) {
00284                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00285                             return MULTIPLE_COMMAND_ERR;
00286                      }
00287                      if(optionType == DEFAULT_ARG) {
00288                             command = DEFAULT_COMMAND;
00289                      } else {
00290                             command = UNDEFAULT_COMMAND;
00291                      }
00292                      if(TRY_INC(i, argc)) {
00293                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00294                             return OPTION_NEEDS_ARG_ERR;
00295                      }
00296                      moduleName = argv[i];
00297                      break;
00298               case DELETE_ARG:
00299                      if(command != NO_COMMAND) {
00300                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00301                             return MULTIPLE_COMMAND_ERR;
00302                      }
00303                      command = DELETE_COMMAND;
00304                      if(TRY_INC(i, argc)) {
00305                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00306                             return OPTION_NEEDS_ARG_ERR;
00307                      }
00308                      moduleName = argv[i];
00309                      break;
00310               case DISABLE_ARG:
00311                      if(command != NO_COMMAND) {
00312                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00313                             return MULTIPLE_COMMAND_ERR;
00314                      }
00315                      command = DISABLE_COMMAND;
00316                      if(TRY_INC(i, argc)) {
00317                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00318                             return OPTION_NEEDS_ARG_ERR;
00319                      }
00320                      moduleName = argv[i];
00321                      break;
00322               case ENABLE_ARG:
00323                      if(command != NO_COMMAND) {
00324                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00325                             return MULTIPLE_COMMAND_ERR;
00326                      }
00327                      command = ENABLE_COMMAND;
00328                      if(TRY_INC(i, argc)) {
00329                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00330                             return OPTION_NEEDS_ARG_ERR;
00331                      }
00332                      moduleName = argv[i];
00333                      break;
00334               case FIPS_ARG:
00335                      if(command != NO_COMMAND) {
00336                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00337                             return MULTIPLE_COMMAND_ERR;
00338                      }
00339                      command = FIPS_COMMAND;
00340                      if(TRY_INC(i, argc)) {
00341                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00342                             return OPTION_NEEDS_ARG_ERR;
00343                      }
00344                      fipsArg = argv[i];
00345                      break;
00346               case CHKFIPS_ARG:
00347                      if(command != NO_COMMAND) {
00348                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00349                             return MULTIPLE_COMMAND_ERR;
00350                      }
00351                      command = CHKFIPS_COMMAND;
00352                      if(TRY_INC(i, argc)) {
00353                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00354                             return OPTION_NEEDS_ARG_ERR;
00355                      }
00356                      fipsArg = argv[i];
00357                      break;
00358               case FORCE_ARG:
00359                      force = 1;
00360                      break;
00361               case NOCERTDB_ARG:
00362                      nocertdb = PR_TRUE;
00363                      break;
00364               case INSTALLDIR_ARG:
00365                      if(installDir != NULL) {
00366                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00367                             return DUPLICATE_OPTION_ERR;
00368                      }
00369                      if(TRY_INC(i, argc)) {
00370                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00371                             return OPTION_NEEDS_ARG_ERR;
00372                      }
00373                      installDir = argv[i];
00374                      break;
00375               case TEMPDIR_ARG:
00376                      if(tempDir != NULL) {
00377                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00378                             return DUPLICATE_OPTION_ERR;
00379                      }
00380                      if(TRY_INC(i, argc)) {
00381                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00382                             return OPTION_NEEDS_ARG_ERR;
00383                      }
00384                      tempDir = argv[i];
00385                      break;
00386               case JAR_ARG:
00387                      if(command != NO_COMMAND) {
00388                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00389                             return MULTIPLE_COMMAND_ERR;
00390                      }
00391                      command = JAR_COMMAND;
00392                      if(TRY_INC(i, argc)) {
00393                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00394                             return OPTION_NEEDS_ARG_ERR;
00395                      }
00396                      jarFile = argv[i];
00397                      break;
00398               case LIBFILE_ARG:
00399                      if(libFile != NULL) {
00400                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00401                             return DUPLICATE_OPTION_ERR;
00402                      }
00403                      if(TRY_INC(i, argc)) {
00404                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00405                             return OPTION_NEEDS_ARG_ERR;
00406                      }
00407                      libFile = argv[i];
00408                      break;
00409               case LIST_ARG:
00410                      if(command != NO_COMMAND) {
00411                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00412                             return MULTIPLE_COMMAND_ERR;
00413                      }
00414                      command = LIST_COMMAND;
00415                      /* This option may or may not have an argument */
00416                      if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
00417                             moduleName = argv[++i];
00418                      }
00419                      break;
00420               case RAW_LIST_ARG:
00421                      if(command != NO_COMMAND) {
00422                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00423                             return MULTIPLE_COMMAND_ERR;
00424                      }
00425                      command = RAW_LIST_COMMAND;
00426                      /* This option may or may not have an argument */
00427                      if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
00428                             moduleName = argv[++i];
00429                      }
00430                      break;
00431               case RAW_ADD_ARG:
00432                      if(command != NO_COMMAND) {
00433                             PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
00434                             return MULTIPLE_COMMAND_ERR;
00435                      }
00436                      command = RAW_ADD_COMMAND;
00437                      if(TRY_INC(i, argc)) {
00438                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00439                             return OPTION_NEEDS_ARG_ERR;
00440                      }
00441                      moduleSpec = argv[i];
00442                      break;
00443               case MECHANISMS_ARG:
00444                      if(mechanisms != NULL) {
00445                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00446                             return DUPLICATE_OPTION_ERR;
00447                      }
00448                      if(TRY_INC(i, argc)) {
00449                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00450                             return OPTION_NEEDS_ARG_ERR;
00451                      }
00452                      mechanisms = argv[i];
00453                      break;
00454               case NEWPWFILE_ARG:
00455                      if(newpwFile != NULL) {
00456                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00457                             return DUPLICATE_OPTION_ERR;
00458                      }
00459                      if(TRY_INC(i, argc)) {
00460                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00461                             return OPTION_NEEDS_ARG_ERR;
00462                      }
00463                      newpwFile = argv[i];
00464                      break;
00465               case PWFILE_ARG:
00466                      if(pwFile != NULL) {
00467                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00468                             return DUPLICATE_OPTION_ERR;
00469                      }
00470                      if(TRY_INC(i, argc)) {
00471                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00472                             return OPTION_NEEDS_ARG_ERR;
00473                      }
00474                      pwFile = argv[i];
00475                      break;
00476               case SLOT_ARG:
00477                      if(slotName != NULL) {
00478                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00479                             return DUPLICATE_OPTION_ERR;
00480                      }
00481                      if(TRY_INC(i, argc)) {
00482                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00483                             return OPTION_NEEDS_ARG_ERR;
00484                      }
00485                      slotName = argv[i];
00486                      break;
00487               case SECMOD_ARG:
00488                      if(secmodName != NULL) {
00489                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00490                             return DUPLICATE_OPTION_ERR;
00491                      }
00492                      if(TRY_INC(i, argc)) {
00493                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00494                             return OPTION_NEEDS_ARG_ERR;
00495                      }
00496                      secmodName = argv[i];
00497                      break;
00498               case STRING_ARG:
00499                      if(secmodString != NULL) {
00500                             PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
00501                             return DUPLICATE_OPTION_ERR;
00502                      }
00503                      if(TRY_INC(i, argc)) {
00504                             PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
00505                             return OPTION_NEEDS_ARG_ERR;
00506                      }
00507                      secmodString = argv[i];
00508                      break;
00509               }
00510        }
00511        return SUCCESS;
00512 }
00513 
00514 /************************************************************************
00515  *
00516  * v e r i f y _ p a r a m s
00517  */
00518 static Error
00519 verify_params()
00520 {
00521        switch(command) {
00522        case ADD_COMMAND:
00523               if(libFile == NULL) {
00524                      PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
00525                             commandNames[ADD_COMMAND], optionStrings[LIBFILE_ARG]);
00526                      return MISSING_PARAM_ERR;
00527               }
00528               break;
00529        case CHANGEPW_COMMAND:
00530               break;
00531        case CREATE_COMMAND:
00532               break;
00533        case DELETE_COMMAND:
00534               break;
00535        case DISABLE_COMMAND:
00536               break;
00537        case ENABLE_COMMAND:
00538               break;
00539        case FIPS_COMMAND:
00540        case CHKFIPS_COMMAND:
00541               if(PL_strcasecmp(fipsArg, "true") &&
00542                      PL_strcasecmp(fipsArg, "false")) {
00543                      PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
00544                      return INVALID_FIPS_ARG;
00545               }
00546               break;
00547        case JAR_COMMAND:
00548               if(installDir == NULL) {
00549                      PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
00550                             commandNames[JAR_COMMAND], optionStrings[INSTALLDIR_ARG]);
00551                      return MISSING_PARAM_ERR;
00552               }
00553               break;
00554        case LIST_COMMAND:
00555        case RAW_LIST_COMMAND:
00556               break;
00557        case RAW_ADD_COMMAND:
00558               break;
00559        case UNDEFAULT_COMMAND:
00560        case DEFAULT_COMMAND:
00561               if(mechanisms == NULL) {
00562                      PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
00563                             commandNames[command], optionStrings[MECHANISMS_ARG]);
00564                      return MISSING_PARAM_ERR;
00565               }
00566               break;
00567        default:
00568               /* Ignore this here */
00569               break;
00570        }
00571 
00572        return SUCCESS;
00573 }
00574 
00575 /********************************************************************
00576  *
00577  * i n i t _ c r y p t o
00578  *
00579  * Does crypto initialization that all commands will require.
00580  * If -nocertdb option is specified, don't open key or cert db (we don't
00581  * need them if we aren't going to be verifying signatures).  This is
00582  * because serverland doesn't always have cert and key database files
00583  * available.
00584  */
00585 static Error
00586 check_crypto(PRBool create, PRBool readOnly)
00587 {
00588        char *dir;
00589        char *moddbname=NULL;
00590        Error retval;
00591        static const char multiaccess[] = { "multiaccess:" };
00592 
00593        dir = SECU_ConfigDirectory(dbdir); /* dir is never NULL */
00594        if (dir[0] == '\0') {
00595               PR_fprintf(PR_STDERR, errStrings[NO_DBDIR_ERR]);
00596               retval=NO_DBDIR_ERR;
00597               goto loser;
00598        }
00599        if (strncmp(dir, multiaccess, sizeof multiaccess - 1) == 0) {
00600               /* won't attempt to handle the multiaccess case. */
00601               return SUCCESS;
00602        }
00603 
00604        /* Make sure db directory exists and is readable */
00605        if(PR_Access(dir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
00606               PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dir);
00607               retval = DIR_DOESNT_EXIST_ERR;
00608               goto loser;
00609        } else if(PR_Access(dir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
00610               PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dir);
00611               retval = DIR_NOT_READABLE_ERR;
00612               goto loser;
00613        }
00614 
00615        if (secmodName == NULL) {
00616               secmodName = "secmod.db";
00617        }
00618 
00619        moddbname = PR_smprintf("%s/%s", dir, secmodName);
00620        if (!moddbname)
00621            return OUT_OF_MEM_ERR;
00622 
00623        /* Check for the proper permissions on databases */
00624        if(create) {
00625               /* Make sure dbs don't already exist, and the directory is
00626                      writeable */
00627               if(PR_Access(moddbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
00628                      PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],
00629                                 moddbname);
00630                      retval=FILE_ALREADY_EXISTS_ERR;
00631                      goto loser;
00632               } else 
00633               if(PR_Access(dir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
00634                      PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dir);
00635                      retval=DIR_NOT_WRITEABLE_ERR;
00636                      goto loser;
00637               }
00638        } else {
00639               /* Make sure dbs are readable and writeable */
00640               if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
00641                      PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], moddbname);
00642                      retval=FILE_NOT_READABLE_ERR;
00643                      goto loser;
00644               }
00645 
00646               /* Check for write access if we'll be making changes */
00647               if( !readOnly ) {
00648                      if(PR_Access(moddbname, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
00649                             PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
00650                                                  moddbname);
00651                             retval=FILE_NOT_WRITEABLE_ERR;
00652                             goto loser;
00653                      }
00654               }
00655               PR_fprintf(PR_STDOUT, msgStrings[USING_DBDIR_MSG],
00656                 SECU_ConfigDirectory(NULL));
00657        }
00658        retval=SUCCESS;
00659 loser:
00660        if (moddbname) {
00661               PR_Free(moddbname);
00662        }
00663        return retval;
00664 }
00665 
00666 static Error
00667 init_crypto(PRBool create, PRBool readOnly)
00668 {
00669 
00670        PRUint32  flags = 0;
00671        SECStatus rv;
00672        Error     retval;
00673        /* Open/create key database */
00674 
00675        if (readOnly) flags |= NSS_INIT_READONLY;
00676        if (nocertdb) flags |= NSS_INIT_NOCERTDB;
00677        rv = NSS_Initialize(SECU_ConfigDirectory(NULL), dbprefix, dbprefix,
00678                      secmodName, flags);
00679        if (rv != SECSuccess) {
00680               SECU_PrintPRandOSError(progName);
00681               retval=NSS_INITIALIZE_FAILED_ERR;
00682        } else 
00683               retval=SUCCESS;
00684 
00685        return retval;
00686 }
00687 
00688 /*************************************************************************
00689  *
00690  * u s a g e
00691  */
00692 static void
00693 usage()
00694 {
00695        PR_fprintf(PR_STDOUT,
00696 "\nNetscape Cryptographic Module Utility\n"
00697 "Usage: modutil [command] [options]\n\n"
00698 "                            COMMANDS\n"
00699 "---------------------------------------------------------------------------\n"
00700 "-add MODULE_NAME                 Add the named module to the module database\n"
00701 "   -libfile LIBRARY_FILE         The name of the file (.so or .dll)\n"
00702 "                                 containing the implementation of PKCS #11\n"
00703 "   [-ciphers CIPHER_LIST]        Enable the given ciphers on this module\n"
00704 "   [-mechanisms MECHANISM_LIST]  Make the module a default provider of the\n"
00705 "                                 given mechanisms\n"
00706 "   [-string CONFIG_STRING]       Pass a configuration string to this module\n"
00707 "-changepw TOKEN                  Change the password on the named token\n"
00708 "   [-pwfile FILE]                The old password is in this file\n"
00709 "   [-newpwfile FILE]             The new password is in this file\n"
00710 "-chkfips [ true | false ]        If true, verify  FIPS mode.  If false,\n"
00711 "                                 verify not FIPS mode\n"
00712 "-create                          Create a new set of security databases\n"
00713 "-default MODULE                  Make the given module a default provider\n"
00714 "   -mechanisms MECHANISM_LIST    of the given mechanisms\n"
00715 "   [-slot SLOT]                  limit change to only the given slot\n"
00716 "-delete MODULE                   Remove the named module from the module\n"
00717 "                                 database\n"
00718 "-disable MODULE                  Disable the named module\n"
00719 "   [-slot SLOT]                  Disable only the named slot on the module\n"
00720 "-enable MODULE                   Enable the named module\n"
00721 "   [-slot SLOT]                  Enable only the named slot on the module\n"
00722 "-fips [ true | false ]           If true, enable FIPS mode.  If false,\n"
00723 "                                 disable FIPS mode\n"
00724 "-force                           Do not run interactively\n"
00725 "-jar JARFILE                     Install a PKCS #11 module from the given\n"
00726 "                                 JAR file in the PKCS #11 JAR format\n"
00727 "   -installdir DIR               Use DIR as the root directory of the\n"
00728 "                                 installation\n"
00729 "   [-tempdir DIR]                Use DIR as the temporary installation\n"
00730 "                                 directory. If not specified, the current\n"
00731 "                                 directory is used\n"
00732 "-list [MODULE]                   Lists information about the specified module\n"
00733 "                                 or about all modules if none is specified\n"
00734 "-rawadd MODULESPEC               Add module spec string to secmod DB\n"
00735 "-rawlist [MODULE]                Display module spec(s) for one or all\n"
00736 "                                 loadable modules\n"
00737 "-undefault MODULE                The given module is NOT a default provider\n"
00738 "   -mechanisms MECHANISM_LIST    of the listed mechanisms\n"
00739 "   [-slot SLOT]                  limit change to only the given slot\n"
00740 "---------------------------------------------------------------------------\n"
00741 "\n"
00742 "                             OPTIONS\n"
00743 "---------------------------------------------------------------------------\n"
00744 "-dbdir DIR                       Directory DIR contains the security databases\n"
00745 "-dbprefix prefix                 Prefix for the security databases\n"
00746 "-nocertdb                        Do not load certificate or key databases. No\n"
00747 "                                 verification will be performed on JAR files.\n"
00748 "-secmod secmodName               Name of the security modules file\n"
00749 "---------------------------------------------------------------------------\n"
00750 "\n"
00751 "Mechanism lists are colon-separated.  The following mechanisms are recognized:\n"
00752 "RSA, DSA, DH, RC2, RC4, RC5, AES, DES, MD2, MD5, SHA1, SHA256, SHA512,\n"
00753 "SSL, TLS, RANDOM, and FRIENDLY\n"
00754 "\n"
00755 "Cipher lists are colon-separated.  The following ciphers are recognized:\n"
00756 "\n"
00757 "\nQuestions or bug reports should be sent to modutil-support@netscape.com.\n"
00758 );
00759 
00760 }
00761 
00762 /*************************************************************************
00763  *
00764  * m a i n
00765  */
00766 int
00767 main(int argc, char *argv[])
00768 {
00769        int errcode = SUCCESS;
00770        PRBool createdb, readOnly;
00771 #define STDINBUF_SIZE 80
00772        char stdinbuf[STDINBUF_SIZE];
00773 
00774        progName = strrchr(argv[0], '/');
00775        progName = progName ? progName+1 : argv[0];
00776 
00777 
00778        PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
00779 
00780        if(parse_args(argc, argv) != SUCCESS) {
00781               usage();
00782               errcode = INVALID_USAGE_ERR;
00783               goto loser;
00784        }
00785 
00786        if(verify_params() != SUCCESS) {
00787               usage();
00788               errcode = INVALID_USAGE_ERR;
00789               goto loser;
00790        }
00791 
00792        if(command==NO_COMMAND) {
00793               PR_fprintf(PR_STDERR, errStrings[NO_COMMAND_ERR]);
00794               usage();
00795               errcode = INVALID_USAGE_ERR;
00796               goto loser;
00797        }
00798 
00799        /* Set up crypto stuff */
00800        createdb = command==CREATE_COMMAND;
00801        readOnly = ((command == LIST_COMMAND) || 
00802                    (command == CHKFIPS_COMMAND) ||
00803                    (command == RAW_LIST_COMMAND));
00804 
00805        /* Make sure browser is not running if we're writing to a database */
00806        /* Do this before initializing crypto */
00807        if(!readOnly && !force) {
00808               char *response;
00809 
00810               PR_fprintf(PR_STDOUT, msgStrings[BROWSER_RUNNING_MSG]);
00811               if( ! PR_fgets(stdinbuf, STDINBUF_SIZE, PR_STDIN)) {
00812                      PR_fprintf(PR_STDERR, errStrings[STDIN_READ_ERR]);
00813                      errcode = STDIN_READ_ERR;
00814                      goto loser;
00815               }
00816               if( (response=strtok(stdinbuf, " \r\n\t")) ) {
00817                      if(!PL_strcasecmp(response, "q")) {
00818                             PR_fprintf(PR_STDOUT, msgStrings[ABORTING_MSG]);
00819                             errcode = SUCCESS;
00820                             goto loser;
00821                      }
00822               }
00823               PR_fprintf(PR_STDOUT, "\n");
00824        }
00825 
00826        errcode = check_crypto(createdb, readOnly);
00827        if( errcode != SUCCESS) {
00828               goto loser;
00829        }
00830 
00831        if ((command == RAW_LIST_COMMAND) || (command == RAW_ADD_COMMAND)) {
00832               if(!moduleName) {
00833                      char *readOnlyStr, *noCertDBStr, *sep;
00834                      if (!secmodName) secmodName="secmod.db";
00835                      if (!dbprefix) dbprefix = "";
00836                      sep = ((command == RAW_LIST_COMMAND) && nocertdb) ? "," : " ";
00837                      readOnlyStr = (command == RAW_LIST_COMMAND) ? "readOnly" : "" ;
00838                      noCertDBStr = nocertdb ? "noCertDB" : "";
00839                      SECU_ConfigDirectory(dbdir);
00840 
00841                      moduleName=PR_smprintf(
00842     "name=\"NSS default Module DB\" parameters=\"configdir=%s certPrefix=%s "
00843     "keyPrefix=%s secmod=%s flags=%s%s%s\" NSS=\"flags=internal,moduleDB,"
00844     "moduleDBOnly,critical\"",
00845                                             SECU_ConfigDirectory(NULL),dbprefix,dbprefix,
00846                                             secmodName, readOnlyStr,sep, noCertDBStr);
00847               }
00848               if (command == RAW_LIST_COMMAND) {
00849                      errcode = RawListModule(moduleName);
00850               } else {
00851                      PORT_Assert(moduleSpec);
00852                      errcode = RawAddModule(moduleName,moduleSpec);
00853               }
00854               goto loser;
00855        }
00856 
00857        errcode = init_crypto(createdb, readOnly);
00858        if( errcode != SUCCESS) {
00859               goto loser;
00860        }
00861 
00862        /* Execute the command */
00863        switch(command) {
00864        case ADD_COMMAND:
00865               errcode = AddModule(moduleName, libFile, ciphers, mechanisms, secmodString);
00866               break;
00867        case CHANGEPW_COMMAND:
00868               errcode = ChangePW(tokenName, pwFile, newpwFile);
00869               break;
00870        case CREATE_COMMAND:
00871               /* The work was already done in init_crypto() */
00872               break;
00873        case DEFAULT_COMMAND:
00874               errcode = SetDefaultModule(moduleName, slotName, mechanisms);
00875               break;
00876        case DELETE_COMMAND:
00877               errcode = DeleteModule(moduleName);
00878               break;
00879        case DISABLE_COMMAND:
00880               errcode = EnableModule(moduleName, slotName, PR_FALSE);
00881               break;
00882        case ENABLE_COMMAND:
00883               errcode = EnableModule(moduleName, slotName, PR_TRUE);
00884               break;
00885        case FIPS_COMMAND:
00886               errcode = FipsMode(fipsArg);
00887               break;
00888        case CHKFIPS_COMMAND:
00889               errcode = ChkFipsMode(fipsArg);
00890               break;
00891        case JAR_COMMAND:
00892               Pk11Install_SetErrorHandler(install_error);
00893               errcode = Pk11Install_DoInstall(jarFile, installDir, tempDir,
00894                                               PR_STDOUT, force, nocertdb);
00895               break;
00896        case LIST_COMMAND:
00897               if(moduleName) {
00898                      errcode = ListModule(moduleName);
00899               } else {
00900                      errcode = ListModules();
00901               }
00902               break;
00903        case UNDEFAULT_COMMAND:
00904               errcode = UnsetDefaultModule(moduleName, slotName, mechanisms);
00905               break;
00906        default:
00907               PR_fprintf(PR_STDERR, "This command is not supported yet.\n");
00908               errcode = INVALID_USAGE_ERR;
00909               break;
00910        }
00911 
00912        if (NSS_Shutdown() != SECSuccess) {
00913               exit(1);
00914        }
00915 
00916 loser:
00917        PR_Cleanup();
00918        return errcode;
00919 }
00920 
00921 /************************************************************************
00922  *
00923  * i n s t a l l _ e r r o r
00924  *
00925  * Callback function to handle errors in PK11 JAR file installation.
00926  */
00927 static void
00928 install_error(char *message)
00929 {
00930        PR_fprintf(PR_STDERR, "Install error: %s\n", message);
00931 }
00932 
00933 /*************************************************************************
00934  *
00935  * o u t _ o f _ m e m o r y
00936  */
00937 void
00938 out_of_memory(void)
00939 {
00940        PR_fprintf(PR_STDERR, errStrings[OUT_OF_MEM_ERR]);
00941        exit(OUT_OF_MEM_ERR);
00942 }
00943 
00944 
00945 /**************************************************************************
00946  *
00947  * P R _ f g e t s
00948  *
00949  * fgets implemented with NSPR.
00950  */
00951 static char*
00952 PR_fgets(char *buf, int size, PRFileDesc *file)
00953 {
00954        int i;
00955        int status;
00956        char c;
00957 
00958        i=0;
00959        while(i < size-1) {
00960               status = PR_Read(file, (void*) &c, 1);
00961               if(status==-1) {
00962                      return NULL;
00963               } else if(status==0) {
00964                      break;
00965               }
00966               buf[i++] = c;
00967               if(c=='\n') {
00968                      break;
00969               }
00970        }
00971        buf[i]='\0';
00972 
00973        return buf;
00974 }