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