security/nss/cmd/p7env/p7env.c

Wed, 31 Dec 2014 07:16:47 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 07:16:47 +0100
branch
TOR_BUG_9701
changeset 3
141e0f1194b1
permissions
-rw-r--r--

Revert simplistic fix pending revisit of Mozilla integration attempt.

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this
     3  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 /*
     6  * p7env -- A command to create a pkcs7 enveloped data.
     7  */
     9 #include "nspr.h"
    10 #include "secutil.h"
    11 #include "plgetopt.h"
    12 #include "secpkcs7.h"
    13 #include "cert.h"
    14 #include "certdb.h"
    15 #include "nss.h"
    17 #if defined(XP_UNIX)
    18 #include <unistd.h>
    19 #endif
    21 #include <stdio.h>
    22 #include <string.h>
    24 #if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4))
    25 extern int fread(char *, size_t, size_t, FILE*);
    26 extern int fwrite(char *, size_t, size_t, FILE*);
    27 extern int fprintf(FILE *, char *, ...);
    28 #endif
    31 static void
    32 Usage(char *progName)
    33 {
    34     fprintf(stderr,
    35 	    "Usage:  %s -r recipient [-d dbdir] [-i input] [-o output]\n",
    36 	    progName);
    37     fprintf(stderr, "%-20s Nickname of cert to use for encryption\n",
    38 	    "-r recipient");
    39     fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n",
    40 	    "-d dbdir");
    41     fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n",
    42 	    "-i input");
    43     fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n",
    44 	    "-o output");
    45     exit(-1);
    46 }
    48 struct recipient {
    49     struct recipient *next;
    50     char *nickname;
    51     CERTCertificate *cert;
    52 };
    54 static void
    55 EncryptOut(void *arg, const char *buf, unsigned long len)
    56 {
    57    FILE *out;
    59    out = arg; 
    60    fwrite (buf, len, 1, out);
    61 }
    63 static int
    64 EncryptFile(FILE *outFile, FILE *inFile, struct recipient *recipients,
    65 	    char *progName)
    66 {
    67     SEC_PKCS7ContentInfo *cinfo;
    68     SEC_PKCS7EncoderContext *ecx;
    69     struct recipient *rcpt;
    70     SECStatus rv;
    72     if (outFile == NULL || inFile == NULL || recipients == NULL)
    73 	return -1;
    75     /* XXX Need a better way to handle that certUsage stuff! */
    76     /* XXX keysize? */
    77     cinfo = SEC_PKCS7CreateEnvelopedData (recipients->cert,
    78 					  certUsageEmailRecipient,
    79 					  NULL, SEC_OID_DES_EDE3_CBC, 0, 
    80 					  NULL, NULL);
    81     if (cinfo == NULL)
    82 	return -1;
    84     for (rcpt = recipients->next; rcpt != NULL; rcpt = rcpt->next) {
    85 	rv = SEC_PKCS7AddRecipient (cinfo, rcpt->cert, certUsageEmailRecipient,
    86 				    NULL);
    87 	if (rv != SECSuccess) {
    88 	    SECU_PrintError(progName, "error adding recipient \"%s\"",
    89 			    rcpt->nickname);
    90 	    return -1;
    91 	}
    92     }
    94     ecx = SEC_PKCS7EncoderStart (cinfo, EncryptOut, outFile, NULL);
    95     if (ecx == NULL)
    96 	return -1;
    98     for (;;) {
    99 	char ibuf[1024];
   100 	int nb;
   102 	if (feof(inFile))
   103 	    break;
   104 	nb = fread(ibuf, 1, sizeof(ibuf), inFile);
   105 	if (nb == 0) {
   106 	    if (ferror(inFile)) {
   107 		PORT_SetError(SEC_ERROR_IO);
   108 		rv = SECFailure;
   109 	    }
   110 	    break;
   111 	}
   112 	rv = SEC_PKCS7EncoderUpdate(ecx, ibuf, nb);
   113 	if (rv != SECSuccess)
   114 	    break;
   115     }
   117     if (SEC_PKCS7EncoderFinish(ecx, NULL, NULL) != SECSuccess)
   118 	rv = SECFailure;
   120     SEC_PKCS7DestroyContentInfo (cinfo);
   122     if (rv != SECSuccess)
   123 	return -1;
   125     return 0;
   126 }
   128 int
   129 main(int argc, char **argv)
   130 {
   131     char *progName;
   132     FILE *inFile, *outFile;
   133     char *certName;
   134     CERTCertDBHandle *certHandle;
   135     struct recipient *recipients, *rcpt;
   136     PLOptState *optstate;
   137     PLOptStatus status;
   138     SECStatus rv;
   140     progName = strrchr(argv[0], '/');
   141     progName = progName ? progName+1 : argv[0];
   143     inFile = NULL;
   144     outFile = NULL;
   145     certName = NULL;
   146     recipients = NULL;
   147     rcpt = NULL;
   149     /*
   150      * Parse command line arguments
   151      * XXX This needs to be enhanced to allow selection of algorithms
   152      * and key sizes (or to look up algorithms and key sizes for each
   153      * recipient in the magic database).
   154      */
   155     optstate = PL_CreateOptState(argc, argv, "d:i:o:r:");
   156     while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
   157 	switch (optstate->option) {
   158 	  case '?':
   159 	    Usage(progName);
   160 	    break;
   162 	  case 'd':
   163 	    SECU_ConfigDirectory(optstate->value);
   164 	    break;
   166 	  case 'i':
   167 	    inFile = fopen(optstate->value, "r");
   168 	    if (!inFile) {
   169 		fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
   170 			progName, optstate->value);
   171 		return -1;
   172 	    }
   173 	    break;
   175 	  case 'o':
   176 	    outFile = fopen(optstate->value, "wb");
   177 	    if (!outFile) {
   178 		fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
   179 			progName, optstate->value);
   180 		return -1;
   181 	    }
   182 	    break;
   184 	  case 'r':
   185 	    if (rcpt == NULL) {
   186 		recipients = rcpt = PORT_Alloc (sizeof(struct recipient));
   187 	    } else {
   188 		rcpt->next = PORT_Alloc (sizeof(struct recipient));
   189 		rcpt = rcpt->next;
   190 	    }
   191 	    if (rcpt == NULL) {
   192 		fprintf(stderr, "%s: unable to allocate recipient struct\n",
   193 			progName);
   194 		return -1;
   195 	    }
   196 	    rcpt->nickname = strdup(optstate->value);
   197 	    rcpt->cert = NULL;
   198 	    rcpt->next = NULL;
   199 	    break;
   200 	}
   201     }
   203     if (!recipients) Usage(progName);
   205     if (!inFile) inFile = stdin;
   206     if (!outFile) outFile = stdout;
   208     /* Call the NSS initialization routines */
   209     PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
   210     rv = NSS_Init(SECU_ConfigDirectory(NULL));
   211     if (rv != SECSuccess) {
   212     	SECU_PrintPRandOSError(progName);
   213 	return -1;
   214     }
   216     /* open cert database */
   217     certHandle = CERT_GetDefaultCertDB();
   218     if (certHandle == NULL) {
   219 	return -1;
   220     }
   222     /* find certs */
   223     for (rcpt = recipients; rcpt != NULL; rcpt = rcpt->next) {
   224 	rcpt->cert = CERT_FindCertByNickname(certHandle, rcpt->nickname);
   225 	if (rcpt->cert == NULL) {
   226 	    SECU_PrintError(progName,
   227 			    "the cert for name \"%s\" not found in database",
   228 			    rcpt->nickname);
   229 	    return -1;
   230 	}
   231     }
   233     if (EncryptFile(outFile, inFile, recipients, progName)) {
   234 	SECU_PrintError(progName, "problem encrypting data");
   235 	return -1;
   236     }
   238     return 0;
   239 }

mercurial