Skip to content

Commit

Permalink
Add Message-Authenticator support
Browse files Browse the repository at this point in the history
  • Loading branch information
jrisc committed Sep 5, 2024
1 parent b9b654e commit 0ffe5a4
Show file tree
Hide file tree
Showing 7 changed files with 438 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 0ffe5a4

Please sign in to comment.