Back to index

lightning-sunbird  0.9+nobinonly
Classes | Enumerations | Functions | Variables
cmsutil.c File Reference
#include "nspr.h"
#include "secutil.h"
#include "plgetopt.h"
#include "secpkcs7.h"
#include "cert.h"
#include "certdb.h"
#include "secoid.h"
#include "cms.h"
#include "nss.h"
#include "smime.h"
#include "pk11func.h"
#include <stdio.h>
#include <string.h>

Go to the source code of this file.

Classes

struct  optionsStr
struct  decodeOptionsStr
struct  signOptionsStr
struct  envelopeOptionsStr
struct  certsonlyOptionsStr
struct  encryptOptionsStr

Enumerations

enum  Mode {
  UNKNOWN, DECODE, SIGN, ENCRYPT,
  ENVELOPE, CERTSONLY, UNKNOWN, DECODE,
  SIGN, ENCRYPT, ENVELOPE, CERTSONLY
}

Functions

int nss_CMSArray_Count (void **array)
static SECStatus DigestFile (PLArenaPool *poolp, SECItem ***digests, SECItem *input, SECAlgorithmID **algids)
static void Usage (char *progName)
static NSSCMSMessage * decode (FILE *out, SECItem *input, const struct decodeOptionsStr *decodeOptions)
static NSSCMSMessage * signed_data (struct signOptionsStr *signOptions)
static NSSCMSMessage * enveloped_data (struct envelopeOptionsStr *envelopeOptions)
PK11SymKey * dkcb (void *arg, SECAlgorithmID *algid)
static SECStatus get_enc_params (struct encryptOptionsStr *encryptOptions)
static NSSCMSMessage * encrypted_data (struct encryptOptionsStr *encryptOptions)
static NSSCMSMessage * signed_data_certsonly (struct certsonlyOptionsStr *certsonlyOptions)
static char * pl_fgets (char *buf, int size, PRFileDesc *fd)
static int doBatchDecode (FILE *outFile, PRFileDesc *batchFile, const struct decodeOptionsStr *decodeOptions)
int main (int argc, char **argv)
 The Xalan testcases app.

Variables

char * progName = NULL
static int cms_verbose = 0
static secuPWData pwdata = { PW_NONE, 0 }
static PK11PasswordFunc pwcb = NULL
static voidpwcb_arg = NULL

Class Documentation

struct optionsStr

Definition at line 157 of file cmsutil.c.

Class Members
CERTCertDBHandle * certHandle
SECCertUsage certUsage
char * password
struct decodeOptionsStr

Definition at line 163 of file cmsutil.c.

Collaboration diagram for decodeOptionsStr:
Class Members
PK11SymKey * bulkkey
SECItem content
NSSCMSGetDecryptKeyCallback dkcb
int headerLevel
PRBool keepCerts
struct optionsStr * options
PRBool suppressContent
struct signOptionsStr

Definition at line 173 of file cmsutil.c.

Collaboration diagram for signOptionsStr:
Class Members
PRBool detached
char * encryptionKeyPreferenceNick
SECOidTag hashAlgTag
char * nickname
struct optionsStr * options
PRBool signingTime
PRBool smimeProfile
struct envelopeOptionsStr

Definition at line 183 of file cmsutil.c.

Collaboration diagram for envelopeOptionsStr:
Class Members
struct optionsStr * options
char ** recipients
struct certsonlyOptionsStr

Definition at line 188 of file cmsutil.c.

Collaboration diagram for certsonlyOptionsStr:
Class Members
struct optionsStr * options
char ** recipients
struct encryptOptionsStr

Definition at line 193 of file cmsutil.c.

Collaboration diagram for encryptOptionsStr:
Class Members
SECOidTag bulkalgtag
PK11SymKey * bulkkey
PRFileDesc * envFile
NSSCMSMessage * envmsg
SECItem * input
int keysize
struct optionsStr * options
FILE * outfile
char ** recipients

Enumeration Type Documentation

enum Mode
Enumerator:
UNKNOWN 
DECODE 
SIGN 
ENCRYPT 
ENVELOPE 
CERTSONLY 
UNKNOWN 
DECODE 
SIGN 
ENCRYPT 
ENVELOPE 
CERTSONLY 

Definition at line 1012 of file cmsutil.c.


Function Documentation

static NSSCMSMessage* decode ( FILE out,
SECItem *  input,
const struct decodeOptionsStr decodeOptions 
) [static]

Definition at line 206 of file cmsutil.c.

