security/nss/cmd/p7env/p7env.c

changeset 0
6474c204b198
     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 +}

mercurial