1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2024-09-20 10:40:39 +03:00
SoftEtherVPN/src/Cedar/Client.c
Michael Clausen 462840cf6e Using client parameter in function CtConnect
Using the global client variable might lead to strange behavoir if multiple clients are allocated and to crashes in the case the client was not initialized with CtStartClient()
2016-10-03 13:31:03 +02:00

11117 lines
224 KiB
C

// SoftEther VPN Source Code
// Cedar Communication Module
//
// SoftEther VPN Server, Client and Bridge are free software under GPLv2.
//
// Copyright (c) 2012-2016 Daiyuu Nobori.
// Copyright (c) 2012-2016 SoftEther VPN Project, University of Tsukuba, Japan.
// Copyright (c) 2012-2016 SoftEther Corporation.
//
// All Rights Reserved.
//
// http://www.softether.org/
//
// Author: Daiyuu Nobori
// Contributors:
// - nattoheaven (https://github.com/nattoheaven)
// 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.
// Client.c
// Client Manager
#include "CedarPch.h"
static CLIENT *client = NULL;
static LISTENER *cn_listener = NULL;
static LOCK *cn_listener_lock = NULL;
static UINT64 cn_next_allow = 0;
static LOCK *ci_active_sessions_lock = NULL;
static UINT ci_num_active_sessions = 0;
// In Windows 8 or later, change unreasonable setting of WCM to ensure normal VPN communication
void CiDisableWcmNetworkMinimize(CLIENT *c)
{
#ifdef OS_WIN32
// Validate arguments
if (c == NULL)
{
return;
}
if (c->Config.NoChangeWcmNetworkSettingOnWindows8)
{
return;
}
MsDisableWcmNetworkMinimize();
#endif // OS_WIN32
}
// Compare RPC_CLIENT_ENUM_ACCOUNT_ITEM items by last connected date (Reverse)
int CiCompareClientAccountEnumItemByLastConnectDateTime(void *p1, void *p2)
{
RPC_CLIENT_ENUM_ACCOUNT_ITEM *a1, *a2;
if (p1 == NULL || p2 == NULL)
{
return 0;
}
a1 = *(RPC_CLIENT_ENUM_ACCOUNT_ITEM **)p1;
a2 = *(RPC_CLIENT_ENUM_ACCOUNT_ITEM **)p2;
if (a1 == NULL || a2 == NULL)
{
return 0;
}
if (a1->LastConnectDateTime > a2->LastConnectDateTime)
{
return -1;
}
else if (a1->LastConnectDateTime < a2->LastConnectDateTime)
{
return 1;
}
return 0;
}
// If machine changed, reshuffle MAC address for all virtual NIC
void CiChangeAllVLanMacAddressIfMachineChanged(CLIENT *c)
{
UCHAR current_hash_new[SHA1_SIZE];
UCHAR current_hash[SHA1_SIZE];
UCHAR current_hash_old[SHA1_SIZE];
UCHAR saved_hash[SHA1_SIZE];
// Validate arguments
if (c == NULL)
{
return;
}
#ifdef OS_WIN32
if (MsIsAdmin() == false)
{
return;
}
#endif
CiGetCurrentMachineHashNew(current_hash_new);
CiGetCurrentMachineHash(current_hash);
CiGetCurrentMachineHashOld(current_hash_old);
if (CiReadLastMachineHash(saved_hash) == false)
{
CiWriteLastMachineHash(current_hash_new);
return;
}
if (Cmp(saved_hash, current_hash_old, SHA1_SIZE) == 0)
{
CiWriteLastMachineHash(current_hash_new);
return;
}
if (Cmp(saved_hash, current_hash, SHA1_SIZE) == 0)
{
CiWriteLastMachineHash(current_hash_new);
return;
}
if (Cmp(saved_hash, current_hash_new, SHA1_SIZE) == 0)
{
return;
}
if (CiWriteLastMachineHash(current_hash_new) == false)
{
return;
}
CiChangeAllVLanMacAddress(c);
}
// Get current machine hash (Old)
void CiGetCurrentMachineHashOld(void *data)
{
char name[MAX_PATH];
char *product_id = NULL;
// Validate arguments
if (data == NULL)
{
return;
}
#ifdef OS_WIN32
// Priduct ID
product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
if (product_id == NULL)
{
product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
}
StrCpy(name, sizeof(name), product_id);
Free(product_id);
#else // OS_WIN32
GetMachineName(name, sizeof(name));
#endif // OS_WIN32
Trim(name);
StrUpper(name);
Hash(data, name, StrLen(name), true);
}
// Get current machine hash
void CiGetCurrentMachineHash(void *data)
{
char name[MAX_PATH];
char *product_id = NULL;
// Validate arguments
if (data == NULL)
{
return;
}
GetMachineName(name, sizeof(name));
Trim(name);
StrUpper(name);
Hash(data, name, StrLen(name), true);
}
// Get current machine hash (without using domain name)
void CiGetCurrentMachineHashNew(void *data)
{
char name[MAX_PATH];
char *p;
// Validate arguments
if (data == NULL)
{
return;
}
GetMachineName(name, sizeof(name));
// Ignore after first period(.)
for(p=name; *p; p++)
if(*p == '.')
*p = 0;
Trim(name);
StrUpper(name);
Hash(data, name, StrLen(name), true);
}
// Write machine hash
bool CiWriteLastMachineHash(void *data)
{
// Validate arguments
if (data == NULL)
{
return false;
}
#ifdef OS_WIN32
if (MsRegWriteBinEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "LastMachineHash", data, SHA1_SIZE, true) == false)
{
return false;
}
return true;
#else // OS_WIN32
return false;
#endif // OS_WIN32
}
// Get previous machine hash
bool CiReadLastMachineHash(void *data)
{
BUF *b = NULL;
// Validate arguments
if (data == NULL)
{
return false;
}
#ifdef OS_WIN32
b = MsRegReadBinEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "LastMachineHash", true);
if (b == NULL)
{
return false;
}
if (b->Size == SHA1_SIZE)
{
Copy(data, b->Buf, b->Size);
FreeBuf(b);
return true;
}
FreeBuf(b);
return false;
#else // OS_WIN32
return false;
#endif // OS_WIN32
}
// If the MAC address of each virtual LAN card has been eliminated, set it to random numbers
// (measures for Windows 8 -> 8.1 upgrade problem)
void CiChangeAllVLanMacAddressIfCleared(CLIENT *c)
{
#ifdef OS_WIN32
RPC_CLIENT_ENUM_VLAN t;
// Validate arguments
if (c == NULL)
{
return;
}
if (MsIsInfCatalogRequired() == false)
{
// Not required for other than Windows 8
return;
}
Zero(&t, sizeof(t));
if (CtEnumVLan(c, &t))
{
UINT i;
for (i = 0;i < t.NumItem;i++)
{
RPC_CLIENT_ENUM_VLAN_ITEM *e = t.Items[i];
UCHAR mac[6];
if (StrToMac(mac, e->MacAddress))
{
if (mac[0] == 0x00 &&
mac[1] == 0x00 &&
mac[2] == 0x01 &&
mac[3] == 0x00 &&
mac[4] == 0x00 &&
mac[5] == 0x01)
{
char *name = e->DeviceName;
RPC_CLIENT_SET_VLAN s;
UCHAR mac[6];
GenMacAddress(mac);
Zero(&s, sizeof(s));
StrCpy(s.DeviceName, sizeof(s.DeviceName), name);
MacToStr(s.MacAddress, sizeof(s.MacAddress), mac);
CtSetVLan(c, &s);
}
}
}
CiFreeClientEnumVLan(&t);
}
#endif // OS_WIN32
}
// Set the MAC address of all virtual LAN cards to random number
void CiChangeAllVLanMacAddress(CLIENT *c)
{
RPC_CLIENT_ENUM_VLAN t;
// Validate arguments
if (c == NULL)
{
return;
}
Zero(&t, sizeof(t));
if (CtEnumVLan(c, &t))
{
UINT i;
for (i = 0;i < t.NumItem;i++)
{
RPC_CLIENT_ENUM_VLAN_ITEM *e = t.Items[i];
UCHAR mac[6];
if (StrToMac(mac, e->MacAddress) && mac[1] == 0xAC)
{
char *name = e->DeviceName;
RPC_CLIENT_SET_VLAN s;
UCHAR mac[6];
GenMacAddress(mac);
Zero(&s, sizeof(s));
StrCpy(s.DeviceName, sizeof(s.DeviceName), name);
MacToStr(s.MacAddress, sizeof(s.MacAddress), mac);
CtSetVLan(c, &s);
}
}
CiFreeClientEnumVLan(&t);
}
}
// Wait for preparation of notification service to complete
void CnWaitForCnServiceReady()
{
UINT64 start_time = Tick64();
while ((start_time + (UINT64)CLIENT_WAIT_CN_READY_TIMEOUT) >= Tick64())
{
if (CnIsCnServiceReady())
{
break;
}
SleepThread(100);
}
}
// Check whether preparation of notification service completed
bool CnIsCnServiceReady()
{
SOCK *s;
// Confirm running the notification service
if (CnCheckAlreadyExists(false) == false)
{
// Not running
return false;
}
// Try to connect to the TCP port
s = ConnectEx("localhost", CLIENT_NOTIFY_PORT, 500);
if (s == NULL)
{
// The TCP port is not opened
return false;
}
Disconnect(s);
ReleaseSock(s);
// Running
return true;
}
// Check whether the notification service is already running
bool CnCheckAlreadyExists(bool lock)
{
bool ret = false;
#ifdef OS_WIN32
ret = Win32CnCheckAlreadyExists(lock);
#endif
return ret;
}
typedef struct CNC_STATUS_PRINTER_WINDOW_PARAM
{
THREAD *Thread;
SESSION *Session;
SOCK *Sock;
} CNC_STATUS_PRINTER_WINDOW_PARAM;
typedef struct CNC_CONNECT_ERROR_DLG_THREAD_PARAM
{
SESSION *Session;
SOCK *Sock;
bool HaltThread;
EVENT *Event;
} CNC_CONNECT_ERROR_DLG_THREAD_PARAM;
// Get the file name of vpnclient.exe in Win32
char *CiGetVpnClientExeFileName()
{
if (Is64() == false)
{
return CLIENT_WIN32_EXE_FILENAME;
}
else
{
if (IsX64())
{
return CLIENT_WIN32_EXE_FILENAME_X64;
}
else
{
return CLIENT_WIN32_EXE_FILENAME_IA64;
}
}
}
// Thread to stop forcibly the Certificate check dialog client
void CncCheckCertHaltThread(THREAD *thread, void *param)
{
CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
while (true)
{
if (dp->Session->Halt || dp->HaltThread)
{
break;
}
Wait(dp->Event, 100);
}
Disconnect(dp->Sock);
}
// Show the certification check dialog
void CncCheckCert(SESSION *session, UI_CHECKCERT *dlg)
{
SOCK *s;
PACK *p;
CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
THREAD *t;
// Validate arguments
if (dlg == NULL || session == NULL)
{
return;
}
s = CncConnect();
if (s == NULL)
{
return;
}
p = NewPack();
PackAddStr(p, "function", "check_cert");
PackAddUniStr(p, "AccountName", dlg->AccountName);
PackAddStr(p, "ServerName", dlg->ServerName);
PackAddX(p, "x", dlg->x);
PackAddX(p, "parent_x", dlg->parent_x);
PackAddX(p, "old_x", dlg->old_x);
PackAddBool(p, "DiffWarning", dlg->DiffWarning);
PackAddBool(p, "Ok", dlg->Ok);
PackAddBool(p, "SaveServerCert", dlg->SaveServerCert);
SendPack(s, p);
FreePack(p);
dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
dp->Sock = s;
dp->Event = NewEvent();
dp->Session = session;
t = NewThread(CncCheckCertHaltThread, dp);
p = RecvPack(s);
if (p != NULL)
{
dlg->Ok = PackGetBool(p, "Ok");
dlg->DiffWarning = PackGetBool(p, "DiffWarning");
dlg->SaveServerCert = PackGetBool(p, "SaveServerCert");
FreePack(p);
}
dp->HaltThread = true;
Set(dp->Event);
WaitThread(t, INFINITE);
ReleaseEvent(dp->Event);
Free(dp);
ReleaseThread(t);
Disconnect(s);
ReleaseSock(s);
}
// Smart card signature dialog
bool CncSecureSignDlg(SECURE_SIGN *sign)
{
SOCK *s;
PACK *p;
bool ret = false;
// Validate arguments
if (sign == NULL)
{
return false;
}
s = CncConnect();
if (s == NULL)
{
return false;
}
p = NewPack();
PackAddStr(p, "function", "secure_sign");
OutRpcSecureSign(p, sign);
SendPack(s, p);
FreePack(p);
p = RecvPack(s);
if (p != NULL)
{
ret = PackGetBool(p, "ret");
if (ret)
{
FreeRpcSecureSign(sign);
Zero(sign, sizeof(SECURE_SIGN));
InRpcSecureSign(sign, p);
}
FreePack(p);
}
Disconnect(s);
ReleaseSock(s);
return ret;
}
// Show the NIC information dialog
SOCK *CncNicInfo(UI_NICINFO *info)
{
SOCK *s;
PACK *p;
bool ret = false;
// Validate arguments
if (info == NULL)
{
return NULL;
}
s = CncConnectEx(200);
if (s == NULL)
{
return NULL;
}
p = NewPack();
PackAddStr(p, "function", "nicinfo");
PackAddStr(p, "NicName", info->NicName);
PackAddUniStr(p, "AccountName", info->AccountName);
SendPack(s, p);
FreePack(p);
return s;
}
// Close the NIC information dialog
void CncNicInfoFree(SOCK *s)
{
// Validate arguments
if (s == NULL)
{
return;
}
Disconnect(s);
ReleaseSock(s);
}
// Show the message dialog
SOCK *CncMsgDlg(UI_MSG_DLG *dlg)
{
SOCK *s;
PACK *p;
bool ret = false;
char *utf;
// Validate arguments
if (dlg == NULL)
{
return NULL;
}
s = CncConnectEx(200);
if (s == NULL)
{
return NULL;
}
p = NewPack();
PackAddStr(p, "function", "msg_dialog");
PackAddStr(p, "ServerName", dlg->ServerName);
PackAddStr(p, "HubName", dlg->HubName);
utf = CopyUniToUtf(dlg->Msg);
PackAddData(p, "Msg", utf, StrLen(utf));
Free(utf);
SendPack(s, p);
FreePack(p);
return s;
}
// Close the message dialog
void CndMsgDlgFree(SOCK *s)
{
// Validate arguments
if (s == NULL)
{
return;
}
Disconnect(s);
ReleaseSock(s);
}
// The thread to stop the password input dialog client forcibly
void CncPasswordDlgHaltThread(THREAD *thread, void *param)
{
CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
while (true)
{
if (dp->Session->Halt || dp->HaltThread)
{
break;
}
Wait(dp->Event, 100);
}
Disconnect(dp->Sock);
}
// Show the password input dialog
bool CncPasswordDlg(SESSION *session, UI_PASSWORD_DLG *dlg)
{
SOCK *s;
PACK *p;
CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
THREAD *t;
bool ret = false;
// Validate arguments
if (dlg == NULL || session == NULL)
{
return false;
}
s = CncConnect();
if (s == NULL)
{
Wait(session->HaltEvent, session->RetryInterval);
return true;
}
p = NewPack();
PackAddStr(p, "function", "password_dialog");
PackAddInt(p, "Type", dlg->Type);
PackAddStr(p, "Username", dlg->Username);
PackAddStr(p, "Password", dlg->Password);
PackAddStr(p, "ServerName", dlg->ServerName);
PackAddInt(p, "RetryIntervalSec", dlg->RetryIntervalSec);
PackAddBool(p, "ProxyServer", dlg->ProxyServer);
PackAddBool(p, "AdminMode", dlg->AdminMode);
PackAddBool(p, "ShowNoSavePassword", dlg->ShowNoSavePassword);
PackAddBool(p, "NoSavePassword", dlg->NoSavePassword);
SendPack(s, p);
FreePack(p);
dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
dp->Session = session;
dp->Sock = s;
dp->Event = NewEvent();
t = NewThread(CncConnectErrorDlgHaltThread, dp);
p = RecvPack(s);
if (p != NULL)
{
ret = PackGetBool(p, "ok");
dlg->NoSavePassword = PackGetBool(p, "NoSavePassword");
dlg->ProxyServer = PackGetBool(p, "ProxyServer");
dlg->Type = PackGetInt(p, "Type");
PackGetStr(p, "Username", dlg->Username, sizeof(dlg->Username));
PackGetStr(p, "Password", dlg->Password, sizeof(dlg->Password));
FreePack(p);
}
dp->HaltThread = true;
Set(dp->Event);
WaitThread(t, INFINITE);
ReleaseEvent(dp->Event);
Free(dp);
ReleaseThread(t);
Disconnect(s);
ReleaseSock(s);
return ret;
}
// Thread to stop the connection error dialog client forcibly
void CncConnectErrorDlgHaltThread(THREAD *thread, void *param)
{
CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
while (true)
{
if (dp->Session->Halt || dp->HaltThread)
{
break;
}
Wait(dp->Event, 100);
}
Disconnect(dp->Sock);
}
// Show the connection error dialog
bool CncConnectErrorDlg(SESSION *session, UI_CONNECTERROR_DLG *dlg)
{
SOCK *s;
PACK *p;
CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
THREAD *t;
bool ret = false;
// Validate arguments
if (dlg == NULL || session == NULL)
{
return false;
}
s = CncConnect();
if (s == NULL)
{
Wait(session->HaltEvent, session->RetryInterval);
return true;
}
p = NewPack();
PackAddStr(p, "function", "connecterror_dialog");
PackAddUniStr(p, "AccountName", dlg->AccountName);
PackAddStr(p, "ServerName", dlg->ServerName);
PackAddInt(p, "Err", dlg->Err);
PackAddInt(p, "CurrentRetryCount", dlg->CurrentRetryCount);
PackAddInt(p, "RetryLimit", dlg->RetryLimit);
PackAddInt(p, "RetryIntervalSec", dlg->RetryIntervalSec);
PackAddBool(p, "HideWindow", dlg->HideWindow);
SendPack(s, p);
FreePack(p);
dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
dp->Session = session;
dp->Sock = s;
dp->Event = NewEvent();
t = NewThread(CncConnectErrorDlgHaltThread, dp);
p = RecvPack(s);
if (p != NULL)
{
ret = PackGetBool(p, "ok");
dlg->HideWindow = PackGetBool(p, "HideWindow");
FreePack(p);
}
dp->HaltThread = true;
Set(dp->Event);
WaitThread(t, INFINITE);
ReleaseEvent(dp->Event);
Free(dp);
ReleaseThread(t);
Disconnect(s);
ReleaseSock(s);
return ret;
}
// Thread for the status indicator client
void CncStatusPrinterWindowThreadProc(THREAD *thread, void *param)
{
CNC_STATUS_PRINTER_WINDOW_PARAM *pp;
SOCK *sock;
PACK *p;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
pp = (CNC_STATUS_PRINTER_WINDOW_PARAM *)param;
sock = pp->Sock;
pp->Thread = thread;
AddRef(pp->Thread->ref);
NoticeThreadInit(thread);
p = RecvPack(sock);
if (p != NULL)
{
// Stop the session
StopSessionEx(pp->Session, true);
FreePack(p);
}
}
// Create a status indicator client
SOCK *CncStatusPrinterWindowStart(SESSION *s)
{
SOCK *sock;
PACK *p;
THREAD *t;
CNC_STATUS_PRINTER_WINDOW_PARAM *param;
// Validate arguments
if (s == NULL)
{
return NULL;
}
sock = CncConnect();
if (sock == NULL)
{
return NULL;
}
p = NewPack();
PackAddStr(p, "function", "status_printer");
PackAddUniStr(p, "account_name", s->Account->ClientOption->AccountName);
if (SendPack(sock, p) == false)
{
FreePack(p);
ReleaseSock(sock);
return NULL;
}
FreePack(p);
param = ZeroMalloc(sizeof(CNC_STATUS_PRINTER_WINDOW_PARAM));
param->Sock = sock;
param->Session = s;
sock->Param = param;
t = NewThread(CncStatusPrinterWindowThreadProc, param);
WaitThreadInit(t);
ReleaseThread(t);
return sock;
}
// Send a string to the status indicator
void CncStatusPrinterWindowPrint(SOCK *s, wchar_t *str)
{
CNC_STATUS_PRINTER_WINDOW_PARAM *param;
PACK *p;
// Validate arguments
if (s == NULL || str == NULL)
{
return;
}
param = (CNC_STATUS_PRINTER_WINDOW_PARAM *)s->Param;
p = NewPack();
PackAddUniStr(p, "string", str);
SendPack(s, p);
FreePack(p);
}
// Stop the status indicator client
void CncStatusPrinterWindowStop(SOCK *s)
{
CNC_STATUS_PRINTER_WINDOW_PARAM *param;
// Validate arguments
if (s == NULL)
{
return;
}
param = (CNC_STATUS_PRINTER_WINDOW_PARAM *)s->Param;
// Disconnect the client socket
Disconnect(s);
// Terminate the thread
WaitThread(param->Thread, INFINITE);
ReleaseThread(param->Thread);
Free(param);
ReleaseSock(s);
}
// Start the driver installer for Windows Vista
bool CncExecDriverInstaller(char *arg)
{
SOCK *s = CncConnect();
PACK *p;
bool ret;
if (s == NULL)
{
return false;
}
p = NewPack();
PackAddStr(p, "function", "exec_driver_installer");
PackAddStr(p, "arg", arg);
SendPack(s, p);
FreePack(p);
p = RecvPack(s);
if (p == NULL)
{
Disconnect(s);
ReleaseSock(s);
return false;
}
ret = PackGetBool(p, "ret");
FreePack(p);
Disconnect(s);
ReleaseSock(s);
return ret;
}
// Let the current running client notification services releasing the socket
void CncReleaseSocket()
{
SOCK *s = CncConnect();
PACK *p;
if (s == NULL)
{
return;
}
p = NewPack();
PackAddStr(p, "function", "release_socket");
#ifdef OS_WIN32
PackAddInt(p, "pid", MsGetProcessId());
#endif // OS_WIN32
SendPack(s, p);
FreePack(p);
Disconnect(s);
ReleaseSock(s);
}
// Get the Session ID of the client notification service
UINT CncGetSessionId()
{
SOCK *s = CncConnect();
PACK *p;
UINT ret;
if (s == NULL)
{
return INFINITE;
}
p = NewPack();
PackAddStr(p, "function", "get_session_id");
SendPack(s, p);
FreePack(p);
p = RecvPack(s);
if (p == NULL)
{
Disconnect(s);
ReleaseSock(s);
return INFINITE;
}
ret = PackGetInt(p, "session_id");
FreePack(p);
Disconnect(s);
ReleaseSock(s);
return ret;
}
// Terminate the process of the client notification service
void CncExit()
{
SOCK *s = CncConnectEx(256);
PACK *p;
if (s != NULL)
{
p = NewPack();
PackAddStr(p, "function", "exit");
SendPack(s, p);
FreePack(p);
FreePack(RecvPack(s));
Disconnect(s);
ReleaseSock(s);
}
#ifdef OS_WIN32
MsKillOtherInstanceEx("vpnclient");
#endif // OS_WIN32
}
// Connect to the client notification service
SOCK *CncConnect()
{
return CncConnectEx(0);
}
SOCK *CncConnectEx(UINT timeout)
{
SOCK *s = ConnectEx("localhost", CLIENT_NOTIFY_PORT, timeout);
return s;
}
#ifdef OS_WIN32
// Thread for the certificate check dialog
void Win32CnCheckCertThreadProc(THREAD *thread, void *param)
{
UI_CHECKCERT *dlg;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
dlg = (UI_CHECKCERT *)param;
CheckCertDlg(dlg);
{
PACK *p = NewPack();
PackAddBool(p, "Ok", dlg->Ok);
PackAddBool(p, "SaveServerCert", dlg->SaveServerCert);
SendPack(dlg->Sock, p);
FreePack(p);
FreePack(RecvPack(dlg->Sock));
}
Disconnect(dlg->Sock);
}
// Certificate check dialog
void Win32CnCheckCert(SOCK *s, PACK *p)
{
UI_CHECKCERT dlg;
THREAD *t;
Zero(&dlg, sizeof(dlg));
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
PackGetUniStr(p, "AccountName", dlg.AccountName, sizeof(dlg.AccountName));
PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
dlg.x = PackGetX(p, "x");
dlg.parent_x = PackGetX(p, "parent_x");
dlg.old_x = PackGetX(p, "old_x");
dlg.DiffWarning = PackGetBool(p, "DiffWarning");
dlg.Ok = PackGetBool(p, "Ok");
dlg.SaveServerCert = PackGetBool(p, "SaveServerCert");
dlg.Sock = s;
t = NewThread(Win32CnCheckCertThreadProc, &dlg);
FreePack(RecvPack(s));
dlg.Halt = true;
WaitThread(t, INFINITE);
ReleaseThread(t);
FreeX(dlg.parent_x);
FreeX(dlg.old_x);
FreeX(dlg.x);
}
// Message display dialog thread procedure
void Win32CnMsgDlgThreadProc(THREAD *thread, void *param)
{
UI_MSG_DLG *dlg = (UI_MSG_DLG *)param;
wchar_t tmp[MAX_SIZE];
char url[MAX_SIZE];
// Validate arguments
if (thread == NULL || dlg == NULL)
{
return;
}
UniFormat(tmp, sizeof(tmp), _UU("CM_MSG_TITLE"),
dlg->ServerName, dlg->HubName);
if (IsURLMsg(dlg->Msg, url, sizeof(url)) == false)
{
OnceMsgEx(NULL, tmp, dlg->Msg, true, 167, &dlg->Halt);
}
else
{
if (MsExecute(url, NULL) == false)
{
OnceMsgEx(NULL, tmp, dlg->Msg, true, 167, &dlg->Halt);
}
}
Disconnect(dlg->Sock);
}
// NIC information dialog thread procedure
void Win32CnNicInfoThreadProc(THREAD *thread, void *param)
{
UI_NICINFO *info = (UI_NICINFO *)param;
// Validate arguments
if (thread == NULL || info == NULL)
{
return;
}
if (MsIsNt())
{
// Do not show a dialog on Windows 9x system
NicInfo(info);
}
Disconnect(info->Sock);
}
// NIC information dialog
void Win32CnNicInfo(SOCK *s, PACK *p)
{
UI_NICINFO info;
THREAD *t;
Zero(&info, sizeof(info));
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
PackGetStr(p, "NicName", info.NicName, sizeof(info.NicName));
PackGetUniStr(p, "AccountName", info.AccountName, sizeof(info.AccountName));
info.Sock = s;
t = NewThread(Win32CnNicInfoThreadProc, &info);
FreePack(RecvPack(s));
info.Halt = true;
WaitThread(t, INFINITE);
ReleaseThread(t);
}
// Message display dialog
void Win32CnMsgDlg(SOCK *s, PACK *p)
{
UI_MSG_DLG dlg;
THREAD *t;
UINT utf_size;
char *utf;
wchar_t *msg;
Zero(&dlg, sizeof(dlg));
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
PackGetStr(p, "HubName", dlg.HubName, sizeof(dlg.HubName));
utf_size = PackGetDataSize(p, "Msg");
utf = ZeroMalloc(utf_size + 8);
PackGetData(p, "Msg", utf);
msg = CopyUtfToUni(utf);
Free(utf);
dlg.Sock = s;
dlg.Msg = msg;
t = NewThread(Win32CnMsgDlgThreadProc, &dlg);
FreePack(RecvPack(s));
dlg.Halt = true;
WaitThread(t, INFINITE);
ReleaseThread(t);
Free(msg);
}
// Thread for Password input dialog
void Win32CnPasswordDlgThreadProc(THREAD *thread, void *param)
{
UI_PASSWORD_DLG *dlg;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
dlg = (UI_PASSWORD_DLG *)param;
if (PasswordDlg(NULL, dlg))
{
PACK *p = NewPack();
PackAddBool(p, "ok", true);
PackAddStr(p, "Username", dlg->Username);
PackAddStr(p, "Password", dlg->Password);
PackAddInt(p, "Type", dlg->Type);
PackAddBool(p, "ProxyServer", dlg->ProxyServer);
PackAddBool(p, "NoSavePassword", dlg->NoSavePassword);
SendPack(dlg->Sock, p);
FreePack(p);
FreePack(RecvPack(dlg->Sock));
}
Disconnect(dlg->Sock);
}
// Password input dialog
void Win32CnPasswordDlg(SOCK *s, PACK *p)
{
UI_PASSWORD_DLG dlg;
THREAD *t = NULL;
Zero(&dlg, sizeof(dlg));
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
dlg.Type = PackGetInt(p, "Type");
PackGetStr(p, "Username", dlg.Username, sizeof(dlg.Username));
PackGetStr(p, "Password", dlg.Password, sizeof(dlg.Password));
PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
dlg.RetryIntervalSec = PackGetInt(p, "RetryIntervalSec");
dlg.ProxyServer = PackGetBool(p, "ProxyServer");
dlg.AdminMode = PackGetBool(p, "AdminMode");
dlg.ShowNoSavePassword = PackGetBool(p, "ShowNoSavePassword");
dlg.NoSavePassword = PackGetBool(p, "NoSavePassword");
dlg.CancelEvent = NewEvent();
dlg.Sock = s;
t = NewThread(Win32CnPasswordDlgThreadProc, &dlg);
FreePack(RecvPack(s));
Set(dlg.CancelEvent);
WaitThread(t, INFINITE);
ReleaseEvent(dlg.CancelEvent);
ReleaseThread(t);
}
// Thread for the connection error dialog
void Win32CnConnectErrorDlgThreadProc(THREAD *thread, void *param)
{
UI_CONNECTERROR_DLG *dlg;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
dlg = (UI_CONNECTERROR_DLG *)param;
if (ConnectErrorDlg(dlg))
{
PACK *p = NewPack();
PackAddBool(p, "ok", true);
PackAddBool(p, "HideWindow", dlg->HideWindow);
SendPack(dlg->Sock, p);
FreePack(p);
FreePack(RecvPack(dlg->Sock));
}
Disconnect(dlg->Sock);
}
// Connection Error dialog (Win32)
void Win32CnConnectErrorDlg(SOCK *s, PACK *p)
{
UI_CONNECTERROR_DLG dlg;
THREAD *t;
Zero(&dlg, sizeof(dlg));
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
PackGetUniStr(p, "AccountName", dlg.AccountName, sizeof(dlg.AccountName));
PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
dlg.Err = PackGetInt(p, "Err");
dlg.CurrentRetryCount = PackGetInt(p, "CurrentRetryCount");
dlg.RetryLimit = PackGetInt(p, "RetryLimit");
dlg.RetryIntervalSec = PackGetInt(p, "RetryIntervalSec");
dlg.HideWindow = PackGetBool(p, "HideWindow");
dlg.CancelEvent = NewEvent();
dlg.Sock = s;
t = NewThread(Win32CnConnectErrorDlgThreadProc, &dlg);
FreePack(RecvPack(s));
Set(dlg.CancelEvent);
WaitThread(t, INFINITE);
ReleaseEvent(dlg.CancelEvent);
ReleaseThread(t);
}
// Status indicator (Win32)
void Win32CnStatusPrinter(SOCK *s, PACK *p)
{
STATUS_WINDOW *w;
wchar_t account_name[MAX_ACCOUNT_NAME_LEN + 1];
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
PackGetUniStr(p, "account_name", account_name, sizeof(account_name));
w = StatusPrinterWindowStart(s, account_name);
while (true)
{
PACK *p = RecvPack(s);
if (p == NULL)
{
// Exit the dialog because it is disconnected
break;
}
else
{
wchar_t tmp[MAX_SIZE];
// Rewrite the string
PackGetUniStr(p, "string", tmp, sizeof(tmp));
StatusPrinterWindowPrint(w, tmp);
FreePack(p);
}
}
StatusPrinterWindowStop(w);
}
// Start the driver installer (for Windows Vista)
void Win32CnExecDriverInstaller(SOCK *s, PACK *p)
{
char arg[MAX_SIZE];
bool ret;
void *helper = NULL;
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
if (PackGetStr(p, "arg", arg, sizeof(arg)) == false)
{
return;
}
if (MsIsVista())
{
helper = CmStartUacHelper();
}
ret = MsExecDriverInstaller(arg);
CmStopUacHelper(helper);
p = NewPack();
PackAddBool(p, "ret", ret);
SendPack(s, p);
FreePack(p);
}
#endif // OS_WIN32
// Start the driver installer
void CnExecDriverInstaller(SOCK *s, PACK *p)
{
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
#ifdef OS_WIN32
Win32CnExecDriverInstaller(s, p);
#endif // OS_WIN32
}
// Certificate confirmation dialog
void CnCheckCert(SOCK *s, PACK *p)
{
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
#ifdef OS_WIN32
Win32CnCheckCert(s, p);
#endif // OS_WIN32
}
// NIC information dialog
void CnNicInfo(SOCK *s, PACK *p)
{
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
#ifdef OS_WIN32
Win32CnNicInfo(s, p);
#endif // OS_WIN32
}
// Message display dialog
void CnMsgDlg(SOCK *s, PACK *p)
{
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
#ifdef OS_WIN32
Win32CnMsgDlg(s, p);
#endif // OS_WIN32
}
// Password input dialog
void CnPasswordDlg(SOCK *s, PACK *p)
{
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
#ifdef OS_WIN32
Win32CnPasswordDlg(s, p);
#endif // OS_WIN32
}
// Connection Error dialog
void CnConnectErrorDlg(SOCK *s, PACK *p)
{
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
#ifdef OS_WIN32
Win32CnConnectErrorDlg(s, p);
#endif // OS_WIN32
}
// Status indicator
void CnStatusPrinter(SOCK *s, PACK *p)
{
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
#ifdef OS_WIN32
Win32CnStatusPrinter(s, p);
#endif // OS_WIN32
}
// Client notification service listener thread
void CnListenerProc(THREAD *thread, void *param)
{
TCP_ACCEPTED_PARAM *data = (TCP_ACCEPTED_PARAM *)param;
SOCK *s;
PACK *p;
// Validate arguments
if (data == NULL || thread == NULL)
{
return;
}
#ifdef OS_WIN32
//Set Application ID
JL_SetCurrentProcessExplicitAppUserModelID(APPID_CM);
#endif // OS_WIN32
s = data->s;
AddRef(s->ref);
NoticeThreadInit(thread);
if (s->LocalIP.addr[0] == 127)
{
p = RecvPack(s);
if (p != NULL)
{
char function[MAX_SIZE];
if (PackGetStr(p, "function", function, sizeof(function)))
{
if (StrCmpi(function, "status_printer") == 0)
{
CnStatusPrinter(s, p);
}
else if (StrCmpi(function, "connecterror_dialog") == 0)
{
CnConnectErrorDlg(s, p);
}
else if (StrCmpi(function, "msg_dialog") == 0)
{
CnMsgDlg(s, p);
}
else if (StrCmpi(function, "nicinfo") == 0)
{
CnNicInfo(s, p);
}
else if (StrCmpi(function, "password_dialog") == 0)
{
CnPasswordDlg(s, p);
}
else if (StrCmpi(function, "secure_sign") == 0)
{
CnSecureSign(s, p);
}
else if (StrCmpi(function, "check_cert") == 0)
{
CnCheckCert(s, p);
}
else if (StrCmpi(function, "exit") == 0)
{
#ifdef OS_WIN32
MsTerminateProcess();
#else // OS_WIN32
_exit(0);
#endif // OS_WIN32
}
else if (StrCmpi(function, "get_session_id") == 0)
{
PACK *p = NewPack();
#ifdef OS_WIN32
PackAddInt(p, "session_id", MsGetCurrentTerminalSessionId());
#endif // OS_WIN32
SendPack(s, p);
FreePack(p);
}
else if (StrCmpi(function, "exec_driver_installer") == 0)
{
CnExecDriverInstaller(s, p);
}
else if (StrCmpi(function, "release_socket") == 0)
{
// Stop the listener
CnReleaseSocket(s, p);
}
}
FreePack(p);
}
}
Disconnect(s);
ReleaseSock(s);
}
// Do the Secure Sign
void CnSecureSign(SOCK *s, PACK *p)
{
SECURE_SIGN sign;
bool ret = false;
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
Zero(&sign, sizeof(sign));
InRpcSecureSign(&sign, p);
#ifdef OS_WIN32
// Win32: Show dialog
ret = Win32CiSecureSign(&sign);
#else // OS_WIN32
// UNIX: not implemented
ret = false;
#endif // OS_WIN32
p = NewPack();
OutRpcSecureSign(p, &sign);
FreeRpcSecureSign(&sign);
PackAddBool(p, "ret", ret);
SendPack(s, p);
FreePack(p);
}
// Stop the listener
void CnReleaseSocket(SOCK *s, PACK *p)
{
UINT pid = 0;
UINT current_pid = 0;
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
pid = PackGetInt(p, "pid");
#ifdef OS_WIN32
current_pid = MsGetProcessId();
#endif // OS_WIN32
if (current_pid == pid)
{
return;
}
Lock(cn_listener_lock);
{
if (cn_listener != NULL)
{
if (cn_listener->Halt == false)
{
StopListener(cn_listener);
cn_next_allow = Tick64() + (6 * 1000);
}
}
}
Unlock(cn_listener_lock);
}
// Start the client notification service
void CnStart()
{
CEDAR *cedar;
LISTENER *o;
UINT last_cursor_hash = 0;
bool last_session_active = false;
cn_next_allow = 0;
cn_listener_lock = NewLock();
#ifdef OS_WIN32
MsSetShutdownParameters(0xff, 0x00000001);
InitWinUi(_UU("CN_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
#endif // OS_WIN32
cedar = NewCedar(NULL, NULL);
if (CnCheckAlreadyExists(true))
{
// Already started
ReleaseCedar(cedar);
#ifdef OS_WIN32
FreeWinUi();
#endif // OS_WIN32
return;
}
#ifdef OS_WIN32
MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY,
"NotifyServerProcessId", MsGetProcessId());
#endif // OS_WIN32
DisableDosProtect();
BEGIN_LISTENER:
Lock(cn_listener_lock);
cn_listener = o = NewListenerEx2(cedar, LISTENER_TCP, CLIENT_NOTIFY_PORT, CnListenerProc, NULL, true);
Unlock(cn_listener_lock);
while (true)
{
UINT current_cursor_hash = 0;
bool cursor_changed = false;
#ifdef OS_WIN32
// Get the current cursor position
current_cursor_hash = MsGetCursorPosHash();
#endif // OS_WIN32
if (last_cursor_hash != current_cursor_hash)
{
// Check the cursor position
cursor_changed = true;
last_cursor_hash = current_cursor_hash;
}
Lock(cn_listener_lock);
// Check the status periodically after that the listener has started
if (cn_listener->Status == LISTENER_STATUS_TRYING || cn_listener->Halt)
{
bool session_active = false;
#ifdef OS_WIN32
session_active = MsIsCurrentTerminalSessionActive();
if (cursor_changed)
{
// If the cursor position is changed but the terminal session is
// not active, the cursor position is regarded as not changed.
if (session_active == false)
{
cursor_changed = false;
}
}
if (last_session_active != session_active)
{
//If the cursor position doesn't changed but the terminal session
// became active than previous, the cursor position is regarded as changed.
last_session_active = session_active;
if (session_active)
{
cursor_changed = true;
}
}
#endif // OS_WIN32
// If the port cannot be opened
if (cn_next_allow <= Tick64())
{
if (cursor_changed || cn_listener->Halt)
{
if (cursor_changed)
{
// It can be judged to have the rights to open the port
// since the mouse cursor is moving.
// So, take over the port which is owned by other process forcibly
CncReleaseSocket();
}
if (cn_listener->Halt)
{
ReleaseListener(cn_listener);
cn_listener = NULL;
Unlock(cn_listener_lock);
goto BEGIN_LISTENER;
}
}
}
}
Unlock(cn_listener_lock);
SleepThread(1000);
}
}
// Confirm whether the account file is parsed successfully
bool CiTryToParseAccount(BUF *b)
{
RPC_CLIENT_CREATE_ACCOUNT *a;
// Validate arguments
if (b == NULL)
{
return false;
}
a = CiCfgToAccount(b);
if (a != NULL)
{
CiFreeClientCreateAccount(a);
Free(a);
return true;
}
else
{
return false;
}
}
bool CiTryToParseAccountFile(wchar_t *name)
{
bool ret;
BUF *b;
// Validate arguments
if (name == NULL)
{
return false;
}
b = ReadDumpW(name);
if (b == NULL)
{
return false;
}
ret = CiTryToParseAccount(b);
FreeBuf(b);
return ret;
}
// Confirm whether the account information includes sensitive information
bool CiHasAccountSensitiveInformation(BUF *b)
{
RPC_CLIENT_CREATE_ACCOUNT *a;
bool ret = false;
// Validate arguments
if (b == NULL)
{
return false;
}
a = CiCfgToAccount(b);
if (a == NULL)
{
return false;
}
if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
{
ret = true;
}
else if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
{
ret = true;
}
CiFreeClientCreateAccount(a);
Free(a);
return ret;
}
bool CiHasAccountSensitiveInformationFile(wchar_t *name)
{
bool ret = false;
BUF *b;
// Validate arguments
if (name == NULL)
{
return false;
}
b = ReadDumpW(name);
if (b == NULL)
{
return false;
}
ret = CiHasAccountSensitiveInformation(b);
FreeBuf(b);
return ret;
}
// Delete the sensitive information in the account information
bool CiEraseSensitiveInAccount(BUF *b)
{
RPC_CLIENT_CREATE_ACCOUNT *a;
BUF *b2;
bool ret = false;
// Validate arguments
if (b == NULL)
{
return false;
}
a = CiCfgToAccount(b);
if (a == NULL)
{
return false;
}
if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
{
Zero(a->ClientAuth->HashedPassword, sizeof(a->ClientAuth->HashedPassword));
ClearStr(a->ClientAuth->Username, sizeof(a->ClientAuth->Username));
}
else if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
{
ClearStr(a->ClientAuth->PlainPassword, sizeof(a->ClientAuth->PlainPassword));
ClearStr(a->ClientAuth->Username, sizeof(a->ClientAuth->Username));
}
b2 = CiAccountToCfg(a);
if (b2 != NULL)
{
ret = true;
ClearBuf(b);
WriteBuf(b, b2->Buf, b2->Size);
SeekBuf(b, 0, 0);
FreeBuf(b2);
}
CiFreeClientCreateAccount(a);
Free(a);
return ret;
}
// Read the account information from the buffer
RPC_CLIENT_CREATE_ACCOUNT *CiCfgToAccount(BUF *b)
{
RPC_CLIENT_CREATE_ACCOUNT *t;
FOLDER *f;
ACCOUNT *a;
// Validate arguments
if (b == NULL)
{
return NULL;
}
f = CfgBufTextToFolder(b);
if (f == NULL)
{
return NULL;
}
a = CiLoadClientAccount(f);
CfgDeleteFolder(f);
if (a == NULL)
{
return NULL;
}
DeleteLock(a->lock);
t = ZeroMalloc(sizeof(RPC_CLIENT_CREATE_ACCOUNT));
t->ClientOption = a->ClientOption;
t->ClientAuth = a->ClientAuth;
t->StartupAccount = a->StartupAccount;
t->CheckServerCert = a->CheckServerCert;
t->ServerCert = a->ServerCert;
Free(a);
return t;
}
// Write the account information to a buffer
BUF *CiAccountToCfg(RPC_CLIENT_CREATE_ACCOUNT *t)
{
BUF *b;
FOLDER *root;
ACCOUNT a;
// Validate arguments
if (t == NULL)
{
return NULL;
}
root = CfgCreateFolder(NULL, TAG_ROOT);
Zero(&a, sizeof(a));
a.ClientOption = t->ClientOption;
a.ClientAuth = t->ClientAuth;
a.CheckServerCert = t->CheckServerCert;
a.ServerCert = t->ServerCert;
a.StartupAccount = t->StartupAccount;
CiWriteAccountData(root, &a);
b = CfgFolderToBufEx(root, true, true);
CfgDeleteFolder(root);
return b;
}
// RPC dispatch routine
PACK *CiRpcDispatch(RPC *rpc, char *name, PACK *p)
{
CLIENT *c = rpc->Param;
PACK *ret;
// Validate arguments
if (rpc == NULL || name == NULL || p == NULL)
{
return NULL;
}
ret = NewPack();
if (StrCmpi(name, "GetClientVersion") == 0)
{
RPC_CLIENT_VERSION a;
if (CtGetClientVersion(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientVersion(ret, &a);
}
}
else if (StrCmpi(name, "GetCmSetting") == 0)
{
CM_SETTING a;
if (CtGetCmSetting(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcCmSetting(ret, &a);
}
}
else if (StrCmpi(name, "SetCmSetting") == 0)
{
CM_SETTING a;
Zero(&a, sizeof(a));
InRpcCmSetting(&a, p);
if (CtSetCmSetting(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "SetPassword") == 0)
{
RPC_CLIENT_PASSWORD a;
InRpcClientPassword(&a, p);
if (CtSetPassword(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "GetPasswordSetting") == 0)
{
RPC_CLIENT_PASSWORD_SETTING a;
if (CtGetPasswordSetting(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientPasswordSetting(ret, &a);
}
}
else if (StrCmpi(name, "EnumCa") == 0)
{
RPC_CLIENT_ENUM_CA a;
if (CtEnumCa(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientEnumCa(ret, &a);
CiFreeClientEnumCa(&a);
}
}
else if (StrCmpi(name, "AddCa") == 0)
{
RPC_CERT a;
InRpcCert(&a, p);
if (CtAddCa(c, &a) == false)
{
RpcError(ret, c->Err);
}
FreeX(a.x);
}
else if (StrCmpi(name, "DeleteCa") == 0)
{
RPC_CLIENT_DELETE_CA a;
InRpcClientDeleteCa(&a, p);
if (CtDeleteCa(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "GetCa") == 0)
{
RPC_GET_CA a;
InRpcGetCa(&a, p);
if (CtGetCa(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcGetCa(ret, &a);
}
CiFreeGetCa(&a);
}
else if (StrCmpi(name, "EnumSecure") == 0)
{
RPC_CLIENT_ENUM_SECURE a;
if (CtEnumSecure(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientEnumSecure(ret, &a);
CiFreeClientEnumSecure(&a);
}
}
else if (StrCmpi(name, "UseSecure") == 0)
{
RPC_USE_SECURE a;
InRpcUseSecure(&a, p);
if (CtUseSecure(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "GetUseSecure") == 0)
{
RPC_USE_SECURE a;
Zero(&a, sizeof(a));
if (CtGetUseSecure(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcUseSecure(ret, &a);
}
}
else if (StrCmpi(name, "EnumObjectInSecure") == 0)
{
RPC_ENUM_OBJECT_IN_SECURE a;
if (CtEnumObjectInSecure(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcEnumObjectInSecure(ret, &a);
CiFreeEnumObjectInSecure(&a);
}
}
else if (StrCmpi(name, "CreateVLan") == 0)
{
RPC_CLIENT_CREATE_VLAN a;
InRpcCreateVLan(&a, p);
if (CtCreateVLan(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "UpgradeVLan") == 0)
{
RPC_CLIENT_CREATE_VLAN a;
InRpcCreateVLan(&a, p);
if (CtUpgradeVLan(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "GetVLan") == 0)
{
RPC_CLIENT_GET_VLAN a;
InRpcClientGetVLan(&a, p);
if (CtGetVLan(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientGetVLan(ret, &a);
}
}
else if (StrCmpi(name, "SetVLan") == 0)
{
RPC_CLIENT_SET_VLAN a;
InRpcClientSetVLan(&a, p);
if (CtSetVLan(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "EnumVLan") == 0)
{
RPC_CLIENT_ENUM_VLAN a;
if (CtEnumVLan(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientEnumVLan(ret, &a);
CiFreeClientEnumVLan(&a);
}
}
else if (StrCmpi(name, "DeleteVLan") == 0)
{
RPC_CLIENT_CREATE_VLAN a;
InRpcCreateVLan(&a, p);
if (CtDeleteVLan(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "EnableVLan") == 0)
{
RPC_CLIENT_CREATE_VLAN a;
InRpcCreateVLan(&a, p);
if (CtEnableVLan(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "DisableVLan") == 0)
{
RPC_CLIENT_CREATE_VLAN a;
InRpcCreateVLan(&a, p);
if (CtDisableVLan(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "CreateAccount") == 0)
{
RPC_CLIENT_CREATE_ACCOUNT a;
InRpcClientCreateAccount(&a, p);
if (CtCreateAccount(c, &a, false) == false)
{
RpcError(ret, c->Err);
}
CiFreeClientCreateAccount(&a);
}
else if (StrCmpi(name, "EnumAccount") == 0)
{
RPC_CLIENT_ENUM_ACCOUNT a;
if (CtEnumAccount(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientEnumAccount(ret, &a);
CiFreeClientEnumAccount(&a);
}
}
else if (StrCmpi(name, "DeleteAccount") == 0)
{
RPC_CLIENT_DELETE_ACCOUNT a;
InRpcClientDeleteAccount(&a, p);
if (CtDeleteAccount(c, &a, false) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "SetStartupAccount") == 0)
{
RPC_CLIENT_DELETE_ACCOUNT a;
InRpcClientDeleteAccount(&a, p);
if (CtSetStartupAccount(c, &a, false) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "RemoveStartupAccount") == 0)
{
RPC_CLIENT_DELETE_ACCOUNT a;
InRpcClientDeleteAccount(&a, p);
if (CtRemoveStartupAccount(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "GetIssuer") == 0)
{
RPC_GET_ISSUER a;
InRpcGetIssuer(&a, p);
if (CtGetIssuer(c, &a))
{
OutRpcGetIssuer(ret, &a);
}
else
{
RpcError(ret, c->Err);
}
CiFreeGetIssuer(&a);
}
else if (StrCmpi(name, "GetCommonProxySetting") == 0)
{
INTERNET_SETTING t;
InRpcInternetSetting(&t, p);
if (CtGetCommonProxySetting(c, &t))
{
OutRpcInternetSetting(ret, &t);
}
else
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "SetCommonProxySetting") == 0)
{
INTERNET_SETTING t;
InRpcInternetSetting(&t, p);
if (CtSetCommonProxySetting(c, &t))
{
OutRpcInternetSetting(ret, &t);
}
else
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "SetAccount") == 0)
{
RPC_CLIENT_CREATE_ACCOUNT a;
InRpcClientCreateAccount(&a, p);
if (CtSetAccount(c, &a, false) == false)
{
RpcError(ret, c->Err);
}
CiFreeClientCreateAccount(&a);
}
else if (StrCmpi(name, "GetAccount") == 0)
{
RPC_CLIENT_GET_ACCOUNT a;
InRpcClientGetAccount(&a, p);
if (CtGetAccount(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientGetAccount(ret, &a);
}
CiFreeClientGetAccount(&a);
}
else if (StrCmpi(name, "RenameAccount") == 0)
{
RPC_RENAME_ACCOUNT a;
InRpcRenameAccount(&a, p);
if (CtRenameAccount(c, &a, false) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "SetClientConfig") == 0)
{
CLIENT_CONFIG a;
InRpcClientConfig(&a, p);
if (CtSetClientConfig(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "GetClientConfig") == 0)
{
CLIENT_CONFIG a;
if (CtGetClientConfig(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientConfig(ret, &a);
}
}
else if (StrCmpi(name, "Connect") == 0)
{
RPC_CLIENT_CONNECT a;
InRpcClientConnect(&a, p);
if (CtConnect(c, &a) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "Disconnect") == 0)
{
RPC_CLIENT_CONNECT a;
InRpcClientConnect(&a, p);
if (CtDisconnect(c, &a, false) == false)
{
RpcError(ret, c->Err);
}
}
else if (StrCmpi(name, "GetAccountStatus") == 0)
{
RPC_CLIENT_GET_CONNECTION_STATUS a;
InRpcClientGetConnectionStatus(&a, p);
if (CtGetAccountStatus(c, &a) == false)
{
RpcError(ret, c->Err);
}
else
{
OutRpcClientGetConnectionStatus(ret, &a);
}
CiFreeClientGetConnectionStatus(&a);
}
else
{
FreePack(ret);
ret = NULL;
}
return ret;
}
// Set the CM_SETTING
UINT CcSetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a)
{
PACK *ret, *p;
UINT err;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcCmSetting(p, a);
ret = RpcCall(r->Rpc, "SetCmSetting", p);
if (RpcIsOk(ret))
{
FreePack(ret);
return 0;
}
else
{
err = RpcGetError(ret);
FreePack(ret);
return err;
}
}
// Get the CM_SETTING
UINT CcGetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a)
{
PACK *ret;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "GetCmSetting", NULL);
if (RpcIsOk(ret))
{
InRpcCmSetting(a, ret);
FreePack(ret);
return 0;
}
else
{
UINT err = RpcGetError(ret);
FreePack(ret);
return err;
}
}
// Get the client version
UINT CcGetClientVersion(REMOTE_CLIENT *r, RPC_CLIENT_VERSION *a)
{
PACK *ret;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "GetClientVersion", NULL);
if (RpcIsOk(ret))
{
InRpcClientVersion(a, ret);
FreePack(ret);
return 0;
}
else
{
UINT err = RpcGetError(ret);
FreePack(ret);
return err;
}
}
// Set the password
UINT CcSetPassword(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD *pass)
{
PACK *ret, *p;
// Validate arguments
if (r == NULL || pass == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientPassword(p, pass);
ret = RpcCall(r->Rpc, "SetPassword", p);
if (RpcIsOk(ret))
{
FreePack(ret);
return 0;
}
else
{
UINT err = RpcGetError(ret);
FreePack(ret);
return err;
}
}
// Get the password setting
UINT CcGetPasswordSetting(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD_SETTING *a)
{
PACK *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "GetPasswordSetting", NULL);
if (RpcIsOk(ret))
{
InRpcClientPasswordSetting(a, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Enumerate the CA
UINT CcEnumCa(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_CA *e)
{
PACK *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || e == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "EnumCa", NULL);
if (RpcIsOk(ret))
{
InRpcClientEnumCa(e, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Add the CA
UINT CcAddCa(REMOTE_CLIENT *r, RPC_CERT *cert)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || cert == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcCert(p, cert);
ret = RpcCall(r->Rpc, "AddCa", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Delete the CA
UINT CcDeleteCa(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_CA *c)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || c == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientDeleteCa(p, c);
ret = RpcCall(r->Rpc, "DeleteCa", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get the proxy setting
UINT CcGetCommonProxySetting(REMOTE_CLIENT *r, INTERNET_SETTING *a)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcInternetSetting(p, a);
ret = RpcCall(r->Rpc, "GetCommonProxySetting", p);
if (RpcIsOk(ret))
{
Zero(a, sizeof(INTERNET_SETTING));
InRpcInternetSetting(a, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Set the proxy setting
UINT CcSetCommonProxySetting(REMOTE_CLIENT *r, INTERNET_SETTING *a)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcInternetSetting(p, a);
ret = RpcCall(r->Rpc, "SetCommonProxySetting", p);
if (RpcIsOk(ret))
{
Zero(a, sizeof(INTERNET_SETTING));
InRpcInternetSetting(a, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get the issuer
UINT CcGetIssuer(REMOTE_CLIENT *r, RPC_GET_ISSUER *a)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcGetIssuer(p, a);
ret = RpcCall(r->Rpc, "GetIssuer", p);
if (RpcIsOk(ret))
{
if (a->x != NULL)
{
FreeX(a->x);
a->x = NULL;
}
InRpcGetIssuer(a, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get the CA
UINT CcGetCa(REMOTE_CLIENT *r, RPC_GET_CA *get)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || get == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcGetCa(p, get);
ret = RpcCall(r->Rpc, "GetCa", p);
if (RpcIsOk(ret))
{
InRpcGetCa(get, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Enumeration of the secure devices
UINT CcEnumSecure(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_SECURE *e)
{
PACK *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || e == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "EnumSecure", NULL);
if (RpcIsOk(ret))
{
InRpcClientEnumSecure(e, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get the secure device that the user is using
UINT CcGetUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || sec == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
ret = RpcCall(r->Rpc, "GetUseSecure", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
else
{
InRpcUseSecure(sec, ret);
}
FreePack(ret);
return err;
}
// Use the secure device
UINT CcUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || sec == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcUseSecure(p, sec);
ret = RpcCall(r->Rpc, "UseSecure", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Enumerate objects in the secure device
UINT CcEnumObjectInSecure(REMOTE_CLIENT *r, RPC_ENUM_OBJECT_IN_SECURE *e)
{
PACK *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || e == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "EnumObjectInSecure", NULL);
if (RpcIsOk(ret))
{
InRpcEnumObjectInSecure(e, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get a next recommended virtual LAN card name
bool CiGetNextRecommendedVLanName(REMOTE_CLIENT *r, char *name, UINT size)
{
RPC_CLIENT_ENUM_VLAN t;
UINT i;
bool b;
UINT j;
bool ok = false;
// Validate arguments
if (r == NULL || name == NULL)
{
return false;
}
Zero(&t, sizeof(t));
if (CcEnumVLan(r, &t) != ERR_NO_ERROR)
{
return false;
}
for (i = 1;i < 128;i++)
{
char tmp[MAX_SIZE];
CiGenerateVLanRegulatedName(tmp, sizeof(tmp), i);
b = false;
for (j = 0;j < t.NumItem;j++)
{
if (StrCmpi(t.Items[j]->DeviceName, tmp) == 0)
{
b = true;
break;
}
}
if (b == false)
{
ok = true;
StrCpy(name, size, tmp);
break;
}
}
if (ok)
{
CiFreeClientEnumVLan(&t);
}
return true;
}
// Generate a virtual LAN card name automatically
void CiGenerateVLanRegulatedName(char *name, UINT size, UINT i)
{
// Validate arguments
if (name == NULL)
{
return;
}
if (i == 1)
{
StrCpy(name, size, "VPN");
}
else
{
Format(name, size, "VPN%u", i);
}
}
// Examine whether the specified name is valid as a virtual LAN card name of Windows 8 and later?
bool CiIsValidVLanRegulatedName(char *name)
{
UINT i;
// Validate arguments
if (name == NULL)
{
return false;
}
for (i = 1;i < 128;i++)
{
char tmp[MAX_SIZE];
CiGenerateVLanRegulatedName(tmp, sizeof(tmp), i);
if (StrCmpi(name, tmp) == 0)
{
return true;
}
}
return false;
}
// Create a VLAN
UINT CcCreateVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create)
{
PACK *ret, *p;
UINT err = 0;
char *s = NULL;
// Validate arguments
if (r == NULL || create == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcCreateVLan(p, create);
#ifdef OS_WIN32
s = MsNoWarningSoundInit();
#endif // OS_WIN32
ret = RpcCall(r->Rpc, "CreateVLan", p);
#ifdef OS_WIN32
MsNoWarningSoundFree(s);
#endif // OS_WIN32
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Upgrade the VLAN
UINT CcUpgradeVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create)
{
PACK *ret, *p;
UINT err = 0;
char *s = NULL;
// Validate arguments
if (r == NULL || create == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcCreateVLan(p, create);
#ifdef OS_WIN32
s = MsNoWarningSoundInit();
#endif // OS_WIN32
ret = RpcCall(r->Rpc, "UpgradeVLan", p);
#ifdef OS_WIN32
MsNoWarningSoundFree(s);
#endif // OS_WIN32
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get the VLAN
UINT CcGetVLan(REMOTE_CLIENT *r, RPC_CLIENT_GET_VLAN *get)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || get == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientGetVLan(p, get);
ret = RpcCall(r->Rpc, "GetVLan", p);
if (RpcIsOk(ret))
{
InRpcClientGetVLan(get, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// VLAN configuration
UINT CcSetVLan(REMOTE_CLIENT *r, RPC_CLIENT_SET_VLAN *set)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || set == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientSetVLan(p, set);
ret = RpcCall(r->Rpc, "SetVLan", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Enumeration of VLAN
UINT CcEnumVLan(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_VLAN *e)
{
PACK *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || e == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "EnumVLan", NULL);
if (RpcIsOk(ret))
{
InRpcClientEnumVLan(e, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Delete the VLAN
UINT CcDeleteVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *d)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || d == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcCreateVLan(p, d);
ret = RpcCall(r->Rpc, "DeleteVLan", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Enable the VLAN
UINT CcEnableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || vlan == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcCreateVLan(p, vlan);
ret = RpcCall(r->Rpc, "EnableVLan", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Disable the VLAN
UINT CcDisableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || vlan == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcCreateVLan(p, vlan);
ret = RpcCall(r->Rpc, "DisableVLan", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Create an Account
UINT CcCreateAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientCreateAccount(p, a);
ret = RpcCall(r->Rpc, "CreateAccount", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Enumeration of accounts
UINT CcEnumAccount(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_ACCOUNT *e)
{
PACK *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || e == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "EnumAccount", NULL);
if (RpcIsOk(ret))
{
UINT i;
InRpcClientEnumAccount(e, ret);
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_ACCOUNT_ITEM *t = e->Items[i];
if (IsEmptyStr(t->HubName) && t->Port == 0)
{
UINT err2;
RPC_CLIENT_GET_ACCOUNT a;
// Because the Client Manager can not get the port number and HUB name
// when enumerating in the VPN Client of the old version, get these separately.
Zero(&a, sizeof(a));
UniStrCpy(a.AccountName, sizeof(a.AccountName), t->AccountName);
err2 = CcGetAccount(r, &a);
if (err2 == ERR_NO_ERROR)
{
StrCpy(t->HubName, sizeof(t->HubName), a.ClientOption->HubName);
t->Port = a.ClientOption->Port;
CiFreeClientGetAccount(&a);
}
}
}
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Unset the startup flag of the accout
UINT CcRemoveStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientDeleteAccount(p, a);
ret = RpcCall(r->Rpc, "RemoveStartupAccount", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Set to start-up flag of the account
UINT CcSetStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientDeleteAccount(p, a);
ret = RpcCall(r->Rpc, "SetStartupAccount", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Delete the account
UINT CcDeleteAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientDeleteAccount(p, a);
ret = RpcCall(r->Rpc, "DeleteAccount", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Account setting
UINT CcSetAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientCreateAccount(p, a);
ret = RpcCall(r->Rpc, "SetAccount", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get the account
UINT CcGetAccount(REMOTE_CLIENT *r, RPC_CLIENT_GET_ACCOUNT *a)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || a == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientGetAccount(p, a);
ret = RpcCall(r->Rpc, "GetAccount", p);
if (RpcIsOk(ret))
{
InRpcClientGetAccount(a, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Change the account name
UINT CcRenameAccount(REMOTE_CLIENT *r, RPC_RENAME_ACCOUNT *rename)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || rename == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcRenameAccount(p, rename);
ret = RpcCall(r->Rpc, "RenameAccount", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Set the Client configuration
UINT CcSetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o)
{
PACK *p, *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || o == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientConfig(p, o);
ret = RpcCall(r->Rpc, "SetClientConfig", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get the client configuration
UINT CcGetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o)
{
PACK *ret;
UINT err = 0;
// Validate arguments
if (r == NULL || o == NULL)
{
return ERR_INTERNAL_ERROR;
}
ret = RpcCall(r->Rpc, "GetClientConfig", NULL);
if (RpcIsOk(ret))
{
InRpcClientConfig(o, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Set the service to foreground process
void CcSetServiceToForegroundProcess(REMOTE_CLIENT *r)
{
// Validate arguments
if (r == NULL)
{
return;
}
// Abolition
/*
if (r->Rpc != NULL && r->Rpc->Sock != NULL && r->Rpc->Sock->RemoteIP.addr[0] == 127)
{
if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) &&
GET_KETA(GetOsInfo()->OsType, 100) >= 2)
{
// Only on a Windows 2000 or later
RPC_CLIENT_VERSION v;
Zero(&v, sizeof(v));
if (r->ClientBuildInt == 0)
{
CcGetClientVersion(r, &v);
r->ClientBuildInt = v.ClientBuildInt;
r->ProcessId = v.ProcessId;
}
if (r->ProcessId != 0 && r->ClientBuildInt <= 5080)
{
#ifdef OS_WIN32
// Set the service process as a foreground window
AllowFGWindow(v.ProcessId);
#endif // OS_WIN32
}
}
}*/
}
// Connect
UINT CcConnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || connect == NULL)
{
return ERR_INTERNAL_ERROR;
}
CcSetServiceToForegroundProcess(r);
p = NewPack();
OutRpcClientConnect(p, connect);
ret = RpcCall(r->Rpc, "Connect", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Disconnect
UINT CcDisconnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || connect == NULL)
{
return ERR_INTERNAL_ERROR;
}
CcSetServiceToForegroundProcess(r);
p = NewPack();
OutRpcClientConnect(p, connect);
ret = RpcCall(r->Rpc, "Disconnect", p);
if (RpcIsOk(ret) == false)
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Get the account status
UINT CcGetAccountStatus(REMOTE_CLIENT *r, RPC_CLIENT_GET_CONNECTION_STATUS *st)
{
PACK *ret, *p;
UINT err = 0;
// Validate arguments
if (r == NULL || st == NULL)
{
return ERR_INTERNAL_ERROR;
}
p = NewPack();
OutRpcClientGetConnectionStatus(p, st);
ret = RpcCall(r->Rpc, "GetAccountStatus", p);
if (RpcIsOk(ret))
{
InRpcClientGetConnectionStatus(st, ret);
}
else
{
err = RpcGetError(ret);
}
FreePack(ret);
return err;
}
// Client service sends a notification to the connection manager
void CiNotify(CLIENT *c)
{
CiNotifyInternal(c);
}
void CiNotifyInternal(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
// Set all the notification event
LockList(c->NotifyCancelList);
{
UINT i;
for (i = 0;i < LIST_NUM(c->NotifyCancelList);i++)
{
CANCEL *cancel = LIST_DATA(c->NotifyCancelList, i);
Cancel(cancel);
}
}
UnlockList(c->NotifyCancelList);
}
// Release the RPC_CLIENT_ENUM_ACCOUNT
void CiFreeClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *a)
{
UINT i;
// Validate arguments
if (a == NULL)
{
return;
}
for (i = 0;i < a->NumItem;i++)
{
RPC_CLIENT_ENUM_ACCOUNT_ITEM *e = a->Items[i];
Free(e);
}
Free(a->Items);
}
// Thread to save the configuration file periodically
void CiSaverThread(THREAD *t, void *param)
{
CLIENT *c = (CLIENT *)param;
// Validate arguments
if (t == NULL || param == NULL)
{
return;
}
NoticeThreadInit(t);
// Wait for a certain period of time
while (c->Halt == false)
{
Wait(c->SaverHalter, CLIENT_SAVER_INTERVAL);
// Save
CiSaveConfigurationFile(c);
}
}
// Initialize the Saver
void CiInitSaver(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
c->SaverHalter = NewEvent();
c->SaverThread = NewThread(CiSaverThread, c);
WaitThreadInit(c->SaverThread);
}
// Release the Saver
void CiFreeSaver(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
c->Halt = true;
Set(c->SaverHalter);
WaitThread(c->SaverThread, INFINITE);
ReleaseThread(c->SaverThread);
ReleaseEvent(c->SaverHalter);
}
// CM_SETTING
void InRpcCmSetting(CM_SETTING *c, PACK *p)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(CM_SETTING));
c->EasyMode = PackGetBool(p, "EasyMode");
c->LockMode = PackGetBool(p, "LockMode");
PackGetData2(p, "HashedPassword", c->HashedPassword, sizeof(c->HashedPassword));
}
void OutRpcCmSetting(PACK *p, CM_SETTING *c)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
PackAddBool(p, "EasyMode", c->EasyMode);
PackAddBool(p, "LockMode", c->LockMode);
PackAddData(p, "HashedPassword", c->HashedPassword, sizeof(c->HashedPassword));
}
// CLIENT_CONFIG
void InRpcClientConfig(CLIENT_CONFIG *c, PACK *p)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(CLIENT_CONFIG));
c->UseKeepConnect = PackGetInt(p, "UseKeepConnect") == 0 ? false : true;
c->KeepConnectPort = PackGetInt(p, "KeepConnectPort");
c->KeepConnectProtocol = PackGetInt(p, "KeepConnectProtocol");
c->KeepConnectInterval = PackGetInt(p, "KeepConnectInterval");
c->AllowRemoteConfig = PackGetInt(p, "AllowRemoteConfig") == 0 ? false : true;
PackGetStr(p, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost));
}
void OutRpcClientConfig(PACK *p, CLIENT_CONFIG *c)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
PackAddInt(p, "UseKeepConnect", c->UseKeepConnect);
PackAddInt(p, "KeepConnectPort", c->KeepConnectPort);
PackAddInt(p, "KeepConnectProtocol", c->KeepConnectProtocol);
PackAddInt(p, "KeepConnectInterval", c->KeepConnectInterval);
PackAddInt(p, "AllowRemoteConfig", c->AllowRemoteConfig);
PackAddStr(p, "KeepConnectHost", c->KeepConnectHost);
}
// RPC_CLIENT_VERSION
void InRpcClientVersion(RPC_CLIENT_VERSION *ver, PACK *p)
{
// Validate arguments
if (ver == NULL || p == NULL)
{
return;
}
Zero(ver, sizeof(RPC_CLIENT_VERSION));
PackGetStr(p, "ClientProductName", ver->ClientProductName, sizeof(ver->ClientProductName));
PackGetStr(p, "ClientVersionString", ver->ClientVersionString, sizeof(ver->ClientVersionString));
PackGetStr(p, "ClientBuildInfoString", ver->ClientBuildInfoString, sizeof(ver->ClientBuildInfoString));
ver->ClientVerInt = PackGetInt(p, "ClientVerInt");
ver->ClientBuildInt = PackGetInt(p, "ClientBuildInt");
ver->ProcessId = PackGetInt(p, "ProcessId");
ver->OsType = PackGetInt(p, "OsType");
ver->IsVLanNameRegulated = PackGetBool(p, "IsVLanNameRegulated");
ver->IsVgcSupported = PackGetBool(p, "IsVgcSupported");
ver->ShowVgcLink = PackGetBool(p, "ShowVgcLink");
PackGetStr(p, "ClientId", ver->ClientId, sizeof(ver->ClientId));
}
void OutRpcClientVersion(PACK *p, RPC_CLIENT_VERSION *ver)
{
// Validate arguments
if (ver == NULL || p == NULL)
{
return;
}
PackAddStr(p, "ClientProductName", ver->ClientProductName);
PackAddStr(p, "ClientVersionString", ver->ClientVersionString);
PackAddStr(p, "ClientBuildInfoString", ver->ClientBuildInfoString);
PackAddInt(p, "ClientVerInt", ver->ClientVerInt);
PackAddInt(p, "ClientBuildInt", ver->ClientBuildInt);
PackAddInt(p, "ProcessId", ver->ProcessId);
PackAddInt(p, "OsType", ver->OsType);
PackAddBool(p, "IsVLanNameRegulated", ver->IsVLanNameRegulated);
PackAddBool(p, "IsVgcSupported", ver->IsVgcSupported);
PackAddBool(p, "ShowVgcLink", ver->ShowVgcLink);
PackAddStr(p, "ClientId", ver->ClientId);
}
// RPC_CLIENT_PASSWORD
void InRpcClientPassword(RPC_CLIENT_PASSWORD *pw, PACK *p)
{
// Validate arguments
if (pw == NULL || p == NULL)
{
return;
}
Zero(pw, sizeof(RPC_CLIENT_PASSWORD));
PackGetStr(p, "Password", pw->Password, sizeof(pw->Password));
pw->PasswordRemoteOnly = PackGetInt(p, "PasswordRemoteOnly");
}
void OutRpcClientPassword(PACK *p, RPC_CLIENT_PASSWORD *pw)
{
// Validate arguments
if (pw == NULL || p == NULL)
{
return;
}
PackAddStr(p, "Password", pw->Password);
PackAddInt(p, "PasswordRemoteOnly", pw->PasswordRemoteOnly);
}
// RPC_CLIENT_PASSWORD_SETTING
void InRpcClientPasswordSetting(RPC_CLIENT_PASSWORD_SETTING *a, PACK *p)
{
// Validate arguments
if (a == NULL || p == NULL)
{
return;
}
Zero(a, sizeof(RPC_CLIENT_PASSWORD_SETTING));
a->IsPasswordPresented = PackGetInt(p, "IsPasswordPresented") == 0 ? false : true;
a->PasswordRemoteOnly = PackGetInt(p, "PasswordRemoteOnly") == 0 ? false : true;
}
void OutRpcClientPasswordSetting(PACK *p, RPC_CLIENT_PASSWORD_SETTING *a)
{
// Validate arguments
if (a == NULL || p == NULL)
{
return;
}
PackAddInt(p, "IsPasswordPresented", a->IsPasswordPresented);
PackAddInt(p, "PasswordRemoteOnly", a->PasswordRemoteOnly);
}
// RPC_CLIENT_ENUM_CA
void InRpcClientEnumCa(RPC_CLIENT_ENUM_CA *e, PACK *p)
{
UINT i;
// Validate arguments
if (e == NULL || p == NULL)
{
return;
}
Zero(e, sizeof(RPC_CLIENT_ENUM_CA));
e->NumItem = PackGetNum(p, "NumItem");
e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM *) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_CA_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM));
e->Items[i] = item;
item->Key = PackGetIntEx(p, "Key", i);
PackGetUniStrEx(p, "SubjectName", item->SubjectName, sizeof(item->SubjectName), i);
PackGetUniStrEx(p, "IssuerName", item->IssuerName, sizeof(item->IssuerName), i);
item->Expires = PackGetInt64Ex(p, "Expires", i);
}
}
void OutRpcClientEnumCa(PACK *p, RPC_CLIENT_ENUM_CA *e)
{
UINT i;
// Validate arguments
if (e == NULL || p == NULL)
{
return;
}
PackAddNum(p, "NumItem", e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_CA_ITEM *item = e->Items[i];
PackAddIntEx(p, "Key", item->Key, i, e->NumItem);
PackAddUniStrEx(p, "SubjectName", item->SubjectName, i, e->NumItem);
PackAddUniStrEx(p, "IssuerName", item->IssuerName, i, e->NumItem);
PackAddInt64Ex(p, "Expires", item->Expires, i, e->NumItem);
}
}
// RPC_GET_ISSUER
void InRpcGetIssuer(RPC_GET_ISSUER *c, PACK *p)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(RPC_GET_ISSUER));
b = PackGetBuf(p, "x");
if (b != NULL)
{
if (c->x != NULL)
{
FreeX(c->x);
}
c->x = BufToX(b, false);
FreeBuf(b);
}
b = PackGetBuf(p, "issuer_x");
if (b != NULL)
{
c->issuer_x = BufToX(b, false);
FreeBuf(b);
}
}
void OutRpcGetIssuer(PACK *p, RPC_GET_ISSUER *c)
{
BUF *b;
// Validate arguments
if (p == NULL || c == NULL)
{
return;
}
if (c->x != NULL)
{
b = XToBuf(c->x, false);
PackAddBuf(p, "x", b);
FreeBuf(b);
}
if (c->issuer_x != NULL)
{
b = XToBuf(c->issuer_x, false);
PackAddBuf(p, "issuer_x", b);
FreeBuf(b);
}
}
// TRAFFIC_EX
void InRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i)
{
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
Zero(t, sizeof(TRAFFIC));
t->Recv.BroadcastBytes = PackGetInt64Ex(p, "Ex.Recv.BroadcastBytes", i);
t->Recv.BroadcastCount = PackGetInt64Ex(p, "Ex.Recv.BroadcastCount", i);
t->Recv.UnicastBytes = PackGetInt64Ex(p, "Ex.Recv.UnicastBytes", i);
t->Recv.UnicastCount = PackGetInt64Ex(p, "Ex.Recv.UnicastCount", i);
t->Send.BroadcastBytes = PackGetInt64Ex(p, "Ex.Send.BroadcastBytes", i);
t->Send.BroadcastCount = PackGetInt64Ex(p, "Ex.Send.BroadcastCount", i);
t->Send.UnicastBytes = PackGetInt64Ex(p, "Ex.Send.UnicastBytes", i);
t->Send.UnicastCount = PackGetInt64Ex(p, "Ex.Send.UnicastCount", i);
}
void OutRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i, UINT num)
{
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
PackAddInt64Ex(p, "Ex.Recv.BroadcastBytes", t->Recv.BroadcastBytes, i, num);
PackAddInt64Ex(p, "Ex.Recv.BroadcastCount", t->Recv.BroadcastCount, i, num);
PackAddInt64Ex(p, "Ex.Recv.UnicastBytes", t->Recv.UnicastBytes, i, num);
PackAddInt64Ex(p, "Ex.Recv.UnicastCount", t->Recv.UnicastCount, i, num);
PackAddInt64Ex(p, "Ex.Send.BroadcastBytes", t->Send.BroadcastBytes, i, num);
PackAddInt64Ex(p, "Ex.Send.BroadcastCount", t->Send.BroadcastCount, i, num);
PackAddInt64Ex(p, "Ex.Send.UnicastBytes", t->Send.UnicastBytes, i, num);
PackAddInt64Ex(p, "Ex.Send.UnicastCount", t->Send.UnicastCount, i, num);
}
// TRAFFIC
void InRpcTraffic(TRAFFIC *t, PACK *p)
{
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
Zero(t, sizeof(TRAFFIC));
t->Recv.BroadcastBytes = PackGetInt64(p, "Recv.BroadcastBytes");
t->Recv.BroadcastCount = PackGetInt64(p, "Recv.BroadcastCount");
t->Recv.UnicastBytes = PackGetInt64(p, "Recv.UnicastBytes");
t->Recv.UnicastCount = PackGetInt64(p, "Recv.UnicastCount");
t->Send.BroadcastBytes = PackGetInt64(p, "Send.BroadcastBytes");
t->Send.BroadcastCount = PackGetInt64(p, "Send.BroadcastCount");
t->Send.UnicastBytes = PackGetInt64(p, "Send.UnicastBytes");
t->Send.UnicastCount = PackGetInt64(p, "Send.UnicastCount");
}
void OutRpcTraffic(PACK *p, TRAFFIC *t)
{
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
PackAddInt64(p, "Recv.BroadcastBytes", t->Recv.BroadcastBytes);
PackAddInt64(p, "Recv.BroadcastCount", t->Recv.BroadcastCount);
PackAddInt64(p, "Recv.UnicastBytes", t->Recv.UnicastBytes);
PackAddInt64(p, "Recv.UnicastCount", t->Recv.UnicastCount);
PackAddInt64(p, "Send.BroadcastBytes", t->Send.BroadcastBytes);
PackAddInt64(p, "Send.BroadcastCount", t->Send.BroadcastCount);
PackAddInt64(p, "Send.UnicastBytes", t->Send.UnicastBytes);
PackAddInt64(p, "Send.UnicastCount", t->Send.UnicastCount);
}
// RPC_CERT
void InRpcCert(RPC_CERT *c, PACK *p)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(RPC_CERT));
b = PackGetBuf(p, "x");
if (b == NULL)
{
return;
}
c->x = BufToX(b, false);
FreeBuf(b);
}
void OutRpcCert(PACK *p, RPC_CERT *c)
{
BUF *b;
// Validate arguments
if (p == NULL || c == NULL)
{
return;
}
if (c->x != NULL)
{
b = XToBuf(c->x, false);
PackAddBuf(p, "x", b);
FreeBuf(b);
}
}
// RPC_CLIENT_DELETE_CA
void InRpcClientDeleteCa(RPC_CLIENT_DELETE_CA *c, PACK *p)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(RPC_CLIENT_DELETE_CA));
c->Key = PackGetInt(p, "Key");
}
void OutRpcClientDeleteCa(PACK *p, RPC_CLIENT_DELETE_CA *c)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
PackAddInt(p, "Key", c->Key);
}
// RPC_GET_CA
void InRpcGetCa(RPC_GET_CA *c, PACK *p)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(RPC_GET_CA));
c->Key = PackGetInt(p, "Key");
b = PackGetBuf(p, "x");
if (b != NULL)
{
c->x = BufToX(b, false);
FreeBuf(b);
}
}
void OutRpcGetCa(PACK *p, RPC_GET_CA *c)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
PackAddInt(p, "Key", c->Key);
if (c->x != NULL)
{
BUF *b = XToBuf(c->x, false);
PackAddBuf(p, "x", b);
FreeBuf(b);
}
}
// RPC_CLIENT_ENUM_SECURE
void InRpcClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e, PACK *p)
{
UINT i;
// Validate arguments
if (e == NULL || p == NULL)
{
return;
}
Zero(e, sizeof(RPC_CLIENT_ENUM_SECURE));
e->NumItem = PackGetNum(p, "NumItem");
e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM *) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM));
item->DeviceId = PackGetIntEx(p, "DeviceId", i);
item->Type = PackGetIntEx(p, "Type", i);
PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
PackGetStrEx(p, "Manufacturer", item->Manufacturer, sizeof(item->Manufacturer), i);
}
}
void OutRpcClientEnumSecure(PACK *p, RPC_CLIENT_ENUM_SECURE *e)
{
UINT i;
// Validate arguments
if (e == NULL || p == NULL)
{
return;
}
PackAddNum(p, "NumItem", e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i];
PackAddIntEx(p, "DeviceId", item->DeviceId, i, e->NumItem);
PackAddIntEx(p, "Type", item->Type, i, e->NumItem);
PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);
PackAddStrEx(p, "Manufacturer", item->Manufacturer, i, e->NumItem);
}
}
// RPC_USE_SECURE
void InRpcUseSecure(RPC_USE_SECURE *u, PACK *p)
{
// Validate arguments
if (u == NULL || p == NULL)
{
return;
}
Zero(u, sizeof(RPC_USE_SECURE));
u->DeviceId = PackGetInt(p, "DeviceId");
}
void OutRpcUseSecure(PACK *p, RPC_USE_SECURE *u)
{
// Validate arguments
if (u == NULL || p == NULL)
{
return;
}
PackAddInt(p, "DeviceId", u->DeviceId);
}
// Release the RPC_ENUM_OBJECT_IN_SECURE
void CiFreeEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *a)
{
UINT i;
// Validate arguments
if (a == NULL)
{
return;
}
for (i = 0;i < a->NumItem;i++)
{
Free(a->ItemName[i]);
}
Free(a->ItemName);
Free(a->ItemType);
}
// RPC_ENUM_OBJECT_IN_SECURE
void InRpcEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *e, PACK *p)
{
UINT i;
// Validate arguments
if (e == NULL || p == NULL)
{
return;
}
Zero(e, sizeof(RPC_ENUM_OBJECT_IN_SECURE));
e->NumItem = PackGetNum(p, "NumItem");
e->hWnd = PackGetInt(p, "hWnd");
e->ItemName = ZeroMalloc(sizeof(char *) * e->NumItem);
e->ItemType = ZeroMalloc(sizeof(bool) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
char name[MAX_SIZE];
Zero(name, sizeof(name));
PackGetStrEx(p, "ItemName", name, sizeof(name), i);
e->ItemName[i] = CopyStr(name);
e->ItemType[i] = PackGetIntEx(p, "ItemType", i) ? true : false;
}
}
void OutRpcEnumObjectInSecure(PACK *p, RPC_ENUM_OBJECT_IN_SECURE *e)
{
UINT i;
// Validate arguments
if (e == NULL || p == NULL)
{
return;
}
PackAddNum(p, "NumItem", e->NumItem);
PackAddInt(p, "hWnd", e->hWnd);
for (i = 0;i < e->NumItem;i++)
{
PackAddStrEx(p, "ItemName", e->ItemName[i], i, e->NumItem);
PackAddIntEx(p, "ItemType", e->ItemType[i], i, e->NumItem);
}
}
// RPC_CLIENT_CREATE_VLAN
void InRpcCreateVLan(RPC_CLIENT_CREATE_VLAN *v, PACK *p)
{
// Validate arguments
if (v == NULL || p == NULL)
{
return;
}
Zero(v, sizeof(RPC_CLIENT_CREATE_VLAN));
PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
}
void OutRpcCreateVLan(PACK *p, RPC_CLIENT_CREATE_VLAN *v)
{
// Validate arguments
if (v == NULL || p == NULL)
{
return;
}
PackAddStr(p, "DeviceName", v->DeviceName);
}
// RPC_CLIENT_GET_VLAN
void InRpcClientGetVLan(RPC_CLIENT_GET_VLAN *v, PACK *p)
{
// Validate arguments
if (v == NULL || p == NULL)
{
return;
}
Zero(v, sizeof(RPC_CLIENT_GET_VLAN));
PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
v->Enabled = PackGetInt(p, "Enabled") ? true : false;
PackGetStr(p, "MacAddress", v->MacAddress, sizeof(v->MacAddress));
PackGetStr(p, "Version", v->Version, sizeof(v->Version));
PackGetStr(p, "FileName", v->FileName, sizeof(v->FileName));
PackGetStr(p, "Guid", v->Guid, sizeof(v->Guid));
}
void OutRpcClientGetVLan(PACK *p, RPC_CLIENT_GET_VLAN *v)
{
// Validate arguments
if (v == NULL || p == NULL)
{
return;
}
PackAddStr(p, "DeviceName", v->DeviceName);
PackAddInt(p, "Enabled", v->Enabled);
PackAddStr(p, "MacAddress", v->MacAddress);
PackAddStr(p, "Version", v->Version);
PackAddStr(p, "FileName", v->FileName);
PackAddStr(p, "Guid", v->Guid);
}
// RPC_CLIENT_SET_VLAN
void InRpcClientSetVLan(RPC_CLIENT_SET_VLAN *v, PACK *p)
{
// Validate arguments
if (v == NULL || p == NULL)
{
return;
}
Zero(v, sizeof(RPC_CLIENT_SET_VLAN));
PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
PackGetStr(p, "MacAddress", v->MacAddress, sizeof(v->MacAddress));
}
void OutRpcClientSetVLan(PACK *p, RPC_CLIENT_SET_VLAN *v)
{
// Validate arguments
if (v == NULL || p == NULL)
{
return;
}
PackAddStr(p, "DeviceName", v->DeviceName);
PackAddStr(p, "MacAddress", v->MacAddress);
}
// RPC_CLIENT_ENUM_VLAN
void InRpcClientEnumVLan(RPC_CLIENT_ENUM_VLAN *v, PACK *p)
{
UINT i;
// Validate arguments
if (v == NULL || p == NULL)
{
return;
}
Zero(v, sizeof(RPC_CLIENT_ENUM_VLAN));
v->NumItem = PackGetNum(p, "NumItem");
v->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * v->NumItem);
for (i = 0;i < v->NumItem;i++)
{
RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i] =
ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
item->Enabled = PackGetIntEx(p, "Enabled", i) ? true : false;
PackGetStrEx(p, "MacAddress", item->MacAddress, sizeof(item->MacAddress), i);
PackGetStrEx(p, "Version", item->Version, sizeof(item->Version), i);
}
}
void OutRpcClientEnumVLan(PACK *p, RPC_CLIENT_ENUM_VLAN *v)
{
UINT i;
// Validate arguments
if (v == NULL || p == NULL)
{
return;
}
PackAddNum(p, "NumItem", v->NumItem);
for (i = 0;i < v->NumItem;i++)
{
RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i];
PackAddStrEx(p, "DeviceName", item->DeviceName, i, v->NumItem);
PackAddIntEx(p, "Enabled", item->Enabled, i, v->NumItem);
PackAddStrEx(p, "MacAddress", item->MacAddress, i, v->NumItem);
PackAddStrEx(p, "Version", item->Version, i, v->NumItem);
}
}
// CLIENT_OPTION
void InRpcClientOption(CLIENT_OPTION *c, PACK *p)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(CLIENT_OPTION));
PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
PackGetStr(p, "Hostname", c->Hostname, sizeof(c->Hostname));
c->Port = PackGetInt(p, "Port");
c->PortUDP = PackGetInt(p, "PortUDP");
c->ProxyType = PackGetInt(p, "ProxyType");
c->ProxyPort = PackGetInt(p, "ProxyPort");
c->NumRetry = PackGetInt(p, "NumRetry");
c->RetryInterval = PackGetInt(p, "RetryInterval");
c->MaxConnection = PackGetInt(p, "MaxConnection");
c->AdditionalConnectionInterval = PackGetInt(p, "AdditionalConnectionInterval");
c->ConnectionDisconnectSpan = PackGetInt(p, "ConnectionDisconnectSpan");
c->HideStatusWindow = PackGetBool(p, "HideStatusWindow");
c->HideNicInfoWindow = PackGetBool(p, "HideNicInfoWindow");
c->DisableQoS = PackGetBool(p, "DisableQoS");
PackGetStr(p, "ProxyName", c->ProxyName, sizeof(c->ProxyName));
PackGetStr(p, "ProxyUsername", c->ProxyUsername, sizeof(c->ProxyUsername));
PackGetStr(p, "ProxyPassword", c->ProxyPassword, sizeof(c->ProxyPassword));
PackGetStr(p, "HubName", c->HubName, sizeof(c->HubName));
PackGetStr(p, "DeviceName", c->DeviceName, sizeof(c->DeviceName));
c->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;
c->UseCompress = PackGetInt(p, "UseCompress") ? true : false;
c->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;
c->NoRoutingTracking = PackGetInt(p, "NoRoutingTracking") ? true : false;
c->RequireMonitorMode = PackGetBool(p, "RequireMonitorMode");
c->RequireBridgeRoutingMode = PackGetBool(p, "RequireBridgeRoutingMode");
c->FromAdminPack = PackGetBool(p, "FromAdminPack");
c->NoTls1 = PackGetBool(p, "NoTls1");
c->NoUdpAcceleration = PackGetBool(p, "NoUdpAcceleration");
PackGetData2(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE);
}
void OutRpcClientOption(PACK *p, CLIENT_OPTION *c)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
PackAddUniStr(p, "AccountName", c->AccountName);
PackAddStr(p, "Hostname", c->Hostname);
PackAddStr(p, "ProxyName", c->ProxyName);
PackAddStr(p, "ProxyUsername", c->ProxyUsername);
PackAddStr(p, "ProxyPassword", c->ProxyPassword);
PackAddStr(p, "HubName", c->HubName);
PackAddStr(p, "DeviceName", c->DeviceName);
PackAddInt(p, "Port", c->Port);
PackAddInt(p, "PortUDP", c->PortUDP);
PackAddInt(p, "ProxyType", c->ProxyType);
PackAddInt(p, "ProxyPort", c->ProxyPort);
PackAddInt(p, "NumRetry", c->NumRetry);
PackAddInt(p, "RetryInterval", c->RetryInterval);
PackAddInt(p, "MaxConnection", c->MaxConnection);
PackAddInt(p, "UseEncrypt", c->UseEncrypt);
PackAddInt(p, "UseCompress", c->UseCompress);
PackAddInt(p, "HalfConnection", c->HalfConnection);
PackAddInt(p, "NoRoutingTracking", c->NoRoutingTracking);
PackAddInt(p, "AdditionalConnectionInterval", c->AdditionalConnectionInterval);
PackAddInt(p, "ConnectionDisconnectSpan", c->ConnectionDisconnectSpan);
PackAddBool(p, "HideStatusWindow", c->HideStatusWindow);
PackAddBool(p, "HideNicInfoWindow", c->HideNicInfoWindow);
PackAddBool(p, "RequireMonitorMode", c->RequireMonitorMode);
PackAddBool(p, "RequireBridgeRoutingMode", c->RequireBridgeRoutingMode);
PackAddBool(p, "DisableQoS", c->DisableQoS);
PackAddBool(p, "FromAdminPack", c->FromAdminPack);
PackAddBool(p, "NoTls1", c->NoTls1);
PackAddBool(p, "NoUdpAcceleration", c->NoUdpAcceleration);
PackAddData(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE);
}
// CLIENT_AUTH
void InRpcClientAuth(CLIENT_AUTH *c, PACK *p)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(CLIENT_AUTH));
c->AuthType = PackGetInt(p, "AuthType");
PackGetStr(p, "Username", c->Username, sizeof(c->Username));
switch (c->AuthType)
{
case CLIENT_AUTHTYPE_ANONYMOUS:
break;
case CLIENT_AUTHTYPE_PASSWORD:
if (PackGetDataSize(p, "HashedPassword") == SHA1_SIZE)
{
PackGetData(p, "HashedPassword", c->HashedPassword);
}
break;
case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
PackGetStr(p, "PlainPassword", c->PlainPassword, sizeof(c->PlainPassword));
break;
case CLIENT_AUTHTYPE_CERT:
b = PackGetBuf(p, "ClientX");
if (b != NULL)
{
c->ClientX = BufToX(b, false);
FreeBuf(b);
}
b = PackGetBuf(p, "ClientK");
if (b != NULL)
{
c->ClientK = BufToK(b, true, false, NULL);
FreeBuf(b);
}
break;
case CLIENT_AUTHTYPE_SECURE:
PackGetStr(p, "SecurePublicCertName", c->SecurePublicCertName, sizeof(c->SecurePublicCertName));
PackGetStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName, sizeof(c->SecurePrivateKeyName));
break;
}
}
void OutRpcClientAuth(PACK *p, CLIENT_AUTH *c)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
PackAddInt(p, "AuthType", c->AuthType);
PackAddStr(p, "Username", c->Username);
switch (c->AuthType)
{
case CLIENT_AUTHTYPE_ANONYMOUS:
break;
case CLIENT_AUTHTYPE_PASSWORD:
PackAddData(p, "HashedPassword", c->HashedPassword, SHA1_SIZE);
break;
case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
PackAddStr(p, "PlainPassword", c->PlainPassword);
break;
case CLIENT_AUTHTYPE_CERT:
b = XToBuf(c->ClientX, false);
if (b != NULL)
{
PackAddBuf(p, "ClientX", b);
FreeBuf(b);
}
b = KToBuf(c->ClientK, false, NULL);
if (b != NULL)
{
PackAddBuf(p, "ClientK", b);
FreeBuf(b);
}
break;
case CLIENT_AUTHTYPE_SECURE:
PackAddStr(p, "SecurePublicCertName", c->SecurePublicCertName);
PackAddStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName);
break;
}
}
// RPC_CLIENT_CREATE_ACCOUNT
void InRpcClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *c, PACK *p)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(RPC_CLIENT_CREATE_ACCOUNT));
c->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
c->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
InRpcClientOption(c->ClientOption, p);
InRpcClientAuth(c->ClientAuth, p);
c->StartupAccount = PackGetInt(p, "StartupAccount") ? true : false;
c->CheckServerCert = PackGetInt(p, "CheckServerCert") ? true : false;
b = PackGetBuf(p, "ServerCert");
if (b != NULL)
{
c->ServerCert = BufToX(b, false);
FreeBuf(b);
}
PackGetData2(p, "ShortcutKey", c->ShortcutKey, sizeof(c->ShortcutKey));
}
void OutRpcClientCreateAccount(PACK *p, RPC_CLIENT_CREATE_ACCOUNT *c)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
OutRpcClientOption(p, c->ClientOption);
OutRpcClientAuth(p, c->ClientAuth);
PackAddInt(p, "StartupAccount", c->StartupAccount);
PackAddInt(p, "CheckServerCert", c->CheckServerCert);
if (c->ServerCert != NULL)
{
b = XToBuf(c->ServerCert, false);
if (b != NULL)
{
PackAddBuf(p, "ServerCert", b);
FreeBuf(b);
}
}
PackAddData(p, "ShortcutKey", c->ShortcutKey, sizeof(c->ShortcutKey));
}
// RPC_CLIENT_ENUM_ACCOUNT
void InRpcClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *e, PACK *p)
{
UINT i;
// Validate arguments
if (e == NULL || p == NULL)
{
return;
}
Zero(e, sizeof(RPC_CLIENT_ENUM_ACCOUNT));
e->NumItem = PackGetNum(p, "NumItem");
e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM *) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i] =
ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM));
PackGetUniStrEx(p, "AccountName", item->AccountName, sizeof(item->AccountName), i);
PackGetStrEx(p, "UserName", item->UserName, sizeof(item->UserName), i);
PackGetStrEx(p, "ServerName", item->ServerName, sizeof(item->ServerName), i);
PackGetStrEx(p, "ProxyName", item->ProxyName, sizeof(item->ProxyName), i);
PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
item->ProxyType = PackGetIntEx(p, "ProxyType", i);
item->Active = PackGetIntEx(p, "Active", i) ? true : false;
item->StartupAccount = PackGetIntEx(p, "StartupAccount", i) ? true : false;
item->Connected = PackGetBoolEx(p, "Connected", i);
item->Port = PackGetIntEx(p, "Port", i);
PackGetStrEx(p, "HubName", item->HubName, sizeof(item->HubName), i);
item->CreateDateTime = PackGetInt64Ex(p, "CreateDateTime", i);
item->UpdateDateTime = PackGetInt64Ex(p, "UpdateDateTime", i);
item->LastConnectDateTime = PackGetInt64Ex(p, "LastConnectDateTime", i);
}
}
void OutRpcClientEnumAccount(PACK *p, RPC_CLIENT_ENUM_ACCOUNT *e)
{
UINT i;
// Validate arguments
if (e == NULL || p == NULL)
{
return;
}
PackAddNum(p, "NumItem", e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i];
PackAddUniStrEx(p, "AccountName", item->AccountName, i, e->NumItem);
PackAddStrEx(p, "UserName", item->UserName, i, e->NumItem);
PackAddStrEx(p, "ServerName", item->ServerName, i, e->NumItem);
PackAddStrEx(p, "ProxyName", item->ProxyName, i, e->NumItem);
PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);
PackAddIntEx(p, "ProxyType", item->ProxyType, i, e->NumItem);
PackAddIntEx(p, "Active", item->Active, i, e->NumItem);
PackAddIntEx(p, "StartupAccount", item->StartupAccount, i, e->NumItem);
PackAddBoolEx(p, "Connected", item->Connected, i, e->NumItem);
PackAddIntEx(p, "Port", item->Port, i, e->NumItem);
PackAddStrEx(p, "HubName", item->HubName, i, e->NumItem);
PackAddInt64Ex(p, "CreateDateTime", item->CreateDateTime, i, e->NumItem);
PackAddInt64Ex(p, "UpdateDateTime", item->UpdateDateTime, i, e->NumItem);
PackAddInt64Ex(p, "LastConnectDateTime", item->LastConnectDateTime, i, e->NumItem);
}
}
// RPC_CLIENT_DELETE_ACCOUNT
void InRpcClientDeleteAccount(RPC_CLIENT_DELETE_ACCOUNT *a, PACK *p)
{
// Validate arguments
if (a == NULL || p == NULL)
{
return;
}
Zero(a, sizeof(RPC_CLIENT_DELETE_ACCOUNT));
PackGetUniStr(p, "AccountName", a->AccountName, sizeof(a->AccountName));
}
void OutRpcClientDeleteAccount(PACK *p, RPC_CLIENT_DELETE_ACCOUNT *a)
{
// Validate arguments
if (a == NULL || p == NULL)
{
return;
}
PackAddUniStr(p, "AccountName", a->AccountName);
}
// RPC_RENAME_ACCOUNT
void InRpcRenameAccount(RPC_RENAME_ACCOUNT *a, PACK *p)
{
// Validate arguments
if (a == NULL || p == NULL)
{
return;
}
Zero(a, sizeof(RPC_RENAME_ACCOUNT));
PackGetUniStr(p, "OldName", a->OldName, sizeof(a->OldName));
PackGetUniStr(p, "NewName", a->NewName, sizeof(a->NewName));
}
void OutRpcRenameAccount(PACK *p, RPC_RENAME_ACCOUNT *a)
{
// Validate arguments
if (a == NULL || p == NULL)
{
return;
}
PackAddUniStr(p, "OldName", a->OldName);
PackAddUniStr(p, "NewName", a->NewName);
}
// RPC_CLIENT_GET_ACCOUNT
void InRpcClientGetAccount(RPC_CLIENT_GET_ACCOUNT *c, PACK *p)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(RPC_CLIENT_GET_ACCOUNT));
c->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
c->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
c->StartupAccount = PackGetInt(p, "StartupAccount") ? true : false;
c->CheckServerCert = PackGetInt(p, "CheckServerCert") ? true : false;
b = PackGetBuf(p, "ServerCert");
if (b != NULL)
{
c->ServerCert = BufToX(b, false);
FreeBuf(b);
}
InRpcClientOption(c->ClientOption, p);
InRpcClientAuth(c->ClientAuth, p);
c->CreateDateTime = PackGetInt64(p, "CreateDateTime");
c->UpdateDateTime = PackGetInt64(p, "UpdateDateTime");
c->LastConnectDateTime = PackGetInt64(p, "LastConnectDateTime");
PackGetData2(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);
}
void OutRpcClientGetAccount(PACK *p, RPC_CLIENT_GET_ACCOUNT *c)
{
BUF *b;
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
PackAddUniStr(p, "AccountName", c->AccountName);
PackAddInt(p, "StartupAccount", c->StartupAccount);
PackAddInt(p, "CheckServerCert", c->CheckServerCert);
if (c->ServerCert != NULL)
{
b = XToBuf(c->ServerCert, false);
if (b != NULL)
{
PackAddBuf(p, "ServerCert", b);
FreeBuf(b);
}
}
OutRpcClientOption(p, c->ClientOption);
OutRpcClientAuth(p, c->ClientAuth);
PackAddData(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);
PackAddInt64(p, "CreateDateTime", c->CreateDateTime);
PackAddInt64(p, "UpdateDateTime", c->UpdateDateTime);
PackAddInt64(p, "LastConnectDateTime", c->LastConnectDateTime);
}
// RPC_CLIENT_CONNECT
void InRpcClientConnect(RPC_CLIENT_CONNECT *c, PACK *p)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
Zero(c, sizeof(RPC_CLIENT_CONNECT));
PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
}
void OutRpcClientConnect(PACK *p, RPC_CLIENT_CONNECT *c)
{
// Validate arguments
if (c == NULL || p == NULL)
{
return;
}
PackAddUniStr(p, "AccountName", c->AccountName);
}
// POLICY
void InRpcPolicy(POLICY *o, PACK *p)
{
POLICY *pol;
// Validate arguments
if (o == NULL || p == NULL)
{
return;
}
pol = PackGetPolicy(p);
Copy(o, pol, sizeof(POLICY));
Free(pol);
}
void OutRpcPolicy(PACK *p, POLICY *o)
{
// Validate arguments
if (o == NULL || p == NULL)
{
return;
}
PackAddPolicy(p, o);
}
// RPC_CLIENT_GET_CONNECTION_STATUS
void InRpcClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *s, PACK *p)
{
BUF *b;
// Validate arguments
if (s == NULL || p == NULL)
{
return;
}
Zero(s, sizeof(RPC_CLIENT_GET_CONNECTION_STATUS));
PackGetUniStr(p, "AccountName", s->AccountName, sizeof(s->AccountName));
PackGetStr(p, "ServerName", s->ServerName, sizeof(s->ServerName));
PackGetStr(p, "ServerProductName", s->ServerProductName, sizeof(s->ServerProductName));
PackGetStr(p, "CipherName", s->CipherName, sizeof(s->CipherName));
PackGetStr(p, "SessionName", s->SessionName, sizeof(s->SessionName));
PackGetStr(p, "ConnectionName", s->ConnectionName, sizeof(s->ConnectionName));
if (PackGetDataSize(p, "SessionKey") == SHA1_SIZE)
{
PackGetData(p, "SessionKey", s->SessionKey);
}
s->SessionStatus = PackGetInt(p, "SessionStatus");
s->ServerPort = PackGetInt(p, "ServerPort");
s->ServerProductVer = PackGetInt(p, "ServerProductVer");
s->ServerProductBuild = PackGetInt(p, "ServerProductBuild");
s->NumConnectionsEatablished = PackGetInt(p, "NumConnectionsEatablished");
s->MaxTcpConnections = PackGetInt(p, "MaxTcpConnections");
s->NumTcpConnections = PackGetInt(p, "NumTcpConnections");
s->NumTcpConnectionsUpload = PackGetInt(p, "NumTcpConnectionsUpload");
s->NumTcpConnectionsDownload = PackGetInt(p, "NumTcpConnectionsDownload");
s->StartTime = PackGetInt64(p, "StartTime");
s->FirstConnectionEstablisiedTime = PackGetInt64(p, "FirstConnectionEstablisiedTime");
s->CurrentConnectionEstablishTime = PackGetInt64(p, "CurrentConnectionEstablishTime");
s->TotalSendSize = PackGetInt64(p, "TotalSendSize");
s->TotalRecvSize = PackGetInt64(p, "TotalRecvSize");
s->TotalSendSizeReal = PackGetInt64(p, "TotalSendSizeReal");
s->TotalRecvSizeReal = PackGetInt64(p, "TotalRecvSizeReal");
s->Active = PackGetInt(p, "Active") ? true : false;
s->Connected = PackGetInt(p, "Connected") ? true : false;
s->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;
s->QoS = PackGetInt(p, "QoS") ? true : false;
s->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;
s->UseCompress = PackGetInt(p, "UseCompress") ? true : false;
s->IsRUDPSession = PackGetInt(p, "IsRUDPSession") ? true : false;
PackGetStr(p, "UnderlayProtocol", s->UnderlayProtocol, sizeof(s->UnderlayProtocol));
s->IsUdpAccelerationEnabled = PackGetInt(p, "IsUdpAccelerationEnabled") ? true : false;
s->IsUsingUdpAcceleration = PackGetInt(p, "IsUsingUdpAcceleration") ? true : false;
s->IsBridgeMode = PackGetBool(p, "IsBridgeMode");
s->IsMonitorMode = PackGetBool(p, "IsMonitorMode");
s->VLanId = PackGetInt(p, "VLanId");
b = PackGetBuf(p, "ServerX");
if (b != NULL)
{
s->ServerX = BufToX(b, false);
FreeBuf(b);
}
b = PackGetBuf(p, "ClientX");
if (b != NULL)
{
s->ClientX = BufToX(b, false);
FreeBuf(b);
}
InRpcPolicy(&s->Policy, p);
InRpcTraffic(&s->Traffic, p);
}
void OutRpcClientGetConnectionStatus(PACK *p, RPC_CLIENT_GET_CONNECTION_STATUS *c)
{
BUF *b;
// Validate arguments
if (p == NULL || c == NULL)
{
return;
}
PackAddUniStr(p, "AccountName", c->AccountName);
PackAddStr(p, "ServerName", c->ServerName);
PackAddStr(p, "ServerProductName", c->ServerProductName);
PackAddStr(p, "CipherName", c->CipherName);
PackAddStr(p, "SessionName", c->SessionName);
PackAddStr(p, "ConnectionName", c->ConnectionName);
PackAddData(p, "SessionKey", c->SessionKey, SHA1_SIZE);
PackAddInt(p, "Active", c->Active);
PackAddInt(p, "Connected", c->Connected);
PackAddInt(p, "SessionStatus", c->SessionStatus);
PackAddInt(p, "ServerPort", c->ServerPort);
PackAddInt(p, "ServerProductVer", c->ServerProductVer);
PackAddInt(p, "ServerProductBuild", c->ServerProductBuild);
PackAddInt(p, "NumConnectionsEatablished", c->NumConnectionsEatablished);
PackAddInt(p, "HalfConnection", c->HalfConnection);
PackAddInt(p, "QoS", c->QoS);
PackAddInt(p, "MaxTcpConnections", c->MaxTcpConnections);
PackAddInt(p, "NumTcpConnections", c->NumTcpConnections);
PackAddInt(p, "NumTcpConnectionsUpload", c->NumTcpConnectionsUpload);
PackAddInt(p, "NumTcpConnectionsDownload", c->NumTcpConnectionsDownload);
PackAddInt(p, "UseEncrypt", c->UseEncrypt);
PackAddInt(p, "UseCompress", c->UseCompress);
PackAddInt(p, "IsRUDPSession", c->IsRUDPSession);
PackAddStr(p, "UnderlayProtocol", c->UnderlayProtocol);
PackAddInt(p, "IsUdpAccelerationEnabled", c->IsUdpAccelerationEnabled);
PackAddInt(p, "IsUsingUdpAcceleration", c->IsUsingUdpAcceleration);
PackAddBool(p, "IsBridgeMode", c->IsBridgeMode);
PackAddBool(p, "IsMonitorMode", c->IsMonitorMode);
PackAddInt64(p, "StartTime", c->StartTime);
PackAddInt64(p, "FirstConnectionEstablisiedTime", c->FirstConnectionEstablisiedTime);
PackAddInt64(p, "CurrentConnectionEstablishTime", c->CurrentConnectionEstablishTime);
PackAddInt64(p, "TotalSendSize", c->TotalSendSize);
PackAddInt64(p, "TotalRecvSize", c->TotalRecvSize);
PackAddInt64(p, "TotalSendSizeReal", c->TotalSendSizeReal);
PackAddInt64(p, "TotalRecvSizeReal", c->TotalRecvSizeReal);
PackAddInt(p, "VLanId", c->VLanId);
OutRpcPolicy(p, &c->Policy);
OutRpcTraffic(p, &c->Traffic);
if (c->ServerX != NULL)
{
b = XToBuf(c->ServerX, false);
PackAddBuf(p, "ServerX", b);
FreeBuf(b);
}
if (c->ClientX != NULL)
{
b = XToBuf(c->ClientX, false);
PackAddBuf(p, "ClientX", b);
FreeBuf(b);
}
}
void InRpcClientNotify(RPC_CLIENT_NOTIFY *n, PACK *p)
{
// Validate arguments
if (n == NULL || p == NULL)
{
return;
}
Zero(n, sizeof(RPC_CLIENT_NOTIFY));
n->NotifyCode = PackGetInt(p, "NotifyCode");
}
void OutRpcClientNotify(PACK *p, RPC_CLIENT_NOTIFY *n)
{
// Validate arguments
if (n == NULL || p == NULL)
{
return;
}
PackAddInt(p, "NotifyCode", n->NotifyCode);
}
// Notification main
void CiNotifyMain(CLIENT *c, SOCK *s)
{
CANCEL *cancel;
// Validate arguments
if (c == NULL || s == NULL)
{
return;
}
// Register a Cencel
cancel = NewCancel();
LockList(c->NotifyCancelList);
{
Add(c->NotifyCancelList, cancel);
}
UnlockList(c->NotifyCancelList);
// Wait
while (true)
{
char ch = '@';
SOCKSET set;
InitSockSet(&set);
AddSockSet(&set, s);
Select(&set, INFINITE, cancel, NULL);
if (c->Halt)
{
// Abort
break;
}
// 1 byte transmission
if (Send(s, &ch, 1, false) == 0)
{
// Disconnected
break;
}
}
// Disconnect
Disconnect(s);
// Unregister the Cancel
LockList(c->NotifyCancelList);
{
Delete(c->NotifyCancelList, cancel);
}
UnlockList(c->NotifyCancelList);
ReleaseCancel(cancel);
}
// RPC acceptance code
void CiRpcAccepted(CLIENT *c, SOCK *s)
{
UCHAR hashed_password[SHA1_SIZE];
UINT rpc_mode;
UINT retcode;
RPC *rpc;
// Validate arguments
if (c == NULL || s == NULL)
{
return;
}
// Receive the RPC mode
if (RecvAll(s, &rpc_mode, sizeof(UINT), false) == false)
{
return;
}
rpc_mode = Endian32(rpc_mode);
if (rpc_mode == CLIENT_RPC_MODE_NOTIFY)
{
// Notification mode
CiNotifyMain(c, s);
return;
}
else if (rpc_mode == CLIENT_RPC_MODE_SHORTCUT || rpc_mode == CLIENT_RPC_MODE_SHORTCUT_DISCONNECT)
{
// Shortcut key received
UCHAR key[SHA1_SIZE];
UINT err = ERR_NO_ERROR;
if (RecvAll(s, key, SHA1_SIZE, false))
{
UINT i;
wchar_t title[MAX_ACCOUNT_NAME_LEN + 1];
bool ok = false;
// Connect to the specified setting
LockList(c->AccountList);
{
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
Lock(a->lock);
{
if (Cmp(a->ShortcutKey, key, SHA1_SIZE) == 0)
{
ok = true;
UniStrCpy(title, sizeof(title), a->ClientOption->AccountName);
}
}
Unlock(a->lock);
}
}
UnlockList(c->AccountList);
if (ok == false)
{
err = ERR_ACCOUNT_NOT_FOUND;
}
else
{
RPC_CLIENT_CONNECT t;
Zero(&t, sizeof(t));
UniStrCpy(t.AccountName, sizeof(t.AccountName), title);
if (rpc_mode == CLIENT_RPC_MODE_SHORTCUT)
{
// Connect
if (CtConnect(c, &t))
{
err = ERR_NO_ERROR;
}
else
{
err = c->Err;
}
}
else
{
// Connect
if (CtDisconnect(c, &t, false))
{
err = ERR_NO_ERROR;
}
else
{
err = c->Err;
}
}
}
err = Endian32(err);
SendAll(s, &err, sizeof(UINT), false);
RecvAll(s, &err, sizeof(UINT), false);
}
return;
}
// Password reception
if (RecvAll(s, hashed_password, SHA1_SIZE, false) == false)
{
return;
}
retcode = 0;
// Password comparison
if (Cmp(hashed_password, c->EncryptedPassword, SHA1_SIZE) != 0)
{
retcode = 1;
}
if (c->PasswordRemoteOnly && s->RemoteIP.addr[0] == 127)
{
// If in a mode that requires a password only remote,
// the password sent from localhost is considered to be always correct
retcode = 0;
}
Lock(c->lock);
{
if (c->Config.AllowRemoteConfig == false)
{
// If the remote control is prohibited,
// identify whether this connection is from remote
if (s->RemoteIP.addr[0] != 127)
{
retcode = 2;
}
}
}
Unlock(c->lock);
retcode = Endian32(retcode);
// Error code transmission
if (SendAll(s, &retcode, sizeof(UINT), false) == false)
{
return;
}
if (retcode != 0)
{
// Disconnect due to an error
return;
}
// Create a RPC server
rpc = StartRpcServer(s, CiRpcDispatch, c);
// RPC server operation
RpcServer(rpc);
// Release the RPC server
EndRpc(rpc);
}
// RPC acceptance thread
void CiRpcAcceptThread(THREAD *thread, void *param)
{
CLIENT_RPC_CONNECTION *conn;
CLIENT *c;
SOCK *s;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
conn = (CLIENT_RPC_CONNECTION *)param;
s = conn->Sock;
c = conn->Client;
AddRef(s->ref);
// Add to the RPC connection list
LockList(c->RpcConnectionList);
{
Add(c->RpcConnectionList, conn);
}
UnlockList(c->RpcConnectionList);
NoticeThreadInit(thread);
// Main process
CiRpcAccepted(c, s);
// Release from the connection list
LockList(c->RpcConnectionList);
{
Delete(c->RpcConnectionList, conn);
}
UnlockList(c->RpcConnectionList);
ReleaseSock(conn->Sock);
ReleaseThread(conn->Thread);
Free(conn);
Disconnect(s);
ReleaseSock(s);
}
// RPC server thread
void CiRpcServerThread(THREAD *thread, void *param)
{
CLIENT *c;
SOCK *listener;
UINT i;
LIST *thread_list;
// Validate arguments
if (thread == NULL || param == NULL)
{
return;
}
c = (CLIENT *)param;
// RPC connection list
c->RpcConnectionList = NewList(NULL);
// Open the port
listener = NULL;
for (i = CLIENT_CONFIG_PORT;i < (CLIENT_CONFIG_PORT + 5);i++)
{
listener = Listen(i);
if (listener != NULL)
{
break;
}
}
if (listener == NULL)
{
// Error
Alert(CEDAR_PRODUCT_STR " VPN Client RPC Port Open Failed.", CEDAR_CLIENT_STR);
return;
}
#ifdef OS_WIN32
MsRegWriteIntEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PORT, i, false, true);
MsRegWriteIntEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PID, MsGetCurrentProcessId(), false, true);
#endif // OS_WIN32
c->RpcListener = listener;
AddRef(listener->ref);
NoticeThreadInit(thread);
while (true)
{
// Wait for client connection
CLIENT_RPC_CONNECTION *conn;
SOCK *s = Accept(listener);
if (s == NULL)
{
// Stop
break;
}
// Create a client processing thread
conn = ZeroMalloc(sizeof(CLIENT_RPC_CONNECTION));
conn->Client = c;
conn->Sock = s;
AddRef(s->ref);
conn->Thread = NewThread(CiRpcAcceptThread, (void *)conn);
WaitThreadInit(conn->Thread);
ReleaseSock(s);
}
// Release the listener
ReleaseSock(listener);
thread_list = NewListFast(NULL);
// Set all the event notification
LockList(c->NotifyCancelList);
{
UINT i;
for (i = 0;i < LIST_NUM(c->NotifyCancelList);i++)
{
CANCEL *cancel = LIST_DATA(c->NotifyCancelList, i);
Cancel(cancel);
}
}
UnlockList(c->NotifyCancelList);
// Disconnect all the connections of connected yet
LockList(c->RpcConnectionList);
{
for (i = 0;i < LIST_NUM(c->RpcConnectionList);i++)
{
CLIENT_RPC_CONNECTION *cc = LIST_DATA(c->RpcConnectionList, i);
AddRef(cc->Thread->ref);
Add(thread_list, cc->Thread);
Disconnect(cc->Sock);
}
}
UnlockList(c->RpcConnectionList);
for (i = 0;i < LIST_NUM(thread_list);i++)
{
THREAD *t = LIST_DATA(thread_list, i);
WaitThread(t, INFINITE);
ReleaseThread(t);
}
ReleaseList(c->RpcConnectionList);
ReleaseList(thread_list);
#ifdef OS_WIN32
MsRegDeleteValueEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PORT, false, true);
MsRegDeleteValueEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PID, false, true);
#endif // OS_WIN32
}
// Start the Keep
void CiInitKeep(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
c->Keep = StartKeep();
// Apply settings
if (c->Config.UseKeepConnect)
{
KEEP *k = c->Keep;
Lock(k->lock);
{
StrCpy(k->ServerName, sizeof(k->ServerName), c->Config.KeepConnectHost);
k->ServerPort = c->Config.KeepConnectPort;
k->Interval = c->Config.KeepConnectInterval * 1000;
k->UdpMode = (c->Config.KeepConnectProtocol == CONNECTION_UDP) ? true : false;
k->Enable = true;
}
Unlock(k->lock);
}
}
// Stop the Keep
void CiFreeKeep(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
StopKeep(c->Keep);
c->Keep = NULL;
}
// Start the RPC
void CiStartRpcServer(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
c->RpcThread = NewThread(CiRpcServerThread, (void *)c);
WaitThreadInit(c->RpcThread);
}
// Stop the RPC
void CiStopRpcServer(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
Disconnect(c->RpcListener);
ReleaseSock(c->RpcListener);
WaitThread(c->RpcThread, INFINITE);
ReleaseThread(c->RpcThread);
}
// Wait for the next notification
bool CcWaitNotify(NOTIFY_CLIENT *n)
{
UCHAR c;
// Validate arguments
if (n == NULL)
{
return false;
}
// 1 character reception
if (RecvAll(n->Sock, &c, 1, false) == false)
{
// Disconnected
return false;
}
return true;
}
// Connect as a notification client
NOTIFY_CLIENT *CcConnectNotify(REMOTE_CLIENT *rc)
{
NOTIFY_CLIENT *n;
SOCK *s;
char tmp[MAX_SIZE];
bool rpc_mode = false;
UINT port;
// Validate arguments
if (rc == NULL || rc->Rpc == NULL || rc->Rpc->Sock == NULL)
{
return NULL;
}
// Connect
IPToStr(tmp, sizeof(tmp), &rc->Rpc->Sock->RemoteIP);
port = rc->Rpc->Sock->RemotePort;
s = Connect(tmp, port);
if (s == NULL)
{
return NULL;
}
rpc_mode = Endian32(rpc_mode);
if (SendAll(s, &rpc_mode, sizeof(rpc_mode), false) == false)
{
ReleaseSock(s);
return NULL;
}
n = ZeroMalloc(sizeof(NOTIFY_CLIENT));
n->Sock = s;
return n;
}
// Stop the notification client
void CcStopNotify(NOTIFY_CLIENT *n)
{
// Validate arguments
if (n == NULL)
{
return;
}
Disconnect(n->Sock);
}
// Delete the notification client
void CcDisconnectNotify(NOTIFY_CLIENT *n)
{
// Validate arguments
if (n == NULL)
{
return;
}
// Disconnect
Disconnect(n->Sock);
ReleaseSock(n->Sock);
// Memory release
Free(n);
}
// Disconnect the remote connection
void CcDisconnectRpc(REMOTE_CLIENT *rc)
{
// Validate arguments
if (rc == NULL)
{
return;
}
RpcFree(rc->Rpc);
Free(rc);
}
// Connect to the client to start the shortcut connection setting
UINT CcShortcut(UCHAR *key)
{
UINT ret;
// Validate arguments
if (key == NULL)
{
return ERR_INVALID_PARAMETER;
}
CcConnectRpcEx("localhost", NULL, NULL, NULL, key, &ret, false, 0);
return ret;
}
// Disconnect the connected shortcut connection
UINT CcShortcutDisconnect(UCHAR *key)
{
UINT ret;
// Validate arguments
if (key == NULL)
{
return ERR_INVALID_PARAMETER;
}
CcConnectRpcEx("localhost", NULL, NULL, NULL, key, &ret, true, 0);
return ret;
}
// Connect to the remote client
REMOTE_CLIENT *CcConnectRpc(char *server_name, char *password, bool *bad_pass, bool *no_remote, UINT wait_retry)
{
return CcConnectRpcEx(server_name, password, bad_pass, no_remote, NULL, NULL, false, wait_retry);
}
REMOTE_CLIENT *CcConnectRpcEx(char *server_name, char *password, bool *bad_pass, bool *no_remote, UCHAR *key, UINT *key_error_code, bool shortcut_disconnect, UINT wait_retry)
{
SOCK *s = NULL;
UINT i;
UINT retcode;
UINT rpc_mode = CLIENT_RPC_MODE_MANAGEMENT;
RPC *rpc;
REMOTE_CLIENT *ret;
UCHAR hash_password[SHA1_SIZE];
UINT port_start;
UINT64 try_started = 0;
bool ok;
UINT reg_port = 0;
UINT reg_pid = 0;
// Validate arguments
if (server_name == NULL)
{
return NULL;
}
if (password == NULL)
{
password = "";
}
if (key_error_code != NULL)
{
*key_error_code = ERR_NO_ERROR;
}
if (bad_pass != NULL)
{
*bad_pass = false;
}
if (no_remote != NULL)
{
*no_remote = false;
}
#ifdef OS_WIN32
// read the current port number from the registry of the localhost
if (StrCmpi(server_name, "localhost") == 0)
{
reg_port = MsRegReadIntEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PORT, false, true);
reg_pid = MsRegReadIntEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PID, false, true);
if (reg_pid != 0)
{
if (MsIsServiceRunning(GC_SVC_NAME_VPNCLIENT) == false)
{
reg_port = 0;
}
}
else
{
reg_port = 0;
}
}
#endif // OS_WIN32
port_start = CLIENT_CONFIG_PORT - 1;
if (reg_port != 0)
{
s = Connect(server_name, reg_port);
if (s != NULL)
{
goto L_TRY;
}
}
RETRY:
port_start++;
if (port_start >= (CLIENT_CONFIG_PORT + 5))
{
return NULL;
}
ok = false;
while (true)
{
for (i = port_start;i < (CLIENT_CONFIG_PORT + 5);i++)
{
if (CheckTCPPort(server_name, i))
{
ok = true;
break;
}
}
if (ok)
{
break;
}
if (wait_retry == 0)
{
break;
}
if (try_started == 0)
{
try_started = Tick64();
}
if ((try_started + (UINT64)wait_retry) <= Tick64())
{
break;
}
}
if (ok == false)
{
if (key_error_code)
{
*key_error_code = ERR_CONNECT_FAILED;
}
return NULL;
}
port_start = i;
s = Connect(server_name, i);
if (s == NULL)
{
if (key_error_code)
{
*key_error_code = ERR_CONNECT_FAILED;
}
goto RETRY;
}
L_TRY:
SetTimeout(s, 10000);
Hash(hash_password, password, StrLen(password), true);
if (key != NULL)
{
if (shortcut_disconnect == false)
{
rpc_mode = CLIENT_RPC_MODE_SHORTCUT;
}
else
{
rpc_mode = CLIENT_RPC_MODE_SHORTCUT_DISCONNECT;
}
}
rpc_mode = Endian32(rpc_mode);
SendAdd(s, &rpc_mode, sizeof(UINT));
if (key != NULL)
{
SendAdd(s, key, SHA1_SIZE);
}
else
{
SendAdd(s, hash_password, SHA1_SIZE);
}
if (SendNow(s, false) == false)
{
ReleaseSock(s);
goto RETRY;
}
if (RecvAll(s, &retcode, sizeof(UINT), false) == false)
{
ReleaseSock(s);
goto RETRY;
}
retcode = Endian32(retcode);
if (retcode >= 1024)
{
ReleaseSock(s);
goto RETRY;
}
if (key != NULL)
{
if (key_error_code)
{
*key_error_code = retcode;
}
SendAll(s, &retcode, sizeof(UINT), false);
ReleaseSock(s);
return NULL;
}
switch (retcode)
{
case 1:
if (bad_pass != NULL)
{
*bad_pass = true;
}
break;
case 2:
if (no_remote != NULL)
{
*no_remote = true;
}
break;
}
if (retcode != 0)
{
ReleaseSock(s);
return NULL;
}
SetTimeout(s, INFINITE);
rpc = StartRpcClient(s, NULL);
ReleaseSock(s);
ret = ZeroMalloc(sizeof(REMOTE_CLIENT));
ret->Rpc = rpc;
rpc->Param = ret;
if (ret != NULL)
{
RPC_CLIENT_VERSION t;
Zero(&t, sizeof(t));
CcGetClientVersion(ret, &t);
ret->OsType = t.OsType;
ret->Unix = OS_IS_UNIX(ret->OsType);
ret->Win9x = OS_IS_WINDOWS_9X(ret->OsType);
ret->IsVgcSupported = t.IsVgcSupported;
ret->ShowVgcLink = t.ShowVgcLink;
StrCpy(ret->ClientId, sizeof(ret->ClientId), t.ClientId);
}
return ret;
}
// Get a RPC_CLIENT_GET_CONNECTION_STATUS from the session
void CiGetSessionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st, SESSION *s)
{
// Validate arguments
if (st == NULL || s == NULL)
{
return;
}
Lock(s->lock);
{
// Operation flag
st->Active = true;
// Session status
st->SessionStatus = s->ClientStatus;
// Account name
UniStrCpy(st->AccountName, sizeof(st->AccountName), s->ClientOption->AccountName);
if (s->ClientStatus == CLIENT_STATUS_ESTABLISHED && s->Connection != NULL)
{
Lock(s->Connection->lock);
{
// Connected flag
st->Connected = true;
// Product name
StrCpy(st->ServerProductName, sizeof(st->ServerProductName), s->Connection->ServerStr);
// Version
st->ServerProductVer = s->Connection->ServerVer;
// Build Number
st->ServerProductBuild = s->Connection->ServerBuild;
// Server certificate
st->ServerX = CloneX(s->Connection->ServerX);
// Client certificate
st->ClientX = CloneX(s->Connection->ClientX);
// Connection completion time of this connection
st->CurrentConnectionEstablishTime = TickToTime(s->CurrentConnectionEstablishTime);
// Maximum number of the TCP connections
st->MaxTcpConnections = s->MaxConnection;
// Half-connection
st->HalfConnection = s->HalfConnection;
// VLAN
st->VLanId = s->VLanId;
// VoIP / QoS
st->QoS = s->QoS;
if (s->Connection->Protocol == CONNECTION_TCP)
{
UINT i;
// Number of current TCP connections
LockList(s->Connection->Tcp->TcpSockList);
{
st->NumTcpConnections = LIST_NUM(s->Connection->Tcp->TcpSockList);
if (st->HalfConnection)
{
for (i = 0;i < st->NumTcpConnections;i++)
{
TCPSOCK *ts = LIST_DATA(s->Connection->Tcp->TcpSockList, i);
if (ts->Direction & TCP_SERVER_TO_CLIENT)
{
st->NumTcpConnectionsDownload++;
}
else
{
st->NumTcpConnectionsUpload++;
}
}
}
}
UnlockList(s->Connection->Tcp->TcpSockList);
}
// Use of encryption
st->UseEncrypt = s->UseEncrypt;
if (st->UseEncrypt)
{
StrCpy(st->CipherName, sizeof(st->CipherName), s->Connection->CipherName);
}
// Use of compression
st->UseCompress = s->UseCompress;
// R-UDP
st->IsRUDPSession = s->IsRUDPSession;
// Physical communication protocol
StrCpy(st->UnderlayProtocol, sizeof(st->UnderlayProtocol), s->UnderlayProtocol);
// UDP acceleration function
st->IsUdpAccelerationEnabled = s->UseUdpAcceleration;
st->IsUsingUdpAcceleration = s->IsUsingUdpAcceleration;
// Session key
Copy(st->SessionKey, s->SessionKey, SHA1_SIZE);
// Policy
Copy(&st->Policy, s->Policy, sizeof(POLICY));
// Data size
if (s->ServerMode == false)
{
st->TotalSendSize = s->TotalSendSize;
st->TotalRecvSize = s->TotalRecvSize;
st->TotalRecvSizeReal = s->TotalRecvSizeReal;
st->TotalSendSizeReal = s->TotalSendSizeReal;
}
else
{
st->TotalSendSize = s->TotalRecvSize;
st->TotalRecvSize = s->TotalSendSize;
st->TotalRecvSizeReal = s->TotalSendSizeReal;
st->TotalSendSizeReal = s->TotalRecvSizeReal;
}
// Session name
StrCpy(st->SessionName, sizeof(st->SessionName), s->Name);
// Connection name
StrCpy(st->ConnectionName, sizeof(st->ConnectionName), s->Connection->Name);
// Server name
StrCpy(st->ServerName, sizeof(st->ServerName), s->Connection->ServerName);
// Port number
st->ServerPort = s->Connection->ServerPort;
// Traffic data
Lock(s->TrafficLock);
{
Copy(&st->Traffic, s->Traffic, sizeof(TRAFFIC));
}
Unlock(s->TrafficLock);
st->IsBridgeMode = s->IsBridgeMode;
st->IsMonitorMode = s->IsMonitorMode;
}
Unlock(s->Connection->lock);
}
// Connection start time
st->StartTime = TickToTime(s->CreatedTime);
// Connection completion time of the first connection
st->FirstConnectionEstablisiedTime = TickToTime(s->FirstConnectionEstablisiedTime);
// Number of connections have been established so far
st->NumConnectionsEatablished = s->NumConnectionsEatablished;
}
Unlock(s->lock);
}
// Get the connection status
bool CtGetAccountStatus(CLIENT *c, RPC_CLIENT_GET_CONNECTION_STATUS *st)
{
// Validate arguments
if (c == NULL || st == NULL)
{
return false;
}
LockList(c->AccountList);
{
ACCOUNT t, *r;
// Search for account
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), st->AccountName);
r = Search(c->AccountList, &t);
if (r == NULL)
{
// Specified account is not found
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
Lock(r->lock);
{
Zero(st, sizeof(RPC_CLIENT_GET_CONNECTION_STATUS));
if (r->ClientSession != NULL)
{
SESSION *s = r->ClientSession;
CiGetSessionStatus(st, s);
}
}
Unlock(r->lock);
}
UnlockList(c->AccountList);
return true;
}
// Release the connection status
void CiFreeClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st)
{
// Validate arguments
if (st == NULL)
{
return;
}
if (st->ServerX != NULL)
{
FreeX(st->ServerX);
}
if (st->ClientX != NULL)
{
FreeX(st->ClientX);
}
}
// Verification procedure of the server certificate
bool CiCheckCertProc(SESSION *s, CONNECTION *c, X *server_x, bool *expired)
{
#ifdef OS_WIN32
ACCOUNT *a;
X *old_x = NULL;
UI_CHECKCERT dlg;
// Validate arguments
if (s == NULL || c == NULL || server_x == NULL)
{
return false;
}
if (expired != NULL)
{
*expired = false;
}
Zero(&dlg, sizeof(dlg));
a = s->Account;
if (a == NULL)
{
return false;
}
Lock(a->lock);
{
if (a->CheckServerCert == false)
{
// Not to validate the server certificate
Unlock(a->lock);
return true;
}
if (a->ServerCert != NULL)
{
old_x = CloneX(a->ServerCert);
}
}
Unlock(a->lock);
if (CheckXDateNow(server_x) == false)
{
// Expired
if (old_x != NULL)
{
FreeX(old_x);
}
if (expired != NULL)
{
*expired = true;
}
return false;
}
if (old_x != NULL)
{
if (CompareX(old_x, server_x))
{
// Matched exactly to the certificate that is already registered
if (old_x != NULL)
{
FreeX(old_x);
}
return true;
}
else
{
dlg.DiffWarning = true;
}
}
// Because this certificate can not be trusted, confirm to be trusted by showing a dialog box
UniStrCpy(dlg.AccountName, sizeof(dlg.AccountName), a->ClientOption->AccountName);
StrCpy(dlg.ServerName, sizeof(dlg.ServerName), a->ClientOption->Hostname);
dlg.x = server_x;
dlg.old_x = old_x;
dlg.Session = s;
AddRef(s->ref);
CncCheckCert(s, &dlg);
ReleaseSession(s);
if (old_x != NULL)
{
FreeX(old_x);
}
if (dlg.Ok && dlg.SaveServerCert)
{
// Save the server certificate and trust it from the next time
Lock(a->lock);
{
if (a->ServerCert != NULL)
{
FreeX(a->ServerCert);
}
a->ServerCert = CloneX(server_x);
}
Unlock(a->lock);
CiSaveConfigurationFile(s->Cedar->Client);
}
return dlg.Ok;
#else // OS_WIN32
ACCOUNT *a;
X *old_x = NULL;
// Validate arguments
if (s == NULL || c == NULL || server_x == NULL)
{
return false;
}
if (expired != NULL)
{
*expired = false;
}
a = s->Account;
if (a == NULL)
{
return false;
}
Lock(a->lock);
{
if (a->CheckServerCert == false)
{
// Not to validate the server certificate
Unlock(a->lock);
return true;
}
if (a->ServerCert != NULL)
{
old_x = CloneX(a->ServerCert);
}
}
Unlock(a->lock);
if (CheckXDateNow(server_x) == false)
{
// Expired
if (old_x != NULL)
{
FreeX(old_x);
}
if (expired != NULL)
{
*expired = true;
}
return false;
}
if (old_x != NULL)
{
if (CompareX(old_x, server_x))
{
// Exactly matched to the certificate that is already registered
if (old_x != NULL)
{
FreeX(old_x);
}
return true;
}
else
{
// Mismatch
if (old_x != NULL)
{
FreeX(old_x);
}
return false;
}
}
if (old_x != NULL)
{
FreeX(old_x);
}
return false;
#endif // OS_WIN32
}
// Signature procedure with a secure device
bool CiSecureSignProc(SESSION *s, CONNECTION *c, SECURE_SIGN *sign)
{
// The UI is available in Win32
return CncSecureSignDlg(sign);
}
#ifdef OS_WIN32
// Signing procedure (for Win32)
bool Win32CiSecureSign(SECURE_SIGN *sign)
{
bool ret = false;
BUF *random;
// Validate arguments
if (sign == NULL)
{
return false;
}
random = NewBuf();
WriteBuf(random, sign->Random, SHA1_SIZE);
// Batch processing
{
WINUI_SECURE_BATCH batch[] =
{
{WINUI_SECURE_READ_CERT, sign->SecurePublicCertName, true, NULL, NULL, NULL, NULL, NULL, NULL},
{WINUI_SECURE_SIGN_WITH_KEY, sign->SecurePrivateKeyName, true, random, NULL, NULL, NULL, NULL, NULL}
};
if (SecureDeviceWindow(NULL, batch, sizeof(batch) / sizeof(batch[0]),
sign->UseSecureDeviceId, sign->BitmapId) == false)
{
// Failure
if (batch[0].OutputX != 0)
{
FreeX(batch[0].OutputX);
}
ret = false;
}
else
{
// Success
ret = true;
sign->ClientCert = batch[0].OutputX;
Copy(sign->Signature, batch[1].OutputSign, 128);
}
}
FreeBuf(random);
return ret;
}
#endif // OS_WIN32
// Disconnect
bool CtDisconnect(CLIENT *c, RPC_CLIENT_CONNECT *connect, bool inner)
{
bool ret = false;
ACCOUNT t, *r;
SESSION *s = NULL;
// Validate arguments
if (c == NULL || connect == NULL)
{
return false;
}
LockList(c->AccountList);
{
// Search for account
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), connect->AccountName);
r = Search(c->AccountList, &t);
if (r == NULL)
{
// Specified account isn't found
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
Lock(r->lock);
{
if (r->ClientSession == NULL)
{
// Not connected
CiSetError(c, ERR_ACCOUNT_INACTIVE);
}
else
{
s = r->ClientSession;
AddRef(s->ref);
// Disconnect complete
r->ClientSession = NULL;
ret = true;
}
}
Unlock(r->lock);
}
UnlockList(c->AccountList);
if (s != NULL)
{
// Disconnect the connection (Wait until the disconnection is complete)
CLog(c, "LC_DISCONNECT", connect->AccountName);
StopSession(s);
ReleaseSession(s);
}
if (ret != false)
{
CiNotify(c);
}
return ret;
}
// Connect
bool CtConnect(CLIENT *c, RPC_CLIENT_CONNECT *connect)
{
bool ret = false;
RPC_CLIENT_ENUM_VLAN t;
// Validate arguments
if (c == NULL || connect == NULL)
{
return false;
}
Lock(c->lockForConnect);
{
Zero(&t, sizeof(t));
if (CtEnumVLan(c, &t))
{
if (t.NumItem == 0)
{
// There are no virtual LAN cards in the system
if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) || OS_IS_UNIX(GetOsInfo()->OsType))
{
// Only in Linux system or Windows NT system,
// create a new virtual LAN card which named as "VPN" automatically
RPC_CLIENT_CREATE_VLAN t;
Zero(&t, sizeof(t));
StrCpy(t.DeviceName, sizeof(t.DeviceName), "VPN");
CtCreateVLan(c, &t);
}
}
CiFreeClientEnumVLan(&t);
}
}
Unlock(c->lockForConnect);
CiNormalizeAccountVLan(c);
// Ensure successfully VPN communication by changing the irrational WCM settings in the case of Windows 8 or later
CiDisableWcmNetworkMinimize(c);
LockList(c->AccountList);
{
ACCOUNT t, *r;
bool unix_disabled = false;
// Search for account
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), connect->AccountName);
r = Search(c->AccountList, &t);
if (r == NULL)
{
// Specified account isn't found
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
#ifndef OS_WIN32
// Search for the virtual LAN card
LockList(c->UnixVLanList);
{
UNIX_VLAN *v, t;
Zero(&t, sizeof(t));
StrCpy(t.Name, sizeof(t.Name), r->ClientOption->DeviceName);
v = Search(c->UnixVLanList, &t);
if (v == NULL)
{
UnlockList(c->UnixVLanList);
CiSetError(c, ERR_OBJECT_NOT_FOUND);
return false;
}
unix_disabled = v->Enabled ? false : true;
}
UnlockList(c->UnixVLanList);
#endif // OS_WIN32
Lock(r->lock);
{
bool already_used = false;
UINT i;
if (r->ClientSession != NULL)
{
// Already in connecting
CiSetError(c, ERR_ACCOUNT_ACTIVE);
}
else if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE &&
c->UseSecureDeviceId == 0)
{
// Secure device is not specified
CiSetError(c, ERR_NO_SECURE_DEVICE_SPECIFIED);
}
#ifdef OS_WIN32
else if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, r->ClientOption->DeviceName) == false &&
MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, r->ClientOption->DeviceName) == false)
{
// Virtual LAN card can not be found
CiSetError(c, ERR_VLAN_FOR_ACCOUNT_NOT_FOUND);
CiNotify(c);
CiSendGlobalPulse(c);
}
else if (MsIsVLanEnabled(r->ClientOption->DeviceName) == false)
{
// The virtual LAN card is disabled
CiSetError(c, ERR_VLAN_FOR_ACCOUNT_DISABLED);
CiNotify(c);
CiSendGlobalPulse(c);
}
#else // OS_WIN32
else if (unix_disabled)
{
// The virtual LAN card is disabled
CiSetError(c, ERR_VLAN_FOR_ACCOUNT_DISABLED);
CiNotify(c);
CiSendGlobalPulse(c);
}
#endif // OS_WIN32
else
{
// Check whether the virtual LAN card is being used by a different account already
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
if (a != r)
{
if (StrCmpi(a->ClientOption->DeviceName,
r->ClientOption->DeviceName) == 0)
{
if (a->ClientSession != NULL)
{
already_used = true;
break;
}
}
}
}
if (already_used)
{
CiSetError(c, ERR_VLAN_FOR_ACCOUNT_USED);
}
else
{
// Start the connection
PACKET_ADAPTER *pa = VLanGetPacketAdapter();
if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
{
// Register a procedure for secure device authentication
r->ClientAuth->SecureSignProc = CiSecureSignProc;
}
else
{
r->ClientAuth->SecureSignProc = NULL;
}
if (r->CheckServerCert)
{
// Register a procedure to validate the server certificate
r->ClientAuth->CheckCertProc = CiCheckCertProc;
}
else
{
r->ClientAuth->CheckCertProc = NULL;
}
r->StatusPrinter = CiClientStatusPrinter;
r->LastConnectDateTime = SystemTime64();
CLog(c, "LC_CONNECT", connect->AccountName);
r->ClientSession = NewClientSessionEx(c->Cedar, r->ClientOption, r->ClientAuth, pa, r);
Notify(r->ClientSession, CLIENT_NOTIFY_ACCOUNT_CHANGED);
ret = true;
}
}
}
Unlock(r->lock);
}
UnlockList(c->AccountList);
CiSaveConfigurationFile(c);
return ret;
}
// Get the account information
bool CtGetAccount(CLIENT *c, RPC_CLIENT_GET_ACCOUNT *a)
{
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
LockList(c->AccountList);
{
ACCOUNT t, *r;
// Search for account
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
r = Search(c->AccountList, &t);
if (r == NULL)
{
// Specified account can not be found
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
Lock(r->lock);
{
// Copy the client option
if (a->ClientOption != NULL)
{
Free(a->ClientOption);
}
a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
Copy(a->ClientOption, r->ClientOption, sizeof(CLIENT_OPTION));
// Copy the authentication data
if (a->ClientAuth != NULL)
{
CiFreeClientAuth(a->ClientAuth);
}
a->ClientAuth = CopyClientAuth(r->ClientAuth);
a->StartupAccount = r->StartupAccount;
a->CheckServerCert = r->CheckServerCert;
a->ServerCert = NULL;
if (r->ServerCert != NULL)
{
a->ServerCert = CloneX(r->ServerCert);
}
// Shortcut Key
Copy(a->ShortcutKey, r->ShortcutKey, SHA1_SIZE);
a->CreateDateTime = r->CreateDateTime;
a->LastConnectDateTime = r->LastConnectDateTime;
a->UpdateDateTime = r->UpdateDateTime;
}
Unlock(r->lock);
}
UnlockList(c->AccountList);
return true;
}
// Change the account name
bool CtRenameAccount(CLIENT *c, RPC_RENAME_ACCOUNT *rename, bool inner)
{
bool ret;
// Validate arguments
if (c == NULL || rename == NULL)
{
return false;
}
ret = false;
if (UniStrCmp(rename->NewName, rename->OldName) == 0)
{
// The name has not been changed
return true;
}
LockList(c->AccountList);
{
ACCOUNT t, *r, *r2;
if (UniStrLen(rename->NewName) == 0)
{
// Name is invalid
CiSetError(c, ERR_INVALID_VALUE);
UnlockList(c->AccountList);
return false;
}
// Search for old account name
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), rename->OldName);
r = Search(c->AccountList, &t);
if (r == NULL)
{
// Specified account can not be found
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
// Search for a new account name
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), rename->NewName);
r2 = Search(c->AccountList, &t);
if (r2 != NULL)
{
// Account with the specified name already exists
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_ALREADY_EXISTS);
return false;
}
Free(t.ClientOption);
Lock(r->lock);
{
// Check the operating state of the account
if (r->ClientSession != NULL)
{
// The Account is working
Unlock(r->lock);
UnlockList(c->AccountList);
CiSetError(c, ERR_ACCOUNT_ACTIVE);
return false;
}
// Update the account name
UniStrCpy(r->ClientOption->AccountName, sizeof(r->ClientOption->AccountName),
rename->NewName);
CLog(c, "LC_RENAME_ACCOUNT", rename->OldName, rename->NewName);
ret = true;
}
Unlock(r->lock);
Sort(c->AccountList);
}
UnlockList(c->AccountList);
CiSaveConfigurationFile(c);
CiNotify(c);
return ret;
}
// Set the client configuration
bool CtSetClientConfig(CLIENT *c, CLIENT_CONFIG *o)
{
KEEP *k;
// Validate arguments
if (c == NULL || o == NULL)
{
return false;
}
if (o->UseKeepConnect)
{
if (IsEmptyStr(o->KeepConnectHost) ||
o->KeepConnectPort == 0 ||
o->KeepConnectPort >= 65536)
{
CiSetError(c, ERR_INVALID_PARAMETER);
return false;
}
}
Lock(c->lock);
{
Copy(&c->Config, o, sizeof(CLIENT_CONFIG));
}
Unlock(c->lock);
// Save the settings
CiSaveConfigurationFile(c);
// Apply the Keep Connect
k = c->Keep;
Lock(k->lock);
{
if (o->UseKeepConnect)
{
StrCpy(k->ServerName, sizeof(k->ServerName), c->Config.KeepConnectHost);
k->ServerPort = c->Config.KeepConnectPort;
k->Interval = c->Config.KeepConnectInterval * 1000;
k->UdpMode = (c->Config.KeepConnectProtocol == CONNECTION_UDP) ? true : false;
k->Enable = true;
}
else
{
k->Enable = false;
}
}
Unlock(k->lock);
return true;
}
// Get the network client configuration
bool CtGetClientConfig(CLIENT *c, CLIENT_CONFIG *o)
{
// Validate arguments
if (c == NULL || o == NULL)
{
return false;
}
Lock(c->lock);
{
Copy(o, &c->Config, sizeof(CLIENT_CONFIG));
}
Unlock(c->lock);
return true;
}
// Unset the startup attribute of the account
bool CtRemoveStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a)
{
bool ret;
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
ret = false;
LockList(c->AccountList);
{
ACCOUNT t, *r;
// Search for an Account
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
r = Search(c->AccountList, &t);
if (r == NULL)
{
// Specified account can not be found
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
Lock(r->lock);
{
// Unset the startup account
ret = true;
r->StartupAccount = false;
}
Unlock(r->lock);
}
UnlockList(c->AccountList);
if (ret)
{
CiSaveConfigurationFile(c);
CiNotify(c);
}
return ret;
}
// Set the account as a start-up account
bool CtSetStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a, bool inner)
{
bool ret;
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
ret = false;
LockList(c->AccountList);
{
ACCOUNT t, *r;
// Search for an account
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
r = Search(c->AccountList, &t);
if (r == NULL)
{
// Specified account can not be found
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
Lock(r->lock);
{
// Set to a start-up account
ret = true;
r->StartupAccount = true;
}
Unlock(r->lock);
}
UnlockList(c->AccountList);
if (ret)
{
CiSaveConfigurationFile(c);
CiNotify(c);
}
return ret;
}
// Delete the account
bool CtDeleteAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a, bool inner)
{
bool ret;
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
ret = false;
if (c->Halt)
{
// Don't allow the removal of the account in the process of stopping
CiSetError(c, ERR_INTERNAL_ERROR);
return false;
}
LockList(c->AccountList);
{
ACCOUNT t, *r;
// Search for an Account
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
r = Search(c->AccountList, &t);
if (r == NULL)
{
// Specified account can not be found
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
Lock(r->lock);
{
// Check the operating state of the account
if (r->ClientSession != NULL)
{
// The account is active
Unlock(r->lock);
UnlockList(c->AccountList);
CiSetError(c, ERR_ACCOUNT_ACTIVE);
return false;
}
// Remove this account from the list
Delete(c->AccountList, r);
}
Unlock(r->lock);
// Free the memory of this account
CiFreeAccount(r);
CLog(c, "LC_DELETE_ACCOUNT", a->AccountName);
ret = true;
}
UnlockList(c->AccountList);
if (ret)
{
CiSaveConfigurationFile(c);
CiNotify(c);
}
return ret;
}
// Enumeration of accounts
bool CtEnumAccount(CLIENT *c, RPC_CLIENT_ENUM_ACCOUNT *e)
{
// Validate arguments
if (c == NULL || e == NULL)
{
return false;
}
LockList(c->AccountList);
{
UINT i;
// Number of accounts
e->NumItem = LIST_NUM(c->AccountList);
e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM *) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM));
e->Items[i] = item;
// Account name
UniStrCpy(item->AccountName, sizeof(item->AccountName), a->ClientOption->AccountName);
// User name
StrCpy(item->UserName, sizeof(item->UserName), a->ClientAuth->Username);
// Server name
StrCpy(item->ServerName, sizeof(item->ServerName), a->ClientOption->Hostname);
// Proxy type
item->ProxyType = a->ClientOption->ProxyType;
// Device name
StrCpy(item->DeviceName, sizeof(item->DeviceName), a->ClientOption->DeviceName);
// Proxy information
if (item->ProxyType != PROXY_DIRECT)
{
StrCpy(item->ProxyName, sizeof(item->ProxyName), a->ClientOption->ProxyName);
}
// Startup
item->StartupAccount = a->StartupAccount;
// Active flag
item->Active = (a->ClientSession == NULL ? false : true);
// Connection flag
item->Connected = (item->Active == false) ? false : a->ClientSession->ConnectSucceed;
// Port number
item->Port = a->ClientOption->Port;
// Virtual HUB name
StrCpy(item->HubName, sizeof(item->HubName), a->ClientOption->HubName);
item->CreateDateTime = a->CreateDateTime;
item->LastConnectDateTime = a->LastConnectDateTime;
item->UpdateDateTime = a->UpdateDateTime;
}
}
UnlockList(c->AccountList);
return true;
}
// Configure the account
bool CtSetAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a, bool inner)
{
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
// Check whether an account already exists
LockList(c->AccountList);
{
ACCOUNT t, *ret;
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),
a->ClientOption->AccountName);
ret = Search(c->AccountList, &t);
if (ret == NULL)
{
// Not exist
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
return false;
}
Free(t.ClientOption);
if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
{
if (a->ClientAuth->ClientX == NULL ||
a->ClientAuth->ClientX->is_compatible_bit == false ||
a->ClientAuth->ClientK == NULL)
{
// Client certificate is invalid
UnlockList(c->AccountList);
CiSetError(c, ERR_NOT_RSA_1024);
return false;
}
}
if (a->ServerCert != NULL && a->ServerCert->is_compatible_bit == false)
{
// Server certificate is invalid
UnlockList(c->AccountList);
CiSetError(c, ERR_NOT_RSA_1024);
return false;
}
Lock(ret->lock);
{
#if 0
// Rewriting of the configuration is done even account running in the current version
// (New setting isn't applied until connecting next time)
if (ret->ClientSession != NULL)
{
// The account is operating
Unlock(ret->lock);
UnlockList(c->AccountList);
CiSetError(c, ERR_ACCOUNT_ACTIVE);
return false;
}
#endif
// Delete the client authentication data
CiFreeClientAuth(ret->ClientAuth);
// Copy the client authentication data
ret->ClientAuth = CopyClientAuth(a->ClientAuth);
// Delete the client option
Free(ret->ClientOption);
// Copy the client option
ret->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
Copy(ret->ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
ret->StartupAccount = a->StartupAccount;
ret->CheckServerCert = a->CheckServerCert;
if (a->ServerCert != NULL)
{
if (ret->ServerCert != NULL)
{
FreeX(ret->ServerCert);
}
ret->ServerCert = CloneX(a->ServerCert);
}
else
{
if (ret->ServerCert != NULL)
{
FreeX(ret->ServerCert);
}
ret->ServerCert = false;
}
ret->UpdateDateTime = SystemTime64();
}
Unlock(ret->lock);
}
UnlockList(c->AccountList);
CiSaveConfigurationFile(c);
CiNotify(c);
return true;
}
// Create an account
bool CtCreateAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a, bool inner)
{
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
// Check whether an account already exists
LockList(c->AccountList);
{
ACCOUNT t, *ret, *new_account;
t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),
a->ClientOption->AccountName);
ret = Search(c->AccountList, &t);
if (ret != NULL)
{
// Already exist
UnlockList(c->AccountList);
Free(t.ClientOption);
CiSetError(c, ERR_ACCOUNT_ALREADY_EXISTS);
return false;
}
Free(t.ClientOption);
if (UniStrLen(a->ClientOption->AccountName) == 0)
{
// The name is invalid
UnlockList(c->AccountList);
CiSetError(c, ERR_INVALID_VALUE);
return false;
}
if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
{
if (a->ClientAuth->ClientX == NULL ||
a->ClientAuth->ClientX->is_compatible_bit == false ||
a->ClientAuth->ClientK == NULL)
{
// The client certificate is invalid
UnlockList(c->AccountList);
CiSetError(c, ERR_NOT_RSA_1024);
return false;
}
}
if (a->ServerCert != NULL && a->ServerCert->is_compatible_bit == false)
{
// The server certificate is invalid
UnlockList(c->AccountList);
CiSetError(c, ERR_NOT_RSA_1024);
return false;
}
// Add a new account
new_account = ZeroMalloc(sizeof(ACCOUNT));
new_account->lock = NewLock();
// Copy the client authentication data
new_account->ClientAuth = CopyClientAuth(a->ClientAuth);
// Copy the client option
new_account->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
Copy(new_account->ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
new_account->StartupAccount = a->StartupAccount;
new_account->CheckServerCert = a->CheckServerCert;
if (a->ServerCert != NULL)
{
new_account->ServerCert = CloneX(a->ServerCert);
}
// Shortcut Key
if (IsZero(a->ShortcutKey, SHA1_SIZE))
{
Rand(new_account->ShortcutKey, SHA1_SIZE);
}
else
{
Copy(new_account->ShortcutKey, a->ShortcutKey, SHA1_SIZE);
}
new_account->CreateDateTime = new_account->UpdateDateTime = SystemTime64();
// Insert into the list
Insert(c->AccountList, new_account);
CLog(c, "LC_NEW_ACCOUNT", a->ClientOption->AccountName);
}
UnlockList(c->AccountList);
CiNormalizeAccountVLan(c);
CiSaveConfigurationFile(c);
CiNotify(c);
return true;
}
// Release the account acquisition structure
void CiFreeClientGetAccount(RPC_CLIENT_GET_ACCOUNT *a)
{
// Validate arguments
if (a == NULL)
{
return;
}
// Release the account information
if (a->ServerCert != NULL)
{
FreeX(a->ServerCert);
}
CiFreeClientAuth(a->ClientAuth);
Free(a->ClientOption);
}
// Release the account creation structure
void CiFreeClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *a)
{
// Validate arguments
if (a == NULL)
{
return;
}
// Release the account information
if (a->ServerCert != NULL)
{
FreeX(a->ServerCert);
}
CiFreeClientAuth(a->ClientAuth);
Free(a->ClientOption);
}
// Stop the virtual LAN card
bool CtDisableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan)
{
UINT i;
bool used;
// Validate arguments
if (c == NULL || vlan == NULL)
{
return false;
}
#ifndef OS_WIN32
#ifdef NO_VLAN
if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
{
// Can not be added or removed the virtual LAN card in MacOS X
CiSetError(c, ERR_NOT_SUPPORTED);
return false;
}
#endif // NO_VLAN
// Check whether the virtual LAN card with the specified name is not
// being used by one or more accounts
used = false;
LockList(c->AccountList);
{
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
if (StrCmpi(a->ClientOption->DeviceName, vlan->DeviceName) == 0)
{
Lock(a->lock);
{
if (a->ClientSession != NULL)
{
used = true;
}
}
Unlock(a->lock);
}
}
}
UnlockList(c->AccountList);
// Search for the virtual LAN card
LockList(c->UnixVLanList);
{
UNIX_VLAN *v, t;
Zero(&t, sizeof(t));
StrCpy(t.Name, sizeof(t.Name), vlan->DeviceName);
v = Search(c->UnixVLanList, &t);
if (v == NULL)
{
UnlockList(c->UnixVLanList);
CiSetError(c, ERR_OBJECT_NOT_FOUND);
return false;
}
// Stop
v->Enabled = false;
}
UnlockList(c->UnixVLanList);
CiSaveConfigurationFile(c);
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#else // OS_WIN32
// Check whether the virtual LAN card with the specified name is not
// being used by one or more accounts
used = false;
LockList(c->AccountList);
{
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
if (StrCmpi(a->ClientOption->DeviceName, vlan->DeviceName) == 0)
{
Lock(a->lock);
{
if (a->ClientSession != NULL)
{
used = true;
}
}
Unlock(a->lock);
}
}
}
UnlockList(c->AccountList);
#if 0
if (used)
{
// In using
CiSetError(c, ERR_VLAN_IS_USED);
return false;
}
#endif
// Check whether the virtual LAN card are present
if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, vlan->DeviceName) == false &&
MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, vlan->DeviceName) == false)
{
CiSetError(c, ERR_OBJECT_NOT_FOUND);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
if (MsIs64BitWindows() && Is32() && MsIsAdmin())
{
// Execute the driver_installer to process since this Windows is 64 bit
// but this code is 32 bit
char tmp[MAX_SIZE];
Format(tmp, sizeof(tmp), "disablevlan %s", vlan->DeviceName);
if (MsExecDriverInstaller(tmp) == false)
{
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
else
{
// Stop the virtual LAN card
if (MsDisableVLan(vlan->DeviceName) == false)
{
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#endif // OS_WIN32
}
// Start the virtual LAN card
bool CtEnableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan)
{
// Validate arguments
if (c == NULL || vlan == NULL)
{
return false;
}
#ifndef OS_WIN32
#ifdef NO_VLAN
if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
{
// Can not be added or removed the virtual LAN card in MacOS X
CiSetError(c, ERR_NOT_SUPPORTED);
return false;
}
#endif // NO_VLAN
// Search the virtual LAN card
LockList(c->UnixVLanList);
{
UNIX_VLAN *v, t;
Zero(&t, sizeof(t));
StrCpy(t.Name, sizeof(t.Name), vlan->DeviceName);
v = Search(c->UnixVLanList, &t);
if (v == NULL)
{
UnlockList(c->UnixVLanList);
CiSetError(c, ERR_OBJECT_NOT_FOUND);
return false;
}
// Enable
v->Enabled = true;
}
UnlockList(c->UnixVLanList);
CiSaveConfigurationFile(c);
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#else // OS_WIN32
// Check whether the virtual LAN card are present
if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, vlan->DeviceName) == false &&
MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, vlan->DeviceName) == false)
{
CiSetError(c, ERR_OBJECT_NOT_FOUND);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
if (MsIs64BitWindows() && Is32() && MsIsAdmin())
{
// Execute the driver_installer to process since this Windows is 64 bit
// but this code is 32 bit
char tmp[MAX_SIZE];
Format(tmp, sizeof(tmp), "enablevlan %s", vlan->DeviceName);
if (MsExecDriverInstaller(tmp) == false)
{
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
else
{
// Start the virtual LAN card
if (MsEnableVLan(vlan->DeviceName) == false)
{
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#endif // OS_WIN32
}
// Delete the virtual LAN card
bool CtDeleteVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *d)
{
UINT i;
bool used;
// Validate arguments
if (c == NULL || d == NULL)
{
return false;
}
#ifndef OS_WIN32
#ifdef NO_VLAN
if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
{
// Can not be added or removed the virtual LAN card in MacOS X
CiSetError(c, ERR_NOT_SUPPORTED);
return false;
}
#endif // NO_VLAN
// Check whether the virtual LAN card with the specified name is not
// being used by one or more accounts
used = false;
LockList(c->AccountList);
{
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
if (StrCmpi(a->ClientOption->DeviceName, d->DeviceName) == 0)
{
used = true;
}
}
}
UnlockList(c->AccountList);
#if 0
if (used)
{
// In using
CiSetError(c, ERR_VLAN_IS_USED);
return false;
}
#endif
// Search for the virtual LAN card
LockList(c->UnixVLanList);
{
UNIX_VLAN *v, t;
Zero(&t, sizeof(t));
StrCpy(t.Name, sizeof(t.Name), d->DeviceName);
v = Search(c->UnixVLanList, &t);
if (v == NULL)
{
UnlockList(c->UnixVLanList);
CiSetError(c, ERR_OBJECT_NOT_FOUND);
return false;
}
// Remove
if (Delete(c->UnixVLanList, v))
{
Free(v);
}
CLog(c, "LC_DELETE_VLAN", d->DeviceName);
UnixVLanDelete(d->DeviceName);
}
UnlockList(c->UnixVLanList);
CiNormalizeAccountVLan(c);
CiSaveConfigurationFile(c);
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#else // OS_WIN32
if (MsIsNt() == false)
{
// Not available in Win9x
CiSetError(c, ERR_NOT_SUPPORTED);
return false;
}
// Check whether the virtual LAN card are present
if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, d->DeviceName) == false &&
MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, d->DeviceName) == false)
{
CiSetError(c, ERR_OBJECT_NOT_FOUND);
return false;
}
// Check whether the virtual LAN card with the specified name is not
// being used by one or more accounts
used = false;
LockList(c->AccountList);
{
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
if (StrCmpi(a->ClientOption->DeviceName, d->DeviceName) == 0)
{
used = true;
}
}
}
UnlockList(c->AccountList);
#if 0
if (used)
{
// In using
CiSetError(c, ERR_VLAN_IS_USED);
return false;
}
#endif
if (MsIs64BitWindows() && Is32() && MsIsAdmin())
{
// Execute the driver_installer to process since this Windows is 64 bit
// but this code is 32 bit
char tmp[MAX_SIZE];
Format(tmp, sizeof(tmp), "uninstvlan %s", d->DeviceName);
if (MsExecDriverInstaller(tmp) == false)
{
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
return false;
}
}
else
{
// Delete the virtual LAN card directly
if (MsUninstallVLan(d->DeviceName) == false)
{
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
CLog(c, "LC_DELETE_VLAN", d->DeviceName);
CiNormalizeAccountVLan(c);
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#endif // OS_WIN32
}
// Get the name of the first VLAN
char *CiGetFirstVLan(CLIENT *c)
{
char *ret = NULL;
RPC_CLIENT_ENUM_VLAN t;
// Validate arguments
if (c == NULL)
{
return NULL;
}
Zero(&t, sizeof(t));
if (CtEnumVLan(c, &t) == false)
{
return NULL;
}
if (t.NumItem >= 1)
{
UINT i;
char *tmp = t.Items[0]->DeviceName;
for (i = 0;i < t.NumItem;i++)
{
if (t.Items[i]->Enabled)
{
tmp = t.Items[i]->DeviceName;
}
}
ret = CopyStr(tmp);
}
CiFreeClientEnumVLan(&t);
return ret;
}
// Enumerate virtual LAN cards
bool CtEnumVLan(CLIENT *c, RPC_CLIENT_ENUM_VLAN *e)
{
UINT i;
TOKEN_LIST *t;
// Validate arguments
if (c == NULL || e == NULL)
{
return false;
}
#ifndef OS_WIN32
LockList(c->UnixVLanList);
{
e->NumItem = LIST_NUM(c->UnixVLanList);
e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_VLAN_ITEM *item;
UNIX_VLAN *v;
v = LIST_DATA(c->UnixVLanList, i);
e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
item = e->Items[i];
item->Enabled = v->Enabled;
BinToStr(item->MacAddress, sizeof(item->MacAddress), v->MacAddress, 6);
StrCpy(item->DeviceName, sizeof(item->DeviceName), v->Name);
StrCpy(item->Version, sizeof(item->Version), c->Cedar->VerString);
}
}
UnlockList(c->UnixVLanList);
return true;
#else // OS_WIN32
// Enumeration
t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
if (t == NULL)
{
// Enumeration failure
e->NumItem = 0;
e->Items = ZeroMalloc(0);
}
else
{
// Enumeration success
e->NumItem = t->NumTokens;
e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
char *tmp;
RPC_CLIENT_ENUM_VLAN_ITEM *item;
e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
item = e->Items[i];
StrCpy(item->DeviceName, sizeof(item->DeviceName), t->Token[i]);
item->Enabled = MsIsVLanEnabled(item->DeviceName);
tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG, item->DeviceName);
if (tmp == NULL)
{
tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, item->DeviceName);
}
StrCpy(item->MacAddress, sizeof(item->MacAddress), tmp);
Free(tmp);
tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG, item->DeviceName);
if (tmp == NULL)
{
tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG_OLD, item->DeviceName);
}
StrCpy(item->Version, sizeof(item->Version), tmp);
Free(tmp);
}
FreeToken(t);
}
return true;
#endif // OS_WIN32
}
// Release the virtual LAN card enumeration
void CiFreeClientEnumVLan(RPC_CLIENT_ENUM_VLAN *e)
{
UINT i;
// Validate arguments
if (e == NULL)
{
return;
}
for (i = 0;i < e->NumItem;i++)
{
Free(e->Items[i]);
}
Free(e->Items);
}
// Set the information about the virtual LAN card
bool CtSetVLan(CLIENT *c, RPC_CLIENT_SET_VLAN *set)
{
// Validate arguments
if (c == NULL || set == NULL)
{
return false;
}
#ifndef OS_WIN32
LockList(c->UnixVLanList);
{
UNIX_VLAN t, *r;
Zero(&t, sizeof(t));
StrCpy(t.Name, sizeof(t.Name), set->DeviceName);
r = Search(c->UnixVLanList, &t);
if (r == NULL)
{
// Not exist
CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
UnlockList(c->UnixVLanList);
return false;
}
StrToMac(r->MacAddress, set->MacAddress);
}
UnlockList(c->UnixVLanList);
CiSaveConfigurationFile(c);
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#else // OS_WIN32
// Check whether the virtual LAN card with the specified name already exists
if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, set->DeviceName) == false &&
MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, set->DeviceName) == false)
{
// Not exist
CiSetError(c, ERR_OBJECT_NOT_FOUND);
return false;
}
// Configuring MAC address
MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, set->DeviceName, set->MacAddress);
MsSetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, set->DeviceName, set->MacAddress);
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#endif // OS_WIN32
}
// Get the information about the virtual LAN card
bool CtGetVLan(CLIENT *c, RPC_CLIENT_GET_VLAN *get)
{
char *tmp;
// Validate arguments
if (c == NULL || get == NULL)
{
return false;
}
#ifndef OS_WIN32
// Unsupported
CiSetError(c, ERR_NOT_SUPPORTED);
return false;
#else // OS_WIN32
// Check whether the virtual LAN card with the specified name already exists
if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, get->DeviceName) == false &&
MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName) == false)
{
// Not exist
CiSetError(c, ERR_OBJECT_NOT_FOUND);
return false;
}
// Activity
get->Enabled = MsIsVLanEnabled(get->DeviceName);
// MAC address
tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
if (tmp == NULL)
{
tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
}
StrCpy(get->MacAddress, sizeof(get->MacAddress), tmp);
Free(tmp);
// Version
tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
if (tmp == NULL)
{
tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
}
StrCpy(get->Version, sizeof(get->Version), tmp);
Free(tmp);
// File name
tmp = MsGetDriverFileName(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
if (tmp == NULL)
{
tmp = MsGetDriverFileName(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
}
StrCpy(get->FileName, sizeof(get->FileName), tmp);
Free(tmp);
// GUID
tmp = MsGetNetworkAdapterGuid(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
if (tmp == NULL)
{
tmp = MsGetNetworkAdapterGuid(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
}
StrCpy(get->Guid, sizeof(get->Guid), tmp);
Free(tmp);
return true;
#endif // OS_WIN32
}
#ifdef OS_WIN32
// Initialize the driver version information structure
void CiInitDriverVerStruct(MS_DRIVER_VER *ver)
{
UINT cedar_ver = CEDAR_VER;
// Validate arguments
if (ver == NULL)
{
return;
}
Zero(ver, sizeof(MS_DRIVER_VER));
ver->Year = BUILD_DATE_Y;
ver->Month = BUILD_DATE_M;
ver->Day = BUILD_DATE_D;
ver->Major = cedar_ver / 100;
ver->Minor = cedar_ver % 100;
ver->Build = CEDAR_BUILD;
}
#endif // OS_WIN32
// Upgrade the virtual LAN card
bool CtUpgradeVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create)
{
bool use_old_name = false;
#ifdef OS_WIN32
KAKUSHI *k = NULL;
MS_DRIVER_VER ver;
#endif // OS_WIN32
// Validate arguments
if (c == NULL || create == NULL)
{
return false;
}
#ifndef OS_WIN32
// Always succeed
return true;
#else // OS_WIN32
CiInitDriverVerStruct(&ver);
if (MsIsNt() == false)
{
// Not available in Win9x
CiSetError(c, ERR_NOT_SUPPORTED);
return false;
}
// Check whether the LAN card with the specified name already exists
if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, create->DeviceName) == false &&
MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName) == false)
{
// Not exist
CiSetError(c, ERR_OBJECT_NOT_FOUND);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName))
{
use_old_name = true;
}
if (MsIsVista() == false)
{
k = InitKakushi();
}
if (MsIsVista() == false)
{
// Perform the installation (other than Windows Vista)
if (MsUpgradeVLan(use_old_name ? VLAN_ADAPTER_NAME_TAG_OLD : VLAN_ADAPTER_NAME_TAG,
use_old_name ? VLAN_CONNECTION_NAME_OLD : VLAN_CONNECTION_NAME,
create->DeviceName, &ver) == false)
{
// Installation Failed
FreeKakushi(k);
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
else
{
// Perform the installation (Windows Vista)
char tmp[MAX_SIZE];
Format(tmp, sizeof(tmp), "upgradevlan %s", create->DeviceName);
if (CncExecDriverInstaller(tmp) == false)
{
// Installation Failed
FreeKakushi(k);
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
FreeKakushi(k);
CLog(c, "LC_UPDATE_VLAN", create->DeviceName);
CiNotify(c);
CiSendGlobalPulse(c);
return true;
#endif // OS_WIN32
}
// Create a virtual LAN card
bool CtCreateVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create)
{
TOKEN_LIST *t;
UINT max_len;
#ifdef OS_WIN32
KAKUSHI *k = NULL;
#endif // OS_WIN32
// Validate arguments
if (c == NULL || create == NULL)
{
return false;
}
if (SearchStrEx(create->DeviceName, " ", 0, false) != INFINITE)
{
// Spaces in the name is not allowed
CiSetError(c, ERR_INVALID_PARAMETER);
return false;
}
#ifndef OS_WIN32
// Non-Win32
#ifdef NO_VLAN
if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
{
// A virtual LAN card can not be added or removed in MacOS X
CiSetError(c, ERR_NOT_SUPPORTED);
return false;
}
#endif // NO_VLAN
// Check whether the specified name is valid or not
if (IsSafeStr(create->DeviceName) == false)
{
// Name is invalid
CiSetError(c, ERR_VLAN_INVALID_NAME);
return false;
}
// Check whether the LAN card of the specified name already exists
LockList(c->UnixVLanList);
{
UNIX_VLAN t, *r;
Zero(&t, sizeof(t));
StrCpy(t.Name, sizeof(t.Name), create->DeviceName);
r = Search(c->UnixVLanList, &t);
if (r != NULL)
{
// Already exist
CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
UnlockList(c->UnixVLanList);
return false;
}
// Register
r = ZeroMalloc(sizeof(UNIX_VLAN));
r->Enabled = true;
GenMacAddress(r->MacAddress);
StrCpy(r->Name, sizeof(r->Name), create->DeviceName);
// Create a Tap
if (UnixVLanCreate(r->Name, r->MacAddress) == false)
{
// Failure
Free(r);
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
UnlockList(c->UnixVLanList);
return false;
}
CLog(c, "LC_CREATE_VLAN", create->DeviceName);
Add(c->UnixVLanList, r);
}
UnlockList(c->UnixVLanList);
CiNormalizeAccountVLan(c);
CiNotify(c);
CiSendGlobalPulse(c);
CiSaveConfigurationFile(c);
return true;
#else // OS_WIN32
if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
{
// Only one LAN card is available in the Win9x
TOKEN_LIST *t;
t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
if (t != NULL)
{
if (t->NumTokens >= 1)
{
FreeToken(t);
CiSetError(c, ERR_NOT_SUPPORTED);
return false;
}
FreeToken(t);
}
}
// Check whether the specified name is valid or not
if (IsSafeStr(create->DeviceName) == false)
{
// Name is invalid
CiSetError(c, ERR_VLAN_INVALID_NAME);
return false;
}
max_len = MsIsNt() ? MAX_DEVICE_NAME_LEN : MAX_DEVICE_NAME_LEN_9X;
if (StrLen(create->DeviceName) > max_len)
{
// Name is too long
CiSetError(c, ERR_VLAN_INVALID_NAME);
return false;
}
// Regulation in Windows 8 / 10
if (MsIsInfCatalogRequired())
{
if (CiIsValidVLanRegulatedName(create->DeviceName) == false)
{
// Name is invalid
CiSetError(c, ERR_VLAN_INVALID_NAME);
return false;
}
}
// Check whether the LAN card with the specified name already exists
if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, create->DeviceName) ||
MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName))
{
// Already exist
CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
return false;
}
if (MsIsNt())
{
if (MsIsVista() == false)
{
k = InitKakushi();
}
}
if (MsIsVista() == false)
{
MS_DRIVER_VER ver;
CiInitDriverVerStruct(&ver);
// Perform the installation (other than Windows Vista)
if (MsInstallVLan(VLAN_ADAPTER_NAME_TAG, VLAN_CONNECTION_NAME, create->DeviceName, &ver) == false)
{
// Installation Failed
FreeKakushi(k);
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
else
{
// Perform the installation (Windows Vista)
char tmp[MAX_SIZE];
Format(tmp, sizeof(tmp), "instvlan %s", create->DeviceName);
if (CncExecDriverInstaller(tmp) == false)
{
// Installation Failed
FreeKakushi(k);
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
CiNotify(c);
CiSendGlobalPulse(c);
return false;
}
}
FreeKakushi(k);
t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
if (t->NumTokens == 1)
{
UINT i;
// If the result of the installation, virtual LAN card is only one,
// set virtual LAN card setting of all existing accounts to this virtual LAN card
LockList(c->AccountList);
{
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
Lock(a->lock);
{
if (a->ClientOption != NULL)
{
StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), create->DeviceName);
}
}
Unlock(a->lock);
}
}
UnlockList(c->AccountList);
}
FreeToken(t);
CLog(c, "LC_CREATE_VLAN", create->DeviceName);
CiNormalizeAccountVLan(c);
CiNotify(c);
CiSendGlobalPulse(c);
CiSaveConfigurationFile(c);
if (MsIsNt() == false)
{
if (GetOsInfo()->OsType == OSTYPE_WINDOWS_ME)
{
// Show the warning in the case of Windows Me
MsgBox(NULL, 0x00000040L, _UU("CM_9X_VLAN_ME_MESSAGE"));
}
ReleaseThread(NewThread(Win9xRebootThread, NULL));
}
return true;
#endif // OS_WIN32
}
// Enumerate objects in the secure device
bool CtEnumObjectInSecure(CLIENT *c, RPC_ENUM_OBJECT_IN_SECURE *e)
{
UINT i;
// Validate arguments
if (c == NULL || e == NULL)
{
return false;
}
e->NumItem = 5;
e->ItemName = ZeroMalloc(sizeof(char *) * e->NumItem);
e->ItemType = ZeroMalloc(sizeof(bool) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
char tmp[MAX_SIZE];
Format(tmp, sizeof(tmp), "Test Object %u", i);
e->ItemName[i] = CopyStr(tmp);
e->ItemType[i] = (i % 2 == 0) ? false : true;
}
return true;
}
// Get the secure device to be used
bool CtGetUseSecure(CLIENT *c, RPC_USE_SECURE *sec)
{
// Validate arguments
if (c == NULL || sec == NULL)
{
return false;
}
sec->DeviceId = c->UseSecureDeviceId;
return true;
}
// Specifying a secure device to be used
bool CtUseSecure(CLIENT *c, RPC_USE_SECURE *sec)
{
// Validate arguments
if (c == NULL || sec == NULL)
{
return false;
}
// Do not check whether there is the specified device on the client manager
/* if (CheckSecureDeviceId(sec->DeviceId))
{
c->UseSecureDeviceId = sec->DeviceId;
}
else
{
CiSetError(c, ERR_OBJECT_NOT_FOUND);
return false;
}
*/
c->UseSecureDeviceId = sec->DeviceId;
CiSaveConfigurationFile(c);
return true;
}
// Enumeration of secure devices
bool CtEnumSecure(CLIENT *c, RPC_CLIENT_ENUM_SECURE *e)
{
LIST *o;
UINT i;
// Validate arguments
if (c == NULL || e == NULL)
{
return false;
}
o = GetSecureDeviceList();
e->NumItem = LIST_NUM(o);
e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM *) * e->NumItem);
for (i = 0;i < LIST_NUM(o);i++)
{
RPC_CLIENT_ENUM_SECURE_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM));
SECURE_DEVICE *s = LIST_DATA(o, i);
item->DeviceId = s->Id;
StrCpy(item->DeviceName, sizeof(item->DeviceName), s->DeviceName);
StrCpy(item->Manufacturer, sizeof(item->Manufacturer), s->Manufacturer);
item->Type = s->Type;
e->Items[i] = item;
}
return true;
}
// Release the secure device enumeration
void CiFreeClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e)
{
UINT i;
// Validate arguments
if (e == NULL)
{
return;
}
for (i = 0;i < e->NumItem;i++)
{
Free(e->Items[i]);
}
Free(e->Items);
}
// Release the RPC_GET_ISSUER
void CiFreeGetIssuer(RPC_GET_ISSUER *a)
{
// Validate arguments
if (a == NULL)
{
return;
}
if (a->issuer_x != NULL)
{
FreeX(a->issuer_x);
}
if (a->x != NULL)
{
FreeX(a->x);
}
}
// Get the common proxy settings
bool CtGetCommonProxySetting(CLIENT *c, INTERNET_SETTING *a)
{
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
Copy(a, &c->CommonProxySetting, sizeof(INTERNET_SETTING));
return true;
}
// Set the common proxy settings
bool CtSetCommonProxySetting(CLIENT *c, INTERNET_SETTING *a)
{
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
Copy(&c->CommonProxySetting, a, sizeof(INTERNET_SETTING));
CiSaveConfigurationFile(c);
return true;
}
// Get the issuer
bool CtGetIssuer(CLIENT *c, RPC_GET_ISSUER *a)
{
X *x;
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
x = FindCaSignedX(c->Cedar->CaList, a->x);
if (x == NULL)
{
CiSetError(c, ERR_OBJECT_NOT_FOUND);;
return false;
}
else
{
a->issuer_x = x;
if (a->x != NULL)
{
FreeX(a->x);
a->x = NULL;
}
return true;
}
}
// Get the CA certificate
bool CtGetCa(CLIENT *c, RPC_GET_CA *get)
{
bool ret = true;
X *cert = NULL;
// Validate arguments
if (c == NULL || get == NULL)
{
return false;
}
LockList(c->Cedar->CaList);
{
UINT i;
for (i = 0;i < LIST_NUM(c->Cedar->CaList);i++)
{
X *x = LIST_DATA(c->Cedar->CaList, i);
if (POINTER_TO_KEY(x) == get->Key)
{
cert = CloneX(x);
break;
}
}
}
UnlockList(c->Cedar->CaList);
if (cert == NULL)
{
// Certificate does not exist
ret = false;
CiSetError(c, ERR_OBJECT_NOT_FOUND);
}
else
{
ret = true;
get->x = cert;
}
return ret;
}
// Delete the CA certificate
bool CtDeleteCa(CLIENT *c, RPC_CLIENT_DELETE_CA *p)
{
bool ret;
// Validate arguments
if (c == NULL || p == NULL)
{
return false;
}
ret = DeleteCa(c->Cedar, p->Key);
if (ret == false)
{
CiSetError(c, ERR_OBJECT_NOT_FOUND);
}
CiSaveConfigurationFile(c);
return ret;
}
// Add a CA certificate
bool CtAddCa(CLIENT *c, RPC_CERT *cert)
{
// Validate arguments
if (c == NULL || cert == NULL)
{
return false;
}
if (cert->x->is_compatible_bit == false)
{
CiSetError(c, ERR_NOT_RSA_1024);
return false;
}
AddCa(c->Cedar, cert->x);
CiSaveConfigurationFile(c);
return true;
}
// Enumerate the trusted CA
bool CtEnumCa(CLIENT *c, RPC_CLIENT_ENUM_CA *e)
{
// Validate arguments
if (c == NULL || e == NULL)
{
return false;
}
Zero(e, sizeof(RPC_CLIENT_ENUM_CA));
LockList(c->Cedar->CaList);
{
UINT i;
e->NumItem = LIST_NUM(c->Cedar->CaList);
e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM *) * e->NumItem);
for (i = 0;i < e->NumItem;i++)
{
X *x = LIST_DATA(c->Cedar->CaList, i);
e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM));
GetAllNameFromNameEx(e->Items[i]->SubjectName, sizeof(e->Items[i]->SubjectName), x->subject_name);
GetAllNameFromNameEx(e->Items[i]->IssuerName, sizeof(e->Items[i]->IssuerName), x->issuer_name);
e->Items[i]->Expires = x->notAfter;
e->Items[i]->Key = POINTER_TO_KEY(x);
}
}
UnlockList(c->Cedar->CaList);
return true;
}
// Release the CA enumeration
void CiFreeClientEnumCa(RPC_CLIENT_ENUM_CA *e)
{
UINT i;
// Validate arguments
if (e == NULL)
{
return;
}
for (i = 0;i < e->NumItem;i++)
{
RPC_CLIENT_ENUM_CA_ITEM *ca = e->Items[i];
Free(ca);
}
Free(e->Items);
}
// Get the password setting
bool CtGetPasswordSetting(CLIENT *c, RPC_CLIENT_PASSWORD_SETTING *a)
{
UCHAR hash[SHA1_SIZE];
// Validate arguments
if (c == NULL || a == NULL)
{
return false;
}
Hash(hash, "", 0, true);
if (Cmp(hash, c->EncryptedPassword, SHA1_SIZE) == 0)
{
a->IsPasswordPresented = false;
}
else
{
a->IsPasswordPresented = true;
}
a->PasswordRemoteOnly = c->PasswordRemoteOnly;
return true;
}
// Set the password
bool CtSetPassword(CLIENT *c, RPC_CLIENT_PASSWORD *pass)
{
char *str;
if (c == NULL)
{
return false;
}
if (pass->Password == NULL)
{
str = "";
}
else
{
str = pass->Password;
}
if (StrCmp(str, "********") != 0)
{
// Hash the password
Hash(c->EncryptedPassword, str, StrLen(str), true);
}
c->PasswordRemoteOnly = pass->PasswordRemoteOnly;
CLog(c, "LC_SET_PASSWORD");
CiSaveConfigurationFile(c);
return true;
}
void CiFreeIni(LIST *o)
{
// Validate arguments
if (o == NULL)
{
return;
}
FreeIni(o);
}
// Read the custom.ini file
LIST *CiLoadIni()
{
BUF *b = ReadDump(CLIENT_CUSTOM_INI_FILENAME);
LIST *ini;
if (b == NULL)
{
return NULL;
}
ini = ReadIni(b);
FreeBuf(b);
return ini;
}
// Reflect the settings of the custom.ini
void CiLoadIniSettings(CLIENT *c)
{
LIST *o;
//char *log;
//char *config;
if (c == NULL)
{
return;
}
o = CiLoadIni();
if (o == NULL)
{
return;
}
/*log = IniStrValue(o, "NoSaveLog");
config = IniStrValue(o, "NoSaveConfig");
if(StrCmpi(log, "true") == 0)
{
c->NoSaveLog = true;
}
if(StrCmpi(config, "true") == 0)
{
c->NoSaveConfig = true;
}*/
c->NoSaveLog = ToBool(IniStrValue(o, "NoSaveLog"));
c->NoSaveConfig = ToBool(IniStrValue(o, "NoSaveConfig"));
CiFreeIni(o);
}
bool CiLoadConfigFilePathFromIni(char *path, UINT size)
{
char *tmp;
LIST *o;
bool ret = false;
// Validate arguments
if (path == NULL)
{
return false;
}
o = CiLoadIni();
if (o == NULL)
{
return false;
}
StrCpy(path, size, "");
tmp = IniStrValue(o, "ConfigPath");
NormalizePath(path, size, tmp);
if (IsEmptyStr(path) == false)
{
ret = true;
}
else
{
ret = false;
}
CiFreeIni(o);
return ret;
}
// Set the client error code
void CiSetError(CLIENT *c, UINT err)
{
// Validate arguments
if (c == NULL)
{
return;
}
c->Err = err;
}
// UNIX virtual LAN card comparison function
int CiCompareUnixVLan(void *p1, void *p2)
{
UNIX_VLAN *v1, *v2;
if (p1 == NULL || p2 == NULL)
{
return 0;
}
v1 = *(UNIX_VLAN **)p1;
v2 = *(UNIX_VLAN **)p2;
if (v1 == NULL || v2 == NULL)
{
return 0;
}
return StrCmpi(v1->Name, v2->Name);
}
// Modify the account settings that an incorrect VLAN name is specified
void CiNormalizeAccountVLan(CLIENT *c)
{
bool b = false;
char *name;
UINT i;
// Validate arguments
if (c == NULL)
{
return;
}
name = CiGetFirstVLan(c);
if (name != NULL)
{
LockList(c->AccountList);
{
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
Lock(a->lock);
{
if (a->ClientOption != NULL)
{
if (CiIsVLan(c, a->ClientOption->DeviceName) == false)
{
StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName),
name);
b = true;
}
}
}
Unlock(a->lock);
}
}
UnlockList(c->AccountList);
Free(name);
}
if (b)
{
CiNotify(c);
CiSendGlobalPulse(c);
CiSaveConfigurationFile(c);
}
}
// Check whether a virtual LAN card of the specified name exists
bool CiIsVLan(CLIENT *c, char *name)
{
// Validate arguments
if (c == NULL || name == NULL)
{
return false;
}
#ifdef OS_WIN32
{
TOKEN_LIST *t;
UINT i;
t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
if (t == NULL)
{
return false;
}
for (i = 0;i < t->NumTokens;i++)
{
if (StrCmpi(t->Token[i], name) == 0)
{
FreeToken(t);
return true;
}
}
FreeToken(t);
return false;
}
#else // OS_WIN32
{
UNIX_VLAN *v;
UINT i;
bool ret = false;
LockList(c->UnixVLanList);
{
for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
{
v = (UNIX_VLAN *)LIST_DATA(c->UnixVLanList, i);
if (StrCmpi(v->Name, name) == 0)
{
ret = true;
}
}
}
UnlockList(c->UnixVLanList);
return ret;
}
#endif // OS_WIN32
}
// If a non-existent virtual LAN card is specified in any Account, and only
// one virtual LAN card is installed, set the virtual LAN card to the account
void CiSetVLanToDefault(CLIENT *c)
{
char device_name[MAX_SIZE];
// Validate arguments
if (c == NULL)
{
return;
}
#ifdef OS_WIN32
{
TOKEN_LIST *t;
t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
if (t == NULL)
{
return;
}
if (t->NumTokens != 1)
{
FreeToken(t);
return;
}
StrCpy(device_name, sizeof(device_name), t->Token[0]);
FreeToken(t);
}
#else // OS_WIN32
{
UINT i;
UNIX_VLAN *v;
LockList(c->UnixVLanList);
if (LIST_NUM(c->UnixVLanList) != 1)
{
UnlockList(c->UnixVLanList);
return;
}
v = LIST_DATA(c->UnixVLanList, 0);
StrCpy(device_name, sizeof(device_name), v->Name);
UnlockList(c->UnixVLanList);
}
#endif // OS_WIN32
{
UINT i;
LockList(c->AccountList);
{
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
Lock(a->lock);
{
if (CiIsVLan(c, a->ClientOption->DeviceName) == false)
{
StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName),
device_name);
}
}
Unlock(a->lock);
}
}
UnlockList(c->AccountList);
}
}
// Initialize the settings
void CiInitConfiguration(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
#ifdef OS_UNIX
// Initialize the VLAN
UnixVLanInit();
#endif // OS_UNIX
// Account list
c->AccountList = NewList(CiCompareAccount);
// Unix version VLAN list
if (OS_IS_UNIX(GetOsInfo()->OsType))
{
c->UnixVLanList = NewList(CiCompareUnixVLan);
}
// Read the configuration file
CLog(c, "LC_LOAD_CONFIG_1");
if (CiLoadConfigurationFile(c) == false)
{
CLog(c, "LC_LOAD_CONFIG_3");
// Do the initial setup because the configuration file does not exist
// Clear the password
Hash(c->EncryptedPassword, "", 0, true);
// Initialize the client configuration
if (OS_IS_WINDOWS(GetOsInfo()->OsType))
{
// Disable remote management in Windows
c->Config.AllowRemoteConfig = false;
}
else
{
// Disable the remote management also in case of UNIX
c->Config.AllowRemoteConfig = false;
}
StrCpy(c->Config.KeepConnectHost, sizeof(c->Config.KeepConnectHost), CLIENT_DEFAULT_KEEPALIVE_HOST);
c->Config.KeepConnectPort = CLIENT_DEFAULT_KEEPALIVE_PORT;
c->Config.KeepConnectProtocol = CONNECTION_UDP;
c->Config.KeepConnectInterval = CLIENT_DEFAULT_KEEPALIVE_INTERVAL;
c->Config.UseKeepConnect = false; // Don't use the connection maintenance function by default in the Client
// Eraser
c->Eraser = NewEraser(c->Logger, 0);
}
else
{
CLog(c, "LC_LOAD_CONFIG_2");
}
// Appropriate setting for virtual LAN card
CiSetVLanToDefault(c);
}
// Release the settings
void CiFreeConfiguration(CLIENT *c)
{
UINT i;
// Validate arguments
if (c == NULL)
{
return;
}
// Write to the configuration file
CiSaveConfigurationFile(c);
// Release the configuration file
FreeCfgRw(c->CfgRw);
// Release the account list
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
CiFreeAccount(a);
}
ReleaseList(c->AccountList);
if (c->UnixVLanList != NULL)
{
// Release of UNIX version VLAN list
for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
{
UNIX_VLAN *v = LIST_DATA(c->UnixVLanList, i);
Free(v);
}
ReleaseList(c->UnixVLanList);
}
c->UnixVLanList = NULL;
#ifdef OS_UNIX
// Release the VLAN
UnixVLanFree();
#endif // OS_UNIX
}
// Release the certificate data acquisition
void CiFreeGetCa(RPC_GET_CA *a)
{
// Validate arguments
if (a == NULL)
{
return;
}
FreeX(a->x);
}
// Release the client authentication data
void CiFreeClientAuth(CLIENT_AUTH *auth)
{
// Validate arguments
if (auth == NULL)
{
return;
}
if (auth->ClientX != NULL)
{
FreeX(auth->ClientX);
}
if (auth->ClientK != NULL)
{
FreeK(auth->ClientK);
}
Free(auth);
}
// Release the account
void CiFreeAccount(ACCOUNT *a)
{
// Validate arguments
if (a == NULL)
{
return;
}
// Release the lock
DeleteLock(a->lock);
// Release the client option
Free(a->ClientOption);
// Release the client authentication data
CiFreeClientAuth(a->ClientAuth);
if (a->ServerCert != NULL)
{
FreeX(a->ServerCert);
}
Free(a);
}
// Sort accounts
int CiCompareAccount(void *p1, void *p2)
{
ACCOUNT *a1, *a2;
if (p1 == NULL || p2 == NULL)
{
return 0;
}
a1 = *(ACCOUNT **)p1;
a2 = *(ACCOUNT **)p2;
if (a1 == NULL || a2 == NULL)
{
return 0;
}
return UniStrCmpi(a1->ClientOption->AccountName, a2->ClientOption->AccountName);
}
// Read the client configuration
void CiLoadClientConfig(CLIENT_CONFIG *c, FOLDER *f)
{
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
c->UseKeepConnect = CfgGetBool(f, "UseKeepConnect");
CfgGetStr(f, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost));
c->KeepConnectPort = CfgGetInt(f, "KeepConnectPort");
c->KeepConnectProtocol = CfgGetInt(f, "KeepConnectProtocol");
c->AllowRemoteConfig = CfgGetBool(f, "AllowRemoteConfig");
c->KeepConnectInterval = MAKESURE(CfgGetInt(f, "KeepConnectInterval"), KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX);
c->NoChangeWcmNetworkSettingOnWindows8 = CfgGetBool(f, "NoChangeWcmNetworkSettingOnWindows8");
}
// Read the client authentication data
CLIENT_AUTH *CiLoadClientAuth(FOLDER *f)
{
CLIENT_AUTH *a;
char *s;
BUF *b;
// Validate arguments
if (f == NULL)
{
return NULL;
}
a = ZeroMalloc(sizeof(CLIENT_AUTH));
a->AuthType = CfgGetInt(f, "AuthType");
CfgGetStr(f, "Username", a->Username, sizeof(a->Username));
switch (a->AuthType)
{
case CLIENT_AUTHTYPE_ANONYMOUS:
break;
case CLIENT_AUTHTYPE_PASSWORD:
CfgGetByte(f, "HashedPassword", a->HashedPassword, SHA1_SIZE);
break;
case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
b = CfgGetBuf(f, "EncryptedPassword");
if (b != NULL)
{
s = DecryptPassword(b);
StrCpy(a->PlainPassword, sizeof(a->PlainPassword), s);
Free(s);
FreeBuf(b);
}
break;
case CLIENT_AUTHTYPE_CERT:
b = CfgGetBuf(f, "ClientCert");
if (b != NULL)
{
a->ClientX = BufToX(b, false);
}
FreeBuf(b);
b = CfgGetBuf(f, "ClientKey");
if (b != NULL)
{
a->ClientK = BufToK(b, true, false, NULL);
}
FreeBuf(b);
break;
case CLIENT_AUTHTYPE_SECURE:
CfgGetStr(f, "SecurePublicCertName", a->SecurePublicCertName, sizeof(a->SecurePublicCertName));
CfgGetStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName, sizeof(a->SecurePrivateKeyName));
break;
}
return a;
}
// Read the client option
CLIENT_OPTION *CiLoadClientOption(FOLDER *f)
{
CLIENT_OPTION *o;
char *s;
BUF *b;
// Validate arguments
if (f == NULL)
{
return NULL;
}
o = ZeroMalloc(sizeof(CLIENT_OPTION));
CfgGetUniStr(f, "AccountName", o->AccountName, sizeof(o->AccountName));
CfgGetStr(f, "Hostname", o->Hostname, sizeof(o->Hostname));
o->Port = CfgGetInt(f, "Port");
o->PortUDP = CfgGetInt(f, "PortUDP");
o->ProxyType = CfgGetInt(f, "ProxyType");
CfgGetStr(f, "ProxyName", o->ProxyName, sizeof(o->ProxyName));
o->ProxyPort = CfgGetInt(f, "ProxyPort");
CfgGetStr(f, "ProxyUsername", o->ProxyUsername, sizeof(o->ProxyUsername));
b = CfgGetBuf(f, "ProxyPassword");
s = DecryptPassword(b);
StrCpy(o->ProxyPassword, sizeof(o->ProxyPassword), s);
Free(s);
FreeBuf(b);
o->NumRetry = CfgGetInt(f, "NumRetry");
o->RetryInterval = CfgGetInt(f, "RetryInterval");
CfgGetStr(f, "HubName", o->HubName, sizeof(o->HubName));
o->MaxConnection = CfgGetInt(f, "MaxConnection");
o->UseEncrypt = CfgGetBool(f, "UseEncrypt");
o->UseCompress = CfgGetBool(f, "UseCompress");
o->HalfConnection = CfgGetBool(f, "HalfConnection");
o->NoRoutingTracking = CfgGetBool(f, "NoRoutingTracking");
CfgGetStr(f, "DeviceName", o->DeviceName, sizeof(o->DeviceName));
o->AdditionalConnectionInterval = CfgGetInt(f, "AdditionalConnectionInterval");
o->HideStatusWindow = CfgGetBool(f, "HideStatusWindow");
o->HideNicInfoWindow = CfgGetBool(f, "HideNicInfoWindow");
o->ConnectionDisconnectSpan = CfgGetInt(f, "ConnectionDisconnectSpan");
o->RequireMonitorMode = CfgGetBool(f, "RequireMonitorMode");
o->RequireBridgeRoutingMode = CfgGetBool(f, "RequireBridgeRoutingMode");
o->DisableQoS = CfgGetBool(f, "DisableQoS");
o->FromAdminPack = CfgGetBool(f, "FromAdminPack");
o->NoTls1 = CfgGetBool(f, "NoTls1");
o->NoUdpAcceleration = CfgGetBool(f, "NoUdpAcceleration");
b = CfgGetBuf(f, "HostUniqueKey");
if (b != NULL)
{
if (b->Size == SHA1_SIZE)
{
Copy(o->HostUniqueKey, b->Buf, SHA1_SIZE);
}
FreeBuf(b);
}
return o;
}
// Read the account data
ACCOUNT *CiLoadClientAccount(FOLDER *f)
{
ACCOUNT *a;
FOLDER *client_option_folder, *client_auth_folder;
BUF *b;
char tmp[64];
// Validate arguments
if (f == NULL)
{
return NULL;
}
client_option_folder = CfgGetFolder(f, "ClientOption");
if (client_option_folder != NULL)
{
// Compare whether it matches to the account name that is already registered
}
client_auth_folder = CfgGetFolder(f, "ClientAuth");
if (client_option_folder == NULL || client_auth_folder == NULL)
{
return NULL;
}
a = ZeroMalloc(sizeof(ACCOUNT));
a->lock = NewLock();
a->ClientOption = CiLoadClientOption(client_option_folder);
a->ClientAuth = CiLoadClientAuth(client_auth_folder);
a->StartupAccount = CfgGetBool(f, "StartupAccount");
a->CheckServerCert = CfgGetBool(f, "CheckServerCert");
a->CreateDateTime = CfgGetInt64(f, "CreateDateTime");
a->UpdateDateTime = CfgGetInt64(f, "UpdateDateTime");
a->LastConnectDateTime = CfgGetInt64(f, "LastConnectDateTime");
b = CfgGetBuf(f, "ServerCert");
if (b != NULL)
{
a->ServerCert = BufToX(b, false);
FreeBuf(b);
}
if (CfgGetStr(f, "ShortcutKey", tmp, sizeof(tmp)))
{
BUF *b = StrToBin(tmp);
if (b->Size == SHA1_SIZE)
{
Copy(a->ShortcutKey, b->Buf, SHA1_SIZE);
}
FreeBuf(b);
}
if (IsZero(a->ShortcutKey, SHA1_SIZE))
{
Rand(a->ShortcutKey, SHA1_SIZE);
}
return a;
}
// Read the account database
void CiLoadAccountDatabase(CLIENT *c, FOLDER *f)
{
TOKEN_LIST *t;
UINT i;
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
t = CfgEnumFolderToTokenList(f);
if (t == NULL)
{
return;
}
for (i = 0;i < t->NumTokens;i++)
{
FOLDER *ff = CfgGetFolder(f, t->Token[i]);
if (ff != NULL)
{
ACCOUNT *a = CiLoadClientAccount(ff);
if (a != NULL)
{
{
Add(c->AccountList, a);
}
}
}
}
Sort(c->AccountList);
FreeToken(t);
}
// Read the root CA certificate
void CiLoadCACert(CLIENT *c, FOLDER *f)
{
BUF *b;
X *x;
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
b = CfgGetBuf(f, "X509");
if (b == NULL)
{
return;
}
x = BufToX(b, false);
AddCa(c->Cedar, x);
FreeX(x);
FreeBuf(b);
}
// Read the root CA list
void CiLoadCAList(CLIENT *c, FOLDER *f)
{
CEDAR *cedar;
TOKEN_LIST *t;
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
t = CfgEnumFolderToTokenList(f);
cedar = c->Cedar;
LockList(cedar->CaList);
{
UINT i;
for (i = 0;i < t->NumTokens;i++)
{
FOLDER *folder = CfgGetFolder(f, t->Token[i]);
CiLoadCACert(c, folder);
}
}
UnlockList(cedar->CaList);
FreeToken(t);
}
// Read a VLAN
void CiLoadVLan(CLIENT *c, FOLDER *f)
{
char tmp[MAX_SIZE];
UCHAR addr[6];
BUF *b;
UNIX_VLAN *v;
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
if (CfgGetStr(f, "MacAddress", tmp, sizeof(tmp)) == false)
{
return;
}
b = StrToBin(tmp);
if (b == NULL)
{
return;
}
if (b->Size != 6)
{
FreeBuf(b);
return;
}
Copy(addr, b->Buf, 6);
FreeBuf(b);
if (IsZero(addr, 6))
{
return;
}
v = ZeroMalloc(sizeof(UNIX_VLAN));
Copy(v->MacAddress, addr, 6);
StrCpy(v->Name, sizeof(v->Name), f->Name);
v->Enabled = CfgGetBool(f, "Enabled");
Add(c->UnixVLanList, v);
#ifdef OS_UNIX
UnixVLanCreate(v->Name, v->MacAddress);
#endif // OS_UNIX
}
// Read a VLAN list
void CiLoadVLanList(CLIENT *c, FOLDER *f)
{
TOKEN_LIST *t;
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
t = CfgEnumFolderToTokenList(f);
LockList(c->UnixVLanList);
{
UINT i;
for (i = 0;i < t->NumTokens;i++)
{
FOLDER *folder = CfgGetFolder(f, t->Token[i]);
CiLoadVLan(c, folder);
}
}
UnlockList(c->UnixVLanList);
FreeToken(t);
}
// Read the configuration from the configuration file
bool CiReadSettingFromCfg(CLIENT *c, FOLDER *root)
{
FOLDER *config;
FOLDER *cert;
FOLDER *db;
FOLDER *vlan;
FOLDER *cmsetting;
FOLDER *proxy;
char user_agent[MAX_SIZE];
// Validate arguments
if (c == NULL || root == NULL)
{
return false;
}
// Initialize the setting if there isn't either of AccountDatabase and Config
config = CfgGetFolder(root, "Config");
if (config == NULL)
{
return false;
}
db = CfgGetFolder(root, "AccountDatabase");
if (db == NULL)
{
return false;
}
cmsetting = CfgGetFolder(root, "ClientManagerSetting");
CiLoadClientConfig(&c->Config, config);
proxy = CfgGetFolder(root, "CommonProxySetting");
if (proxy != NULL)
{
INTERNET_SETTING t;
BUF *pw;
// Proxy Setting
Zero(&t, sizeof(t));
t.ProxyType = CfgGetInt(proxy, "ProxyType");
CfgGetStr(proxy, "ProxyHostName", t.ProxyHostName, sizeof(t.ProxyHostName));
t.ProxyPort = CfgGetInt(proxy, "ProxyPort");
CfgGetStr(proxy, "ProxyUsername", t.ProxyUsername, sizeof(t.ProxyUsername));
pw = CfgGetBuf(proxy, "ProxyPassword");
if (pw != NULL)
{
char *pw_str = DecryptPassword(pw);
StrCpy(t.ProxyPassword, sizeof(t.ProxyPassword), pw_str);
Free(pw_str);
FreeBuf(pw);
}
Copy(&c->CommonProxySetting, &t, sizeof(INTERNET_SETTING));
}
// Eraser
c->Eraser = NewEraser(c->Logger, CfgGetInt64(config, "AutoDeleteCheckDiskFreeSpaceMin"));
if (OS_IS_UNIX(GetOsInfo()->OsType)
#ifdef NO_VLAN
&& GetOsInfo()->OsType != OSTYPE_MACOS_X
#endif // NO_VLAN
)
{
// Read the UNIX version virtual LAN card list (except MacOS)
vlan = CfgGetFolder(root, "UnixVLan");
if (vlan != NULL)
{
CiLoadVLanList(c, vlan);
}
}
#ifdef NO_VLAN
if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
{
#ifdef OS_UNIX
UNIX_VLAN *uv;
// Create a Tap for MacOS X
if (UnixVLanCreate(CLIENT_MACOS_TAP_NAME, NULL) == false)
{
// Fail (abort)
CLog(c, "LC_TAP_NOT_FOUND");
Alert("tun/tap driver not found.", NULL);
exit(0);
}
uv = ZeroMalloc(sizeof(UNIX_VLAN));
uv->Enabled = true;
StrCpy(uv->Name, sizeof(uv->Name), CLIENT_MACOS_TAP_NAME);
Add(c->UnixVLanList, uv);
#endif // OS_UNIX
}
#endif // NO_VLAN
CiLoadAccountDatabase(c, db);
if (CfgGetByte(root, "EncryptedPassword", c->EncryptedPassword, SHA1_SIZE) == false)
{
Hash(c->EncryptedPassword, "", 0, true);
}
c->PasswordRemoteOnly = CfgGetBool(root, "PasswordRemoteOnly");
c->UseSecureDeviceId = CfgGetInt(root, "UseSecureDeviceId");
if (CfgGetStr(root, "UserAgent", user_agent, sizeof(user_agent)))
{
if (IsEmptyStr(user_agent) == false)
{
Free(c->Cedar->HttpUserAgent);
c->Cedar->HttpUserAgent = CopyStr(user_agent);
}
}
cert = CfgGetFolder(root, "RootCA");
if (cert != NULL)
{
CiLoadCAList(c, cert);
}
c->DontSavePassword = CfgGetBool(root, "DontSavePassword");
if (cmsetting != NULL)
{
UINT ostype = GetOsInfo()->OsType;
// CM_SETTING
CM_SETTING *s = c->CmSetting;
if (OS_IS_UNIX(ostype) || OS_IS_WINDOWS_NT(ostype))
{
s->EasyMode = CfgGetBool(cmsetting, "EasyMode");
}
s->LockMode = CfgGetBool(cmsetting, "LockMode");
CfgGetByte(cmsetting, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));
}
return true;
}
// Read the configuration file
bool CiLoadConfigurationFile(CLIENT *c)
{
bool ret;
FOLDER *root;
char path[MAX_SIZE];
// Validate arguments
if (c == NULL)
{
return false;
}
// Read the configuration file
if (CiLoadConfigFilePathFromIni(path, sizeof(path)))
{
c->CfgRw = NewCfgRw(&root, path);
}
else
{
c->CfgRw = NewCfgRw(&root, CLIENT_CONFIG_FILE_NAME);
}
if (root == NULL)
{
return false;
}
ret = CiReadSettingFromCfg(c, root);
CfgDeleteFolder(root);
return ret;
}
// Write the CLIENT_CONFIG
void CiWriteClientConfig(FOLDER *cc, CLIENT_CONFIG *config)
{
// Validate arguments
if (cc == NULL || config == NULL)
{
return;
}
CfgAddBool(cc, "UseKeepConnect", config->UseKeepConnect);
CfgAddStr(cc, "KeepConnectHost", config->KeepConnectHost);
CfgAddInt(cc, "KeepConnectPort", config->KeepConnectPort);
CfgAddInt(cc, "KeepConnectProtocol", config->KeepConnectProtocol);
CfgAddBool(cc, "AllowRemoteConfig", config->AllowRemoteConfig);
CfgAddInt(cc, "KeepConnectInterval", config->KeepConnectInterval);
CfgAddBool(cc, "NoChangeWcmNetworkSettingOnWindows8", config->NoChangeWcmNetworkSettingOnWindows8);
}
// Write the client authentication data
void CiWriteClientAuth(FOLDER *f, CLIENT_AUTH *a)
{
BUF *b;
// Validate arguments
if (f == NULL || a == NULL)
{
return;
}
CfgAddInt(f, "AuthType", a->AuthType);
CfgAddStr(f, "Username", a->Username);
switch (a->AuthType)
{
case CLIENT_AUTHTYPE_ANONYMOUS:
break;
case CLIENT_AUTHTYPE_PASSWORD:
CfgAddByte(f, "HashedPassword", a->HashedPassword, SHA1_SIZE);
break;
case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
b = EncryptPassword(a->PlainPassword);
CfgAddByte(f, "EncryptedPassword", b->Buf, b->Size);
FreeBuf(b);
break;
case CLIENT_AUTHTYPE_CERT:
if (a->ClientK != NULL && a->ClientX != NULL)
{
b = XToBuf(a->ClientX, false);
CfgAddByte(f, "ClientCert", b->Buf, b->Size);
FreeBuf(b);
b = KToBuf(a->ClientK, false, NULL);
CfgAddByte(f, "ClientKey", b->Buf, b->Size);
FreeBuf(b);
}
break;
case CLIENT_AUTHTYPE_SECURE:
CfgAddStr(f, "SecurePublicCertName", a->SecurePublicCertName);
CfgAddStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName);
break;
}
}
// Write the client option
void CiWriteClientOption(FOLDER *f, CLIENT_OPTION *o)
{
BUF *b;
// Validate arguments
if (f == NULL || o == NULL)
{
return;
}
CfgAddUniStr(f, "AccountName", o->AccountName);
CfgAddStr(f, "Hostname", o->Hostname);
CfgAddInt(f, "Port", o->Port);
CfgAddInt(f, "PortUDP", o->PortUDP);
CfgAddInt(f, "ProxyType", o->ProxyType);
CfgAddStr(f, "ProxyName", o->ProxyName);
CfgAddInt(f, "ProxyPort", o->ProxyPort);
CfgAddStr(f, "ProxyUsername", o->ProxyUsername);
b = EncryptPassword(o->ProxyPassword);
CfgAddByte(f, "ProxyPassword", b->Buf, b->Size);
FreeBuf(b);
CfgAddInt(f, "NumRetry", o->NumRetry);
CfgAddInt(f, "RetryInterval", o->RetryInterval);
CfgAddStr(f, "HubName", o->HubName);
CfgAddInt(f, "MaxConnection", o->MaxConnection);
CfgAddBool(f, "UseEncrypt", o->UseEncrypt);
CfgAddBool(f, "UseCompress", o->UseCompress);
CfgAddBool(f, "HalfConnection", o->HalfConnection);
CfgAddBool(f, "NoRoutingTracking", o->NoRoutingTracking);
CfgAddStr(f, "DeviceName", o->DeviceName);
CfgAddInt(f, "AdditionalConnectionInterval", o->AdditionalConnectionInterval);
CfgAddBool(f, "HideStatusWindow", o->HideStatusWindow);
CfgAddBool(f, "HideNicInfoWindow", o->HideNicInfoWindow);
CfgAddInt(f, "ConnectionDisconnectSpan", o->ConnectionDisconnectSpan);
CfgAddBool(f, "RequireMonitorMode", o->RequireMonitorMode);
CfgAddBool(f, "RequireBridgeRoutingMode", o->RequireBridgeRoutingMode);
CfgAddBool(f, "DisableQoS", o->DisableQoS);
CfgAddBool(f, "NoTls1", o->NoTls1);
CfgAddBool(f, "NoUdpAcceleration", o->NoUdpAcceleration);
if (o->FromAdminPack)
{
CfgAddBool(f, "FromAdminPack", o->FromAdminPack);
}
if (IsZero(o->HostUniqueKey, SHA1_SIZE) == false)
{
BUF *b = MemToBuf(o->HostUniqueKey, SHA1_SIZE);
CfgAddBuf(f, "HostUniqueKey", b);
FreeBuf(b);
}
}
// Decrypt the password
char *DecryptPassword(BUF *b)
{
char *str;
char *key = "EncryptPassword";
CRYPT *c;
// Validate arguments
if (b == NULL)
{
return CopyStr("");
}
str = ZeroMalloc(b->Size + 1);
c = NewCrypt(key, sizeof(key));
Encrypt(c, str, b->Buf, b->Size);
FreeCrypt(c);
str[b->Size] = 0;
return str;
}
char *DecryptPassword2(BUF *b)
{
char *str;
char *key = "EncryptPassword2";
CRYPT *c;
// Validate arguments
if (b == NULL)
{
return CopyStr("");
}
str = ZeroMalloc(b->Size + 1);
c = NewCrypt(key, StrLen(key));
Encrypt(c, str, b->Buf, b->Size);
FreeCrypt(c);
str[b->Size] = 0;
return str;
}
// Encrypt the password
BUF *EncryptPassword(char *password)
{
UCHAR *tmp;
UINT size;
char *key = "EncryptPassword";
CRYPT *c;
BUF *b;
// Validate arguments
if (password == NULL)
{
password = "";
}
size = StrLen(password) + 1;
tmp = ZeroMalloc(size);
c = NewCrypt(key, sizeof(key));
Encrypt(c, tmp, password, size - 1);
FreeCrypt(c);
b = NewBuf();
WriteBuf(b, tmp, size - 1);
SeekBuf(b, 0, 0);
Free(tmp);
return b;
}
BUF *EncryptPassword2(char *password)
{
UCHAR *tmp;
UINT size;
char *key = "EncryptPassword2";
CRYPT *c;
BUF *b;
// Validate arguments
if (password == NULL)
{
password = "";
}
size = StrLen(password) + 1;
tmp = ZeroMalloc(size);
c = NewCrypt(key, StrLen(key));
Encrypt(c, tmp, password, size - 1);
FreeCrypt(c);
b = NewBuf();
WriteBuf(b, tmp, size - 1);
SeekBuf(b, 0, 0);
Free(tmp);
return b;
}
// Write the account data
void CiWriteAccountData(FOLDER *f, ACCOUNT *a)
{
// Validate arguments
if (f == NULL || a == NULL)
{
return;
}
// Client Option
CiWriteClientOption(CfgCreateFolder(f, "ClientOption"), a->ClientOption);
// Client authentication data
CiWriteClientAuth(CfgCreateFolder(f, "ClientAuth"), a->ClientAuth);
// Startup account
CfgAddBool(f, "StartupAccount", a->StartupAccount);
// Server certificate check flag
CfgAddBool(f, "CheckServerCert", a->CheckServerCert);
// Date and time
CfgAddInt64(f, "CreateDateTime", a->CreateDateTime);
CfgAddInt64(f, "UpdateDateTime", a->UpdateDateTime);
CfgAddInt64(f, "LastConnectDateTime", a->LastConnectDateTime);
// Server certificate body
if (a->ServerCert != NULL)
{
BUF *b = XToBuf(a->ServerCert, false);
if (b != NULL)
{
CfgAddBuf(f, "ServerCert", b);
FreeBuf(b);
}
}
// Shortcut Key
if (IsZero(a->ShortcutKey, SHA1_SIZE) == false)
{
char tmp[64];
BinToStr(tmp, sizeof(tmp), a->ShortcutKey, SHA1_SIZE);
CfgAddStr(f, "ShortcutKey", tmp);
}
}
// Write the account database
void CiWriteAccountDatabase(CLIENT *c, FOLDER *f)
{
char name[MAX_SIZE];
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
LockList(c->AccountList);
{
UINT i;
for (i = 0;i < LIST_NUM(c->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(c->AccountList, i);
{
Format(name, sizeof(name), "Account%u", i);
Lock(a->lock);
{
CiWriteAccountData(CfgCreateFolder(f, name), a);
}
Unlock(a->lock);
}
}
}
UnlockList(c->AccountList);
}
// Write the CA certificate
void CiWriteCACert(CLIENT *c, FOLDER *f, X *x)
{
BUF *b;
// Validate arguments
if (c == NULL || f == NULL || x == NULL)
{
return;
}
b = XToBuf(x, false);
CfgAddBuf(f, "X509", b);
FreeBuf(b);
}
// Write a VLAN
void CiWriteVLan(CLIENT *c, FOLDER *f, UNIX_VLAN *v)
{
char tmp[MAX_SIZE];
// Validate arguments
if (c == NULL || f == NULL || v == NULL)
{
return;
}
MacToStr(tmp, sizeof(tmp), v->MacAddress);
CfgAddStr(f, "MacAddress", tmp);
CfgAddBool(f, "Enabled", v->Enabled);
}
// Write a VLAN list
void CiWriteVLanList(CLIENT *c, FOLDER *f)
{
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
LockList(c->UnixVLanList);
{
UINT i;
for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
{
UNIX_VLAN *v = LIST_DATA(c->UnixVLanList, i);
CiWriteVLan(c, CfgCreateFolder(f, v->Name), v);
}
}
UnlockList(c->UnixVLanList);
}
// Write the CA list
void CiWriteCAList(CLIENT *c, FOLDER *f)
{
CEDAR *cedar;
// Validate arguments
if (c == NULL || f == NULL)
{
return;
}
cedar = c->Cedar;
LockList(cedar->CaList);
{
UINT i;
for (i = 0;i < LIST_NUM(cedar->CaList);i++)
{
char tmp[MAX_SIZE];
X *x = LIST_DATA(cedar->CaList, i);
Format(tmp, sizeof(tmp), "Certificate%u", i);
CiWriteCACert(c, CfgCreateFolder(f, tmp), x);
}
}
UnlockList(cedar->CaList);
}
// Write the current settings to ROOT
void CiWriteSettingToCfg(CLIENT *c, FOLDER *root)
{
FOLDER *cc;
FOLDER *account_database;
FOLDER *ca;
FOLDER *vlan;
FOLDER *cmsetting;
FOLDER *proxy;
// Validate arguments
if (c == NULL || root == NULL)
{
return;
}
cmsetting = CfgCreateFolder(root, "ClientManagerSetting");
// CLIENT_CONFIG
cc = CfgCreateFolder(root, "Config");
CiWriteClientConfig(cc, &c->Config);
// Eraser
CfgAddInt64(cc, "AutoDeleteCheckDiskFreeSpaceMin", c->Eraser->MinFreeSpace);
// Account Database
account_database = CfgCreateFolder(root, "AccountDatabase");
CiWriteAccountDatabase(c, account_database);
// Proxy
proxy = CfgCreateFolder(root, "CommonProxySetting");
if (proxy != NULL)
{
INTERNET_SETTING *t = &c->CommonProxySetting;
BUF *pw;
CfgAddInt(proxy, "ProxyType", t->ProxyType);
CfgAddStr(proxy, "ProxyHostName", t->ProxyHostName);
CfgAddInt(proxy, "ProxyPort", t->ProxyPort);
CfgAddStr(proxy, "ProxyUsername", t->ProxyUsername);
if (IsEmptyStr(t->ProxyPassword) == false)
{
pw = EncryptPassword(t->ProxyPassword);
CfgAddBuf(proxy, "ProxyPassword", pw);
FreeBuf(pw);
}
}
// CA
ca = CfgCreateFolder(root, "RootCA");
CiWriteCAList(c, ca);
// VLAN
if (OS_IS_UNIX(GetOsInfo()->OsType)
#ifdef NO_VLAN
&& GetOsInfo()->OsType != OSTYPE_MACOS_X
#endif // NO_VLAN
)
{
vlan = CfgCreateFolder(root, "UnixVLan");
CiWriteVLanList(c, vlan);
}
// Password
CfgAddByte(root, "EncryptedPassword", c->EncryptedPassword, SHA1_SIZE);
CfgAddBool(root, "PasswordRemoteOnly", c->PasswordRemoteOnly);
// UseSecureDeviceId
CfgAddInt(root, "UseSecureDeviceId", c->UseSecureDeviceId);
// DontSavePassword
CfgAddBool(root, "DontSavePassword", c->DontSavePassword);
// UserAgent
if (c->Cedar != NULL)
{
CfgAddStr(root, "UserAgent", c->Cedar->HttpUserAgent);
}
if (cmsetting != NULL)
{
CM_SETTING *s = c->CmSetting;
CfgAddBool(cmsetting, "EasyMode", s->EasyMode);
CfgAddBool(cmsetting, "LockMode", s->LockMode);
if (IsZero(s->HashedPassword, sizeof(s->HashedPassword)) == false)
{
CfgAddByte(cmsetting, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));
}
}
}
// Create the inner VPN Server
SERVER *CiNewInnerVPNServer(CLIENT *c, bool relay_server)
{
SERVER *s = NULL;
// Validate arguments
if (c == NULL)
{
return NULL;
}
SetNatTLowPriority();
s = SiNewServerEx(false, true, relay_server);
return s;
}
// Stop the inner VPN Server
void CiFreeInnerVPNServer(CLIENT *c, SERVER *s)
{
// Validate arguments
if (c == NULL || s == NULL)
{
return;
}
SiReleaseServer(s);
}
// Apply settings of Inner VPN Server
void CiApplyInnerVPNServerConfig(CLIENT *c)
{
}
// Write to the configuration file
void CiSaveConfigurationFile(CLIENT *c)
{
FOLDER *root;
// Validate arguments
if (c == NULL)
{
return;
}
// Do not save the configuration file
if(c->NoSaveConfig)
{
return;
}
root = CfgCreateFolder(NULL, TAG_ROOT);
CiWriteSettingToCfg(c, root);
SaveCfgRw(c->CfgRw, root);
CfgDeleteFolder(root);
}
// Set the CM_SETTING
bool CtSetCmSetting(CLIENT *c, CM_SETTING *s)
{
// Validate arguments
if (c == NULL || s == NULL)
{
return false;
}
Copy(c->CmSetting, s, sizeof(CM_SETTING));
CiSaveConfigurationFile(c);
return true;
}
// Get the CM_SETTING
bool CtGetCmSetting(CLIENT *c, CM_SETTING *s)
{
// Validate arguments
if (c == NULL || s == NULL)
{
return false;
}
Copy(s, c->CmSetting, sizeof(CM_SETTING));
return true;
}
// Get the client version
bool CtGetClientVersion(CLIENT *c, RPC_CLIENT_VERSION *ver)
{
// Validate arguments
if (ver == NULL)
{
return false;
}
Zero(ver, sizeof(RPC_CLIENT_VERSION));
StrCpy(ver->ClientProductName, sizeof(ver->ClientProductName), CEDAR_CLIENT_STR);
StrCpy(ver->ClientVersionString, sizeof(ver->ClientVersionString), c->Cedar->VerString);
StrCpy(ver->ClientBuildInfoString, sizeof(ver->ClientBuildInfoString), c->Cedar->BuildInfo);
ver->ClientVerInt = c->Cedar->Version;
ver->ClientBuildInt = c->Cedar->Build;
#ifdef OS_WIN32
ver->ProcessId = MsGetProcessId();
ver->IsVLanNameRegulated = MsIsInfCatalogRequired();
#endif // OS_WIN32
ver->OsType = GetOsInfo()->OsType;
return true;
}
// Creating a Client object
CLIENT *CiNewClient()
{
CLIENT *c = ZeroMalloc(sizeof(CLIENT));
// StartCedarLog();
if (ci_active_sessions_lock == NULL)
{
ci_active_sessions_lock = NewLock();
ci_num_active_sessions = 0;
}
#ifdef OS_WIN32
if (MsIsWindows7())
{
c->MsSuspendHandler = MsNewSuspendHandler();
}
#endif // OS_WIN32
c->CmSetting = ZeroMalloc(sizeof(CM_SETTING));
c->SockList = NewSockList();
c->lock = NewLock();
c->lockForConnect = NewLock();
c->ref = NewRef();
c->Cedar = NewCedar(NULL, NULL);
c->Cedar->Client = c;
c->NotifyCancelList = NewList(NULL);
Hash(c->EncryptedPassword, "", 0, true);
#ifdef OS_WIN32
c->GlobalPulse = MsOpenOrCreateGlobalPulse(CLIENT_GLOBAL_PULSE_NAME);
#endif // OS_WIN32
if (c->GlobalPulse != NULL)
{
c->PulseRecvThread = NewThread(CiPulseRecvThread, c);
}
CiLoadIniSettings(c);
// Log Settings
if(c->NoSaveLog == false)
{
MakeDir(CLIENT_LOG_DIR_NAME);
c->Logger = NewLog(CLIENT_LOG_DIR_NAME, CLIENT_LOG_PREFIX, LOG_SWITCH_DAY);
}
CLog(c, "L_LINE");
CLog(c, "LC_START_2", CEDAR_CLIENT_STR, c->Cedar->VerString);
CLog(c, "LC_START_3", c->Cedar->BuildInfo);
CLog(c, "LC_START_1");
#ifdef OS_WIN32
{
// Initialize the Win32 UI
wchar_t tmp[MAX_SIZE];
StrToUni(tmp, sizeof(tmp), CEDAR_CLIENT_STR);
InitWinUi(tmp, _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
}
#endif // OS_WIN32
// Initialize the settings
CiInitConfiguration(c);
// Raise the priority
OSSetHighPriority();
#ifdef OS_WIN32
// For Win9x, release the DHCP address of all the virtual LAN card
if (MsIsNt() == false)
{
Win32ReleaseAllDhcp9x(true);
}
#endif // OS_WIN32
CiChangeAllVLanMacAddressIfMachineChanged(c);
CiChangeAllVLanMacAddressIfCleared(c);
// Initialize the internal VPN server
CiApplyInnerVPNServerConfig(c);
return c;
}
// Examine whether two proxy server settings equal
bool CompareInternetSetting(INTERNET_SETTING *s1, INTERNET_SETTING *s2)
{
// Validate arguments
if (s1 == NULL || s2 == NULL)
{
return false;
}
if (s1->ProxyType != s2->ProxyType)
{
return false;
}
if (s1->ProxyType == PROXY_DIRECT)
{
return true;
}
if (s1->ProxyPort != s2->ProxyPort)
{
return false;
}
if (StrCmp(s1->ProxyHostName, s2->ProxyHostName) != 0)
{
return false;
}
if (StrCmp(s1->ProxyUsername, s2->ProxyUsername) != 0)
{
return false;
}
if (StrCmp(s1->ProxyPassword, s2->ProxyPassword) != 0)
{
return false;
}
return true;
}
// Send a global pulse
void CiSendGlobalPulse(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
#ifdef OS_WIN32
MsSendGlobalPulse(c->GlobalPulse);
#endif // OS_WIN32
}
// Pulse reception thread
void CiPulseRecvThread(THREAD *thread, void *param)
{
#ifdef OS_WIN32
CLIENT *c = (CLIENT *)param;
if (c == NULL)
{
return;
}
while (true)
{
if (c->HaltPulseThread)
{
break;
}
MsWaitForGlobalPulse(c->GlobalPulse, INFINITE);
if (c->HaltPulseThread)
{
break;
}
CiNotifyInternal(c);
}
#endif // OS_WIN32
}
// Clean-up the client
void CiCleanupClient(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
// Release the settings
CiFreeConfiguration(c);
#ifdef OS_WIN32
// Release the Win32 UI
FreeWinUi();
#endif // OS_WIN32
CLog(c, "LC_END");
CLog(c, "L_LINE");
FreeEraser(c->Eraser);
FreeLog(c->Logger);
c->Logger = NULL;
ReleaseCedar(c->Cedar);
DeleteLock(c->lockForConnect);
DeleteLock(c->lock);
c->HaltPulseThread = true;
if (c->GlobalPulse != NULL)
{
#ifdef OS_WIN32
MsSendGlobalPulse(c->GlobalPulse);
#endif // OS_WIN32
}
if (c->PulseRecvThread != NULL)
{
WaitThread(c->PulseRecvThread, INFINITE);
ReleaseThread(c->PulseRecvThread);
}
if (c->GlobalPulse != NULL)
{
#ifdef OS_WIN32
MsCloseGlobalPulse(c->GlobalPulse);
#endif // OS_WIN32
}
ReleaseList(c->NotifyCancelList);
FreeSockList(c->SockList);
Free(c->CmSetting);
#ifdef OS_WIN32
if (c->MsSuspendHandler != NULL)
{
MsFreeSuspendHandler(c->MsSuspendHandler);
}
#endif // OS_WIN32
Free(c);
#ifdef OS_WIN32
// For Win9x, release the DHCP address of all the virtual LAN card
if (MsIsNt() == false)
{
Win32ReleaseAllDhcp9x(true);
}
#endif // OS_WIN32
StopCedarLog();
if (ci_active_sessions_lock != NULL)
{
DeleteLock(ci_active_sessions_lock);
ci_active_sessions_lock = NULL;
ci_num_active_sessions = 0;
}
}
// Increment of the number of active sessions
void CiIncrementNumActiveSessions()
{
Lock(ci_active_sessions_lock);
{
ci_num_active_sessions++;
}
Unlock(ci_active_sessions_lock);
}
// Decrement of the number of active sessions
void CiDecrementNumActiveSessions()
{
Lock(ci_active_sessions_lock);
{
if (ci_num_active_sessions >= 1)
{
ci_num_active_sessions--;
}
}
Unlock(ci_active_sessions_lock);
}
// Get the number of active sessions
UINT CiGetNumActiveSessions()
{
UINT ret;
Lock(ci_active_sessions_lock);
{
ret = ci_num_active_sessions;
}
Unlock(ci_active_sessions_lock);
return ret;
}
// Release the client
void CtReleaseClient(CLIENT *c)
{
// Validate arguments
if (c == NULL)
{
return;
}
if (Release(c->ref) == 0)
{
CiCleanupClient(c);
}
}
// Start the operation of the client program
void CtStartClient()
{
UINT i;
LIST *o;
if (client != NULL)
{
// It is already in running
return;
}
// OS check
CiCheckOs();
#ifdef OS_WIN32
RegistWindowsFirewallAll();
#endif
// Creating a client
client = CiNewClient();
// Start the Keep
CiInitKeep(client);
// Start the RPC server
CiStartRpcServer(client);
// Start the Saver
CiInitSaver(client);
// Start the startup connection
o = NewListFast(NULL);
LockList(client->AccountList);
{
for (i = 0;i < LIST_NUM(client->AccountList);i++)
{
ACCOUNT *a = LIST_DATA(client->AccountList, i);
Lock(a->lock);
{
if (a->StartupAccount)
{
Add(o, CopyUniStr(a->ClientOption->AccountName));
}
}
Unlock(a->lock);
}
}
UnlockList(client->AccountList);
for (i = 0;i < LIST_NUM(o);i++)
{
wchar_t *s = LIST_DATA(o, i);
RPC_CLIENT_CONNECT c;
Zero(&c, sizeof(c));
UniStrCpy(c.AccountName, sizeof(c.AccountName), s);
CtConnect(client, &c);
Free(s);
}
ReleaseList(o);
}
// Stop the operation of the client program
void CtStopClient()
{
UINT i, num;
ACCOUNT **account_list;
if (client == NULL)
{
// It is not running yet
return;
}
// Halting flag
client->Halt = true;
// Disconnect all the RPC
CiStopRpcServer(client);
// Exit the client notification service
CncExit();
// Exit the Keep
CiFreeKeep(client);
// Disconnect all accounts connected
LockList(client->AccountList);
{
num = LIST_NUM(client->AccountList);
account_list = ToArray(client->AccountList);
}
UnlockList(client->AccountList);
for (i = 0;i < num;i++)
{
ACCOUNT *a = account_list[i];
SESSION *s = NULL;
Lock(a->lock);
{
if (a->ClientSession != NULL)
{
s = a->ClientSession;
AddRef(s->ref);
}
}
Unlock(a->lock);
if (s != NULL)
{
StopSession(s);
ReleaseSession(s);
Lock(a->lock);
{
if (a->ClientSession != NULL)
{
ReleaseSession(a->ClientSession);
a->ClientSession = NULL;
}
}
Unlock(a->lock);
}
}
Free(account_list);
// Stop the Saver
CiFreeSaver(client);
// Release the client
CtReleaseClient(client);
client = NULL;
}
// OS check
void CiCheckOs()
{
// Get the OS type
OS_INFO *info = GetOsInfo();
if (OS_IS_WINDOWS(info->OsType))
{
bool ok = IS_CLIENT_SUPPORTED_OS(info->OsType);
if (ok == false)
{
Alert(
CEDAR_PRODUCT_STR " VPN Client doesn't support this Windows Operating System.\n"
CEDAR_PRODUCT_STR " VPN Client requires Windows 98, Windows Me, Windows 2000, Windows XP, Windows Server 2003 or Greater.\n\n"
"Please contact your system administrator.", CEDAR_PRODUCT_STR " VPN Client");
exit(0);
}
}
}
// Get the client object
CLIENT *CtGetClient()
{
if (client == NULL)
{
return NULL;
}
AddRef(client->ref);
return client;
}
// Client status indicator
void CiClientStatusPrinter(SESSION *s, wchar_t *status)
{
#ifdef OS_WIN32
ACCOUNT *a;
// Validate arguments
if (s == NULL || status == NULL)
{
return;
}
a = s->Account;
if (a == NULL)
{
return;
}
if (UniStrCmpi(status, L"init") == 0)
{
if (a->StatusWindow == NULL && s->Win32HideConnectWindow == false)
{
a->StatusWindow = CncStatusPrinterWindowStart(s);
}
}
else if (UniStrCmpi(status, L"free") == 0)
{
if (a->StatusWindow != NULL)
{
CncStatusPrinterWindowStop(a->StatusWindow);
a->StatusWindow = NULL;
}
}
else
{
if (a->StatusWindow != NULL)
{
CncStatusPrinterWindowPrint(a->StatusWindow, status);
}
}
#else // OS_WIN32
UniPrint(L"Status: %s\n", status);
#endif // OS_WIN32
}
// 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/