Make the PKCS#7 S/MIME functions check for passed NULL pointers.
authorDr. Stephen Henson <steve@openssl.org>
Thu, 9 Dec 1999 01:31:32 +0000 (01:31 +0000)
committerDr. Stephen Henson <steve@openssl.org>
Thu, 9 Dec 1999 01:31:32 +0000 (01:31 +0000)
Fix the usage message of smime utility and sanitise the return
codes.

Add some documentation.

apps/smime.c
crypto/pkcs7/pk7_smime.c
crypto/pkcs7/pkcs7.h
crypto/pkcs7/pkcs7err.c
doc/man/smime.pod [new file with mode: 0644]

index 0d713a5..f87b419 100644 (file)
@@ -136,6 +136,8 @@ int MAIN(int argc, char **argv)
                                flags &= ~PKCS7_DETACHED;
                else if (!strcmp (*args, "-binary"))
                                flags |= PKCS7_BINARY;
+               else if (!strcmp (*args, "-nosigs"))
+                               flags |= PKCS7_NOSIGS;
                else if (!strcmp (*args, "-to")) {
                        if (args[1]) {
                                args++;
@@ -224,6 +226,13 @@ int MAIN(int argc, char **argv)
                BIO_printf (bio_err, "-rc2-40        encrypt with RC2-40\n");
                BIO_printf (bio_err, "-rc2-64        encrypt with RC2-64\n");
                BIO_printf (bio_err, "-rc2-128       encrypt with RC2-128\n");
+               BIO_printf (bio_err, "-nointern      don't search certificates in message for signer\n");
+               BIO_printf (bio_err, "-nosigs        don't verify message signature\n");
+               BIO_printf (bio_err, "-noverify      don't verify signers certificate\n");
+               BIO_printf (bio_err, "-nocerts       don't include signers certificate when signing\n");
+               BIO_printf (bio_err, "-nodetach      use opaque signing\n");
+               BIO_printf (bio_err, "-noattr        don't include any signed attributes\n");
+               BIO_printf (bio_err, "-binary        don't translate message to text\n");
                BIO_printf (bio_err, "-in file       input file\n");
                BIO_printf (bio_err, "-certfile file other certificates file\n");
                BIO_printf (bio_err, "-signer file   signer certificate file\n");
@@ -235,6 +244,8 @@ int MAIN(int argc, char **argv)
                BIO_printf (bio_err, "-from ad       from address\n");
                BIO_printf (bio_err, "-subject s     subject\n");
                BIO_printf (bio_err, "-text          include or delete text MIME headers\n");
+               BIO_printf (bio_err, "-CApath dir    trusted certificates directory\n");
+               BIO_printf (bio_err, "-CAfile file   trusted certificates file\n");
                BIO_printf (bio_err, "cert.pem       recipient certificate(s)\n");
                goto end;
        }
@@ -319,6 +330,7 @@ int MAIN(int argc, char **argv)
                if(!(store = setup_verify(CAfile, CApath))) goto end;
 
        ret = 3;
+
        if(operation == SMIME_ENCRYPT) {
                p7 = PKCS7_encrypt(encerts, in, cipher, flags);
        } else if(operation == SMIME_SIGN) {
@@ -327,34 +339,35 @@ int MAIN(int argc, char **argv)
        } else {
                if(!(p7 = SMIME_read_PKCS7(in, &indata))) {
                        BIO_printf(bio_err, "Error reading S/MIME message\n");
-                       ret = 4;
                        goto end;
                }
        }
-                       
+
        if(!p7) {
                BIO_printf(bio_err, "Error creating PKCS#7 structure\n");
                goto end;
        }
 
+       ret = 4;
        if(operation == SMIME_DECRYPT) {
-               if(!PKCS7_decrypt(p7, key, recip, out, flags))
+               if(!PKCS7_decrypt(p7, key, recip, out, flags)) {
                        BIO_printf(bio_err, "Error decrypting PKCS#7 structure\n");
-               else ret = 0;
+                       goto end;
+               }
        } else if(operation == SMIME_VERIFY) {
                STACK_OF(X509) *signers;
                signers = PKCS7_iget_signers(p7, other, flags);
                if(PKCS7_verify(p7, other, store, indata, out, flags)) {
                        BIO_printf(bio_err, "Verification Successful\n");
-                       ret = 0;
                } else {
                        BIO_printf(bio_err, "Verification Failure\n");
-                       ret = 5;
+                       goto end;
                }
                if(!save_certs(signerfile, signers)) {
                        BIO_printf(bio_err, "Error writing signers to %s\n",
                                                                signerfile);
-                       ret = 2;
+                       ret = 5;
+                       goto end;
                }
                sk_X509_free(signers);
        } else if(operation == SMIME_PK7OUT) {
@@ -365,6 +378,7 @@ int MAIN(int argc, char **argv)
                if(subject) BIO_printf(out, "Subject: %s\n", subject);
                SMIME_write_PKCS7(out, p7, in, flags);
        }
+       ret = 0;
 end:
        if(ret) ERR_print_errors(bio_err);
        sk_X509_pop_free(encerts, X509_free);
index 3f6cad4..4b557f4 100644 (file)
@@ -150,14 +150,19 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
        BIO *p7bio;
        BIO *tmpout;
 
+       if(!p7) {
+               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_INVALID_NULL_POINTER);
+               return NULL;
+       }
+
        if(!PKCS7_type_is_signed(p7)) {
-                               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
+               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_WRONG_CONTENT_TYPE);
                return 0;
        }
 
        /* Check for no data and no content: no data to verify signature */
        if(PKCS7_get_detached(p7) && !indata) {
-                               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
+               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_CONTENT);
                return 0;
        }
 
