X-Git-Url: https://git.openssl.org/?p=openssl.git;a=blobdiff_plain;f=apps%2Fca.c;h=102ff87d6fe1c712668ba7406f8ddca145dc96de;hp=3cad05d68d63dcd982bce73471025b8a10d077e0;hb=218712ffddfdf3c7574c1d945e094f6601500caa;hpb=1421aeadd757e0c564314ba62521979d08884ccc diff --git a/apps/ca.c b/apps/ca.c index 3cad05d68d..102ff87d6f 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -28,11 +28,7 @@ #ifndef W_OK # ifdef OPENSSL_SYS_VMS -# if defined(__DECC) -# include -# else -# include -# endif +# include # elif !defined(OPENSSL_SYS_VXWORKS) && !defined(OPENSSL_SYS_WINDOWS) # include # endif @@ -47,8 +43,14 @@ # define R_OK 4 #endif -#undef BSIZE -#define BSIZE 256 +#ifndef PATH_MAX +# define PATH_MAX 4096 +#endif +#ifndef NAME_MAX +# define NAME_MAX 255 +#endif + +#define CERT_MAX (PATH_MAX + NAME_MAX) #define BASE_SECTION "ca" @@ -82,56 +84,60 @@ #define ENV_DATABASE "database" /* Additional revocation information types */ - -#define REV_NONE 0 /* No addditional information */ -#define REV_CRL_REASON 1 /* Value is CRL reason code */ -#define REV_HOLD 2 /* Value is hold instruction */ -#define REV_KEY_COMPROMISE 3 /* Value is cert key compromise time */ -#define REV_CA_COMPROMISE 4 /* Value is CA key compromise time */ +typedef enum { + REV_VALID = -1, /* Valid (not-revoked) status */ + REV_NONE = 0, /* No additional information */ + REV_CRL_REASON = 1, /* Value is CRL reason code */ + REV_HOLD = 2, /* Value is hold instruction */ + REV_KEY_COMPROMISE = 3, /* Value is cert key compromise time */ + REV_CA_COMPROMISE = 4 /* Value is CA key compromise time */ +} REVINFO_TYPE; static char *lookup_conf(const CONF *conf, const char *group, const char *tag); -static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, + +static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, char *enddate, - long days, int batch, char *ext_sect, CONF *conf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, + long days, int batch, const 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, +static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, int batch, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, int batch, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy); -static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, +static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, char *ext_sect, CONF *conf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, const char *ext_sect, CONF *conf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy); -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(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, - char *subj, unsigned long chtype, int multirdn, - int email_dn, char *startdate, char *enddate, long days, - int batch, int verbose, X509_REQ *req, char *ext_sect, + const char *subj, unsigned long chtype, int multirdn, + int email_dn, const char *startdate, const char *enddate, long days, + int batch, int verbose, X509_REQ *req, const char *ext_sect, CONF *conf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign); -static int do_revoke(X509 *x509, CA_DB *db, int ext, char *extval); static int get_certificate_status(const char *ser_status, CA_DB *db); static int do_updatedb(CA_DB *db); static int check_time_format(const char *str); -char *make_revocation_str(int rev_type, char *rev_arg); -int make_revoked(X509_REVOKED *rev, const char *str); -static int old_entry_print(ASN1_OBJECT *obj, ASN1_STRING *str); +static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, + const char *extval); +static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg); +static int make_revoked(X509_REVOKED *rev, const char *str); +static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str); +static void write_new_certificate(BIO *bp, X509 *x, int output_der, int notext); static CONF *extconf = NULL; static int preserve = 0; @@ -147,11 +153,11 @@ typedef enum OPTION_choice { OPT_GENCRL, OPT_MSIE_HACK, OPT_CRLDAYS, OPT_CRLHOURS, OPT_CRLSEC, OPT_INFILES, OPT_SS_CERT, OPT_SPKAC, OPT_REVOKE, OPT_VALID, OPT_EXTENSIONS, OPT_EXTFILE, OPT_STATUS, OPT_UPDATEDB, OPT_CRLEXTS, - OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, - OPT_CRL_CA_COMPROMISE + /* Do not change the order here; see related case statements below */ + OPT_CRL_REASON, OPT_CRL_HOLD, OPT_CRL_COMPROMISE, OPT_CRL_CA_COMPROMISE } OPTION_CHOICE; -OPTIONS ca_options[] = { +const OPTIONS ca_options[] = { {"help", OPT_HELP, '-', "Display this summary"}, {"verbose", OPT_VERBOSE, '-', "Verbose output during processing"}, {"config", OPT_CONFIG, 's', "A config file"}, @@ -159,7 +165,7 @@ OPTIONS ca_options[] = { {"subj", OPT_SUBJ, 's', "Use arg instead of request's subject"}, {"utf8", OPT_UTF8, '-', "Input characters are UTF8 (default ASCII)"}, {"create_serial", OPT_CREATE_SERIAL, '-', - "If reading serial fails, create a new random serial"}, + "If reading serial fails, create a new random serial"}, {"multivalue-rdn", OPT_MULTIVALUE_RDN, '-', "Enable support for multivalued RDNs"}, {"startdate", OPT_STARTDATE, 's', "Cert notBefore, YYMMDDHHMMSSZ"}, @@ -194,7 +200,8 @@ OPTIONS ca_options[] = { {"spkac", OPT_SPKAC, '<', "File contains DN and signed public key and challenge"}, {"revoke", OPT_REVOKE, '<', "Revoke a cert (given in file)"}, - {"valid", OPT_VALID, 's'}, + {"valid", OPT_VALID, 's', + "Add a Valid(not-revoked) DB entry about a cert (given in file)"}, {"extensions", OPT_EXTENSIONS, 's', "Extension section (override value in config file)"}, {"extfile", OPT_EXTFILE, '<', @@ -222,7 +229,7 @@ int ca_main(int argc, char **argv) ENGINE *e = NULL; BIGNUM *crlnumber = NULL, *serial = NULL; EVP_PKEY *pkey = NULL; - BIO *in = NULL, *out = NULL, *Sout = NULL, *Cout = NULL; + BIO *in = NULL, *out = NULL, *Sout = NULL; ASN1_INTEGER *tmpser; ASN1_TIME *tmptm; CA_DB *db = NULL; @@ -234,27 +241,31 @@ int ca_main(int argc, char **argv) const EVP_MD *dgst = NULL; char *configfile = default_config_file, *section = NULL; char *md = NULL, *policy = NULL, *keyfile = NULL; - char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL; - char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL; - char *extensions = NULL, *extfile = NULL, *key = NULL, *passinarg = NULL; + char *certfile = NULL, *crl_ext = NULL, *crlnumberfile = NULL, *key = NULL; + const char *infile = NULL, *spkac_file = NULL, *ss_cert_file = NULL; + const char *extensions = NULL, *extfile = NULL, *passinarg = NULL; char *outdir = NULL, *outfile = NULL, *rev_arg = NULL, *ser_status = NULL; - char *serialfile = NULL, *startdate = NULL, *subj = NULL; - char *prog, *enddate = NULL; + const char *serialfile = NULL, *subj = NULL; + char *prog, *startdate = NULL, *enddate = NULL; char *dbfile = NULL, *f, *randfile = NULL; - char buf[3][BSIZE]; + char new_cert[CERT_MAX + 1]; + char tmp[10 + 1] = "\0"; char *const *pp; const char *p; int create_ser = 0, free_key = 0, total = 0, total_done = 0; int batch = 0, default_op = 1, doupdatedb = 0, ext_copy = EXT_COPY_NONE; int keyformat = FORMAT_PEM, multirdn = 0, notext = 0, output_der = 0; int ret = 1, email_dn = 1, req = 0, verbose = 0, gencrl = 0, dorevoke = 0; - int i, j, rev_type = REV_NONE, selfsign = 0; + int i, j, selfsign = 0; long crldays = 0, crlhours = 0, crlsec = 0, days = 0; - unsigned long chtype = MBSTRING_ASC, nameopt = 0, certopt = 0; + unsigned long chtype = MBSTRING_ASC, certopt = 0; X509 *x509 = NULL, *x509p = NULL, *x = NULL; + REVINFO_TYPE rev_type = REV_NONE; X509_REVOKED *r = NULL; OPTION_CHOICE o; + new_cert[CERT_MAX] = '\0'; + prog = opt_init(argc, argv, ca_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -401,21 +412,12 @@ opthelp: case OPT_CRLEXTS: crl_ext = opt_arg(); break; - case OPT_CRL_REASON: - rev_arg = opt_arg(); - rev_type = REV_CRL_REASON; - break; + case OPT_CRL_REASON: /* := REV_CRL_REASON */ case OPT_CRL_HOLD: - rev_arg = opt_arg(); - rev_type = REV_HOLD; - break; case OPT_CRL_COMPROMISE: - rev_arg = opt_arg(); - rev_type = REV_KEY_COMPROMISE; - break; case OPT_CRL_CA_COMPROMISE: rev_arg = opt_arg(); - rev_type = REV_CA_COMPROMISE; + rev_type = (o - OPT_CRL_REASON) + REV_CRL_REASON; break; case OPT_ENGINE: e = setup_engine(opt_arg(), 0); @@ -496,7 +498,7 @@ end_of_options: /* report status of cert with serial number given on command line */ if (ser_status) { dbfile = lookup_conf(conf, section, ENV_DATABASE); - if (dbfile == NULL) + if (dbfile == NULL) goto end; db = load_index(dbfile, &db_attr); @@ -567,14 +569,11 @@ end_of_options: f = NCONF_get_string(conf, section, ENV_NAMEOPT); if (f) { - if (!set_name_ex(&nameopt, f)) { + if (!set_nameopt(f)) { BIO_printf(bio_err, "Invalid name options: \"%s\"\n", f); goto end; } default_op = 0; - } else { - nameopt = XN_FLAG_ONELINE; - ERR_clear_error(); } f = NCONF_get_string(conf, section, ENV_CERTOPT); @@ -864,7 +863,7 @@ end_of_options: j = certify_spkac(&x, spkac_file, pkey, x509, dgst, sigopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, extensions, - conf, verbose, certopt, nameopt, default_op, + conf, verbose, certopt, get_nameopt(), default_op, ext_copy); if (j < 0) goto end; @@ -889,7 +888,7 @@ end_of_options: attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, - conf, verbose, certopt, nameopt, default_op, + conf, verbose, certopt, get_nameopt(), default_op, ext_copy); if (j < 0) goto end; @@ -909,7 +908,7 @@ end_of_options: j = certify(&x, infile, pkey, x509p, dgst, sigopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, - certopt, nameopt, default_op, ext_copy, selfsign); + certopt, get_nameopt(), default_op, ext_copy, selfsign); if (j < 0) goto end; if (j > 0) { @@ -928,7 +927,7 @@ end_of_options: j = certify(&x, argv[i], pkey, x509p, dgst, sigopts, attribs, db, serial, subj, chtype, multirdn, email_dn, startdate, enddate, days, batch, extensions, conf, verbose, - certopt, nameopt, default_op, ext_copy, selfsign); + certopt, get_nameopt(), default_op, ext_copy, selfsign); if (j < 0) goto end; if (j > 0) { @@ -953,14 +952,14 @@ end_of_options: "\n%d out of %d certificate requests certified, commit? [y/n]", total_done, total); (void)BIO_flush(bio_err); - buf[0][0] = '\0'; - if (!fgets(buf[0], 10, stdin)) { + tmp[0] = '\0'; + if (fgets(tmp, sizeof(tmp), stdin) == NULL) { BIO_printf(bio_err, "CERTIFICATION CANCELED: I/O error\n"); ret = 0; goto end; } - if ((buf[0][0] != 'y') && (buf[0][0] != 'Y')) { + if (tmp[0] != 'y' && tmp[0] != 'Y') { BIO_printf(bio_err, "CERTIFICATION CANCELED\n"); ret = 0; goto end; @@ -980,33 +979,32 @@ end_of_options: if (verbose) BIO_printf(bio_err, "writing new certificates\n"); for (i = 0; i < sk_X509_num(cert_sk); i++) { - const ASN1_INTEGER *serialNumber = X509_get_serialNumber(x); + BIO *Cout = NULL; + X509 *xi = sk_X509_value(cert_sk, i); + ASN1_INTEGER *serialNumber = X509_get_serialNumber(xi); int k; char *n; - x = sk_X509_value(cert_sk, i); - j = ASN1_STRING_length(serialNumber); - p = (const char *)ASN1_STRING_data((ASN1_INTEGER *)serialNumber); + p = (const char *)ASN1_STRING_get0_data(serialNumber); - if (strlen(outdir) >= (size_t)(j ? BSIZE - j * 2 - 6 : BSIZE - 8)) { + if (strlen(outdir) >= (size_t)(j ? CERT_MAX - j * 2 - 6 : CERT_MAX - 8)) { BIO_printf(bio_err, "certificate file name too long\n"); goto end; } - strcpy(buf[2], outdir); - + strcpy(new_cert, outdir); #ifndef OPENSSL_SYS_VMS - OPENSSL_strlcat(buf[2], "/", sizeof(buf[2])); + OPENSSL_strlcat(new_cert, "/", sizeof(new_cert)); #endif - n = (char *)&(buf[2][strlen(buf[2])]); + n = (char *)&(new_cert[strlen(new_cert)]); if (j > 0) { for (k = 0; k < j; k++) { - if (n >= &(buf[2][sizeof(buf[2])])) + if (n >= &(new_cert[sizeof(new_cert)])) break; BIO_snprintf(n, - &buf[2][0] + sizeof(buf[2]) - n, + &new_cert[0] + sizeof(new_cert) - n, "%02X", (unsigned char)*(p++)); n += 2; } @@ -1020,15 +1018,16 @@ end_of_options: *(n++) = 'm'; *n = '\0'; if (verbose) - BIO_printf(bio_err, "writing %s\n", buf[2]); + BIO_printf(bio_err, "writing %s\n", new_cert); - Cout = BIO_new_file(buf[2], "w"); + Cout = BIO_new_file(new_cert, "w"); if (Cout == NULL) { - perror(buf[2]); + perror(new_cert); goto end; } - write_new_certificate(Cout, x, 0, notext); - write_new_certificate(Sout, x, output_der, notext); + write_new_certificate(Cout, xi, 0, notext); + write_new_certificate(Sout, xi, output_der, notext); + BIO_free_all(Cout); } if (sk_X509_num(cert_sk)) { @@ -1098,13 +1097,13 @@ end_of_options: if (tmptm == NULL) goto end; X509_gmtime_adj(tmptm, 0); - X509_CRL_set_lastUpdate(crl, tmptm); + X509_CRL_set1_lastUpdate(crl, tmptm); if (!X509_time_adj_ex(tmptm, crldays, crlhours * 60 * 60 + crlsec, NULL)) { BIO_puts(bio_err, "error setting CRL nextUpdate\n"); goto end; } - X509_CRL_set_nextUpdate(crl, tmptm); + X509_CRL_set1_nextUpdate(crl, tmptm); ASN1_TIME_free(tmptm); @@ -1195,7 +1194,7 @@ end_of_options: if (revcert == NULL) goto end; if (dorevoke == 2) - rev_type = -1; + rev_type = REV_VALID; j = do_revoke(revcert, db, rev_type, rev_arg); if (j <= 0) goto end; @@ -1213,7 +1212,6 @@ end_of_options: /*****************************************************************/ ret = 0; end: - BIO_free_all(Cout); BIO_free_all(Sout); BIO_free_all(out); BIO_free_all(in); @@ -1233,6 +1231,7 @@ end_of_options: X509_CRL_free(crl); NCONF_free(conf); NCONF_free(extconf); + release_engine(e); return (ret); } @@ -1244,12 +1243,13 @@ static char *lookup_conf(const CONF *conf, const char *section, const char *tag) return entry; } -static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, char *enddate, - long days, int batch, char *ext_sect, CONF *lconf, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, + long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign) { @@ -1269,7 +1269,7 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, goto end; } if (verbose) - X509_REQ_print(bio_err, req); + X509_REQ_print_ex(bio_err, req, nameopt, X509_FLAG_COMPAT); BIO_printf(bio_err, "Check that the request matches the signature\n"); @@ -1311,12 +1311,12 @@ static int certify(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, return (ok); } -static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, +static int certify_cert(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, int batch, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, int batch, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy) { @@ -1366,20 +1366,19 @@ static int certify_cert(X509 **xret, char *infile, EVP_PKEY *pkey, X509 *x509, static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, BIGNUM *serial, - char *subj, unsigned long chtype, int multirdn, - int email_dn, char *startdate, char *enddate, long days, - int batch, int verbose, X509_REQ *req, char *ext_sect, + const char *subj, unsigned long chtype, int multirdn, + int email_dn, const char *startdate, const char *enddate, long days, + int batch, int verbose, X509_REQ *req, const char *ext_sect, CONF *lconf, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy, int selfsign) { X509_NAME *name = NULL, *CAname = NULL, *subject = NULL, *dn_subject = NULL; - ASN1_UTCTIME *tm; + const ASN1_TIME *tm; ASN1_STRING *str, *str2; ASN1_OBJECT *obj; X509 *ret = NULL; - X509_NAME_ENTRY *ne; - X509_NAME_ENTRY *tne, *push; + X509_NAME_ENTRY *ne, *tne; EVP_PKEY *pktmp; int ok = -1, i, j, last, nid; const char *p; @@ -1412,41 +1411,37 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, ne = X509_NAME_get_entry(name, i); str = X509_NAME_ENTRY_get_data(ne); obj = X509_NAME_ENTRY_get_object(ne); + nid = OBJ_obj2nid(obj); if (msie_hack) { /* assume all type should be strings */ - nid = OBJ_obj2nid(X509_NAME_ENTRY_get_object(ne)); if (str->type == V_ASN1_UNIVERSALSTRING) ASN1_UNIVERSALSTRING_to_string(str); - if ((str->type == V_ASN1_IA5STRING) && - (nid != NID_pkcs9_emailAddress)) + if (str->type == V_ASN1_IA5STRING && nid != NID_pkcs9_emailAddress) str->type = V_ASN1_T61STRING; - if ((nid == NID_pkcs9_emailAddress) && - (str->type == V_ASN1_PRINTABLESTRING)) + if (nid == NID_pkcs9_emailAddress + && str->type == V_ASN1_PRINTABLESTRING) str->type = V_ASN1_IA5STRING; } /* If no EMAIL is wanted in the subject */ - if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && (!email_dn)) + if (nid == NID_pkcs9_emailAddress && !email_dn) continue; /* check some things */ - if ((OBJ_obj2nid(obj) == NID_pkcs9_emailAddress) && - (str->type != V_ASN1_IA5STRING)) { + if (nid == NID_pkcs9_emailAddress && str->type != V_ASN1_IA5STRING) { BIO_printf(bio_err, "\nemailAddress type needs to be of type IA5STRING\n"); goto end; } - if ((str->type != V_ASN1_BMPSTRING) - && (str->type != V_ASN1_UTF8STRING)) { + if (str->type != V_ASN1_BMPSTRING && str->type != V_ASN1_UTF8STRING) { j = ASN1_PRINTABLE_type(str->data, str->length); - if (((j == V_ASN1_T61STRING) && - (str->type != V_ASN1_T61STRING)) || - ((j == V_ASN1_IA5STRING) && - (str->type == V_ASN1_PRINTABLESTRING))) { + if ((j == V_ASN1_T61STRING && str->type != V_ASN1_T61STRING) || + (j == V_ASN1_IA5STRING && str->type == V_ASN1_PRINTABLESTRING)) + { BIO_printf(bio_err, "\nThe string contains characters that are illegal for the ASN.1 type\n"); goto end; @@ -1484,6 +1479,8 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, last = -1; for (;;) { + X509_NAME_ENTRY *push = NULL; + /* lookup the object in the supplied name list */ j = X509_NAME_get_index_by_OBJ(name, obj, last); if (j < 0) { @@ -1496,7 +1493,6 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, last = j; /* depending on the 'policy', decide what to do. */ - push = NULL; if (strcmp(cv->value, "optional") == 0) { if (tne != NULL) push = tne; @@ -1577,10 +1573,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "The subject name appears to be ok, checking data base for clashes\n"); - /* Build the correct Subject if no e-mail is wanted in the subject */ - /* - * and add it later on because of the method extensions are added - * (altName) + /* + * Build the correct Subject if no e-mail is wanted in the subject. + * And add it later on because of the method extensions are added (altName) */ if (email_dn) @@ -1636,16 +1631,16 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (rrow != NULL) { BIO_printf(bio_err, "The matching entry has the following details\n"); - if (rrow[DB_type][0] == 'E') + if (rrow[DB_type][0] == DB_TYPE_EXP) p = "Expired"; - else if (rrow[DB_type][0] == 'R') + else if (rrow[DB_type][0] == DB_TYPE_REV) p = "Revoked"; - else if (rrow[DB_type][0] == 'V') + else if (rrow[DB_type][0] == DB_TYPE_VAL) p = "Valid"; else p = "\ninvalid type, Data base error\n"; BIO_printf(bio_err, "Type :%s\n", p);; - if (rrow[DB_type][0] == 'R') { + if (rrow[DB_type][0] == DB_TYPE_REV) { p = rrow[DB_exp_date]; if (p == NULL) p = "undef"; @@ -1685,7 +1680,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, goto end; #endif - if (BN_to_ASN1_INTEGER(serial, (ASN1_INTEGER *)X509_get_serialNumber(ret)) == NULL) + if (BN_to_ASN1_INTEGER(serial, X509_get_serialNumber(ret)) == NULL) goto end; if (selfsign) { if (!X509_set_issuer_name(ret, subject)) @@ -1695,17 +1690,12 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, goto end; } - if (strcmp(startdate, "today") == 0) - X509_gmtime_adj(X509_get_notBefore(ret), 0); - else - ASN1_TIME_set_string(X509_get_notBefore(ret), startdate); + if (!set_cert_times(ret, startdate, enddate, days)) + goto end; - if (enddate == NULL) - X509_time_adj_ex(X509_get_notAfter(ret), days, 0, NULL); - else { + if (enddate != NULL) { int tdays; - ASN1_TIME_set_string(X509_get_notAfter(ret), enddate); - ASN1_TIME_diff(&tdays, NULL, NULL, X509_get_notAfter(ret)); + ASN1_TIME_diff(&tdays, NULL, NULL, X509_get0_notAfter(ret)); days = tdays; } @@ -1791,7 +1781,7 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, } BIO_printf(bio_err, "Certificate is to be certified until "); - ASN1_TIME_print(bio_err, X509_get_notAfter(ret)); + ASN1_TIME_print(bio_err, X509_get0_notAfter(ret)); if (days) BIO_printf(bio_err, " (%ld days)", days); BIO_printf(bio_err, "\n"); @@ -1801,13 +1791,13 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "Sign the certificate? [y/n]:"); (void)BIO_flush(bio_err); buf[0] = '\0'; - if (!fgets(buf, sizeof(buf) - 1, stdin)) { + if (fgets(buf, sizeof(buf), stdin) == NULL) { BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED: I/O error\n"); ok = 0; goto end; } - if (!((buf[0] == 'y') || (buf[0] == 'Y'))) { + if (!(buf[0] == 'y' || buf[0] == 'Y')) { BIO_printf(bio_err, "CERTIFICATE WILL NOT BE CERTIFIED\n"); ok = 0; goto end; @@ -1822,9 +1812,9 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, if (!do_X509_sign(ret, pkey, dgst, sigopts)) goto end; - /* We now just add it to the database */ + /* We now just add it to the database as DB_TYPE_VAL('V') */ row[DB_type] = OPENSSL_strdup("V"); - tm = X509_get_notAfter(ret); + tm = X509_get0_notAfter(ret); row[DB_exp_date] = app_malloc(tm->length + 1, "row expdate"); memcpy(row[DB_exp_date], tm->data, tm->length); row[DB_exp_date][tm->length] = '\0'; @@ -1839,10 +1829,8 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, } irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row space"); - for (i = 0; i < DB_NUMBER; i++) { + for (i = 0; i < DB_NUMBER; i++) irow[i] = row[i]; - row[i] = NULL; - } irow[DB_NUMBER] = NULL; if (!TXT_DB_insert(db->db, irow)) { @@ -1850,10 +1838,14 @@ static int do_body(X509 **xret, EVP_PKEY *pkey, X509 *x509, BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); goto end; } + irow = NULL; ok = 1; end: - for (i = 0; i < DB_NUMBER; i++) - OPENSSL_free(row[i]); + if (irow != NULL) { + for (i = 0; i < DB_NUMBER; i++) + OPENSSL_free(row[i]); + OPENSSL_free(irow); + } X509_NAME_free(CAname); X509_NAME_free(subject); @@ -1879,13 +1871,13 @@ static void write_new_certificate(BIO *bp, X509 *x, int output_der, PEM_write_bio_X509(bp, x); } -static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, +static int certify_spkac(X509 **xret, const char *infile, EVP_PKEY *pkey, X509 *x509, const EVP_MD *dgst, STACK_OF(OPENSSL_STRING) *sigopts, STACK_OF(CONF_VALUE) *policy, CA_DB *db, - BIGNUM *serial, char *subj, unsigned long chtype, - int multirdn, int email_dn, char *startdate, - char *enddate, long days, char *ext_sect, + BIGNUM *serial, const char *subj, unsigned long chtype, + int multirdn, int email_dn, const char *startdate, + const char *enddate, long days, const char *ext_sect, CONF *lconf, int verbose, unsigned long certopt, unsigned long nameopt, int default_op, int ext_copy) { @@ -1917,7 +1909,6 @@ static int certify_spkac(X509 **xret, char *infile, EVP_PKEY *pkey, sk = CONF_get_section(parms, "default"); if (sk_CONF_VALUE_num(sk) == 0) { BIO_printf(bio_err, "no name/value pairs found in %s\n", infile); - CONF_free(parms); goto end; } @@ -2021,9 +2012,10 @@ static int check_time_format(const char *str) return ASN1_TIME_set_string(NULL, str); } -static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) +static int do_revoke(X509 *x509, CA_DB *db, REVINFO_TYPE rev_type, + const char *value) { - ASN1_UTCTIME *tm = NULL; + const ASN1_TIME *tm = NULL; char *row[DB_NUMBER], **rrow, **irow; char *rev_str = NULL; BIGNUM *bn = NULL; @@ -2054,63 +2046,70 @@ static int do_revoke(X509 *x509, CA_DB *db, int type, char *value) "Adding Entry with serial number %s to DB for %s\n", row[DB_serial], row[DB_name]); - /* We now just add it to the database */ + /* We now just add it to the database as DB_TYPE_REV('V') */ row[DB_type] = OPENSSL_strdup("V"); - tm = X509_get_notAfter(x509); + tm = X509_get0_notAfter(x509); row[DB_exp_date] = app_malloc(tm->length + 1, "row exp_data"); memcpy(row[DB_exp_date], tm->data, tm->length); row[DB_exp_date][tm->length] = '\0'; row[DB_rev_date] = NULL; row[DB_file] = OPENSSL_strdup("unknown"); + if (row[DB_type] == NULL || row[DB_file] == NULL) { + BIO_printf(bio_err, "Memory allocation failure\n"); + goto end; + } + irow = app_malloc(sizeof(*irow) * (DB_NUMBER + 1), "row ptr"); - for (i = 0; i < DB_NUMBER; i++) { + for (i = 0; i < DB_NUMBER; i++) irow[i] = row[i]; - row[i] = NULL; - } irow[DB_NUMBER] = NULL; if (!TXT_DB_insert(db->db, irow)) { BIO_printf(bio_err, "failed to update database\n"); BIO_printf(bio_err, "TXT_DB error number %ld\n", db->db->error); + OPENSSL_free(irow); goto end; } + for (i = 0; i < DB_NUMBER; i++) + row[i] = NULL; + /* Revoke Certificate */ - if (type == -1) + if (rev_type == REV_VALID) ok = 1; else - ok = do_revoke(x509, db, type, value); + /* Retry revocation after DB insertion */ + ok = do_revoke(x509, db, rev_type, value); goto end; } else if (index_name_cmp_noconst(row, rrow)) { BIO_printf(bio_err, "ERROR:name does not match %s\n", row[DB_name]); goto end; - } else if (type == -1) { + } else if (rev_type == REV_VALID) { BIO_printf(bio_err, "ERROR:Already present, serial number %s\n", row[DB_serial]); goto end; - } else if (rrow[DB_type][0] == 'R') { + } else if (rrow[DB_type][0] == DB_TYPE_REV) { BIO_printf(bio_err, "ERROR:Already revoked, serial number %s\n", row[DB_serial]); goto end; } else { BIO_printf(bio_err, "Revoking Certificate %s.\n", rrow[DB_serial]); - rev_str = make_revocation_str(type, value); + rev_str = make_revocation_str(rev_type, value); if (!rev_str) { BIO_printf(bio_err, "Error in revocation arguments\n"); goto end; } - rrow[DB_type][0] = 'R'; + rrow[DB_type][0] = DB_TYPE_REV; rrow[DB_type][1] = '\0'; rrow[DB_rev_date] = rev_str; } ok = 1; end: - for (i = 0; i < DB_NUMBER; i++) { + for (i = 0; i < DB_NUMBER; i++) OPENSSL_free(row[i]); - } return (ok); } @@ -2130,7 +2129,7 @@ static int get_certificate_status(const char *serial, CA_DB *db) if (serial_len % 2) { /* * Set the first char to 0 - */ ; + */ row[DB_serial][0] = '0'; /* Copy String from serial to row[DB_serial] */ @@ -2143,8 +2142,7 @@ static int get_certificate_status(const char *serial, CA_DB *db) } /* Make it Upper Case */ - for (i = 0; row[DB_serial][i] != '\0'; i++) - row[DB_serial][i] = toupper((unsigned char)row[DB_serial][i]); + make_uppercase(row[DB_serial]); ok = 1; @@ -2154,19 +2152,19 @@ static int get_certificate_status(const char *serial, CA_DB *db) BIO_printf(bio_err, "Serial %s not present in db.\n", row[DB_serial]); ok = -1; goto end; - } else if (rrow[DB_type][0] == 'V') { + } else if (rrow[DB_type][0] == DB_TYPE_VAL) { BIO_printf(bio_err, "%s=Valid (%c)\n", row[DB_serial], rrow[DB_type][0]); goto end; - } else if (rrow[DB_type][0] == 'R') { + } else if (rrow[DB_type][0] == DB_TYPE_REV) { BIO_printf(bio_err, "%s=Revoked (%c)\n", row[DB_serial], rrow[DB_type][0]); goto end; - } else if (rrow[DB_type][0] == 'E') { + } else if (rrow[DB_type][0] == DB_TYPE_EXP) { BIO_printf(bio_err, "%s=Expired (%c)\n", row[DB_serial], rrow[DB_type][0]); goto end; - } else if (rrow[DB_type][0] == 'S') { + } else if (rrow[DB_type][0] == DB_TYPE_SUSP) { BIO_printf(bio_err, "%s=Suspended (%c)\n", row[DB_serial], rrow[DB_type][0]); goto end; @@ -2208,7 +2206,7 @@ static int do_updatedb(CA_DB *db) for (i = 0; i < sk_OPENSSL_PSTRING_num(db->db->data); i++) { rrow = sk_OPENSSL_PSTRING_value(db->db->data, i); - if (rrow[DB_type][0] == 'V') { + if (rrow[DB_type][0] == DB_TYPE_VAL) { /* ignore entries that are not valid */ if (strncmp(rrow[DB_exp_date], "49", 2) <= 0) db_y2k = 1; @@ -2218,14 +2216,14 @@ static int do_updatedb(CA_DB *db) if (db_y2k == a_y2k) { /* all on the same y2k side */ if (strcmp(rrow[DB_exp_date], a_tm_s) <= 0) { - rrow[DB_type][0] = 'E'; + rrow[DB_type][0] = DB_TYPE_EXP; rrow[DB_type][1] = '\0'; cnt++; BIO_printf(bio_err, "%s=Expired\n", rrow[DB_serial]); } } else if (db_y2k < a_y2k) { - rrow[DB_type][0] = 'E'; + rrow[DB_type][0] = DB_TYPE_EXP; rrow[DB_type][1] = '\0'; cnt++; @@ -2265,15 +2263,17 @@ static const char *crl_reasons[] = { * additional argument */ -char *make_revocation_str(int rev_type, char *rev_arg) +static char *make_revocation_str(REVINFO_TYPE rev_type, const char *rev_arg) { - char *other = NULL, *str; - const char *reason = NULL; + char *str; + const char *reason = NULL, *other = NULL; ASN1_OBJECT *otmp; ASN1_UTCTIME *revtm = NULL; int i; + switch (rev_type) { case REV_NONE: + case REV_VALID: break; case REV_CRL_REASON: @@ -2291,7 +2291,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) case REV_HOLD: /* Argument is an OID */ - otmp = OBJ_txt2obj(rev_arg, 0); ASN1_OBJECT_free(otmp); @@ -2306,7 +2305,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) case REV_KEY_COMPROMISE: case REV_CA_COMPROMISE: - /* Argument is the key compromise time */ if (!ASN1_GENERALIZEDTIME_set_string(NULL, rev_arg)) { BIO_printf(bio_err, @@ -2321,7 +2319,6 @@ char *make_revocation_str(int rev_type, char *rev_arg) reason = "CAkeyTime"; break; - } revtm = X509_gmtime_adj(NULL, 0); @@ -2358,7 +2355,7 @@ char *make_revocation_str(int rev_type, char *rev_arg) * 2 OK and some extensions added (i.e. V2 CRL) */ -int make_revoked(X509_REVOKED *rev, const char *str) +static int make_revoked(X509_REVOKED *rev, const char *str) { char *tmp = NULL; int reason_code = -1; @@ -2412,10 +2409,12 @@ int make_revoked(X509_REVOKED *rev, const char *str) return ret; } -static int old_entry_print(ASN1_OBJECT *obj, ASN1_STRING *str) +static int old_entry_print(const ASN1_OBJECT *obj, const ASN1_STRING *str) { - char buf[25], *pbuf, *p; + char buf[25], *pbuf; + const char *p; int j; + j = i2a_ASN1_OBJECT(bio_err, obj); pbuf = buf; for (j = 22 - j; j > 0; j--) @@ -2435,7 +2434,7 @@ static int old_entry_print(ASN1_OBJECT *obj, ASN1_STRING *str) else BIO_printf(bio_err, "ASN.1 %2d:'", str->type); - p = (char *)str->data; + p = (const char *)str->data; for (j = str->length; j > 0; j--) { if ((*p >= ' ') && (*p <= '~')) BIO_printf(bio_err, "%c", *p);