One feature wasn't quite commited yet
[openssl.git] / apps / apps.c
index ab30e53ba5c74f9c15dc8db29407986c370d2d8e..90159d5546a3fef8df338f2d628ca73d1b1b0fdb 100644 (file)
@@ -369,6 +369,57 @@ int dump_cert_text (BIO *out, X509 *x)
         return 0;
 }
 
+int password_callback(char *buf, int bufsiz, int verify,
+       PW_CB_DATA *cb_data)
+       {
+       int i,j;
+       char prompt[80];
+       const char *prompt_info = NULL;
+       const char *password = NULL;
+
+       if (cb_data)
+               {
+               if (cb_data->password)
+                       password = cb_data->password;
+               if (cb_data->prompt_info)
+                       prompt_info = cb_data->prompt_info;
+               }
+
+       if(password) {
+               i=strlen(password);
+               i=(i > bufsiz)?bufsiz:i;
+               memcpy(buf,password,i);
+               return(i);
+       }
+
+       if (EVP_get_pw_prompt())
+               BIO_snprintf(prompt, sizeof(prompt)-1, EVP_get_pw_prompt(),
+                       prompt_info ? prompt_info : "");
+       else
+               BIO_snprintf(prompt, sizeof(prompt)-1,
+                       "Enter pass phrase for %s:",
+                       prompt_info ? prompt_info : "");
+
+       for (;;)
+               {
+               i=EVP_read_pw_string(buf,bufsiz,prompt,verify);
+               if (i != 0)
+                       {
+                       BIO_printf(bio_err,"aborted!\n");
+                       memset(buf,0,(unsigned int)bufsiz);
+                       return(-1);
+                       }
+               j=strlen(buf);
+               if (j < PW_MIN_LENGTH)
+                       {
+                       BIO_printf(bio_err,"phrase is too short, needs to be at least %d chars\n",PW_MIN_LENGTH);
+                       }
+               else
+                       break;
+               }
+       return(j);
+       }
+
 static char *app_get_pass(BIO *err, char *arg, int keepbio);
 
 int app_passwd(BIO *err, char *arg1, char *arg2, char **pass1, char **pass2)
@@ -470,7 +521,8 @@ int add_oid_section(BIO *err, LHASH *conf)
        return 1;
 }
 
-X509 *load_cert(BIO *err, char *file, int format)
+X509 *load_cert(BIO *err, const char *file, int format,
+       const char *pass, ENGINE *e, const char *cert_descrip)
        {
        ASN1_HEADER *ah=NULL;
        BUF_MEM *buf=NULL;
@@ -492,7 +544,9 @@ X509 *load_cert(BIO *err, char *file, int format)
                {
                if (BIO_read_filename(cert,file) <= 0)
                        {
-                       perror(file);
+                       BIO_printf(err, "Error opening %s %s\n",
+                               cert_descrip, file);
+                       ERR_print_errors(err);
                        goto end;
                        }
                }
@@ -543,7 +597,8 @@ X509 *load_cert(BIO *err, char *file, int format)
                ah->data=NULL;
                }
        else if (format == FORMAT_PEM)
-               x=PEM_read_bio_X509_AUX(cert,NULL,NULL,NULL);
+               x=PEM_read_bio_X509_AUX(cert,NULL,
+                       (pem_password_cb *)password_callback, NULL);
        else if (format == FORMAT_PKCS12)
                {
                PKCS12 *p12 = d2i_PKCS12_bio(cert, NULL);
@@ -553,7 +608,8 @@ X509 *load_cert(BIO *err, char *file, int format)
                p12 = NULL;
                }
        else    {
-               BIO_printf(err,"bad input format specified for input cert\n");
+               BIO_printf(err,"bad input format specified for %s\n",
+                       cert_descrip);
                goto end;
                }
 end:
@@ -568,10 +624,15 @@ end:
        return(x);
        }
 
-EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass, ENGINE *e)
+EVP_PKEY *load_key(BIO *err, const char *file, int format,
+       const char *pass, ENGINE *e, const char *key_descrip)
        {
        BIO *key=NULL;
        EVP_PKEY *pkey=NULL;
+       PW_CB_DATA cb_data;
+
+       cb_data.password = pass;
+       cb_data.prompt_info = file;
 
        if (file == NULL)
                {
@@ -583,7 +644,8 @@ EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass, ENGINE *e)
                if (!e)
                        BIO_printf(bio_err,"no engine specified\n");
                else
-                       pkey = ENGINE_load_private_key(e, file, pass);
+                       pkey = ENGINE_load_private_key(e, file,
+                               (pem_password_cb *)password_callback, &cb_data);
                goto end;
                }
        key=BIO_new(BIO_s_file());
