From 693aab21f0ab530f7c0d3e68a1c0a84b759195a7 Mon Sep 17 00:00:00 2001 From: Kaspar Brand Date: Mon, 19 Sep 2011 20:23:27 +0000 Subject: [PATCH] Add ssl_log_xerror() and ssl_log_rxerror(), modeled after ssl_log_cxerror(). Add SSL_X509_NAME_to_string(), which converts an X509 distinguished name to an RFC 2253 formatted string. Adapt ssl_log_*error() to make use of SSL_X509_NAME_to_string(). git-svn-id: https://svn.apache.org/repos/asf/httpd/httpd/trunk@1172797 13f79535-47bb-0310-9956-ffa450edef68 --- modules/ssl/ssl_engine_log.c | 109 +++++++++++++++++++++++++++-------- modules/ssl/ssl_private.h | 19 ++++-- modules/ssl/ssl_util_ssl.c | 32 ++++++++++ modules/ssl/ssl_util_ssl.h | 1 + 4 files changed, 132 insertions(+), 29 deletions(-) diff --git a/modules/ssl/ssl_engine_log.c b/modules/ssl/ssl_engine_log.c index 389f045c75..03cb1c8317 100644 --- a/modules/ssl/ssl_engine_log.c +++ b/modules/ssl/ssl_engine_log.c @@ -108,44 +108,49 @@ void ssl_log_ssl_error(const char *file, int line, int level, server_rec *s) } } -void ssl_log_cxerror(const char *file, int line, int level, - apr_status_t rv, conn_rec *c, X509 *cert, - const char *format, ...) +static void ssl_log_cert_error(const char *file, int line, int level, + apr_status_t rv, const server_rec *s, + const conn_rec *c, const request_rec *r, + apr_pool_t *p, X509 *cert, const char *format, + va_list ap) { - va_list ap; char buf[HUGE_STRING_LEN]; + int msglen, n; + char *name; - if (!APLOG_IS_LEVEL(mySrvFromConn(c),level)) { - /* Bail early since the rest of this function is expensive. */ - return; - } - - va_start(ap, format); apr_vsnprintf(buf, sizeof buf, format, ap); - va_end(ap); + + msglen = strlen(buf); if (cert) { BIO *bio = BIO_new(BIO_s_mem()); if (bio) { - int n, msglen; + /* + * Limit the maximum length of the subject and issuer DN strings + * in the log message. 300 characters should always be sufficient + * for holding both the timestamp, module name, pid etc. stuff + * at the beginning of the line and the trailing information about + * serial, notbefore and notafter. + */ + int maxdnlen = (HUGE_STRING_LEN - msglen - 300) / 2; BIO_puts(bio, " [subject: "); - n = X509_NAME_print_ex(bio, X509_get_subject_name(cert), 0, - XN_FLAG_RFC2253 & ~XN_FLAG_DN_REV); - if (n == 0) { + name = SSL_X509_NAME_to_string(p, X509_get_subject_name(cert), + maxdnlen); + if (!strIsEmpty(name)) { + BIO_puts(bio, name); + } else { BIO_puts(bio, "-empty-"); - } else if (n < 0) { - BIO_puts(bio, "(ERROR)"); } BIO_puts(bio, " / issuer: "); - n = X509_NAME_print_ex(bio, X509_get_issuer_name(cert), 0, - XN_FLAG_RFC2253 & ~XN_FLAG_DN_REV); - if (n == 0) { + name = SSL_X509_NAME_to_string(p, X509_get_issuer_name(cert), + maxdnlen); + if (!strIsEmpty(name)) { + BIO_puts(bio, name); + } else { BIO_puts(bio, "-empty-"); - } else if (n < 0) { - BIO_puts(bio, "(ERROR)"); } BIO_puts(bio, " / serial: "); @@ -160,7 +165,6 @@ void ssl_log_cxerror(const char *file, int line, int level, BIO_puts(bio, "]"); - msglen = strlen(buf); n = BIO_read(bio, buf + msglen, sizeof buf - msglen - 1); if (n > 0) buf[msglen + n] = '\0'; @@ -168,7 +172,62 @@ void ssl_log_cxerror(const char *file, int line, int level, BIO_free(bio); } } + else { + apr_snprintf(buf + msglen, sizeof buf - msglen, + " [certificate: -not available-]"); + } + + if (r) { + ap_log_rerror(file, line, APLOG_MODULE_INDEX, level, rv, r, "%s", buf); + } + else if (c) { + ap_log_cerror(file, line, APLOG_MODULE_INDEX, level, rv, c, "%s", buf); + } + else if (s) { + ap_log_error(file, line, APLOG_MODULE_INDEX, level, rv, s, "%s", buf); + } + +} + +/* + * Wrappers for ap_log_error/ap_log_cerror/ap_log_rerror which log additional + * details of the X509 cert. For ssl_log_xerror, a pool needs to be passed in + * as well (for temporary allocation of the cert's subject/issuer name strings, + * in the other cases we use the connection and request pool, respectively). + */ +void ssl_log_xerror(const char *file, int line, int level, apr_status_t rv, + apr_pool_t *ptemp, server_rec *s, X509 *cert, + const char *fmt, ...) +{ + if (APLOG_IS_LEVEL(s,level)) { + va_list ap; + va_start(ap, fmt); + ssl_log_cert_error(file, line, level, rv, s, NULL, NULL, ptemp, + cert, fmt, ap); + va_end(ap); + } +} + +void ssl_log_cxerror(const char *file, int line, int level, apr_status_t rv, + conn_rec *c, X509 *cert, const char *fmt, ...) +{ + if (APLOG_IS_LEVEL(mySrvFromConn(c),level)) { + va_list ap; + va_start(ap, fmt); + ssl_log_cert_error(file, line, level, rv, NULL, c, NULL, c->pool, + cert, fmt, ap); + va_end(ap); + } +} - ap_log_cerror(file, line, APLOG_MODULE_INDEX, level, rv, c, - "%s%s", buf, cert ? "" : " [certificate: -not available-]"); +void ssl_log_rxerror(const char *file, int line, int level, apr_status_t rv, + request_rec *r, X509 *cert, const char *fmt, ...) +{ + if (APLOG_R_IS_LEVEL(r,level)) { + va_list ap; + va_start(ap, fmt); + ssl_log_cert_error(file, line, level, rv, NULL, NULL, r, r->pool, + cert, fmt, ap); + va_end(ap); + } } diff --git a/modules/ssl/ssl_private.h b/modules/ssl/ssl_private.h index 2a55f6795e..ef85e6be75 100644 --- a/modules/ssl/ssl_private.h +++ b/modules/ssl/ssl_private.h @@ -852,15 +852,26 @@ int ssl_stapling_mutex_reinit(server_rec *, apr_pool_t *); void ssl_die(void); void ssl_log_ssl_error(const char *, int, int, server_rec *); -/* ssl_log_cxerror is a wrapper for ap_log_cerror which takes a - * certificate as an additional argument and appends details of that - * cert to the log message. All other arguments interpreted exactly - * as ap_log_cerror. */ +/* ssl_log_xerror, ssl_log_cxerror and ssl_log_rxerror are wrappers for the + * respective ap_log_*error functions and take a certificate as an + * additional argument (whose details are appended to the log message). + * The other arguments are interpreted exactly as with their ap_log_*error + * counterparts. */ +void ssl_log_xerror(const char *file, int line, int level, + apr_status_t rv, apr_pool_t *p, server_rec *s, + X509 *cert, const char *format, ...) + __attribute__((format(printf,8,9))); + void ssl_log_cxerror(const char *file, int line, int level, apr_status_t rv, conn_rec *c, X509 *cert, const char *format, ...) __attribute__((format(printf,7,8))); +void ssl_log_rxerror(const char *file, int line, int level, + apr_status_t rv, request_rec *r, X509 *cert, + const char *format, ...) + __attribute__((format(printf,7,8))); + #define SSLLOG_MARK __FILE__,__LINE__ /** Variables */ diff --git a/modules/ssl/ssl_util_ssl.c b/modules/ssl/ssl_util_ssl.c index dc59224734..50d117df08 100644 --- a/modules/ssl/ssl_util_ssl.c +++ b/modules/ssl/ssl_util_ssl.c @@ -297,6 +297,38 @@ char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne) return result; } +/* + * convert an X509_NAME to an RFC 2253 formatted string, optionally truncated + * to maxlen characters (specify a maxlen of 0 for no length limit) + */ +char *SSL_X509_NAME_to_string(apr_pool_t *p, X509_NAME *dn, unsigned int maxlen) +{ + char *result = NULL; + BIO *bio; + int len; + + if ((bio = BIO_new(BIO_s_mem())) == NULL) + return NULL; + X509_NAME_print_ex(bio, dn, 0, XN_FLAG_RFC2253); + len = BIO_pending(bio); + if (len > 0) { + result = apr_palloc(p, maxlen ? maxlen+1 : len+1); + if (maxlen && maxlen < len) { + len = BIO_read(bio, result, maxlen); + if (maxlen > 2) { + /* insert trailing ellipsis if there's enough space */ + apr_snprintf(result + maxlen - 3, 4, "..."); + } + } else { + len = BIO_read(bio, result, len); + } + result[len] = NUL; + } + BIO_free(bio); + + return result; +} + /* retrieve subject CommonName of certificate */ BOOL SSL_X509_getCN(apr_pool_t *p, X509 *xs, char **cppCN) { diff --git a/modules/ssl/ssl_util_ssl.h b/modules/ssl/ssl_util_ssl.h index 3da9c462f9..f8611be2ce 100644 --- a/modules/ssl/ssl_util_ssl.h +++ b/modules/ssl/ssl_util_ssl.h @@ -67,6 +67,7 @@ char *SSL_make_ciphersuite(apr_pool_t *, SSL *); BOOL SSL_X509_isSGC(X509 *); BOOL SSL_X509_getBC(X509 *, int *, int *); char *SSL_X509_NAME_ENTRY_to_string(apr_pool_t *p, X509_NAME_ENTRY *xsne); +char *SSL_X509_NAME_to_string(apr_pool_t *, X509_NAME *, unsigned int); BOOL SSL_X509_getCN(apr_pool_t *, X509 *, char **); BOOL SSL_X509_INFO_load_file(apr_pool_t *, STACK_OF(X509_INFO) *, const char *); BOOL SSL_X509_INFO_load_path(apr_pool_t *, STACK_OF(X509_INFO) *, const char *); -- 2.40.0