summaryrefslogtreecommitdiff
path: root/security/nss/cmd/smimetools/cmsutil.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/nss/cmd/smimetools/cmsutil.c')
-rw-r--r--security/nss/cmd/smimetools/cmsutil.c877
1 files changed, 0 insertions, 877 deletions
diff --git a/security/nss/cmd/smimetools/cmsutil.c b/security/nss/cmd/smimetools/cmsutil.c
deleted file mode 100644
index 094a1d75c..000000000
--- a/security/nss/cmd/smimetools/cmsutil.c
+++ /dev/null
@@ -1,877 +0,0 @@
-/*
- * The contents of this file are subject to the Mozilla Public
- * License Version 1.1 (the "License"); you may not use this file
- * except in compliance with the License. You may obtain a copy of
- * the License at http://www.mozilla.org/MPL/
- *
- * Software distributed under the License is distributed on an "AS
- * IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
- * implied. See the License for the specific language governing
- * rights and limitations under the License.
- *
- * The Original Code is the Netscape security libraries.
- *
- * The Initial Developer of the Original Code is Netscape
- * Communications Corporation. Portions created by Netscape are
- * Copyright (C) 1994-2000 Netscape Communications Corporation. All
- * Rights Reserved.
- *
- * Contributor(s):
- *
- * Alternatively, the contents of this file may be used under the
- * terms of the GNU General Public License Version 2 or later (the
- * "GPL"), in which case the provisions of the GPL are applicable
- * instead of those above. If you wish to allow use of your
- * version of this file only under the terms of the GPL and not to
- * allow others to use your version of this file under the MPL,
- * indicate your decision by deleting the provisions above and
- * replace them with the notice and other provisions required by
- * the GPL. If you do not delete the provisions above, a recipient
- * may use your version of this file under either the MPL or the
- * GPL.
- */
-
-/*
- * cmsutil -- A command to work with CMS data
- *
- * $Id$
- */
-
-#include "nspr.h"
-#include "secutil.h"
-#include "plgetopt.h"
-#include "secpkcs7.h"
-#include "cert.h"
-#include "certdb.h"
-#include "cdbhdl.h"
-#include "secoid.h"
-#include "cms.h"
-#include "smime.h"
-
-#if defined(XP_UNIX)
-#include <unistd.h>
-#endif
-
-#include <stdio.h>
-#include <string.h>
-
-extern void SEC_Init(void); /* XXX */
-
-static SECStatus
-DigestFile(PLArenaPool *poolp, SECItem ***digests, FILE *inFile, SECAlgorithmID **algids)
-{
- NSSCMSDigestContext *digcx;
- int nb;
- char ibuf[4096];
- SECStatus rv;
-
- digcx = NSS_CMSDigestContext_StartMultiple(algids);
- if (digcx == NULL)
- return SECFailure;
-
- for (;;) {
- if (feof(inFile)) break;
- nb = fread(ibuf, 1, sizeof(ibuf), inFile);
- if (nb == 0) {
- if (ferror(inFile)) {
- PORT_SetError(SEC_ERROR_IO);
- NSS_CMSDigestContext_Cancel(digcx);
- return SECFailure;
- }
- /* eof */
- break;
- }
- NSS_CMSDigestContext_Update(digcx, (const unsigned char *)ibuf, nb);
- }
-
- rv = NSS_CMSDigestContext_FinishMultiple(digcx, poolp, digests);
-
- return rv;
-}
-
-
-static void
-Usage(char *progName)
-{
- fprintf(stderr, "Usage: %s [-D|-S|-E] [<options>] [-d dbdir] [-u certusage]\n", progName);
- fprintf(stderr, " -i infile use infile as source of data (default: stdin)\n");
- fprintf(stderr, " -o outfile use outfile as destination of data (default: stdout)\n");
- fprintf(stderr, " -d dbdir key/cert database directory (default: ~/.netscape)\n");
- fprintf(stderr, " -p password use password as key db password (default: prompt)\n");
- fprintf(stderr, " -u certusage set type of certificate usage (default: certUsageEmailSigner)\n");
- fprintf(stderr, "\n");
- fprintf(stderr, " -D decode a CMS message\n");
- fprintf(stderr, " -c content use this detached content\n");
- fprintf(stderr, " -n suppress output of content\n");
- fprintf(stderr, " -h num generate email headers with info about CMS message\n");
- fprintf(stderr, " -S create a CMS signed message\n");
- fprintf(stderr, " -N nick use certificate named \"nick\" for signing\n");
- fprintf(stderr, " -T do not include content in CMS message\n");
- fprintf(stderr, " -G include a signing time attribute\n");
- fprintf(stderr, " -P include a SMIMECapabilities attribute\n");
- fprintf(stderr, " -Y nick include a EncryptionKeyPreference attribute with cert\n");
- fprintf(stderr, " -E create a CMS enveloped message (NYI)\n");
- fprintf(stderr, " -r id,... create envelope for these recipients,\n");
- fprintf(stderr, " where id can be a certificate nickname or email address\n");
- fprintf(stderr, "\nCert usage codes:\n");
- fprintf(stderr, "%-25s 0 - certUsageSSLClient\n", " ");
- fprintf(stderr, "%-25s 1 - certUsageSSLServer\n", " ");
- fprintf(stderr, "%-25s 2 - certUsageSSLServerWithStepUp\n", " ");
- fprintf(stderr, "%-25s 3 - certUsageSSLCA\n", " ");
- fprintf(stderr, "%-25s 4 - certUsageEmailSigner\n", " ");
- fprintf(stderr, "%-25s 5 - certUsageEmailRecipient\n", " ");
- fprintf(stderr, "%-25s 6 - certUsageObjectSigner\n", " ");
- fprintf(stderr, "%-25s 7 - certUsageUserCertImport\n", " ");
- fprintf(stderr, "%-25s 8 - certUsageVerifyCA\n", " ");
- fprintf(stderr, "%-25s 9 - certUsageProtectedObjectSigner\n", " ");
- fprintf(stderr, "%-25s 10 - certUsageStatusResponder\n", " ");
- fprintf(stderr, "%-25s 11 - certUsageAnyCA\n", " ");
-
- exit(-1);
-}
-
-static CERTCertDBHandle certHandleStatic; /* avoid having to allocate */
-
-static CERTCertDBHandle *
-OpenCertDB(char *progName)
-{
- CERTCertDBHandle *certHandle;
- SECStatus rv;
-
- certHandle = &certHandleStatic;
- rv = CERT_OpenCertDB(certHandle, PR_FALSE, SECU_CertDBNameCallback, NULL);
- if (rv != SECSuccess) {
- SECU_PrintError(progName, "could not open cert database");
- return NULL;
- }
-
- return certHandle;
-}
-
-char *
-ownpw(PK11SlotInfo *info, PRBool retry, void *arg)
-{
- char * passwd = NULL;
-
- if ( (!retry) && arg ) {
- passwd = PL_strdup((char *)arg);
- }
-
- return passwd;
-}
-
-struct optionsStr {
- char *password;
- SECCertUsage certUsage;
- CERTCertDBHandle *certHandle;
-};
-
-struct decodeOptionsStr {
- FILE *contentFile;
- int headerLevel;
- PRBool suppressContent;
-};
-
-struct signOptionsStr {
- char *nickname;
- char *encryptionKeyPreferenceNick;
- PRBool signingTime;
- PRBool smimeProfile;
- PRBool detached;
-};
-
-struct envelopeOptionsStr {
- char **recipients;
-};
-
-static int
-decode(FILE *out, FILE *infile, char *progName, struct optionsStr options, struct decodeOptionsStr decodeOptions)
-{
- NSSCMSDecoderContext *dcx;
- NSSCMSMessage *cmsg;
- NSSCMSContentInfo *cinfo;
- NSSCMSSignedData *sigd = NULL;
- NSSCMSEnvelopedData *envd;
- SECAlgorithmID **digestalgs;
- unsigned char buffer[32];
- int nlevels, i, nsigners, j;
- char *signercn;
- NSSCMSSignerInfo *si;
- SECOidTag typetag;
- SECItem **digests;
- PLArenaPool *poolp;
- int nb;
- char ibuf[4096];
- PK11PasswordFunc pwcb;
- void *pwcb_arg;
- SECItem *item;
-
- pwcb = (options.password != NULL) ? ownpw : NULL;
- pwcb_arg = (options.password != NULL) ? (void *)options.password : NULL;
-
- dcx = NSS_CMSDecoder_Start(NULL,
- NULL, NULL, /* content callback */
- pwcb, pwcb_arg, /* password callback */
- NULL, NULL); /* decrypt key callback */
-
- for (;;) {
- if (feof(infile)) break;
- nb = fread(ibuf, 1, sizeof(ibuf), infile);
- if (nb == 0) {
- if (ferror(infile)) {
- fprintf(stderr, "ERROR: file i/o error.\n");
- NSS_CMSDecoder_Cancel(dcx);
- return SECFailure;
- }
- /* eof */
- break;
- }
- (void)NSS_CMSDecoder_Update(dcx, (const char *)ibuf, nb);
- }
- cmsg = NSS_CMSDecoder_Finish(dcx);
- if (cmsg == NULL)
- return -1;
-
- if (decodeOptions.headerLevel >= 0) {
- fprintf(out, "SMIME: ", decodeOptions.headerLevel, i);
- }
-
- nlevels = NSS_CMSMessage_ContentLevelCount(cmsg);
- for (i = 0; i < nlevels; i++) {
- cinfo = NSS_CMSMessage_ContentLevel(cmsg, i);
- typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
-
- if (decodeOptions.headerLevel >= 0)
- fprintf(out, "\tlevel=%d.%d; ", decodeOptions.headerLevel, nlevels - i);
-
- switch (typetag) {
- case SEC_OID_PKCS7_SIGNED_DATA:
- if (decodeOptions.headerLevel >= 0)
- fprintf(out, "type=signedData; ");
- sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo);
- if (sigd == NULL) {
- SECU_PrintError(progName, "problem finding signedData component");
- return -1;
- }
-
- /* if we have a content file, but no digests for this signedData */
- if (decodeOptions.contentFile != NULL && !NSS_CMSSignedData_HasDigests(sigd)) {
- if ((poolp = PORT_NewArena(1024)) == NULL) {
- fprintf(stderr, "Out of memory.\n");
- return -1;
- }
- digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd);
- if (DigestFile (poolp, &digests, decodeOptions.contentFile, digestalgs) != SECSuccess) {
- SECU_PrintError(progName, "problem computing message digest");
- return -1;
- }
- if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, digests) != SECSuccess) {
-
- SECU_PrintError(progName, "problem setting message digests");
- return -1;
- }
- PORT_FreeArena(poolp, PR_FALSE);
- }
-
- /* still no digests? */
- if (!NSS_CMSSignedData_HasDigests(sigd)) {
- SECU_PrintError(progName, "no message digests");
- return -1;
- }
-
- /* find out about signers */
- nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
- if (decodeOptions.headerLevel >= 0)
- fprintf(out, "nsigners=%d; ", nsigners);
- if (nsigners == 0) {
- /* must be a cert transport message */
- } else {
- /* import the certificates */
- if (NSS_CMSSignedData_ImportCerts(sigd, options.certHandle, options.certUsage, PR_FALSE) != SECSuccess) {
- SECU_PrintError(progName, "cert import failed");
- return -1;
- }
-
- for (j = 0; j < nsigners; j++) {
- si = NSS_CMSSignedData_GetSignerInfo(sigd, j);
-
- signercn = NSS_CMSSignerInfo_GetSignerCommonName(si);
- if (signercn == NULL)
- signercn = "";
- if (decodeOptions.headerLevel >= 0)
- fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, signercn);
- (void)NSS_CMSSignedData_VerifySignerInfo(sigd, j, options.certHandle, options.certUsage);
-
- if (decodeOptions.headerLevel >= 0)
- fprintf(out, "signer%d.status=%s; ", j, NSS_CMSUtil_VerificationStatusToString(NSS_CMSSignerInfo_GetVerificationStatus(si)));
- /* XXX what do we do if we don't print headers? */
- }
- }
- break;
- case SEC_OID_PKCS7_ENVELOPED_DATA:
- if (decodeOptions.headerLevel >= 0)
- fprintf(out, "type=envelopedData; ");
- envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo);
- break;
- case SEC_OID_PKCS7_DATA:
- if (decodeOptions.headerLevel >= 0)
- fprintf(out, "type=data; ");
- break;
- default:
- break;
- }
- if (decodeOptions.headerLevel >= 0)
- fprintf(out, "\n");
- }
-
- if (!decodeOptions.suppressContent) {
- if (decodeOptions.contentFile) {
- char buffer[4096];
- size_t nbytes;
- /* detached content: print content file */
- fseek(decodeOptions.contentFile, 0, SEEK_SET);
- while ((nbytes = fread(buffer, 1, sizeof(buffer), decodeOptions.contentFile)) != 0) {
- fwrite(buffer, nbytes, 1, out);
- }
- } else {
- if ((item = NSS_CMSMessage_GetContent(cmsg)) != NULL) {
- fwrite(item->data, item->len, 1, out);
- }
- }
- }
-
- NSS_CMSMessage_Destroy(cmsg);
- return 0;
-}
-
-static void
-writeout(void *arg, const char *buf, unsigned long len)
-{
- FILE *f = (FILE *)arg;
-
- if (f != NULL && buf != NULL)
- (void)fwrite(buf, len, 1, f);
-}
-
-static int
-sign(FILE *out, FILE *infile, char *progName, struct optionsStr options, struct signOptionsStr signOptions)
-{
- NSSCMSEncoderContext *ecx;
- NSSCMSMessage *cmsg;
- NSSCMSContentInfo *cinfo;
- NSSCMSSignedData *sigd;
- NSSCMSSignerInfo *signerinfo;
- int nb;
- char ibuf[4096];
- PK11PasswordFunc pwcb;
- void *pwcb_arg;
- CERTCertificate *cert, *ekpcert;
-
- if (signOptions.nickname == NULL) {
- fprintf(stderr, "ERROR: please indicate the nickname of a certificate to sign with.\n");
- return SECFailure;
- }
-
- if ((cert = CERT_FindCertByNickname(options.certHandle, signOptions.nickname)) == NULL) {
- SECU_PrintError(progName, "the corresponding cert for key \"%s\" does not exist",
- signOptions.nickname);
- return SECFailure;
- }
-
- /*
- * create the message object
- */
- cmsg = NSS_CMSMessage_Create(NULL); /* create a message on its own pool */
- if (cmsg == NULL) {
- fprintf(stderr, "ERROR: cannot create CMS message.\n");
- return SECFailure;
- }
- /*
- * build chain of objects: message->signedData->data
- */
- if ((sigd = NSS_CMSSignedData_Create(cmsg)) == NULL) {
- fprintf(stderr, "ERROR: cannot create CMS signedData object.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
- cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
- if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot attach CMS signedData object.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
-
- cinfo = NSS_CMSSignedData_GetContentInfo(sigd);
- /* we're always passing data in and detaching optionally */
- if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, signOptions.detached) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
-
- /*
- * create & attach signer information
- */
- if ((signerinfo = NSS_CMSSignerInfo_Create(cmsg, cert, SEC_OID_SHA1)) == NULL) {
- fprintf(stderr, "ERROR: cannot create CMS signerInfo object.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
-
- /* we want the cert chain included for this one */
- if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChain, options.certUsage) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot find cert chain.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
-
- if (signOptions.signingTime) {
- if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot add signingTime attribute.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
- }
- if (signOptions.smimeProfile) {
- if (NSS_CMSSignerInfo_AddSMIMECaps(signerinfo) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot add SMIMECaps attribute.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
- }
- if (signOptions.encryptionKeyPreferenceNick) {
- /* get the cert, add it to the message */
- if ((ekpcert = CERT_FindCertByNickname(options.certHandle, signOptions.encryptionKeyPreferenceNick)) == NULL) {
- SECU_PrintError(progName, "the corresponding cert for key \"%s\" does not exist",
- signOptions.encryptionKeyPreferenceNick);
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
- if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert, options.certHandle) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
- if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
- } else {
- /* check signing cert for fitness as encryption cert */
- /* if yes, add signing cert as EncryptionKeyPreference */
- if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, cert, options.certHandle) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot add default SMIMEEncKeyPrefs attribute.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
- }
-
- if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot add CMS signerInfo object.\n");
- NSS_CMSMessage_Destroy(cmsg);
- return SECFailure;
- }
-
- /*
- * do not add signer independent certificates
- */
-
- pwcb = (options.password != NULL) ? ownpw : NULL;
- pwcb_arg = (options.password != NULL) ? (void *)options.password : NULL;
-
- ecx = NSS_CMSEncoder_Start(cmsg,
- writeout, out, /* DER output callback */
- NULL, NULL, /* destination storage */
- pwcb, pwcb_arg, /* password callback */
- NULL, NULL, /* decrypt key callback */
- NULL, NULL); /* detached digests (not used, we feed) */
-
- for (;;) {
- if (feof(infile)) break;
- nb = fread(ibuf, 1, sizeof(ibuf), infile);
- if (nb == 0) {
- if (ferror(infile)) {
- fprintf(stderr, "ERROR: file i/o error.\n");
- NSS_CMSEncoder_Cancel(ecx);
- return SECFailure;
- }
- /* eof */
- break;
- }
- (void)NSS_CMSEncoder_Update(ecx, (const char *)ibuf, nb);
- }
- if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) {
- fprintf(stderr, "ERROR: DER encoding problem.\n");
- return SECFailure;
- }
-
- NSS_CMSMessage_Destroy(cmsg);
- return SECSuccess;
-}
-
-static int
-envelope(FILE *out, FILE *infile, char *progName, struct optionsStr options, struct envelopeOptionsStr envelopeOptions)
-{
- SECStatus retval = SECFailure;
- NSSCMSEncoderContext *ecx;
- NSSCMSMessage *cmsg = NULL;
- NSSCMSContentInfo *cinfo;
- NSSCMSEnvelopedData *envd;
- NSSCMSRecipientInfo *recipientinfo;
- int cnt;
- int nb;
- char ibuf[4096];
- PK11PasswordFunc pwcb;
- void *pwcb_arg;
- CERTCertificate **recipientcerts;
- PLArenaPool *tmppoolp = NULL;
- SECOidTag bulkalgtag;
- int keysize, i;
-
- if ((cnt = NSS_CMSArray_Count(envelopeOptions.recipients)) == 0) {
- fprintf(stderr, "ERROR: please indicate the nickname of a certificate to sign with.\n");
- goto loser;
- }
-
- if ((tmppoolp = PORT_NewArena (1024)) == NULL) {
- fprintf(stderr, "ERROR: out of memory.\n");
- goto loser;
- }
-
- /* XXX find the recipient's certs by email address or nickname */
- if ((recipientcerts = (CERTCertificate **)NSS_CMSArray_Alloc(tmppoolp, cnt)) == NULL) {
- fprintf(stderr, "ERROR: out of memory.\n");
- goto loser;
- }
-
- for (i=0; envelopeOptions.recipients[i] != NULL; i++) {
- if ((recipientcerts[i] = CERT_FindCertByNicknameOrEmailAddr(options.certHandle, envelopeOptions.recipients[i])) == NULL) {
- SECU_PrintError(progName, "cannot find certificate for \"%s\"", envelopeOptions.recipients[i]);
- goto loser;
- }
- }
- recipientcerts[i] = NULL;
-
- /* find a nice bulk algorithm */
- if (NSS_SMIMEUtil_FindBulkAlgForRecipients(recipientcerts, &bulkalgtag, &keysize) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot find common bulk algorithm.\n");
- goto loser;
- }
-
- /*
- * create the message object
- */
- cmsg = NSS_CMSMessage_Create(NULL); /* create a message on its own pool */
- if (cmsg == NULL) {
- fprintf(stderr, "ERROR: cannot create CMS message.\n");
- goto loser;
- }
- /*
- * build chain of objects: message->envelopedData->data
- */
- if ((envd = NSS_CMSEnvelopedData_Create(cmsg, bulkalgtag, keysize)) == NULL) {
- fprintf(stderr, "ERROR: cannot create CMS envelopedData object.\n");
- goto loser;
- }
- cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
- if (NSS_CMSContentInfo_SetContent_EnvelopedData(cmsg, cinfo, envd) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot attach CMS envelopedData object.\n");
- goto loser;
- }
- cinfo = NSS_CMSEnvelopedData_GetContentInfo(envd);
- /* we're always passing data in, so the content is NULL */
- if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
- goto loser;
- }
-
- /*
- * create & attach recipient information
- */
- for (i = 0; recipientcerts[i] != NULL; i++) {
- if ((recipientinfo = NSS_CMSRecipientInfo_Create(cmsg, recipientcerts[i])) == NULL) {
- fprintf(stderr, "ERROR: cannot create CMS recipientInfo object.\n");
- goto loser;
- }
- if (NSS_CMSEnvelopedData_AddRecipient(envd, recipientinfo) != SECSuccess) {
- fprintf(stderr, "ERROR: cannot add CMS recipientInfo object.\n");
- goto loser;
- }
- }
-
- /* we might need a password for diffie hellman key agreement, so set it up... */
- pwcb = (options.password != NULL) ? ownpw : NULL;
- pwcb_arg = (options.password != NULL) ? (void *)options.password : NULL;
-
- ecx = NSS_CMSEncoder_Start(cmsg,
- writeout, out, /* DER output callback */
- NULL, NULL, /* destination storage */
- pwcb, pwcb_arg, /* password callback */
- NULL, NULL, /* decrypt key callback (not used) */
- NULL, NULL); /* detached digests (not used) */
-
- for (;;) {
- if (feof(infile)) break;
- nb = fread(ibuf, 1, sizeof(ibuf), infile);
- if (nb == 0) {
- if (ferror(infile)) {
- fprintf(stderr, "ERROR: file i/o error.\n");
- NSS_CMSEncoder_Cancel(ecx);
- goto loser;
- }
- /* eof */
- break;
- }
- (void)NSS_CMSEncoder_Update(ecx, (const char *)ibuf, nb);
- }
- if (NSS_CMSEncoder_Finish(ecx) != SECSuccess) {
- fprintf(stderr, "ERROR: DER encoding problem.\n");
- goto loser;
- }
-
- retval = SECSuccess;
-
-loser:
- if (cmsg)
- NSS_CMSMessage_Destroy(cmsg);
- if (tmppoolp)
- PORT_FreeArena(tmppoolp, PR_FALSE);
- return retval;
-}
-
-typedef enum { UNKNOWN, DECODE, SIGN, ENCRYPT } Mode;
-
-int
-main(int argc, char **argv)
-{
- char *progName;
- FILE *outFile, *inFile;
- PLOptState *optstate;
- PLOptStatus status;
- Mode mode = UNKNOWN;
- struct decodeOptionsStr decodeOptions = { 0 };
- struct signOptionsStr signOptions = { 0 };
- struct envelopeOptionsStr envelopeOptions = { 0 };
- struct optionsStr options = { 0 };
- int exitstatus;
- static char *ptrarray[128] = { 0 };
- int nrecipients = 0;
-
- progName = strrchr(argv[0], '/');
- progName = progName ? progName+1 : argv[0];
-
- inFile = stdin;
- outFile = stdout;
- mode = UNKNOWN;
- decodeOptions.contentFile = NULL;
- decodeOptions.suppressContent = PR_FALSE;
- decodeOptions.headerLevel = -1;
- options.certUsage = certUsageEmailSigner;
- options.password = NULL;
- signOptions.nickname = NULL;
- signOptions.detached = PR_FALSE;
- signOptions.signingTime = PR_FALSE;
- signOptions.smimeProfile = PR_FALSE;
- signOptions.encryptionKeyPreferenceNick = NULL;
- envelopeOptions.recipients = NULL;
-
- /*
- * Parse command line arguments
- */
- optstate = PL_CreateOptState(argc, argv, "DSEnN:TGPY:h:p:i:c:d:o:s:u:r:");
- while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
- switch (optstate->option) {
- case '?':
- Usage(progName);
- break;
-
- case 'D':
- mode = DECODE;
- break;
- case 'S':
- mode = SIGN;
- break;
- case 'E':
- mode = ENCRYPT;
- break;
-
- case 'n':
- if (mode != DECODE) {
- fprintf(stderr, "%s: option -n only supported with option -D.\n", progName);
- Usage(progName);
- exit(1);
- }
- decodeOptions.suppressContent = PR_TRUE;
- break;
-
- case 'N':
- if (mode != SIGN) {
- fprintf(stderr, "%s: option -N only supported with option -S.\n", progName);
- Usage(progName);
- exit(1);
- }
- signOptions.nickname = strdup(optstate->value);
- break;
-
- case 'Y':
- if (mode != SIGN) {
- fprintf(stderr, "%s: option -Y only supported with option -S.\n", progName);
- Usage(progName);
- exit(1);
- }
- signOptions.encryptionKeyPreferenceNick = strdup(optstate->value);
- break;
-
- case 'T':
- if (mode != SIGN) {
- fprintf(stderr, "%s: option -T only supported with option -S.\n", progName);
- Usage(progName);
- exit(1);
- }
- signOptions.detached = PR_TRUE;
- break;
-
- case 'G':
- if (mode != SIGN) {
- fprintf(stderr, "%s: option -G only supported with option -S.\n", progName);
- Usage(progName);
- exit(1);
- }
- signOptions.signingTime = PR_TRUE;
- break;
-
- case 'P':
- if (mode != SIGN) {
- fprintf(stderr, "%s: option -P only supported with option -S.\n", progName);
- Usage(progName);
- exit(1);
- }
- signOptions.smimeProfile = PR_TRUE;
- break;
-
- case 'h':
- if (mode != DECODE) {
- fprintf(stderr, "%s: option -h only supported with option -D.\n", progName);
- Usage(progName);
- exit(1);
- }
- decodeOptions.headerLevel = atoi(optstate->value);
- if (decodeOptions.headerLevel < 0) {
- fprintf(stderr, "option -h cannot have a negative value.\n");
- exit(1);
- }
- break;
-
- case 'p':
- if (!optstate->value) {
- fprintf(stderr, "%s: option -p must have a value.\n", progName);
- Usage(progName);
- exit(1);
- }
-
- options.password = strdup(optstate->value);
- break;
-
- case 'i':
- if ((inFile = fopen(optstate->value, "r")) == NULL) {
- fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
- progName, optstate->value);
- exit(1);
- }
- break;
-
- case 'c':
- if (mode != DECODE) {
- fprintf(stderr, "%s: option -c only supported with option -D.\n", progName);
- Usage(progName);
- exit(1);
- }
- if ((decodeOptions.contentFile = fopen(optstate->value, "r")) == NULL) {
- fprintf(stderr, "%s: unable to open \"%s\" for reading.\n",
- progName, optstate->value);
- exit(1);
- }
- break;
-
- case 'o':
- if ((outFile = fopen(optstate->value, "w")) == NULL) {
- fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
- progName, optstate->value);
- exit(1);
- }
- break;
-
- case 'r':
- if (!optstate->value) {
- fprintf(stderr, "%s: option -r must have a value.\n", progName);
- Usage(progName);
- exit(1);
- }
-#if 0
- fprintf(stderr, "recipient = %s\n", optstate->value);
-#endif
- envelopeOptions.recipients = ptrarray;
- envelopeOptions.recipients[nrecipients++] = strdup(optstate->value);
- envelopeOptions.recipients[nrecipients] = NULL;
- break;
-
- case 'd':
- SECU_ConfigDirectory(optstate->value);
- break;
-
- case 'u': {
- int usageType;
-
- usageType = atoi (strdup(optstate->value));
- if (usageType < certUsageSSLClient || usageType > certUsageAnyCA)
- return -1;
- options.certUsage = (SECCertUsage)usageType;
- break;
- }
-
- }
- }
-
- /* Call the libsec initialization routines */
- PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
- SECU_PKCS11Init(PR_FALSE);
- SEC_Init();
-
- /* open cert database */
- options.certHandle = OpenCertDB(progName);
- if (options.certHandle == NULL) {
- return -1;
- }
- CERT_SetDefaultCertDB(options.certHandle);
-
- exitstatus = 0;
- switch (mode) {
- case DECODE:
- if (decode(outFile, inFile, progName, options, decodeOptions)) {
- SECU_PrintError(progName, "problem decoding");
- exitstatus = 1;
- }
- break;
- case SIGN:
- if (sign(outFile, inFile, progName, options, signOptions)) {
- SECU_PrintError(progName, "problem signing");
- exitstatus = 1;
- }
- break;
- case ENCRYPT:
- if (envelope(outFile, inFile, progName, options, envelopeOptions)) {
- SECU_PrintError(progName, "problem encrypting");
- exitstatus = 1;
- }
- break;
- default:
- fprintf(stderr, "One of options -D, -S or -E must be set.\n");
- Usage(progName);
- exitstatus = 1;
- }
- if (outFile != stdout)
- fclose(outFile);
-
- exit(exitstatus);
-}