1From f1cdbb33ec61c4a64a32e107d4d02f936051c708 Mon Sep 17 00:00:00 2001 2From: "Alan T. DeKok" <aland@freeradius.org> 3Date: Mon, 7 Feb 2022 22:26:05 -0500 4Subject: [PATCH] it's probably wrong to be completely retarded. Let's fix 5 that. 6 7CVE: CVE-2022-41860 8 9Upstream-Status: Backport 10[https://github.com/FreeRADIUS/freeradius-server/commit/f1cdbb33ec61c4a64a32e107d4d02f936051c708] 11 12Signed-off-by: Yi Zhao <yi.zhao@windriver.com> 13--- 14 src/modules/rlm_eap/libeap/eapsimlib.c | 69 +++++++++++++++++++------- 15 1 file changed, 52 insertions(+), 17 deletions(-) 16 17diff --git a/src/modules/rlm_eap/libeap/eapsimlib.c b/src/modules/rlm_eap/libeap/eapsimlib.c 18index cf1e8a7dd9..e438a844ea 100644 19--- a/src/modules/rlm_eap/libeap/eapsimlib.c 20+++ b/src/modules/rlm_eap/libeap/eapsimlib.c 21@@ -307,42 +307,77 @@ int unmap_eapsim_basictypes(RADIUS_PACKET *r, 22 newvp->vp_length = 1; 23 fr_pair_add(&(r->vps), newvp); 24 25+ /* 26+ * EAP-SIM has a 1 octet of subtype, and 2 octets 27+ * reserved. 28+ */ 29 attr += 3; 30 attrlen -= 3; 31 32- /* now, loop processing each attribute that we find */ 33- while(attrlen > 0) { 34+ /* 35+ * Loop over each attribute. The format is: 36+ * 37+ * 1 octet of type 38+ * 1 octet of length (value 1..255) 39+ * ((4 * length) - 2) octets of data. 40+ */ 41+ while (attrlen > 0) { 42 uint8_t *p; 43 44- if(attrlen < 2) { 45+ if (attrlen < 2) { 46 fr_strerror_printf("EAP-Sim attribute %d too short: %d < 2", es_attribute_count, attrlen); 47 return 0; 48 } 49 50+ if (!attr[1]) { 51+ fr_strerror_printf("EAP-Sim attribute %d (no.%d) has no data", eapsim_attribute, 52+ es_attribute_count); 53+ return 0; 54+ } 55+ 56 eapsim_attribute = attr[0]; 57 eapsim_len = attr[1] * 4; 58 59+ /* 60+ * The length includes the 2-byte header. 61+ */ 62 if (eapsim_len > attrlen) { 63 fr_strerror_printf("EAP-Sim attribute %d (no.%d) has length longer than data (%d > %d)", 64 eapsim_attribute, es_attribute_count, eapsim_len, attrlen); 65 return 0; 66 } 67 68- if(eapsim_len > MAX_STRING_LEN) { 69- eapsim_len = MAX_STRING_LEN; 70- } 71- if (eapsim_len < 2) { 72- fr_strerror_printf("EAP-Sim attribute %d (no.%d) has length too small", eapsim_attribute, 73- es_attribute_count); 74- return 0; 75- } 76+ newvp = fr_pair_afrom_num(r, eapsim_attribute + PW_EAP_SIM_BASE, 0); 77+ if (!newvp) { 78+ /* 79+ * RFC 4186 Section 8.1 says 0..127 are 80+ * "non-skippable". If one such 81+ * attribute is found and we don't 82+ * understand it, the server has to send: 83+ * 84+ * EAP-Request/SIM/Notification packet with an 85+ * (AT_NOTIFICATION code, which implies general failure ("General 86+ * failure after authentication" (0), or "General failure" (16384), 87+ * depending on the phase of the exchange), which terminates the 88+ * authentication exchange. 89+ */ 90+ if (eapsim_attribute <= 127) { 91+ fr_strerror_printf("Unknown mandatory attribute %d, failing", 92+ eapsim_attribute); 93+ return 0; 94+ } 95 96- newvp = fr_pair_afrom_num(r, eapsim_attribute+PW_EAP_SIM_BASE, 0); 97- newvp->vp_length = eapsim_len-2; 98- newvp->vp_octets = p = talloc_array(newvp, uint8_t, newvp->vp_length); 99- memcpy(p, &attr[2], eapsim_len-2); 100- fr_pair_add(&(r->vps), newvp); 101- newvp = NULL; 102+ } else { 103+ /* 104+ * It's known, ccount for header, and 105+ * copy the value over. 106+ */ 107+ newvp->vp_length = eapsim_len - 2; 108+ 109+ newvp->vp_octets = p = talloc_array(newvp, uint8_t, newvp->vp_length); 110+ memcpy(p, &attr[2], newvp->vp_length); 111+ fr_pair_add(&(r->vps), newvp); 112+ } 113 114 /* advance pointers, decrement length */ 115 attr += eapsim_len; 116-- 1172.25.1 118 119