@@ -594,7 +656,8 @@ EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass, ENGINE *e)
                }
        if (BIO_read_filename(key,file) <= 0)
                {
-               perror(file);
+               BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
+               ERR_print_errors(err);
                goto end;
                }
        if (format == FORMAT_ASN1)
@@ -603,7 +666,8 @@ EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass, ENGINE *e)
                }
        else if (format == FORMAT_PEM)
                {
-               pkey=PEM_read_bio_PrivateKey(key,NULL,NULL,pass);
+               pkey=PEM_read_bio_PrivateKey(key,NULL,
+                       (pem_password_cb *)password_callback, &cb_data);
                }
        else if (format == FORMAT_PKCS12)
                {
@@ -615,20 +679,25 @@ EVP_PKEY *load_key(BIO *err, char *file, int format, char *pass, ENGINE *e)
                }
        else
                {
-               BIO_printf(err,"bad input format specified for key\n");
+               BIO_printf(err,"bad input format specified for key file\n");
                goto end;
                }
  end:
        if (key != NULL) BIO_free(key);
        if (pkey == NULL)
-               BIO_printf(err,"unable to load Private Key\n");
+               BIO_printf(err,"unable to load %s\n", key_descrip);
        return(pkey);
        }
 
-EVP_PKEY *load_pubkey(BIO *err, char *file, int format, ENGINE *e)
+EVP_PKEY *load_pubkey(BIO *err, const char *file, int format,
+       const char *pass, ENGINE *e, const char *key_descrip)
        {
        BIO *key=NULL;
        EVP_PKEY *pkey=NULL;
+       PW_CB_DATA cb_data;
+
+       cb_data.password = pass;
+       cb_data.prompt_info = file;
 
        if (file == NULL)
                {
@@ -640,7 +709,8 @@ EVP_PKEY *load_pubkey(BIO *err, char *file, int format, ENGINE *e)
                if (!e)
                        BIO_printf(bio_err,"no engine specified\n");
                else
-                       pkey = ENGINE_load_public_key(e, file, NULL);
+                       pkey = ENGINE_load_public_key(e, file,
+                               (pem_password_cb *)password_callback, &cb_data);
                goto end;
                }
        key=BIO_new(BIO_s_file());
@@ -651,7 +721,8 @@ EVP_PKEY *load_pubkey(BIO *err, char *file, int format, ENGINE *e)
                }
        if (BIO_read_filename(key,file) <= 0)
                {
-               perror(file);
+               BIO_printf(err, "Error opening %s %s\n", key_descrip, file);
+               ERR_print_errors(err);
                goto end;
                }
        if (format == FORMAT_ASN1)
@@ -660,27 +731,33 @@ EVP_PKEY *load_pubkey(BIO *err, char *file, int format, ENGINE *e)
                }
        else if (format == FORMAT_PEM)
                {
-               pkey=PEM_read_bio_PUBKEY(key,NULL,NULL,NULL);
+               pkey=PEM_read_bio_PUBKEY(key,NULL,
+                       (pem_password_cb *)password_callback, &cb_data);
                }
        else
                {
-               BIO_printf(err,"bad input format specified for key\n");
+               BIO_printf(err,"bad input format specified for key file\n");
                goto end;
                }
  end:
        if (key != NULL) BIO_free(key);
        if (pkey == NULL)
-               BIO_printf(err,"unable to load Public Key\n");
+               BIO_printf(err,"unable to load %s\n", key_descrip);
        return(pkey);
        }
 
-STACK_OF(X509) *load_certs(BIO *err, char *file, int format)
+STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
+       const char *pass, ENGINE *e, const char *cert_descrip)
        {
        BIO *certs;
        int i;
        STACK_OF(X509) *othercerts = NULL;
        STACK_OF(X509_INFO) *allcerts = NULL;
        X509_INFO *xi;
+       PW_CB_DATA cb_data;
+
+       cb_data.password = pass;
+       cb_data.prompt_info = file;
 
        if((certs = BIO_new(BIO_s_file())) == NULL)
                {
@@ -694,7 +771,9 @@ STACK_OF(X509) *load_certs(BIO *err, char *file, int format)
                {
                if (BIO_read_filename(certs,file) <= 0)
                        {
-                       perror(file);
+                       BIO_printf(err, "Error opening %s %s\n",
+                               cert_descrip, file);
+                       ERR_print_errors(err);
                        goto end;
                        }
                }
@@ -708,7 +787,8 @@ STACK_OF(X509) *load_certs(BIO *err, char *file, int format)
                        othercerts = NULL;
                        goto end;
                        }
-               allcerts = PEM_X509_INFO_read_bio(certs, NULL, NULL, NULL);
+               allcerts = PEM_X509_INFO_read_bio(certs, NULL,
+                               (pem_password_cb *)password_callback, &cb_data);
                for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
                        {
                        xi = sk_X509_INFO_value (allcerts, i);
@@ -721,7 +801,8 @@ STACK_OF(X509) *load_certs(BIO *err, char *file, int format)
                goto end;
                }
        else    {
-               BIO_printf(err,"bad input format specified for input cert\n");
+               BIO_printf(err,"bad input format specified for %s\n",
+                       cert_descrip);
                goto end;
                }
 end:
@@ -796,6 +877,7 @@ int set_name_ex(unsigned long *flags, const char *arg)
                { "nofname", XN_FLAG_FN_NONE, XN_FLAG_FN_MASK},
                { "sname", XN_FLAG_FN_SN, XN_FLAG_FN_MASK},
                { "lname", XN_FLAG_FN_LN, XN_FLAG_FN_MASK},
+               { "align", XN_FLAG_FN_ALIGN, 0},
                { "oid", XN_FLAG_FN_OID, XN_FLAG_FN_MASK},
                { "space_eq", XN_FLAG_SPC_EQ, 0},
                { "dump_unknown", XN_FLAG_DUMP_UNKNOWN_FIELDS, 0},
@@ -808,6 +890,62 @@ int set_name_ex(unsigned long *flags, const char *arg)
        return set_multi_opts(flags, arg, ex_tbl);
 }
 
