From f0357d40002e9533939b3647fb21cc23f49bb1cc Mon Sep 17 00:00:00 2001 From: Daiyuu Nobori Date: Sat, 19 Oct 2019 17:34:12 +0900 Subject: [PATCH] - Fixed the problem occurs when RPC messages between Cluster Members exceed 64Kbytes. - Fixed the RADIUS PEAP client to use the standard TLS versioning. - Implementation of a function to fix the MAC address of L3 VPN protocol by entering e.g. "MAC: 112233445566" in the "Notes" field of the user information. - Implementation of a function to fix the virtual MAC address to be assigned to the L3 VPN client as a string attribute from RADIUS server when authentication. --- src/Cedar/Account.c | 46 ++++++++++++++++ src/Cedar/Account.h | 3 ++ src/Cedar/Connection.h | 1 + src/Cedar/Hub.c | 7 ++- src/Cedar/Hub.h | 2 +- src/Cedar/IPC.c | 12 ++++- src/Cedar/IPC.h | 8 ++- src/Cedar/Proto_EtherIP.c | 2 +- src/Cedar/Proto_OpenVPN.c | 2 + src/Cedar/Proto_PPP.c | 8 +-- src/Cedar/Protocol.c | 38 ++++++++++++- src/Cedar/Radius.c | 109 ++++++++++++++++++++++++++++---------- src/Cedar/Radius.h | 6 +++ src/Cedar/Server.c | 9 +++- src/Cedar/Server.h | 1 + src/Cedar/Session.c | 43 ++++++++------- src/Cedar/Session.h | 2 +- src/Mayaqua/Network.c | 7 ++- src/Mayaqua/Network.h | 1 + 19 files changed, 246 insertions(+), 61 deletions(-) diff --git a/src/Cedar/Account.c b/src/Cedar/Account.c index 217e41d6..67f45e46 100644 --- a/src/Cedar/Account.c +++ b/src/Cedar/Account.c @@ -1272,3 +1272,49 @@ int CompareUserName(void *p1, void *p2) return StrCmpi(u1->Name, u2->Name); } +// Get the MAC address from the user's note string +bool GetUserMacAddressFromUserNote(UCHAR *mac, wchar_t *note) +{ + bool ret = false; + UINT i; + + Zero(mac, 6); + if (mac == NULL || note == NULL) + { + return false; + } + + i = UniSearchStrEx(note, USER_MAC_STR_PREFIX, 0, false); + if (i != INFINITE) + { + wchar_t *macstr_start = ¬e[i + UniStrLen(USER_MAC_STR_PREFIX)]; + wchar_t macstr2[MAX_SIZE]; + UNI_TOKEN_LIST *tokens; + + UniStrCpy(macstr2, sizeof(macstr2), macstr_start); + + UniTrim(macstr2); + + tokens = UniParseToken(macstr2, L" ,/()[]."); + if (tokens != NULL) + { + if (tokens->NumTokens >= 1) + { + wchar_t *macstr = tokens->Token[0]; + + if (UniIsEmptyStr(macstr) == false) + { + char macstr_a[MAX_SIZE]; + + UniToStr(macstr_a, sizeof(macstr_a), macstr); + + ret = StrToMac(mac, macstr_a); + } + } + + UniFreeToken(tokens); + } + } + + return ret; +} diff --git a/src/Cedar/Account.h b/src/Cedar/Account.h index f133a168..37a55c31 100644 --- a/src/Cedar/Account.h +++ b/src/Cedar/Account.h @@ -8,6 +8,8 @@ #ifndef ACCOUNT_H #define ACCOUNT_H +#define USER_MAC_STR_PREFIX L"MAC:" + // Policy item struct POLICY_ITEM { @@ -202,6 +204,7 @@ char *PolicyIdToStr(UINT i); POLICY_ITEM *GetPolicyItem(UINT id); void GetPolicyValueRangeStr(wchar_t *str, UINT size, UINT id); void FormatPolicyValue(wchar_t *str, UINT size, UINT id, UINT value); +bool GetUserMacAddressFromUserNote(UCHAR *mac, wchar_t *note); #endif // ACCOUNT_H diff --git a/src/Cedar/Connection.h b/src/Cedar/Connection.h index bed31883..de6a50fd 100644 --- a/src/Cedar/Connection.h +++ b/src/Cedar/Connection.h @@ -207,6 +207,7 @@ struct CONNECTION void *hWndForUI; // Parent window bool IsInProc; // In-process char InProcPrefix[64]; // Prefix + UINT InProcLayer; // InProc layer UINT AdditionalConnectionFailedCounter; // Additional connection failure counter UINT64 LastCounterResetTick; // Time the counter was reset finally bool WasSstp; // Processed the SSTP diff --git a/src/Cedar/Hub.c b/src/Cedar/Hub.c index aac02954..02f2de14 100644 --- a/src/Cedar/Hub.c +++ b/src/Cedar/Hub.c @@ -62,7 +62,7 @@ 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) +EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username, char *vpn_protocol_state_str) { HUB *hub = NULL; EAP_CLIENT *ret = NULL; @@ -112,6 +112,11 @@ EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, ch if (eap != NULL) { + if (IsEmptyStr(vpn_protocol_state_str) == false) + { + StrCpy(eap->In_VpnProtocolState, sizeof(eap->In_VpnProtocolState), vpn_protocol_state_str); + } + if (use_peap == false) { // EAP diff --git a/src/Cedar/Hub.h b/src/Cedar/Hub.h index bde62b1e..2c2dc66a 100644 --- a/src/Cedar/Hub.h +++ b/src/Cedar/Hub.h @@ -532,7 +532,7 @@ 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); +EAP_CLIENT *HubNewEapClient(CEDAR *cedar, char *hubname, char *client_ip_str, char *username, char *vpn_protocol_state_str); #endif // HUB_H diff --git a/src/Cedar/IPC.c b/src/Cedar/IPC.c index 1098ef81..9263e903 100644 --- a/src/Cedar/IPC.c +++ b/src/Cedar/IPC.c @@ -217,7 +217,7 @@ IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code) param->UserName, param->Password, error_code, ¶m->ClientIp, param->ClientPort, ¶m->ServerIp, param->ServerPort, param->ClientHostname, param->CryptName, - param->BridgeMode, param->Mss, NULL, param->ClientCertificate); + param->BridgeMode, param->Mss, NULL, param->ClientCertificate, param->Layer); return ipc; } @@ -226,7 +226,8 @@ 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, 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, + UINT layer) { IPC *ipc; UINT dummy_int = 0; @@ -274,6 +275,12 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char ipc->Cedar = cedar; AddRef(cedar->ref); + ipc->Layer = layer; + if (ipc->Layer == 0) + { + ipc->Layer = IPC_LAYER_2; + } + ipc->FlushList = NewTubeFlushList(); StrCpy(ipc->ClientHostname, sizeof(ipc->ClientHostname), client_hostname); @@ -368,6 +375,7 @@ IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char PackAddStr(p, "inproc_postfix", postfix); PackAddStr(p, "inproc_cryptname", crypt_name); + PackAddInt(p, "inproc_layer", ipc->Layer); // Node information Zero(&info, sizeof(info)); diff --git a/src/Cedar/IPC.h b/src/Cedar/IPC.h index 5b4382c7..60d54400 100644 --- a/src/Cedar/IPC.h +++ b/src/Cedar/IPC.h @@ -21,6 +21,9 @@ #define IPC_PASSWORD_MSCHAPV2_TAG "xH7DiNlurDhcYV4a:" +#define IPC_LAYER_2 2 +#define IPC_LAYER_3 3 + // ARP table entry struct IPC_ARP { @@ -58,6 +61,7 @@ struct IPC_PARAM UINT Mss; bool IsL3Mode; X *ClientCertificate; + UINT Layer; }; // IPC_ASYNC object @@ -102,6 +106,7 @@ struct IPC TUBE_FLUSH_LIST *FlushList; // Tube Flush List UCHAR MsChapV2_ServerResponse[20]; // Server response DHCP_CLASSLESS_ROUTE_TABLE ClasslessRoute; // Classless routing table + UINT Layer; }; // MS-CHAPv2 authentication information @@ -117,7 +122,8 @@ struct IPC_MSCHAP_V2_AUTHINFO IPC *NewIPC(CEDAR *cedar, char *client_name, char *postfix, char *hubname, char *username, char *password, 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, + UINT layer); IPC *NewIPCByParam(CEDAR *cedar, IPC_PARAM *param, UINT *error_code); IPC *NewIPCBySock(CEDAR *cedar, SOCK *s, void *mac_address); void FreeIPC(IPC *ipc); diff --git a/src/Cedar/Proto_EtherIP.c b/src/Cedar/Proto_EtherIP.c index f8428af1..60d4616e 100644 --- a/src/Cedar/Proto_EtherIP.c +++ b/src/Cedar/Proto_EtherIP.c @@ -64,7 +64,7 @@ void EtherIPIpcConnectThread(THREAD *t, void *p) &s->ClientIP, s->ClientPort, &s->ServerIP, s->ServerPort, tmp, - s->CryptName, true, mss, NULL, NULL); + s->CryptName, true, mss, NULL, NULL, IPC_LAYER_2); if (ipc != NULL) { diff --git a/src/Cedar/Proto_OpenVPN.c b/src/Cedar/Proto_OpenVPN.c index cd4e0aa3..e4d09d12 100644 --- a/src/Cedar/Proto_OpenVPN.c +++ b/src/Cedar/Proto_OpenVPN.c @@ -1071,6 +1071,8 @@ void OvsBeginIPCAsyncConnectionIfEmpty(OPENVPN_SERVER *s, OPENVPN_SESSION *se, O } } + p.Layer = (se->Mode == OPENVPN_MODE_L2) ? IPC_LAYER_2 : IPC_LAYER_3; + // Calculate the MSS p.Mss = OvsCalcTcpMss(s, se, c); Debug("MSS=%u\n", p.Mss); diff --git a/src/Cedar/Proto_PPP.c b/src/Cedar/Proto_PPP.c index ea8097bf..71ab6a33 100644 --- a/src/Cedar/Proto_PPP.c +++ b/src/Cedar/Proto_PPP.c @@ -202,7 +202,7 @@ void PPPThread(THREAD *thread, void *param) IPToStr(client_ip_tmp, sizeof(client_ip_tmp), &p->ClientIP); - eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id); + eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id, "L3:PPP"); if (eap) { @@ -913,7 +913,8 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req) // Attempt to connect with IPC ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password, &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, - p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient, NULL); + p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient, NULL, + IPC_LAYER_3); if (ipc != NULL) { @@ -1046,7 +1047,8 @@ PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req) ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password, &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort, - p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, NULL); + p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, NULL, + IPC_LAYER_3); if (ipc != NULL) { diff --git a/src/Cedar/Protocol.c b/src/Cedar/Protocol.c index 36db2d0a..52eb839d 100644 --- a/src/Cedar/Protocol.c +++ b/src/Cedar/Protocol.c @@ -1788,6 +1788,7 @@ bool ServerAccept(CONNECTION *c) UINT authtype; POLICY *policy; UINT assigned_vlan_id = 0; + UCHAR assigned_ipc_mac_address[6]; HUB *hub; SESSION *s = NULL; UINT64 user_expires = 0; @@ -1856,6 +1857,8 @@ bool ServerAccept(CONNECTION *c) Zero(ctoken_hash_str, sizeof(ctoken_hash_str)); + Zero(assigned_ipc_mac_address, sizeof(assigned_ipc_mac_address)); + Zero(mschap_v2_server_response_20, sizeof(mschap_v2_server_response_20)); Zero(&udp_acceleration_client_ip, sizeof(udp_acceleration_client_ip)); @@ -2190,6 +2193,7 @@ bool ServerAccept(CONNECTION *c) PackGetStr(p, "inproc_postfix", c->InProcPrefix, sizeof(c->InProcPrefix)); Zero(tmp, sizeof(tmp)); PackGetStr(p, "inproc_cryptname", tmp, sizeof(tmp)); + c->InProcLayer = PackGetInt(p, "inproc_layer"); if (c->FirstSock != NULL) { @@ -2214,6 +2218,9 @@ bool ServerAccept(CONNECTION *c) } use_udp_acceleration_client = false; + + Format(radius_login_opt.In_VpnProtocolState, sizeof(radius_login_opt.In_VpnProtocolState), + "L%u:%s", c->InProcLayer, c->InProcPrefix); } else { @@ -2227,6 +2234,9 @@ bool ServerAccept(CONNECTION *c) { c->CipherName = CopyStr(c->FirstSock->CipherName); } + + Format(radius_login_opt.In_VpnProtocolState, sizeof(radius_login_opt.In_VpnProtocolState), + "L%u:%s", IPC_LAYER_2, "SEVPN"); } if (support_bulk_on_rudp && c->FirstSock != NULL && c->FirstSock->IsRUDPSocket && @@ -2784,11 +2794,19 @@ bool ServerAccept(CONNECTION *c) } } + // Check the assigned MAC Address + if (radius_login_opt.Out_IsRadiusLogin) + { + Copy(assigned_ipc_mac_address, radius_login_opt.Out_VirtualMacAddress, 6); + } + if (StrCmpi(username, ADMINISTRATOR_USERNAME) != 0) { // Get the policy if (farm_member == false) { + bool is_asterisk_user = false; + // In the case of not a farm member user = AcGetUser(hub, username); if (user == NULL) @@ -2803,12 +2821,29 @@ bool ServerAccept(CONNECTION *c) error_detail = "AcGetUser"; goto CLEANUP; } + + is_asterisk_user = true; } policy = NULL; Lock(user->lock); { + if (is_asterisk_user == false) + { + UCHAR associated_mac_address[6]; + + // Get the associated virtual MAC address + if (GetUserMacAddressFromUserNote(associated_mac_address, user->Note)) + { + if (IsZero(assigned_ipc_mac_address, 6)) + { + WHERE; + Copy(assigned_ipc_mac_address, associated_mac_address, 6); + } + } + } + // Get the expiration date user_expires = user->ExpireTime; @@ -3478,7 +3513,8 @@ bool ServerAccept(CONNECTION *c) // Create a Session StrLower(username); - s = NewServerSessionEx(c->Cedar, c, hub, username, policy, c->IsInProc); + s = NewServerSessionEx(c->Cedar, c, hub, username, policy, c->IsInProc, + (c->IsInProc && IsZero(assigned_ipc_mac_address, 6) == false) ? assigned_ipc_mac_address : NULL); s->EnableUdpRecovery = enable_udp_recovery; s->LocalHostSession = local_host_session; diff --git a/src/Cedar/Radius.c b/src/Cedar/Radius.c index a0157c00..864e3a0e 100644 --- a/src/Cedar/Radius.c +++ b/src/Cedar/Radius.c @@ -217,11 +217,11 @@ bool SendPeapRawPacket(EAP_CLIENT *e, UCHAR *peap_data, UINT peap_size) fragments = NewListFast(NULL); for (num = 0;;num++) { - UCHAR tmp[1024]; + UCHAR tmp[200]; EAP_PEAP *send_peap_message; UINT sz; - sz = ReadBuf(buf, tmp, 1024); + sz = ReadBuf(buf, tmp, 200); if (sz == 0) { @@ -593,6 +593,11 @@ void EapSetRadiusGeneralAttributes(RADIUS_PACKET *r, EAP_CLIENT *e) Add(r->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_NAS_ID, 0, 0, CEDAR_SERVER_STR, StrLen(CEDAR_SERVER_STR))); + if (IsEmptyStr(e->In_VpnProtocolState) == false) + { + Add(r->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_PROXY_STATE, 0, 0, e->In_VpnProtocolState, StrLen(e->In_VpnProtocolState))); + } + ui = Endian32(2); Add(r->AvpList, NewRadiusAvp(RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_NETWORK_ACCESS_SERVER_TYPE, &ui, sizeof(UINT))); @@ -914,11 +919,27 @@ RADIUS_PACKET *EapSendPacketAndRecvResponse(EAP_CLIENT *e, RADIUS_PACKET *r) { RADIUS_AVP *eap_msg = GetRadiusAvp(rp, RADIUS_ATTRIBUTE_EAP_MESSAGE); RADIUS_AVP *vlan_avp = GetRadiusAvp(rp, RADIUS_ATTRIBUTE_VLAN_ID); + RADIUS_AVP *framed_interface_id_avp = GetRadiusAvp(rp, RADIUS_ATTRIBUTE_FRAMED_INTERFACE_ID); if (eap_msg != NULL) { e->LastRecvEapId = ((EAP_MESSAGE *)(eap_msg->Data))->Id; } + if (framed_interface_id_avp != NULL) + { + // FRAMED_INTERFACE_ID + char tmp_str[64]; + UCHAR mac_address[6]; + + Zero(tmp_str, sizeof(tmp_str)); + Copy(tmp_str, framed_interface_id_avp->Data, MIN(framed_interface_id_avp->DataSize, sizeof(tmp_str) - 1)); + + if (StrToMac(mac_address, tmp_str)) + { + Copy(e->LastRecvVirtualMacAddress, mac_address, 6); + } + } + if (vlan_avp != NULL) { // VLAN ID @@ -1642,6 +1663,11 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec // Try the EAP authentication for RADIUS first EAP_CLIENT *eap = mschap.MsChapV2_EapClient; + if (IsEmptyStr(opt->In_VpnProtocolState) == false) + { + StrCpy(eap->In_VpnProtocolState, sizeof(eap->In_VpnProtocolState), opt->In_VpnProtocolState); + } + if (eap->PeapMode == false) { ret = EapClientSendMsChapv2AuthClientResponse(eap, mschap.MsChapV2_ClientResponse, @@ -1662,6 +1688,8 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec opt->Out_VLanId = eap->LastRecvVLanId; } + Copy(opt->Out_VirtualMacAddress, eap->LastRecvVirtualMacAddress, 6); + return true; } else @@ -1776,31 +1804,31 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec // Service-Type ui = Endian32(2); - RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_SERVICE_TYPE, 0, 0, &ui, sizeof(ui)); // NAS-Port-Type ui = Endian32(5); - RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_NAS_PORT_TYPE, 0, 0, &ui, sizeof(ui)); // Tunnel-Type ui = Endian32(1); - RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_TYPE, 0, 0, &ui, sizeof(ui)); // Tunnel-Medium-Type ui = Endian32(1); - RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_MEDIUM_TYPE, 0, 0, &ui, sizeof(ui)); // Called-Station-ID - VPN Hub Name if (IsEmptyStr(hubname) == false) { - RadiusAddValue(p, 30, 0, 0, hubname, StrLen(hubname)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_CALLED_STATION_ID, 0, 0, hubname, StrLen(hubname)); } // Calling-Station-Id - RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_CALLING_STATION_ID, 0, 0, client_ip_str, StrLen(client_ip_str)); // Tunnel-Client-Endpoint - RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_CLIENT_ENDPOINT, 0, 0, client_ip_str, StrLen(client_ip_str)); } else { @@ -1814,69 +1842,74 @@ bool RadiusLogin(CONNECTION *c, char *server, UINT port, UCHAR *secret, UINT sec // Acct-Session-Id us = Endian16(session_id % 254 + 1); session_id++; - RadiusAddValue(p, 44, 0, 0, &us, sizeof(us)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_ACCT_SESSION_ID, 0, 0, &us, sizeof(us)); // NAS-IP-Address if (c != NULL && c->FirstSock != NULL && c->FirstSock->IPv6 == false) { ui = IPToUINT(&c->FirstSock->LocalIP); - RadiusAddValue(p, 4, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_NAS_IP, 0, 0, &ui, sizeof(ui)); } // Service-Type ui = Endian32(2); - RadiusAddValue(p, 6, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_SERVICE_TYPE, 0, 0, &ui, sizeof(ui)); // MS-RAS-Vendor - ui = Endian32(311); - RadiusAddValue(p, 26, 311, 9, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_VERSION, ms_ras_version, StrLen(ms_ras_version)); // MS-RAS-Version RadiusAddValue(p, 26, 311, 18, ms_ras_version, StrLen(ms_ras_version)); // NAS-Port-Type ui = Endian32(5); - RadiusAddValue(p, 61, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_NAS_PORT_TYPE, 0, 0, &ui, sizeof(ui)); // Tunnel-Type ui = Endian32(1); - RadiusAddValue(p, 64, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_TYPE, 0, 0, &ui, sizeof(ui)); // Tunnel-Medium-Type ui = Endian32(1); - RadiusAddValue(p, 65, 0, 0, &ui, sizeof(ui)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_MEDIUM_TYPE, 0, 0, &ui, sizeof(ui)); // Called-Station-ID - VPN Hub Name if (IsEmptyStr(hubname) == false) { - RadiusAddValue(p, 30, 0, 0, hubname, StrLen(hubname)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_CALLED_STATION_ID, 0, 0, hubname, StrLen(hubname)); } // Calling-Station-Id - RadiusAddValue(p, 31, 0, 0, client_ip_str, StrLen(client_ip_str)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_CALLING_STATION_ID, 0, 0, client_ip_str, StrLen(client_ip_str)); // Tunnel-Client-Endpoint - RadiusAddValue(p, 66, 0, 0, client_ip_str, StrLen(client_ip_str)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_TUNNEL_CLIENT_ENDPOINT, 0, 0, client_ip_str, StrLen(client_ip_str)); // MS-RAS-Client-Version - RadiusAddValue(p, 26, 311, 35, ms_ras_version, StrLen(ms_ras_version)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_RAS_CLIENT_VERSION, ms_ras_version, StrLen(ms_ras_version)); // MS-RAS-Client-Name - RadiusAddValue(p, 26, 311, 34, client_ip_str, StrLen(client_ip_str)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_RAS_CLIENT_NAME, client_ip_str, StrLen(client_ip_str)); // MS-CHAP-Challenge - RadiusAddValue(p, 26, 311, 11, mschap.MsChapV2_ServerChallenge, sizeof(mschap.MsChapV2_ServerChallenge)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_CHAP_CHALLENGE, mschap.MsChapV2_ServerChallenge, sizeof(mschap.MsChapV2_ServerChallenge)); // MS-CHAP2-Response Zero(ms_chapv2_response, sizeof(ms_chapv2_response)); Copy(ms_chapv2_response + 2, mschap.MsChapV2_ClientChallenge, 16); Copy(ms_chapv2_response + 2 + 16 + 8, mschap.MsChapV2_ClientResponse, 24); - RadiusAddValue(p, 26, 311, 25, ms_chapv2_response, sizeof(ms_chapv2_response)); + RadiusAddValue(p, RADIUS_ATTRIBUTE_VENDOR_SPECIFIC, RADIUS_VENDOR_MICROSOFT, RADIUS_MS_CHAP2_RESPONSE, ms_chapv2_response, sizeof(ms_chapv2_response)); // NAS-ID WriteBuf(p, nas_id->Buf, nas_id->Size); } + if (IsEmptyStr(opt->In_VpnProtocolState) == false) + { + // Proxy state as protocol details + RadiusAddValue(p, RADIUS_ATTRIBUTE_PROXY_STATE, 0, 0, opt->In_VpnProtocolState, StrLen(opt->In_VpnProtocolState)); + } + SeekBuf(p, 0, 0); WRITE_USHORT(((UCHAR *)p->Buf) + 2, (USHORT)p->Size); @@ -1967,6 +2000,9 @@ RECV_RETRY: // Success if (recv_buf[0] == 2) { + LIST *o; + BUF *buf = NewBufFromMemory(recv_buf, recv_size); + ret = true; if (is_mschap && mschap_v2_server_response_20 != NULL) @@ -2004,12 +2040,26 @@ RECV_RETRY: } } - if (opt->In_CheckVLanId) + o = RadiusParseOptions(buf); + if (o != NULL) { - BUF *buf = NewBufFromMemory(recv_buf, recv_size); - LIST *o = RadiusParseOptions(buf); + DHCP_OPTION *framed_interface_id_option = GetDhcpOption(o, RADIUS_ATTRIBUTE_FRAMED_INTERFACE_ID); - if (o != NULL) + if (framed_interface_id_option != NULL) + { + char tmp_str[64]; + UCHAR mac_address[6]; + + Zero(tmp_str, sizeof(tmp_str)); + Copy(tmp_str, framed_interface_id_option->Data, MIN(framed_interface_id_option->Size, sizeof(tmp_str) - 1)); + + if (StrToMac(mac_address, tmp_str)) + { + Copy(opt->Out_VirtualMacAddress, mac_address, 6); + } + } + + if (opt->In_CheckVLanId) { DHCP_OPTION *vlan_option = GetDhcpOption(o, RADIUS_ATTRIBUTE_VLAN_ID); @@ -2028,9 +2078,10 @@ RECV_RETRY: } } - FreeBuf(buf); FreeDhcpOptions(o); } + + FreeBuf(buf); } break; } diff --git a/src/Cedar/Radius.h b/src/Cedar/Radius.h index 10b2cfb1..fb077c31 100644 --- a/src/Cedar/Radius.h +++ b/src/Cedar/Radius.h @@ -36,6 +36,7 @@ #define RADIUS_ATTRIBUTE_EAP_MESSAGE 79 #define RADIUS_ATTRIBUTE_EAP_AUTHENTICATOR 80 #define RADIUS_ATTRIBUTE_VLAN_ID 81 +#define RADIUS_ATTRIBUTE_FRAMED_INTERFACE_ID 96 #define RADIUS_MAX_NAS_ID_LEN 253 // RADIUS codes @@ -230,6 +231,9 @@ struct EAP_CLIENT UCHAR RecvLastCode; UINT LastRecvVLanId; + UCHAR LastRecvVirtualMacAddress[6]; + + char In_VpnProtocolState[64]; }; void FreeRadiusPacket(RADIUS_PACKET *p); @@ -268,6 +272,8 @@ struct RADIUS_LOGIN_OPTION UINT Out_VLanId; bool Out_IsRadiusLogin; char NasId[RADIUS_MAX_NAS_ID_LEN + 1]; // NAS-Identifier + char Out_VirtualMacAddress[6]; + char In_VpnProtocolState[64]; }; // Function prototype diff --git a/src/Cedar/Server.c b/src/Cedar/Server.c index 6a922d14..b47927b5 100644 --- a/src/Cedar/Server.c +++ b/src/Cedar/Server.c @@ -10099,12 +10099,17 @@ void SiFarmServMain(SERVER *server, SOCK *sock, FARM_MEMBER *f) } // Receive - p = HttpServerRecv(sock); + p = HttpServerRecvEx(sock, FIRM_SERV_RECV_PACK_MAX_SIZE); t->Response = p; Set(t->CompleteEvent); - send_noop = false; + if (p == NULL) + { + // Avoid infinite loop + Disconnect(sock); + goto DISCONNECTED; + } } } while (t != NULL); diff --git a/src/Cedar/Server.h b/src/Cedar/Server.h index 5e9233e6..eaaac853 100644 --- a/src/Cedar/Server.h +++ b/src/Cedar/Server.h @@ -52,6 +52,7 @@ extern char *SERVER_CONFIG_FILE_NAME; #define MEMBER_SELECTOR_CONNECT_TIMEOUT 2000 #define MEMBER_SELECTOR_DATA_TIMEOUT 5000 +#define FIRM_SERV_RECV_PACK_MAX_SIZE (100 * 1024 * 1024) // Virtual HUB list hosted by each farm member struct HUB_LIST diff --git a/src/Cedar/Session.c b/src/Cedar/Session.c index ab3bc970..88e96f2d 100644 --- a/src/Cedar/Session.c +++ b/src/Cedar/Session.c @@ -2047,9 +2047,9 @@ void if_free(SESSION *s); // Create a server session SESSION *NewServerSession(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy) { - return NewServerSessionEx(cedar, c, h, username, policy, false); + return NewServerSessionEx(cedar, c, h, username, policy, false, NULL); } -SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode) +SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode, UCHAR *ipc_mac_address) { SESSION *s; char name[MAX_SIZE]; @@ -2170,28 +2170,35 @@ SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, // Generate a MAC address for IPC if (s->InProcMode) { - char tmp[MAX_SIZE]; - char machine[MAX_SIZE]; - UCHAR hash[SHA1_SIZE]; + if (ipc_mac_address != NULL) + { + Copy(s->IpcMacAddress, ipc_mac_address, 6); + } + else + { + char tmp[MAX_SIZE]; + char machine[MAX_SIZE]; + UCHAR hash[SHA1_SIZE]; - GetMachineName(machine, sizeof(machine)); + GetMachineName(machine, sizeof(machine)); - Format(tmp, sizeof(tmp), "%s@%s@%u", machine, h->Name, s->UniqueId); + Format(tmp, sizeof(tmp), "%s@%s@%u", machine, h->Name, s->UniqueId); - StrUpper(tmp); - Trim(tmp); + StrUpper(tmp); + Trim(tmp); - Sha0(hash, tmp, StrLen(tmp)); + Sha0(hash, tmp, StrLen(tmp)); - s->IpcMacAddress[0] = 0xCA; - s->IpcMacAddress[1] = hash[1]; - s->IpcMacAddress[2] = hash[2]; - s->IpcMacAddress[3] = hash[3]; - s->IpcMacAddress[4] = hash[4]; - s->IpcMacAddress[5] = hash[5]; + s->IpcMacAddress[0] = 0xCA; + s->IpcMacAddress[1] = hash[1]; + s->IpcMacAddress[2] = hash[2]; + s->IpcMacAddress[3] = hash[3]; + s->IpcMacAddress[4] = hash[4]; + s->IpcMacAddress[5] = hash[5]; - MacToStr(tmp, sizeof(tmp), s->IpcMacAddress); - Debug("MAC Address for IPC: %s\n", tmp); + MacToStr(tmp, sizeof(tmp), s->IpcMacAddress); + Debug("MAC Address for IPC: %s\n", tmp); + } } return s; diff --git a/src/Cedar/Session.h b/src/Cedar/Session.h index a17e0547..2c980248 100644 --- a/src/Cedar/Session.h +++ b/src/Cedar/Session.h @@ -300,7 +300,7 @@ SESSION *NewRpcSession(CEDAR *cedar, CLIENT_OPTION *option); SESSION *NewRpcSessionEx(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str); SESSION *NewRpcSessionEx2(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str, void *hWnd); SESSION *NewServerSession(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy); -SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode); +SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode, UCHAR *ipc_mac_address); void ClientThread(THREAD *t, void *param); void ReleaseSession(SESSION *s); void CleanupSession(SESSION *s); diff --git a/src/Mayaqua/Network.c b/src/Mayaqua/Network.c index d484a601..1bb2f6d1 100644 --- a/src/Mayaqua/Network.c +++ b/src/Mayaqua/Network.c @@ -19947,6 +19947,10 @@ void FlushTubeFlushList(TUBE_FLUSH_LIST *f) // The server receives a PACK from the client PACK *HttpServerRecv(SOCK *s) +{ + return HttpServerRecvEx(s, 0); +} +PACK *HttpServerRecvEx(SOCK *s, UINT max_data_size) { BUF *b; PACK *p; @@ -19955,6 +19959,7 @@ PACK *HttpServerRecv(SOCK *s) UCHAR *tmp; HTTP_VALUE *v; UINT num_noop = 0; + if (max_data_size == 0) max_data_size = HTTP_PACK_MAX_SIZE; // Validate arguments if (s == NULL) { @@ -19985,7 +19990,7 @@ START: } size = GetContentLength(h); - if (size == 0 || size > HTTP_PACK_MAX_SIZE) + if (size == 0 || (size > max_data_size)) { FreeHttpHeader(h); goto BAD_REQUEST; diff --git a/src/Mayaqua/Network.h b/src/Mayaqua/Network.h index 54fe2c76..5689a8ee 100644 --- a/src/Mayaqua/Network.h +++ b/src/Mayaqua/Network.h @@ -969,6 +969,7 @@ bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version); bool HttpServerSend(SOCK *s, PACK *p); bool HttpClientSend(SOCK *s, PACK *p); PACK *HttpServerRecv(SOCK *s); +PACK *HttpServerRecvEx(SOCK *s, UINT max_data_size); PACK *HttpClientRecv(SOCK *s); bool GetIPViaDnsProxyForJapanFlets(IP *ip_ret, char *hostname, bool ipv6, UINT timeout, bool *cancel, char *dns_proxy_hostname);