diff --git a/ChangeLog b/ChangeLog index 0024770..ae8fd60 100644 --- a/ChangeLog +++ b/ChangeLog @@ -11,6 +11,7 @@ unreleased chanes Misc: - Move radsecproxy manpage to section 8 - Log CUI and operator-name if present + - Log CN for incomming TLS connections 2020-08-06 1.8.2 Bug fixes: diff --git a/dtls.c b/dtls.c index 7db28f6..620259d 100644 --- a/dtls.c +++ b/dtls.c @@ -304,7 +304,7 @@ void *dtlsservernew(void *arg) { unsigned long error; struct timeval timeout; struct addrinfo tmpsrvaddr; - char tmp[INET6_ADDRSTRLEN]; + char tmp[INET6_ADDRSTRLEN], *subj; debug(DBG_WARN, "dtlsservernew: incoming DTLS connection from %s", addr2string((struct sockaddr *)¶ms->addr, tmp, sizeof(tmp))); @@ -343,6 +343,12 @@ void *dtlsservernew(void *arg) { while (conf) { if (accepted_tls == conf->tlsconf && verifyconfcert(cert, conf)) { + subj = getcertsubject(cert); + if(subj) { + debug(DBG_WARN, "dtlsservernew: DTLS connection from %s, client %s, subject %s up", + addr2string((struct sockaddr *)¶ms->addr, tmp, sizeof(tmp)), conf->name, subj); + free(subj); + } X509_free(cert); client = addclient(conf, 1); if (client) { @@ -524,6 +530,7 @@ int dtlsconnect(struct server *server, int timeout, char *text) { unsigned long error; BIO *bio; struct addrinfo *source = NULL; + char *subj; debug(DBG_DBG, "dtlsconnect: called from %s", text); pthread_mutex_lock(&server->lock); @@ -601,12 +608,16 @@ int dtlsconnect(struct server *server, int timeout, char *text) { if (!cert) continue; if (verifyconfcert(cert, server->conf)) { + subj = getcertsubject(cert); + if(subj) { + debug(DBG_WARN, "dtlsconnect: DTLS connection to %s, subject %s up", server->conf->name, subj); + free(subj); + } X509_free(cert); break; } X509_free(cert); } - debug(DBG_WARN, "dtlsconnect: DTLS connection to %s up", server->conf->name); pthread_mutex_lock(&server->lock); server->state = RSP_SERVER_STATE_CONNECTED; diff --git a/tls.c b/tls.c index 97bf891..f717d98 100644 --- a/tls.c +++ b/tls.c @@ -91,6 +91,7 @@ int tlsconnect(struct server *server, int timeout, char *text) { unsigned long error; int origflags; struct addrinfo *source = NULL; + char *subj; debug(DBG_DBG, "tlsconnect: called from %s", text); pthread_mutex_lock(&server->lock); @@ -157,6 +158,11 @@ int tlsconnect(struct server *server, int timeout, char *text) { if (!cert) continue; if (verifyconfcert(cert, server->conf)) { + subj = getcertsubject(cert); + if(subj) { + debug(DBG_WARN, "tlsconnect: TLS connection to %s, subject %s up", server->conf->name, subj); + free(subj); + } X509_free(cert); break; } @@ -492,7 +498,7 @@ void *tlsservernew(void *arg) { unsigned long error; struct client *client; struct tls *accepted_tls = NULL; - char tmp[INET6_ADDRSTRLEN]; + char tmp[INET6_ADDRSTRLEN], *subj; s = *(int *)arg; free(arg); @@ -538,6 +544,12 @@ void *tlsservernew(void *arg) { while (conf) { if (accepted_tls == conf->tlsconf && verifyconfcert(cert, conf)) { + subj = getcertsubject(cert); + if(subj) { + debug(DBG_WARN, "tlsservernew: TLS connection from %s, client %s, subject %s up", + addr2string((struct sockaddr *)&from,tmp, sizeof(tmp)), conf->name, subj); + free(subj); + } X509_free(cert); client = addclient(conf, 1); if (client) { diff --git a/tlscommon.c b/tlscommon.c index 48c8db4..53d4671 100644 --- a/tlscommon.c +++ b/tlscommon.c @@ -98,6 +98,37 @@ void sslinit() { #endif } +/** + * Print a human readable form of X509_NAME + * + * This is a direct replacement for X509_NAME_oneline() which should no longer be used. + * + * @param name The X509_Name to be printed. + */ +static char *print_x509_name(X509_NAME *name) { + BIO *bio; + char *buf; + + bio = BIO_new(BIO_s_mem()); + if (!bio) { + debug(DBG_ERR, "getcertsubject: BIO_new failed"); + return NULL; + } + + X509_NAME_print_ex(bio, name, 0, XN_FLAG_RFC2253); + + buf = malloc(BIO_number_written(bio)+1); + if (buf) { + BIO_read(bio, buf, BIO_number_written(bio)); + buf[BIO_number_written(bio)] = '\0'; + } else { + debug(DBG_ERR, "getcertsubject: malloc failed"); + } + BIO_free(bio); + + return buf; +} + static int pem_passwd_cb(char *buf, int size, int rwflag, void *userdata) { int pwdlen = strlen(userdata); if (rwflag != 0 || pwdlen > size) /* not for decryption or too large */ @@ -116,43 +147,43 @@ static int verify_cb(int ok, X509_STORE_CTX *ctx) { depth = X509_STORE_CTX_get_error_depth(ctx); if (depth > MAX_CERT_DEPTH) { - ok = 0; - err = X509_V_ERR_CERT_CHAIN_TOO_LONG; - X509_STORE_CTX_set_error(ctx, err); + ok = 0; + err = X509_V_ERR_CERT_CHAIN_TOO_LONG; + X509_STORE_CTX_set_error(ctx, err); } if (!ok) { - if (err_cert) - buf = X509_NAME_oneline(X509_get_subject_name(err_cert), NULL, 0); - debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf ? buf : ""); - free(buf); - buf = NULL; - - switch (err) { - case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: - if (err_cert) { - buf = X509_NAME_oneline(X509_get_issuer_name(err_cert), NULL, 0); - if (buf) { - debug(DBG_WARN, "\tIssuer=%s", buf); - free(buf); - buf = NULL; - } - } - break; - case X509_V_ERR_CERT_NOT_YET_VALID: - case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: - debug(DBG_WARN, "\tCertificate not yet valid"); - break; - case X509_V_ERR_CERT_HAS_EXPIRED: - debug(DBG_WARN, "Certificate has expired"); - break; - case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: - debug(DBG_WARN, "Certificate no longer valid (after notAfter)"); - break; - case X509_V_ERR_NO_EXPLICIT_POLICY: - debug(DBG_WARN, "No Explicit Certificate Policy"); - break; - } + if (err_cert) + buf = print_x509_name(X509_get_subject_name(err_cert)); + debug(DBG_WARN, "verify error: num=%d:%s:depth=%d:%s", err, X509_verify_cert_error_string(err), depth, buf ? buf : ""); + free(buf); + buf = NULL; + + switch (err) { + case X509_V_ERR_UNABLE_TO_GET_ISSUER_CERT: + if (err_cert) { + buf = print_x509_name(X509_get_issuer_name(err_cert)); + if (buf) { + debug(DBG_WARN, "\tIssuer=%s", buf); + free(buf); + buf = NULL; + } + } + break; + case X509_V_ERR_CERT_NOT_YET_VALID: + case X509_V_ERR_ERROR_IN_CERT_NOT_BEFORE_FIELD: + debug(DBG_WARN, "\tCertificate not yet valid"); + break; + case X509_V_ERR_CERT_HAS_EXPIRED: + debug(DBG_WARN, "Certificate has expired"); + break; + case X509_V_ERR_ERROR_IN_CERT_NOT_AFTER_FIELD: + debug(DBG_WARN, "Certificate no longer valid (after notAfter)"); + break; + case X509_V_ERR_NO_EXPLICIT_POLICY: + debug(DBG_WARN, "No Explicit Certificate Policy"); + break; + } } #ifdef DEBUG printf("certificate verify returns %d\n", ok); @@ -742,7 +773,7 @@ int verifyconfcert(X509 *cert, struct clsrvconf *conf) { int ok = 1; struct list_node *entry; - subject = X509_NAME_oneline(X509_get_subject_name(cert), NULL, 0); + subject = getcertsubject(cert); debug(DBG_DBG, "verifyconfcert: verify certificate for host %s, subject %s", conf->name, subject); if (conf->certnamecheck) { debug(DBG_DBG, "verifyconfcert: verify hostname"); @@ -765,6 +796,10 @@ int verifyconfcert(X509 *cert, struct clsrvconf *conf) { return ok; } +char *getcertsubject(X509 *cert) { + return print_x509_name(X509_get_subject_name(cert)); +} + #if OPENSSL_VERSION_NUMBER >= 0x10100000 static int parse_tls_version(const char* version) { if (!strcasecmp("SSL3", version)) { diff --git a/tlscommon.h b/tlscommon.h index c376675..6be9079 100644 --- a/tlscommon.h +++ b/tlscommon.h @@ -41,6 +41,7 @@ struct tls *tlsgettls(char *alt1, char *alt2); SSL_CTX *tlsgetctx(uint8_t type, struct tls *t); X509 *verifytlscert(SSL *ssl); int verifyconfcert(X509 *cert, struct clsrvconf *conf); +char *getcertsubject(X509 *cert); int conftls_cb(struct gconffile **cf, void *arg, char *block, char *opt, char *val); int addmatchcertattr(struct clsrvconf *conf, const char *match); void freematchcertattr(struct clsrvconf *conf);