New options to the -verify program which can be used for chain verification.
[openssl.git] / apps / req.c
index fd23f578d78a5f9a00499dfc2fd9b0af1fa0b589..59a38982b9020ac44c5f4e019e60bc0b9dd75ab0 100644 (file)
@@ -66,7 +66,6 @@
 #include "apps.h"
 #include <openssl/bio.h>
 #include <openssl/evp.h>
-#include <openssl/rand.h>
 #include <openssl/conf.h>
 #include <openssl/err.h>
 #include <openssl/asn1.h>
@@ -82,6 +81,8 @@
 #define DISTINGUISHED_NAME     "distinguished_name"
 #define ATTRIBUTES     "attributes"
 #define V3_EXTENSIONS  "x509_extensions"
+#define REQ_EXTENSIONS "req_extensions"
+#define DIRSTRING_TYPE "dirstring_type"
 
 #define DEFAULT_KEY_LENGTH     512
 #define MIN_KEY_LENGTH         384
@@ -142,6 +143,7 @@ int MAIN(int argc, char **argv)
        int nodes=0,kludge=0;
        char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL;
        char *extensions = NULL;
+       char *req_exts = NULL;
        EVP_CIPHER *cipher=NULL;
        int modulus=0;
        char *p;
@@ -150,6 +152,7 @@ int MAIN(int argc, char **argv)
        MS_STATIC char config_name[256];
 #endif
 
+       req_conf = NULL;
 #ifndef NO_DES
        cipher=EVP_des_ede3_cbc();
 #endif
@@ -242,11 +245,11 @@ int MAIN(int argc, char **argv)
                                        perror(p);
                                        goto end;
                                        }
-                               if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL)) == NULL)
+                               if ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL,NULL)) == NULL)
                                        {
                                        ERR_clear_error();
                                        (void)BIO_reset(in);
-                                       if ((xtmp=PEM_read_bio_X509(in,NULL,NULL)) == NULL)
+                                       if ((xtmp=PEM_read_bio_X509(in,NULL,NULL,NULL)) == NULL)
                                                {
                                                BIO_printf(bio_err,"unable to load DSA parameters from file\n");
                                                goto end;
@@ -308,8 +311,17 @@ int MAIN(int argc, char **argv)
                        /* ok */
                        digest=md_alg;
                        }
+               else if (strcmp(*argv,"-extensions") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       extensions = *(++argv);
+                       }
+               else if (strcmp(*argv,"-reqexts") == 0)
+                       {
+                       if (--argc < 1) goto bad;
+                       req_exts = *(++argv);
+                       }
                else
-
                        {
                        BIO_printf(bio_err,"unknown option %s\n",*argv);
                        badops=1;
@@ -347,6 +359,8 @@ bad:
                BIO_printf(bio_err," -asn1-kludge   Output the 'request' in a format that is wrong but some CA's\n");
                BIO_printf(bio_err,"                have been reported as requiring\n");
                BIO_printf(bio_err,"                [ It is now always turned on but can be turned off with -no-asn1-kludge ]\n");
+               BIO_printf(bio_err," -extensions .. specify certificate extension section (override value in config file)\n");
+               BIO_printf(bio_err," -reqexts ..    specify request extension section (override value in config file)\n");
                goto end;
                }
 
@@ -425,7 +439,8 @@ bad:
                        digest=md_alg;
                }
 
-       extensions = CONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
+       if(!extensions)
+               extensions = CONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
        if(extensions) {
                /* Check syntax of file */
                X509V3_CTX ctx;
@@ -438,6 +453,28 @@ bad:
                }
        }
 
