" -batch - Don't ask questions\n",
" -msie_hack - msie modifications to handle all those universal strings\n",
" -revoke file - Revoke a certificate (given in file)\n",
+" -subj arg - Use arg instead of request's subject\n",
" -extensions .. - Extension section (override value in config file)\n",
" -extfile file - Configuration file with X509v3 extentions to add\n",
" -crlexts .. - CRL extension section (override value in config file)\n",
static int save_serial(char *serialfile, BIGNUM *serial);
static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,TXT_DB *db,
- BIGNUM *serial, char *startdate,char *enddate, int days,
- int batch, char *ext_sect, LHASH *conf,int verbose);
+ BIGNUM *serial, char *subj, char *startdate,char *enddate,
+ int days, int batch, char *ext_sect, LHASH *conf,int verbose);
static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
- TXT_DB *db, BIGNUM *serial,char *startdate,
+ TXT_DB *db, BIGNUM *serial, char *subj, char *startdate,
char *enddate, int days, int batch, char *ext_sect,
LHASH *conf,int verbose);
static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
- TXT_DB *db, BIGNUM *serial,char *startdate,
+ TXT_DB *db, BIGNUM *serial,char *subj, char *startdate,
char *enddate, int days, char *ext_sect,LHASH *conf,
int verbose);
static int fix_data(int nid, int *type);
static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext);
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
- STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
+ STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,char *subj,
char *startdate, char *enddate, int days, int batch, int verbose,
X509_REQ *req, char *ext_sect, LHASH *conf);
+static X509_NAME *do_subject(char *subject);
static int do_revoke(X509 *x509, TXT_DB *db, int ext, char *extval);
static int get_certificate_status(const char *ser_status, TXT_DB *db);
static int do_updatedb(TXT_DB *db);
char *serialfile=NULL;
char *extensions=NULL;
char *extfile=NULL;
+ char *subj=NULL;
char *crl_ext=NULL;
int rev_type = REV_NONE;
char *rev_arg = NULL;
if (--argc < 1) goto bad;
section= *(++argv);
}
+ else if (strcmp(*argv,"-subj") == 0)
+ {
+ if (--argc < 1) goto bad;
+ subj= *(++argv);
+ /* preserve=1; */
+ }
else if (strcmp(*argv,"-startdate") == 0)
{
if (--argc < 1) goto bad;
lookup_fail(section,ENV_CERTIFICATE);
goto err;
}
- if (BIO_read_filename(in,certfile) <= 0)
+ if (BIO_read_filename(in,certfile) <= 0)
{
perror(certfile);
BIO_printf(bio_err,"trying to load CA certificate\n");
C routines to convert the directory syntax to Unixly, and give
that to access(). However, time's too short to do that just
now.
- */
+ */
if (access(outdir,R_OK|W_OK|X_OK) != 0)
{
BIO_printf(bio_err,"I am unable to access the %s directory\n",outdir);
{
BIO_printf(bio_err,"Malloc failure\n");
goto err;
- }
+ }
else if (i == 0)
- {
+ {
if (verbose) BIO_printf(bio_err,
"No entries found to mark expired\n");
}
/* We can have sections in the ext file */
if (!extensions && !(extensions = CONF_get_string(extconf, "default", "extensions")))
extensions = "default";
- }
+ }
/*****************************************************************/
if (req || gencrl)
{
total++;
j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
- serial,startdate,enddate, days,extensions,conf,
+ serial,subj,startdate,enddate, days,extensions,conf,
verbose);
if (j < 0) goto err;
if (j > 0)
{
total++;
j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
- db,serial,startdate,enddate,days,batch,
+ db,serial,subj,startdate,enddate,days,batch,
extensions,conf,verbose);
if (j < 0) goto err;
if (j > 0)
{
total++;
j=certify(&x,infile,pkey,x509,dgst,attribs,db,
- serial,startdate,enddate,days,batch,
+ serial,subj,startdate,enddate,days,batch,
extensions,conf,verbose);
if (j < 0) goto err;
if (j > 0)
{
total++;
j=certify(&x,argv[i],pkey,x509,dgst,attribs,db,
- serial,startdate,enddate,days,batch,
+ serial,subj,startdate,enddate,days,batch,
extensions,conf,verbose);
if (j < 0) goto err;
if (j > 0)
static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
- BIGNUM *serial, char *startdate, char *enddate, int days,
+ BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
int batch, char *ext_sect, LHASH *lconf, int verbose)
{
X509_REQ *req=NULL;
else
BIO_printf(bio_err,"Signature ok\n");
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate, enddate,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate, enddate,
days,batch,verbose,req,ext_sect,lconf);
err:
static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
- BIGNUM *serial, char *startdate, char *enddate, int days,
+ BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
int batch, char *ext_sect, LHASH *lconf, int verbose)
{
X509 *req=NULL;
if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
goto err;
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,days,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,days,
batch,verbose,rreq,ext_sect,lconf);
err:
}
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
- STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial,
+ STACK_OF(CONF_VALUE) *policy, TXT_DB *db, BIGNUM *serial, char *subj,
char *startdate, char *enddate, int days, int batch, int verbose,
X509_REQ *req, char *ext_sect, LHASH *lconf)
{
for (i=0; i<DB_NUMBER; i++)
row[i]=NULL;
- BIO_printf(bio_err,"The Subjects Distinguished Name is as follows\n");
+ if (subj)
+ {
+ X509_NAME *n = do_subject(subj);
+
+ if (!n)
+ {
+ ERR_print_errors(bio_err);
+ goto err;
+ }
+ X509_REQ_set_subject_name(req,n);
+ req->req_info->enc.modified = 1;
+ X509_NAME_free(n);
+ }
+
+ BIO_printf(bio_err,"The Subject's Distinguished Name is as follows\n");
name=X509_REQ_get_subject_name(req);
for (i=0; i<X509_NAME_entry_count(name); i++)
{
static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, TXT_DB *db,
- BIGNUM *serial, char *startdate, char *enddate, int days,
+ BIGNUM *serial, char *subj, char *startdate, char *enddate, int days,
char *ext_sect, LHASH *lconf, int verbose)
{
STACK_OF(CONF_VALUE) *sk=NULL;
X509_REQ_set_pubkey(req,pktmp);
EVP_PKEY_free(pktmp);
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,startdate,enddate,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,startdate,enddate,
days,1,verbose,req,ext_sect,lconf);
err:
if (req != NULL) X509_REQ_free(req);
return ret;
}
+
+static X509_NAME *do_subject(char *subject)
+ {
+ X509_NAME *n = NULL;
+
+ int i, nid, ne_num=0;
+
+ char *ne_name = NULL;
+ char *ne_value = NULL;
+
+ char *tmp = NULL;
+ char *p[2];
+
+ char *str_list[256];
+
+ p[0] = ",/";
+ p[1] = "=";
+
+ n = X509_NAME_new();
+
+ tmp = strtok(subject, p[0]);
+ while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
+ {
+ char *token = tmp;
+
+ while (token[0] == ' ')
+ token++;
+ str_list[ne_num] = token;
+
+ tmp = strtok(NULL, p[0]);
+ ne_num++;
+ }
+
+ for (i = 0; i < ne_num; i++)
+ {
+ ne_name = strtok(str_list[i], p[1]);
+ ne_value = strtok(NULL, p[1]);
+
+ if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
+ {
+ BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
+ continue;
+ }
+
+ if (ne_value == NULL)
+ {
+ BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
+ continue;
+ }
+
+ if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
+ {
+ X509_NAME_free(n);
+ return NULL;
+ }
+ }
+
+ return n;
+ }
* require. This format is wrong
*/
-static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,int attribs);
+static int make_REQ(X509_REQ *req,EVP_PKEY *pkey,char *dn,int attribs);
+static int build_subject(X509_REQ *req, char *subj);
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);
static LHASH *config=NULL;
#endif
static LHASH *req_conf=NULL;
+static int batch=0;
#define TYPE_RSA 1
#define TYPE_DSA 2
X509 *x509ss=NULL;
X509_REQ *req=NULL;
EVP_PKEY *pkey=NULL;
- int i,badops=0,newreq=0,newkey= -1,pkey_type=TYPE_RSA;
+ int i,badops=0,newreq=0,newkey= -1,verbose=0,pkey_type=TYPE_RSA;
BIO *in=NULL,*out=NULL;
int informat,outformat,verify=0,noout=0,text=0,keyform=FORMAT_PEM;
int nodes=0,kludge=0,newhdr=0,subject=0;
char *passargin = NULL, *passargout = NULL;
char *passin = NULL, *passout = NULL;
char *p;
+ char *subj = NULL;
const EVP_MD *md_alg=NULL,*digest=EVP_md5();
#ifndef MONOLITH
MS_STATIC char config_name[256];
newreq=1;
}
+ else if (strcmp(*argv,"-batch") == 0)
+ batch=1;
else if (strcmp(*argv,"-newhdr") == 0)
newhdr=1;
else if (strcmp(*argv,"-modulus") == 0)
nodes=1;
else if (strcmp(*argv,"-noout") == 0)
noout=1;
+ else if (strcmp(*argv,"-verbose") == 0)
+ verbose=1;
else if (strcmp(*argv,"-nameopt") == 0)
{
if (--argc < 1) goto bad;
kludge=1;
else if (strcmp(*argv,"-no-asn1-kludge") == 0)
kludge=0;
+ else if (strcmp(*argv,"-subj") == 0)
+ {
+ if (--argc < 1) goto bad;
+ subj= *(++argv);
+ }
else if (strcmp(*argv,"-days") == 0)
{
if (--argc < 1) goto 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");
- BIO_printf(bio_err," -engine e use engine e, possibly a hardware device.\n");
- BIO_printf(bio_err," -key file use the private key contained in file\n");
+ BIO_printf(bio_err," -engine e use engine e, possibly a hardware device\n");
+ 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");
BIO_printf(bio_err," -keyform arg key file format\n");
BIO_printf(bio_err," -keyout arg file to send the key to\n");
BIO_printf(bio_err," -rand file%cfile%c...\n", LIST_SEPARATOR_CHAR, LIST_SEPARATOR_CHAR);
BIO_printf(bio_err," the random number generator\n");
BIO_printf(bio_err," -newkey rsa:bits generate a new RSA key of 'bits' in size\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 template file.\n");
+ BIO_printf(bio_err," -subj arg set or modify request subject\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");
BIO_printf(bio_err," -days number of days a certificate generated by -x509 is valid for.\n");
BIO_printf(bio_err," -set_serial serial number to use for a certificate generated by -x509.\n");
BIO_printf(bio_err,"unable to load Private key\n");
goto end;
}
- if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
+ if (EVP_PKEY_type(pkey->type) == EVP_PKEY_DSA)
{
char *randfile = CONF_get_string(req_conf,SECTION,"RANDFILE");
if (randfile == NULL)
ERR_clear_error();
app_RAND_load_file(randfile, bio_err, 0);
- }
+ }
}
if (newreq && (pkey == NULL))
goto end;
}
- i=make_REQ(req,pkey,!x509);
+ i=make_REQ(req,pkey,subj,!x509);
+ subj=NULL; /* done processing '-subj' option */
if ((kludge > 0) && !sk_X509_ATTRIBUTE_num(req->req_info->attributes))
{
sk_X509_ATTRIBUTE_free(req->req_info->attributes);
/* 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;
- }
-
+ {
+ BIO_printf(bio_err,
+ "Error Loading extension section %s\n",
+ extensions);
+ goto end;
+ }
+
if (!(i=X509_sign(x509ss,pkey,digest)))
goto end;
}
/* 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;
- }
+ {
+ BIO_printf(bio_err,
+ "Error Loading extension section %s\n",
+ req_exts);
+ goto end;
+ }
if (!(i=X509_REQ_sign(req,pkey,digest)))
goto end;
}
}
+ if (subj && x509)
+ {
+ BIO_printf(bio_err, "Cannot modifiy certificate subject\n");
+ goto end;
+ }
+
+ if (subj && !x509)
+ {
+ if (verbose)
+ {
+ BIO_printf(bio_err, "Modifying Request's Subject\n");
+ print_name(bio_err, "old subject=", X509_REQ_get_subject_name(req), nmflag);
+ }
+
+ if (build_subject(req, subj) == 0)
+ {
+ BIO_printf(bio_err, "ERROR: cannot modify subject\n");
+ ex=1;
+ goto end;
+ }
+
+ req->req_info->enc.modified = 1;
+
+ if (verbose)
+ {
+ print_name(bio_err, "new subject=", X509_REQ_get_subject_name(req), nmflag);
+ }
+ }
+
if (verify && !x509)
{
int tmp=0;
EXIT(ex);
}
-static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, int attribs)
+static int make_REQ(X509_REQ *req, EVP_PKEY *pkey, char *subj, int attribs)
{
int ret=0,i;
char no_prompt = 0;
/* setup version number */
if (!X509_REQ_set_version(req,0L)) goto err; /* version 1 */
- if(no_prompt) i = auto_info(req, dn_sk, attr_sk, attribs);
- else i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs);
+ if (no_prompt)
+ i = auto_info(req, dn_sk, attr_sk, attribs);
+ else
+ {
+ if (subj)
+ i = build_subject(req, subj);
+ else
+ i = prompt_info(req, dn_sk, dn_sect, attr_sk, attr_sect, attribs);
+ }
if(!i) goto err;
X509_REQ_set_pubkey(req,pkey);
return(ret);
}
+static int build_subject(X509_REQ *req, char *subject)
+ {
+ X509_NAME *n = NULL;
+
+ int i, nid, ne_num=0;
+
+ char *ne_name = NULL;
+ char *ne_value = NULL;
+
+ char *tmp = NULL;
+ char *p[2];
+
+ char *str_list[256];
+
+ p[0] = ",/";
+ p[1] = "=";
+
+ n = X509_NAME_new();
+
+ tmp = strtok(subject, p[0]);
+ while((tmp != NULL) && (ne_num < (sizeof str_list/sizeof *str_list)))
+ {
+ char *token = tmp;
+
+ while (token[0] == ' ')
+ token++;
+ str_list[ne_num] = token;
+
+ tmp = strtok(NULL, p[0]);
+ ne_num++;
+ }
+
+ for(i = 0; i < ne_num; i++)
+ {
+ ne_name = strtok(str_list[i], p[1]);
+ ne_value = strtok(NULL, p[1]);
+
+ if ((nid=OBJ_txt2nid(ne_name)) == NID_undef)
+ {
+ BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_name);
+ continue;
+ }
+
+ if (ne_value == NULL)
+ {
+ BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_name);
+ continue;
+ }
+
+ if (!X509_NAME_add_entry_by_NID(n, nid, MBSTRING_ASC, (unsigned char*)ne_value, -1,-1,0))
+ {
+ X509_NAME_free(n);
+ return 0;
+ }
+ }
+
+ if (!X509_REQ_set_subject_name(req, n))
+ return 0;
+ X509_NAME_free(n);
+ return 1;
+}
+
static int prompt_info(X509_REQ *req,
STACK_OF(CONF_VALUE) *dn_sk, char *dn_sect,
CONF_VALUE *v;
X509_NAME *subj;
subj = X509_REQ_get_subject_name(req);
- 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");
- BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n");
- BIO_printf(bio_err,"For some fields there will be a default value,\n");
- BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
- BIO_printf(bio_err,"-----\n");
+
+ if(!batch)
+ {
+ 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");
+ BIO_printf(bio_err,"There are quite a few fields but you can leave some blank\n");
+ BIO_printf(bio_err,"For some fields there will be a default value,\n");
+ BIO_printf(bio_err,"If you enter '.', the field will be left blank.\n");
+ BIO_printf(bio_err,"-----\n");
+ }
if (sk_CONF_VALUE_num(dn_sk))
if (attribs)
{
- if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0))
+ if ((attr_sk != NULL) && (sk_CONF_VALUE_num(attr_sk) > 0) && (!batch))
{
BIO_printf(bio_err,"\nPlease enter the following 'extra' attributes\n");
BIO_printf(bio_err,"to be sent with your certificate request\n");
int i,ret=0;
MS_STATIC char buf[1024];
start:
- BIO_printf(bio_err,"%s [%s]:",text,def);
+ if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
(void)BIO_flush(bio_err);
- if (value != NULL)
+ if(value != NULL)
{
strcpy(buf,value);
strcat(buf,"\n");
else
{
buf[0]='\0';
- fgets(buf,1024,stdin);
+ if (!batch)
+ {
+ fgets(buf,1024,stdin);
+ }
+ else
+ {
+ buf[0] = '\n';
+ buf[1] = '\0';
+ }
}
if (buf[0] == '\0') return(0);
return(0);
}
buf[--i]='\0';
-
#ifdef CHARSET_EBCDIC
ebcdic2ascii(buf, buf, i);
#endif
static char buf[1024];
start:
- BIO_printf(bio_err,"%s [%s]:",text,def);
+ if (!batch) BIO_printf(bio_err,"%s [%s]:",text,def);
(void)BIO_flush(bio_err);
if (value != NULL)
{
else
{
buf[0]='\0';
- fgets(buf,1024,stdin);
+ if (!batch)
+ {
+ fgets(buf,1024,stdin);
+ }
+ else
+ {
+ buf[0] = '\n';
+ buf[1] = '\0';
+ }
}
if (buf[0] == '\0') return(0);