{
    NSSCMSDecoderContext *dcx;
    NSSCMSMessage *cmsg;
    int nlevels, i;
    SECItem sitem = { 0, 0, 0 };

    PORT_SetError(0);
    dcx = NSS_CMSDecoder_Start(NULL, 
                               NULL, NULL,         /* content callback     */
                               pwcb, pwcb_arg,     /* password callback    */
                            decodeOptions->dkcb, /* decrypt key callback */
                               decodeOptions->bulkkey);
    (void)NSS_CMSDecoder_Update(dcx, (char *)input->data, input->len);
    cmsg = NSS_CMSDecoder_Finish(dcx);
    if (cmsg == NULL) {
       fprintf(stderr, "%s: failed to decode message.\n", progName);
       return NULL;
    }

    if (decodeOptions->headerLevel >= 0) {
       /*fprintf(out, "SMIME: ", decodeOptions->headerLevel, i);*/
       fprintf(out, "SMIME: ");
    }

    nlevels = NSS_CMSMessage_ContentLevelCount(cmsg);
    for (i = 0; i < nlevels; i++) {
       NSSCMSContentInfo *cinfo;
       SECOidTag typetag;

       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:
         {
           NSSCMSSignedData *sigd = NULL;
           SECItem **digests;
           int nsigners;
           int j;

           if (decodeOptions->headerLevel >= 0)
              fprintf(out, "type=signedData; ");
           sigd = (NSSCMSSignedData *)NSS_CMSContentInfo_GetContent(cinfo);
           if (sigd == NULL) {
              SECU_PrintError(progName, "signedData component missing");
              goto loser;
           }

           /* if we have a content file, but no digests for this signedData */
           if (decodeOptions->content.data != NULL && 
               !NSS_CMSSignedData_HasDigests(sigd)) {
              PLArenaPool     *poolp;
              SECAlgorithmID **digestalgs;

              /* detached content: grab content file */
              sitem = decodeOptions->content;

              if ((poolp = PORT_NewArena(1024)) == NULL) {
                  fprintf(stderr, "cmsutil: Out of memory.\n");
                  goto loser;
              }
              digestalgs = NSS_CMSSignedData_GetDigestAlgs(sigd);
              if (DigestFile (poolp, &digests, &sitem, digestalgs) 
                    != SECSuccess) {
                  SECU_PrintError(progName, 
                                  "problem computing message digest");
                  PORT_FreeArena(poolp, PR_FALSE);
                  goto loser;
              }
              if (NSS_CMSSignedData_SetDigests(sigd, digestalgs, digests) 
                  != SECSuccess) {
                  SECU_PrintError(progName, 
                                  "problem setting message digests");
                  PORT_FreeArena(poolp, PR_FALSE);
                  goto loser;
              }
              PORT_FreeArena(poolp, PR_FALSE);
           }

           /* import the certificates */
           if (NSS_CMSSignedData_ImportCerts(sigd, 
                                          decodeOptions->options->certHandle, 
                                          decodeOptions->options->certUsage, 
                                          decodeOptions->keepCerts) 
                 != SECSuccess) {
              SECU_PrintError(progName, "cert import failed");
              goto loser;
           }

           /* find out about signers */
           nsigners = NSS_CMSSignedData_SignerInfoCount(sigd);
           if (decodeOptions->headerLevel >= 0)
              fprintf(out, "nsigners=%d; ", nsigners);
           if (nsigners == 0) {
              /* Might be a cert transport message
              ** or might be an invalid message, such as a QA test message
              ** or a message from an attacker.
              */
              SECStatus rv;
              rv = NSS_CMSSignedData_VerifyCertsOnly(sigd, 
                                          decodeOptions->options->certHandle, 
                                          decodeOptions->options->certUsage);
              if (rv != SECSuccess) {
                  fprintf(stderr, "cmsutil: Verify certs-only failed!\n");
                  goto loser;
              }
              return cmsg;
           }

           /* still no digests? */
           if (!NSS_CMSSignedData_HasDigests(sigd)) {
              SECU_PrintError(progName, "no message digests");
              goto loser;
           }

           for (j = 0; j < nsigners; j++) {
              const char * svs;
              NSSCMSSignerInfo *si;
              NSSCMSVerificationStatus vs;
              SECStatus bad;

              si = NSS_CMSSignedData_GetSignerInfo(sigd, j);
              if (decodeOptions->headerLevel >= 0) {
                  char *signercn;
                  static char empty[] = { "" };

                  signercn = NSS_CMSSignerInfo_GetSignerCommonName(si);
                  if (signercn == NULL)
                     signercn = empty;
                  fprintf(out, "\n\t\tsigner%d.id=\"%s\"; ", j, signercn);
                  if (signercn != empty)
                      PORT_Free(signercn);
              }
              bad = NSS_CMSSignedData_VerifySignerInfo(sigd, j, 
                                         decodeOptions->options->certHandle, 
                                         decodeOptions->options->certUsage);
              vs  = NSS_CMSSignerInfo_GetVerificationStatus(si);
              svs = NSS_CMSUtil_VerificationStatusToString(vs);
              if (decodeOptions->headerLevel >= 0) {
                  fprintf(out, "signer%d.status=%s; ", j, svs);
                  /* goto loser ? */
              } else if (bad && out) {
                  fprintf(stderr, "signer %d status = %s\n", j, svs);
                  goto loser;
              }
           }
         }
         break;
       case SEC_OID_PKCS7_ENVELOPED_DATA:
         {
           NSSCMSEnvelopedData *envd;
           if (decodeOptions->headerLevel >= 0)
              fprintf(out, "type=envelopedData; ");
           envd = (NSSCMSEnvelopedData *)NSS_CMSContentInfo_GetContent(cinfo);
           if (envd == NULL) {
              SECU_PrintError(progName, "envelopedData component missing");
              goto loser;
           }
         }
         break;
       case SEC_OID_PKCS7_ENCRYPTED_DATA:
         {
           NSSCMSEncryptedData *encd;
           if (decodeOptions->headerLevel >= 0)
              fprintf(out, "type=encryptedData; ");
           encd = (NSSCMSEncryptedData *)NSS_CMSContentInfo_GetContent(cinfo);
           if (encd == NULL) {
              SECU_PrintError(progName, "encryptedData component missing");
              goto loser;
           }
         }
         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 && out) {
       SECItem *item = (sitem.data ? &sitem 
                                   : NSS_CMSMessage_GetContent(cmsg));
       if (item && item->data && item->len) {
           fwrite(item->data, item->len, 1, out);
       }
    }
    return cmsg;

loser:
    if (cmsg)
       NSS_CMSMessage_Destroy(cmsg);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus DigestFile ( PLArenaPool poolp,
SECItem ***  digests,
SECItem *  input,
SECAlgorithmID **  algids 
) [static]

Definition at line 89 of file cmsutil.c.

{
    NSSCMSDigestContext *digcx;
    SECStatus rv;

    digcx = NSS_CMSDigestContext_StartMultiple(algids);
    if (digcx == NULL)
       return SECFailure;

    NSS_CMSDigestContext_Update(digcx, input->data, input->len);

    rv = NSS_CMSDigestContext_FinishMultiple(digcx, poolp, digests);
    return rv;
}

Here is the call graph for this function:

Here is the caller graph for this function:

PK11SymKey* dkcb ( void arg,
SECAlgorithmID *  algid 
)

Definition at line 752 of file cmsutil.c.

{
    return (PK11SymKey*)arg;
}
static int doBatchDecode ( FILE outFile,
PRFileDesc batchFile,
const struct decodeOptionsStr decodeOptions 
) [static]

Definition at line 1015 of file cmsutil.c.

{
    char * str;
    int    exitStatus = 0;
    char   batchLine[512];

    while (NULL != (str = pl_fgets(batchLine, sizeof batchLine, batchFile))) {
       NSSCMSMessage *cmsg = NULL;
       PRFileDesc *   inFile;
       int            len = strlen(str);
       SECStatus      rv;
       SECItem        input = {0, 0, 0};
       char           cc;

       while (len > 0 && 
              ((cc = str[len - 1]) == '\n' || cc == '\r')) {
           str[--len] = '\0';
       }
       if (!len) /* skip empty line */
           continue;
       if (str[0] == '#')
           continue;  /* skip comment line */
       fprintf(outFile, "========== %s ==========\n", str);
       inFile = PR_Open(str, PR_RDONLY, 00660);
       if (inFile == NULL) {
           fprintf(outFile, "%s: unable to open \"%s\" for reading\n",
                  progName, str);
           exitStatus = 1;
           continue;
       }
       rv = SECU_FileToItem(&input, inFile);
       PR_Close(inFile);
       if (rv != SECSuccess) {
           SECU_PrintError(progName, "unable to read infile");
           exitStatus = 1;
           continue;
       }
       cmsg = decode(outFile, &input, decodeOptions);
       SECITEM_FreeItem(&input, PR_FALSE);
       if (cmsg)
           NSS_CMSMessage_Destroy(cmsg);
       else {
           SECU_PrintError(progName, "problem decoding");
           exitStatus = 1;
       }
    }
    return exitStatus;
}

Here is the call graph for this function:

static NSSCMSMessage* encrypted_data ( struct encryptOptionsStr encryptOptions) [static]

Definition at line 812 of file cmsutil.c.

{
    SECStatus rv = SECFailure;
    NSSCMSMessage *cmsg = NULL;
    NSSCMSContentInfo *cinfo;
    NSSCMSEncryptedData *encd;
    NSSCMSEncoderContext *ecx = NULL;
    PLArenaPool *tmppoolp = NULL;
    SECItem derOut = { 0, 0, 0 };
    /* arena for output */
    tmppoolp = PORT_NewArena(1024);
    if (!tmppoolp) {
       fprintf(stderr, "%s: out of memory.\n", progName);
       return NULL;
    }
    /*
     * create the message object
     */
    cmsg = NSS_CMSMessage_Create(NULL);
    if (cmsg == NULL) {
       fprintf(stderr, "ERROR: cannot create CMS message.\n");
       goto loser;
    }
    /*
     * build chain of objects: message->encryptedData->data
     */
    if ((encd = NSS_CMSEncryptedData_Create(cmsg, encryptOptions->bulkalgtag, 
                                                  encryptOptions->keysize)) 
           == NULL) {
       fprintf(stderr, "ERROR: cannot create CMS encryptedData object.\n");
       goto loser;
    }
    cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
    if (NSS_CMSContentInfo_SetContent_EncryptedData(cmsg, cinfo, encd)
          != SECSuccess) {
       fprintf(stderr, "ERROR: cannot attach CMS encryptedData object.\n");
       goto loser;
    }
    cinfo = NSS_CMSEncryptedData_GetContentInfo(encd);
    /* 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;
    }
    ecx = NSS_CMSEncoder_Start(cmsg, NULL, NULL, &derOut, tmppoolp, NULL, NULL,
                               dkcb, encryptOptions->bulkkey, NULL, NULL);
    if (!ecx) {
       fprintf(stderr, "%s: cannot create encoder context.\n", progName);
       goto loser;
    }
    rv = NSS_CMSEncoder_Update(ecx, (char *)encryptOptions->input->data, 
                                    encryptOptions->input->len);
    if (rv) {
       fprintf(stderr, "%s: failed to add data to encoder.\n", progName);
       goto loser;
    }
    rv = NSS_CMSEncoder_Finish(ecx);
    if (rv) {
       fprintf(stderr, "%s: failed to encrypt data.\n", progName);
       goto loser;
    }
    fwrite(derOut.data, derOut.len, 1, encryptOptions->outfile);
    /*
    if (bulkkey)
       PK11_FreeSymKey(bulkkey);
       */
    if (tmppoolp)
       PORT_FreeArena(tmppoolp, PR_FALSE);
    return cmsg;
loser:
    /*
    if (bulkkey)
       PK11_FreeSymKey(bulkkey);
       */
    if (tmppoolp)
       PORT_FreeArena(tmppoolp, PR_FALSE);
    if (cmsg)
       NSS_CMSMessage_Destroy(cmsg);
    return NULL;
}

Here is the call graph for this function:

static NSSCMSMessage* enveloped_data ( struct envelopeOptionsStr envelopeOptions) [static]

Definition at line 641 of file cmsutil.c.

{
    NSSCMSMessage *cmsg = NULL;
    NSSCMSContentInfo *cinfo;
    NSSCMSEnvelopedData *envd;
    NSSCMSRecipientInfo *recipientinfo;
    CERTCertificate **recipientcerts = NULL;
    CERTCertDBHandle *dbhandle;
    PLArenaPool *tmppoolp = NULL;
    SECOidTag bulkalgtag;
    int keysize, i = 0;
    int cnt;
    dbhandle = envelopeOptions->options->certHandle;
    /* count the recipients */
    if ((cnt = nss_CMSArray_Count((void **)envelopeOptions->recipients)) == 0) {
       fprintf(stderr, "ERROR: please name at least one recipient.\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 **)PORT_ArenaZAlloc(tmppoolp, 
                                        (cnt+1)*sizeof(CERTCertificate*)))
            == NULL) {
       fprintf(stderr, "ERROR: out of memory.\n");
       goto loser;
    }
    for (i=0; envelopeOptions->recipients[i] != NULL; i++) {
       if ((recipientcerts[i] = 
             CERT_FindCertByNicknameOrEmailAddr(dbhandle,  
                                               envelopeOptions->recipients[i]))
               == NULL) {
           SECU_PrintError(progName, "cannot find certificate for \"%s\"", 
                           envelopeOptions->recipients[i]);
           i=0;
           goto loser;
       }
    }
    recipientcerts[i] = NULL;
    i=0;
    /* 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;
       }
       CERT_DestroyCertificate(recipientcerts[i]);
    }
    if (tmppoolp)
       PORT_FreeArena(tmppoolp, PR_FALSE);
    return cmsg;
loser:
    if (recipientcerts) {
       for (; recipientcerts[i] != NULL; i++) {
           CERT_DestroyCertificate(recipientcerts[i]);
       }
    }
    if (cmsg)
       NSS_CMSMessage_Destroy(cmsg);
    if (tmppoolp)
       PORT_FreeArena(tmppoolp, PR_FALSE);
    return NULL;
}

Here is the call graph for this function:

Here is the caller graph for this function:

static SECStatus get_enc_params ( struct encryptOptionsStr encryptOptions) [static]

Definition at line 758 of file cmsutil.c.

{
    struct envelopeOptionsStr envelopeOptions;
    SECStatus rv = SECFailure;
    NSSCMSMessage *env_cmsg;
    NSSCMSContentInfo *cinfo;
    int i, nlevels;
    /*
     * construct an enveloped data message to obtain bulk keys
     */
    if (encryptOptions->envmsg) {
       env_cmsg = encryptOptions->envmsg; /* get it from an old message */
    } else {
       SECItem dummyOut = { 0, 0, 0 };
       SECItem dummyIn  = { 0, 0, 0 };
       char str[] = "Hello!";
       PLArenaPool *tmparena = PORT_NewArena(1024);
       dummyIn.data = (unsigned char *)str;
       dummyIn.len = strlen(str);
       envelopeOptions.options = encryptOptions->options;
       envelopeOptions.recipients = encryptOptions->recipients;
       env_cmsg = enveloped_data(&envelopeOptions);
       NSS_CMSDEREncode(env_cmsg, &dummyIn, &dummyOut, tmparena);
       PR_Write(encryptOptions->envFile, dummyOut.data, dummyOut.len);
       PORT_FreeArena(tmparena, PR_FALSE);
    }
    /*
     * get the content info for the enveloped data 
     */
    nlevels = NSS_CMSMessage_ContentLevelCount(env_cmsg);
    for (i = 0; i < nlevels; i++) {
       SECOidTag typetag;
       cinfo = NSS_CMSMessage_ContentLevel(env_cmsg, i);
       typetag = NSS_CMSContentInfo_GetContentTypeTag(cinfo);
       if (typetag == SEC_OID_PKCS7_DATA) {
           /*
            * get the symmetric key
            */
           encryptOptions->bulkalgtag = NSS_CMSContentInfo_GetContentEncAlgTag(cinfo);
           encryptOptions->keysize = NSS_CMSContentInfo_GetBulkKeySize(cinfo);
           encryptOptions->bulkkey = NSS_CMSContentInfo_GetBulkKey(cinfo);
           rv = SECSuccess;
           break;
       }
    }
    if (i == nlevels) {
       fprintf(stderr, "%s: could not retrieve enveloped data.", progName);
    }
    if (env_cmsg)
       NSS_CMSMessage_Destroy(env_cmsg);
    return rv;
}

