Merge tag 'release_3_0_4_rc1' into tr-upgrade
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_ttls / ttls.c
index f33733d..8eb5892 100644 (file)
@@ -24,6 +24,7 @@
 RCSID("$Id$")
 
 #include "eap_ttls.h"
+#include "eap_chbind.h"
 
 /*
  *    0                   1                   2                   3
@@ -263,6 +264,9 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, REQUEST *fake, SSL *ssl,
                        pairfree(&first);
                        return NULL;
                }
+               if (vendor == VENDORPEC_UKERNA) {
+                       RDEBUG("Received UKERNA attr %d!", attr);
+               }       
 
                /*
                 *      If it's a type from our dictionary, then
@@ -695,11 +699,30 @@ static rlm_rcode_t CC_HINT(nonnull) process_reply(UNUSED eap_handler_t *handler,
                        pairfree(&vp);
                }
 
+               /* move channel binding responses; we need to send them */
+               pairfilter(tls_session, &vp, &reply->vps, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY);
+               if (pairfind(vp, PW_UKERNA_CHBIND, VENDORPEC_UKERNA, TAG_ANY) != NULL) {
+                       t->authenticated = true;
+                       /*
+                        *      Use the tunneled reply, but not now.
+                        */
+                       if (t->use_tunneled_reply) {
+                               rad_assert(!t->accept_vps);
+                               pairfilter(t, &t->accept_vps, &reply->vps,
+                                         0, 0, TAG_ANY);
+                               rad_assert(!reply->vps);
+                       }
+                       rcode = RLM_MODULE_HANDLED;
+               }
+               
                /*
                 *      Handle the ACK, by tunneling any necessary reply
                 *      VP's back to the client.
                 */
                if (vp) {
+                       RDEBUG("sending tunneled reply attributes");
+                       debug_pair_list(vp);
+                       RDEBUG("end tunneled reply attributes");
                        vp2diameter(request, tls_session, vp);
                        pairfree(&vp);
                }
@@ -761,6 +784,10 @@ static rlm_rcode_t CC_HINT(nonnull) process_reply(UNUSED eap_handler_t *handler,
                 */
                pairfilter(t, &vp, &reply->vps, PW_REPLY_MESSAGE, 0, TAG_ANY);
 
+               /* also move chbind messages, if any */
+               pairfilter(t, &vp, &reply->vps, PW_UKERNA_CHBIND, VENDORPEC_UKERNA,
+                         TAG_ANY);
+
                /*
                 *      Handle the ACK, by tunneling any necessary reply
                 *      VP's back to the client.
@@ -920,6 +947,8 @@ int eapttls_process(eap_handler_t *handler, tls_session_t *tls_session)
        uint8_t const *data;
        size_t data_len;
        REQUEST *request = handler->request;
+       eap_chbind_packet_t *chbind_packet;
+       size_t chbind_len;
 
        /*
         *      Just look at the buffer directly, without doing
@@ -1159,6 +1188,46 @@ int eapttls_process(eap_handler_t *handler, tls_session_t *tls_session)
        }
 
        /*
+        *      Process channel binding here.
+        */
+       chbind_len = eap_chbind_vp2packet(fake->packet->vps, &chbind_packet);
+       if (chbind_len > 0) {
+               int chbind_rcode;
+               CHBIND_REQ *req = chbind_allocate();
+
+               RDEBUG("received chbind request");
+               req->chbind_req_pkt = (uint8_t *)chbind_packet;
+               req->chbind_req_len = chbind_len;
+               if (fake->username) {
+                       req->username = fake->username->vp_octets;
+                       req->username_len = fake->username->length;
+               } else {
+                       req->username = NULL;
+                       req->username_len = 0;
+               }
+               chbind_rcode = chbind_process(request, req);
+
+               /* free the chbind packet; we're done with it */
+               free(chbind_packet);
+
+               /* encapsulate response here */
+               if (req->chbind_resp_len > 0) {
+                       RDEBUG("sending chbind response");
+                       pairadd(&fake->reply->vps,
+                               eap_chbind_packet2vp(fake, (eap_chbind_packet_t *)req->chbind_resp,
+                                                     req->chbind_resp_len));
+               } else {
+                       RDEBUG("no chbind response");
+               }
+
+               /* clean up chbind req */
+               chbind_free(req);
+
+               if (chbind_rcode != PW_CODE_AUTHENTICATION_ACK)
+                       return chbind_rcode;
+       }
+
+       /*
         *      Call authentication recursively, which will
         *      do PAP, CHAP, MS-CHAP, etc.
         */