From: Arran Cudbard-Bell Date: Thu, 20 May 2021 20:35:38 +0000 (+0200) Subject: Convert base64 code to work with dbuffs/sbuffs X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6a5826d3a0e8e6428c7ad19f3e0e1611cd7ef994;p=thirdparty%2Ffreeradius-server.git Convert base64 code to work with dbuffs/sbuffs --- diff --git a/src/lib/eap_aka_sim/id.c b/src/lib/eap_aka_sim/id.c index c40b95ec347..51bb2b6828d 100644 --- a/src/lib/eap_aka_sim/id.c +++ b/src/lib/eap_aka_sim/id.c @@ -514,19 +514,19 @@ int fr_aka_sim_id_3gpp_pseudonym_encrypt(char out[AKA_SIM_3GPP_PSEUDONYM_LEN + 1 /* * Consume tag (6 bits) + key_ind (4 bits) + encr[0] (8 bits) = 18 bits (or 3 bytes of b64) */ - *out_p++ = fr_base64_str[tag & 0x3f]; /* 6 bits tag */ - *out_p++ = fr_base64_str[((key_ind & 0x0f) << 2) | ((u_p[0] & 0xc0) >> 6)]; /* 4 bits key_ind + 2 high bits encr[0] */ - *out_p++ = fr_base64_str[u_p[0] & 0x3f]; /* 6 low bits of encr[0] */ + *out_p++ = fr_base64_alphabet_encode[tag & 0x3f]; /* 6 bits tag */ + *out_p++ = fr_base64_alphabet_encode[((key_ind & 0x0f) << 2) | ((u_p[0] & 0xc0) >> 6)]; /* 4 bits key_ind + 2 high bits encr[0] */ + *out_p++ = fr_base64_alphabet_encode[u_p[0] & 0x3f]; /* 6 low bits of encr[0] */ u_p++; /* * Consume 3 bytes of input for 4 bytes of b64 (5 iterations) */ while (u_p < u_end) { - *out_p++ = fr_base64_str[(u_p[0] & 0xfc) >> 2]; /* 6 high bits of p[0] */ - *out_p++ = fr_base64_str[((u_p[0] & 0x03) << 4) | ((u_p[1] & 0xf0) >> 4)]; /* 2 low bits of p[0] + 4 high bits of p[1] */ - *out_p++ = fr_base64_str[((u_p[1] & 0x0f) << 2) | ((u_p[2] & 0xc0) >> 6)]; /* 4 low bits of p[1] + 2 high bits of p[2] */ - *out_p++ = fr_base64_str[u_p[2] & 0x3f]; /* 6 low bits of p[2] */ + *out_p++ = fr_base64_alphabet_encode[(u_p[0] & 0xfc) >> 2]; /* 6 high bits of p[0] */ + *out_p++ = fr_base64_alphabet_encode[((u_p[0] & 0x03) << 4) | ((u_p[1] & 0xf0) >> 4)]; /* 2 low bits of p[0] + 4 high bits of p[1] */ + *out_p++ = fr_base64_alphabet_encode[((u_p[1] & 0x0f) << 2) | ((u_p[2] & 0xc0) >> 6)]; /* 4 low bits of p[1] + 2 high bits of p[2] */ + *out_p++ = fr_base64_alphabet_encode[u_p[2] & 0x3f]; /* 6 low bits of p[2] */ u_p += 3; } if ((out_p - out) != AKA_SIM_3GPP_PSEUDONYM_LEN) { diff --git a/src/lib/server/password.c b/src/lib/server/password.c index bf1bc466d1e..e3072772b3b 100644 --- a/src/lib/server/password.c +++ b/src/lib/server/password.c @@ -434,8 +434,8 @@ static ssize_t normify(normalise_t *action, uint8_t *buffer, size_t bufflen, if ((len * 3) >= ((min_len * 4))) { ssize_t decoded; - decoded = fr_base64_decode(buffer, bufflen, known_good, len); - if (decoded < 0) return 0; + decoded = fr_base64_decode(&FR_DBUFF_TMP(buffer, bufflen), &FR_SBUFF_IN(known_good, len), true, true); + if (decoded <= 0) return 0; if (decoded >= (ssize_t) min_len) { if (action) *action = NORMALISED_B64; return decoded; diff --git a/src/lib/server/tmpl_tokenize.c b/src/lib/server/tmpl_tokenize.c index 1391eab457d..a20f878167b 100644 --- a/src/lib/server/tmpl_tokenize.c +++ b/src/lib/server/tmpl_tokenize.c @@ -2241,7 +2241,7 @@ static ssize_t tmpl_afrom_ipv4_substr(TALLOC_CTX *ctx, tmpl_t **out, fr_sbuff_t /* * Check for char sequence * - * xxx.xxxx.xxx.xxx + * xxx.xxx.xxx.xxx */ if (!(fr_sbuff_out(NULL, &octet, &our_in) && fr_sbuff_next_if_char(&our_in, '.') && fr_sbuff_out(NULL, &octet, &our_in) && fr_sbuff_next_if_char(&our_in, '.') && diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index fba3ca6ed99..d821cd6f68f 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -1558,13 +1558,13 @@ static xlat_action_t xlat_func_base64_encode(TALLOC_CTX *ctx, fr_dcursor_t *out, return XLAT_ACTION_FAIL; } - elen = fr_base64_encode(buff, alen + 1, in->vb_octets, in->vb_length); + elen = fr_base64_encode(&FR_SBUFF_OUT(buff, talloc_array_length(buff)), + &FR_DBUFF_TMP(in->vb_octets, in->vb_length), true); if (elen < 0) { RPEDEBUG("Base64 encoding failed"); talloc_free(vb); return XLAT_ACTION_FAIL; } - fr_assert((size_t)elen <= alen); vb->tainted = in->tainted; fr_dcursor_append(out, vb); @@ -1593,23 +1593,26 @@ static xlat_action_t xlat_func_base64_decode(TALLOC_CTX *ctx, fr_dcursor_t *out, fr_value_box_list_t *args) { size_t alen; - ssize_t declen; + ssize_t declen = 0; uint8_t *decbuf; fr_value_box_t *vb; fr_value_box_t *in = fr_dlist_head(args); alen = FR_BASE64_DEC_LENGTH(in->vb_length); - MEM(vb = fr_value_box_alloc_null(ctx)); - MEM(fr_value_box_mem_alloc(vb, &decbuf, vb, NULL, alen, in->tainted) == 0); - declen = fr_base64_decode(decbuf, alen, in->vb_strvalue, in->vb_length); - if (declen < 0) { - REDEBUG("Base64 string invalid"); - talloc_free(vb); - return XLAT_ACTION_FAIL; + if (alen > 0) { + MEM(fr_value_box_mem_alloc(vb, &decbuf, vb, NULL, alen, in->tainted) == 0); + declen = fr_base64_decode(&FR_DBUFF_TMP(decbuf, alen), + &FR_SBUFF_IN(in->vb_strvalue, in->vb_length), true, true); + if (declen < 0) { + RPEDEBUG("Base64 string invalid"); + talloc_free(vb); + return XLAT_ACTION_FAIL; + } + + MEM(fr_value_box_mem_realloc(vb, NULL, vb, declen) == 0); } - MEM(fr_value_box_mem_realloc(vb, NULL, vb, declen) == 0); vb->tainted = in->tainted; fr_dcursor_append(out, vb); diff --git a/src/lib/util/base64.c b/src/lib/util/base64.c index 6cb0ee4f92a..ca04494bfb5 100644 --- a/src/lib/util/base64.c +++ b/src/lib/util/base64.c @@ -1,7 +1,4 @@ /* - * @copyright 1999, 2000, 2001, 2004, 2005, 2006 Free Software - * Foundation, Inc. - * * 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) @@ -22,17 +19,83 @@ * @see RFC 3548 . * * @file src/lib/util/base64.c - * @author Simon Josefsson. + * + * @copyright 2021 Arran Cudbard-Bell (a.cudbardb@freeradius.org) */ RCSID("$Id$") #include "base64.h" #include - +#include #define us(x) (uint8_t) x -char const fr_base64_str[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; +char const fr_base64_alphabet_encode[UINT8_MAX] = { + [0] = 'A', + [1] = 'B', + [2] = 'C', + [3] = 'D', + [4] = 'E', + [5] = 'F', + [6] = 'G', + [7] = 'H', + [8] = 'I', + [9] = 'J', + [10] = 'K', + [11] = 'L', + [12] = 'M', + [13] = 'N', + [14] = 'O', + [15] = 'P', + [16] = 'Q', + [17] = 'R', + [18] = 'S', + [19] = 'T', + [20] = 'U', + [21] = 'V', + [22] = 'W', + [23] = 'X', + [24] = 'Y', + [25] = 'Z', + [26] = 'a', + [27] = 'b', + [28] = 'c', + [29] = 'd', + [30] = 'e', + [31] = 'f', + [32] = 'g', + [33] = 'h', + [34] = 'i', + [35] = 'j', + [36] = 'k', + [37] = 'l', + [38] = 'm', + [39] = 'n', + [40] = 'o', + [41] = 'p', + [42] = 'q', + [43] = 'r', + [44] = 's', + [45] = 't', + [46] = 'u', + [47] = 'v', + [48] = 'w', + [49] = 'x', + [50] = 'y', + [51] = 'z', + [52] = '0', + [53] = '1', + [54] = '2', + [55] = '3', + [56] = '4', + [57] = '5', + [58] = '6', + [59] = '7', + [60] = '8', + [61] = '9', + [62] = '+', + [63] = '/' +}; uint8_t const fr_base64_alphabet_decode[UINT8_MAX] = { ['A'] = 0, @@ -98,138 +161,188 @@ uint8_t const fr_base64_alphabet_decode[UINT8_MAX] = { ['8'] = 60, ['9'] = 61, ['+'] = 62, - ['.'] = 62, ['/'] = 63 }; /** Base 64 encode binary data * - * Base64 encode IN array of size INLEN into OUT array of size OUTLEN. + * Base64 encode in bytes to base64, writing to out. * - * @param[out] out Where to write Base64 string. - * @param[in] outlen size of buffer including NULL byte. - * @param[in] in Data to encode. - * @param[in] inlen Length of data to encode. + * @param[out] out Where to write Base64 string. + * @param[in] in Data to encode. + * @param[in] add_padding Add padding bytes. + * @param[in] alphabet to use for encoding. * @return * - Amount of data we wrote to the buffer. - * - -1 if output buffer was too small. + * - <0 the number of bytes we would have needed in the ouput buffer. */ -size_t fr_base64_encode(char *out, size_t outlen, uint8_t const *in, size_t inlen) +ssize_t fr_base64_encode_nstd(fr_sbuff_t *out, fr_dbuff_t *in, + bool add_padding, char const alphabet[static UINT8_MAX]) { - char *p = out; - size_t need = FR_BASE64_ENC_LENGTH(inlen) + 1; + fr_sbuff_t our_out = FR_SBUFF_NO_ADVANCE(out); + fr_dbuff_t our_in = FR_DBUFF_NO_ADVANCE(in); - if (outlen < need) { - fr_strerror_printf("Output buffer too small, exected %zu bytes, got %zu bytes", need, outlen); - *out = '\0'; - return -1; - } + fr_strerror_const("Insufficient buffer space"); + + for (;;) { + uint8_t a, b, c; + + switch (fr_dbuff_extend_lowat(NULL, &our_in, 3)) { + /* + * Enough bytes for a 24bit quanta + */ + default: + a = *fr_dbuff_current(&our_in); + b = *(fr_dbuff_current(&our_in) + 1); + c = *(fr_dbuff_current(&our_in) + 2); + FR_SBUFF_IN_CHAR_RETURN(&our_out, + alphabet[(a >> 2) & 0x3f], + alphabet[((a << 4) + (b >> 4)) & 0x3f], + alphabet[((b << 2) + (c >> 6)) & 0x3f], + alphabet[c & 0x3f]); + fr_dbuff_advance(&our_in, 3); + continue; - while (inlen) { - *p++ = fr_base64_str[(in[0] >> 2) & 0x3f]; - *p++ = fr_base64_str[((in[0] << 4) + (--inlen ? in[1] >> 4 : 0)) & 0x3f]; - *p++ = (inlen ? fr_base64_str[((in[1] << 2) + (--inlen ? in[2] >> 6 : 0)) & 0x3f] : '='); - *p++ = inlen ? fr_base64_str[in[2] & 0x3f] : '='; + case 2: + a = *fr_dbuff_current(&our_in); + b = *(fr_dbuff_current(&our_in) + 1); + FR_SBUFF_IN_CHAR_RETURN(&our_out, + alphabet[(a >> 2) & 0x3f], + alphabet[((a << 4) + (b >> 4)) & 0x3f], + alphabet[(b << 2) & 0x3f]); + fr_dbuff_advance(&our_in, 2); /* Place at the end */ + if (add_padding) FR_SBUFF_IN_CHAR_RETURN(&our_out, '='); + break; - if (inlen) inlen--; - if (inlen) in += 3; + case 1: + a = *fr_dbuff_current(&our_in); + FR_SBUFF_IN_CHAR_RETURN(&our_out, + alphabet[(a >> 2) & 0x3f], + alphabet[(a << 4) & 0x3f]); + fr_dbuff_advance(&our_in, 1); /* Place at the end */ + if (add_padding) FR_SBUFF_IN_STRCPY_LITERAL_RETURN(&our_out, "=="); + break; + + case 0: + goto done; + } + done: + break; } - p[0] = '\0'; + fr_strerror_clear(); - return p - out; + fr_dbuff_set(in, &our_in); + return fr_sbuff_set(out, &our_out); } /* 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, -1 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 -1 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[out] out Where to write the decoded data. - * @param[in] outlen The length of the output buffer. - * @param[in] in Base64 string to decode. - * @param[in] inlen length of Base64 string. + * @param[out] out Where to write the decoded binary data. + * @param[in] in Base64 string to decode. + * @param[in] expect_padding Expect, and advanced past padding characters '=' at + * the end of the string. + * @param[in] no_trailing Error out if we find non-base64 characters + * at the end of the string. + * @param[in] alphabet to use for decoding. * @return * - <= 0 on failure. The offset where the decoding error occurred as a negative integer. * - Length of decoded data. */ -ssize_t fr_base64_decode_nstd(uint8_t *out, size_t outlen, char const *in, size_t inlen, uint8_t const alphabet[static UINT8_MAX]) +ssize_t fr_base64_decode_nstd(fr_dbuff_t *out, fr_sbuff_t *in, + bool expect_padding, bool no_trailing, uint8_t const alphabet[static UINT8_MAX]) { - uint8_t *out_p = out; - uint8_t *out_end = out + outlen; - char const *p = in, *q; - char const *end = p + inlen; + fr_sbuff_t our_in = FR_SBUFF_NO_ADVANCE(in); + fr_dbuff_t our_out = FR_DBUFF_NO_ADVANCE(out); + fr_sbuff_marker_t m_final; + uint8_t pad; /* * Process complete 24bit quanta */ - while ((end - p) >= 4) { - if (!fr_is_base64_nstd(p[0], alphabet) || !fr_is_base64_nstd(p[1], alphabet) || - !fr_is_base64_nstd(p[2], alphabet) || !fr_is_base64_nstd(p[3], alphabet)) break; + while (fr_sbuff_extend_lowat(NULL, &our_in, 4) >= 4) { + char *p = fr_sbuff_current(&our_in); - /* - * Check we have enough bytes to write out - * the 24bit quantum. - */ - if ((out_end - out_p) <= 3) { + if (!fr_is_base64_nstd(p[0], alphabet) || + !fr_is_base64_nstd(p[1], alphabet) || + !fr_is_base64_nstd(p[2], alphabet) || + !fr_is_base64_nstd(p[3], alphabet)) break; + + if (fr_dbuff_in_bytes(&our_out, + ((alphabet[us(p[0])] << 2) | (alphabet[us(p[1])] >> 4)), + ((alphabet[us(p[1])] << 4) & 0xf0) | (alphabet[us(p[2])] >> 2), + ((alphabet[us(p[2])] << 6) & 0xc0) | alphabet[us(p[3])]) != 3) { oob: - fr_strerror_printf("Output buffer too small, needed at least %zu bytes", outlen + 1); - return p - end; + fr_strerror_printf("Output buffer too small, needed at least %zu bytes", + fr_dbuff_used(&our_out) + 1); + return -fr_sbuff_used(&our_in); } - *out_p++ = ((alphabet[us(p[0])] << 2) | (alphabet[us(p[1])] >> 4)); - *out_p++ = ((alphabet[us(p[1])] << 4) & 0xf0) | (alphabet[us(p[2])] >> 2); - *out_p++ = ((alphabet[us(p[2])] << 6) & 0xc0) | alphabet[us(p[3])]; - - p += 4; /* 32bit input -> 24bit output */ + fr_sbuff_advance(&our_in, 4); } - q = p; + fr_sbuff_marker(&m_final, &our_in); /* * Find the first non-base64 char */ - while ((q < end) && fr_is_base64_nstd(*q, alphabet)) q++; + while (fr_sbuff_extend(&our_in) && fr_is_base64_nstd(*fr_sbuff_current(&our_in), alphabet)) { + fr_sbuff_advance(&our_in, 1); + } - switch (q - p) { + switch (fr_sbuff_behind(&m_final)) { case 0: /* Final quantum is 24 bits */ + pad = 0; break; case 2: /* Final quantum is 8 bits */ - if ((out_end - out_p) < 1) goto oob; - *out_p++ = ((alphabet[us(p[0])] << 2) | (alphabet[us(p[1])] >> 4)); - p += 2; + { + char *p = fr_sbuff_current(&m_final); + + if (fr_dbuff_in_bytes(&our_out, + (alphabet[us(p[0])] << 2) | (alphabet[us(p[1])] >> 4)) != 1) goto oob; + pad = 2; + } break; case 3: /* Final quantum is 16 bits */ - if ((out_end - out_p) < 2) goto oob; - *out_p++ = ((alphabet[us(p[0])] << 2) | (alphabet[us(p[1])] >> 4)); - *out_p++ = ((alphabet[us(p[1])] << 4) & 0xf0) | (alphabet[us(p[2])] >> 2); - p += 3; + { + char *p = fr_sbuff_current(&m_final); + + if (fr_dbuff_in_bytes(&our_out, + ((alphabet[us(p[0])] << 2) | (alphabet[us(p[1])] >> 4)), + ((alphabet[us(p[1])] << 4) & 0xf0) | (alphabet[us(p[2])] >> 2)) != 2) goto oob; + pad = 1; + } break; default: fr_strerror_const("Invalid base64 padding data"); - return p - end; + return -fr_sbuff_used(&our_in); } - while (p < end) { - if (*p != '=') { - fr_strerror_printf("Found non-padding char '%c' at end of base64 string", *p); - return p - end; + if (expect_padding) { + uint8_t i; + for (i = 0; i < pad; i++) { + if (!fr_sbuff_extend(&our_in)) { + fr_strerror_printf("Missing padding '=' at end of base64 string. " + "Expected %u padding char(s)", pad); + return -fr_sbuff_used(&our_in); + } + if (!fr_sbuff_next_if_char(&our_in, '=')) { + fr_strerror_printf("Found non-padding char '%c' at end of base64 string", + *fr_sbuff_current(&our_in)); + return -fr_sbuff_used(&our_in); + } } - p++; } - return out_p - out; + if (no_trailing && fr_sbuff_extend(&our_in)) { + fr_strerror_printf("Found trailing garbage '%c' at end of base64 string", + *fr_sbuff_current(&our_in)); + return -fr_sbuff_used(&our_in); + } + + fr_sbuff_set(in, &our_in); + return fr_dbuff_set(out, &our_out); } diff --git a/src/lib/util/base64.h b/src/lib/util/base64.h index 290e1be048d..0295f950018 100644 --- a/src/lib/util/base64.h +++ b/src/lib/util/base64.h @@ -30,6 +30,8 @@ extern "C" { #include #include +#include +#include #include #include @@ -41,14 +43,15 @@ extern "C" { #define FR_BASE64_ENC_LENGTH(_inlen) ((((_inlen) + 2) / 3) * 4) #define FR_BASE64_DEC_LENGTH(_inlen) ((3 * ((_inlen) / 4)) + 2) -extern char const fr_base64_str[]; +extern char const fr_base64_alphabet_encode[UINT8_MAX]; extern uint8_t const fr_base64_alphabet_decode[UINT8_MAX]; /** 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. + * @param[in] c char to check. + * @return * - true if c is a character from the Base64 alphabet. * - false if character is not in the Base64 alphabet. */ @@ -57,14 +60,23 @@ static inline bool fr_is_base64_nstd(char c, uint8_t const alphabet[static UINT8 return (c == 'A') || (alphabet[(uint8_t)c] > 0); } -#define fr_is_base64(_c) fr_is_base64_nstd(_c, fr_base64_alphabet_decode) - size_t fr_base64_encode(char * restrict out, size_t outlen, uint8_t const * restrict in, size_t inlen); +#define fr_is_base64(_c) fr_is_base64_nstd(_c, fr_base64_alphabet_decode) + + +ssize_t fr_base64_encode_nstd(fr_sbuff_t *out, fr_dbuff_t *in, + bool add_padding, char const alphabet[static UINT8_MAX]) + CC_HINT(nonnull); -#define fr_base64_decode(_out, _outlen, _in, _inlen) fr_base64_decode_nstd(_out, _outlen, _in, _inlen, fr_base64_alphabet_decode) -ssize_t fr_base64_decode_nstd(uint8_t * restrict out, size_t outlen, char const * restrict in, size_t inlen, uint8_t const alphabet[static UINT8_MAX]); +#define fr_base64_encode(_out, _in, _add_padding) \ + fr_base64_encode_nstd(_out, _in, _add_padding, fr_base64_alphabet_encode); +ssize_t fr_base64_decode_nstd(fr_dbuff_t *out, fr_sbuff_t *in, + bool expect_padding, bool no_trailing, uint8_t const alphabet[static UINT8_MAX]) + CC_HINT(nonnull); +#define fr_base64_decode(_out, _in, _expect_padding, _no_trailing) \ + fr_base64_decode_nstd(_out, _in, _expect_padding, _no_trailing, fr_base64_alphabet_decode) #ifdef __cplusplus } diff --git a/src/lib/util/sbuff.h b/src/lib/util/sbuff.h index 4d78fd81897..00117f7e8ad 100644 --- a/src/lib/util/sbuff.h +++ b/src/lib/util/sbuff.h @@ -1183,11 +1183,12 @@ size_t _fr_sbuff_move_sbuff_to_marker(fr_sbuff_marker_t *out, fr_sbuff_t *in, si #define FR_SBUFF_IN_CHAR_RETURN(_sbuff, ...) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, _sbuff, ((char []){ __VA_ARGS__ }), sizeof((char []){ __VA_ARGS__ })) ssize_t fr_sbuff_in_strcpy(fr_sbuff_t *sbuff, char const *str); -#define fr_sbuff_in_strcpy_literal(_sbuff, _str) fr_sbuff_in_bstrncpy(_sbuff, _str, sizeof(_str) - 1) #define FR_SBUFF_IN_STRCPY_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_strcpy, ##__VA_ARGS__) ssize_t fr_sbuff_in_bstrncpy(fr_sbuff_t *sbuff, char const *str, size_t len); #define FR_SBUFF_IN_BSTRNCPY_RETURN(...) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, ##__VA_ARGS__) + +#define fr_sbuff_in_strcpy_literal(_sbuff, _str) fr_sbuff_in_bstrncpy(_sbuff, _str, sizeof(_str) - 1) #define FR_SBUFF_IN_STRCPY_LITERAL_RETURN(_sbuff, _str) FR_SBUFF_RETURN(fr_sbuff_in_bstrncpy, _sbuff, _str, sizeof(_str) - 1) ssize_t fr_sbuff_in_bstrcpy_buffer(fr_sbuff_t *sbuff, char const *str); diff --git a/src/modules/rlm_pap/rlm_pap.c b/src/modules/rlm_pap/rlm_pap.c index 838cbca516a..22da5b554e5 100644 --- a/src/modules/rlm_pap/rlm_pap.c +++ b/src/modules/rlm_pap/rlm_pap.c @@ -535,8 +535,9 @@ static inline CC_HINT(nonnull) unlang_action_t pap_auth_pbkdf2_parse(rlm_rcode_t */ } else { fr_strerror_clear(); - slen = fr_base64_decode((uint8_t *)&iterations, sizeof(iterations), (char const *)p, q - p); - if (slen < 0) { + slen = fr_base64_decode(&FR_DBUFF_TMP((uint8_t *)&iterations, sizeof(iterations)), + &FR_SBUFF_IN((char const *)p, (char const *)q), false, false); + if (slen <= 0) { RPEDEBUG("Failed decoding PBKDF2-Password iterations component (%.*s)", (int)(q - p), p); goto finish; } @@ -560,8 +561,9 @@ static inline CC_HINT(nonnull) unlang_action_t pap_auth_pbkdf2_parse(rlm_rcode_t } MEM(salt = talloc_array(request, uint8_t, FR_BASE64_DEC_LENGTH(q - p))); - slen = fr_base64_decode(salt, talloc_array_length(salt), (char const *) p, q - p); - if (slen < 0) { + slen = fr_base64_decode(&FR_DBUFF_TMP(salt, talloc_array_length(salt)), + &FR_SBUFF_IN((char const *) p, (char const *)q), false, false); + if (slen <= 0) { RPEDEBUG("Failed decoding PBKDF2-Password salt component"); goto finish; } @@ -574,8 +576,9 @@ static inline CC_HINT(nonnull) unlang_action_t pap_auth_pbkdf2_parse(rlm_rcode_t goto finish; } - slen = fr_base64_decode(hash, sizeof(hash), (char const *)p, end - p); - if (slen < 0) { + slen = fr_base64_decode(&FR_DBUFF_TMP(hash, sizeof(hash)), + &FR_SBUFF_IN((char const *)p, (char const *)end), false, false); + if (slen <= 0) { RPEDEBUG("Failed decoding PBKDF2-Password hash component"); goto finish; } diff --git a/src/tests/keywords/base64 b/src/tests/keywords/base64 index 43c63d42c4f..e2a7e36bc3f 100644 --- a/src/tests/keywords/base64 +++ b/src/tests/keywords/base64 @@ -107,4 +107,20 @@ if (&Tmp-Octets-1 != 0x008000000000000000000000000039383739) { test_fail } +# Regression tests +update request { + &Tmp-Octets-0 := %{base64decode:5RNqNl8iYLbkCc7JhR8as4TtDDCX6otuuWtcja8rITUyx9zrnHSe9tTHGmKK} +} + +if (&Tmp-Octets-0 != 0xe5136a365f2260b6e409cec9851f1ab384ed0c3097ea8b6eb96b5c8daf2b213532c7dceb9c749ef6d4c71a628a) { + test_fail +} + +update request { + &Tmp-Octets-0 := "%{base64decode:eHfXPKZ+2iv9cnMV1MOmE/moYYA1Uk5xTmw4aVlMYmtDYzdKaFI4YXM0VHRERENYNm90dXVXdGNqYThySVRVeXg5enJuSFNlOXRUSEdtS0s=}" +} + +if (&Tmp-Octets-0 != 0x7877d73ca67eda2bfd727315d4c3a613f9a8618035524e714e6c3869594c626b4363374a685238617334547444444358366f7475755774636a6138724954557978397a726e48536539745448476d4b4b) { + test_fail +} success