#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"
#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
* 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;
#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;
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
}
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 ((dsa_params=PEM_read_bio_DSAparams(in,NULL,NULL)) == NULL)
{
ERR_clear_error();
- BIO_reset(in);
+ (void)BIO_reset(in);
if ((xtmp=PEM_read_bio_X509(in,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)
{
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);
+#ifndef VMS
+ strcat(config_name,"/");
+#endif
+ 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);
+ 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))
{
if (!EVP_PKEY_assign_RSA(pkey,
RSA_generate_key(newkey,0x10001,
- req_cb,(char *)bio_err)))
+ req_cb,bio_err)))
goto end;
}
else
}
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 */
+
+ 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;
}
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);
}
-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);
/* 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="";
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;
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");
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;
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);
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;
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;
start:
BIO_printf(bio_err,"%s [%s]:",text,def);
- BIO_flush(bio_err);
+ (void)BIO_flush(bio_err);
if (value != NULL)
{
strcpy(buf,value);
/* 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;
{ 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);
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='*';
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;
}
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;
+}