]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Move more functions to global namespace
authorAlan T. DeKok <aland@freeradius.org>
Wed, 11 May 2011 12:25:16 +0000 (14:25 +0200)
committerAlan T. DeKok <aland@freeradius.org>
Wed, 11 May 2011 12:25:16 +0000 (14:25 +0200)
src/include/tls.h
src/main/tls.c
src/modules/rlm_eap/libeap/eap_tls.c
src/modules/rlm_eap/libeap/eap_tls.h

index 2c69bbcc2ca0eda4e97884902607944f1ec78a32..ef568636cc0ebab45b5ba65d73b081c331e60e3c 100644 (file)
@@ -299,8 +299,16 @@ fr_tls_server_conf_t *tls_server_conf_parse(CONF_SECTION *cs);
 fr_tls_server_conf_t *tls_client_conf_parse(CONF_SECTION *cs);
 void tls_server_conf_free(fr_tls_server_conf_t *conf);
 int            tls_handshake_recv(REQUEST *, tls_session_t *ssn);
-int            tls_handshake_send(REQUEST *,tls_session_t *ssn);
-void           tls_session_information(tls_session_t *tls_session);
+int            tls_handshake_send(REQUEST *, tls_session_t *ssn);
+void           tls_session_information(tls_session_t *ssn);
+
+/*
+ *     Low-level TLS stuff
+ */
+int tls_success(tls_session_t *ssn, REQUEST *request);
+void tls_fail(tls_session_t *ssn);
+fr_tls_status_t tls_ack_handler(tls_session_t *tls_session, REQUEST *request);
+fr_tls_status_t tls_application_data(tls_session_t *ssn, REQUEST *request);
 
 /* Session */
 void           session_free(void *ssn);
