pwdbio = BIO_push(btmp, pwdbio);
#endif
} else if (strcmp(arg, "stdin") == 0) {
+ unbuffer(stdin);
pwdbio = dup_bio_in(FORMAT_TEXT);
if (pwdbio == NULL) {
BIO_printf(bio_err, "Can't open BIO for stdin\n");
return OPENSSL_strdup(tpass);
}
+char *app_conf_try_string(const CONF *conf, const char *group, const char *name)
+{
+ char *res;
+
+ ERR_set_mark();
+ res = NCONF_get_string(conf, group, name);
+ if (res == NULL)
+ ERR_pop_to_mark();
+ else
+ ERR_clear_last_mark();
+ return res;
+}
+
+
CONF *app_load_config_bio(BIO *in, const char *filename)
{
long errorline = -1;
CONF_VALUE *cnf;
int i;
- if ((p = NCONF_get_string(conf, NULL, "oid_section")) == NULL) {
- ERR_clear_error();
+ if ((p = app_conf_try_string(conf, NULL, "oid_section")) == NULL)
return 1;
- }
if ((sktmp = NCONF_get_section(conf, p)) == NULL) {
BIO_printf(bio_err, "problem loading oid section %s\n", p);
return 0;
BIO_printf(bio_err, "Unable to load %s from %s\n", desc, uri);
}
} else {
- (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
+ (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 0,
NULL, NULL, NULL, &cert, NULL, NULL, NULL);
}
return cert;
BIO_printf(bio_err, "Unable to load %s from %s\n", desc, uri);
}
} else {
- (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
+ (void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc, 0,
NULL, NULL, NULL, NULL, NULL, &crl, NULL);
}
return crl;
}
+/* Could be simplified if OSSL_STORE supported CSRs, see FR #15725 */
X509_REQ *load_csr(const char *file, int format, const char *desc)
{
X509_REQ *req = NULL;
if (format == FORMAT_UNDEF)
format = FORMAT_PEM;
- if (desc == NULL)
- desc = "CSR";
in = bio_open_default(file, 'r', format);
if (in == NULL)
goto end;
end:
if (req == NULL) {
ERR_print_errors(bio_err);
- BIO_printf(bio_err, "Unable to load %s\n", desc);
+ if (desc != NULL)
+ BIO_printf(bio_err, "Unable to load %s\n", desc);
}
BIO_free(in);
return req;
}
+/* Better extend OSSL_STORE to support CSRs, see FR #15725 */
+X509_REQ *load_csr_autofmt(const char *infile, int format,
+ STACK_OF(OPENSSL_STRING) *vfyopts, const char *desc)
+{
+ X509_REQ *csr;
+
+ if (format != FORMAT_UNDEF) {
+ csr = load_csr(infile, format, desc);
+ } else { /* try PEM, then DER */
+ BIO *bio_bak = bio_err;
+
+ bio_err = NULL; /* do not show errors on more than one try */
+ csr = load_csr(infile, FORMAT_PEM, NULL /* desc */);
+ bio_err = bio_bak;
+ if (csr == NULL) {
+ ERR_clear_error();
+ csr = load_csr(infile, FORMAT_ASN1, NULL /* desc */);
+ }
+ if (csr == NULL) {
+ BIO_printf(bio_err, "error: unable to load %s from file '%s'\n",
+ desc, infile);
+ }
+ }
+ if (csr != NULL) {
+ EVP_PKEY *pkey = X509_REQ_get0_pubkey(csr);
+ int ret = do_X509_REQ_verify(csr, pkey, vfyopts);
+
+ if (pkey == NULL || ret < 0)
+ BIO_puts(bio_err, "Warning: error while verifying CSR self-signature\n");
+ else if (ret == 0)
+ BIO_puts(bio_err, "Warning: CSR self-signature does not match the contents\n");
+ return csr;
+ }
+ return csr;
+}
+
void cleanse(char *str)
{
if (str != NULL)
if (desc == NULL)
desc = "private key";
- if (format == FORMAT_ENGINE) {
+ if (format == FORMAT_ENGINE)
uri = allocated_uri = make_engine_uri(e, uri, desc);
- }
- (void)load_key_certs_crls(uri, format, may_stdin, pass, desc,
+ (void)load_key_certs_crls(uri, format, may_stdin, pass, desc, 0,
&pkey, NULL, NULL, NULL, NULL, NULL, NULL);
OPENSSL_free(allocated_uri);
return pkey;
}
+/* first try reading public key, on failure resort to loading private key */
EVP_PKEY *load_pubkey(const char *uri, int format, int maybe_stdin,
const char *pass, ENGINE *e, const char *desc)
{
if (desc == NULL)
desc = "public key";
- if (format == FORMAT_ENGINE) {
+ if (format == FORMAT_ENGINE)
uri = allocated_uri = make_engine_uri(e, uri, desc);
- }
- (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc,
+ (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 1,
NULL, &pkey, NULL, NULL, NULL, NULL, NULL);
-
+ if (pkey == NULL)
+ (void)load_key_certs_crls(uri, format, maybe_stdin, pass, desc, 0,
+ &pkey, NULL, NULL, NULL, NULL, NULL, NULL);
OPENSSL_free(allocated_uri);
return pkey;
}
int suppress_decode_errors)
{
EVP_PKEY *params = NULL;
- BIO *bio_bak = bio_err;
if (desc == NULL)
desc = "key parameters";
- if (suppress_decode_errors)
- bio_err = NULL;
(void)load_key_certs_crls(uri, format, maybe_stdin, NULL, desc,
+ suppress_decode_errors,
NULL, NULL, ¶ms, NULL, NULL, NULL, NULL);
if (params != NULL && keytype != NULL && !EVP_PKEY_is_a(params, keytype)) {
ERR_print_errors(bio_err);
EVP_PKEY_free(params);
params = NULL;
}
- bio_err = bio_bak;
return params;
}
return ret;
}
pass_string = get_passwd(pass, desc);
- ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc,
+ ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass_string, desc, 0,
NULL, NULL, NULL, pcert, pcerts, NULL, NULL);
clear_free(pass_string);
if (desc == NULL)
desc = "certificates";
- ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin, pass, desc,
+ ret = load_key_certs_crls(uri, FORMAT_UNDEF, maybe_stdin, pass, desc, 0,
NULL, NULL, NULL, NULL, certs, NULL, NULL);
if (!ret && was_NULL) {
if (desc == NULL)
desc = "CRLs";
- ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc,
+ ret = load_key_certs_crls(uri, FORMAT_UNDEF, 0, pass, desc, 0,
NULL, NULL, NULL, NULL, NULL, NULL, crls);
if (!ret && was_NULL) {
* of *pcerts and *pcrls (as far as they are not NULL).
*/
int load_key_certs_crls(const char *uri, int format, int maybe_stdin,
- const char *pass, const char *desc, EVP_PKEY **ppkey,
- EVP_PKEY **ppubkey, EVP_PKEY **pparams,
+ const char *pass, const char *desc, int quiet,
+ EVP_PKEY **ppkey, EVP_PKEY **ppubkey,
+ EVP_PKEY **pparams,
X509 **pcert, STACK_OF(X509) **pcerts,
X509_CRL **pcrl, STACK_OF(X509_CRL) **pcrls)
{
const OSSL_PARAM *params = NULL;
if (failed == NULL) {
- BIO_printf(bio_err, "Internal error: nothing to load from %s\n",
- uri != NULL ? uri : "<stdin>");
+ if (!quiet)
+ BIO_printf(bio_err, "Internal error: nothing to load from %s\n",
+ uri != NULL ? uri : "<stdin>");
return 0;
}
ERR_set_mark();
SET_EXPECT1(pcert, OSSL_STORE_INFO_CERT);
if (pcerts != NULL) {
if (*pcerts == NULL && (*pcerts = sk_X509_new_null()) == NULL) {
- BIO_printf(bio_err, "Out of memory loading");
+ if (!quiet)
+ BIO_printf(bio_err, "Out of memory loading");
goto end;
}
SET_EXPECT(OSSL_STORE_INFO_CERT);
SET_EXPECT1(pcrl, OSSL_STORE_INFO_CRL);
if (pcrls != NULL) {
if (*pcrls == NULL && (*pcrls = sk_X509_CRL_new_null()) == NULL) {
- BIO_printf(bio_err, "Out of memory loading");
+ if (!quiet)
+ BIO_printf(bio_err, "Out of memory loading");
goto end;
}
SET_EXPECT(OSSL_STORE_INFO_CRL);
BIO *bio;
if (!maybe_stdin) {
- BIO_printf(bio_err, "No filename or uri specified for loading");
+ if (!quiet)
+ BIO_printf(bio_err, "No filename or uri specified for loading");
goto end;
}
uri = "<stdin>";
params, NULL, NULL);
}
if (ctx == NULL) {
- BIO_printf(bio_err, "Could not open file or uri for loading");
+ if (!quiet)
+ BIO_printf(bio_err, "Could not open file or uri for loading");
goto end;
}
if (expect > 0 && !OSSL_STORE_expect(ctx, expect))
* so if the caller asked for a public key, and we got a private
* key, we can still pass it back.
*/
- /* fall thru */
+ /* fall through */
case OSSL_STORE_INFO_PUBKEY:
if (ppubkey != NULL) {
ok = (*ppubkey = OSSL_STORE_INFO_get1_PUBKEY(info)) != NULL;
OSSL_STORE_INFO_free(info);
if (!ok) {
failed = OSSL_STORE_INFO_type_string(type);
- BIO_printf(bio_err, "Error reading");
+ if (!quiet)
+ BIO_printf(bio_err, "Error reading");
break;
}
}
pcrls = NULL;
if (failed == NULL) {
failed = FAIL_NAME;
- if (failed != NULL)
- BIO_printf(bio_err, "Could not read");
+ if (failed != NULL && !quiet)
+ BIO_printf(bio_err, "Could not find");
+ } else if (!quiet) {
+ BIO_printf(bio_err, "Could not read");
}
- if (failed != NULL) {
+ if (failed != NULL && !quiet) {
unsigned long err = ERR_peek_last_error();
if (desc != NULL && strstr(desc, failed) != NULL) {
BIO_printf(bio_err, "\n");
ERR_print_errors(bio_err);
}
- if (bio_err == NULL || failed == NULL)
+ if (quiet || failed == NULL)
/* clear any suppressed or spurious errors */
ERR_pop_to_mark();
else
goto end;
if (CAfile != NULL) {
if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_PEM,
- libctx, propq) <= 0) {
- BIO_printf(bio_err, "Error loading file %s\n", CAfile);
- goto end;
+ libctx, propq) <= 0) {
+ ERR_clear_error();
+ if (X509_LOOKUP_load_file_ex(lookup, CAfile, X509_FILETYPE_ASN1,
+ libctx, propq) <= 0) {
+ BIO_printf(bio_err, "Error loading file %s\n", CAfile);
+ goto end;
+ }
}
} else {
X509_LOOKUP_load_file_ex(lookup, NULL, X509_FILETYPE_DEFAULT,
static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
#undef BSIZE
#define BSIZE 256
-BIGNUM *load_serial(const char *serialfile, int create, ASN1_INTEGER **retai)
+BIGNUM *load_serial(const char *serialfile, int *exists, int create,
+ ASN1_INTEGER **retai)
{
BIO *in = NULL;
BIGNUM *ret = NULL;
goto err;
in = BIO_new_file(serialfile, "r");
+ if (exists != NULL)
+ *exists = in != NULL;
if (in == NULL) {
if (!create) {
perror(serialfile);
}
ERR_clear_error();
ret = BN_new();
- if (ret == NULL || !rand_serial(ret, ai))
+ if (ret == NULL) {
BIO_printf(bio_err, "Out of memory\n");
+ } else if (!rand_serial(ret, ai)) {
+ BIO_printf(bio_err, "Error creating random number to store in %s\n",
+ serialfile);
+ BN_free(ret);
+ ret = NULL;
+ }
} else {
if (!a2i_ASN1_INTEGER(in, ai, buf, 1024)) {
BIO_printf(bio_err, "Unable to load number from %s\n",
}
}
- if (ret && retai) {
+ if (ret != NULL && retai != NULL) {
*retai = ai;
ai = NULL;
}
err:
- ERR_print_errors(bio_err);
+ if (ret == NULL)
+ ERR_print_errors(bio_err);
BIO_free(in);
ASN1_INTEGER_free(ai);
return ret;
else
retdb->attributes.unique_subject = 1;
- if (dbattr_conf) {
- char *p = NCONF_get_string(dbattr_conf, NULL, "unique_subject");
+ if (dbattr_conf != NULL) {
+ char *p = app_conf_try_string(dbattr_conf, NULL, "unique_subject");
- if (p) {
+ if (p != NULL)
retdb->attributes.unique_subject = parse_yesno(p, 1);
- }
}
retdb->dbfname = OPENSSL_strdup(dbfile);
}
/* Ensure RFC 5280 compliance, adapt keyIDs as needed, and sign the cert info */
-int do_X509_sign(X509 *cert, EVP_PKEY *pkey, const char *md,
+int do_X509_sign(X509 *cert, int force_v1, EVP_PKEY *pkey, const char *md,
STACK_OF(OPENSSL_STRING) *sigopts, X509V3_CTX *ext_ctx)
{
- const STACK_OF(X509_EXTENSION) *exts = X509_get0_extensions(cert);
EVP_MD_CTX *mctx = EVP_MD_CTX_new();
int self_sign;
int rv = 0;
- if (sk_X509_EXTENSION_num(exts /* may be NULL */) > 0) {
- /* Prevent X509_V_ERR_EXTENSIONS_REQUIRE_VERSION_3 */
+ if (!force_v1) {
if (!X509_set_version(cert, X509_VERSION_3))
goto end;
if (ERR_GET_LIB(err) != ERR_LIB_SSL)
err = ERR_peek_last_error();
if (ERR_GET_LIB(err) != ERR_LIB_SSL)
- return NULL;
+ return NULL; /* likely no TLS error */
switch (ERR_GET_REASON(err)) {
case SSL_R_WRONG_VERSION_NUMBER:
return "Server did not accept our TLS certificate, likely due to mismatch with server's trust anchor or missing revocation status";
case SSL_AD_REASON_OFFSET + SSL3_AD_HANDSHAKE_FAILURE:
return "TLS handshake failure. Possibly the server requires our TLS certificate but did not receive it";
- default: /* no error or no hint available for error */
- return NULL;
+ default:
+ return NULL; /* no hint available for TLS error */
}
}
+static BIO *http_tls_shutdown(BIO *bio)
+{
+ if (bio != NULL) {
+ BIO *cbio;
+ const char *hint = tls_error_hint();
+
+ if (hint != NULL)
+ BIO_printf(bio_err, "%s\n", hint);
+ (void)ERR_set_mark();
+ BIO_ssl_shutdown(bio);
+ cbio = BIO_pop(bio); /* connect+HTTP BIO */
+ BIO_free(bio); /* SSL BIO */
+ (void)ERR_pop_to_mark(); /* hide SSL_R_READ_BIO_NOT_SET etc. */
+ bio = cbio;
+ }
+ return bio;
+}
+
/* HTTP callback function that supports TLS connection also via HTTPS proxy */
BIO *app_http_tls_cb(BIO *bio, void *arg, int connect, int detail)
{
if (connect) {
SSL *ssl;
BIO *sbio = NULL;
+ X509_STORE *ts = SSL_CTX_get_cert_store(ssl_ctx);
+ X509_VERIFY_PARAM *vpm = X509_STORE_get0_param(ts);
+ const char *host = vpm == NULL ? NULL :
+ X509_VERIFY_PARAM_get0_host(vpm, 0 /* first hostname */);
/* adapt after fixing callback design flaw, see #17088 */
if ((info->use_proxy
|| (sbio = BIO_new(BIO_f_ssl())) == NULL) {
return NULL;
}
- if (ssl_ctx == NULL || (ssl = SSL_new(ssl_ctx)) == NULL) {
+ if ((ssl = SSL_new(ssl_ctx)) == NULL) {
BIO_free(sbio);
return NULL;
}
- /* adapt after fixing callback design flaw, see #17088 */
- SSL_set_tlsext_host_name(ssl, info->server); /* not critical to do */
+ if (vpm != NULL)
+ SSL_set_tlsext_host_name(ssl, host /* may be NULL */);
SSL_set_connect_state(ssl);
BIO_set_ssl(sbio, ssl, BIO_CLOSE);
bio = BIO_push(sbio, bio);
- }
- if (!connect) {
- const char *hint;
- BIO *cbio;
-
- if (!detail) { /* disconnecting after error */
- hint = tls_error_hint();
- if (hint != NULL)
- ERR_add_error_data(2, " : ", hint);
- }
- if (ssl_ctx != NULL) {
- (void)ERR_set_mark();
- BIO_ssl_shutdown(bio);
- cbio = BIO_pop(bio); /* connect+HTTP BIO */
- BIO_free(bio); /* SSL BIO */
- (void)ERR_pop_to_mark(); /* hide SSL_R_READ_BIO_NOT_SET etc. */
- bio = cbio;
- }
+ } else { /* disconnect from TLS */
+ bio = http_tls_shutdown(bio);
}
return bio;
}
BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
void *prefix = NULL;
+ if (b == NULL)
+ return NULL;
+
#ifdef OPENSSL_SYS_VMS
if (FMT_istext(format))
b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
BIO_NOCLOSE | (FMT_istext(format) ? BIO_FP_TEXT : 0));
#ifdef OPENSSL_SYS_VMS
- if (FMT_istext(format))
+ if (b != NULL && FMT_istext(format))
b = BIO_push(BIO_new(BIO_f_linebuffer()), b);
#endif
return b;
{
int provider_options = opt_provider_option_given();
int libctx = app_get0_libctx() != NULL || app_get0_propq() != NULL;
-#ifndef OPENSSL_NO_ENGINE
- ENGINE *e = ENGINE_get_first();
-
- if (e != NULL) {
- ENGINE_free(e);
- return 1;
- }
-#endif
/*
* Having a provider option specified or a custom library context or
* property query, is a sure sign we're not using legacy.