Skip to content

Commit

Permalink
libkrad: Add Message-Authenticator support
Browse files Browse the repository at this point in the history
draft-ietf-radext-deprecating-radius-03 describes multiple mitigation
measures for recent vulnerabilities discovered in the RADIUS protocol,
especially the BlastRADIUS one (CVE-2024-3596). One of them is the
enforcement of the Message-Authenticator attribute.

Message-Authenticator was initially defined in RFC2869 (2000) as an
extension to improve authenticity and integrity verification.

However the BlastRADIUS vulnerability is now pushing vendors to
generalize the use of this attibute. FreeRADIUS is now enforcing
Message-Authenticator since versions 3.2.5 and 3.0.27. libkrad has to
support Message-Authenticator in order to remain compatible with these
implementations.
  • Loading branch information
jrisc committed Sep 5, 2024
1 parent b9b654e commit 147d94b
Show file tree
Hide file tree
Showing 7 changed files with 447 additions and 44 deletions.
4 changes: 4 additions & 0 deletions src/include/krb5/krb5.hin
Original file line number Diff line number Diff line change
Expand Up @@ -1516,6 +1516,10 @@ krb5_k_verify_checksum_iov(krb5_context context, krb5_cksumtype cksumtype,
krb5_error_code KRB5_CALLCONV
krb5_k_prf(krb5_context context, krb5_key key, krb5_data *input, krb5_data *output);

krb5_error_code
krb5_krad_hmacmd5_checksum(const krb5_data *secret, const krb5_crypto_iov *data,
size_t num_data, krb5_data *output);

#ifdef KRB5_OLD_CRYPTO
/*
* old cryptosystem routine prototypes. These are now layered
Expand Down
50 changes: 50 additions & 0 deletions src/lib/crypto/krb/checksum_hmac_md5.c
Original file line number Diff line number Diff line change
Expand Up @@ -92,3 +92,53 @@ krb5_error_code krb5int_hmacmd5_checksum(const struct krb5_cksumtypes *ctp,
free(hash_iov);
return ret;
}

krb5_error_code
krb5_krad_hmacmd5_checksum(const krb5_data *secret, const krb5_crypto_iov *data,
size_t num_data, krb5_data *output)
{
krb5_error_code ret;
const struct krb5_hash_provider *hash;
krb5_keyblock key = {0};
krb5_data hashed_secret = empty_data();
krb5_crypto_iov iov;

hash = &krb5int_hash_md5;

if (secret->length > hash->blocksize) {
/* Secret is too long, hash it to shrink it to 16 bits
* (see RFC2104 section 3). */
hashed_secret.length = hash->hashsize;
ret = alloc_data(&hashed_secret, hash->hashsize);
if (ret)
goto cleanup;

iov.flags = KRB5_CRYPTO_TYPE_DATA;
iov.data = *secret;

ret = hash->hash(&iov, 1, &hashed_secret);
if (ret)
goto cleanup;

secret = &hashed_secret;
}

key.length = secret->length;
key.contents = malloc(key.length);
if (!key.contents) {
ret = ENOMEM;
goto cleanup;
}

ret = k5_rand2key_direct(secret, &key);
if (ret)
goto cleanup;

ret = krb5int_hmac_keyblock(hash, &key, data, num_data, output);

cleanup:
zapfree(hashed_secret.data, hashed_secret.length);
zapfree(key.contents, key.length);

