1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/security/nss/cmd/p7env/p7env.c Wed Dec 31 06:09:35 2014 +0100 1.3 @@ -0,0 +1,239 @@ 1.4 +/* This Source Code Form is subject to the terms of the Mozilla Public 1.5 + * License, v. 2.0. If a copy of the MPL was not distributed with this 1.6 + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ 1.7 + 1.8 +/* 1.9 + * p7env -- A command to create a pkcs7 enveloped data. 1.10 + */ 1.11 + 1.12 +#include "nspr.h" 1.13 +#include "secutil.h" 1.14 +#include "plgetopt.h" 1.15 +#include "secpkcs7.h" 1.16 +#include "cert.h" 1.17 +#include "certdb.h" 1.18 +#include "nss.h" 1.19 + 1.20 +#if defined(XP_UNIX) 1.21 +#include <unistd.h> 1.22 +#endif 1.23 + 1.24 +#include <stdio.h> 1.25 +#include <string.h> 1.26 + 1.27 +#if (defined(XP_WIN) && !defined(WIN32)) || (defined(__sun) && !defined(SVR4)) 1.28 +extern int fread(char *, size_t, size_t, FILE*); 1.29 +extern int fwrite(char *, size_t, size_t, FILE*); 1.30 +extern int fprintf(FILE *, char *, ...); 1.31 +#endif 1.32 + 1.33 + 1.34 +static void 1.35 +Usage(char *progName) 1.36 +{ 1.37 + fprintf(stderr, 1.38 + "Usage: %s -r recipient [-d dbdir] [-i input] [-o output]\n", 1.39 + progName); 1.40 + fprintf(stderr, "%-20s Nickname of cert to use for encryption\n", 1.41 + "-r recipient"); 1.42 + fprintf(stderr, "%-20s Cert database directory (default is ~/.netscape)\n", 1.43 + "-d dbdir"); 1.44 + fprintf(stderr, "%-20s Define an input file to use (default is stdin)\n", 1.45 + "-i input"); 1.46 + fprintf(stderr, "%-20s Define an output file to use (default is stdout)\n", 1.47 + "-o output"); 1.48 + exit(-1); 1.49 +} 1.50 + 1.51 +struct recipient { 1.52 + struct recipient *next; 1.53 + char *nickname; 1.54 + CERTCertificate *cert; 1.55 +}; 1.56 + 1.57 +static void 1.58 +EncryptOut(void *arg, const char *buf, unsigned long len) 1.59 +{ 1.60 + FILE *out; 1.61 + 1.62 + out = arg; 1.63 + fwrite (buf, len, 1, out); 1.64 +} 1.65 + 1.66 +static int 1.67 +EncryptFile(FILE *outFile, FILE *inFile, struct recipient *recipients, 1.68 + char *progName) 1.69 +{ 1.70 + SEC_PKCS7ContentInfo *cinfo; 1.71 + SEC_PKCS7EncoderContext *ecx; 1.72 + struct recipient *rcpt; 1.73 + SECStatus rv; 1.74 + 1.75 + if (outFile == NULL || inFile == NULL || recipients == NULL) 1.76 + return -1; 1.77 + 1.78 + /* XXX Need a better way to handle that certUsage stuff! */ 1.79 + /* XXX keysize? */ 1.80 + cinfo = SEC_PKCS7CreateEnvelopedData (recipients->cert, 1.81 + certUsageEmailRecipient, 1.82 + NULL, SEC_OID_DES_EDE3_CBC, 0, 1.83 + NULL, NULL); 1.84 + if (cinfo == NULL) 1.85 + return -1; 1.86 + 1.87 + for (rcpt = recipients->next; rcpt != NULL; rcpt = rcpt->next) { 1.88 + rv = SEC_PKCS7AddRecipient (cinfo, rcpt->cert, certUsageEmailRecipient, 1.89 + NULL); 1.90 + if (rv != SECSuccess) { 1.91 + SECU_PrintError(progName, "error adding recipient \"%s\"", 1.92 + rcpt->nickname); 1.93 + return -1; 1.94 + } 1.95 + } 1.96 + 1.97 + ecx = SEC_PKCS7EncoderStart (cinfo, EncryptOut, outFile, NULL); 1.98 + if (ecx == NULL) 1.99 + return -1; 1.100 + 1.101 + for (;;) { 1.102 + char ibuf[1024]; 1.103 + int nb; 1.104 + 1.105 + if (feof(inFile)) 1.106 + break; 1.107 + nb = fread(ibuf, 1, sizeof(ibuf), inFile); 1.108 + if (nb == 0) { 1.109 + if (ferror(inFile)) { 1.110 + PORT_SetError(SEC_ERROR_IO); 1.111 + rv = SECFailure; 1.112 + } 1.113 + break; 1.114 + } 1.115 + rv = SEC_PKCS7EncoderUpdate(ecx, ibuf, nb); 1.116 + if (rv != SECSuccess) 1.117 + break; 1.118 + } 1.119 + 1.120 + if (SEC_PKCS7EncoderFinish(ecx, NULL, NULL) != SECSuccess) 1.121 + rv = SECFailure; 1.122 + 1.123 + SEC_PKCS7DestroyContentInfo (cinfo); 1.124 + 1.125 + if (rv != SECSuccess) 1.126 + return -1; 1.127 + 1.128 + return 0; 1.129 +} 1.130 + 1.131 +int 1.132 +main(int argc, char **argv) 1.133 +{ 1.134 + char *progName; 1.135 + FILE *inFile, *outFile; 1.136 + char *certName; 1.137 + CERTCertDBHandle *certHandle; 1.138 + struct recipient *recipients, *rcpt; 1.139 + PLOptState *optstate; 1.140 + PLOptStatus status; 1.141 + SECStatus rv; 1.142 + 1.143 + progName = strrchr(argv[0], '/'); 1.144 + progName = progName ? progName+1 : argv[0]; 1.145 + 1.146 + inFile = NULL; 1.147 + outFile = NULL; 1.148 + certName = NULL; 1.149 + recipients = NULL; 1.150 + rcpt = NULL; 1.151 + 1.152 + /* 1.153 + * Parse command line arguments 1.154 + * XXX This needs to be enhanced to allow selection of algorithms 1.155 + * and key sizes (or to look up algorithms and key sizes for each 1.156 + * recipient in the magic database). 1.157 + */ 1.158 + optstate = PL_CreateOptState(argc, argv, "d:i:o:r:"); 1.159 + while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) { 1.160 + switch (optstate->option) { 1.161 + case '?': 1.162 + Usage(progName); 1.163 + break; 1.164 + 1.165 + case 'd': 1.166 + SECU_ConfigDirectory(optstate->value); 1.167 + break; 1.168 + 1.169 + case 'i': 1.170 + inFile = fopen(optstate->value, "r"); 1.171 + if (!inFile) { 1.172 + fprintf(stderr, "%s: unable to open \"%s\" for reading\n", 1.173 + progName, optstate->value); 1.174 + return -1; 1.175 + } 1.176 + break; 1.177 + 1.178 + case 'o': 1.179 + outFile = fopen(optstate->value, "wb"); 1.180 + if (!outFile) { 1.181 + fprintf(stderr, "%s: unable to open \"%s\" for writing\n", 1.182 + progName, optstate->value); 1.183 + return -1; 1.184 + } 1.185 + break; 1.186 + 1.187 + case 'r': 1.188 + if (rcpt == NULL) { 1.189 + recipients = rcpt = PORT_Alloc (sizeof(struct recipient)); 1.190 + } else { 1.191 + rcpt->next = PORT_Alloc (sizeof(struct recipient)); 1.192 + rcpt = rcpt->next; 1.193 + } 1.194 + if (rcpt == NULL) { 1.195 + fprintf(stderr, "%s: unable to allocate recipient struct\n", 1.196 + progName); 1.197 + return -1; 1.198 + } 1.199 + rcpt->nickname = strdup(optstate->value); 1.200 + rcpt->cert = NULL; 1.201 + rcpt->next = NULL; 1.202 + break; 1.203 + } 1.204 + } 1.205 + 1.206 + if (!recipients) Usage(progName); 1.207 + 1.208 + if (!inFile) inFile = stdin; 1.209 + if (!outFile) outFile = stdout; 1.210 + 1.211 + /* Call the NSS initialization routines */ 1.212 + PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1); 1.213 + rv = NSS_Init(SECU_ConfigDirectory(NULL)); 1.214 + if (rv != SECSuccess) { 1.215 + SECU_PrintPRandOSError(progName); 1.216 + return -1; 1.217 + } 1.218 + 1.219 + /* open cert database */ 1.220 + certHandle = CERT_GetDefaultCertDB(); 1.221 + if (certHandle == NULL) { 1.222 + return -1; 1.223 + } 1.224 + 1.225 + /* find certs */ 1.226 + for (rcpt = recipients; rcpt != NULL; rcpt = rcpt->next) { 1.227 + rcpt->cert = CERT_FindCertByNickname(certHandle, rcpt->nickname); 1.228 + if (rcpt->cert == NULL) { 1.229 + SECU_PrintError(progName, 1.230 + "the cert for name \"%s\" not found in database", 1.231 + rcpt->nickname); 1.232 + return -1; 1.233 + } 1.234 + } 1.235 + 1.236 + if (EncryptFile(outFile, inFile, recipients, progName)) { 1.237 + SECU_PrintError(progName, "problem encrypting data"); 1.238 + return -1; 1.239 + } 1.240 + 1.241 + return 0; 1.242 +}