From: Arran Cudbard-Bell Date: Tue, 28 Jul 2020 18:23:03 +0000 (-0400) Subject: hex: Add explicit error checks X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=c8f9ab2fff4e2e32e7abdec41b712fdf3a751417;p=thirdparty%2Ffreeradius-server.git hex: Add explicit error checks --- diff --git a/src/lib/ldap/util.c b/src/lib/ldap/util.c index f65ecb74fbf..b0974e1139b 100644 --- a/src/lib/ldap/util.c +++ b/src/lib/ldap/util.c @@ -216,7 +216,7 @@ bool fr_ldap_util_is_dn(char const *in, size_t inlen) /* * Hex encoding, consume three chars */ - if (fr_hex2bin(&FR_DBUFF_TMP((uint8_t *) &c, 1), &FR_SBUFF_IN(p + 1, 2)) == 1) { + if (fr_hex2bin(NULL, &FR_DBUFF_TMP((uint8_t *) &c, 1), &FR_SBUFF_IN(p + 1, 2), false) == 1) { inlen -= 2; p += 2; continue; @@ -417,7 +417,7 @@ size_t fr_ldap_util_normalise_dn(char *out, char const *in) * special encoding, get rewritten to the * special encoding. */ - if (fr_hex2bin(&FR_DBUFF_TMP((uint8_t *) &c, 1), &FR_SBUFF_IN(p + 1, 2)) == 1) { + if (fr_hex2bin(NULL, &FR_DBUFF_TMP((uint8_t *) &c, 1), &FR_SBUFF_IN(p + 1, 2), false) == 1) { switch (c) { case ' ': case '#': diff --git a/src/lib/server/client.c b/src/lib/server/client.c index 6ab9855e4fb..9f2fd09c25c 100644 --- a/src/lib/server/client.c +++ b/src/lib/server/client.c @@ -741,7 +741,9 @@ RADCLIENT *client_afrom_cs(TALLOC_CTX *ctx, CONF_SECTION *cs, CONF_SECTION *serv hex_len = talloc_array_length(value) - 3; bin_len = (hex_len / 2) + 1; MEM(bin = talloc_array(c, uint8_t, bin_len)); - converted = fr_hex2bin(&FR_DBUFF_TMP(bin, bin_len), &FR_SBUFF_IN(value + 2, hex_len)); + converted = fr_hex2bin(NULL, + &FR_DBUFF_TMP(bin, bin_len), + &FR_SBUFF_IN(value + 2, hex_len), false); if (converted < (bin_len - 1)) { cf_log_err(cs, "Invalide hex string in shared secret"); goto error; diff --git a/src/lib/server/map.c b/src/lib/server/map.c index 9962633dbd9..e0517eb5f27 100644 --- a/src/lib/server/map.c +++ b/src/lib/server/map.c @@ -113,7 +113,7 @@ bool map_cast_from_hex(vp_map_t *map, fr_token_t rhs_type, char const *rhs) ptr = talloc_array(map, uint8_t, len >> 1); if (!ptr) return false; - fr_hex2bin(&FR_DBUFF_TMP(ptr, len >> 1), &FR_SBUFF_IN(rhs + 2, len)); + fr_hex2bin(NULL, &FR_DBUFF_TMP(ptr, len >> 1), &FR_SBUFF_IN(rhs + 2, len), false); /* * Convert to da->type (if possible); diff --git a/src/lib/server/password.c b/src/lib/server/password.c index 22f1284c7e1..c01b69b848d 100644 --- a/src/lib/server/password.c +++ b/src/lib/server/password.c @@ -418,7 +418,7 @@ static ssize_t normify(normalise_t *action, uint8_t *buffer, size_t bufflen, if (!(len & 0x01) && len >= (2 * min_len)) { size_t decoded; - decoded = fr_hex2bin(&FR_DBUFF_TMP(buffer, bufflen), &FR_SBUFF_IN(known_good, len)); + decoded = fr_hex2bin(NULL, &FR_DBUFF_TMP(buffer, bufflen), &FR_SBUFF_IN(known_good, len), false); if (decoded == (len >> 1)) { if (action) *action = NORMALISED_HEX; return decoded; diff --git a/src/lib/server/tmpl.c b/src/lib/server/tmpl.c index bb8acecb029..b9a991365bf 100644 --- a/src/lib/server/tmpl.c +++ b/src/lib/server/tmpl.c @@ -1733,7 +1733,7 @@ ssize_t tmpl_afrom_str(TALLOC_CTX *ctx, vp_tmpl_t **out, vpt = tmpl_alloc(ctx, TMPL_TYPE_DATA, in, inlen, type); (void)fr_value_box_mem_alloc(vpt, &bin, &vpt->data.literal, NULL, binlen, false); - len = fr_hex2bin(&FR_DBUFF_TMP(bin, binlen), &FR_SBUFF_IN(in + 2, inlen - 2)); + len = fr_hex2bin(NULL, &FR_DBUFF_TMP(bin, binlen), &FR_SBUFF_IN(in + 2, inlen - 2), false); if (len != binlen) { fr_strerror_printf("Hex string contains non-hex char"); talloc_free(vpt); diff --git a/src/lib/server/util.c b/src/lib/server/util.c index 0e664be4302..8e9f12b76bc 100644 --- a/src/lib/server/util.c +++ b/src/lib/server/util.c @@ -311,7 +311,9 @@ ssize_t rad_filename_unescape(char *out, size_t outlen, char const *in, size_t i /* * If hex2bin returns 0 the next two chars weren't hexits. */ - if (fr_hex2bin(&FR_DBUFF_TMP((uint8_t *) out, 1), &FR_SBUFF_IN(in, 1)) == 0) return in - (p + 1); + if (fr_hex2bin(NULL, + &FR_DBUFF_TMP((uint8_t *) out, 1), + &FR_SBUFF_IN(in, 1), false) == 0) return in - (p + 1); in += 2; out++; freespace--; diff --git a/src/lib/tls/ctx.c b/src/lib/tls/ctx.c index 9ee80745d9c..866ce7eb4ec 100644 --- a/src/lib/tls/ctx.c +++ b/src/lib/tls/ctx.c @@ -395,7 +395,9 @@ SSL_CTX *fr_tls_ctx_alloc(fr_tls_conf_t const *conf, bool client) * Check the password now, so that we don't have * errors at run-time. */ - hex_len = fr_hex2bin(&FR_DBUFF_TMP(buffer, sizeof(buffer)), &FR_SBUFF_IN(conf->psk_password, psk_len)); + hex_len = fr_hex2bin(NULL, + &FR_DBUFF_TMP(buffer, sizeof(buffer)), + &FR_SBUFF_IN(conf->psk_password, psk_len), false); if (psk_len != (2 * hex_len)) { ERROR("psk_hexphrase is not all hex"); goto error; diff --git a/src/lib/tls/session.c b/src/lib/tls/session.c index 815a9d8f0a4..58903e36c38 100644 --- a/src/lib/tls/session.c +++ b/src/lib/tls/session.c @@ -392,8 +392,9 @@ unsigned int fr_tls_session_psk_client_cb(SSL *ssl, UNUSED char const *hint, strlcpy(identity, conf->psk_identity, max_identity_len); - return fr_hex2bin(&FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len), - &FR_SBUFF_IN(conf->psk_password, (size_t)psk_len)); + return fr_hex2bin(NULL, + &FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len), + &FR_SBUFF_IN(conf->psk_password, (size_t)psk_len), false); } /** Determine the PSK to use for an incoming connection @@ -458,7 +459,9 @@ unsigned int fr_tls_session_psk_server_cb(SSL *ssl, const char *identity, * convert the expansion from printable string * back to hex. */ - return fr_hex2bin(&FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len), &FR_SBUFF_IN(buffer, hex_len)); + return fr_hex2bin(NULL, + &FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len), + &FR_SBUFF_IN(buffer, hex_len), false); } if (!conf->psk_identity) { @@ -479,7 +482,9 @@ unsigned int fr_tls_session_psk_server_cb(SSL *ssl, const char *identity, psk_len = strlen(conf->psk_password); if (psk_len > (2 * max_psk_len)) return 0; - return fr_hex2bin(&FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len), &FR_SBUFF_IN(conf->psk_password, psk_len)); + return fr_hex2bin(NULL, + &FR_DBUFF_TMP((uint8_t *)psk, (size_t)max_psk_len), + &FR_SBUFF_IN(conf->psk_password, psk_len), false); } #endif /* PSK_MAX_IDENTITY_LEN */ diff --git a/src/lib/unlang/xlat_builtin.c b/src/lib/unlang/xlat_builtin.c index cce0b3ed129..188dda16d06 100644 --- a/src/lib/unlang/xlat_builtin.c +++ b/src/lib/unlang/xlat_builtin.c @@ -1709,10 +1709,11 @@ static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_cursor_t *out, REQUEST *request, UNUSED void const *xlat_inst, UNUSED void *xlat_thread_inst, fr_value_box_t **in) { - fr_value_box_t *result; - char *buff = NULL, *p, *end; - uint8_t *bin; - size_t len, outlen; + fr_value_box_t *result; + char *buff = NULL, *p, *end; + uint8_t *bin; + size_t len, outlen; + fr_sbuff_parse_error_t err; /* * If there's no input, there's no output @@ -1742,7 +1743,12 @@ static xlat_action_t xlat_func_bin(TALLOC_CTX *ctx, fr_cursor_t *out, MEM(result = fr_value_box_alloc_null(ctx)); MEM(fr_value_box_mem_alloc(result, &bin, result, NULL, outlen, fr_value_box_list_tainted(*in)) == 0); - fr_hex2bin(&FR_DBUFF_TMP(bin, outlen), &FR_SBUFF_IN(p, end - p)); + fr_hex2bin(&err, &FR_DBUFF_TMP(bin, outlen), &FR_SBUFF_IN(p, end - p), true); + if (err) { + REDEBUG2("Invalid hex string"); + talloc_free(result); + return XLAT_ACTION_FAIL; + } fr_cursor_append(out, result); diff --git a/src/lib/util/ascend.c b/src/lib/util/ascend.c index 791f46b2d3f..0507ead484b 100644 --- a/src/lib/util/ascend.c +++ b/src/lib/util/ascend.c @@ -396,7 +396,9 @@ static int ascend_parse_ipx_net(int argc, char **argv, /* * Node must be 6 octets long. */ - token = fr_hex2bin(&FR_DBUFF_TMP(net->node, IPX_NODE_ADDR_LEN), &FR_SBUFF_IN(p, strlen(p))); + token = fr_hex2bin(NULL, + &FR_DBUFF_TMP(net->node, IPX_NODE_ADDR_LEN), + &FR_SBUFF_IN(p, strlen(p)), false); if (token != IPX_NODE_ADDR_LEN) return -1; /* @@ -894,10 +896,14 @@ static int ascend_parse_generic(int argc, char **argv, filter->offset = rcode; filter->offset = htons(filter->offset); - rcode = fr_hex2bin(&FR_DBUFF_TMP(filter->mask, sizeof(filter->mask)), &FR_SBUFF_IN(argv[1], strlen(argv[1]))); + rcode = fr_hex2bin(NULL, + &FR_DBUFF_TMP(filter->mask, sizeof(filter->mask)), + &FR_SBUFF_IN(argv[1], strlen(argv[1])), false); if (rcode != sizeof(filter->mask)) return -1; - token = fr_hex2bin(&FR_DBUFF_TMP(filter->value, sizeof(filter->value)), &FR_SBUFF_IN(argv[2], strlen(argv[2]))); + token = fr_hex2bin(NULL, + &FR_DBUFF_TMP(filter->value, sizeof(filter->value)), + &FR_SBUFF_IN(argv[2], strlen(argv[2])), false); if (token != sizeof(filter->value)) return -1; filter->len = rcode; diff --git a/src/lib/util/hex.c b/src/lib/util/hex.c index 2ad75cdcc16..0ec3ffb3779 100644 --- a/src/lib/util/hex.c +++ b/src/lib/util/hex.c @@ -28,28 +28,50 @@ static char const hextab[] = "0123456789abcdef"; /** Convert hex strings to binary data * - * @param[out] out Output buffer to write to. - * @param[in] in Input string. + * @param[out] err If non-null contains any parse errors. + * @param[out] out Output buffer to write to. + * @param[in] in Input string. + * @param[in] no_trailing Error and return 0 if we find an odd length hex + * string. * @return * - >=0 the number of bytes written to out. + * - 0 no input data, or parse error. * - <0 number of bytes we would have needed to copy the next hexit. */ -ssize_t fr_hex2bin(fr_dbuff_t *out, fr_sbuff_t *in) +ssize_t fr_hex2bin(fr_sbuff_parse_error_t *err, fr_dbuff_t *out, fr_sbuff_t *in, bool no_trailing) { - size_t total = 0; + size_t total = 0; + fr_sbuff_t our_in = FR_SBUFF_NO_ADVANCE(in); + fr_dbuff_t our_out = FR_DBUFF_NO_ADVANCE(out); - while (!FR_SBUFF_CANT_EXTEND_LOWAT(in, 2)) { + while (!FR_SBUFF_CANT_EXTEND_LOWAT(&our_in, 2)) { char *c1, *c2; - if(!(c1 = memchr(hextab, tolower((int) *in->p), sizeof(hextab))) || - !(c2 = memchr(hextab, tolower((int) *(in->p + 1)), sizeof(hextab)))) break; + if(!(c1 = memchr(hextab, tolower((int) *our_in.p), sizeof(hextab))) || + !(c2 = memchr(hextab, tolower((int) *(our_in.p + 1)), sizeof(hextab)))) { + if (!c2 && no_trailing) { + got_trailing: + if (err) *err = FR_SBUFF_PARSE_ERROR_TRAILING; + return 0; + } + goto done; + } - FR_DBUFF_BYTES_IN_RETURN(out, ((c1 - hextab) << 4) + (c2 - hextab)); + FR_DBUFF_BYTES_IN_RETURN(&our_out, ((c1 - hextab) << 4) + (c2 - hextab)); - fr_sbuff_advance(in, 2); + fr_sbuff_advance(&our_in, 2); total++; }; + if (no_trailing && (fr_sbuff_remaining(&our_in) > 0) && + memchr(hextab, tolower((int) *our_in.p), sizeof(hextab))) goto got_trailing; + +done: + fr_sbuff_set(in, &our_in); + fr_dbuff_set(out, &our_out); + + if (err) *err = FR_SBUFF_PARSE_OK; + return total; } diff --git a/src/lib/util/hex.h b/src/lib/util/hex.h index 80e84e72628..52fe8698677 100644 --- a/src/lib/util/hex.h +++ b/src/lib/util/hex.h @@ -32,7 +32,7 @@ extern "C" { #include #include -ssize_t fr_hex2bin(fr_dbuff_t *out, fr_sbuff_t *in); +ssize_t fr_hex2bin(fr_sbuff_parse_error_t *err, fr_dbuff_t *out, fr_sbuff_t *in, bool no_trailing); ssize_t fr_bin2hex(fr_sbuff_t *out, fr_dbuff_t *in); diff --git a/src/lib/util/sbuff.h b/src/lib/util/sbuff.h index 3df44668d44..25f2b3ddf8e 100644 --- a/src/lib/util/sbuff.h +++ b/src/lib/util/sbuff.h @@ -808,6 +808,37 @@ do { \ if (_match_len) *(_match_len) = _match_len_tmp; \ } while (0) +/** Build a talloc wrapper function for a fr_sbuff_out_* function + * + * @param[in] _func to call. + * @param[in] _in input sbuff arg. + * @param[in] _len expected output len. + * @param[in] ... additional arguments to pass to _func. + */ +#define SBUFF_OUT_TALLOC_ERR_FUNC_DEF(_func, _in, _len, ...) \ +{ \ + fr_sbuff_t sbuff; \ + fr_sbuff_uctx_talloc_t tctx; \ + fr_sbuff_parse_error_t err; \ + ssize_t slen; \ + fr_sbuff_init_talloc(ctx, &sbuff, &tctx, \ + ((_len) != SIZE_MAX) ? (_len) : 1024, \ + ((_len) != SIZE_MAX) ? (_len) : SIZE_MAX); \ + slen = _func(&err, &sbuff, _in, _len, ##__VA_ARGS__); \ + if (slen <= 0) { \ + if (err != FR_SBUFF_PARSE_OK) { \ + TALLOC_FREE(sbuff.buff); \ + } else { \ + fr_sbuff_trim_talloc(&sbuff, 0); \ + } \ + *out = sbuff.buff; \ + return 0; \ + } \ + fr_sbuff_trim_talloc(&sbuff, SIZE_MAX); \ + *out = sbuff.buff; \ + return (size_t)slen; \ +} + /** Build a talloc wrapper function for a fr_sbuff_out_* function * * @param[in] _func to call. diff --git a/src/lib/util/value.c b/src/lib/util/value.c index 4fef355b4eb..761c519283e 100644 --- a/src/lib/util/value.c +++ b/src/lib/util/value.c @@ -4432,7 +4432,7 @@ parse: ret = len >> 1; p = talloc_array(ctx, uint8_t, ret); - if (fr_hex2bin(&FR_DBUFF_TMP(p, ret), &FR_SBUFF_IN(in + 2, len)) != (ssize_t)ret) { + if (fr_hex2bin(NULL, &FR_DBUFF_TMP(p, ret), &FR_SBUFF_IN(in + 2, len), false) != (ssize_t)ret) { talloc_free(p); fr_strerror_printf("Invalid hex data"); return -1; @@ -4452,7 +4452,8 @@ parse: return -1; } - bin = fr_hex2bin(&FR_DBUFF_TMP((uint8_t *) &dst->datum.filter, (len - 2) / 2), &FR_SBUFF_IN(in + 2, len - 2)); + bin = fr_hex2bin(NULL, &FR_DBUFF_TMP((uint8_t *) &dst->datum.filter, (len - 2) / 2), + &FR_SBUFF_IN(in + 2, len - 2), false); if (bin < ret) { memset(((uint8_t *) &dst->datum.filter) + bin, 0, ret - bin); } diff --git a/src/modules/proto_bfd/proto_bfd.c b/src/modules/proto_bfd/proto_bfd.c index 557c4a84f17..579f7df0fef 100644 --- a/src/modules/proto_bfd/proto_bfd.c +++ b/src/modules/proto_bfd/proto_bfd.c @@ -456,7 +456,8 @@ static ssize_t bfd_parse_secret(CONF_SECTION *cs, uint8_t secret[BFD_MAX_SECRET_ return -1; } - return fr_hex2bin(&FR_DBUFF_TMP(secret, BFD_MAX_SECRET_LENGTH), &FR_SBUFF_IN(value + 2, (len - 2))); + return fr_hex2bin(NULL, &FR_DBUFF_TMP(secret, BFD_MAX_SECRET_LENGTH), + &FR_SBUFF_IN(value + 2, (len - 2)), false); } if (len >= 20) { diff --git a/src/modules/rlm_digest/rlm_digest.c b/src/modules/rlm_digest/rlm_digest.c index f166b78f2fd..3a72d88efc1 100644 --- a/src/modules/rlm_digest/rlm_digest.c +++ b/src/modules/rlm_digest/rlm_digest.c @@ -205,7 +205,8 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(UNUSED module_ctx_t const * * Set A1 to Digest-HA1 if no User-Password found */ if (passwd->da == attr_digest_ha1) { - if (fr_hex2bin(&FR_DBUFF_TMP(&a1[0], sizeof(a1)), &FR_SBUFF_IN(passwd->vp_strvalue, passwd->vp_length)) != 16) { + if (fr_hex2bin(NULL, &FR_DBUFF_TMP(&a1[0], sizeof(a1)), + &FR_SBUFF_IN(passwd->vp_strvalue, passwd->vp_length), false) != 16) { RDEBUG2("Invalid text in Digest-HA1"); return RLM_MODULE_INVALID; } @@ -428,8 +429,8 @@ static rlm_rcode_t CC_HINT(nonnull) mod_authenticate(UNUSED module_ctx_t const * return RLM_MODULE_INVALID; } - if (fr_hex2bin(&FR_DBUFF_TMP(&hash[0], sizeof(hash)), - &FR_SBUFF_IN(vp->vp_strvalue, vp->vp_length)) != (ssize_t)(vp->vp_length >> 1)) { + if (fr_hex2bin(NULL, &FR_DBUFF_TMP(&hash[0], sizeof(hash)), + &FR_SBUFF_IN(vp->vp_strvalue, vp->vp_length), false) != (ssize_t)(vp->vp_length >> 1)) { RDEBUG2("Invalid text in Digest-Response"); return RLM_MODULE_INVALID; } diff --git a/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c b/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c index 1098688e8c4..4f94ebb2c4c 100644 --- a/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c +++ b/src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c @@ -390,7 +390,8 @@ static rlm_rcode_t mschap_finalize(REQUEST *request, rlm_eap_mschapv2_t const *i if (n == 3) { RDEBUG2("Found new challenge from MS-CHAP-Error: err=%d retry=%d challenge=%s", err, retry, buf); - fr_hex2bin(&FR_DBUFF_TMP(data->auth_challenge, 16), &FR_SBUFF_IN(buf, strlen(buf))); + fr_hex2bin(NULL, &FR_DBUFF_TMP(data->auth_challenge, 16), + &FR_SBUFF_IN(buf, strlen(buf)), false); } else { RDEBUG2("Could not parse new challenge from MS-CHAP-Error: %d", n); } diff --git a/src/modules/rlm_mschap/rlm_mschap.c b/src/modules/rlm_mschap/rlm_mschap.c index 071b10f6898..f78181da705 100644 --- a/src/modules/rlm_mschap/rlm_mschap.c +++ b/src/modules/rlm_mschap/rlm_mschap.c @@ -1222,7 +1222,8 @@ static int CC_HINT(nonnull (1, 2, 4, 5, 6)) do_mschap(rlm_mschap_t const *inst, /* * Update the NT hash hash, from the NT key. */ - if (fr_hex2bin(&FR_DBUFF_TMP(nthashhash, NT_DIGEST_LENGTH), &FR_SBUFF_IN(buffer + 8, len)) != NT_DIGEST_LENGTH) { + if (fr_hex2bin(NULL, &FR_DBUFF_TMP(nthashhash, NT_DIGEST_LENGTH), + &FR_SBUFF_IN(buffer + 8, len), false) != NT_DIGEST_LENGTH) { REDEBUG("Invalid output from ntlm_auth: NT_KEY has non-hex values"); return -1; } diff --git a/src/modules/rlm_pap/rlm_pap.c b/src/modules/rlm_pap/rlm_pap.c index ba69a30f34c..c89b2c2eee4 100644 --- a/src/modules/rlm_pap/rlm_pap.c +++ b/src/modules/rlm_pap/rlm_pap.c @@ -717,7 +717,8 @@ static rlm_rcode_t CC_HINT(nonnull) pap_auth_lm(UNUSED rlm_pap_t const *inst, RE len = xlat_eval(charbuf, sizeof(charbuf), request, "%{mschap:LM-Hash %{User-Password}}", NULL, NULL); if (len < 0) return RLM_MODULE_FAIL; - if ((fr_hex2bin(&FR_DBUFF_TMP(digest, sizeof(digest)), &FR_SBUFF_IN(charbuf, len)) != (ssize_t)known_good->vp_length) || + if ((fr_hex2bin(NULL, &FR_DBUFF_TMP(digest, sizeof(digest)), &FR_SBUFF_IN(charbuf, len), false) != + (ssize_t)known_good->vp_length) || (fr_digest_cmp(digest, known_good->vp_octets, known_good->vp_length) != 0)) { REDEBUG("LM digest does not match \"known good\" digest"); REDEBUG3("Calculated : %pH", fr_box_octets(digest, sizeof(digest))); @@ -746,7 +747,8 @@ static rlm_rcode_t CC_HINT(nonnull) pap_auth_ns_mta_md5(UNUSED rlm_pap_t const * /* * Sanity check the value of NS-MTA-MD5-Password */ - if (fr_hex2bin(&FR_DBUFF_TMP(digest, sizeof(digest)), &FR_SBUFF_IN(known_good->vp_strvalue, known_good->vp_length)) != 16) { + if (fr_hex2bin(NULL, &FR_DBUFF_TMP(digest, sizeof(digest)), + &FR_SBUFF_IN(known_good->vp_strvalue, known_good->vp_length), false) != 16) { REDEBUG("\"known good\" NS-MTA-MD5-Password has invalid value"); return RLM_MODULE_INVALID; } diff --git a/src/modules/rlm_unpack/rlm_unpack.c b/src/modules/rlm_unpack/rlm_unpack.c index 166cadca98b..fff635f6b43 100644 --- a/src/modules/rlm_unpack/rlm_unpack.c +++ b/src/modules/rlm_unpack/rlm_unpack.c @@ -128,13 +128,17 @@ static ssize_t unpack_xlat(UNUSED TALLOC_CTX *ctx, char **out, size_t outlen, * Hex data. */ len = strlen(data_name + 2); - if ((len & 0x01) != 0) { - REDEBUG("Invalid hex string in '%s'", data_name); - goto nothing; + if (len > 0) { + fr_sbuff_parse_error_t err; + + input = blob; + input_len = fr_hex2bin(&err, &FR_DBUFF_TMP(blob, sizeof(blob)), + &FR_SBUFF_IN(data_name + 2, len), true); + if (err) { + REDEBUG("Invalid hex string in '%s'", data_name); + goto nothing; + } } - input = blob; - input_len = fr_hex2bin(&FR_DBUFF_TMP(blob, sizeof(blob)), &FR_SBUFF_IN(data_name + 2, len)); - } else { GOTO_ERROR; }