+       p = CONF_get_string(req_conf, SECTION, DIRSTRING_TYPE);
+
+       if(p && !ASN1_STRING_set_default_mask_asc(p)) {
+               BIO_printf(bio_err, "Invalid DiretoryString setting %s", p);
+               goto end;
+       }
+
+       if(!req_exts)
+               req_exts = CONF_get_string(req_conf, SECTION, REQ_EXTENSIONS);
+       if(req_exts) {
+               /* Check syntax of file */
+               X509V3_CTX ctx;
+               X509V3_set_ctx_test(&ctx);
+               X509V3_set_conf_lhash(&ctx, req_conf);
+               if(!X509V3_EXT_add_conf(req_conf, &ctx, req_exts, NULL)) {
+                       BIO_printf(bio_err,
+                        "Error Loading request extension section %s\n",
+                                                               req_exts);
+                       goto end;
+               }
+       }
+
        in=BIO_new(BIO_s_file());
        out=BIO_new(BIO_s_file());
        if ((in == NULL) || (out == NULL))
@@ -455,7 +492,7 @@ bad:
                        rsa=d2i_RSAPrivateKey_bio(in,NULL);
                else */
                if (keyform == FORMAT_PEM)
-                       pkey=PEM_read_bio_PrivateKey(in,NULL,NULL);
+                       pkey=PEM_read_bio_PrivateKey(in,NULL,NULL,NULL);
                else
                        {
                        BIO_printf(bio_err,"bad input format specified for X509 request\n");
@@ -471,25 +508,9 @@ bad:
 
        if (newreq && (pkey == NULL))
                {
-               char *randfile;
-               char buffer[200];
-
-               if ((randfile=CONF_get_string(req_conf,SECTION,"RANDFILE")) == NULL)
-                       randfile=RAND_file_name(buffer,200);
-#ifdef WINDOWS
-               BIO_printf(bio_err,"Loading 'screen' into random state -");
-               BIO_flush(bio_err);
-               RAND_screen();
-               BIO_printf(bio_err," done\n");
-#endif
-               if ((randfile == NULL) || !RAND_load_file(randfile,1024L*1024L))
-                       {
-                       BIO_printf(bio_err,"unable to load 'random state'\n");
-                       BIO_printf(bio_err,"What this means is that the random number generator has not been seeded\n");
-                       BIO_printf(bio_err,"with much random data.\n");
-                       BIO_printf(bio_err,"Consider setting the RANDFILE environment variable to point at a file that\n");
-                       BIO_printf(bio_err,"'random' data can be kept in.\n");
-                       }
+               char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
+               app_RAND_load_file(randfile, bio_err, 0);
+       
                if (newkey <= 0)
                        {
                        newkey=(int)CONF_get_number(req_conf,SECTION,BITS);
@@ -527,8 +548,7 @@ bad:
                        }
 #endif
 
-               if ((randfile == NULL) || (RAND_write_file(randfile) == 0))
-                       BIO_printf(bio_err,"unable to write 'random state'\n");
+               app_RAND_write_file(randfile, bio_err);
 
                if (pkey == NULL) goto end;
 
@@ -560,7 +580,7 @@ bad:
                i=0;
 loop:
                if (!PEM_write_bio_PrivateKey(out,pkey,cipher,
-                       NULL,0,NULL))
+                       NULL,0,NULL,NULL))
                        {
                        if ((ERR_GET_REASON(ERR_peek_error()) ==
                                PEM_R_PROBLEMS_GETTING_PASSWORD) && (i < 3))
@@ -594,7 +614,7 @@ loop:
                if      (informat == FORMAT_ASN1)
                        req=d2i_X509_REQ_bio(in,NULL);
                else if (informat == FORMAT_PEM)
-                       req=PEM_read_bio_X509_REQ(in,NULL,NULL);
+                       req=PEM_read_bio_X509_REQ(in,NULL,NULL,NULL);
                else
                        {
                        BIO_printf(bio_err,"bad input format specified for X509 request\n");
@@ -677,6 +697,22 @@ loop:
                        }
                else
                        {
+                       X509V3_CTX ext_ctx;
+
+                       /* Set up V3 context struct */
+
+                       X509V3_set_ctx(&ext_ctx, NULL, NULL, req, NULL, 0);
+                       X509V3_set_conf_lhash(&ext_ctx, req_conf);
+
+                       /* Add extensions */
+                       if(req_exts && !X509V3_EXT_REQ_add_conf(req_conf, 
+                                       &ext_ctx, req_exts, req))
+                           {
+                           BIO_printf(bio_err,
+                                      "Error Loading extension section %s\n",
+                                      req_exts);
+                           goto end;
+                           }
                        if (!(i=X509_REQ_sign(req,pkey,digest)))
                                goto end;
                        }
@@ -809,6 +845,7 @@ end:
        X509_free(x509ss);
        X509V3_EXT_cleanup();
        OBJ_cleanup();
+       ASN1_STRING_TABLE_cleanup();
 #ifndef NO_DSA
        if (dsa_params != NULL) DSA_free(dsa_params);
 #endif
@@ -823,7 +860,7 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
        char buf[100];
        int nid,min,max;
        char *type,*def,*tmp,*value,*tmp_attr;
-       STACK *sk,*attr=NULL;
+       STACK_OF(CONF_VALUE) *sk, *attr=NULL;
        CONF_VALUE *v;
        
        tmp=CONF_get_string(req_conf,SECTION,DISTINGUISHED_NAME);
@@ -855,6 +892,9 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
 
        ri=req->req_info;
 
+       /* setup version number */
+       if (!ASN1_INTEGER_set(ri->version,0L)) goto err; /* version 1 */
+
        BIO_printf(bio_err,"You are about to be asked to enter information that will be incorporated\n");
        BIO_printf(bio_err,"into your certificate request.\n");
        BIO_printf(bio_err,"What you are about to enter is what is called a Distinguished Name or a DN.\n");
@@ -863,18 +903,16 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
        BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
        BIO_printf(bio_err,"-----\n");
 
-       /* setup version number */
-       if (!ASN1_INTEGER_set(ri->version,0L)) goto err; /* version 1 */
 
-       if (sk_num(sk))
+       if (sk_CONF_VALUE_num(sk))
                {
                i= -1;
 start:         for (;;)
                        {
                        i++;
-                       if ((int)sk_num(sk) <= i) break;
+                       if (sk_CONF_VALUE_num(sk) <= i) break;
 
-                       v=(CONF_VALUE *)sk_value(sk,i);
+                       v=sk_CONF_VALUE_value(sk,i);
                        p=q=NULL;
                        type=v->name;
                        if(!check_end(type,"_min") || !check_end(type,"_max") ||
@@ -918,7 +956,7 @@ start:              for (;;)
 
                if (attribs)
                        {
-                       if ((attr != NULL) && (sk_num(attr) > 0))
+                       if ((attr != NULL) && (sk_CONF_VALUE_num(attr) > 0))
                                {
                                BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
                                BIO_printf(bio_err,"to be sent with your certificate request\n");
@@ -928,10 +966,11 @@ start:            for (;;)
 start2:                        for (;;)
                                {
                                i++;
-                               if ((attr == NULL) || ((int)sk_num(attr) <= i))
+                               if ((attr == NULL) ||
+                                           (sk_CONF_VALUE_num(attr) <= i))
                                        break;
 
-                               v=(CONF_VALUE *)sk_value(attr,i);
+                               v=sk_CONF_VALUE_value(attr,i);
                                type=v->name;
                                if ((nid=OBJ_txt2nid(type)) == NID_undef)
                                        goto start2;
@@ -974,8 +1013,7 @@ err:
 static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
             int nid, int min, int max)
        {
-       int i,j,ret=0;
-       X509_NAME_ENTRY *ne=NULL;
+       int i,ret=0;
        MS_STATIC char buf[1024];
 
        BIO_printf(bio_err,"%s [%s]:",text,def);
@@ -1010,21 +1048,14 @@ static int add_DN_object(X509_NAME *n, char *text, char *def, char *value,
                }
        buf[--i]='\0';
 
-       j=ASN1_PRINTABLE_type((unsigned char *)buf,-1);
-       if (req_fix_data(nid,&j,i,min,max) == 0)
-               goto err;
 #ifdef CHARSET_EBCDIC
        ebcdic2ascii(buf, buf, i);
 #endif
-       if ((ne=X509_NAME_ENTRY_create_by_NID(NULL,nid,j,(unsigned char *)buf,
-               strlen(buf)))
-               == NULL) goto err;
-       if (!X509_NAME_add_entry(n,ne,X509_NAME_entry_count(n),0))
-               goto err;
-
+       if(!req_fix_data(-1, NULL, i, min, max)) goto err;
+       if (!X509_NAME_add_entry_by_NID(n,nid, MBSTRING_ASC,
+                               (unsigned char *) buf, -1,-1,0)) goto err;
        ret=1;
 err:
-       if (ne != NULL) X509_NAME_ENTRY_free(ne);
        return(ret);
        }
 
@@ -1093,7 +1124,7 @@ start:
                else    goto err;
                }
 
-       if (!ASN1_STRING_set(bs,(unsigned char *)buf,i+1))
+       if (!ASN1_STRING_set(bs,(unsigned char *)buf,i))
                { BIO_printf(bio_err,"Malloc failure\n"); goto err; }
 
        if ((at=ASN1_TYPE_new()) == NULL)
@@ -1131,23 +1162,24 @@ static void MS_CALLBACK req_cb(int p, int n, void *arg)
 
 static int req_fix_data(int nid, int *type, int len, int min, int max)
        {
-       if (nid == NID_pkcs9_emailAddress)
-               *type=V_ASN1_IA5STRING;
-       if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
-               *type=V_ASN1_T61STRING;
-       if ((nid == NID_pkcs9_challengePassword) &&
-               (*type == V_ASN1_IA5STRING))
-               *type=V_ASN1_T61STRING;
-
-       if ((nid == NID_pkcs9_unstructuredName) &&
-               (*type == V_ASN1_T61STRING))
-               {
-               BIO_printf(bio_err,"invalid characters in string, please re-enter the string\n");
-               return(0);
-               }
-       if (nid == NID_pkcs9_unstructuredName)
-               *type=V_ASN1_IA5STRING;
-
+       if(type) {
+               if (nid == NID_pkcs9_emailAddress)
+                       *type=V_ASN1_IA5STRING;
+               if ((nid == NID_commonName) && (*type == V_ASN1_IA5STRING))
+                       *type=V_ASN1_T61STRING;
+               if ((nid == NID_pkcs9_challengePassword) &&
+                       (*type == V_ASN1_IA5STRING))
+                       *type=V_ASN1_T61STRING;
+
+               if ((nid == NID_pkcs9_unstructuredName) &&
+                       (*type == V_ASN1_T61STRING))
+                       {
+                       BIO_printf(bio_err,"invalid characters in string, please re-enter the string\n");
+                       return(0);
+                       }
+               if (nid == NID_pkcs9_unstructuredName)
+                       *type=V_ASN1_IA5STRING;
+       }
        if (len < min)
                {
                BIO_printf(bio_err,"string is too short, it needs to be at least %d bytes long\n",min);
@@ -1176,7 +1208,7 @@ static int check_end(char *str, char *end)
 static int add_oid_section(LHASH *conf)
 {      
        char *p;
-       STACK *sktmp;
+       STACK_OF(CONF_VALUE) *sktmp;
        CONF_VALUE *cnf;
        int i;
        if(!(p=CONF_get_string(conf,NULL,"oid_section"))) return 1;
@@ -1184,8 +1216,8 @@ static int add_oid_section(LHASH *conf)
                BIO_printf(bio_err, "problem loading oid section %s\n", p);
                return 0;
        }
-       for(i = 0; i < sk_num(sktmp); i++) {
-               cnf = (CONF_VALUE *)sk_value(sktmp, i);
+       for(i = 0; i < sk_CONF_VALUE_num(sktmp); i++) {
+               cnf = sk_CONF_VALUE_value(sktmp, i);
                if(OBJ_create(cnf->value, cnf->name, cnf->name) == NID_undef) {
                        BIO_printf(bio_err, "problem creating object %s=%s\n",
                                                         cnf->name, cnf->value);