The branch main has been updated by markj:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=8d5c7813061dfa0b187500dfe3aeea7a28181c13

commit 8d5c7813061dfa0b187500dfe3aeea7a28181c13
Author:     Mark Johnston <[email protected]>
AuthorDate: 2021-05-25 17:59:09 +0000
Commit:     Mark Johnston <[email protected]>
CommitDate: 2021-05-26 20:30:23 +0000

    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
---
 lib/libradius/radlib.c | 54 ++++++++++++++++++++++++++++++++++++--------------
 1 file changed, 39 insertions(+), 15 deletions(-)

diff --git a/lib/libradius/radlib.c b/lib/libradius/radlib.c
index e01c486a1ba6..18aee8b53024 100644
--- a/lib/libradius/radlib.c
+++ b/lib/libradius/radlib.c
@@ -187,7 +187,7 @@ is_valid_response(struct rad_handle *h, int srv,
        MD5_CTX ctx;
        unsigned char md5[MD5_DIGEST_LENGTH];
        const struct rad_server *srvp;
-       int len;
+       int alen, len;
 #ifdef WITH_SSL
        HMAC_CTX *hctx;
        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 */
        if (h->in_len < POS_ATTRS)
                return 0;
-       len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
-       if (len > h->in_len)
+       len = (h->in[POS_LENGTH] << 8) | h->in[POS_LENGTH + 1];
+       if (len < POS_ATTRS || len > h->in_len)
                return 0;
 
        /* Check the response authenticator */
@@ -233,9 +233,16 @@ is_valid_response(struct rad_handle *h, int srv,
                /* Search and verify the Message-Authenticator */
                hctx = HMAC_CTX_new();
                while (pos < len - 2) {
-
                        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);
 
                                HMAC_Init_ex(hctx, srvp->secret,
@@ -255,7 +262,12 @@ is_valid_response(struct rad_handle *h, int srv,
                                }
                                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);
        }
@@ -272,7 +284,7 @@ is_valid_request(struct rad_handle *h)
        MD5_CTX ctx;
        unsigned char md5[MD5_DIGEST_LENGTH];
        const struct rad_server *srvp;
-       int len;
+       int alen, len;
 #ifdef WITH_SSL
        HMAC_CTX *hctx;
        u_char resp[MSGSIZE], md[EVP_MAX_MD_SIZE];
@@ -285,8 +297,8 @@ is_valid_request(struct rad_handle *h)
        /* Check the message length */
        if (h->in_len < POS_ATTRS)
                return (0);
-       len = h->in[POS_LENGTH] << 8 | h->in[POS_LENGTH+1];
-       if (len > h->in_len)
+       len = (h->in[POS_LENGTH] << 8) | h->in[POS_LENGTH + 1];
+       if (len < POS_ATTRS || len > h->in_len)
                return (0);
 
        if (h->in[POS_CODE] != RAD_ACCESS_REQUEST) {
@@ -307,7 +319,18 @@ is_valid_request(struct rad_handle *h)
        pos = POS_ATTRS;
        hctx = HMAC_CTX_new();
        while (pos < len - 2) {
+               alen = h->in[pos + 1];
+               if (alen < 2)
+                       return (0);
                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);
                        /* zero fill the Request-Authenticator */
                        if (h->in[POS_CODE] != RAD_ACCESS_REQUEST)
@@ -327,7 +350,7 @@ is_valid_request(struct rad_handle *h)
                        }
                        break;
                }
-               pos += h->in[pos + 1];
+               pos += alen;
        }
        HMAC_CTX_free(hctx);
 #endif
@@ -929,9 +952,9 @@ rad_cvt_string(const void *data, size_t len)
  * returns -1.
  */
 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)
                return 0;
@@ -940,13 +963,14 @@ rad_get_attr(struct rad_handle *h, const void **value, 
size_t *len)
                return -1;
        }
        type = h->in[h->in_pos++];
-       *len = h->in[h->in_pos++] - 2;
-       if (h->in_pos + (int)*len > h->in_len) {
+       len = h->in[h->in_pos++];
+       if (len < 2 || h->in_pos + len > h->in_len) {
                generr(h, "Malformed attribute in response");
                return -1;
        }
+       *lenp = len;
        *value = &h->in[h->in_pos];
-       h->in_pos += *len;
+       h->in_pos += len;
        return type;
 }
 
_______________________________________________
[email protected] mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "[email protected]"

Reply via email to