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