Fixes from clang / scan-build
[freeradius.git] / src / modules / rlm_eap / types / rlm_eap_ttls / ttls.c
index 232ae60..fc2aca3 100644 (file)
@@ -76,21 +76,18 @@ static int diameter_verify(REQUEST *request,
                 */
                offset = 8;
                if ((length & (1 << 31)) != 0) {
-                       int attribute;
                        uint32_t vendor;
                        DICT_ATTR *da;
 
                        memcpy(&vendor, data, sizeof(vendor));
                        vendor = ntohl(vendor);
 
-                       if (vendor > 65535) {
-                               RDEBUG2("Vendor codes larger than 65535 are not supported");
+                       if (vendor > FR_MAX_VENDOR) {
+                               RDEBUG2("Vendor codes larger than 2^24 are not supported");
                                return 0;
                        }
 
-                       attribute = (vendor << 16) | attr;
-
-                       da = dict_attrbyvalue(attribute);
+                       da = dict_attrbyvalue(attr, vendor);
 
                        /*
                         *      SHOULD check ((length & (1 << 30)) != 0)
@@ -191,6 +188,7 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                               const uint8_t *data, size_t data_len)
 {
        uint32_t        attr;
+       uint32_t        vendor;
        uint32_t        length;
        size_t          offset;
        size_t          size;
@@ -204,6 +202,7 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                memcpy(&attr, data, sizeof(attr));
                data += 4;
                attr = ntohl(attr);
+               vendor = 0;
 
                memcpy(&length, data, sizeof(length));
                data += 4;
@@ -215,25 +214,15 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                 */
                offset = 8;
                if ((length & (1 << 31)) != 0) {
-                       uint32_t vendor;
-
                        memcpy(&vendor, data, sizeof(vendor));
                        vendor = ntohl(vendor);
 
-                       if (attr > 65535) {
-                               RDEBUG2("Cannot handle vendor attributes greater than 65535");
-                               pairfree(&first);
-                               return NULL;
-                       }
-
-                       if (vendor > 32767) {
-                               RDEBUG2("Cannot handle vendor Id greater than 32767");
+                       if (vendor > FR_MAX_VENDOR) {
+                               RDEBUG2("Cannot handle vendor Id greater than 2^&24");
                                pairfree(&first);
                                return NULL;
                        }
 
-                       attr |= (vendor << 16);
-
                        data += 4; /* skip the vendor field, it's zero */
                        offset += 4; /* offset to value field */
                }
@@ -242,7 +231,7 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                 *      Vendor attributes can be larger than 255.
                 *      Normal attributes cannot be.
                 */
-               if ((attr > 255) && (VENDOR(attr) == 0)) {
+               if ((attr > 255) && (vendor == 0)) {
                        RDEBUG2("Cannot handle Diameter attributes");
                        pairfree(&first);
                        return NULL;
@@ -268,7 +257,7 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                /*
                 *      Create it.
                 */
-               vp = paircreate(attr, PW_TYPE_OCTETS);
+               vp = paircreate(attr, vendor, PW_TYPE_OCTETS);
                if (!vp) {
                        RDEBUG2("Failure in creating VP");
                        pairfree(&first);
@@ -340,7 +329,7 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
 
                                        if (size == 0) break;
 
-                                       vp = paircreate(attr, PW_TYPE_OCTETS);
+                                       vp = paircreate(attr, vendor, PW_TYPE_OCTETS);
                                        if (!vp) {
                                                RDEBUG2("Failure in creating VP");
                                                pairfree(&first);
@@ -503,7 +492,7 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
                 *      issues.
                 */
                length = vp->length;
-               vendor = (vp->attribute >> 16) & 0xffff;
+               vendor = vp->vendor;
                if (vendor != 0) {
                        attr = vp->attribute & 0xffff;
                        length |= (1 << 31);
@@ -594,7 +583,7 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
 
                if ((debug_flag > 2) && fr_log_fp) {
                        for (i = 0; i < total; i++) {
-                               if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data out %04x: ", i);
+                               if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data out %04x: ", (int) i);
 
                                fprintf(fr_log_fp, "%02x ", buffer[i]);
 
@@ -609,7 +598,7 @@ static int vp2diameter(REQUEST *request, tls_session_t *tls_session, VALUE_PAIR
                /*
                 *      FIXME: Check the return code.
                 */
-               tls_handshake_send(tls_session);
+               tls_handshake_send(request, tls_session);
        }
 
        /*
@@ -629,6 +618,8 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
        ttls_tunnel_t *t = tls_session->opaque;
 
        handler = handler;      /* -Wunused */
+       rad_assert(request != NULL);
+       rad_assert(handler->request == request);
 
        /*
         *      If the response packet was Access-Accept, then
@@ -666,7 +657,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      packet, and we will send EAP-Success.
                 */
                vp = NULL;
-               pairmove2(&vp, &reply->vps, PW_MSCHAP2_SUCCESS);
+               pairmove2(&vp, &reply->vps, PW_MSCHAP2_SUCCESS, VENDORPEC_MICROSOFT);
                if (vp) {
                        RDEBUG("Got MS-CHAP2-Success, tunneling it to the client in a challenge.");
                        rcode = RLM_MODULE_HANDLED;
@@ -676,16 +667,16 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                         *      Delete MPPE keys & encryption policy.  We don't
                         *      want these here.
                         */
-                       pairdelete(&reply->vps, ((311 << 16) | 7));
-                       pairdelete(&reply->vps, ((311 << 16) | 8));
-                       pairdelete(&reply->vps, ((311 << 16) | 16));
-                       pairdelete(&reply->vps, ((311 << 16) | 17));
+                       pairdelete(&reply->vps, 7, VENDORPEC_MICROSOFT);
+                       pairdelete(&reply->vps, 8, VENDORPEC_MICROSOFT);
+                       pairdelete(&reply->vps, 16, VENDORPEC_MICROSOFT);
+                       pairdelete(&reply->vps, 17, VENDORPEC_MICROSOFT);
 
                        /*
                         *      Use the tunneled reply, but not now.
                         */
                        if (t->use_tunneled_reply) {
-                               t->reply = reply->vps;
+                               t->accept_vps = reply->vps;
                                reply->vps = NULL;
                        }
 
@@ -699,7 +690,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                         *      can figure it out, from the non-tunneled
                         *      EAP-Success packet.
                         */
-                       pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE);
+                       pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE, 0);
                        pairfree(&vp);
                }
 
@@ -720,7 +711,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      tunneled user!
                 */
                if (t->use_tunneled_reply) {
-                       pairdelete(&reply->vps, PW_PROXY_STATE);
+                       pairdelete(&reply->vps, PW_PROXY_STATE, 0);
                        pairadd(&request->reply->vps, reply->vps);
                        reply->vps = NULL;
                }
@@ -747,7 +738,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      Get rid of the old State, too.
                 */
                pairfree(&t->state);
-               pairmove2(&t->state, &reply->vps, PW_STATE);
+               pairmove2(&t->state, &reply->vps, PW_STATE, 0);
 
                /*
                 *      We should really be a bit smarter about this,
@@ -757,7 +748,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      method works in 99.9% of the situations.
                 */
                vp = NULL;
-               pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE);
+               pairmove2(&vp, &reply->vps, PW_EAP_MESSAGE, 0);
 
                /*
                 *      There MUST be a Reply-Message in the challenge,
@@ -767,7 +758,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
                 *      we MUST create one, with an empty string as
                 *      it's value.
                 */
-               pairmove2(&vp, &reply->vps, PW_REPLY_MESSAGE);
+               pairmove2(&vp, &reply->vps, PW_REPLY_MESSAGE, 0);
 
                /*
                 *      Handle the ACK, by tunneling any necessary reply
@@ -790,6 +781,7 @@ static int process_reply(EAP_HANDLER *handler, tls_session_t *tls_session,
 }
 
 
+#ifdef WITH_PROXY
 /*
  *     Do post-proxy processing,
  */
@@ -799,6 +791,7 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
        tls_session_t *tls_session = (tls_session_t *) data;
        REQUEST *fake, *request = handler->request;
 
+       rad_assert(request != NULL);
        RDEBUG("Passing reply from proxy back into the tunnel.");
 
        /*
@@ -813,8 +806,6 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
         *      Do the callback, if it exists, and if it was a success.
         */
        if (fake && (handler->request->proxy_reply->code == PW_AUTHENTICATION_ACK)) {
-               REQUEST *request = handler->request;
-
                /*
                 *      Terrible hacks.
                 */
@@ -828,7 +819,8 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
                request->proxy_reply = NULL;
 
                if ((debug_flag > 0) && fr_log_fp) {
-                       fprintf(fr_log_fp, "server %s {\n", fake->server);
+                       fprintf(fr_log_fp, "server %s {\n",
+                               (fake->server == NULL) ? "" : fake->server);
                }
 
                /*
@@ -840,7 +832,8 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
                RDEBUG2("post-auth returns %d", rcode);
 
                if ((debug_flag > 0) && fr_log_fp) {
-                       fprintf(fr_log_fp, "} # server %s\n", fake->server);
+                       fprintf(fr_log_fp, "} # server %s\n",
+                               (fake->server == NULL) ? "" : fake->server);
                        
                        RDEBUG("Final reply from tunneled session code %d",
                               fake->reply->code);
@@ -862,12 +855,12 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
                switch (rcode) {
                 case RLM_MODULE_FAIL:
                        request_free(&fake);
-                       eaptls_fail(handler->eap_ds, 0);
+                       eaptls_fail(handler, 0);
                        return 0;
                        break;
 
                 default:  /* Don't Do Anything */
-                       RDEBUG2("sGot reply %d",
+                       RDEBUG2("Got reply %d",
                               request->proxy_reply->code);
                        break;
                }
@@ -899,18 +892,18 @@ static int eapttls_postproxy(EAP_HANDLER *handler, void *data)
 
        case RLM_MODULE_OK:
                RDEBUG("Reply was OK");
-               eaptls_success(handler->eap_ds, 0);
-               eaptls_gen_mppe_keys(&handler->request->reply->vps,
-                                    tls_session->ssl,
-                                    "ttls keying material");
-               return 1;
+
+               /*
+                *      Success: Automatically return MPPE keys.
+                */
+               return eaptls_success(handler, 0);
 
        default:
                RDEBUG("Reply was unknown.");
                break;
        }
 
-       eaptls_fail(handler->eap_ds, 0);
+       eaptls_fail(handler, 0);
        return 0;
 }
 
@@ -924,14 +917,13 @@ static void my_request_free(void *data)
 
        request_free(&request);
 }
-
+#endif /* WITH_PROXY */
 
 /*
  *     Process the "diameter" contents of the tunneled data.
  */
 int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
 {
-       int err;
        int rcode = PW_AUTHENTICATION_REJECT;
        REQUEST *fake;
        VALUE_PAIR *vp;
@@ -940,17 +932,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
        size_t data_len;
        REQUEST *request = handler->request;
 
-       /*
-        *      FIXME: if the SSL session says "want read", or
-        *      similar, leave the data in the clean_out buffer.  This
-        *      lets the application data be sent across multiple
-        *      fragments.
-        */
-       err = tls_handshake_recv(tls_session);
-       if (!err) {
-               RDEBUG2("Failed in SSL");
-               return RLM_MODULE_REJECT;
-       }
+       rad_assert(request != NULL);
 
        /*
         *      Just look at the buffer directly, without doing
@@ -985,7 +967,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                size_t i;
 
                for (i = 0; i < data_len; i++) {
-                       if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data in %04x: ", i);
+                       if ((i & 0x0f) == 0) fprintf(fr_log_fp, "  TTLS tunnel data in %04x: ", (int) i);
 
                        fprintf(fr_log_fp, "%02x ", data[i]);
 
@@ -1018,7 +1000,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
        /*
         *      Tell the request that it's a fake one.
         */
-       vp = pairmake("Freeradius-Proxied-T<o", "127.0.0.1", T_OP_EQ);
+       vp = pairmake("Freeradius-Proxied-To", "127.0.0.1", T_OP_EQ);
        if (vp) {
                pairadd(&fake->packet->vps, vp);
        }
@@ -1032,8 +1014,8 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
        /*
         *      Update other items in the REQUEST data structure.
         */
-       fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
-       fake->password = pairfind(fake->packet->vps, PW_USER_PASSWORD);
+       fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0);
+       fake->password = pairfind(fake->packet->vps, PW_USER_PASSWORD, 0);
 
        /*
         *      No User-Name, try to create one from stored data.
@@ -1044,7 +1026,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                 *      an EAP-Identity, and pull it out of there.
                 */
                if (!t->username) {
-                       vp = pairfind(fake->packet->vps, PW_EAP_MESSAGE);
+                       vp = pairfind(fake->packet->vps, PW_EAP_MESSAGE, 0);
                        if (vp &&
                            (vp->length >= EAP_HEADER_LEN + 2) &&
                            (vp->vp_strvalue[0] == PW_EAP_RESPONSE) &&
@@ -1070,7 +1052,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                                 */
                                if (t->default_eap_type != 0) {
                                        RDEBUG("Setting default EAP type for tunneled EAP session.");
-                                       vp = paircreate(PW_EAP_TYPE,
+                                       vp = paircreate(PW_EAP_TYPE, 0,
                                                        PW_TYPE_INTEGER);
                                        rad_assert(vp != NULL);
                                        vp->vp_integer = t->default_eap_type;
@@ -1090,7 +1072,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                if (t->username) {
                        vp = paircopy(t->username);
                        pairadd(&fake->packet->vps, vp);
-                       fake->username = pairfind(fake->packet->vps, PW_USER_NAME);
+                       fake->username = pairfind(fake->packet->vps, PW_USER_NAME, 0);
                }
        } /* else the request ALREADY had a User-Name */
 
@@ -1118,7 +1100,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         *      don't copy it.
                         */
                        if ((vp->attribute > 255) &&
-                           (((vp->attribute >> 16) & 0xffff) == 0)) {
+                           (vp->vendor == 0)) {
                                continue;
                        }
 
@@ -1131,7 +1113,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         *      AND attributes which are copied there
                         *      from below.
                         */
-                       if (pairfind(fake->packet->vps, vp->attribute)) {
+                       if (pairfind(fake->packet->vps, vp->attribute, vp->vendor)) {
                                continue;
                        }
 
@@ -1166,12 +1148,12 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         *      Don't copy from the head, we've already
                         *      checked it.
                         */
-                       copy = paircopy2(vp, vp->attribute);
+                       copy = paircopy2(vp, vp->attribute, vp->vendor);
                        pairadd(&fake->packet->vps, copy);
                }
        }
 
-       if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER)) != NULL) {
+       if ((vp = pairfind(request->config_items, PW_VIRTUAL_SERVER, 0)) != NULL) {
                fake->server = vp->vp_strvalue;
 
        } else if (t->virtual_server) {
@@ -1185,7 +1167,8 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
 
                debug_pair_list(fake->packet->vps);
 
-               fprintf(fr_log_fp, "server %s {\n", fake->server);
+               fprintf(fr_log_fp, "server %s {\n",
+                       (fake->server == NULL) ? "" : fake->server);
        }
 
        /*
@@ -1199,7 +1182,8 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         *      attributes.
         */
        if ((debug_flag > 0) && fr_log_fp) {
-               fprintf(fr_log_fp, "} # server %s\n", fake->server);
+               fprintf(fr_log_fp, "} # server %s\n",
+                       (fake->server == NULL) ? "" : fake->server);
 
                RDEBUG("Got tunneled reply code %d", fake->reply->code);
                
@@ -1211,7 +1195,8 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
         */
        switch (fake->reply->code) {
        case 0:                 /* No reply code, must be proxied... */
-               vp = pairfind(fake->config_items, PW_PROXY_TO_REALM);
+#ifdef WITH_PROXY
+         vp = pairfind(fake->config_items, PW_PROXY_TO_REALM, 0);
                if (vp) {
                        eap_tunnel_data_t *tunnel;
                        RDEBUG("Tunneled authentication will be proxied to %s", vp->vp_strvalue);
@@ -1222,7 +1207,7 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         */
                        pairmove2(&(request->config_items),
                                  &(fake->config_items),
-                                 PW_PROXY_TO_REALM);
+                                 PW_PROXY_TO_REALM, 0);
 
                        /*
                         *      Seed the proxy packet with the
@@ -1230,6 +1215,12 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         */
                        rad_assert(request->proxy == NULL);
                        request->proxy = fake->packet;
+                       memset(&request->proxy->src_ipaddr, 0,
+                              sizeof(request->proxy->src_ipaddr));
+                       memset(&request->proxy->src_ipaddr, 0,
+                              sizeof(request->proxy->src_ipaddr));
+                       request->proxy->src_port = 0;
+                       request->proxy->dst_port = 0;
                        fake->packet = NULL;
                        rad_free(&fake->reply);
                        fake->reply = NULL;
@@ -1272,7 +1263,9 @@ int eapttls_process(EAP_HANDLER *handler, tls_session_t *tls_session)
                         */
                        rcode = PW_STATUS_CLIENT;
 
-               } else {
+               } else
+#endif /* WITH_PROXY */
+                 {
                        RDEBUG("No tunneled reply was found for request %d , and the request was not proxied: rejecting the user.",
                               request->number);
                        rcode = PW_AUTHENTICATION_REJECT;