]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
Be more forgiving about decoding data in TTLS tunnels
authorAlan T. DeKok <aland@freeradius.org>
Fri, 20 Jul 2012 23:29:34 +0000 (19:29 -0400)
committerAlan T. DeKok <aland@freeradius.org>
Fri, 20 Jul 2012 23:34:42 +0000 (19:34 -0400)
Allow unknown / invalid attrs as "raw" attributes.
Decode byte, short, IPv6*

src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c

index 71a126d935e4a97748c06dd67582a3465b9c5db2..3a88f26ce8b416831e3292b27fb00fd04fafd218 100644 (file)
@@ -83,8 +83,13 @@ static int diameter_verify(REQUEST *request,
                        memcpy(&vendor, data, sizeof(vendor));
                        vendor = ntohl(vendor);
 
+                       if (attr > 65535) {
+                               RDEBUG2("Cannot handle vendor attributes greater than 65535");
+                               return 0;
+                       }
+
                        if (vendor > 65535) {
-                               RDEBUG2("Vendor codes larger than 65535 are not supported");
+                               RDEBUG2("Cannot handle vendor Id greater than 65535");
                                return 0;
                        }
 
@@ -220,33 +225,20 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                        memcpy(&vendor, data, sizeof(vendor));
                        vendor = ntohl(vendor);
 
-                       if (attr > 65535) {
-                               RDEBUG2("Cannot handle vendor attributes greater than 65535");
-                               pairfree(&first);
-                               return NULL;
-                       }
+                       data += 4; /* skip the vendor field, it's zero */
+                       offset += 4; /* offset to value field */
+                       length &= 0x00ffffff;
 
-                       if (vendor > 65535) {
-                               RDEBUG2("Cannot handle vendor Id greater than 65535");
-                               pairfree(&first);
-                               return NULL;
-                       }
+                       if (attr > 65535) goto next_attr;
+                       if (vendor > 65535) goto next_attr;
 
                        attr |= (vendor << 16);
-
-                       data += 4; /* skip the vendor field, it's zero */
-                       offset += 4; /* offset to value field */
                }
 
                /*
-                *      Vendor attributes can be larger than 255.
-                *      Normal attributes cannot be.
+                *      Get the length.
                 */
-               if ((attr > 255) && (VENDOR(attr) == 0)) {
-                       RDEBUG2("Cannot handle Diameter attributes");
-                       pairfree(&first);
-                       return NULL;
-               }
+               length &= 0x00ffffff;
 
                /*
                 *      FIXME: Handle the M bit.  For now, we assume that
@@ -254,11 +246,6 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                 *      with the M bit set.
                 */
                
-               /*
-                *      Get the length.
-                */
-               length &= 0x00ffffff;
-
                /*
                 *      Get the size of the value portion of the
                 *      attribute.
@@ -266,11 +253,20 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                size = length - offset;
 
                /*
-                *      Create it.
+                *      Vendor attributes can be larger than 255.
+                *      Normal attributes cannot be.
+                */
+               if ((attr > 255) && (VENDOR(attr) == 0)) {
+                       RDEBUG2("Cannot handle Diameter attributes");
+                       goto next_attr;
+               }
+
+               /*
+                *      Create it.  If this fails, it's because we're OOM.
                 */
                vp = paircreate(attr, PW_TYPE_OCTETS);
                if (!vp) {
-                       RDEBUG2("Failure in creating VP");
+                       RDEBUG2("diameter2vp: Failed creating attribute %u", attr);
                        pairfree(&first);
                        return NULL;
                }
@@ -283,11 +279,16 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                case PW_TYPE_INTEGER:
                case PW_TYPE_DATE:
                        if (size != vp->length) {
-                               RDEBUG2("Invalid length attribute %d",
-                                      attr);
-                               pairfree(&first);
-                               pairfree(&vp);
-                               return NULL;
+                               /*
+                                *      Bad format.  Create a "raw"
+                                *      attribute.
+                                */
+               raw:
+                               vp = paircreate_raw(vp->attribute,
+                                                   PW_TYPE_OCTETS, vp);
+                               vp->length = size;
+                               memcpy(vp->vp_octets, data, vp->length);
+                               break;
                        }
                        memcpy(&vp->vp_integer, data, vp->length);
 
@@ -298,27 +299,47 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
                        break;
 
                case PW_TYPE_IPADDR:
-                       if (size != vp->length) {
-                               RDEBUG2("Invalid length attribute %d",
-                                      attr);
-                               pairfree(&first);
-                               pairfree(&vp);
-                               return NULL;
-                       }
-                 memcpy(&vp->vp_ipaddr, data, vp->length);
-
-                 /*
-                  *    Stored in network byte order: don't change it.
-                  */
-                 break;
-
-                 /*
-                  *    String, octet, etc.  Copy the data from the
-                  *    value field over verbatim.
-                  *
-                  *    FIXME: Ipv6 attributes ?
-                  *
-                  */
+                       if (size != vp->length) goto raw;
+                       memcpy(&vp->vp_ipaddr, data, vp->length);
+
+                       /*
+                        *      Stored in network byte order: don't change it.
+                        */
+                       break;
+
+               case PW_TYPE_BYTE:
+                       if (size != vp->length) goto raw;
+                       vp->vp_integer = data[0];
+                       break;
+
+               case PW_TYPE_SHORT:
+                       if (size != vp->length) goto raw;
+                       vp->vp_integer = (data[0] * 256) + data[1];
+                       break;
+
+               case PW_TYPE_SIGNED:
+                       if (size != vp->length) goto raw;
+                       memcpy(&vp->vp_signed, data, vp->length);
+                       vp->vp_signed = ntohl(vp->vp_signed);
+                       break;
+
+               case PW_TYPE_IPV6ADDR:
+                       if (size != vp->length) goto raw;
+                       memcpy(&vp->vp_ipv6addr, data, vp->length);
+                       break;
+
+               case PW_TYPE_IPV6PREFIX:
+                       if (size != vp->length) goto raw;
+                       memcpy(&vp->vp_ipv6prefix, data, vp->length);
+                       break;
+
+                       /*
+                        *      String, octet, etc.  Copy the data from the
+                        *      value field over verbatim.
+                        *
+                        *      FIXME: Ipv6 attributes ?
+                        *
+                        */
                case PW_TYPE_OCTETS:
                        if (attr == PW_EAP_MESSAGE) {
                                const uint8_t *eap_message = data;
@@ -342,7 +363,7 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
 
                                        vp = paircreate(attr, PW_TYPE_OCTETS);
                                        if (!vp) {
-                                               RDEBUG2("Failure in creating VP");
+                                               RDEBUG2("Failed creating EAP-Message");
                                                pairfree(&first);
                                                return NULL;
                                        }
@@ -354,7 +375,7 @@ static VALUE_PAIR *diameter2vp(REQUEST *request, SSL *ssl,
 
                default:
                        vp->length = size;
-                       memcpy(vp->vp_strvalue, data, vp->length);
+                       memcpy(vp->vp_octets, data, vp->length);
                        break;
                }