Here is the call graph for this function:

int main ( int  argc,
char **  argv 
)

The Xalan testcases app.

Definition at line 1066 of file cmsutil.c.

{
    FILE *outFile;
    NSSCMSMessage *cmsg = NULL;
    PRFileDesc *inFile;
    PLOptState *optstate;
    PLOptStatus status;
    Mode mode = UNKNOWN;
    struct decodeOptionsStr decodeOptions = { 0 };
    struct signOptionsStr signOptions = { 0 };
    struct envelopeOptionsStr envelopeOptions = { 0 };
    struct certsonlyOptionsStr certsonlyOptions = { 0 };
    struct encryptOptionsStr encryptOptions = { 0 };
    struct optionsStr options = { 0 };
    int exitstatus;
    static char *ptrarray[128] = { 0 };
    int nrecipients = 0;
    char *str, *tok;
    char *envFileName;
    SECItem input = { 0, 0, 0};
    SECItem envmsg = { 0, 0, 0 };
    SECStatus rv;
    PRFileDesc *contentFile = NULL;
    PRBool      batch = PR_FALSE;

#ifdef NISCC_TEST
    const char *ev = PR_GetEnv("NSS_DISABLE_ARENA_FREE_LIST");
    PORT_Assert(ev); 
    ev = PR_GetEnv("NSS_STRICT_SHUTDOWN");
    PORT_Assert(ev); 
#endif 

    progName = strrchr(argv[0], '/');
    if (!progName)
       progName = strrchr(argv[0], '\\');
    progName = progName ? progName+1 : argv[0];

    inFile = PR_STDIN;
    outFile = stdout;
    envFileName = NULL;
    mode = UNKNOWN;
    decodeOptions.content.data = NULL;
    decodeOptions.content.len  = 0;
    decodeOptions.suppressContent = PR_FALSE;
    decodeOptions.headerLevel = -1;
    decodeOptions.keepCerts = PR_FALSE;
    options.certUsage = certUsageEmailSigner;
    options.password = NULL;
    signOptions.nickname = NULL;
    signOptions.detached = PR_FALSE;
    signOptions.signingTime = PR_FALSE;
    signOptions.smimeProfile = PR_FALSE;
    signOptions.encryptionKeyPreferenceNick = NULL;
    signOptions.hashAlgTag = SEC_OID_SHA1;
    envelopeOptions.recipients = NULL;
    encryptOptions.recipients = NULL;
    encryptOptions.envmsg = NULL;
    encryptOptions.envFile = NULL;
    encryptOptions.bulkalgtag = SEC_OID_UNKNOWN;
    encryptOptions.bulkkey = NULL;
    encryptOptions.keysize = -1;

    /*
     * Parse command line arguments
     */
    optstate = PL_CreateOptState(argc, argv, 
                             "CDEGH:N:OPSTY:bc:d:e:h:i:kno:p:r:s:u:v");
    while ((status = PL_GetNextOpt(optstate)) == PL_OPT_OK) {
       switch (optstate->option) {
       case 'C':
           mode = ENCRYPT;
           break;
       case 'D':
           mode = DECODE;
           break;
       case 'E':
           mode = ENVELOPE;
           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 'H':
           if (mode != SIGN) {
               fprintf(stderr,
                       "%s: option -H only supported with option -S.\n",
                       progName);
               Usage(progName);
               exit(1);
           }
           decodeOptions.suppressContent = PR_TRUE;
           if (!strcmp(optstate->value, "MD2"))
               signOptions.hashAlgTag = SEC_OID_MD2;
           else if (!strcmp(optstate->value, "MD4"))
               signOptions.hashAlgTag = SEC_OID_MD4;
           else if (!strcmp(optstate->value, "MD5"))
               signOptions.hashAlgTag = SEC_OID_MD5;
           else if (!strcmp(optstate->value, "SHA1"))
               signOptions.hashAlgTag = SEC_OID_SHA1;
           else if (!strcmp(optstate->value, "SHA256"))
               signOptions.hashAlgTag = SEC_OID_SHA256;
           else if (!strcmp(optstate->value, "SHA384"))
               signOptions.hashAlgTag = SEC_OID_SHA384;
           else if (!strcmp(optstate->value, "SHA512"))
               signOptions.hashAlgTag = SEC_OID_SHA512;
           else {
               fprintf(stderr,
           "%s: -H requires one of MD2,MD4,MD5,SHA1,SHA256,SHA384,SHA512\n",
                       progName);
               exit(1);
           }
           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 'O':
           mode = CERTSONLY;
           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 'S':
           mode = SIGN;
           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 '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 'b':
           if (mode != DECODE) {
              fprintf(stderr, 
                      "%s: option -b only supported with option -D.\n", 
                      progName);
              Usage(progName);
              exit(1);
           }
           batch = PR_TRUE;
           break;

       case 'c':
           if (mode != DECODE) {
              fprintf(stderr, 
                      "%s: option -c only supported with option -D.\n", 
                      progName);
              Usage(progName);
              exit(1);
           }
           contentFile = PR_Open(optstate->value, PR_RDONLY, 006600);
           if (contentFile == NULL) {
              fprintf(stderr, "%s: unable to open \"%s\" for reading.\n",
                     progName, optstate->value);
              exit(1);
           }

           rv = SECU_FileToItem(&decodeOptions.content, contentFile);
           PR_Close(contentFile);
           if (rv != SECSuccess) {
              SECU_PrintError(progName, "problem reading content file");
              exit(1);
           }
           if (!decodeOptions.content.data) {
              /* file was zero length */
              decodeOptions.content.data = (unsigned char *)PORT_Strdup("");
              decodeOptions.content.len  = 0;
           }

           break;
       case 'd':
           SECU_ConfigDirectory(optstate->value);
           break;
       case 'e':
           envFileName = strdup(optstate->value);
           encryptOptions.envFile = PR_Open(envFileName, PR_RDONLY, 00660);
           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 'i':
           if (!optstate->value) {
               fprintf(stderr, "-i option requires filename argument\n");
               exit(1);
           }
           inFile = PR_Open(optstate->value, PR_RDONLY, 00660);
           if (inFile == NULL) {
              fprintf(stderr, "%s: unable to open \"%s\" for reading\n",
                     progName, optstate->value);
              exit(1);
           }
           break;

       case 'k':
           if (mode != DECODE) {
              fprintf(stderr, 
                      "%s: option -k only supported with option -D.\n", 
                      progName);
              Usage(progName);
              exit(1);
           }
           decodeOptions.keepCerts = PR_TRUE;
           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 'o':
           outFile = fopen(optstate->value, "wb");
           if (outFile == NULL) {
              fprintf(stderr, "%s: unable to open \"%s\" for writing\n",
                     progName, optstate->value);
              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 'r':
           if (!optstate->value) {
              fprintf(stderr, "%s: option -r must have a value.\n", progName);
              Usage(progName);
              exit(1);
           }
           envelopeOptions.recipients = ptrarray;
           str = (char *)optstate->value;
           do {
              tok = strchr(str, ',');
              if (tok) *tok = '\0';
              envelopeOptions.recipients[nrecipients++] = strdup(str);
              if (tok) str = tok + 1;
           } while (tok);
           envelopeOptions.recipients[nrecipients] = NULL;
           encryptOptions.recipients = envelopeOptions.recipients;
           certsonlyOptions.recipients = envelopeOptions.recipients;
           break;

       case 'u': {
           int usageType;

           usageType = atoi (strdup(optstate->value));
           if (usageType < certUsageSSLClient || usageType > certUsageAnyCA)
              return -1;
           options.certUsage = (SECCertUsage)usageType;
           break;
         }
       case 'v':
           cms_verbose = 1;
           break;

       }
    }
    if (status == PL_OPT_BAD)
       Usage(progName);
    PL_DestroyOptState(optstate);

    if (mode == UNKNOWN)
       Usage(progName);

    if (mode != CERTSONLY && !batch) {
       rv = SECU_FileToItem(&input, inFile);
       if (rv != SECSuccess) {
           SECU_PrintError(progName, "unable to read infile");
           exit(1);
       }
       if (inFile != PR_STDIN) {
           PR_Close(inFile);
       }
    }
    if (cms_verbose) {
       fprintf(stderr, "received commands\n");
    }

    /* Call the libsec initialization routines */
    PR_Init(PR_SYSTEM_THREAD, PR_PRIORITY_NORMAL, 1);
    rv = NSS_InitReadWrite(SECU_ConfigDirectory(NULL));
    if (SECSuccess != rv) {
       SECU_PrintError(progName, "NSS_Init failed");
       exit(1);
    }
    if (cms_verbose) {
       fprintf(stderr, "NSS has been initialized.\n");
    }
    options.certHandle = CERT_GetDefaultCertDB();
    if (!options.certHandle) {
       SECU_PrintError(progName, "No default cert DB");
       exit(1);
    }
    if (cms_verbose) {
       fprintf(stderr, "Got default certdb\n");
    }
    if (options.password)
    {
       pwdata.source = PW_PLAINTEXT;
       pwdata.data = options.password;
    }
    pwcb = SECU_GetModulePassword;
    pwcb_arg = (void *)&pwdata;

    PK11_SetPasswordFunc(&SECU_GetModulePassword);


#if defined(_WIN32)
    if (outFile == stdout) {
       /* If we're going to write binary data to stdout, we must put stdout
       ** into O_BINARY mode or else outgoing \n's will become \r\n's.
       */
       int smrv = _setmode(_fileno(stdout), _O_BINARY);
       if (smrv == -1) {
           fprintf(stderr,
           "%s: Cannot change stdout to binary mode. Use -o option instead.\n",
                   progName);
           return smrv;
       }
    }
#endif

    exitstatus = 0;
    switch (mode) {
    case DECODE:       /* -D */
       decodeOptions.options = &options;
       if (encryptOptions.envFile) {
           /* Decoding encrypted-data, so get the bulkkey from an
            * enveloped-data message.
            */
           SECU_FileToItem(&envmsg, encryptOptions.envFile);
           decodeOptions.options = &options;
           encryptOptions.envmsg = decode(NULL, &envmsg, &decodeOptions);
           if (!encryptOptions.envmsg) {
              SECU_PrintError(progName, "problem decoding env msg");
              exitstatus = 1;
              break;
           }
           rv = get_enc_params(&encryptOptions);
           decodeOptions.dkcb = dkcb;
           decodeOptions.bulkkey = encryptOptions.bulkkey;
       }
       if (!batch) {
           cmsg = decode(outFile, &input, &decodeOptions);
           if (!cmsg) {
              SECU_PrintError(progName, "problem decoding");
              exitstatus = 1;
           }
       } else {
           exitstatus = doBatchDecode(outFile, inFile, &decodeOptions);
           if (inFile != PR_STDIN) {
              PR_Close(inFile);
           }
       }
       break;
    case SIGN:         /* -S */
       signOptions.options = &options;
       cmsg = signed_data(&signOptions);
       if (!cmsg) {
           SECU_PrintError(progName, "problem signing");
           exitstatus = 1;
       }
       break;
    case ENCRYPT:      /* -C */
       if (!envFileName) {
           fprintf(stderr, "%s: you must specify an envelope file with -e.\n",
                   progName);
           exit(1);
       }
       encryptOptions.options = &options;
       encryptOptions.input = &input;
       encryptOptions.outfile = outFile;
       /* decode an enveloped-data message to get the bulkkey (create
        * a new one if neccessary)
        */
       if (!encryptOptions.envFile) {
           encryptOptions.envFile = PR_Open(envFileName, 
                                            PR_WRONLY|PR_CREATE_FILE, 00660);
           if (!encryptOptions.envFile) {
              fprintf(stderr, "%s: failed to create file %s.\n", progName,
                      envFileName);
              exit(1);
           }
       } else {
           SECU_FileToItem(&envmsg, encryptOptions.envFile);
           decodeOptions.options = &options;
           encryptOptions.envmsg = decode(NULL, &envmsg, &decodeOptions);
           if (encryptOptions.envmsg == NULL) {
              SECU_PrintError(progName, "problem decrypting env msg");
              exitstatus = 1;
              break;
           }
       }
       rv = get_enc_params(&encryptOptions);
       /* create the encrypted-data message */
       cmsg = encrypted_data(&encryptOptions);
       if (!cmsg) {
           SECU_PrintError(progName, "problem encrypting");
           exitstatus = 1;
       }
       if (encryptOptions.bulkkey) {
           PK11_FreeSymKey(encryptOptions.bulkkey);
           encryptOptions.bulkkey = NULL;
       }
       break;
    case ENVELOPE:     /* -E */
       envelopeOptions.options = &options;
       cmsg = enveloped_data(&envelopeOptions);
       if (!cmsg) {
           SECU_PrintError(progName, "problem enveloping");
           exitstatus = 1;
       }
       break;
    case CERTSONLY:    /* -O */
       certsonlyOptions.options = &options;
       cmsg = signed_data_certsonly(&certsonlyOptions);
       if (!cmsg) {
           SECU_PrintError(progName, "problem with certs-only");
           exitstatus = 1;
       }
       break;
    default:
       fprintf(stderr, "One of options -D, -S or -E must be set.\n");
       Usage(progName);
       exitstatus = 1;
    }
    if ( (mode == SIGN || mode == ENVELOPE || mode == CERTSONLY)
         && (!exitstatus) ) {
       PLArenaPool *arena = PORT_NewArena(1024);
       NSSCMSEncoderContext *ecx;
       SECItem output = { 0, 0, 0 };

       if (!arena) {
           fprintf(stderr, "%s: out of memory.\n", progName);
           exit(1);
       }

       if (cms_verbose) {
           fprintf(stderr, "cmsg [%p]\n", cmsg);
           fprintf(stderr, "arena [%p]\n", arena);
           if (pwcb_arg)
              fprintf(stderr, "password [%s]\n", (char *)pwcb_arg);
           else
              fprintf(stderr, "password [NULL]\n");
       }
       ecx = NSS_CMSEncoder_Start(cmsg, 
                                   NULL, NULL,     /* DER output callback  */
                                   &output, arena, /* destination storage  */
                                   pwcb, pwcb_arg, /* password callback    */
                                   NULL, NULL,     /* decrypt key callback */
                                   NULL, NULL );   /* detached digests    */
       if (!ecx) {
           fprintf(stderr, "%s: cannot create encoder context.\n", progName);
           exit(1);
       }
       if (cms_verbose) {
           fprintf(stderr, "input len [%d]\n", input.len);
           { unsigned int j; 
              for(j=0;j<input.len;j++)
            fprintf(stderr, "%2x%c", input.data[j], (j>0&&j%35==0)?'\n':' ');
           }
       }
       if (input.len > 0) { /* skip if certs-only (or other zero content) */
           rv = NSS_CMSEncoder_Update(ecx, (char *)input.data, input.len);
           if (rv) {
              fprintf(stderr, 
                      "%s: failed to add data to encoder.\n", progName);
              exit(1);
           }
       }
       rv = NSS_CMSEncoder_Finish(ecx);
       if (rv) {
            SECU_PrintError(progName, "failed to encode data");
           exit(1);
       }

       if (cms_verbose) {
           fprintf(stderr, "encoding passed\n");
       }
       fwrite(output.data, output.len, 1, outFile);
       if (cms_verbose) {
           fprintf(stderr, "wrote to file\n");
       }
       PORT_FreeArena(arena, PR_FALSE);
    }
    if (cmsg)
       NSS_CMSMessage_Destroy(cmsg);
    if (outFile != stdout)
       fclose(outFile);

    SECITEM_FreeItem(&decodeOptions.content, PR_FALSE);
    SECITEM_FreeItem(&envmsg, PR_FALSE);
    SECITEM_FreeItem(&input, PR_FALSE);
    if (NSS_Shutdown() != SECSuccess) {
       SECU_PrintError(progName, "NSS_Shutdown failed");
       exitstatus = 1;
    }
    PR_Cleanup();
    return exitstatus;
}

Here is the call graph for this function:

int nss_CMSArray_Count ( void **  array)

Definition at line 78 of file cmsutil.c.

{
    int n = 0;
    if (array == NULL)
       return 0;
    while (*array++ != NULL)
       n++;
    return n;
}
static char* pl_fgets ( char *  buf,
int  size,
PRFileDesc fd 
) [static]

Definition at line 985 of file cmsutil.c.

{
    char * bp = buf;
    int    nb = 0;;

    while (size > 1) {
       nb = PR_Read(fd, bp, 1);
       if (nb < 0) {
           /* deal with error */
           return NULL;
       } else if (nb == 0) {
           /* deal with EOF */
           return NULL;
       } else if (*bp == '\n') {
           /* deal with EOL */
           ++bp;  /* keep EOL character */
           break;
       } else {
           /* ordinary character */
           ++bp;
           --size;
       }
    }
    *bp = '\0';
    return buf;
}

Here is the caller graph for this function:

static NSSCMSMessage* signed_data ( struct signOptionsStr signOptions) [static]

Definition at line 421 of file cmsutil.c.

{
    NSSCMSMessage *cmsg = NULL;
    NSSCMSContentInfo *cinfo;
    NSSCMSSignedData *sigd;
    NSSCMSSignerInfo *signerinfo;
    CERTCertificate *cert= NULL, *ekpcert = NULL;

    if (cms_verbose) {
       fprintf(stderr, "Input to signed_data:\n");
       if (signOptions->options->password)
           fprintf(stderr, "password [%s]\n", signOptions->options->password);
       else
           fprintf(stderr, "password [NULL]\n");
       fprintf(stderr, "certUsage [%d]\n", signOptions->options->certUsage);
       if (signOptions->options->certHandle)
           fprintf(stderr, "certdb [%p]\n", signOptions->options->certHandle);
       else
           fprintf(stderr, "certdb [NULL]\n");
       if (signOptions->nickname)
           fprintf(stderr, "nickname [%s]\n", signOptions->nickname);
       else
           fprintf(stderr, "nickname [NULL]\n");
    }
    if (signOptions->nickname == NULL) {
       fprintf(stderr, 
        "ERROR: please indicate the nickname of a certificate to sign with.\n");
       return NULL;
    }
    if ((cert = CERT_FindUserCertByUsage(signOptions->options->certHandle, 
                                         signOptions->nickname,
                                         signOptions->options->certUsage,
                                         PR_FALSE,
                                         &pwdata)) == NULL) {
       SECU_PrintError(progName, 
                       "the corresponding cert for key \"%s\" does not exist",
                       signOptions->nickname);
       return NULL;
    }
    if (cms_verbose) {
       fprintf(stderr, "Found certificate for %s\n", signOptions->nickname);
    }
    /*
     * 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 NULL;
    }
    /*
     * build chain of objects: message->signedData->data
     */
    if ((sigd = NSS_CMSSignedData_Create(cmsg)) == NULL) {
       fprintf(stderr, "ERROR: cannot create CMS signedData object.\n");
       goto loser;
    }
    cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
    if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) 
          != SECSuccess) {
       fprintf(stderr, "ERROR: cannot attach CMS signedData object.\n");
       goto loser;
    }
    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");
       goto loser;
    }
    /* 
     * create & attach signer information
     */
    signerinfo = NSS_CMSSignerInfo_Create(cmsg, cert, signOptions->hashAlgTag);
    if (signerinfo == NULL) {
       fprintf(stderr, "ERROR: cannot create CMS signerInfo object.\n");
       goto loser;
    }
    if (cms_verbose) {
       fprintf(stderr,
               "Created CMS message, added signed data w/ signerinfo\n");
    }
    /* we want the cert chain included for this one */
    if (NSS_CMSSignerInfo_IncludeCerts(signerinfo, NSSCMSCM_CertChain, 
                                       signOptions->options->certUsage) 
          != SECSuccess) {
       fprintf(stderr, "ERROR: cannot find cert chain.\n");
       goto loser;
    }
    if (cms_verbose) {
       fprintf(stderr, "imported certificate\n");
    }
    if (signOptions->signingTime) {
       if (NSS_CMSSignerInfo_AddSigningTime(signerinfo, PR_Now()) 
             != SECSuccess) {
           fprintf(stderr, "ERROR: cannot add signingTime attribute.\n");
           goto loser;
       }
    }
    if (signOptions->smimeProfile) {
       if (NSS_CMSSignerInfo_AddSMIMECaps(signerinfo) != SECSuccess) {
           fprintf(stderr, "ERROR: cannot add SMIMECaps attribute.\n");
           goto loser;
       }
    }

    if (!signOptions->encryptionKeyPreferenceNick) {
       /* check signing cert for fitness as encryption cert */
        SECStatus FitForEncrypt = CERT_CheckCertUsage(cert,
                                                      certUsageEmailRecipient);

        if (SECSuccess == FitForEncrypt) {
            /* if yes, add signing cert as EncryptionKeyPreference */
            if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, cert, 
                                              signOptions->options->certHandle)
                  != SECSuccess) {
                fprintf(stderr, 
                    "ERROR: cannot add default SMIMEEncKeyPrefs attribute.\n");
                goto loser;
            }
            if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, cert, 
                                              signOptions->options->certHandle)
                  != SECSuccess) {
                fprintf(stderr, 
                    "ERROR: cannot add default MS SMIMEEncKeyPrefs attribute.\n");
                goto loser;
            }
        } else {
            /* this is a dual-key cert case, we need to look for the encryption
               certificate under the same nickname as the signing cert */
            /* get the cert, add it to the message */
            if ((ekpcert = CERT_FindUserCertByUsage(
                                              signOptions->options->certHandle,
                                              signOptions->nickname,
                                              certUsageEmailRecipient,
                                              PR_FALSE,
                                              &pwdata)) == NULL) {
                SECU_PrintError(progName, 
                         "the corresponding cert for key \"%s\" does not exist",
                         signOptions->encryptionKeyPreferenceNick);
                goto loser;
            }
            if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert, 
                                              signOptions->options->certHandle)
                  != SECSuccess) {
                fprintf(stderr, 
                        "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
                goto loser;
            }
            if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ekpcert, 
                                              signOptions->options->certHandle)
                  != SECSuccess) {
                fprintf(stderr, 
                        "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
                goto loser;
            }
            if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
                fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
                goto loser;
            }
        }
    } else if (PL_strcmp(signOptions->encryptionKeyPreferenceNick, "NONE") == 0) {
        /* No action */
    } else {
       /* get the cert, add it to the message */
       if ((ekpcert = CERT_FindUserCertByUsage(
                                     signOptions->options->certHandle, 
                                    signOptions->encryptionKeyPreferenceNick,
                                     certUsageEmailRecipient, PR_FALSE, &pwdata))
             == NULL) {
           SECU_PrintError(progName, 
                      "the corresponding cert for key \"%s\" does not exist",
                       signOptions->encryptionKeyPreferenceNick);
           goto loser;
       }
       if (NSS_CMSSignerInfo_AddSMIMEEncKeyPrefs(signerinfo, ekpcert, 
                                            signOptions->options->certHandle)
             != SECSuccess) {
           fprintf(stderr, "ERROR: cannot add SMIMEEncKeyPrefs attribute.\n");
           goto loser;
       }
       if (NSS_CMSSignerInfo_AddMSSMIMEEncKeyPrefs(signerinfo, ekpcert, 
                                            signOptions->options->certHandle)
             != SECSuccess) {
           fprintf(stderr, "ERROR: cannot add MS SMIMEEncKeyPrefs attribute.\n");
           goto loser;
       }
       if (NSS_CMSSignedData_AddCertificate(sigd, ekpcert) != SECSuccess) {
           fprintf(stderr, "ERROR: cannot add encryption certificate.\n");
           goto loser;
       }
    }

    if (NSS_CMSSignedData_AddSignerInfo(sigd, signerinfo) != SECSuccess) {
       fprintf(stderr, "ERROR: cannot add CMS signerInfo object.\n");
       goto loser;
    }
    if (cms_verbose) {
       fprintf(stderr, "created signed-data message\n");
    }
    if (ekpcert) {
       CERT_DestroyCertificate(ekpcert);
    }
    if (cert) {
       CERT_DestroyCertificate(cert);
    }
    return cmsg;
