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

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. /*
  34.  * p7env -- A command to create a pkcs7 enveloped data.
  35.  *
  36.  * $Id: p7env.c,v 1.1 2000/03/31 20:12:23 relyea%netscape.com Exp $
  37.  */
  38. #include "nspr.h"
  39. #include "secutil.h"
  40. #include "plgetopt.h"
  41. #include "secpkcs7.h"
  42. #include "cert.h"
  43. #include "certdb.h"
  44. #include "cdbhdl.h"
  45. #if defined(XP_UNIX)
  46. #include <unistd.h>
  47. #endif
  48. #include <stdio.h>
  49. #include <string.h>
  50. #if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
  51. extern int fread(char *, size_t, size_t, FILE*);
  52. extern int fwrite(char *, size_t, size_t, FILE*);
  53. extern int fprintf(FILE *, char *, ...);
  54. #endif
  55. extern void SEC_Init(void); /* XXX */
  56. static void
  57. Usage(char *progName)
  58. {
  59.     fprintf(stderr,
  60.     "Usage:  %s -r recipient [-d dbdir] [-i input] [-o output]n",
  61.     progName);
  62.     fprintf(stderr, "%-20s Nickname of cert to use for encryptionn",
  63.     "-r recipient");
  64.     fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)n",
  65.     "-d dbdir");
  66.     fprintf(stderr, "%-20s Define an input file to use (default is stdin)n",
  67.     "-i input");
  68.     fprintf(stderr, "%-20s Define an output file to use (default is stdout)n",
  69.     "-o output");
  70.     exit(-1);
  71. }
  72. static CERTCertDBHandle certHandleStatic; /* avoid having to allocate */
  73. static CERTCertDBHandle *
  74. OpenCertDB(char *progName)
  75. {
  76.     CERTCertDBHandle *certHandle;
  77.     SECStatus rv;
  78.     certHandle = &certHandleStatic;
  79.     rv = CERT_OpenCertDB(certHandle, PR_FALSE, SECU_CertDBNameCallback, NULL);
  80.     if (rv != SECSuccess) {
  81.         SECU_PrintError(progName, "could not open cert database");
  82. return NULL;
  83.     }
  84.     return certHandle;
  85. }
  86. struct recipient {
  87.     struct recipient *next;
  88.     char *nickname;
  89.     CERTCertificate *cert;
  90. };
  91. static void
  92. EncryptOut(void *arg, const char *buf, unsigned long len)
  93. {
  94.    FILE *out;
  95.    out = arg; 
  96.    fwrite (buf, len, 1, out);
  97. }
  98. static int
  99. EncryptFile(FILE *outFile, FILE *inFile, struct recipient *recipients,
  100.     char *progName)
  101. {
  102.     SEC_PKCS7ContentInfo *cinfo;
  103.     SEC_PKCS7EncoderContext *ecx;
  104.     struct recipient *rcpt;
  105.     SECStatus rv;
  106.     if (outFile == NULL || inFile == NULL || recipients == NULL)
  107. return -1;
  108.     /* XXX Need a better way to handle that certUsage stuff! */
  109.     /* XXX keysize? */
  110.     cinfo = SEC_PKCS7CreateEnvelopedData (recipients->cert,
  111.   certUsageEmailRecipient,
  112.   NULL, SEC_OID_DES_EDE3_CBC, 0, 
  113.   NULL, NULL);
  114.     if (cinfo == NULL)
  115. return -1;
  116.     for (rcpt = recipients->next; rcpt != NULL; rcpt = rcpt->next) {
  117. rv = SEC_PKCS7AddRecipient (cinfo, rcpt->cert, certUsageEmailRecipient,
  118.     NULL);
  119. if (rv != SECSuccess) {
  120.     SECU_PrintError(progName, "error adding recipient "%s"",
  121.     rcpt->nickname);
  122.     return -1;
  123. }
  124.     }
  125.     ecx = SEC_PKCS7EncoderStart (cinfo, EncryptOut, outFile, NULL);
  126.     if (ecx == NULL)
  127. return -1;
  128.     for (;;) {
  129. char ibuf[1024];
  130. int nb;
  131.  
  132. if (feof(inFile))
  133.     break;
  134. nb = fread(ibuf, 1, sizeof(ibuf), inFile);
  135. if (nb == 0) {
  136.     if (ferror(inFile)) {
  137. PORT_SetError(SEC_ERROR_IO);
  138. rv = SECFailure;
  139.     }
  140.     break;
  141. }
  142. rv = SEC_PKCS7EncoderUpdate(ecx, ibuf, nb);
  143. if (rv != SECSuccess)
  144.     break;
  145.     }
  146.     if (SEC_PKCS7EncoderFinish(ecx, NULL, NULL) != SECSuccess)
  147. rv = SECFailure;
  148.     SEC_PKCS7DestroyContentInfo (cinfo);
  149.     if (rv != SECSuccess)
  150. return -1;
  151.     return 0;
  152. }
  153. int
  154. main(int argc, char **argv)
  155. {
  156.     char *progName;
  157.     FILE *inFile, *outFile;
  158.     char *certName;
  159.     CERTCertDBHandle *certHandle;
  160.     CERTCertificate *cert;
  161.     struct recipient *recipients, *rcpt;
  162.     PLOptState *optstate;
  163.     PLOptStatus status;
  164.     progName = strrchr(argv[0], '/');
  165.     progName = progName ? progName+1 : argv[0];
  166.     inFile = NULL;
  167.     outFile = NULL;
  168.     certName = NULL;
  169.     recipients = NULL;
  170.     rcpt = NULL;
  171.     /*
  172.      * Parse command line arguments
  173.      * XXX This needs to be enhanced to allow selection of algorithms
  174.      * and key sizes (or to look up algorithms and key sizes for each
  175.      * recipient in the magic database).
  176.      */
  177.     optstate = PL_CreateOptState(argc, argv, "d:i:o:r:");
  178.     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
  179. switch (optstate->option) {
  180.   case '?':
  181.     Usage(progName);
  182.     break;
  183.   case 'd':
  184.     SECU_ConfigDirectory(optstate->value);
  185.     break;
  186.   case 'i':
  187.     inFile = fopen(optstate->value, "r");
  188.     if (!inFile) {
  189. fprintf(stderr, "%s: unable to open "%s" for readingn",
  190. progName, optstate->value);
  191. return -1;
  192.     }
  193.     break;
  194.   case 'o':
  195.     outFile = fopen(optstate->value, "w");
  196.     if (!outFile) {
  197. fprintf(stderr, "%s: unable to open "%s" for writingn",
  198. progName, optstate->value);
  199. return -1;
  200.     }
  201.     break;
  202.   case 'r':
  203.     if (rcpt == NULL) {
  204. recipients = rcpt = PORT_Alloc (sizeof(struct recipient));
  205.     } else {
  206. rcpt->next = PORT_Alloc (sizeof(struct recipient));
  207. rcpt = rcpt->next;
  208.     }
  209.     if (rcpt == NULL) {
  210. fprintf(stderr, "%s: unable to allocate recipient structn",
  211. progName);
  212. return -1;
  213.     }
  214.     rcpt->nickname = strdup(optstate->value);
  215.     rcpt->cert = NULL;
  216.     rcpt->next = NULL;
  217.     break;
  218. }
  219.     }
  220.     if (!recipients) Usage(progName);
  221.     if (!inFile) inFile = stdin;
  222.     if (!outFile) outFile = stdout;
  223.     /* Call the libsec initialization routines */
  224.     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
  225.     SECU_PKCS11Init(PR_FALSE);
  226.     SEC_Init();
  227.     /* open cert database */
  228.     certHandle = OpenCertDB(progName);
  229.     if (certHandle == NULL) {
  230. return -1;
  231.     }
  232.     CERT_SetDefaultCertDB(certHandle);
  233.     /* find certs */
  234.     for (rcpt = recipients; rcpt != NULL; rcpt = rcpt->next) {
  235. rcpt->cert = CERT_FindCertByNickname(certHandle, rcpt->nickname);
  236. if (rcpt->cert == NULL) {
  237.     SECU_PrintError(progName,
  238.     "the cert for name "%s" not found in database",
  239.     rcpt->nickname);
  240.     return -1;
  241. }
  242.     }
  243.     if (EncryptFile(outFile, inFile, recipients, progName)) {
  244. SECU_PrintError(progName, "problem encrypting data");
  245. return -1;
  246.     }
  247.     return 0;
  248. }