X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Freq.c;h=c5becc9d4dd19401873f5c3b673b7e55788c78d9;hp=729cb2d5bd74f47bd9a1e8f69b4d6db93887b920;hb=6d5ffb591ba0baa98be27df8acabf2018473dd3d;hpb=9226e2187c14979352cb78886ab8f0a90b3aef46 diff --git a/apps/req.c b/apps/req.c index 729cb2d5bd..c5becc9d4d 100644 --- a/apps/req.c +++ b/apps/req.c @@ -56,6 +56,12 @@ * [including the GNU Public Licence.] */ +/* Until the key-gen callbacks are modified to use newer prototypes, we allow + * deprecated functions for openssl-internal code */ +#ifdef OPENSSL_NO_DEPRECATED +#undef OPENSSL_NO_DEPRECATED +#endif + #include #include #include @@ -73,6 +79,7 @@ #include #include #include +#include "../crypto/cryptlib.h" #define SECTION "req" @@ -112,9 +119,10 @@ * require. This format is wrong */ -static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int attribs, - unsigned long chtype); -static int build_subject(X509_REQ *req, char *subj, unsigned long chtype); +static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int mutlirdn, + int attribs,unsigned long chtype); +static int build_subject(X509_REQ *req, char *subj, unsigned long chtype, + int multirdn); static int prompt_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect, STACK_OF(CONF_VALUE) *attr_sk, char *attr_sect, int attribs, @@ -126,15 +134,14 @@ static int add_attribute_object(X509_REQ *req, char *text, char *def, char *value, int nid, int n_min, int n_max, unsigned long chtype); static int add_DN_object(X509_NAME *n, char *text, char *def, char *value, - int nid,int n_min,int n_max, unsigned long chtype); + int nid,int n_min,int n_max, unsigned long chtype, int mval); #ifndef OPENSSL_NO_RSA -static void MS_CALLBACK req_cb(int p,int n,void *arg); +static int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb); #endif static int req_check_len(int len,int n_min,int n_max); static int check_end(char *str, char *end); #ifndef MONOLITH static char *default_config_file=NULL; -static CONF *config=NULL; #endif static CONF *req_conf=NULL; static int batch=0; @@ -166,7 +173,9 @@ int MAIN(int argc, char **argv) int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM; int nodes=0,kludge=0,newhdr=0,subject=0,pubkey=0; char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL; +#ifndef OPENSSL_NO_ENGINE char *engine=NULL; +#endif char *extensions = NULL; char *req_exts = NULL; const EVP_CIPHER *cipher=NULL; @@ -177,10 +186,11 @@ int MAIN(int argc, char **argv) char *passin = NULL, *passout = NULL; char *p; char *subj = NULL; + int multirdn = 0; const EVP_MD *md_alg=NULL,*digest=EVP_md5(); unsigned long chtype = MBSTRING_ASC; #ifndef MONOLITH - MS_STATIC char config_name[256]; + char *to_free; long errline; #endif @@ -214,11 +224,13 @@ int MAIN(int argc, char **argv) if (--argc < 1) goto bad; outformat=str2fmt(*(++argv)); } +#ifndef OPENSSL_NO_ENGINE else if (strcmp(*argv,"-engine") == 0) { if (--argc < 1) goto bad; engine= *(++argv); } +#endif else if (strcmp(*argv,"-key") == 0) { if (--argc < 1) goto bad; @@ -430,6 +442,8 @@ int MAIN(int argc, char **argv) if (--argc < 1) goto bad; subj= *(++argv); } + else if (strcmp(*argv,"-multivalue-rdn") == 0) + multirdn=1; else if (strcmp(*argv,"-days") == 0) { if (--argc < 1) goto bad; @@ -482,7 +496,9 @@ bad: BIO_printf(bio_err," -verify verify signature on REQ\n"); BIO_printf(bio_err," -modulus RSA modulus\n"); BIO_printf(bio_err," -nodes don't encrypt the output key\n"); +#ifndef OPENSSL_NO_ENGINE BIO_printf(bio_err," -engine e use engine e, possibly a hardware device\n"); +#endif BIO_printf(bio_err," -subject output the request's subject\n"); BIO_printf(bio_err," -passin private key password source\n"); BIO_printf(bio_err," -key file use the private key contained in file\n"); @@ -499,6 +515,7 @@ bad: BIO_printf(bio_err," -[digest] Digest to sign with (md5, sha1, md2, mdc2, md4)\n"); BIO_printf(bio_err," -config file request template file.\n"); BIO_printf(bio_err," -subj arg set or modify request subject\n"); + BIO_printf(bio_err," -multivalue-rdn enable support for multivalued RDNs\n"); BIO_printf(bio_err," -new new request.\n"); BIO_printf(bio_err," -batch do not ask anything during request generation\n"); BIO_printf(bio_err," -x509 output a x509 structure instead of a cert. req.\n"); @@ -510,7 +527,7 @@ bad: 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"); BIO_printf(bio_err," -utf8 input characters are UTF8 (default ASCII)\n"); - BIO_printf(bio_err," -nameopt arg - various certificate name options\n"); + BIO_printf(bio_err," -nameopt arg - various certificate name options\n"); BIO_printf(bio_err," -reqopt arg - various request text options\n\n"); goto end; } @@ -527,14 +544,7 @@ bad: if (p == NULL) p=getenv("SSLEAY_CONF"); if (p == NULL) - { - strcpy(config_name,X509_get_default_cert_area()); -#ifndef OPENSSL_SYS_VMS - strcat(config_name,"/"); -#endif - strcat(config_name,OPENSSL_CONF); - p=config_name; - } + p=to_free=make_config_name(); default_config_file=p; config=NCONF_new(NULL); i=NCONF_load(config, p, &errline); @@ -542,7 +552,7 @@ bad: if (template != NULL) { - long errline; + long errline = -1; if( verbose ) BIO_printf(bio_err,"Using configuration from %s\n",template); @@ -681,7 +691,9 @@ bad: if ((in == NULL) || (out == NULL)) goto end; +#ifndef OPENSSL_NO_ENGINE e = setup_engine(bio_err, engine, 0); +#endif if (keyfile != NULL) { @@ -705,6 +717,7 @@ bad: if (newreq && (pkey == NULL)) { + BN_GENCB cb; char *randfile = NCONF_get_string(req_conf,SECTION,"RANDFILE"); if (randfile == NULL) ERR_clear_error(); @@ -721,22 +734,26 @@ bad: if (newkey < MIN_KEY_LENGTH && (pkey_type == TYPE_RSA || pkey_type == TYPE_DSA)) { BIO_printf(bio_err,"private key length is too short,\n"); - BIO_printf(bio_err,"it needs to be at least %d bits, not %d\n",MIN_KEY_LENGTH,newkey); + BIO_printf(bio_err,"it needs to be at least %d bits, not %ld\n",MIN_KEY_LENGTH,newkey); goto end; } - BIO_printf(bio_err,"Generating a %d bit %s private key\n", + BIO_printf(bio_err,"Generating a %ld bit %s private key\n", newkey,(pkey_type == TYPE_RSA)?"RSA": (pkey_type == TYPE_DSA)?"DSA":"EC"); if ((pkey=EVP_PKEY_new()) == NULL) goto end; #ifndef OPENSSL_NO_RSA + BN_GENCB_set(&cb, req_cb, bio_err); if (pkey_type == TYPE_RSA) { - if (!EVP_PKEY_assign_RSA(pkey, - RSA_generate_key(newkey,0x10001, - req_cb,bio_err))) + RSA *rsa = RSA_new(); + if(!rsa || !RSA_generate_key_ex(rsa, newkey, 0x10001, &cb) || + !EVP_PKEY_assign_RSA(pkey, rsa)) + { + if(rsa) RSA_free(rsa); goto end; + } } else #endif @@ -875,7 +892,7 @@ loop: goto end; } - i=make_REQ(req,pkey,subj,!x509, chtype); + i=make_REQ(req,pkey,subj,multirdn,!x509, chtype); subj=NULL; /* done processing '-subj' option */ if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes)) { @@ -895,7 +912,7 @@ loop: if ((x509ss=X509_new()) == NULL) goto end; /* Set version to V3 */ - if(!X509_set_version(x509ss, 2)) goto end; + if(extensions && !X509_set_version(x509ss, 2)) goto end; if (serial) { if (!X509_set_serialNumber(x509ss, serial)) goto end; @@ -968,7 +985,7 @@ loop: print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag); } - if (build_subject(req, subj, chtype) == 0) + if (build_subject(req, subj, chtype, multirdn) == 0) { BIO_printf(bio_err, "ERROR: cannot modify subject\n"); ex=1; @@ -1131,6 +1148,10 @@ loop: } ex=0; end: +#ifndef MONOLITH + if(to_free) + OPENSSL_free(to_free); +#endif if (ex) { ERR_print_errors(bio_err); @@ -1152,11 +1173,11 @@ end: if (ec_params != NULL) EC_KEY_free(ec_params); #endif apps_shutdown(); - EXIT(ex); + OPENSSL_EXIT(ex); } -static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs, - unsigned long chtype) +static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int multirdn, + int attribs, unsigned long chtype) { int ret=0,i; char no_prompt = 0; @@ -1206,7 +1227,7 @@ static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs, else { if (subj) - i = build_subject(req, subj, chtype); + i = build_subject(req, subj, chtype, multirdn); else i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs, chtype); } @@ -1223,11 +1244,11 @@ err: * subject is expected to be in the format /type0=value0/type1=value1/type2=... * where characters may be escaped by \ */ -static int build_subject(X509_REQ *req, char *subject, unsigned long chtype) +static int build_subject(X509_REQ *req, char *subject, unsigned long chtype, int multirdn) { X509_NAME *n; - if (!(n = do_subject(subject, chtype))) + if (!(n = parse_name(subject, chtype, multirdn))) return 0; if (!X509_REQ_set_subject_name(req, n)) @@ -1248,7 +1269,7 @@ static int prompt_info(X509_REQ *req, int i; char *p,*q; char buf[100]; - int nid; + int nid, mval; long n_min,n_max; char *type,*def,*value; CONF_VALUE *v; @@ -1291,15 +1312,28 @@ start: for (;;) if(*p) type = p; break; } + if (*type == '+') + { + mval = -1; + type++; + } + else + mval = 0; /* If OBJ not recognised ignore it */ if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start; + + if(strlen(v->name) > sizeof buf-9) + { + BIO_printf(bio_err,"Name '%s' too long\n",v->name); + return 0; + } + sprintf(buf,"%s_default",v->name); if ((def=NCONF_get_string(req_conf,dn_sect,buf)) == NULL) { ERR_clear_error(); def=""; } - sprintf(buf,"%s_value",v->name); if ((value=NCONF_get_string(req_conf,dn_sect,buf)) == NULL) { @@ -1309,14 +1343,20 @@ start: for (;;) sprintf(buf,"%s_min",v->name); if (!NCONF_get_number(req_conf,dn_sect,buf, &n_min)) + { + ERR_clear_error(); n_min = -1; + } sprintf(buf,"%s_max",v->name); if (!NCONF_get_number(req_conf,dn_sect,buf, &n_max)) + { + ERR_clear_error(); n_max = -1; + } if (!add_DN_object(subj,v->value,def,value,nid, - n_min,n_max, chtype)) + n_min,n_max, chtype, mval)) return 0; } if (X509_NAME_entry_count(subj) == 0) @@ -1346,6 +1386,12 @@ start2: for (;;) if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start2; + if(strlen(v->name) > sizeof buf-9) + { + BIO_printf(bio_err,"Name '%s' too long\n",v->name); + return 0; + } + sprintf(buf,"%s_default",type); if ((def=NCONF_get_string(req_conf,attr_sect,buf)) == NULL) @@ -1400,6 +1446,7 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, for (i = 0; i < sk_CONF_VALUE_num(dn_sk); i++) { + int mval; v=sk_CONF_VALUE_value(dn_sk,i); p=q=NULL; type=v->name; @@ -1416,8 +1463,19 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, if(*p) type = p; break; } +#ifndef CHARSET_EBCDIC + if (*p == '+') +#else + if (*p == os_toascii['+']) +#endif + { + p++; + mval = -1; + } + else + mval = 0; if (!X509_NAME_add_entry_by_txt(subj,type, chtype, - (unsigned char *) v->value,-1,-1,0)) return 0; + (unsigned char *) v->value,-1,-1,mval)) return 0; } @@ -1440,7 +1498,7 @@ static int auto_info(X509_REQ *req, STACK_OF(CONF_VALUE) *dn_sk, static int add_DN_object(X509_NAME *n, char *text, char *def, char *value, - int nid, int n_min, int n_max, unsigned long chtype) + int nid, int n_min, int n_max, unsigned long chtype, int mval) { int i,ret=0; MS_STATIC char buf[1024]; @@ -1449,6 +1507,7 @@ start: (void)BIO_flush(bio_err); if(value != NULL) { + OPENSSL_assert(strlen(value) < sizeof buf-2); strcpy(buf,value); strcat(buf,"\n"); BIO_printf(bio_err,"%s\n",value); @@ -1458,7 +1517,7 @@ start: buf[0]='\0'; if (!batch) { - fgets(buf,1024,stdin); + fgets(buf,sizeof buf,stdin); } else { @@ -1489,7 +1548,7 @@ start: #endif if(!req_check_len(i, n_min, n_max)) goto start; if (!X509_NAME_add_entry_by_NID(n,nid, chtype, - (unsigned char *) buf, -1,-1,0)) goto err; + (unsigned char *) buf, -1,-1,mval)) goto err; ret=1; err: return(ret); @@ -1507,6 +1566,7 @@ start: (void)BIO_flush(bio_err); if (value != NULL) { + OPENSSL_assert(strlen(value) < sizeof buf-2); strcpy(buf,value); strcat(buf,"\n"); BIO_printf(bio_err,"%s\n",value); @@ -1516,7 +1576,7 @@ start: buf[0]='\0'; if (!batch) { - fgets(buf,1024,stdin); + fgets(buf,sizeof buf,stdin); } else { @@ -1560,7 +1620,7 @@ err: } #ifndef OPENSSL_NO_RSA -static void MS_CALLBACK req_cb(int p, int n, void *arg) +static int MS_CALLBACK req_cb(int p, int n, BN_GENCB *cb) { char c='*'; @@ -1568,11 +1628,12 @@ static void MS_CALLBACK req_cb(int p, int n, void *arg) if (p == 1) c='+'; if (p == 2) c='*'; if (p == 3) c='\n'; - BIO_write((BIO *)arg,&c,1); - (void)BIO_flush((BIO *)arg); + BIO_write(cb->arg,&c,1); + (void)BIO_flush(cb->arg); #ifdef LINT p=n; #endif + return 1; } #endif