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.

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

mercurial