From 4ecef18da4eef3e393f683356f16fa621cd205f2 Mon Sep 17 00:00:00 2001 From: Arran Cudbard-Bell Date: Wed, 17 Oct 2012 15:32:41 +0100 Subject: [PATCH] fixes #108 Add function to convert FR value pair types to network byte order --- src/include/base64.h | 4 +-- src/include/libradius.h | 1 + src/lib/base64.c | 16 +++++------ src/lib/radius.c | 63 +++++++++++++++++++++++++++++++++++++++++ src/main/xlat.c | 39 +++++++++++++++++-------- 5 files changed, 101 insertions(+), 22 deletions(-) diff --git a/src/include/base64.h b/src/include/base64.h index 84ecf52e98f..645e111906f 100644 --- a/src/include/base64.h +++ b/src/include/base64.h @@ -31,10 +31,10 @@ RCSIDH(base64_h, "$Id$") extern int fr_isbase64 (char ch); -extern void fr_base64_encode (const char *in, size_t inlen, +extern void fr_base64_encode (const uint8_t *in, size_t inlen, char *out, size_t outlen); -extern size_t fr_base64_encode_alloc (const char *in, size_t inlen, char **out); +extern size_t fr_base64_encode_alloc (const uint8_t *in, size_t inlen, char **out); extern int fr_base64_decode (const char *in, size_t inlen, char *out, size_t *outlen); diff --git a/src/include/libradius.h b/src/include/libradius.h index 7f757770bd8..1c15f32e7cb 100644 --- a/src/include/libradius.h +++ b/src/include/libradius.h @@ -344,6 +344,7 @@ int rad_chap_encode(RADIUS_PACKET *packet, uint8_t *output, VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *original, const char *secret, int attribute, int length, const uint8_t *data); +ssize_t rad_vp2data(const VALUE_PAIR *vp, uint8_t *out, size_t outlen); int rad_vp2attr(const RADIUS_PACKET *packet, const RADIUS_PACKET *original, const char *secret, const VALUE_PAIR *vp, uint8_t *ptr); diff --git a/src/lib/base64.c b/src/lib/base64.c index 2541bf1c05d..b796c6ad480 100644 --- a/src/lib/base64.c +++ b/src/lib/base64.c @@ -63,7 +63,7 @@ to_uchar (char ch) If OUTLEN is less than FR_BASE64_ENC_LENGTH(INLEN), write as many bytes as possible. If OUTLEN is larger than FR_BASE64_ENC_LENGTH(INLEN), also zero terminate the output buffer. */ -void fr_base64_encode (const char *in, size_t inlen, +void fr_base64_encode (const uint8_t *in, size_t inlen, char *out, size_t outlen) { static const char b64str[64] = @@ -71,23 +71,23 @@ void fr_base64_encode (const char *in, size_t inlen, while (inlen && outlen) { - *out++ = b64str[(to_uchar (in[0]) >> 2) & 0x3f]; + *out++ = b64str[(in[0] >> 2) & 0x3f]; if (!--outlen) break; - *out++ = b64str[((to_uchar (in[0]) << 4) - + (--inlen ? to_uchar (in[1]) >> 4 : 0)) + *out++ = b64str[((in[0] << 4) + + (--inlen ? in[1] >> 4 : 0)) & 0x3f]; if (!--outlen) break; *out++ = (inlen - ? b64str[((to_uchar (in[1]) << 2) - + (--inlen ? to_uchar (in[2]) >> 6 : 0)) + ? b64str[((in[1] << 2) + + (--inlen ? in[2] >> 6 : 0)) & 0x3f] : '='); if (!--outlen) break; - *out++ = inlen ? b64str[to_uchar (in[2]) & 0x3f] : '='; + *out++ = inlen ? b64str[in[2] & 0x3f] : '='; if (!--outlen) break; if (inlen) @@ -110,7 +110,7 @@ void fr_base64_encode (const char *in, size_t inlen, indicates length of the requested memory block, i.e., FR_BASE64_ENC_LENGTH(inlen) + 1. */ size_t -fr_base64_encode_alloc (const char *in, size_t inlen, char **out) +fr_base64_encode_alloc (const uint8_t *in, size_t inlen, char **out) { size_t outlen = 1 + FR_BASE64_ENC_LENGTH (inlen); diff --git a/src/lib/radius.c b/src/lib/radius.c index 7c5a4372db0..397281721c5 100644 --- a/src/lib/radius.c +++ b/src/lib/radius.c @@ -2740,6 +2740,69 @@ VALUE_PAIR *rad_attr2vp(const RADIUS_PACKET *packet, const RADIUS_PACKET *origin return data2vp(packet, original, secret, attribute, length, data, vp); } +/** + * Converts vp_data to network byte order + * Returns: + * -1 on error, or the length of the value + */ +ssize_t rad_vp2data(const VALUE_PAIR *vp, uint8_t *out, size_t outlen) +{ + size_t len = 0; + uint32_t lvalue; + + len = vp->length; + if (outlen < len) { + fr_strerror_printf("ERROR: rad_vp2data buffer passed too small"); + return -1; + } + + switch(vp->type) { + case PW_TYPE_STRING: + case PW_TYPE_OCTETS: + case PW_TYPE_IFID: + case PW_TYPE_IPADDR: + case PW_TYPE_IPV6ADDR: + case PW_TYPE_IPV6PREFIX: + case PW_TYPE_ABINARY: + case PW_TYPE_TLV: + memcpy(out, vp->vp_octets, len); + break; + case PW_TYPE_BYTE: + out[0] = vp->vp_integer & 0xff; + break; + + case PW_TYPE_SHORT: + out[0] = (vp->vp_integer >> 8) & 0xff; + out[1] = vp->vp_integer & 0xff; + break; + + case PW_TYPE_INTEGER: + lvalue = htonl(vp->vp_integer); + memcpy(out, &lvalue, sizeof(lvalue)); + break; + + case PW_TYPE_DATE: + lvalue = htonl(vp->vp_date); + memcpy(out, &lvalue, sizeof(lvalue)); + break; + + case PW_TYPE_SIGNED: + { + int32_t slvalue; + + slvalue = htonl(vp->vp_signed); + memcpy(out, &slvalue, sizeof(slvalue)); + break; + } + /* unknown type: ignore it */ + default: + fr_strerror_printf("ERROR: Unknown attribute type %d", + vp->type); + return -1; + } + + return len; +} /* * Calculate/check digest, and decode radius attributes. diff --git a/src/main/xlat.c b/src/main/xlat.c index 42c4fdffd61..dddc64cea81 100644 --- a/src/main/xlat.c +++ b/src/main/xlat.c @@ -542,8 +542,10 @@ static size_t xlat_hex(UNUSED void *instance, REQUEST *request, UNUSED RADIUS_ESCAPE_STRING func) { size_t i; - uint8_t *p; VALUE_PAIR *vp; + uint8_t buffer[MAX_STRING_LEN]; + ssize_t ret; + size_t len; while (isspace((int) *fmt)) fmt++; @@ -551,21 +553,23 @@ static size_t xlat_hex(UNUSED void *instance, REQUEST *request, *out = '\0'; return 0; } - + + ret = rad_vp2data(vp, buffer, sizeof(buffer)); + len = (size_t) ret; + /* * Don't truncate the data. */ - if (outlen < (vp->length * 2)) { + if ((ret < 0 ) || (outlen < (len * 2))) { *out = 0; return 0; } - p = &vp->vp_octets[0]; - for (i = 0; i < vp->length; i++) { - snprintf(out + 2*i, 3, "%02x", p[i]); + for (i = 0; i < len; i++) { + snprintf(out + 2*i, 3, "%02x", buffer[i]); } - return vp->length * 2; + return len * 2; } /** @@ -575,7 +579,10 @@ static size_t xlat_base64(UNUSED void *instance, REQUEST *request, const char *fmt, char *out, size_t outlen) { VALUE_PAIR *vp; - size_t len; + uint8_t buffer[MAX_STRING_LEN]; + ssize_t ret; + size_t len; + size_t enc; while (isspace((int) *fmt)) fmt++; @@ -584,19 +591,27 @@ static size_t xlat_base64(UNUSED void *instance, REQUEST *request, return 0; } - len = FR_BASE64_ENC_LENGTH(vp->length); + ret = rad_vp2data(vp, buffer, sizeof(buffer)); + if (ret < 0) { + *out = 0; + return 0; + } + + len = (size_t) ret; + + enc = FR_BASE64_ENC_LENGTH(len); /* * Don't truncate the data. */ - if (outlen < (len + 1)) { + if (outlen < (enc + 1)) { *out = 0; return 0; } - fr_base64_encode((char *) vp->vp_octets, vp->length, out, outlen); + fr_base64_encode(buffer, len, out, outlen); - return len; + return enc; } #ifdef HAVE_REGEX_H -- 2.47.3