From: Arran Cudbard-Bell Date: Fri, 22 Feb 2013 01:27:20 +0000 (-0500) Subject: Reformat base64 code, use library base64 functions in rlm_pap X-Git-Tag: release_3_0_0_beta1~959 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=5e4acf077c3fc3ba1eca4201b91f3344fa110136;p=thirdparty%2Ffreeradius-server.git Reformat base64 code, use library base64 functions in rlm_pap --- diff --git a/src/include/base64.h b/src/include/base64.h index 6dad9de9bb1..01f27b70c20 100644 --- a/src/include/base64.h +++ b/src/include/base64.h @@ -1,45 +1,45 @@ -/* base64.h -- Encode binary data using printable characters. - Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. - Written by Simon Josefsson. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - +/* + * Copyright (C) 2004, 2005, 2006 Free Software Foundation, Inc. + * Written by Simon Josefsson. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ #ifndef _FR_BASE64_H -# define _FR_BASE64_H +#define _FR_BASE64_H #include RCSIDH(base64_h, "$Id$") -# include +#include +#include /* This uses that the expression (n+(k-1))/k means the smallest integer >= n/k, i.e., the ceiling of n/k. */ -# define FR_BASE64_ENC_LENGTH(inlen) ((((inlen) + 2) / 3) * 4) -# define FR_BASE64_DEC_LENGTH(inlen) ((3 * (inlen / 4)) + 2) - -extern int fr_isbase64 (char ch); +#define FR_BASE64_ENC_LENGTH(inlen) ((((inlen) + 2) / 3) * 4) +#define FR_BASE64_DEC_LENGTH(inlen) ((3 * (inlen / 4)) + 2) -extern void fr_base64_encode (const uint8_t *in, size_t inlen, - char *out, size_t outlen); +int fr_isbase64(char c); -extern size_t fr_base64_encode_alloc (const uint8_t *in, size_t inlen, char **out); +size_t fr_base64_encode(const uint8_t *in, size_t inlen, char *out, + size_t outlen); + +ssize_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); +ssize_t fr_base64_decode(const char *in, size_t inlen, uint8_t *out, + size_t outlen); -extern int fr_base64_decode_alloc (const char *in, size_t inlen, - char **out, size_t *outlen); +ssize_t fr_base64_decode_alloc(const char *in, size_t inlen, uint8_t **out); -#endif /* BASE64_H */ +#endif /* _FR_BASE64_H */ diff --git a/src/lib/base64.c b/src/lib/base64.c index ee65088429b..4b71eab2c88 100644 --- a/src/lib/base64.c +++ b/src/lib/base64.c @@ -1,44 +1,26 @@ -/* base64.c -- Encode binary data using printable characters. - Copyright (C) 1999, 2000, 2001, 2004, 2005, 2006 Free Software - Foundation, Inc. - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 2, or (at your option) - any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program; if not, write to the Free Software Foundation, - Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ - -/* Written by Simon Josefsson. Partially adapted from GNU MailUtils - * (mailbox/filter_trans.c, as of 2004-11-28). Improved by review - * from Paul Eggert, Bruno Haible, and Stepan Kasal. +/* + * Copyright (C) 1999, 2000, 2001, 2004, 2005, 2006 Free Software + * Foundation, Inc. * - * See also RFC 3548 . + * This program is left software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. * - * Be careful with error checking. Here is how you would typically - * use these functions: - * - * bool ok = fr_base64_decode_alloc (in, inlen, &out, &outlen); - * if (!ok) - * FAIL: input was not valid base64 - * if (out == NULL) - * FAIL: memory allocation error - * OK: data in OUT/OUTLEN - * - * size_t outlen = fr_base64_encode_alloc (in, inlen, &out); - * if (out == NULL && outlen == 0 && inlen != 0) - * FAIL: input too long - * if (out == NULL) - * FAIL: memory allocation error - * OK: data in OUT/OUTLEN. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +/** + * @brief Encode/decode binary data using printable characters. + * @author Simon Josefsson. + * @see RFC 3548 . */ #include RCSID("$Id$") @@ -46,110 +28,111 @@ RCSID("$Id$") #include #include -/* Get malloc. */ -#include - /* Get UCHAR_MAX. */ +#include #include -/* C89 compliant way to cast 'char' to 'unsigned char'. */ -static inline unsigned char -to_uchar (char ch) -{ - return ch; -} +#define us(x) (uint8_t) x -/* Base64 encode IN array of size INLEN into OUT array of size OUTLEN. - 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 uint8_t *in, size_t inlen, - char *out, size_t outlen) +/** Base 64 encode binary data + * + * Base64 encode IN array of size INLEN into OUT array of size OUTLEN. + * + * @param[in] in Data to encode. + * @param[in] inlen Length of data to encode. + * @param[out] out Where to write Base64 string. + * @param[in] outlen size of buffer including NULL byte. + * @return The amount of data we wrote to the buffer or -1 if output buffer + * was too small. + */ +size_t fr_base64_encode(const uint8_t *in, size_t inlen, char *out, + size_t outlen) { - static const char b64str[64] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; + static const char b64str[64] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklm" + "nopqrstuvwxyz0123456789+/"; - while (inlen && outlen) - { - *out++ = b64str[(in[0] >> 2) & 0x3f]; - if (!--outlen) - break; - *out++ = b64str[((in[0] << 4) - + (--inlen ? in[1] >> 4 : 0)) - & 0x3f]; - if (!--outlen) - break; - *out++ = - (inlen - ? b64str[((in[1] << 2) - + (--inlen ? in[2] >> 6 : 0)) - & 0x3f] - : '='); - if (!--outlen) - break; - *out++ = inlen ? b64str[in[2] & 0x3f] : '='; - if (!--outlen) - break; - if (inlen) - inlen--; - if (inlen) - in += 3; - } + char *p = out; + if (outlen < (FR_BASE64_ENC_LENGTH(inlen) + 1)) { + *out = '\0'; + return -1; + } + + while (inlen) { + *p++ = b64str[(in[0] >> 2) & 0x3f]; + + *p++ = b64str[((in[0] << 4) + + (--inlen ? in[1] >> 4 : 0)) & 0x3f]; + + *p++ = (inlen ? b64str[((in[1] << 2) + + (--inlen ? in[2] >> 6 : 0)) & 0x3f] : '='); + + *p++ = inlen ? b64str[in[2] & 0x3f] : '='; + + if (inlen) inlen--; + if (inlen) in += 3; + } - if (outlen) - *out = '\0'; + p[0] = '\0'; + + return p - out; } -/* Allocate a buffer and store zero terminated base64 encoded data - from array IN of size INLEN, returning FR_BASE64_ENC_LENGTH(INLEN), i.e., - the length of the encoded data, excluding the terminating zero. On - return, the OUT variable will hold a pointer to newly allocated - memory that must be deallocated by the caller. If output string - length would overflow, 0 is returned and OUT is set to NULL. If - memory allocation failed, OUT is set to NULL, and the return value - indicates length of the requested memory block, i.e., - FR_BASE64_ENC_LENGTH(inlen) + 1. */ -size_t -fr_base64_encode_alloc (const uint8_t *in, size_t inlen, char **out) +/** Allocate a buffer and store zero terminated base64 encoded data + * + * Allocate a buffer and store zero terminated base64 encoded data from array + * IN of size INLEN, returning FR_BASE64_ENC_LENGTH(INLEN), i.e., + * the length of the encoded data, excluding the terminating zero. + * + * On return, the OUT variable will hold a pointer to newly allocated memory + * that must be deallocated by the caller. + * + * If output string length would overflow, 0 is returned and OUT is set to NULL. + * + * @param[in] in Binary data in. + * @param[in] inlen Length of binary data. + * @param[out] out Which to write the pointer to the newly allocated buffer. + * @return The length of the string in the output buffer or -1 on error. + */ +ssize_t fr_base64_encode_alloc(const uint8_t *in, size_t inlen, char **out) { - size_t outlen = 1 + FR_BASE64_ENC_LENGTH (inlen); - - /* Check for overflow in outlen computation. - * - * If there is no overflow, outlen >= inlen. - * - * If the operation (inlen + 2) overflows then it yields at most +1, so - * outlen is 0. - * - * If the multiplication overflows, we lose at least half of the - * correct value, so the result is < ((inlen + 2) / 3) * 2, which is - * less than (inlen + 2) * 0.66667, which is less than inlen as soon as - * (inlen > 4). - */ - if (inlen > outlen) - { - *out = NULL; - return 0; - } - - *out = malloc (outlen); - if (!*out) - return outlen; - - fr_base64_encode (in, inlen, *out, outlen); + size_t outlen = FR_BASE64_ENC_LENGTH(inlen) + 1; + + /* Check for overflow in outlen computation. + * + * If there is no overflow, outlen >= inlen. + * + * If the operation (inlen + 2) overflows then it yields at most +1, so + * outlen is 0. + * + * If the multiplication overflows, we lose at least half of the + * correct value, so the result is < ((inlen + 2) / 3) * 2, which is + * less than (inlen + 2) * 0.66667, which is less than inlen as soon as + * (inlen > 4). + */ + if (inlen > outlen) { + *out = '\0'; + return -1; + } - return outlen - 1; + *out = talloc_array(NULL, char, outlen); + if (!*out) { + return -1; + } + + return fr_base64_encode(in, inlen, *out, outlen); } -/* With this approach this file works independent of the charset used - (think EBCDIC). However, it does assume that the characters in the - Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX - 1003.1-2001 require that char and unsigned char are 8-bit - quantities, though, taking care of that problem. But this may be a - potential problem on non-POSIX C99 platforms. - - IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_" - as the formal parameter rather than "x". */ +/* + * With this approach this file works independent of the charset used + * (think EBCDIC). However, it does assume that the characters in the + * Base64 alphabet (A-Za-z0-9+/) are encoded in 0..255. POSIX + * 1003.1-2001 require that char and unsigned char are 8-bit + * quantities, though, taking care of that problem. But this may be a + * potential problem on non-POSIX C99 platforms. + * + * IBM C V6 for AIX mishandles "#define B64(x) ...'x'...", so use "_" + * as the formal parameter rather than "x". + */ #define B64(_) \ ((_) == 'A' ? 0 \ : (_) == 'B' ? 1 \ @@ -290,132 +273,136 @@ static const signed char b64[0x100] = { # define uchar_in_range(c) ((c) <= 255) #endif -/* Return TRUE if CH is a character from the Base64 alphabet, and - FALSE otherwise. Note that '=' is padding and not considered to be - part of the alphabet. */ -int fr_isbase64 (char ch) +/** Check if char is in Base64 alphabet + * + * Note that '=' is padding and not considered to be part of the alphabet. + * + * @param c char to check. + * @return TRUE if CH is a character from the Base64 alphabet, and FALSE + * otherwise. + */ +int fr_isbase64(char c) { - return uchar_in_range (to_uchar (ch)) && 0 <= b64[to_uchar (ch)]; + return uchar_in_range(us(c)) && 0 <= b64[us(c)]; } -/* Decode base64 encoded input array IN of length INLEN to output - array OUT that can hold *OUTLEN bytes. Return TRUE if decoding was - successful, i.e. if the input was valid base64 data, FALSE - otherwise. If *OUTLEN is too small, as many bytes as possible will - be written to OUT. On return, *OUTLEN holds the length of decoded - bytes in OUT. Note that as soon as any non-alphabet characters are - encountered, decoding is stopped and FALSE is returned. This means - that, when applicable, you must remove any line terminators that is - part of the data stream before calling this function. */ -int fr_base64_decode (const char *in, size_t inlen, - char *out, size_t *outlen) +/* Decode base64 encoded input array. + * + * Decode base64 encoded input array IN of length INLEN to output array OUT that + * can hold *OUTLEN bytes. Return TRUE if decoding was successful, i.e. + * if the input was valid base64 data, FALSE otherwise. + * + * If *OUTLEN is too small, as many bytes as possible will be written to OUT. + * On return, *OUTLEN holds the length of decoded bytes in OUT. + * + * Note that as soon as any non-alphabet characters are encountered, + * decoding is stopped and FALSE is returned. + * + * This means that, when applicable, you must remove any line terminators + * that is part of the data stream before calling this function. + * + * @param[in] in Base64 string to decode. + * @param[in] inlen length of Base64 string. + * @param[out] out Where to write the decoded data. + * @param[in] outlen The length of the output buffer. + * @return -1 on error, else the length of decoded data. + */ +ssize_t fr_base64_decode(const char *in, size_t inlen, uint8_t *out, + size_t outlen) { - size_t outleft = *outlen; - - while (inlen >= 2) - { - if (!fr_isbase64 (in[0]) || !fr_isbase64 (in[1])) - break; - - if (outleft) - { - *out++ = ((b64[to_uchar (in[0])] << 2) - | (b64[to_uchar (in[1])] >> 4)); - outleft--; + uint8_t *p = out; + + if (outlen < FR_BASE64_DEC_LENGTH(inlen)) { + return -1; } - if (inlen == 2) - break; - - if (in[2] == '=') - { - if (inlen != 4) - break; - - if (in[3] != '=') - break; - - } - else - { - if (!fr_isbase64 (in[2])) - break; - - if (outleft) - { - *out++ = (((b64[to_uchar (in[1])] << 4) & 0xf0) - | (b64[to_uchar (in[2])] >> 2)); - outleft--; - } - - if (inlen == 3) - break; - - if (in[3] == '=') - { - if (inlen != 4) - break; - } - else - { - if (!fr_isbase64 (in[3])) - break; - - if (outleft) - { - *out++ = (((b64[to_uchar (in[2])] << 6) & 0xc0) - | b64[to_uchar (in[3])]); - outleft--; + while (inlen >= 2) { + if (!fr_isbase64(in[0]) || !fr_isbase64(in[1])) { + break; } - } - } - - in += 4; - inlen -= 4; - } - - *outlen -= outleft; - if (inlen != 0) - return FALSE; + *p++ = ((b64[us(in[0])] << 2) | + (b64[us(in[1])] >> 4)); + + if (inlen == 2) break; + + if (in[2] == '=') { + if ((inlen != 4) || (in[3] != '=')) break; + } else { + if (!fr_isbase64(in[2])) break; + + *p++ = ((b64[us(in[1])] << 4) & 0xf0) | + (b64[us(in[2])] >> 2); + + if (inlen == 3) break; + + if (in[3] == '=') { + if (inlen != 4) break; + } else { + if (!fr_isbase64(in[3])) break; + + *p++ = ((b64[us(in[2])] << 6) & 0xc0) | + b64[us(in[3])]; + } + } + + in += 4; + inlen -= 4; + } - return TRUE; + if (inlen != 0) { + return -1; + } + + return p - out; } -/* Allocate an output buffer in *OUT, and decode the base64 encoded - data stored in IN of size INLEN to the *OUT buffer. On return, the - size of the decoded data is stored in *OUTLEN. OUTLEN may be NULL, - if the caller is not interested in the decoded length. *OUT may be - NULL to indicate an out of memory error, in which case *OUTLEN - contains the size of the memory block needed. The function returns - TRUE on successful decoding and memory allocation errors. (Use the - *OUT and *OUTLEN parameters to differentiate between successful - decoding and memory error.) The function returns FALSE if the - input was invalid, in which case *OUT is NULL and *OUTLEN is - undefined. */ -int fr_base64_decode_alloc (const char *in, size_t inlen, char **out, - size_t *outlen) +/** Allocate a buffer and store decoded data. + * + * Allocate an output buffer in *OUT, and decode the base64 encoded data stored + * in IN of size INLEN to the *OUT buffer. + * + * On return, the size of the decoded data is stored in *OUTLEN. + * OUTLEN may be NULL, if the caller is not interested in the decoded length. + * *OUT may be NULL to indicate an out of memory error, in which case *OUTLEN + * contains the size of the memory block needed. + * + * The function returns TRUE on successful decoding and memory allocation + * errors. (Use the *OUT and *OUTLEN parameters to differentiate between + * successful decoding and memory error.) + * + * The function returns FALSE if the input was invalid, in which case *OUT is + * NULL and *OUTLEN is undefined. + * + * @param[in] in Base64 string to decode. + * @param[in] inlen length of Base64 string. + * @param[out] out Where to write the pointer to the decoded data. + * @return -1 on error, else the length of data written to the buffer. + */ +ssize_t fr_base64_decode_alloc(const char *in, size_t inlen, uint8_t **out) { - /* This may allocate a few bytes too much, depending on input, - but it's not worth the extra CPU time to compute the exact amount. - The exact amount is 3 * inlen / 4, minus 1 if the input ends - with "=" and minus another 1 if the input ends with "==". - Dividing before multiplying avoids the possibility of overflow. */ - size_t needlen = FR_BASE64_DEC_LENGTH(inlen); - - *out = malloc (needlen); - if (!*out) - return TRUE; - - if (!fr_base64_decode (in, inlen, *out, &needlen)) - { - free (*out); - *out = NULL; - return FALSE; - } - - if (outlen) - *outlen = needlen; + ssize_t ret; + /* + * This may allocate a few bytes too much, depending on input, + * but it's not worth the extra CPU time to compute the exact amount. + * The exact amount is 3 * inlen / 4, minus 1 if the input ends + * with "=" and minus another 1 if the input ends with "==". + * Dividing before multiplying avoids the possibility of overflow. + */ + size_t needlen = FR_BASE64_DEC_LENGTH(inlen); + + *out = talloc_array(NULL, uint8_t, needlen); + if (!*out) { + return -1; + } - return TRUE; + ret = fr_base64_decode(in, inlen, *out, needlen); + if (ret < 0) { + talloc_free(*out); + *out = '\0'; + + return -1; + } + + return ret; } diff --git a/src/main/xlat.c b/src/main/xlat.c index ee79b8f89a5..1f487d114aa 100644 --- a/src/main/xlat.c +++ b/src/main/xlat.c @@ -565,8 +565,6 @@ static size_t xlat_base64(UNUSED void *instance, REQUEST *request, VALUE_PAIR *vp; uint8_t buffer[MAX_STRING_LEN]; ssize_t ret; - size_t len; - size_t enc; while (isspace((int) *fmt)) fmt++; @@ -580,22 +578,8 @@ static size_t xlat_base64(UNUSED void *instance, REQUEST *request, *out = 0; return 0; } - - len = (size_t) ret; - - enc = FR_BASE64_ENC_LENGTH(len); - - /* - * Don't truncate the data. - */ - if (outlen < (enc + 1)) { - *out = 0; - return 0; - } - - fr_base64_encode(buffer, len, out, outlen); - return enc; + return fr_base64_encode(buffer, (size_t) ret, out, outlen); } /** Prints the current module processing the request diff --git a/src/modules/rlm_expr/rlm_expr.c b/src/modules/rlm_expr/rlm_expr.c index 6108c29defe..801a0effe42 100644 --- a/src/modules/rlm_expr/rlm_expr.c +++ b/src/modules/rlm_expr/rlm_expr.c @@ -640,9 +640,7 @@ static size_t base64_xlat(UNUSED void *instance, REQUEST *request, return 0; } - fr_base64_encode((uint8_t *) buffer, len, out, outlen); - - return strlen(out); + return fr_base64_encode((uint8_t *) buffer, len, out, outlen); } /** @@ -653,12 +651,10 @@ static size_t base64_xlat(UNUSED void *instance, REQUEST *request, static size_t base64_to_hex_xlat(UNUSED void *instance, REQUEST *request, const char *fmt, char *out, size_t outlen) { - char *p; - char buffer[1024]; - char decbuf[1024]; + uint8_t decbuf[1024], *p; - size_t declen = sizeof(decbuf); + ssize_t declen; size_t freespace = outlen; size_t len; @@ -670,7 +666,8 @@ static size_t base64_to_hex_xlat(UNUSED void *instance, REQUEST *request, return 0; } - if (!fr_base64_decode(buffer, len, decbuf, &declen)) { + declen = fr_base64_decode(buffer, len, decbuf, sizeof(decbuf)); + if (declen < 0) { radlog(L_ERR, "rlm_expr: base64 string invalid"); *out = '\0'; return 0; diff --git a/src/modules/rlm_pap/rlm_pap.c b/src/modules/rlm_pap/rlm_pap.c index bfe3671843c..5029f0ebf61 100644 --- a/src/modules/rlm_pap/rlm_pap.c +++ b/src/modules/rlm_pap/rlm_pap.c @@ -27,6 +27,7 @@ RCSID("$Id$") #include #include +#include #include @@ -119,76 +120,12 @@ static int pap_instantiate(CONF_SECTION *conf, void **instance) return 0; } - -/* - * Decode one base64 chunk - */ -static int decode_it(const char *src, uint8_t *dst) -{ - int i; - unsigned int x = 0; - - for(i = 0; i < 4; i++) { - if (src[i] >= 'A' && src[i] <= 'Z') - x = (x << 6) + (unsigned int)(src[i] - 'A' + 0); - else if (src[i] >= 'a' && src[i] <= 'z') - x = (x << 6) + (unsigned int)(src[i] - 'a' + 26); - else if(src[i] >= '0' && src[i] <= '9') - x = (x << 6) + (unsigned int)(src[i] - '0' + 52); - else if(src[i] == '+') - x = (x << 6) + 62; - else if (src[i] == '/') - x = (x << 6) + 63; - else if (src[i] == '=') - x = (x << 6); - else return 0; - } - - dst[2] = (unsigned char)(x & 255); x >>= 8; - dst[1] = (unsigned char)(x & 255); x >>= 8; - dst[0] = (unsigned char)(x & 255); - - return 1; -} - - -/* - * Base64 decoding. - */ -static int base64_decode (const char *src, uint8_t *dst) -{ - int length, equals; - int i, num; - uint8_t last[3]; - - length = equals = 0; - while (src[length] && src[length] != '=') length++; - - while (src[length + equals] == '=') equals++; - - num = (length + equals) / 4; - - for (i = 0; i < num - 1; i++) { - if (!decode_it(src, dst)) return 0; - src += 4; - dst += 3; - } - - decode_it(src, last); - for (i = 0; i < (3 - equals); i++) { - dst[i] = last[i]; - } - - return (num * 3) - equals; -} - - /* * Hex or base64 or bin auto-discovery. */ static void normify(REQUEST *request, VALUE_PAIR *vp, size_t min_length) { - size_t decoded; + uint8_t buffer[64]; if (min_length >= sizeof(buffer)) return; /* paranoia */ @@ -197,7 +134,9 @@ static void normify(REQUEST *request, VALUE_PAIR *vp, size_t min_length) * Hex encoding. */ if (vp->length >= (2 * min_length)) { - decoded = fr_hex2bin(vp->vp_strvalue, buffer, vp->length >> 1); + size_t decoded; + decoded = fr_hex2bin(vp->vp_strvalue, buffer, + vp->length >> 1); if (decoded == (vp->length >> 1)) { RDEBUG2("Normalizing %s from hex encoding", vp->da->name); memcpy(vp->vp_octets, buffer, decoded); @@ -211,8 +150,11 @@ static void normify(REQUEST *request, VALUE_PAIR *vp, size_t min_length) * and we want to avoid division... */ if ((vp->length * 3) >= ((min_length * 4))) { - decoded = base64_decode(vp->vp_strvalue, buffer); - if (decoded >= min_length) { + ssize_t decoded; + decoded = fr_base64_decode(vp->vp_strvalue, vp->length, buffer, + sizeof(buffer)); + if (decoded < 0) return; + if (decoded >= (ssize_t) min_length) { RDEBUG2("Normalizing %s from base64 encoding", vp->da->name); memcpy(vp->vp_octets, buffer, decoded); vp->length = decoded; @@ -264,7 +206,7 @@ static rlm_rcode_t pap_authorize(void *instance, REQUEST *request) q = vp->vp_strvalue; p = strchr(q + 1, '}'); if (!p) { - int decoded; + ssize_t decoded; /* * Password already exists: use @@ -281,9 +223,12 @@ static rlm_rcode_t pap_authorize(void *instance, REQUEST *request) * and re-write the attribute to * have the decoded value. */ - decoded = base64_decode(vp->vp_strvalue, binbuf); + decoded = fr_base64_decode(vp->vp_strvalue, + vp->length, + binbuf, + sizeof(binbuf)); if ((decoded > 0) && (binbuf[0] == '{') && - (memchr(binbuf, '}', decoded) != NULL)) { + memchr(binbuf, '}', decoded)) { memcpy(vp->vp_octets, binbuf, decoded); vp->length = decoded; goto redo;