/* apps/req.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
* All rights reserved.
*
* This package is an SSL implementation written
#include <stdlib.h>
#include <time.h>
#include <string.h>
-#ifdef WIN16
+#ifdef NO_STDIO
#define APPS_WIN16
#endif
#include "apps.h"
#include "err.h"
#include "asn1.h"
#include "x509.h"
+#include "x509v3.h"
#include "objects.h"
#include "pem.h"
#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
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);
+static void MS_CALLBACK req_cb(int p,int n,char *arg);
static int req_fix_data(int nid,int *type,int len,int min,int max);
+static int check_end(char *str, char *end);
+static int add_oid_section(LHASH *conf);
#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();
+static int check_end();
+static int add_oid_section();
#endif
#ifndef MONOLITH
int argc;
char **argv;
{
+#ifndef NO_DSA
DSA *dsa_params=NULL;
+#endif
int ex=1,x509=0,days=30;
X509 *x509ss=NULL;
X509_REQ *req=NULL;
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;
if (bio_err == NULL)
if ((bio_err=BIO_new(BIO_s_file())) != NULL)
- BIO_set_fp(bio_err,stderr,BIO_NOCLOSE);
+ BIO_set_fp(bio_err,stderr,BIO_NOCLOSE|BIO_FP_TEXT);
infile=NULL;
outfile=NULL;
}
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 if (strncmp("dsa:",p,4) == 0)
+ else
+#ifndef NO_DSA
+ if (strncmp("dsa:",p,4) == 0)
{
X509 *xtmp=NULL;
EVP_PKEY *dtmp;
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);
BIO_printf(bio_err,"Certificate does not contain DSA parameters\n");
goto end;
}
-
}
BIO_free(in);
newkey=BN_num_bits(dsa_params->p);
in=NULL;
}
- else if (strncmp("dh:",p,4) == 0)
+ else
+#endif
+#ifndef NO_DH
+ if (strncmp("dh:",p,4) == 0)
{
pkey_type=TYPE_DH;
p+=3;
}
else
+#endif
pkey_type=TYPE_RSA;
newreq=1;
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");
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");
}
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);
+ strcat(config_name,OPENSSL_CONF);
p=config_name;
}
default_config_file=p;
}
}
+ 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))
{
digest=md_alg;
}
+ extensions = CONF_get_string(req_conf, SECTION, V3_EXTENSIONS);
+
in=BIO_new(BIO_s_file());
out=BIO_new(BIO_s_file());
if ((in == NULL) || (out == NULL))
if (pkey_type == TYPE_RSA)
{
if (!EVP_PKEY_assign_RSA(pkey,
- RSA_generate_key(newkey,0x10001,req_cb)))
+ RSA_generate_key(newkey,0x10001,
+ req_cb,(char *)bio_err)))
goto end;
}
else
if (newreq || x509)
{
+#ifndef NO_DSA
if (pkey->type == EVP_PKEY_DSA)
digest=EVP_dss1();
+#endif
if (pkey == NULL)
{
}
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,
(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 */
+
+ ext_ctx.issuer_cert = x509ss;
+ ext_ctx.subject_cert = x509ss;
+ ext_ctx.subject_req = NULL;
+ ext_ctx.crl = NULL;
+ ext_ctx.flags = 0;
+
+ /* 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;
}
i=X509_REQ_verify(req,pkey);
- if (tmp) pkey=NULL;
+ if (tmp) {
+ EVP_PKEY_free(pkey);
+ pkey=NULL;
+ }
if (i < 0)
{
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");
}
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);
}
EVP_PKEY *pkey;
int attribs;
{
- int ret=0,i,j;
- unsigned char *p;
+ int ret=0,i;
+ unsigned char *p,*q;
X509_REQ_INFO *ri;
char buf[100];
int nid,min,max;
if ((int)sk_num(sk) <= i) break;
v=(CONF_VALUE *)sk_value(sk,i);
- p=NULL;
+ p=q=NULL;
type=v->name;
- for (j=0; type[j] != '\0'; j++)
- {
- if ( (type[j] == ':') ||
- (type[j] == ',') ||
- (type[j] == '.'))
- p= (unsigned char *)&(type[j+1]);
- }
- if (p != NULL)
- type=(char *)p;
- if ((nid=OBJ_txt2nid(type)) == NID_undef)
- goto start;
-
+ 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 != '.')) break;
+ if (*p) type=(char *)p;
+ /* 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="";
return(0);
}
-static void MS_CALLBACK req_cb(p, n)
+static void MS_CALLBACK req_cb(p,n,arg)
int p;
int n;
+char *arg;
{
char c='*';
if (p == 1) c='+';
if (p == 2) c='*';
if (p == 3) c='\n';
- BIO_write(bio_err,&c,1);
- BIO_flush(bio_err);
+ BIO_write((BIO *)arg,&c,1);
+ BIO_flush((BIO *)arg);
#ifdef LINT
p=n;
#endif
}
return(1);
}
+
+/* Check if the end of a string matches 'end' */
+static int check_end(str, 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;
+fprintf(stderr, "Matching %s, %s %s\n", str, end, tmp);
+ return strcmp(tmp, end);
+}
+
+static int add_oid_section(conf)
+LHASH *conf;
+{
+ char *p;
+ STACK *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_num(sktmp); i++) {
+ cnf = (CONF_VALUE *)sk_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;
+}