diff options
Diffstat (limited to 'lib/libssl/src/apps/req.c')
-rw-r--r-- | lib/libssl/src/apps/req.c | 322 |
1 files changed, 191 insertions, 131 deletions
diff --git a/lib/libssl/src/apps/req.c b/lib/libssl/src/apps/req.c index f51345f5a28..463ac156ea4 100644 --- a/lib/libssl/src/apps/req.c +++ b/lib/libssl/src/apps/req.c @@ -64,15 +64,16 @@ #define APPS_WIN16 #endif #include "apps.h" -#include "bio.h" -#include "evp.h" -#include "rand.h" -#include "conf.h" -#include "err.h" -#include "asn1.h" -#include "x509.h" -#include "objects.h" -#include "pem.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> +#include <openssl/x509.h> +#include <openssl/x509v3.h> +#include <openssl/objects.h> +#include <openssl/pem.h> #define SECTION "req" @@ -80,6 +81,7 @@ #define KEYFILE "default_keyfile" #define DISTINGUISHED_NAME "distinguished_name" #define ATTRIBUTES "attributes" +#define V3_EXTENSIONS "x509_extensions" #define DEFAULT_KEY_LENGTH 512 #define MIN_KEY_LENGTH 384 @@ -105,22 +107,16 @@ * require. This format is wrong */ -#ifndef NOPROTO static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,int attribs); -static int add_attribute_object(STACK *n, char *text, char *def, - char *value, int nid,int min,int max); +static int add_attribute_object(STACK_OF(X509_ATTRIBUTE) *n, char *text, + char *def, char *value, int nid, int min, + int max); static int add_DN_object(X509_NAME *n, char *text, char *def, char *value, int nid,int min,int max); -static void MS_CALLBACK req_cb(int p,int n,char *arg); +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); -#else -static int make_REQ(); -static int add_attribute_object(); -static int add_DN_object(); -static void MS_CALLBACK req_cb(); -static int req_fix_data(); -#endif - +static int check_end(char *str, char *end); +static int add_oid_section(LHASH *conf); #ifndef MONOLITH static char *default_config_file=NULL; static LHASH *config=NULL; @@ -131,9 +127,7 @@ static LHASH *req_conf=NULL; #define TYPE_DSA 2 #define TYPE_DH 3 -int MAIN(argc, argv) -int argc; -char **argv; +int MAIN(int argc, char **argv) { #ifndef NO_DSA DSA *dsa_params=NULL; @@ -147,10 +141,11 @@ char **argv; int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM; int nodes=0,kludge=0; char *infile,*outfile,*prog,*keyfile=NULL,*template=NULL,*keyout=NULL; + char *extensions = NULL; EVP_CIPHER *cipher=NULL; int modulus=0; char *p; - EVP_MD *md_alg=NULL,*digest=EVP_md5(); + const EVP_MD *md_alg=NULL,*digest=EVP_md5(); #ifndef MONOLITH MS_STATIC char config_name[256]; #endif @@ -221,13 +216,16 @@ char **argv; } else if (strcmp(*argv,"-newkey") == 0) { + int is_numeric; + if (--argc < 1) goto bad; p= *(++argv); - if ((strncmp("rsa:",p,4) == 0) || - ((p[0] >= '0') && (p[0] <= '9'))) + is_numeric = p[0] >= '0' && p[0] <= '9'; + if (strncmp("rsa:",p,4) == 0 || is_numeric) { pkey_type=TYPE_RSA; - p+=4; + if(!is_numeric) + p+=4; newkey= atoi(p); } else @@ -244,21 +242,20 @@ 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(); - BIO_reset(in); - if ((xtmp=PEM_read_bio_X509(in,NULL,NULL)) == NULL) + (void)BIO_reset(in); + 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; } - /* This will 'disapear' - * when we free xtmp */ dtmp=X509_get_pubkey(xtmp); if (dtmp->type == EVP_PKEY_DSA) dsa_params=DSAparams_dup(dtmp->pkey.dsa); + EVP_PKEY_free(dtmp); X509_free(xtmp); if (dsa_params == NULL) { @@ -329,7 +326,7 @@ bad: BIO_printf(bio_err,"where options are\n"); BIO_printf(bio_err," -inform arg input format - one of DER TXT PEM\n"); BIO_printf(bio_err," -outform arg output format - one of DER TXT PEM\n"); - BIO_printf(bio_err," -in arg inout file\n"); + BIO_printf(bio_err," -in arg input file\n"); BIO_printf(bio_err," -out arg output file\n"); BIO_printf(bio_err," -text text form of request\n"); BIO_printf(bio_err," -noout do not output REQ\n"); @@ -343,7 +340,7 @@ bad: BIO_printf(bio_err," -newkey dsa:file generate a new DSA key, parameters taken from CA in 'file'\n"); BIO_printf(bio_err," -[digest] Digest to sign with (md5, sha1, md2, mdc2)\n"); - BIO_printf(bio_err," -config file request templace file.\n"); + BIO_printf(bio_err," -config file request template file.\n"); BIO_printf(bio_err," -new new request.\n"); BIO_printf(bio_err," -x509 output a x509 structure instead of a cert. req.\n"); BIO_printf(bio_err," -days number of days a x509 generated by -x509 is valid for.\n"); @@ -354,15 +351,20 @@ bad: } ERR_load_crypto_strings(); + X509V3_add_standard_extensions(); #ifndef MONOLITH /* Lets load up our environment a little */ - p=getenv("SSLEAY_CONF"); + p=getenv("OPENSSL_CONF"); + if (p == NULL) + p=getenv("SSLEAY_CONF"); if (p == NULL) { strcpy(config_name,X509_get_default_cert_area()); - strcat(config_name,"/lib/"); - strcat(config_name,SSLEAY_CONF); +#ifndef VMS + strcat(config_name,"/"); +#endif + strcat(config_name,OPENSSL_CONF); p=config_name; } default_config_file=p; @@ -392,6 +394,30 @@ bad: } } + if (req_conf != NULL) + { + p=CONF_get_string(req_conf,NULL,"oid_file"); + if (p != NULL) + { + BIO *oid_bio; + + oid_bio=BIO_new_file(p,"r"); + if (oid_bio == NULL) + { + /* + BIO_printf(bio_err,"problems opening %s for extra oid's\n",p); + ERR_print_errors(bio_err); + */ + } + else + { + OBJ_create_objects(oid_bio); + BIO_free(oid_bio); + } + } + } + if(!add_oid_section(req_conf)) goto end; + if ((md_alg == NULL) && ((p=CONF_get_string(req_conf,SECTION,"default_md")) != NULL)) { @@ -399,6 +425,19 @@ bad: digest=md_alg; } + extensions = CONF_get_string(req_conf, SECTION, V3_EXTENSIONS); + if(extensions) { + /* 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, extensions, NULL)) { + BIO_printf(bio_err, + "Error Loading extension section %s\n", extensions); + goto end; + } + } + in=BIO_new(BIO_s_file()); out=BIO_new(BIO_s_file()); if ((in == NULL) || (out == NULL)) @@ -416,7 +455,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"); @@ -474,7 +513,7 @@ bad: { if (!EVP_PKEY_assign_RSA(pkey, RSA_generate_key(newkey,0x10001, - req_cb,(char *)bio_err))) + req_cb,bio_err))) goto end; } else @@ -521,7 +560,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)) @@ -555,7 +594,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"); @@ -599,12 +638,12 @@ loop: } if (x509) { + EVP_PKEY *tmppkey; + X509V3_CTX ext_ctx; if ((x509ss=X509_new()) == NULL) goto end; - /* don't set the version number, for starters - * the field is null and second, null is v0 - * if (!ASN1_INTEGER_set(ci->version,0L)) goto end; - */ + /* Set version to V3 */ + if(!X509_set_version(x509ss, 2)) goto end; ASN1_INTEGER_set(X509_get_serialNumber(x509ss),0L); X509_set_issuer_name(x509ss, @@ -614,7 +653,24 @@ loop: (long)60*60*24*days); X509_set_subject_name(x509ss, X509_REQ_get_subject_name(req)); - X509_set_pubkey(x509ss,X509_REQ_get_pubkey(req)); + tmppkey = X509_REQ_get_pubkey(req); + X509_set_pubkey(x509ss,tmppkey); + EVP_PKEY_free(tmppkey); + + /* Set up V3 context struct */ + + X509V3_set_ctx(&ext_ctx, x509ss, x509ss, NULL, NULL, 0); + X509V3_set_conf_lhash(&ext_ctx, req_conf); + + /* Add extensions */ + if(extensions && !X509V3_EXT_add_conf(req_conf, + &ext_ctx, extensions, x509ss)) + { + BIO_printf(bio_err, + "Error Loading extension section %s\n", + extensions); + goto end; + } if (!(i=X509_sign(x509ss,pkey,digest))) goto end; @@ -638,7 +694,10 @@ loop: } i=X509_REQ_verify(req,pkey); - if (tmp) pkey=NULL; + if (tmp) { + EVP_PKEY_free(pkey); + pkey=NULL; + } if (i < 0) { @@ -695,9 +754,11 @@ loop: goto end; } fprintf(stdout,"Modulus="); +#ifndef NO_RSA if (pubkey->type == EVP_PKEY_RSA) BN_print(out,pubkey->pkey.rsa->n); else +#endif fprintf(stdout,"Wrong Algorithm type"); fprintf(stdout,"\n"); } @@ -741,29 +802,28 @@ end: ERR_print_errors(bio_err); } if ((req_conf != NULL) && (req_conf != config)) CONF_free(req_conf); - if (in != NULL) BIO_free(in); - if (out != NULL) BIO_free(out); - if (pkey != NULL) EVP_PKEY_free(pkey); - if (req != NULL) X509_REQ_free(req); - if (x509ss != NULL) X509_free(x509ss); + BIO_free(in); + BIO_free(out); + EVP_PKEY_free(pkey); + X509_REQ_free(req); + X509_free(x509ss); + X509V3_EXT_cleanup(); + OBJ_cleanup(); #ifndef NO_DSA if (dsa_params != NULL) DSA_free(dsa_params); #endif EXIT(ex); } -static int make_REQ(req,pkey,attribs) -X509_REQ *req; -EVP_PKEY *pkey; -int attribs; +static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs) { - int ret=0,i,j; - unsigned char *p,*q; + int ret=0,i; + char *p,*q; X509_REQ_INFO *ri; 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); @@ -806,53 +866,32 @@ int attribs; /* 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; - /* Allow for raw OIDs */ - /* [n.mm.ooo.ppp] */ - for (j=0; type[j] != '\0'; j++) - { - if ( (type[j] == ':') || - (type[j] == ',') || - (type[j] == '.')) - p=(unsigned char *)&(type[j+1]); - if (type[j] == '[') - { - p=(unsigned char *)&(type[j+1]); - for (j++; type[j] != '\0'; j++) - if (type[j] == ']') - { - q=(unsigned char *)&(type[j]); - break; - } + if(!check_end(type,"_min") || !check_end(type,"_max") || + !check_end(type,"_default") || + !check_end(type,"_value")) continue; + /* Skip past any leading X. X: X, etc to allow for + * multiple instances + */ + for(p = v->name; *p ; p++) + if ((*p == ':') || (*p == ',') || + (*p == '.')) { + p++; + if(*p) type = p; break; - } - } - if (p != NULL) - type=(char *)p; - if ((nid=OBJ_txt2nid(type)) == NID_undef) - { - /* Add a new one if possible */ - if ((p != NULL) && (q != NULL) && (*q == ']')) - { - *q='\0'; - nid=OBJ_create((char *)p,NULL,NULL); - *q=']'; - if (nid == NID_undef) goto start; - } - else - goto start; } - + /* If OBJ not recognised ignore it */ + if ((nid=OBJ_txt2nid(type)) == NID_undef) goto start; sprintf(buf,"%s_default",v->name); if ((def=CONF_get_string(req_conf,tmp,buf)) == NULL) def=""; @@ -871,7 +910,7 @@ start: for (;;) min,max)) goto err; } - if (sk_num(ri->subject->entries) == 0) + if (sk_X509_NAME_ENTRY_num(ri->subject->entries) == 0) { BIO_printf(bio_err,"error, no objects specified in config file\n"); goto err; @@ -879,7 +918,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"); @@ -889,10 +928,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; @@ -932,21 +972,15 @@ err: return(ret); } -static int add_DN_object(n,text,def,value,nid,min,max) -X509_NAME *n; -char *text; -char *def; -char *value; -int nid; -int min; -int max; +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; MS_STATIC char buf[1024]; BIO_printf(bio_err,"%s [%s]:",text,def); - BIO_flush(bio_err); + (void)BIO_flush(bio_err); if (value != NULL) { strcpy(buf,value); @@ -980,6 +1014,9 @@ int max; 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; @@ -992,14 +1029,9 @@ err: return(ret); } -static int add_attribute_object(n,text,def,value,nid,min,max) -STACK *n; -char *text; -char *def; -char *value; -int nid; -int min; -int max; +static int add_attribute_object(STACK_OF(X509_ATTRIBUTE) *n, char *text, + char *def, char *value, int nid, int min, + int max) { int i,z; X509_ATTRIBUTE *xa=NULL; @@ -1009,7 +1041,7 @@ int max; start: BIO_printf(bio_err,"%s [%s]:",text,def); - BIO_flush(bio_err); + (void)BIO_flush(bio_err); if (value != NULL) { strcpy(buf,value); @@ -1043,7 +1075,7 @@ start: /* add object plus value */ if ((xa=X509_ATTRIBUTE_new()) == NULL) goto err; - if ((xa->value.set=sk_new_null()) == NULL) + if ((xa->value.set=sk_ASN1_TYPE_new_null()) == NULL) goto err; xa->set=1; @@ -1069,12 +1101,12 @@ start: { BIO_printf(bio_err,"Malloc failure\n"); goto err; } ASN1_TYPE_set(at,bs->type,(char *)bs); - sk_push(xa->value.set,(char *)at); + sk_ASN1_TYPE_push(xa->value.set,at); bs=NULL; at=NULL; /* only one item per attribute */ - if (!sk_push(n,(char *)xa)) goto err; + if (!sk_X509_ATTRIBUTE_push(n,xa)) goto err; return(1); err: if (xa != NULL) X509_ATTRIBUTE_free(xa); @@ -1083,10 +1115,7 @@ err: return(0); } -static void MS_CALLBACK req_cb(p,n,arg) -int p; -int n; -char *arg; +static void MS_CALLBACK req_cb(int p, int n, void *arg) { char c='*'; @@ -1095,16 +1124,13 @@ char *arg; if (p == 2) c='*'; if (p == 3) c='\n'; BIO_write((BIO *)arg,&c,1); - BIO_flush((BIO *)arg); + (void)BIO_flush((BIO *)arg); #ifdef LINT p=n; #endif } -static int req_fix_data(nid,type,len,min,max) -int nid; -int *type; -int len,min,max; +static int req_fix_data(int nid, int *type, int len, int min, int max) { if (nid == NID_pkcs9_emailAddress) *type=V_ASN1_IA5STRING; @@ -1135,3 +1161,37 @@ int len,min,max; } return(1); } + +/* Check if the end of a string matches 'end' */ +static int check_end(char *str, char *end) +{ + int elen, slen; + char *tmp; + elen = strlen(end); + slen = strlen(str); + if(elen > slen) return 1; + tmp = str + slen - elen; + return strcmp(tmp, end); +} + +static int add_oid_section(LHASH *conf) +{ + char *p; + STACK_OF(CONF_VALUE) *sktmp; + CONF_VALUE *cnf; + int i; + if(!(p=CONF_get_string(conf,NULL,"oid_section"))) return 1; + if(!(sktmp = CONF_get_section(conf, p))) { + BIO_printf(bio_err, "problem loading oid section %s\n", p); + return 0; + } + 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); + return 0; + } + } + return 1; +} |