// SoftEther VPN Source Code // Cedar Communication Module // // SoftEther VPN Server, Client and Bridge are free software under GPLv2. // // Copyright (c) 2012-2015 Daiyuu Nobori. // Copyright (c) 2012-2015 SoftEther VPN Project, University of Tsukuba, Japan. // Copyright (c) 2012-2015 SoftEther Corporation. // // All Rights Reserved. // // http://www.softether.org/ // // Author: Daiyuu Nobori // Comments: Tetsuo Sugiyama, Ph.D. // // This program is free software; you can redistribute it and/or // modify it under the terms of the GNU General Public License // version 2 as published by the Free Software Foundation. // // This program is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License version 2 // along with this program; if not, write to the Free Software // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, // EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. // IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY // CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, // TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE // SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. // // THE LICENSE AGREEMENT IS ATTACHED ON THE SOURCE-CODE PACKAGE // AS "LICENSE.TXT" FILE. READ THE TEXT FILE IN ADVANCE TO USE THE SOFTWARE. // // // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, // UNDER JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, // MERGE, PUBLISH, DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS // SOFTWARE, THAT ANY JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS // SOFTWARE OR ITS CONTENTS, AGAINST US (SOFTETHER PROJECT, SOFTETHER // CORPORATION, DAIYUU NOBORI OR OTHER SUPPLIERS), OR ANY JURIDICAL // DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND OF USING, COPYING, // MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING, AND/OR // SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO // EXCLUSIVE JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, // JAPAN. YOU MUST WAIVE ALL DEFENSES OF LACK OF PERSONAL JURISDICTION // AND FORUM NON CONVENIENS. PROCESS MAY BE SERVED ON EITHER PARTY IN // THE MANNER AUTHORIZED BY APPLICABLE LAW OR COURT RULE. // // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS // YOU HAVE A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY // CRIMINAL LAWS OR CIVIL RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS // SOFTWARE IN OTHER COUNTRIES IS COMPLETELY AT YOUR OWN RISK. THE // SOFTETHER VPN PROJECT HAS DEVELOPED AND DISTRIBUTED THIS SOFTWARE TO // COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING CIVIL RIGHTS INCLUDING // PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER COUNTRIES' LAWS OR // CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES. WE HAVE // NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ // COUNTRIES AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE // WORLD, WITH DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY // COUNTRIES' LAWS, REGULATIONS AND CIVIL RIGHTS TO MAKE THE SOFTWARE // COMPLY WITH ALL COUNTRIES' LAWS BY THE PROJECT. EVEN IF YOU WILL BE // SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A PUBLIC SERVANT IN YOUR // COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE LIABLE TO // RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT // JUST A STATEMENT FOR WARNING AND DISCLAIMER. // // // SOURCE CODE CONTRIBUTION // ------------------------ // // Your contribution to SoftEther VPN Project is much appreciated. // Please send patches to us through GitHub. // Read the SoftEther VPN Patch Acceptance Policy in advance: // http://www.softether.org/5-download/src/9.patch // // // DEAR SECURITY EXPERTS // --------------------- // // If you find a bug or a security vulnerability please kindly inform us // about the problem immediately so that we can fix the security problem // to protect a lot of users around the world as soon as possible. // // Our e-mail address for security reports is: // softether-vpn-security [at] softether.org // // Please note that the above e-mail address is not a technical support // inquiry address. If you need technical assistance, please visit // http://www.softether.org/ and ask your question on the users forum. // // Thank you for your cooperation. // // // NO MEMORY OR RESOURCE LEAKS // --------------------------- // // The memory-leaks and resource-leaks verification under the stress // test has been passed before release this source code. // NM.c // VPN User-mode Router Manager for Win32 #include #ifdef WIN32 #define SM_C #define CM_C #define NM_C #define _WIN32_WINNT 0x0502 #define WINVER 0x0502 #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "CMInner.h" #include "SMInner.h" #include "NMInner.h" #include "EMInner.h" #include "../PenCore/resource.h" // Global variable static NM *nm = NULL; // Dialog proc for the push routing option UINT NmEditPushRouteProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { SM_HUB *r = (SM_HUB *)param; char *str = NULL; // Validate arguments if (hWnd == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: SetTextA(hWnd, E_TEXT, r->CurrentPushRouteStr); Focus(hWnd, E_TEXT); SetIcon(hWnd, 0, ICO_PROTOCOL); break; case WM_COMMAND: switch (wParam) { case IDOK: str = GetTextA(hWnd, E_TEXT); if (str != NULL) { bool ok = true; if (CheckClasslessRouteTableStr(str) == false) { if (MsgBox(hWnd, MB_ICONWARNING | MB_OKCANCEL | MB_DEFBUTTON2, _UU("NM_PUSH_ROUTE_WARNING")) == IDCANCEL) { ok = false; } } if (ok) { if (IsEmptyStr(str) == false) { if (GetCapsBool(r->p->CapsList, "b_suppport_push_route") == false) { MsgBox(hWnd, MB_ICONEXCLAMATION, _UU("ERR_147")); } } StrCpy(r->CurrentPushRouteStr, sizeof(r->CurrentPushRouteStr), str); EndDialog(hWnd, 1); } Free(str); } break; case IDCANCEL: Close(hWnd); break; } break; case WM_CLOSE: EndDialog(hWnd, 0); break; } return 0; } // Edit dialog for the push routing option bool NmEditPushRoute(HWND hWnd, SM_HUB *r) { // Validate arguments if (r == NULL) { return false; } return Dialog(hWnd, D_NM_PUSH, NmEditPushRouteProc, r); } // Change Password dialog UINT NmChangePasswordProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { RPC *r = (RPC *)param; char tmp1[MAX_SIZE]; char tmp2[MAX_SIZE]; RPC_SET_PASSWORD t; // Validate arguments if (hWnd == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: FormatText(hWnd, 0, r->Sock->RemoteHostname); FormatText(hWnd, S_TITLE, r->Sock->RemoteHostname); break; case WM_COMMAND: GetTxtA(hWnd, E_PASSWORD1, tmp1, sizeof(tmp1)); GetTxtA(hWnd, E_PASSWORD2, tmp2, sizeof(tmp2)); switch (LOWORD(wParam)) { case E_PASSWORD1: case E_PASSWORD2: SetEnable(hWnd, IDOK, StrCmp(tmp1, tmp2) == 0); break; } switch (wParam) { case IDOK: Zero(&t, sizeof(t)); Hash(t.HashedPassword, tmp1, StrLen(tmp1), true); if (CALL(hWnd, NcSetPassword(r, &t))) { MsgBox(hWnd, MB_ICONINFORMATION, _UU("NM_PASSWORD_MSG")); EndDialog(hWnd, true); } break; case IDCANCEL: Close(hWnd); break; } break; case WM_CLOSE: EndDialog(hWnd, false); break; } return 0; } // Change the password void NmChangePassword(HWND hWnd, RPC *r) { // Validate arguments if (hWnd == NULL || r == NULL) { return; } Dialog(hWnd, D_NM_CHANGE_PASSWORD, NmChangePasswordProc, r); } // DHCP enumeration initialization void NmDhcpInit(HWND hWnd, SM_HUB *r) { // Validate arguments if (hWnd == NULL || r == NULL) { return; } SetIcon(hWnd, 0, ICO_INTERNET); LvInit(hWnd, L_TABLE); LvInsertColumn(hWnd, L_TABLE, 0, _UU("DHCP_DHCP_ID"), 50); LvInsertColumn(hWnd, L_TABLE, 1, _UU("DHCP_LEASED_TIME"), 200); LvInsertColumn(hWnd, L_TABLE, 2, _UU("DHCP_EXPIRE_TIME"), 200); LvInsertColumn(hWnd, L_TABLE, 3, _UU("DHCP_MAC_ADDRESS"), 130); LvInsertColumn(hWnd, L_TABLE, 4, _UU("DHCP_IP_ADDRESS"), 100); LvInsertColumn(hWnd, L_TABLE, 5, _UU("DHCP_HOSTNAME"), 150); NmDhcpRefresh(hWnd, r); } // DHCP enumeration void NmDhcpRefresh(HWND hWnd, SM_HUB *r) { LVB *b; RPC_ENUM_DHCP t; UINT i; // Validate arguments if (hWnd == NULL || r == NULL) { Close(hWnd); return; } Zero(&t, sizeof(t)); StrCpy(t.HubName, sizeof(t.HubName), r->HubName); if (CALL(hWnd, ScEnumDHCP(r->Rpc, &t)) == false) { return; } b = LvInsertStart(); for (i = 0;i < t.NumItem;i++) { RPC_ENUM_DHCP_ITEM *e = &t.Items[i]; wchar_t tmp0[MAX_SIZE]; wchar_t tmp1[MAX_SIZE]; wchar_t tmp2[MAX_SIZE]; wchar_t tmp3[MAX_SIZE]; wchar_t tmp4[MAX_SIZE]; wchar_t tmp5[MAX_SIZE]; char str[MAX_SIZE]; // ID UniToStru(tmp0, e->Id); // Time GetDateTimeStrEx64(tmp1, sizeof(tmp1), SystemToLocal64(e->LeasedTime), NULL); GetDateTimeStrEx64(tmp2, sizeof(tmp2), SystemToLocal64(e->ExpireTime), NULL); MacToStr(str, sizeof(str), e->MacAddress); StrToUni(tmp3, sizeof(tmp3), str); IPToStr32(str, sizeof(str), e->IpAddress); StrToUni(tmp4, sizeof(tmp4), str); StrToUni(tmp5, sizeof(tmp5), e->Hostname); LvInsertAdd(b, ICO_INTERNET, NULL, 6, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5); } LvInsertEnd(b, hWnd, L_TABLE); FreeRpcEnumDhcp(&t); } // DHCP enumeration procedure UINT NmDhcpProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { SM_HUB *r = (SM_HUB *)param; // Validate arguments if (hWnd == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: NmDhcpInit(hWnd, r); SetTimer(hWnd, 1, NM_DHCP_REFRESH_TIME, NULL); break; case WM_COMMAND: switch (wParam) { case IDCANCEL: Close(hWnd); break; case B_REFRESH: NmDhcpRefresh(hWnd, r); break; } break; case WM_TIMER: switch (wParam) { case 1: KillTimer(hWnd, 1); NmDhcpRefresh(hWnd, r); SetTimer(hWnd, 1, NM_DHCP_REFRESH_TIME, NULL); break; } break; case WM_CLOSE: EndDialog(hWnd, false); break; } LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE); return 0; } // DHCP enumeration void NmDhcp(HWND hWnd, SM_HUB *r) { // Validate arguments if (hWnd == NULL || r == NULL) { return; } Dialog(hWnd, D_NM_DHCP, NmDhcpProc, r); } // NAT enumeration initialization void NmNatInit(HWND hWnd, SM_HUB *r) { // Validate arguments if (hWnd == NULL || r == NULL) { return; } SetIcon(hWnd, 0, ICO_PROTOCOL); LvInit(hWnd, L_TABLE); LvInsertColumn(hWnd, L_TABLE, 0, _UU("NM_NAT_ID"), 50); LvInsertColumn(hWnd, L_TABLE, 1, _UU("NM_NAT_PROTOCOL"), 80); LvInsertColumn(hWnd, L_TABLE, 2, _UU("NM_NAT_SRC_HOST"), 100); LvInsertColumn(hWnd, L_TABLE, 3, _UU("NM_NAT_SRC_PORT"), 80); LvInsertColumn(hWnd, L_TABLE, 4, _UU("NM_NAT_DST_HOST"), 150); LvInsertColumn(hWnd, L_TABLE, 5, _UU("NM_NAT_DST_PORT"), 80); LvInsertColumn(hWnd, L_TABLE, 6, _UU("NM_NAT_CREATED"), 200); LvInsertColumn(hWnd, L_TABLE, 7, _UU("NM_NAT_LAST_COMM"), 200); LvInsertColumn(hWnd, L_TABLE, 8, _UU("NM_NAT_SIZE"), 120); LvInsertColumn(hWnd, L_TABLE, 9, _UU("NM_NAT_TCP_STATUS"), 120); NmNatRefresh(hWnd, r); } // NAT enumeration void NmNatRefresh(HWND hWnd, SM_HUB *r) { LVB *b; RPC_ENUM_NAT t; UINT i; // Validate arguments if (hWnd == NULL || r == NULL) { return; } Zero(&t, sizeof(t)); StrCpy(t.HubName, sizeof(t.HubName), r->HubName); if (CALL(hWnd, ScEnumNAT(r->Rpc, &t)) == false) { Close(hWnd); return; } b = LvInsertStart(); for (i = 0;i < t.NumItem;i++) { RPC_ENUM_NAT_ITEM *e = &t.Items[i]; wchar_t tmp0[MAX_SIZE]; wchar_t *tmp1 = L""; wchar_t tmp2[MAX_SIZE]; wchar_t tmp3[MAX_SIZE]; wchar_t tmp4[MAX_SIZE]; wchar_t tmp5[MAX_SIZE]; wchar_t tmp6[MAX_SIZE]; wchar_t tmp7[MAX_SIZE]; wchar_t tmp8[MAX_SIZE]; wchar_t *tmp9 = L""; char v1[128], v2[128]; // ID UniToStru(tmp0, e->Id); // Protocol switch (e->Protocol) { case NAT_TCP: tmp1 = _UU("NM_NAT_PROTO_TCP"); break; case NAT_UDP: tmp1 = _UU("NM_NAT_PROTO_UDP"); break; case NAT_DNS: tmp1 = _UU("NM_NAT_PROTO_DNS"); break; case NAT_ICMP: tmp1 = _UU("NM_NAT_PROTO_ICMP"); break; } // Source host StrToUni(tmp2, sizeof(tmp2), e->SrcHost); // Source port UniToStru(tmp3, e->SrcPort); // Destination host StrToUni(tmp4, sizeof(tmp4), e->DestHost); // Destination port UniToStru(tmp5, e->DestPort); // Creation date and time of the session GetDateTimeStrEx64(tmp6, sizeof(tmp6), SystemToLocal64(e->CreatedTime), NULL); // Last communication date and time GetDateTimeStrEx64(tmp7, sizeof(tmp7), SystemToLocal64(e->LastCommTime), NULL); // Communication amount ToStr3(v1, sizeof(v1), e->RecvSize); ToStr3(v2, sizeof(v2), e->SendSize); UniFormat(tmp8, sizeof(tmp8), L"%S / %S", v1, v2); // TCP state if (e->Protocol == NAT_TCP) { switch (e->TcpStatus) { case NAT_TCP_CONNECTING: tmp9 = _UU("NAT_TCP_CONNECTING"); break; case NAT_TCP_SEND_RESET: tmp9 = _UU("NAT_TCP_SEND_RESET"); break; case NAT_TCP_CONNECTED: tmp9 = _UU("NAT_TCP_CONNECTED"); break; case NAT_TCP_ESTABLISHED: tmp9 = _UU("NAT_TCP_ESTABLISHED"); break; case NAT_TCP_WAIT_DISCONNECT: tmp9 = _UU("NAT_TCP_WAIT_DISCONNECT"); break; } } LvInsertAdd(b, ICO_PROTOCOL, NULL, 10, tmp0, tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9); } LvInsertEnd(b, hWnd, L_TABLE); FreeRpcEnumNat(&t); } // NAT enumeration procedure UINT NmNatProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { SM_HUB *r = (SM_HUB *)param; // Validate arguments if (hWnd == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: NmNatInit(hWnd, r); SetTimer(hWnd, 1, NM_NAT_REFRESH_TIME, NULL); break; case WM_COMMAND: switch (wParam) { case IDCANCEL: Close(hWnd); break; case B_REFRESH: NmNatRefresh(hWnd, r); break; } break; case WM_TIMER: switch (wParam) { case 1: KillTimer(hWnd, 1); NmNatRefresh(hWnd, r); SetTimer(hWnd, 1, NM_NAT_REFRESH_TIME, NULL); break; } break; case WM_CLOSE: EndDialog(hWnd, false); break; } LvStandardHandler(hWnd, msg, wParam, lParam, L_TABLE); return 0; } // NAT enumeration void NmNat(HWND hWnd, SM_HUB *r) { // Validate arguments if (hWnd == NULL || r == NULL) { return; } Dialog(hWnd, D_NM_NAT, NmNatProc, r); } // Show the information of the router bool NmInfo(HWND hWnd, SM_SERVER *s, void *param) { LVB *b; RPC_NAT_INFO t; wchar_t tmp[MAX_SIZE]; // Validate arguments if (hWnd == NULL || s == NULL) { return false; } Zero(&t, sizeof(t)); if (CALL(hWnd, NcGetInfo(s->Rpc, &t)) == false) { return false; } b = LvInsertStart(); StrToUni(tmp, sizeof(tmp), t.NatProductName); LvInsertAdd(b, ICO_ROUTER, NULL, 2, _UU("NM_INFO_PRODUCT_NAME"), tmp); StrToUni(tmp, sizeof(tmp), t.NatVersionString); LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("NM_INFO_VERSION_STR"), tmp); StrToUni(tmp, sizeof(tmp), t.NatBuildInfoString); LvInsertAdd(b, ICO_INFORMATION, NULL, 2, _UU("NM_INFO_BUILD_INFO"), tmp); StrToUni(tmp, sizeof(tmp), t.NatHostName); LvInsertAdd(b, ICO_TOWER, NULL, 2, _UU("NM_INFO_HOSTNAME"), tmp); // OS StrToUni(tmp, sizeof(tmp), t.OsInfo.OsSystemName); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SYSTEM_NAME"), tmp); StrToUni(tmp, sizeof(tmp), t.OsInfo.OsProductName); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_PRODUCT_NAME"), tmp); if (t.OsInfo.OsServicePack != 0) { UniFormat(tmp, sizeof(tmp), _UU("SM_OS_SP_TAG"), t.OsInfo.OsServicePack); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_SERVICE_PACK"), tmp); } StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVendorName); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VENDER_NAME"), tmp); StrToUni(tmp, sizeof(tmp), t.OsInfo.OsVersion); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_VERSION"), tmp); StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelName); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_NAME"), tmp); StrToUni(tmp, sizeof(tmp), t.OsInfo.KernelVersion); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_OS_KERNEL_VERSION"), tmp); // Memory information if (t.MemInfo.TotalMemory != 0) { char vv[128]; ToStr3(vv, sizeof(vv), t.MemInfo.TotalMemory); UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv); LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_TOTAL_MEMORY"), tmp); ToStr3(vv, sizeof(vv), t.MemInfo.UsedMemory); UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv); LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_USED_MEMORY"), tmp); ToStr3(vv, sizeof(vv), t.MemInfo.FreeMemory); UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv); LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_MEMORY"), tmp); ToStr3(vv, sizeof(vv), t.MemInfo.TotalPhys); UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv); LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_TOTAL_PHYS"), tmp); ToStr3(vv, sizeof(vv), t.MemInfo.UsedPhys); UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv); LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_USED_PHYS"), tmp); ToStr3(vv, sizeof(vv), t.MemInfo.FreePhys); UniFormat(tmp, sizeof(tmp), _UU("SM_ST_RAM_SIZE_KB"), vv); LvInsertAdd(b, ICO_MEMORY, NULL, 2, _UU("SM_ST_FREE_PHYS"), tmp); } LvInsertEnd(b, hWnd, L_STATUS); FreeRpcNatInfo(&t); return true; } // Show the status of the router bool NmStatus(HWND hWnd, SM_SERVER *s, void *param) { LVB *b; RPC_NAT_STATUS t; wchar_t tmp[MAX_SIZE]; SM_HUB *h = (SM_HUB *)param; // Validate arguments if (hWnd == NULL || s == NULL) { return false; } Zero(&t, sizeof(t)); StrCpy(t.HubName, sizeof(t.HubName), h->HubName); if (CALL(hWnd, ScGetSecureNATStatus(s->Rpc, &t)) == false) { return false; } b = LvInsertStart(); StrToUni(tmp, sizeof(tmp), h->HubName); LvInsertAdd(b, ICO_HUB, NULL, 2, _UU("SM_HUB_COLUMN_1"), tmp); UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumTcpSessions); LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_TCP"), tmp); UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumUdpSessions); LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_UDP"), tmp); UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumIcmpSessions); LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_ICMP"), tmp); UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_SESSION"), t.NumDnsSessions); LvInsertAdd(b, ICO_PROTOCOL, NULL, 2, _UU("NM_STATUS_DNS"), tmp); UniFormat(tmp, sizeof(tmp), _UU("SM_SNAT_NUM_CLIENT"), t.NumDhcpClients); LvInsertAdd(b, ICO_PROTOCOL_DHCP, NULL, 2, _UU("NM_STATUS_DHCP"), tmp); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_SNAT_IS_KERNEL"), t.IsKernelMode ? _UU("SEC_YES") : _UU("SEC_NO")); LvInsertAdd(b, ICO_MACHINE, NULL, 2, _UU("SM_SNAT_IS_RAW"), t.IsRawIpMode ? _UU("SEC_YES") : _UU("SEC_NO")); LvInsertEnd(b, hWnd, L_STATUS); FreeRpcNatStatus(&t); return true; } // Convert the contents of the form to the VH_OPTION void NmEditVhOptionFormToVH(HWND hWnd, VH_OPTION *t) { char tmp[MAX_SIZE]; BUF *b; // Validate arguments if (hWnd == NULL || t == NULL) { return; } Zero(t, sizeof(VH_OPTION)); GetTxtA(hWnd, E_MAC, tmp, sizeof(tmp)); b = StrToBin(tmp); if (b != NULL) { if (b->Size == 6) { Copy(t->MacAddress, b->Buf, 6); } FreeBuf(b); } UINTToIP(&t->Ip, IpGet(hWnd, E_IP)); UINTToIP(&t->Mask, IpGet(hWnd, E_MASK)); t->UseNat = IsChecked(hWnd, R_USE_NAT); t->Mtu = GetInt(hWnd, E_MTU); t->NatTcpTimeout = GetInt(hWnd, E_TCP); t->NatUdpTimeout = GetInt(hWnd, E_UDP); t->UseDhcp = IsChecked(hWnd, R_USE_DHCP); UINTToIP(&t->DhcpLeaseIPStart, IpGet(hWnd, E_DHCP_START)); UINTToIP(&t->DhcpLeaseIPEnd, IpGet(hWnd, E_DHCP_END)); UINTToIP(&t->DhcpSubnetMask, IpGet(hWnd, E_DHCP_MASK)); t->DhcpExpireTimeSpan = GetInt(hWnd, E_EXPIRES); UINTToIP(&t->DhcpGatewayAddress, IpGet(hWnd, E_GATEWAY)); UINTToIP(&t->DhcpDnsServerAddress, IpGet(hWnd, E_DNS)); UINTToIP(&t->DhcpDnsServerAddress2, IpGet(hWnd, E_DNS2)); GetTxtA(hWnd, E_DOMAIN, t->DhcpDomainName, sizeof(t->DhcpDomainName)); t->SaveLog = IsChecked(hWnd, R_SAVE_LOG); } // Initialize void NmEditVhOptionInit(HWND hWnd, SM_HUB *r) { char tmp[MAX_SIZE]; VH_OPTION t; // Validate arguments if (hWnd == NULL || r == NULL) { return; } SetIcon(hWnd, 0, ICO_ROUTER); FormatText(hWnd, S_TITLE, r->HubName); Zero(&t, sizeof(VH_OPTION)); StrCpy(t.HubName, sizeof(t.HubName), r->HubName); if (CALL(hWnd, ScGetSecureNATOption(r->Rpc, &t)) == false) { EndDialog(hWnd, false); return; } if (GetCapsBool(r->p->CapsList, "b_virtual_nat_disabled")) { SetEnable(hWnd, R_USE_NAT, false); Check(hWnd, R_USE_NAT, false); } MacToStr(tmp, sizeof(tmp), t.MacAddress); SetTextA(hWnd, E_MAC, tmp); IpSet(hWnd, E_IP, IPToUINT(&t.Ip)); IpSet(hWnd, E_MASK, IPToUINT(&t.Mask)); Check(hWnd, R_USE_NAT, t.UseNat); SetIntEx(hWnd, E_MTU, t.Mtu); SetIntEx(hWnd, E_TCP, t.NatTcpTimeout); SetIntEx(hWnd, E_UDP, t.NatUdpTimeout); Check(hWnd, R_USE_DHCP, t.UseDhcp); IpSet(hWnd, E_DHCP_START, IPToUINT(&t.DhcpLeaseIPStart)); IpSet(hWnd, E_DHCP_END, IPToUINT(&t.DhcpLeaseIPEnd)); IpSet(hWnd, E_DHCP_MASK, IPToUINT(&t.DhcpSubnetMask)); SetIntEx(hWnd, E_EXPIRES, t.DhcpExpireTimeSpan); if (IPToUINT(&t.DhcpGatewayAddress) != 0) { IpSet(hWnd, E_GATEWAY, IPToUINT(&t.DhcpGatewayAddress)); } if (IPToUINT(&t.DhcpDnsServerAddress) != 0) { IpSet(hWnd, E_DNS, IPToUINT(&t.DhcpDnsServerAddress)); } if (IPToUINT(&t.DhcpDnsServerAddress2) != 0) { IpSet(hWnd, E_DNS2, IPToUINT(&t.DhcpDnsServerAddress2)); } SetTextA(hWnd, E_DOMAIN, t.DhcpDomainName); Check(hWnd, R_SAVE_LOG, t.SaveLog); StrCpy(r->CurrentPushRouteStr, sizeof(r->CurrentPushRouteStr), t.DhcpPushRoutes); if (GetCapsBool(r->p->CapsList, "b_suppport_push_route_config") == false) { Disable(hWnd, S_1); Disable(hWnd, S_2); Disable(hWnd, B_PUSH); } NmEditVhOptionUpdate(hWnd, r); } void NmEditVhOptionUpdate(HWND hWnd, SM_HUB *r) { VH_OPTION t; bool ok = true; // Validate arguments if (hWnd == NULL || r == NULL) { return; } NmEditVhOptionFormToVH(hWnd, &t); if (IsZero(t.MacAddress, 6)) { ok = false; } if (IPToUINT(&t.Ip) == 0 || IPToUINT(&t.Mask) == 0) { ok = false; } if (IpIsFilled(hWnd, E_IP) == false || IpIsFilled(hWnd, E_MASK) == false) { ok = false; } if (IsHostIPAddress4(&t.Ip) == false || IsSubnetMask4(&t.Mask) == false) { ok = false; } if (t.UseNat) { if (t.Mtu < 64 || t.Mtu > 1500) { ok = false; } if (t.NatTcpTimeout < (NAT_TCP_MIN_TIMEOUT / 1000) || t.NatTcpTimeout > (NAT_TCP_MAX_TIMEOUT / 1000)) { ok = false; } if (t.NatUdpTimeout < (NAT_UDP_MIN_TIMEOUT / 1000) || t.NatUdpTimeout > (NAT_UDP_MAX_TIMEOUT / 1000)) { ok = false; } } if (t.UseDhcp) { if (IpIsFilled(hWnd, E_DHCP_START) == false || IpIsFilled(hWnd, E_DHCP_END) == false || IpIsFilled(hWnd, E_DHCP_MASK) == false) { ok = false; } if (IpGetFilledNum(hWnd, E_GATEWAY) != 0 && IpGetFilledNum(hWnd, E_GATEWAY) != 4) { ok = false; } if (IpGetFilledNum(hWnd, E_DNS) != 0 && IpGetFilledNum(hWnd, E_DNS) != 4) { ok = false; } if (IpGetFilledNum(hWnd, E_DNS2) != 0 && IpGetFilledNum(hWnd, E_DNS2) != 4) { ok = false; } if (IPToUINT(&t.DhcpLeaseIPStart) == 0 || IPToUINT(&t.DhcpLeaseIPEnd) == 0 || IPToUINT(&t.DhcpSubnetMask) == 0) { ok = false; } if (t.DhcpExpireTimeSpan < 15) { ok = false; } if (Endian32(IPToUINT(&t.DhcpLeaseIPStart)) > Endian32(IPToUINT(&t.DhcpLeaseIPEnd))) { ok = false; } if (IsHostIPAddress4(&t.DhcpLeaseIPStart) == false || IsHostIPAddress4(&t.DhcpLeaseIPEnd) == false) { ok = false; } if (IsSubnetMask4(&t.DhcpSubnetMask) == false) { ok = false; } } SetEnable(hWnd, E_MTU, t.UseNat); SetEnable(hWnd, E_TCP, t.UseNat); SetEnable(hWnd, E_UDP, t.UseNat); SetEnable(hWnd, E_DHCP_START, t.UseDhcp); SetEnable(hWnd, E_DHCP_END, t.UseDhcp); SetEnable(hWnd, E_DHCP_MASK, t.UseDhcp); SetEnable(hWnd, E_EXPIRES, t.UseDhcp); SetEnable(hWnd, E_GATEWAY, t.UseDhcp); SetEnable(hWnd, E_DNS, t.UseDhcp); SetEnable(hWnd, E_DNS2, t.UseDhcp); SetEnable(hWnd, E_DOMAIN, t.UseDhcp); SetEnable(hWnd, IDOK, ok); } // [OK] button void NmEditVhOptionOnOk(HWND hWnd, SM_HUB *r) { VH_OPTION t; // Validate arguments if (hWnd == NULL || r == NULL) { return; } NmEditVhOptionFormToVH(hWnd, &t); StrCpy(t.HubName, sizeof(t.HubName), r->HubName); t.ApplyDhcpPushRoutes = true; StrCpy(t.DhcpPushRoutes, sizeof(t.DhcpPushRoutes), r->CurrentPushRouteStr); if (CALL(hWnd, ScSetSecureNATOption(r->Rpc, &t))) { EndDialog(hWnd, true); } } // Virtual host options editing dialog UINT NmEditVhOptionProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { SM_HUB *r = (SM_HUB *)param; // Validate arguments if (hWnd == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: NmEditVhOptionInit(hWnd, r); break; case WM_COMMAND: switch (LOWORD(wParam)) { case E_MAC: case E_IP: case E_MASK: case R_USE_NAT: case E_MTU: case E_TCP: case E_UDP: case R_SAVE_LOG: case R_USE_DHCP: case E_DHCP_START: case E_DHCP_END: case E_DHCP_MASK: case E_EXPIRES: case E_GATEWAY: case E_DNS: case E_DNS2: case E_DOMAIN: NmEditVhOptionUpdate(hWnd, r); break; } switch (wParam) { case IDOK: NmEditVhOptionOnOk(hWnd, r); break; case IDCANCEL: EndDialog(hWnd, false); break; case R_USE_NAT: if (IsChecked(hWnd, R_USE_NAT)) { FocusEx(hWnd, E_MTU); } if (IsChecked(hWnd, R_USE_DHCP)) { Focus(hWnd, E_DHCP_START); } break; case B_PUSH: NmEditPushRoute(hWnd, r); break; } break; } return 0; } // Edit the virtual host option void NmEditVhOption(HWND hWnd, SM_HUB *r) { // Validate arguments if (hWnd == NULL || r == NULL) { return; } Zero(r->CurrentPushRouteStr, sizeof(r->CurrentPushRouteStr)); Dialog(hWnd, D_NM_OPTION, NmEditVhOptionProc, r); } // Edit the client configuration void NmEditClientConfig(HWND hWnd, RPC *r) { CM_ACCOUNT a; RPC_CREATE_LINK t; bool ret = false; // Validate arguments if (hWnd == NULL || r == NULL) { return; } Zero(&a, sizeof(a)); Zero(&t, sizeof(t)); a.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION)); a.NatMode = true; a.Rpc = r; if (CALLEX(hWnd, NcGetClientConfig(r, &t)) != ERR_NO_ERROR) { // Create New a.ClientOption->Port = 443; a.ClientOption->RetryInterval = 15; a.ClientOption->NumRetry = INFINITE; a.ClientOption->AdditionalConnectionInterval = 1; a.ClientOption->UseEncrypt = true; a.ClientOption->NoRoutingTracking = true; a.ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH)); a.ClientAuth->AuthType = CLIENT_AUTHTYPE_PASSWORD; } else { // Edit a.EditMode = true; Copy(a.ClientOption, t.ClientOption, sizeof(CLIENT_OPTION)); a.ClientAuth = CopyClientAuth(t.ClientAuth); FreeRpcCreateLink(&t); } ret = CmEditAccountDlg(hWnd, &a); Free(a.ServerCert); Free(a.ClientOption); CiFreeClientAuth(a.ClientAuth); } // Initialize void NmMainDlgInit(HWND hWnd, RPC *r) { // Validate arguments if (r == NULL || hWnd == NULL) { return; } SetIcon(hWnd, 0, ICO_ROUTER); FormatText(hWnd, 0, r->Sock->RemoteHostname); DlgFont(hWnd, S_STATUS, 11, true); NmMainDlgRefresh(hWnd, r); } // Update void NmMainDlgRefresh(HWND hWnd, RPC *r) { #if 0 RPC_NAT_STATUS t; wchar_t tmp[MAX_SIZE]; wchar_t tmp2[MAX_SIZE]; // Validate arguments if (r == NULL || hWnd == NULL) { return; } Zero(&t, sizeof(RPC_NAT_STATUS)); CALL(hWnd, NcGetStatus(r, &t)); if (t.Online == false) { UniStrCpy(tmp, sizeof(tmp), _UU("NM_OFFLINE")); Enable(hWnd, B_CONNECT); Disable(hWnd, B_DISCONNECT); } else { if (t.Connected) { UniFormat(tmp, sizeof(tmp), _UU("NM_CONNECTED"), t.Status.ServerName); } else { if (t.LastError == ERR_NO_ERROR) { UniStrCpy(tmp, sizeof(tmp), _UU("NM_CONNECTING")); } else { UniFormat(tmp, sizeof(tmp), _UU("NM_CONNECT_ERROR"), t.LastError, _E(t.LastError)); } } Disable(hWnd, B_CONNECT); Enable(hWnd, B_DISCONNECT); } UniFormat(tmp2, sizeof(tmp2), _UU("NM_STATUS_TAG"), tmp); SetText(hWnd, S_STATUS, tmp2); FreeRpcNatStatus(&t); #endif } // Main dialog procedure UINT NmMainDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { #if 0 SM_HUB *r = (SM_HUB *)param; RPC_DUMMY dummy; SM_SERVER sm; // Validate arguments if (hWnd == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: NmMainDlgInit(hWnd, r); SetTimer(hWnd, 1, NM_REFRESH_TIME, NULL); break; case WM_COMMAND: switch (wParam) { case B_SETTING: // Connection setting NmEditClientConfig(hWnd, r); break; case B_CONNECT: // Connection Zero(&dummy, sizeof(dummy)); CALL(hWnd, NcOnline(r, &dummy)); NmMainDlgRefresh(hWnd, r); break; case B_DISCONNECT: // Disconnect Zero(&dummy, sizeof(dummy)); CALL(hWnd, NcOffline(r, &dummy)); NmMainDlgRefresh(hWnd, r); break; case B_OPTION: // Operation setting NmEditVhOption(hWnd, r->Rpc); break; case B_NAT: // NAT NmNat(hWnd, r); break; case B_DHCP: // DHCP NmDhcp(hWnd, r); break; case B_STATUS: // Status Zero(&sm, sizeof(sm)); sm.Rpc = r; SmStatusDlg(hWnd, &sm, NULL, true, true, _UU("NM_STATUS"), ICO_ROUTER, NULL, NmStatus); break; case B_INFO: // Information Zero(&sm, sizeof(sm)); sm.Rpc = r; SmStatusDlg(hWnd, &sm, NULL, false, true, _UU("NM_INFO"), ICO_ROUTER, NULL, NmInfo); break; case B_REFRESH: // Refresh NmMainDlgRefresh(hWnd, r); break; case B_PASSWORD: // Change the password NmChangePassword(hWnd, r); break; case B_ABOUT: // Version information About(hWnd, nm->Cedar, CEDAR_ROUTER_STR); break; case IDCANCEL: Close(hWnd); break; } break; case WM_TIMER: switch (wParam) { case 1: KillTimer(hWnd, 1); if (IsEnable(hWnd, 0)) { NmMainDlgRefresh(hWnd, r); } SetTimer(hWnd, 1, NM_REFRESH_TIME, NULL); break; } break; case WM_CLOSE: EndDialog(hWnd, false); break; } #endif return 0; } // Main dialog void NmMainDlg(RPC *r) { // Validate arguments if (r == NULL) { return; } Dialog(NULL, D_NM_MAIN, NmMainDlgProc, r); } // Login dialog UINT NmLogin(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { NM_LOGIN *login = (NM_LOGIN *)param; char tmp[MAX_SIZE]; // Validate arguments if (hWnd == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: FormatText(hWnd, S_TITLE, login->Hostname); break; case WM_COMMAND: switch (wParam) { case IDOK: GetTxtA(hWnd, E_PASSWORD, tmp, sizeof(tmp)); Hash(login->hashed_password, tmp, StrLen(tmp), true); EndDialog(hWnd, true); break; case IDCANCEL: Close(hWnd); break; } break; case WM_CLOSE: EndDialog(hWnd, false); break; } return 0; } // Connecting dialog UINT NmConnectDlgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam, void *param) { NM_CONNECT *t = (NM_CONNECT *)param; RPC *rpc; NM_LOGIN login; UINT err; // Validate arguments if (hWnd == NULL) { return 0; } switch (msg) { case WM_INITDIALOG: FormatText(hWnd, S_TITLE, t->Hostname); SetTimer(hWnd, 1, 50, NULL); break; case WM_TIMER: switch (wParam) { case 1: KillTimer(hWnd, 1); while (true) { bool flag = false; RETRY_PASSWORD: // Password input dialog Zero(&login, sizeof(login)); login.Hostname = t->Hostname; login.Port = t->Port; Hash(login.hashed_password, "", 0, true); if (flag) { if (Dialog(hWnd, D_NM_LOGIN, NmLogin, &login) == false) { EndDialog(hWnd, false); break; } } RETRY_CONNECT: Refresh(DlgItem(hWnd, S_TITLE)); Refresh(hWnd); // Connection rpc = NatAdminConnect(nm->Cedar, t->Hostname, t->Port, login.hashed_password, &err); if (rpc != NULL) { t->Rpc = rpc; EndDialog(hWnd, true); break; } // Error if (err == ERR_ACCESS_DENIED || err == ERR_AUTH_FAILED) { if (flag) { if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _E(err)) == IDCANCEL) { EndDialog(hWnd, false); break; } } flag = true; goto RETRY_PASSWORD; } else { if (MsgBox(hWnd, MB_ICONEXCLAMATION | MB_RETRYCANCEL, _E(err)) == IDCANCEL) { EndDialog(hWnd, false); break; } goto RETRY_CONNECT; } } break; } break; } return 0; } // Connect to the User-mode NAT program RPC *NmConnect(char *hostname, UINT port) { NM_CONNECT t; // Validate arguments if (hostname == NULL || port == 0) { return NULL; } Zero(&t, sizeof(t)); t.Hostname = hostname; t.Port = port; Dialog(NULL, D_NM_CONNECT, NmConnectDlgProc, &t); return t.Rpc; } // Main process void MainNM() { UINT port; char hostname[MAX_HOST_NAME_LEN + 1]; char *tmp = RemoteDlg(NULL, NM_SETTING_REG_KEY, ICO_ROUTER, _UU("NM_TITLE"), _UU("NM_CONNECT_TITLE"), NULL); TOKEN_LIST *t; Zero(hostname, sizeof(hostname)); if (tmp == NULL) { return; } t = ParseToken(tmp, ":"); port = DEFAULT_NAT_ADMIN_PORT; if (t->NumTokens >= 2) { UINT i = ToInt(t->Token[1]); if (i != 0) { port = i; } } if (t->NumTokens >= 1) { RPC *rpc; StrCpy(hostname, sizeof(hostname), t->Token[0]); // Connection Trim(hostname); if (StrLen(hostname) != 0) { rpc = NmConnect(hostname, port); if (rpc != NULL) { // Connected NmMainDlg(rpc); NatAdminDisconnect(rpc); } } } FreeToken(t); Free(tmp); } // Initialize void InitNM() { if (nm != NULL) { // Already initialized return; } nm = ZeroMalloc(sizeof(NM)); InitWinUi(_UU("NM_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE")); nm->Cedar = NewCedar(NULL, NULL); InitCM(false); InitSM(); } // Release void FreeNM() { if (nm == NULL) { // Uninitialized return; } FreeSM(); FreeCM(); ReleaseCedar(nm->Cedar); FreeWinUi(); Free(nm); nm = NULL; } // Execution of NM void NMExec() { InitNM(); MainNM(); FreeNM(); } #endif // Developed by SoftEther VPN Project at University of Tsukuba in Japan. // Department of Computer Science has dozens of overly-enthusiastic geeks. // Join us: http://www.tsukuba.ac.jp/english/admission/