#include <openssl/ocsp.h>
#include <openssl/pem.h>
-#ifdef OPENSSL_SYS_WINDOWS
-#define strcasecmp _stricmp
-#else
-# ifdef NO_STRINGS_H
- int strcasecmp();
-# else
-# include <strings.h>
-# endif /* NO_STRINGS_H */
-#endif
-
#ifndef W_OK
# ifdef OPENSSL_SYS_VMS
# if defined(__DECC)
# else
# include <unixlib.h>
# endif
-# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS)
+# elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) && !defined(OPENSSL_SYS_NETWARE)
# include <sys/file.h>
# endif
#endif
#define ENV_NEW_CERTS_DIR "new_certs_dir"
#define ENV_CERTIFICATE "certificate"
#define ENV_SERIAL "serial"
+#define ENV_CRLNUMBER "crlnumber"
#define ENV_CRL "crl"
#define ENV_PRIVATE_KEY "private_key"
#define ENV_RANDFILE "RANDFILE"
" -keyform arg - private key file format (PEM or ENGINE)\n",
" -key arg - key to decode the private key if it is encrypted\n",
" -cert file - The CA certificate\n",
+" -selfsign - sign a certificate with the key associated with it\n",
" -in file - The input PEM encoded certificate request(s)\n",
" -out file - Where to put the output file(s)\n",
" -outdir dir - Where to put output certificates\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",
+" -multivalue-rdn - enable support for multivalued RDNs\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 void lookup_fail(char *name,char *tag);
static int certify(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,CA_DB *db,
- BIGNUM *serial, char *subj, int email_dn, char *startdate,
+ BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate,
char *enddate, long days, int batch, char *ext_sect, CONF *conf,
int verbose, unsigned long certopt, unsigned long nameopt,
int default_op, int ext_copy, int selfsign);
static int certify_cert(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
- CA_DB *db, BIGNUM *serial, char *subj, int email_dn,
+ CA_DB *db, BIGNUM *serial, char *subj, int multirdn, int email_dn,
char *startdate, char *enddate, long days, int batch,
char *ext_sect, CONF *conf,int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy,
ENGINE *e);
static int certify_spkac(X509 **xret, char *infile,EVP_PKEY *pkey,X509 *x509,
const EVP_MD *dgst,STACK_OF(CONF_VALUE) *policy,
- CA_DB *db, BIGNUM *serial,char *subj, int email_dn,
+ CA_DB *db, BIGNUM *serial,char *subj, int multirdn, int email_dn,
char *startdate, char *enddate, long days, char *ext_sect,
CONF *conf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy);
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, CA_DB *db, BIGNUM *serial,char *subj,
+ STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial,char *subj, int multirdn,
int email_dn, char *startdate, char *enddate, long days, int batch,
int verbose, X509_REQ *req, char *ext_sect, CONF *conf,
unsigned long certopt, unsigned long nameopt, int default_op,
char *outfile=NULL;
char *outdir=NULL;
char *serialfile=NULL;
+ char *crlnumberfile=NULL;
char *extensions=NULL;
char *extfile=NULL;
char *subj=NULL;
+ int multirdn = 0;
char *tmp_email_dn=NULL;
char *crl_ext=NULL;
int rev_type = REV_NONE;
char *rev_arg = NULL;
BIGNUM *serial=NULL;
+ BIGNUM *crlnumber=NULL;
char *startdate=NULL;
char *enddate=NULL;
long days=0;
subj= *(++argv);
/* preserve=1; */
}
+ else if (strcmp(*argv,"-multivalue-rdn") == 0)
+ multirdn=1;
else if (strcmp(*argv,"-startdate") == 0)
{
if (--argc < 1) goto bad;
{
total++;
j=certify_spkac(&x,spkac_file,pkey,x509,dgst,attribs,db,
- serial,subj,email_dn,startdate,enddate,days,extensions,
+ serial,subj,multirdn,email_dn,startdate,enddate,days,extensions,
conf,verbose,certopt,nameopt,default_op,ext_copy);
if (j < 0) goto err;
if (j > 0)
{
total++;
j=certify_cert(&x,ss_cert_file,pkey,x509,dgst,attribs,
- db,serial,subj,email_dn,startdate,enddate,days,batch,
+ db,serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, e);
if (j < 0) goto err;
{
total++;
j=certify(&x,infile,pkey,x509p,dgst,attribs,db,
- serial,subj,email_dn,startdate,enddate,days,batch,
+ serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, selfsign);
if (j < 0) goto err;
{
total++;
j=certify(&x,argv[i],pkey,x509p,dgst,attribs,db,
- serial,subj,email_dn,startdate,enddate,days,batch,
+ serial,subj,multirdn,email_dn,startdate,enddate,days,batch,
extensions,conf,verbose, certopt, nameopt,
default_op, ext_copy, selfsign);
if (j < 0) goto err;
BIO_printf(bio_err,"Write out database with %d new entries\n",sk_X509_num(cert_sk));
- if(strlen(serialfile) > BSIZE-5 || strlen(dbfile) > BSIZE-5)
- {
- BIO_printf(bio_err,"file name too long\n");
- goto err;
- }
-
- strcpy(buf[0],serialfile);
-
-#ifdef OPENSSL_SYS_VMS
- strcat(buf[0],"-new");
-#else
- strcat(buf[0],".new");
-#endif
-
- if (!save_serial(buf[0],serial,NULL)) goto err;
+ if (!save_serial(serialfile,"new",serial,NULL)) goto err;
if (!save_index(dbfile, "new", db)) goto err;
}
if (sk_X509_num(cert_sk))
{
/* Rename the database and the serial file */
- strncpy(buf[2],serialfile,BSIZE-4);
- buf[2][BSIZE-4]='\0';
-
-#ifdef OPENSSL_SYS_VMS
- strcat(buf[2],"-old");
-#else
- strcat(buf[2],".old");
-#endif
-
- BIO_free(in);
- BIO_free_all(out);
- in=NULL;
- out=NULL;
- if (rename(serialfile,buf[2]) < 0)
- {
- BIO_printf(bio_err,"unable to rename %s to %s\n",
- serialfile,buf[2]);
- perror("reason");
- goto err;
- }
- if (rename(buf[0],serialfile) < 0)
- {
- BIO_printf(bio_err,"unable to rename %s to %s\n",
- buf[0],serialfile);
- perror("reason");
- rename(buf[2],serialfile);
- goto err;
- }
+ if (!rotate_serial(serialfile,"new","old")) goto err;
if (!rotate_index(dbfile,"new","old")) goto err;
}
}
+ if ((crlnumberfile=NCONF_get_string(conf,section,ENV_CRLNUMBER))
+ != NULL)
+ if ((crlnumber=load_serial(crlnumberfile,0,NULL)) == NULL)
+ {
+ BIO_printf(bio_err,"error while loading CRL number\n");
+ goto err;
+ }
+
if (!crldays && !crlhours)
{
if (!NCONF_get_number(conf,section,
/* Add any extensions asked for */
- if (crl_ext)
+ if (crl_ext || crlnumberfile != NULL)
{
X509V3_CTX crlctx;
X509V3_set_ctx(&crlctx, x509, NULL, NULL, crl, 0);
X509V3_set_nconf(&crlctx, conf);
- if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
- crl_ext, crl)) goto err;
+ if (crl_ext)
+ if (!X509V3_EXT_CRL_add_nconf(conf, &crlctx,
+ crl_ext, crl)) goto err;
+ if (crlnumberfile != NULL)
+ {
+ tmpser = BN_to_ASN1_INTEGER(crlnumber, NULL);
+ if (!tmpser) goto err;
+ X509_CRL_add1_ext_i2d(crl,NID_crl_number,tmpser,0,0);
+ ASN1_INTEGER_free(tmpser);
+ crl_v2 = 1;
+ if (!BN_add_word(crlnumber,1)) goto err;
+ }
}
if (crl_ext || crl_v2)
{
goto err; /* version 2 CRL */
}
+
+ if (crlnumberfile != NULL) /* we have a CRL number that need updating */
+ if (!save_serial(crlnumberfile,"new",crlnumber,NULL)) goto err;
+
if (!X509_CRL_sign(crl,pkey,dgst)) goto err;
PEM_write_bio_X509_CRL(Sout,crl);
+
+ if (crlnumberfile != NULL) /* Rename the crlnumber file */
+ if (!rotate_serial(crlnumberfile,"new","old")) goto err;
+
}
/*****************************************************************/
if (dorevoke)
static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
- BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
+ BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
long days, int batch, char *ext_sect, CONF *lconf, int verbose,
unsigned long certopt, unsigned long nameopt, int default_op,
int ext_copy, int selfsign)
else
BIO_printf(bio_err,"Signature ok\n");
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, email_dn,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj, multirdn, email_dn,
startdate,enddate,days,batch,verbose,req,ext_sect,lconf,
certopt, nameopt, default_op, ext_copy, selfsign);
static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
- BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
+ BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
long days, int batch, char *ext_sect, CONF *lconf, int verbose,
unsigned long certopt, unsigned long nameopt, int default_op,
int ext_copy, ENGINE *e)
if ((rreq=X509_to_X509_REQ(req,NULL,EVP_md5())) == NULL)
goto err;
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,multirdn,email_dn,startdate,enddate,
days,batch,verbose,rreq,ext_sect,lconf, certopt, nameopt, default_op,
ext_copy, 0);
static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst,
STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, char *subj,
+ int multirdn,
int email_dn, char *startdate, char *enddate, long days, int batch,
int verbose, X509_REQ *req, char *ext_sect, CONF *lconf,
unsigned long certopt, unsigned long nameopt, int default_op,
if (subj)
{
- X509_NAME *n = do_subject(subj, MBSTRING_ASC);
+ X509_NAME *n = parse_name(subj, MBSTRING_ASC, multirdn);
if (!n)
{
static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509,
const EVP_MD *dgst, STACK_OF(CONF_VALUE) *policy, CA_DB *db,
- BIGNUM *serial, char *subj, int email_dn, char *startdate, char *enddate,
+ BIGNUM *serial, char *subj, int multirdn, int email_dn, char *startdate, char *enddate,
long days, char *ext_sect, CONF *lconf, int verbose, unsigned long certopt,
unsigned long nameopt, int default_op, int ext_copy)
{
X509_REQ_set_pubkey(req,pktmp);
EVP_PKEY_free(pktmp);
- ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,email_dn,startdate,enddate,
+ ok=do_body(xret,pkey,x509,dgst,policy,db,serial,subj,multirdn,email_dn,startdate,enddate,
days,1,verbose,req,ext_sect,lconf, certopt, nameopt, default_op,
ext_copy, 0);
err:
return ret;
}
-/*
- * subject is expected to be in the format /type0=value0/type1=value1/type2=...
- * where characters may be escaped by \
- */
-X509_NAME *do_subject(char *subject, long chtype)
- {
- size_t buflen = strlen(subject)+1; /* to copy the types and values into. due to escaping, the copy can only become shorter */
- char *buf = OPENSSL_malloc(buflen);
- size_t max_ne = buflen / 2 + 1; /* maximum number of name elements */
- char **ne_types = OPENSSL_malloc(max_ne * sizeof (char *));
- char **ne_values = OPENSSL_malloc(max_ne * sizeof (char *));
-
- char *sp = subject, *bp = buf;
- int i, ne_num = 0;
-
- X509_NAME *n = NULL;
- int nid;
-
- if (!buf || !ne_types || !ne_values)
- {
- BIO_printf(bio_err, "malloc error\n");
- goto error;
- }
-
- if (*subject != '/')
- {
- BIO_printf(bio_err, "Subject does not start with '/'.\n");
- goto error;
- }
- sp++; /* skip leading / */
-
- while (*sp)
- {
- /* collect type */
- ne_types[ne_num] = bp;
- while (*sp)
- {
- if (*sp == '\\') /* is there anything to escape in the type...? */
- {
- if (*++sp)
- *bp++ = *sp++;
- else
- {
- BIO_printf(bio_err, "escape character at end of string\n");
- goto error;
- }
- }
- else if (*sp == '=')
- {
- sp++;
- *bp++ = '\0';
- break;
- }
- else
- *bp++ = *sp++;
- }
- if (!*sp)
- {
- BIO_printf(bio_err, "end of string encountered while processing type of subject name element #%d\n", ne_num);
- goto error;
- }
- ne_values[ne_num] = bp;
- while (*sp)
- {
- if (*sp == '\\')
- {
- if (*++sp)
- *bp++ = *sp++;
- else
- {
- BIO_printf(bio_err, "escape character at end of string\n");
- goto error;
- }
- }
- else if (*sp == '/')
- {
- sp++;
- break;
- }
- else
- *bp++ = *sp++;
- }
- *bp++ = '\0';
- ne_num++;
- }
-
- if (!(n = X509_NAME_new()))
- goto error;
-
- for (i = 0; i < ne_num; i++)
- {
- if ((nid=OBJ_txt2nid(ne_types[i])) == NID_undef)
- {
- BIO_printf(bio_err, "Subject Attribute %s has no known NID, skipped\n", ne_types[i]);
- continue;
- }
-
- if (!*ne_values[i])
- {
- BIO_printf(bio_err, "No value provided for Subject Attribute %s, skipped\n", ne_types[i]);
- continue;
- }
-
- if (!X509_NAME_add_entry_by_NID(n, nid, chtype, (unsigned char*)ne_values[i], -1,-1,0))
- goto error;
- }
-
- OPENSSL_free(ne_values);
- OPENSSL_free(ne_types);
- OPENSSL_free(buf);
- return n;
-
-error:
- X509_NAME_free(n);
- if (ne_values)
- OPENSSL_free(ne_values);
- if (ne_types)
- OPENSSL_free(ne_types);
- if (buf)
- OPENSSL_free(buf);
- return NULL;
-}
-
int old_entry_print(BIO *bp, ASN1_OBJECT *obj, ASN1_STRING *str)
{
char buf[25],*pbuf, *p;
char *tmp = NULL;
char *rtime_str, *reason_str = NULL, *arg_str = NULL, *p;
int reason_code = -1;
- int i, ret = 0;
+ int ret = 0;
+ unsigned int i;
ASN1_OBJECT *hold = NULL;
ASN1_GENERALIZEDTIME *comp_time = NULL;
tmp = BUF_strdup(str);
return ret;
}
-