From: Alan T. DeKok Date: Mon, 23 May 2011 14:06:50 +0000 (+0200) Subject: Print, parse, and encode, decode "long" attributes X-Git-Tag: release_3_0_0_beta0~811 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=4c0d5e3474fc821e47645a21541326e9b7da1452;p=thirdparty%2Ffreeradius-server.git Print, parse, and encode, decode "long" attributes --- diff --git a/src/include/radius.h b/src/include/radius.h index 9d595929508..34bcb6d88ee 100644 --- a/src/include/radius.h +++ b/src/include/radius.h @@ -25,6 +25,8 @@ #define PW_TYPE_EXTENDED_FLAGS 16 #define PW_TYPE_EVS 17 +#define PW_FLAG_LONG (1 << 8) + #define PW_AUTHENTICATION_REQUEST 1 #define PW_AUTHENTICATION_ACK 2 #define PW_AUTHENTICATION_REJECT 3 diff --git a/src/lib/print.c b/src/lib/print.c index 7ae05f7456d..b0f1d37bc84 100644 --- a/src/lib/print.c +++ b/src/lib/print.c @@ -215,6 +215,8 @@ int vp_prints_value(char * out, size_t outlen, const VALUE_PAIR *vp, int delimit out[0] = '\0'; if (!vp) return 0; + if ((vp->type & PW_FLAG_LONG) != 0) goto do_tlv; + switch (vp->type) { case PW_TYPE_STRING: if ((delimitst == 1) && vp->flags.has_tag) { @@ -337,6 +339,7 @@ int vp_prints_value(char * out, size_t outlen, const VALUE_PAIR *vp, int delimit break; case PW_TYPE_TLV: + do_tlv: if (outlen <= (2 * (vp->length + 1))) return 0; strcpy(buf, "0x"); @@ -466,7 +469,7 @@ const char *vp_print_name(char *buffer, size_t bufsize, bufsize -= len; } - len = vp_print_attr_oid(p, bufsize , attr, dv_type); + vp_print_attr_oid(p, bufsize , attr, dv_type); return buffer; } diff --git a/src/lib/radius.c b/src/lib/radius.c index c559e02d032..8f2140e0ce9 100644 --- a/src/lib/radius.c +++ b/src/lib/radius.c @@ -833,6 +833,12 @@ static ssize_t vp2data_any(const RADIUS_PACKET *packet, data = vp->vp_octets; len = vp->length; + /* + * Short-circuit it for long attributes. They can't be + * encrypted, tagged, etc. + */ + if ((vp->type & PW_FLAG_LONG) != 0) goto do_tlv; + switch(vp->type) { case PW_TYPE_STRING: case PW_TYPE_OCTETS: @@ -888,6 +894,7 @@ static ssize_t vp2data_any(const RADIUS_PACKET *packet, } case PW_TYPE_TLV: + do_tlv: data = vp->vp_tlv; if (!data) { fr_strerror_printf("ERROR: Cannot encode NULL TLV"); @@ -2740,12 +2747,13 @@ static ssize_t data2vp_raw(UNUSED const RADIUS_PACKET *packet, vp->length = length; /* - * If the data is too large, mark it as a "TLV". + * If it's short, put it into the array. If it's too + * long, flag it as such, and put it somewhere else; */ if (length <= sizeof(vp->vp_octets)) { memcpy(vp->vp_octets, data, length); } else { - vp->type = PW_TYPE_TLV; + vp->type |= PW_FLAG_LONG; vp->vp_tlv = malloc(length); if (!vp->vp_tlv) { pairfree(&vp); diff --git a/src/lib/valuepair.c b/src/lib/valuepair.c index 8d8ed531b22..e7258ca654b 100644 --- a/src/lib/valuepair.c +++ b/src/lib/valuepair.c @@ -1108,34 +1108,36 @@ VALUE_PAIR *pairparsevalue(VALUE_PAIR *vp, const char *value) /* raw octets: 0x01020304... */ case PW_TYPE_OCTETS: if (strncasecmp(value, "0x", 2) == 0) { + size_t size; uint8_t *us; + cp = value + 2; us = vp->vp_octets; vp->length = 0; - /* - * There is only one character, - * die. + * Invalid. */ - if ((strlen(cp) & 0x01) != 0) { + size = strlen(cp); + if ((size & 0x01) != 0) { fr_strerror_printf("Hex string is not an even length string."); return NULL; } - - while (*cp && - (vp->length < MAX_STRING_LEN)) { - unsigned int tmp; - - if (sscanf(cp, "%02x", &tmp) != 1) { - fr_strerror_printf("Non-hex characters at %c%c", cp[0], cp[1]); + vp->length = size >> 1; + if (size > 2*sizeof(vp->vp_octets)) { + vp->type |= PW_FLAG_LONG; + us = vp->vp_tlv = malloc(vp->length); + if (!us) { + fr_strerror_printf("Out of memory."); return NULL; } + } - cp += 2; - *(us++) = tmp; - vp->length++; + if (fr_hex2bin(cp, us, + vp->length) != vp->length) { + fr_strerror_printf("Invalid hex data"); + return NULL; } } break; @@ -1306,6 +1308,7 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value, unsigned int dv_type = 1; size_t size; const char *p = attribute; + void *data; char *q; VALUE_PAIR *vp; DICT_VENDOR *dv; @@ -1499,6 +1502,7 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value, if (!value) return vp; size = strlen(value + 2); + data = vp->vp_octets; /* * We may be reading something like Attr-5. i.e. @@ -1515,7 +1519,14 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value, case PW_TYPE_ABINARY: vp->length = size >> 1; if (vp->length > sizeof(vp->vp_octets)) { - vp->length = sizeof(vp->vp_octets); + vp->vp_tlv = malloc(vp->length); + if (!vp->vp_tlv) { + fr_strerror_printf("Out of memory"); + free(vp); + return NULL; + } + data = vp->vp_tlv; + vp->type |= PW_FLAG_LONG; } break; @@ -1523,12 +1534,19 @@ static VALUE_PAIR *pairmake_any(const char *attribute, const char *value, vp->length = size >> 1; memset(&vp->vp_strvalue, 0, sizeof(vp->vp_strvalue)); if (vp->length >= sizeof(vp->vp_strvalue)) { - vp->length = sizeof(vp->vp_strvalue) - 1; + vp->vp_tlv = malloc(vp->length); + if (!vp->vp_tlv) { + fr_strerror_printf("Out of memory"); + free(vp); + return NULL; + } + data = vp->vp_tlv; + vp->type |= PW_FLAG_LONG; } break; } - if (fr_hex2bin(value + 2, vp->vp_octets, size) != vp->length) { + if (fr_hex2bin(value + 2, data, size) != vp->length) { fr_strerror_printf("Invalid hex string"); free(vp); return NULL;