@@ -170,7 +175,7 @@ int PKCS7_verify(PKCS7 *p7, STACK_OF(X509) *certs, X509_STORE *store,
        sinfos = PKCS7_get_signer_info(p7);
 
        if(!sinfos || !sk_PKCS7_SIGNER_INFO_num(sinfos)) {
-                               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
+               PKCS7err(PKCS7_F_PKCS7_VERIFY,PKCS7_R_NO_SIGNATURES_ON_DATA);
                return 0;
        }
 
@@ -264,6 +269,11 @@ STACK_OF(X509) *PKCS7_iget_signers(PKCS7 *p7, STACK_OF(X509) *certs, int flags)
        X509 *signer;
        int i;
 
+       if(!p7) {
+               PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_INVALID_NULL_POINTER);
+               return NULL;
+       }
+
        if(!PKCS7_type_is_signed(p7)) {
                PKCS7err(PKCS7_F_PKCS7_IGET_SIGNERS,PKCS7_R_WRONG_CONTENT_TYPE);
                return NULL;
@@ -376,10 +386,17 @@ int PKCS7_decrypt(PKCS7 *p7, EVP_PKEY *pkey, X509 *cert, BIO *data, int flags)
        BIO *tmpmem;
        int ret, i;
        char buf[4096];
+
+       if(!p7) {
+               PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_INVALID_NULL_POINTER);
+               return 0;
+       }
+
        if(!PKCS7_type_is_enveloped(p7)) {
                PKCS7err(PKCS7_F_PKCS7_DECRYPT,PKCS7_R_WRONG_CONTENT_TYPE);
                return 0;
        }