return ret;
}
1 change: 1 addition & 0 deletions src/lib/crypto/libk5crypto.exports
Original file line number Diff line number Diff line change
Expand Up @@ -103,3 +103,4 @@ krb5_c_prfplus
krb5_c_derive_prfplus
k5_enctype_to_ssf
krb5int_c_deprecated_enctype
krb5_krad_hmacmd5_checksum
17 changes: 17 additions & 0 deletions src/lib/krad/attr.c
Original file line number Diff line number Diff line change
Expand Up @@ -122,6 +122,23 @@ static const attribute_record attributes[UCHAR_MAX] = {
{"NAS-Port-Type", 4, 4, NULL, NULL},
{"Port-Limit", 4, 4, NULL, NULL},
{"Login-LAT-Port", 1, MAX_ATTRSIZE, NULL, NULL},
{NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
{NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
{NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
{NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
{NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
{NULL, 0, 0, NULL, NULL}, /* Reserved for tunnelling */
{NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
{NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
{NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
{NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
{NULL, 0, 0, NULL, NULL}, /* Reserved for Apple Remote Access Protocol */
{NULL, 0, 0, NULL, NULL}, /* Password-Retry */
{NULL, 0, 0, NULL, NULL}, /* Prompt */
{NULL, 0, 0, NULL, NULL}, /* Connect-Info */
{NULL, 0, 0, NULL, NULL}, /* Configuration-Token */
{NULL, 0, 0, NULL, NULL}, /* EAP-Message */
{"Message-Authenticator", MD5_DIGEST_SIZE, MD5_DIGEST_SIZE, NULL, NULL},
};

/* Encode User-Password attribute. */
Expand Down
63 changes: 52 additions & 11 deletions src/lib/krad/attrset.c
Original file line number Diff line number Diff line change
Expand Up @@ -164,34 +164,75 @@ krad_attrset_copy(const krad_attrset *set, krad_attrset **copy)
return 0;
}

static krb5_error_code
iter_attr_encode(krb5_context ctx, const char *secret,
const unsigned char *auth, krad_attr type,
const krb5_data *data, unsigned char outbuf[MAX_ATTRSETSIZE],
size_t *i)
{
unsigned char buffer[MAX_ATTRSIZE];
size_t attrlen;
krb5_error_code retval;

retval = kr_attr_encode(ctx, secret, auth, type, data, buffer, &attrlen);
if (retval)
return retval;

if (*i + attrlen + 2 > MAX_ATTRSETSIZE)
return EMSGSIZE;

outbuf[(*i)++] = type;
outbuf[(*i)++] = attrlen + 2;
memcpy(outbuf + *i, buffer, attrlen);
*i += attrlen;

return 0;
}

krb5_error_code
kr_attrset_encode(const krad_attrset *set, const char *secret,
const unsigned char *auth,
unsigned char outbuf[MAX_ATTRSETSIZE], size_t *outlen)
{
unsigned char buffer[MAX_ATTRSIZE];
krb5_error_code retval;
size_t i = 0, attrlen;
krad_attr msgauth_type;
const krb5_data *msgauth;
size_t i = 0;
attr *a;

if (set == NULL) {
*outlen = 0;
return 0;
}

K5_TAILQ_FOREACH(a, &set->list, list) {
retval = kr_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
buffer, &attrlen);
msgauth_type = krad_attr_name2num("Message-Authenticator");

msgauth = krad_attrset_get(set, msgauth_type, 0);
if (msgauth) {
/* Write Message-Authenticator as first attribute.
*
* draft-ietf-radext-deprecating-radius-03 (section 5.2.4):
* Servers MUST add Message-Authenticator as the first attribute in
* all responses to Access-Request packets.
*
* draft-ietf-radext-deprecating-radius-03 (section 5.2.1):
* The Message-Authenticator SHOULD be the first attribute in all
* Access-Request packets.
*/
retval = iter_attr_encode(set->ctx, secret, auth, msgauth_type, msgauth,
outbuf, &i);
if (retval != 0)
return retval;
}

if (i + attrlen + 2 > MAX_ATTRSETSIZE)
return EMSGSIZE;
K5_TAILQ_FOREACH(a, &set->list, list) {
if (a->type == msgauth_type)
continue;

outbuf[i++] = a->type;
outbuf[i++] = attrlen + 2;
memcpy(&outbuf[i], buffer, attrlen);
i += attrlen;
retval = iter_attr_encode(set->ctx, secret, auth, a->type, &a->attr,
outbuf, &i);
if (retval != 0)
return retval;
}

*outlen = i;
Expand Down
2 changes: 2 additions & 0 deletions src/lib/krad/internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,8 @@
#define UCHAR_MAX 255
#endif

#define MD5_DIGEST_SIZE 16

/* RFC 2865 */
#define MAX_ATTRSIZE (UCHAR_MAX - 2)
#define MAX_ATTRSETSIZE (KRAD_PACKET_SIZE_MAX - 20)
Expand Down
Loading

0 comments on commit 147d94b

Please sign in to comment.