+int set_ext_copy(int *copy_type, const char *arg)
+{
+       if (!strcasecmp(arg, "none"))
+               *copy_type = EXT_COPY_NONE;
+       else if (!strcasecmp(arg, "copy"))
+               *copy_type = EXT_COPY_ADD;
+       else if (!strcasecmp(arg, "copyall"))
+               *copy_type = EXT_COPY_ALL;
+       else
+               return 0;
+       return 1;
+}
+
+int copy_extensions(X509 *x, X509_REQ *req, int copy_type)
+{
+       STACK_OF(X509_EXTENSION) *exts = NULL;
+       X509_EXTENSION *ext, *tmpext;
+       ASN1_OBJECT *obj;
+       int i, idx, ret = 0;
+       if (!x || !req || (copy_type == EXT_COPY_NONE))
+               return 1;
+       exts = X509_REQ_get_extensions(req);
+
+       for(i = 0; i < sk_X509_EXTENSION_num(exts); i++) {
+               ext = sk_X509_EXTENSION_value(exts, i);
+               obj = X509_EXTENSION_get_object(ext);
+               idx = X509_get_ext_by_OBJ(x, obj, -1);
+               /* Does extension exist? */
+               if (idx != -1) {
+                       /* If normal copy don't override existing extension */
+                       if (copy_type == EXT_COPY_ADD)
+                               continue;
+                       /* Delete all extensions of same type */
+                       do {
+                               tmpext = X509_get_ext(x, idx);
+                               X509_delete_ext(x, idx);
+                               X509_EXTENSION_free(tmpext);
+                               idx = X509_get_ext_by_OBJ(x, obj, -1);
+                       } while (idx != -1);
+               }
+               if (!X509_add_ext(x, ext, -1))
+                       goto end;
+       }
+
+       ret = 1;
+
+       end:
+
+       sk_X509_EXTENSION_pop_free(exts, X509_EXTENSION_free);
+
+       return ret;
+}
+               
+               
+                       
+
 static int set_multi_opts(unsigned long *flags, const char *arg, const NAME_EX_TBL *in_tbl)
 {
        STACK_OF(CONF_VALUE) *vals;
@@ -899,3 +1037,34 @@ X509_STORE *setup_verify(BIO *bp, char *CAfile, char *CApath)
        X509_STORE_free(store);
        return NULL;
 }
+
+ENGINE *setup_engine(BIO *err, const char *engine, int debug)
+        {
+        ENGINE *e = NULL;
+
+        if (engine)
+                {
+               if((e = ENGINE_by_id(engine)) == NULL)
+                       {
+                       BIO_printf(err,"invalid engine \"%s\"\n", engine);
+                       return NULL;
+                       }
+               if (debug)
+                       {
+                       ENGINE_ctrl(e, ENGINE_CTRL_SET_LOGSTREAM,
+                               0, err, 0);
+                       }
+#if 0 /* not yet implemented but on it's way */
+                ENGINE_ctrl_cmd(e, "SET_USER_INTERFACE", 0, UI_OpenSSL(), 0, 1);
+#endif
+               if(!ENGINE_set_default(e, ENGINE_METHOD_ALL))
+                       {
+                       BIO_printf(err,"can't use that engine\n");
+                       return NULL;
+                       }
+               BIO_printf(err,"engine \"%s\" set.\n", engine);
+               /* Free our "structural" reference. */
+               ENGINE_free(e);
+               }
+        return e;
+        }