Skip to content
Permalink
Browse files

Fix various binary safety issues in rlm_mschap

  • Loading branch information
arr2036 committed Sep 25, 2019
1 parent 5723996 commit 0f04379c9c932320f98fa564211947bf86f950c1
@@ -89,41 +89,25 @@ int do_auth_wbclient(rlm_mschap_t const *inst, REQUEST *request,
uint8_t nthashhash[NT_DIGEST_LENGTH])
{
int ret = -1;
struct wbcContext *wb_ctx = NULL;
struct wbcAuthUserParams authparams;
struct wbcContext *wb_ctx = NULL;
struct wbcAuthUserParams *authparams;
wbcErr err;
ssize_t slen;
struct wbcAuthUserInfo *info = NULL;
struct wbcAuthErrorInfo *error = NULL;
char user_name_buf[500];
char domain_name_buf[500];
uint8_t resp[NT_LENGTH];

/*
* Clear the auth parameters - this is important, as
* there are options that will cause wbcAuthenticateUserEx
* to bomb out if not zero.
*/
memset(&authparams, 0, sizeof(authparams));

/*
* wb_username must be set for this function to be called
* wb_username must be set for this function to be called
*/
rad_assert(inst->wb_username);

MEM(authparams = talloc_zero_pooled_object(NULL, wbcAuthUserParams, 2, 1024));
/*
* Get the username and domain from the configuration
* Domain first so we don't leave holes in the pool
*/
slen = tmpl_expand(&authparams.account_name, user_name_buf, sizeof(user_name_buf),
request, inst->wb_username, NULL, NULL);
if (slen < 0) {
REDEBUG2("Unable to expand winbind_username");
goto finish;
}

if (inst->wb_domain) {
slen = tmpl_expand(&authparams.domain_name, domain_name_buf, sizeof(domain_name_buf),
request, inst->wb_domain, NULL, NULL);
slen = tmpl_aexpand(authparams, &authparams.domain_name, request, inst->wb_domain, NULL, NULL);
if (slen < 0) {
REDEBUG2("Unable to expand winbind_domain");
goto finish;
@@ -132,6 +116,14 @@ int do_auth_wbclient(rlm_mschap_t const *inst, REQUEST *request,
RWDEBUG2("No domain specified; authentication may fail because of this");
}

/*
* Get the username and domain from the configuration
*/
slen = tmpl_aexpand(authparams, &authparams.account_name, request, inst->wb_username, NULL, NULL);
if (slen < 0) {
REDEBUG2("Unable to expand winbind_username");
goto finish;
}

/*
* Build the wbcAuthUserParams structure with what we know
@@ -142,8 +134,7 @@ int do_auth_wbclient(rlm_mschap_t const *inst, REQUEST *request,
memcpy(resp, response, NT_LENGTH);
authparams.password.response.nt_data = resp;

memcpy(authparams.password.response.challenge, challenge,
sizeof(authparams.password.response.challenge));
memcpy(authparams.password.response.challenge, challenge, sizeof(authparams.password.response.challenge));

authparams.parameter_control |= WBC_MSV1_0_ALLOW_MSVCHAPV2 |
WBC_MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT |
@@ -158,8 +149,9 @@ int do_auth_wbclient(rlm_mschap_t const *inst, REQUEST *request,
goto finish;
}

RDEBUG2("sending authentication request user='%s' domain='%s'",
authparams.account_name, authparams.domain_name);
RDEBUG2("Sending authentication request user \"%pV\" domain \"%pV\"",
fr_box_strvalue_buffer(authparams.account_name),
fr_box_strvalue_buffer(authparams.domain_name));

err = wbcCtxAuthenticateUserEx(wb_ctx, &authparams, &info, &error);
if (err == WBC_ERR_AUTH_ERROR && inst->wb_retry_with_normalised_username) {
@@ -172,18 +164,23 @@ int do_auth_wbclient(rlm_mschap_t const *inst, REQUEST *request,
authparams.account_name);
if (!normalised_username) goto release;

RDEBUG2("Starting retry, normalised username %s to %s", authparams.account_name, normalised_username);
if (strcmp(authparams.account_name, normalised_username) == 0) goto release;
RDEBUG2("Starting retry, normalised username \"%pV\" -> \"%pV\"",
fr_box_strvalue_buffer(authparams.account_name),
fr_box_strvalue_buffer(normalised_username));

if (talloc_memcmp_bstr(authparams.account_name, normalised_username) == 0) goto release;

TALLOC_FREE(authparams.account_name);
authparams.account_name = normalised_username;

/* Set MS-CHAP-USER-NAME */
MEM(pair_update_request(&vp_chap_user_name, attr_ms_chap_user_name) >= 0);
fr_pair_value_bstrncpy(vp_chap_user_name,
normalised_username, talloc_array_length(normalised_username) - 1);

RDEBUG2("Retrying authentication request user='%s' domain='%s'",
authparams.account_name, authparams.domain_name);
RDEBUG2("Retrying authentication request user \"%pV\" domain \"%s\"",
fr_box_strvalue_buffer(authparams.account_name),
fr_box_strvalue_buffer(normalised_username));

/* Recalculate hash */
vp_challenge = fr_pair_find_by_da(request->packet->vps, attr_ms_chap_challenge, TAG_ANY);
@@ -198,10 +195,10 @@ int do_auth_wbclient(rlm_mschap_t const *inst, REQUEST *request,
goto release;
}

mschap_challenge_hash(vp_response->vp_octets + 2,
mschap_challenge_hash(authparams.password.response.challenge,
vp_response->vp_octets + 2,
vp_challenge->vp_octets,
normalised_username,
authparams.password.response.challenge);
vp_chap_user_name->vp_strvalue, vp_chap_user_name->vp_length, talloc);

err = wbcCtxAuthenticateUserEx(wb_ctx, &authparams, &info, &error);
release:
@@ -272,6 +269,7 @@ int do_auth_wbclient(rlm_mschap_t const *inst, REQUEST *request,
}

finish:
talloc_free(authparams);
if (info) wbcFreeMemory(info);
if (error) wbcFreeMemory(error);

@@ -69,18 +69,18 @@ int mschap_nt_password_hash(uint8_t *out, char const *password)
* implements RFC2759 ChallengeHash()
* generates 64 bit challenge
*/
void mschap_challenge_hash(uint8_t const *peer_challenge,
uint8_t const *auth_challenge,
char const *user_name, uint8_t *challenge )
void mschap_challenge_hash(uint8_t challenge[static MSCHAP_CHALLENGE_LENGTH],
uint8_t const *peer_challenge,
uint8_t const *auth_challenge,
char const *user_name, size_t user_name_len)
{
fr_sha1_ctx Context;
uint8_t hash[20];

fr_sha1_init(&Context);
fr_sha1_update(&Context, peer_challenge, 16);
fr_sha1_update(&Context, auth_challenge, 16);
fr_sha1_update(&Context, (uint8_t const *) user_name,
strlen(user_name));
fr_sha1_update(&Context, (uint8_t const *) user_name, user_name_len);
fr_sha1_final(hash, &Context);
memcpy(challenge, hash, 8); //-V512
}
@@ -90,7 +90,7 @@ void mschap_challenge_hash(uint8_t const *peer_challenge,
* according to RFC 2759 GenerateAuthenticatorResponse()
* returns 42-octet response string
*/
void mschap_auth_response(char const *username,
void mschap_auth_response(char const *username, size_t username_len,
uint8_t const *nt_hash_hash,
uint8_t const *ntresponse,
uint8_t const *peer_challenge, uint8_t const *auth_challenge,
@@ -121,7 +121,7 @@ void mschap_auth_response(char const *username,
fr_sha1_update(&Context, ntresponse, 24);
fr_sha1_update(&Context, magic1, 39);
fr_sha1_final(digest, &Context);
mschap_challenge_hash(peer_challenge, auth_challenge, username, challenge);
mschap_challenge_hash(challenge, peer_challenge, auth_challenge, username, username_len);
fr_sha1_init(&Context);
fr_sha1_update(&Context, digest, 20);
fr_sha1_update(&Context, challenge, 8);
@@ -147,3 +147,31 @@ void mschap_auth_response(char const *username,
}
}

/*
* add_reply() adds either MS-CHAP2-Success or MS-CHAP-Error
* attribute to reply packet
*/
void mschap_add_reply(REQUEST *request, uint8_t ident,
fr_dict_attr_t const *da, char const *value, size_t len)
{
VALUE_PAIR *vp;

MEM(pair_update_reply(&vp, da) >= 0);
if (vp->vp_type == FR_TYPE_STRING) {
char *p;

p = talloc_array(vp, char, len + 1 + 1); /* Account for the ident byte */
p[len + 1] = '\0'; /* Always \0 terminate */
p[0] = ident;
memcpy(p + 1, value, len);
fr_pair_value_strsteal(vp, p);
} else {
uint8_t *p;

p = talloc_array(vp, uint8_t, len + 1); /* Account for the ident byte */
p[0] = ident;
memcpy(p + 1, value, len);
fr_pair_value_memsteal(vp, p, false);
}
}

@@ -6,16 +6,21 @@ RCSIDH(mschap_h, "$Id$")

#define NT_DIGEST_LENGTH 16
#define LM_DIGEST_LENGTH 16
#define MSCHAP_CHALLENGE_LENGTH 8

int mschap_nt_password_hash(uint8_t *out, char const *password);
void mschap_challenge_hash(uint8_t const *peer_challenge,
uint8_t const *auth_challenge,
char const *user_name, uint8_t *challenge );

void mschap_auth_response(char const *username,
uint8_t const *nt_hash_hash,
uint8_t const *ntresponse,
uint8_t const *peer_challenge, uint8_t const *auth_challenge,
char *response);
void mschap_add_reply(REQUEST *request, unsigned char ident,
fr_dict_attr_t const *da, char const *value, size_t len);
int mschap_nt_password_hash(uint8_t out[static NT_DIGEST_LENGTH], char const *password);


void mschap_challenge_hash(uint8_t challenge[static MSCHAP_CHALLENGE_LENGTH],
uint8_t const *peer_challenge,
uint8_t const *auth_challenge,
char const *user_name, size_t user_name_len);

void mschap_auth_response(char const *use_rname, size_t user_name_len,
uint8_t const *nt_hash_hash,
uint8_t const *ntresponse,
uint8_t const *peer_challenge, uint8_t const *auth_challenge,
char *response);

void mschap_add_reply(REQUEST *request, unsigned char ident,
fr_dict_attr_t const *da, char const *value, size_t len);

0 comments on commit 0f04379

Please sign in to comment.
You can’t perform that action at this time.