loser:
    if (ekpcert) {
       CERT_DestroyCertificate(ekpcert);
    }
    if (cert) {
       CERT_DestroyCertificate(cert);
    }
    NSS_CMSMessage_Destroy(cmsg);
    return NULL;
}

Here is the call graph for this function:

static NSSCMSMessage* signed_data_certsonly ( struct certsonlyOptionsStr certsonlyOptions) [static]

Definition at line 895 of file cmsutil.c.

{
    NSSCMSMessage *cmsg = NULL;
    NSSCMSContentInfo *cinfo;
    NSSCMSSignedData *sigd;
    CERTCertificate **certs = NULL;
    CERTCertDBHandle *dbhandle;
    PLArenaPool *tmppoolp = NULL;
    int i = 0, cnt;
    dbhandle = certsonlyOptions->options->certHandle;
    if ((cnt = nss_CMSArray_Count((void**)certsonlyOptions->recipients)) == 0) {
       fprintf(stderr, 
        "ERROR: please indicate the nickname of a certificate to sign with.\n");
       goto loser;
    }
    if (!(tmppoolp = PORT_NewArena(1024))) {
       fprintf(stderr, "ERROR: out of memory.\n");
       goto loser;
    }
    if (!(certs = PORT_ArenaZNewArray(tmppoolp, CERTCertificate *, cnt + 1))) {
       fprintf(stderr, "ERROR: out of memory.\n");
       goto loser;
    }
    for (i=0; certsonlyOptions->recipients[i] != NULL; i++) {
       if ((certs[i] = 
             CERT_FindCertByNicknameOrEmailAddr(dbhandle,
                                             certsonlyOptions->recipients[i]))
               == NULL) {
           SECU_PrintError(progName, "cannot find certificate for \"%s\"", 
                           certsonlyOptions->recipients[i]);
           i=0;
           goto loser;
       }
    }
    certs[i] = NULL;
    i=0;
    /*
     * create the message object
     */
    cmsg = NSS_CMSMessage_Create(NULL);
    if (cmsg == NULL) {
       fprintf(stderr, "ERROR: cannot create CMS message.\n");
       goto loser;
    }
    /*
     * build chain of objects: message->signedData->data
     */
    if ((sigd = NSS_CMSSignedData_CreateCertsOnly(cmsg, certs[0], PR_TRUE))
          == NULL) {
       fprintf(stderr, "ERROR: cannot create CMS signedData object.\n");
       goto loser;
    }
    CERT_DestroyCertificate(certs[0]);
    for (i=1; i<cnt; i++) {
       if (NSS_CMSSignedData_AddCertChain(sigd, certs[i])) {
           fprintf(stderr, "ERROR: cannot add cert chain for \"%s\".\n",
                   certsonlyOptions->recipients[i]);
           goto loser;
       }
       CERT_DestroyCertificate(certs[i]);
    }
    cinfo = NSS_CMSMessage_GetContentInfo(cmsg);
    if (NSS_CMSContentInfo_SetContent_SignedData(cmsg, cinfo, sigd) 
          != SECSuccess) {
       fprintf(stderr, "ERROR: cannot attach CMS signedData object.\n");
       goto loser;
    }
    cinfo = NSS_CMSSignedData_GetContentInfo(sigd);
    if (NSS_CMSContentInfo_SetContent_Data(cmsg, cinfo, NULL, PR_FALSE) 
          != SECSuccess) {
       fprintf(stderr, "ERROR: cannot attach CMS data object.\n");
       goto loser;
    }
    if (tmppoolp)
       PORT_FreeArena(tmppoolp, PR_FALSE);
    return cmsg;
loser:
    if (certs) {
       for (; i<cnt; i++) {
           CERT_DestroyCertificate(certs[i]);
       }
    }
    if (cmsg)
       NSS_CMSMessage_Destroy(cmsg);
    if (tmppoolp)
       PORT_FreeArena(tmppoolp, PR_FALSE);
    return NULL;
}

