diff --git a/src/Cedar/Proto_PPP.h b/src/Cedar/Proto_PPP.h index b6011a76..2943a276 100644 --- a/src/Cedar/Proto_PPP.h +++ b/src/Cedar/Proto_PPP.h @@ -413,6 +413,7 @@ bool PPPParseUsername(CEDAR *cedar, char *src, ETHERIP_ID *dst); void GenerateNtPasswordHash(UCHAR *dst, char *password); void GenerateNtPasswordHashHash(UCHAR *dst_hash, UCHAR *src_hash); void MsChapV2Server_GenerateChallenge(UCHAR *dst); +void MsChapV2Client_GenerateChallenge(UCHAR *dst); void MsChapV2_GenerateChallenge8(UCHAR *dst, UCHAR *client_challenge, UCHAR *server_challenge, char *username); void MsChapV2Client_GenerateResponse(UCHAR *dst, UCHAR *challenge8, UCHAR *nt_password_hash); void MsChapV2Server_GenerateResponse(UCHAR *dst, UCHAR *nt_password_hash_hash, UCHAR *client_response, UCHAR *challenge8); diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index e2efd2b9..6a5e0cf3 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -1914,7 +1914,7 @@ bool ServerAccept(CONNECTION *c) if (auth_ret == false) { - // Attempt external authentication registered users + // Attempt external authentication bool fail_ext_user_auth = false; if (GetGlobalServerFlag(GSF_DISABLE_RADIUS_AUTH) != 0) { @@ -1923,7 +1923,7 @@ bool ServerAccept(CONNECTION *c) if (fail_ext_user_auth == false) { - auth_ret = SamAuthUserByPlainPassword(c, hub, username, plain_password, false, mschap_v2_server_response_20, &radius_login_opt); + auth_ret = SamAuthUserByPlainPassword(c, hub, username, plain_password, true, mschap_v2_server_response_20, &radius_login_opt); } if (auth_ret && pol == NULL) @@ -1932,37 +1932,6 @@ bool ServerAccept(CONNECTION *c) } } - if (auth_ret == false) - { - // Attempt external authentication asterisk user - bool b = false; - bool fail_ext_user_auth = false; - - if (GetGlobalServerFlag(GSF_DISABLE_RADIUS_AUTH) != 0) - { - fail_ext_user_auth = true; - } - - if (fail_ext_user_auth == false) - { - AcLock(hub); - { - b = AcIsUser(hub, "*"); - } - AcUnlock(hub); - - // If there is asterisk user, log on as the user - if (b) - { - auth_ret = SamAuthUserByPlainPassword(c, hub, username, plain_password, true, mschap_v2_server_response_20, &radius_login_opt); - if (auth_ret && pol == NULL) - { - pol = SamGetUserPolicy(hub, "*"); - } - } - } - } - if (pol != NULL) { no_save_password = pol->NoSavePassword; diff --git a/src/Cedar/Sam.c b/src/Cedar/Sam.c index c8b63e40..004c018d 100644 --- a/src/Cedar/Sam.c +++ b/src/Cedar/Sam.c @@ -9,6 +9,7 @@ #include "Account.h" #include "Cedar.h" +#include "Connection.h" #include "Hub.h" #include "IPC.h" #include "Proto_PPP.h" @@ -420,7 +421,7 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p bool auth_by_nt = false; HUB *h; // Validate arguments - if (hub == NULL || c == NULL || username == NULL) + if (hub == NULL || c == NULL || username == NULL || password == NULL || opt == NULL) { return false; } @@ -438,7 +439,14 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p AcLock(hub); { USER *u; - u = AcGetUser(hub, ast == false ? username : "*"); + + // Find exact user first + u = AcGetUser(hub, username); + if (u == NULL && ast) + { + u = AcGetUser(hub, "*"); + } + if (u) { Lock(u->lock); @@ -447,7 +455,7 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p { // Radius authentication AUTHRADIUS *auth = (AUTHRADIUS *)u->AuthData; - if (ast || auth->RadiusUsername == NULL || UniStrLen(auth->RadiusUsername) == 0) + if (auth->RadiusUsername == NULL || UniStrLen(auth->RadiusUsername) == 0) { if( IsEmptyStr(h->RadiusRealm) == false ) { @@ -472,7 +480,7 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p { // NT authentication AUTHNT *auth = (AUTHNT *)u->AuthData; - if (ast || auth->NtUsername == NULL || UniStrLen(auth->NtUsername) == 0) + if (auth->NtUsername == NULL || UniStrLen(auth->NtUsername) == 0) { name = CopyStrToUni(username); } @@ -508,10 +516,75 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p char suffix_filter[MAX_SIZE]; wchar_t suffix_filter_w[MAX_SIZE]; UINT interval; + EAP_CLIENT *eap = NULL; + char password1[MAX_SIZE]; + UCHAR client_challenge[16]; + UCHAR server_challenge[16]; + UCHAR challenge8[8]; + UCHAR client_response[24]; + UCHAR ntlm_hash[MD5_SIZE]; Zero(suffix_filter, sizeof(suffix_filter)); Zero(suffix_filter_w, sizeof(suffix_filter_w)); + // MSCHAPv2 / EAP wrapper for SEVPN + if (c->IsInProc == false && StartWith(password, IPC_PASSWORD_MSCHAPV2_TAG) == false) + { + char client_ip_str[MAX_SIZE]; + char utf8[MAX_SIZE]; + + // Convert the user name to a Unicode string + UniToStr(utf8, sizeof(utf8), name); + utf8[MAX_SIZE-1] = 0; + + Zero(client_ip_str, sizeof(client_ip_str)); + if (c != NULL && c->FirstSock != NULL) + { + IPToStr(client_ip_str, sizeof(client_ip_str), &c->FirstSock->RemoteIP); + } + + if (hub->RadiusConvertAllMsChapv2AuthRequestToEap) + { + // Do EAP or PEAP + eap = HubNewEapClient(hub->Cedar, hub->Name, client_ip_str, utf8, opt->In_VpnProtocolState); + + // Prepare MSCHAP response and replace plain password + if (eap != NULL) + { + char server_challenge_hex[MAX_SIZE]; + char client_challenge_hex[MAX_SIZE]; + char client_response_hex[MAX_SIZE]; + char eap_client_hex[64]; + + MsChapV2Client_GenerateChallenge(client_challenge); + GenerateNtPasswordHash(ntlm_hash, password); + Copy(server_challenge, eap->MsChapV2Challenge.Chap_ChallengeValue, 16); + MsChapV2_GenerateChallenge8(challenge8, client_challenge, server_challenge, utf8); + MsChapV2Client_GenerateResponse(client_response, challenge8, ntlm_hash); + + BinToStr(server_challenge_hex, sizeof(server_challenge_hex), + server_challenge, sizeof(server_challenge)); + BinToStr(client_challenge_hex, sizeof(client_challenge_hex), + client_challenge, sizeof(client_challenge)); + BinToStr(client_response_hex, sizeof(client_response_hex), + client_response, sizeof(client_response)); + BinToStr(eap_client_hex, sizeof(eap_client_hex), &eap, 8); + Format(password1, sizeof(password1), "%s%s:%s:%s:%s:%s", + IPC_PASSWORD_MSCHAPV2_TAG, + utf8, + server_challenge_hex, + client_challenge_hex, + client_response_hex, + eap_client_hex); + password = password1; + } + } + else + { + // Todo: Do MSCHAPv2 + } + } + // Get the Radius server information if (GetRadiusServerEx2(hub, radius_server_addr, sizeof(radius_server_addr), &radius_server_port, radius_secret, sizeof(radius_secret), &interval, suffix_filter, sizeof(suffix_filter))) { @@ -528,10 +601,7 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p if (b) { - if (opt != NULL) - { - opt->Out_IsRadiusLogin = true; - } + opt->Out_IsRadiusLogin = true; } } @@ -541,6 +611,11 @@ bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *p { HLog(hub, "LH_NO_RADIUS_SETTING", name); } + + if (eap != NULL) + { + ReleaseEapClient(eap); + } } else {