mirror of
https://github.com/SoftEtherVPN/SoftEtherVPN.git
synced 2024-11-23 01:49:53 +03:00
10729 lines
217 KiB
C
10729 lines
217 KiB
C
// SoftEther VPN Source Code - Developer Edition Master Branch
|
|
// Cedar Communication Module
|
|
// © 2020 Nokia
|
|
|
|
// Client.c
|
|
// Client Manager
|
|
|
|
#include "Client.h"
|
|
|
|
#include "Account.h"
|
|
#include "Admin.h"
|
|
#include "Cedar.h"
|
|
#include "CM.h"
|
|
#include "Connection.h"
|
|
#include "IPC.h"
|
|
#include "Listener.h"
|
|
#include "Logging.h"
|
|
#include "Protocol.h"
|
|
#include "Remote.h"
|
|
#include "Virtual.h"
|
|
#include "VLanUnix.h"
|
|
#include "VLanWin32.h"
|
|
#include "Win32Com.h"
|
|
#include "WinUi.h"
|
|
|
|
#include "Mayaqua/Cfg.h"
|
|
#include "Mayaqua/Encrypt.h"
|
|
#include "Mayaqua/FileIO.h"
|
|
#include "Mayaqua/Internat.h"
|
|
#include "Mayaqua/Kernel.h"
|
|
#include "Mayaqua/MayaType.h"
|
|
#include "Mayaqua/Memory.h"
|
|
#include "Mayaqua/Microsoft.h"
|
|
#include "Mayaqua/Network.h"
|
|
#include "Mayaqua/Object.h"
|
|
#include "Mayaqua/OS.h"
|
|
#include "Mayaqua/Pack.h"
|
|
#include "Mayaqua/Secure.h"
|
|
#include "Mayaqua/Str.h"
|
|
#include "Mayaqua/Table.h"
|
|
#include "Mayaqua/Tick64.h"
|
|
#include "Mayaqua/Win32.h"
|
|
|
|
#include <stdlib.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
|
|
// Product 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);
|
|
|
|
Sha0(data, name, StrLen(name));
|
|
}
|
|
|
|
// 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);
|
|
|
|
Sha0(data, name, StrLen(name));
|
|
}
|
|
|
|
// 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);
|
|
|
|
Sha0(data, name, StrLen(name));
|
|
}
|
|
|
|
|
|
// 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[0] == 0x00 && mac[1] == 0xAC) || (mac[0] == 0x5E)))
|
|
{
|
|
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)
|
|
{
|
|
#ifdef OS_WIN32
|
|
return Win32CnCheckAlreadyExists(lock);
|
|
#else
|
|
return false;
|
|
#endif
|
|
}
|
|
|
|
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;
|
|
|
|
// 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;
|
|
// 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;
|
|
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);
|
|
}
|
|
|
|
// 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)
|
|
{
|
|
PACK *p;
|
|
// Validate arguments
|
|
if (s == NULL || str == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
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);
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
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 (IsLocalHostIP(&s->LocalIP))
|
|
{
|
|
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())
|
|
{
|
|
#ifdef OS_WIN32
|
|
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();
|
|
}
|
|
#endif // OS_WIN32
|
|
|
|
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;
|
|
}
|
|
|
|
// 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->RetryOnServerCert = a->RetryOnServerCert;
|
|
t->AddDefaultCA = a->AddDefaultCA;
|
|
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.RetryOnServerCert = t->RetryOnServerCert;
|
|
a.AddDefaultCA = t->AddDefaultCA;
|
|
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)
|
|
{
|
|
PACK *ret;
|
|
CLIENT *c;
|
|
// Validate arguments
|
|
if (rpc == NULL || name == NULL || p == NULL)
|
|
{
|
|
return NULL;
|
|
}
|
|
c = rpc->Param;
|
|
|
|
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 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;
|
|
}
|
|
|
|
// 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 account
|
|
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);
|
|
|
|
PackSetCurrentJsonGroupName(p, "CAList");
|
|
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);
|
|
PackAddTime64Ex(p, "Expires", item->Expires, i, e->NumItem);
|
|
}
|
|
PackSetCurrentJsonGroupName(p, NULL);
|
|
}
|
|
|
|
// 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);
|
|
|
|
PackSetCurrentJsonGroupName(p, "SecureDeviceList");
|
|
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);
|
|
}
|
|
PackSetCurrentJsonGroupName(p, NULL);
|
|
}
|
|
|
|
// 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 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);
|
|
|
|
PackSetCurrentJsonGroupName(p, "ObjectList");
|
|
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);
|
|
}
|
|
PackSetCurrentJsonGroupName(p, NULL);
|
|
}
|
|
|
|
// 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);
|
|
|
|
PackSetCurrentJsonGroupName(p, "VLanList");
|
|
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);
|
|
}
|
|
PackSetCurrentJsonGroupName(p, NULL);
|
|
}
|
|
|
|
// 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));
|
|
// Extract hint string from hostname
|
|
UINT i = SearchStrEx(c->Hostname, "/", 0, false);
|
|
if (i != INFINITE)
|
|
{
|
|
StrCpy(c->HintStr, sizeof(c->HintStr), c->Hostname + i + 1);
|
|
c->Hostname[i] = 0;
|
|
}
|
|
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, "CustomHttpHeader", c->CustomHttpHeader, sizeof(c->CustomHttpHeader));
|
|
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->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);
|
|
// Append hint string to hostname
|
|
if (IsEmptyStr(c->HintStr))
|
|
{
|
|
// No hint
|
|
PackAddStr(p, "Hostname", c->Hostname);
|
|
}
|
|
else
|
|
{
|
|
char hostname[MAX_SIZE];
|
|
StrCpy(hostname, sizeof(hostname), c->Hostname);
|
|
StrCat(hostname, sizeof(hostname), "/");
|
|
StrCat(hostname, sizeof(hostname), c->HintStr);
|
|
PackAddStr(p, "Hostname", hostname);
|
|
}
|
|
PackAddStr(p, "ProxyName", c->ProxyName);
|
|
PackAddStr(p, "ProxyUsername", c->ProxyUsername);
|
|
PackAddStr(p, "ProxyPassword", c->ProxyPassword);
|
|
PackAddStr(p, "CustomHttpHeader", c->CustomHttpHeader);
|
|
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);
|
|
PackAddBool(p, "UseEncrypt", c->UseEncrypt);
|
|
PackAddBool(p, "UseCompress", c->UseCompress);
|
|
PackAddBool(p, "HalfConnection", c->HalfConnection);
|
|
PackAddBool(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, "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;
|
|
|
|
case CLIENT_AUTHTYPE_OPENSSLENGINE:
|
|
b = PackGetBuf(p, "ClientX");
|
|
if (b != NULL)
|
|
{
|
|
c->ClientX = BufToX(b, false);
|
|
FreeBuf(b);
|
|
}
|
|
PackGetStr(p, "OpensslEnginePrivateKeyName", c->OpensslEnginePrivateKeyName, sizeof(c->OpensslEnginePrivateKeyName));
|
|
PackGetStr(p, "OpensslEngineName", c->OpensslEngineName, sizeof(c->OpensslEngineName));
|
|
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;
|
|
|
|
case CLIENT_AUTHTYPE_OPENSSLENGINE:
|
|
b = XToBuf(c->ClientX, false);
|
|
if (b != NULL)
|
|
{
|
|
PackAddBuf(p, "ClientX", b);
|
|
FreeBuf(b);
|
|
}
|
|
PackAddStr(p, "OpensslEnginePrivateKeyName", c->OpensslEnginePrivateKeyName);
|
|
PackAddStr(p, "OpensslEngineName", c->OpensslEngineName);
|
|
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;
|
|
c->RetryOnServerCert = PackGetInt(p, "RetryOnServerCert") ? true : false;
|
|
c->AddDefaultCA = PackGetInt(p, "AddDefaultCA") ? 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);
|
|
PackAddInt(p, "RetryOnServerCert", c->RetryOnServerCert);
|
|
PackAddInt(p, "AddDefaultCA", c->AddDefaultCA);
|
|
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);
|
|
|
|
PackSetCurrentJsonGroupName(p, "AccountList");
|
|
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);
|
|
PackAddTime64Ex(p, "CreateDateTime", item->CreateDateTime, i, e->NumItem);
|
|
PackAddTime64Ex(p, "UpdateDateTime", item->UpdateDateTime, i, e->NumItem);
|
|
PackAddTime64Ex(p, "LastConnectDateTime", item->LastConnectDateTime, i, e->NumItem);
|
|
}
|
|
PackSetCurrentJsonGroupName(p, NULL);
|
|
}
|
|
|
|
// 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;
|
|
c->RetryOnServerCert = PackGetInt(p, "RetryOnServerCert") ? true : false;
|
|
c->AddDefaultCA = PackGetInt(p, "AddDefaultCA") ? 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);
|
|
PackAddInt(p, "RetryOnServerCert", c->RetryOnServerCert);
|
|
PackAddInt(p, "AddDefaultCA", c->AddDefaultCA);
|
|
|
|
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);
|
|
|
|
PackAddTime64(p, "CreateDateTime", c->CreateDateTime);
|
|
PackAddTime64(p, "UpdateDateTime", c->UpdateDateTime);
|
|
PackAddTime64(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->NumConnectionsEstablished = PackGetInt(p, "NumConnectionsEstablished");
|
|
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");
|
|
/* !!! Do not correct the spelling to keep the backward protocol compatibility !!! */
|
|
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);
|
|
|
|
PackAddBool(p, "Active", c->Active);
|
|
PackAddBool(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, "NumConnectionsEstablished", c->NumConnectionsEstablished);
|
|
PackAddBool(p, "HalfConnection", c->HalfConnection);
|
|
PackAddBool(p, "QoS", c->QoS);
|
|
PackAddInt(p, "MaxTcpConnections", c->MaxTcpConnections);
|
|
PackAddInt(p, "NumTcpConnections", c->NumTcpConnections);
|
|
PackAddInt(p, "NumTcpConnectionsUpload", c->NumTcpConnectionsUpload);
|
|
PackAddInt(p, "NumTcpConnectionsDownload", c->NumTcpConnectionsDownload);
|
|
PackAddBool(p, "UseEncrypt", c->UseEncrypt);
|
|
PackAddBool(p, "UseCompress", c->UseCompress);
|
|
PackAddBool(p, "IsRUDPSession", c->IsRUDPSession);
|
|
PackAddStr(p, "UnderlayProtocol", c->UnderlayProtocol);
|
|
PackAddBool(p, "IsUdpAccelerationEnabled", c->IsUdpAccelerationEnabled);
|
|
PackAddBool(p, "IsUsingUdpAcceleration", c->IsUsingUdpAcceleration);
|
|
|
|
PackAddBool(p, "IsBridgeMode", c->IsBridgeMode);
|
|
PackAddBool(p, "IsMonitorMode", c->IsMonitorMode);
|
|
|
|
PackAddTime64(p, "StartTime", c->StartTime);
|
|
PackAddTime64(p, "FirstConnectionEstablisiedTime", c->FirstConnectionEstablisiedTime);
|
|
PackAddTime64(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);
|
|
}
|
|
}
|
|
|
|
// Notification main
|
|
void CiNotifyMain(CLIENT *c, SOCK *s)
|
|
{
|
|
CANCEL *cancel;
|
|
// Validate arguments
|
|
if (c == NULL || s == NULL)
|
|
{
|
|
return;
|
|
}
|
|
|
|
// Register a Cancel
|
|
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);
|
|
(void)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 && IsLocalHostIP(&s->RemoteIP))
|
|
{
|
|
// 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 (IsLocalHostIP(&s->RemoteIP) == false)
|
|
{
|
|
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];
|
|
UINT rpc_mode = 0;
|
|
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;
|
|
}
|
|
}
|
|
|
|
if (reg_port != 0)
|
|
{
|
|
s = Connect(server_name, reg_port);
|
|
|
|
if (s != NULL)
|
|
{
|
|
goto L_TRY;
|
|
}
|
|
}
|
|
|
|
#endif // OS_WIN32
|
|
|
|
port_start = CLIENT_CONFIG_PORT - 1;
|
|
|
|
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);
|
|
|
|
Sha0(hash_password, password, StrLen(password));
|
|
|
|
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));
|
|
rpc->Param = ret;
|
|
|
|
if (ret != NULL)
|
|
{
|
|
RPC_CLIENT_VERSION t;
|
|
|
|
ret->Rpc = rpc;
|
|
Zero(&t, sizeof(t));
|
|
CcGetClientVersion(ret, &t);
|
|
ret->OsType = t.OsType;
|
|
ret->Unix = OS_IS_UNIX(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);
|
|
// Protocol details
|
|
StrCpy(st->ProtocolDetails, sizeof(st->ProtocolDetails), s->ProtocolDetails);
|
|
Trim(st->ProtocolDetails);
|
|
// UDP acceleration function
|
|
if (s->IpcSessionShared != NULL && IsEmptyStr(s->IpcSessionShared->ProtocolDetails) == false)
|
|
{
|
|
char tmp[sizeof(s->IpcSessionShared->ProtocolDetails)];
|
|
StrCpy(tmp, sizeof(tmp), s->IpcSessionShared->ProtocolDetails);
|
|
Trim(tmp);
|
|
StrCat(st->ProtocolDetails, sizeof(st->ProtocolDetails), " ");
|
|
StrCat(st->ProtocolDetails, sizeof(st->ProtocolDetails), tmp);
|
|
|
|
st->IsUdpAccelerationEnabled = s->IpcSessionShared->EnableUdpAccel;
|
|
st->IsUsingUdpAcceleration = s->IpcSessionShared->UsingUdpAccel;
|
|
}
|
|
else
|
|
{
|
|
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
|
|
/* !!! Do not correct the spelling to keep the backward protocol compatibility !!! */
|
|
st->FirstConnectionEstablisiedTime = TickToTime(s->FirstConnectionEstablisiedTime);
|
|
// Number of connections have been established so far
|
|
st->NumConnectionsEstablished = s->NumConnectionsEstablished;
|
|
}
|
|
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;
|
|
}
|
|
}
|
|
|
|
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, MIN(sizeof(sign->Signature),sizeof(batch[1].OutputSign)));
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
// Create a new virtual LAN card named "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 if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_OPENSSLENGINE)
|
|
{
|
|
/* r->ClientAuth->ClientK = OpensslEngineToK("asdf"); */
|
|
r->ClientAuth->SecureSignProc = NULL;
|
|
}
|
|
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;
|
|
}
|
|
|
|
// Put all unused TUN interfaces down
|
|
// Requires account and VLan lists of the CLIENT argument to be already locked
|
|
bool CtVLansDown(CLIENT *c)
|
|
{
|
|
#ifndef UNIX_LINUX
|
|
return true;
|
|
#else
|
|
int i;
|
|
LIST *tmpVLanList;
|
|
UNIX_VLAN t, *r;
|
|
bool result = true;
|
|
|
|
if (c == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
tmpVLanList = CloneList(c->UnixVLanList);
|
|
if (tmpVLanList == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
// Remove from tmpVLanList all VLans corresponding to active sessions
|
|
for (i = 0; i < LIST_NUM(c->AccountList); ++i)
|
|
{
|
|
ACCOUNT *a = LIST_DATA(c->AccountList, i);
|
|
if (a->ClientSession == NULL)
|
|
{
|
|
continue;
|
|
}
|
|
|
|
Zero(&t, sizeof(t));
|
|
StrCpy(t.Name, sizeof(t.Name), a->ClientOption->DeviceName);
|
|
r = Search(tmpVLanList, &t);
|
|
Delete(tmpVLanList, r);
|
|
}
|
|
|
|
// Set down every VLan in tmpVLanList
|
|
for (i = 0; i < LIST_NUM(tmpVLanList) && result; ++i)
|
|
{
|
|
r = LIST_DATA(tmpVLanList, i);
|
|
result = UnixVLanSetState(r->Name, false);
|
|
// [MP:] Should we report *critical* error on failure?
|
|
}
|
|
|
|
ReleaseList(tmpVLanList);
|
|
return result;
|
|
#endif
|
|
}
|
|
|
|
// Put all TUN interfaces up
|
|
// Requires VLan list of the CLIENT argument to be already locked
|
|
bool CtVLansUp(CLIENT *c)
|
|
{
|
|
#ifndef UNIX_LINUX
|
|
return true;
|
|
#else
|
|
int i;
|
|
UNIX_VLAN *r;
|
|
|
|
if (c == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
for (i = 0; i < LIST_NUM(c->UnixVLanList); ++i)
|
|
{
|
|
r = LIST_DATA(c->UnixVLanList, i);
|
|
UnixVLanSetState(r->Name, true);
|
|
}
|
|
|
|
return true;
|
|
#endif
|
|
}
|
|
|
|
// 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 account name (restore the correct case)
|
|
UniStrCpy(a->AccountName, sizeof(a->AccountName), r->ClientOption->AccountName);
|
|
|
|
// 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->RetryOnServerCert = r->RetryOnServerCert;
|
|
a->AddDefaultCA = r->AddDefaultCA;
|
|
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);
|
|
|
|
// Apply TAP state
|
|
LockList(c->AccountList);
|
|
LockList(c->UnixVLanList);
|
|
|
|
CtVLansDown(c);
|
|
|
|
UnlockList(c->UnixVLanList);
|
|
UnlockList(c->AccountList);
|
|
|
|
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);
|
|
// Append hint string to hostname
|
|
if (IsEmptyStr(a->ClientOption->HintStr) == false)
|
|
{
|
|
StrCat(item->ServerName, sizeof(item->ServerName), "/");
|
|
StrCat(item->ServerName, sizeof(item->ServerName), a->ClientOption->HintStr);
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
}
|
|
|
|
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;
|
|
ret->RetryOnServerCert = a->RetryOnServerCert;
|
|
ret->AddDefaultCA = a->AddDefaultCA;
|
|
|
|
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;
|
|
}
|
|
}
|
|
|
|
// 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;
|
|
new_account->RetryOnServerCert = a->RetryOnServerCert;
|
|
new_account->AddDefaultCA = a->AddDefaultCA;
|
|
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
|
|
|
|
// 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)
|
|
{
|
|
// 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_VERSION_MAJOR;
|
|
ver->Minor = CEDAR_VERSION_MINOR;
|
|
ver->Build = CEDAR_VERSION_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
|
|
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);
|
|
|
|
// 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;
|
|
}
|
|
|
|
// Perform the installation
|
|
char tmp[MAX_SIZE];
|
|
Format(tmp, sizeof(tmp), "upgradevlan %s", create->DeviceName);
|
|
|
|
if (CncExecDriverInstaller(tmp) == false)
|
|
{
|
|
// Installation Failed
|
|
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
|
|
CiNotify(c);
|
|
CiSendGlobalPulse(c);
|
|
return false;
|
|
}
|
|
|
|
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;
|
|
|
|
// 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 TUN
|
|
if (UnixVLanCreate(r->Name, r->MacAddress, false) == 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
|
|
// 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 = MAX_DEVICE_NAME_LEN;
|
|
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;
|
|
}
|
|
|
|
// Perform the installation (Windows Vista)
|
|
char tmp[MAX_SIZE];
|
|
Format(tmp, sizeof(tmp), "instvlan %s", create->DeviceName);
|
|
|
|
if (CncExecDriverInstaller(tmp) == false)
|
|
{
|
|
CiSetError(c, ERR_VLAN_INSTALL_ERROR);
|
|
CiNotify(c);
|
|
CiSendGlobalPulse(c);
|
|
return false;
|
|
}
|
|
|
|
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);
|
|
|
|
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;
|
|
}
|
|
|
|
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;
|
|
}
|
|
|
|
Sha0(hash, "", 0);
|
|
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;
|
|
}
|
|
|
|
str = pass->Password;
|
|
|
|
if (StrCmp(str, "********") != 0)
|
|
{
|
|
// Hash the password
|
|
Sha0(c->EncryptedPassword, str, StrLen(str));
|
|
}
|
|
|
|
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
|
|
{
|
|
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
|
|
Sha0(c->EncryptedPassword, "", 0);
|
|
// Initialize the client configuration
|
|
// Disable remote management
|
|
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;
|
|
|
|
case CLIENT_AUTHTYPE_OPENSSLENGINE:
|
|
b = CfgGetBuf(f, "ClientCert");
|
|
if (b != NULL)
|
|
{
|
|
a->ClientX = BufToX(b, false);
|
|
}
|
|
FreeBuf(b);
|
|
if (CfgGetStr(f, "OpensslEnginePrivateKeyName", a->OpensslEnginePrivateKeyName, sizeof(a->OpensslEnginePrivateKeyName)))
|
|
{
|
|
a->ClientK = OpensslEngineToK(a->OpensslEnginePrivateKeyName, a->OpensslEngineName);
|
|
}
|
|
CfgGetStr(f, "OpensslEngineName", a->OpensslEngineName, sizeof(a->OpensslEngineName));
|
|
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));
|
|
// Extract hint string from hostname
|
|
UINT i = SearchStrEx(o->Hostname, "/", 0, false);
|
|
if (i != INFINITE)
|
|
{
|
|
StrCpy(o->HintStr, sizeof(o->HintStr), o->Hostname + i + 1);
|
|
o->Hostname[i] = 0;
|
|
}
|
|
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);
|
|
CfgGetStr(f, "CustomHttpHeader", o->CustomHttpHeader, sizeof(o->CustomHttpHeader));
|
|
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->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->RetryOnServerCert = CfgGetBool(f, "RetryOnServerCert");
|
|
a->AddDefaultCA = CfgGetBool(f, "AddDefaultCA");
|
|
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, false);
|
|
#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);
|
|
}
|
|
|
|
CfgGetStr(proxy, "CustomHttpHeader", t.CustomHttpHeader, sizeof(t.CustomHttpHeader));
|
|
|
|
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) == 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)
|
|
{
|
|
Sha0(c->EncryptedPassword, "", 0);
|
|
}
|
|
|
|
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;
|
|
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;
|
|
|
|
case CLIENT_AUTHTYPE_OPENSSLENGINE:
|
|
if (a->ClientX != NULL) {
|
|
b = XToBuf(a->ClientX, false);
|
|
CfgAddByte(f, "ClientCert", b->Buf, b->Size);
|
|
FreeBuf(b);
|
|
}
|
|
CfgAddStr(f, "OpensslEnginePrivateKeyName", a->OpensslEnginePrivateKeyName);
|
|
CfgAddStr(f, "OpensslEngineName", a->OpensslEngineName);
|
|
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);
|
|
// Append hint string to hostname
|
|
if (IsEmptyStr(o->HintStr))
|
|
{
|
|
// No hint
|
|
CfgAddStr(f, "Hostname", o->Hostname);
|
|
}
|
|
else
|
|
{
|
|
char hostname[MAX_SIZE];
|
|
StrCpy(hostname, sizeof(hostname), o->Hostname);
|
|
StrCat(hostname, sizeof(hostname), "/");
|
|
StrCat(hostname, sizeof(hostname), o->HintStr);
|
|
CfgAddStr(f, "Hostname", 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);
|
|
CfgAddStr(f, "CustomHttpHeader", o->CustomHttpHeader);
|
|
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, "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)); // NOTE by Daiyuu Nobori 2018-09-28: This is not a bug! Do not try to fix it!!
|
|
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)); // NOTE by Daiyuu Nobori 2018-09-28: This is not a bug! Do not try to fix it!!
|
|
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);
|
|
|
|
// Retry on invalid server certificate flag
|
|
CfgAddBool(f, "RetryOnServerCert", a->RetryOnServerCert);
|
|
|
|
// Add default SSL trust store
|
|
CfgAddBool(f, "AddDefaultCA", a->AddDefaultCA);
|
|
|
|
// 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);
|
|
}
|
|
|
|
CfgAddStr(proxy, "CustomHttpHeader", t->CustomHttpHeader);
|
|
}
|
|
|
|
// 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));
|
|
}
|
|
}
|
|
}
|
|
|
|
// 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);
|
|
|
|
Sha0(c->EncryptedPassword, "", 0);
|
|
|
|
#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();
|
|
|
|
CiChangeAllVLanMacAddressIfMachineChanged(c);
|
|
|
|
CiChangeAllVLanMacAddressIfCleared(c);
|
|
|
|
// Initialize the internal VPN server
|
|
CiApplyInnerVPNServerConfig(c);
|
|
|
|
return c;
|
|
}
|
|
|
|
// 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);
|
|
|
|
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);
|
|
}
|
|
|
|
// 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;
|
|
}
|
|
|
|
#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;
|
|
}
|
|
|
|
// 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
|
|
}
|
|
|
|
|