int rad_lockfd_nonblock(int fd, int lock_len);
int rad_unlockfd(int fd, int lock_len);
size_t fr_bin2hex(char *hex, uint8_t const *bin, size_t inlen);
-size_t fr_hex2bin(uint8_t *bin, char const *hex, size_t outlen);
+size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen);
uint32_t fr_strtoul(char const *value, char **end);
bool is_whitespace(char const *value);
bool is_integer(char const *value);
/*
* Node must be 6 octets long.
*/
- token = fr_hex2bin(net->node, p, IPX_NODE_ADDR_LEN);
+ token = fr_hex2bin(net->node, IPX_NODE_ADDR_LEN, p, strlen(p));
if (token != IPX_NODE_ADDR_LEN) return -1;
/*
filter->offset = rcode;
filter->offset = htons(filter->offset);
- rcode = fr_hex2bin(filter->mask, argv[1], sizeof(filter->mask));
+ rcode = fr_hex2bin(filter->mask, sizeof(filter->mask), argv[1], strlen(argv[1]));
if (rcode != sizeof(filter->mask)) return -1;
- token = fr_hex2bin(filter->value, argv[2], sizeof(filter->value));
+ token = fr_hex2bin(filter->value, sizeof(filter->value), argv[2], strlen(argv[2]));
if (token != sizeof(filter->value)) return -1;
filter->len = rcode;
/** Convert hex strings to binary data
*
* @param bin Buffer to write output to.
- * @param hex input string.
* @param outlen length of output buffer (or length of input string / 2).
+ * @param hex input string.
+ * @param inlen length of the input string
* @return length of data written to buffer.
*/
-size_t fr_hex2bin(uint8_t *bin, char const *hex, size_t outlen)
+size_t fr_hex2bin(uint8_t *bin, size_t outlen, char const *hex, size_t inlen)
{
size_t i;
+ size_t len;
char *c1, *c2;
- for (i = 0; i < outlen; i++) {
+ /*
+ * Smartly truncate output, caller should check number of bytes
+ * written.
+ */
+ len = inlen >> 1;
+ if (len > outlen) len = outlen;
+
+ for (i = 0; i < len; i++) {
if(!(c1 = memchr(hextab, tolower((int) hex[i << 1]), 16)) ||
!(c2 = memchr(hextab, tolower((int) hex[(i << 1) + 1]), 16)))
break;
- bin[i] = ((c1-hextab)<<4) + (c2-hextab);
+ bin[i] = ((c1-hextab)<<4) + (c2-hextab);
}
return i;
vp->length = len >> 1;
p = talloc_array(vp, uint8_t, vp->length);
- if (fr_hex2bin(p, value + 2, len) != vp->length) {
+ if (fr_hex2bin(p, vp->length, value + 2, len) != vp->length) {
talloc_free(p);
fr_strerror_printf("Invalid hex data");
return -1;
fr_strerror_printf("No memory");
return -1;
}
- if (fr_hex2bin(p, value + 2, len) != vp->length) {
+ if (fr_hex2bin(p, vp->length, value + 2, len) != vp->length) {
fr_strerror_printf("Invalid hex data in TLV");
return -1;
}
vp->length = size >> 1;
data = talloc_array(vp, uint8_t, vp->length);
- if (fr_hex2bin(data, value + 2, size) != vp->length) {
+ if (fr_hex2bin(data, vp->length, value + 2, size) != vp->length) {
fr_strerror_printf("Invalid hex string");
talloc_free(vp);
return NULL;
psk_len = strlen(conf->psk_password);
if (psk_len > (2 * max_psk_len)) return 0;
- return fr_hex2bin(psk, conf->psk_password, psk_len);
+ return fr_hex2bin(psk, max_psk_len, conf->psk_password, psk_len);
}
static unsigned int psk_client_callback(SSL *ssl, UNUSED char const *hint,
strlcpy(identity, conf->psk_identity, max_identity_len);
- return fr_hex2bin(psk, conf->psk_password, psk_len);
+ return fr_hex2bin(psk, max_psk_len, conf->psk_password, psk_len);
}
#endif
return NULL;
}
- hex_len = fr_hex2bin((uint8_t *) buffer, conf->psk_password, psk_len);
+ hex_len = fr_hex2bin((uint8_t *) buffer, sizeof(buffer), conf->psk_password, psk_len);
if (psk_len != (2 * hex_len)) {
ERROR("psk_hexphrase is not all hex");
return NULL;
return -(p - fmt);
}
- if (!fr_hex2bin((uint8_t *) q, p, 2)) {
+ if (!fr_hex2bin((uint8_t *) q, 1, p, 2)) {
talloc_free(node);
*error = "Invalid hex characters";
return -(p - fmt);
* Set A1 to Digest-HA1 if no User-Password found
*/
if (passwd->da->attr == PW_DIGEST_HA1) {
- if (fr_hex2bin(&a1[0], passwd->vp_strvalue, 16) != 16) {
+ if (fr_hex2bin(&a1[0], sizeof(a1), passwd->vp_strvalue, passwd->length) != 16) {
RDEBUG2("Invalid text in Digest-HA1");
return RLM_MODULE_INVALID;
}
return RLM_MODULE_INVALID;
}
- if (fr_hex2bin(&hash[0], vp->vp_strvalue, vp->length >> 1) != (vp->length >> 1)) {
+ if (fr_hex2bin(&hash[0], sizeof(hash), vp->vp_strvalue, vp->length) != (vp->length >> 1)) {
RDEBUG2("Invalid text in Digest-Response");
return RLM_MODULE_INVALID;
}
if (password->length == 32) {
p = talloc_array(password, uint8_t, 16);
- password->length = fr_hex2bin(p, password->vp_strvalue, 16);
+ password->length = fr_hex2bin(p, 16, password->vp_strvalue, password->length);
}
if (password->length != 16) {
REDEBUG("Bad NT-Password");
n = sscanf(response->vp_strvalue, "%*cE=%d R=%d C=%32s", &err, &retry, &buf[0]);
if (n == 3) {
DEBUG2("Found new challenge from MS-CHAP-Error: err=%d retry=%d challenge=%s", err, retry, buf);
- fr_hex2bin(data->challenge, buf, 16);
+ fr_hex2bin(data->challenge, 16, buf, strlen(buf));
} else {
DEBUG2("Could not parse new challenge from MS-CHAP-Error: %d", n);
}
} else { /* run ntlm_auth */
int result;
char buffer[256];
+ size_t len;
memset(nthashhash, 0, 16);
* Check the length. It should be at least 32,
* with an LF at the end.
*/
- if (strlen(buffer + 8) < 32) {
+ len = strlen(buffer + 8);
+ if (len < 32) {
REDEBUG2("Invalid output from ntlm_auth: NT_KEY has unexpected length");
return -1;
}
/*
* Update the NT hash hash, from the NT key.
*/
- if (fr_hex2bin(nthashhash, buffer + 8, 16) != 16) {
+ if (fr_hex2bin(nthashhash, sizeof(nthashhash), buffer + 8, len) != 16) {
REDEBUG("Invalid output from ntlm_auth: NT_KEY has non-hex values");
return -1;
}
* There are notes in otp_radstate as to why the state
* value is encoded as hexits.
*/
- len = fr_hex2bin(bin_state, vp->vp_strvalue, vp->length);
+ len = fr_hex2bin(bin_state, sizeof(bin_state), vp->vp_strvalue, vp->length);
if (len != (vp->length / 2)) {
REDEBUG("bad radstate for [%s]: not hex", username);
if (min_length >= sizeof(buffer)) return; /* paranoia */
+ rad_assert((vp->da->type == PW_TYPE_OCTETS) || (vp->da->type == PW_TYPE_STRING));
+
/*
* Hex encoding.
*/
if (vp->length >= (2 * min_length)) {
size_t decoded;
- decoded = fr_hex2bin(buffer, vp->vp_strvalue, sizeof(buffer));
+
+ decoded = fr_hex2bin(buffer, sizeof(buffer), vp->vp_strvalue, vp->length);
if (decoded == (vp->length >> 1)) {
RDEBUG2("Normalizing %s from hex encoding, %zu bytes -> %zu bytes",
vp->da->name, vp->length, decoded);
{
uint8_t digest[16];
char charbuf[32 + 1];
+ ssize_t len;
RDEBUG("Comparing with \"known-good\" NT-Password");
return RLM_MODULE_INVALID;
}
- if (radius_xlat(charbuf, sizeof(charbuf), request, "%{mschap:NT-Hash %{User-Password}}", NULL, NULL) < 0){
+ len = radius_xlat(charbuf, sizeof(charbuf), request, "%{mschap:NT-Hash %{User-Password}}", NULL, NULL);
+ if (len < 0) {
return RLM_MODULE_REJECT;
}
- if ((fr_hex2bin(digest, charbuf, sizeof(digest)) != vp->length) ||
+ if ((fr_hex2bin(digest, sizeof(digest), charbuf, len) != vp->length) ||
(rad_digest_cmp(digest, vp->vp_octets, vp->length) != 0)) {
REDEBUG("NT digest does not match \"known good\" digest");
return RLM_MODULE_REJECT;
{
uint8_t digest[16];
char charbuf[32 + 1];
+ ssize_t len;
RDEBUG("Comparing with \"known-good\" LM-Password");
return RLM_MODULE_INVALID;
}
- if (radius_xlat(charbuf, sizeof(charbuf), request, "%{mschap:LM-Hash %{User-Password}}", NULL, NULL) < 0){
+ len = radius_xlat(charbuf, sizeof(charbuf), request, "%{mschap:LM-Hash %{User-Password}}", NULL, NULL);
+ if (len < 0){
return RLM_MODULE_FAIL;
}
- if ((fr_hex2bin(digest, charbuf, sizeof(digest)) != vp->length) ||
+ if ((fr_hex2bin(digest, sizeof(digest), charbuf, len) != vp->length) ||
(rad_digest_cmp(digest, vp->vp_octets, vp->length) != 0)) {
REDEBUG("LM digest does not match \"known good\" digest");
return RLM_MODULE_REJECT;
/*
* Sanity check the value of NS-MTA-MD5-Password
*/
- if (fr_hex2bin(digest, vp->vp_strvalue, 32) != 16) {
+ if (fr_hex2bin(digest, sizeof(digest), vp->vp_strvalue, vp->length) != 16) {
REDEBUG("\"known good\" NS-MTA-MD5-Password has invalid value");
return RLM_MODULE_INVALID;
}
goto nothing;
}
input = blob;
- input_len = fr_hex2bin(blob, data_name + 2, sizeof(blob));
+ input_len = fr_hex2bin(blob, sizeof(blob), data_name + 2, len);
} else {
GOTO_ERROR;