Hi all,
The patch that allows authorization decision in EAP-TLS module for
freeRadius 1.1.6 is attached. This patch has the same functionality as
previously announced patch for 1.1.0.
The patch works as follows: after successful TLS authentication external
script is invoked and subject name and issuer is passed to that script.
So the script can decide if user is authorized.
Cheers,
Michal P.
--
Michal Prochazka // michalp(a)ics.muni.cz
Supercomputing Center Brno
Institute of Computer Science
Masaryk University
Botanicka 68a, 60200 Brno, CZ
CESNET z.s.p.o.
Zikova 4, 16200 Praha 6, CZ
Index: raddb/Makefile
===================================================================
RCS file: /home/michalp/cvsroot/freeradius-tls/raddb/Makefile,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- raddb/Makefile 28 May 2007 07:17:06 -0000 1.1.1.1
+++ raddb/Makefile 28 May 2007 11:36:56 -0000 1.2
@@ -1,7 +1,7 @@
#
# Makefile
#
-# Version: $Id: Makefile,v 1.1.1.1 2007/05/28 07:17:06 michalp Exp $
+# Version: $Id: Makefile,v 1.2 2007/05/28 11:36:56 michalp Exp $
#
include ../Make.inc
@@ -13,7 +13,7 @@
experimental.conf hints huntgroups ldap.attrmap \
mssql.conf naslist naspasswd oraclesql.conf postgresql.conf \
preproxy_users proxy.conf radiusd.conf realms snmp.conf \
- sql.conf sqlippool.conf users otp.conf
+ sql.conf sqlippool.conf users otp.conf check_tls_script
all:
Index: raddb/check_tls_script
===================================================================
RCS file: raddb/check_tls_script
diff -N raddb/check_tls_script
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ raddb/check_tls_script 28 May 2007 11:36:56 -0000 1.1
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# File containing subjects + issuers which are allowed
+ALLOWED_CERTS_FILE=/etc/raddb/radius_allowed_certs
+LOG_FILE=/var/log/radtls.log
+
+# Get values from env variables
+SUBJECT=$X509_SUBJECT
+ISSUER=$X509_ISSUER
+
+
+# Get the number of occurrence of the ISSUER - SUBJECT in the
+# ALLOWED_CERTS_FILE.
+# This grep expression getting only exact match.
+# !!! Keep in mind that issuer and subject is covered by double quotes !!!
+
+RESULT=`grep -x -c "$ISSUER - $SUBJECT" $ALLOWED_CERTS_FILE`
+
+# If one or more line matched log it else log unauthorize access
+if [ $RESULT -ge 1 ]; then
+ echo -e `date` " $ISSUER - $SUBJECT - successfull" >> $LOG_FILE
+ exit 0
+else
+ echo -e `date` " $ISSUER - $SUBJECT - unatuhorized" >> $LOG_FILE
+ exit 1
+fi
+
Index: raddb/eap.conf
===================================================================
RCS file: /home/michalp/cvsroot/freeradius-tls/raddb/eap.conf,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- raddb/eap.conf 28 May 2007 07:17:06 -0000 1.1.1.1
+++ raddb/eap.conf 28 May 2007 07:23:47 -0000 1.2
@@ -5,7 +5,7 @@
# common side effect of setting 'Auth-Type := EAP' is that the
# users then cannot use ANY other authentication method.
#
-# $Id: eap.conf,v 1.1.1.1 2007/05/28 07:17:06 michalp Exp $
+# $Id: eap.conf,v 1.2 2007/05/28 07:23:47 michalp Exp $
#
eap {
# Invoke the default supported EAP type when
@@ -189,7 +189,16 @@
# the check succeeds.
#
# check_cert_cn = %{User-Name}
- #
+
+ # Check the subject and issuer of the client certificate by
+ # the script. Script is invoked after successful TLS
+ # authentication. X509_SUBJECT and X509_ISSUER environ
+ # variables are passed to the script. Return value of the
+ # script decide if the request is discarded (return 0) or
+ # allowed (return != 0)
+ #
+ # check_script = /usr/local/etc/raddb/check_tls_script
+
# Set this option to specify the allowed
# TLS cipher suites. The format is listed
# in "man 1 ciphers".
Index: share/dictionary.freeradius.internal
===================================================================
RCS file: /home/michalp/cvsroot/freeradius-tls/share/dictionary.freeradius.internal,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- share/dictionary.freeradius.internal 28 May 2007 07:17:06 -0000 1.1.1.1
+++ share/dictionary.freeradius.internal 28 May 2007 07:23:47 -0000 1.2
@@ -2,7 +2,7 @@
#
# Non Protocol Attributes used by FreeRADIUS
#
-# $Id: dictionary.freeradius.internal,v 1.1.1.1 2007/05/28 07:17:06 michalp Exp $
+# $Id: dictionary.freeradius.internal,v 1.2 2007/05/28 07:23:47 michalp Exp $
#
# The attributes number ranges are allocates as follows:
@@ -128,6 +128,8 @@
ATTRIBUTE Server-Identity 1099 string
ATTRIBUTE Cleartext-Password 1100 string
ATTRIBUTE Password-With-Header 1101 string
+ATTRIBUTE X509-Subject 1102 string
+ATTRIBUTE X509-Issuer 1103 string
#
# Range: 1200-1279
Index: src/include/radius.h
===================================================================
RCS file: /home/michalp/cvsroot/freeradius-tls/src/include/radius.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/include/radius.h 28 May 2007 07:17:06 -0000 1.1.1.1
+++ src/include/radius.h 28 May 2007 07:23:47 -0000 1.2
@@ -1,7 +1,7 @@
/*
* radius.h Constants of the radius protocol.
*
- * Version: $Id: radius.h,v 1.1.1.1 2007/05/28 07:17:06 michalp Exp $
+ * Version: $Id: radius.h,v 1.2 2007/05/28 07:23:47 michalp Exp $
*
*/
@@ -201,7 +201,11 @@
#define PW_SMD5_PASSWORD 1096
#define PW_CLEARTEXT_PASSWORD 1100
#define PW_PASSWORD_WITH_HEADER 1101
-
+/*
+* X509 client Subject and Issuer
+*/
+#define PW_X509_SUBJECT 1102
+#define PW_X509_ISSUER 1103
/*
* Integer Translations
Index: src/modules/rlm_eap/types/rlm_eap_tls/Makefile.in
===================================================================
RCS file: /home/michalp/cvsroot/freeradius-tls/src/modules/rlm_eap/types/rlm_eap_tls/Makefile.in,v
retrieving revision 1.1.1.1
diff -u -r1.1.1.1 Makefile.in
--- src/modules/rlm_eap/types/rlm_eap_tls/Makefile.in 28 May 2007 07:17:06 -0000 1.1.1.1
+++ src/modules/rlm_eap/types/rlm_eap_tls/Makefile.in 28 May 2007 11:41:52 -0000
@@ -1,5 +1,5 @@
#
-# $Id: Makefile.in,v 1.1.1.1 2007/05/28 07:17:06 michalp Exp $
+# $Id: Makefile.in,v 1.2 2007/05/28 07:23:47 michalp Exp $
#
TARGET = @targetname@
@@ -7,7 +7,7 @@
HEADERS = rlm_eap_tls.h ../../eap.h ../../rlm_eap.h
RLM_CFLAGS = -I../.. -I../../libeap $(INCLTDL) $(OPENSSL_INCLUDE) @eap_tls_cflags@
RLM_LIBS = @eap_tls_ldflags@ ../../libeap/libeap.la $(OPENSSL_LIBS)
-RLM_INSTALL =
+RLM_INSTALL =
RLM_DIR=../../
include ${RLM_DIR}../rules.mak
Index: src/modules/rlm_eap/types/rlm_eap_tls/check_tls_script.in
===================================================================
RCS file: src/modules/rlm_eap/types/rlm_eap_tls/check_tls_script.in
diff -N src/modules/rlm_eap/types/rlm_eap_tls/check_tls_script.in
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ src/modules/rlm_eap/types/rlm_eap_tls/check_tls_script.in 28 May 2007 08:05:34 -0000 1.1
@@ -0,0 +1,27 @@
+#!/bin/sh
+
+# File containing subjects + issuers which are allowed
+ALLOWED_CERTS_FILE=@sysconfdir@/radius_allowed_certs
+LOG_FILE=@logdir@/radtls.log
+
+# Get values from env variables
+SUBJECT=$X509_SUBJECT
+ISSUER=$X509_ISSUER
+
+
+# Get the number of occurrence of the ISSUER - SUBJECT in the
+# ALLOWED_CERTS_FILE.
+# This grep expression getting only exact match.
+# !!! Keep in mind that issuer and subject is covered by double quotes !!!
+
+RESULT=`grep -x -c "$ISSUER - $SUBJECT" $ALLOWED_CERTS_FILE`
+
+# If one or more line matched log it else log unauthorize access
+if [ $RESULT -ge 1 ]; then
+ echo -e `date` " $ISSUER - $SUBJECT - successfull" >> $LOG_FILE
+ exit 0
+else
+ echo -e `date` " $ISSUER - $SUBJECT - unatuhorized" >> $LOG_FILE
+ exit 1
+fi
+
Index: src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c
===================================================================
RCS file: /home/michalp/cvsroot/freeradius-tls/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c 28 May 2007 07:17:06 -0000 1.1.1.1
+++ src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c 28 May 2007 07:23:47 -0000 1.2
@@ -1,7 +1,7 @@
/*
* rlm_eap_tls.c contains the interfaces that are called from eap
*
- * Version: $Id: rlm_eap_tls.c,v 1.1.1.1 2007/05/28 07:17:06 michalp Exp $
+ * Version: $Id: rlm_eap_tls.c,v 1.2 2007/05/28 07:23:47 michalp Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -68,6 +68,8 @@
offsetof(EAP_TLS_CONF, cipher_list), NULL, NULL},
{ "check_cert_issuer", PW_TYPE_STRING_PTR,
offsetof(EAP_TLS_CONF, check_cert_issuer), NULL, NULL},
+ { "check_script", PW_TYPE_STRING_PTR,
+ offsetof(EAP_TLS_CONF, check_script), NULL, NULL},
{ NULL, -1, 0, NULL, NULL } /* end the list */
};
@@ -698,11 +700,14 @@
/*
* Do authentication, by letting EAP-TLS do most of the work.
*/
-static int eaptls_authenticate(void *arg UNUSED, EAP_HANDLER *handler)
+static int eaptls_authenticate(void *arg, EAP_HANDLER *handler)
{
eaptls_status_t status;
tls_session_t *tls_session = (tls_session_t *) handler->opaque;
-
+ eap_tls_t *inst;
+
+ inst = (eap_tls_t *) arg;
+
DEBUG2(" rlm_eap_tls: Authenticate");
status = eaptls_process(handler);
@@ -713,6 +718,71 @@
* EAP-TLS-Success packet here.
*/
case EAPTLS_SUCCESS:
+ /*
+ * When EAPTLS successed and if check_script is defined
+ * add X509 subject and issuer from client certificate
+ * to the packet and send it to the defined script by
+ * radius_exec_program.
+ */
+
+
+ if (inst->conf->check_script != NULL) {
+ VALUE_PAIR *vp = NULL;
+ char x509_subject[256];
+ char x509_issuer[256];
+ int result;
+
+ if (access(inst->conf->check_script, X_OK) != 0) {
+ DEBUG2(" eaptls_check_script: file %s not \
+ found or it is not executable\n",
+ inst->conf->check_script);
+ return 0;
+ }
+
+ DEBUG2(" eaptls_check_script: processing script %s\n",
+ inst->conf->check_script);
+
+
+ x509_subject[0] = x509_issuer[0] = '\0';
+ X509_NAME_oneline(X509_get_subject_name(tls_session->ssl->session->peer),
+ x509_subject, 256);
+ X509_NAME_oneline(X509_get_issuer_name(tls_session->ssl->session->peer),
+ x509_issuer, 256);
+
+ /*
+ * Create X509_Subject pair
+ */
+ vp = paircreate(PW_X509_SUBJECT, PW_TYPE_OCTETS);
+ memcpy(vp->strvalue, x509_subject, strlen(x509_subject));
+ vp->length = strlen(x509_subject);
+ pairadd(&(handler->request->packet->vps), vp);
+ vp = NULL;
+
+ /*
+ * Create X509_Issuer pair
+ */
+ vp = paircreate(PW_X509_ISSUER, PW_TYPE_OCTETS);
+ memcpy(vp->strvalue, x509_issuer, strlen(x509_issuer));
+ vp->length = strlen(x509_issuer);
+ pairadd(&(handler->request->packet->vps), vp);
+ vp = NULL;
+
+ /*
+ * Run the script and get the result of the script
+ */
+ result = radius_exec_program( inst->conf->check_script, handler->request,
+ 1, NULL, 0, handler->request->packet->vps, NULL);
+ if (result != 0) {
+ radlog(L_ERR, " eaptls_check_script: rlm_exec (%s): \
+ External script failed",
+ inst->conf->check_script);
+ return 0;
+ }
+
+ pairdelete(&(handler->request->packet->vps), PW_X509_SUBJECT);
+ pairdelete(&(handler->request->packet->vps), PW_X509_ISSUER);
+ }
+
break;
/*
@@ -722,7 +792,6 @@
*/
case EAPTLS_HANDLED:
return 1;
-
/*
* Handshake is done, proceed with decoding tunneled
* data.
Index: src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h
===================================================================
RCS file: /home/michalp/cvsroot/freeradius-tls/src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h,v
retrieving revision 1.1.1.1
retrieving revision 1.2
diff -u -r1.1.1.1 -r1.2
--- src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h 28 May 2007 07:17:06 -0000 1.1.1.1
+++ src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.h 28 May 2007 07:23:47 -0000 1.2
@@ -1,7 +1,7 @@
/*
* rlm_eap_tls.h
*
- * Version: $Id: rlm_eap_tls.h,v 1.1.1.1 2007/05/28 07:17:06 michalp Exp $
+ * Version: $Id: rlm_eap_tls.h,v 1.2 2007/05/28 07:23:47 michalp Exp $
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@@ -54,6 +54,7 @@
char *check_cert_cn;
char *cipher_list;
char *check_cert_issuer;
+ char *check_script;
} EAP_TLS_CONF;
/* This structure gets stored in arg */