]> git.ipfire.org Git - thirdparty/freeradius-server.git/commitdiff
hex: Add explicit error checks
authorArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 28 Jul 2020 18:23:03 +0000 (14:23 -0400)
committerArran Cudbard-Bell <a.cudbardb@freeradius.org>
Tue, 28 Jul 2020 18:23:03 +0000 (14:23 -0400)
20 files changed:
src/lib/ldap/util.c
src/lib/server/client.c
src/lib/server/map.c
src/lib/server/password.c
src/lib/server/tmpl.c
src/lib/server/util.c
src/lib/tls/ctx.c
src/lib/tls/session.c
src/lib/unlang/xlat_builtin.c
src/lib/util/ascend.c
src/lib/util/hex.c
src/lib/util/hex.h
src/lib/util/sbuff.h
src/lib/util/value.c
src/modules/proto_bfd/proto_bfd.c
src/modules/rlm_digest/rlm_digest.c
src/modules/rlm_eap/types/rlm_eap_mschapv2/rlm_eap_mschapv2.c
src/modules/rlm_mschap/rlm_mschap.c
src/modules/rlm_pap/rlm_pap.c
src/modules/rlm_unpack/rlm_unpack.c

index f65ecb74fbf80e6e5643fcdd0d2bf8bbce7b9a34..b0974e1139b8ca357b0530eba47922fc9f3d947d 100644 (file)
@@ -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 '#':
index 6ab9855e4fb760b3bed794652aa53ced53c1985c..9f2fd09c25c6ae3dde0819441dab28de9d70bacd 100644 (file)
@@ -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;
index 9962633dbd9412f9e9d1174716b8118db115ff84..e0517eb5f27e3dd15967c025b17c63790742a851 100644 (file)
@@ -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);
index 22f1284c7e1983d81903197303a9359c05def51c..c01b69b848d6a76ab1fb7ab2463ae3d8d4d08682 100644 (file)
@@ -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;
index bb8acecb02976b79b690bbee654d20659d05c1a4..b9a991365bf01b97986583cd8b1fdb7ba1d8fc07 100644 (file)
@@ -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);
index 0e664be4302cb623802056f8d67b3d4f933f96ec..8e9f12b76bcbdbfd19bd55c25cdb96e6b783e1c5 100644 (file)
@@ -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--;
index 9ee80745d9c0706ffe1a394d0616f4a68ee9a069..866ce7eb4ecee3b547609b36e7148cd6a66b4400 100644 (file)
@@ -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;
index 815a9d8f0a4efcc7fac8cea7099b84a27aa5969d..58903e36c38986d2cfe531215d9f59aa131dd71a 100644 (file)
@@ -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 */
 
index cce0b3ed12996a95616974f078eb6235b153f144..188dda16d06011102102e7ad843ead46efaf47ee 100644 (file)
@@ -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);
 
index 791f46b2d3f8e3a763dc561df4133a3285f1b9a3..0507ead484b670cd718fda1e2acb5e646fe931d2 100644 (file)
@@ -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;
index 2ad75cdcc16e08a0d2693aaeed9e04062d69dafc..0ec3ffb37791418a0cb7188ac285f4a72dba6679 100644 (file)
@@ -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;
 }
 
index 80e84e72628ad1b93f179e280a6c1666b644f623..52fe8698677e99562e722773291b95579f451153 100644 (file)
@@ -32,7 +32,7 @@ extern "C" {
 #include <freeradius-devel/util/sbuff.h>
 #include <freeradius-devel/util/dbuff.h>
 
-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);
 
index 3df44668d4493e027fe908867ddddd7711cbd54f..25f2b3ddf8e9576c6684e4d3fb292a183a047e77 100644 (file)
@@ -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.
index 4fef355b4ebbb0594a9b4fd05cc4f6a389e8fda4..761c519283e0359564e028083381c776cd5b4d3d 100644 (file)
@@ -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);
                        }
index 557c4a84f17e61842e3d85ded0f7b8dffb6c4f49..579f7df0feff14772317619ad9835187acee0f3c 100644 (file)
@@ -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) {
index f166b78f2fd7ae3128955a7f72e72bf3aea4877e..3a72d88efc1637035b3209cc62956189ccec2bd8 100644 (file)
@@ -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;
        }
index 1098688e8c4a0e048b1187b561be54c865db2ade..4f94ebb2c4c6ec7a07b82934f5be38de550d7bf0 100644 (file)
@@ -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);
                        }
index 071b10f68987fe9acb7d161a28139260f022be81..f78181da7051a8d69188c5f8d329ac868ff07b2a 100644 (file)
@@ -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;
                }
index ba69a30f34c17d62596a3b88af5bf2ad19336b98..c89b2c2eee424c3029d597088551ef4714631b10 100644 (file)
@@ -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;
        }
index 166cadca98b7caf012f1f1f29ebe885c23f319d5..fff635f6b432a0b85c52aea3bcb01b001d4d2418 100644 (file)
@@ -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;
        }