[mod_openssl] safer_X509_NAME_oneline() (fixes #2693)

provide a safer X590_NAME_oneline() with return value semantics similar
to those of snprintf() and use safer_X509_NAME_oneline() to set
SSL_CLIENT_S_DN when client cert is validated.

The manpage for X509_NAME_oneline() says:

    The functions X509_NAME_oneline() and X509_NAME_print() are legacy functions which produce a non standard output form, they don't handle multi character fields and have various quirks and inconsistencies. Their use is strongly discouraged in new applications.

Besides X509_NAME_oneline() function being deprecated, until fairly recently, there was a security issue with the function, too.

https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2016-2176

    The X509_NAME_oneline function in crypto/x509/x509_obj.c in OpenSSL before 1.0.1t and 1.0.2 before 1.0.2h allows remote attackers to obtain sensitive information from process stack memory or cause a denial of service (buffer over-read) via crafted EBCDIC ASN.1 data.

github: closes #63, closes #83

x-ref:
  "support SSL_CLIENT_VERIFY & SSL_CLIENT_S_DN"
  https://redmine.lighttpd.net/issues/2693
  https://github.com/lighttpd/lighttpd1.4/pull/63
  https://github.com/lighttpd/lighttpd1.4/pull/83
personal/stbuehler/mod-csrf
Glenn Strauss 5 years ago
parent e29f7d5738
commit fb87ae8604
  1. 33
      src/mod_openssl.c

@ -170,6 +170,23 @@ FREE_FUNC(mod_openssl_free)
}
static int
safer_X509_NAME_oneline(X509_NAME *name, char *buf, size_t sz)
{
BIO *bio = BIO_new(BIO_s_mem());
if (bio) {
int len = X509_NAME_print_ex(bio, name, 0, XN_FLAG_ONELINE);
BIO_gets(bio, buf, (int)sz); /*(may be truncated if len >= sz)*/
BIO_free(bio);
return len; /*return value has similar semantics to that of snprintf()*/
}
else {
buf[0] = '\0';
return -1;
}
}
static void
ssl_info_callback (const SSL *ssl, int where, int ret)
{
@ -228,7 +245,7 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
err_cert = ctx->current_cert;
#endif
if (NULL == err_cert) return !hctx->conf.ssl_verifyclient_enforce;
X509_NAME_oneline(X509_get_subject_name(err_cert), buf, sizeof(buf));
safer_X509_NAME_oneline(X509_get_subject_name(err_cert),buf,sizeof(buf));
log_error_write(srv, __FILE__, __LINE__, "SDSSSDSS",
"SSL: verify error:num=", err, ":",
X509_verify_cert_error_string(err), ":depth=", depth,
@ -240,7 +257,7 @@ verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
*/
if (!preverify_ok && (err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT_LOCALLY ||
err == X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT)) {
X509_NAME_oneline(X509_get_issuer_name(err_cert), buf, sizeof(buf));
safer_X509_NAME_oneline(X509_get_issuer_name(err_cert),buf,sizeof(buf));
log_error_write(srv, __FILE__, __LINE__, "SS", "SSL: issuer=", buf);
}
@ -1493,8 +1510,18 @@ https_add_ssl_client_entries (server *srv, connection *con, handler_ctx *hctx)
CONST_STR_LEN("SUCCESS"));
}
buffer_copy_string_len(srv->tmp_buf, CONST_STR_LEN("SSL_CLIENT_S_DN_"));
xn = X509_get_subject_name(xs);
{
char buf[256];
int len = safer_X509_NAME_oneline(xn, buf, sizeof(buf));
if (len > 0) {
if (len >= (int)sizeof(buf)) len = (int)sizeof(buf)-1;
array_set_key_value(con->environment,
CONST_STR_LEN("SSL_CLIENT_S_DN"),
buf, (size_t)len);
}
}
buffer_copy_string_len(srv->tmp_buf, CONST_STR_LEN("SSL_CLIENT_S_DN_"));
for (i = 0, nentries = X509_NAME_entry_count(xn); i < nentries; ++i) {
int xobjnid;
const char * xobjsn;

Loading…
Cancel
Save