]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Add virtual-server option for EAP-TLS to allow certificate field checks
authorMatthew Newton <mcn4@leicester.ac.uk>
Wed, 8 Feb 2012 10:51:44 +0000 (11:51 +0100)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 8 Feb 2012 10:58:09 +0000 (11:58 +0100)
Normally attributes such as TLS-Client-Cert-Common-Name can be seen in
Post-Auth only, which is too late to act if the return to the client should
be changed. This code adds a virtual-server option to EAP-TLS to allow
these values to be examined, and the return status updated accordingly.

raddb/mods-available/eap
raddb/sites-available/check-eap-tls [new file with mode: 0644]
src/include/tls.h
src/main/tls.c
src/modules/rlm_eap/types/rlm_eap_tls/rlm_eap_tls.c

index 26a7f43ad8a5a6b7ac237963be9344d87f9794d2..6bb736c18c187aa1f2c91185bdd6f685b2d49351 100644 (file)
                        #
                        ecdh_curve = "prime256v1"
 
+                       #
+                       # As part of checking a client certificate, the EAP-TLS
+                       # sets some attributes such as TLS-Client-Cert-CN. This
+                       # virtual server has access to these attributes, and can
+                       # be used to accept or reject the request.
+                       #
+               #       virtual_server = check-eap-tls
+
                        #
                        #  Session resumption / fast reauthentication
                        #  cache.
diff --git a/raddb/sites-available/check-eap-tls b/raddb/sites-available/check-eap-tls
new file mode 100644 (file)
index 0000000..15dc628
--- /dev/null
@@ -0,0 +1,54 @@
+# This virtual server allows EAP-TLS to reject access requests
+# based on some certificate attributes.
+
+# Value-pairs that are available for checking include:
+#
+#   TLS-Client-Cert-Subject
+#   TLS-Client-Cert-Issuer
+#   TLS-Client-Cert-Common-Name
+#   TLS-Client-Cert-Subject-Alt-Name-Email
+#
+# To see a full list of attributes, run the server in debug mode
+# with this virtual server configured, and look at the attributes
+# passed in to this virtual server.
+
+server check-eap-tls {
+
+
+# Authorize - this is the only section required.
+#
+# To accept the access request, set Auth-Type = Accept, otherwise
+# set it to Reject.
+
+authorize {
+       if ("%{TLS-Client-Cert-Common-Name}" == "client.example.com") {
+               update config {
+                       Auth-Type = Accept
+               }
+       }
+       else {
+               update config {
+                       Auth-Type = Reject
+               }
+               update reply {
+                       Reply-Message = "Your certificate is not valid."
+               }
+       }
+
+#      if ("host/%{TLS-Client-Cert-Common-Name}" == "%{User-Name}") {
+#              update config {
+#                      Auth-Type = Accept
+#              }
+#      }
+#      else {
+#              update config {
+#                      Auth-Type = Reject
+#              }
+#      }
+
+}
+
+
+
+}
+
index ffac65ff2df4bfeeb4379a0ce15bbd093ec47ae5..2d78709a62a08c1f6f59863778823228ca117cc9 100644 (file)
@@ -367,6 +367,8 @@ struct fr_tls_server_conf_t {
        char            *verify_client_cert_cmd;
        int             require_client_cert;
 
+       char            *virtual_server; /* for processing certificates */
+
 #ifdef HAVE_OPENSSL_OCSP_H
        /*
         * OCSP Configuration
index 17332391746bc36e6e1941989c618e4e11133cf3..cf29dd1054921b8b93ffc88a10306df1f2fca262 100644 (file)
@@ -831,6 +831,8 @@ static CONF_PARSER tls_server_config[] = {
          offsetof(fr_tls_server_conf_t, make_cert_command), NULL, NULL},
        { "require_client_cert", PW_TYPE_BOOLEAN,
          offsetof(fr_tls_server_conf_t, require_client_cert), NULL, NULL },
+       { "virtual_server", PW_TYPE_STRING_PTR,
+         offsetof(fr_tls_server_conf_t, virtual_server), NULL, NULL},
 
 #if OPENSSL_VERSION_NUMBER >= 0x0090800fL
 #ifndef OPENSSL_NO_ECDH
index 56ac645242090c5f69b4e0081978dd869163323b..6ec6267a428cc70f78c18ff93f169204ebccb0c5 100644 (file)
@@ -259,6 +259,7 @@ static int eaptls_authenticate(UNUSED void *arg, EAP_HANDLER *handler)
        fr_tls_status_t status;
        tls_session_t *tls_session = (tls_session_t *) handler->opaque;
        REQUEST *request = handler->request;
+       fr_tls_server_conf_t *conf;
 
        RDEBUG2("Authenticate");
 
@@ -268,8 +269,54 @@ static int eaptls_authenticate(UNUSED void *arg, EAP_HANDLER *handler)
                /*
                 *      EAP-TLS handshake was successful, return an
                 *      EAP-TLS-Success packet here.
+                *
+                *      If a virtual server was configured, check that
+                *      it accepts the certificates, too.
                 */
        case FR_TLS_SUCCESS:
+               conf = SSL_get_ex_data(tls_session->ssl, FR_TLS_EX_INDEX_CONF);
+               if (conf && conf->virtual_server) {
+                       VALUE_PAIR *vp;
+                       REQUEST *fake;
+
+                       /* create a fake request */
+                       fake = request_alloc_fake(request);
+                       rad_assert(fake->packet->vps == NULL);
+
+                       fake->packet->vps = paircopy(request->packet->vps);
+
+                       /* set the virtual server to use */
+                       if ((vp = pairfind(request->config_items,
+                                          PW_VIRTUAL_SERVER, 0)) != NULL) {
+                               fake->server = vp->vp_strvalue;
+                       } else {
+                               fake->server = conf->virtual_server;
+                       }
+
+                       RDEBUG("Processing EAP-TLS Certificate check:");
+                       debug_pair_list(fake->packet->vps);
+
+                       RDEBUG("server %s {", fake->server);
+
+                       rad_authenticate(fake);
+
+                       RDEBUG("} # server %s", fake->server);
+
+                       /* copy the reply vps back to our reply */
+                       pairadd(&request->reply->vps, fake->reply->vps);
+                       fake->reply->vps = NULL;
+
+                       /* reject if virtual server didn't return accept */
+                       if (fake->reply->code != PW_AUTHENTICATION_ACK) {
+                               RDEBUG2("Certifictes were rejected by the virtual server");
+                               request_free(&fake);
+                               eaptls_fail(handler, 0);
+                               return 0;
+                       }
+
+                       request_free(&fake);
+                       /* success */
+               }
                break;
 
                /*