From 1a10cbf69b07b049e1e452b63d1fb333650b10ac Mon Sep 17 00:00:00 2001
From: Mike Ross <Michael.Ross2@Boeing.com>
Date: Sun, 15 Aug 2010 15:49:46 -0700
Subject: [PATCH] Added option for certificate logging to EAP TLS authentication

---
 raddb/eap.conf                                     |    9 ++
 .../rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c        |   97 ++++++++++++++++++-
 .../rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h        |    3 +
 3 files changed, 103 insertions(+), 6 deletions(-)

diff --git a/raddb/eap.conf b/raddb/eap.conf
index 75098b1..cf31708 100644
--- a/raddb/eap.conf
+++ b/raddb/eap.conf
@@ -249,6 +249,15 @@
 		       #
 		#	check_cert_cn = %{User-Name}
 		#
+			
+			#
+			# If log_certificates is set, the Issuer,
+			# Serial Number, Expiration Date, and 
+			# Subject of the client certificate are
+			# written to the log file.
+			#
+		#	log_certificates = yes
+
 			# Set this option to specify the allowed
 			# TLS cipher suites.  The format is listed
 			# in "man 1 ciphers".
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
index 11ed96a..466df22 100644
--- a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
+++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
@@ -20,6 +20,7 @@
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  * Copyright 2003  Alan DeKok <aland@freeradius.org>
  * Copyright 2006  The FreeRADIUS server project
+ * Copyright 2010  The Boeing Company
  *
  */
 
@@ -94,6 +95,8 @@ static CONF_PARSER module_config[] = {
 	  offsetof(EAP_TLS_CONF, cipher_list), NULL, NULL},
 	{ "check_cert_issuer", PW_TYPE_STRING_PTR,
 	  offsetof(EAP_TLS_CONF, check_cert_issuer), NULL, NULL},
+	{ "log_certificates", PW_TYPE_BOOLEAN,
+	  offsetof(EAP_TLS_CONF, log_certificates), NULL, "no" },
 	{ "make_cert_command", PW_TYPE_STRING_PTR,
 	  offsetof(EAP_TLS_CONF, make_cert_command), NULL, NULL},
 
@@ -102,6 +105,77 @@ static CONF_PARSER module_config[] = {
  	{ NULL, -1, 0, NULL, NULL }           /* end the list */
 };
 
+/*
+ *
+ *  Write the certificate serial number, expiration
+ *  date, issuer, and subject to the log file
+ */
+static int log_full_cert(int ok, X509 *cert)
+{
+	const int ub_serial = 20;
+	const int ub_time = 15;
+
+	char serialNumber[2*ub_serial+1];
+	char expiration[ub_time+1];
+	char issuer[ub_name+1];
+	char subject[ub_name+1];
+	char *pTemp = NULL;
+	int local_ok = ok;
+	int i = 0;
+	ASN1_INTEGER *pSn = NULL;
+	ASN1_TIME *pTime = NULL;
+
+	/*
+	 *  Get the Serial Number and format for display
+	 */
+	serialNumber[0] = '\0';
+	pSn = X509_get_serialNumber(cert);
+	pTemp = serialNumber;
+	if ( pSn == NULL || pSn->length > ub_serial ) {
+		radlog(L_AUTH, "rlm_eap_tls:  Malformed Certificate Serial Number");
+		local_ok = 0;
+	} else {
+		for (i = 0; i < pSn->length; i++) {
+			sprintf(pTemp, "%02x", (int)pSn->data[i]);
+			pTemp += 2;
+		}
+	}
+
+	/*
+	 * Get the Expiration Date and format for display
+	 */
+	expiration[0] = '\0';
+	pTime = X509_get_notAfter(cert);
+	if ( pTime == NULL  || pTime->length > ub_time ) {
+		radlog(L_AUTH, "rlm_eap_tls:  Malformed Certificate Expiration");
+		local_ok = 0;
+	} else {
+		strncpy(expiration, (char*) pTime->data, pTime->length);
+		expiration[pTime->length] = '\0';
+	}
+
+	/*
+	 *	Get the Issuer
+	 */
+	issuer[0] = '\0';
+	X509_NAME_oneline(X509_get_issuer_name(cert), issuer,
+			  ub_name);
+
+	/*
+	 *	Get the Subject
+	 */
+	subject[0] = '\0';
+	X509_NAME_oneline(X509_get_subject_name(cert), subject,
+			  ub_name);
+
+	/*
+	 *  Log required attributes
+	 */
+	radlog(L_AUTH, "Certificate: Serial=%s; Expiration=%s; Issuer:%s; Subject:%s",
+		serialNumber, expiration, issuer, subject);
+
+	return local_ok;
+}
 
 /*
  *	TODO: Check for the type of key exchange * like conf->dh_key
@@ -256,12 +330,6 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
 	err = X509_STORE_CTX_get_error(ctx);
 	depth = X509_STORE_CTX_get_error_depth(ctx);
 
-	if (!my_ok) {
-		radlog(L_ERR,"--> verify error:num=%d:%s\n",err,
-			X509_verify_cert_error_string(err));
-		return my_ok;
-	}
-
 	/*
 	 * Retrieve the pointer to the SSL of the connection currently treated
 	 * and the application specific data stored into the SSL object.
@@ -271,6 +339,15 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
 	request = handler->request;
 	conf = (EAP_TLS_CONF *)SSL_get_ex_data(ssl, 1);
 
+	if (!my_ok) {
+		radlog(L_ERR,"--> verify error:num=%d:%s\n",err,
+			X509_verify_cert_error_string(err));
+		if (conf->log_certificates) {
+			log_full_cert(my_ok, client_cert);
+		}
+		return my_ok;
+	}
+
 	/*
 	 *	Get the Subject & Issuer
 	 */
@@ -346,6 +423,14 @@ static int cbtls_verify(int ok, X509_STORE_CTX *ctx)
 				}
 			}
 		} /* check_cert_cn */
+
+		/*
+		 *	If the conf telss us to, log the certificate
+		 */
+		if (conf->log_certificates) {
+			my_ok = log_full_cert(my_ok, client_cert);
+		}
+
 	} /* depth == 0 */
 
 	if (debug_flag > 0) {
diff --git a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
index 470dbcd..7846d1e 100644
--- a/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
+++ b/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
@@ -20,6 +20,8 @@
  * Copyright 2001  hereUare Communications, Inc. <raghud@hereuare.com>
  * Copyright 2003  Alan DeKok <aland@freeradius.org>
  * Copyright 2006  The FreeRADIUS server project
+ * Copyright 2010  The Boeing Company
+ *
  */
 #ifndef _RLM_EAP_TLS_H
 #define _RLM_EAP_TLS_H
@@ -59,6 +61,7 @@ typedef struct eap_tls_conf {
 	char		*check_cert_cn;
 	char		*cipher_list;
 	char		*check_cert_issuer;
+	int		log_certificates;
 
         int     	session_cache_enable;
         int     	session_timeout;
-- 
1.7.0.4