Here is the call graph for this function:

static void Usage ( char *  progName) [static]

Definition at line 107 of file cmsutil.c.

{
    fprintf(stderr, 
"Usage:  %s [-C|-D|-E|-O|-S] [<options>] [-d dbdir] [-u certusage]\n"
" -C            create a CMS encrypted data message\n"
" -D            decode a CMS message\n"
"  -b           decode a batch of files named in infile\n"
"  -c content   use this detached content\n"
"  -n           suppress output of content\n"
"  -h num       display num levels of CMS message info as email headers\n"
"  -k           keep decoded encryption certs in perm cert db\n"
" -E            create a CMS enveloped data message\n"
"  -r id,...    create envelope for these recipients,\n"
"               where id can be a certificate nickname or email address\n"
" -S            create a CMS signed data message\n"
"  -G           include a signing time attribute\n"
"  -H hash      use hash (default:SHA1)\n"
"  -N nick      use certificate named \"nick\" for signing\n"
"  -P           include a SMIMECapabilities attribute\n"
"  -T           do not include content in CMS message\n"
"  -Y nick      include a EncryptionKeyPreference attribute with cert\n"
"                 (use \"NONE\" to omit)\n"
" -O            create a CMS signed message containing only certificates\n"
" General Options:\n"
" -d dbdir      key/cert database directory (default: ~/.netscape)\n"
" -e envelope   enveloped data message in this file is used for bulk key\n"
" -i infile     use infile as source of data (default: stdin)\n"
" -o outfile    use outfile as destination of data (default: stdout)\n"
" -p password   use password as key db password (default: prompt)\n"
" -u certusage  set type of certificate usage (default: certUsageEmailSigner)\n"
" -v            print debugging information\n"
"\n"
"Cert usage codes:\n",
           progName);
    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);
}

Here is the call graph for this function:


Variable Documentation

int cms_verbose = 0 [static]

Definition at line 68 of file cmsutil.c.

char* progName = NULL

Definition at line 67 of file cmsutil.c.

Definition at line 70 of file cmsutil.c.

void* pwcb_arg = NULL [static]

Definition at line 71 of file cmsutil.c.

secuPWData pwdata = { PW_NONE, 0 } [static]

Definition at line 69 of file cmsutil.c.