summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHitendra Prajapati <hprajapati@mvista.com>2025-12-23 10:29:32 +0530
committerGyorgy Sarvari <skandigraun@gmail.com>2025-12-25 10:17:01 +0100
commit4ac316bf47260fa7b6bfba546dd38e02f9440d4b (patch)
tree36d53d246e4dce0fd2494b409ea1da1cf221060a
parentd2894888c92700c368a7665ded60810df5d8438c (diff)
downloadmeta-openembedded-4ac316bf47260fa7b6bfba546dd38e02f9440d4b.tar.gz
krb5: fix for CVE-2024-3596
Upstream-Status: Backport from https://github.com/krb5/krb5/commit/871125fea8ce0370a972bf65f7d1de63f619b06c Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com> Signed-off-by: Gyorgy Sarvari <skandigraun@gmail.com>
-rw-r--r--meta-oe/recipes-connectivity/krb5/krb5/CVE-2024-3596.patch628
-rw-r--r--meta-oe/recipes-connectivity/krb5/krb5_1.17.2.bb1
2 files changed, 629 insertions, 0 deletions
diff --git a/meta-oe/recipes-connectivity/krb5/krb5/CVE-2024-3596.patch b/meta-oe/recipes-connectivity/krb5/krb5/CVE-2024-3596.patch
new file mode 100644
index 0000000000..8e74b07aef
--- /dev/null
+++ b/meta-oe/recipes-connectivity/krb5/krb5/CVE-2024-3596.patch
@@ -0,0 +1,628 @@
1From 871125fea8ce0370a972bf65f7d1de63f619b06c Mon Sep 17 00:00:00 2001
2From: Julien Rische <jrische@redhat.com>
3Date: Thu, 22 Aug 2024 17:15:50 +0200
4Subject: [PATCH] Generate and verify message MACs in libkrad
5
6Implement some of the measures specified in
7draft-ietf-radext-deprecating-radius-03 for mitigating the BlastRADIUS
8attack (CVE-2024-3596):
9
10* Include a Message-Authenticator MAC as the first attribute when
11 generating a packet of type Access-Request, Access-Reject,
12 Access-Accept, or Access-Challenge (sections 5.2.1 and 5.2.4), if
13 the secret is non-empty. (An empty secret indicates the use of Unix
14 domain socket transport.)
15
16* Validate the Message-Authenticator MAC in received packets, if
17 present.
18
19FreeRADIUS enforces Message-Authenticator as of versions 3.2.5 and
203.0.27. libkrad must generate Message-Authenticator attributes in
21order to remain compatible with these implementations.
22
23[ghudson@mit.edu: adjusted style and naming; simplified some
24functions; edited commit message]
25
26ticket: 9142 (new)
27tags: pullup
28target_version: 1.21-next
29
30CVE: CVE-2024-3596
31Upstream-Status: Backport [https://github.com/krb5/krb5/commit/871125fea8ce0370a972bf65f7d1de63f619b06c]
32Signed-off-by: Hitendra Prajapati <hprajapati@mvista.com>
33---
34 src/include/k5-int.h | 5 +
35 src/lib/crypto/krb/checksum_hmac_md5.c | 28 ++++
36 src/lib/crypto/libk5crypto.exports | 1 +
37 src/lib/krad/attr.c | 17 ++
38 src/lib/krad/attrset.c | 58 +++++--
39 src/lib/krad/internal.h | 7 +-
40 src/lib/krad/packet.c | 205 +++++++++++++++++++++++--
41 src/lib/krad/t_attrset.c | 2 +-
42 src/lib/krad/t_daemon.py | 3 +-
43 src/lib/krad/t_packet.c | 11 ++
44 src/tests/t_otp.py | 3 +
45 11 files changed, 309 insertions(+), 31 deletions(-)
46
47diff --git a/src/include/k5-int.h b/src/include/k5-int.h
48index 5928c82..9b3aa13 100644
49--- a/src/include/k5-int.h
50+++ b/src/include/k5-int.h
51@@ -2394,4 +2394,9 @@ void k5_change_error_message_code(krb5_context ctx, krb5_error_code oldcode,
52 #define k5_prependmsg krb5_prepend_error_message
53 #define k5_wrapmsg krb5_wrap_error_message
54
55+/* Generate an HMAC-MD5 keyed checksum as specified by RFC 2104. */
56+krb5_error_code
57+k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data,
58+ krb5_data *output);
59+
60 #endif /* _KRB5_INT_H */
61diff --git a/src/lib/crypto/krb/checksum_hmac_md5.c b/src/lib/crypto/krb/checksum_hmac_md5.c
62index ec024f3..a809388 100644
63--- a/src/lib/crypto/krb/checksum_hmac_md5.c
64+++ b/src/lib/crypto/krb/checksum_hmac_md5.c
65@@ -92,3 +92,31 @@ cleanup:
66 free(hash_iov);
67 return ret;
68 }
69+
70+krb5_error_code
71+k5_hmac_md5(const krb5_data *key, const krb5_crypto_iov *data, size_t num_data,
72+ krb5_data *output)
73+{
74+ krb5_error_code ret;
75+ const struct krb5_hash_provider *hash = &krb5int_hash_md5;
76+ krb5_keyblock keyblock = { 0 };
77+ krb5_data hashed_key;
78+ uint8_t hkeybuf[16];
79+ krb5_crypto_iov iov;
80+
81+ /* Hash the key if it is longer than the block size. */
82+ if (key->length > hash->blocksize) {
83+ hashed_key = make_data(hkeybuf, sizeof(hkeybuf));
84+ iov.flags = KRB5_CRYPTO_TYPE_DATA;
85+ iov.data = *key;
86+ ret = hash->hash(&iov, 1, &hashed_key);
87+ if (ret)
88+ return ret;
89+ key = &hashed_key;
90+ }
91+
92+ keyblock.magic = KV5M_KEYBLOCK;
93+ keyblock.length = key->length;
94+ keyblock.contents = (uint8_t *)key->data;
95+ return krb5int_hmac_keyblock(hash, &keyblock, data, num_data, output);
96+}
97diff --git a/src/lib/crypto/libk5crypto.exports b/src/lib/crypto/libk5crypto.exports
98index 90afdf5..02efa3b 100644
99--- a/src/lib/crypto/libk5crypto.exports
100+++ b/src/lib/crypto/libk5crypto.exports
101@@ -110,3 +110,4 @@ krb5_c_prfplus
102 krb5_c_derive_prfplus
103 k5_enctype_to_ssf
104 krb5int_c_deprecated_enctype
105+k5_hmac_md5
106diff --git a/src/lib/krad/attr.c b/src/lib/krad/attr.c
107index 9c13d9d..4ad3212 100644
108--- a/src/lib/krad/attr.c
109+++ b/src/lib/krad/attr.c
110@@ -122,6 +122,23 @@ static const attribute_record attributes[UCHAR_MAX] = {
111 {"NAS-Port-Type", 4, 4, NULL, NULL},
112 {"Port-Limit", 4, 4, NULL, NULL},
113 {"Login-LAT-Port", 1, MAX_ATTRSIZE, NULL, NULL},
114+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
115+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
116+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
117+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
118+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
119+ {NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
120+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
121+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
122+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
123+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
124+ {NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
125+ {NULL, 0, 0, NULL, NULL}, /* Password-Retry */
126+ {NULL, 0, 0, NULL, NULL}, /* Prompt */
127+ {NULL, 0, 0, NULL, NULL}, /* Connect-Info */
128+ {NULL, 0, 0, NULL, NULL}, /* Configuration-Token */
129+ {NULL, 0, 0, NULL, NULL}, /* EAP-Message */
130+ {"Message-Authenticator", MD5_DIGEST_SIZE, MD5_DIGEST_SIZE, NULL, NULL},
131 };
132
133 /* Encode User-Password attribute. */
134diff --git a/src/lib/krad/attrset.c b/src/lib/krad/attrset.c
135index 03c6137..f279949 100644
136--- a/src/lib/krad/attrset.c
137+++ b/src/lib/krad/attrset.c
138@@ -164,14 +164,42 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
139 return 0;
140 }
141
142+/* Place an encoded attributes into outbuf at position *i. Increment *i by the
143+ * length of the encoding. */
144+static krb5_error_code
145+append_attr(krb5_context ctx, const char *secret,
146+ const uint8_t *auth, krad_attr type, const krb5_data *data,
147+ uint8_t outbuf[MAX_ATTRSETSIZE], size_t *i)
148+{
149+ uint8_t buffer[MAX_ATTRSIZE];
150+ size_t attrlen;
151+ krb5_error_code retval;
152+
153+ retval = kr_attr_encode(ctx, secret, auth, type, data, buffer, &attrlen);
154+ if (retval)
155+ return retval;
156+
157+ if (attrlen > MAX_ATTRSETSIZE - *i - 2)
158+ return EMSGSIZE;
159+
160+ outbuf[(*i)++] = type;
161+ outbuf[(*i)++] = attrlen + 2;
162+ memcpy(outbuf + *i, buffer, attrlen);
163+ *i += attrlen;
164+
165+ return 0;
166+}
167+
168 krb5_error_code
169 kr_attrset_encode(const krad_attrset *set, const char *secret,
170- const unsigned char *auth,
171+ const uint8_t *auth, krb5_boolean add_msgauth,
172 unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
173 {
174- unsigned char buffer[MAX_ATTRSIZE];
175 krb5_error_code retval;
176- size_t i = 0, attrlen;
177+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
178+ const uint8_t zeroes[MD5_DIGEST_SIZE] = { 0 };
179+ krb5_data zerodata;
180+ size_t i = 0;
181 attr *a;
182
183 if (set == NULL) {
184@@ -179,19 +207,21 @@ kr_attrset_encode(const krad_attrset *set, const char *secret,
185 return 0;
186 }
187
188- K5_TAILQ_FOREACH(a, &set->list, list) {
189- retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
190- buffer, &attrlen);
191- if (retval != 0)
192+ if (add_msgauth) {
193+ /* Encode Message-Authenticator as the first attribute, per
194+ * draft-ietf-radext-deprecating-radius-03 section 5.2. */
195+ zerodata = make_data((uint8_t *)zeroes, MD5_DIGEST_SIZE);
196+ retval = append_attr(set->ctx, secret, auth, msgauth_type, &zerodata,
197+ outbuf, &i);
198+ if (retval)
199 return retval;
200+ }
201
202- if (i + attrlen + 2 > MAX_ATTRSETSIZE)
203- return EMSGSIZE;
204-
205- outbuf[i++] = a->type;
206- outbuf[i++] = attrlen + 2;
207- memcpy(&outbuf[i], buffer, attrlen);
208- i += attrlen;
209+ K5_TAILQ_FOREACH(a, &set->list, list) {
210+ retval = append_attr(set->ctx, secret, auth, a->type, &a->attr,
211+ outbuf, &i);
212+ if (retval)
213+ return retval;
214 }
215
216 *outlen = i;
217diff --git a/src/lib/krad/internal.h b/src/lib/krad/internal.h
218index 996a893..8194b00 100644
219--- a/src/lib/krad/internal.h
220+++ b/src/lib/krad/internal.h
221@@ -43,6 +43,8 @@
222 #define UCHAR_MAX 255
223 #endif
224
225+#define MD5_DIGEST_SIZE 16
226+
227 /* RFC 2865 */
228 #define MAX_ATTRSIZE (UCHAR_MAX - 2)
229 #define MAX_ATTRSETSIZE (KRAD_PACKET_SIZE_MAX - 20)
230@@ -65,10 +67,11 @@ kr_attr_decode(krb5_context ctx, const char *secret, const unsigned char *auth,
231 krad_attr type, const krb5_data *in,
232 unsigned char outbuf[MAX_ATTRSIZE], size_t *outlen);
233
234-/* Encode the attributes into the buffer. */
235+/* Encode set into outbuf. If add_msgauth is true, include a zeroed
236+ * Message-Authenticator as the first attribute. */
237 krb5_error_code
238 kr_attrset_encode(const krad_attrset *set, const char *secret,
239- const unsigned char *auth,
240+ const uint8_t *auth, krb5_boolean add_msgauth,
241 unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen);
242
243 /* Decode attributes from a buffer. */
244diff --git a/src/lib/krad/packet.c b/src/lib/krad/packet.c
245index c597174..539af5a 100644
246--- a/src/lib/krad/packet.c
247+++ b/src/lib/krad/packet.c
248@@ -36,6 +36,7 @@
249 typedef unsigned char uchar;
250
251 /* RFC 2865 */
252+#define MSGAUTH_SIZE (2 + MD5_DIGEST_SIZE)
253 #define OFFSET_CODE 0
254 #define OFFSET_ID 1
255 #define OFFSET_LENGTH 2
256@@ -222,6 +223,106 @@ packet_set_attrset(krb5_context ctx, const char *secret, krad_packet *pkt)
257 return kr_attrset_decode(ctx, &tmp, secret, pkt_auth(pkt), &pkt->attrset);
258 }
259
260+/* Determine if a packet requires a Message-Authenticator attribute. */
261+static inline krb5_boolean
262+requires_msgauth(const char *secret, krad_code code)
263+{
264+ /* If no secret is provided, assume that the transport is a UNIX socket.
265+ * Message-Authenticator is required only on UDP and TCP connections. */
266+ if (*secret == '\0')
267+ return FALSE;
268+
269+ /*
270+ * Per draft-ietf-radext-deprecating-radius-03 sections 5.2.1 and 5.2.4,
271+ * Message-Authenticator is required in Access-Request packets and all
272+ * potential responses when UDP or TCP transport is used.
273+ */
274+ return code == krad_code_name2num("Access-Request") ||
275+ code == krad_code_name2num("Access-Reject") ||
276+ code == krad_code_name2num("Access-Accept") ||
277+ code == krad_code_name2num("Access-Challenge");
278+}
279+
280+/* Check if the packet has a Message-Authenticator attribute. */
281+static inline krb5_boolean
282+has_pkt_msgauth(const krad_packet *pkt)
283+{
284+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
285+
286+ return krad_attrset_get(pkt->attrset, msgauth_type, 0) != NULL;
287+}
288+
289+/* Return the beginning of the Message-Authenticator attribute in pkt, or NULL
290+ * if no such attribute is present. */
291+static const uint8_t *
292+lookup_msgauth_addr(const krad_packet *pkt)
293+{
294+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
295+ size_t i;
296+ uint8_t *p;
297+
298+ i = OFFSET_ATTR;
299+ while (i + 2 < pkt->pkt.length) {
300+ p = (uint8_t *)offset(&pkt->pkt, i);
301+ if (msgauth_type == *p)
302+ return p;
303+ i += p[1];
304+ }
305+
306+ return NULL;
307+}
308+
309+/*
310+ * Calculate the message authenticator MAC for pkt as specified in RFC 2869
311+ * section 5.14, placing the result in mac_out. Use the provided authenticator
312+ * auth, which may be from pkt or from a corresponding request.
313+ */
314+static krb5_error_code
315+calculate_mac(const char *secret, const krad_packet *pkt,
316+ const uint8_t auth[AUTH_FIELD_SIZE],
317+ uint8_t mac_out[MD5_DIGEST_SIZE])
318+{
319+ uint8_t zeroed_msgauth[MSGAUTH_SIZE];
320+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
321+ const uint8_t *msgauth_attr, *msgauth_end, *pkt_end;
322+ krb5_crypto_iov input[5];
323+ krb5_data ksecr, mac;
324+
325+ msgauth_attr = lookup_msgauth_addr(pkt);
326+ if (msgauth_attr == NULL)
327+ return EINVAL;
328+ msgauth_end = msgauth_attr + MSGAUTH_SIZE;
329+ pkt_end = (const uint8_t *)pkt->pkt.data + pkt->pkt.length;
330+
331+ /* Read code, id, and length from the packet. */
332+ input[0].flags = KRB5_CRYPTO_TYPE_DATA;
333+ input[0].data = make_data(pkt->pkt.data, OFFSET_AUTH);
334+
335+ /* Read the provided authenticator. */
336+ input[1].flags = KRB5_CRYPTO_TYPE_DATA;
337+ input[1].data = make_data((uint8_t *)auth, AUTH_FIELD_SIZE);
338+
339+ /* Read any attributes before Message-Authenticator. */
340+ input[2].flags = KRB5_CRYPTO_TYPE_DATA;
341+ input[2].data = make_data(pkt_attr(pkt), msgauth_attr - pkt_attr(pkt));
342+
343+ /* Read Message-Authenticator with the data bytes all set to zero, per RFC
344+ * 2869 section 5.14. */
345+ zeroed_msgauth[0] = msgauth_type;
346+ zeroed_msgauth[1] = MSGAUTH_SIZE;
347+ memset(zeroed_msgauth + 2, 0, MD5_DIGEST_SIZE);
348+ input[3].flags = KRB5_CRYPTO_TYPE_DATA;
349+ input[3].data = make_data(zeroed_msgauth, MSGAUTH_SIZE);
350+
351+ /* Read any attributes after Message-Authenticator. */
352+ input[4].flags = KRB5_CRYPTO_TYPE_DATA;
353+ input[4].data = make_data((uint8_t *)msgauth_end, pkt_end - msgauth_end);
354+
355+ mac = make_data(mac_out, MD5_DIGEST_SIZE);
356+ ksecr = string2data((char *)secret);
357+ return k5_hmac_md5(&ksecr, input, 5, &mac);
358+}
359+
360 ssize_t
361 krad_packet_bytes_needed(const krb5_data *buffer)
362 {
363@@ -255,6 +356,7 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
364 krad_packet *pkt;
365 uchar id;
366 size_t attrset_len;
367+ krb5_boolean msgauth_required;
368
369 pkt = packet_new();
370 if (pkt == NULL) {
371@@ -274,9 +376,13 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
372 if (retval != 0)
373 goto error;
374
375+ /* Determine if Message-Authenticator is required. */
376+ msgauth_required = (*secret != '\0' &&
377+ code == krad_code_name2num("Access-Request"));
378+
379 /* Encode the attributes. */
380- retval = kr_attrset_encode(set, secret, pkt_auth(pkt), pkt_attr(pkt),
381- &attrset_len);
382+ retval = kr_attrset_encode(set, secret, pkt_auth(pkt), msgauth_required,
383+ pkt_attr(pkt), &attrset_len);
384 if (retval != 0)
385 goto error;
386
387@@ -285,6 +391,13 @@ krad_packet_new_request(krb5_context ctx, const char *secret, krad_code code,
388 pkt_code_set(pkt, code);
389 pkt_len_set(pkt, pkt->pkt.length);
390
391+ if (msgauth_required) {
392+ /* Calculate and set the Message-Authenticator MAC. */
393+ retval = calculate_mac(secret, pkt, pkt_auth(pkt), pkt_attr(pkt) + 2);
394+ if (retval != 0)
395+ goto error;
396+ }
397+
398 /* Copy the attrset for future use. */
399 retval = packet_set_attrset(ctx, secret, pkt);
400 if (retval != 0)
401@@ -307,14 +420,18 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
402 krb5_error_code retval;
403 krad_packet *pkt;
404 size_t attrset_len;
405+ krb5_boolean msgauth_required;
406
407 pkt = packet_new();
408 if (pkt == NULL)
409 return ENOMEM;
410
411+ /* Determine if Message-Authenticator is required. */
412+ msgauth_required = requires_msgauth(secret, code);
413+
414 /* Encode the attributes. */
415- retval = kr_attrset_encode(set, secret, pkt_auth(request), pkt_attr(pkt),
416- &attrset_len);
417+ retval = kr_attrset_encode(set, secret, pkt_auth(request),
418+ msgauth_required, pkt_attr(pkt), &attrset_len);
419 if (retval != 0)
420 goto error;
421
422@@ -330,6 +447,18 @@ krad_packet_new_response(krb5_context ctx, const char *secret, krad_code code,
423 if (retval != 0)
424 goto error;
425
426+ if (msgauth_required) {
427+ /*
428+ * Calculate and replace the Message-Authenticator MAC. Per RFC 2869
429+ * section 5.14, use the authenticator from the request, not from the
430+ * response.
431+ */
432+ retval = calculate_mac(secret, pkt, pkt_auth(request),
433+ pkt_attr(pkt) + 2);
434+ if (retval != 0)
435+ goto error;
436+ }
437+
438 /* Copy the attrset for future use. */
439 retval = packet_set_attrset(ctx, secret, pkt);
440 if (retval != 0)
441@@ -343,6 +472,34 @@ error:
442 return retval;
443 }
444
445+/* Verify the Message-Authenticator value in pkt, using the provided
446+ * authenticator (which may be from pkt or from a corresponding request). */
447+static krb5_error_code
448+verify_msgauth(const char *secret, const krad_packet *pkt,
449+ const uint8_t auth[AUTH_FIELD_SIZE])
450+{
451+ uint8_t mac[MD5_DIGEST_SIZE];
452+ krad_attr msgauth_type = krad_attr_name2num("Message-Authenticator");
453+ const krb5_data *msgauth;
454+ krb5_error_code retval;
455+
456+ msgauth = krad_packet_get_attr(pkt, msgauth_type, 0);
457+ if (msgauth == NULL)
458+ return ENODATA;
459+
460+ retval = calculate_mac(secret, pkt, auth, mac);
461+ if (retval)
462+ return retval;
463+
464+ if (msgauth->length != MD5_DIGEST_SIZE)
465+ return EMSGSIZE;
466+
467+ if (k5_bcmp(mac, msgauth->data, MD5_DIGEST_SIZE) != 0)
468+ return EBADMSG;
469+
470+ return 0;
471+}
472+
473 /* Decode a packet. */
474 static krb5_error_code
475 decode_packet(krb5_context ctx, const char *secret, const krb5_data *buffer,
476@@ -394,21 +551,35 @@ krad_packet_decode_request(krb5_context ctx, const char *secret,
477 krad_packet **reqpkt)
478 {
479 const krad_packet *tmp = NULL;
480+ krad_packet *req;
481 krb5_error_code retval;
482
483- retval = decode_packet(ctx, secret, buffer, reqpkt);
484- if (cb != NULL && retval == 0) {
485+ retval = decode_packet(ctx, secret, buffer, &req);
486+ if (retval)
487+ return retval;
488+
489+ /* Verify Message-Authenticator if present. */
490+ if (has_pkt_msgauth(req)) {
491+ retval = verify_msgauth(secret, req, pkt_auth(req));
492+ if (retval) {
493+ krad_packet_free(req);
494+ return retval;
495+ }
496+ }
497+
498+ if (cb != NULL) {
499 for (tmp = (*cb)(data, FALSE); tmp != NULL; tmp = (*cb)(data, FALSE)) {
500 if (pkt_id_get(*reqpkt) == pkt_id_get(tmp))
501 break;
502 }
503- }
504
505- if (cb != NULL && (retval != 0 || tmp != NULL))
506- (*cb)(data, TRUE);
507+ if (tmp != NULL)
508+ (*cb)(data, TRUE);
509+ }
510
511+ *reqpkt = req;
512 *duppkt = tmp;
513- return retval;
514+ return 0;
515 }
516
517 krb5_error_code
518@@ -435,9 +606,17 @@ krad_packet_decode_response(krb5_context ctx, const char *secret,
519 break;
520 }
521
522- /* If the authenticator matches, then the response is valid. */
523- if (memcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) == 0)
524- break;
525+ /* Verify the response authenticator. */
526+ if (k5_bcmp(pkt_auth(*rsppkt), auth, sizeof(auth)) != 0)
527+ continue;
528+
529+ /* Verify Message-Authenticator if present. */
530+ if (has_pkt_msgauth(*rsppkt)) {
531+ if (verify_msgauth(secret, *rsppkt, pkt_auth(tmp)) != 0)
532+ continue;
533+ }
534+
535+ break;
536 }
537 }
538
539diff --git a/src/lib/krad/t_attrset.c b/src/lib/krad/t_attrset.c
540index 7928335..fd11ee5 100644
541--- a/src/lib/krad/t_attrset.c
542+++ b/src/lib/krad/t_attrset.c
543@@ -62,7 +62,7 @@ main()
544 noerror(krad_attrset_add(set, krad_attr_name2num("User-Password"), &tmp));
545
546 /* Encode attrset. */
547- noerror(kr_attrset_encode(set, "foo", auth, buffer, &encode_len));
548+ noerror(kr_attrset_encode(set, "foo", auth, FALSE, buffer, &encode_len));
549 krad_attrset_free(set);
550
551 /* Manually encode User-Name. */
552diff --git a/src/lib/krad/t_daemon.py b/src/lib/krad/t_daemon.py
553index 7668cd7..7fa0449 100755
554--- a/src/lib/krad/t_daemon.py
555+++ b/src/lib/krad/t_daemon.py
556@@ -40,6 +40,7 @@ DICTIONARY = """
557 ATTRIBUTE\tUser-Name\t1\tstring
558 ATTRIBUTE\tUser-Password\t2\toctets
559 ATTRIBUTE\tNAS-Identifier\t32\tstring
560+ATTRIBUTE\tMessage-Authenticator\t80\toctets
561 """
562
563 class TestServer(server.Server):
564@@ -52,7 +53,7 @@ class TestServer(server.Server):
565 if key == "User-Password":
566 passwd = map(pkt.PwDecrypt, pkt[key])
567
568- reply = self.CreateReplyPacket(pkt)
569+ reply = self.CreateReplyPacket(pkt, message_authenticator=True)
570 if passwd == ['accept']:
571 reply.code = packet.AccessAccept
572 else:
573diff --git a/src/lib/krad/t_packet.c b/src/lib/krad/t_packet.c
574index 0a92e9c..745fb21 100644
575--- a/src/lib/krad/t_packet.c
576+++ b/src/lib/krad/t_packet.c
577@@ -159,6 +159,9 @@ main(int argc, const char **argv)
578 krb5_data username, password;
579 krb5_boolean auth = FALSE;
580 krb5_context ctx;
581+ const krad_packet *dupreq;
582+ const krb5_data *encpkt;
583+ krad_packet *decreq;
584
585 username = string2data("testUser");
586
587@@ -171,9 +174,17 @@ main(int argc, const char **argv)
588
589 password = string2data("accept");
590 noerror(make_packet(ctx, &username, &password, &packets[ACCEPT_PACKET]));
591+ encpkt = krad_packet_encode(packets[ACCEPT_PACKET]);
592+ noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL,
593+ &dupreq, &decreq));
594+ krad_packet_free(decreq);
595
596 password = string2data("reject");
597 noerror(make_packet(ctx, &username, &password, &packets[REJECT_PACKET]));
598+ encpkt = krad_packet_encode(packets[REJECT_PACKET]);
599+ noerror(krad_packet_decode_request(ctx, "foo", encpkt, NULL, NULL,
600+ &dupreq, &decreq));
601+ krad_packet_free(decreq);
602
603 memset(&hints, 0, sizeof(hints));
604 hints.ai_family = AF_INET;
605diff --git a/src/tests/t_otp.py b/src/tests/t_otp.py
606index cba871a..1ec9165 100755
607--- a/src/tests/t_otp.py
608+++ b/src/tests/t_otp.py
609@@ -49,6 +49,7 @@ ATTRIBUTE User-Name 1 string
610 ATTRIBUTE User-Password 2 octets
611 ATTRIBUTE Service-Type 6 integer
612 ATTRIBUTE NAS-Identifier 32 string
613+ATTRIBUTE Message-Authenticator 80 octets
614 '''
615
616 class RadiusDaemon(Process):
617@@ -97,6 +98,8 @@ class RadiusDaemon(Process):
618 reply.code = packet.AccessReject
619 replyq['reply'] = False
620
621+ reply.add_message_authenticator()
622+
623 outq.put(replyq)
624 if addr is None:
625 sock.send(reply.ReplyPacket())
626--
6272.50.1
628
diff --git a/meta-oe/recipes-connectivity/krb5/krb5_1.17.2.bb b/meta-oe/recipes-connectivity/krb5/krb5_1.17.2.bb
index d889855649..ed17b57b19 100644
--- a/meta-oe/recipes-connectivity/krb5/krb5_1.17.2.bb
+++ b/meta-oe/recipes-connectivity/krb5/krb5_1.17.2.bb
@@ -41,6 +41,7 @@ SRC_URI = "http://web.mit.edu/kerberos/dist/${BPN}/${SHRT_VER}/${BP}.tar.gz \
41 file://CVE-2025-3576-01.patch;striplevel=2 \ 41 file://CVE-2025-3576-01.patch;striplevel=2 \
42 file://CVE-2025-3576-02.patch;striplevel=2 \ 42 file://CVE-2025-3576-02.patch;striplevel=2 \
43 file://CVE-2025-24528.patch;striplevel=2 \ 43 file://CVE-2025-24528.patch;striplevel=2 \
44 file://CVE-2024-3596.patch;striplevel=2 \
44" 45"
45SRC_URI[md5sum] = "aa4337fffa3b61f22dbd0167f708818f" 46SRC_URI[md5sum] = "aa4337fffa3b61f22dbd0167f708818f"
46SRC_URI[sha256sum] = "1a4bba94df92f6d39a197a10687653e8bfbc9a2076e129f6eb92766974f86134" 47SRC_URI[sha256sum] = "1a4bba94df92f6d39a197a10687653e8bfbc9a2076e129f6eb92766974f86134"