Put SSL errors into Module-Failure-Message
[freeradius.git] / src / modules / rlm_eap / libeap / eap_tls.c
index ec9a3d0..6983713 100644 (file)
@@ -105,6 +105,8 @@ 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;
 
        reply.code = EAPTLS_SUCCESS;
@@ -113,6 +115,80 @@ 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);
+               pairadd(&vps, vp);
+               
+               vp = paircopy2(request->packet->vps, PW_STRIPPED_USER_NAME, 0);
+               pairadd(&vps, vp);
+               
+               if (vps) {
+                       SSL_SESSION_set_ex_data(tls_session->ssl->session,
+                                               eaptls_session_idx, 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,
+                                            eaptls_session_idx);
+               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);
+               }
+       }
+
+       /*
+        *      Call compose AFTER checking for cached data.
+        */
        eaptls_compose(handler->eap_ds, &reply);
 
        /*
@@ -122,8 +198,6 @@ int eaptls_success(EAP_HANDLER *handler, int peap_flag)
                eaptls_gen_mppe_keys(&handler->request->reply->vps,
                                     tls_session->ssl, tls_session->prf_label);
        } else {
-               REQUEST *request = handler->request;
-
                RDEBUG("WARNING: Not adding MPPE keys because there is no PRF label");
        }
 
@@ -261,7 +335,8 @@ static eaptls_status_t eaptls_ack_handler(EAP_HANDLER *handler)
                return EAPTLS_FAIL;
 
        case handshake:
-               if (tls_session->info.handshake_type == finished) {
+               if ((tls_session->info.handshake_type == finished) &&
+                   (tls_session->dirty_out.used == 0)) {
                        RDEBUG2("ACK handshake is finished");
 
                        /* 
@@ -376,7 +451,8 @@ static eaptls_status_t eaptls_verify(EAP_HANDLER *handler)
                RDEBUG2("Received EAP-TLS ACK message");
                return eaptls_ack_handler(handler);
 #else
-               if (prev_eap_ds->request->id == eap_ds->response->id) {
+               if (prev_eap_ds &&
+                   (prev_eap_ds->request->id == eap_ds->response->id)) {
                        /*
                         *      Run the ACK handler directly from here.
                         */
@@ -684,7 +760,7 @@ static eaptls_status_t eaptls_operation(eaptls_status_t status,
         *      If more info
         *      is required then send another request.
         */
-       if (!tls_handshake_recv(tls_session)) {
+       if (!tls_handshake_recv(handler->request, tls_session)) {
                DEBUG2("TLS receive handshake failed during operation");
                eaptls_fail(handler, tls_session->peap_flag);
                return EAPTLS_FAIL;
@@ -979,3 +1055,4 @@ int eaptls_compose(EAP_DS *eap_ds, EAPTLS_PACKET *reply)
 
        return 1;
 }
+