Some constification and stacks that slipped through the cracks (how?).
[openssl.git] / apps / pkcs12.c
index 96e0379fade98d1519ccafa492b5ffc668edad4e..1550c07240594da630e373fa8407689a160ea83e 100644 (file)
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <pem.h>
-#include <err.h>
-#include "pkcs12.h"
+#include <openssl/des.h>
+#include <openssl/pem.h>
+#include <openssl/err.h>
+#include <openssl/pkcs12.h>
 
 #include "apps.h"
 #define PROG pkcs12_main
 
 EVP_CIPHER *enc;
 
-#define _ITER_ 1000
 
 #define NOKEYS         0x1
 #define NOCERTS        0x2
@@ -76,29 +76,16 @@ EVP_CIPHER *enc;
 #define CLCERTS                0x8
 #define CACERTS                0x10
 
-#ifndef NOPROTO
-int get_cert_chain(X509 *cert, STACK **chain);
-int dump_certs_keys_p12(BIO *out, PKCS12 *p12, unsigned char *pass, int passlen, int options);
-int dump_certs_pkeys_bags(BIO *out, STACK *bags, unsigned char *pass, int passlen, int options);
-int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, unsigned char *pass, int passlen, int options);
-int print_attribs(BIO *out, STACK *attrlst, char *name);
+int get_cert_chain(X509 *cert, STACK_OF(X509) **chain);
+int dump_cert_text (BIO *out, X509 *x);
+int dump_certs_keys_p12(BIO *out, PKCS12 *p12, char *pass, int passlen, int options);
+int dump_certs_pkeys_bags(BIO *out, STACK *bags, char *pass, int passlen, int options);
+int dump_certs_pkeys_bag(BIO *out, PKCS12_SAFEBAG *bags, char *pass, int passlen, int options);
+int print_attribs(BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, char *name);
 void hex_prin(BIO *out, unsigned char *buf, int len);
 int alg_print(BIO *x, X509_ALGOR *alg);
-int cert_load(BIO *in, STACK *sk);
-#else
-int get_cert_chain();
-int dump_certs_keys_p12();
-int dump_certs_pkeys_bags();
-int dump_certs_pkeys_bag();
-int print_attribs();
-void hex_prin();
-int alg_print();
-int cert_load();
-#endif
-
-int MAIN(argc, argv)
-int argc;
-char **argv;
+int cert_load(BIO *in, STACK_OF(X509) *sk);
+int MAIN(int argc, char **argv)
 {
     char *infile=NULL, *outfile=NULL, *keyname = NULL; 
     char *certfile=NULL;
@@ -111,14 +98,16 @@ char **argv;
     int options = 0;
     int chain = 0;
     int badarg = 0;
-    int iter = _ITER_;
+    int iter = PKCS12_DEFAULT_ITER;
     int maciter = 1;
     int twopass = 0;
     int keytype = 0;
     int cert_pbe = NID_pbe_WithSHA1And40BitRC2_CBC;
     int ret = 1;
     int macver = 1;
+    int noprompt = 0;
     STACK *canames = NULL;
+    char *cpass = NULL, *mpass = NULL;
 
     apps_startup();
 
@@ -150,7 +139,8 @@ char **argv;
 #endif
                else if (!strcmp (*args, "-des3")) enc = EVP_des_ede3_cbc();
                else if (!strcmp (*args, "-noiter")) iter = 1;
-               else if (!strcmp (*args, "-maciter")) maciter = _ITER_;
+               else if (!strcmp (*args, "-maciter"))
+                                        maciter = PKCS12_DEFAULT_ITER;
                else if (!strcmp (*args, "-nodes")) enc=NULL;
                else if (!strcmp (*args, "-inkey")) {
                    if (args[1]) {
@@ -183,6 +173,22 @@ char **argv;
                        args++; 
                        outfile = *args;
                    } else badarg = 1;
+               } else if (!strcmp (*args, "-envpass")) {
+                   if (args[1]) {
+                       args++; 
+                       if(!(cpass = getenv(*args))) {
+                               BIO_printf(bio_err,
+                                "Can't read environment variable %s\n", *args);
+                               goto end;
+                       }
+                       noprompt = 1;
+                   } else badarg = 1;
+               } else if (!strcmp (*args, "-password")) {
+                   if (args[1]) {
+                       args++; 
+                       cpass = *args;
+                       noprompt = 1;
+                   } else badarg = 1;
                } else badarg = 1;
 
        } else badarg = 1;
