libradius: Fix input validation bugs
Approved by: so Security: FreeBSD-SA-21:12.libradius Security: CVE-2021-29629 MFC after: now Sponsored by: The FreeBSD Foundation
This commit is contained in:
parent
f4c460dacd
commit
8d5c781306
@ -187,7 +187,7 @@ is_valid_response(struct rad_handle *h, int srv,
|
|||||||
MD5_CTX ctx;
|
MD5_CTX ctx;
|
||||||
unsigned char md5[MD5_DIGEST_LENGTH];
|
unsigned char md5[MD5_DIGEST_LENGTH];
|
||||||
const struct rad_server *srvp;
|
const struct rad_server *srvp;
|
||||||
int len;
|
int alen, len;
|
||||||
#ifdef WITH_SSL
|
#ifdef WITH_SSL
|
||||||
HMAC_CTX *hctx;
|
HMAC_CTX *hctx;
|
||||||
u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
|
u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
|
||||||
@ -206,8 +206,8 @@ is_valid_response(struct rad_handle *h, int srv,
|
|||||||
/* Check the message length */
|
/* Check the message length */
|
||||||
if (h->in_len < POS_ATTRS)
|
if (h->in_len < POS_ATTRS)
|
||||||
return 0;
|
return 0;
|
||||||
len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
|
len = (h->in[POS_LENGTH] << 8) | h->in[POS_LENGTH + 1];
|
||||||
if (len > h->in_len)
|
if (len < POS_ATTRS || len > h->in_len)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* Check the response authenticator */
|
/* Check the response authenticator */
|
||||||
@ -233,9 +233,16 @@ is_valid_response(struct rad_handle *h, int srv,
|
|||||||
/* Search and verify the Message-Authenticator */
|
/* Search and verify the Message-Authenticator */
|
||||||
hctx = HMAC_CTX_new();
|
hctx = HMAC_CTX_new();
|
||||||
while (pos < len - 2) {
|
while (pos < len - 2) {
|
||||||
|
|
||||||
if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
|
if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
|
||||||
/* zero fill the Message-Authenticator */
|
if (h->in[pos + 1] != MD5_DIGEST_LENGTH + 2) {
|
||||||
|
HMAC_CTX_free(hctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
if (len - pos < MD5_DIGEST_LENGTH + 2) {
|
||||||
|
HMAC_CTX_free(hctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
|
memset(&resp[pos + 2], 0, MD5_DIGEST_LENGTH);
|
||||||
|
|
||||||
HMAC_Init_ex(hctx, srvp->secret,
|
HMAC_Init_ex(hctx, srvp->secret,
|
||||||
@ -255,7 +262,12 @@ is_valid_response(struct rad_handle *h, int srv,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pos += h->in[pos + 1];
|
alen = h->in[pos + 1];
|
||||||
|
if (alen < 2) {
|
||||||
|
HMAC_CTX_free(hctx);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
pos += alen;
|
||||||
}
|
}
|
||||||
HMAC_CTX_free(hctx);
|
HMAC_CTX_free(hctx);
|
||||||
}
|
}
|
||||||
@ -272,7 +284,7 @@ is_valid_request(struct rad_handle *h)
|
|||||||
MD5_CTX ctx;
|
MD5_CTX ctx;
|
||||||
unsigned char md5[MD5_DIGEST_LENGTH];
|
unsigned char md5[MD5_DIGEST_LENGTH];
|
||||||
const struct rad_server *srvp;
|
const struct rad_server *srvp;
|
||||||
int len;
|
int alen, len;
|
||||||
#ifdef WITH_SSL
|
#ifdef WITH_SSL
|
||||||
HMAC_CTX *hctx;
|
HMAC_CTX *hctx;
|
||||||
u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
|
u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
|
||||||
@ -285,8 +297,8 @@ is_valid_request(struct rad_handle *h)
|
|||||||
/* Check the message length */
|
/* Check the message length */
|
||||||
if (h->in_len < POS_ATTRS)
|
if (h->in_len < POS_ATTRS)
|
||||||
return (0);
|
return (0);
|
||||||
len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
|
len = (h->in[POS_LENGTH] << 8) | h->in[POS_LENGTH + 1];
|
||||||
if (len > h->in_len)
|
if (len < POS_ATTRS || len > h->in_len)
|
||||||
return (0);
|
return (0);
|
||||||
|
|
||||||
if (h->in[POS_CODE] != RAD_ACCESS_REQUEST) {
|
if (h->in[POS_CODE] != RAD_ACCESS_REQUEST) {
|
||||||
@ -307,7 +319,18 @@ is_valid_request(struct rad_handle *h)
|
|||||||
pos = POS_ATTRS;
|
pos = POS_ATTRS;
|
||||||
hctx = HMAC_CTX_new();
|
hctx = HMAC_CTX_new();
|
||||||
while (pos < len - 2) {
|
while (pos < len - 2) {
|
||||||
|
alen = h->in[pos + 1];
|
||||||
|
if (alen < 2)
|
||||||
|
return (0);
|
||||||
if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
|
if (h->in[pos] == RAD_MESSAGE_AUTHENTIC) {
|
||||||
|
if (len - pos < MD5_DIGEST_LENGTH + 2) {
|
||||||
|
HMAC_CTX_free(hctx);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
|
if (alen < MD5_DIGEST_LENGTH + 2) {
|
||||||
|
HMAC_CTX_free(hctx);
|
||||||
|
return (0);
|
||||||
|
}
|
||||||
memcpy(resp, h->in, MSGSIZE);
|
memcpy(resp, h->in, MSGSIZE);
|
||||||
/* zero fill the Request-Authenticator */
|
/* zero fill the Request-Authenticator */
|
||||||
if (h->in[POS_CODE] != RAD_ACCESS_REQUEST)
|
if (h->in[POS_CODE] != RAD_ACCESS_REQUEST)
|
||||||
@ -327,7 +350,7 @@ is_valid_request(struct rad_handle *h)
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
pos += h->in[pos + 1];
|
pos += alen;
|
||||||
}
|
}
|
||||||
HMAC_CTX_free(hctx);
|
HMAC_CTX_free(hctx);
|
||||||
#endif
|
#endif
|
||||||
@ -929,9 +952,9 @@ rad_cvt_string(const void *data, size_t len)
|
|||||||
* returns -1.
|
* returns -1.
|
||||||
*/
|
*/
|
||||||
int
|
int
|
||||||
rad_get_attr(struct rad_handle *h, const void **value, size_t *len)
|
rad_get_attr(struct rad_handle *h, const void **value, size_t *lenp)
|
||||||
{
|
{
|
||||||
int type;
|
int len, type;
|
||||||
|
|
||||||
if (h->in_pos >= h->in_len)
|
if (h->in_pos >= h->in_len)
|
||||||
return 0;
|
return 0;
|
||||||
@ -940,13 +963,14 @@ rad_get_attr(struct rad_handle *h, const void **value, size_t *len)
|
|||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
type = h->in[h->in_pos++];
|
type = h->in[h->in_pos++];
|
||||||
*len = h->in[h->in_pos++] - 2;
|
len = h->in[h->in_pos++];
|
||||||
if (h->in_pos + (int)*len > h->in_len) {
|
if (len < 2 || h->in_pos + len > h->in_len) {
|
||||||
generr(h, "Malformed attribute in response");
|
generr(h, "Malformed attribute in response");
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
*lenp = len;
|
||||||
*value = &h->in[h->in_pos];
|
*value = &h->in[h->in_pos];
|
||||||
h->in_pos += *len;
|
h->in_pos += len;
|
||||||
return type;
|
return type;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user