+
        if(!X509_check_private_key(cert, pkey)) {
                PKCS7err(PKCS7_F_PKCS7_DECRYPT,
                                PKCS7_R_PRIVATE_KEY_DOES_NOT_MATCH_CERTIFICATE);
index 7369e32..63a97e1 100644 (file)
@@ -455,6 +455,7 @@ int SMIME_text(BIO *in, BIO *out);
 #define PKCS7_R_ERROR_SETTING_CIPHER                    121
 #define PKCS7_R_INTERNAL_ERROR                          102
 #define PKCS7_R_INVALID_MIME_TYPE                       131
+#define PKCS7_R_INVALID_NULL_POINTER                    143
 #define PKCS7_R_MIME_NO_CONTENT_TYPE                    132
 #define PKCS7_R_MIME_PARSE_ERROR                        133
 #define PKCS7_R_MIME_SIG_PARSE_ERROR                    134
index d0a1f59..d8491ff 100644 (file)
@@ -105,6 +105,7 @@ static ERR_STRING_DATA PKCS7_str_reasons[]=
 {PKCS7_R_ERROR_SETTING_CIPHER            ,"error setting cipher"},
 {PKCS7_R_INTERNAL_ERROR                  ,"internal error"},
 {PKCS7_R_INVALID_MIME_TYPE               ,"invalid mime type"},
+{PKCS7_R_INVALID_NULL_POINTER            ,"invalid null pointer"},
 {PKCS7_R_MIME_NO_CONTENT_TYPE            ,"mime no content type"},
 {PKCS7_R_MIME_PARSE_ERROR                ,"mime parse error"},
 {PKCS7_R_MIME_SIG_PARSE_ERROR            ,"mime sig parse error"},
diff --git a/doc/man/smime.pod b/doc/man/smime.pod
new file mode 100644 (file)
index 0000000..6ec5640
--- /dev/null
@@ -0,0 +1,241 @@
+=pod
+
+=head1 NAME
+
+smime - S/MIME utility
+
+=head1 SYNOPSIS
+
+B<openssl> B<smime>
+[B<-encrypt>]
+[B<-decrypt>]
+[B<-sign>]
+[B<-verify>]
+[B<-pk7out>]
+[B<-des3>]
+[B<-rc2-40>]
+[B<-rc2-64>]
+[B<-rc2-128>]
+[B<-in file>]
+[B<-certfile file>]
+[B<-signer file>]
+[B<-recip  file>]
+[B<-in file>]
+[B<-inkey file>]
+[B<-out file>]
+[B<-to addr>]
+[B<-from ad>]
+[B<-subject s>]
+[B<-text>]
+[cert.pem]...
+
+=head1 DESCRIPTION
+
+The B<smime> command handles S/MIME mail. It can encrypt, decrypt, sign and
+verify S/MIME messages.
+
+=head1 COMMAND OPTIONS
+
+There are five operation options that set the type of operation to be performed.
+The meaning of the other options varies according to the operation type.
+
+=over 4
+
+=item B<-encrypt>
+
+encrypt mail for the given recipient certificates. Input file is the message
+to be encrypted. The output file is the encrypted mail in MIME format.
+
+=item B<-decrypt>
+
+decrypt mail using the supplied certificate and private key. Expects an
+encrypted mail message in MIME format for the input file. The decrypted mail
+is written to the output file.
+
+=item B<-sign>
+
+sign mail using the supplied certificate and private key. Input file is
+the message to be signed. The signed message in MIME format is written
+to the output file.
+
+=item B<-verify>
+
+verify signed mail. Expects a signed mail message on input and outputs
+the signed data. Both clear text and opaque signing is supported.
+
+=item B<-pk7out>
+
+takes an input message and writes out a PEM encoded PKCS#7 structure.
+
+=item B<-in filename>
+
+the input message to be encrypted or signed or the MIME message to
+be decrypted or verified.
+
+=item B<-out filename>
+
+the message text that has been decrypted or verified or the output MIME
+format message that has been signed or verified.
+
+=item B<-text>
+
+this option adds plain text (text/plain) MIME headers to the supplied
+message if encrypting or signing. If decrypting or verifying it strips
+off text headers: if the decrypted or verified message is not of MIME 
+type text/plain then an error occurs.
+
+=item B<-CAfile file>
+
+a file containing trusted CA certificates, only used with B<-verify>.
+
+=item B<-CApath dir>
+
+a directory containing trusted CA certificates, only used with
+B<-verify>. This directory must be a standard certificate directory: that
+is a hash of each subject name (using B<x509 -hash>) should be linked
+to each certificate.
+
+=item B<-des3 -rc2-40 -rc2-64 -rc2-128>
+
+the encryption algorithm to use. DES (56 bits), triple DES (168 bits)
+or 40, 64 or 128 bit RC2 respectively if not specified 40 bit RC2 is
+used. Only used with B<-encrypt>.
+
+=item B<-nointern>
+
+when verifying a message normally certificates (if any) included in
+the message are searched for the signing certificate. With this option
+only the certificates specified in the B<-certfile> option are used.
+The supplied certificates can still be used as untrusted CAs however.
+
+=item B<-noverify>
+
+do not verify the signers certificate of a signed message.
+
+=item B<-nochain>
+
+do not do chain verification of signers certfificates: that is don't
+use the certificates in the signed message as untrusted CAs.
+
+=item B<-nosigs>
+
+don't try to verify the signatures on the message.
+
+=item B<-nocerts>
+
+when signing a message the signer's certificate is normally included
+with this option it is excluded. This will reduce the size of the
+signed message but the verifier must have a copy of the signers certificate
+available locally (passed using the B<-certfile> option for example).
+
+=item B<-noattr>
+
+normally when a message is signed a set of attributes are included which
+include the signing time and supported symmetric algorithms. With this
+option they are not included.
+
+=item B<-binary>
+
+normally the input message is converted to "canonical" format which is
+effectively using CR and LF as end of line. When this option is present
+no translation occurs. This is useful when handling binary data which may
+not be in MIME format.
+
+=item B<-nodetach>
+
+when signing a message use opaque signing: this form is more resistant
+to translation by mail relays but it cannot be read by mail agents that
+do not support S/MIME.  Without this option cleartext signing with
+the MIME type multipart/signed is used.
+
+=item B<-certfile file>
+
+allows additional certificates to be specified. When signing these will
+be included with the message. When verifying these will be searched for
+the signers certificates. The certificates should be in PEM format.
+
+=item B<-signer file>
+
+the signers certificate when signing a message. If a message is
+being verified then the signers certificates will be written to this
+file if the verification was successful.
+
+=item B<-recip file>
+
+the recipients certificate when decrypting a message. This certificate
+must match one of the recipients of the message or an error occurs.
+
+=item B<-inkey file>
+
+the private key to use when signing or decrypting. This must match the
+corresponding certificate. If this option is not specified then the
+private key must be included in the certificate file specified with
+the B<-recip> or B<-signer> file.
+
+=item B<cert.pem...>
+
+one or more certificates of message recipients: used when encrypting
+a message. 
+
+=item B<-to, -from, -subject>
+
+the relevant mail headers. These are included outside the signed
+portion of a message so they may be included manually. If signing
+then many S/MIME mail clients check the signers certificate's email
+address matches that specified in the From: address.
+
+=back
+
+=head1 NOTES
+
+The MIME message must be sent without any blank lines between the
+headers and the output. Some mail programs will automatically add
+a blank line. Piping the mail directly to sendmail is one way to
+achieve the correct format.
+
+A "signed and encrypted" message is one where a signed message is
+then encrypted. This can be produced by encrypting an already signed
+message.
+
+This version of the program only allows one signer per message but it
+will verify multiple signers on received messages. Some S/MIME clients
+choke if a message contains mutiple signers. It is possible to sign
+messages "in parallel" by signing an already signed message.
+
+=head1 EXIT CODES
+
+=over 4
+
+=item 0
+
+the operation was completely successful
+
+=item 1 
+
+an error occurred parsing the command options.
+
+=item 2
+
+one of the input files could not be read.
+
+=item 3
+
+an error occurred creating the PKCS#7 file or when reading the MIME
+message.
+
+=item 4
+
+an error occurred decrypting or verifying the message.
+
+=item 5
+
+the message was verified correctly but an error occured writing out
+the signers certificates.
+
+=back
+
+=head1 EXAMPLES
+
+to be added.
+
+=cut