From: Alan T. DeKok Date: Fri, 20 Jul 2012 23:29:34 +0000 (-0400) Subject: Be more forgiving about decoding data in TTLS tunnels X-Git-Tag: release_2_2_0~91 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41bb275514c30318a6d83d34c16dc1a940418e1e;p=thirdparty%2Ffreeradius-server.git Be more forgiving about decoding data in TTLS tunnels Allow unknown / invalid attrs as "raw" attributes. Decode byte, short, IPv6* --- diff --git a/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c b/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c index 71a126d935e..3a88f26ce8b 100644 --- a/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c +++ b/src/modules/rlm_eap/types/rlm_eap_ttls/ttls.c @@ -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; }