util.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 "signtool.h"
  34. #include "cdbhdl.h"
  35. #include "prio.h"
  36. #include "prmem.h"
  37. static int is_dir (char *filename);
  38. static char *certDBNameCallback(void *arg, int dbVersion);
  39. /***********************************************************************
  40.  *
  41.  * O p e n C e r t D B
  42.  */
  43. CERTCertDBHandle *
  44. OpenCertDB(PRBool readOnly)
  45. {
  46.     CERTCertDBHandle *db;
  47.     SECStatus rv;
  48.     /* Allocate a handle to fill with CERT_OpenCertDB below */
  49.     db = (CERTCertDBHandle *) PORT_ZAlloc (sizeof(CERTCertDBHandle));
  50.     if (db == NULL) 
  51.         {
  52. SECU_PrintError(progName, "unable to get database handle");
  53. return NULL;
  54.         }
  55.     rv = CERT_OpenCertDB (db, readOnly, certDBNameCallback, NULL);
  56.     if (rv) 
  57.         {
  58. SECU_PrintError(progName, "could not open certificate database");
  59. if (db) PORT_Free (db);
  60. return NULL;
  61.         }
  62.      else
  63.         {
  64. CERT_SetDefaultCertDB(db);
  65.         }
  66.     return db;
  67. }
  68. /***********************************************************
  69.  * Nasty hackish function definitions
  70.  */
  71. long *mozilla_event_queue = 0;
  72. #ifndef XP_WIN
  73. char *XP_GetString (int i)
  74. {
  75.   return SECU_ErrorStringRaw ((int16) i);
  76. }
  77. #endif
  78. void FE_SetPasswordEnabled()
  79. {
  80. }
  81. void /*MWContext*/ *FE_GetInitContext (void)
  82. {
  83.   return 0;
  84. }
  85. void /*MWContext*/ *XP_FindSomeContext()
  86. {
  87.   /* No windows context in command tools */
  88.   return NULL;
  89. }
  90. void ET_moz_CallFunction()
  91. {
  92. }
  93. /*
  94.  *  R e m o v e A l l A r c
  95.  *
  96.  *  Remove .arc directories that are lingering
  97.  *  from a previous run of signtool.
  98.  *
  99.  */
  100. int
  101. RemoveAllArc(char *tree)
  102. {
  103. PRDir *dir;
  104. PRDirEntry *entry;
  105. char *archive=NULL;
  106. int retval = 0;
  107. dir = PR_OpenDir (tree);
  108. if (!dir) return -1;
  109. for (entry = PR_ReadDir (dir,0); entry; entry = PR_ReadDir (dir,0)) {
  110. if(entry->name[0] == '.') {
  111. continue;
  112. }
  113. if(archive) PR_Free(archive);
  114. archive = PR_smprintf("%s/%s", tree, entry->name);
  115.     if (PL_strcaserstr (entry->name, ".arc")
  116. == (entry->name + strlen(entry->name) - 4) ) {
  117. if(verbosity >= 0) {
  118. PR_fprintf(outputFD, "removing: %sn", archive);
  119. }
  120. if(rm_dash_r(archive)) {
  121. PR_fprintf(errorFD, "Error removing %sn", archive);
  122. errorCount++;
  123. retval = -1;
  124. goto finish;
  125. }
  126. } else if(is_dir(archive)) {
  127. if(RemoveAllArc(archive)) {
  128. retval = -1;
  129. goto finish;
  130. }
  131. }
  132. }
  133. finish:
  134. PR_CloseDir (dir);
  135. if(archive) PR_Free(archive);
  136. return retval;
  137. }
  138. /*
  139.  *  r m _ d a s h _ r
  140.  *
  141.  *  Remove a file, or a directory recursively.
  142.  *
  143.  */
  144. int rm_dash_r (char *path)
  145. {
  146. PRDir *dir;
  147. PRDirEntry *entry;
  148. PRFileInfo fileinfo;
  149. char filename[FNSIZE];
  150. if(PR_GetFileInfo(path, &fileinfo) != PR_SUCCESS) {
  151. /*fprintf(stderr, "Error: Unable to access %sn", filename);*/
  152. return -1;
  153. }
  154. if(fileinfo.type == PR_FILE_DIRECTORY) {
  155. dir = PR_OpenDir(path);
  156. if(!dir) {
  157. PR_fprintf(errorFD, "Error: Unable to open directory %s.n", path);
  158. errorCount++;
  159. return -1;
  160. }
  161. /* Recursively delete all entries in the directory */
  162. while((entry = PR_ReadDir(dir, PR_SKIP_BOTH)) != NULL) {
  163. sprintf(filename, "%s/%s", path, entry->name);
  164. if(rm_dash_r(filename)) return -1;
  165. }
  166. if(PR_CloseDir(dir) != PR_SUCCESS) {
  167. PR_fprintf(errorFD, "Error: Could not close %s.n", path);
  168. errorCount++;
  169. return -1;
  170. }
  171. /* Delete the directory itself */
  172. if(PR_RmDir(path) != PR_SUCCESS) {
  173. PR_fprintf(errorFD, "Error: Unable to delete %sn", path);
  174. errorCount++;
  175. return -1;
  176. }
  177. } else {
  178. if(PR_Delete(path) != PR_SUCCESS) {
  179. PR_fprintf(errorFD, "Error: Unable to delete %sn", path);
  180. errorCount++;
  181. return -1;
  182. }
  183. }
  184. return 0;
  185. }
  186. /*
  187.  *  u s a g e 
  188.  * 
  189.  *  Print some useful help information
  190.  *
  191.  */
  192. void
  193. usage (void)
  194. {
  195.   PR_fprintf(outputFD, "n");
  196.   PR_fprintf(outputFD, "%s %s - a signing tool for jar filesn", LONG_PROGRAM_NAME, VERSION);
  197.   PR_fprintf(outputFD, "n");
  198.   PR_fprintf(outputFD, "Usage:  %s [options] directory-tree nn", PROGRAM_NAME);
  199.   PR_fprintf(outputFD, "    -b"basename"ttbasename of .sf, .rsa files for signingn");
  200.   PR_fprintf(outputFD, "    -c#ttttCompression level, 0-9, 0=nonen");
  201.   PR_fprintf(outputFD, "    -d"certificate directory"tcontains cert*.db and key*.dbn");
  202.   PR_fprintf(outputFD, "    -e".ext"tttsign only files with this extensionn");
  203.   PR_fprintf(outputFD, "    -f"filename"tttread commands from filen");
  204.   PR_fprintf(outputFD, "    -G"nickname"ttcreate object-signing cert with this nicknamen");
  205.   PR_fprintf(outputFD, "    -i"installer script"tassign installer javascriptn");
  206.   PR_fprintf(outputFD, "    -j"javascript directory"tsign javascript files in this subtreen");
  207.   PR_fprintf(outputFD, "    -Jttttdirectory contains HTML files. Javascript willn"
  208. "ttttbe extracted and signed.n");
  209.   PR_fprintf(outputFD, "    -k"cert nickname"ttsign with this certificaten");
  210.   PR_fprintf(outputFD, "    --leavearctttdo not delete .arc directories createdn"
  211. "ttttby -J optionn");
  212.   PR_fprintf(outputFD, "    -m"metafile"ttinclude custom meta-informationn");
  213.   PR_fprintf(outputFD, "    --norecursetttdo not operate on subdirectoriesn");
  214.   PR_fprintf(outputFD, "    -ottttoptimize - omit optional headersn");
  215.   PR_fprintf(outputFD, "    --outfile "filename"tredirect output to filen");
  216.   PR_fprintf(outputFD, "    -p"password"ttfor password on command line (insecure)n");
  217.   PR_fprintf(outputFD, "    -s keysizetttkeysize in bits of generated certn");
  218.   PR_fprintf(outputFD, "    -t tokentttname of token on which to generate certn");
  219.   PR_fprintf(outputFD, "    --verbosity #ttSet amount of debugging information to generate.n"
  220. "ttttLower number means less output, 0 is default.n");
  221.   PR_fprintf(outputFD, "    -x"name"tttdirectory or filename to excluden");
  222.   PR_fprintf(outputFD, "    -zttttomit signing time from signaturen");
  223.   PR_fprintf(outputFD, "    -Z"jarfile"tttcreate JAR file with the given name.n"
  224.   "tttt(Default compression level is 6.)n");
  225.   PR_fprintf(outputFD, "n");
  226.   PR_fprintf(outputFD, "%s -ln", PROGRAM_NAME);
  227.   PR_fprintf(outputFD, "  lists the signing certificates in your databasen");
  228.   PR_fprintf(outputFD, "n");
  229.   PR_fprintf(outputFD, "%s -Ln", PROGRAM_NAME);
  230.   PR_fprintf(outputFD, "  lists all certificates in your database, marks object-signing certificatesn");
  231.   PR_fprintf(outputFD, "n");
  232.   PR_fprintf(outputFD, "%s -Mn", PROGRAM_NAME);
  233.   PR_fprintf(outputFD, "  lists the PKCS #11 modules available to %sn", PROGRAM_NAME);
  234.   PR_fprintf(outputFD, "n");
  235.   PR_fprintf(outputFD, "%s -v file.jarn", PROGRAM_NAME);
  236.   PR_fprintf(outputFD, "  show the contents of the specified jar filen");
  237.   PR_fprintf(outputFD, "n");
  238.   PR_fprintf(outputFD, "%s -w file.jarn", PROGRAM_NAME);
  239.   PR_fprintf(outputFD, "  if valid, tries to tell you who signed the jar filen");
  240.   PR_fprintf(outputFD, "n");
  241.   PR_fprintf(outputFD, "For more details, visitn");
  242.   PR_fprintf(outputFD, 
  243. "  http://developer.netscape.com/library/documentation/signedobj/signtool/n");
  244.   exit (0);
  245. }
  246. /*
  247.  *  p r i n t _ e r r o r
  248.  *
  249.  *  For the undocumented -E function. If an older version
  250.  *  of communicator gives you a numeric error, we can see what
  251.  *  really happened without doing hex math.
  252.  *
  253.  */
  254. void
  255. print_error (int err)
  256. {
  257.   PR_fprintf(errorFD, "Error %d: %sn", err, JAR_get_error (err));
  258. errorCount++;
  259.   give_help (err);
  260. }
  261. /*
  262.  *  o u t _ o f _ m e m o r y
  263.  *
  264.  *  Out of memory, exit Signtool.
  265.  * 
  266.  */
  267. void
  268. out_of_memory (void)
  269. {
  270.   PR_fprintf(errorFD, "%s: out of memoryn", PROGRAM_NAME);
  271. errorCount++;
  272.   exit (ERRX);
  273. }
  274. /*
  275.  *  V e r i f y C e r t D i r
  276.  *
  277.  *  Validate that the specified directory
  278.  *  contains a certificate database
  279.  *
  280.  */
  281. void
  282. VerifyCertDir(char *dir, char *keyName)
  283. {
  284.   char fn [FNSIZE];
  285.   sprintf (fn, "%s/cert7.db", dir);
  286.   if (PR_Access (fn, PR_ACCESS_EXISTS))
  287.     {
  288.     PR_fprintf(errorFD, "%s: No certificate database in "%s"n", PROGRAM_NAME,
  289. dir);
  290.     PR_fprintf(errorFD, "%s: Check the -d arguments that you gaven",
  291. PROGRAM_NAME);
  292. errorCount++;
  293.     exit (ERRX);
  294.     }
  295. if(verbosity >= 0) {
  296. PR_fprintf(outputFD, "using certificate directory: %sn", dir);
  297. }
  298.   if (keyName == NULL)
  299.     return;
  300.   /* if the user gave the -k key argument, verify that 
  301.      a key database already exists */
  302.   sprintf (fn, "%s/key3.db", dir);
  303.   if (PR_Access (fn, PR_ACCESS_EXISTS))
  304.     {
  305.     PR_fprintf(errorFD, "%s: No private key database in "%s"n", PROGRAM_NAME,
  306. dir);
  307.     PR_fprintf(errorFD, "%s: Check the -d arguments that you gaven",
  308. PROGRAM_NAME);
  309. errorCount++;
  310.     exit (ERRX);
  311.     }
  312. }
  313. /*
  314.  *  f o r e a c h 
  315.  * 
  316.  *  A recursive function to loop through all names in
  317.  *  the specified directory, as well as all subdirectories.
  318.  *
  319.  *  FIX: Need to see if all platforms allow multiple
  320.  *  opendir's to be called.
  321.  *
  322.  */
  323. int
  324. foreach(char *dirname, char *prefix, 
  325.        int (*fn)(char *relpath, char *basedir, char *reldir, char *filename,
  326. void* arg),
  327. PRBool recurse, PRBool includeDirs, void *arg) {
  328. char newdir [FNSIZE];
  329. int retval = 0;
  330. PRDir *dir;
  331. PRDirEntry *entry;
  332. strcpy (newdir, dirname);
  333. if (*prefix) {
  334. strcat (newdir, "/");
  335. strcat (newdir, prefix);
  336. }
  337. dir = PR_OpenDir (newdir);
  338. if (!dir) return -1;
  339. for (entry = PR_ReadDir (dir,0); entry; entry = PR_ReadDir (dir,0)) {
  340. if (*entry->name == '.' || *entry->name == '#')
  341. continue;
  342. /* can't sign self */
  343. if (!strcmp (entry->name, "META-INF"))
  344. continue;
  345. /* -x option */
  346. if (PL_HashTableLookup(excludeDirs, entry->name))
  347. continue;
  348. strcpy (newdir, dirname);
  349. if (*dirname)
  350. strcat (newdir, "/");
  351. if (*prefix) {
  352. strcat (newdir, prefix);
  353. strcat (newdir, "/");
  354. }
  355. strcat (newdir, entry->name);
  356. if(!is_dir(newdir) || includeDirs) {
  357. char newpath [FNSIZE];
  358. strcpy (newpath, prefix);
  359. if (*newpath)
  360. strcat (newpath, "/");
  361. strcat (newpath, entry->name);
  362. if( (*fn) (newpath, dirname, prefix, (char *) entry->name, arg)) {
  363. retval = -1;
  364. break;
  365. }
  366. }
  367. if (is_dir (newdir)) {
  368. if(recurse) {
  369. char newprefix [FNSIZE];
  370. strcpy (newprefix, prefix);
  371. if (*newprefix) {
  372. strcat (newprefix, "/");
  373. }
  374. strcat (newprefix, entry->name);
  375. if(foreach (dirname, newprefix, fn, recurse, includeDirs,arg)) {
  376. retval = -1;
  377. break;
  378. }
  379. }
  380. }
  381. }
  382. PR_CloseDir (dir);
  383. return retval;
  384. }
  385. /*
  386.  *  i s _ d i r
  387.  *
  388.  *  Return 1 if file is a directory.
  389.  *  Wonder if this runs on a mac, trust not.
  390.  *
  391.  */
  392. static int is_dir (char *filename)
  393. {
  394. PRFileInfo finfo;
  395. if( PR_GetFileInfo(filename, &finfo) != PR_SUCCESS ) {
  396. printf("Unable to get information about %sn", filename);
  397. return 0;
  398. }
  399. return ( finfo.type == PR_FILE_DIRECTORY );
  400. }
  401. /*
  402.  *  p a s s w o r d _ h a r d c o d e 
  403.  *
  404.  *  A function to use the password passed in the -p(password) argument
  405.  *  of the command line. This is only to be used for build & testing purposes,
  406.  *  as it's extraordinarily insecure. 
  407.  *
  408.  *  After use once, null it out otherwise PKCS11 calls us forever.
  409.  *
  410.  */
  411. SECItem *
  412. password_hardcode(void *arg, SECKEYKeyDBHandle *handle)
  413. {
  414.   SECItem *pw = NULL;
  415.   if (password) {
  416.     pw = SECITEM_AllocItem(NULL, NULL, PL_strlen(password));
  417.     pw->data = PL_strdup(password);
  418.     password = NULL;
  419.   }
  420.   return pw;
  421. }
  422. char *
  423. pk11_password_hardcode(PK11SlotInfo *slot, PRBool retry, void *arg)
  424. {
  425.   char *pw;
  426.   pw = password ? PORT_Strdup (password) : NULL;
  427.   password = NULL;
  428.   return pw;
  429. }
  430. /************************************************************************
  431.  *
  432.  * c e r t D B N a m e C a l l b a c k
  433.  */
  434. static char *
  435. certDBNameCallback(void *arg, int dbVersion)
  436. {
  437.     char *fnarg;
  438.     char *dir;
  439.     char *filename;
  440.     
  441.     dir = SECU_ConfigDirectory (NULL);
  442.     switch ( dbVersion ) {
  443.       case 7:
  444.         fnarg = "7";
  445.         break;
  446.       case 6:
  447. fnarg = "6";
  448. break;
  449.       case 5:
  450. fnarg = "5";
  451. break;
  452.       case 4:
  453.       default:
  454. fnarg = "";
  455. break;
  456.     }
  457.     filename = PR_smprintf("%s/cert%s.db", dir, fnarg);
  458.     return(filename);
  459. }
  460. /***************************************************************
  461.  *
  462.  * s e c E r r o r S t r i n g
  463.  *
  464.  * Returns an error string corresponding to the given error code.
  465.  * Doesn't cover all errors; returns a default for many.
  466.  * Returned string is only valid until the next call of this function.
  467.  */
  468. const char*
  469. secErrorString(long code)
  470. {
  471. static char errstring[80]; /* dynamically constructed error string */
  472. char *c; /* the returned string */
  473. switch(code) {
  474. case SEC_ERROR_IO: c = "io error";
  475. break;
  476. case SEC_ERROR_LIBRARY_FAILURE: c = "security library failure";
  477. break;
  478. case SEC_ERROR_BAD_DATA: c = "bad data";
  479. break;
  480. case SEC_ERROR_OUTPUT_LEN: c = "output length";
  481. break;
  482. case SEC_ERROR_INPUT_LEN: c = "input length";
  483. break;
  484. case SEC_ERROR_INVALID_ARGS: c = "invalid args";
  485. break;
  486. case SEC_ERROR_EXPIRED_CERTIFICATE: c = "expired certificate";
  487. break;
  488. case SEC_ERROR_REVOKED_CERTIFICATE: c = "revoked certificate";
  489. break;
  490. case SEC_ERROR_INADEQUATE_KEY_USAGE: c = "inadequate key usage";
  491. break;
  492. case SEC_ERROR_INADEQUATE_CERT_TYPE: c = "inadequate certificate type";
  493. break;
  494. case SEC_ERROR_UNTRUSTED_CERT: c = "untrusted cert";
  495. break;
  496. case SEC_ERROR_NO_KRL: c = "no key revocation list";
  497. break;
  498. case SEC_ERROR_KRL_BAD_SIGNATURE: c = "key revocation list: bad signature";
  499. break;
  500. case SEC_ERROR_KRL_EXPIRED: c = "key revocation list expired";
  501. break;
  502. case SEC_ERROR_REVOKED_KEY: c = "revoked key";
  503. break;
  504. case SEC_ERROR_CRL_BAD_SIGNATURE:
  505. c = "certificate revocation list: bad signature";
  506. break;
  507. case SEC_ERROR_CRL_EXPIRED: c = "certificate revocation list expired";
  508. break;
  509. case SEC_ERROR_CRL_NOT_YET_VALID:
  510. c = "certificate revocation list not yet valid";
  511. break;
  512. case SEC_ERROR_UNKNOWN_ISSUER: c = "unknown issuer";
  513. break;
  514. case SEC_ERROR_EXPIRED_ISSUER_CERTIFICATE: c = "expired issuer certificate";
  515. break;
  516. case SEC_ERROR_BAD_SIGNATURE: c = "bad signature";
  517. break;
  518. case SEC_ERROR_BAD_KEY: c = "bad key";
  519. break;
  520. case SEC_ERROR_NOT_FORTEZZA_ISSUER: c = "not fortezza issuer";
  521. break;
  522. case SEC_ERROR_CA_CERT_INVALID:
  523. c = "Certificate Authority certificate invalid";
  524. break;
  525. case SEC_ERROR_EXTENSION_NOT_FOUND: c = "extension not found";
  526. break;
  527. case SEC_ERROR_CERT_NOT_IN_NAME_SPACE: c = "certificate not in name space";
  528. break;
  529. case SEC_ERROR_UNTRUSTED_ISSUER: c = "untrusted issuer";
  530. break;
  531. default:
  532. sprintf(errstring, "security error %ld", code);
  533. c = errstring;
  534. break;
  535. }
  536. return c;
  537. }
  538. /***************************************************************
  539.  *
  540.  * d i s p l a y V e r i f y L o g
  541.  *
  542.  * Prints the log of a cert verification.
  543.  */
  544. void
  545. displayVerifyLog(CERTVerifyLog *log)
  546. {
  547. CERTVerifyLogNode *node;
  548. CERTCertificate *cert;
  549. char *name;
  550. if( !log  || (log->count <= 0) ) {
  551. return;
  552. }
  553. for(node = log->head; node != NULL; node = node->next) {
  554. if( !(cert = node->cert) ) {
  555. continue;
  556. }
  557. /* Get a name for this cert */
  558. if(cert->nickname != NULL) {
  559. name = cert->nickname;
  560. } else if(cert->emailAddr != NULL) {
  561. name = cert->emailAddr;
  562. } else {
  563. name = cert->subjectName;
  564. }
  565. printf( "%s%s:n",
  566. name,
  567. (node->depth > 0) ? " [Certificate Authority]" : ""
  568. );
  569. printf("t%sn", secErrorString(node->error));
  570. }
  571. }
  572. /*
  573.  *  J a r L i s t M o d u l e s
  574.  *
  575.  *  Print a list of the PKCS11 modules that are
  576.  *  available. This is useful for smartcard people to
  577.  *  make sure they have the drivers loaded.
  578.  *
  579.  */
  580. void
  581. JarListModules(void)
  582. {
  583.   int i;
  584.   int count = 0;
  585.   SECMODModuleList *modules = NULL;
  586.   static SECMODListLock *moduleLock = NULL;
  587.   SECMODModuleList *mlp;
  588.   modules = SECMOD_GetDefaultModuleList();
  589.   if (modules == NULL)
  590.     {
  591.     PR_fprintf(errorFD, "%s: Can't get module listn", PROGRAM_NAME);
  592. errorCount++;
  593.     exit (ERRX);
  594.     }
  595.   if ((moduleLock = SECMOD_NewListLock()) == NULL)
  596.     {
  597.     /* this is the wrong text */
  598.     PR_fprintf(errorFD, "%s: unable to acquire lock on module listn",
  599. PROGRAM_NAME);
  600. errorCount++;
  601.     exit (ERRX);
  602.     }
  603.   SECMOD_GetReadLock (moduleLock);
  604.   PR_fprintf(outputFD, "nListing of PKCS11 modulesn");
  605.   PR_fprintf(outputFD, "-----------------------------------------------n");
  606.  
  607.   for (mlp = modules; mlp != NULL; mlp = mlp->next) 
  608.     {
  609.     count++;
  610.     PR_fprintf(outputFD, "%3d. %sn", count, mlp->module->commonName);
  611.     if (mlp->module->internal)
  612.       PR_fprintf(outputFD, "          (this module is internally loaded)n");
  613.     else
  614.       PR_fprintf(outputFD, "          (this is an external module)n");
  615.     if (mlp->module->dllName)
  616.       PR_fprintf(outputFD, "          DLL name: %sn", mlp->module->dllName);
  617.     if (mlp->module->slotCount == 0)
  618.       PR_fprintf(outputFD, "          slots: There are no slots attached to this modulen");
  619.     else
  620.       PR_fprintf(outputFD, "          slots: %d slots attachedn", mlp->module->slotCount);
  621.     if (mlp->module->loaded == 0)
  622.       PR_fprintf(outputFD, "          status: Not loadedn");
  623.     else
  624.       PR_fprintf(outputFD, "          status: loadedn");
  625.     for (i = 0; i < mlp->module->slotCount; i++) 
  626.       {
  627.       PK11SlotInfo *slot = mlp->module->slots[i];
  628.       PR_fprintf(outputFD, "n");
  629.       PR_fprintf(outputFD, "    slot: %sn", PK11_GetSlotName(slot));
  630.       PR_fprintf(outputFD, "   token: %sn", PK11_GetTokenName(slot));
  631.       }
  632.     }
  633.   PR_fprintf(outputFD, "-----------------------------------------------n");
  634.   if (count == 0)
  635.     PR_fprintf(outputFD,
  636. "Warning: no modules were found (should have at least one)n");
  637.   SECMOD_ReleaseReadLock (moduleLock);
  638. }
  639. /**********************************************************************
  640.  * c h o p
  641.  *
  642.  * Eliminates leading and trailing whitespace.  Returns a pointer to the 
  643.  * beginning of non-whitespace, or an empty string if it's all whitespace.
  644.  */
  645. char*
  646. chop(char *str)
  647. {
  648. char *start, *end;
  649. if(str) {
  650. start = str;
  651. /* Nip leading whitespace */
  652. while(isspace(*start)) {
  653. start++;
  654. }
  655. /* Nip trailing whitespace */
  656. if(strlen(start) > 0) {
  657. end = start + strlen(start) - 1;
  658. while(isspace(*end) && end > start) {
  659. end--;
  660. }
  661. *(end+1) = '';
  662. }
  663. return start;
  664. } else {
  665. return NULL;
  666. }
  667. }
  668. /***********************************************************************
  669.  *
  670.  * F a t a l E r r o r
  671.  *
  672.  * Outputs an error message and bails out of the program.
  673.  */
  674. void
  675. FatalError(char *msg)
  676. {
  677. if(!msg) msg = "";
  678. PR_fprintf(errorFD, "FATAL ERROR: %sn", msg);
  679. errorCount++;
  680. exit(ERRX);
  681. }
  682. /*************************************************************************
  683.  *
  684.  * I n i t C r y p t o
  685.  */
  686. int
  687. InitCrypto(char *cert_dir, PRBool readOnly)
  688. {
  689.   SECStatus rv;
  690.   static int prior = 0;
  691. PK11SlotInfo *slotinfo;
  692.   CERTCertDBHandle *db;
  693. if (prior == 0) {
  694. /* some functions such as OpenKeyDB expect this path to be
  695.  * implicitly set prior to calling */
  696. SECU_ConfigDirectory (cert_dir);
  697. if ((rv = SECU_PKCS11Init(readOnly)) != SECSuccess) {
  698. PR_fprintf(errorFD, "%s: Unable to initialize PKCS11, code %dn",
  699. PROGRAM_NAME, rv);
  700. errorCount++;
  701. exit (ERRX);
  702. }
  703. SEC_Init();
  704. /* Been there done that */
  705. prior++;
  706. /* open cert database and set the default certificate DB */
  707. db = OpenCertDB(readOnly); 
  708. if (db == NULL) return -1;
  709. CERT_SetDefaultCertDB (db);
  710. if(password) {
  711. PK11_SetPasswordFunc(pk11_password_hardcode);
  712. /* Must login to FIPS before you do anything else */
  713. if(PK11_IsFIPS()) {
  714. slotinfo = PK11_GetInternalSlot();
  715. if(!slotinfo) {
  716. fprintf(stderr, "%s: Unable to get PKCS #11 Internal Slot."
  717.   "n", PROGRAM_NAME);
  718. return -1;
  719. }
  720. if(PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
  721.   NULL /*wincx*/) != SECSuccess) {
  722. fprintf(stderr, "%s: Unable to authenticate to %s.n",
  723. PROGRAM_NAME, PK11_GetSlotName(slotinfo));
  724. return -1;
  725. }
  726. }
  727. /* Make sure there is a password set on the internal key slot */
  728. slotinfo = PK11_GetInternalKeySlot();
  729. if(!slotinfo) {
  730. fprintf(stderr, "%s: Unable to get PKCS #11 Internal Key Slot."
  731.   "n", PROGRAM_NAME);
  732. return -1;
  733. }
  734. if(PK11_NeedUserInit(slotinfo)) {
  735. PR_fprintf(errorFD,
  736. "nWARNING: No password set on internal key database.  Most operations will fail."
  737. "nYou must use Communicator to create a password.n");
  738. warningCount++;
  739. }
  740. /* Make sure we can authenticate to the key slot in FIPS mode */
  741. if(PK11_IsFIPS()) {
  742. if(PK11_Authenticate(slotinfo, PR_FALSE /*loadCerts*/,
  743.   NULL /*wincx*/) != SECSuccess) {
  744. fprintf(stderr, "%s: Unable to authenticate to %s.n",
  745. PROGRAM_NAME, PK11_GetSlotName(slotinfo));
  746. return -1;
  747. }
  748. }
  749. }
  750. return 0;
  751. }
  752. /* Windows foolishness is now in the secutil lib */
  753. /*****************************************************************
  754.  *  g e t _ d e f a u l t _ c e r t _ d i r
  755.  *
  756.  *  Attempt to locate a certificate directory.
  757.  *  Failing that, complain that the user needs to
  758.  *  use the -d(irectory) parameter.
  759.  *
  760.  */
  761. char *get_default_cert_dir (void)
  762. {
  763.   char *home;
  764.   char *cd = NULL;
  765.   static char db [FNSIZE];
  766. #ifdef XP_UNIX
  767.   home = getenv ("HOME");
  768.   if (home && *home)
  769.     {
  770.     sprintf (db, "%s/.netscape", home);
  771.     cd = db;
  772.     }
  773. #endif
  774. #ifdef XP_PC
  775.   FILE *fp;
  776.   /* first check the environment override */
  777.   home = getenv ("JAR_HOME");
  778.   if (home && *home)
  779.     {
  780.     sprintf (db, "%s/cert7.db", home);
  781.     if ((fp = fopen (db, "r")) != NULL)
  782.       {
  783.       fclose (fp);
  784.       cd = home;
  785.       }
  786.     }
  787.   /* try the old navigator directory */
  788.   if (cd == NULL)
  789.     {
  790.     home = "c:/Program Files/Netscape/Navigator";
  791.     sprintf (db, "%s/cert7.db", home);
  792.     if ((fp = fopen (db, "r")) != NULL)
  793.       {
  794.       fclose (fp);
  795.       cd = home;
  796.       }
  797.     }
  798.   /* Try the current directory, I wonder if this
  799.      is really a good idea. Remember, Windows only.. */
  800.   if (cd == NULL)
  801.     {
  802.     home = ".";
  803.     sprintf (db, "%s/cert7.db", home);
  804.     if ((fp = fopen (db, "r")) != NULL)
  805.       {
  806.       fclose (fp);
  807.       cd = home;
  808.       }
  809.     }
  810. #endif
  811.   if (!cd)
  812.     {
  813.     PR_fprintf(errorFD,
  814. "You must specify the location of your certificate directoryn");
  815.     PR_fprintf(errorFD,
  816. "with the -d option. Example: -d ~/.netscape in many cases with Unix.n");
  817. errorCount++;
  818.     exit (ERRX);
  819.     }
  820.   return cd;
  821. }
  822. /************************************************************************
  823.  * g i v e _ h e l p
  824.  */
  825. void give_help (int status)
  826. {
  827.   if (status == SEC_ERROR_UNKNOWN_ISSUER)
  828.     {
  829.     PR_fprintf(errorFD,
  830. "The Certificate Authority (CA) for this certificaten");
  831.     PR_fprintf(errorFD,
  832. "does not appear to be in your database. You should contactn");
  833.     PR_fprintf(errorFD,
  834. "the organization which issued this certificate to obtainn");
  835.     PR_fprintf(errorFD, "a copy of its CA Certificate.n");
  836.     }
  837. }
  838. /**************************************************************************
  839.  *
  840.  * p r _ f g e t s
  841.  *
  842.  * fgets implemented with NSPR.
  843.  */
  844. char*
  845. pr_fgets(char *buf, int size, PRFileDesc *file)
  846. {
  847. int i;
  848. int status;
  849. char c;
  850. i=0;
  851. while(i < size-1) {
  852. status = PR_Read(file, (void*) &c, 1);
  853. if(status==-1) {
  854. return NULL;
  855. } else if(status==0) {
  856. break;
  857. }
  858. buf[i++] = c;
  859. if(c=='n') {
  860. break;
  861. }
  862. }
  863. buf[i]='';
  864. return buf;
  865. }