@@ -356,6 +364,7 @@ struct fr_tls_server_conf_t {
 
        char            *verify_tmp_dir;
        char            *verify_client_cert_cmd;
+       int             require_client_cert;
 
 #ifdef HAVE_OPENSSL_OCSP_H
        /*
index b34036e13203c6f443ff719f414356aebc8a30e3..ce01f3f5443b7c70ecf2e56051afeaf665bb5b0b 100644 (file)
@@ -736,6 +736,8 @@ static CONF_PARSER tls_server_config[] = {
          offsetof(fr_tls_server_conf_t, check_cert_issuer), NULL, NULL},
        { "make_cert_command", PW_TYPE_STRING_PTR,
          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 },
 
        { "cache", PW_TYPE_SUBSECTION, 0, NULL, (const void *) cache_config },
 
@@ -1076,7 +1078,6 @@ int cbtls_verify(int ok, X509_STORE_CTX *ctx)
        char cn_str[1024];
        char buf[64];
        X509 *client_cert;
-       X509 *issuer_cert;
        SSL *ssl;
        int err, depth, lookup;
        fr_tls_server_conf_t *conf;
@@ -1820,4 +1821,235 @@ fr_tls_server_conf_t *tls_client_conf_parse(CONF_SECTION *cs)
        return conf;
 }
 
+int tls_success(tls_session_t *ssn, REQUEST *request)
+{
+       VALUE_PAIR *vp, *vps = NULL;
+       fr_tls_server_conf_t *conf;
+
+       conf = (fr_tls_server_conf_t *)SSL_get_ex_data(ssn->ssl, FR_TLS_EX_INDEX_CONF);
+       rad_assert(conf != NULL);
+
+       /*
+        *      If there's no session resumption, delete the entry
+        *      from the cache.  This means either it's disabled
+        *      globally for this SSL context, OR we were told to
+        *      disable it for this user.
+        *
+        *      This also means you can't turn it on just for one
+        *      user.
+        */
+       if ((!ssn->allow_session_resumption) ||
+           (((vp = pairfind(request->config_items, 1127, 0)) != NULL) &&
+            (vp->vp_integer == 0))) {
+               SSL_CTX_remove_session(ssn->ctx,
+                                      ssn->ssl->session);
+               ssn->allow_session_resumption = 0;
+
+               /*
+                *      If we're in a resumed session and it's
+                *      not allowed, 
+                */
+               if (SSL_session_reused(ssn->ssl)) {
+                       RDEBUG("FAIL: Forcibly stopping session resumption as it is not allowed.");
+                       return -1;
+               }
+               
+               /*
+                *      Else resumption IS allowed, so we store the
+                *      user data in the cache.
+                */
+       } else if (!SSL_session_reused(ssn->ssl)) {
+               RDEBUG2("Saving response in the cache");
+               
+               vp = paircopy2(request->reply->vps, PW_USER_NAME, 0);
+               if (vp) pairadd(&vps, vp);
+               
+               vp = paircopy2(request->packet->vps, PW_STRIPPED_USER_NAME, 0);
+               if (vp) pairadd(&vps, vp);
+               
+               vp = paircopy2(request->reply->vps, PW_CACHED_SESSION_POLICY, 0);
+               if (vp) pairadd(&vps, vp);
+               
+               if (vps) {
+                       SSL_SESSION_set_ex_data(ssn->ssl->session,
+                                               FR_TLS_EX_INDEX_VPS, vps);
+               } else {
+                       RDEBUG2("WARNING: No information to cache: session caching will be disabled for this session.");
+                       SSL_CTX_remove_session(ssn->ctx,
+                                              ssn->ssl->session);
+               }
+
+               /*
+                *      Else the session WAS allowed.  Copy the cached
+                *      reply.
+                */
+       } else {
+              
+               vp = SSL_SESSION_get_ex_data(ssn->ssl->session,
+                                            FR_TLS_EX_INDEX_VPS);
+               if (!vp) {
+                       RDEBUG("WARNING: No information in cached session!");
+                       return -1;
+
+               } else {
+                       RDEBUG("Adding cached attributes to the reply:");
+                       debug_pair_list(vp);
+                       pairadd(&request->reply->vps, paircopy(vp));
+
+                       /*
+                        *      Mark the request as resumed.
+                        */
+                       vp = pairmake("EAP-Session-Resumed", "1", T_OP_SET);
+                       if (vp) pairadd(&request->packet->vps, vp);
+               }
+       }
+
+       return 0;
+}
+
+
+void tls_fail(tls_session_t *ssn)
+{
+       /*
+        *      Force the session to NOT be cached.
+        */
+       SSL_CTX_remove_session(ssn->ctx, ssn->ssl->session);
+}
+
+fr_tls_status_t tls_application_data(tls_session_t *ssn,
+                                    REQUEST *request)
+                                    
+{
+       int err;
+
+       /*      
+        *      Decrypt the complete record.
+        */
+       err = BIO_write(ssn->into_ssl, ssn->dirty_in.data,
+                       ssn->dirty_in.used);
+       if (err != (int) ssn->dirty_in.used) {
+               record_init(&ssn->dirty_in);
+               RDEBUG("Failed writing %d to SSL BIO: %d",
+                      ssn->dirty_in.used, err);
+               return FR_TLS_FAIL;
+       }
+       
+       /*
+        *      Clear the dirty buffer now that we are done with it
+        *      and init the clean_out buffer to store decrypted data
+        */
+       record_init(&ssn->dirty_in);
+       record_init(&ssn->clean_out);
+       
+       /*
+        *      Read (and decrypt) the tunneled data from the
+        *      SSL session, and put it into the decrypted
+        *      data buffer.
+        */
+       err = SSL_read(ssn->ssl, ssn->clean_out.data,
+                      sizeof(ssn->clean_out.data));
+       
+       if (err < 0) {
+               int code;
+
+               RDEBUG("SSL_read Error");
+               
+               code = SSL_get_error(ssn->ssl, err);
+               switch (code) {
+               case SSL_ERROR_WANT_READ:
+                       return FR_TLS_MORE_FRAGMENTS;
+                       DEBUG("Error in fragmentation logic: SSL_WANT_READ");
+                       break;
+
+               case SSL_ERROR_WANT_WRITE:
+                       DEBUG("Error in fragmentation logic: SSL_WANT_WRITE");
+                       break;
+
+               default:
+                       DEBUG("Error in fragmentation logic: ?");
+
+                       /*
+                        *      FIXME: Call int_ssl_check?
+                        */
+                       break;
+               }
+               return FR_TLS_FAIL;
+       }
+       
+       if (err == 0) {
+               RDEBUG("WARNING: No data inside of the tunnel.");
+       }
+       
+       /*
+        *      Passed all checks, successfully decrypted data
+        */
+       ssn->clean_out.used = err;
+       
+       return FR_TLS_OK;
+}
+
+
+/*
+ * Acknowledge received is for one of the following messages sent earlier
+ * 1. Handshake completed Message, so now send, EAP-Success
+ * 2. Alert Message, now send, EAP-Failure
+ * 3. Fragment Message, now send, next Fragment
+ */
+fr_tls_status_t tls_ack_handler(tls_session_t *ssn, REQUEST *request)
+{
+       RDEBUG2("Received TLS ACK");
+
+       if (ssn == NULL){
+               radlog_request(L_ERR, 0, request, "FAIL: Unexpected ACK received.  Could not obtain session information.");
+               return FR_TLS_INVALID;
+       }
+       if (ssn->info.initialized == 0) {
+               RDEBUG("No SSL info available. Waiting for more SSL data.");
+               return FR_TLS_REQUEST;
+       }
+       if ((ssn->info.content_type == handshake) &&
+           (ssn->info.origin == 0)) {
+               radlog_request(L_ERR, 0, request, "FAIL: ACK without earlier message.");
+               return FR_TLS_INVALID;
+       }
+
+       switch (ssn->info.content_type) {
+       case alert:
+               RDEBUG2("ACK alert");
+               return FR_TLS_FAIL;
+
+       case handshake:
+               if ((ssn->info.handshake_type == finished) &&
+                   (ssn->dirty_out.used == 0)) {
+                       RDEBUG2("ACK handshake is finished");
+
+                       /* 
+                        *      From now on all the content is
+                        *      application data set it here as nobody else
+                        *      sets it.
+                        */
+                       ssn->info.content_type = application_data;
+                       return FR_TLS_SUCCESS;
+               } /* else more data to send */
+
+               RDEBUG2("ACK handshake fragment handler");
+               /* Fragmentation handler, send next fragment */
+               return FR_TLS_REQUEST;
+
+       case application_data:
+               RDEBUG2("ACK handshake fragment handler in application data");
+               return FR_TLS_REQUEST;
+                                               
+               /*
+                *      For the rest of the conditions, switch over
+                *      to the default section below.
+                */
+       default:
+               RDEBUG2("ACK default");
+               radlog_request(L_ERR, 0, request, "Invalid ACK received: %d",
+                      ssn->info.content_type);
+               return FR_TLS_INVALID;
+       }
+}
+
 #endif /* WITH_TLS */
