From c58974367039b764bd918b31290afbd424ca8c45 Mon Sep 17 00:00:00 2001 From: Kevin Wasserman Date: Fri, 10 Feb 2012 11:51:12 -0500 Subject: [PATCH 1/1] Simplify and document radius_utils.c and radius_utils.h --- libeap/src/utils/radius_utils.c | 85 +++++++++++++++-------------------------- libeap/src/utils/radius_utils.h | 60 +++++++++++++++++++++++------ 2 files changed, 79 insertions(+), 66 deletions(-) diff --git a/libeap/src/utils/radius_utils.c b/libeap/src/utils/radius_utils.c index 8bdba6c..b5b8e80 100644 --- a/libeap/src/utils/radius_utils.c +++ b/libeap/src/utils/radius_utils.c @@ -20,59 +20,37 @@ #include "radius_utils.h" #include "wpabuf.h" -struct radius_vendor_attr_struct +int radius_add_tlv(struct wpabuf **buf, u32 type, u32 vendor, u8 *data, + size_t len) { - struct wpabuf *buf; - u8 *len_pos; - size_t start; -}; - -radius_vendor_attr radius_vendor_attr_start(struct wpabuf *buf, u32 vendor) -{ - radius_vendor_attr attr = (radius_vendor_attr )os_zalloc(sizeof(*attr)); - if (!attr) - return attr; - attr->buf = buf; - attr->start = wpabuf_len(buf); - wpabuf_put_u8(buf, 26); - attr->len_pos = (u8*)wpabuf_put(buf, 1); - /* @TODO: Verify high 8 bits of vendor are 0? */ - wpabuf_put_be32(buf, vendor); - return attr; -} + u8 base_type; + u8 total; + if (vendor) { + if (len + 6 > RADIUS_MAX_ATTR_LEN) + return -1; + total = len + 2 + 6; + base_type = RADIUS_ATTR_VENDOR_SPECIFIC; + } else { + if (len > RADIUS_MAX_ATTR_LEN) + return -1; + total = len + 2; + base_type = type; + } -radius_vendor_attr radius_vendor_attr_add_subtype(radius_vendor_attr attr, - u8 type, - u8 *data, - size_t len) -{ - if (attr == VENDOR_ATTR_INVALID) - return attr; - if (len + 2 + (wpabuf_len(attr->buf) - attr->start) > 255) { - os_free(attr); - return VENDOR_ATTR_INVALID; - } - wpabuf_put_u8(attr->buf, type); - wpabuf_put_u8(attr->buf, len + 2); - wpabuf_put_data(attr->buf, data, len); - return attr; -} + /* ensure buffer has enough space */ + if (wpabuf_resize(buf, total)) + return -1; -radius_vendor_attr radius_vendor_attr_finish(radius_vendor_attr attr) -{ - /* poke size into correct place and free attr */ - size_t len; - radius_vendor_attr ret = VENDOR_ATTR_INVALID; - if (attr == ret) - return ret; - - len = wpabuf_len(attr->buf) - attr->start; - if (len < 255) { - ret = attr; - *(attr->len_pos) = (u8 )len; - } - os_free(attr); - return ret; + /* write into buffer */ + wpabuf_put_u8(*buf, base_type); + wpabuf_put_u8(*buf, total); + if (vendor) { + wpabuf_put_be32(*buf, vendor); + wpabuf_put_u8(*buf, (u8 )type); + wpabuf_put_u8(*buf, (u8 )len+2); + } + wpabuf_put_data(*buf, data, len); + return 0; } struct radius_parser_struct @@ -99,7 +77,7 @@ void radius_parser_finish(radius_parser parser) } int radius_parser_parse_tlv(radius_parser parser, u8 *type, u32 *vendor_id, - void **value, size_t *len) + void **value, size_t *len) { u8 rawtype, rawlen; if (!parser) @@ -117,8 +95,7 @@ int radius_parser_parse_tlv(radius_parser parser, u8 *type, u32 *vendor_id, *vendor_id = WPA_GET_BE24(&parser->data[parser->pos + 3]); *value = &parser->data[parser->pos + 6]; *len = rawlen - 6; - } - else { + } else { if (rawlen < 3) return -1; @@ -132,7 +109,7 @@ int radius_parser_parse_tlv(radius_parser parser, u8 *type, u32 *vendor_id, } int radius_parser_parse_vendor_specific(radius_parser parser, u8 *vendor_type, - void **value, size_t *len) + void **value, size_t *len) { u8 rawtype, rawlen; if (!parser) diff --git a/libeap/src/utils/radius_utils.h b/libeap/src/utils/radius_utils.h index 46ab65d..b0560a4 100644 --- a/libeap/src/utils/radius_utils.h +++ b/libeap/src/utils/radius_utils.h @@ -1,5 +1,5 @@ /* - * RADIUS tlv construction utilites + * RADIUS tlv construction and parsing utilites * Copyright (c) 2012, Painless Security, LLC * * This program is free software; you can redistribute it and/or modify @@ -16,24 +16,60 @@ #define RADIUS_UTILS_H struct wpabuf; - -struct radius_vendor_attr_struct; -typedef struct radius_vendor_attr_struct *radius_vendor_attr; -#define VENDOR_ATTR_INVALID NULL -radius_vendor_attr radius_vendor_attr_start(struct wpabuf *buf, u32 vendor); -radius_vendor_attr radius_vendor_attr_add_subtype(radius_vendor_attr attr, - u8 type, - u8 *data, size_t len); -radius_vendor_attr radius_vendor_attr_finish(radius_vendor_attr attr); - struct radius_parser_struct; typedef struct radius_parser_struct *radius_parser; + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Simple utility to add a single type-length-value attribute to a buffer. + * Currently, there is no dictionary support: 'type' and 'len' are always + * assumed to be octets, and data is placed directly into buf untranslated + * for byte order. If vendor is zero, len should be no greater than 253 + * otherwise, no greater than 247. + * returns 0 on success, -1 on failure (allocation failure or len too large) + */ +int radius_add_tlv(struct wpabuf **buf, u32 type, u32 vendor, u8 *data, + size_t len); + +/* + * simple radius parser + * Could be made considerably simpler by dropping support for parsing multiple + * sub-attributes from a vsa. + */ + +/* + * create parser object + */ radius_parser radius_parser_start(void *tlvdata, size_t len); + +/* + * parse a single tlv; + * There is no dictionary support; if the tlv is a vsa (attribute 26), + * sub-attributes are not immediately parsed: instead, the raw data is returned + * in 'value'. + * returns 0 on success, -1 on failure (malformed buffer or end of buffer) + */ int radius_parser_parse_tlv(radius_parser parser, u8 *type, u32 *vendor_id, void **value, size_t *len); + +/* + * parse a single sub-attribute of a vsa: assumes octets for + * vendor_type and len + * returns 0 on success, -1 on failure (malformed buffer or end of buffer) + */ int radius_parser_parse_vendor_specific(radius_parser parser, u8 *vendor_type, - void **value, size_t *len); + void **value, size_t *len); + +/* + * destroy parser object + */ void radius_parser_finish(radius_parser parser); +#ifdef __cplusplus +} +#endif #endif /* RADIUS_UTILS_H */ \ No newline at end of file -- 2.1.4