@@ -219,9 +225,17 @@ char **argv;
        BIO_printf (bio_err, "-descert      encrypt PKCS#12 certificates with triple DES (default RC2-40)\n");
        BIO_printf (bio_err, "-keyex        set MS key exchange type\n");
        BIO_printf (bio_err, "-keysig       set MS key signature type\n");
+       BIO_printf (bio_err, "-password p   set import/export password (NOT RECOMMENDED)\n");
+       BIO_printf (bio_err, "-envpass p    set import/export password from environment\n");
        goto end;
     }
 
+    if(cpass) mpass = cpass;
+    else {
+       cpass = pass;
+       mpass = macpass;
+    }
+
     ERR_load_crypto_strings();
 
     in = BIO_new (BIO_s_file());
@@ -272,11 +286,11 @@ if (export_cert) {
        PKCS8_PRIV_KEY_INFO *p8;
        PKCS7 *authsafe;
        X509 *cert, *ucert = NULL;
-       STACK *certs;
+       STACK_OF(X509) *certs;
        char *catmp;
        int i, pmatch = 0;
        unsigned char keyid[EVP_MAX_MD_SIZE];
-       int keyidlen;
+       unsigned int keyidlen;
        /* Get private key so we can match it to a certificate */
        key = PEM_read_bio_PrivateKey(inkey ? inkey : in, NULL, NULL);
        if (!inkey) BIO_reset(in);
@@ -286,7 +300,7 @@ if (export_cert) {
                goto end;
        }
 
-       certs = sk_new(NULL);
+       certs = sk_X509_new(NULL);
 
        /* Load in all certs in input file */
        if(!cert_load(in, certs)) {
@@ -309,8 +323,8 @@ if (export_cert) {
 
        /* Find certificate (if any) matching private key */
 
-       for(i = 0; i < sk_num(certs); i++) {
-                       cert = (X509 *)sk_value(certs, i);
+       for(i = 0; i < sk_X509_num(certs); i++) {
+                       cert = sk_X509_value(certs, i);
                        if(X509_check_private_key(cert, key)) {
                                ucert = cert;
                                break;
@@ -325,7 +339,7 @@ if (export_cert) {
        /* If chaining get chain from user cert */
        if (chain) {
                int vret;
-               STACK *chain2;
+               STACK_OF(X509) *chain2;
                        
                vret = get_cert_chain (ucert, &chain2);
                if (vret) {
@@ -334,15 +348,15 @@ if (export_cert) {
                        goto end;
                }
                /* Exclude verified certificate */
-               for (i = 1; i < sk_num (chain2) ; i++) 
-                                sk_push(certs, sk_value (chain2, i));
-               sk_free(chain2);
+               for (i = 1; i < sk_X509_num (chain2) ; i++) 
+                                sk_X509_push(certs, sk_X509_value (chain2, i));
+               sk_X509_free(chain2);
                        
        }
 
        /* We now have loads of certificates: include them all */
-       for(i = 0; i < sk_num(certs); i++) {
-               cert = (X509 *)sk_value(certs, i);
+       for(i = 0; i < sk_X509_num(certs); i++) {
+               cert = sk_X509_value(certs, i);
                bag = M_PKCS12_x5092certbag(cert);
                /* If it matches private key mark it */
                if(cert == ucert) {
@@ -357,13 +371,14 @@ if (export_cert) {
 
        if (canames) sk_free(canames);
 
-       if(EVP_read_pw_string (pass, 50, "Enter Export Password:", 1)) {
+       if(!noprompt &&
+               EVP_read_pw_string(pass, 50, "Enter Export Password:", 1)) {
            BIO_printf (bio_err, "Can't read Password\n");
            goto end;
         }
        if (!twopass) strcpy(macpass, pass);
        /* Turn certbags into encrypted authsafe */
-       authsafe = PKCS12_pack_p7encdata (cert_pbe, pass, -1, NULL, 0,
+       authsafe = PKCS12_pack_p7encdata (cert_pbe, cpass, -1, NULL, 0,
                                                                 iter, bags);
        sk_pop_free(bags, PKCS12_SAFEBAG_free);
 
@@ -380,10 +395,10 @@ if (export_cert) {
        EVP_PKEY_free(key);
        if(keytype) PKCS8_add_keyusage(p8, keytype);
        bag = PKCS12_MAKE_SHKEYBAG (NID_pbe_WithSHA1And3_Key_TripleDES_CBC,
-                       pass, -1, NULL, 0, iter, p8);
+                       cpass, -1, NULL, 0, iter, p8);
        PKCS8_PRIV_KEY_INFO_free(p8);
         if (name) PKCS12_add_friendlyname (bag, name, -1);
-       PKCS12_add_localkeyid (bag, keyid, keyidlen);
+       if(pmatch) PKCS12_add_localkeyid (bag, keyid, keyidlen);
        bags = sk_new(NULL);
        sk_push (bags, (char *)bag);
        /* Turn it into unencrypted safe bag */
@@ -397,7 +412,7 @@ if (export_cert) {
 
        sk_pop_free(safes, PKCS7_free);
 
-       PKCS12_set_mac (p12, macpass, -1, NULL, 0, maciter, NULL);
+       PKCS12_set_mac (p12, mpass, -1, NULL, 0, maciter, NULL);
 
        i2d_PKCS12_bio (out, p12);
 
@@ -406,14 +421,14 @@ if (export_cert) {
        ret = 0;
        goto end;
        
-}
+    }
 
     if (!(p12 = d2i_PKCS12_bio (in, NULL))) {
        ERR_print_errors(bio_err);
        goto end;
     }
 
-    if(EVP_read_pw_string (pass, 50, "Enter Import Password:", 0)) {
+    if(!noprompt && EVP_read_pw_string(pass, 50, "Enter Import Password:", 0)) {
        BIO_printf (bio_err, "Can't read Password\n");
        goto end;
     }
@@ -422,14 +437,14 @@ if (export_cert) {
 
     if (options & INFO) BIO_printf (bio_err, "MAC Iteration %ld\n", p12->mac->iter ? ASN1_INTEGER_get (p12->mac->iter) : 1);
     if(macver) {
-       if (!PKCS12_verify_mac (p12, macpass, -1)) {
+       if (!PKCS12_verify_mac (p12, mpass, -1)) {
            BIO_printf (bio_err, "Mac verify errror: invalid password?\n");
            ERR_print_errors (bio_err);
            goto end;
        } else BIO_printf (bio_err, "MAC verified OK\n");
     }
 
-    if (!dump_certs_keys_p12 (out, p12, pass, -1, options)) {
+    if (!dump_certs_keys_p12 (out, p12, cpass, -1, options)) {
        BIO_printf(bio_err, "Error outputting keys and certificates\n");
        ERR_print_errors (bio_err);
        goto end;
@@ -437,12 +452,11 @@ if (export_cert) {
     PKCS12_free(p12);
     ret = 0;
     end:
+    BIO_free(out);
     EXIT(ret);
 }
 
-int dump_cert_text (out, x)
-BIO *out;
-X509 *x;
+int dump_cert_text (BIO *out, X509 *x)
 {
        char buf[256];
        X509_NAME_oneline(X509_get_subject_name(x),buf,256);
@@ -456,12 +470,8 @@ X509 *x;
         return 0;
 }
 
-int dump_certs_keys_p12 (out, p12, pass, passlen, options)
-BIO *out;
-PKCS12 *p12;
-unsigned char *pass;
-int passlen;
-int options;
+int dump_certs_keys_p12 (BIO *out, PKCS12 *p12, char *pass,
+            int passlen, int options)
 {
        STACK *asafes, *bags;
        int i, bagnid;
@@ -493,12 +503,8 @@ int options;
        return 1;
 }
 
-int dump_certs_pkeys_bags (out, bags, pass, passlen, options)
-BIO *out;
-STACK *bags;
-unsigned char *pass;
-int passlen;
-int options;
+int dump_certs_pkeys_bags (BIO *out, STACK *bags, char *pass,
+            int passlen, int options)
 {
        int i;
        for (i = 0; i < sk_num (bags); i++) {
@@ -509,12 +515,8 @@ int options;
        return 1;
 }
 
-int dump_certs_pkeys_bag (out, bag, pass, passlen, options)
-BIO *out;
-PKCS12_SAFEBAG *bag;
-unsigned char *pass;
-int passlen;
-int options;
+int dump_certs_pkeys_bag (BIO *out, PKCS12_SAFEBAG *bag, char *pass,
+            int passlen, int options)
 {
        EVP_PKEY *pkey;
        PKCS8_PRIV_KEY_INFO *p8;
@@ -584,13 +586,11 @@ int options;
 
 /* Hope this is OK .... */
 
-int get_cert_chain (cert, chain)
-X509 *cert;
-STACK **chain;
+int get_cert_chain (X509 *cert, STACK_OF(X509) **chain)
 {
        X509_STORE *store;
        X509_STORE_CTX store_ctx;
-       STACK *chn;
+       STACK_OF(X509) *chn;
        int i;
        X509 *x;
        store = X509_STORE_new ();
@@ -600,9 +600,9 @@ STACK **chain;
                i = X509_STORE_CTX_get_error (&store_ctx);
                goto err;
        }
-       chn =  sk_dup(X509_STORE_CTX_get_chain (&store_ctx));
-       for (i = 0; i < sk_num(chn); i++) {
-               x = (X509 *)sk_value(chn, i);
+       chn =  sk_X509_dup(X509_STORE_CTX_get_chain (&store_ctx));
+       for (i = 0; i < sk_X509_num(chn); i++) {
+               x = sk_X509_value(chn, i);
                CRYPTO_add(&x->references,1,CRYPTO_LOCK_X509);
        }
        i = 0;
@@ -614,9 +614,7 @@ err:
        return i;
 }      
 
-int alg_print (x, alg)
-BIO *x;
-X509_ALGOR *alg;
+int alg_print (BIO *x, X509_ALGOR *alg)
 {
        PBEPARAM *pbe;
        unsigned char *p;
@@ -630,16 +628,14 @@ X509_ALGOR *alg;
 
 /* Load all certificates from a given file */
 
-int cert_load(in, sk)
-BIO *in;
-STACK *sk;
+int cert_load(BIO *in, STACK_OF(X509) *sk)
 {
        int ret;
        X509 *cert;
        ret = 0;
        while((cert = PEM_read_bio_X509(in, NULL, NULL))) {
                ret = 1;
-               sk_push(sk, (char *)cert);
+               sk_X509_push(sk, cert);
        }
        if(ret) ERR_clear_error();
        return ret;
@@ -647,10 +643,7 @@ STACK *sk;
 
 /* Generalised attribute print: handle PKCS#8 and bag attributes */
 
-int print_attribs (out, attrlst, name)
-BIO *out;
-STACK *attrlst;
-char *name;
+int print_attribs (BIO *out, STACK_OF(X509_ATTRIBUTE) *attrlst, char *name)
 {
        X509_ATTRIBUTE *attr;
        ASN1_TYPE *av;
@@ -660,13 +653,13 @@ char *name;
                BIO_printf(out, "%s: <No Attributes>\n", name);
                return 1;
        }
-       if(!sk_num(attrlst)) {
+       if(!sk_X509_ATTRIBUTE_num(attrlst)) {
                BIO_printf(out, "%s: <Empty Attributes>\n", name);
                return 1;
        }
        BIO_printf(out, "%s\n", name);
-       for(i = 0; i < sk_num(attrlst); i++) {
-               attr = (X509_ATTRIBUTE *) sk_value(attrlst, i);
+       for(i = 0; i < sk_X509_ATTRIBUTE_num(attrlst); i++) {
+               attr = sk_X509_ATTRIBUTE_value(attrlst, i);
                attr_nid = OBJ_obj2nid(attr->object);
                BIO_printf(out, "    ");
                if(attr_nid == NID_undef) {
@@ -674,8 +667,8 @@ char *name;
                        BIO_printf(out, ": ");
                } else BIO_printf(out, "%s: ", OBJ_nid2ln(attr_nid));
 
-               if(sk_num(attr->value.set)) {
-                       av = (ASN1_TYPE *)sk_value(attr->value.set, 0);
+               if(sk_ASN1_TYPE_num(attr->value.set)) {
+                       av = sk_ASN1_TYPE_value(attr->value.set, 0);
                        switch(av->type) {
                                case V_ASN1_BMPSTRING:
                                value = uni2asc(av->value.bmpstring->data,
@@ -705,10 +698,7 @@ char *name;
        return 1;
 }
 
-void hex_prin(out, buf, len)
-BIO *out;
-unsigned char *buf;
-int len;
+void hex_prin(BIO *out, unsigned char *buf, int len)
 {
        int i;
        for (i = 0; i < len; i++) BIO_printf (out, "%02X ", buf[i]);