index e322da6930034a3968df83fe4f4d46f55196eeb7..a54a929790e11caf8873410a68caa3b3847c2f66 100644 (file)
@@ -105,7 +105,6 @@ int eaptls_start(EAP_DS *eap_ds, int peap_flag)
 int eaptls_success(EAP_HANDLER *handler, int peap_flag)
 {
        EAPTLS_PACKET   reply;
-       VALUE_PAIR *vp, *vps = NULL;
        REQUEST *request = handler->request;
        tls_session_t *tls_session = handler->opaque;
 
@@ -116,79 +115,7 @@ int eaptls_success(EAP_HANDLER *handler, int peap_flag)
        reply.data = NULL;
        reply.dlen = 0;
 
-       /*
-        *      If there's no session resumption, delete the entry
-        *      from the cache.  This means either it's disabled
-        *      globally for this SSL context, OR we were told to
-        *      disable it for this user.
-        *
-        *      This also means you can't turn it on just for one
-        *      user.
-        */
-       if ((!tls_session->allow_session_resumption) ||
-           (((vp = pairfind(request->config_items, 1127, 0)) != NULL) &&
-            (vp->vp_integer == 0))) {
-               SSL_CTX_remove_session(tls_session->ctx,
-                                      tls_session->ssl->session);
-               tls_session->allow_session_resumption = 0;
-
-               /*
-                *      If we're in a resumed session and it's
-                *      not allowed, 
-                */
-               if (SSL_session_reused(tls_session->ssl)) {
-                       RDEBUG("FAIL: Forcibly stopping session resumption as it is not allowed.");
-                       return eaptls_fail(handler, peap_flag);
-               }
-               
-               /*
-                *      Else resumption IS allowed, so we store the
-                *      user data in the cache.
-                */
-       } else if (!SSL_session_reused(tls_session->ssl)) {
-               RDEBUG2("Saving response in the cache");
-               
-               vp = paircopy2(request->reply->vps, PW_USER_NAME, 0);
-               if (vp) pairadd(&vps, vp);
-               
-               vp = paircopy2(request->packet->vps, PW_STRIPPED_USER_NAME, 0);
-               if (vp) pairadd(&vps, vp);
-               
-               vp = paircopy2(request->reply->vps, PW_CACHED_SESSION_POLICY, 0);
-               if (vp) pairadd(&vps, vp);
-               
-               if (vps) {
-                       SSL_SESSION_set_ex_data(tls_session->ssl->session,
-                                               FR_TLS_EX_INDEX_VPS, vps);
-               } else {
-                       RDEBUG2("WARNING: No information to cache: session caching will be disabled for this session.");
-                       SSL_CTX_remove_session(tls_session->ctx,
-                                              tls_session->ssl->session);
-               }
-
-               /*
-                *      Else the session WAS allowed.  Copy the cached
-                *      reply.
-                */
-       } else {
-              
-               vp = SSL_SESSION_get_ex_data(tls_session->ssl->session,
-                                            FR_TLS_EX_INDEX_VPS);
-               if (!vp) {
-                       RDEBUG("WARNING: No information in cached session!");
-                       return eaptls_fail(handler, peap_flag);
-               } else {
-                       RDEBUG("Adding cached attributes to the reply:");
-                       debug_pair_list(vp);
-                       pairadd(&request->reply->vps, paircopy(vp));
-
-                       /*
-                        *      Mark the request as resumed.
-                        */
-                       vp = pairmake("EAP-Session-Resumed", "1", T_OP_SET);
-                       if (vp) pairadd(&request->packet->vps, vp);
-               }
-       }
+       tls_success(tls_session, request);
 
        /*
         *      Call compose AFTER checking for cached data.
@@ -307,71 +234,6 @@ int eaptls_request(EAP_DS *eap_ds, tls_session_t *ssn)
        return 1;
 }
 
-/*
- * Acknowledge received is for one of the following messages sent earlier
- * 1. Handshake completed Message, so now send, EAP-Success
- * 2. Alert Message, now send, EAP-Failure
- * 3. Fragment Message, now send, next Fragment
- */
-static fr_tls_status_t eaptls_ack_handler(EAP_HANDLER *handler)
-{
-       tls_session_t *tls_session;
-       REQUEST *request = handler->request;
-
-       tls_session = (tls_session_t *)handler->opaque;
-       if (tls_session == NULL){
-               radlog_request(L_ERR, 0, request, "FAIL: Unexpected ACK received.  Could not obtain session information.");
-               return FR_TLS_FAIL;
-       }
-       if (tls_session->info.initialized == 0) {
-               RDEBUG("No SSL info available. Waiting for more SSL data.");
-               return FR_TLS_REQUEST;
-       }
-       if ((tls_session->info.content_type == handshake) &&
-           (tls_session->info.origin == 0)) {
-               radlog_request(L_ERR, 0, request, "FAIL: ACK without earlier message.");
-               return FR_TLS_FAIL;
-       }
-
-       switch (tls_session->info.content_type) {
-       case alert:
-               RDEBUG2("ACK alert");
-               eaptls_fail(handler, tls_session->peap_flag);
-               return FR_TLS_FAIL;
-
-       case handshake:
-               if ((tls_session->info.handshake_type == finished) &&
-                   (tls_session->dirty_out.used == 0)) {
-                       RDEBUG2("ACK handshake is finished");
-
-                       /* 
-                        *      From now on all the content is
-                        *      application data set it here as nobody else
-                        *      sets it.
-                        */
-                       tls_session->info.content_type = application_data;
-                       return FR_TLS_SUCCESS;
-               } /* else more data to send */
-
-               RDEBUG2("ACK handshake fragment handler");
-               /* Fragmentation handler, send next fragment */
-               return FR_TLS_REQUEST;
-
-       case application_data:
-               RDEBUG2("ACK handshake fragment handler in application data");
-               return FR_TLS_REQUEST;
-                                               
-               /*
-                *      For the rest of the conditions, switch over
-                *      to the default section below.
-                */
-       default:
-               RDEBUG2("ACK default");
-               radlog_request(L_ERR, 0, request, "Invalid ACK received: %d",
-                      tls_session->info.content_type);
-               return FR_TLS_FAIL;
-       }
-}
 
 /*
  *     Similarly, when the EAP server receives an EAP-Response with
@@ -449,25 +311,17 @@ static fr_tls_status_t eaptls_verify(EAP_HANDLER *handler)
            ((eap_ds->response->length == EAP_HEADER_LEN + 2) &&
             ((eaptls_packet->flags & 0xc0) == 0x00))) {
 
-#if 0
-               /*
-                *      Un-comment this for TLS inside of TTLS/PEAP
-                */
-               RDEBUG2("Received EAP-TLS ACK message");
-               return eaptls_ack_handler(handler);
-#else
                if (prev_eap_ds &&
                    (prev_eap_ds->request->id == eap_ds->response->id)) {
                        /*
                         *      Run the ACK handler directly from here.
                         */
                        RDEBUG2("Received TLS ACK");
-                       return eaptls_ack_handler(handler);
+                       return tls_ack_handler(handler->opaque, request);
                } else {
                        radlog_request(L_ERR, 0, request, "Received Invalid TLS ACK");
                        return FR_TLS_INVALID;
                }
-#endif
        }
 
        /*
@@ -930,8 +784,6 @@ fr_tls_status_t eaptls_process(EAP_HANDLER *handler)
         *      The TLS data will be in the tls_session structure.
         */
        if (SSL_is_init_finished(tls_session->ssl)) {
-               int err;
-
                /*
                 *      The initialization may be finished, but if
                 *      there more fragments coming, then send ACK,
@@ -951,55 +803,7 @@ fr_tls_status_t eaptls_process(EAP_HANDLER *handler)
                        goto done;
                }
 
-               /*      
-                *      Decrypt the complete record.
-                */
-               BIO_write(tls_session->into_ssl, tls_session->dirty_in.data,
-                         tls_session->dirty_in.used);
-
-               /*
-                *      Clear the dirty buffer now that we are done with it
-                *      and init the clean_out buffer to store decrypted data
-                */
-               (tls_session->record_init)(&tls_session->dirty_in);
-               (tls_session->record_init)(&tls_session->clean_out);
-
-               /*
-                *      Read (and decrypt) the tunneled data from the
-                *      SSL session, and put it into the decrypted
-                *      data buffer.
-                */
-               err = SSL_read(tls_session->ssl, tls_session->clean_out.data,
-                              sizeof(tls_session->clean_out.data));
-
-               if (err < 0) {
-                       RDEBUG("SSL_read Error");
-
-                       switch (SSL_get_error(tls_session->ssl, err)) {
-                       case SSL_ERROR_WANT_READ:
-                       case SSL_ERROR_WANT_WRITE:
-                               RDEBUG("Error in fragmentation logic");
-                               break;
-                       default:
-                               /*
-                                *      FIXME: Call int_ssl_check?
-                                */
-                               break;
-                       }
-                       status = FR_TLS_FAIL;
-                       goto done;
-               }
-
-               if (err == 0) {
-                       RDEBUG("WARNING: No data inside of the tunnel.");
-               }
-       
-               /*
-                *      Passed all checks, successfully decrypted data
-                */
-               tls_session->clean_out.used = err;
-               
-               status = FR_TLS_OK;
+               status = tls_application_data(tls_session, request);
                goto done;
        }
 
index a1c41106b40235337e6e044e9ac31a6bdadc2ba5..6b434f054caeee26f881e8396a60ad110c75a141 100644 (file)
@@ -51,6 +51,7 @@ RCSIDH(eap_tls_h, "$Id$")
 #include <unistd.h>
 #endif
 
+#include <freeradius-devel/radiusd.h>
 #include <freeradius-devel/tls.h>
 
 #include "eap.h"