modutil.c
上传用户:lyxiangda
上传日期:2007-01-12
资源大小:3042k
文件大小:24k
源码类别:

CA认证

开发平台:

WINDOWS

  1. /*
  2.  * The contents of this file are subject to the Mozilla Public
  3.  * License Version 1.1 (the "License"); you may not use this file
  4.  * except in compliance with the License. You may obtain a copy of
  5.  * the License at http://www.mozilla.org/MPL/
  6.  * 
  7.  * Software distributed under the License is distributed on an "AS
  8.  * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
  9.  * implied. See the License for the specific language governing
  10.  * rights and limitations under the License.
  11.  * 
  12.  * The Original Code is the Netscape security libraries.
  13.  * 
  14.  * The Initial Developer of the Original Code is Netscape
  15.  * Communications Corporation.  Portions created by Netscape are 
  16.  * Copyright (C) 1994-2000 Netscape Communications Corporation.  All
  17.  * Rights Reserved.
  18.  * 
  19.  * Contributor(s):
  20.  * 
  21.  * Alternatively, the contents of this file may be used under the
  22.  * terms of the GNU General Public License Version 2 or later (the
  23.  * "GPL"), in which case the provisions of the GPL are applicable 
  24.  * instead of those above.  If you wish to allow use of your 
  25.  * version of this file only under the terms of the GPL and not to
  26.  * allow others to use your version of this file under the MPL,
  27.  * indicate your decision by deleting the provisions above and
  28.  * replace them with the notice and other provisions required by
  29.  * the GPL.  If you do not delete the provisions above, a recipient
  30.  * may use your version of this file under either the MPL or the
  31.  * GPL.
  32.  */
  33. #include "modutil.h"
  34. #include "install.h"
  35. #include <plstr.h>
  36. #include "secrng.h"
  37. #include "certdb.h" /* for CERT_DB_FILE_VERSION */
  38. static void install_error(char *message);
  39. static char* PR_fgets(char *buf, int size, PRFileDesc *file);
  40. /* This enum must be kept in sync with the commandNames list */
  41. typedef enum {
  42. NO_COMMAND,
  43. ADD_COMMAND,
  44. CHANGEPW_COMMAND,
  45. CREATE_COMMAND,
  46. DEFAULT_COMMAND,
  47. DELETE_COMMAND,
  48. DISABLE_COMMAND,
  49. ENABLE_COMMAND,
  50. FIPS_COMMAND,
  51. JAR_COMMAND,
  52. LIST_COMMAND,
  53. UNDEFAULT_COMMAND
  54. } Command;
  55. /* This list must be kept in sync with the Command enum */
  56. static char *commandNames[] = {
  57. "(no command)",
  58. "-add",
  59. "-changepw",
  60. "-create",
  61. "-default",
  62. "-delete",
  63. "-disable",
  64. "-enable",
  65. "-fips",
  66. "-jar",
  67. "-list",
  68. "-undefault"
  69. };
  70. /* this enum must be kept in sync with the optionStrings list */
  71. typedef enum {
  72. ADD_ARG=0,
  73. CHANGEPW_ARG,
  74. CIPHERS_ARG,
  75. CREATE_ARG,
  76. DBDIR_ARG,
  77. DEFAULT_ARG,
  78. DELETE_ARG,
  79. DISABLE_ARG,
  80. ENABLE_ARG,
  81. FIPS_ARG,
  82. FORCE_ARG,
  83. JAR_ARG,
  84. LIBFILE_ARG,
  85. LIST_ARG,
  86. MECHANISMS_ARG,
  87. NEWPWFILE_ARG,
  88. PWFILE_ARG,
  89. SLOT_ARG,
  90. UNDEFAULT_ARG,
  91. INSTALLDIR_ARG,
  92. TEMPDIR_ARG,
  93. NOCERTDB_ARG,
  94. NUM_ARGS /* must be last */
  95. } Arg;
  96. /* This list must be kept in sync with the Arg enum */
  97. static char *optionStrings[] = {
  98. "-add",
  99. "-changepw",
  100. "-ciphers",
  101. "-create",
  102. "-dbdir",
  103. "-default",
  104. "-delete",
  105. "-disable",
  106. "-enable",
  107. "-fips",
  108. "-force",
  109. "-jar",
  110. "-libfile",
  111. "-list",
  112. "-mechanisms",
  113. "-newpwfile",
  114. "-pwfile",
  115. "-slot",
  116. "-undefault",
  117. "-installdir",
  118. "-tempdir",
  119. "-nocertdb"
  120. };
  121. /* Increment i if doing so would have i still be less than j.  If you
  122.    are able to do this, return 0.  Otherwise return 1. */
  123. #define TRY_INC(i,j)  ( ((i+1)<j) ? (++i, 0) : 1 )
  124. /********************************************************************
  125.  *
  126.  * file-wide variables obtained from the command line
  127.  */
  128. static Command command = NO_COMMAND;
  129. static char* pwFile = NULL;
  130. static char* newpwFile = NULL;
  131. static char* moduleName = NULL;
  132. static char* slotName = NULL;
  133. static char* tokenName = NULL;
  134. static char* libFile = NULL;
  135. static char* dbdir = NULL;
  136. static char* mechanisms = NULL;
  137. static char* ciphers = NULL;
  138. static char* fipsArg = NULL;
  139. static char* jarFile = NULL;
  140. static char* installDir = NULL;
  141. static char* tempDir = NULL;
  142. static short force = 0;
  143. static PRBool nocertdb = PR_FALSE;
  144. /*******************************************************************
  145.  *
  146.  * p a r s e _ a r g s
  147.  */
  148. static Error
  149. parse_args(int argc, char *argv[])
  150. {
  151. int i;
  152. char *arg;
  153. int optionType;
  154. /* Loop over all arguments */
  155. for(i=1; i < argc; i++) {
  156. arg = argv[i];
  157. /* Make sure this is an option and not some floating argument */
  158. if(arg[0] != '-') {
  159. PR_fprintf(PR_STDERR, errStrings[UNEXPECTED_ARG_ERR], argv[i]);
  160. return UNEXPECTED_ARG_ERR;
  161. }
  162. /* Find which option this is */
  163. for(optionType=0; optionType < NUM_ARGS; optionType++) {
  164. if(! strcmp(arg, optionStrings[optionType])) {
  165. break;
  166. }
  167. }
  168. /* Deal with this specific option */
  169. switch(optionType) {
  170. case NUM_ARGS:
  171. default:
  172. PR_fprintf(PR_STDERR, errStrings[UNKNOWN_OPTION_ERR], arg);
  173. return UNKNOWN_OPTION_ERR;
  174. break;
  175. case ADD_ARG:
  176. if(command != NO_COMMAND) {
  177. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  178. return MULTIPLE_COMMAND_ERR;
  179. }
  180. command = ADD_COMMAND;
  181. if(TRY_INC(i, argc)) {
  182. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  183. return OPTION_NEEDS_ARG_ERR;
  184. }
  185. moduleName = argv[i];
  186. break;
  187. case CHANGEPW_ARG:
  188. if(command != NO_COMMAND) {
  189. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  190. return MULTIPLE_COMMAND_ERR;
  191. }
  192. command = CHANGEPW_COMMAND;
  193. if(TRY_INC(i, argc)) {
  194. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  195. return OPTION_NEEDS_ARG_ERR;
  196. }
  197. tokenName = argv[i];
  198. break;
  199. case CIPHERS_ARG:
  200. if(ciphers != NULL) {
  201. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  202. return DUPLICATE_OPTION_ERR;
  203. }
  204. if(TRY_INC(i, argc)) {
  205. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  206. return OPTION_NEEDS_ARG_ERR;
  207. }
  208. ciphers = argv[i];
  209. break;
  210. case CREATE_ARG:
  211. if(command != NO_COMMAND) {
  212. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  213. return MULTIPLE_COMMAND_ERR;
  214. }
  215. command = CREATE_COMMAND;
  216. break;
  217. case DBDIR_ARG:
  218. if(dbdir != NULL) {
  219. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  220. return DUPLICATE_OPTION_ERR;
  221. }
  222. if(TRY_INC(i, argc)) {
  223. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  224. return OPTION_NEEDS_ARG_ERR;
  225. }
  226. dbdir = argv[i];
  227. break;
  228. case UNDEFAULT_ARG:
  229. case DEFAULT_ARG:
  230. if(command != NO_COMMAND) {
  231. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  232. return MULTIPLE_COMMAND_ERR;
  233. }
  234. if(optionType == DEFAULT_ARG) {
  235. command = DEFAULT_COMMAND;
  236. } else {
  237. command = UNDEFAULT_COMMAND;
  238. }
  239. if(TRY_INC(i, argc)) {
  240. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  241. return OPTION_NEEDS_ARG_ERR;
  242. }
  243. moduleName = argv[i];
  244. break;
  245. case DELETE_ARG:
  246. if(command != NO_COMMAND) {
  247. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  248. return MULTIPLE_COMMAND_ERR;
  249. }
  250. command = DELETE_COMMAND;
  251. if(TRY_INC(i, argc)) {
  252. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  253. return OPTION_NEEDS_ARG_ERR;
  254. }
  255. moduleName = argv[i];
  256. break;
  257. case DISABLE_ARG:
  258. if(command != NO_COMMAND) {
  259. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  260. return MULTIPLE_COMMAND_ERR;
  261. }
  262. command = DISABLE_COMMAND;
  263. if(TRY_INC(i, argc)) {
  264. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  265. return OPTION_NEEDS_ARG_ERR;
  266. }
  267. moduleName = argv[i];
  268. break;
  269. case ENABLE_ARG:
  270. if(command != NO_COMMAND) {
  271. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  272. return MULTIPLE_COMMAND_ERR;
  273. }
  274. command = ENABLE_COMMAND;
  275. if(TRY_INC(i, argc)) {
  276. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  277. return OPTION_NEEDS_ARG_ERR;
  278. }
  279. moduleName = argv[i];
  280. break;
  281. case FIPS_ARG:
  282. if(command != NO_COMMAND) {
  283. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  284. return MULTIPLE_COMMAND_ERR;
  285. }
  286. command = FIPS_COMMAND;
  287. if(TRY_INC(i, argc)) {
  288. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  289. return OPTION_NEEDS_ARG_ERR;
  290. }
  291. fipsArg = argv[i];
  292. break;
  293. case FORCE_ARG:
  294. force = 1;
  295. break;
  296. case NOCERTDB_ARG:
  297. nocertdb = PR_TRUE;
  298. break;
  299. case INSTALLDIR_ARG:
  300. if(installDir != NULL) {
  301. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  302. return DUPLICATE_OPTION_ERR;
  303. }
  304. if(TRY_INC(i, argc)) {
  305. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  306. return OPTION_NEEDS_ARG_ERR;
  307. }
  308. installDir = argv[i];
  309. break;
  310. case TEMPDIR_ARG:
  311. if(tempDir != NULL) {
  312. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  313. return DUPLICATE_OPTION_ERR;
  314. }
  315. if(TRY_INC(i, argc)) {
  316. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  317. return OPTION_NEEDS_ARG_ERR;
  318. }
  319. tempDir = argv[i];
  320. break;
  321. case JAR_ARG:
  322. if(command != NO_COMMAND) {
  323. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  324. return MULTIPLE_COMMAND_ERR;
  325. }
  326. command = JAR_COMMAND;
  327. if(TRY_INC(i, argc)) {
  328. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  329. return OPTION_NEEDS_ARG_ERR;
  330. }
  331. jarFile = argv[i];
  332. break;
  333. case LIBFILE_ARG:
  334. if(libFile != NULL) {
  335. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  336. return DUPLICATE_OPTION_ERR;
  337. }
  338. if(TRY_INC(i, argc)) {
  339. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  340. return OPTION_NEEDS_ARG_ERR;
  341. }
  342. libFile = argv[i];
  343. break;
  344. case LIST_ARG:
  345. if(command != NO_COMMAND) {
  346. PR_fprintf(PR_STDERR, errStrings[MULTIPLE_COMMAND_ERR], arg);
  347. return MULTIPLE_COMMAND_ERR;
  348. }
  349. command = LIST_COMMAND;
  350. /* This option may or may not have an argument */
  351. if( (i+1 < argc) && (argv[i+1][0] != '-') ) {
  352. moduleName = argv[++i];
  353. }
  354. break;
  355. case MECHANISMS_ARG:
  356. if(mechanisms != NULL) {
  357. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  358. return DUPLICATE_OPTION_ERR;
  359. }
  360. if(TRY_INC(i, argc)) {
  361. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  362. return OPTION_NEEDS_ARG_ERR;
  363. }
  364. mechanisms = argv[i];
  365. break;
  366. case NEWPWFILE_ARG:
  367. if(newpwFile != NULL) {
  368. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  369. return DUPLICATE_OPTION_ERR;
  370. }
  371. if(TRY_INC(i, argc)) {
  372. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  373. return OPTION_NEEDS_ARG_ERR;
  374. }
  375. newpwFile = argv[i];
  376. break;
  377. case PWFILE_ARG:
  378. if(pwFile != NULL) {
  379. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  380. return DUPLICATE_OPTION_ERR;
  381. }
  382. if(TRY_INC(i, argc)) {
  383. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  384. return OPTION_NEEDS_ARG_ERR;
  385. }
  386. pwFile = argv[i];
  387. break;
  388. case SLOT_ARG:
  389. if(slotName != NULL) {
  390. PR_fprintf(PR_STDERR, errStrings[DUPLICATE_OPTION_ERR], arg);
  391. return DUPLICATE_OPTION_ERR;
  392. }
  393. if(TRY_INC(i, argc)) {
  394. PR_fprintf(PR_STDERR, errStrings[OPTION_NEEDS_ARG_ERR], arg);
  395. return OPTION_NEEDS_ARG_ERR;
  396. }
  397. slotName = argv[i];
  398. break;
  399. }
  400. }
  401. return SUCCESS;
  402. }
  403. /************************************************************************
  404.  *
  405.  * v e r i f y _ p a r a m s
  406.  */
  407. static Error
  408. verify_params()
  409. {
  410. switch(command) {
  411. case ADD_COMMAND:
  412. if(libFile == NULL) {
  413. PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
  414. commandNames[ADD_COMMAND], optionStrings[LIBFILE_ARG]);
  415. return MISSING_PARAM_ERR;
  416. }
  417. break;
  418. case CHANGEPW_COMMAND:
  419. break;
  420. case CREATE_COMMAND:
  421. break;
  422. case DELETE_COMMAND:
  423. break;
  424. case DISABLE_COMMAND:
  425. break;
  426. case ENABLE_COMMAND:
  427. break;
  428. case FIPS_COMMAND:
  429. if(PL_strcasecmp(fipsArg, "true") &&
  430. PL_strcasecmp(fipsArg, "false")) {
  431. PR_fprintf(PR_STDERR, errStrings[INVALID_FIPS_ARG]);
  432. return INVALID_FIPS_ARG;
  433. }
  434. break;
  435. case JAR_COMMAND:
  436. if(installDir == NULL) {
  437. PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
  438. commandNames[JAR_COMMAND], optionStrings[INSTALLDIR_ARG]);
  439. return MISSING_PARAM_ERR;
  440. }
  441. break;
  442. case LIST_COMMAND:
  443. break;
  444. case UNDEFAULT_COMMAND:
  445. case DEFAULT_COMMAND:
  446. if(mechanisms == NULL) {
  447. PR_fprintf(PR_STDERR, errStrings[MISSING_PARAM_ERR],
  448. commandNames[command], optionStrings[MECHANISMS_ARG]);
  449. return MISSING_PARAM_ERR;
  450. }
  451. break;
  452. default:
  453. /* Ignore this here */
  454. break;
  455. }
  456. return SUCCESS;
  457. }
  458. /********************************************************************
  459.  *
  460.  * i n i t _ c r y p t o
  461.  *
  462.  * Does crypto initialization that all commands will require.
  463.  * If -nocertdb option is specified, don't open key or cert db (we don't
  464.  * need them if we aren't going to be verifying signatures).  This is
  465.  * because serverland doesn't always have cert and key database files
  466.  * available.
  467.  */
  468. static Error
  469. init_crypto(PRBool create, PRBool readOnly)
  470. {
  471. char *moddbname=NULL, *dir, *keydbname, *certdbname;
  472. PRBool free_moddbname = PR_FALSE;
  473. Error retval;
  474. if(SECU_ConfigDirectory(dbdir)[0] == '') {
  475. PR_fprintf(PR_STDERR, errStrings[NO_DBDIR_ERR]);
  476. retval=NO_DBDIR_ERR;
  477. goto loser;
  478. }
  479. moddbname = SECU_SECModDBName(); /* this changes later in the function */
  480. dir = SECU_ConfigDirectory(NULL);
  481. keydbname = SECU_KeyDBNameCallback(NULL, PRIVATE_KEY_DB_FILE_VERSION);
  482. certdbname = SECU_CertDBNameCallback(NULL, CERT_DB_FILE_VERSION);
  483. /* Make sure db directory exists and is readable */
  484. if(PR_Access(dir, PR_ACCESS_EXISTS) != PR_SUCCESS) {
  485. PR_fprintf(PR_STDERR, errStrings[DIR_DOESNT_EXIST_ERR], dir);
  486. retval = DIR_DOESNT_EXIST_ERR;
  487. goto loser;
  488. } else if(PR_Access(dir, PR_ACCESS_READ_OK) != PR_SUCCESS) {
  489. PR_fprintf(PR_STDERR, errStrings[DIR_NOT_READABLE_ERR], dir);
  490. retval = DIR_NOT_READABLE_ERR;
  491. goto loser;
  492. }
  493. /* Check for the proper permissions on databases */
  494. if(create) {
  495. /* Make sure dbs don't already exist, and the directory is
  496. writeable */
  497. if(PR_Access(moddbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
  498. PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],
  499.   moddbname);
  500. retval=FILE_ALREADY_EXISTS_ERR;
  501. goto loser;
  502. } else if(PR_Access(keydbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
  503. PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR], keydbname);
  504. retval=FILE_ALREADY_EXISTS_ERR;
  505. goto loser;
  506. } else if(PR_Access(certdbname, PR_ACCESS_EXISTS)==PR_SUCCESS) {
  507. PR_fprintf(PR_STDERR, errStrings[FILE_ALREADY_EXISTS_ERR],certdbname);
  508. retval=FILE_ALREADY_EXISTS_ERR;
  509. goto loser;
  510. } else if(PR_Access(dir, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
  511. PR_fprintf(PR_STDERR, errStrings[DIR_NOT_WRITEABLE_ERR], dir);
  512. retval=DIR_NOT_WRITEABLE_ERR;
  513. goto loser;
  514. }
  515. } else {
  516. /* Make sure dbs are readable and writeable */
  517. if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
  518. #ifndef XP_PC
  519. /* in serverland, they always use secmod.db, even on UNIX. Try
  520.    this */
  521. moddbname = PR_smprintf("%s/secmod.db", dir);
  522. free_moddbname = PR_TRUE;
  523. if(PR_Access(moddbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
  524. #endif
  525. PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR], moddbname);
  526. retval=FILE_NOT_READABLE_ERR;
  527. goto loser;
  528. #ifndef XP_PC
  529. }
  530. #endif
  531. }
  532. if(!nocertdb) { /* don't open cert and key db if -nocertdb */
  533. if(PR_Access(keydbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
  534. PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
  535.   keydbname);
  536. retval=FILE_NOT_READABLE_ERR;
  537. goto loser;
  538. }
  539. if(PR_Access(certdbname, PR_ACCESS_READ_OK) != PR_SUCCESS) {
  540. PR_fprintf(PR_STDERR, errStrings[FILE_NOT_READABLE_ERR],
  541.   certdbname);
  542. retval=FILE_NOT_READABLE_ERR;
  543. goto loser;
  544. }
  545. }
  546. /* Check for write access if we'll be making changes */
  547. if( !readOnly ) {
  548. if(PR_Access(moddbname, PR_ACCESS_WRITE_OK) != PR_SUCCESS) {
  549. PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
  550.   moddbname);
  551. retval=FILE_NOT_WRITEABLE_ERR;
  552. goto loser;
  553. }
  554. if(!nocertdb) { /* don't open key and cert db if -nocertdb */
  555. if(PR_Access(keydbname, PR_ACCESS_WRITE_OK)
  556. != PR_SUCCESS) {
  557. PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
  558.   keydbname);
  559. retval=FILE_NOT_WRITEABLE_ERR;
  560. goto loser;
  561. }
  562. if(PR_Access(certdbname, PR_ACCESS_WRITE_OK)
  563. != PR_SUCCESS) {
  564. PR_fprintf(PR_STDERR, errStrings[FILE_NOT_WRITEABLE_ERR],
  565.   certdbname);
  566. retval=FILE_NOT_WRITEABLE_ERR;
  567. goto loser;
  568. }
  569. }
  570. }
  571. PR_fprintf(PR_STDOUT, msgStrings[USING_DBDIR_MSG],
  572.   SECU_ConfigDirectory(NULL));
  573. }
  574. SEC_Init();
  575. /* Open/create key database */
  576. RNG_RNGInit(); /* This is required before SECU_OpenKeyDB */
  577. RNG_SystemInfoForRNG();
  578. if(!nocertdb) {
  579. if(create) PR_fprintf(PR_STDOUT, msgStrings[CREATING_DB_MSG],
  580.   keydbname);
  581. if(SECU_OpenKeyDB(readOnly) == NULL) {
  582. PR_fprintf(PR_STDERR, "n");
  583. PR_fprintf(PR_STDERR, errStrings[DB_ACCESS_ERR], keydbname);
  584. retval=DB_ACCESS_ERR;
  585. goto loser;
  586. }
  587. if(create) PR_fprintf(PR_STDOUT, msgStrings[DONE_MSG]);
  588. }
  589. /* Open/create cert database */
  590. if(!nocertdb) {
  591. if(create) PR_fprintf(PR_STDOUT, msgStrings[CREATING_DB_MSG],
  592.   certdbname);
  593. if(SECU_OpenCertDB(readOnly) == NULL) {
  594. PR_fprintf(PR_STDERR, "n");
  595. PR_fprintf(PR_STDERR, errStrings[DB_ACCESS_ERR], certdbname);
  596. retval=DB_ACCESS_ERR;
  597. goto loser;
  598. }
  599. if(create) PR_fprintf(PR_STDOUT, msgStrings[DONE_MSG]);
  600. }
  601. /* Open/create module database */
  602. if(create) PR_fprintf(PR_STDOUT, msgStrings[CREATING_DB_MSG], moddbname);
  603. SECMOD_init(moddbname);
  604. if(create) PR_fprintf(PR_STDOUT, msgStrings[DONE_MSG]);
  605. retval=SUCCESS;
  606. loser:
  607. if(free_moddbname) {
  608. PR_Free(moddbname);
  609. }
  610. return retval;
  611. }
  612. /*************************************************************************
  613.  *
  614.  * u s a g e
  615.  */
  616. static void
  617. usage()
  618. {
  619. PR_fprintf(PR_STDOUT,
  620. "nNetscape Cryptographic Module Utilityn"
  621. "Usage: modutil [command] [options]nn"
  622. "                            COMMANDSn"
  623. "---------------------------------------------------------------------------n"
  624. "-add MODULE_NAME                 Add the named module to the module databasen"
  625. "   -libfile LIBRARY_FILE         The name of the file (.so or .dll)n"
  626. "                                 containing the implementation of PKCS #11n"
  627. "   [-ciphers CIPHER_LIST]        Enable the given ciphers on this modulen"
  628. "   [-mechanisms MECHANISM_LIST]  Make the module a default provider of then"
  629. "                                 given mechanismsn"
  630. "-changepw TOKEN                  Change the password on the named tokenn"
  631. "   [-pwfile FILE]                The old password is in this filen"
  632. "   [-newpwfile FILE]             The new password is in this filen"
  633. "-create                          Create a new set of security databasesn"
  634. "-default MODULE                  Make the given module a default providern"
  635. "   -mechanisms MECHANISM_LIST    of the given mechanismsn"
  636. "   [-slot SLOT]                  limit change to only the given slotn"
  637. "-delete MODULE                   Remove the named module from the modulen"
  638. "                                 databasen"
  639. "-disable MODULE                  Disable the named modulen"
  640. "   [-slot SLOT]                  Disable only the named slot on the modulen"
  641. "-enable MODULE                   Enable the named modulen"
  642. "   [-slot SLOT]                  Enable only the named slot on the modulen"
  643. "-fips [ true | false ]           If true, enable FIPS mode.  If false,n"
  644. "                                 disable FIPS moden"
  645. "-force                           Do not run interactivelyn"
  646. "-jar JARFILE                     Install a PKCS #11 module from the givenn"
  647. "                                 JAR file in the PKCS #11 JAR formatn"
  648. "   -installdir DIR               Use DIR as the root directory of then"
  649. "                                 installationn"
  650. "   [-tempdir DIR]                Use DIR as the temporary installationn"
  651. "                                 directory. If not specified, the currentn"
  652. "                                 directory is usedn"
  653. "-list [MODULE]                   Lists information about the specified modulen"
  654. "                                 or about all modules if none is specifiedn"
  655. "-undefault MODULE                The given module is NOT a default providern"
  656. "   -mechanisms MECHANISM_LIST    of the listed mechanismsn"
  657. "   [-slot SLOT]                  limit change to only the given slotn"
  658. "---------------------------------------------------------------------------n"
  659. "n"
  660. "                             OPTIONSn"
  661. "---------------------------------------------------------------------------n"
  662. "-dbdir DIR                       Directory DIR contains the security databasesn"
  663. "-nocertdb                        Do not load certificate or key databases. Non"
  664. "                                 verification will be performed on JAR files.n"
  665. "---------------------------------------------------------------------------n"
  666. "n"
  667. "Mechanism lists are colon-separated.  The following mechanisms are recognized:n"
  668. "RSA, DSA, RC2, RC4, RC5, DES, DH, FORTEZZA, SHA1, MD5, MD2, SSL, TLS, RANDOM,n"
  669. " FRIENDLYn"
  670. "n"
  671. "Cipher lists are colon-separated.  The following ciphers are recognized:n"
  672. "FORTEZZAn"
  673. "nQuestions or bug reports should be sent to modutil-support@netscape.com.n"
  674. );
  675. }
  676. /*************************************************************************
  677.  *
  678.  * m a i n
  679.  */
  680. int
  681. main(int argc, char *argv[])
  682. {
  683. int errcode = SUCCESS;
  684. PRBool createdb, readOnly;
  685. #define STDINBUF_SIZE 80
  686. char stdinbuf[STDINBUF_SIZE];
  687. PR_Init(PR_USER_THREAD, PR_PRIORITY_NORMAL, 0);
  688. if(parse_args(argc, argv) != SUCCESS) {
  689. usage();
  690. errcode = INVALID_USAGE_ERR;
  691. goto loser;
  692. }
  693. if(verify_params() != SUCCESS) {
  694. usage();
  695. errcode = INVALID_USAGE_ERR;
  696. goto loser;
  697. }
  698. if(command==NO_COMMAND) {
  699. PR_fprintf(PR_STDERR, errStrings[NO_COMMAND_ERR]);
  700. usage();
  701. errcode = INVALID_USAGE_ERR;
  702. goto loser;
  703. }
  704. /* Set up crypto stuff */
  705. createdb = command==CREATE_COMMAND;
  706. readOnly = command==LIST_COMMAND;
  707. /* Make sure browser is not running if we're writing to a database */
  708. /* Do this before initializing crypto */
  709. if(!readOnly && !force) {
  710. char *response;
  711. PR_fprintf(PR_STDOUT, msgStrings[BROWSER_RUNNING_MSG]);
  712. if( ! PR_fgets(stdinbuf, STDINBUF_SIZE, PR_STDIN)) {
  713. PR_fprintf(PR_STDERR, errStrings[STDIN_READ_ERR]);
  714. errcode = STDIN_READ_ERR;
  715. goto loser;
  716. }
  717. if( (response=strtok(stdinbuf, " rnt")) ) {
  718. if(!PL_strcasecmp(response, "q")) {
  719. PR_fprintf(PR_STDOUT, msgStrings[ABORTING_MSG]);
  720. errcode = SUCCESS;
  721. goto loser;
  722. }
  723. }
  724. PR_fprintf(PR_STDOUT, "n");
  725. }
  726. errcode = init_crypto(createdb, readOnly);
  727. if( errcode != SUCCESS) {
  728. goto loser;
  729. }
  730. /* Execute the command */
  731. switch(command) {
  732. case ADD_COMMAND:
  733. errcode = AddModule(moduleName, libFile, ciphers, mechanisms);
  734. break;
  735. case CHANGEPW_COMMAND:
  736. errcode = ChangePW(tokenName, pwFile, newpwFile);
  737. break;
  738. case CREATE_COMMAND:
  739. /* The work was already done in init_crypto() */
  740. break;
  741. case DEFAULT_COMMAND:
  742. errcode = SetDefaultModule(moduleName, slotName, mechanisms);
  743. break;
  744. case DELETE_COMMAND:
  745. errcode = DeleteModule(moduleName);
  746. break;
  747. case DISABLE_COMMAND:
  748. errcode = EnableModule(moduleName, slotName, PR_FALSE);
  749. break;
  750. case ENABLE_COMMAND:
  751. errcode = EnableModule(moduleName, slotName, PR_TRUE);
  752. break;
  753. case FIPS_COMMAND:
  754. errcode = FipsMode(fipsArg);
  755. break;
  756. case JAR_COMMAND:
  757. Pk11Install_SetErrorHandler(install_error);
  758. errcode = Pk11Install_DoInstall(jarFile, installDir, tempDir,
  759. PR_STDOUT, force, nocertdb);
  760. break;
  761. case LIST_COMMAND:
  762. if(moduleName) {
  763. errcode = ListModule(moduleName);
  764. } else {
  765. errcode = ListModules();
  766. }
  767. break;
  768. case UNDEFAULT_COMMAND:
  769. errcode = UnsetDefaultModule(moduleName, slotName, mechanisms);
  770. break;
  771. default:
  772. PR_fprintf(PR_STDERR, "This command is not supported yet.n");
  773. errcode = INVALID_USAGE_ERR;
  774. break;
  775. }
  776. loser:
  777. PR_Cleanup();
  778. return errcode;
  779. }
  780. /************************************************************************
  781.  *
  782.  * i n s t a l l _ e r r o r
  783.  *
  784.  * Callback function to handle errors in PK11 JAR file installation.
  785.  */
  786. static void
  787. install_error(char *message)
  788. {
  789. PR_fprintf(PR_STDERR, "Install error: %sn", message);
  790. }
  791. /*************************************************************************
  792.  *
  793.  * o u t _ o f _ m e m o r y
  794.  */
  795. void
  796. out_of_memory(void)
  797. {
  798. PR_fprintf(PR_STDERR, errStrings[OUT_OF_MEM_ERR]);
  799. exit(OUT_OF_MEM_ERR);
  800. }
  801. /**************************************************************************
  802.  *
  803.  * P R _ f g e t s
  804.  *
  805.  * fgets implemented with NSPR.
  806.  */
  807. static char*
  808. PR_fgets(char *buf, int size, PRFileDesc *file)
  809. {
  810. int i;
  811. int status;
  812. char c;
  813. i=0;
  814. while(i < size-1) {
  815. status = PR_Read(file, (void*) &c, 1);
  816. if(status==-1) {
  817. return NULL;
  818. } else if(status==0) {
  819. break;
  820. }
  821. buf[i++] = c;
  822. if(c=='n') {
  823. break;
  824. }
  825. }
  826. buf[i]='';
  827. return buf;
  828. }