X-Git-Url: https://git.openssl.org/?a=blobdiff_plain;f=apps%2Fx509.c;h=29dc74ca9e9648c5fcdb7496c2a53330ae96b4cc;hb=15b7175f558bf9eb057ec3266685486f727dd70f;hp=2ddb5499398c2fe1b469a9601b7ec620b8b00885;hpb=51e5df0ed01efa47335940425cc8744ecff1b6ae;p=openssl.git diff --git a/apps/x509.c b/apps/x509.c index 2ddb549939..29dc74ca9e 100644 --- a/apps/x509.c +++ b/apps/x509.c @@ -39,12 +39,12 @@ static int purpose_print(BIO *bio, X509 *cert, X509_PURPOSE *pt); static int print_x509v3_exts(BIO *bio, X509 *x, const char *ext_names); typedef enum OPTION_choice { - OPT_ERR = -1, OPT_EOF = 0, OPT_HELP, + OPT_COMMON, OPT_INFORM, OPT_OUTFORM, OPT_KEYFORM, OPT_REQ, OPT_CAFORM, OPT_CAKEYFORM, OPT_VFYOPT, OPT_SIGOPT, OPT_DAYS, OPT_PASSIN, OPT_EXTFILE, - OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_SIGNKEY, OPT_CA, OPT_CAKEY, + OPT_EXTENSIONS, OPT_IN, OPT_OUT, OPT_KEY, OPT_SIGNKEY, OPT_CA, OPT_CAKEY, OPT_CASERIAL, OPT_SET_SERIAL, OPT_NEW, OPT_FORCE_PUBKEY, OPT_SUBJ, - OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_NAMEOPT, + OPT_ADDTRUST, OPT_ADDREJECT, OPT_SETALIAS, OPT_CERTOPT, OPT_DATEOPT, OPT_NAMEOPT, OPT_EMAIL, OPT_OCSP_URI, OPT_SERIAL, OPT_NEXT_SERIAL, OPT_MODULUS, OPT_PUBKEY, OPT_X509TOREQ, OPT_TEXT, OPT_HASH, OPT_ISSUER_HASH, OPT_SUBJECT, OPT_ISSUER, OPT_FINGERPRINT, OPT_DATES, @@ -61,7 +61,7 @@ const OPTIONS x509_options[] = { {"help", OPT_HELP, '-', "Display this summary"}, {"in", OPT_IN, '<', - "Certificate input (default stdin), or CSR input file with -req"}, + "Certificate input, or CSR input file with -req (default stdin)"}, {"passin", OPT_PASSIN, 's', "Private key and cert file pass-phrase source"}, {"new", OPT_NEW, '-', "Generate a certificate from scratch"}, {"x509toreq", OPT_X509TOREQ, '-', @@ -72,8 +72,10 @@ const OPTIONS x509_options[] = { {"inform", OPT_INFORM, 'f', "CSR input file format (DER or PEM) - default PEM"}, {"vfyopt", OPT_VFYOPT, 's', "CSR verification parameter in n:v form"}, + {"key", OPT_KEY, 's', + "Key for signing, and to include unless using -force_pubkey"}, {"signkey", OPT_SIGNKEY, 's', - "Key used to self-sign certificate or cert request"}, + "Same as -key"}, {"keyform", OPT_KEYFORM, 'E', "Key input format (ENGINE, other values ignored)"}, {"out", OPT_OUT, '>', "Output file - default stdout"}, @@ -85,6 +87,7 @@ const OPTIONS x509_options[] = { OPT_SECTION("Certificate printing"), {"text", OPT_TEXT, '-', "Print the certificate in text form"}, + {"dateopt", OPT_DATEOPT, 's', "Datetime format used for printing. (rfc_822/iso_8601). Default is rfc_822."}, {"certopt", OPT_CERTOPT, 's', "Various certificate text printing options"}, {"fingerprint", OPT_FINGERPRINT, '-', "Print the certificate fingerprint"}, {"alias", OPT_ALIAS, '-', "Print certificate alias"}, @@ -149,7 +152,7 @@ const OPTIONS x509_options[] = { OPT_SECTION("Micro-CA"), {"CA", OPT_CA, '<', - "Use the given CA certificate, conflicts with -signkey"}, + "Use the given CA certificate, conflicts with -key"}, {"CAform", OPT_CAFORM, 'F', "CA cert format (PEM/DER/P12); has no effect"}, {"CAkey", OPT_CAKEY, 's', "The corresponding CA key; default is -CA arg"}, {"CAkeyform", OPT_CAKEYFORM, 'E', @@ -187,9 +190,7 @@ static void warn_copying(ASN1_OBJECT *excluded, const char *names) sn); } -static X509_REQ *x509_to_req(X509 *cert, EVP_PKEY *pkey, const EVP_MD *digest, - STACK_OF(OPENSSL_STRING) *sigopts, - int ext_copy, const char *names) +static X509_REQ *x509_to_req(X509 *cert, int ext_copy, const char *names) { const STACK_OF(X509_EXTENSION) *cert_exts = X509_get0_extensions(cert); int i, n = sk_X509_EXTENSION_num(cert_exts /* may be NULL */); @@ -225,8 +226,6 @@ static X509_REQ *x509_to_req(X509 *cert, EVP_PKEY *pkey, const EVP_MD *digest, goto err; } } - if (!do_X509_REQ_sign(req, pkey, digest, sigopts)) - goto err; sk_X509_EXTENSION_free(exts); return req; @@ -236,6 +235,21 @@ static X509_REQ *x509_to_req(X509 *cert, EVP_PKEY *pkey, const EVP_MD *digest, return NULL; } +static int self_signed(X509_STORE *ctx, X509 *cert) +{ + X509_STORE_CTX *xsc = X509_STORE_CTX_new(); + int ret = 0; + + if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, cert, NULL)) { + BIO_printf(bio_err, "Error initialising X509 store\n"); + } else { + X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); + ret = X509_verify_cert(xsc) > 0; + } + X509_STORE_CTX_free(xsc); + return ret; +} + int x509_main(int argc, char **argv) { ASN1_INTEGER *sno = NULL; @@ -244,9 +258,10 @@ int x509_main(int argc, char **argv) CONF *extconf = NULL; int ext_copy = EXT_COPY_UNSET; X509V3_CTX ext_ctx; - EVP_PKEY *signkey = NULL, *CAkey = NULL, *pubkey = NULL; + EVP_PKEY *privkey = NULL, *CAkey = NULL, *pubkey = NULL; + EVP_PKEY *pkey; int newcert = 0; - char *subj = NULL; + char *subj = NULL, *digest = NULL; X509_NAME *fsubj = NULL; const unsigned long chtype = MBSTRING_ASC; const int multirdn = 1; @@ -255,22 +270,22 @@ int x509_main(int argc, char **argv) X509 *x = NULL, *xca = NULL, *issuer_cert; X509_REQ *req = NULL, *rq = NULL; X509_STORE *ctx = NULL; - const EVP_MD *digest = NULL; char *CAkeyfile = NULL, *CAserial = NULL, *pubkeyfile = NULL, *alias = NULL; char *checkhost = NULL, *checkemail = NULL, *checkip = NULL; char *ext_names = NULL; char *extsect = NULL, *extfile = NULL, *passin = NULL, *passinarg = NULL; - char *infile = NULL, *outfile = NULL, *signkeyfile = NULL, *CAfile = NULL; + char *infile = NULL, *outfile = NULL, *privkeyfile = NULL, *CAfile = NULL; char *prog; int days = UNSET_DAYS; /* not explicitly set */ int x509toreq = 0, modulus = 0, print_pubkey = 0, pprint = 0; - int CAformat = FORMAT_PEM, CAkeyformat = FORMAT_PEM; + int CAformat = FORMAT_UNDEF, CAkeyformat = FORMAT_UNDEF; + unsigned long dateopt = ASN1_DTFLGS_RFC822; int fingerprint = 0, reqfile = 0, checkend = 0; - int informat = FORMAT_PEM, outformat = FORMAT_PEM, keyformat = FORMAT_PEM; + int informat = FORMAT_UNDEF, outformat = FORMAT_PEM, keyformat = FORMAT_UNDEF; int next_serial = 0, subject_hash = 0, issuer_hash = 0, ocspid = 0; int noout = 0, CA_createserial = 0, email = 0; int ocsp_uri = 0, trustout = 0, clrtrust = 0, clrreject = 0, aliasout = 0; - int ret = 1, i, num = 0, badsig = 0, clrext = 0, nocert = 0; + int ret = 1, i, j, num = 0, badsig = 0, clrext = 0, nocert = 0; int text = 0, serial = 0, subject = 0, issuer = 0, startdate = 0, ext = 0; int enddate = 0; time_t checkoffset = 0; @@ -284,9 +299,10 @@ int x509_main(int argc, char **argv) ctx = X509_STORE_new(); if (ctx == NULL) - goto end; + goto err; X509_STORE_set_verify_cb(ctx, callb); + opt_set_unknown_name("digest"); prog = opt_init(argc, argv, x509_options); while ((o = opt_next()) != OPT_EOF) { switch (o) { @@ -294,7 +310,7 @@ int x509_main(int argc, char **argv) case OPT_ERR: opthelp: BIO_printf(bio_err, "%s: Use -help for summary.\n", prog); - goto end; + goto err; case OPT_HELP: opt_help(x509_options); ret = 0; @@ -328,11 +344,19 @@ int x509_main(int argc, char **argv) case OPT_REQ: reqfile = 1; break; + + case OPT_DATEOPT: + if (!set_dateopt(&dateopt, opt_arg())) { + BIO_printf(bio_err, + "Invalid date format: %s\n", opt_arg()); + goto err; + } + break; case OPT_COPY_EXTENSIONS: if (!set_ext_copy(&ext_copy, opt_arg())) { BIO_printf(bio_err, "Invalid extension copy option: %s\n", opt_arg()); - goto end; + goto err; } break; @@ -353,7 +377,7 @@ int x509_main(int argc, char **argv) if (days < -1) { BIO_printf(bio_err, "%s: -days parameter arg must be >= -1\n", prog); - goto end; + goto err; } break; case OPT_PASSIN: @@ -373,8 +397,9 @@ int x509_main(int argc, char **argv) case OPT_EXTENSIONS: extsect = opt_arg(); break; + case OPT_KEY: case OPT_SIGNKEY: - signkeyfile = opt_arg(); + privkeyfile = opt_arg(); break; case OPT_CA: CAfile = opt_arg(); @@ -403,30 +428,25 @@ int x509_main(int argc, char **argv) subj = opt_arg(); break; case OPT_ADDTRUST: + if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) + goto end; if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { - BIO_printf(bio_err, - "%s: Invalid trust object value %s\n", + BIO_printf(bio_err, "%s: Invalid trust object value %s\n", prog, opt_arg()); goto opthelp; } - if (trust == NULL && (trust = sk_ASN1_OBJECT_new_null()) == NULL) - goto end; sk_ASN1_OBJECT_push(trust, objtmp); - objtmp = NULL; trustout = 1; break; case OPT_ADDREJECT: + if (reject == NULL && (reject = sk_ASN1_OBJECT_new_null()) == NULL) + goto end; if ((objtmp = OBJ_txt2obj(opt_arg(), 0)) == NULL) { - BIO_printf(bio_err, - "%s: Invalid reject object value %s\n", + BIO_printf(bio_err, "%s: Invalid reject object value %s\n", prog, opt_arg()); goto opthelp; } - if (reject == NULL - && (reject = sk_ASN1_OBJECT_new_null()) == NULL) - goto end; sk_ASN1_OBJECT_push(reject, objtmp); - objtmp = NULL; trustout = 1; break; case OPT_SETALIAS: @@ -545,11 +565,11 @@ int x509_main(int argc, char **argv) case OPT_CHECKEND: checkend = 1; { - intmax_t temp = 0; - if (!opt_imax(opt_arg(), &temp)) + ossl_intmax_t temp = 0; + if (!opt_intmax(opt_arg(), &temp)) goto opthelp; checkoffset = (time_t)temp; - if ((intmax_t)checkoffset != temp) { + if ((ossl_intmax_t)checkoffset != temp) { BIO_printf(bio_err, "%s: Checkend time out of range %s\n", prog, opt_arg()); goto opthelp; @@ -569,27 +589,30 @@ int x509_main(int argc, char **argv) preserve_dates = 1; break; case OPT_MD: - if (!opt_md(opt_unknown(), &digest)) - goto opthelp; + digest = opt_unknown(); + break; } } - /* No extra arguments. */ - argc = opt_num_rest(); - if (argc != 0) + if (!opt_check_rest_arg(NULL)) + goto opthelp; + + if (!app_RAND_load()) + goto end; + + if (!opt_check_md(digest)) goto opthelp; - app_RAND_load(); if (preserve_dates && days != UNSET_DAYS) { BIO_printf(bio_err, "Cannot use -preserve_dates with -days option\n"); - goto end; + goto err; } if (days == UNSET_DAYS) days = DEFAULT_DAYS; if (!app_passwd(passinarg, NULL, &passin, NULL)) { BIO_printf(bio_err, "Error getting password\n"); - goto end; + goto err; } if (!X509_STORE_set_default_paths_ex(ctx, app_get0_libctx(), @@ -598,16 +621,16 @@ int x509_main(int argc, char **argv) if (newcert && infile != NULL) { BIO_printf(bio_err, "The -in option cannot be used with -new\n"); - goto end; + goto err; } if (newcert && reqfile) { BIO_printf(bio_err, "The -req option cannot be used with -new\n"); - goto end; + goto err; } - if (signkeyfile != NULL) { - signkey = load_key(signkeyfile, keyformat, 0, passin, e, "private key"); - if (signkey == NULL) + if (privkeyfile != NULL) { + privkey = load_key(privkeyfile, keyformat, 0, passin, e, "private key"); + if (privkey == NULL) goto end; } if (pubkeyfile != NULL) { @@ -620,12 +643,12 @@ int x509_main(int argc, char **argv) if (subj == NULL) { BIO_printf(bio_err, "The -new option requires a subject to be set using -subj\n"); - goto end; + goto err; } - if (signkeyfile == NULL && pubkeyfile == NULL) { + if (privkeyfile == NULL && pubkeyfile == NULL) { BIO_printf(bio_err, - "The -new option without -signkey requires using -force_pubkey\n"); - goto end; + "The -new option requires using the -key or -force_pubkey option\n"); + goto err; } } if (subj != NULL @@ -635,9 +658,9 @@ int x509_main(int argc, char **argv) if (CAkeyfile == NULL) CAkeyfile = CAfile; if (CAfile != NULL) { - if (signkeyfile != NULL) { - BIO_printf(bio_err, "Cannot use both -signkey and -CA option\n"); - goto end; + if (privkeyfile != NULL) { + BIO_printf(bio_err, "Cannot use both -key/-signkey and -CA option\n"); + goto err; } } else if (CAkeyfile != NULL) { BIO_printf(bio_err, @@ -665,37 +688,32 @@ int x509_main(int argc, char **argv) if (!X509V3_EXT_add_nconf(extconf, &ctx2, extsect, NULL)) { BIO_printf(bio_err, "Error checking extension section %s\n", extsect); - goto end; + goto err; } } if (reqfile) { - EVP_PKEY *pkey; - + if (infile == NULL) + BIO_printf(bio_err, + "Warning: Reading cert request from stdin since no -in option is given\n"); req = load_csr(infile, informat, "certificate request input"); if (req == NULL) goto end; if ((pkey = X509_REQ_get0_pubkey(req)) == NULL) { - BIO_printf(bio_err, "Error unpacking public key\n"); - goto end; + BIO_printf(bio_err, "Error unpacking public key from CSR\n"); + goto err; } i = do_X509_REQ_verify(req, pkey, vfyopts); - if (i < 0) { - BIO_printf(bio_err, - "Error while verifying certificate request self-signature\n"); - goto end; - } - if (i == 0) { - BIO_printf(bio_err, - "Certificate request self-signature did not match the contents\n"); - goto end; - } else { - BIO_printf(bio_err, "Certificate request self-signature ok\n"); + if (i <= 0) { + BIO_printf(bio_err, i < 0 + ? "Error while verifying certificate request self-signature\n" + : "Certificate request self-signature did not match the contents\n"); + goto err; } + BIO_printf(out, "Certificate request self-signature ok\n"); - print_name(bio_err, "subject=", X509_REQ_get_subject_name(req), - get_nameopt()); + print_name(out, "subject=", X509_REQ_get_subject_name(req)); } else if (!x509toreq && ext_copy != EXT_COPY_UNSET) { BIO_printf(bio_err, "Warning: ignoring -copy_extensions since neither -x509toreq nor -req is given\n"); } @@ -705,10 +723,10 @@ int x509_main(int argc, char **argv) BIO_printf(bio_err, "Warning: ignoring -preserve_dates option with -req or -new\n"); preserve_dates = 0; - if (signkeyfile == NULL && CAkeyfile == NULL) { + if (privkeyfile == NULL && CAkeyfile == NULL) { BIO_printf(bio_err, - "We need a private key to sign with, use -signkey or -CAkey or -CA with private key\n"); - goto end; + "We need a private key to sign with, use -key or -CAkey or -CA with private key\n"); + goto err; } if ((x = X509_new_ex(app_get0_libctx(), app_get0_propq())) == NULL) goto end; @@ -720,14 +738,17 @@ int x509_main(int argc, char **argv) if (req != NULL && ext_copy != EXT_COPY_UNSET) { if (clrext && ext_copy != EXT_COPY_NONE) { BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n"); - goto end; + goto err; } else if (!copy_extensions(x, req, ext_copy)) { BIO_printf(bio_err, "Error copying extensions from request\n"); - goto end; + goto err; } } } else { - x = load_cert_pass(infile, 1, passin, "certificate"); + if (infile == NULL) + BIO_printf(bio_err, + "Warning: Reading certificate from stdin since no -in option is given\n"); + x = load_cert_pass(infile, informat, 1, passin, "certificate"); if (x == NULL) goto end; } @@ -735,14 +756,14 @@ int x509_main(int argc, char **argv) && !X509_set_subject_name(x, fsubj != NULL ? fsubj : X509_REQ_get_subject_name(req))) goto end; - if ((pubkey != NULL || signkey != NULL || req != NULL) + if ((pubkey != NULL || privkey != NULL || req != NULL) && !X509_set_pubkey(x, pubkey != NULL ? pubkey : - signkey != NULL ? signkey : + privkey != NULL ? privkey : X509_REQ_get0_pubkey(req))) goto end; if (CAfile != NULL) { - xca = load_cert_pass(CAfile, 1, passin, "CA certificate"); + xca = load_cert_pass(CAfile, CAformat, 1, passin, "CA certificate"); if (xca == NULL) goto end; } @@ -753,7 +774,6 @@ int x509_main(int argc, char **argv) if (!noout || text || next_serial) OBJ_create("2.99999.3", "SET.ex3", "SET x509v3 extension 3"); - /* TODO: why is this strange object created (and no error checked)? */ if (alias) X509_alias_set1(x, (unsigned char *)alias, -1); @@ -764,19 +784,13 @@ int x509_main(int argc, char **argv) X509_reject_clear(x); if (trust != NULL) { - for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) { - objtmp = sk_ASN1_OBJECT_value(trust, i); - X509_add1_trust_object(x, objtmp); - } - objtmp = NULL; + for (i = 0; i < sk_ASN1_OBJECT_num(trust); i++) + X509_add1_trust_object(x, sk_ASN1_OBJECT_value(trust, i)); } if (reject != NULL) { - for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) { - objtmp = sk_ASN1_OBJECT_value(reject, i); - X509_add1_reject_object(x, objtmp); - } - objtmp = NULL; + for (i = 0; i < sk_ASN1_OBJECT_num(reject); i++) + X509_add1_reject_object(x, sk_ASN1_OBJECT_value(reject, i)); } if (clrext && ext_names != NULL) @@ -789,10 +803,6 @@ int x509_main(int argc, char **argv) X509_EXTENSION_free(X509_delete_ext(x, i)); } - if ((reqfile || newcert || signkey != NULL || CAfile != NULL) - && !preserve_dates && !set_cert_times(x, NULL, NULL, days)) - goto end; - issuer_cert = x; if (CAfile != NULL) { issuer_cert = xca; @@ -800,37 +810,67 @@ int x509_main(int argc, char **argv) sno = x509_load_serial(CAfile, CAserial, CA_createserial); if (sno == NULL) goto end; + if (!x509toreq && !reqfile && !newcert && !self_signed(ctx, x)) + goto end; + } else { + if (privkey != NULL && !cert_matches_key(x, privkey)) + BIO_printf(bio_err, + "Warning: Signature key and public key of cert do not match\n"); } if (sno != NULL && !X509_set_serialNumber(x, sno)) goto end; - if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert))) - goto end; + if (reqfile || newcert || privkey != NULL || CAfile != NULL) { + if (!preserve_dates && !set_cert_times(x, NULL, NULL, days)) + goto end; + if (!X509_set_issuer_name(x, X509_get_subject_name(issuer_cert))) + goto end; + } - X509V3_set_ctx(&ext_ctx, issuer_cert, x, req, NULL, X509V3_CTX_REPLACE); - if (extconf != NULL) { + X509V3_set_ctx(&ext_ctx, issuer_cert, x, NULL, NULL, X509V3_CTX_REPLACE); + /* prepare fallback for AKID, but only if issuer cert equals subject cert */ + if (CAfile == NULL) { + if (!X509V3_set_issuer_pkey(&ext_ctx, privkey)) + goto end; + } + if (extconf != NULL && !x509toreq) { X509V3_set_nconf(&ext_ctx, extconf); if (!X509V3_EXT_add_nconf(extconf, &ext_ctx, extsect, x)) { BIO_printf(bio_err, "Error adding extensions from section %s\n", extsect); - goto end; + goto err; } } /* At this point the contents of the certificate x have been finished. */ + pkey = X509_get0_pubkey(x); + if ((print_pubkey != 0 || modulus != 0) && pkey == NULL) { + BIO_printf(bio_err, "Error getting public key\n"); + goto err; + } + if (x509toreq) { /* also works in conjunction with -req */ - if (signkey == NULL) { - BIO_printf(bio_err, "Must specify request key using -signkey\n"); - goto end; + if (privkey == NULL) { + BIO_printf(bio_err, "Must specify request signing key using -key\n"); + goto err; } if (clrext && ext_copy != EXT_COPY_NONE) { BIO_printf(bio_err, "Must not use -clrext together with -copy_extensions\n"); + goto err; + } + if ((rq = x509_to_req(x, ext_copy, ext_names)) == NULL) goto end; + if (extconf != NULL) { + X509V3_set_nconf(&ext_ctx, extconf); + if (!X509V3_EXT_REQ_add_nconf(extconf, &ext_ctx, extsect, rq)) { + BIO_printf(bio_err, + "Error adding request extensions from section %s\n", extsect); + goto err; + } } - if ((rq = x509_to_req(x, signkey, digest, sigopts, - ext_copy, ext_names)) == NULL) + if (!do_X509_REQ_sign(rq, privkey, digest, sigopts)) goto end; if (!noout) { if (outformat == FORMAT_ASN1) { @@ -842,36 +882,21 @@ int x509_main(int argc, char **argv) if (!i) { BIO_printf(bio_err, "Unable to write certificate request\n"); - goto end; + goto err; } } noout = 1; - } else if (signkey != NULL) { - if (!do_X509_sign(x, signkey, digest, sigopts, &ext_ctx)) + } else if (privkey != NULL) { + if (!do_X509_sign(x, privkey, digest, sigopts, &ext_ctx)) goto end; } else if (CAfile != NULL) { - if (!reqfile && !newcert) { /* certificate should be self-signed */ - X509_STORE_CTX *xsc = X509_STORE_CTX_new(); - - if (xsc == NULL || !X509_STORE_CTX_init(xsc, ctx, x, NULL)) { - BIO_printf(bio_err, "Error initialising X509 store\n"); - X509_STORE_CTX_free(xsc); - goto end; - } - X509_STORE_CTX_set_cert(xsc, x); - X509_STORE_CTX_set_flags(xsc, X509_V_FLAG_CHECK_SS_SIGNATURE); - i = X509_verify_cert(xsc); - X509_STORE_CTX_free(xsc); - if (i <= 0) - goto end; - } if ((CAkey = load_key(CAkeyfile, CAkeyformat, 0, passin, e, "CA private key")) == NULL) goto end; if (!X509_check_private_key(xca, CAkey)) { BIO_printf(bio_err, "CA certificate and CA private key do not match\n"); - goto end; + goto err; } if (!do_X509_sign(x, CAkey, digest, sigopts, &ext_ctx)) @@ -884,163 +909,138 @@ int x509_main(int argc, char **argv) corrupt_signature(signature); } - if (num) { /* TODO remove this needless guard and extra indentation below */ - /* Process print options in the given order, as indicated by index i */ - for (i = 1; i <= num; i++) { - if (issuer == i) { - print_name(out, "issuer=", X509_get_issuer_name(x), - get_nameopt()); - } else if (subject == i) { - print_name(out, "subject=", - X509_get_subject_name(x), get_nameopt()); - } else if (serial == i) { - BIO_printf(out, "serial="); - i2a_ASN1_INTEGER(out, X509_get0_serialNumber(x)); - BIO_printf(out, "\n"); - } else if (next_serial == i) { - ASN1_INTEGER *ser = X509_get_serialNumber(x); - BIGNUM *bnser = ASN1_INTEGER_to_BN(ser, NULL); - - if (!bnser) - goto end; - if (!BN_add_word(bnser, 1)) - goto end; - ser = BN_to_ASN1_INTEGER(bnser, NULL); - if (!ser) - goto end; + /* Process print options in the given order, as indicated by index i */ + for (i = 1; i <= num; i++) { + if (i == issuer) { + print_name(out, "issuer=", X509_get_issuer_name(x)); + } else if (i == subject) { + print_name(out, "subject=", X509_get_subject_name(x)); + } else if (i == serial) { + BIO_printf(out, "serial="); + i2a_ASN1_INTEGER(out, X509_get0_serialNumber(x)); + BIO_printf(out, "\n"); + } else if (i == next_serial) { + ASN1_INTEGER *ser; + BIGNUM *bnser = ASN1_INTEGER_to_BN(X509_get0_serialNumber(x), NULL); + + if (bnser == NULL) + goto end; + if (!BN_add_word(bnser, 1) + || (ser = BN_to_ASN1_INTEGER(bnser, NULL)) == NULL) { BN_free(bnser); - i2a_ASN1_INTEGER(out, ser); - ASN1_INTEGER_free(ser); - BIO_puts(out, "\n"); - } else if (email == i || ocsp_uri == i) { - STACK_OF(OPENSSL_STRING) *emlst; - int j; - - if (email == i) - emlst = X509_get1_email(x); - else - emlst = X509_get1_ocsp(x); - for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) - BIO_printf(out, "%s\n", - sk_OPENSSL_STRING_value(emlst, j)); - X509_email_free(emlst); - } else if (aliasout == i) { - unsigned char *alstr; - - alstr = X509_alias_get0(x, NULL); - if (alstr) - BIO_printf(out, "%s\n", alstr); - else - BIO_puts(out, "\n"); - } else if (subject_hash == i) { - BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); + goto end; + } + BN_free(bnser); + i2a_ASN1_INTEGER(out, ser); + ASN1_INTEGER_free(ser); + BIO_puts(out, "\n"); + } else if (i == email || i == ocsp_uri) { + STACK_OF(OPENSSL_STRING) *emlst = + i == email ? X509_get1_email(x) : X509_get1_ocsp(x); + + for (j = 0; j < sk_OPENSSL_STRING_num(emlst); j++) + BIO_printf(out, "%s\n", sk_OPENSSL_STRING_value(emlst, j)); + X509_email_free(emlst); + } else if (i == aliasout) { + unsigned char *alstr = X509_alias_get0(x, NULL); + + if (alstr) + BIO_printf(out, "%s\n", alstr); + else + BIO_puts(out, "\n"); + } else if (i == subject_hash) { + BIO_printf(out, "%08lx\n", X509_subject_name_hash(x)); #ifndef OPENSSL_NO_MD5 - } else if (subject_hash_old == i) { - BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); + } else if (i == subject_hash_old) { + BIO_printf(out, "%08lx\n", X509_subject_name_hash_old(x)); #endif - } else if (issuer_hash == i) { - BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); + } else if (i == issuer_hash) { + BIO_printf(out, "%08lx\n", X509_issuer_name_hash(x)); #ifndef OPENSSL_NO_MD5 - } else if (issuer_hash_old == i) { - BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); + } else if (i == issuer_hash_old) { + BIO_printf(out, "%08lx\n", X509_issuer_name_hash_old(x)); #endif - } else if (pprint == i) { - X509_PURPOSE *ptmp; - int j; - - BIO_printf(out, "Certificate purposes:\n"); - for (j = 0; j < X509_PURPOSE_get_count(); j++) { - ptmp = X509_PURPOSE_get0(j); - purpose_print(out, x, ptmp); - } - } else if (modulus == i) { - EVP_PKEY *pkey; - - pkey = X509_get0_pubkey(x); - if (pkey == NULL) { - BIO_printf(bio_err, - "Modulus unavailable: cannot get key\n"); - goto end; - } - BIO_printf(out, "Modulus="); - if (EVP_PKEY_is_a(pkey, "RSA")) { - BIGNUM *n; - - /* Every RSA key has an 'n' */ - EVP_PKEY_get_bn_param(pkey, "n", &n); - BN_print(out, n); - BN_free(n); - } else if (EVP_PKEY_is_a(pkey, "DSA")) { - BIGNUM *dsapub; - - /* Every DSA key has an 'pub' */ - EVP_PKEY_get_bn_param(pkey, "pub", &dsapub); - BN_print(out, dsapub); - BN_free(dsapub); - } else { - BIO_printf(out, "No modulus for this public key type"); - } - BIO_printf(out, "\n"); - } else if (print_pubkey == i) { - EVP_PKEY *pkey; - - pkey = X509_get0_pubkey(x); - if (pkey == NULL) { - BIO_printf(bio_err, "Error getting public key\n"); - goto end; - } - PEM_write_bio_PUBKEY(out, pkey); - } else if (text == i) { - X509_print_ex(out, x, get_nameopt(), certflag); - } else if (startdate == i) { - BIO_puts(out, "notBefore="); - ASN1_TIME_print(out, X509_get0_notBefore(x)); - BIO_puts(out, "\n"); - } else if (enddate == i) { - BIO_puts(out, "notAfter="); - ASN1_TIME_print(out, X509_get0_notAfter(x)); - BIO_puts(out, "\n"); - } else if (fingerprint == i) { - int j; - unsigned int n; - unsigned char md[EVP_MAX_MD_SIZE]; - const EVP_MD *fdig = digest; - - if (fdig == NULL) - fdig = EVP_sha1(); - - if (!X509_digest(x, fdig, md, &n)) { - BIO_printf(bio_err, "Out of memory\n"); - goto end; - } - BIO_printf(out, "%s Fingerprint=", - OBJ_nid2sn(EVP_MD_type(fdig))); - for (j = 0; j < (int)n; j++) { - BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) - ? '\n' : ':'); - } - } else if (ocspid == i) { - X509_ocspid_print(out, x); - } else if (ext == i) { - print_x509v3_exts(out, x, ext_names); + } else if (i == pprint) { + BIO_printf(out, "Certificate purposes:\n"); + for (j = 0; j < X509_PURPOSE_get_count(); j++) + purpose_print(out, x, X509_PURPOSE_get0(j)); + } else if (i == modulus) { + BIO_printf(out, "Modulus="); + if (EVP_PKEY_is_a(pkey, "RSA")) { + BIGNUM *n = NULL; + + /* Every RSA key has an 'n' */ + EVP_PKEY_get_bn_param(pkey, "n", &n); + BN_print(out, n); + BN_free(n); + } else if (EVP_PKEY_is_a(pkey, "DSA")) { + BIGNUM *dsapub = NULL; + + /* Every DSA key has a 'pub' */ + EVP_PKEY_get_bn_param(pkey, "pub", &dsapub); + BN_print(out, dsapub); + BN_free(dsapub); + } else { + BIO_printf(out, "No modulus for this public key type"); + } + BIO_printf(out, "\n"); + } else if (i == print_pubkey) { + PEM_write_bio_PUBKEY(out, pkey); + } else if (i == text) { + X509_print_ex(out, x, get_nameopt(), certflag); + } else if (i == startdate) { + BIO_puts(out, "notBefore="); + ASN1_TIME_print_ex(out, X509_get0_notBefore(x), dateopt); + BIO_puts(out, "\n"); + } else if (i == enddate) { + BIO_puts(out, "notAfter="); + ASN1_TIME_print_ex(out, X509_get0_notAfter(x), dateopt); + BIO_puts(out, "\n"); + } else if (i == fingerprint) { + unsigned int n; + unsigned char md[EVP_MAX_MD_SIZE]; + const char *fdigname = digest; + EVP_MD *fdig; + int digres; + + if (fdigname == NULL) + fdigname = "SHA1"; + + if ((fdig = EVP_MD_fetch(app_get0_libctx(), fdigname, + app_get0_propq())) == NULL) { + BIO_printf(bio_err, "Unknown digest\n"); + goto err; + } + digres = X509_digest(x, fdig, md, &n); + EVP_MD_free(fdig); + if (!digres) { + BIO_printf(bio_err, "Out of memory\n"); + goto err; } + + BIO_printf(out, "%s Fingerprint=", fdigname); + for (j = 0; j < (int)n; j++) + BIO_printf(out, "%02X%c", md[j], (j + 1 == (int)n) ? '\n' : ':'); + } else if (i == ocspid) { + X509_ocspid_print(out, x); + } else if (i == ext) { + print_x509v3_exts(out, x, ext_names); } } if (checkend) { time_t tcheck = time(NULL) + checkoffset; - if (X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0) { + ret = X509_cmp_time(X509_get0_notAfter(x), &tcheck) < 0; + if (ret) BIO_printf(out, "Certificate will expire\n"); - ret = 1; - } else { + else BIO_printf(out, "Certificate will not expire\n"); - ret = 0; - } goto end; } - print_cert_checks(out, x, checkhost, checkemail, checkip); + if (!check_cert_attributes(out, x, checkhost, checkemail, checkip, 1)) + goto err; if (noout || nocert) { ret = 0; @@ -1056,17 +1056,20 @@ int x509_main(int argc, char **argv) i = PEM_write_bio_X509(out, x); } else { BIO_printf(bio_err, "Bad output format specified for outfile\n"); - goto end; + goto err; } if (!i) { BIO_printf(bio_err, "Unable to write certificate\n"); - goto end; + goto err; } + ret = 0; + goto end; + + err: + ERR_print_errors(bio_err); end: - if (ret != 0) - ERR_print_errors(bio_err); NCONF_free(extconf); BIO_free_all(out); X509_STORE_free(ctx); @@ -1074,7 +1077,7 @@ int x509_main(int argc, char **argv) X509_REQ_free(req); X509_free(x); X509_free(xca); - EVP_PKEY_free(signkey); + EVP_PKEY_free(privkey); EVP_PKEY_free(CAkey); EVP_PKEY_free(pubkey); sk_OPENSSL_STRING_free(sigopts); @@ -1083,7 +1086,6 @@ int x509_main(int argc, char **argv) ASN1_INTEGER_free(sno); sk_ASN1_OBJECT_pop_free(trust, ASN1_OBJECT_free); sk_ASN1_OBJECT_pop_free(reject, ASN1_OBJECT_free); - ASN1_OBJECT_free(objtmp); release_engine(e); clear_free(passin); return ret; @@ -1148,7 +1150,7 @@ static int callb(int ok, X509_STORE_CTX *ctx) return 0; } else { err_cert = X509_STORE_CTX_get_current_cert(ctx); - print_name(bio_err, NULL, X509_get_subject_name(err_cert), 0); + print_name(bio_err, "subject=", X509_get_subject_name(err_cert)); BIO_printf(bio_err, "Error with certificate - error %d at depth %d\n%s\n", err, X509_STORE_CTX_get_error_depth(ctx),