diff --git a/src/Cedar/Cedar.h b/src/Cedar/Cedar.h index 097b6a4c..ec1b18b9 100644 --- a/src/Cedar/Cedar.h +++ b/src/Cedar/Cedar.h @@ -366,6 +366,7 @@ #define AUTHTYPE_ROOTCERT 3 // Root certificate which is issued by trusted Certificate Authority #define AUTHTYPE_RADIUS 4 // Radius authentication #define AUTHTYPE_NT 5 // Windows NT authentication +#define AUTHTYPE_EXTERNAL 96 // External authentication (completed) #define AUTHTYPE_WIREGUARD_KEY 97 // WireGuard public key authentication #define AUTHTYPE_OPENVPN_CERT 98 // TLS client certificate authentication #define AUTHTYPE_TICKET 99 // Ticket authentication diff --git a/src/Cedar/Hub.c b/src/Cedar/Hub.c index f0006a6c..01412ddc 100644 --- a/src/Cedar/Hub.c +++ b/src/Cedar/Hub.c @@ -91,7 +91,8 @@ UINT num_admin_options = sizeof(admin_options) / sizeof(ADMIN_OPTION); // Create an EAP client for the specified Virtual Hub -EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username, char *vpn_protocol_state_str) +EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username, char *vpn_protocol_state_str, bool proxy_only, + PPP_LCP **response, UCHAR last_recv_eapid) { HUB *hub = NULL; EAP_CLIENT *ret = NULL; @@ -137,7 +138,7 @@ EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, ch if (GetIP(&ip, radius_servers_list->Token[i])) { eap = NewEapClient(&ip, radius_port, radius_secret, radius_retry_interval, - RADIUS_INITIAL_EAP_TIMEOUT, client_ip_str, username, hubname); + RADIUS_INITIAL_EAP_TIMEOUT, client_ip_str, username, hubname, last_recv_eapid); if (eap != NULL) { @@ -146,7 +147,19 @@ EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, ch StrCpy(eap->In_VpnProtocolState, sizeof(eap->In_VpnProtocolState), vpn_protocol_state_str); } - if (use_peap == false) + if (proxy_only && response != NULL) + { + // EAP proxy for EAP-capable clients + PPP_LCP *lcp = EapClientSendEapIdentity(eap); + if (lcp != NULL) + { + *response = lcp; + eap->GiveupTimeout = RADIUS_RETRY_TIMEOUT; + ret = eap; + finish = true; + } + } + else if (use_peap == false) { // EAP if (EapClientSendMsChapv2AuthRequest(eap)) diff --git a/src/Cedar/Hub.h b/src/Cedar/Hub.h index d63f118f..e16bc66a 100644 --- a/src/Cedar/Hub.h +++ b/src/Cedar/Hub.h @@ -537,7 +537,8 @@ bool IsUserMatchInUserList(LIST *o, char *filename, UINT64 user_hash); bool IsUserMatchInUserListWithCacheExpires(LIST *o, char *filename, UINT64 user_hash, UINT64 lifetime); bool IsUserMatchInUserListWithCacheExpiresAcl(LIST *o, char *name_in_acl, UINT64 user_hash, UINT64 lifetime); bool CheckMaxLoggedPacketsPerMinute(SESSION *s, UINT max_packets, UINT64 now); -EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username, char *vpn_protocol_state_str); +EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username, char *vpn_protocol_state_str, bool proxy_only, + PPP_LCP **response, UCHAR last_recv_eapid); #endif // HUB_H diff --git a/src/Cedar/IPC.c b/src/Cedar/IPC.c index ef8a7bef..67dfdf23 100644 --- a/src/Cedar/IPC.c +++ b/src/Cedar/IPC.c @@ -244,7 +244,8 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code) param->UserName, param->Password, param->WgKey, error_code, ¶m->ClientIp, param->ClientPort, ¶m->ServerIp, param->ServerPort, param->ClientHostname, param->CryptName, - param->BridgeMode, param->Mss, NULL, param->ClientCertificate, param->Layer); + param->BridgeMode, param->Mss, NULL, param->ClientCertificate, param->RadiusOK, + param->Layer); return ipc; } @@ -253,7 +254,7 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code) IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password, char *wg_key, UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, char *client_hostname, char *crypt_name, - bool bridge_mode, UINT mss, EAP_CLIENT *eap_client, X *client_certificate, + bool bridge_mode, UINT mss, EAP_CLIENT *eap_client, X *client_certificate, bool external_auth, UINT layer) { IPC *ipc; @@ -360,6 +361,10 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char { p = PackLoginWithOpenVPNCertificate(hubname, username, client_certificate); } + else if (external_auth) + { + p = PackLoginWithExternal(hubname, username); + } else { p = PackLoginWithPlainPassword(hubname, username, password); diff --git a/src/Cedar/IPC.h b/src/Cedar/IPC.h index 9dc1805d..1a341ec8 100644 --- a/src/Cedar/IPC.h +++ b/src/Cedar/IPC.h @@ -91,6 +91,7 @@ struct IPC_PARAM UINT Mss; bool IsL3Mode; X *ClientCertificate; + bool RadiusOK; UINT Layer; }; @@ -180,7 +181,7 @@ struct IPC_IPV6_ROUTER_ADVERTISEMENT IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password, char *wg_key, UINT *error_code, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, char *client_hostname, char *crypt_name, - bool bridge_mode, UINT mss, EAP_CLIENT *eap_client, X *client_certificate, + bool bridge_mode, UINT mss, EAP_CLIENT *eap_client, X *client_certificate, bool external_auth, UINT layer); IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code); IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address); diff --git a/src/Cedar/Proto_EtherIP.c b/src/Cedar/Proto_EtherIP.c index 3e457774..6f47ac64 100644 --- a/src/Cedar/Proto_EtherIP.c +++ b/src/Cedar/Proto_EtherIP.c @@ -75,7 +75,7 @@ void EtherIPIpcConnectThread(THREAD *t, void *p) &s->ClientIP, s->ClientPort, &s->ServerIP, s->ServerPort, tmp, - s->CryptName, true, mss, NULL, NULL, IPC_LAYER_2); + s->CryptName, true, mss, NULL, NULL, false, IPC_LAYER_2); if (ipc != NULL) { diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index 0b8fa2dc..2c586e30 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -50,9 +50,9 @@ void PPPThread(THREAD *thread, void *param) p->SentReqPacketList = NewList(NULL); p->DelayedPackets = NewList(PPPDelayedPacketsComparator); - p->MsChapV2_UseDoubleMsChapV2 = CedarIsThereAnyEapEnabledRadiusConfig(p->Cedar); + p->UseEapRadius = CedarIsThereAnyEapEnabledRadiusConfig(p->Cedar); - Debug("MsChapV2_UseDoubleMsChapV2 = 0x%x\n", p->MsChapV2_UseDoubleMsChapV2); + Debug("UseEapRadius = 0x%x\n", p->UseEapRadius); //// Link establishment phase @@ -292,6 +292,7 @@ void PPPThread(THREAD *thread, void *param) eapPacket = lcpEap->Data; Copy(eapPacket->Data, welcomeMessage, StrLen(welcomeMessage)); PPPSetStatus(p, PPP_STATUS_AUTHENTICATING); + PPPFreeEapClient(p); if (PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcpEap) == false) { PPPSetStatus(p, PPP_STATUS_FAIL); @@ -1056,7 +1057,7 @@ bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET * ok = PPPParseMSCHAP2ResponsePacketEx(p, chap, use_eap); // If we got only first packet of double CHAP then send second challenge - if (ok && p->MsChapV2_UseDoubleMsChapV2 && p->EapClient != NULL && p->Ipc == NULL) + if (ok && p->UseEapRadius && p->EapClient != NULL && p->Ipc == NULL) { lcp = BuildMSCHAP2ChallengePacket(p); if (PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_CHAP, lcp) == false) @@ -1273,6 +1274,12 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP); ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2; + // Forward EAP response to Radius server + if (p->EapClient != NULL) + { + return PPPProcessEapResponseForRadius(p, eap_packet, eap_datasize); + } + switch (eap_packet->Type) { case PPP_EAP_TYPE_IDENTITY: @@ -1339,20 +1346,23 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req { case AUTHTYPE_RADIUS: // Create EAP client if needed - if (p->MsChapV2_UseDoubleMsChapV2 && p->EapClient == NULL) + if (p->EapClient == NULL) { char client_ip_tmp[256]; + PPP_LCP *response = NULL; IPToStr(client_ip_tmp, sizeof(client_ip_tmp), &p->ClientIP); - Debug("EAP-MSCHAPv2 creating EAP RADIUS client\n"); - p->EapClient = HubNewEapClient(p->Cedar, p->Eap_Identity.HubName, client_ip_tmp, p->Eap_Identity.UserName, "L3:PPP"); + Debug("Creating EAP RADIUS client\n"); + p->EapClient = HubNewEapClient(p->Cedar, p->Eap_Identity.HubName, client_ip_tmp, p->Eap_Identity.UserName, "L3:PPP", true, + &response, pp->Lcp->Id); - if (p->EapClient == NULL) + if (p->EapClient == NULL || response == NULL) { PPP_PACKET *pack = ZeroMalloc(sizeof(PPP_PACKET)); pack->IsControl = true; pack->Protocol = PPP_PROTOCOL_EAP; PPPSetStatus(p, PPP_STATUS_AUTH_FAIL); pack->Lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, p->Eap_PacketId); + Debug("Failed to connect to a RADIUS server\n"); if (PPPSendPacketAndFree(p, pack) == false) { @@ -1360,8 +1370,19 @@ bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req WHERE; return false; } - break; } + else + { + // Send first response to client + if (PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, response) == false) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + } + + break; } case AUTHTYPE_ANONYMOUS: case AUTHTYPE_PASSWORD: @@ -1505,6 +1526,84 @@ bool PPPProcessIPv6CPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET * return true; } +// Process EAP response for RADIUS (as proxy) +bool PPPProcessEapResponseForRadius(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eap_datasize) +{ + PPP_LCP *lcp; + IPC *ipc; + UINT error_code; + + if (p == NULL || eap_packet == NULL || p->EapClient == NULL) + { + return false; + } + + lcp = EapClientSendEapRequest(p->EapClient, eap_packet, eap_datasize); + if (lcp == NULL) + { + return false; + } + + switch (lcp->Code) + { + case PPP_EAP_CODE_REQUEST: + // Send back to client + if (PPPSendAndRetransmitRequest(p, PPP_PROTOCOL_EAP, lcp) == false) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + + return true; + case PPP_EAP_CODE_SUCCESS: + if (p->Ipc == NULL) + { + Debug("PPP Radius creating IPC\n"); + ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, p->Eap_Identity.HubName, p->Eap_Identity.UserName, "", NULL, + &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, + p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient, NULL, + true, IPC_LAYER_3); + + if (ipc != NULL) + { + p->Ipc = ipc; + + // Setting user timeouts + p->PacketRecvTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000 * 3 / 4; // setting to 3/4 of the user timeout + p->DataTimeout = (UINT64)p->Ipc->Policy->TimeOut * 1000; + if (p->TubeRecv != NULL) + { + p->TubeRecv->DataTimeout = p->DataTimeout; + } + p->UserConnectionTimeout = (UINT64)p->Ipc->Policy->AutoDisconnect * 1000; + p->UserConnectionTick = Tick64(); + p->AuthOk = true; + PPPSetStatus(p, PPP_STATUS_AUTH_SUCCESS); + break; + } + } + case PPP_EAP_CODE_FAILURE: + default: + PPPSetStatus(p, PPP_STATUS_AUTH_FAIL); + break; + } + + // Send success or failure + PPP_PACKET* pack; + pack = ZeroMalloc(sizeof(PPP_PACKET)); + pack->IsControl = true; + pack->Protocol = PPP_PROTOCOL_EAP; + pack->Lcp = lcp; + if (PPPSendPacketAndFree(p, pack) == false) + { + PPPSetStatus(p, PPP_STATUS_FAIL); + WHERE; + return false; + } + + return true; +} // Processes request packets bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) @@ -1754,7 +1853,7 @@ bool PPPProcessPAPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp) ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password, NULL, &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, NULL, - IPC_LAYER_3); + false, IPC_LAYER_3); if (ipc != NULL) { @@ -3063,10 +3162,10 @@ bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp, bool use_eap) // Normal MSCHAPv2 only // For EAP-MSCHAPv2, EAP client is created before sending the challenge - if (p->MsChapV2_UseDoubleMsChapV2 && p->EapClient == NULL && use_eap == false) + if (p->UseEapRadius && p->EapClient == NULL && use_eap == false) { Debug("Double MSCHAPv2 creating EAP client\n"); - eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id, "L3:PPP"); + eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id, "L3:PPP", false, NULL, 0); // We do not know the user's auth type, so do not fail PPP if eap is null if (eap) @@ -3083,7 +3182,7 @@ bool PPPParseMSCHAP2ResponsePacketEx(PPP_SESSION *p, PPP_LCP *lcp, bool use_eap) ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password, NULL, &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient, NULL, - + IPC_LAYER_3); + false, IPC_LAYER_3); if (ipc != NULL) { @@ -3708,7 +3807,7 @@ bool PPPProcessEAPTlsResponse(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eapSize) ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, p->Eap_Identity.HubName, p->Eap_Identity.UserName, "", NULL, &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, p->Eap_TlsCtx.ClientCert.X, - IPC_LAYER_3); + false, IPC_LAYER_3); // We use the SAM authentication here, because the handshake can still fail at this point if (ipc != NULL) diff --git a/src/Cedar/Proto_PPP.h b/src/Cedar/Proto_PPP.h index b6011a76..1278fbcd 100644 --- a/src/Cedar/Proto_PPP.h +++ b/src/Cedar/Proto_PPP.h @@ -294,7 +294,7 @@ struct PPP_SESSION UINT MsChapV2_ErrorCode; // Authentication failure error code of MS-CHAPv2 UINT MsChapV2_PacketId; // MS-CHAPv2 Packet ID - bool MsChapV2_UseDoubleMsChapV2; // Use the double-MSCHAPv2 technique + bool UseEapRadius; // Use EAP for RADIUS authentication EAP_CLIENT *EapClient; // EAP client UCHAR ServerInterfaceId[8]; // Server IPv6CP Interface Identifier @@ -343,6 +343,7 @@ bool PPPProcessCHAPResponsePacketEx(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET * bool PPPProcessIPCPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessEAPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); bool PPPProcessIPv6CPResponsePacket(PPP_SESSION *p, PPP_PACKET *pp, PPP_PACKET *req); +bool PPPProcessEapResponseForRadius(PPP_SESSION *p, PPP_EAP *eap_packet, UINT eap_datasize); // Request packets bool PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); bool PPPProcessLCPRequestPacket(PPP_SESSION *p, PPP_PACKET *pp); @@ -413,6 +414,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..761bc773 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -1702,6 +1702,9 @@ bool ServerAccept(CONNECTION *c) case CLIENT_AUTHTYPE_CERT: authtype_str = _UU("LH_AUTH_CERT"); break; + case AUTHTYPE_EXTERNAL: + authtype_str = _UU("LH_AUTH_EXTERNAL"); + break; case AUTHTYPE_WIREGUARD_KEY: authtype_str = _UU("LH_AUTH_WIREGUARD_KEY"); break; @@ -1829,6 +1832,11 @@ bool ServerAccept(CONNECTION *c) // Anonymous authentication (this have been already attempted) break; + case AUTHTYPE_EXTERNAL: + // External authentication already completed + auth_ret = true; + break; + case AUTHTYPE_TICKET: // Ticket authentication if (PackGetDataSize(p, "ticket") == SHA1_SIZE) @@ -1914,7 +1922,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 +1931,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 +1940,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; @@ -6742,6 +6719,25 @@ PACK *PackLoginWithAnonymous(char *hubname, char *username) return p; } +// Create a packet for external login +PACK *PackLoginWithExternal(char *hubname, char *username) +{ + PACK *p; + // Validate arguments + if (hubname == NULL || username == NULL) + { + return NULL; + } + + p = NewPack(); + PackAddStr(p, "method", "login"); + PackAddStr(p, "hubname", hubname); + PackAddStr(p, "username", username); + PackAddInt(p, "authtype", AUTHTYPE_EXTERNAL); + + return p; +} + // Create a packet for the additional connection PACK *PackAdditionalConnect(UCHAR *session_key) { diff --git a/src/Cedar/Protocol.h b/src/Cedar/Protocol.h index ebcc1052..28f68717 100644 --- a/src/Cedar/Protocol.h +++ b/src/Cedar/Protocol.h @@ -134,6 +134,7 @@ void PackAddPolicy(PACK *p, POLICY *y); PACK *PackWelcome(SESSION *s); PACK *PackHello(void *random, UINT ver, UINT build, char *server_str); bool GetHello(PACK *p, void *random, UINT *ver, UINT *build, char *server_str, UINT server_str_size); +PACK *PackLoginWithExternal(char *hubname, char *username); PACK *PackLoginWithAnonymous(char *hubname, char *username); PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password); PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password); diff --git a/src/Cedar/Radius.c b/src/Cedar/Radius.c index 067ea5c5..14c0821c 100644 --- a/src/Cedar/Radius.c +++ b/src/Cedar/Radius.c @@ -10,6 +10,7 @@ #include "Connection.h" #include "IPC.h" #include "Server.h" +#include "Proto_PPP.h" #include "Mayaqua/DNS.h" #include "Mayaqua/Internat.h" @@ -19,7 +20,7 @@ #include "Mayaqua/Tick64.h" // send PEAP-MSCHAPv2 auth client response -bool PeapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge) +bool PeapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge, char *username) { bool ret = false; EAP_MSCHAPV2_RESPONSE msg1; @@ -37,13 +38,13 @@ bool PeapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_respo msg1.Type = EAP_TYPE_MS_AUTH; msg1.Chap_Opcode = EAP_MSCHAPV2_OP_RESPONSE; msg1.Chap_Id = e->MsChapV2Challenge.Chap_Id; - msg1.Chap_Len = Endian16(54 + StrLen(e->Username)); + msg1.Chap_Len = Endian16(54 + StrLen(username)); msg1.Chap_ValueSize = 49; Copy(msg1.Chap_PeerChallenge, client_challenge, 16); Copy(msg1.Chap_NtResponse, client_response, 24); - Copy(msg1.Chap_Name, e->Username, MIN(StrLen(e->Username), 255)); + Copy(msg1.Chap_Name, username, MIN(StrLen(username), 255)); - if (SendPeapPacket(e, &msg1, 59 + StrLen(e->Username)) && + if (SendPeapPacket(e, &msg1, 59 + StrLen(username)) && GetRecvPeapMessage(e, &msg2)) { if (msg2.Type == EAP_TYPE_MS_AUTH && @@ -300,7 +301,7 @@ bool SendPeapRawPacket(EAP_CLIENT *e, UCHAR *peap_data, UINT peap_size) Add(send_packet->AvpList, eap_avp); - response_packet = EapSendPacketAndRecvResponse(e, send_packet); + response_packet = EapSendPacketAndRecvResponse(e, send_packet, true); if (response_packet != NULL) { @@ -502,7 +503,7 @@ bool StartPeapClient(EAP_CLIENT *e) Copy(eap1->Data, e->Username, StrLen(e->Username)); Add(request1->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, eap1, StrLen(e->Username) + 5)); - response1 = EapSendPacketAndRecvResponse(e, request1); + response1 = EapSendPacketAndRecvResponse(e, request1, true); if (response1 != NULL) { @@ -532,7 +533,7 @@ bool StartPeapClient(EAP_CLIENT *e) Add(request2->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, eap2, 6)); - response2 = EapSendPacketAndRecvResponse(e, request2); + response2 = EapSendPacketAndRecvResponse(e, request2, true); if (response2 != NULL && response2->Parse_EapMessage_DataSize != 0 && response2->Parse_EapMessage != NULL) { @@ -632,7 +633,7 @@ void EapSetRadiusGeneralAttributes(RADIUS_PACKET *r, EAP_CLIENT *e) } // Send a MSCHAPv2 client auth response1 -bool EapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge) +bool EapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge, char *username) { bool ret = false; RADIUS_PACKET *request1 = NULL; @@ -657,20 +658,20 @@ bool EapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_respon eap1 = ZeroMalloc(sizeof(EAP_MSCHAPV2_RESPONSE)); eap1->Code = EAP_CODE_RESPONSE; - eap1->Id = e->NextEapId++; - eap1->Len = Endian16(59 + StrLen(e->Username)); + eap1->Id = e->LastRecvEapId; + eap1->Len = Endian16(59 + StrLen(username)); eap1->Type = EAP_TYPE_MS_AUTH; eap1->Chap_Opcode = EAP_MSCHAPV2_OP_RESPONSE; eap1->Chap_Id = e->MsChapV2Challenge.Chap_Id; - eap1->Chap_Len = Endian16(54 + StrLen(e->Username)); + eap1->Chap_Len = Endian16(54 + StrLen(username)); eap1->Chap_ValueSize = 49; Copy(eap1->Chap_PeerChallenge, client_challenge, 16); Copy(eap1->Chap_NtResponse, client_response, 24); - Copy(eap1->Chap_Name, e->Username, MIN(StrLen(e->Username), 255)); + Copy(eap1->Chap_Name, username, MIN(StrLen(username), 255)); - Add(request1->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, eap1, StrLen(e->Username) + 59)); + Add(request1->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, eap1, StrLen(username) + 59)); - response1 = EapSendPacketAndRecvResponse(e, request1); + response1 = EapSendPacketAndRecvResponse(e, request1, false); if (response1 != NULL) { @@ -713,14 +714,14 @@ bool EapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_respon eap2 = ZeroMalloc(sizeof(EAP_MSCHAPV2_SUCCESS_CLIENT)); eap2->Code = EAP_CODE_RESPONSE; - eap2->Id = e->NextEapId++; + eap2->Id = e->LastRecvEapId; eap2->Len = Endian16(6); eap2->Type = EAP_TYPE_MS_AUTH; eap2->Chap_Opcode = EAP_MSCHAPV2_OP_SUCCESS; Add(request2->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, eap2, 6)); - response2 = EapSendPacketAndRecvResponse(e, request2); + response2 = EapSendPacketAndRecvResponse(e, request2, false); if (response2 != NULL) { @@ -770,13 +771,13 @@ bool EapClientSendMsChapv2AuthRequest(EAP_CLIENT *e) eap1 = ZeroMalloc(sizeof(EAP_MESSAGE)); eap1->Code = EAP_CODE_RESPONSE; - eap1->Id = e->NextEapId++; + eap1->Id = e->LastRecvEapId; eap1->Len = Endian16(StrLen(e->Username) + 5); eap1->Type = EAP_TYPE_IDENTITY; Copy(eap1->Data, e->Username, StrLen(e->Username)); Add(request1->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, eap1, StrLen(e->Username) + 5)); - response1 = EapSendPacketAndRecvResponse(e, request1); + response1 = EapSendPacketAndRecvResponse(e, request1, false); if (response1 != NULL) { @@ -799,14 +800,14 @@ bool EapClientSendMsChapv2AuthRequest(EAP_CLIENT *e) eap2 = ZeroMalloc(sizeof(EAP_MESSAGE)); eap2->Code = EAP_CODE_RESPONSE; - eap2->Id = e->NextEapId++; + eap2->Id = e->LastRecvEapId; eap2->Len = Endian16(6); eap2->Type = EAP_TYPE_LEGACY_NAK; eap2->Data[0] = EAP_TYPE_MS_AUTH; Add(request2->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, eap2, 6)); - response2 = EapSendPacketAndRecvResponse(e, request2); + response2 = EapSendPacketAndRecvResponse(e, request2, false); if (response2 != NULL && response2->Parse_EapMessage_DataSize != 0 && response2->Parse_EapMessage != NULL) { @@ -849,8 +850,141 @@ LABEL_PARSE_EAP: return ret; } +// Send a EAP identity request to Radius +PPP_LCP *EapClientSendEapIdentity(EAP_CLIENT *e) +{ + PPP_LCP *lcp = NULL; + RADIUS_PACKET *request = NULL; + RADIUS_PACKET *response = NULL; + EAP_MESSAGE *eap1 = NULL; + if (e == NULL) + { + return NULL; + } + + request = NewRadiusPacket(RADIUS_CODE_ACCESS_REQUEST, e->NextRadiusPacketId++); + EapSetRadiusGeneralAttributes(request, e); + + eap1 = ZeroMalloc(sizeof(EAP_MESSAGE)); + eap1->Code = EAP_CODE_RESPONSE; + eap1->Id = e->LastRecvEapId; + eap1->Len = Endian16(StrLen(e->Username) + 5); + eap1->Type = EAP_TYPE_IDENTITY; + Copy(eap1->Data, e->Username, StrLen(e->Username)); + Add(request->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, eap1, StrLen(e->Username) + 5)); + Debug("Radius proxy: send access-request %d with EAP code %d id %d type %d datasize %d\n", + request->PacketId, eap1->Code, eap1->Id, eap1->Type, StrLen(e->Username)); + + response = EapSendPacketAndRecvResponse(e, request, false); + + if (response != NULL) + { + if (response->Parse_EapMessage_DataSize >= 5 && response->Parse_EapMessage != NULL) + { + EAP_MESSAGE *eap2 = response->Parse_EapMessage; + UINT datasize = response->Parse_EapMessage_DataSize - 5; + lcp = BuildEAPPacketEx(eap2->Code, eap2->Id, eap2->Type, datasize); + PPP_EAP *eap_packet = lcp->Data; + Copy(eap_packet->Data, eap2->Data, datasize); + Debug("Radius proxy: received access-challenge %d with EAP code %d id %d type %d datasize %d\n", + response->PacketId, eap2->Code, eap2->Id, eap2->Type, datasize); + } + } + + FreeRadiusPacket(request); + FreeRadiusPacket(response); + Free(eap1); + + return lcp; +} + +// Send generic EAP Radius request (client EAP response) and get reply +PPP_LCP *EapClientSendEapRequest(EAP_CLIENT *e, PPP_EAP *eap_request, UINT request_datasize) +{ + PPP_LCP *lcp = NULL; + RADIUS_PACKET *request = NULL; + RADIUS_PACKET *response = NULL; + EAP_MESSAGE *eap1 = NULL; + UCHAR *pos; + UINT remaining; + if (e == NULL || eap_request == NULL) + { + return NULL; + } + + request = NewRadiusPacket(RADIUS_CODE_ACCESS_REQUEST, e->NextRadiusPacketId++); + EapSetRadiusGeneralAttributes(request, e); + + if (e->LastStateSize != 0) + { + Add(request->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_STATE, 0, 0, + e->LastState, e->LastStateSize)); + } + + eap1 = ZeroMalloc(sizeof(EAP_MESSAGE)); + eap1->Code = EAP_CODE_RESPONSE; + eap1->Id = e->LastRecvEapId; + eap1->Len = Endian16(request_datasize + 5); + eap1->Type = eap_request->Type; + Copy(eap1->Data, eap_request->Data, request_datasize); + + // Fragmentation + pos = (UCHAR *)eap1; + remaining = request_datasize + 5; + while (remaining > 0) + { + UINT size = MIN(253, remaining); + Add(request->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_EAP_MESSAGE, 0, 0, pos, size)); + pos += size; + remaining -= size; + } + Debug("Radius proxy: send access-request %d with EAP code %d id %d type %d datasize %d\n", + request->PacketId, eap1->Code, eap1->Id, eap1->Type, request_datasize); + + response = EapSendPacketAndRecvResponse(e, request, false); + + if (response != NULL) + { + switch (response->Code) + { + case RADIUS_CODE_ACCESS_CHALLENGE: + if (response->Parse_EapMessage_DataSize >= 5 && response->Parse_EapMessage != NULL) + { + EAP_MESSAGE *eap2 = response->Parse_EapMessage; + UINT datasize = response->Parse_EapMessage_DataSize - 5; + lcp = BuildEAPPacketEx(eap2->Code, eap2->Id, eap2->Type, datasize); + PPP_EAP *eap_packet = lcp->Data; + Copy(eap_packet->Data, eap2->Data, datasize); + Debug("Radius proxy: received access-challenge %d with EAP code %d id %d type %d datasize %d\n", + response->PacketId, eap2->Code, eap2->Id, eap2->Type, datasize); + } + else + { + Debug("Radius proxy error: received access-challenge %d without EAP\n", response->PacketId); + lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, e->LastRecvEapId); + } + break; + case RADIUS_CODE_ACCESS_ACCEPT: + Debug("Radius proxy: received access-accept %d\n", response->PacketId); + lcp = NewPPPLCP(PPP_EAP_CODE_SUCCESS, e->LastRecvEapId); + break; + case RADIUS_CODE_ACCESS_REJECT: + default: + Debug("Radius proxy: received access-reject %d\n", response->PacketId); + lcp = NewPPPLCP(PPP_EAP_CODE_FAILURE, e->LastRecvEapId); + break; + } + } + + FreeRadiusPacket(request); + FreeRadiusPacket(response); + Free(eap1); + + return lcp; +} + // Send a packet and recv a response -RADIUS_PACKET *EapSendPacketAndRecvResponse(EAP_CLIENT *e, RADIUS_PACKET *r) +RADIUS_PACKET *EapSendPacketAndRecvResponse(EAP_CLIENT *e, RADIUS_PACKET *r, bool parse_inner) { SOCKSET set; UINT64 giveup_tick = 0; @@ -990,7 +1124,7 @@ RADIUS_PACKET *EapSendPacketAndRecvResponse(EAP_CLIENT *e, RADIUS_PACKET *r) { EAP_MESSAGE *eap_msg = (EAP_MESSAGE *)rp->Parse_EapMessage; - if (eap_msg->Type == EAP_TYPE_PEAP) + if (parse_inner && eap_msg->Type == EAP_TYPE_PEAP) { EAP_PEAP *peap_message = (EAP_PEAP *)eap_msg; @@ -1166,7 +1300,8 @@ bool EapSendPacket(EAP_CLIENT *e, RADIUS_PACKET *r) } // New EAP client -EAP_CLIENT *NewEapClient(IP *server_ip, UINT server_port, char *shared_secret, UINT resend_timeout, UINT giveup_timeout, char *client_ip_str, char *username, char *hubname) +EAP_CLIENT *NewEapClient(IP *server_ip, UINT server_port, char *shared_secret, UINT resend_timeout, UINT giveup_timeout, char *client_ip_str, + char *username, char *hubname, UCHAR last_recv_eapid) { EAP_CLIENT *e; if (server_ip == NULL) @@ -1198,7 +1333,7 @@ EAP_CLIENT *NewEapClient(IP *server_ip, UINT server_port, char *shared_secret, U StrCpy(e->CalledStationStr, sizeof(e->CalledStationStr), hubname); StrCpy(e->ClientIpStr, sizeof(e->ClientIpStr), client_ip_str); StrCpy(e->Username, sizeof(e->Username), username); - e->LastRecvEapId = 0; + e->LastRecvEapId = last_recv_eapid; e->PEAP_CurrentReceivingMsg = NewBuf(); @@ -1679,15 +1814,16 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec StrCpy(eap->In_VpnProtocolState, sizeof(eap->In_VpnProtocolState), opt->In_VpnProtocolState); } + // Use the username known to the client instead of parsed by us, or response may be invalid if (eap->PeapMode == false) { ret = EapClientSendMsChapv2AuthClientResponse(eap, mschap.MsChapV2_ClientResponse, - mschap.MsChapV2_ClientChallenge); + mschap.MsChapV2_ClientChallenge, mschap.MsChapV2_PPPUsername); } else { ret = PeapClientSendMsChapv2AuthClientResponse(eap, mschap.MsChapV2_ClientResponse, - mschap.MsChapV2_ClientChallenge); + mschap.MsChapV2_ClientChallenge, mschap.MsChapV2_PPPUsername); } if (ret) diff --git a/src/Cedar/Radius.h b/src/Cedar/Radius.h index 8c422368..ccae30c9 100644 --- a/src/Cedar/Radius.h +++ b/src/Cedar/Radius.h @@ -215,7 +215,6 @@ struct EAP_CLIENT UINT ResendTimeout; UINT GiveupTimeout; UCHAR TmpBuffer[4096]; - UCHAR NextEapId; UCHAR LastRecvEapId; bool PeapMode; @@ -249,17 +248,20 @@ RADIUS_AVP *GetRadiusAvp(RADIUS_PACKET *p, UCHAR type); void RadiusTest(); -EAP_CLIENT *NewEapClient(IP *server_ip, UINT server_port, char *shared_secret, UINT resend_timeout, UINT giveup_timeout, char *client_ip_str, char *username, char *hubname); +EAP_CLIENT *NewEapClient(IP *server_ip, UINT server_port, char *shared_secret, UINT resend_timeout, UINT giveup_timeout, char *client_ip_str, + char *username, char *hubname, UCHAR last_recv_eapid); void ReleaseEapClient(EAP_CLIENT *e); void CleanupEapClient(EAP_CLIENT *e); bool EapClientSendMsChapv2AuthRequest(EAP_CLIENT *e); -bool EapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge); +bool EapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge, char *username); +PPP_LCP *EapClientSendEapIdentity(EAP_CLIENT *e); +PPP_LCP *EapClientSendEapRequest(EAP_CLIENT *e, PPP_EAP *eap_request, UINT request_datasize); void EapSetRadiusGeneralAttributes(RADIUS_PACKET *r, EAP_CLIENT *e); bool EapSendPacket(EAP_CLIENT *e, RADIUS_PACKET *r); -RADIUS_PACKET *EapSendPacketAndRecvResponse(EAP_CLIENT *e, RADIUS_PACKET *r); +RADIUS_PACKET *EapSendPacketAndRecvResponse(EAP_CLIENT *e, RADIUS_PACKET *r, bool parse_inner); bool PeapClientSendMsChapv2AuthRequest(EAP_CLIENT *eap); -bool PeapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge); +bool PeapClientSendMsChapv2AuthClientResponse(EAP_CLIENT *e, UCHAR *client_response, UCHAR *client_challenge, char *username); bool StartPeapClient(EAP_CLIENT *e); bool StartPeapSslClient(EAP_CLIENT *e); diff --git a/src/Cedar/Sam.c b/src/Cedar/Sam.c index c8b63e40..4a223d64 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, false, NULL, 0); + + // 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 { diff --git a/src/bin/hamcore/strtable_cn.stb b/src/bin/hamcore/strtable_cn.stb index eabcf38f..efc11a1e 100644 --- a/src/bin/hamcore/strtable_cn.stb +++ b/src/bin/hamcore/strtable_cn.stb @@ -1939,6 +1939,7 @@ LH_AUTH_PASSWORD 密码验证 LH_AUTH_PLAIN_PASSWORD 外部服务器身份验证 LH_AUTH_CERT 证书验证 LH_AUTH_TICKET 票证验证 +LH_AUTH_EXTERNAL 外部服务器身份验证 LH_AUTH_WIREGUARD_KEY WireGuard public key authentication LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication LH_AUTH_RADIUS_NOT_SUPPORT 连接 "%S": 用户 "%S" 身份验证方法 RADIUS 或 Active Directory (NT 域),但 VPN Server 是 "%S",因为 RADIUS 或 Active Directory (NT 域)不能使用。连接被拒绝。 diff --git a/src/bin/hamcore/strtable_en.stb b/src/bin/hamcore/strtable_en.stb index 508960b7..c7e9698c 100644 --- a/src/bin/hamcore/strtable_en.stb +++ b/src/bin/hamcore/strtable_en.stb @@ -1925,6 +1925,7 @@ LH_AUTH_PASSWORD Password authentication LH_AUTH_PLAIN_PASSWORD External server authentication LH_AUTH_CERT Certificate authentication LH_AUTH_TICKET Ticket authentication +LH_AUTH_EXTERNAL External server authentication LH_AUTH_WIREGUARD_KEY WireGuard public key authentication LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication LH_AUTH_RADIUS_NOT_SUPPORT Connection "%S": The authentication method of the user "%S" has been specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, the edition of the VPN Server is "%S". This edition does not support RADIUS Authentication nor Active Directory Authentication (NT Domain Authentication). The connection will be denied. diff --git a/src/bin/hamcore/strtable_ja.stb b/src/bin/hamcore/strtable_ja.stb index 8a6cb1c2..c6dd947e 100644 --- a/src/bin/hamcore/strtable_ja.stb +++ b/src/bin/hamcore/strtable_ja.stb @@ -1927,6 +1927,7 @@ LH_AUTH_PASSWORD パスワード認証 LH_AUTH_PLAIN_PASSWORD 外部サーバー認証 LH_AUTH_CERT 証明書認証 LH_AUTH_TICKET チケット認証 +LH_AUTH_EXTERNAL 外部サーバー認証 LH_AUTH_WIREGUARD_KEY WireGuard 公開鍵認証 LH_AUTH_OPENVPN_CERT OpenVPN 証明書認証 LH_AUTH_RADIUS_NOT_SUPPORT コネクション "%S": ユーザー "%S" の認証方法として RADIUS 認証または Active Directory 認証 (NT ドメイン認証) が指定されましたが、現在の VPN Server のエディションは "%S" であるため、RADIUS 認証または Active Directory 認証 (NT ドメイン認証) を使用することができません。接続は拒否されます。 diff --git a/src/bin/hamcore/strtable_ko.stb b/src/bin/hamcore/strtable_ko.stb index 96298f5e..de30a1d2 100644 --- a/src/bin/hamcore/strtable_ko.stb +++ b/src/bin/hamcore/strtable_ko.stb @@ -1905,6 +1905,7 @@ LH_AUTH_PASSWORD 암호 인증 LH_AUTH_PLAIN_PASSWORD 외부 서버 인증 LH_AUTH_CERT 인증서 인증 LH_AUTH_TICKET 티켓 인증 +LH_AUTH_EXTERNAL 외부 서버 인증 LH_AUTH_WIREGUARD_KEY WireGuard public key authentication LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication LH_AUTH_RADIUS_NOT_SUPPORT 연결 "%S"사용자 "%S"의 인증 방법으로 RADIUS 인증 또는 Active Directory 인증 (NT 도메인 인증)이 지정 되었으나, 현재 VPN Server 버전은 "%S"이기 때문에 RADIUS 인증 또는 Active Directory 인증 (NT 도메인 인증)을 사용할 수 없습니다. 연결이 거부됩니다. diff --git a/src/bin/hamcore/strtable_pt_br.stb b/src/bin/hamcore/strtable_pt_br.stb index 197b3d8a..f78a8179 100644 --- a/src/bin/hamcore/strtable_pt_br.stb +++ b/src/bin/hamcore/strtable_pt_br.stb @@ -1924,6 +1924,7 @@ LH_AUTH_PASSWORD Senha LH_AUTH_PLAIN_PASSWORD External server authentication LH_AUTH_CERT Certificate authentication LH_AUTH_TICKET Ticket authentication +LH_AUTH_EXTERNAL External server authentication LH_AUTH_WIREGUARD_KEY WireGuard public key authentication LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication LH_AUTH_RADIUS_NOT_SUPPORT Connection "%S": The authentication method of the user "%S" has been specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, the edition of the VPN Server is "%S". This edition does not support RADIUS Authentication nor Active Directory Authentication (NT Domain Authentication). The connection will be denied. diff --git a/src/bin/hamcore/strtable_ru.stb b/src/bin/hamcore/strtable_ru.stb index a4afbdcf..a61a6e9e 100644 --- a/src/bin/hamcore/strtable_ru.stb +++ b/src/bin/hamcore/strtable_ru.stb @@ -1924,6 +1924,7 @@ LH_AUTH_PASSWORD Password authentication LH_AUTH_PLAIN_PASSWORD External server authentication LH_AUTH_CERT Certificate authentication LH_AUTH_TICKET Ticket authentication +LH_AUTH_EXTERNAL External server authentication LH_AUTH_WIREGUARD_KEY WireGuard public key authentication LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication LH_AUTH_RADIUS_NOT_SUPPORT Connection "%S": The authentication method of the user "%S" has been specified as RADIUS Authentication or Active Directory Authentication (NT Domain Authentication). However, the edition of the VPN Server is "%S". This edition does not support RADIUS Authentication nor Active Directory Authentication (NT Domain Authentication). The connection will be denied. diff --git a/src/bin/hamcore/strtable_tw.stb b/src/bin/hamcore/strtable_tw.stb index 9891eb22..69dc3818 100644 --- a/src/bin/hamcore/strtable_tw.stb +++ b/src/bin/hamcore/strtable_tw.stb @@ -1941,6 +1941,7 @@ LH_AUTH_PASSWORD 密碼驗證 LH_AUTH_PLAIN_PASSWORD 外部伺服器身份驗證 LH_AUTH_CERT 證書驗證 LH_AUTH_TICKET 票證驗證 +LH_AUTH_EXTERNAL 外部伺服器身份驗證 LH_AUTH_WIREGUARD_KEY WireGuard public key authentication LH_AUTH_OPENVPN_CERT OpenVPN certificate authentication LH_AUTH_RADIUS_NOT_SUPPORT 連接 "%S": 用戶 "%S" 身份驗證方法 RADIUS 或 Active Directory (NT 域),但 VPN Server 是 "%S",因為 RADIUS 或 Active Directory (NT 域)不能使用。連接被拒絕。