|
|
047f28 |
From: Antonio Torres <antorres@redhat.com>
|
|
|
047f28 |
Date: Fri, 09 Dec 2022
|
|
|
047f28 |
Subject: Fix crash on unknown option in EAP-SIM
|
|
|
047f28 |
|
|
|
047f28 |
When an EAP-SIM supplicant sends an unknown SIM option, the server will try to
|
|
|
047f28 |
look that option up in the internal dictionaries. This lookup will fail, but the
|
|
|
047f28 |
SIM code will not check for that failure. Instead, it will dereference a NULL
|
|
|
047f28 |
pointer, and cause the server to crash.
|
|
|
047f28 |
|
|
|
047f28 |
Backport of:
|
|
|
047f28 |
https://github.com/FreeRADIUS/freeradius-server/commit/f1cdbb33ec61c4a64a
|
|
|
047f28 |
https://github.com/FreeRADIUS/freeradius-server/commit/71128cac3ee236a88a05cc7bddd43e43a88a3089
|
|
|
047f28 |
|
|
|
047f28 |
Resolves: https://bugzilla.redhat.com/show_bug.cgi?id=2151704
|
|
|
047f28 |
Signed-off-by: Antonio Torres <antorres@redhat.com>
|
|
|
047f28 |
---
|
|
|
047f28 |
diff --git a/src/modules/rlm_eap/libeap/eapsimlib.c b/src/modules/rlm_eap/libeap/eapsimlib.c
|
|
|
047f28 |
index cf1e8a7dd92..e438a844eab 100644
|
|
|
047f28 |
--- a/src/modules/rlm_eap/libeap/eapsimlib.c
|
|
|
047f28 |
+++ b/src/modules/rlm_eap/libeap/eapsimlib.c
|
|
|
047f28 |
@@ -307,42 +307,77 @@ int unmap_eapsim_basictypes(RADIUS_PACKET *r,
|
|
|
047f28 |
newvp->vp_length = 1;
|
|
|
047f28 |
fr_pair_add(&(r->vps), newvp);
|
|
|
047f28 |
|
|
|
047f28 |
+ /*
|
|
|
047f28 |
+ * EAP-SIM has a 1 octet of subtype, and 2 octets
|
|
|
047f28 |
+ * reserved.
|
|
|
047f28 |
+ */
|
|
|
047f28 |
attr += 3;
|
|
|
047f28 |
attrlen -= 3;
|
|
|
047f28 |
|
|
|
047f28 |
- /* now, loop processing each attribute that we find */
|
|
|
047f28 |
- while(attrlen > 0) {
|
|
|
047f28 |
+ /*
|
|
|
047f28 |
+ * Loop over each attribute. The format is:
|
|
|
047f28 |
+ *
|
|
|
047f28 |
+ * 1 octet of type
|
|
|
047f28 |
+ * 1 octet of length (value 1..255)
|
|
|
047f28 |
+ * ((4 * length) - 2) octets of data.
|
|
|
047f28 |
+ */
|
|
|
047f28 |
+ while (attrlen > 0) {
|
|
|
047f28 |
uint8_t *p;
|
|
|
047f28 |
|
|
|
047f28 |
- if(attrlen < 2) {
|
|
|
047f28 |
+ if (attrlen < 2) {
|
|
|
047f28 |
fr_strerror_printf("EAP-Sim attribute %d too short: %d < 2", es_attribute_count, attrlen);
|
|
|
047f28 |
return 0;
|
|
|
047f28 |
}
|
|
|
047f28 |
|
|
|
047f28 |
+ if (!attr[1]) {
|
|
|
047f28 |
+ fr_strerror_printf("EAP-Sim attribute %d (no.%d) has no data", attr[0],
|
|
|
047f28 |
+ es_attribute_count);
|
|
|
047f28 |
+ return 0;
|
|
|
047f28 |
+ }
|
|
|
047f28 |
+
|
|
|
047f28 |
eapsim_attribute = attr[0];
|
|
|
047f28 |
eapsim_len = attr[1] * 4;
|
|
|
047f28 |
|
|
|
047f28 |
+ /*
|
|
|
047f28 |
+ * The length includes the 2-byte header.
|
|
|
047f28 |
+ */
|
|
|
047f28 |
if (eapsim_len > attrlen) {
|
|
|
047f28 |
fr_strerror_printf("EAP-Sim attribute %d (no.%d) has length longer than data (%d > %d)",
|
|
|
047f28 |
eapsim_attribute, es_attribute_count, eapsim_len, attrlen);
|
|
|
047f28 |
return 0;
|
|
|
047f28 |
}
|
|
|
047f28 |
|
|
|
047f28 |
- if(eapsim_len > MAX_STRING_LEN) {
|
|
|
047f28 |
- eapsim_len = MAX_STRING_LEN;
|
|
|
047f28 |
- }
|
|
|
047f28 |
- if (eapsim_len < 2) {
|
|
|
047f28 |
- fr_strerror_printf("EAP-Sim attribute %d (no.%d) has length too small", eapsim_attribute,
|
|
|
047f28 |
- es_attribute_count);
|
|
|
047f28 |
- return 0;
|
|
|
047f28 |
- }
|
|
|
047f28 |
+ newvp = fr_pair_afrom_num(r, eapsim_attribute + PW_EAP_SIM_BASE, 0);
|
|
|
047f28 |
+ if (!newvp) {
|
|
|
047f28 |
+ /*
|
|
|
047f28 |
+ * RFC 4186 Section 8.1 says 0..127 are
|
|
|
047f28 |
+ * "non-skippable". If one such
|
|
|
047f28 |
+ * attribute is found and we don't
|
|
|
047f28 |
+ * understand it, the server has to send:
|
|
|
047f28 |
+ *
|
|
|
047f28 |
+ * EAP-Request/SIM/Notification packet with an
|
|
|
047f28 |
+ * (AT_NOTIFICATION code, which implies general failure ("General
|
|
|
047f28 |
+ * failure after authentication" (0), or "General failure" (16384),
|
|
|
047f28 |
+ * depending on the phase of the exchange), which terminates the
|
|
|
047f28 |
+ * authentication exchange.
|
|
|
047f28 |
+ */
|
|
|
047f28 |
+ if (eapsim_attribute <= 127) {
|
|
|
047f28 |
+ fr_strerror_printf("Unknown mandatory attribute %d, failing",
|
|
|
047f28 |
+ eapsim_attribute);
|
|
|
047f28 |
+ return 0;
|
|
|
047f28 |
+ }
|
|
|
047f28 |
|
|
|
047f28 |
- newvp = fr_pair_afrom_num(r, eapsim_attribute+PW_EAP_SIM_BASE, 0);
|
|
|
047f28 |
- newvp->vp_length = eapsim_len-2;
|
|
|
047f28 |
- newvp->vp_octets = p = talloc_array(newvp, uint8_t, newvp->vp_length);
|
|
|
047f28 |
- memcpy(p, &attr[2], eapsim_len-2);
|
|
|
047f28 |
- fr_pair_add(&(r->vps), newvp);
|
|
|
047f28 |
- newvp = NULL;
|
|
|
047f28 |
+ } else {
|
|
|
047f28 |
+ /*
|
|
|
047f28 |
+ * It's known, ccount for header, and
|
|
|
047f28 |
+ * copy the value over.
|
|
|
047f28 |
+ */
|
|
|
047f28 |
+ newvp->vp_length = eapsim_len - 2;
|
|
|
047f28 |
+
|
|
|
047f28 |
+ newvp->vp_octets = p = talloc_array(newvp, uint8_t, newvp->vp_length);
|
|
|
047f28 |
+ memcpy(p, &attr[2], newvp->vp_length);
|
|
|
047f28 |
+ fr_pair_add(&(r->vps), newvp);
|
|
|
047f28 |
+ }
|
|
|
047f28 |
|
|
|
047f28 |
/* advance pointers, decrement length */
|
|
|
047f28 |
attr += eapsim_len;
|