1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Cedar Communication Module
3 // © 2020 Nokia
4 
5 // Client.c
6 // Client Manager
7 
8 #include "Client.h"
9 
10 #include "Account.h"
11 #include "Admin.h"
12 #include "Cedar.h"
13 #include "CM.h"
14 #include "Connection.h"
15 #include "IPC.h"
16 #include "Listener.h"
17 #include "Logging.h"
18 #include "Protocol.h"
19 #include "Remote.h"
20 #include "Virtual.h"
21 #include "VLanUnix.h"
22 #include "VLanWin32.h"
23 #include "Win32Com.h"
24 #include "WinUi.h"
25 
26 #include "Mayaqua/Cfg.h"
27 #include "Mayaqua/Encrypt.h"
28 #include "Mayaqua/FileIO.h"
29 #include "Mayaqua/Internat.h"
30 #include "Mayaqua/Kernel.h"
31 #include "Mayaqua/MayaType.h"
32 #include "Mayaqua/Memory.h"
33 #include "Mayaqua/Microsoft.h"
34 #include "Mayaqua/Network.h"
35 #include "Mayaqua/Object.h"
36 #include "Mayaqua/OS.h"
37 #include "Mayaqua/Pack.h"
38 #include "Mayaqua/Secure.h"
39 #include "Mayaqua/Str.h"
40 #include "Mayaqua/Table.h"
41 #include "Mayaqua/Tick64.h"
42 #include "Mayaqua/Win32.h"
43 
44 #include <stdlib.h>
45 
46 static CLIENT *client = NULL;
47 static LISTENER *cn_listener = NULL;
48 static LOCK *cn_listener_lock = NULL;
49 static UINT64 cn_next_allow = 0;
50 static LOCK *ci_active_sessions_lock = NULL;
51 static UINT ci_num_active_sessions = 0;
52 
53 
54 // In Windows 8 or later, change unreasonable setting of WCM to ensure normal VPN communication
CiDisableWcmNetworkMinimize(CLIENT * c)55 void CiDisableWcmNetworkMinimize(CLIENT *c)
56 {
57 #ifdef	OS_WIN32
58 	// Validate arguments
59 	if (c == NULL)
60 	{
61 		return;
62 	}
63 
64 	if (c->Config.NoChangeWcmNetworkSettingOnWindows8)
65 	{
66 		return;
67 	}
68 
69 	MsDisableWcmNetworkMinimize();
70 #endif	// OS_WIN32
71 }
72 
73 // Compare RPC_CLIENT_ENUM_ACCOUNT_ITEM items by last connected date (Reverse)
CiCompareClientAccountEnumItemByLastConnectDateTime(void * p1,void * p2)74 int CiCompareClientAccountEnumItemByLastConnectDateTime(void *p1, void *p2)
75 {
76 	RPC_CLIENT_ENUM_ACCOUNT_ITEM *a1, *a2;
77 	if (p1 == NULL || p2 == NULL)
78 	{
79 		return 0;
80 	}
81 	a1 = *(RPC_CLIENT_ENUM_ACCOUNT_ITEM **)p1;
82 	a2 = *(RPC_CLIENT_ENUM_ACCOUNT_ITEM **)p2;
83 	if (a1 == NULL || a2 == NULL)
84 	{
85 		return 0;
86 	}
87 	if (a1->LastConnectDateTime > a2->LastConnectDateTime)
88 	{
89 		return -1;
90 	}
91 	else if (a1->LastConnectDateTime < a2->LastConnectDateTime)
92 	{
93 		return 1;
94 	}
95 
96 	return 0;
97 }
98 
99 // If machine changed, reshuffle MAC address for all virtual NIC
CiChangeAllVLanMacAddressIfMachineChanged(CLIENT * c)100 void CiChangeAllVLanMacAddressIfMachineChanged(CLIENT *c)
101 {
102 	UCHAR current_hash_new[SHA1_SIZE];
103 	UCHAR current_hash[SHA1_SIZE];
104 	UCHAR current_hash_old[SHA1_SIZE];
105 	UCHAR saved_hash[SHA1_SIZE];
106 	// Validate arguments
107 	if (c == NULL)
108 	{
109 		return;
110 	}
111 
112 #ifdef OS_WIN32
113 	if (MsIsAdmin() == false)
114 	{
115 		return;
116 	}
117 #endif
118 
119 	CiGetCurrentMachineHashNew(current_hash_new);
120 	CiGetCurrentMachineHash(current_hash);
121 	CiGetCurrentMachineHashOld(current_hash_old);
122 
123 	if (CiReadLastMachineHash(saved_hash) == false)
124 	{
125 		CiWriteLastMachineHash(current_hash_new);
126 		return;
127 	}
128 
129 	if (Cmp(saved_hash, current_hash_old, SHA1_SIZE) == 0)
130 	{
131 		CiWriteLastMachineHash(current_hash_new);
132 		return;
133 	}
134 
135 	if (Cmp(saved_hash, current_hash, SHA1_SIZE) == 0)
136 	{
137 		CiWriteLastMachineHash(current_hash_new);
138 		return;
139 	}
140 
141 	if (Cmp(saved_hash, current_hash_new, SHA1_SIZE) == 0)
142 	{
143 		return;
144 	}
145 
146 	if (CiWriteLastMachineHash(current_hash_new) == false)
147 	{
148 		return;
149 	}
150 
151 	CiChangeAllVLanMacAddress(c);
152 }
153 
154 // Get current machine hash (Old)
CiGetCurrentMachineHashOld(void * data)155 void CiGetCurrentMachineHashOld(void *data)
156 {
157 	char name[MAX_PATH];
158 	char *product_id = NULL;
159 	// Validate arguments
160 	if (data == NULL)
161 	{
162 		return;
163 	}
164 
165 #ifdef	OS_WIN32
166 	// Product ID
167 	product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion", "ProductId");
168 	if (product_id == NULL)
169 	{
170 		product_id = MsRegReadStr(REG_LOCAL_MACHINE, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion", "ProductId");
171 	}
172 
173 	StrCpy(name, sizeof(name), product_id);
174 
175 	Free(product_id);
176 
177 #else	// OS_WIN32
178 	GetMachineName(name, sizeof(name));
179 #endif	// OS_WIN32
180 
181 	Trim(name);
182 	StrUpper(name);
183 
184 	Sha0(data, name, StrLen(name));
185 }
186 
187 // Get current machine hash
CiGetCurrentMachineHash(void * data)188 void CiGetCurrentMachineHash(void *data)
189 {
190 	char name[MAX_PATH];
191 	char *product_id = NULL;
192 	// Validate arguments
193 	if (data == NULL)
194 	{
195 		return;
196 	}
197 
198 	GetMachineName(name, sizeof(name));
199 
200 	Trim(name);
201 	StrUpper(name);
202 
203 	Sha0(data, name, StrLen(name));
204 }
205 
206 // Get current machine hash (without using domain name)
CiGetCurrentMachineHashNew(void * data)207 void CiGetCurrentMachineHashNew(void *data)
208 {
209 	char name[MAX_PATH];
210 	char *p;
211 
212 	// Validate arguments
213 	if (data == NULL)
214 	{
215 		return;
216 	}
217 
218 	GetMachineName(name, sizeof(name));
219 
220 	// Ignore after first period(.)
221 	for(p=name; *p; p++)
222 		if(*p == '.')
223 			*p = 0;
224 
225 	Trim(name);
226 	StrUpper(name);
227 
228 	Sha0(data, name, StrLen(name));
229 }
230 
231 
232 // Write machine hash
CiWriteLastMachineHash(void * data)233 bool CiWriteLastMachineHash(void *data)
234 {
235 	// Validate arguments
236 	if (data == NULL)
237 	{
238 		return false;
239 	}
240 
241 #ifdef OS_WIN32
242 	if (MsRegWriteBinEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "LastMachineHash", data, SHA1_SIZE, true) == false)
243 	{
244 		return false;
245 	}
246 
247 	return true;
248 #else	// OS_WIN32
249 	return false;
250 #endif	// OS_WIN32
251 }
252 
253 // Get previous machine hash
CiReadLastMachineHash(void * data)254 bool CiReadLastMachineHash(void *data)
255 {
256 	BUF *b = NULL;
257 	// Validate arguments
258 	if (data == NULL)
259 	{
260 		return false;
261 	}
262 
263 #ifdef OS_WIN32
264 	b = MsRegReadBinEx(REG_LOCAL_MACHINE, MS_REG_TCP_SETTING_KEY, "LastMachineHash", true);
265 	if (b == NULL)
266 	{
267 		return false;
268 	}
269 	if (b->Size == SHA1_SIZE)
270 	{
271 		Copy(data, b->Buf, b->Size);
272 		FreeBuf(b);
273 
274 		return true;
275 	}
276 
277 	FreeBuf(b);
278 	return false;
279 #else	// OS_WIN32
280 	return false;
281 #endif	// OS_WIN32
282 }
283 
284 // If the MAC address of each virtual LAN card has been eliminated, set it to random numbers
285 // (measures for Windows 8 -> 8.1 upgrade problem)
CiChangeAllVLanMacAddressIfCleared(CLIENT * c)286 void CiChangeAllVLanMacAddressIfCleared(CLIENT *c)
287 {
288 #ifdef	OS_WIN32
289 	RPC_CLIENT_ENUM_VLAN t;
290 	// Validate arguments
291 	if (c == NULL)
292 	{
293 		return;
294 	}
295 
296 	if (MsIsInfCatalogRequired() == false)
297 	{
298 		// Not required for other than Windows 8
299 		return;
300 	}
301 
302 	Zero(&t, sizeof(t));
303 	if (CtEnumVLan(c, &t))
304 	{
305 		UINT i;
306 
307 		for (i = 0;i < t.NumItem;i++)
308 		{
309 			RPC_CLIENT_ENUM_VLAN_ITEM *e = t.Items[i];
310 			UCHAR mac[6];
311 
312 			if (StrToMac(mac, e->MacAddress))
313 			{
314 				if (mac[0] == 0x00 &&
315 					mac[1] == 0x00 &&
316 					mac[2] == 0x01 &&
317 					mac[3] == 0x00 &&
318 					mac[4] == 0x00 &&
319 					mac[5] == 0x01)
320 				{
321 					char *name = e->DeviceName;
322 					RPC_CLIENT_SET_VLAN s;
323 					UCHAR mac[6];
324 
325 					GenMacAddress(mac);
326 
327 					Zero(&s, sizeof(s));
328 					StrCpy(s.DeviceName, sizeof(s.DeviceName), name);
329 
330 					MacToStr(s.MacAddress, sizeof(s.MacAddress), mac);
331 
332 					CtSetVLan(c, &s);
333 				}
334 			}
335 		}
336 
337 		CiFreeClientEnumVLan(&t);
338 	}
339 #endif	// OS_WIN32
340 }
341 
342 // Set the MAC address of all virtual LAN cards to random number
CiChangeAllVLanMacAddress(CLIENT * c)343 void CiChangeAllVLanMacAddress(CLIENT *c)
344 {
345 	RPC_CLIENT_ENUM_VLAN t;
346 	// Validate arguments
347 	if (c == NULL)
348 	{
349 		return;
350 	}
351 
352 	Zero(&t, sizeof(t));
353 	if (CtEnumVLan(c, &t))
354 	{
355 		UINT i;
356 
357 		for (i = 0;i < t.NumItem;i++)
358 		{
359 			RPC_CLIENT_ENUM_VLAN_ITEM *e = t.Items[i];
360 			UCHAR mac[6];
361 
362 			if (StrToMac(mac, e->MacAddress) && ((mac[0] == 0x00 && mac[1] == 0xAC) || (mac[0] == 0x5E)))
363 			{
364 				char *name = e->DeviceName;
365 				RPC_CLIENT_SET_VLAN s;
366 				UCHAR mac[6];
367 
368 				GenMacAddress(mac);
369 
370 				Zero(&s, sizeof(s));
371 				StrCpy(s.DeviceName, sizeof(s.DeviceName), name);
372 
373 				MacToStr(s.MacAddress, sizeof(s.MacAddress), mac);
374 
375 				CtSetVLan(c, &s);
376 			}
377 		}
378 
379 		CiFreeClientEnumVLan(&t);
380 	}
381 }
382 
383 // Wait for preparation of notification service to complete
CnWaitForCnServiceReady()384 void CnWaitForCnServiceReady()
385 {
386 	UINT64 start_time = Tick64();
387 
388 	while ((start_time + (UINT64)CLIENT_WAIT_CN_READY_TIMEOUT) >= Tick64())
389 	{
390 		if (CnIsCnServiceReady())
391 		{
392 			break;
393 		}
394 
395 		SleepThread(100);
396 	}
397 }
398 
399 // Check whether preparation of notification service completed
CnIsCnServiceReady()400 bool CnIsCnServiceReady()
401 {
402 	SOCK *s;
403 	// Confirm running the notification service
404 	if (CnCheckAlreadyExists(false) == false)
405 	{
406 		// Not running
407 		return false;
408 	}
409 
410 	// Try to connect to the TCP port
411 	s = ConnectEx("localhost", CLIENT_NOTIFY_PORT, 500);
412 	if (s == NULL)
413 	{
414 		// The TCP port is not opened
415 		return false;
416 	}
417 
418 	Disconnect(s);
419 	ReleaseSock(s);
420 
421 	// Running
422 	return true;
423 }
424 
425 // Check whether the notification service is already running
CnCheckAlreadyExists(bool lock)426 bool CnCheckAlreadyExists(bool lock)
427 {
428 #ifdef	OS_WIN32
429 	return Win32CnCheckAlreadyExists(lock);
430 #else
431 	return false;
432 #endif
433 }
434 
435 typedef struct CNC_STATUS_PRINTER_WINDOW_PARAM
436 {
437 	THREAD *Thread;
438 	SESSION *Session;
439 	SOCK *Sock;
440 } CNC_STATUS_PRINTER_WINDOW_PARAM;
441 
442 typedef struct CNC_CONNECT_ERROR_DLG_THREAD_PARAM
443 {
444 	SESSION *Session;
445 	SOCK *Sock;
446 	bool HaltThread;
447 	EVENT *Event;
448 } CNC_CONNECT_ERROR_DLG_THREAD_PARAM;
449 
450 // Thread to stop forcibly the Certificate check dialog client
CncCheckCertHaltThread(THREAD * thread,void * param)451 void CncCheckCertHaltThread(THREAD *thread, void *param)
452 {
453 	CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;
454 	// Validate arguments
455 	if (thread == NULL || param == NULL)
456 	{
457 		return;
458 	}
459 
460 	while (true)
461 	{
462 		if (dp->Session->Halt || dp->HaltThread)
463 		{
464 			break;
465 		}
466 
467 		Wait(dp->Event, 100);
468 	}
469 
470 	Disconnect(dp->Sock);
471 }
472 
473 // Show the certification check dialog
CncCheckCert(SESSION * session,UI_CHECKCERT * dlg)474 void CncCheckCert(SESSION *session, UI_CHECKCERT *dlg)
475 {
476 	SOCK *s;
477 	PACK *p;
478 	CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
479 	THREAD *t;
480 	// Validate arguments
481 	if (dlg == NULL || session == NULL)
482 	{
483 		return;
484 	}
485 
486 	s = CncConnect();
487 	if (s == NULL)
488 	{
489 		return;
490 	}
491 
492 	p = NewPack();
493 	PackAddStr(p, "function", "check_cert");
494 	PackAddUniStr(p, "AccountName", dlg->AccountName);
495 	PackAddStr(p, "ServerName", dlg->ServerName);
496 	PackAddX(p, "x", dlg->x);
497 	PackAddX(p, "parent_x", dlg->parent_x);
498 	PackAddX(p, "old_x", dlg->old_x);
499 	PackAddBool(p, "DiffWarning", dlg->DiffWarning);
500 	PackAddBool(p, "Ok", dlg->Ok);
501 	PackAddBool(p, "SaveServerCert", dlg->SaveServerCert);
502 
503 	SendPack(s, p);
504 	FreePack(p);
505 
506 	dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
507 	dp->Sock = s;
508 	dp->Event = NewEvent();
509 	dp->Session = session;
510 
511 	t = NewThread(CncCheckCertHaltThread, dp);
512 
513 	p = RecvPack(s);
514 	if (p != NULL)
515 	{
516 		dlg->Ok = PackGetBool(p, "Ok");
517 		dlg->DiffWarning = PackGetBool(p, "DiffWarning");
518 		dlg->SaveServerCert = PackGetBool(p, "SaveServerCert");
519 
520 		FreePack(p);
521 	}
522 
523 	dp->HaltThread = true;
524 	Set(dp->Event);
525 
526 	WaitThread(t, INFINITE);
527 
528 	ReleaseEvent(dp->Event);
529 	Free(dp);
530 	ReleaseThread(t);
531 
532 	Disconnect(s);
533 	ReleaseSock(s);
534 }
535 
536 // Smart card signature dialog
CncSecureSignDlg(SECURE_SIGN * sign)537 bool CncSecureSignDlg(SECURE_SIGN *sign)
538 {
539 	SOCK *s;
540 	PACK *p;
541 	bool ret = false;
542 	// Validate arguments
543 	if (sign == NULL)
544 	{
545 		return false;
546 	}
547 
548 	s = CncConnect();
549 	if (s == NULL)
550 	{
551 		return false;
552 	}
553 
554 	p = NewPack();
555 	PackAddStr(p, "function", "secure_sign");
556 	OutRpcSecureSign(p, sign);
557 
558 	SendPack(s, p);
559 	FreePack(p);
560 
561 	p = RecvPack(s);
562 	if (p != NULL)
563 	{
564 		ret = PackGetBool(p, "ret");
565 
566 		if (ret)
567 		{
568 			FreeRpcSecureSign(sign);
569 
570 			Zero(sign, sizeof(SECURE_SIGN));
571 			InRpcSecureSign(sign, p);
572 		}
573 
574 		FreePack(p);
575 	}
576 
577 	Disconnect(s);
578 	ReleaseSock(s);
579 
580 	return ret;
581 }
582 
583 // Show the NIC information dialog
CncNicInfo(UI_NICINFO * info)584 SOCK *CncNicInfo(UI_NICINFO *info)
585 {
586 	SOCK *s;
587 	PACK *p;
588 	// Validate arguments
589 	if (info == NULL)
590 	{
591 		return NULL;
592 	}
593 
594 	s = CncConnectEx(200);
595 	if (s == NULL)
596 	{
597 		return NULL;
598 	}
599 
600 	p = NewPack();
601 	PackAddStr(p, "function", "nicinfo");
602 	PackAddStr(p, "NicName", info->NicName);
603 	PackAddUniStr(p, "AccountName", info->AccountName);
604 
605 	SendPack(s, p);
606 	FreePack(p);
607 
608 	return s;
609 }
610 
611 // Close the NIC information dialog
CncNicInfoFree(SOCK * s)612 void CncNicInfoFree(SOCK *s)
613 {
614 	// Validate arguments
615 	if (s == NULL)
616 	{
617 		return;
618 	}
619 
620 	Disconnect(s);
621 	ReleaseSock(s);
622 }
623 
624 // Show the message dialog
CncMsgDlg(UI_MSG_DLG * dlg)625 SOCK *CncMsgDlg(UI_MSG_DLG *dlg)
626 {
627 	SOCK *s;
628 	PACK *p;
629 	char *utf;
630 	// Validate arguments
631 	if (dlg == NULL)
632 	{
633 		return NULL;
634 	}
635 
636 	s = CncConnectEx(200);
637 	if (s == NULL)
638 	{
639 		return NULL;
640 	}
641 
642 	p = NewPack();
643 	PackAddStr(p, "function", "msg_dialog");
644 	PackAddStr(p, "ServerName", dlg->ServerName);
645 	PackAddStr(p, "HubName", dlg->HubName);
646 	utf = CopyUniToUtf(dlg->Msg);
647 	PackAddData(p, "Msg", utf, StrLen(utf));
648 	Free(utf);
649 
650 	SendPack(s, p);
651 	FreePack(p);
652 
653 	return s;
654 }
655 
656 // Close the message dialog
CndMsgDlgFree(SOCK * s)657 void CndMsgDlgFree(SOCK *s)
658 {
659 	// Validate arguments
660 	if (s == NULL)
661 	{
662 		return;
663 	}
664 
665 	Disconnect(s);
666 	ReleaseSock(s);
667 }
668 
669 // Show the password input dialog
CncPasswordDlg(SESSION * session,UI_PASSWORD_DLG * dlg)670 bool CncPasswordDlg(SESSION *session, UI_PASSWORD_DLG *dlg)
671 {
672 	SOCK *s;
673 	PACK *p;
674 	CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
675 	THREAD *t;
676 	bool ret = false;
677 	// Validate arguments
678 	if (dlg == NULL || session == NULL)
679 	{
680 		return false;
681 	}
682 
683 	s = CncConnect();
684 	if (s == NULL)
685 	{
686 		Wait(session->HaltEvent, session->RetryInterval);
687 		return true;
688 	}
689 
690 	p = NewPack();
691 	PackAddStr(p, "function", "password_dialog");
692 	PackAddInt(p, "Type", dlg->Type);
693 	PackAddStr(p, "Username", dlg->Username);
694 	PackAddStr(p, "Password", dlg->Password);
695 	PackAddStr(p, "ServerName", dlg->ServerName);
696 	PackAddInt(p, "RetryIntervalSec", dlg->RetryIntervalSec);
697 	PackAddBool(p, "ProxyServer", dlg->ProxyServer);
698 	PackAddBool(p, "AdminMode", dlg->AdminMode);
699 	PackAddBool(p, "ShowNoSavePassword", dlg->ShowNoSavePassword);
700 	PackAddBool(p, "NoSavePassword", dlg->NoSavePassword);
701 
702 	SendPack(s, p);
703 	FreePack(p);
704 
705 	dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
706 	dp->Session = session;
707 	dp->Sock = s;
708 	dp->Event = NewEvent();
709 
710 	t = NewThread(CncConnectErrorDlgHaltThread, dp);
711 
712 	p = RecvPack(s);
713 	if (p != NULL)
714 	{
715 		ret = PackGetBool(p, "ok");
716 		dlg->NoSavePassword = PackGetBool(p, "NoSavePassword");
717 		dlg->ProxyServer = PackGetBool(p, "ProxyServer");
718 		dlg->Type = PackGetInt(p, "Type");
719 		PackGetStr(p, "Username", dlg->Username, sizeof(dlg->Username));
720 		PackGetStr(p, "Password", dlg->Password, sizeof(dlg->Password));
721 
722 		FreePack(p);
723 	}
724 
725 	dp->HaltThread = true;
726 	Set(dp->Event);
727 
728 	WaitThread(t, INFINITE);
729 
730 	ReleaseEvent(dp->Event);
731 	Free(dp);
732 	ReleaseThread(t);
733 
734 	Disconnect(s);
735 	ReleaseSock(s);
736 
737 	return ret;
738 }
739 
740 // Thread to stop the connection error dialog client forcibly
CncConnectErrorDlgHaltThread(THREAD * thread,void * param)741 void CncConnectErrorDlgHaltThread(THREAD *thread, void *param)
742 {
743 	CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp = (CNC_CONNECT_ERROR_DLG_THREAD_PARAM *)param;
744 	// Validate arguments
745 	if (thread == NULL || param == NULL)
746 	{
747 		return;
748 	}
749 
750 	while (true)
751 	{
752 		if (dp->Session->Halt || dp->HaltThread)
753 		{
754 			break;
755 		}
756 
757 		Wait(dp->Event, 100);
758 	}
759 
760 	Disconnect(dp->Sock);
761 }
762 
763 // Show the connection error dialog
CncConnectErrorDlg(SESSION * session,UI_CONNECTERROR_DLG * dlg)764 bool CncConnectErrorDlg(SESSION *session, UI_CONNECTERROR_DLG *dlg)
765 {
766 	SOCK *s;
767 	PACK *p;
768 	CNC_CONNECT_ERROR_DLG_THREAD_PARAM *dp;
769 	THREAD *t;
770 	bool ret = false;
771 	// Validate arguments
772 	if (dlg == NULL || session == NULL)
773 	{
774 		return false;
775 	}
776 
777 	s = CncConnect();
778 	if (s == NULL)
779 	{
780 		Wait(session->HaltEvent, session->RetryInterval);
781 		return true;
782 	}
783 
784 	p = NewPack();
785 	PackAddStr(p, "function", "connecterror_dialog");
786 	PackAddUniStr(p, "AccountName", dlg->AccountName);
787 	PackAddStr(p, "ServerName", dlg->ServerName);
788 	PackAddInt(p, "Err", dlg->Err);
789 	PackAddInt(p, "CurrentRetryCount", dlg->CurrentRetryCount);
790 	PackAddInt(p, "RetryLimit", dlg->RetryLimit);
791 	PackAddInt(p, "RetryIntervalSec", dlg->RetryIntervalSec);
792 	PackAddBool(p, "HideWindow", dlg->HideWindow);
793 
794 	SendPack(s, p);
795 	FreePack(p);
796 
797 	dp = ZeroMalloc(sizeof(CNC_CONNECT_ERROR_DLG_THREAD_PARAM));
798 	dp->Session = session;
799 	dp->Sock = s;
800 	dp->Event = NewEvent();
801 
802 	t = NewThread(CncConnectErrorDlgHaltThread, dp);
803 
804 	p = RecvPack(s);
805 	if (p != NULL)
806 	{
807 		ret = PackGetBool(p, "ok");
808 		dlg->HideWindow = PackGetBool(p, "HideWindow");
809 
810 		FreePack(p);
811 	}
812 
813 	dp->HaltThread = true;
814 	Set(dp->Event);
815 
816 	WaitThread(t, INFINITE);
817 
818 	ReleaseEvent(dp->Event);
819 	Free(dp);
820 	ReleaseThread(t);
821 
822 	Disconnect(s);
823 	ReleaseSock(s);
824 
825 	return ret;
826 }
827 
828 // Thread for the status indicator client
CncStatusPrinterWindowThreadProc(THREAD * thread,void * param)829 void CncStatusPrinterWindowThreadProc(THREAD *thread, void *param)
830 {
831 	CNC_STATUS_PRINTER_WINDOW_PARAM *pp;
832 	SOCK *sock;
833 	PACK *p;
834 	// Validate arguments
835 	if (thread == NULL || param == NULL)
836 	{
837 		return;
838 	}
839 
840 	pp = (CNC_STATUS_PRINTER_WINDOW_PARAM *)param;
841 	sock = pp->Sock;
842 	pp->Thread = thread;
843 	AddRef(pp->Thread->ref);
844 
845 	NoticeThreadInit(thread);
846 
847 	p = RecvPack(sock);
848 	if (p != NULL)
849 	{
850 		// Stop the session
851 		StopSessionEx(pp->Session, true);
852 
853 		FreePack(p);
854 	}
855 }
856 
857 // Create a status indicator client
CncStatusPrinterWindowStart(SESSION * s)858 SOCK *CncStatusPrinterWindowStart(SESSION *s)
859 {
860 	SOCK *sock;
861 	PACK *p;
862 	THREAD *t;
863 	CNC_STATUS_PRINTER_WINDOW_PARAM *param;
864 	// Validate arguments
865 	if (s == NULL)
866 	{
867 		return NULL;
868 	}
869 
870 	sock = CncConnect();
871 
872 	if (sock == NULL)
873 	{
874 		return NULL;
875 	}
876 
877 	p = NewPack();
878 	PackAddStr(p, "function", "status_printer");
879 	PackAddUniStr(p, "account_name", s->Account->ClientOption->AccountName);
880 
881 	if (SendPack(sock, p) == false)
882 	{
883 		FreePack(p);
884 		ReleaseSock(sock);
885 
886 		return NULL;
887 	}
888 
889 	FreePack(p);
890 
891 	param = ZeroMalloc(sizeof(CNC_STATUS_PRINTER_WINDOW_PARAM));
892 	param->Sock = sock;
893 	param->Session = s;
894 
895 	sock->Param = param;
896 
897 	t = NewThread(CncStatusPrinterWindowThreadProc, param);
898 	WaitThreadInit(t);
899 
900 	ReleaseThread(t);
901 
902 	return sock;
903 }
904 
905 // Send a string to the status indicator
CncStatusPrinterWindowPrint(SOCK * s,wchar_t * str)906 void CncStatusPrinterWindowPrint(SOCK *s, wchar_t *str)
907 {
908 	PACK *p;
909 	// Validate arguments
910 	if (s == NULL || str == NULL)
911 	{
912 		return;
913 	}
914 
915 	p = NewPack();
916 	PackAddUniStr(p, "string", str);
917 	SendPack(s, p);
918 	FreePack(p);
919 }
920 
921 // Stop the status indicator client
CncStatusPrinterWindowStop(SOCK * s)922 void CncStatusPrinterWindowStop(SOCK *s)
923 {
924 	CNC_STATUS_PRINTER_WINDOW_PARAM *param;
925 	// Validate arguments
926 	if (s == NULL)
927 	{
928 		return;
929 	}
930 
931 	param = (CNC_STATUS_PRINTER_WINDOW_PARAM *)s->Param;
932 
933 	// Disconnect the client socket
934 	Disconnect(s);
935 
936 	// Terminate the thread
937 	WaitThread(param->Thread, INFINITE);
938 	ReleaseThread(param->Thread);
939 
940 	Free(param);
941 	ReleaseSock(s);
942 }
943 
944 // Start the driver installer for Windows Vista
CncExecDriverInstaller(char * arg)945 bool CncExecDriverInstaller(char *arg)
946 {
947 	SOCK *s = CncConnect();
948 	PACK *p;
949 	bool ret;
950 	if (s == NULL)
951 	{
952 		return false;
953 	}
954 
955 	p = NewPack();
956 	PackAddStr(p, "function", "exec_driver_installer");
957 	PackAddStr(p, "arg", arg);
958 
959 	SendPack(s, p);
960 	FreePack(p);
961 
962 	p = RecvPack(s);
963 	if (p == NULL)
964 	{
965 		Disconnect(s);
966 		ReleaseSock(s);
967 		return false;
968 	}
969 
970 	ret = PackGetBool(p, "ret");
971 
972 	FreePack(p);
973 
974 	Disconnect(s);
975 	ReleaseSock(s);
976 
977 	return ret;
978 }
979 
980 // Let the current running client notification services releasing the socket
CncReleaseSocket()981 void CncReleaseSocket()
982 {
983 	SOCK *s = CncConnect();
984 	PACK *p;
985 	if (s == NULL)
986 	{
987 		return;
988 	}
989 
990 	p = NewPack();
991 	PackAddStr(p, "function", "release_socket");
992 
993 #ifdef OS_WIN32
994 	PackAddInt(p, "pid", MsGetProcessId());
995 #endif	// OS_WIN32
996 
997 	SendPack(s, p);
998 	FreePack(p);
999 
1000 	Disconnect(s);
1001 	ReleaseSock(s);
1002 }
1003 
1004 // Terminate the process of the client notification service
CncExit()1005 void CncExit()
1006 {
1007 	SOCK *s = CncConnectEx(256);
1008 	PACK *p;
1009 	if (s != NULL)
1010 	{
1011 		p = NewPack();
1012 		PackAddStr(p, "function", "exit");
1013 
1014 		SendPack(s, p);
1015 
1016 		FreePack(p);
1017 
1018 		FreePack(RecvPack(s));
1019 
1020 		Disconnect(s);
1021 		ReleaseSock(s);
1022 	}
1023 
1024 #ifdef	OS_WIN32
1025 	MsKillOtherInstanceEx("vpnclient");
1026 #endif	// OS_WIN32
1027 }
1028 
1029 // Connect to the client notification service
CncConnect()1030 SOCK *CncConnect()
1031 {
1032 	return CncConnectEx(0);
1033 }
CncConnectEx(UINT timeout)1034 SOCK *CncConnectEx(UINT timeout)
1035 {
1036 	SOCK *s = ConnectEx("localhost", CLIENT_NOTIFY_PORT, timeout);
1037 
1038 	return s;
1039 }
1040 
1041 #ifdef	OS_WIN32
1042 
1043 // Thread for the certificate check dialog
Win32CnCheckCertThreadProc(THREAD * thread,void * param)1044 void Win32CnCheckCertThreadProc(THREAD *thread, void *param)
1045 {
1046 	UI_CHECKCERT *dlg;
1047 	// Validate arguments
1048 	if (thread == NULL || param == NULL)
1049 	{
1050 		return;
1051 	}
1052 
1053 	dlg = (UI_CHECKCERT *)param;
1054 
1055 	CheckCertDlg(dlg);
1056 	{
1057 		PACK *p = NewPack();
1058 
1059 		PackAddBool(p, "Ok", dlg->Ok);
1060 		PackAddBool(p, "SaveServerCert", dlg->SaveServerCert);
1061 
1062 		SendPack(dlg->Sock, p);
1063 		FreePack(p);
1064 
1065 		FreePack(RecvPack(dlg->Sock));
1066 	}
1067 
1068 	Disconnect(dlg->Sock);
1069 }
1070 
1071 // Certificate check dialog
Win32CnCheckCert(SOCK * s,PACK * p)1072 void Win32CnCheckCert(SOCK *s, PACK *p)
1073 {
1074 	UI_CHECKCERT dlg;
1075 	THREAD *t;
1076 	Zero(&dlg, sizeof(dlg));
1077 	// Validate arguments
1078 	if (s == NULL || p == NULL)
1079 	{
1080 		return;
1081 	}
1082 
1083 	PackGetUniStr(p, "AccountName", dlg.AccountName, sizeof(dlg.AccountName));
1084 	PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
1085 	dlg.x = PackGetX(p, "x");
1086 	dlg.parent_x = PackGetX(p, "parent_x");
1087 	dlg.old_x = PackGetX(p, "old_x");
1088 	dlg.DiffWarning = PackGetBool(p, "DiffWarning");
1089 	dlg.Ok = PackGetBool(p, "Ok");
1090 	dlg.SaveServerCert = PackGetBool(p, "SaveServerCert");
1091 	dlg.Sock = s;
1092 
1093 	t = NewThread(Win32CnCheckCertThreadProc, &dlg);
1094 
1095 	FreePack(RecvPack(s));
1096 
1097 	dlg.Halt = true;
1098 
1099 	WaitThread(t, INFINITE);
1100 	ReleaseThread(t);
1101 
1102 	FreeX(dlg.parent_x);
1103 	FreeX(dlg.old_x);
1104 	FreeX(dlg.x);
1105 }
1106 
1107 // Message display dialog thread procedure
Win32CnMsgDlgThreadProc(THREAD * thread,void * param)1108 void Win32CnMsgDlgThreadProc(THREAD *thread, void *param)
1109 {
1110 	UI_MSG_DLG *dlg = (UI_MSG_DLG *)param;
1111 	wchar_t tmp[MAX_SIZE];
1112 	char url[MAX_SIZE];
1113 	// Validate arguments
1114 	if (thread == NULL || dlg == NULL)
1115 	{
1116 		return;
1117 	}
1118 
1119 	UniFormat(tmp, sizeof(tmp), _UU("CM_MSG_TITLE"),
1120 		dlg->ServerName, dlg->HubName);
1121 
1122 	if (IsURLMsg(dlg->Msg, url, sizeof(url)) == false)
1123 	{
1124 		OnceMsgEx(NULL, tmp, dlg->Msg, true, 167, &dlg->Halt);
1125 	}
1126 	else
1127 	{
1128 		if (MsExecute(url, NULL) == false)
1129 		{
1130 			OnceMsgEx(NULL, tmp, dlg->Msg, true, 167, &dlg->Halt);
1131 		}
1132 	}
1133 
1134 	Disconnect(dlg->Sock);
1135 }
1136 
1137 // NIC information dialog thread procedure
Win32CnNicInfoThreadProc(THREAD * thread,void * param)1138 void Win32CnNicInfoThreadProc(THREAD *thread, void *param)
1139 {
1140 	UI_NICINFO *info = (UI_NICINFO *)param;
1141 	// Validate arguments
1142 	if (thread == NULL || info == NULL)
1143 	{
1144 		return;
1145 	}
1146 
1147 	NicInfo(info);
1148 
1149 	Disconnect(info->Sock);
1150 }
1151 
1152 // NIC information dialog
Win32CnNicInfo(SOCK * s,PACK * p)1153 void Win32CnNicInfo(SOCK *s, PACK *p)
1154 {
1155 	UI_NICINFO info;
1156 	THREAD *t;
1157 	Zero(&info, sizeof(info));
1158 	// Validate arguments
1159 	if (s == NULL || p == NULL)
1160 	{
1161 		return;
1162 	}
1163 
1164 	PackGetStr(p, "NicName", info.NicName, sizeof(info.NicName));
1165 	PackGetUniStr(p, "AccountName", info.AccountName, sizeof(info.AccountName));
1166 
1167 	info.Sock = s;
1168 
1169 	t = NewThread(Win32CnNicInfoThreadProc, &info);
1170 
1171 	FreePack(RecvPack(s));
1172 
1173 	info.Halt = true;
1174 
1175 	WaitThread(t, INFINITE);
1176 	ReleaseThread(t);
1177 }
1178 
1179 // Message display dialog
Win32CnMsgDlg(SOCK * s,PACK * p)1180 void Win32CnMsgDlg(SOCK *s, PACK *p)
1181 {
1182 	UI_MSG_DLG dlg;
1183 	THREAD *t;
1184 	UINT utf_size;
1185 	char *utf;
1186 	wchar_t *msg;
1187 	Zero(&dlg, sizeof(dlg));
1188 	// Validate arguments
1189 	if (s == NULL || p == NULL)
1190 	{
1191 		return;
1192 	}
1193 
1194 	PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
1195 	PackGetStr(p, "HubName", dlg.HubName, sizeof(dlg.HubName));
1196 
1197 	utf_size = PackGetDataSize(p, "Msg");
1198 	utf = ZeroMalloc(utf_size + 8);
1199 
1200 	PackGetData(p, "Msg", utf);
1201 
1202 	msg = CopyUtfToUni(utf);
1203 	Free(utf);
1204 
1205 	dlg.Sock = s;
1206 	dlg.Msg = msg;
1207 
1208 	t = NewThread(Win32CnMsgDlgThreadProc, &dlg);
1209 
1210 	FreePack(RecvPack(s));
1211 
1212 	dlg.Halt = true;
1213 
1214 	WaitThread(t, INFINITE);
1215 	ReleaseThread(t);
1216 
1217 	Free(msg);
1218 }
1219 
1220 // Thread for Password input dialog
Win32CnPasswordDlgThreadProc(THREAD * thread,void * param)1221 void Win32CnPasswordDlgThreadProc(THREAD *thread, void *param)
1222 {
1223 	UI_PASSWORD_DLG *dlg;
1224 	// Validate arguments
1225 	if (thread == NULL || param == NULL)
1226 	{
1227 		return;
1228 	}
1229 
1230 	dlg = (UI_PASSWORD_DLG *)param;
1231 
1232 	if (PasswordDlg(NULL, dlg))
1233 	{
1234 		PACK *p = NewPack();
1235 
1236 		PackAddBool(p, "ok", true);
1237 		PackAddStr(p, "Username", dlg->Username);
1238 		PackAddStr(p, "Password", dlg->Password);
1239 		PackAddInt(p, "Type", dlg->Type);
1240 		PackAddBool(p, "ProxyServer", dlg->ProxyServer);
1241 		PackAddBool(p, "NoSavePassword", dlg->NoSavePassword);
1242 
1243 		SendPack(dlg->Sock, p);
1244 		FreePack(p);
1245 
1246 		FreePack(RecvPack(dlg->Sock));
1247 	}
1248 
1249 	Disconnect(dlg->Sock);
1250 }
1251 
1252 // Password input dialog
Win32CnPasswordDlg(SOCK * s,PACK * p)1253 void Win32CnPasswordDlg(SOCK *s, PACK *p)
1254 {
1255 	UI_PASSWORD_DLG dlg;
1256 	THREAD *t = NULL;
1257 	Zero(&dlg, sizeof(dlg));
1258 	// Validate arguments
1259 	if (s == NULL || p == NULL)
1260 	{
1261 		return;
1262 	}
1263 
1264 	dlg.Type = PackGetInt(p, "Type");
1265 	PackGetStr(p, "Username", dlg.Username, sizeof(dlg.Username));
1266 	PackGetStr(p, "Password", dlg.Password, sizeof(dlg.Password));
1267 	PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
1268 	dlg.RetryIntervalSec = PackGetInt(p, "RetryIntervalSec");
1269 	dlg.ProxyServer = PackGetBool(p, "ProxyServer");
1270 	dlg.AdminMode = PackGetBool(p, "AdminMode");
1271 	dlg.ShowNoSavePassword = PackGetBool(p, "ShowNoSavePassword");
1272 	dlg.NoSavePassword = PackGetBool(p, "NoSavePassword");
1273 	dlg.CancelEvent = NewEvent();
1274 	dlg.Sock = s;
1275 
1276 	t = NewThread(Win32CnPasswordDlgThreadProc, &dlg);
1277 
1278 	FreePack(RecvPack(s));
1279 
1280 	Set(dlg.CancelEvent);
1281 
1282 	WaitThread(t, INFINITE);
1283 	ReleaseEvent(dlg.CancelEvent);
1284 	ReleaseThread(t);
1285 }
1286 
1287 // Thread for the connection error dialog
Win32CnConnectErrorDlgThreadProc(THREAD * thread,void * param)1288 void Win32CnConnectErrorDlgThreadProc(THREAD *thread, void *param)
1289 {
1290 	UI_CONNECTERROR_DLG *dlg;
1291 	// Validate arguments
1292 	if (thread == NULL || param == NULL)
1293 	{
1294 		return;
1295 	}
1296 
1297 	dlg = (UI_CONNECTERROR_DLG *)param;
1298 
1299 	if (ConnectErrorDlg(dlg))
1300 	{
1301 		PACK *p = NewPack();
1302 
1303 		PackAddBool(p, "ok", true);
1304 		PackAddBool(p, "HideWindow", dlg->HideWindow);
1305 
1306 		SendPack(dlg->Sock, p);
1307 		FreePack(p);
1308 
1309 		FreePack(RecvPack(dlg->Sock));
1310 	}
1311 
1312 	Disconnect(dlg->Sock);
1313 }
1314 
1315 // Connection Error dialog (Win32)
Win32CnConnectErrorDlg(SOCK * s,PACK * p)1316 void Win32CnConnectErrorDlg(SOCK *s, PACK *p)
1317 {
1318 	UI_CONNECTERROR_DLG dlg;
1319 	THREAD *t;
1320 	Zero(&dlg, sizeof(dlg));
1321 	// Validate arguments
1322 	if (s == NULL || p == NULL)
1323 	{
1324 		return;
1325 	}
1326 
1327 	PackGetUniStr(p, "AccountName", dlg.AccountName, sizeof(dlg.AccountName));
1328 	PackGetStr(p, "ServerName", dlg.ServerName, sizeof(dlg.ServerName));
1329 	dlg.Err = PackGetInt(p, "Err");
1330 	dlg.CurrentRetryCount = PackGetInt(p, "CurrentRetryCount");
1331 	dlg.RetryLimit = PackGetInt(p, "RetryLimit");
1332 	dlg.RetryIntervalSec = PackGetInt(p, "RetryIntervalSec");
1333 	dlg.HideWindow = PackGetBool(p, "HideWindow");
1334 	dlg.CancelEvent = NewEvent();
1335 	dlg.Sock = s;
1336 
1337 	t = NewThread(Win32CnConnectErrorDlgThreadProc, &dlg);
1338 
1339 	FreePack(RecvPack(s));
1340 
1341 	Set(dlg.CancelEvent);
1342 
1343 	WaitThread(t, INFINITE);
1344 	ReleaseEvent(dlg.CancelEvent);
1345 	ReleaseThread(t);
1346 }
1347 
1348 // Status indicator (Win32)
Win32CnStatusPrinter(SOCK * s,PACK * p)1349 void Win32CnStatusPrinter(SOCK *s, PACK *p)
1350 {
1351 	STATUS_WINDOW *w;
1352 	wchar_t account_name[MAX_ACCOUNT_NAME_LEN + 1];
1353 	// Validate arguments
1354 	if (s == NULL || p == NULL)
1355 	{
1356 		return;
1357 	}
1358 
1359 	PackGetUniStr(p, "account_name", account_name, sizeof(account_name));
1360 
1361 	w = StatusPrinterWindowStart(s, account_name);
1362 
1363 	while (true)
1364 	{
1365 		PACK *p = RecvPack(s);
1366 
1367 		if (p == NULL)
1368 		{
1369 			// Exit the dialog because it is disconnected
1370 			break;
1371 		}
1372 		else
1373 		{
1374 			wchar_t tmp[MAX_SIZE];
1375 
1376 			// Rewrite the string
1377 			PackGetUniStr(p, "string", tmp, sizeof(tmp));
1378 
1379 			StatusPrinterWindowPrint(w, tmp);
1380 
1381 			FreePack(p);
1382 		}
1383 	}
1384 
1385 	StatusPrinterWindowStop(w);
1386 }
1387 
1388 // Start the driver installer (for Windows Vista)
Win32CnExecDriverInstaller(SOCK * s,PACK * p)1389 void Win32CnExecDriverInstaller(SOCK *s, PACK *p)
1390 {
1391 	char arg[MAX_SIZE];
1392 	bool ret;
1393 	void *helper = NULL;
1394 	// Validate arguments
1395 	if (s == NULL || p == NULL)
1396 	{
1397 		return;
1398 	}
1399 
1400 	if (PackGetStr(p, "arg", arg, sizeof(arg)) == false)
1401 	{
1402 		return;
1403 	}
1404 
1405 	helper = CmStartUacHelper();
1406 
1407 	ret = MsExecDriverInstaller(arg);
1408 
1409 	CmStopUacHelper(helper);
1410 
1411 	p = NewPack();
1412 	PackAddBool(p, "ret", ret);
1413 	SendPack(s, p);
1414 
1415 	FreePack(p);
1416 }
1417 
1418 #endif	// OS_WIN32
1419 
1420 // Start the driver installer
CnExecDriverInstaller(SOCK * s,PACK * p)1421 void CnExecDriverInstaller(SOCK *s, PACK *p)
1422 {
1423 	// Validate arguments
1424 	if (s == NULL || p == NULL)
1425 	{
1426 		return;
1427 	}
1428 
1429 #ifdef	OS_WIN32
1430 	Win32CnExecDriverInstaller(s, p);
1431 #endif	// OS_WIN32
1432 }
1433 
1434 // Certificate confirmation dialog
CnCheckCert(SOCK * s,PACK * p)1435 void CnCheckCert(SOCK *s, PACK *p)
1436 {
1437 	// Validate arguments
1438 	if (s == NULL || p == NULL)
1439 	{
1440 		return;
1441 	}
1442 
1443 #ifdef	OS_WIN32
1444 	Win32CnCheckCert(s, p);
1445 #endif	// OS_WIN32
1446 }
1447 
1448 // NIC information dialog
CnNicInfo(SOCK * s,PACK * p)1449 void CnNicInfo(SOCK *s, PACK *p)
1450 {
1451 	// Validate arguments
1452 	if (s == NULL || p == NULL)
1453 	{
1454 		return;
1455 	}
1456 
1457 #ifdef	OS_WIN32
1458 	Win32CnNicInfo(s, p);
1459 #endif	// OS_WIN32
1460 }
1461 
1462 // Message display dialog
CnMsgDlg(SOCK * s,PACK * p)1463 void CnMsgDlg(SOCK *s, PACK *p)
1464 {
1465 	// Validate arguments
1466 	if (s == NULL || p == NULL)
1467 	{
1468 		return;
1469 	}
1470 
1471 #ifdef	OS_WIN32
1472 	Win32CnMsgDlg(s, p);
1473 #endif	// OS_WIN32
1474 }
1475 
1476 // Password input dialog
CnPasswordDlg(SOCK * s,PACK * p)1477 void CnPasswordDlg(SOCK *s, PACK *p)
1478 {
1479 	// Validate arguments
1480 	if (s == NULL || p == NULL)
1481 	{
1482 		return;
1483 	}
1484 
1485 #ifdef	OS_WIN32
1486 	Win32CnPasswordDlg(s, p);
1487 #endif	// OS_WIN32
1488 }
1489 
1490 // Connection Error dialog
CnConnectErrorDlg(SOCK * s,PACK * p)1491 void CnConnectErrorDlg(SOCK *s, PACK *p)
1492 {
1493 	// Validate arguments
1494 	if (s == NULL || p == NULL)
1495 	{
1496 		return;
1497 	}
1498 
1499 #ifdef	OS_WIN32
1500 	Win32CnConnectErrorDlg(s, p);
1501 #endif	// OS_WIN32
1502 }
1503 
1504 // Status indicator
CnStatusPrinter(SOCK * s,PACK * p)1505 void CnStatusPrinter(SOCK *s, PACK *p)
1506 {
1507 	// Validate arguments
1508 	if (s == NULL || p == NULL)
1509 	{
1510 		return;
1511 	}
1512 
1513 #ifdef	OS_WIN32
1514 	Win32CnStatusPrinter(s, p);
1515 #endif	// OS_WIN32
1516 }
1517 // Client notification service listener thread
CnListenerProc(THREAD * thread,void * param)1518 void CnListenerProc(THREAD *thread, void *param)
1519 {
1520 	TCP_ACCEPTED_PARAM *data = (TCP_ACCEPTED_PARAM *)param;
1521 	SOCK *s;
1522 	PACK *p;
1523 	// Validate arguments
1524 	if (data == NULL || thread == NULL)
1525 	{
1526 		return;
1527 	}
1528 
1529 #ifdef	OS_WIN32
1530 	//Set Application ID
1531 	JL_SetCurrentProcessExplicitAppUserModelID(APPID_CM);
1532 #endif	// OS_WIN32
1533 
1534 	s = data->s;
1535 	AddRef(s->ref);
1536 	NoticeThreadInit(thread);
1537 
1538 	if (IsLocalHostIP(&s->LocalIP))
1539 	{
1540 		p = RecvPack(s);
1541 
1542 		if (p != NULL)
1543 		{
1544 			char function[MAX_SIZE];
1545 
1546 			if (PackGetStr(p, "function", function, sizeof(function)))
1547 			{
1548 				if (StrCmpi(function, "status_printer") == 0)
1549 				{
1550 					CnStatusPrinter(s, p);
1551 				}
1552 				else if (StrCmpi(function, "connecterror_dialog") == 0)
1553 				{
1554 					CnConnectErrorDlg(s, p);
1555 				}
1556 				else if (StrCmpi(function, "msg_dialog") == 0)
1557 				{
1558 					CnMsgDlg(s, p);
1559 				}
1560 				else if (StrCmpi(function, "nicinfo") == 0)
1561 				{
1562 					CnNicInfo(s, p);
1563 				}
1564 				else if (StrCmpi(function, "password_dialog") == 0)
1565 				{
1566 					CnPasswordDlg(s, p);
1567 				}
1568 				else if (StrCmpi(function, "secure_sign") == 0)
1569 				{
1570 					CnSecureSign(s, p);
1571 				}
1572 				else if (StrCmpi(function, "check_cert") == 0)
1573 				{
1574 					CnCheckCert(s, p);
1575 				}
1576 				else if (StrCmpi(function, "exit") == 0)
1577 				{
1578 #ifdef	OS_WIN32
1579 					MsTerminateProcess();
1580 #else	// OS_WIN32
1581 					_exit(0);
1582 #endif	// OS_WIN32
1583 				}
1584 				else if (StrCmpi(function, "get_session_id") == 0)
1585 				{
1586 					PACK *p = NewPack();
1587 #ifdef	OS_WIN32
1588 					PackAddInt(p, "session_id", MsGetCurrentTerminalSessionId());
1589 #endif	// OS_WIN32
1590 					SendPack(s, p);
1591 					FreePack(p);
1592 				}
1593 				else if (StrCmpi(function, "exec_driver_installer") == 0)
1594 				{
1595 					CnExecDriverInstaller(s, p);
1596 				}
1597 				else if (StrCmpi(function, "release_socket") == 0)
1598 				{
1599 					// Stop the listener
1600 					CnReleaseSocket(s, p);
1601 				}
1602 			}
1603 
1604 			FreePack(p);
1605 		}
1606 	}
1607 
1608 	Disconnect(s);
1609 	ReleaseSock(s);
1610 }
1611 
1612 // Do the Secure Sign
CnSecureSign(SOCK * s,PACK * p)1613 void CnSecureSign(SOCK *s, PACK *p)
1614 {
1615 	SECURE_SIGN sign;
1616 	bool ret = false;
1617 	// Validate arguments
1618 	if (s == NULL || p == NULL)
1619 	{
1620 		return;
1621 	}
1622 
1623 	Zero(&sign, sizeof(sign));
1624 	InRpcSecureSign(&sign, p);
1625 
1626 #ifdef	OS_WIN32
1627 	// Win32: Show dialog
1628 	ret = Win32CiSecureSign(&sign);
1629 #else	// OS_WIN32
1630 	// UNIX: not implemented
1631 	ret = false;
1632 #endif	// OS_WIN32
1633 
1634 	p = NewPack();
1635 
1636 	OutRpcSecureSign(p, &sign);
1637 	FreeRpcSecureSign(&sign);
1638 
1639 	PackAddBool(p, "ret", ret);
1640 
1641 	SendPack(s, p);
1642 	FreePack(p);
1643 }
1644 
1645 // Stop the listener
CnReleaseSocket(SOCK * s,PACK * p)1646 void CnReleaseSocket(SOCK *s, PACK *p)
1647 {
1648 	UINT pid = 0;
1649 	UINT current_pid = 0;
1650 	// Validate arguments
1651 	if (s == NULL || p == NULL)
1652 	{
1653 		return;
1654 	}
1655 
1656 	pid = PackGetInt(p, "pid");
1657 
1658 #ifdef	OS_WIN32
1659 	current_pid = MsGetProcessId();
1660 #endif	// OS_WIN32
1661 
1662 	if (current_pid == pid)
1663 	{
1664 		return;
1665 	}
1666 
1667 	Lock(cn_listener_lock);
1668 	{
1669 		if (cn_listener != NULL)
1670 		{
1671 			if (cn_listener->Halt == false)
1672 			{
1673 				StopListener(cn_listener);
1674 
1675 				cn_next_allow = Tick64() + (6 * 1000);
1676 			}
1677 		}
1678 	}
1679 	Unlock(cn_listener_lock);
1680 }
1681 
1682 // Start the client notification service
CnStart()1683 void CnStart()
1684 {
1685 	CEDAR *cedar;
1686 	LISTENER *o;
1687 	UINT last_cursor_hash = 0;
1688 	bool last_session_active = false;
1689 
1690 	cn_next_allow = 0;
1691 	cn_listener_lock = NewLock();
1692 
1693 #ifdef	OS_WIN32
1694 	MsSetShutdownParameters(0xff, 0x00000001);
1695 	InitWinUi(_UU("CN_TITLE"), _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
1696 #endif	// OS_WIN32
1697 
1698 	cedar = NewCedar(NULL, NULL);
1699 
1700 	if (CnCheckAlreadyExists(true))
1701 	{
1702 		// Already started
1703 		ReleaseCedar(cedar);
1704 #ifdef	OS_WIN32
1705 		FreeWinUi();
1706 #endif	// OS_WIN32
1707 		return;
1708 	}
1709 
1710 #ifdef	OS_WIN32
1711 	MsRegWriteInt(REG_CURRENT_USER, CM_REG_KEY,
1712 		"NotifyServerProcessId", MsGetProcessId());
1713 #endif	// OS_WIN32
1714 
1715 	DisableDosProtect();
1716 
1717 BEGIN_LISTENER:
1718 	Lock(cn_listener_lock);
1719 	cn_listener = o = NewListenerEx2(cedar, LISTENER_TCP, CLIENT_NOTIFY_PORT, CnListenerProc, NULL, true);
1720 	Unlock(cn_listener_lock);
1721 
1722 	while (true)
1723 	{
1724 		UINT current_cursor_hash = 0;
1725 		bool cursor_changed = false;
1726 
1727 #ifdef	OS_WIN32
1728 		// Get the current cursor position
1729 		current_cursor_hash = MsGetCursorPosHash();
1730 #endif	// OS_WIN32
1731 
1732 		if (last_cursor_hash != current_cursor_hash)
1733 		{
1734 			// Check the cursor position
1735 			cursor_changed = true;
1736 			last_cursor_hash = current_cursor_hash;
1737 		}
1738 
1739 		Lock(cn_listener_lock);
1740 
1741 		// Check the status periodically after that the listener has started
1742 		if (cn_listener->Status == LISTENER_STATUS_TRYING || cn_listener->Halt)
1743 		{
1744 			bool session_active = false;
1745 #ifdef	OS_WIN32
1746 			session_active = MsIsCurrentTerminalSessionActive();
1747 			if (cursor_changed)
1748 			{
1749 				// If the cursor position is changed but the terminal session is
1750 				// not active, the cursor position is regarded as not changed.
1751 				if (session_active == false)
1752 				{
1753 					cursor_changed = false;
1754 				}
1755 			}
1756 			if (last_session_active != session_active)
1757 			{
1758 				//If the cursor position doesn't changed but the terminal session
1759 				// became active than previous, the cursor position is regarded as changed.
1760 				last_session_active = session_active;
1761 
1762 				if (session_active)
1763 				{
1764 					cursor_changed = true;
1765 				}
1766 			}
1767 #endif	// OS_WIN32
1768 
1769 			// If the port cannot be opened
1770 			if (cn_next_allow <= Tick64())
1771 			{
1772 #ifdef  OS_WIN32
1773 				if (cursor_changed)
1774 				{
1775 					// It can be judged to have the rights to open the port
1776 					// since the mouse cursor is moving.
1777 					// So, take over the port which is owned by other process forcibly
1778 					CncReleaseSocket();
1779 				}
1780 #endif  // OS_WIN32
1781 
1782 				if (cn_listener->Halt)
1783 				{
1784 					ReleaseListener(cn_listener);
1785 					cn_listener = NULL;
1786 
1787 					Unlock(cn_listener_lock);
1788 					goto BEGIN_LISTENER;
1789 				}
1790 			}
1791 		}
1792 
1793 		Unlock(cn_listener_lock);
1794 
1795 		SleepThread(1000);
1796 	}
1797 }
1798 
1799 // Confirm whether the account file is parsed successfully
CiTryToParseAccount(BUF * b)1800 bool CiTryToParseAccount(BUF *b)
1801 {
1802 	RPC_CLIENT_CREATE_ACCOUNT *a;
1803 	// Validate arguments
1804 	if (b == NULL)
1805 	{
1806 		return false;
1807 	}
1808 
1809 	a = CiCfgToAccount(b);
1810 	if (a != NULL)
1811 	{
1812 		CiFreeClientCreateAccount(a);
1813 		Free(a);
1814 
1815 		return true;
1816 	}
1817 	else
1818 	{
1819 		return false;
1820 	}
1821 }
CiTryToParseAccountFile(wchar_t * name)1822 bool CiTryToParseAccountFile(wchar_t *name)
1823 {
1824 	bool ret;
1825 	BUF *b;
1826 	// Validate arguments
1827 	if (name == NULL)
1828 	{
1829 		return false;
1830 	}
1831 
1832 	b = ReadDumpW(name);
1833 	if (b == NULL)
1834 	{
1835 		return false;
1836 	}
1837 
1838 	ret = CiTryToParseAccount(b);
1839 
1840 	FreeBuf(b);
1841 
1842 	return ret;
1843 }
1844 
1845 // Confirm whether the account information includes sensitive information
CiHasAccountSensitiveInformation(BUF * b)1846 bool CiHasAccountSensitiveInformation(BUF *b)
1847 {
1848 	RPC_CLIENT_CREATE_ACCOUNT *a;
1849 	bool ret = false;
1850 	// Validate arguments
1851 	if (b == NULL)
1852 	{
1853 		return false;
1854 	}
1855 
1856 	a = CiCfgToAccount(b);
1857 	if (a == NULL)
1858 	{
1859 		return false;
1860 	}
1861 
1862 	if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
1863 	{
1864 		ret = true;
1865 	}
1866 	else if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
1867 	{
1868 		ret = true;
1869 	}
1870 
1871 	CiFreeClientCreateAccount(a);
1872 	Free(a);
1873 
1874 	return ret;
1875 }
1876 
1877 // Delete the sensitive information in the account information
CiEraseSensitiveInAccount(BUF * b)1878 bool CiEraseSensitiveInAccount(BUF *b)
1879 {
1880 	RPC_CLIENT_CREATE_ACCOUNT *a;
1881 	BUF *b2;
1882 	bool ret = false;
1883 	// Validate arguments
1884 	if (b == NULL)
1885 	{
1886 		return false;
1887 	}
1888 
1889 	a = CiCfgToAccount(b);
1890 	if (a == NULL)
1891 	{
1892 		return false;
1893 	}
1894 
1895 	if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD)
1896 	{
1897 		Zero(a->ClientAuth->HashedPassword, sizeof(a->ClientAuth->HashedPassword));
1898 		ClearStr(a->ClientAuth->Username, sizeof(a->ClientAuth->Username));
1899 	}
1900 	else if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
1901 	{
1902 		ClearStr(a->ClientAuth->PlainPassword, sizeof(a->ClientAuth->PlainPassword));
1903 		ClearStr(a->ClientAuth->Username, sizeof(a->ClientAuth->Username));
1904 	}
1905 
1906 	b2 = CiAccountToCfg(a);
1907 	if (b2 != NULL)
1908 	{
1909 		ret = true;
1910 
1911 		ClearBuf(b);
1912 
1913 		WriteBuf(b, b2->Buf, b2->Size);
1914 		SeekBuf(b, 0, 0);
1915 
1916 		FreeBuf(b2);
1917 	}
1918 
1919 	CiFreeClientCreateAccount(a);
1920 	Free(a);
1921 
1922 	return ret;
1923 }
1924 
1925 // Read the account information from the buffer
CiCfgToAccount(BUF * b)1926 RPC_CLIENT_CREATE_ACCOUNT *CiCfgToAccount(BUF *b)
1927 {
1928 	RPC_CLIENT_CREATE_ACCOUNT *t;
1929 	FOLDER *f;
1930 	ACCOUNT *a;
1931 	// Validate arguments
1932 	if (b == NULL)
1933 	{
1934 		return NULL;
1935 	}
1936 
1937 	f = CfgBufTextToFolder(b);
1938 	if (f == NULL)
1939 	{
1940 		return NULL;
1941 	}
1942 
1943 	a = CiLoadClientAccount(f);
1944 
1945 	CfgDeleteFolder(f);
1946 
1947 	if (a == NULL)
1948 	{
1949 		return NULL;
1950 	}
1951 
1952 	DeleteLock(a->lock);
1953 
1954 	t = ZeroMalloc(sizeof(RPC_CLIENT_CREATE_ACCOUNT));
1955 	t->ClientOption = a->ClientOption;
1956 	t->ClientAuth = a->ClientAuth;
1957 	t->StartupAccount = a->StartupAccount;
1958 	t->CheckServerCert = a->CheckServerCert;
1959 	t->RetryOnServerCert = a->RetryOnServerCert;
1960 	t->ServerCert = a->ServerCert;
1961 	Free(a);
1962 
1963 	return t;
1964 }
1965 
1966 // Write the account information to a buffer
CiAccountToCfg(RPC_CLIENT_CREATE_ACCOUNT * t)1967 BUF *CiAccountToCfg(RPC_CLIENT_CREATE_ACCOUNT *t)
1968 {
1969 	BUF *b;
1970 	FOLDER *root;
1971 	ACCOUNT a;
1972 	// Validate arguments
1973 	if (t == NULL)
1974 	{
1975 		return NULL;
1976 	}
1977 
1978 	root = CfgCreateFolder(NULL, TAG_ROOT);
1979 	Zero(&a, sizeof(a));
1980 	a.ClientOption = t->ClientOption;
1981 	a.ClientAuth = t->ClientAuth;
1982 	a.CheckServerCert = t->CheckServerCert;
1983 	a.RetryOnServerCert = t->RetryOnServerCert;
1984 	a.ServerCert = t->ServerCert;
1985 	a.StartupAccount = t->StartupAccount;
1986 
1987 	CiWriteAccountData(root, &a);
1988 
1989 	b = CfgFolderToBufEx(root, true, true);
1990 	CfgDeleteFolder(root);
1991 
1992 	return b;
1993 }
1994 
1995 // RPC dispatch routine
CiRpcDispatch(RPC * rpc,char * name,PACK * p)1996 PACK *CiRpcDispatch(RPC *rpc, char *name, PACK *p)
1997 {
1998 	PACK *ret;
1999 	CLIENT *c;
2000 	// Validate arguments
2001 	if (rpc == NULL || name == NULL || p == NULL)
2002 	{
2003 		return NULL;
2004 	}
2005 	c = rpc->Param;
2006 
2007 	ret = NewPack();
2008 
2009 	if (StrCmpi(name, "GetClientVersion") == 0)
2010 	{
2011 		RPC_CLIENT_VERSION a;
2012 		if (CtGetClientVersion(c, &a) == false)
2013 		{
2014 			RpcError(ret, c->Err);
2015 		}
2016 		else
2017 		{
2018 			OutRpcClientVersion(ret, &a);
2019 		}
2020 	}
2021 	else if (StrCmpi(name, "GetCmSetting") == 0)
2022 	{
2023 		CM_SETTING a;
2024 		if (CtGetCmSetting(c, &a) == false)
2025 		{
2026 			RpcError(ret, c->Err);
2027 		}
2028 		else
2029 		{
2030 			OutRpcCmSetting(ret, &a);
2031 		}
2032 	}
2033 	else if (StrCmpi(name, "SetCmSetting") == 0)
2034 	{
2035 		CM_SETTING a;
2036 		Zero(&a, sizeof(a));
2037 		InRpcCmSetting(&a, p);
2038 		if (CtSetCmSetting(c, &a) == false)
2039 		{
2040 			RpcError(ret, c->Err);
2041 		}
2042 	}
2043 	else if (StrCmpi(name, "SetPassword") == 0)
2044 	{
2045 		RPC_CLIENT_PASSWORD a;
2046 		InRpcClientPassword(&a, p);
2047 		if (CtSetPassword(c, &a) == false)
2048 		{
2049 			RpcError(ret, c->Err);
2050 		}
2051 	}
2052 	else if (StrCmpi(name, "GetPasswordSetting") == 0)
2053 	{
2054 		RPC_CLIENT_PASSWORD_SETTING a;
2055 		if (CtGetPasswordSetting(c, &a) == false)
2056 		{
2057 			RpcError(ret, c->Err);
2058 		}
2059 		else
2060 		{
2061 			OutRpcClientPasswordSetting(ret, &a);
2062 		}
2063 	}
2064 	else if (StrCmpi(name, "EnumCa") == 0)
2065 	{
2066 		RPC_CLIENT_ENUM_CA a;
2067 		if (CtEnumCa(c, &a) == false)
2068 		{
2069 			RpcError(ret, c->Err);
2070 		}
2071 		else
2072 		{
2073 			OutRpcClientEnumCa(ret, &a);
2074 			CiFreeClientEnumCa(&a);
2075 		}
2076 	}
2077 	else if (StrCmpi(name, "AddCa") == 0)
2078 	{
2079 		RPC_CERT a;
2080 		InRpcCert(&a, p);
2081 		if (CtAddCa(c, &a) == false)
2082 		{
2083 			RpcError(ret, c->Err);
2084 		}
2085 		FreeX(a.x);
2086 	}
2087 	else if (StrCmpi(name, "DeleteCa") == 0)
2088 	{
2089 		RPC_CLIENT_DELETE_CA a;
2090 		InRpcClientDeleteCa(&a, p);
2091 		if (CtDeleteCa(c, &a) == false)
2092 		{
2093 			RpcError(ret, c->Err);
2094 		}
2095 	}
2096 	else if (StrCmpi(name, "GetCa") == 0)
2097 	{
2098 		RPC_GET_CA a;
2099 		InRpcGetCa(&a, p);
2100 		if (CtGetCa(c, &a) == false)
2101 		{
2102 			RpcError(ret, c->Err);
2103 		}
2104 		else
2105 		{
2106 			OutRpcGetCa(ret, &a);
2107 		}
2108 		CiFreeGetCa(&a);
2109 	}
2110 	else if (StrCmpi(name, "EnumSecure") == 0)
2111 	{
2112 		RPC_CLIENT_ENUM_SECURE a;
2113 		if (CtEnumSecure(c, &a) == false)
2114 		{
2115 			RpcError(ret, c->Err);
2116 		}
2117 		else
2118 		{
2119 			OutRpcClientEnumSecure(ret, &a);
2120 			CiFreeClientEnumSecure(&a);
2121 		}
2122 	}
2123 	else if (StrCmpi(name, "UseSecure") == 0)
2124 	{
2125 		RPC_USE_SECURE a;
2126 		InRpcUseSecure(&a, p);
2127 		if (CtUseSecure(c, &a) == false)
2128 		{
2129 			RpcError(ret, c->Err);
2130 		}
2131 	}
2132 	else if (StrCmpi(name, "GetUseSecure") == 0)
2133 	{
2134 		RPC_USE_SECURE a;
2135 		Zero(&a, sizeof(a));
2136 		if (CtGetUseSecure(c, &a) == false)
2137 		{
2138 			RpcError(ret, c->Err);
2139 		}
2140 		else
2141 		{
2142 			OutRpcUseSecure(ret, &a);
2143 		}
2144 	}
2145 	else if (StrCmpi(name, "EnumObjectInSecure") == 0)
2146 	{
2147 		RPC_ENUM_OBJECT_IN_SECURE a;
2148 		if (CtEnumObjectInSecure(c, &a) == false)
2149 		{
2150 			RpcError(ret, c->Err);
2151 		}
2152 		else
2153 		{
2154 			OutRpcEnumObjectInSecure(ret, &a);
2155 			CiFreeEnumObjectInSecure(&a);
2156 		}
2157 	}
2158 	else if (StrCmpi(name, "CreateVLan") == 0)
2159 	{
2160 		RPC_CLIENT_CREATE_VLAN a;
2161 		InRpcCreateVLan(&a, p);
2162 		if (CtCreateVLan(c, &a) == false)
2163 		{
2164 			RpcError(ret, c->Err);
2165 		}
2166 	}
2167 	else if (StrCmpi(name, "UpgradeVLan") == 0)
2168 	{
2169 		RPC_CLIENT_CREATE_VLAN a;
2170 		InRpcCreateVLan(&a, p);
2171 		if (CtUpgradeVLan(c, &a) == false)
2172 		{
2173 			RpcError(ret, c->Err);
2174 		}
2175 	}
2176 	else if (StrCmpi(name, "GetVLan") == 0)
2177 	{
2178 		RPC_CLIENT_GET_VLAN a;
2179 		InRpcClientGetVLan(&a, p);
2180 		if (CtGetVLan(c, &a) == false)
2181 		{
2182 			RpcError(ret, c->Err);
2183 		}
2184 		else
2185 		{
2186 			OutRpcClientGetVLan(ret, &a);
2187 		}
2188 	}
2189 	else if (StrCmpi(name, "SetVLan") == 0)
2190 	{
2191 		RPC_CLIENT_SET_VLAN a;
2192 		InRpcClientSetVLan(&a, p);
2193 		if (CtSetVLan(c, &a) == false)
2194 		{
2195 			RpcError(ret, c->Err);
2196 		}
2197 	}
2198 	else if (StrCmpi(name, "EnumVLan") == 0)
2199 	{
2200 		RPC_CLIENT_ENUM_VLAN a;
2201 		if (CtEnumVLan(c, &a) == false)
2202 		{
2203 			RpcError(ret, c->Err);
2204 		}
2205 		else
2206 		{
2207 			OutRpcClientEnumVLan(ret, &a);
2208 			CiFreeClientEnumVLan(&a);
2209 		}
2210 	}
2211 	else if (StrCmpi(name, "DeleteVLan") == 0)
2212 	{
2213 		RPC_CLIENT_CREATE_VLAN a;
2214 		InRpcCreateVLan(&a, p);
2215 		if (CtDeleteVLan(c, &a) == false)
2216 		{
2217 			RpcError(ret, c->Err);
2218 		}
2219 	}
2220 	else if (StrCmpi(name, "EnableVLan") == 0)
2221 	{
2222 		RPC_CLIENT_CREATE_VLAN a;
2223 		InRpcCreateVLan(&a, p);
2224 		if (CtEnableVLan(c, &a) == false)
2225 		{
2226 			RpcError(ret, c->Err);
2227 		}
2228 	}
2229 	else if (StrCmpi(name, "DisableVLan") == 0)
2230 	{
2231 		RPC_CLIENT_CREATE_VLAN a;
2232 		InRpcCreateVLan(&a, p);
2233 		if (CtDisableVLan(c, &a) == false)
2234 		{
2235 			RpcError(ret, c->Err);
2236 		}
2237 	}
2238 	else if (StrCmpi(name, "CreateAccount") == 0)
2239 	{
2240 		RPC_CLIENT_CREATE_ACCOUNT a;
2241 		InRpcClientCreateAccount(&a, p);
2242 		if (CtCreateAccount(c, &a, false) == false)
2243 		{
2244 			RpcError(ret, c->Err);
2245 		}
2246 		CiFreeClientCreateAccount(&a);
2247 	}
2248 	else if (StrCmpi(name, "EnumAccount") == 0)
2249 	{
2250 		RPC_CLIENT_ENUM_ACCOUNT a;
2251 		if (CtEnumAccount(c, &a) == false)
2252 		{
2253 			RpcError(ret, c->Err);
2254 		}
2255 		else
2256 		{
2257 			OutRpcClientEnumAccount(ret, &a);
2258 			CiFreeClientEnumAccount(&a);
2259 		}
2260 	}
2261 	else if (StrCmpi(name, "DeleteAccount") == 0)
2262 	{
2263 		RPC_CLIENT_DELETE_ACCOUNT a;
2264 		InRpcClientDeleteAccount(&a, p);
2265 		if (CtDeleteAccount(c, &a, false) == false)
2266 		{
2267 			RpcError(ret, c->Err);
2268 		}
2269 	}
2270 	else if (StrCmpi(name, "SetStartupAccount") == 0)
2271 	{
2272 		RPC_CLIENT_DELETE_ACCOUNT a;
2273 		InRpcClientDeleteAccount(&a, p);
2274 		if (CtSetStartupAccount(c, &a, false) == false)
2275 		{
2276 			RpcError(ret, c->Err);
2277 		}
2278 	}
2279 	else if (StrCmpi(name, "RemoveStartupAccount") == 0)
2280 	{
2281 		RPC_CLIENT_DELETE_ACCOUNT a;
2282 		InRpcClientDeleteAccount(&a, p);
2283 		if (CtRemoveStartupAccount(c, &a) == false)
2284 		{
2285 			RpcError(ret, c->Err);
2286 		}
2287 	}
2288 	else if (StrCmpi(name, "GetIssuer") == 0)
2289 	{
2290 		RPC_GET_ISSUER a;
2291 		InRpcGetIssuer(&a, p);
2292 		if (CtGetIssuer(c, &a))
2293 		{
2294 			OutRpcGetIssuer(ret, &a);
2295 		}
2296 		else
2297 		{
2298 			RpcError(ret, c->Err);
2299 		}
2300 		CiFreeGetIssuer(&a);
2301 	}
2302 	else if (StrCmpi(name, "GetCommonProxySetting") == 0)
2303 	{
2304 		INTERNET_SETTING t;
2305 		InRpcInternetSetting(&t, p);
2306 		if (CtGetCommonProxySetting(c, &t))
2307 		{
2308 			OutRpcInternetSetting(ret, &t);
2309 		}
2310 		else
2311 		{
2312 			RpcError(ret, c->Err);
2313 		}
2314 	}
2315 	else if (StrCmpi(name, "SetCommonProxySetting") == 0)
2316 	{
2317 		INTERNET_SETTING t;
2318 		InRpcInternetSetting(&t, p);
2319 		if (CtSetCommonProxySetting(c, &t))
2320 		{
2321 			OutRpcInternetSetting(ret, &t);
2322 		}
2323 		else
2324 		{
2325 			RpcError(ret, c->Err);
2326 		}
2327 	}
2328 	else if (StrCmpi(name, "SetAccount") == 0)
2329 	{
2330 		RPC_CLIENT_CREATE_ACCOUNT a;
2331 		InRpcClientCreateAccount(&a, p);
2332 		if (CtSetAccount(c, &a, false) == false)
2333 		{
2334 			RpcError(ret, c->Err);
2335 		}
2336 		CiFreeClientCreateAccount(&a);
2337 	}
2338 	else if (StrCmpi(name, "GetAccount") == 0)
2339 	{
2340 		RPC_CLIENT_GET_ACCOUNT a;
2341 		InRpcClientGetAccount(&a, p);
2342 		if (CtGetAccount(c, &a) == false)
2343 		{
2344 			RpcError(ret, c->Err);
2345 		}
2346 		else
2347 		{
2348 			OutRpcClientGetAccount(ret, &a);
2349 		}
2350 		CiFreeClientGetAccount(&a);
2351 	}
2352 	else if (StrCmpi(name, "RenameAccount") == 0)
2353 	{
2354 		RPC_RENAME_ACCOUNT a;
2355 		InRpcRenameAccount(&a, p);
2356 		if (CtRenameAccount(c, &a, false) == false)
2357 		{
2358 			RpcError(ret, c->Err);
2359 		}
2360 	}
2361 	else if (StrCmpi(name, "SetClientConfig") == 0)
2362 	{
2363 		CLIENT_CONFIG a;
2364 		InRpcClientConfig(&a, p);
2365 		if (CtSetClientConfig(c, &a) == false)
2366 		{
2367 			RpcError(ret, c->Err);
2368 		}
2369 	}
2370 	else if (StrCmpi(name, "GetClientConfig") == 0)
2371 	{
2372 		CLIENT_CONFIG a;
2373 		if (CtGetClientConfig(c, &a) == false)
2374 		{
2375 			RpcError(ret, c->Err);
2376 		}
2377 		else
2378 		{
2379 			OutRpcClientConfig(ret, &a);
2380 		}
2381 	}
2382 	else if (StrCmpi(name, "Connect") == 0)
2383 	{
2384 		RPC_CLIENT_CONNECT a;
2385 		InRpcClientConnect(&a, p);
2386 		if (CtConnect(c, &a) == false)
2387 		{
2388 			RpcError(ret, c->Err);
2389 		}
2390 	}
2391 	else if (StrCmpi(name, "Disconnect") == 0)
2392 	{
2393 		RPC_CLIENT_CONNECT a;
2394 		InRpcClientConnect(&a, p);
2395 		if (CtDisconnect(c, &a, false) == false)
2396 		{
2397 			RpcError(ret, c->Err);
2398 		}
2399 	}
2400 	else if (StrCmpi(name, "GetAccountStatus") == 0)
2401 	{
2402 		RPC_CLIENT_GET_CONNECTION_STATUS a;
2403 		InRpcClientGetConnectionStatus(&a, p);
2404 		if (CtGetAccountStatus(c, &a) == false)
2405 		{
2406 			RpcError(ret, c->Err);
2407 		}
2408 		else
2409 		{
2410 			OutRpcClientGetConnectionStatus(ret, &a);
2411 		}
2412 		CiFreeClientGetConnectionStatus(&a);
2413 	}
2414 	else
2415 	{
2416 		FreePack(ret);
2417 		ret = NULL;
2418 	}
2419 
2420 	return ret;
2421 }
2422 
2423 // Set the CM_SETTING
CcSetCmSetting(REMOTE_CLIENT * r,CM_SETTING * a)2424 UINT CcSetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a)
2425 {
2426 	PACK *ret, *p;
2427 	UINT err;
2428 	// Validate arguments
2429 	if (r == NULL || a == NULL)
2430 	{
2431 		return ERR_INTERNAL_ERROR;
2432 	}
2433 
2434 	p = NewPack();
2435 	OutRpcCmSetting(p, a);
2436 
2437 	ret = RpcCall(r->Rpc, "SetCmSetting", p);
2438 
2439 	if (RpcIsOk(ret))
2440 	{
2441 		FreePack(ret);
2442 		return 0;
2443 	}
2444 	else
2445 	{
2446 		err = RpcGetError(ret);
2447 		FreePack(ret);
2448 		return err;
2449 	}
2450 }
2451 
2452 // Get the CM_SETTING
CcGetCmSetting(REMOTE_CLIENT * r,CM_SETTING * a)2453 UINT CcGetCmSetting(REMOTE_CLIENT *r, CM_SETTING *a)
2454 {
2455 	PACK *ret;
2456 	// Validate arguments
2457 	if (r == NULL || a == NULL)
2458 	{
2459 		return ERR_INTERNAL_ERROR;
2460 	}
2461 
2462 	ret = RpcCall(r->Rpc, "GetCmSetting", NULL);
2463 
2464 	if (RpcIsOk(ret))
2465 	{
2466 		InRpcCmSetting(a, ret);
2467 		FreePack(ret);
2468 		return 0;
2469 	}
2470 	else
2471 	{
2472 		UINT err = RpcGetError(ret);
2473 		FreePack(ret);
2474 		return err;
2475 	}
2476 }
2477 
2478 // Get the client version
CcGetClientVersion(REMOTE_CLIENT * r,RPC_CLIENT_VERSION * a)2479 UINT CcGetClientVersion(REMOTE_CLIENT *r, RPC_CLIENT_VERSION *a)
2480 {
2481 	PACK *ret;
2482 	// Validate arguments
2483 	if (r == NULL || a == NULL)
2484 	{
2485 		return ERR_INTERNAL_ERROR;
2486 	}
2487 
2488 	ret = RpcCall(r->Rpc, "GetClientVersion", NULL);
2489 
2490 	if (RpcIsOk(ret))
2491 	{
2492 		InRpcClientVersion(a, ret);
2493 		FreePack(ret);
2494 		return 0;
2495 	}
2496 	else
2497 	{
2498 		UINT err = RpcGetError(ret);
2499 		FreePack(ret);
2500 		return err;
2501 	}
2502 }
2503 
2504 // Set the password
CcSetPassword(REMOTE_CLIENT * r,RPC_CLIENT_PASSWORD * pass)2505 UINT CcSetPassword(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD *pass)
2506 {
2507 	PACK *ret, *p;
2508 	// Validate arguments
2509 	if (r == NULL || pass == NULL)
2510 	{
2511 		return ERR_INTERNAL_ERROR;
2512 	}
2513 
2514 	p = NewPack();
2515 
2516 	OutRpcClientPassword(p, pass);
2517 
2518 	ret = RpcCall(r->Rpc, "SetPassword", p);
2519 
2520 	if (RpcIsOk(ret))
2521 	{
2522 		FreePack(ret);
2523 		return 0;
2524 	}
2525 	else
2526 	{
2527 		UINT err = RpcGetError(ret);
2528 		FreePack(ret);
2529 		return err;
2530 	}
2531 }
2532 
2533 // Get the password setting
CcGetPasswordSetting(REMOTE_CLIENT * r,RPC_CLIENT_PASSWORD_SETTING * a)2534 UINT CcGetPasswordSetting(REMOTE_CLIENT *r, RPC_CLIENT_PASSWORD_SETTING *a)
2535 {
2536 	PACK *ret;
2537 	UINT err = 0;
2538 	// Validate arguments
2539 	if (r == NULL || a == NULL)
2540 	{
2541 		return ERR_INTERNAL_ERROR;
2542 	}
2543 
2544 	ret = RpcCall(r->Rpc, "GetPasswordSetting", NULL);
2545 
2546 	if (RpcIsOk(ret))
2547 	{
2548 		InRpcClientPasswordSetting(a, ret);
2549 	}
2550 	else
2551 	{
2552 		err = RpcGetError(ret);
2553 	}
2554 
2555 	FreePack(ret);
2556 	return err;
2557 }
2558 
2559 // Enumerate the CA
CcEnumCa(REMOTE_CLIENT * r,RPC_CLIENT_ENUM_CA * e)2560 UINT CcEnumCa(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_CA *e)
2561 {
2562 	PACK *ret;
2563 	UINT err = 0;
2564 	// Validate arguments
2565 	if (r == NULL || e == NULL)
2566 	{
2567 		return ERR_INTERNAL_ERROR;
2568 	}
2569 
2570 	ret = RpcCall(r->Rpc, "EnumCa", NULL);
2571 
2572 	if (RpcIsOk(ret))
2573 	{
2574 		InRpcClientEnumCa(e, ret);
2575 	}
2576 	else
2577 	{
2578 		err = RpcGetError(ret);
2579 	}
2580 
2581 	FreePack(ret);
2582 
2583 	return err;
2584 }
2585 
2586 // Add the CA
CcAddCa(REMOTE_CLIENT * r,RPC_CERT * cert)2587 UINT CcAddCa(REMOTE_CLIENT *r, RPC_CERT *cert)
2588 {
2589 	PACK *p, *ret;
2590 	UINT err = 0;
2591 	// Validate arguments
2592 	if (r == NULL || cert == NULL)
2593 	{
2594 		return ERR_INTERNAL_ERROR;
2595 	}
2596 
2597 	p = NewPack();
2598 	OutRpcCert(p, cert);
2599 
2600 	ret = RpcCall(r->Rpc, "AddCa", p);
2601 
2602 	if (RpcIsOk(ret) == false)
2603 	{
2604 		err = RpcGetError(ret);
2605 	}
2606 
2607 	FreePack(ret);
2608 
2609 	return err;
2610 }
2611 
2612 // Delete the CA
CcDeleteCa(REMOTE_CLIENT * r,RPC_CLIENT_DELETE_CA * c)2613 UINT CcDeleteCa(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_CA *c)
2614 {
2615 	PACK *p, *ret;
2616 	UINT err = 0;
2617 	// Validate arguments
2618 	if (r == NULL || c == NULL)
2619 	{
2620 		return ERR_INTERNAL_ERROR;
2621 	}
2622 
2623 	p = NewPack();
2624 	OutRpcClientDeleteCa(p, c);
2625 
2626 	ret = RpcCall(r->Rpc, "DeleteCa", p);
2627 
2628 	if (RpcIsOk(ret) == false)
2629 	{
2630 		err = RpcGetError(ret);
2631 	}
2632 
2633 	FreePack(ret);
2634 
2635 	return err;
2636 }
2637 
2638 // Get the issuer
CcGetIssuer(REMOTE_CLIENT * r,RPC_GET_ISSUER * a)2639 UINT CcGetIssuer(REMOTE_CLIENT *r, RPC_GET_ISSUER *a)
2640 {
2641 	PACK *p, *ret;
2642 	UINT err = 0;
2643 	// Validate arguments
2644 	if (r == NULL || a == NULL)
2645 	{
2646 		return ERR_INTERNAL_ERROR;
2647 	}
2648 
2649 	p = NewPack();
2650 	OutRpcGetIssuer(p, a);
2651 
2652 	ret = RpcCall(r->Rpc, "GetIssuer", p);
2653 
2654 	if (RpcIsOk(ret))
2655 	{
2656 		if (a->x != NULL)
2657 		{
2658 			FreeX(a->x);
2659 			a->x = NULL;
2660 		}
2661 		InRpcGetIssuer(a, ret);
2662 	}
2663 	else
2664 	{
2665 		err = RpcGetError(ret);
2666 	}
2667 
2668 	FreePack(ret);
2669 
2670 	return err;
2671 }
2672 
2673 // Get the CA
CcGetCa(REMOTE_CLIENT * r,RPC_GET_CA * get)2674 UINT CcGetCa(REMOTE_CLIENT *r, RPC_GET_CA *get)
2675 {
2676 	PACK *p, *ret;
2677 	UINT err = 0;
2678 	// Validate arguments
2679 	if (r == NULL || get == NULL)
2680 	{
2681 		return ERR_INTERNAL_ERROR;
2682 	}
2683 
2684 	p = NewPack();
2685 	OutRpcGetCa(p, get);
2686 
2687 	ret = RpcCall(r->Rpc, "GetCa", p);
2688 
2689 	if (RpcIsOk(ret))
2690 	{
2691 		InRpcGetCa(get, ret);
2692 	}
2693 	else
2694 	{
2695 		err = RpcGetError(ret);
2696 	}
2697 
2698 	FreePack(ret);
2699 
2700 	return err;
2701 }
2702 
2703 // Enumeration of the secure devices
CcEnumSecure(REMOTE_CLIENT * r,RPC_CLIENT_ENUM_SECURE * e)2704 UINT CcEnumSecure(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_SECURE *e)
2705 {
2706 	PACK *ret;
2707 	UINT err = 0;
2708 	// Validate arguments
2709 	if (r == NULL || e == NULL)
2710 	{
2711 		return ERR_INTERNAL_ERROR;
2712 	}
2713 
2714 	ret = RpcCall(r->Rpc, "EnumSecure", NULL);
2715 
2716 	if (RpcIsOk(ret))
2717 	{
2718 		InRpcClientEnumSecure(e, ret);
2719 	}
2720 	else
2721 	{
2722 		err = RpcGetError(ret);
2723 	}
2724 
2725 	FreePack(ret);
2726 
2727 	return err;
2728 }
2729 
2730 // Get the secure device that the user is using
CcGetUseSecure(REMOTE_CLIENT * r,RPC_USE_SECURE * sec)2731 UINT CcGetUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec)
2732 {
2733 	PACK *p, *ret;
2734 	UINT err = 0;
2735 	// Validate arguments
2736 	if (r == NULL || sec == NULL)
2737 	{
2738 		return ERR_INTERNAL_ERROR;
2739 	}
2740 
2741 	p = NewPack();
2742 
2743 	ret = RpcCall(r->Rpc, "GetUseSecure", p);
2744 
2745 	if (RpcIsOk(ret) == false)
2746 	{
2747 		err = RpcGetError(ret);
2748 	}
2749 	else
2750 	{
2751 		InRpcUseSecure(sec, ret);
2752 	}
2753 
2754 	FreePack(ret);
2755 
2756 	return err;
2757 }
2758 
2759 // Use the secure device
CcUseSecure(REMOTE_CLIENT * r,RPC_USE_SECURE * sec)2760 UINT CcUseSecure(REMOTE_CLIENT *r, RPC_USE_SECURE *sec)
2761 {
2762 	PACK *p, *ret;
2763 	UINT err = 0;
2764 	// Validate arguments
2765 	if (r == NULL || sec == NULL)
2766 	{
2767 		return ERR_INTERNAL_ERROR;
2768 	}
2769 
2770 	p = NewPack();
2771 	OutRpcUseSecure(p, sec);
2772 
2773 	ret = RpcCall(r->Rpc, "UseSecure", p);
2774 
2775 	if (RpcIsOk(ret) == false)
2776 	{
2777 		err = RpcGetError(ret);
2778 	}
2779 
2780 	FreePack(ret);
2781 
2782 	return err;
2783 }
2784 
2785 // Get a next recommended virtual LAN card name
CiGetNextRecommendedVLanName(REMOTE_CLIENT * r,char * name,UINT size)2786 bool CiGetNextRecommendedVLanName(REMOTE_CLIENT *r, char *name, UINT size)
2787 {
2788 	RPC_CLIENT_ENUM_VLAN t;
2789 	UINT i;
2790 	bool b;
2791 	UINT j;
2792 	bool ok = false;
2793 	// Validate arguments
2794 	if (r == NULL || name == NULL)
2795 	{
2796 		return false;
2797 	}
2798 
2799 	Zero(&t, sizeof(t));
2800 
2801 	if (CcEnumVLan(r, &t) != ERR_NO_ERROR)
2802 	{
2803 		return false;
2804 	}
2805 
2806 	for (i = 1;i < 128;i++)
2807 	{
2808 		char tmp[MAX_SIZE];
2809 
2810 		CiGenerateVLanRegulatedName(tmp, sizeof(tmp), i);
2811 
2812 		b = false;
2813 
2814 		for (j = 0;j < t.NumItem;j++)
2815 		{
2816 			if (StrCmpi(t.Items[j]->DeviceName, tmp) == 0)
2817 			{
2818 				b = true;
2819 				break;
2820 			}
2821 		}
2822 
2823 		if (b == false)
2824 		{
2825 			ok = true;
2826 
2827 			StrCpy(name, size, tmp);
2828 			break;
2829 		}
2830 	}
2831 
2832 	if (ok)
2833 	{
2834 		CiFreeClientEnumVLan(&t);
2835 	}
2836 
2837 	return true;
2838 }
2839 
2840 // Generate a virtual LAN card name automatically
CiGenerateVLanRegulatedName(char * name,UINT size,UINT i)2841 void CiGenerateVLanRegulatedName(char *name, UINT size, UINT i)
2842 {
2843 	// Validate arguments
2844 	if (name == NULL)
2845 	{
2846 		return;
2847 	}
2848 
2849 	if (i == 1)
2850 	{
2851 		StrCpy(name, size, "VPN");
2852 	}
2853 	else
2854 	{
2855 		Format(name, size, "VPN%u", i);
2856 	}
2857 }
2858 
2859 // Examine whether the specified name is valid as a virtual LAN card name of Windows 8 and later?
CiIsValidVLanRegulatedName(char * name)2860 bool CiIsValidVLanRegulatedName(char *name)
2861 {
2862 	UINT i;
2863 	// Validate arguments
2864 	if (name == NULL)
2865 	{
2866 		return false;
2867 	}
2868 
2869 	for (i = 1;i < 128;i++)
2870 	{
2871 		char tmp[MAX_SIZE];
2872 
2873 		CiGenerateVLanRegulatedName(tmp, sizeof(tmp), i);
2874 
2875 		if (StrCmpi(name, tmp) == 0)
2876 		{
2877 			return true;
2878 		}
2879 	}
2880 
2881 	return false;
2882 }
2883 
2884 // Create a VLAN
CcCreateVLan(REMOTE_CLIENT * r,RPC_CLIENT_CREATE_VLAN * create)2885 UINT CcCreateVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create)
2886 {
2887 	PACK *ret, *p;
2888 	UINT err = 0;
2889 	char *s = NULL;
2890 	// Validate arguments
2891 	if (r == NULL || create == NULL)
2892 	{
2893 		return ERR_INTERNAL_ERROR;
2894 	}
2895 
2896 	p = NewPack();
2897 	OutRpcCreateVLan(p, create);
2898 
2899 #ifdef	OS_WIN32
2900 	s = MsNoWarningSoundInit();
2901 #endif	// OS_WIN32
2902 
2903 	ret = RpcCall(r->Rpc, "CreateVLan", p);
2904 
2905 #ifdef	OS_WIN32
2906 	MsNoWarningSoundFree(s);
2907 #endif	// OS_WIN32
2908 
2909 	if (RpcIsOk(ret) == false)
2910 	{
2911 		err = RpcGetError(ret);
2912 	}
2913 
2914 	FreePack(ret);
2915 
2916 	return err;
2917 }
2918 
2919 // Upgrade the VLAN
CcUpgradeVLan(REMOTE_CLIENT * r,RPC_CLIENT_CREATE_VLAN * create)2920 UINT CcUpgradeVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *create)
2921 {
2922 	PACK *ret, *p;
2923 	UINT err = 0;
2924 	char *s = NULL;
2925 	// Validate arguments
2926 	if (r == NULL || create == NULL)
2927 	{
2928 		return ERR_INTERNAL_ERROR;
2929 	}
2930 
2931 	p = NewPack();
2932 	OutRpcCreateVLan(p, create);
2933 
2934 #ifdef	OS_WIN32
2935 	s = MsNoWarningSoundInit();
2936 #endif	// OS_WIN32
2937 
2938 	ret = RpcCall(r->Rpc, "UpgradeVLan", p);
2939 
2940 #ifdef	OS_WIN32
2941 	MsNoWarningSoundFree(s);
2942 #endif	// OS_WIN32
2943 
2944 
2945 	if (RpcIsOk(ret) == false)
2946 	{
2947 		err = RpcGetError(ret);
2948 	}
2949 
2950 	FreePack(ret);
2951 
2952 	return err;
2953 }
2954 
2955 // Get the VLAN
CcGetVLan(REMOTE_CLIENT * r,RPC_CLIENT_GET_VLAN * get)2956 UINT CcGetVLan(REMOTE_CLIENT *r, RPC_CLIENT_GET_VLAN *get)
2957 {
2958 	PACK *ret, *p;
2959 	UINT err = 0;
2960 	// Validate arguments
2961 	if (r == NULL || get == NULL)
2962 	{
2963 		return ERR_INTERNAL_ERROR;
2964 	}
2965 
2966 	p = NewPack();
2967 	OutRpcClientGetVLan(p, get);
2968 
2969 	ret = RpcCall(r->Rpc, "GetVLan", p);
2970 
2971 	if (RpcIsOk(ret))
2972 	{
2973 		InRpcClientGetVLan(get, ret);
2974 	}
2975 	else
2976 	{
2977 		err = RpcGetError(ret);
2978 	}
2979 
2980 	FreePack(ret);
2981 
2982 	return err;
2983 }
2984 
2985 // VLAN configuration
CcSetVLan(REMOTE_CLIENT * r,RPC_CLIENT_SET_VLAN * set)2986 UINT CcSetVLan(REMOTE_CLIENT *r, RPC_CLIENT_SET_VLAN *set)
2987 {
2988 	PACK *ret, *p;
2989 	UINT err = 0;
2990 	// Validate arguments
2991 	if (r == NULL || set == NULL)
2992 	{
2993 		return ERR_INTERNAL_ERROR;
2994 	}
2995 
2996 	p = NewPack();
2997 	OutRpcClientSetVLan(p, set);
2998 
2999 	ret = RpcCall(r->Rpc, "SetVLan", p);
3000 
3001 	if (RpcIsOk(ret) == false)
3002 	{
3003 		err = RpcGetError(ret);
3004 	}
3005 
3006 	FreePack(ret);
3007 
3008 	return err;
3009 }
3010 
3011 // Enumeration of VLAN
CcEnumVLan(REMOTE_CLIENT * r,RPC_CLIENT_ENUM_VLAN * e)3012 UINT CcEnumVLan(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_VLAN *e)
3013 {
3014 	PACK *ret;
3015 	UINT err = 0;
3016 	// Validate arguments
3017 	if (r == NULL || e == NULL)
3018 	{
3019 		return ERR_INTERNAL_ERROR;
3020 	}
3021 
3022 	ret = RpcCall(r->Rpc, "EnumVLan", NULL);
3023 
3024 	if (RpcIsOk(ret))
3025 	{
3026 		InRpcClientEnumVLan(e, ret);
3027 	}
3028 	else
3029 	{
3030 		err = RpcGetError(ret);
3031 	}
3032 
3033 	FreePack(ret);
3034 
3035 	return err;
3036 }
3037 
3038 // Delete the VLAN
CcDeleteVLan(REMOTE_CLIENT * r,RPC_CLIENT_CREATE_VLAN * d)3039 UINT CcDeleteVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *d)
3040 {
3041 	PACK *ret, *p;
3042 	UINT err = 0;
3043 	// Validate arguments
3044 	if (r == NULL || d == NULL)
3045 	{
3046 		return ERR_INTERNAL_ERROR;
3047 	}
3048 
3049 	p = NewPack();
3050 	OutRpcCreateVLan(p, d);
3051 
3052 	ret = RpcCall(r->Rpc, "DeleteVLan", p);
3053 
3054 	if (RpcIsOk(ret) == false)
3055 	{
3056 		err = RpcGetError(ret);
3057 	}
3058 
3059 	FreePack(ret);
3060 
3061 	return err;
3062 }
3063 
3064 // Enable the VLAN
CcEnableVLan(REMOTE_CLIENT * r,RPC_CLIENT_CREATE_VLAN * vlan)3065 UINT CcEnableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan)
3066 {
3067 	PACK *ret, *p;
3068 	UINT err = 0;
3069 	// Validate arguments
3070 	if (r == NULL || vlan == NULL)
3071 	{
3072 		return ERR_INTERNAL_ERROR;
3073 	}
3074 
3075 	p = NewPack();
3076 	OutRpcCreateVLan(p, vlan);
3077 
3078 	ret = RpcCall(r->Rpc, "EnableVLan", p);
3079 
3080 	if (RpcIsOk(ret) == false)
3081 	{
3082 		err = RpcGetError(ret);
3083 	}
3084 
3085 	FreePack(ret);
3086 
3087 	return err;
3088 }
3089 
3090 // Disable the VLAN
CcDisableVLan(REMOTE_CLIENT * r,RPC_CLIENT_CREATE_VLAN * vlan)3091 UINT CcDisableVLan(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_VLAN *vlan)
3092 {
3093 	PACK *ret, *p;
3094 	UINT err = 0;
3095 	// Validate arguments
3096 	if (r == NULL || vlan == NULL)
3097 	{
3098 		return ERR_INTERNAL_ERROR;
3099 	}
3100 
3101 	p = NewPack();
3102 	OutRpcCreateVLan(p, vlan);
3103 
3104 	ret = RpcCall(r->Rpc, "DisableVLan", p);
3105 
3106 	if (RpcIsOk(ret) == false)
3107 	{
3108 		err = RpcGetError(ret);
3109 	}
3110 
3111 	FreePack(ret);
3112 
3113 	return err;
3114 }
3115 
3116 // Create an Account
CcCreateAccount(REMOTE_CLIENT * r,RPC_CLIENT_CREATE_ACCOUNT * a)3117 UINT CcCreateAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a)
3118 {
3119 	PACK *ret, *p;
3120 	UINT err = 0;
3121 	// Validate arguments
3122 	if (r == NULL || a == NULL)
3123 	{
3124 		return ERR_INTERNAL_ERROR;
3125 	}
3126 
3127 	p = NewPack();
3128 	OutRpcClientCreateAccount(p, a);
3129 
3130 	ret = RpcCall(r->Rpc, "CreateAccount", p);
3131 
3132 	if (RpcIsOk(ret) == false)
3133 	{
3134 		err = RpcGetError(ret);
3135 	}
3136 
3137 	FreePack(ret);
3138 
3139 	return err;
3140 }
3141 
3142 // Enumeration of accounts
CcEnumAccount(REMOTE_CLIENT * r,RPC_CLIENT_ENUM_ACCOUNT * e)3143 UINT CcEnumAccount(REMOTE_CLIENT *r, RPC_CLIENT_ENUM_ACCOUNT *e)
3144 {
3145 	PACK *ret;
3146 	UINT err = 0;
3147 	// Validate arguments
3148 	if (r == NULL || e == NULL)
3149 	{
3150 		return ERR_INTERNAL_ERROR;
3151 	}
3152 
3153 	ret = RpcCall(r->Rpc, "EnumAccount", NULL);
3154 
3155 	if (RpcIsOk(ret))
3156 	{
3157 		UINT i;
3158 		InRpcClientEnumAccount(e, ret);
3159 
3160 		for (i = 0;i < e->NumItem;i++)
3161 		{
3162 			RPC_CLIENT_ENUM_ACCOUNT_ITEM *t = e->Items[i];
3163 
3164 			if (IsEmptyStr(t->HubName) && t->Port == 0)
3165 			{
3166 				UINT err2;
3167 				RPC_CLIENT_GET_ACCOUNT a;
3168 
3169 				// Because the Client Manager can not get the port number and HUB name
3170 				// when enumerating in the VPN Client of the old version, get these separately.
3171 				Zero(&a, sizeof(a));
3172 				UniStrCpy(a.AccountName, sizeof(a.AccountName), t->AccountName);
3173 				err2 = CcGetAccount(r, &a);
3174 				if (err2 == ERR_NO_ERROR)
3175 				{
3176 					StrCpy(t->HubName, sizeof(t->HubName), a.ClientOption->HubName);
3177 					t->Port = a.ClientOption->Port;
3178 
3179 					CiFreeClientGetAccount(&a);
3180 				}
3181 			}
3182 		}
3183 	}
3184 	else
3185 	{
3186 		err = RpcGetError(ret);
3187 	}
3188 
3189 	FreePack(ret);
3190 
3191 	return err;
3192 }
3193 
3194 // Unset the startup flag of the account
CcRemoveStartupAccount(REMOTE_CLIENT * r,RPC_CLIENT_DELETE_ACCOUNT * a)3195 UINT CcRemoveStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
3196 {
3197 	PACK *ret, *p;
3198 	UINT err = 0;
3199 	// Validate arguments
3200 	if (r == NULL || a == NULL)
3201 	{
3202 		return ERR_INTERNAL_ERROR;
3203 	}
3204 
3205 	p = NewPack();
3206 	OutRpcClientDeleteAccount(p, a);
3207 
3208 	ret = RpcCall(r->Rpc, "RemoveStartupAccount", p);
3209 
3210 	if (RpcIsOk(ret) == false)
3211 	{
3212 		err = RpcGetError(ret);
3213 	}
3214 
3215 	FreePack(ret);
3216 
3217 	return err;
3218 }
3219 
3220 // Set to start-up flag of the account
CcSetStartupAccount(REMOTE_CLIENT * r,RPC_CLIENT_DELETE_ACCOUNT * a)3221 UINT CcSetStartupAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
3222 {
3223 	PACK *ret, *p;
3224 	UINT err = 0;
3225 	// Validate arguments
3226 	if (r == NULL || a == NULL)
3227 	{
3228 		return ERR_INTERNAL_ERROR;
3229 	}
3230 
3231 	p = NewPack();
3232 	OutRpcClientDeleteAccount(p, a);
3233 
3234 	ret = RpcCall(r->Rpc, "SetStartupAccount", p);
3235 
3236 	if (RpcIsOk(ret) == false)
3237 	{
3238 		err = RpcGetError(ret);
3239 	}
3240 
3241 	FreePack(ret);
3242 
3243 	return err;
3244 }
3245 
3246 // Delete the account
CcDeleteAccount(REMOTE_CLIENT * r,RPC_CLIENT_DELETE_ACCOUNT * a)3247 UINT CcDeleteAccount(REMOTE_CLIENT *r, RPC_CLIENT_DELETE_ACCOUNT *a)
3248 {
3249 	PACK *ret, *p;
3250 	UINT err = 0;
3251 	// Validate arguments
3252 	if (r == NULL || a == NULL)
3253 	{
3254 		return ERR_INTERNAL_ERROR;
3255 	}
3256 
3257 	p = NewPack();
3258 	OutRpcClientDeleteAccount(p, a);
3259 
3260 	ret = RpcCall(r->Rpc, "DeleteAccount", p);
3261 
3262 	if (RpcIsOk(ret) == false)
3263 	{
3264 		err = RpcGetError(ret);
3265 	}
3266 
3267 	FreePack(ret);
3268 
3269 	return err;
3270 }
3271 
3272 // Account setting
CcSetAccount(REMOTE_CLIENT * r,RPC_CLIENT_CREATE_ACCOUNT * a)3273 UINT CcSetAccount(REMOTE_CLIENT *r, RPC_CLIENT_CREATE_ACCOUNT *a)
3274 {
3275 	PACK *ret, *p;
3276 	UINT err = 0;
3277 	// Validate arguments
3278 	if (r == NULL || a == NULL)
3279 	{
3280 		return ERR_INTERNAL_ERROR;
3281 	}
3282 
3283 	p = NewPack();
3284 	OutRpcClientCreateAccount(p, a);
3285 
3286 	ret = RpcCall(r->Rpc, "SetAccount", p);
3287 
3288 	if (RpcIsOk(ret) == false)
3289 	{
3290 		err = RpcGetError(ret);
3291 	}
3292 
3293 	FreePack(ret);
3294 
3295 	return err;
3296 }
3297 
3298 // Get the account
CcGetAccount(REMOTE_CLIENT * r,RPC_CLIENT_GET_ACCOUNT * a)3299 UINT CcGetAccount(REMOTE_CLIENT *r, RPC_CLIENT_GET_ACCOUNT *a)
3300 {
3301 	PACK *ret, *p;
3302 	UINT err = 0;
3303 	// Validate arguments
3304 	if (r == NULL || a == NULL)
3305 	{
3306 		return ERR_INTERNAL_ERROR;
3307 	}
3308 
3309 	p = NewPack();
3310 	OutRpcClientGetAccount(p, a);
3311 
3312 	ret = RpcCall(r->Rpc, "GetAccount", p);
3313 
3314 	if (RpcIsOk(ret))
3315 	{
3316 		InRpcClientGetAccount(a, ret);
3317 	}
3318 	else
3319 	{
3320 		err = RpcGetError(ret);
3321 	}
3322 
3323 	FreePack(ret);
3324 
3325 	return err;
3326 }
3327 
3328 // Change the account name
CcRenameAccount(REMOTE_CLIENT * r,RPC_RENAME_ACCOUNT * rename)3329 UINT CcRenameAccount(REMOTE_CLIENT *r, RPC_RENAME_ACCOUNT *rename)
3330 {
3331 	PACK *p, *ret;
3332 	UINT err = 0;
3333 	// Validate arguments
3334 	if (r == NULL || rename == NULL)
3335 	{
3336 		return ERR_INTERNAL_ERROR;
3337 	}
3338 
3339 	p = NewPack();
3340 	OutRpcRenameAccount(p, rename);
3341 
3342 	ret = RpcCall(r->Rpc, "RenameAccount", p);
3343 
3344 	if (RpcIsOk(ret) == false)
3345 	{
3346 		err = RpcGetError(ret);
3347 	}
3348 
3349 	FreePack(ret);
3350 
3351 	return err;
3352 }
3353 
3354 // Set the Client configuration
CcSetClientConfig(REMOTE_CLIENT * r,CLIENT_CONFIG * o)3355 UINT CcSetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o)
3356 {
3357 	PACK *p, *ret;
3358 	UINT err = 0;
3359 	// Validate arguments
3360 	if (r == NULL || o == NULL)
3361 	{
3362 		return ERR_INTERNAL_ERROR;
3363 	}
3364 
3365 	p = NewPack();
3366 	OutRpcClientConfig(p, o);
3367 
3368 	ret = RpcCall(r->Rpc, "SetClientConfig", p);
3369 
3370 	if (RpcIsOk(ret) == false)
3371 	{
3372 		err = RpcGetError(ret);
3373 	}
3374 
3375 	FreePack(ret);
3376 
3377 	return err;
3378 }
3379 
3380 // Get the client configuration
CcGetClientConfig(REMOTE_CLIENT * r,CLIENT_CONFIG * o)3381 UINT CcGetClientConfig(REMOTE_CLIENT *r, CLIENT_CONFIG *o)
3382 {
3383 	PACK *ret;
3384 	UINT err = 0;
3385 	// Validate arguments
3386 	if (r == NULL || o == NULL)
3387 	{
3388 		return ERR_INTERNAL_ERROR;
3389 	}
3390 
3391 	ret = RpcCall(r->Rpc, "GetClientConfig", NULL);
3392 
3393 	if (RpcIsOk(ret))
3394 	{
3395 		InRpcClientConfig(o, ret);
3396 	}
3397 	else
3398 	{
3399 		err = RpcGetError(ret);
3400 	}
3401 
3402 	FreePack(ret);
3403 
3404 	return err;
3405 }
3406 
3407 // Set the service to foreground process
CcSetServiceToForegroundProcess(REMOTE_CLIENT * r)3408 void CcSetServiceToForegroundProcess(REMOTE_CLIENT *r)
3409 {
3410 	// Validate arguments
3411 	if (r == NULL)
3412 	{
3413 		return;
3414 	}
3415 	// Abolition
3416 /*
3417 	if (r->Rpc != NULL && r->Rpc->Sock != NULL && r->Rpc->Sock->RemoteIP.addr[0] == 127)
3418 	{
3419 		if (OS_IS_WINDOWS_NT(GetOsInfo()->OsType) &&
3420 			GET_KETA(GetOsInfo()->OsType, 100) >= 2)
3421 		{
3422 			// Only on a Windows 2000 or later
3423 			RPC_CLIENT_VERSION v;
3424 			Zero(&v, sizeof(v));
3425 
3426 			if (r->ClientBuildInt == 0)
3427 			{
3428 				CcGetClientVersion(r, &v);
3429 				r->ClientBuildInt = v.ClientBuildInt;
3430 				r->ProcessId = v.ProcessId;
3431 			}
3432 			if (r->ProcessId != 0 && r->ClientBuildInt <= 5080)
3433 			{
3434 #ifdef	OS_WIN32
3435 				// Set the service process as a foreground window
3436 				AllowFGWindow(v.ProcessId);
3437 #endif	// OS_WIN32
3438 			}
3439 		}
3440 	}*/
3441 }
3442 
3443 // Connect
CcConnect(REMOTE_CLIENT * r,RPC_CLIENT_CONNECT * connect)3444 UINT CcConnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect)
3445 {
3446 	PACK *ret, *p;
3447 	UINT err = 0;
3448 	// Validate arguments
3449 	if (r == NULL || connect == NULL)
3450 	{
3451 		return ERR_INTERNAL_ERROR;
3452 	}
3453 
3454 	CcSetServiceToForegroundProcess(r);
3455 
3456 	p = NewPack();
3457 	OutRpcClientConnect(p, connect);
3458 
3459 	ret = RpcCall(r->Rpc, "Connect", p);
3460 
3461 	if (RpcIsOk(ret) == false)
3462 	{
3463 		err = RpcGetError(ret);
3464 	}
3465 
3466 	FreePack(ret);
3467 
3468 	return err;
3469 }
3470 
3471 // Disconnect
CcDisconnect(REMOTE_CLIENT * r,RPC_CLIENT_CONNECT * connect)3472 UINT CcDisconnect(REMOTE_CLIENT *r, RPC_CLIENT_CONNECT *connect)
3473 {
3474 	PACK *ret, *p;
3475 	UINT err = 0;
3476 	// Validate arguments
3477 	if (r == NULL || connect == NULL)
3478 	{
3479 		return ERR_INTERNAL_ERROR;
3480 	}
3481 
3482 	CcSetServiceToForegroundProcess(r);
3483 
3484 	p = NewPack();
3485 	OutRpcClientConnect(p, connect);
3486 
3487 	ret = RpcCall(r->Rpc, "Disconnect", p);
3488 
3489 	if (RpcIsOk(ret) == false)
3490 	{
3491 		err = RpcGetError(ret);
3492 	}
3493 
3494 	FreePack(ret);
3495 
3496 	return err;
3497 }
3498 
3499 // Get the account status
CcGetAccountStatus(REMOTE_CLIENT * r,RPC_CLIENT_GET_CONNECTION_STATUS * st)3500 UINT CcGetAccountStatus(REMOTE_CLIENT *r, RPC_CLIENT_GET_CONNECTION_STATUS *st)
3501 {
3502 	PACK *ret, *p;
3503 	UINT err = 0;
3504 	// Validate arguments
3505 	if (r == NULL || st == NULL)
3506 	{
3507 		return ERR_INTERNAL_ERROR;
3508 	}
3509 
3510 	p = NewPack();
3511 	OutRpcClientGetConnectionStatus(p, st);
3512 
3513 	ret = RpcCall(r->Rpc, "GetAccountStatus", p);
3514 
3515 	if (RpcIsOk(ret))
3516 	{
3517 		InRpcClientGetConnectionStatus(st, ret);
3518 	}
3519 	else
3520 	{
3521 		err = RpcGetError(ret);
3522 	}
3523 
3524 	FreePack(ret);
3525 
3526 	return err;
3527 }
3528 
3529 
3530 // Client service sends a notification to the connection manager
CiNotify(CLIENT * c)3531 void CiNotify(CLIENT *c)
3532 {
3533 	CiNotifyInternal(c);
3534 }
CiNotifyInternal(CLIENT * c)3535 void CiNotifyInternal(CLIENT *c)
3536 {
3537 	// Validate arguments
3538 	if (c == NULL)
3539 	{
3540 		return;
3541 	}
3542 
3543 	// Set all the notification event
3544 	LockList(c->NotifyCancelList);
3545 	{
3546 		UINT i;
3547 		for (i = 0;i < LIST_NUM(c->NotifyCancelList);i++)
3548 		{
3549 			CANCEL *cancel = LIST_DATA(c->NotifyCancelList, i);
3550 			Cancel(cancel);
3551 		}
3552 	}
3553 	UnlockList(c->NotifyCancelList);
3554 }
3555 
3556 // Release the RPC_CLIENT_ENUM_ACCOUNT
CiFreeClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT * a)3557 void CiFreeClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *a)
3558 {
3559 	UINT i;
3560 	// Validate arguments
3561 	if (a == NULL)
3562 	{
3563 		return;
3564 	}
3565 
3566 	for (i = 0;i < a->NumItem;i++)
3567 	{
3568 		RPC_CLIENT_ENUM_ACCOUNT_ITEM *e = a->Items[i];
3569 		Free(e);
3570 	}
3571 	Free(a->Items);
3572 }
3573 
3574 
3575 // Thread to save the configuration file periodically
CiSaverThread(THREAD * t,void * param)3576 void CiSaverThread(THREAD *t, void *param)
3577 {
3578 	CLIENT *c = (CLIENT *)param;
3579 	// Validate arguments
3580 	if (t == NULL || param == NULL)
3581 	{
3582 		return;
3583 	}
3584 
3585 	NoticeThreadInit(t);
3586 
3587 	// Wait for a certain period of time
3588 	while (c->Halt == false)
3589 	{
3590 		Wait(c->SaverHalter, CLIENT_SAVER_INTERVAL);
3591 
3592 		// Save
3593 		CiSaveConfigurationFile(c);
3594 	}
3595 }
3596 
3597 // Initialize the Saver
CiInitSaver(CLIENT * c)3598 void CiInitSaver(CLIENT *c)
3599 {
3600 	// Validate arguments
3601 	if (c == NULL)
3602 	{
3603 		return;
3604 	}
3605 
3606 	c->SaverHalter = NewEvent();
3607 
3608 	c->SaverThread = NewThread(CiSaverThread, c);
3609 	WaitThreadInit(c->SaverThread);
3610 }
3611 
3612 // Release the Saver
CiFreeSaver(CLIENT * c)3613 void CiFreeSaver(CLIENT *c)
3614 {
3615 	// Validate arguments
3616 	if (c == NULL)
3617 	{
3618 		return;
3619 	}
3620 
3621 	c->Halt = true;
3622 	Set(c->SaverHalter);
3623 	WaitThread(c->SaverThread, INFINITE);
3624 	ReleaseThread(c->SaverThread);
3625 
3626 	ReleaseEvent(c->SaverHalter);
3627 }
3628 
3629 // CM_SETTING
InRpcCmSetting(CM_SETTING * c,PACK * p)3630 void InRpcCmSetting(CM_SETTING *c, PACK *p)
3631 {
3632 	// Validate arguments
3633 	if (c == NULL || p == NULL)
3634 	{
3635 		return;
3636 	}
3637 
3638 	Zero(c, sizeof(CM_SETTING));
3639 	c->EasyMode = PackGetBool(p, "EasyMode");
3640 	c->LockMode = PackGetBool(p, "LockMode");
3641 	PackGetData2(p, "HashedPassword", c->HashedPassword, sizeof(c->HashedPassword));
3642 }
OutRpcCmSetting(PACK * p,CM_SETTING * c)3643 void OutRpcCmSetting(PACK *p, CM_SETTING *c)
3644 {
3645 	// Validate arguments
3646 	if (c == NULL || p == NULL)
3647 	{
3648 		return;
3649 	}
3650 
3651 	PackAddBool(p, "EasyMode", c->EasyMode);
3652 	PackAddBool(p, "LockMode", c->LockMode);
3653 	PackAddData(p, "HashedPassword", c->HashedPassword, sizeof(c->HashedPassword));
3654 }
3655 
3656 // CLIENT_CONFIG
InRpcClientConfig(CLIENT_CONFIG * c,PACK * p)3657 void InRpcClientConfig(CLIENT_CONFIG *c, PACK *p)
3658 {
3659 	// Validate arguments
3660 	if (c == NULL || p == NULL)
3661 	{
3662 		return;
3663 	}
3664 
3665 	Zero(c, sizeof(CLIENT_CONFIG));
3666 	c->UseKeepConnect = PackGetInt(p, "UseKeepConnect") == 0 ? false : true;
3667 	c->KeepConnectPort = PackGetInt(p, "KeepConnectPort");
3668 	c->KeepConnectProtocol = PackGetInt(p, "KeepConnectProtocol");
3669 	c->KeepConnectInterval = PackGetInt(p, "KeepConnectInterval");
3670 	c->AllowRemoteConfig = PackGetInt(p, "AllowRemoteConfig") == 0 ? false : true;
3671 	PackGetStr(p, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost));
3672 }
OutRpcClientConfig(PACK * p,CLIENT_CONFIG * c)3673 void OutRpcClientConfig(PACK *p, CLIENT_CONFIG *c)
3674 {
3675 	// Validate arguments
3676 	if (c == NULL || p == NULL)
3677 	{
3678 		return;
3679 	}
3680 
3681 	PackAddInt(p, "UseKeepConnect", c->UseKeepConnect);
3682 	PackAddInt(p, "KeepConnectPort", c->KeepConnectPort);
3683 	PackAddInt(p, "KeepConnectProtocol", c->KeepConnectProtocol);
3684 	PackAddInt(p, "KeepConnectInterval", c->KeepConnectInterval);
3685 	PackAddInt(p, "AllowRemoteConfig", c->AllowRemoteConfig);
3686 	PackAddStr(p, "KeepConnectHost", c->KeepConnectHost);
3687 }
3688 
3689 // RPC_CLIENT_VERSION
InRpcClientVersion(RPC_CLIENT_VERSION * ver,PACK * p)3690 void InRpcClientVersion(RPC_CLIENT_VERSION *ver, PACK *p)
3691 {
3692 	// Validate arguments
3693 	if (ver == NULL || p == NULL)
3694 	{
3695 		return;
3696 	}
3697 
3698 	Zero(ver, sizeof(RPC_CLIENT_VERSION));
3699 	PackGetStr(p, "ClientProductName", ver->ClientProductName, sizeof(ver->ClientProductName));
3700 	PackGetStr(p, "ClientVersionString", ver->ClientVersionString, sizeof(ver->ClientVersionString));
3701 	PackGetStr(p, "ClientBuildInfoString", ver->ClientBuildInfoString, sizeof(ver->ClientBuildInfoString));
3702 	ver->ClientVerInt = PackGetInt(p, "ClientVerInt");
3703 	ver->ClientBuildInt = PackGetInt(p, "ClientBuildInt");
3704 	ver->ProcessId = PackGetInt(p, "ProcessId");
3705 	ver->OsType = PackGetInt(p, "OsType");
3706 	ver->IsVLanNameRegulated = PackGetBool(p, "IsVLanNameRegulated");
3707 	ver->IsVgcSupported = PackGetBool(p, "IsVgcSupported");
3708 	ver->ShowVgcLink = PackGetBool(p, "ShowVgcLink");
3709 	PackGetStr(p, "ClientId", ver->ClientId, sizeof(ver->ClientId));
3710 }
OutRpcClientVersion(PACK * p,RPC_CLIENT_VERSION * ver)3711 void OutRpcClientVersion(PACK *p, RPC_CLIENT_VERSION *ver)
3712 {
3713 	// Validate arguments
3714 	if (ver == NULL || p == NULL)
3715 	{
3716 		return;
3717 	}
3718 
3719 	PackAddStr(p, "ClientProductName", ver->ClientProductName);
3720 	PackAddStr(p, "ClientVersionString", ver->ClientVersionString);
3721 	PackAddStr(p, "ClientBuildInfoString", ver->ClientBuildInfoString);
3722 	PackAddInt(p, "ClientVerInt", ver->ClientVerInt);
3723 	PackAddInt(p, "ClientBuildInt", ver->ClientBuildInt);
3724 	PackAddInt(p, "ProcessId", ver->ProcessId);
3725 	PackAddInt(p, "OsType", ver->OsType);
3726 	PackAddBool(p, "IsVLanNameRegulated", ver->IsVLanNameRegulated);
3727 	PackAddBool(p, "IsVgcSupported", ver->IsVgcSupported);
3728 	PackAddBool(p, "ShowVgcLink", ver->ShowVgcLink);
3729 	PackAddStr(p, "ClientId", ver->ClientId);
3730 }
3731 
3732 // RPC_CLIENT_PASSWORD
InRpcClientPassword(RPC_CLIENT_PASSWORD * pw,PACK * p)3733 void InRpcClientPassword(RPC_CLIENT_PASSWORD *pw, PACK *p)
3734 {
3735 	// Validate arguments
3736 	if (pw == NULL || p == NULL)
3737 	{
3738 		return;
3739 	}
3740 
3741 	Zero(pw, sizeof(RPC_CLIENT_PASSWORD));
3742 	PackGetStr(p, "Password", pw->Password, sizeof(pw->Password));
3743 	pw->PasswordRemoteOnly = PackGetInt(p, "PasswordRemoteOnly");
3744 }
OutRpcClientPassword(PACK * p,RPC_CLIENT_PASSWORD * pw)3745 void OutRpcClientPassword(PACK *p, RPC_CLIENT_PASSWORD *pw)
3746 {
3747 	// Validate arguments
3748 	if (pw == NULL || p == NULL)
3749 	{
3750 		return;
3751 	}
3752 
3753 	PackAddStr(p, "Password", pw->Password);
3754 	PackAddInt(p, "PasswordRemoteOnly", pw->PasswordRemoteOnly);
3755 }
3756 
3757 // RPC_CLIENT_PASSWORD_SETTING
InRpcClientPasswordSetting(RPC_CLIENT_PASSWORD_SETTING * a,PACK * p)3758 void InRpcClientPasswordSetting(RPC_CLIENT_PASSWORD_SETTING *a, PACK *p)
3759 {
3760 	// Validate arguments
3761 	if (a == NULL || p == NULL)
3762 	{
3763 		return;
3764 	}
3765 
3766 	Zero(a, sizeof(RPC_CLIENT_PASSWORD_SETTING));
3767 
3768 	a->IsPasswordPresented = PackGetInt(p, "IsPasswordPresented") == 0 ? false : true;
3769 	a->PasswordRemoteOnly = PackGetInt(p, "PasswordRemoteOnly") == 0 ? false : true;
3770 }
OutRpcClientPasswordSetting(PACK * p,RPC_CLIENT_PASSWORD_SETTING * a)3771 void OutRpcClientPasswordSetting(PACK *p, RPC_CLIENT_PASSWORD_SETTING *a)
3772 {
3773 	// Validate arguments
3774 	if (a == NULL || p == NULL)
3775 	{
3776 		return;
3777 	}
3778 
3779 	PackAddInt(p, "IsPasswordPresented", a->IsPasswordPresented);
3780 	PackAddInt(p, "PasswordRemoteOnly", a->PasswordRemoteOnly);
3781 }
3782 
3783 // RPC_CLIENT_ENUM_CA
InRpcClientEnumCa(RPC_CLIENT_ENUM_CA * e,PACK * p)3784 void InRpcClientEnumCa(RPC_CLIENT_ENUM_CA *e, PACK *p)
3785 {
3786 	UINT i;
3787 	// Validate arguments
3788 	if (e == NULL || p == NULL)
3789 	{
3790 		return;
3791 	}
3792 
3793 	Zero(e, sizeof(RPC_CLIENT_ENUM_CA));
3794 	e->NumItem = PackGetNum(p, "NumItem");
3795 
3796 	e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM *) * e->NumItem);
3797 	for (i = 0;i < e->NumItem;i++)
3798 	{
3799 		RPC_CLIENT_ENUM_CA_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM));
3800 		e->Items[i] = item;
3801 
3802 		item->Key = PackGetIntEx(p, "Key", i);
3803 		PackGetUniStrEx(p, "SubjectName", item->SubjectName, sizeof(item->SubjectName), i);
3804 		PackGetUniStrEx(p, "IssuerName", item->IssuerName, sizeof(item->IssuerName), i);
3805 		item->Expires = PackGetInt64Ex(p, "Expires", i);
3806 	}
3807 }
OutRpcClientEnumCa(PACK * p,RPC_CLIENT_ENUM_CA * e)3808 void OutRpcClientEnumCa(PACK *p, RPC_CLIENT_ENUM_CA *e)
3809 {
3810 	UINT i;
3811 	// Validate arguments
3812 	if (e == NULL || p == NULL)
3813 	{
3814 		return;
3815 	}
3816 
3817 	PackAddNum(p, "NumItem", e->NumItem);
3818 
3819 	PackSetCurrentJsonGroupName(p, "CAList");
3820 	for (i = 0;i < e->NumItem;i++)
3821 	{
3822 		RPC_CLIENT_ENUM_CA_ITEM *item = e->Items[i];
3823 		PackAddIntEx(p, "Key", item->Key, i, e->NumItem);
3824 		PackAddUniStrEx(p, "SubjectName", item->SubjectName, i, e->NumItem);
3825 		PackAddUniStrEx(p, "IssuerName", item->IssuerName, i, e->NumItem);
3826 		PackAddTime64Ex(p, "Expires", item->Expires, i, e->NumItem);
3827 	}
3828 	PackSetCurrentJsonGroupName(p, NULL);
3829 }
3830 
3831 // RPC_GET_ISSUER
InRpcGetIssuer(RPC_GET_ISSUER * c,PACK * p)3832 void InRpcGetIssuer(RPC_GET_ISSUER *c, PACK *p)
3833 {
3834 	BUF *b;
3835 	// Validate arguments
3836 	if (c == NULL || p == NULL)
3837 	{
3838 		return;
3839 	}
3840 
3841 	Zero(c, sizeof(RPC_GET_ISSUER));
3842 	b = PackGetBuf(p, "x");
3843 	if (b != NULL)
3844 	{
3845 		if (c->x != NULL)
3846 		{
3847 			FreeX(c->x);
3848 		}
3849 		c->x = BufToX(b, false);
3850 		FreeBuf(b);
3851 	}
3852 
3853 	b = PackGetBuf(p, "issuer_x");
3854 	if (b != NULL)
3855 	{
3856 		c->issuer_x = BufToX(b, false);
3857 		FreeBuf(b);
3858 	}
3859 }
OutRpcGetIssuer(PACK * p,RPC_GET_ISSUER * c)3860 void OutRpcGetIssuer(PACK *p, RPC_GET_ISSUER *c)
3861 {
3862 	BUF *b;
3863 	// Validate arguments
3864 	if (p == NULL || c == NULL)
3865 	{
3866 		return;
3867 	}
3868 
3869 	if (c->x != NULL)
3870 	{
3871 		b = XToBuf(c->x, false);
3872 
3873 		PackAddBuf(p, "x", b);
3874 		FreeBuf(b);
3875 	}
3876 
3877 	if (c->issuer_x != NULL)
3878 	{
3879 		b = XToBuf(c->issuer_x, false);
3880 
3881 		PackAddBuf(p, "issuer_x", b);
3882 		FreeBuf(b);
3883 	}
3884 }
3885 
3886 // TRAFFIC_EX
InRpcTrafficEx(TRAFFIC * t,PACK * p,UINT i)3887 void InRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i)
3888 {
3889 	// Validate arguments
3890 	if (t == NULL || p == NULL)
3891 	{
3892 		return;
3893 	}
3894 
3895 	Zero(t, sizeof(TRAFFIC));
3896 	t->Recv.BroadcastBytes = PackGetInt64Ex(p, "Ex.Recv.BroadcastBytes", i);
3897 	t->Recv.BroadcastCount = PackGetInt64Ex(p, "Ex.Recv.BroadcastCount", i);
3898 	t->Recv.UnicastBytes = PackGetInt64Ex(p, "Ex.Recv.UnicastBytes", i);
3899 	t->Recv.UnicastCount = PackGetInt64Ex(p, "Ex.Recv.UnicastCount", i);
3900 	t->Send.BroadcastBytes = PackGetInt64Ex(p, "Ex.Send.BroadcastBytes", i);
3901 	t->Send.BroadcastCount = PackGetInt64Ex(p, "Ex.Send.BroadcastCount", i);
3902 	t->Send.UnicastBytes = PackGetInt64Ex(p, "Ex.Send.UnicastBytes", i);
3903 	t->Send.UnicastCount = PackGetInt64Ex(p, "Ex.Send.UnicastCount", i);
3904 }
OutRpcTrafficEx(TRAFFIC * t,PACK * p,UINT i,UINT num)3905 void OutRpcTrafficEx(TRAFFIC *t, PACK *p, UINT i, UINT num)
3906 {
3907 	// Validate arguments
3908 	if (t == NULL || p == NULL)
3909 	{
3910 		return;
3911 	}
3912 
3913 	PackAddInt64Ex(p, "Ex.Recv.BroadcastBytes", t->Recv.BroadcastBytes, i, num);
3914 	PackAddInt64Ex(p, "Ex.Recv.BroadcastCount", t->Recv.BroadcastCount, i, num);
3915 	PackAddInt64Ex(p, "Ex.Recv.UnicastBytes", t->Recv.UnicastBytes, i, num);
3916 	PackAddInt64Ex(p, "Ex.Recv.UnicastCount", t->Recv.UnicastCount, i, num);
3917 	PackAddInt64Ex(p, "Ex.Send.BroadcastBytes", t->Send.BroadcastBytes, i, num);
3918 	PackAddInt64Ex(p, "Ex.Send.BroadcastCount", t->Send.BroadcastCount, i, num);
3919 	PackAddInt64Ex(p, "Ex.Send.UnicastBytes", t->Send.UnicastBytes, i, num);
3920 	PackAddInt64Ex(p, "Ex.Send.UnicastCount", t->Send.UnicastCount, i, num);
3921 }
3922 
3923 // TRAFFIC
InRpcTraffic(TRAFFIC * t,PACK * p)3924 void InRpcTraffic(TRAFFIC *t, PACK *p)
3925 {
3926 	// Validate arguments
3927 	if (t == NULL || p == NULL)
3928 	{
3929 		return;
3930 	}
3931 
3932 	Zero(t, sizeof(TRAFFIC));
3933 	t->Recv.BroadcastBytes = PackGetInt64(p, "Recv.BroadcastBytes");
3934 	t->Recv.BroadcastCount = PackGetInt64(p, "Recv.BroadcastCount");
3935 	t->Recv.UnicastBytes = PackGetInt64(p, "Recv.UnicastBytes");
3936 	t->Recv.UnicastCount = PackGetInt64(p, "Recv.UnicastCount");
3937 	t->Send.BroadcastBytes = PackGetInt64(p, "Send.BroadcastBytes");
3938 	t->Send.BroadcastCount = PackGetInt64(p, "Send.BroadcastCount");
3939 	t->Send.UnicastBytes = PackGetInt64(p, "Send.UnicastBytes");
3940 	t->Send.UnicastCount = PackGetInt64(p, "Send.UnicastCount");
3941 }
OutRpcTraffic(PACK * p,TRAFFIC * t)3942 void OutRpcTraffic(PACK *p, TRAFFIC *t)
3943 {
3944 	// Validate arguments
3945 	if (t == NULL || p == NULL)
3946 	{
3947 		return;
3948 	}
3949 
3950 	PackAddInt64(p, "Recv.BroadcastBytes", t->Recv.BroadcastBytes);
3951 	PackAddInt64(p, "Recv.BroadcastCount", t->Recv.BroadcastCount);
3952 	PackAddInt64(p, "Recv.UnicastBytes", t->Recv.UnicastBytes);
3953 	PackAddInt64(p, "Recv.UnicastCount", t->Recv.UnicastCount);
3954 	PackAddInt64(p, "Send.BroadcastBytes", t->Send.BroadcastBytes);
3955 	PackAddInt64(p, "Send.BroadcastCount", t->Send.BroadcastCount);
3956 	PackAddInt64(p, "Send.UnicastBytes", t->Send.UnicastBytes);
3957 	PackAddInt64(p, "Send.UnicastCount", t->Send.UnicastCount);
3958 }
3959 
3960 // RPC_CERT
InRpcCert(RPC_CERT * c,PACK * p)3961 void InRpcCert(RPC_CERT *c, PACK *p)
3962 {
3963 	BUF *b;
3964 	// Validate arguments
3965 	if (c == NULL || p == NULL)
3966 	{
3967 		return;
3968 	}
3969 
3970 	Zero(c, sizeof(RPC_CERT));
3971 	b = PackGetBuf(p, "x");
3972 	if (b == NULL)
3973 	{
3974 		return;
3975 	}
3976 
3977 	c->x = BufToX(b, false);
3978 	FreeBuf(b);
3979 }
OutRpcCert(PACK * p,RPC_CERT * c)3980 void OutRpcCert(PACK *p, RPC_CERT *c)
3981 {
3982 	BUF *b;
3983 	// Validate arguments
3984 	if (p == NULL || c == NULL)
3985 	{
3986 		return;
3987 	}
3988 
3989 	if (c->x != NULL)
3990 	{
3991 		b = XToBuf(c->x, false);
3992 
3993 		PackAddBuf(p, "x", b);
3994 
3995 		FreeBuf(b);
3996 	}
3997 }
3998 
3999 // RPC_CLIENT_DELETE_CA
InRpcClientDeleteCa(RPC_CLIENT_DELETE_CA * c,PACK * p)4000 void InRpcClientDeleteCa(RPC_CLIENT_DELETE_CA *c, PACK *p)
4001 {
4002 	// Validate arguments
4003 	if (c == NULL || p == NULL)
4004 	{
4005 		return;
4006 	}
4007 
4008 	Zero(c, sizeof(RPC_CLIENT_DELETE_CA));
4009 	c->Key = PackGetInt(p, "Key");
4010 }
OutRpcClientDeleteCa(PACK * p,RPC_CLIENT_DELETE_CA * c)4011 void OutRpcClientDeleteCa(PACK *p, RPC_CLIENT_DELETE_CA *c)
4012 {
4013 	// Validate arguments
4014 	if (c == NULL || p == NULL)
4015 	{
4016 		return;
4017 	}
4018 
4019 	PackAddInt(p, "Key", c->Key);
4020 }
4021 
4022 // RPC_GET_CA
InRpcGetCa(RPC_GET_CA * c,PACK * p)4023 void InRpcGetCa(RPC_GET_CA *c, PACK *p)
4024 {
4025 	BUF *b;
4026 	// Validate arguments
4027 	if (c == NULL || p == NULL)
4028 	{
4029 		return;
4030 	}
4031 
4032 	Zero(c, sizeof(RPC_GET_CA));
4033 
4034 	c->Key = PackGetInt(p, "Key");
4035 
4036 	b = PackGetBuf(p, "x");
4037 	if (b != NULL)
4038 	{
4039 		c->x = BufToX(b, false);
4040 
4041 		FreeBuf(b);
4042 	}
4043 }
OutRpcGetCa(PACK * p,RPC_GET_CA * c)4044 void OutRpcGetCa(PACK *p, RPC_GET_CA *c)
4045 {
4046 	// Validate arguments
4047 	if (c == NULL || p == NULL)
4048 	{
4049 		return;
4050 	}
4051 
4052 	PackAddInt(p, "Key", c->Key);
4053 
4054 	if (c->x != NULL)
4055 	{
4056 		BUF *b = XToBuf(c->x, false);
4057 
4058 		PackAddBuf(p, "x", b);
4059 
4060 		FreeBuf(b);
4061 	}
4062 }
4063 
4064 // RPC_CLIENT_ENUM_SECURE
InRpcClientEnumSecure(RPC_CLIENT_ENUM_SECURE * e,PACK * p)4065 void InRpcClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e, PACK *p)
4066 {
4067 	UINT i;
4068 	// Validate arguments
4069 	if (e == NULL || p == NULL)
4070 	{
4071 		return;
4072 	}
4073 
4074 	Zero(e, sizeof(RPC_CLIENT_ENUM_SECURE));
4075 
4076 	e->NumItem = PackGetNum(p, "NumItem");
4077 	e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM *) * e->NumItem);
4078 	for (i = 0;i < e->NumItem;i++)
4079 	{
4080 		RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM));
4081 
4082 		item->DeviceId = PackGetIntEx(p, "DeviceId", i);
4083 		item->Type = PackGetIntEx(p, "Type", i);
4084 		PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
4085 		PackGetStrEx(p, "Manufacturer", item->Manufacturer, sizeof(item->Manufacturer), i);
4086 	}
4087 }
OutRpcClientEnumSecure(PACK * p,RPC_CLIENT_ENUM_SECURE * e)4088 void OutRpcClientEnumSecure(PACK *p, RPC_CLIENT_ENUM_SECURE *e)
4089 {
4090 	UINT i;
4091 	// Validate arguments
4092 	if (e == NULL || p == NULL)
4093 	{
4094 		return;
4095 	}
4096 
4097 	PackAddNum(p, "NumItem", e->NumItem);
4098 
4099 	PackSetCurrentJsonGroupName(p, "SecureDeviceList");
4100 	for (i = 0;i < e->NumItem;i++)
4101 	{
4102 		RPC_CLIENT_ENUM_SECURE_ITEM *item = e->Items[i];
4103 
4104 		PackAddIntEx(p, "DeviceId", item->DeviceId, i, e->NumItem);
4105 		PackAddIntEx(p, "Type", item->Type, i, e->NumItem);
4106 		PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);
4107 		PackAddStrEx(p, "Manufacturer", item->Manufacturer, i, e->NumItem);
4108 	}
4109 	PackSetCurrentJsonGroupName(p, NULL);
4110 }
4111 
4112 // RPC_USE_SECURE
InRpcUseSecure(RPC_USE_SECURE * u,PACK * p)4113 void InRpcUseSecure(RPC_USE_SECURE *u, PACK *p)
4114 {
4115 	// Validate arguments
4116 	if (u == NULL || p == NULL)
4117 	{
4118 		return;
4119 	}
4120 
4121 	Zero(u, sizeof(RPC_USE_SECURE));
4122 	u->DeviceId = PackGetInt(p, "DeviceId");
4123 }
OutRpcUseSecure(PACK * p,RPC_USE_SECURE * u)4124 void OutRpcUseSecure(PACK *p, RPC_USE_SECURE *u)
4125 {
4126 	// Validate arguments
4127 	if (u == NULL || p == NULL)
4128 	{
4129 		return;
4130 	}
4131 
4132 	PackAddInt(p, "DeviceId", u->DeviceId);
4133 }
4134 
4135 // Release the RPC_ENUM_OBJECT_IN_SECURE
CiFreeEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE * a)4136 void CiFreeEnumObjectInSecure(RPC_ENUM_OBJECT_IN_SECURE *a)
4137 {
4138 	UINT i;
4139 	// Validate arguments
4140 	if (a == NULL)
4141 	{
4142 		return;
4143 	}
4144 
4145 	for (i = 0;i < a->NumItem;i++)
4146 	{
4147 		Free(a->ItemName[i]);
4148 	}
4149 	Free(a->ItemName);
4150 	Free(a->ItemType);
4151 }
4152 
4153 // RPC_ENUM_OBJECT_IN_SECURE
OutRpcEnumObjectInSecure(PACK * p,RPC_ENUM_OBJECT_IN_SECURE * e)4154 void OutRpcEnumObjectInSecure(PACK *p, RPC_ENUM_OBJECT_IN_SECURE *e)
4155 {
4156 	UINT i;
4157 	// Validate arguments
4158 	if (e == NULL || p == NULL)
4159 	{
4160 		return;
4161 	}
4162 
4163 	PackAddNum(p, "NumItem", e->NumItem);
4164 	PackAddInt(p, "hWnd", e->hWnd);
4165 
4166 	PackSetCurrentJsonGroupName(p, "ObjectList");
4167 	for (i = 0;i < e->NumItem;i++)
4168 	{
4169 		PackAddStrEx(p, "ItemName", e->ItemName[i], i, e->NumItem);
4170 		PackAddIntEx(p, "ItemType", e->ItemType[i], i, e->NumItem);
4171 	}
4172 	PackSetCurrentJsonGroupName(p, NULL);
4173 }
4174 
4175 // RPC_CLIENT_CREATE_VLAN
InRpcCreateVLan(RPC_CLIENT_CREATE_VLAN * v,PACK * p)4176 void InRpcCreateVLan(RPC_CLIENT_CREATE_VLAN *v, PACK *p)
4177 {
4178 	// Validate arguments
4179 	if (v == NULL || p == NULL)
4180 	{
4181 		return;
4182 	}
4183 
4184 	Zero(v, sizeof(RPC_CLIENT_CREATE_VLAN));
4185 	PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
4186 }
OutRpcCreateVLan(PACK * p,RPC_CLIENT_CREATE_VLAN * v)4187 void OutRpcCreateVLan(PACK *p, RPC_CLIENT_CREATE_VLAN *v)
4188 {
4189 	// Validate arguments
4190 	if (v == NULL || p == NULL)
4191 	{
4192 		return;
4193 	}
4194 
4195 	PackAddStr(p, "DeviceName", v->DeviceName);
4196 }
4197 
4198 // RPC_CLIENT_GET_VLAN
InRpcClientGetVLan(RPC_CLIENT_GET_VLAN * v,PACK * p)4199 void InRpcClientGetVLan(RPC_CLIENT_GET_VLAN *v, PACK *p)
4200 {
4201 	// Validate arguments
4202 	if (v == NULL || p == NULL)
4203 	{
4204 		return;
4205 	}
4206 
4207 	Zero(v, sizeof(RPC_CLIENT_GET_VLAN));
4208 	PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
4209 	v->Enabled = PackGetInt(p, "Enabled") ? true : false;
4210 	PackGetStr(p, "MacAddress", v->MacAddress, sizeof(v->MacAddress));
4211 	PackGetStr(p, "Version", v->Version, sizeof(v->Version));
4212 	PackGetStr(p, "FileName", v->FileName, sizeof(v->FileName));
4213 	PackGetStr(p, "Guid", v->Guid, sizeof(v->Guid));
4214 }
OutRpcClientGetVLan(PACK * p,RPC_CLIENT_GET_VLAN * v)4215 void OutRpcClientGetVLan(PACK *p, RPC_CLIENT_GET_VLAN *v)
4216 {
4217 	// Validate arguments
4218 	if (v == NULL || p == NULL)
4219 	{
4220 		return;
4221 	}
4222 
4223 	PackAddStr(p, "DeviceName", v->DeviceName);
4224 	PackAddInt(p, "Enabled", v->Enabled);
4225 	PackAddStr(p, "MacAddress", v->MacAddress);
4226 	PackAddStr(p, "Version", v->Version);
4227 	PackAddStr(p, "FileName", v->FileName);
4228 	PackAddStr(p, "Guid", v->Guid);
4229 }
4230 
4231 // RPC_CLIENT_SET_VLAN
InRpcClientSetVLan(RPC_CLIENT_SET_VLAN * v,PACK * p)4232 void InRpcClientSetVLan(RPC_CLIENT_SET_VLAN *v, PACK *p)
4233 {
4234 	// Validate arguments
4235 	if (v == NULL || p == NULL)
4236 	{
4237 		return;
4238 	}
4239 
4240 	Zero(v, sizeof(RPC_CLIENT_SET_VLAN));
4241 	PackGetStr(p, "DeviceName", v->DeviceName, sizeof(v->DeviceName));
4242 	PackGetStr(p, "MacAddress", v->MacAddress, sizeof(v->MacAddress));
4243 }
OutRpcClientSetVLan(PACK * p,RPC_CLIENT_SET_VLAN * v)4244 void OutRpcClientSetVLan(PACK *p, RPC_CLIENT_SET_VLAN *v)
4245 {
4246 	// Validate arguments
4247 	if (v == NULL || p == NULL)
4248 	{
4249 		return;
4250 	}
4251 
4252 	PackAddStr(p, "DeviceName", v->DeviceName);
4253 	PackAddStr(p, "MacAddress", v->MacAddress);
4254 }
4255 
4256 // RPC_CLIENT_ENUM_VLAN
InRpcClientEnumVLan(RPC_CLIENT_ENUM_VLAN * v,PACK * p)4257 void InRpcClientEnumVLan(RPC_CLIENT_ENUM_VLAN *v, PACK *p)
4258 {
4259 	UINT i;
4260 	// Validate arguments
4261 	if (v == NULL || p == NULL)
4262 	{
4263 		return;
4264 	}
4265 
4266 	Zero(v, sizeof(RPC_CLIENT_ENUM_VLAN));
4267 	v->NumItem = PackGetNum(p, "NumItem");
4268 	v->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * v->NumItem);
4269 
4270 	for (i = 0;i < v->NumItem;i++)
4271 	{
4272 		RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i] =
4273 			ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
4274 
4275 		PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
4276 		item->Enabled = PackGetIntEx(p, "Enabled", i) ? true : false;
4277 		PackGetStrEx(p, "MacAddress", item->MacAddress, sizeof(item->MacAddress), i);
4278 		PackGetStrEx(p, "Version", item->Version, sizeof(item->Version), i);
4279 	}
4280 }
OutRpcClientEnumVLan(PACK * p,RPC_CLIENT_ENUM_VLAN * v)4281 void OutRpcClientEnumVLan(PACK *p, RPC_CLIENT_ENUM_VLAN *v)
4282 {
4283 	UINT i;
4284 	// Validate arguments
4285 	if (v == NULL || p == NULL)
4286 	{
4287 		return;
4288 	}
4289 
4290 	PackAddNum(p, "NumItem", v->NumItem);
4291 
4292 	PackSetCurrentJsonGroupName(p, "VLanList");
4293 	for (i = 0;i < v->NumItem;i++)
4294 	{
4295 		RPC_CLIENT_ENUM_VLAN_ITEM *item = v->Items[i];
4296 
4297 		PackAddStrEx(p, "DeviceName", item->DeviceName, i, v->NumItem);
4298 		PackAddIntEx(p, "Enabled", item->Enabled, i, v->NumItem);
4299 		PackAddStrEx(p, "MacAddress", item->MacAddress, i, v->NumItem);
4300 		PackAddStrEx(p, "Version", item->Version, i, v->NumItem);
4301 	}
4302 	PackSetCurrentJsonGroupName(p, NULL);
4303 }
4304 
4305 // CLIENT_OPTION
InRpcClientOption(CLIENT_OPTION * c,PACK * p)4306 void InRpcClientOption(CLIENT_OPTION *c, PACK *p)
4307 {
4308 	// Validate arguments
4309 	if (c == NULL || p == NULL)
4310 	{
4311 		return;
4312 	}
4313 
4314 	Zero(c, sizeof(CLIENT_OPTION));
4315 
4316 	PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
4317 	PackGetStr(p, "Hostname", c->Hostname, sizeof(c->Hostname));
4318 	c->Port = PackGetInt(p, "Port");
4319 	c->PortUDP = PackGetInt(p, "PortUDP");
4320 	c->ProxyType = PackGetInt(p, "ProxyType");
4321 	c->ProxyPort = PackGetInt(p, "ProxyPort");
4322 	c->NumRetry = PackGetInt(p, "NumRetry");
4323 	c->RetryInterval = PackGetInt(p, "RetryInterval");
4324 	c->MaxConnection = PackGetInt(p, "MaxConnection");
4325 	c->AdditionalConnectionInterval = PackGetInt(p, "AdditionalConnectionInterval");
4326 	c->ConnectionDisconnectSpan = PackGetInt(p, "ConnectionDisconnectSpan");
4327 	c->HideStatusWindow = PackGetBool(p, "HideStatusWindow");
4328 	c->HideNicInfoWindow = PackGetBool(p, "HideNicInfoWindow");
4329 	c->DisableQoS = PackGetBool(p, "DisableQoS");
4330 	PackGetStr(p, "ProxyName", c->ProxyName, sizeof(c->ProxyName));
4331 	PackGetStr(p, "ProxyUsername", c->ProxyUsername, sizeof(c->ProxyUsername));
4332 	PackGetStr(p, "ProxyPassword", c->ProxyPassword, sizeof(c->ProxyPassword));
4333 	PackGetStr(p, "CustomHttpHeader", c->CustomHttpHeader, sizeof(c->CustomHttpHeader));
4334 	PackGetStr(p, "HubName", c->HubName, sizeof(c->HubName));
4335 	PackGetStr(p, "DeviceName", c->DeviceName, sizeof(c->DeviceName));
4336 	c->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;
4337 	c->UseCompress = PackGetInt(p, "UseCompress") ? true : false;
4338 	c->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;
4339 	c->NoRoutingTracking = PackGetInt(p, "NoRoutingTracking") ? true : false;
4340 	c->RequireMonitorMode = PackGetBool(p, "RequireMonitorMode");
4341 	c->RequireBridgeRoutingMode = PackGetBool(p, "RequireBridgeRoutingMode");
4342 	c->FromAdminPack = PackGetBool(p, "FromAdminPack");
4343 	c->NoUdpAcceleration = PackGetBool(p, "NoUdpAcceleration");
4344 	PackGetData2(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE);
4345 }
OutRpcClientOption(PACK * p,CLIENT_OPTION * c)4346 void OutRpcClientOption(PACK *p, CLIENT_OPTION *c)
4347 {
4348 	// Validate arguments
4349 	if (c == NULL || p == NULL)
4350 	{
4351 		return;
4352 	}
4353 
4354 	PackAddUniStr(p, "AccountName", c->AccountName);
4355 	PackAddStr(p, "Hostname", c->Hostname);
4356 	PackAddStr(p, "ProxyName", c->ProxyName);
4357 	PackAddStr(p, "ProxyUsername", c->ProxyUsername);
4358 	PackAddStr(p, "ProxyPassword", c->ProxyPassword);
4359 	PackAddStr(p, "CustomHttpHeader", c->CustomHttpHeader);
4360 	PackAddStr(p, "HubName", c->HubName);
4361 	PackAddStr(p, "DeviceName", c->DeviceName);
4362 	PackAddInt(p, "Port", c->Port);
4363 	PackAddInt(p, "PortUDP", c->PortUDP);
4364 	PackAddInt(p, "ProxyType", c->ProxyType);
4365 	PackAddInt(p, "ProxyPort", c->ProxyPort);
4366 	PackAddInt(p, "NumRetry", c->NumRetry);
4367 	PackAddInt(p, "RetryInterval", c->RetryInterval);
4368 	PackAddInt(p, "MaxConnection", c->MaxConnection);
4369 	PackAddBool(p, "UseEncrypt", c->UseEncrypt);
4370 	PackAddBool(p, "UseCompress", c->UseCompress);
4371 	PackAddBool(p, "HalfConnection", c->HalfConnection);
4372 	PackAddBool(p, "NoRoutingTracking", c->NoRoutingTracking);
4373 	PackAddInt(p, "AdditionalConnectionInterval", c->AdditionalConnectionInterval);
4374 	PackAddInt(p, "ConnectionDisconnectSpan", c->ConnectionDisconnectSpan);
4375 	PackAddBool(p, "HideStatusWindow", c->HideStatusWindow);
4376 	PackAddBool(p, "HideNicInfoWindow", c->HideNicInfoWindow);
4377 	PackAddBool(p, "RequireMonitorMode", c->RequireMonitorMode);
4378 	PackAddBool(p, "RequireBridgeRoutingMode", c->RequireBridgeRoutingMode);
4379 	PackAddBool(p, "DisableQoS", c->DisableQoS);
4380 	PackAddBool(p, "FromAdminPack", c->FromAdminPack);
4381 	PackAddBool(p, "NoUdpAcceleration", c->NoUdpAcceleration);
4382 	PackAddData(p, "HostUniqueKey", c->HostUniqueKey, SHA1_SIZE);
4383 }
4384 
4385 // CLIENT_AUTH
InRpcClientAuth(CLIENT_AUTH * c,PACK * p)4386 void InRpcClientAuth(CLIENT_AUTH *c, PACK *p)
4387 {
4388 	BUF *b;
4389 	// Validate arguments
4390 	if (c == NULL || p == NULL)
4391 	{
4392 		return;
4393 	}
4394 
4395 	Zero(c, sizeof(CLIENT_AUTH));
4396 	c->AuthType = PackGetInt(p, "AuthType");
4397 	PackGetStr(p, "Username", c->Username, sizeof(c->Username));
4398 
4399 	switch (c->AuthType)
4400 	{
4401 	case CLIENT_AUTHTYPE_ANONYMOUS:
4402 		break;
4403 
4404 	case CLIENT_AUTHTYPE_PASSWORD:
4405 		if (PackGetDataSize(p, "HashedPassword") == SHA1_SIZE)
4406 		{
4407 			PackGetData(p, "HashedPassword", c->HashedPassword);
4408 		}
4409 		break;
4410 
4411 	case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
4412 		PackGetStr(p, "PlainPassword", c->PlainPassword, sizeof(c->PlainPassword));
4413 		break;
4414 
4415 	case CLIENT_AUTHTYPE_CERT:
4416 		b = PackGetBuf(p, "ClientX");
4417 		if (b != NULL)
4418 		{
4419 			c->ClientX = BufToX(b, false);
4420 			FreeBuf(b);
4421 		}
4422 		b = PackGetBuf(p, "ClientK");
4423 		if (b != NULL)
4424 		{
4425 			c->ClientK = BufToK(b, true, false, NULL);
4426 			FreeBuf(b);
4427 		}
4428 		break;
4429 
4430 	case CLIENT_AUTHTYPE_SECURE:
4431 		PackGetStr(p, "SecurePublicCertName", c->SecurePublicCertName, sizeof(c->SecurePublicCertName));
4432 		PackGetStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName, sizeof(c->SecurePrivateKeyName));
4433 		break;
4434 
4435   case CLIENT_AUTHTYPE_OPENSSLENGINE:
4436 		b = PackGetBuf(p, "ClientX");
4437 		if (b != NULL)
4438 		{
4439 			c->ClientX = BufToX(b, false);
4440 			FreeBuf(b);
4441 		}
4442     PackGetStr(p, "OpensslEnginePrivateKeyName", c->OpensslEnginePrivateKeyName, sizeof(c->OpensslEnginePrivateKeyName));
4443     PackGetStr(p, "OpensslEngineName", c->OpensslEngineName, sizeof(c->OpensslEngineName));
4444     break;
4445 	}
4446 }
OutRpcClientAuth(PACK * p,CLIENT_AUTH * c)4447 void OutRpcClientAuth(PACK *p, CLIENT_AUTH *c)
4448 {
4449 	BUF *b;
4450 	// Validate arguments
4451 	if (c == NULL || p == NULL)
4452 	{
4453 		return;
4454 	}
4455 
4456 	PackAddInt(p, "AuthType", c->AuthType);
4457 	PackAddStr(p, "Username", c->Username);
4458 
4459 	switch (c->AuthType)
4460 	{
4461 	case CLIENT_AUTHTYPE_ANONYMOUS:
4462 		break;
4463 
4464 	case CLIENT_AUTHTYPE_PASSWORD:
4465 		PackAddData(p, "HashedPassword", c->HashedPassword, SHA1_SIZE);
4466 		break;
4467 
4468 	case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
4469 		PackAddStr(p, "PlainPassword", c->PlainPassword);
4470 		break;
4471 
4472 	case CLIENT_AUTHTYPE_CERT:
4473 		b = XToBuf(c->ClientX, false);
4474 		if (b != NULL)
4475 		{
4476 			PackAddBuf(p, "ClientX", b);
4477 			FreeBuf(b);
4478 		}
4479 		b = KToBuf(c->ClientK, false, NULL);
4480 		if (b != NULL)
4481 		{
4482 			PackAddBuf(p, "ClientK", b);
4483 			FreeBuf(b);
4484 		}
4485 		break;
4486 
4487 	case CLIENT_AUTHTYPE_SECURE:
4488 		PackAddStr(p, "SecurePublicCertName", c->SecurePublicCertName);
4489 		PackAddStr(p, "SecurePrivateKeyName", c->SecurePrivateKeyName);
4490 		break;
4491 
4492 	case CLIENT_AUTHTYPE_OPENSSLENGINE:
4493 		b = XToBuf(c->ClientX, false);
4494 		if (b != NULL)
4495 		{
4496 			PackAddBuf(p, "ClientX", b);
4497 			FreeBuf(b);
4498 		}
4499 		PackAddStr(p, "OpensslEnginePrivateKeyName", c->OpensslEnginePrivateKeyName);
4500 		PackAddStr(p, "OpensslEngineName", c->OpensslEngineName);
4501 		break;
4502 	}
4503 }
4504 
4505 // RPC_CLIENT_CREATE_ACCOUNT
InRpcClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT * c,PACK * p)4506 void InRpcClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *c, PACK *p)
4507 {
4508 	BUF *b;
4509 	// Validate arguments
4510 	if (c == NULL || p == NULL)
4511 	{
4512 		return;
4513 	}
4514 
4515 	Zero(c, sizeof(RPC_CLIENT_CREATE_ACCOUNT));
4516 	c->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
4517 	c->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
4518 
4519 	InRpcClientOption(c->ClientOption, p);
4520 	InRpcClientAuth(c->ClientAuth, p);
4521 
4522 	c->StartupAccount = PackGetInt(p, "StartupAccount") ? true : false;
4523 	c->CheckServerCert = PackGetInt(p, "CheckServerCert") ? true : false;
4524 	c->RetryOnServerCert = PackGetInt(p, "RetryOnServerCert") ? true : false;
4525 	b = PackGetBuf(p, "ServerCert");
4526 	if (b != NULL)
4527 	{
4528 		c->ServerCert = BufToX(b, false);
4529 		FreeBuf(b);
4530 	}
4531 	PackGetData2(p, "ShortcutKey", c->ShortcutKey, sizeof(c->ShortcutKey));
4532 }
OutRpcClientCreateAccount(PACK * p,RPC_CLIENT_CREATE_ACCOUNT * c)4533 void OutRpcClientCreateAccount(PACK *p, RPC_CLIENT_CREATE_ACCOUNT *c)
4534 {
4535 	BUF *b;
4536 	// Validate arguments
4537 	if (c == NULL || p == NULL)
4538 	{
4539 		return;
4540 	}
4541 
4542 	OutRpcClientOption(p, c->ClientOption);
4543 	OutRpcClientAuth(p, c->ClientAuth);
4544 
4545 	PackAddInt(p, "StartupAccount", c->StartupAccount);
4546 	PackAddInt(p, "CheckServerCert", c->CheckServerCert);
4547 	PackAddInt(p, "RetryOnServerCert", c->RetryOnServerCert);
4548 	if (c->ServerCert != NULL)
4549 	{
4550 		b = XToBuf(c->ServerCert, false);
4551 		if (b != NULL)
4552 		{
4553 			PackAddBuf(p, "ServerCert", b);
4554 			FreeBuf(b);
4555 		}
4556 	}
4557 	PackAddData(p, "ShortcutKey", c->ShortcutKey, sizeof(c->ShortcutKey));
4558 }
4559 
4560 // RPC_CLIENT_ENUM_ACCOUNT
InRpcClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT * e,PACK * p)4561 void InRpcClientEnumAccount(RPC_CLIENT_ENUM_ACCOUNT *e, PACK *p)
4562 {
4563 	UINT i;
4564 	// Validate arguments
4565 	if (e == NULL || p == NULL)
4566 	{
4567 		return;
4568 	}
4569 
4570 	Zero(e, sizeof(RPC_CLIENT_ENUM_ACCOUNT));
4571 
4572 	e->NumItem = PackGetNum(p, "NumItem");
4573 	e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM *) * e->NumItem);
4574 
4575 	for (i = 0;i < e->NumItem;i++)
4576 	{
4577 		RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i] =
4578 			ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM));
4579 
4580 		PackGetUniStrEx(p, "AccountName", item->AccountName, sizeof(item->AccountName), i);
4581 		PackGetStrEx(p, "UserName", item->UserName, sizeof(item->UserName), i);
4582 		PackGetStrEx(p, "ServerName", item->ServerName, sizeof(item->ServerName), i);
4583 		PackGetStrEx(p, "ProxyName", item->ProxyName, sizeof(item->ProxyName), i);
4584 		PackGetStrEx(p, "DeviceName", item->DeviceName, sizeof(item->DeviceName), i);
4585 		item->ProxyType = PackGetIntEx(p, "ProxyType", i);
4586 		item->Active = PackGetIntEx(p, "Active", i) ? true : false;
4587 		item->StartupAccount = PackGetIntEx(p, "StartupAccount", i) ? true : false;
4588 		item->Connected = PackGetBoolEx(p, "Connected", i);
4589 		item->Port = PackGetIntEx(p, "Port", i);
4590 		PackGetStrEx(p, "HubName", item->HubName, sizeof(item->HubName), i);
4591 		item->CreateDateTime = PackGetInt64Ex(p, "CreateDateTime", i);
4592 		item->UpdateDateTime = PackGetInt64Ex(p, "UpdateDateTime", i);
4593 		item->LastConnectDateTime = PackGetInt64Ex(p, "LastConnectDateTime", i);
4594 	}
4595 }
OutRpcClientEnumAccount(PACK * p,RPC_CLIENT_ENUM_ACCOUNT * e)4596 void OutRpcClientEnumAccount(PACK *p, RPC_CLIENT_ENUM_ACCOUNT *e)
4597 {
4598 	UINT i;
4599 	// Validate arguments
4600 	if (e == NULL || p == NULL)
4601 	{
4602 		return;
4603 	}
4604 
4605 	PackAddNum(p, "NumItem", e->NumItem);
4606 
4607 	PackSetCurrentJsonGroupName(p, "AccountList");
4608 	for (i = 0;i < e->NumItem;i++)
4609 	{
4610 		RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = e->Items[i];
4611 
4612 		PackAddUniStrEx(p, "AccountName", item->AccountName, i, e->NumItem);
4613 		PackAddStrEx(p, "UserName", item->UserName, i, e->NumItem);
4614 		PackAddStrEx(p, "ServerName", item->ServerName, i, e->NumItem);
4615 		PackAddStrEx(p, "ProxyName", item->ProxyName, i, e->NumItem);
4616 		PackAddStrEx(p, "DeviceName", item->DeviceName, i, e->NumItem);
4617 		PackAddIntEx(p, "ProxyType", item->ProxyType, i, e->NumItem);
4618 		PackAddIntEx(p, "Active", item->Active, i, e->NumItem);
4619 		PackAddIntEx(p, "StartupAccount", item->StartupAccount, i, e->NumItem);
4620 		PackAddBoolEx(p, "Connected", item->Connected, i, e->NumItem);
4621 		PackAddIntEx(p, "Port", item->Port, i, e->NumItem);
4622 		PackAddStrEx(p, "HubName", item->HubName, i, e->NumItem);
4623 		PackAddTime64Ex(p, "CreateDateTime", item->CreateDateTime, i, e->NumItem);
4624 		PackAddTime64Ex(p, "UpdateDateTime", item->UpdateDateTime, i, e->NumItem);
4625 		PackAddTime64Ex(p, "LastConnectDateTime", item->LastConnectDateTime, i, e->NumItem);
4626 	}
4627 	PackSetCurrentJsonGroupName(p, NULL);
4628 }
4629 
4630 // RPC_CLIENT_DELETE_ACCOUNT
InRpcClientDeleteAccount(RPC_CLIENT_DELETE_ACCOUNT * a,PACK * p)4631 void InRpcClientDeleteAccount(RPC_CLIENT_DELETE_ACCOUNT *a, PACK *p)
4632 {
4633 	// Validate arguments
4634 	if (a == NULL || p == NULL)
4635 	{
4636 		return;
4637 	}
4638 
4639 	Zero(a, sizeof(RPC_CLIENT_DELETE_ACCOUNT));
4640 	PackGetUniStr(p, "AccountName", a->AccountName, sizeof(a->AccountName));
4641 }
OutRpcClientDeleteAccount(PACK * p,RPC_CLIENT_DELETE_ACCOUNT * a)4642 void OutRpcClientDeleteAccount(PACK *p, RPC_CLIENT_DELETE_ACCOUNT *a)
4643 {
4644 	// Validate arguments
4645 	if (a == NULL || p == NULL)
4646 	{
4647 		return;
4648 	}
4649 
4650 	PackAddUniStr(p, "AccountName", a->AccountName);
4651 }
4652 
4653 // RPC_RENAME_ACCOUNT
InRpcRenameAccount(RPC_RENAME_ACCOUNT * a,PACK * p)4654 void InRpcRenameAccount(RPC_RENAME_ACCOUNT *a, PACK *p)
4655 {
4656 	// Validate arguments
4657 	if (a == NULL || p == NULL)
4658 	{
4659 		return;
4660 	}
4661 
4662 	Zero(a, sizeof(RPC_RENAME_ACCOUNT));
4663 
4664 	PackGetUniStr(p, "OldName", a->OldName, sizeof(a->OldName));
4665 	PackGetUniStr(p, "NewName", a->NewName, sizeof(a->NewName));
4666 }
OutRpcRenameAccount(PACK * p,RPC_RENAME_ACCOUNT * a)4667 void OutRpcRenameAccount(PACK *p, RPC_RENAME_ACCOUNT *a)
4668 {
4669 	// Validate arguments
4670 	if (a == NULL || p == NULL)
4671 	{
4672 		return;
4673 	}
4674 
4675 	PackAddUniStr(p, "OldName", a->OldName);
4676 	PackAddUniStr(p, "NewName", a->NewName);
4677 }
4678 
4679 // RPC_CLIENT_GET_ACCOUNT
InRpcClientGetAccount(RPC_CLIENT_GET_ACCOUNT * c,PACK * p)4680 void InRpcClientGetAccount(RPC_CLIENT_GET_ACCOUNT *c, PACK *p)
4681 {
4682 	BUF *b;
4683 	// Validate arguments
4684 	if (c == NULL || p == NULL)
4685 	{
4686 		return;
4687 	}
4688 
4689 	Zero(c, sizeof(RPC_CLIENT_GET_ACCOUNT));
4690 
4691 	c->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
4692 	c->ClientAuth = ZeroMalloc(sizeof(CLIENT_AUTH));
4693 
4694 	PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
4695 	c->StartupAccount = PackGetInt(p, "StartupAccount") ? true : false;
4696 	c->CheckServerCert = PackGetInt(p, "CheckServerCert") ? true : false;
4697 	c->RetryOnServerCert = PackGetInt(p, "RetryOnServerCert") ? true : false;
4698 	b = PackGetBuf(p, "ServerCert");
4699 	if (b != NULL)
4700 	{
4701 		c->ServerCert = BufToX(b, false);
4702 		FreeBuf(b);
4703 	}
4704 
4705 	InRpcClientOption(c->ClientOption, p);
4706 	InRpcClientAuth(c->ClientAuth, p);
4707 
4708 	c->CreateDateTime = PackGetInt64(p, "CreateDateTime");
4709 	c->UpdateDateTime = PackGetInt64(p, "UpdateDateTime");
4710 	c->LastConnectDateTime = PackGetInt64(p, "LastConnectDateTime");
4711 
4712 	PackGetData2(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);
4713 }
OutRpcClientGetAccount(PACK * p,RPC_CLIENT_GET_ACCOUNT * c)4714 void OutRpcClientGetAccount(PACK *p, RPC_CLIENT_GET_ACCOUNT *c)
4715 {
4716 	BUF *b;
4717 	// Validate arguments
4718 	if (c == NULL || p == NULL)
4719 	{
4720 		return;
4721 	}
4722 
4723 	PackAddUniStr(p, "AccountName", c->AccountName);
4724 	PackAddInt(p, "StartupAccount", c->StartupAccount);
4725 	PackAddInt(p, "CheckServerCert", c->CheckServerCert);
4726 	PackAddInt(p, "RetryOnServerCert", c->RetryOnServerCert);
4727 
4728 	if (c->ServerCert != NULL)
4729 	{
4730 		b = XToBuf(c->ServerCert, false);
4731 		if (b != NULL)
4732 		{
4733 			PackAddBuf(p, "ServerCert", b);
4734 			FreeBuf(b);
4735 		}
4736 	}
4737 
4738 	OutRpcClientOption(p, c->ClientOption);
4739 	OutRpcClientAuth(p, c->ClientAuth);
4740 
4741 	PackAddData(p, "ShortcutKey", c->ShortcutKey, SHA1_SIZE);
4742 
4743 	PackAddTime64(p, "CreateDateTime", c->CreateDateTime);
4744 	PackAddTime64(p, "UpdateDateTime", c->UpdateDateTime);
4745 	PackAddTime64(p, "LastConnectDateTime", c->LastConnectDateTime);
4746 }
4747 
4748 // RPC_CLIENT_CONNECT
InRpcClientConnect(RPC_CLIENT_CONNECT * c,PACK * p)4749 void InRpcClientConnect(RPC_CLIENT_CONNECT *c, PACK *p)
4750 {
4751 	// Validate arguments
4752 	if (c == NULL || p == NULL)
4753 	{
4754 		return;
4755 	}
4756 
4757 	Zero(c, sizeof(RPC_CLIENT_CONNECT));
4758 
4759 	PackGetUniStr(p, "AccountName", c->AccountName, sizeof(c->AccountName));
4760 }
OutRpcClientConnect(PACK * p,RPC_CLIENT_CONNECT * c)4761 void OutRpcClientConnect(PACK *p, RPC_CLIENT_CONNECT *c)
4762 {
4763 	// Validate arguments
4764 	if (c == NULL || p == NULL)
4765 	{
4766 		return;
4767 	}
4768 
4769 	PackAddUniStr(p, "AccountName", c->AccountName);
4770 }
4771 
4772 // POLICY
InRpcPolicy(POLICY * o,PACK * p)4773 void InRpcPolicy(POLICY *o, PACK *p)
4774 {
4775 	POLICY *pol;
4776 	// Validate arguments
4777 	if (o == NULL || p == NULL)
4778 	{
4779 		return;
4780 	}
4781 
4782 	pol = PackGetPolicy(p);
4783 	Copy(o, pol, sizeof(POLICY));
4784 	Free(pol);
4785 }
OutRpcPolicy(PACK * p,POLICY * o)4786 void OutRpcPolicy(PACK *p, POLICY *o)
4787 {
4788 	// Validate arguments
4789 	if (o == NULL || p == NULL)
4790 	{
4791 		return;
4792 	}
4793 
4794 	PackAddPolicy(p, o);
4795 }
4796 
4797 // RPC_CLIENT_GET_CONNECTION_STATUS
InRpcClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS * s,PACK * p)4798 void InRpcClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *s, PACK *p)
4799 {
4800 	BUF *b;
4801 	// Validate arguments
4802 	if (s == NULL || p == NULL)
4803 	{
4804 		return;
4805 	}
4806 
4807 	Zero(s, sizeof(RPC_CLIENT_GET_CONNECTION_STATUS));
4808 
4809 	PackGetUniStr(p, "AccountName", s->AccountName, sizeof(s->AccountName));
4810 
4811 	PackGetStr(p, "ServerName", s->ServerName, sizeof(s->ServerName));
4812 	PackGetStr(p, "ServerProductName", s->ServerProductName, sizeof(s->ServerProductName));
4813 	PackGetStr(p, "CipherName", s->CipherName, sizeof(s->CipherName));
4814 	PackGetStr(p, "SessionName", s->SessionName, sizeof(s->SessionName));
4815 	PackGetStr(p, "ConnectionName", s->ConnectionName, sizeof(s->ConnectionName));
4816 
4817 	if (PackGetDataSize(p, "SessionKey") == SHA1_SIZE)
4818 	{
4819 		PackGetData(p, "SessionKey", s->SessionKey);
4820 	}
4821 
4822 	s->SessionStatus = PackGetInt(p, "SessionStatus");
4823 	s->ServerPort = PackGetInt(p, "ServerPort");
4824 	s->ServerProductVer = PackGetInt(p, "ServerProductVer");
4825 	s->ServerProductBuild = PackGetInt(p, "ServerProductBuild");
4826 	s->NumConnectionsEstablished = PackGetInt(p, "NumConnectionsEstablished");
4827 	s->MaxTcpConnections = PackGetInt(p, "MaxTcpConnections");
4828 	s->NumTcpConnections = PackGetInt(p, "NumTcpConnections");
4829 	s->NumTcpConnectionsUpload = PackGetInt(p, "NumTcpConnectionsUpload");
4830 	s->NumTcpConnectionsDownload = PackGetInt(p, "NumTcpConnectionsDownload");
4831 
4832 	s->StartTime = PackGetInt64(p, "StartTime");
4833 	/* !!! Do not correct the spelling to keep the backward protocol compatibility !!!  */
4834 	s->FirstConnectionEstablisiedTime = PackGetInt64(p, "FirstConnectionEstablisiedTime");
4835 	s->CurrentConnectionEstablishTime = PackGetInt64(p, "CurrentConnectionEstablishTime");
4836 	s->TotalSendSize = PackGetInt64(p, "TotalSendSize");
4837 	s->TotalRecvSize = PackGetInt64(p, "TotalRecvSize");
4838 	s->TotalSendSizeReal = PackGetInt64(p, "TotalSendSizeReal");
4839 	s->TotalRecvSizeReal = PackGetInt64(p, "TotalRecvSizeReal");
4840 
4841 	s->Active = PackGetInt(p, "Active") ? true : false;
4842 	s->Connected = PackGetInt(p, "Connected") ? true : false;
4843 	s->HalfConnection = PackGetInt(p, "HalfConnection") ? true : false;
4844 	s->QoS = PackGetInt(p, "QoS") ? true : false;
4845 	s->UseEncrypt = PackGetInt(p, "UseEncrypt") ? true : false;
4846 	s->UseCompress = PackGetInt(p, "UseCompress") ? true : false;
4847 	s->IsRUDPSession = PackGetInt(p, "IsRUDPSession") ? true : false;
4848 	PackGetStr(p, "UnderlayProtocol", s->UnderlayProtocol, sizeof(s->UnderlayProtocol));
4849 	s->IsUdpAccelerationEnabled = PackGetInt(p, "IsUdpAccelerationEnabled") ? true : false;
4850 	s->IsUsingUdpAcceleration = PackGetInt(p, "IsUsingUdpAcceleration") ? true : false;
4851 
4852 	s->IsBridgeMode = PackGetBool(p, "IsBridgeMode");
4853 	s->IsMonitorMode = PackGetBool(p, "IsMonitorMode");
4854 
4855 	s->VLanId = PackGetInt(p, "VLanId");
4856 
4857 	b = PackGetBuf(p, "ServerX");
4858 	if (b != NULL)
4859 	{
4860 		s->ServerX = BufToX(b, false);
4861 		FreeBuf(b);
4862 	}
4863 
4864 	b = PackGetBuf(p, "ClientX");
4865 	if (b != NULL)
4866 	{
4867 		s->ClientX = BufToX(b, false);
4868 		FreeBuf(b);
4869 	}
4870 
4871 	InRpcPolicy(&s->Policy, p);
4872 
4873 	InRpcTraffic(&s->Traffic, p);
4874 }
OutRpcClientGetConnectionStatus(PACK * p,RPC_CLIENT_GET_CONNECTION_STATUS * c)4875 void OutRpcClientGetConnectionStatus(PACK *p, RPC_CLIENT_GET_CONNECTION_STATUS *c)
4876 {
4877 	BUF *b;
4878 	// Validate arguments
4879 	if (p == NULL || c == NULL)
4880 	{
4881 		return;
4882 	}
4883 
4884 	PackAddUniStr(p, "AccountName", c->AccountName);
4885 
4886 	PackAddStr(p, "ServerName", c->ServerName);
4887 	PackAddStr(p, "ServerProductName", c->ServerProductName);
4888 	PackAddStr(p, "CipherName", c->CipherName);
4889 	PackAddStr(p, "SessionName", c->SessionName);
4890 	PackAddStr(p, "ConnectionName", c->ConnectionName);
4891 
4892 	PackAddData(p, "SessionKey", c->SessionKey, SHA1_SIZE);
4893 
4894 	PackAddBool(p, "Active", c->Active);
4895 	PackAddBool(p, "Connected", c->Connected);
4896 	PackAddInt(p, "SessionStatus", c->SessionStatus);
4897 	PackAddInt(p, "ServerPort", c->ServerPort);
4898 	PackAddInt(p, "ServerProductVer", c->ServerProductVer);
4899 	PackAddInt(p, "ServerProductBuild", c->ServerProductBuild);
4900 	PackAddInt(p, "NumConnectionsEstablished", c->NumConnectionsEstablished);
4901 	PackAddBool(p, "HalfConnection", c->HalfConnection);
4902 	PackAddBool(p, "QoS", c->QoS);
4903 	PackAddInt(p, "MaxTcpConnections", c->MaxTcpConnections);
4904 	PackAddInt(p, "NumTcpConnections", c->NumTcpConnections);
4905 	PackAddInt(p, "NumTcpConnectionsUpload", c->NumTcpConnectionsUpload);
4906 	PackAddInt(p, "NumTcpConnectionsDownload", c->NumTcpConnectionsDownload);
4907 	PackAddBool(p, "UseEncrypt", c->UseEncrypt);
4908 	PackAddBool(p, "UseCompress", c->UseCompress);
4909 	PackAddBool(p, "IsRUDPSession", c->IsRUDPSession);
4910 	PackAddStr(p, "UnderlayProtocol", c->UnderlayProtocol);
4911 	PackAddBool(p, "IsUdpAccelerationEnabled", c->IsUdpAccelerationEnabled);
4912 	PackAddBool(p, "IsUsingUdpAcceleration", c->IsUsingUdpAcceleration);
4913 
4914 	PackAddBool(p, "IsBridgeMode", c->IsBridgeMode);
4915 	PackAddBool(p, "IsMonitorMode", c->IsMonitorMode);
4916 
4917 	PackAddTime64(p, "StartTime", c->StartTime);
4918 	PackAddTime64(p, "FirstConnectionEstablisiedTime", c->FirstConnectionEstablisiedTime);
4919 	PackAddTime64(p, "CurrentConnectionEstablishTime", c->CurrentConnectionEstablishTime);
4920 	PackAddInt64(p, "TotalSendSize", c->TotalSendSize);
4921 	PackAddInt64(p, "TotalRecvSize", c->TotalRecvSize);
4922 	PackAddInt64(p, "TotalSendSizeReal", c->TotalSendSizeReal);
4923 	PackAddInt64(p, "TotalRecvSizeReal", c->TotalRecvSizeReal);
4924 
4925 	PackAddInt(p, "VLanId", c->VLanId);
4926 
4927 	OutRpcPolicy(p, &c->Policy);
4928 
4929 	OutRpcTraffic(p, &c->Traffic);
4930 
4931 	if (c->ServerX != NULL)
4932 	{
4933 		b = XToBuf(c->ServerX, false);
4934 		PackAddBuf(p, "ServerX", b);
4935 		FreeBuf(b);
4936 	}
4937 
4938 	if (c->ClientX != NULL)
4939 	{
4940 		b = XToBuf(c->ClientX, false);
4941 		PackAddBuf(p, "ClientX", b);
4942 		FreeBuf(b);
4943 	}
4944 }
4945 
4946 // Notification main
CiNotifyMain(CLIENT * c,SOCK * s)4947 void CiNotifyMain(CLIENT *c, SOCK *s)
4948 {
4949 	CANCEL *cancel;
4950 	// Validate arguments
4951 	if (c == NULL || s == NULL)
4952 	{
4953 		return;
4954 	}
4955 
4956 	// Register a Cancel
4957 	cancel = NewCancel();
4958 	LockList(c->NotifyCancelList);
4959 	{
4960 		Add(c->NotifyCancelList, cancel);
4961 	}
4962 	UnlockList(c->NotifyCancelList);
4963 
4964 	// Wait
4965 	while (true)
4966 	{
4967 		char ch = '@';
4968 		SOCKSET set;
4969 		InitSockSet(&set);
4970 		AddSockSet(&set, s);
4971 		Select(&set, INFINITE, cancel, NULL);
4972 
4973 		if (c->Halt)
4974 		{
4975 			// Abort
4976 			break;
4977 		}
4978 
4979 		// 1 byte transmission
4980 		if (Send(s, &ch, 1, false) == 0)
4981 		{
4982 			// Disconnected
4983 			break;
4984 		}
4985 	}
4986 
4987 	// Disconnect
4988 	Disconnect(s);
4989 
4990 	// Unregister the Cancel
4991 	LockList(c->NotifyCancelList);
4992 	{
4993 		Delete(c->NotifyCancelList, cancel);
4994 	}
4995 	UnlockList(c->NotifyCancelList);
4996 
4997 	ReleaseCancel(cancel);
4998 }
4999 
5000 // RPC acceptance code
CiRpcAccepted(CLIENT * c,SOCK * s)5001 void CiRpcAccepted(CLIENT *c, SOCK *s)
5002 {
5003 	UCHAR hashed_password[SHA1_SIZE];
5004 	UINT rpc_mode;
5005 	UINT retcode;
5006 	RPC *rpc;
5007 	// Validate arguments
5008 	if (c == NULL || s == NULL)
5009 	{
5010 		return;
5011 	}
5012 
5013 	// Receive the RPC mode
5014 	if (RecvAll(s, &rpc_mode, sizeof(UINT), false) == false)
5015 	{
5016 		return;
5017 	}
5018 
5019 	rpc_mode = Endian32(rpc_mode);
5020 
5021 	if (rpc_mode == CLIENT_RPC_MODE_NOTIFY)
5022 	{
5023 		// Notification mode
5024 		CiNotifyMain(c, s);
5025 		return;
5026 	}
5027 	else if (rpc_mode == CLIENT_RPC_MODE_SHORTCUT || rpc_mode == CLIENT_RPC_MODE_SHORTCUT_DISCONNECT)
5028 	{
5029 		// Shortcut key received
5030 		UCHAR key[SHA1_SIZE];
5031 		UINT err = ERR_NO_ERROR;
5032 		if (RecvAll(s, key, SHA1_SIZE, false))
5033 		{
5034 			UINT i;
5035 			wchar_t title[MAX_ACCOUNT_NAME_LEN + 1];
5036 			bool ok = false;
5037 			// Connect to the specified setting
5038 			LockList(c->AccountList);
5039 			{
5040 				for (i = 0;i < LIST_NUM(c->AccountList);i++)
5041 				{
5042 					ACCOUNT *a = LIST_DATA(c->AccountList, i);
5043 					Lock(a->lock);
5044 					{
5045 						if (Cmp(a->ShortcutKey, key, SHA1_SIZE) == 0)
5046 						{
5047 							ok = true;
5048 							UniStrCpy(title, sizeof(title), a->ClientOption->AccountName);
5049 						}
5050 					}
5051 					Unlock(a->lock);
5052 				}
5053 			}
5054 			UnlockList(c->AccountList);
5055 
5056 			if (ok == false)
5057 			{
5058 				err = ERR_ACCOUNT_NOT_FOUND;
5059 			}
5060 			else
5061 			{
5062 				RPC_CLIENT_CONNECT t;
5063 				Zero(&t, sizeof(t));
5064 				UniStrCpy(t.AccountName, sizeof(t.AccountName), title);
5065 
5066 				if (rpc_mode == CLIENT_RPC_MODE_SHORTCUT)
5067 				{
5068 					// Connect
5069 					if (CtConnect(c, &t))
5070 					{
5071 						err = ERR_NO_ERROR;
5072 					}
5073 					else
5074 					{
5075 						err = c->Err;
5076 					}
5077 				}
5078 				else
5079 				{
5080 					// Connect
5081 					if (CtDisconnect(c, &t, false))
5082 					{
5083 						err = ERR_NO_ERROR;
5084 					}
5085 					else
5086 					{
5087 						err = c->Err;
5088 					}
5089 				}
5090 			}
5091 
5092 			err = Endian32(err);
5093 			SendAll(s, &err, sizeof(UINT), false);
5094 			(void)RecvAll(s, &err, sizeof(UINT), false);
5095 		}
5096 		return;
5097 	}
5098 
5099 	// Password reception
5100 	if (RecvAll(s, hashed_password, SHA1_SIZE, false) == false)
5101 	{
5102 		return;
5103 	}
5104 
5105 	retcode = 0;
5106 
5107 	// Password comparison
5108 	if (Cmp(hashed_password, c->EncryptedPassword, SHA1_SIZE) != 0)
5109 	{
5110 		retcode = 1;
5111 	}
5112 
5113 	if (c->PasswordRemoteOnly && IsLocalHostIP(&s->RemoteIP))
5114 	{
5115 		// If in a mode that requires a password only remote,
5116 		// the password sent from localhost is considered to be always correct
5117 		retcode = 0;
5118 	}
5119 
5120 	Lock(c->lock);
5121 	{
5122 		if (c->Config.AllowRemoteConfig == false)
5123 		{
5124 			// If the remote control is prohibited,
5125 			// identify whether this connection is from remote
5126 			if (IsLocalHostIP(&s->RemoteIP) == false)
5127 			{
5128 				retcode = 2;
5129 			}
5130 		}
5131 	}
5132 	Unlock(c->lock);
5133 
5134 	retcode = Endian32(retcode);
5135 	// Error code transmission
5136 	if (SendAll(s, &retcode, sizeof(UINT), false) == false)
5137 	{
5138 		return;
5139 	}
5140 
5141 
5142 
5143 	if (retcode != 0)
5144 	{
5145 		// Disconnect due to an error
5146 		return;
5147 	}
5148 
5149 	// Create a RPC server
5150 	rpc = StartRpcServer(s, CiRpcDispatch, c);
5151 
5152 	// RPC server operation
5153 	RpcServer(rpc);
5154 
5155 	// Release the RPC server
5156 	EndRpc(rpc);
5157 }
5158 
5159 // RPC acceptance thread
CiRpcAcceptThread(THREAD * thread,void * param)5160 void CiRpcAcceptThread(THREAD *thread, void *param)
5161 {
5162 	CLIENT_RPC_CONNECTION *conn;
5163 	CLIENT *c;
5164 	SOCK *s;
5165 	// Validate arguments
5166 	if (thread == NULL || param == NULL)
5167 	{
5168 		return;
5169 	}
5170 
5171 	conn = (CLIENT_RPC_CONNECTION *)param;
5172 	s = conn->Sock;
5173 	c = conn->Client;
5174 	AddRef(s->ref);
5175 
5176 	// Add to the RPC connection list
5177 	LockList(c->RpcConnectionList);
5178 	{
5179 		Add(c->RpcConnectionList, conn);
5180 	}
5181 	UnlockList(c->RpcConnectionList);
5182 
5183 	NoticeThreadInit(thread);
5184 
5185 	// Main process
5186 	CiRpcAccepted(c, s);
5187 
5188 	// Release from the connection list
5189 	LockList(c->RpcConnectionList);
5190 	{
5191 		Delete(c->RpcConnectionList, conn);
5192 	}
5193 	UnlockList(c->RpcConnectionList);
5194 
5195 	ReleaseSock(conn->Sock);
5196 	ReleaseThread(conn->Thread);
5197 	Free(conn);
5198 
5199 	Disconnect(s);
5200 	ReleaseSock(s);
5201 }
5202 
5203 // RPC server thread
CiRpcServerThread(THREAD * thread,void * param)5204 void CiRpcServerThread(THREAD *thread, void *param)
5205 {
5206 	CLIENT *c;
5207 	SOCK *listener;
5208 	UINT i;
5209 	LIST *thread_list;
5210 	// Validate arguments
5211 	if (thread == NULL || param == NULL)
5212 	{
5213 		return;
5214 	}
5215 
5216 	c = (CLIENT *)param;
5217 
5218 	// RPC connection list
5219 	c->RpcConnectionList = NewList(NULL);
5220 
5221 	// Open the port
5222 	listener = NULL;
5223 	for (i = CLIENT_CONFIG_PORT;i < (CLIENT_CONFIG_PORT + 5);i++)
5224 	{
5225 		listener = Listen(i);
5226 		if (listener != NULL)
5227 		{
5228 			break;
5229 		}
5230 	}
5231 
5232 	if (listener == NULL)
5233 	{
5234 		// Error
5235 		Alert(CEDAR_PRODUCT_STR " VPN Client RPC Port Open Failed.", CEDAR_CLIENT_STR);
5236 		return;
5237 	}
5238 
5239 #ifdef OS_WIN32
5240 	MsRegWriteIntEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PORT, i, false, true);
5241 	MsRegWriteIntEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PID, MsGetCurrentProcessId(), false, true);
5242 #endif	// OS_WIN32
5243 
5244 	c->RpcListener = listener;
5245 	AddRef(listener->ref);
5246 
5247 	NoticeThreadInit(thread);
5248 
5249 	while (true)
5250 	{
5251 		// Wait for client connection
5252 		CLIENT_RPC_CONNECTION *conn;
5253 		SOCK *s = Accept(listener);
5254 		if (s == NULL)
5255 		{
5256 			// Stop
5257 			break;
5258 		}
5259 
5260 		// Create a client processing thread
5261 		conn = ZeroMalloc(sizeof(CLIENT_RPC_CONNECTION));
5262 		conn->Client = c;
5263 		conn->Sock = s;
5264 		AddRef(s->ref);
5265 
5266 		conn->Thread = NewThread(CiRpcAcceptThread, (void *)conn);
5267 		WaitThreadInit(conn->Thread);
5268 
5269 		ReleaseSock(s);
5270 	}
5271 
5272 	// Release the listener
5273 	ReleaseSock(listener);
5274 
5275 	thread_list = NewListFast(NULL);
5276 
5277 	// Set all the event notification
5278 	LockList(c->NotifyCancelList);
5279 	{
5280 		UINT i;
5281 		for (i = 0;i < LIST_NUM(c->NotifyCancelList);i++)
5282 		{
5283 			CANCEL *cancel = LIST_DATA(c->NotifyCancelList, i);
5284 			Cancel(cancel);
5285 		}
5286 	}
5287 	UnlockList(c->NotifyCancelList);
5288 
5289 	// Disconnect all the connections of connected yet
5290 	LockList(c->RpcConnectionList);
5291 	{
5292 		for (i = 0;i < LIST_NUM(c->RpcConnectionList);i++)
5293 		{
5294 			CLIENT_RPC_CONNECTION *cc = LIST_DATA(c->RpcConnectionList, i);
5295 			AddRef(cc->Thread->ref);
5296 			Add(thread_list, cc->Thread);
5297 			Disconnect(cc->Sock);
5298 		}
5299 	}
5300 	UnlockList(c->RpcConnectionList);
5301 
5302 	for (i = 0;i < LIST_NUM(thread_list);i++)
5303 	{
5304 		THREAD *t = LIST_DATA(thread_list, i);
5305 		WaitThread(t, INFINITE);
5306 		ReleaseThread(t);
5307 	}
5308 
5309 	ReleaseList(c->RpcConnectionList);
5310 	ReleaseList(thread_list);
5311 
5312 #ifdef OS_WIN32
5313 	MsRegDeleteValueEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PORT, false, true);
5314 	MsRegDeleteValueEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PID, false, true);
5315 #endif	// OS_WIN32
5316 }
5317 
5318 // Start the Keep
CiInitKeep(CLIENT * c)5319 void CiInitKeep(CLIENT *c)
5320 {
5321 	// Validate arguments
5322 	if (c == NULL)
5323 	{
5324 		return;
5325 	}
5326 
5327 	c->Keep = StartKeep();
5328 
5329 	// Apply settings
5330 	if (c->Config.UseKeepConnect)
5331 	{
5332 		KEEP *k = c->Keep;
5333 		Lock(k->lock);
5334 		{
5335 			StrCpy(k->ServerName, sizeof(k->ServerName), c->Config.KeepConnectHost);
5336 			k->ServerPort = c->Config.KeepConnectPort;
5337 			k->Interval = c->Config.KeepConnectInterval * 1000;
5338 			k->UdpMode = (c->Config.KeepConnectProtocol == CONNECTION_UDP) ? true : false;
5339 			k->Enable = true;
5340 		}
5341 		Unlock(k->lock);
5342 	}
5343 }
5344 
5345 // Stop the Keep
CiFreeKeep(CLIENT * c)5346 void CiFreeKeep(CLIENT *c)
5347 {
5348 	// Validate arguments
5349 	if (c == NULL)
5350 	{
5351 		return;
5352 	}
5353 
5354 	StopKeep(c->Keep);
5355 	c->Keep = NULL;
5356 }
5357 
5358 // Start the RPC
CiStartRpcServer(CLIENT * c)5359 void CiStartRpcServer(CLIENT *c)
5360 {
5361 	// Validate arguments
5362 	if (c == NULL)
5363 	{
5364 		return;
5365 	}
5366 
5367 	c->RpcThread = NewThread(CiRpcServerThread, (void *)c);
5368 	WaitThreadInit(c->RpcThread);
5369 }
5370 
5371 // Stop the RPC
CiStopRpcServer(CLIENT * c)5372 void CiStopRpcServer(CLIENT *c)
5373 {
5374 	// Validate arguments
5375 	if (c == NULL)
5376 	{
5377 		return;
5378 	}
5379 
5380 	Disconnect(c->RpcListener);
5381 	ReleaseSock(c->RpcListener);
5382 
5383 	WaitThread(c->RpcThread, INFINITE);
5384 	ReleaseThread(c->RpcThread);
5385 }
5386 
5387 // Wait for the next notification
CcWaitNotify(NOTIFY_CLIENT * n)5388 bool CcWaitNotify(NOTIFY_CLIENT *n)
5389 {
5390 	UCHAR c;
5391 	// Validate arguments
5392 	if (n == NULL)
5393 	{
5394 		return false;
5395 	}
5396 
5397 	// 1 character reception
5398 	if (RecvAll(n->Sock, &c, 1, false) == false)
5399 	{
5400 		// Disconnected
5401 		return false;
5402 	}
5403 
5404 	return true;
5405 }
5406 
5407 // Connect as a notification client
CcConnectNotify(REMOTE_CLIENT * rc)5408 NOTIFY_CLIENT *CcConnectNotify(REMOTE_CLIENT *rc)
5409 {
5410 	NOTIFY_CLIENT *n;
5411 	SOCK *s;
5412 	char tmp[MAX_SIZE];
5413 	bool rpc_mode = false;
5414 	UINT port;
5415 	// Validate arguments
5416 	if (rc == NULL || rc->Rpc == NULL || rc->Rpc->Sock == NULL)
5417 	{
5418 		return NULL;
5419 	}
5420 
5421 	// Connect
5422 	IPToStr(tmp, sizeof(tmp), &rc->Rpc->Sock->RemoteIP);
5423 	port = rc->Rpc->Sock->RemotePort;
5424 
5425 	s = Connect(tmp, port);
5426 	if (s == NULL)
5427 	{
5428 		return NULL;
5429 	}
5430 
5431 	rpc_mode = Endian32(rpc_mode);
5432 	if (SendAll(s, &rpc_mode, sizeof(rpc_mode), false) == false)
5433 	{
5434 		ReleaseSock(s);
5435 		return NULL;
5436 	}
5437 
5438 	n = ZeroMalloc(sizeof(NOTIFY_CLIENT));
5439 	n->Sock = s;
5440 
5441 	return n;
5442 }
5443 
5444 // Stop the notification client
CcStopNotify(NOTIFY_CLIENT * n)5445 void CcStopNotify(NOTIFY_CLIENT *n)
5446 {
5447 	// Validate arguments
5448 	if (n == NULL)
5449 	{
5450 		return;
5451 	}
5452 
5453 	Disconnect(n->Sock);
5454 }
5455 
5456 // Delete the notification client
CcDisconnectNotify(NOTIFY_CLIENT * n)5457 void CcDisconnectNotify(NOTIFY_CLIENT *n)
5458 {
5459 	// Validate arguments
5460 	if (n == NULL)
5461 	{
5462 		return;
5463 	}
5464 
5465 	// Disconnect
5466 	Disconnect(n->Sock);
5467 	ReleaseSock(n->Sock);
5468 
5469 	// Memory release
5470 	Free(n);
5471 }
5472 
5473 // Disconnect the remote connection
CcDisconnectRpc(REMOTE_CLIENT * rc)5474 void CcDisconnectRpc(REMOTE_CLIENT *rc)
5475 {
5476 	// Validate arguments
5477 	if (rc == NULL)
5478 	{
5479 		return;
5480 	}
5481 
5482 	RpcFree(rc->Rpc);
5483 	Free(rc);
5484 }
5485 
5486 // Connect to the client to start the shortcut connection setting
CcShortcut(UCHAR * key)5487 UINT CcShortcut(UCHAR *key)
5488 {
5489 	UINT ret;
5490 	// Validate arguments
5491 	if (key == NULL)
5492 	{
5493 		return ERR_INVALID_PARAMETER;
5494 	}
5495 
5496 	CcConnectRpcEx("localhost", NULL, NULL, NULL, key, &ret, false, 0);
5497 
5498 	return ret;
5499 }
5500 
5501 // Disconnect the connected shortcut connection
CcShortcutDisconnect(UCHAR * key)5502 UINT CcShortcutDisconnect(UCHAR *key)
5503 {
5504 	UINT ret;
5505 	// Validate arguments
5506 	if (key == NULL)
5507 	{
5508 		return ERR_INVALID_PARAMETER;
5509 	}
5510 
5511 	CcConnectRpcEx("localhost", NULL, NULL, NULL, key, &ret, true, 0);
5512 
5513 	return ret;
5514 }
5515 
5516 // Connect to the remote client
CcConnectRpc(char * server_name,char * password,bool * bad_pass,bool * no_remote,UINT wait_retry)5517 REMOTE_CLIENT *CcConnectRpc(char *server_name, char *password, bool *bad_pass, bool *no_remote, UINT wait_retry)
5518 {
5519 	return CcConnectRpcEx(server_name, password, bad_pass, no_remote, NULL, NULL, false, wait_retry);
5520 }
CcConnectRpcEx(char * server_name,char * password,bool * bad_pass,bool * no_remote,UCHAR * key,UINT * key_error_code,bool shortcut_disconnect,UINT wait_retry)5521 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)
5522 {
5523 	SOCK *s = NULL;
5524 	UINT i;
5525 	UINT retcode;
5526 	UINT rpc_mode = CLIENT_RPC_MODE_MANAGEMENT;
5527 	RPC *rpc;
5528 	REMOTE_CLIENT *ret;
5529 	UCHAR hash_password[SHA1_SIZE];
5530 	UINT port_start;
5531 	UINT64 try_started = 0;
5532 	bool ok;
5533 	UINT reg_port = 0;
5534 	UINT reg_pid = 0;
5535 	// Validate arguments
5536 	if (server_name == NULL)
5537 	{
5538 		return NULL;
5539 	}
5540 	if (password == NULL)
5541 	{
5542 		password = "";
5543 	}
5544 
5545 	if (key_error_code != NULL)
5546 	{
5547 		*key_error_code = ERR_NO_ERROR;
5548 	}
5549 
5550 	if (bad_pass != NULL)
5551 	{
5552 		*bad_pass = false;
5553 	}
5554 
5555 	if (no_remote != NULL)
5556 	{
5557 		*no_remote = false;
5558 	}
5559 
5560 #ifdef	OS_WIN32
5561 	// read the current port number from the registry of the localhost
5562 	if (StrCmpi(server_name, "localhost") == 0)
5563 	{
5564 		reg_port = MsRegReadIntEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PORT, false, true);
5565 		reg_pid = MsRegReadIntEx2(REG_LOCAL_MACHINE, CLIENT_WIN32_REGKEYNAME, CLIENT_WIN32_REGVALUE_PID, false, true);
5566 
5567 		if (reg_pid != 0)
5568 		{
5569 			if (MsIsServiceRunning(GC_SVC_NAME_VPNCLIENT) == false)
5570 			{
5571 				reg_port = 0;
5572 			}
5573 		}
5574 		else
5575 		{
5576 			reg_port = 0;
5577 		}
5578 	}
5579 
5580 	if (reg_port != 0)
5581 	{
5582 		s = Connect(server_name, reg_port);
5583 
5584 		if (s != NULL)
5585 		{
5586 			goto L_TRY;
5587 		}
5588 	}
5589 
5590 #endif	// OS_WIN32
5591 
5592 	port_start = CLIENT_CONFIG_PORT - 1;
5593 
5594 RETRY:
5595 	port_start++;
5596 
5597 	if (port_start >= (CLIENT_CONFIG_PORT + 5))
5598 	{
5599 		return NULL;
5600 	}
5601 
5602 	ok = false;
5603 
5604 	while (true)
5605 	{
5606 		for (i = port_start;i < (CLIENT_CONFIG_PORT + 5);i++)
5607 		{
5608 			if (CheckTCPPort(server_name, i))
5609 			{
5610 				ok = true;
5611 				break;
5612 			}
5613 		}
5614 
5615 		if (ok)
5616 		{
5617 			break;
5618 		}
5619 
5620 		if (wait_retry == 0)
5621 		{
5622 			break;
5623 		}
5624 
5625 		if (try_started == 0)
5626 		{
5627 			try_started = Tick64();
5628 		}
5629 
5630 		if ((try_started + (UINT64)wait_retry) <= Tick64())
5631 		{
5632 			break;
5633 		}
5634 	}
5635 
5636 	if (ok == false)
5637 	{
5638 		if (key_error_code)
5639 		{
5640 			*key_error_code = ERR_CONNECT_FAILED;
5641 		}
5642 		return NULL;
5643 	}
5644 
5645 	port_start = i;
5646 
5647 	s = Connect(server_name, i);
5648 	if (s == NULL)
5649 	{
5650 		if (key_error_code)
5651 		{
5652 			*key_error_code = ERR_CONNECT_FAILED;
5653 		}
5654 		goto RETRY;
5655 	}
5656 L_TRY:
5657 
5658 	SetTimeout(s, 10000);
5659 
5660 	Sha0(hash_password, password, StrLen(password));
5661 
5662 	if (key != NULL)
5663 	{
5664 		if (shortcut_disconnect == false)
5665 		{
5666 			rpc_mode = CLIENT_RPC_MODE_SHORTCUT;
5667 		}
5668 		else
5669 		{
5670 			rpc_mode = CLIENT_RPC_MODE_SHORTCUT_DISCONNECT;
5671 		}
5672 	}
5673 
5674 	rpc_mode = Endian32(rpc_mode);
5675 	SendAdd(s, &rpc_mode, sizeof(UINT));
5676 
5677 	if (key != NULL)
5678 	{
5679 		SendAdd(s, key, SHA1_SIZE);
5680 	}
5681 	else
5682 	{
5683 		SendAdd(s, hash_password, SHA1_SIZE);
5684 	}
5685 
5686 	if (SendNow(s, false) == false)
5687 	{
5688 		ReleaseSock(s);
5689 		goto RETRY;
5690 	}
5691 
5692 	if (RecvAll(s, &retcode, sizeof(UINT), false) == false)
5693 	{
5694 		ReleaseSock(s);
5695 		goto RETRY;
5696 	}
5697 
5698 	retcode = Endian32(retcode);
5699 
5700 	if (retcode >= 1024)
5701 	{
5702 		ReleaseSock(s);
5703 		goto RETRY;
5704 	}
5705 
5706 	if (key != NULL)
5707 	{
5708 		if (key_error_code)
5709 		{
5710 			*key_error_code = retcode;
5711 		}
5712 		SendAll(s, &retcode, sizeof(UINT), false);
5713 		ReleaseSock(s);
5714 		return NULL;
5715 	}
5716 
5717 	switch (retcode)
5718 	{
5719 	case 1:
5720 		if (bad_pass != NULL)
5721 		{
5722 			*bad_pass = true;
5723 		}
5724 		break;
5725 	case 2:
5726 		if (no_remote != NULL)
5727 		{
5728 			*no_remote = true;
5729 		}
5730 		break;
5731 	}
5732 
5733 	if (retcode != 0)
5734 	{
5735 		ReleaseSock(s);
5736 		return NULL;
5737 	}
5738 
5739 	SetTimeout(s, INFINITE);
5740 
5741 	rpc = StartRpcClient(s, NULL);
5742 
5743 	ReleaseSock(s);
5744 
5745 	ret = ZeroMalloc(sizeof(REMOTE_CLIENT));
5746 	rpc->Param = ret;
5747 
5748 	if (ret != NULL)
5749 	{
5750 		RPC_CLIENT_VERSION t;
5751 
5752 		ret->Rpc = rpc;
5753 		Zero(&t, sizeof(t));
5754 		CcGetClientVersion(ret, &t);
5755 		ret->OsType = t.OsType;
5756 		ret->Unix = OS_IS_UNIX(ret->OsType);
5757 		ret->IsVgcSupported = t.IsVgcSupported;
5758 		ret->ShowVgcLink = t.ShowVgcLink;
5759 		StrCpy(ret->ClientId, sizeof(ret->ClientId), t.ClientId);
5760 	}
5761 
5762 	return ret;
5763 }
5764 
5765 // Get a RPC_CLIENT_GET_CONNECTION_STATUS from the session
CiGetSessionStatus(RPC_CLIENT_GET_CONNECTION_STATUS * st,SESSION * s)5766 void CiGetSessionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st, SESSION *s)
5767 {
5768 	// Validate arguments
5769 	if (st == NULL || s == NULL)
5770 	{
5771 		return;
5772 	}
5773 
5774 	Lock(s->lock);
5775 	{
5776 		// Operation flag
5777 		st->Active = true;
5778 
5779 		// Session status
5780 		st->SessionStatus = s->ClientStatus;
5781 
5782 		// Account name
5783 		UniStrCpy(st->AccountName, sizeof(st->AccountName), s->ClientOption->AccountName);
5784 
5785 		if (s->ClientStatus == CLIENT_STATUS_ESTABLISHED && s->Connection != NULL)
5786 		{
5787 			Lock(s->Connection->lock);
5788 			{
5789 				// Connected flag
5790 				st->Connected = true;
5791 				// Product name
5792 				StrCpy(st->ServerProductName, sizeof(st->ServerProductName), s->Connection->ServerStr);
5793 				// Version
5794 				st->ServerProductVer = s->Connection->ServerVer;
5795 				// Build Number
5796 				st->ServerProductBuild = s->Connection->ServerBuild;
5797 				// Server certificate
5798 				st->ServerX = CloneX(s->Connection->ServerX);
5799 				// Client certificate
5800 				st->ClientX = CloneX(s->Connection->ClientX);
5801 				// Connection completion time of this connection
5802 				st->CurrentConnectionEstablishTime = TickToTime(s->CurrentConnectionEstablishTime);
5803 				// Maximum number of the TCP connections
5804 				st->MaxTcpConnections = s->MaxConnection;
5805 				// Half-connection
5806 				st->HalfConnection = s->HalfConnection;
5807 				// VLAN
5808 				st->VLanId = s->VLanId;
5809 				// VoIP / QoS
5810 				st->QoS = s->QoS;
5811 				if (s->Connection->Protocol == CONNECTION_TCP)
5812 				{
5813 					UINT i;
5814 					// Number of current TCP connections
5815 					LockList(s->Connection->Tcp->TcpSockList);
5816 					{
5817 						st->NumTcpConnections = LIST_NUM(s->Connection->Tcp->TcpSockList);
5818 						if (st->HalfConnection)
5819 						{
5820 							for (i = 0;i < st->NumTcpConnections;i++)
5821 							{
5822 								TCPSOCK *ts = LIST_DATA(s->Connection->Tcp->TcpSockList, i);
5823 								if (ts->Direction & TCP_SERVER_TO_CLIENT)
5824 								{
5825 									st->NumTcpConnectionsDownload++;
5826 								}
5827 								else
5828 								{
5829 									st->NumTcpConnectionsUpload++;
5830 								}
5831 							}
5832 						}
5833 					}
5834 					UnlockList(s->Connection->Tcp->TcpSockList);
5835 				}
5836 				// Use of encryption
5837 				st->UseEncrypt = s->UseEncrypt;
5838 				if (st->UseEncrypt)
5839 				{
5840 					StrCpy(st->CipherName, sizeof(st->CipherName), s->Connection->CipherName);
5841 				}
5842 				// Use of compression
5843 				st->UseCompress = s->UseCompress;
5844 				// R-UDP
5845 				st->IsRUDPSession = s->IsRUDPSession;
5846 				// Physical communication protocol
5847 				StrCpy(st->UnderlayProtocol, sizeof(st->UnderlayProtocol), s->UnderlayProtocol);
5848 				// Protocol details
5849 				StrCpy(st->ProtocolDetails, sizeof(st->ProtocolDetails), s->ProtocolDetails);
5850 				Trim(st->ProtocolDetails);
5851 				// UDP acceleration function
5852 				if (s->IpcSessionShared != NULL && IsEmptyStr(s->IpcSessionShared->ProtocolDetails) == false)
5853 				{
5854 					char tmp[sizeof(s->IpcSessionShared->ProtocolDetails)];
5855 					StrCpy(tmp, sizeof(tmp), s->IpcSessionShared->ProtocolDetails);
5856 					Trim(tmp);
5857 					StrCat(st->ProtocolDetails, sizeof(st->ProtocolDetails), " ");
5858 					StrCat(st->ProtocolDetails, sizeof(st->ProtocolDetails), tmp);
5859 
5860 					st->IsUdpAccelerationEnabled = s->IpcSessionShared->EnableUdpAccel;
5861 					st->IsUsingUdpAcceleration = s->IpcSessionShared->UsingUdpAccel;
5862 				}
5863 				else
5864 				{
5865 					st->IsUdpAccelerationEnabled = s->UseUdpAcceleration;
5866 					st->IsUsingUdpAcceleration = s->IsUsingUdpAcceleration;
5867 				}
5868 				// Session key
5869 				Copy(st->SessionKey, s->SessionKey, SHA1_SIZE);
5870 				// Policy
5871 				Copy(&st->Policy, s->Policy, sizeof(POLICY));
5872 				// Data size
5873 				if (s->ServerMode == false)
5874 				{
5875 					st->TotalSendSize = s->TotalSendSize;
5876 					st->TotalRecvSize = s->TotalRecvSize;
5877 					st->TotalRecvSizeReal = s->TotalRecvSizeReal;
5878 					st->TotalSendSizeReal = s->TotalSendSizeReal;
5879 				}
5880 				else
5881 				{
5882 					st->TotalSendSize = s->TotalRecvSize;
5883 					st->TotalRecvSize = s->TotalSendSize;
5884 					st->TotalRecvSizeReal = s->TotalSendSizeReal;
5885 					st->TotalSendSizeReal = s->TotalRecvSizeReal;
5886 				}
5887 				// Session name
5888 				StrCpy(st->SessionName, sizeof(st->SessionName), s->Name);
5889 				// Connection name
5890 				StrCpy(st->ConnectionName, sizeof(st->ConnectionName), s->Connection->Name);
5891 				// Server name
5892 				StrCpy(st->ServerName, sizeof(st->ServerName), s->Connection->ServerName);
5893 				// Port number
5894 				st->ServerPort = s->Connection->ServerPort;
5895 				// Traffic data
5896 				Lock(s->TrafficLock);
5897 				{
5898 					Copy(&st->Traffic, s->Traffic, sizeof(TRAFFIC));
5899 				}
5900 				Unlock(s->TrafficLock);
5901 
5902 				st->IsBridgeMode = s->IsBridgeMode;
5903 				st->IsMonitorMode = s->IsMonitorMode;
5904 			}
5905 			Unlock(s->Connection->lock);
5906 		}
5907 		// Connection start time
5908 		st->StartTime = TickToTime(s->CreatedTime);
5909 		// Connection completion time of the first connection
5910 		/* !!! Do not correct the spelling to keep the backward protocol compatibility !!!  */
5911 		st->FirstConnectionEstablisiedTime = TickToTime(s->FirstConnectionEstablisiedTime);
5912 		// Number of connections have been established so far
5913 		st->NumConnectionsEstablished = s->NumConnectionsEstablished;
5914 	}
5915 	Unlock(s->lock);
5916 }
5917 
5918 // Get the connection status
CtGetAccountStatus(CLIENT * c,RPC_CLIENT_GET_CONNECTION_STATUS * st)5919 bool CtGetAccountStatus(CLIENT *c, RPC_CLIENT_GET_CONNECTION_STATUS *st)
5920 {
5921 	// Validate arguments
5922 	if (c == NULL || st == NULL)
5923 	{
5924 		return false;
5925 	}
5926 
5927 	LockList(c->AccountList);
5928 	{
5929 		ACCOUNT t, *r;
5930 
5931 		// Search for account
5932 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
5933 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), st->AccountName);
5934 
5935 		r = Search(c->AccountList, &t);
5936 		if (r == NULL)
5937 		{
5938 			// Specified account is not found
5939 			UnlockList(c->AccountList);
5940 
5941 			Free(t.ClientOption);
5942 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
5943 			return false;
5944 		}
5945 
5946 		Free(t.ClientOption);
5947 
5948 		Lock(r->lock);
5949 		{
5950 			Zero(st, sizeof(RPC_CLIENT_GET_CONNECTION_STATUS));
5951 			if (r->ClientSession != NULL)
5952 			{
5953 				SESSION *s = r->ClientSession;
5954 				CiGetSessionStatus(st, s);
5955 			}
5956 		}
5957 		Unlock(r->lock);
5958 	}
5959 	UnlockList(c->AccountList);
5960 
5961 	return true;
5962 }
5963 
5964 // Release the connection status
CiFreeClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS * st)5965 void CiFreeClientGetConnectionStatus(RPC_CLIENT_GET_CONNECTION_STATUS *st)
5966 {
5967 	// Validate arguments
5968 	if (st == NULL)
5969 	{
5970 		return;
5971 	}
5972 
5973 	if (st->ServerX != NULL)
5974 	{
5975 		FreeX(st->ServerX);
5976 	}
5977 
5978 	if (st->ClientX != NULL)
5979 	{
5980 		FreeX(st->ClientX);
5981 	}
5982 }
5983 
5984 // Verification procedure of the server certificate
CiCheckCertProc(SESSION * s,CONNECTION * c,X * server_x,bool * expired)5985 bool CiCheckCertProc(SESSION *s, CONNECTION *c, X *server_x, bool *expired)
5986 {
5987 #ifdef	OS_WIN32
5988 	ACCOUNT *a;
5989 	X *old_x = NULL;
5990 	UI_CHECKCERT dlg;
5991 	// Validate arguments
5992 	if (s == NULL || c == NULL || server_x == NULL)
5993 	{
5994 		return false;
5995 	}
5996 
5997 	if (expired != NULL)
5998 	{
5999 		*expired = false;
6000 	}
6001 
6002 	Zero(&dlg, sizeof(dlg));
6003 
6004 	a = s->Account;
6005 	if (a == NULL)
6006 	{
6007 		return false;
6008 	}
6009 
6010 	Lock(a->lock);
6011 	{
6012 		if (a->CheckServerCert == false)
6013 		{
6014 			// Not to validate the server certificate
6015 			Unlock(a->lock);
6016 			return true;
6017 		}
6018 
6019 		if (a->ServerCert != NULL)
6020 		{
6021 			old_x = CloneX(a->ServerCert);
6022 		}
6023 	}
6024 	Unlock(a->lock);
6025 
6026 	if (CheckXDateNow(server_x) == false)
6027 	{
6028 		// Expired
6029 		if (old_x != NULL)
6030 		{
6031 			FreeX(old_x);
6032 		}
6033 
6034 		if (expired != NULL)
6035 		{
6036 			*expired = true;
6037 		}
6038 
6039 		return false;
6040 	}
6041 
6042 	if (old_x != NULL)
6043 	{
6044 		if (CompareX(old_x, server_x))
6045 		{
6046 			// Matched exactly to the certificate that is already registered
6047 			if (old_x != NULL)
6048 			{
6049 				FreeX(old_x);
6050 			}
6051 			return true;
6052 		}
6053 		else
6054 		{
6055 			dlg.DiffWarning = true;
6056 		}
6057 	}
6058 
6059 	// Because this certificate can not be trusted, confirm to be trusted by showing a dialog box
6060 	UniStrCpy(dlg.AccountName, sizeof(dlg.AccountName), a->ClientOption->AccountName);
6061 	StrCpy(dlg.ServerName, sizeof(dlg.ServerName), a->ClientOption->Hostname);
6062 	dlg.x = server_x;
6063 	dlg.old_x = old_x;
6064 
6065 	dlg.Session = s;
6066 	AddRef(s->ref);
6067 
6068 	CncCheckCert(s, &dlg);
6069 
6070 	ReleaseSession(s);
6071 
6072 	if (old_x != NULL)
6073 	{
6074 		FreeX(old_x);
6075 	}
6076 
6077 	if (dlg.Ok && dlg.SaveServerCert)
6078 	{
6079 		// Save the server certificate and trust it from the next time
6080 		Lock(a->lock);
6081 		{
6082 			if (a->ServerCert != NULL)
6083 			{
6084 				FreeX(a->ServerCert);
6085 			}
6086 
6087 			a->ServerCert = CloneX(server_x);
6088 		}
6089 		Unlock(a->lock);
6090 		CiSaveConfigurationFile(s->Cedar->Client);
6091 	}
6092 
6093 	return dlg.Ok;
6094 #else	// OS_WIN32
6095 	ACCOUNT *a;
6096 	X *old_x = NULL;
6097 	// Validate arguments
6098 	if (s == NULL || c == NULL || server_x == NULL)
6099 	{
6100 		return false;
6101 	}
6102 
6103 	if (expired != NULL)
6104 	{
6105 		*expired = false;
6106 	}
6107 
6108 	a = s->Account;
6109 	if (a == NULL)
6110 	{
6111 		return false;
6112 	}
6113 
6114 	Lock(a->lock);
6115 	{
6116 		if (a->CheckServerCert == false)
6117 		{
6118 			// Not to validate the server certificate
6119 			Unlock(a->lock);
6120 			return true;
6121 		}
6122 
6123 		if (a->ServerCert != NULL)
6124 		{
6125 			old_x = CloneX(a->ServerCert);
6126 		}
6127 	}
6128 	Unlock(a->lock);
6129 
6130 	if (CheckXDateNow(server_x) == false)
6131 	{
6132 		// Expired
6133 		if (old_x != NULL)
6134 		{
6135 			FreeX(old_x);
6136 		}
6137 
6138 		if (expired != NULL)
6139 		{
6140 			*expired = true;
6141 		}
6142 
6143 		return false;
6144 	}
6145 
6146 	if (old_x != NULL)
6147 	{
6148 		if (CompareX(old_x, server_x))
6149 		{
6150 			// Exactly matched to the certificate that is already registered
6151 			if (old_x != NULL)
6152 			{
6153 				FreeX(old_x);
6154 			}
6155 			return true;
6156 		}
6157 		else
6158 		{
6159 			// Mismatch
6160 			if (old_x != NULL)
6161 			{
6162 				FreeX(old_x);
6163 			}
6164 			return false;
6165 		}
6166 	}
6167 
6168 	return false;
6169 #endif	// OS_WIN32
6170 }
6171 
6172 // Signature procedure with a secure device
CiSecureSignProc(SESSION * s,CONNECTION * c,SECURE_SIGN * sign)6173 bool CiSecureSignProc(SESSION *s, CONNECTION *c, SECURE_SIGN *sign)
6174 {
6175 	// The UI is available in Win32
6176 	return CncSecureSignDlg(sign);
6177 }
6178 
6179 #ifdef	OS_WIN32
6180 // Signing procedure (for Win32)
Win32CiSecureSign(SECURE_SIGN * sign)6181 bool Win32CiSecureSign(SECURE_SIGN *sign)
6182 {
6183 	bool ret = false;
6184 	BUF *random;
6185 	// Validate arguments
6186 	if (sign == NULL)
6187 	{
6188 		return false;
6189 	}
6190 
6191 	random = NewBuf();
6192 	WriteBuf(random, sign->Random, SHA1_SIZE);
6193 
6194 	// Batch processing
6195 	{
6196 		WINUI_SECURE_BATCH batch[] =
6197 		{
6198 			{WINUI_SECURE_READ_CERT, sign->SecurePublicCertName, true, NULL, NULL, NULL, NULL, NULL, NULL},
6199 			{WINUI_SECURE_SIGN_WITH_KEY, sign->SecurePrivateKeyName, true, random, NULL, NULL, NULL, NULL, NULL}
6200 		};
6201 
6202 		if (SecureDeviceWindow(NULL, batch, sizeof(batch) / sizeof(batch[0]),
6203 			sign->UseSecureDeviceId, sign->BitmapId) == false)
6204 		{
6205 			// Failure
6206 			if (batch[0].OutputX != 0)
6207 			{
6208 				FreeX(batch[0].OutputX);
6209 			}
6210 			ret = false;
6211 		}
6212 		else
6213 		{
6214 			// Success
6215 			ret = true;
6216 			sign->ClientCert = batch[0].OutputX;
6217 			Copy(sign->Signature, batch[1].OutputSign, MIN(sizeof(sign->Signature),sizeof(batch[1].OutputSign)));
6218 		}
6219 	}
6220 
6221 	FreeBuf(random);
6222 
6223 	return ret;
6224 }
6225 #endif	// OS_WIN32
6226 
6227 // Disconnect
CtDisconnect(CLIENT * c,RPC_CLIENT_CONNECT * connect,bool inner)6228 bool CtDisconnect(CLIENT *c, RPC_CLIENT_CONNECT *connect, bool inner)
6229 {
6230 	bool ret = false;
6231 	ACCOUNT t, *r;
6232 	SESSION *s = NULL;
6233 	// Validate arguments
6234 	if (c == NULL || connect == NULL)
6235 	{
6236 		return false;
6237 	}
6238 
6239 	LockList(c->AccountList);
6240 	{
6241 		// Search for account
6242 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6243 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), connect->AccountName);
6244 
6245 		r = Search(c->AccountList, &t);
6246 		if (r == NULL)
6247 		{
6248 			// Specified account isn't found
6249 			UnlockList(c->AccountList);
6250 
6251 			Free(t.ClientOption);
6252 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
6253 			return false;
6254 		}
6255 
6256 		Free(t.ClientOption);
6257 
6258 		Lock(r->lock);
6259 		{
6260 			if (r->ClientSession == NULL)
6261 			{
6262 				// Not connected
6263 				CiSetError(c, ERR_ACCOUNT_INACTIVE);
6264 			}
6265 			else
6266 			{
6267 				s = r->ClientSession;
6268 				AddRef(s->ref);
6269 				// Disconnect complete
6270 				r->ClientSession = NULL;
6271 				ret = true;
6272 			}
6273 		}
6274 		Unlock(r->lock);
6275 	}
6276 	UnlockList(c->AccountList);
6277 
6278 	if (s != NULL)
6279 	{
6280 		// Disconnect the connection (Wait until the disconnection is complete)
6281 		CLog(c, "LC_DISCONNECT", connect->AccountName);
6282 		StopSession(s);
6283 		ReleaseSession(s);
6284 	}
6285 
6286 
6287 	if (ret != false)
6288 	{
6289 		CiNotify(c);
6290 	}
6291 
6292 	return ret;
6293 }
6294 
6295 // Connect
CtConnect(CLIENT * c,RPC_CLIENT_CONNECT * connect)6296 bool CtConnect(CLIENT *c, RPC_CLIENT_CONNECT *connect)
6297 {
6298 	bool ret = false;
6299 	RPC_CLIENT_ENUM_VLAN t;
6300 	// Validate arguments
6301 	if (c == NULL || connect == NULL)
6302 	{
6303 		return false;
6304 	}
6305 
6306 	Lock(c->lockForConnect);
6307 	{
6308 		Zero(&t, sizeof(t));
6309 		if (CtEnumVLan(c, &t))
6310 		{
6311 			if (t.NumItem == 0)
6312 			{
6313 					// Create a new virtual LAN card named "VPN" automatically
6314 					RPC_CLIENT_CREATE_VLAN t;
6315 
6316 					Zero(&t, sizeof(t));
6317 					StrCpy(t.DeviceName, sizeof(t.DeviceName), "VPN");
6318 					CtCreateVLan(c,  &t);
6319 			}
6320 
6321 			CiFreeClientEnumVLan(&t);
6322 		}
6323 	}
6324 	Unlock(c->lockForConnect);
6325 
6326 	CiNormalizeAccountVLan(c);
6327 
6328 	// Ensure successfully VPN communication by changing the irrational WCM settings in the case of Windows 8 or later
6329 	CiDisableWcmNetworkMinimize(c);
6330 
6331 	LockList(c->AccountList);
6332 	{
6333 		ACCOUNT t, *r;
6334 		bool unix_disabled = false;
6335 
6336 		// Search for account
6337 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6338 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), connect->AccountName);
6339 
6340 		r = Search(c->AccountList, &t);
6341 		if (r == NULL)
6342 		{
6343 			// Specified account isn't found
6344 			UnlockList(c->AccountList);
6345 
6346 			Free(t.ClientOption);
6347 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
6348 			return false;
6349 		}
6350 
6351 		Free(t.ClientOption);
6352 
6353 #ifndef	OS_WIN32
6354 		// Search for the virtual LAN card
6355 		LockList(c->UnixVLanList);
6356 		{
6357 			UNIX_VLAN *v, t;
6358 
6359 			Zero(&t, sizeof(t));
6360 			StrCpy(t.Name, sizeof(t.Name), r->ClientOption->DeviceName);
6361 
6362 			v = Search(c->UnixVLanList, &t);
6363 			if (v == NULL)
6364 			{
6365 				UnlockList(c->UnixVLanList);
6366 				CiSetError(c, ERR_OBJECT_NOT_FOUND);
6367 				return false;
6368 			}
6369 
6370 			unix_disabled = v->Enabled ? false : true;
6371 		}
6372 		UnlockList(c->UnixVLanList);
6373 #endif	// OS_WIN32
6374 
6375 		Lock(r->lock);
6376 		{
6377 			bool already_used = false;
6378 			UINT i;
6379 
6380 			if (r->ClientSession != NULL)
6381 			{
6382 				// Already in connecting
6383 				CiSetError(c, ERR_ACCOUNT_ACTIVE);
6384 			}
6385 			else if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE &&
6386 				c->UseSecureDeviceId == 0)
6387 			{
6388 				// Secure device is not specified
6389 				CiSetError(c, ERR_NO_SECURE_DEVICE_SPECIFIED);
6390 			}
6391 #ifdef	OS_WIN32
6392 			else if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, r->ClientOption->DeviceName) == false &&
6393 				MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, r->ClientOption->DeviceName) == false)
6394 			{
6395 				// Virtual LAN card can not be found
6396 				CiSetError(c, ERR_VLAN_FOR_ACCOUNT_NOT_FOUND);
6397 				CiNotify(c);
6398 				CiSendGlobalPulse(c);
6399 			}
6400 			else if (MsIsVLanEnabled(r->ClientOption->DeviceName) == false)
6401 			{
6402 				// The virtual LAN card is disabled
6403 				CiSetError(c, ERR_VLAN_FOR_ACCOUNT_DISABLED);
6404 				CiNotify(c);
6405 				CiSendGlobalPulse(c);
6406 			}
6407 #else	// OS_WIN32
6408 			else if (unix_disabled)
6409 			{
6410 				// The virtual LAN card is disabled
6411 				CiSetError(c, ERR_VLAN_FOR_ACCOUNT_DISABLED);
6412 				CiNotify(c);
6413 				CiSendGlobalPulse(c);
6414 			}
6415 #endif	// OS_WIN32
6416 			else
6417 			{
6418 				// Check whether the virtual LAN card is being used by a different account already
6419 				for (i = 0;i < LIST_NUM(c->AccountList);i++)
6420 				{
6421 					ACCOUNT *a = LIST_DATA(c->AccountList, i);
6422 					if (a != r)
6423 					{
6424 						if (StrCmpi(a->ClientOption->DeviceName,
6425 							r->ClientOption->DeviceName) == 0)
6426 						{
6427 							if (a->ClientSession != NULL)
6428 							{
6429 								already_used = true;
6430 								break;
6431 							}
6432 						}
6433 					}
6434 				}
6435 
6436 				if (already_used)
6437 				{
6438 					CiSetError(c, ERR_VLAN_FOR_ACCOUNT_USED);
6439 				}
6440 				else
6441 				{
6442 					// Start the connection
6443 					PACKET_ADAPTER *pa = VLanGetPacketAdapter();
6444 
6445 					if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
6446 					{
6447 						// Register a procedure for secure device authentication
6448 						r->ClientAuth->SecureSignProc = CiSecureSignProc;
6449 					}
6450           else if (r->ClientAuth->AuthType == CLIENT_AUTHTYPE_OPENSSLENGINE)
6451 					{
6452               /* r->ClientAuth->ClientK = OpensslEngineToK("asdf"); */
6453 						r->ClientAuth->SecureSignProc = NULL;
6454 					}
6455 					else
6456 					{
6457 						r->ClientAuth->SecureSignProc = NULL;
6458 					}
6459 
6460 					if (r->CheckServerCert)
6461 					{
6462 						// Register a procedure to validate the server certificate
6463 						r->ClientAuth->CheckCertProc = CiCheckCertProc;
6464 					}
6465 					else
6466 					{
6467 						r->ClientAuth->CheckCertProc = NULL;
6468 					}
6469 
6470 					r->StatusPrinter = CiClientStatusPrinter;
6471 					r->LastConnectDateTime = SystemTime64();
6472 
6473 					CLog(c, "LC_CONNECT", connect->AccountName);
6474 
6475 					r->ClientSession = NewClientSessionEx(c->Cedar, r->ClientOption, r->ClientAuth, pa, r);
6476 					Notify(r->ClientSession, CLIENT_NOTIFY_ACCOUNT_CHANGED);
6477 
6478 					ret = true;
6479 				}
6480 			}
6481 		}
6482 		Unlock(r->lock);
6483 
6484 	}
6485 	UnlockList(c->AccountList);
6486 
6487 	CiSaveConfigurationFile(c);
6488 
6489 	return ret;
6490 }
6491 
6492 // Put all unused TUN interfaces down
6493 // Requires account and VLan lists of the CLIENT argument to be already locked
CtVLansDown(CLIENT * c)6494 bool CtVLansDown(CLIENT *c)
6495 {
6496 #ifndef UNIX_LINUX
6497 	return true;
6498 #else
6499 	int i;
6500 	LIST *tmpVLanList;
6501 	UNIX_VLAN t, *r;
6502 	bool result = true;
6503 
6504 	if (c == NULL)
6505 	{
6506 		return false;
6507 	}
6508 
6509 	tmpVLanList = CloneList(c->UnixVLanList);
6510 	if (tmpVLanList == NULL)
6511 	{
6512 		return false;
6513 	}
6514 
6515 	// Remove from tmpVLanList all VLans corresponding to active sessions
6516 	for (i = 0; i < LIST_NUM(c->AccountList); ++i)
6517 	{
6518 		ACCOUNT *a = LIST_DATA(c->AccountList, i);
6519 		if (a->ClientSession == NULL)
6520 		{
6521 			continue;
6522 		}
6523 
6524 		Zero(&t, sizeof(t));
6525 		StrCpy(t.Name, sizeof(t.Name), a->ClientOption->DeviceName);
6526 		r = Search(tmpVLanList, &t);
6527 		Delete(tmpVLanList, r);
6528 	}
6529 
6530 	// Set down every VLan in tmpVLanList
6531 	for (i = 0; i < LIST_NUM(tmpVLanList) && result; ++i)
6532 	{
6533 		r = LIST_DATA(tmpVLanList, i);
6534 		result = UnixVLanSetState(r->Name, false);
6535 		// [MP:] Should we report *critical* error on failure?
6536 	}
6537 
6538 	ReleaseList(tmpVLanList);
6539 	return result;
6540 #endif
6541 }
6542 
6543 // Put all TUN interfaces up
6544 // Requires VLan list of the CLIENT argument to be already locked
CtVLansUp(CLIENT * c)6545 bool CtVLansUp(CLIENT *c)
6546 {
6547 #ifndef UNIX_LINUX
6548 	return true;
6549 #else
6550 	int i;
6551 	UNIX_VLAN *r;
6552 
6553 	if (c == NULL)
6554 	{
6555 		return false;
6556 	}
6557 
6558 	for (i = 0; i < LIST_NUM(c->UnixVLanList); ++i)
6559 	{
6560 		r = LIST_DATA(c->UnixVLanList, i);
6561 		UnixVLanSetState(r->Name, true);
6562 	}
6563 
6564 	return true;
6565 #endif
6566 }
6567 
6568 // Get the account information
CtGetAccount(CLIENT * c,RPC_CLIENT_GET_ACCOUNT * a)6569 bool CtGetAccount(CLIENT *c, RPC_CLIENT_GET_ACCOUNT *a)
6570 {
6571 	// Validate arguments
6572 	if (c == NULL || a == NULL)
6573 	{
6574 		return false;
6575 	}
6576 
6577 	LockList(c->AccountList);
6578 	{
6579 		ACCOUNT t, *r;
6580 
6581 		// Search for account
6582 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6583 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
6584 
6585 		r = Search(c->AccountList, &t);
6586 		if (r == NULL)
6587 		{
6588 			// Specified account can not be found
6589 			UnlockList(c->AccountList);
6590 
6591 			Free(t.ClientOption);
6592 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
6593 			return false;
6594 		}
6595 
6596 		Free(t.ClientOption);
6597 
6598 		Lock(r->lock);
6599 		{
6600 			// Copy the client option
6601 			if (a->ClientOption != NULL)
6602 			{
6603 				Free(a->ClientOption);
6604 			}
6605 			a->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6606 			Copy(a->ClientOption, r->ClientOption, sizeof(CLIENT_OPTION));
6607 
6608 			// Copy the authentication data
6609 			if (a->ClientAuth != NULL)
6610 			{
6611 				CiFreeClientAuth(a->ClientAuth);
6612 			}
6613 			a->ClientAuth = CopyClientAuth(r->ClientAuth);
6614 
6615 			a->StartupAccount = r->StartupAccount;
6616 
6617 			a->CheckServerCert = r->CheckServerCert;
6618 			a->RetryOnServerCert = r->RetryOnServerCert;
6619 			a->ServerCert = NULL;
6620 			if (r->ServerCert != NULL)
6621 			{
6622 				a->ServerCert = CloneX(r->ServerCert);
6623 			}
6624 
6625 			// Shortcut Key
6626 			Copy(a->ShortcutKey, r->ShortcutKey, SHA1_SIZE);
6627 
6628 			a->CreateDateTime = r->CreateDateTime;
6629 			a->LastConnectDateTime = r->LastConnectDateTime;
6630 			a->UpdateDateTime = r->UpdateDateTime;
6631 		}
6632 		Unlock(r->lock);
6633 
6634 	}
6635 	UnlockList(c->AccountList);
6636 
6637 	return true;
6638 }
6639 
6640 // Change the account name
CtRenameAccount(CLIENT * c,RPC_RENAME_ACCOUNT * rename,bool inner)6641 bool CtRenameAccount(CLIENT *c, RPC_RENAME_ACCOUNT *rename, bool inner)
6642 {
6643 	bool ret;
6644 	// Validate arguments
6645 	if (c == NULL || rename == NULL)
6646 	{
6647 		return false;
6648 	}
6649 
6650 
6651 	ret = false;
6652 
6653 	if (UniStrCmp(rename->NewName, rename->OldName) == 0)
6654 	{
6655 		// The name has not been changed
6656 		return true;
6657 	}
6658 
6659 	LockList(c->AccountList);
6660 	{
6661 		ACCOUNT t, *r, *r2;
6662 
6663 		if (UniStrLen(rename->NewName) == 0)
6664 		{
6665 			// Name is invalid
6666 			CiSetError(c, ERR_INVALID_VALUE);
6667 			UnlockList(c->AccountList);
6668 			return false;
6669 		}
6670 
6671 		// Search for old account name
6672 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6673 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), rename->OldName);
6674 
6675 		r = Search(c->AccountList, &t);
6676 		if (r == NULL)
6677 		{
6678 			// Specified account can not be found
6679 			UnlockList(c->AccountList);
6680 
6681 			Free(t.ClientOption);
6682 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
6683 			return false;
6684 		}
6685 
6686 		Free(t.ClientOption);
6687 
6688 		// Search for a new account name
6689 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6690 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), rename->NewName);
6691 
6692 		r2 = Search(c->AccountList, &t);
6693 		if (r2 != NULL)
6694 		{
6695 			// Account with the specified name already exists
6696 			UnlockList(c->AccountList);
6697 
6698 			Free(t.ClientOption);
6699 			CiSetError(c, ERR_ACCOUNT_ALREADY_EXISTS);
6700 			return false;
6701 		}
6702 
6703 		Free(t.ClientOption);
6704 
6705 		Lock(r->lock);
6706 		{
6707 			// Check the operating state of the account
6708 			if (r->ClientSession != NULL)
6709 			{
6710 				// The Account is working
6711 				Unlock(r->lock);
6712 				UnlockList(c->AccountList);
6713 				CiSetError(c, ERR_ACCOUNT_ACTIVE);
6714 
6715 				return false;
6716 			}
6717 
6718 			// Update the account name
6719 			UniStrCpy(r->ClientOption->AccountName, sizeof(r->ClientOption->AccountName),
6720 				rename->NewName);
6721 
6722 			CLog(c, "LC_RENAME_ACCOUNT", rename->OldName, rename->NewName);
6723 
6724 			ret = true;
6725 		}
6726 		Unlock(r->lock);
6727 
6728 		Sort(c->AccountList);
6729 
6730 	}
6731 	UnlockList(c->AccountList);
6732 
6733 	CiSaveConfigurationFile(c);
6734 
6735 	CiNotify(c);
6736 
6737 	return ret;
6738 }
6739 
6740 // Set the client configuration
CtSetClientConfig(CLIENT * c,CLIENT_CONFIG * o)6741 bool CtSetClientConfig(CLIENT *c, CLIENT_CONFIG *o)
6742 {
6743 	KEEP *k;
6744 	// Validate arguments
6745 	if (c == NULL || o == NULL)
6746 	{
6747 		return false;
6748 	}
6749 
6750 	if (o->UseKeepConnect)
6751 	{
6752 		if (IsEmptyStr(o->KeepConnectHost) ||
6753 			o->KeepConnectPort == 0 ||
6754 			o->KeepConnectPort >= 65536)
6755 		{
6756 			CiSetError(c, ERR_INVALID_PARAMETER);
6757 			return false;
6758 		}
6759 	}
6760 
6761 	Lock(c->lock);
6762 	{
6763 		Copy(&c->Config, o, sizeof(CLIENT_CONFIG));
6764 	}
6765 	Unlock(c->lock);
6766 
6767 	// Save the settings
6768 	CiSaveConfigurationFile(c);
6769 
6770 	// Apply the Keep Connect
6771 	k = c->Keep;
6772 	Lock(k->lock);
6773 	{
6774 		if (o->UseKeepConnect)
6775 		{
6776 			StrCpy(k->ServerName, sizeof(k->ServerName), c->Config.KeepConnectHost);
6777 			k->ServerPort = c->Config.KeepConnectPort;
6778 			k->Interval = c->Config.KeepConnectInterval * 1000;
6779 			k->UdpMode = (c->Config.KeepConnectProtocol == CONNECTION_UDP) ? true : false;
6780 			k->Enable = true;
6781 		}
6782 		else
6783 		{
6784 			k->Enable = false;
6785 		}
6786 	}
6787 	Unlock(k->lock);
6788 
6789 	// Apply TAP state
6790 	LockList(c->AccountList);
6791 	LockList(c->UnixVLanList);
6792 
6793 	CtVLansDown(c);
6794 
6795 	UnlockList(c->UnixVLanList);
6796 	UnlockList(c->AccountList);
6797 
6798 	return true;
6799 }
6800 
6801 // Get the network client configuration
CtGetClientConfig(CLIENT * c,CLIENT_CONFIG * o)6802 bool CtGetClientConfig(CLIENT *c, CLIENT_CONFIG *o)
6803 {
6804 	// Validate arguments
6805 	if (c == NULL || o == NULL)
6806 	{
6807 		return false;
6808 	}
6809 
6810 	Lock(c->lock);
6811 	{
6812 		Copy(o, &c->Config, sizeof(CLIENT_CONFIG));
6813 	}
6814 	Unlock(c->lock);
6815 
6816 	return true;
6817 }
6818 
6819 // Unset the startup attribute of the account
CtRemoveStartupAccount(CLIENT * c,RPC_CLIENT_DELETE_ACCOUNT * a)6820 bool CtRemoveStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a)
6821 {
6822 	bool ret;
6823 	// Validate arguments
6824 	if (c == NULL || a == NULL)
6825 	{
6826 		return false;
6827 	}
6828 
6829 	ret = false;
6830 
6831 	LockList(c->AccountList);
6832 	{
6833 		ACCOUNT t, *r;
6834 		// Search for an Account
6835 
6836 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6837 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
6838 
6839 		r = Search(c->AccountList, &t);
6840 		if (r == NULL)
6841 		{
6842 			// Specified account can not be found
6843 			UnlockList(c->AccountList);
6844 
6845 			Free(t.ClientOption);
6846 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
6847 			return false;
6848 		}
6849 
6850 		Free(t.ClientOption);
6851 
6852 		Lock(r->lock);
6853 		{
6854 			// Unset the startup account
6855 			ret = true;
6856 			r->StartupAccount = false;
6857 		}
6858 		Unlock(r->lock);
6859 	}
6860 	UnlockList(c->AccountList);
6861 
6862 	if (ret)
6863 	{
6864 		CiSaveConfigurationFile(c);
6865 		CiNotify(c);
6866 	}
6867 
6868 	return ret;
6869 }
6870 
6871 // Set the account as a start-up account
CtSetStartupAccount(CLIENT * c,RPC_CLIENT_DELETE_ACCOUNT * a,bool inner)6872 bool CtSetStartupAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a, bool inner)
6873 {
6874 	bool ret;
6875 	// Validate arguments
6876 	if (c == NULL || a == NULL)
6877 	{
6878 		return false;
6879 	}
6880 
6881 
6882 	ret = false;
6883 
6884 	LockList(c->AccountList);
6885 	{
6886 		ACCOUNT t, *r;
6887 		// Search for an account
6888 
6889 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6890 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
6891 
6892 		r = Search(c->AccountList, &t);
6893 		if (r == NULL)
6894 		{
6895 			// Specified account can not be found
6896 			UnlockList(c->AccountList);
6897 
6898 			Free(t.ClientOption);
6899 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
6900 			return false;
6901 		}
6902 
6903 		Free(t.ClientOption);
6904 
6905 		Lock(r->lock);
6906 		{
6907 			// Set to a start-up account
6908 			ret = true;
6909 			r->StartupAccount = true;
6910 		}
6911 		Unlock(r->lock);
6912 	}
6913 	UnlockList(c->AccountList);
6914 
6915 	if (ret)
6916 	{
6917 		CiSaveConfigurationFile(c);
6918 		CiNotify(c);
6919 	}
6920 
6921 	return ret;
6922 }
6923 
6924 // Delete the account
CtDeleteAccount(CLIENT * c,RPC_CLIENT_DELETE_ACCOUNT * a,bool inner)6925 bool CtDeleteAccount(CLIENT *c, RPC_CLIENT_DELETE_ACCOUNT *a, bool inner)
6926 {
6927 	bool ret;
6928 	// Validate arguments
6929 	if (c == NULL || a == NULL)
6930 	{
6931 		return false;
6932 	}
6933 
6934 	ret = false;
6935 
6936 	if (c->Halt)
6937 	{
6938 		// Don't allow the removal of the account in the process of stopping
6939 		CiSetError(c, ERR_INTERNAL_ERROR);
6940 		return false;
6941 	}
6942 
6943 	LockList(c->AccountList);
6944 	{
6945 		ACCOUNT t, *r;
6946 		// Search for an Account
6947 
6948 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
6949 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName), a->AccountName);
6950 
6951 		r = Search(c->AccountList, &t);
6952 		if (r == NULL)
6953 		{
6954 			// Specified account can not be found
6955 			UnlockList(c->AccountList);
6956 
6957 			Free(t.ClientOption);
6958 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
6959 			return false;
6960 		}
6961 
6962 		Free(t.ClientOption);
6963 
6964 		Lock(r->lock);
6965 		{
6966 			// Check the operating state of the account
6967 			if (r->ClientSession != NULL)
6968 			{
6969 				// The account is active
6970 				Unlock(r->lock);
6971 				UnlockList(c->AccountList);
6972 				CiSetError(c, ERR_ACCOUNT_ACTIVE);
6973 
6974 				return false;
6975 			}
6976 
6977 			// Remove this account from the list
6978 			Delete(c->AccountList, r);
6979 		}
6980 		Unlock(r->lock);
6981 
6982 		// Free the memory of this account
6983 		CiFreeAccount(r);
6984 
6985 		CLog(c, "LC_DELETE_ACCOUNT", a->AccountName);
6986 		ret = true;
6987 
6988 	}
6989 	UnlockList(c->AccountList);
6990 
6991 	if (ret)
6992 	{
6993 		CiSaveConfigurationFile(c);
6994 		CiNotify(c);
6995 	}
6996 
6997 	return ret;
6998 }
6999 
7000 // Enumeration of accounts
CtEnumAccount(CLIENT * c,RPC_CLIENT_ENUM_ACCOUNT * e)7001 bool CtEnumAccount(CLIENT *c, RPC_CLIENT_ENUM_ACCOUNT *e)
7002 {
7003 	// Validate arguments
7004 	if (c == NULL || e == NULL)
7005 	{
7006 		return false;
7007 	}
7008 
7009 	LockList(c->AccountList);
7010 	{
7011 		UINT i;
7012 		// Number of accounts
7013 		e->NumItem = LIST_NUM(c->AccountList);
7014 		e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM *) * e->NumItem);
7015 
7016 		for (i = 0;i < e->NumItem;i++)
7017 		{
7018 			ACCOUNT *a = LIST_DATA(c->AccountList, i);
7019 			RPC_CLIENT_ENUM_ACCOUNT_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_ACCOUNT_ITEM));
7020 			e->Items[i] = item;
7021 
7022 			// Account name
7023 			UniStrCpy(item->AccountName, sizeof(item->AccountName), a->ClientOption->AccountName);
7024 
7025 			// User name
7026 			StrCpy(item->UserName, sizeof(item->UserName), a->ClientAuth->Username);
7027 
7028 			// Server name
7029 			StrCpy(item->ServerName, sizeof(item->ServerName), a->ClientOption->Hostname);
7030 
7031 			// Proxy type
7032 			item->ProxyType = a->ClientOption->ProxyType;
7033 
7034 			// Device name
7035 			StrCpy(item->DeviceName, sizeof(item->DeviceName), a->ClientOption->DeviceName);
7036 
7037 			// Proxy information
7038 			if (item->ProxyType != PROXY_DIRECT)
7039 			{
7040 				StrCpy(item->ProxyName, sizeof(item->ProxyName), a->ClientOption->ProxyName);
7041 			}
7042 
7043 			// Startup
7044 			item->StartupAccount = a->StartupAccount;
7045 
7046 			// Active flag
7047 			item->Active = (a->ClientSession == NULL ? false : true);
7048 
7049 			// Connection flag
7050 			item->Connected = (item->Active == false) ? false : a->ClientSession->ConnectSucceed;
7051 
7052 			// Port number
7053 			item->Port = a->ClientOption->Port;
7054 
7055 			// Virtual HUB name
7056 			StrCpy(item->HubName, sizeof(item->HubName), a->ClientOption->HubName);
7057 
7058 			item->CreateDateTime = a->CreateDateTime;
7059 			item->LastConnectDateTime = a->LastConnectDateTime;
7060 			item->UpdateDateTime = a->UpdateDateTime;
7061 		}
7062 	}
7063 	UnlockList(c->AccountList);
7064 
7065 	return true;
7066 }
7067 
7068 // Configure the account
CtSetAccount(CLIENT * c,RPC_CLIENT_CREATE_ACCOUNT * a,bool inner)7069 bool CtSetAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a, bool inner)
7070 {
7071 	// Validate arguments
7072 	if (c == NULL || a == NULL)
7073 	{
7074 		return false;
7075 	}
7076 
7077 
7078 	// Check whether an account already exists
7079 	LockList(c->AccountList);
7080 	{
7081 		ACCOUNT t, *ret;
7082 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
7083 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),
7084 			a->ClientOption->AccountName);
7085 
7086 		ret = Search(c->AccountList, &t);
7087 		if (ret == NULL)
7088 		{
7089 			// Not exist
7090 			UnlockList(c->AccountList);
7091 			Free(t.ClientOption);
7092 
7093 			CiSetError(c, ERR_ACCOUNT_NOT_FOUND);
7094 
7095 			return false;
7096 		}
7097 		Free(t.ClientOption);
7098 
7099 		if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
7100 		{
7101 			if (a->ClientAuth->ClientX == NULL ||
7102 				a->ClientAuth->ClientX->is_compatible_bit == false ||
7103 				a->ClientAuth->ClientK == NULL)
7104 			{
7105 				// Client certificate is invalid
7106 				UnlockList(c->AccountList);
7107 				CiSetError(c, ERR_NOT_RSA_1024);
7108 				return false;
7109 			}
7110 		}
7111 
7112 		if (a->ServerCert != NULL && a->ServerCert->is_compatible_bit == false)
7113 		{
7114 			// Server certificate is invalid
7115 			UnlockList(c->AccountList);
7116 			CiSetError(c, ERR_NOT_RSA_1024);
7117 			return false;
7118 		}
7119 
7120 		Lock(ret->lock);
7121 		{
7122 
7123 #if	0
7124 			// Rewriting of the configuration is done even account running in the current version
7125 			// (New setting isn't applied until connecting next time)
7126 			if (ret->ClientSession != NULL)
7127 			{
7128 				// The account is operating
7129 				Unlock(ret->lock);
7130 				UnlockList(c->AccountList);
7131 
7132 				CiSetError(c, ERR_ACCOUNT_ACTIVE);
7133 
7134 				return false;
7135 			}
7136 #endif
7137 
7138 			// Delete the client authentication data
7139 			CiFreeClientAuth(ret->ClientAuth);
7140 
7141 			// Copy the client authentication data
7142 			ret->ClientAuth = CopyClientAuth(a->ClientAuth);
7143 
7144 			// Delete the client option
7145 			Free(ret->ClientOption);
7146 
7147 			// Copy the client option
7148 			ret->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
7149 			Copy(ret->ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
7150 
7151 			ret->StartupAccount = a->StartupAccount;
7152 
7153 			ret->CheckServerCert = a->CheckServerCert;
7154 			ret->RetryOnServerCert = a->RetryOnServerCert;
7155 
7156 			if (a->ServerCert != NULL)
7157 			{
7158 				if (ret->ServerCert != NULL)
7159 				{
7160 					FreeX(ret->ServerCert);
7161 				}
7162 				ret->ServerCert = CloneX(a->ServerCert);
7163 			}
7164 			else
7165 			{
7166 				if (ret->ServerCert != NULL)
7167 				{
7168 					FreeX(ret->ServerCert);
7169 				}
7170 				ret->ServerCert = false;
7171 			}
7172 
7173 			ret->UpdateDateTime = SystemTime64();
7174 		}
7175 		Unlock(ret->lock);
7176 	}
7177 	UnlockList(c->AccountList);
7178 
7179 	CiSaveConfigurationFile(c);
7180 
7181 	CiNotify(c);
7182 
7183 	return true;
7184 }
7185 
7186 // Create an account
CtCreateAccount(CLIENT * c,RPC_CLIENT_CREATE_ACCOUNT * a,bool inner)7187 bool CtCreateAccount(CLIENT *c, RPC_CLIENT_CREATE_ACCOUNT *a, bool inner)
7188 {
7189 	// Validate arguments
7190 	if (c == NULL || a == NULL)
7191 	{
7192 		return false;
7193 	}
7194 
7195 
7196 	// Check whether an account already exists
7197 	LockList(c->AccountList);
7198 	{
7199 		ACCOUNT t, *ret, *new_account;
7200 		t.ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
7201 		UniStrCpy(t.ClientOption->AccountName, sizeof(t.ClientOption->AccountName),
7202 			a->ClientOption->AccountName);
7203 
7204 		ret = Search(c->AccountList, &t);
7205 		if (ret != NULL)
7206 		{
7207 			// Already exist
7208 			UnlockList(c->AccountList);
7209 			Free(t.ClientOption);
7210 
7211 			CiSetError(c, ERR_ACCOUNT_ALREADY_EXISTS);
7212 
7213 			return false;
7214 		}
7215 
7216 		Free(t.ClientOption);
7217 
7218 		if (UniStrLen(a->ClientOption->AccountName) == 0)
7219 		{
7220 			// The name is invalid
7221 			UnlockList(c->AccountList);
7222 			CiSetError(c, ERR_INVALID_VALUE);
7223 			return false;
7224 		}
7225 
7226 		if (a->ClientAuth->AuthType == CLIENT_AUTHTYPE_CERT)
7227 		{
7228 			if (a->ClientAuth->ClientX == NULL ||
7229 				a->ClientAuth->ClientX->is_compatible_bit == false ||
7230 				a->ClientAuth->ClientK == NULL)
7231 			{
7232 				// The client certificate is invalid
7233 				UnlockList(c->AccountList);
7234 				CiSetError(c, ERR_NOT_RSA_1024);
7235 				return false;
7236 			}
7237 		}
7238 
7239 		if (a->ServerCert != NULL && a->ServerCert->is_compatible_bit == false)
7240 		{
7241 			// The server certificate is invalid
7242 			UnlockList(c->AccountList);
7243 			CiSetError(c, ERR_NOT_RSA_1024);
7244 			return false;
7245 		}
7246 
7247 		// Add a new account
7248 		new_account = ZeroMalloc(sizeof(ACCOUNT));
7249 		new_account->lock = NewLock();
7250 
7251 		// Copy the client authentication data
7252 		new_account->ClientAuth = CopyClientAuth(a->ClientAuth);
7253 
7254 		// Copy the client option
7255 		new_account->ClientOption = ZeroMalloc(sizeof(CLIENT_OPTION));
7256 		Copy(new_account->ClientOption, a->ClientOption, sizeof(CLIENT_OPTION));
7257 
7258 		new_account->StartupAccount = a->StartupAccount;
7259 
7260 		new_account->CheckServerCert = a->CheckServerCert;
7261 		new_account->RetryOnServerCert = a->RetryOnServerCert;
7262 		if (a->ServerCert != NULL)
7263 		{
7264 			new_account->ServerCert = CloneX(a->ServerCert);
7265 		}
7266 
7267 		// Shortcut Key
7268 		if (IsZero(a->ShortcutKey, SHA1_SIZE))
7269 		{
7270 			Rand(new_account->ShortcutKey, SHA1_SIZE);
7271 		}
7272 		else
7273 		{
7274 			Copy(new_account->ShortcutKey, a->ShortcutKey, SHA1_SIZE);
7275 		}
7276 
7277 		new_account->CreateDateTime = new_account->UpdateDateTime = SystemTime64();
7278 
7279 		// Insert into the list
7280 		Insert(c->AccountList, new_account);
7281 
7282 		CLog(c, "LC_NEW_ACCOUNT", a->ClientOption->AccountName);
7283 	}
7284 	UnlockList(c->AccountList);
7285 
7286 	CiNormalizeAccountVLan(c);
7287 
7288 	CiSaveConfigurationFile(c);
7289 
7290 	CiNotify(c);
7291 
7292 	return true;
7293 }
7294 
7295 // Release the account acquisition structure
CiFreeClientGetAccount(RPC_CLIENT_GET_ACCOUNT * a)7296 void CiFreeClientGetAccount(RPC_CLIENT_GET_ACCOUNT *a)
7297 {
7298 	// Validate arguments
7299 	if (a == NULL)
7300 	{
7301 		return;
7302 	}
7303 
7304 	// Release the account information
7305 	if (a->ServerCert != NULL)
7306 	{
7307 		FreeX(a->ServerCert);
7308 	}
7309 	CiFreeClientAuth(a->ClientAuth);
7310 	Free(a->ClientOption);
7311 }
7312 
7313 // Release the account creation structure
CiFreeClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT * a)7314 void CiFreeClientCreateAccount(RPC_CLIENT_CREATE_ACCOUNT *a)
7315 {
7316 	// Validate arguments
7317 	if (a == NULL)
7318 	{
7319 		return;
7320 	}
7321 
7322 	// Release the account information
7323 	if (a->ServerCert != NULL)
7324 	{
7325 		FreeX(a->ServerCert);
7326 	}
7327 	CiFreeClientAuth(a->ClientAuth);
7328 	Free(a->ClientOption);
7329 }
7330 
7331 // Stop the virtual LAN card
CtDisableVLan(CLIENT * c,RPC_CLIENT_CREATE_VLAN * vlan)7332 bool CtDisableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan)
7333 {
7334 	UINT i;
7335 	bool used;
7336 	// Validate arguments
7337 	if (c == NULL || vlan == NULL)
7338 	{
7339 		return false;
7340 	}
7341 
7342 #ifndef	OS_WIN32
7343 
7344 #ifdef	NO_VLAN
7345 	if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
7346 	{
7347 		// Can not be added or removed the virtual LAN card in MacOS X
7348 		CiSetError(c, ERR_NOT_SUPPORTED);
7349 		return false;
7350 	}
7351 #endif	// NO_VLAN
7352 
7353 	// Check whether the virtual LAN card with the specified name is not
7354 	// being used by one or more accounts
7355 	used = false;
7356 	LockList(c->AccountList);
7357 	{
7358 		for (i = 0;i < LIST_NUM(c->AccountList);i++)
7359 		{
7360 			ACCOUNT *a = LIST_DATA(c->AccountList, i);
7361 			if (StrCmpi(a->ClientOption->DeviceName, vlan->DeviceName) == 0)
7362 			{
7363 				Lock(a->lock);
7364 				{
7365 					if (a->ClientSession != NULL)
7366 					{
7367 						used = true;
7368 					}
7369 				}
7370 				Unlock(a->lock);
7371 			}
7372 		}
7373 	}
7374 	UnlockList(c->AccountList);
7375 
7376 	// Search for the virtual LAN card
7377 	LockList(c->UnixVLanList);
7378 	{
7379 		UNIX_VLAN *v, t;
7380 
7381 		Zero(&t, sizeof(t));
7382 		StrCpy(t.Name, sizeof(t.Name), vlan->DeviceName);
7383 
7384 		v = Search(c->UnixVLanList, &t);
7385 		if (v == NULL)
7386 		{
7387 			UnlockList(c->UnixVLanList);
7388 			CiSetError(c, ERR_OBJECT_NOT_FOUND);
7389 			return false;
7390 		}
7391 
7392 		// Stop
7393 		v->Enabled = false;
7394 	}
7395 	UnlockList(c->UnixVLanList);
7396 
7397 	CiSaveConfigurationFile(c);
7398 	CiNotify(c);
7399 	CiSendGlobalPulse(c);
7400 
7401 	return true;
7402 
7403 #else	// OS_WIN32
7404 
7405 	// Check whether the virtual LAN card with the specified name is not
7406 	// being used by one or more accounts
7407 	used = false;
7408 	LockList(c->AccountList);
7409 	{
7410 		for (i = 0;i < LIST_NUM(c->AccountList);i++)
7411 		{
7412 			ACCOUNT *a = LIST_DATA(c->AccountList, i);
7413 			if (StrCmpi(a->ClientOption->DeviceName, vlan->DeviceName) == 0)
7414 			{
7415 				Lock(a->lock);
7416 				{
7417 					if (a->ClientSession != NULL)
7418 					{
7419 						used = true;
7420 					}
7421 				}
7422 				Unlock(a->lock);
7423 			}
7424 		}
7425 	}
7426 	UnlockList(c->AccountList);
7427 
7428 #if	0
7429 	if (used)
7430 	{
7431 		// In using
7432 		CiSetError(c, ERR_VLAN_IS_USED);
7433 		return false;
7434 	}
7435 #endif
7436 
7437 
7438 	// Check whether the virtual LAN card are present
7439 	if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, vlan->DeviceName) == false &&
7440 		MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, vlan->DeviceName) == false)
7441 	{
7442 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
7443 		CiNotify(c);
7444 		CiSendGlobalPulse(c);
7445 		return false;
7446 	}
7447 
7448 
7449 	if (MsIs64BitWindows() && Is32() && MsIsAdmin())
7450 	{
7451 		// Execute the driver_installer to process since this Windows is 64 bit
7452 		// but this code is 32 bit
7453 		char tmp[MAX_SIZE];
7454 
7455 		Format(tmp, sizeof(tmp), "disablevlan %s", vlan->DeviceName);
7456 
7457 		if (MsExecDriverInstaller(tmp) == false)
7458 		{
7459 			CiSetError(c, ERR_VLAN_INSTALL_ERROR);
7460 			CiNotify(c);
7461 			CiSendGlobalPulse(c);
7462 			return false;
7463 		}
7464 	}
7465 	else
7466 	{
7467 		// Stop the virtual LAN card
7468 		if (MsDisableVLan(vlan->DeviceName) == false)
7469 		{
7470 			CiSetError(c, ERR_VLAN_INSTALL_ERROR);
7471 			CiNotify(c);
7472 			CiSendGlobalPulse(c);
7473 			return false;
7474 		}
7475 	}
7476 
7477 	CiNotify(c);
7478 	CiSendGlobalPulse(c);
7479 
7480 	return true;
7481 
7482 #endif	// OS_WIN32
7483 
7484 }
7485 
7486 // Start the virtual LAN card
CtEnableVLan(CLIENT * c,RPC_CLIENT_CREATE_VLAN * vlan)7487 bool CtEnableVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *vlan)
7488 {
7489 	// Validate arguments
7490 	if (c == NULL || vlan == NULL)
7491 	{
7492 		return false;
7493 	}
7494 
7495 #ifndef	OS_WIN32
7496 
7497 #ifdef	NO_VLAN
7498 	if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
7499 	{
7500 		// Can not be added or removed the virtual LAN card in MacOS X
7501 		CiSetError(c, ERR_NOT_SUPPORTED);
7502 		return false;
7503 	}
7504 #endif	// NO_VLAN
7505 
7506 	// Search the virtual LAN card
7507 	LockList(c->UnixVLanList);
7508 	{
7509 		UNIX_VLAN *v, t;
7510 
7511 		Zero(&t, sizeof(t));
7512 		StrCpy(t.Name, sizeof(t.Name), vlan->DeviceName);
7513 
7514 		v = Search(c->UnixVLanList, &t);
7515 		if (v == NULL)
7516 		{
7517 			UnlockList(c->UnixVLanList);
7518 			CiSetError(c, ERR_OBJECT_NOT_FOUND);
7519 			return false;
7520 		}
7521 
7522 		// Enable
7523 		v->Enabled = true;
7524 	}
7525 	UnlockList(c->UnixVLanList);
7526 
7527 	CiSaveConfigurationFile(c);
7528 	CiNotify(c);
7529 	CiSendGlobalPulse(c);
7530 
7531 	return true;
7532 
7533 #else	// OS_WIN32
7534 
7535 	// Check whether the virtual LAN card are present
7536 	if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, vlan->DeviceName) == false &&
7537 		MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, vlan->DeviceName) == false)
7538 	{
7539 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
7540 		CiNotify(c);
7541 		CiSendGlobalPulse(c);
7542 		return false;
7543 	}
7544 
7545 	if (MsIs64BitWindows() && Is32() && MsIsAdmin())
7546 	{
7547 		// Execute the driver_installer to process since this Windows is 64 bit
7548 		// but this code is 32 bit
7549 		char tmp[MAX_SIZE];
7550 
7551 		Format(tmp, sizeof(tmp), "enablevlan %s", vlan->DeviceName);
7552 
7553 		if (MsExecDriverInstaller(tmp) == false)
7554 		{
7555 			CiSetError(c, ERR_VLAN_INSTALL_ERROR);
7556 			CiNotify(c);
7557 			CiSendGlobalPulse(c);
7558 			return false;
7559 		}
7560 	}
7561 	else
7562 	{
7563 		// Start the virtual LAN card
7564 		if (MsEnableVLan(vlan->DeviceName) == false)
7565 		{
7566 			CiSetError(c, ERR_VLAN_INSTALL_ERROR);
7567 			CiNotify(c);
7568 			CiSendGlobalPulse(c);
7569 			return false;
7570 		}
7571 	}
7572 
7573 	CiNotify(c);
7574 	CiSendGlobalPulse(c);
7575 
7576 	return true;
7577 
7578 #endif	// OS_WIN32
7579 
7580 }
7581 
7582 // Delete the virtual LAN card
CtDeleteVLan(CLIENT * c,RPC_CLIENT_CREATE_VLAN * d)7583 bool CtDeleteVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *d)
7584 {
7585 	UINT i;
7586 	bool used;
7587 	// Validate arguments
7588 	if (c == NULL || d == NULL)
7589 	{
7590 		return false;
7591 	}
7592 
7593 #ifndef	OS_WIN32
7594 
7595 #ifdef	NO_VLAN
7596 	if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
7597 	{
7598 		// Can not be added or removed the virtual LAN card in MacOS X
7599 		CiSetError(c, ERR_NOT_SUPPORTED);
7600 		return false;
7601 	}
7602 #endif	// NO_VLAN
7603 
7604 	// Check whether the virtual LAN card with the specified name is not
7605 	// being used by one or more accounts
7606 	used = false;
7607 	LockList(c->AccountList);
7608 	{
7609 		for (i = 0;i < LIST_NUM(c->AccountList);i++)
7610 		{
7611 			ACCOUNT *a = LIST_DATA(c->AccountList, i);
7612 			if (StrCmpi(a->ClientOption->DeviceName, d->DeviceName) == 0)
7613 			{
7614 				used = true;
7615 			}
7616 		}
7617 	}
7618 	UnlockList(c->AccountList);
7619 
7620 #if	0
7621 	if (used)
7622 	{
7623 		// In using
7624 		CiSetError(c, ERR_VLAN_IS_USED);
7625 		return false;
7626 	}
7627 #endif
7628 
7629 	// Search for the virtual LAN card
7630 	LockList(c->UnixVLanList);
7631 	{
7632 		UNIX_VLAN *v, t;
7633 
7634 		Zero(&t, sizeof(t));
7635 		StrCpy(t.Name, sizeof(t.Name), d->DeviceName);
7636 
7637 		v = Search(c->UnixVLanList, &t);
7638 		if (v == NULL)
7639 		{
7640 			UnlockList(c->UnixVLanList);
7641 			CiSetError(c, ERR_OBJECT_NOT_FOUND);
7642 			return false;
7643 		}
7644 
7645 		// Remove
7646 		if (Delete(c->UnixVLanList, v))
7647 		{
7648 			Free(v);
7649 		}
7650 
7651 		CLog(c, "LC_DELETE_VLAN", d->DeviceName);
7652 
7653 		UnixVLanDelete(d->DeviceName);
7654 	}
7655 	UnlockList(c->UnixVLanList);
7656 
7657 	CiNormalizeAccountVLan(c);
7658 
7659 	CiSaveConfigurationFile(c);
7660 	CiNotify(c);
7661 	CiSendGlobalPulse(c);
7662 
7663 	return true;
7664 
7665 #else	// OS_WIN32
7666 
7667 	// Check whether the virtual LAN card are present
7668 	if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, d->DeviceName) == false &&
7669 		MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, d->DeviceName) == false)
7670 	{
7671 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
7672 		return false;
7673 	}
7674 
7675 	// Check whether the virtual LAN card with the specified name is not
7676 	// being used by one or more accounts
7677 	used = false;
7678 	LockList(c->AccountList);
7679 	{
7680 		for (i = 0;i < LIST_NUM(c->AccountList);i++)
7681 		{
7682 			ACCOUNT *a = LIST_DATA(c->AccountList, i);
7683 			if (StrCmpi(a->ClientOption->DeviceName, d->DeviceName) == 0)
7684 			{
7685 				used = true;
7686 			}
7687 		}
7688 	}
7689 	UnlockList(c->AccountList);
7690 
7691 #if	0
7692 	if (used)
7693 	{
7694 		// In using
7695 		CiSetError(c, ERR_VLAN_IS_USED);
7696 		return false;
7697 	}
7698 #endif
7699 
7700 	if (MsIs64BitWindows() && Is32() && MsIsAdmin())
7701 	{
7702 		// Execute the driver_installer to process since this Windows is 64 bit
7703 		// but this code is 32 bit
7704 		char tmp[MAX_SIZE];
7705 
7706 		Format(tmp, sizeof(tmp), "uninstvlan %s", d->DeviceName);
7707 
7708 		if (MsExecDriverInstaller(tmp) == false)
7709 		{
7710 			CiSetError(c, ERR_VLAN_INSTALL_ERROR);
7711 			return false;
7712 		}
7713 	}
7714 	else
7715 	{
7716 		// Delete the virtual LAN card directly
7717 		if (MsUninstallVLan(d->DeviceName) == false)
7718 		{
7719 			CiSetError(c, ERR_VLAN_INSTALL_ERROR);
7720 			CiNotify(c);
7721 			CiSendGlobalPulse(c);
7722 			return false;
7723 		}
7724 	}
7725 
7726 	CLog(c, "LC_DELETE_VLAN", d->DeviceName);
7727 
7728 	CiNormalizeAccountVLan(c);
7729 
7730 	CiNotify(c);
7731 	CiSendGlobalPulse(c);
7732 
7733 	return true;
7734 
7735 #endif	// OS_WIN32
7736 
7737 }
7738 
7739 // Get the name of the first VLAN
CiGetFirstVLan(CLIENT * c)7740 char *CiGetFirstVLan(CLIENT *c)
7741 {
7742 	char *ret = NULL;
7743 	RPC_CLIENT_ENUM_VLAN t;
7744 	// Validate arguments
7745 	if (c == NULL)
7746 	{
7747 		return NULL;
7748 	}
7749 
7750 	Zero(&t, sizeof(t));
7751 	if (CtEnumVLan(c, &t) == false)
7752 	{
7753 		return NULL;
7754 	}
7755 
7756 	if (t.NumItem >= 1)
7757 	{
7758 		UINT i;
7759 		char *tmp = t.Items[0]->DeviceName;
7760 
7761 		for (i = 0;i < t.NumItem;i++)
7762 		{
7763 			if (t.Items[i]->Enabled)
7764 			{
7765 				tmp = t.Items[i]->DeviceName;
7766 			}
7767 		}
7768 
7769 		ret = CopyStr(tmp);
7770 	}
7771 
7772 	CiFreeClientEnumVLan(&t);
7773 
7774 	return ret;
7775 }
7776 
7777 // Enumerate virtual LAN cards
CtEnumVLan(CLIENT * c,RPC_CLIENT_ENUM_VLAN * e)7778 bool CtEnumVLan(CLIENT *c, RPC_CLIENT_ENUM_VLAN *e)
7779 {
7780 	UINT i;
7781 	TOKEN_LIST *t;
7782 	// Validate arguments
7783 	if (c == NULL || e == NULL)
7784 	{
7785 		return false;
7786 	}
7787 
7788 #ifndef	OS_WIN32
7789 
7790 	LockList(c->UnixVLanList);
7791 	{
7792 		e->NumItem = LIST_NUM(c->UnixVLanList);
7793 		e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * e->NumItem);
7794 
7795 		for (i = 0;i < e->NumItem;i++)
7796 		{
7797 			RPC_CLIENT_ENUM_VLAN_ITEM *item;
7798 			UNIX_VLAN *v;
7799 
7800 			v = LIST_DATA(c->UnixVLanList, i);
7801 			e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
7802 			item = e->Items[i];
7803 
7804 			item->Enabled = v->Enabled;
7805 			BinToStr(item->MacAddress, sizeof(item->MacAddress), v->MacAddress, 6);
7806 			StrCpy(item->DeviceName, sizeof(item->DeviceName), v->Name);
7807 			StrCpy(item->Version, sizeof(item->Version), c->Cedar->VerString);
7808 		}
7809 	}
7810 	UnlockList(c->UnixVLanList);
7811 
7812 	return true;
7813 
7814 #else	// OS_WIN32
7815 
7816 	// Enumeration
7817 	t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
7818 	if (t == NULL)
7819 	{
7820 		// Enumeration failure
7821 		e->NumItem = 0;
7822 		e->Items = ZeroMalloc(0);
7823 	}
7824 	else
7825 	{
7826 		// Enumeration success
7827 		e->NumItem = t->NumTokens;
7828 		e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM *) * e->NumItem);
7829 
7830 		for (i = 0;i < e->NumItem;i++)
7831 		{
7832 			char *tmp;
7833 			RPC_CLIENT_ENUM_VLAN_ITEM *item;
7834 			e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_VLAN_ITEM));
7835 			item = e->Items[i];
7836 
7837 			StrCpy(item->DeviceName, sizeof(item->DeviceName), t->Token[i]);
7838 			item->Enabled = MsIsVLanEnabled(item->DeviceName);
7839 
7840 			tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG, item->DeviceName);
7841 			if (tmp == NULL)
7842 			{
7843 				tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, item->DeviceName);
7844 			}
7845 
7846 			StrCpy(item->MacAddress, sizeof(item->MacAddress), tmp);
7847 			Free(tmp);
7848 
7849 			tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG, item->DeviceName);
7850 			if (tmp == NULL)
7851 			{
7852 				tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG_OLD, item->DeviceName);
7853 			}
7854 
7855 			StrCpy(item->Version, sizeof(item->Version), tmp);
7856 			Free(tmp);
7857 		}
7858 
7859 		FreeToken(t);
7860 	}
7861 
7862 	return true;
7863 
7864 #endif	// OS_WIN32
7865 }
7866 
7867 // Release the virtual LAN card enumeration
CiFreeClientEnumVLan(RPC_CLIENT_ENUM_VLAN * e)7868 void CiFreeClientEnumVLan(RPC_CLIENT_ENUM_VLAN *e)
7869 {
7870 	UINT i;
7871 	// Validate arguments
7872 	if (e == NULL)
7873 	{
7874 		return;
7875 	}
7876 
7877 	for (i = 0;i < e->NumItem;i++)
7878 	{
7879 		Free(e->Items[i]);
7880 	}
7881 	Free(e->Items);
7882 }
7883 
7884 // Set the information about the virtual LAN card
CtSetVLan(CLIENT * c,RPC_CLIENT_SET_VLAN * set)7885 bool CtSetVLan(CLIENT *c, RPC_CLIENT_SET_VLAN *set)
7886 {
7887 	// Validate arguments
7888 	if (c == NULL || set == NULL)
7889 	{
7890 		return false;
7891 	}
7892 
7893 #ifndef	OS_WIN32
7894 
7895 	LockList(c->UnixVLanList);
7896 	{
7897 		UNIX_VLAN t, *r;
7898 		Zero(&t, sizeof(t));
7899 		StrCpy(t.Name, sizeof(t.Name), set->DeviceName);
7900 
7901 		r = Search(c->UnixVLanList, &t);
7902 		if (r == NULL)
7903 		{
7904 			// Not exist
7905 			CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
7906 			UnlockList(c->UnixVLanList);
7907 			return false;
7908 		}
7909 
7910 		StrToMac(r->MacAddress, set->MacAddress);
7911 	}
7912 	UnlockList(c->UnixVLanList);
7913 
7914 	CiSaveConfigurationFile(c);
7915 	CiNotify(c);
7916 	CiSendGlobalPulse(c);
7917 
7918 	return true;
7919 
7920 #else	// OS_WIN32
7921 
7922 	// Check whether the virtual LAN card with the specified name already exists
7923 	if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, set->DeviceName) == false &&
7924 		MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, set->DeviceName) == false)
7925 	{
7926 		// Not exist
7927 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
7928 		return false;
7929 	}
7930 
7931 	// Configuring MAC address
7932 	MsSetMacAddress(VLAN_ADAPTER_NAME_TAG, set->DeviceName, set->MacAddress);
7933 	MsSetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, set->DeviceName, set->MacAddress);
7934 
7935 	CiNotify(c);
7936 	CiSendGlobalPulse(c);
7937 
7938 	return true;
7939 
7940 #endif	// OS_WIN32
7941 }
7942 
7943 // Get the information about the virtual LAN card
CtGetVLan(CLIENT * c,RPC_CLIENT_GET_VLAN * get)7944 bool CtGetVLan(CLIENT *c, RPC_CLIENT_GET_VLAN *get)
7945 {
7946 	char *tmp;
7947 	// Validate arguments
7948 	if (c == NULL || get == NULL)
7949 	{
7950 		return false;
7951 	}
7952 
7953 #ifndef	OS_WIN32
7954 
7955 	// Unsupported
7956 	CiSetError(c, ERR_NOT_SUPPORTED);
7957 	return false;
7958 
7959 #else	// OS_WIN32
7960 
7961 	// Check whether the virtual LAN card with the specified name already exists
7962 	if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, get->DeviceName) == false &&
7963 		MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName) == false)
7964 	{
7965 		// Not exist
7966 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
7967 		return false;
7968 	}
7969 
7970 	// Activity
7971 	get->Enabled = MsIsVLanEnabled(get->DeviceName);
7972 
7973 	// MAC address
7974 	tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
7975 	if (tmp == NULL)
7976 	{
7977 		tmp = MsGetMacAddress(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
7978 	}
7979 	StrCpy(get->MacAddress, sizeof(get->MacAddress), tmp);
7980 	Free(tmp);
7981 
7982 	// Version
7983 	tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
7984 	if (tmp == NULL)
7985 	{
7986 		tmp = MsGetDriverVersion(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
7987 	}
7988 	StrCpy(get->Version, sizeof(get->Version), tmp);
7989 	Free(tmp);
7990 
7991 	// File name
7992 	tmp = MsGetDriverFileName(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
7993 	if (tmp == NULL)
7994 	{
7995 		tmp = MsGetDriverFileName(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
7996 	}
7997 	StrCpy(get->FileName, sizeof(get->FileName), tmp);
7998 	Free(tmp);
7999 
8000 	// GUID
8001 	tmp = MsGetNetworkAdapterGuid(VLAN_ADAPTER_NAME_TAG, get->DeviceName);
8002 	if (tmp == NULL)
8003 	{
8004 		tmp = MsGetNetworkAdapterGuid(VLAN_ADAPTER_NAME_TAG_OLD, get->DeviceName);
8005 	}
8006 	StrCpy(get->Guid, sizeof(get->Guid), tmp);
8007 	Free(tmp);
8008 
8009 	return true;
8010 
8011 #endif	// OS_WIN32
8012 }
8013 
8014 #ifdef	OS_WIN32
8015 // Initialize the driver version information structure
CiInitDriverVerStruct(MS_DRIVER_VER * ver)8016 void CiInitDriverVerStruct(MS_DRIVER_VER *ver)
8017 {
8018 	// Validate arguments
8019 	if (ver == NULL)
8020 	{
8021 		return;
8022 	}
8023 
8024 	Zero(ver, sizeof(MS_DRIVER_VER));
8025 
8026 	ver->Year = BUILD_DATE_Y;
8027 	ver->Month = BUILD_DATE_M;
8028 	ver->Day = BUILD_DATE_D;
8029 	ver->Major = CEDAR_VERSION_MAJOR;
8030 	ver->Minor = CEDAR_VERSION_MINOR;
8031 	ver->Build = CEDAR_VERSION_BUILD;
8032 }
8033 #endif	// OS_WIN32
8034 
8035 // Upgrade the virtual LAN card
CtUpgradeVLan(CLIENT * c,RPC_CLIENT_CREATE_VLAN * create)8036 bool CtUpgradeVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create)
8037 {
8038 	bool use_old_name = false;
8039 
8040 #ifdef OS_WIN32
8041 	MS_DRIVER_VER ver;
8042 #endif	// OS_WIN32
8043 
8044 	// Validate arguments
8045 	if (c == NULL || create == NULL)
8046 	{
8047 		return false;
8048 	}
8049 
8050 
8051 #ifndef	OS_WIN32
8052 
8053 	// Always succeed
8054 	return true;
8055 
8056 #else	// OS_WIN32
8057 
8058 	CiInitDriverVerStruct(&ver);
8059 
8060 	// Check whether the LAN card with the specified name already exists
8061 	if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, create->DeviceName) == false &&
8062 		MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName) == false)
8063 	{
8064 		// Not exist
8065 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
8066 		CiNotify(c);
8067 		CiSendGlobalPulse(c);
8068 		return false;
8069 	}
8070 
8071 	if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName))
8072 	{
8073 		use_old_name = true;
8074 	}
8075 
8076 	// Perform the installation
8077 	char tmp[MAX_SIZE];
8078 	Format(tmp, sizeof(tmp), "upgradevlan %s", create->DeviceName);
8079 
8080 	if (CncExecDriverInstaller(tmp) == false)
8081 	{
8082 		// Installation Failed
8083 		CiSetError(c, ERR_VLAN_INSTALL_ERROR);
8084 		CiNotify(c);
8085 		CiSendGlobalPulse(c);
8086 		return false;
8087 	}
8088 
8089 	CLog(c, "LC_UPDATE_VLAN", create->DeviceName);
8090 
8091 	CiNotify(c);
8092 	CiSendGlobalPulse(c);
8093 
8094 	return true;
8095 
8096 #endif	// OS_WIN32
8097 }
8098 
8099 // Create a virtual LAN card
CtCreateVLan(CLIENT * c,RPC_CLIENT_CREATE_VLAN * create)8100 bool CtCreateVLan(CLIENT *c, RPC_CLIENT_CREATE_VLAN *create)
8101 {
8102 	TOKEN_LIST *t;
8103 	UINT max_len;
8104 
8105 	// Validate arguments
8106 	if (c == NULL || create == NULL)
8107 	{
8108 		return false;
8109 	}
8110 
8111 	if (SearchStrEx(create->DeviceName, " ", 0, false) != INFINITE)
8112 	{
8113 		// Spaces in the name is not allowed
8114 		CiSetError(c, ERR_INVALID_PARAMETER);
8115 		return false;
8116 	}
8117 
8118 #ifndef	OS_WIN32
8119 
8120 	// Non-Win32
8121 #ifdef	NO_VLAN
8122 	if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
8123 	{
8124 		// A virtual LAN card can not be added or removed in MacOS X
8125 		CiSetError(c, ERR_NOT_SUPPORTED);
8126 		return false;
8127 	}
8128 #endif	// NO_VLAN
8129 
8130 	// Check whether the specified name is valid or not
8131 	if (IsSafeStr(create->DeviceName) == false)
8132 	{
8133 		// Name is invalid
8134 		CiSetError(c, ERR_VLAN_INVALID_NAME);
8135 		return false;
8136 	}
8137 
8138 	// Check whether the LAN card of the specified name already exists
8139 	LockList(c->UnixVLanList);
8140 	{
8141 		UNIX_VLAN t, *r;
8142 		Zero(&t, sizeof(t));
8143 		StrCpy(t.Name, sizeof(t.Name), create->DeviceName);
8144 
8145 		r = Search(c->UnixVLanList, &t);
8146 		if (r != NULL)
8147 		{
8148 			// Already exist
8149 			CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
8150 			UnlockList(c->UnixVLanList);
8151 			return false;
8152 		}
8153 
8154 		// Register
8155 		r = ZeroMalloc(sizeof(UNIX_VLAN));
8156 		r->Enabled = true;
8157 		GenMacAddress(r->MacAddress);
8158 		StrCpy(r->Name, sizeof(r->Name), create->DeviceName);
8159 
8160 		// Create a TUN
8161 		if (UnixVLanCreate(r->Name, r->MacAddress, false) == false)
8162 		{
8163 			// Failure
8164 			Free(r);
8165 			CiSetError(c, ERR_VLAN_INSTALL_ERROR);
8166 			UnlockList(c->UnixVLanList);
8167 			return false;
8168 		}
8169 
8170 		CLog(c, "LC_CREATE_VLAN", create->DeviceName);
8171 
8172 		Add(c->UnixVLanList, r);
8173 	}
8174 	UnlockList(c->UnixVLanList);
8175 
8176 	CiNormalizeAccountVLan(c);
8177 
8178 	CiNotify(c);
8179 	CiSendGlobalPulse(c);
8180 	CiSaveConfigurationFile(c);
8181 
8182 	return true;
8183 
8184 #else	// OS_WIN32
8185 	// Check whether the specified name is valid or not
8186 	if (IsSafeStr(create->DeviceName) == false)
8187 	{
8188 		// Name is invalid
8189 		CiSetError(c, ERR_VLAN_INVALID_NAME);
8190 		return false;
8191 	}
8192 
8193 	max_len = MAX_DEVICE_NAME_LEN;
8194 	if (StrLen(create->DeviceName) > max_len)
8195 	{
8196 		// Name is too long
8197 		CiSetError(c, ERR_VLAN_INVALID_NAME);
8198 		return false;
8199 	}
8200 
8201 	// Regulation in Windows 8 / 10
8202 	if (MsIsInfCatalogRequired())
8203 	{
8204 		if (CiIsValidVLanRegulatedName(create->DeviceName) == false)
8205 		{
8206 			// Name is invalid
8207 			CiSetError(c, ERR_VLAN_INVALID_NAME);
8208 			return false;
8209 		}
8210 	}
8211 
8212 	// Check whether the LAN card with the specified name already exists
8213 	if (MsIsVLanExists(VLAN_ADAPTER_NAME_TAG, create->DeviceName) ||
8214 		MsIsVLanExists(VLAN_ADAPTER_NAME_TAG_OLD, create->DeviceName))
8215 	{
8216 		// Already exist
8217 		CiSetError(c, ERR_VLAN_ALREADY_EXISTS);
8218 		return false;
8219 	}
8220 
8221 	// Perform the installation (Windows Vista)
8222 	char tmp[MAX_SIZE];
8223 	Format(tmp, sizeof(tmp), "instvlan %s", create->DeviceName);
8224 
8225 	if (CncExecDriverInstaller(tmp) == false)
8226 	{
8227 		CiSetError(c, ERR_VLAN_INSTALL_ERROR);
8228 		CiNotify(c);
8229 		CiSendGlobalPulse(c);
8230 		return false;
8231 	}
8232 
8233 	t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
8234 	if (t->NumTokens == 1)
8235 	{
8236 		UINT i;
8237 		// If the result of the installation, virtual LAN card is only one,
8238 		// set virtual LAN card setting of all existing accounts to this virtual LAN card
8239 		LockList(c->AccountList);
8240 		{
8241 			for (i = 0;i < LIST_NUM(c->AccountList);i++)
8242 			{
8243 				ACCOUNT *a = LIST_DATA(c->AccountList, i);
8244 				Lock(a->lock);
8245 				{
8246 					if (a->ClientOption != NULL)
8247 					{
8248 						StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName), create->DeviceName);
8249 					}
8250 				}
8251 				Unlock(a->lock);
8252 			}
8253 		}
8254 		UnlockList(c->AccountList);
8255 	}
8256 	FreeToken(t);
8257 
8258 	CLog(c, "LC_CREATE_VLAN", create->DeviceName);
8259 
8260 	CiNormalizeAccountVLan(c);
8261 
8262 	CiNotify(c);
8263 	CiSendGlobalPulse(c);
8264 
8265 	CiSaveConfigurationFile(c);
8266 
8267 	return true;
8268 
8269 #endif	// OS_WIN32
8270 }
8271 
8272 // Enumerate objects in the secure device
CtEnumObjectInSecure(CLIENT * c,RPC_ENUM_OBJECT_IN_SECURE * e)8273 bool CtEnumObjectInSecure(CLIENT *c, RPC_ENUM_OBJECT_IN_SECURE *e)
8274 {
8275 	UINT i;
8276 	// Validate arguments
8277 	if (c == NULL || e == NULL)
8278 	{
8279 		return false;
8280 	}
8281 
8282 	e->NumItem = 5;
8283 	e->ItemName = ZeroMalloc(sizeof(char *) * e->NumItem);
8284 	e->ItemType = ZeroMalloc(sizeof(bool) * e->NumItem);
8285 
8286 	for (i = 0;i < e->NumItem;i++)
8287 	{
8288 		char tmp[MAX_SIZE];
8289 		Format(tmp, sizeof(tmp), "Test Object %u", i);
8290 		e->ItemName[i] = CopyStr(tmp);
8291 		e->ItemType[i] = (i % 2 == 0) ? false : true;
8292 	}
8293 
8294 	return true;
8295 }
8296 
8297 // Get the secure device to be used
CtGetUseSecure(CLIENT * c,RPC_USE_SECURE * sec)8298 bool CtGetUseSecure(CLIENT *c, RPC_USE_SECURE *sec)
8299 {
8300 	// Validate arguments
8301 	if (c == NULL || sec == NULL)
8302 	{
8303 		return false;
8304 	}
8305 
8306 	sec->DeviceId = c->UseSecureDeviceId;
8307 
8308 	return true;
8309 }
8310 
8311 // Specifying a secure device to be used
CtUseSecure(CLIENT * c,RPC_USE_SECURE * sec)8312 bool CtUseSecure(CLIENT *c, RPC_USE_SECURE *sec)
8313 {
8314 	// Validate arguments
8315 	if (c == NULL || sec == NULL)
8316 	{
8317 		return false;
8318 	}
8319 
8320 // Do not check whether there is the specified device on the client manager
8321 /*	if (CheckSecureDeviceId(sec->DeviceId))
8322 	{
8323 		c->UseSecureDeviceId = sec->DeviceId;
8324 	}
8325 	else
8326 	{
8327 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
8328 		return false;
8329 	}
8330 */
8331 	c->UseSecureDeviceId = sec->DeviceId;
8332 
8333 	CiSaveConfigurationFile(c);
8334 
8335 	return true;
8336 }
8337 
8338 // Enumeration of secure devices
CtEnumSecure(CLIENT * c,RPC_CLIENT_ENUM_SECURE * e)8339 bool CtEnumSecure(CLIENT *c, RPC_CLIENT_ENUM_SECURE *e)
8340 {
8341 	LIST *o;
8342 	UINT i;
8343 	// Validate arguments
8344 	if (c == NULL || e == NULL)
8345 	{
8346 		return false;
8347 	}
8348 
8349 	o = GetSecureDeviceList();
8350 
8351 	e->NumItem = LIST_NUM(o);
8352 	e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM *) * e->NumItem);
8353 
8354 	for (i = 0;i < LIST_NUM(o);i++)
8355 	{
8356 		RPC_CLIENT_ENUM_SECURE_ITEM *item = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_SECURE_ITEM));
8357 		SECURE_DEVICE *s = LIST_DATA(o, i);
8358 
8359 		item->DeviceId = s->Id;
8360 		StrCpy(item->DeviceName, sizeof(item->DeviceName), s->DeviceName);
8361 		StrCpy(item->Manufacturer, sizeof(item->Manufacturer), s->Manufacturer);
8362 		item->Type = s->Type;
8363 
8364 		e->Items[i] = item;
8365 	}
8366 
8367 	return true;
8368 }
8369 
8370 // Release the secure device enumeration
CiFreeClientEnumSecure(RPC_CLIENT_ENUM_SECURE * e)8371 void CiFreeClientEnumSecure(RPC_CLIENT_ENUM_SECURE *e)
8372 {
8373 	UINT i;
8374 	// Validate arguments
8375 	if (e == NULL)
8376 	{
8377 		return;
8378 	}
8379 
8380 	for (i = 0;i < e->NumItem;i++)
8381 	{
8382 		Free(e->Items[i]);
8383 	}
8384 	Free(e->Items);
8385 }
8386 
8387 // Release the RPC_GET_ISSUER
CiFreeGetIssuer(RPC_GET_ISSUER * a)8388 void CiFreeGetIssuer(RPC_GET_ISSUER *a)
8389 {
8390 	// Validate arguments
8391 	if (a == NULL)
8392 	{
8393 		return;
8394 	}
8395 
8396 	if (a->issuer_x != NULL)
8397 	{
8398 		FreeX(a->issuer_x);
8399 	}
8400 	if (a->x != NULL)
8401 	{
8402 		FreeX(a->x);
8403 	}
8404 }
8405 
8406 // Get the common proxy settings
CtGetCommonProxySetting(CLIENT * c,INTERNET_SETTING * a)8407 bool CtGetCommonProxySetting(CLIENT *c, INTERNET_SETTING *a)
8408 {
8409 	// Validate arguments
8410 	if (c == NULL || a == NULL)
8411 	{
8412 		return false;
8413 	}
8414 
8415 	Copy(a, &c->CommonProxySetting, sizeof(INTERNET_SETTING));
8416 
8417 	return true;
8418 }
8419 
8420 // Set the common proxy settings
CtSetCommonProxySetting(CLIENT * c,INTERNET_SETTING * a)8421 bool CtSetCommonProxySetting(CLIENT *c, INTERNET_SETTING *a)
8422 {
8423 	// Validate arguments
8424 	if (c == NULL || a == NULL)
8425 	{
8426 		return false;
8427 	}
8428 
8429 	Copy(&c->CommonProxySetting, a, sizeof(INTERNET_SETTING));
8430 
8431 
8432 	CiSaveConfigurationFile(c);
8433 
8434 	return true;
8435 }
8436 
8437 // Get the issuer
CtGetIssuer(CLIENT * c,RPC_GET_ISSUER * a)8438 bool CtGetIssuer(CLIENT *c, RPC_GET_ISSUER *a)
8439 {
8440 	X *x;
8441 	// Validate arguments
8442 	if (c == NULL || a == NULL)
8443 	{
8444 		return false;
8445 	}
8446 
8447 	x = FindCaSignedX(c->Cedar->CaList, a->x);
8448 	if (x == NULL)
8449 	{
8450 		CiSetError(c, ERR_OBJECT_NOT_FOUND);;
8451 		return false;
8452 	}
8453 	else
8454 	{
8455 		a->issuer_x = x;
8456 		if (a->x != NULL)
8457 		{
8458 			FreeX(a->x);
8459 			a->x = NULL;
8460 		}
8461 		return true;
8462 	}
8463 }
8464 
8465 // Get the CA certificate
CtGetCa(CLIENT * c,RPC_GET_CA * get)8466 bool CtGetCa(CLIENT *c, RPC_GET_CA *get)
8467 {
8468 	bool ret = true;
8469 	X *cert = NULL;
8470 	// Validate arguments
8471 	if (c == NULL || get == NULL)
8472 	{
8473 		return false;
8474 	}
8475 
8476 	LockList(c->Cedar->CaList);
8477 	{
8478 		UINT i;
8479 
8480 		for (i = 0;i < LIST_NUM(c->Cedar->CaList);i++)
8481 		{
8482 			X *x = LIST_DATA(c->Cedar->CaList, i);
8483 
8484 			if (POINTER_TO_KEY(x) == get->Key)
8485 			{
8486 				cert = CloneX(x);
8487 				break;
8488 			}
8489 		}
8490 	}
8491 	UnlockList(c->Cedar->CaList);
8492 
8493 	if (cert == NULL)
8494 	{
8495 		// Certificate does not exist
8496 		ret = false;
8497 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
8498 	}
8499 	else
8500 	{
8501 		ret = true;
8502 		get->x = cert;
8503 	}
8504 
8505 	return ret;
8506 }
8507 
8508 // Delete the CA certificate
CtDeleteCa(CLIENT * c,RPC_CLIENT_DELETE_CA * p)8509 bool CtDeleteCa(CLIENT *c, RPC_CLIENT_DELETE_CA *p)
8510 {
8511 	bool ret;
8512 	// Validate arguments
8513 	if (c == NULL || p == NULL)
8514 	{
8515 		return false;
8516 	}
8517 
8518 	ret = DeleteCa(c->Cedar, p->Key);
8519 
8520 	if (ret == false)
8521 	{
8522 		CiSetError(c, ERR_OBJECT_NOT_FOUND);
8523 	}
8524 
8525 	CiSaveConfigurationFile(c);
8526 
8527 	return ret;
8528 }
8529 
8530 // Add a CA certificate
CtAddCa(CLIENT * c,RPC_CERT * cert)8531 bool CtAddCa(CLIENT *c, RPC_CERT *cert)
8532 {
8533 	// Validate arguments
8534 	if (c == NULL || cert == NULL)
8535 	{
8536 		return false;
8537 	}
8538 
8539 	if (cert->x->is_compatible_bit == false)
8540 	{
8541 		CiSetError(c, ERR_NOT_RSA_1024);
8542 		return false;
8543 	}
8544 
8545 	AddCa(c->Cedar, cert->x);
8546 
8547 	CiSaveConfigurationFile(c);
8548 
8549 	return true;
8550 }
8551 
8552 // Enumerate the trusted CA
CtEnumCa(CLIENT * c,RPC_CLIENT_ENUM_CA * e)8553 bool CtEnumCa(CLIENT *c, RPC_CLIENT_ENUM_CA *e)
8554 {
8555 	// Validate arguments
8556 	if (c == NULL || e == NULL)
8557 	{
8558 		return false;
8559 	}
8560 
8561 	Zero(e, sizeof(RPC_CLIENT_ENUM_CA));
8562 
8563 	LockList(c->Cedar->CaList);
8564 	{
8565 		UINT i;
8566 		e->NumItem = LIST_NUM(c->Cedar->CaList);
8567 		e->Items = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM *) * e->NumItem);
8568 
8569 		for (i = 0;i < e->NumItem;i++)
8570 		{
8571 			X *x = LIST_DATA(c->Cedar->CaList, i);
8572 			e->Items[i] = ZeroMalloc(sizeof(RPC_CLIENT_ENUM_CA_ITEM));
8573 			GetAllNameFromNameEx(e->Items[i]->SubjectName, sizeof(e->Items[i]->SubjectName), x->subject_name);
8574 			GetAllNameFromNameEx(e->Items[i]->IssuerName, sizeof(e->Items[i]->IssuerName), x->issuer_name);
8575 			e->Items[i]->Expires = x->notAfter;
8576 			e->Items[i]->Key = POINTER_TO_KEY(x);
8577 		}
8578 	}
8579 	UnlockList(c->Cedar->CaList);
8580 
8581 	return true;
8582 }
8583 
8584 // Release the CA enumeration
CiFreeClientEnumCa(RPC_CLIENT_ENUM_CA * e)8585 void CiFreeClientEnumCa(RPC_CLIENT_ENUM_CA *e)
8586 {
8587 	UINT i;
8588 	// Validate arguments
8589 	if (e == NULL)
8590 	{
8591 		return;
8592 	}
8593 
8594 	for (i = 0;i < e->NumItem;i++)
8595 	{
8596 		RPC_CLIENT_ENUM_CA_ITEM *ca = e->Items[i];
8597 		Free(ca);
8598 	}
8599 	Free(e->Items);
8600 }
8601 
8602 // Get the password setting
CtGetPasswordSetting(CLIENT * c,RPC_CLIENT_PASSWORD_SETTING * a)8603 bool CtGetPasswordSetting(CLIENT *c, RPC_CLIENT_PASSWORD_SETTING *a)
8604 {
8605 	UCHAR hash[SHA1_SIZE];
8606 	// Validate arguments
8607 	if (c == NULL || a == NULL)
8608 	{
8609 		return false;
8610 	}
8611 
8612 	Sha0(hash, "", 0);
8613 	if (Cmp(hash, c->EncryptedPassword, SHA1_SIZE) == 0)
8614 	{
8615 		a->IsPasswordPresented = false;
8616 	}
8617 	else
8618 	{
8619 		a->IsPasswordPresented = true;
8620 	}
8621 
8622 	a->PasswordRemoteOnly = c->PasswordRemoteOnly;
8623 
8624 	return true;
8625 }
8626 
8627 // Set the password
CtSetPassword(CLIENT * c,RPC_CLIENT_PASSWORD * pass)8628 bool CtSetPassword(CLIENT *c, RPC_CLIENT_PASSWORD *pass)
8629 {
8630 	char *str;
8631 	if (c == NULL)
8632 	{
8633 		return false;
8634 	}
8635 
8636 	str = pass->Password;
8637 
8638 	if (StrCmp(str, "********") != 0)
8639 	{
8640 		// Hash the password
8641 		Sha0(c->EncryptedPassword, str, StrLen(str));
8642 	}
8643 
8644 	c->PasswordRemoteOnly = pass->PasswordRemoteOnly;
8645 
8646 	CLog(c, "LC_SET_PASSWORD");
8647 
8648 	CiSaveConfigurationFile(c);
8649 
8650 	return true;
8651 }
8652 
CiFreeIni(LIST * o)8653 void CiFreeIni(LIST *o)
8654 {
8655 	// Validate arguments
8656 	if (o == NULL)
8657 	{
8658 		return;
8659 	}
8660 
8661 	FreeIni(o);
8662 }
8663 
8664 // Read the custom.ini file
CiLoadIni()8665 LIST *CiLoadIni()
8666 {
8667 	BUF *b = ReadDump(CLIENT_CUSTOM_INI_FILENAME);
8668 	LIST *ini;
8669 	if (b == NULL)
8670 	{
8671 		return NULL;
8672 	}
8673 
8674 	ini = ReadIni(b);
8675 
8676 	FreeBuf(b);
8677 
8678 	return ini;
8679 
8680 }
8681 
8682 // Reflect the settings of the custom.ini
CiLoadIniSettings(CLIENT * c)8683 void CiLoadIniSettings(CLIENT *c)
8684 {
8685 	LIST *o;
8686 	//char *log;
8687 	//char *config;
8688 
8689 	if (c == NULL)
8690 	{
8691 		return;
8692 	}
8693 
8694 	o = CiLoadIni();
8695 
8696 	if (o == NULL)
8697 	{
8698 		return;
8699 	}
8700 
8701 	/*log = IniStrValue(o, "NoSaveLog");
8702 	config = IniStrValue(o, "NoSaveConfig");
8703 
8704 	if(StrCmpi(log, "true") == 0)
8705 	{
8706 		c->NoSaveLog = true;
8707 	}
8708 	if(StrCmpi(config, "true") == 0)
8709 	{
8710 		c->NoSaveConfig = true;
8711 	}*/
8712 
8713 	c->NoSaveLog = ToBool(IniStrValue(o, "NoSaveLog"));
8714 	c->NoSaveConfig = ToBool(IniStrValue(o, "NoSaveConfig"));
8715 
8716 	CiFreeIni(o);
8717 
8718 }
8719 
CiLoadConfigFilePathFromIni(char * path,UINT size)8720 bool CiLoadConfigFilePathFromIni(char *path, UINT size)
8721 {
8722 	char *tmp;
8723 	LIST *o;
8724 	bool ret = false;
8725 
8726 	// Validate arguments
8727 	if (path == NULL)
8728 	{
8729 		return false;
8730 	}
8731 
8732 	o = CiLoadIni();
8733 
8734 	if (o == NULL)
8735 	{
8736 		return false;
8737 	}
8738 
8739 	StrCpy(path, size, "");
8740 
8741 	tmp = IniStrValue(o, "ConfigPath");
8742 	NormalizePath(path, size, tmp);
8743 
8744 	if (IsEmptyStr(path) == false)
8745 	{
8746 		ret = true;
8747 	}
8748 	else
8749 	{
8750 		ret = false;
8751 	}
8752 
8753 	CiFreeIni(o);
8754 
8755 	return ret;
8756 }
8757 
8758 // Set the client error code
CiSetError(CLIENT * c,UINT err)8759 void CiSetError(CLIENT *c, UINT err)
8760 {
8761 	// Validate arguments
8762 	if (c == NULL)
8763 	{
8764 		return;
8765 	}
8766 
8767 	c->Err = err;
8768 }
8769 
8770 // UNIX virtual LAN card comparison function
CiCompareUnixVLan(void * p1,void * p2)8771 int CiCompareUnixVLan(void *p1, void *p2)
8772 {
8773 	UNIX_VLAN *v1, *v2;
8774 	if (p1 == NULL || p2 == NULL)
8775 	{
8776 		return 0;
8777 	}
8778 	v1 = *(UNIX_VLAN **)p1;
8779 	v2 = *(UNIX_VLAN **)p2;
8780 	if (v1 == NULL || v2 == NULL)
8781 	{
8782 		return 0;
8783 	}
8784 
8785 	return StrCmpi(v1->Name, v2->Name);
8786 }
8787 
8788 // Modify the account settings that an incorrect VLAN name is specified
CiNormalizeAccountVLan(CLIENT * c)8789 void CiNormalizeAccountVLan(CLIENT *c)
8790 {
8791 	bool b = false;
8792 	char *name;
8793 	UINT i;
8794 	// Validate arguments
8795 	if (c == NULL)
8796 	{
8797 		return;
8798 	}
8799 
8800 	name = CiGetFirstVLan(c);
8801 
8802 	if (name != NULL)
8803 	{
8804 		LockList(c->AccountList);
8805 		{
8806 			for (i = 0;i < LIST_NUM(c->AccountList);i++)
8807 			{
8808 				ACCOUNT *a = LIST_DATA(c->AccountList, i);
8809 
8810 				Lock(a->lock);
8811 				{
8812 					if (a->ClientOption != NULL)
8813 					{
8814 						if (CiIsVLan(c, a->ClientOption->DeviceName) == false)
8815 						{
8816 							StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName),
8817 								name);
8818 							b = true;
8819 						}
8820 					}
8821 				}
8822 				Unlock(a->lock);
8823 			}
8824 		}
8825 		UnlockList(c->AccountList);
8826 
8827 		Free(name);
8828 	}
8829 
8830 	if (b)
8831 	{
8832 		CiNotify(c);
8833 		CiSendGlobalPulse(c);
8834 		CiSaveConfigurationFile(c);
8835 	}
8836 }
8837 
8838 // Check whether a virtual LAN card of the specified name exists
CiIsVLan(CLIENT * c,char * name)8839 bool CiIsVLan(CLIENT *c, char *name)
8840 {
8841 	// Validate arguments
8842 	if (c == NULL || name == NULL)
8843 	{
8844 		return false;
8845 	}
8846 
8847 #ifdef	OS_WIN32
8848 	{
8849 		TOKEN_LIST *t;
8850 		UINT i;
8851 
8852 		t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
8853 		if (t == NULL)
8854 		{
8855 			return false;
8856 		}
8857 
8858 		for (i = 0;i < t->NumTokens;i++)
8859 		{
8860 			if (StrCmpi(t->Token[i], name) == 0)
8861 			{
8862 				FreeToken(t);
8863 				return true;
8864 			}
8865 		}
8866 
8867 		FreeToken(t);
8868 
8869 		return false;
8870 	}
8871 #else	// OS_WIN32
8872 	{
8873 		UNIX_VLAN *v;
8874 		UINT i;
8875 		bool ret = false;
8876 
8877 		LockList(c->UnixVLanList);
8878 		{
8879 			for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
8880 			{
8881 				v = (UNIX_VLAN *)LIST_DATA(c->UnixVLanList, i);
8882 				if (StrCmpi(v->Name, name) == 0)
8883 				{
8884 					ret = true;
8885 				}
8886 			}
8887 		}
8888 		UnlockList(c->UnixVLanList);
8889 
8890 		return ret;
8891 	}
8892 #endif	// OS_WIN32
8893 }
8894 
8895 // If a non-existent virtual LAN card is specified in any Account, and only
8896 // one virtual LAN card is installed, set the virtual LAN card to the account
CiSetVLanToDefault(CLIENT * c)8897 void CiSetVLanToDefault(CLIENT *c)
8898 {
8899 	char device_name[MAX_SIZE];
8900 	// Validate arguments
8901 	if (c == NULL)
8902 	{
8903 		return;
8904 	}
8905 
8906 #ifdef	OS_WIN32
8907 	{
8908 		TOKEN_LIST *t;
8909 
8910 		t = MsEnumNetworkAdapters(VLAN_ADAPTER_NAME, VLAN_ADAPTER_NAME_OLD);
8911 		if (t == NULL)
8912 		{
8913 			return;
8914 		}
8915 		if (t->NumTokens != 1)
8916 		{
8917 			FreeToken(t);
8918 			return;
8919 		}
8920 		StrCpy(device_name, sizeof(device_name), t->Token[0]);
8921 		FreeToken(t);
8922 	}
8923 #else	// OS_WIN32
8924 	{
8925 		UNIX_VLAN *v;
8926 
8927 		LockList(c->UnixVLanList);
8928 
8929 		if (LIST_NUM(c->UnixVLanList) != 1)
8930 		{
8931 			UnlockList(c->UnixVLanList);
8932 			return;
8933 		}
8934 		v = LIST_DATA(c->UnixVLanList, 0);
8935 		StrCpy(device_name, sizeof(device_name), v->Name);
8936 
8937 		UnlockList(c->UnixVLanList);
8938 	}
8939 #endif	// OS_WIN32
8940 
8941 	{
8942 		UINT i;
8943 		LockList(c->AccountList);
8944 		{
8945 			for (i = 0;i < LIST_NUM(c->AccountList);i++)
8946 			{
8947 				ACCOUNT *a = LIST_DATA(c->AccountList, i);
8948 
8949 				Lock(a->lock);
8950 				{
8951 					if (CiIsVLan(c, a->ClientOption->DeviceName) == false)
8952 					{
8953 						StrCpy(a->ClientOption->DeviceName, sizeof(a->ClientOption->DeviceName),
8954 							device_name);
8955 					}
8956 				}
8957 				Unlock(a->lock);
8958 			}
8959 		}
8960 		UnlockList(c->AccountList);
8961 	}
8962 }
8963 
8964 // Initialize the settings
CiInitConfiguration(CLIENT * c)8965 void CiInitConfiguration(CLIENT *c)
8966 {
8967 	// Validate arguments
8968 	if (c == NULL)
8969 	{
8970 		return;
8971 	}
8972 
8973 #ifdef	OS_UNIX
8974 	// Initialize the VLAN
8975 	UnixVLanInit();
8976 #endif	 // OS_UNIX
8977 
8978 	// Account list
8979 	c->AccountList = NewList(CiCompareAccount);
8980 
8981 	// Unix version VLAN list
8982 	if (OS_IS_UNIX(GetOsInfo()->OsType))
8983 	{
8984 		c->UnixVLanList = NewList(CiCompareUnixVLan);
8985 	}
8986 
8987 	// Read the configuration file
8988 	CLog(c, "LC_LOAD_CONFIG_1");
8989 	if (CiLoadConfigurationFile(c) == false)
8990 	{
8991 		CLog(c, "LC_LOAD_CONFIG_3");
8992 		// Do the initial setup because the configuration file does not exist
8993 		// Clear the password
8994 		Sha0(c->EncryptedPassword, "", 0);
8995 		// Initialize the client configuration
8996 		// Disable remote management
8997 		c->Config.AllowRemoteConfig = false;
8998 		StrCpy(c->Config.KeepConnectHost, sizeof(c->Config.KeepConnectHost), CLIENT_DEFAULT_KEEPALIVE_HOST);
8999 		c->Config.KeepConnectPort = CLIENT_DEFAULT_KEEPALIVE_PORT;
9000 		c->Config.KeepConnectProtocol = CONNECTION_UDP;
9001 		c->Config.KeepConnectInterval = CLIENT_DEFAULT_KEEPALIVE_INTERVAL;
9002 		c->Config.UseKeepConnect = false;	// Don't use the connection maintenance function by default in the Client
9003 		// Eraser
9004 		c->Eraser = NewEraser(c->Logger, 0);
9005 	}
9006 	else
9007 	{
9008 		CLog(c, "LC_LOAD_CONFIG_2");
9009 	}
9010 
9011 	// Appropriate setting for virtual LAN card
9012 	CiSetVLanToDefault(c);
9013 }
9014 
9015 // Release the settings
CiFreeConfiguration(CLIENT * c)9016 void CiFreeConfiguration(CLIENT *c)
9017 {
9018 	UINT i;
9019 	// Validate arguments
9020 	if (c == NULL)
9021 	{
9022 		return;
9023 	}
9024 
9025 	// Write to the configuration file
9026 	CiSaveConfigurationFile(c);
9027 
9028 	// Release the configuration file
9029 	FreeCfgRw(c->CfgRw);
9030 
9031 	// Release the account list
9032 	for (i = 0;i < LIST_NUM(c->AccountList);i++)
9033 	{
9034 		ACCOUNT *a = LIST_DATA(c->AccountList, i);
9035 
9036 		CiFreeAccount(a);
9037 	}
9038 	ReleaseList(c->AccountList);
9039 
9040 	if (c->UnixVLanList != NULL)
9041 	{
9042 		// Release of UNIX version VLAN list
9043 		for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
9044 		{
9045 			UNIX_VLAN *v = LIST_DATA(c->UnixVLanList, i);
9046 			Free(v);
9047 		}
9048 		ReleaseList(c->UnixVLanList);
9049 	}
9050 	c->UnixVLanList = NULL;
9051 
9052 #ifdef	OS_UNIX
9053 	// Release the VLAN
9054 	UnixVLanFree();
9055 #endif	// OS_UNIX
9056 }
9057 
9058 // Release the certificate data acquisition
CiFreeGetCa(RPC_GET_CA * a)9059 void CiFreeGetCa(RPC_GET_CA *a)
9060 {
9061 	// Validate arguments
9062 	if (a == NULL)
9063 	{
9064 		return;
9065 	}
9066 
9067 	FreeX(a->x);
9068 }
9069 
9070 // Release the client authentication data
CiFreeClientAuth(CLIENT_AUTH * auth)9071 void CiFreeClientAuth(CLIENT_AUTH *auth)
9072 {
9073 	// Validate arguments
9074 	if (auth == NULL)
9075 	{
9076 		return;
9077 	}
9078 
9079 	if (auth->ClientX != NULL)
9080 	{
9081 		FreeX(auth->ClientX);
9082 	}
9083 	if (auth->ClientK != NULL)
9084 	{
9085 		FreeK(auth->ClientK);
9086 	}
9087 
9088 	Free(auth);
9089 }
9090 
9091 // Release the account
CiFreeAccount(ACCOUNT * a)9092 void CiFreeAccount(ACCOUNT *a)
9093 {
9094 	// Validate arguments
9095 	if (a == NULL)
9096 	{
9097 		return;
9098 	}
9099 
9100 	// Release the lock
9101 	DeleteLock(a->lock);
9102 
9103 	// Release the client option
9104 	Free(a->ClientOption);
9105 
9106 	// Release the client authentication data
9107 	CiFreeClientAuth(a->ClientAuth);
9108 
9109 	if (a->ServerCert != NULL)
9110 	{
9111 		FreeX(a->ServerCert);
9112 	}
9113 
9114 	Free(a);
9115 }
9116 
9117 // Sort accounts
CiCompareAccount(void * p1,void * p2)9118 int CiCompareAccount(void *p1, void *p2)
9119 {
9120 	ACCOUNT *a1, *a2;
9121 	if (p1 == NULL || p2 == NULL)
9122 	{
9123 		return 0;
9124 	}
9125 	a1 = *(ACCOUNT **)p1;
9126 	a2 = *(ACCOUNT **)p2;
9127 	if (a1 == NULL || a2 == NULL)
9128 	{
9129 		return 0;
9130 	}
9131 
9132 	return UniStrCmpi(a1->ClientOption->AccountName, a2->ClientOption->AccountName);
9133 }
9134 
9135 // Read the client configuration
CiLoadClientConfig(CLIENT_CONFIG * c,FOLDER * f)9136 void CiLoadClientConfig(CLIENT_CONFIG *c, FOLDER *f)
9137 {
9138 	// Validate arguments
9139 	if (c == NULL || f == NULL)
9140 	{
9141 		return;
9142 	}
9143 
9144 	c->UseKeepConnect = CfgGetBool(f, "UseKeepConnect");
9145 	CfgGetStr(f, "KeepConnectHost", c->KeepConnectHost, sizeof(c->KeepConnectHost));
9146 	c->KeepConnectPort = CfgGetInt(f, "KeepConnectPort");
9147 	c->KeepConnectProtocol = CfgGetInt(f, "KeepConnectProtocol");
9148 	c->AllowRemoteConfig = CfgGetBool(f, "AllowRemoteConfig");
9149 	c->KeepConnectInterval = MAKESURE(CfgGetInt(f, "KeepConnectInterval"), KEEP_INTERVAL_MIN, KEEP_INTERVAL_MAX);
9150 	c->NoChangeWcmNetworkSettingOnWindows8 = CfgGetBool(f, "NoChangeWcmNetworkSettingOnWindows8");
9151 }
9152 
9153 // Read the client authentication data
CiLoadClientAuth(FOLDER * f)9154 CLIENT_AUTH *CiLoadClientAuth(FOLDER *f)
9155 {
9156 	CLIENT_AUTH *a;
9157 	char *s;
9158 	BUF *b;
9159 	// Validate arguments
9160 	if (f == NULL)
9161 	{
9162 		return NULL;
9163 	}
9164 
9165 	a = ZeroMalloc(sizeof(CLIENT_AUTH));
9166 
9167 	a->AuthType = CfgGetInt(f, "AuthType");
9168 	CfgGetStr(f, "Username", a->Username, sizeof(a->Username));
9169 
9170 	switch (a->AuthType)
9171 	{
9172 	case CLIENT_AUTHTYPE_ANONYMOUS:
9173 		break;
9174 
9175 	case CLIENT_AUTHTYPE_PASSWORD:
9176 		CfgGetByte(f, "HashedPassword", a->HashedPassword, SHA1_SIZE);
9177 		break;
9178 
9179 	case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
9180 		b = CfgGetBuf(f, "EncryptedPassword");
9181 		if (b != NULL)
9182 		{
9183 			s = DecryptPassword(b);
9184 			StrCpy(a->PlainPassword, sizeof(a->PlainPassword), s);
9185 			Free(s);
9186 			FreeBuf(b);
9187 		}
9188 		break;
9189 
9190 	case CLIENT_AUTHTYPE_CERT:
9191 		b = CfgGetBuf(f, "ClientCert");
9192 		if (b != NULL)
9193 		{
9194 			a->ClientX = BufToX(b, false);
9195 		}
9196 		FreeBuf(b);
9197 		b = CfgGetBuf(f, "ClientKey");
9198 		if (b != NULL)
9199 		{
9200 			a->ClientK = BufToK(b, true, false, NULL);
9201 		}
9202 		FreeBuf(b);
9203 		break;
9204 
9205 	case CLIENT_AUTHTYPE_SECURE:
9206 		CfgGetStr(f, "SecurePublicCertName", a->SecurePublicCertName, sizeof(a->SecurePublicCertName));
9207 		CfgGetStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName, sizeof(a->SecurePrivateKeyName));
9208 		break;
9209 
9210 	case CLIENT_AUTHTYPE_OPENSSLENGINE:
9211 		b = CfgGetBuf(f, "ClientCert");
9212 		if (b != NULL)
9213 		{
9214 			a->ClientX = BufToX(b, false);
9215 		}
9216 		FreeBuf(b);
9217 		if (CfgGetStr(f, "OpensslEnginePrivateKeyName", a->OpensslEnginePrivateKeyName, sizeof(a->OpensslEnginePrivateKeyName)))
9218     {
9219         a->ClientK = OpensslEngineToK(a->OpensslEnginePrivateKeyName, a->OpensslEngineName);
9220     }
9221     CfgGetStr(f, "OpensslEngineName", a->OpensslEngineName, sizeof(a->OpensslEngineName));
9222 		break;
9223 	}
9224 
9225 	return a;
9226 }
9227 
9228 // Read the client option
CiLoadClientOption(FOLDER * f)9229 CLIENT_OPTION *CiLoadClientOption(FOLDER *f)
9230 {
9231 	CLIENT_OPTION *o;
9232 	char *s;
9233 	BUF *b;
9234 	// Validate arguments
9235 	if (f == NULL)
9236 	{
9237 		return NULL;
9238 	}
9239 
9240 	o = ZeroMalloc(sizeof(CLIENT_OPTION));
9241 
9242 	CfgGetUniStr(f, "AccountName", o->AccountName, sizeof(o->AccountName));
9243 	CfgGetStr(f, "Hostname", o->Hostname, sizeof(o->Hostname));
9244 	o->Port = CfgGetInt(f, "Port");
9245 	o->PortUDP = CfgGetInt(f, "PortUDP");
9246 	o->ProxyType = CfgGetInt(f, "ProxyType");
9247 	CfgGetStr(f, "ProxyName", o->ProxyName, sizeof(o->ProxyName));
9248 	o->ProxyPort = CfgGetInt(f, "ProxyPort");
9249 	CfgGetStr(f, "ProxyUsername", o->ProxyUsername, sizeof(o->ProxyUsername));
9250 	b = CfgGetBuf(f, "ProxyPassword");
9251 	s = DecryptPassword(b);
9252 	StrCpy(o->ProxyPassword, sizeof(o->ProxyPassword), s);
9253 	Free(s);
9254 	FreeBuf(b);
9255 	CfgGetStr(f, "CustomHttpHeader", o->CustomHttpHeader, sizeof(o->CustomHttpHeader));
9256 	o->NumRetry = CfgGetInt(f, "NumRetry");
9257 	o->RetryInterval = CfgGetInt(f, "RetryInterval");
9258 	CfgGetStr(f, "HubName", o->HubName, sizeof(o->HubName));
9259 	o->MaxConnection = CfgGetInt(f, "MaxConnection");
9260 	o->UseEncrypt = CfgGetBool(f, "UseEncrypt");
9261 	o->UseCompress = CfgGetBool(f, "UseCompress");
9262 	o->HalfConnection = CfgGetBool(f, "HalfConnection");
9263 	o->NoRoutingTracking = CfgGetBool(f, "NoRoutingTracking");
9264 	CfgGetStr(f, "DeviceName", o->DeviceName, sizeof(o->DeviceName));
9265 	o->AdditionalConnectionInterval = CfgGetInt(f, "AdditionalConnectionInterval");
9266 	o->HideStatusWindow = CfgGetBool(f, "HideStatusWindow");
9267 	o->HideNicInfoWindow = CfgGetBool(f, "HideNicInfoWindow");
9268 	o->ConnectionDisconnectSpan = CfgGetInt(f, "ConnectionDisconnectSpan");
9269 	o->RequireMonitorMode = CfgGetBool(f, "RequireMonitorMode");
9270 	o->RequireBridgeRoutingMode = CfgGetBool(f, "RequireBridgeRoutingMode");
9271 	o->DisableQoS = CfgGetBool(f, "DisableQoS");
9272 	o->FromAdminPack = CfgGetBool(f, "FromAdminPack");
9273 	o->NoUdpAcceleration = CfgGetBool(f, "NoUdpAcceleration");
9274 
9275 	b = CfgGetBuf(f, "HostUniqueKey");
9276 	if (b != NULL)
9277 	{
9278 		if (b->Size == SHA1_SIZE)
9279 		{
9280 			Copy(o->HostUniqueKey, b->Buf, SHA1_SIZE);
9281 		}
9282 
9283 		FreeBuf(b);
9284 	}
9285 
9286 	return o;
9287 }
9288 
9289 // Read the account data
CiLoadClientAccount(FOLDER * f)9290 ACCOUNT *CiLoadClientAccount(FOLDER *f)
9291 {
9292 	ACCOUNT *a;
9293 	FOLDER *client_option_folder, *client_auth_folder;
9294 	BUF *b;
9295 	char tmp[64];
9296 	// Validate arguments
9297 	if (f == NULL)
9298 	{
9299 		return NULL;
9300 	}
9301 
9302 	client_option_folder = CfgGetFolder(f, "ClientOption");
9303 
9304 	if (client_option_folder != NULL)
9305 	{
9306 		// Compare whether it matches to the account name that is already registered
9307 	}
9308 
9309 	client_auth_folder = CfgGetFolder(f, "ClientAuth");
9310 
9311 	if (client_option_folder == NULL || client_auth_folder == NULL)
9312 	{
9313 		return NULL;
9314 	}
9315 
9316 	a = ZeroMalloc(sizeof(ACCOUNT));
9317 	a->lock = NewLock();
9318 
9319 	a->ClientOption = CiLoadClientOption(client_option_folder);
9320 	a->ClientAuth = CiLoadClientAuth(client_auth_folder);
9321 
9322 	a->StartupAccount = CfgGetBool(f, "StartupAccount");
9323 	a->CheckServerCert = CfgGetBool(f, "CheckServerCert");
9324 	a->RetryOnServerCert = CfgGetBool(f, "RetryOnServerCert");
9325 	a->CreateDateTime = CfgGetInt64(f, "CreateDateTime");
9326 	a->UpdateDateTime = CfgGetInt64(f, "UpdateDateTime");
9327 	a->LastConnectDateTime = CfgGetInt64(f, "LastConnectDateTime");
9328 
9329 	b = CfgGetBuf(f, "ServerCert");
9330 	if (b != NULL)
9331 	{
9332 		a->ServerCert = BufToX(b, false);
9333 		FreeBuf(b);
9334 	}
9335 
9336 	if (CfgGetStr(f, "ShortcutKey", tmp, sizeof(tmp)))
9337 	{
9338 		BUF *b = StrToBin(tmp);
9339 		if (b->Size == SHA1_SIZE)
9340 		{
9341 			Copy(a->ShortcutKey, b->Buf, SHA1_SIZE);
9342 		}
9343 		FreeBuf(b);
9344 	}
9345 
9346 	if (IsZero(a->ShortcutKey, SHA1_SIZE))
9347 	{
9348 		Rand(a->ShortcutKey, SHA1_SIZE);
9349 	}
9350 
9351 	return a;
9352 }
9353 
9354 // Read the account database
CiLoadAccountDatabase(CLIENT * c,FOLDER * f)9355 void CiLoadAccountDatabase(CLIENT *c, FOLDER *f)
9356 {
9357 	TOKEN_LIST *t;
9358 	UINT i;
9359 	// Validate arguments
9360 	if (c == NULL || f == NULL)
9361 	{
9362 		return;
9363 	}
9364 
9365 	t = CfgEnumFolderToTokenList(f);
9366 	if (t == NULL)
9367 	{
9368 		return;
9369 	}
9370 
9371 	for (i = 0;i < t->NumTokens;i++)
9372 	{
9373 		FOLDER *ff = CfgGetFolder(f, t->Token[i]);
9374 
9375 		if (ff != NULL)
9376 		{
9377 			ACCOUNT *a = CiLoadClientAccount(ff);
9378 			if (a != NULL)
9379 			{
9380 				{
9381 					Add(c->AccountList, a);
9382 				}
9383 			}
9384 		}
9385 	}
9386 
9387 	Sort(c->AccountList);
9388 
9389 	FreeToken(t);
9390 }
9391 
9392 // Read the root CA certificate
CiLoadCACert(CLIENT * c,FOLDER * f)9393 void CiLoadCACert(CLIENT *c, FOLDER *f)
9394 {
9395 	BUF *b;
9396 	X *x;
9397 	// Validate arguments
9398 	if (c == NULL || f == NULL)
9399 	{
9400 		return;
9401 	}
9402 
9403 	b = CfgGetBuf(f, "X509");
9404 	if (b == NULL)
9405 	{
9406 		return;
9407 	}
9408 
9409 	x = BufToX(b, false);
9410 
9411 	AddCa(c->Cedar, x);
9412 
9413 	FreeX(x);
9414 
9415 	FreeBuf(b);
9416 }
9417 
9418 // Read the root CA list
CiLoadCAList(CLIENT * c,FOLDER * f)9419 void CiLoadCAList(CLIENT *c, FOLDER *f)
9420 {
9421 	CEDAR *cedar;
9422 	TOKEN_LIST *t;
9423 	// Validate arguments
9424 	if (c == NULL || f == NULL)
9425 	{
9426 		return;
9427 	}
9428 
9429 	t = CfgEnumFolderToTokenList(f);
9430 
9431 	cedar = c->Cedar;
9432 
9433 	LockList(cedar->CaList);
9434 	{
9435 		UINT i;
9436 		for (i = 0;i < t->NumTokens;i++)
9437 		{
9438 			FOLDER *folder = CfgGetFolder(f, t->Token[i]);
9439 			CiLoadCACert(c, folder);
9440 		}
9441 	}
9442 	UnlockList(cedar->CaList);
9443 
9444 	FreeToken(t);
9445 }
9446 
9447 // Read a VLAN
CiLoadVLan(CLIENT * c,FOLDER * f)9448 void CiLoadVLan(CLIENT *c, FOLDER *f)
9449 {
9450 	char tmp[MAX_SIZE];
9451 	UCHAR addr[6];
9452 	BUF *b;
9453 	UNIX_VLAN *v;
9454 	// Validate arguments
9455 	if (c == NULL || f == NULL)
9456 	{
9457 		return;
9458 	}
9459 
9460 	if (CfgGetStr(f, "MacAddress", tmp, sizeof(tmp)) == false)
9461 	{
9462 		return;
9463 	}
9464 
9465 	b = StrToBin(tmp);
9466 	if (b == NULL)
9467 	{
9468 		return;
9469 	}
9470 
9471 	if (b->Size != 6)
9472 	{
9473 		FreeBuf(b);
9474 		return;
9475 	}
9476 
9477 	Copy(addr, b->Buf, 6);
9478 
9479 	FreeBuf(b);
9480 
9481 	if (IsZero(addr, 6))
9482 	{
9483 		return;
9484 	}
9485 
9486 	v = ZeroMalloc(sizeof(UNIX_VLAN));
9487 	Copy(v->MacAddress, addr, 6);
9488 	StrCpy(v->Name, sizeof(v->Name), f->Name);
9489 	v->Enabled = CfgGetBool(f, "Enabled");
9490 
9491 	Add(c->UnixVLanList, v);
9492 
9493 #ifdef	OS_UNIX
9494 	UnixVLanCreate(v->Name, v->MacAddress, false);
9495 #endif	// OS_UNIX
9496 }
9497 
9498 // Read a VLAN list
CiLoadVLanList(CLIENT * c,FOLDER * f)9499 void CiLoadVLanList(CLIENT *c, FOLDER *f)
9500 {
9501 	TOKEN_LIST *t;
9502 	// Validate arguments
9503 	if (c == NULL || f == NULL)
9504 	{
9505 		return;
9506 	}
9507 
9508 	t = CfgEnumFolderToTokenList(f);
9509 
9510 	LockList(c->UnixVLanList);
9511 	{
9512 		UINT i;
9513 		for (i = 0;i < t->NumTokens;i++)
9514 		{
9515 			FOLDER *folder = CfgGetFolder(f, t->Token[i]);
9516 			CiLoadVLan(c, folder);
9517 		}
9518 	}
9519 	UnlockList(c->UnixVLanList);
9520 
9521 	FreeToken(t);
9522 }
9523 
9524 // Read the configuration from the configuration file
CiReadSettingFromCfg(CLIENT * c,FOLDER * root)9525 bool CiReadSettingFromCfg(CLIENT *c, FOLDER *root)
9526 {
9527 	FOLDER *config;
9528 	FOLDER *cert;
9529 	FOLDER *db;
9530 	FOLDER *vlan;
9531 	FOLDER *cmsetting;
9532 	FOLDER *proxy;
9533 	char user_agent[MAX_SIZE];
9534 	// Validate arguments
9535 	if (c == NULL || root == NULL)
9536 	{
9537 		return false;
9538 	}
9539 
9540 	// Initialize the setting if there isn't either of AccountDatabase and Config
9541 	config = CfgGetFolder(root, "Config");
9542 	if (config == NULL)
9543 	{
9544 		return false;
9545 	}
9546 
9547 	db = CfgGetFolder(root, "AccountDatabase");
9548 	if (db == NULL)
9549 	{
9550 		return false;
9551 	}
9552 
9553 	cmsetting = CfgGetFolder(root, "ClientManagerSetting");
9554 
9555 	CiLoadClientConfig(&c->Config, config);
9556 
9557 
9558 	proxy = CfgGetFolder(root, "CommonProxySetting");
9559 
9560 	if (proxy != NULL)
9561 	{
9562 		INTERNET_SETTING t;
9563 		BUF *pw;
9564 
9565 		// Proxy Setting
9566 		Zero(&t, sizeof(t));
9567 		t.ProxyType = CfgGetInt(proxy, "ProxyType");
9568 		CfgGetStr(proxy, "ProxyHostName", t.ProxyHostName, sizeof(t.ProxyHostName));
9569 		t.ProxyPort = CfgGetInt(proxy, "ProxyPort");
9570 		CfgGetStr(proxy, "ProxyUsername", t.ProxyUsername, sizeof(t.ProxyUsername));
9571 		pw = CfgGetBuf(proxy, "ProxyPassword");
9572 		if (pw != NULL)
9573 		{
9574 			char *pw_str = DecryptPassword(pw);
9575 			StrCpy(t.ProxyPassword, sizeof(t.ProxyPassword), pw_str);
9576 
9577 			Free(pw_str);
9578 			FreeBuf(pw);
9579 		}
9580 
9581 		CfgGetStr(proxy, "CustomHttpHeader", t.CustomHttpHeader, sizeof(t.CustomHttpHeader));
9582 
9583 		Copy(&c->CommonProxySetting, &t, sizeof(INTERNET_SETTING));
9584 	}
9585 
9586 	// Eraser
9587 	c->Eraser = NewEraser(c->Logger, CfgGetInt64(config, "AutoDeleteCheckDiskFreeSpaceMin"));
9588 
9589 	if (OS_IS_UNIX(GetOsInfo()->OsType)
9590 #ifdef	NO_VLAN
9591 	    && GetOsInfo()->OsType != OSTYPE_MACOS_X
9592 #endif	// NO_VLAN
9593 	    )
9594 	{
9595 		// Read the UNIX version virtual LAN card list (except MacOS)
9596 		vlan = CfgGetFolder(root, "UnixVLan");
9597 		if (vlan != NULL)
9598 		{
9599 			CiLoadVLanList(c, vlan);
9600 		}
9601 	}
9602 
9603 #ifdef	NO_VLAN
9604 	if (GetOsInfo()->OsType == OSTYPE_MACOS_X)
9605 	{
9606 #ifdef	OS_UNIX
9607 		UNIX_VLAN *uv;
9608 
9609 		// Create a Tap for MacOS X
9610 		if (UnixVLanCreate(CLIENT_MACOS_TAP_NAME, NULL, false) == false)
9611 		{
9612 			// Fail (abort)
9613 			CLog(c, "LC_TAP_NOT_FOUND");
9614 			Alert("tun/tap driver not found.", NULL);
9615 			exit(0);
9616 		}
9617 
9618 		uv = ZeroMalloc(sizeof(UNIX_VLAN));
9619 		uv->Enabled = true;
9620 		StrCpy(uv->Name, sizeof(uv->Name), CLIENT_MACOS_TAP_NAME);
9621 		Add(c->UnixVLanList, uv);
9622 #endif	// OS_UNIX
9623 	}
9624 #endif	// NO_VLAN
9625 	CiLoadAccountDatabase(c, db);
9626 
9627 	if (CfgGetByte(root, "EncryptedPassword", c->EncryptedPassword, SHA1_SIZE) == false)
9628 	{
9629 		Sha0(c->EncryptedPassword, "", 0);
9630 	}
9631 
9632 	c->PasswordRemoteOnly = CfgGetBool(root, "PasswordRemoteOnly");
9633 	c->UseSecureDeviceId = CfgGetInt(root, "UseSecureDeviceId");
9634 
9635 	if (CfgGetStr(root, "UserAgent", user_agent, sizeof(user_agent)))
9636 	{
9637 		if (IsEmptyStr(user_agent) == false)
9638 		{
9639 			Free(c->Cedar->HttpUserAgent);
9640 			c->Cedar->HttpUserAgent = CopyStr(user_agent);
9641 		}
9642 	}
9643 
9644 	cert = CfgGetFolder(root, "RootCA");
9645 	if (cert != NULL)
9646 	{
9647 		CiLoadCAList(c, cert);
9648 	}
9649 
9650 	c->DontSavePassword = CfgGetBool(root, "DontSavePassword");
9651 
9652 	if (cmsetting != NULL)
9653 	{
9654 		UINT ostype = GetOsInfo()->OsType;
9655 		// CM_SETTING
9656 		CM_SETTING *s = c->CmSetting;
9657 		s->EasyMode = CfgGetBool(cmsetting, "EasyMode");
9658 		s->LockMode = CfgGetBool(cmsetting, "LockMode");
9659 		CfgGetByte(cmsetting, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));
9660 	}
9661 
9662 	return true;
9663 }
9664 
9665 // Read the configuration file
CiLoadConfigurationFile(CLIENT * c)9666 bool CiLoadConfigurationFile(CLIENT *c)
9667 {
9668 	bool ret;
9669 	FOLDER *root;
9670 	char path[MAX_SIZE];
9671 	// Validate arguments
9672 	if (c == NULL)
9673 	{
9674 		return false;
9675 	}
9676 
9677 	// Read the configuration file
9678 	if (CiLoadConfigFilePathFromIni(path, sizeof(path)))
9679 	{
9680 		c->CfgRw = NewCfgRw(&root, path);
9681 	}
9682 	else
9683 	{
9684 		c->CfgRw = NewCfgRw(&root, CLIENT_CONFIG_FILE_NAME);
9685 	}
9686 
9687 	if (root == NULL)
9688 	{
9689 		return false;
9690 	}
9691 
9692 	ret = CiReadSettingFromCfg(c, root);
9693 
9694 	CfgDeleteFolder(root);
9695 
9696 	return ret;
9697 }
9698 
9699 // Write the CLIENT_CONFIG
CiWriteClientConfig(FOLDER * cc,CLIENT_CONFIG * config)9700 void CiWriteClientConfig(FOLDER *cc, CLIENT_CONFIG *config)
9701 {
9702 	// Validate arguments
9703 	if (cc == NULL || config == NULL)
9704 	{
9705 		return;
9706 	}
9707 
9708 	CfgAddBool(cc, "UseKeepConnect", config->UseKeepConnect);
9709 	CfgAddStr(cc, "KeepConnectHost", config->KeepConnectHost);
9710 	CfgAddInt(cc, "KeepConnectPort", config->KeepConnectPort);
9711 	CfgAddInt(cc, "KeepConnectProtocol", config->KeepConnectProtocol);
9712 	CfgAddBool(cc, "AllowRemoteConfig", config->AllowRemoteConfig);
9713 	CfgAddInt(cc, "KeepConnectInterval", config->KeepConnectInterval);
9714 	CfgAddBool(cc, "NoChangeWcmNetworkSettingOnWindows8", config->NoChangeWcmNetworkSettingOnWindows8);
9715 }
9716 
9717 // Write the client authentication data
CiWriteClientAuth(FOLDER * f,CLIENT_AUTH * a)9718 void CiWriteClientAuth(FOLDER *f, CLIENT_AUTH *a)
9719 {
9720 	BUF *b;
9721 	// Validate arguments
9722 	if (f == NULL || a == NULL)
9723 	{
9724 		return;
9725 	}
9726 
9727 	CfgAddInt(f, "AuthType", a->AuthType);
9728 	CfgAddStr(f, "Username", a->Username);
9729 
9730 	switch (a->AuthType)
9731 	{
9732 	case CLIENT_AUTHTYPE_ANONYMOUS:
9733 		break;
9734 
9735 	case CLIENT_AUTHTYPE_PASSWORD:
9736 		CfgAddByte(f, "HashedPassword", a->HashedPassword, SHA1_SIZE);
9737 		break;
9738 
9739 	case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
9740 		b = EncryptPassword(a->PlainPassword);
9741 		CfgAddByte(f, "EncryptedPassword", b->Buf, b->Size);
9742 		FreeBuf(b);
9743 		break;
9744 
9745 	case CLIENT_AUTHTYPE_CERT:
9746 		if (a->ClientK != NULL && a->ClientX != NULL)
9747 		{
9748 			b = XToBuf(a->ClientX, false);
9749 			CfgAddByte(f, "ClientCert", b->Buf, b->Size);
9750 			FreeBuf(b);
9751 
9752 			b = KToBuf(a->ClientK, false, NULL);
9753 			CfgAddByte(f, "ClientKey", b->Buf, b->Size);
9754 			FreeBuf(b);
9755 		}
9756 		break;
9757 
9758 	case CLIENT_AUTHTYPE_SECURE:
9759 		CfgAddStr(f, "SecurePublicCertName", a->SecurePublicCertName);
9760 		CfgAddStr(f, "SecurePrivateKeyName", a->SecurePrivateKeyName);
9761 		break;
9762 
9763 	case CLIENT_AUTHTYPE_OPENSSLENGINE:
9764 		if (a->ClientX != NULL) {
9765 			b = XToBuf(a->ClientX, false);
9766 			CfgAddByte(f, "ClientCert", b->Buf, b->Size);
9767 			FreeBuf(b);
9768 		}
9769 		CfgAddStr(f, "OpensslEnginePrivateKeyName", a->OpensslEnginePrivateKeyName);
9770 		CfgAddStr(f, "OpensslEngineName", a->OpensslEngineName);
9771 	break;
9772 	}
9773 }
9774 
9775 // Write the client option
CiWriteClientOption(FOLDER * f,CLIENT_OPTION * o)9776 void CiWriteClientOption(FOLDER *f, CLIENT_OPTION *o)
9777 {
9778 	BUF *b;
9779 	// Validate arguments
9780 	if (f == NULL || o == NULL)
9781 	{
9782 		return;
9783 	}
9784 
9785 	CfgAddUniStr(f, "AccountName", o->AccountName);
9786 	CfgAddStr(f, "Hostname", o->Hostname);
9787 	CfgAddInt(f, "Port", o->Port);
9788 	CfgAddInt(f, "PortUDP", o->PortUDP);
9789 	CfgAddInt(f, "ProxyType", o->ProxyType);
9790 	CfgAddStr(f, "ProxyName", o->ProxyName);
9791 	CfgAddInt(f, "ProxyPort", o->ProxyPort);
9792 	CfgAddStr(f, "ProxyUsername", o->ProxyUsername);
9793 	b = EncryptPassword(o->ProxyPassword);
9794 	CfgAddByte(f, "ProxyPassword", b->Buf, b->Size);
9795 	FreeBuf(b);
9796 	CfgAddStr(f, "CustomHttpHeader", o->CustomHttpHeader);
9797 	CfgAddInt(f, "NumRetry", o->NumRetry);
9798 	CfgAddInt(f, "RetryInterval", o->RetryInterval);
9799 	CfgAddStr(f, "HubName", o->HubName);
9800 	CfgAddInt(f, "MaxConnection", o->MaxConnection);
9801 	CfgAddBool(f, "UseEncrypt", o->UseEncrypt);
9802 	CfgAddBool(f, "UseCompress", o->UseCompress);
9803 	CfgAddBool(f, "HalfConnection", o->HalfConnection);
9804 	CfgAddBool(f, "NoRoutingTracking", o->NoRoutingTracking);
9805 	CfgAddStr(f, "DeviceName", o->DeviceName);
9806 	CfgAddInt(f, "AdditionalConnectionInterval", o->AdditionalConnectionInterval);
9807 	CfgAddBool(f, "HideStatusWindow", o->HideStatusWindow);
9808 	CfgAddBool(f, "HideNicInfoWindow", o->HideNicInfoWindow);
9809 	CfgAddInt(f, "ConnectionDisconnectSpan", o->ConnectionDisconnectSpan);
9810 	CfgAddBool(f, "RequireMonitorMode", o->RequireMonitorMode);
9811 	CfgAddBool(f, "RequireBridgeRoutingMode", o->RequireBridgeRoutingMode);
9812 	CfgAddBool(f, "DisableQoS", o->DisableQoS);
9813 	CfgAddBool(f, "NoUdpAcceleration", o->NoUdpAcceleration);
9814 
9815 	if (o->FromAdminPack)
9816 	{
9817 		CfgAddBool(f, "FromAdminPack", o->FromAdminPack);
9818 	}
9819 
9820 	if (IsZero(o->HostUniqueKey, SHA1_SIZE) == false)
9821 	{
9822 		BUF *b = MemToBuf(o->HostUniqueKey, SHA1_SIZE);
9823 		CfgAddBuf(f, "HostUniqueKey", b);
9824 		FreeBuf(b);
9825 	}
9826 }
9827 
9828 // Decrypt the password
DecryptPassword(BUF * b)9829 char *DecryptPassword(BUF *b)
9830 {
9831 	char *str;
9832 	char *key = "EncryptPassword";
9833 	CRYPT *c;
9834 	// Validate arguments
9835 	if (b == NULL)
9836 	{
9837 		return CopyStr("");
9838 	}
9839 
9840 	str = ZeroMalloc(b->Size + 1);
9841 	c = NewCrypt(key, sizeof(key)); // NOTE by Daiyuu Nobori 2018-09-28: This is not a bug! Do not try to fix it!!
9842 	Encrypt(c, str, b->Buf, b->Size);
9843 	FreeCrypt(c);
9844 
9845 	str[b->Size] = 0;
9846 
9847 	return str;
9848 }
DecryptPassword2(BUF * b)9849 char *DecryptPassword2(BUF *b)
9850 {
9851 	char *str;
9852 	char *key = "EncryptPassword2";
9853 	CRYPT *c;
9854 	// Validate arguments
9855 	if (b == NULL)
9856 	{
9857 		return CopyStr("");
9858 	}
9859 
9860 	str = ZeroMalloc(b->Size + 1);
9861 	c = NewCrypt(key, StrLen(key));
9862 	Encrypt(c, str, b->Buf, b->Size);
9863 	FreeCrypt(c);
9864 
9865 	str[b->Size] = 0;
9866 
9867 	return str;
9868 }
9869 
9870 // Encrypt the password
EncryptPassword(char * password)9871 BUF *EncryptPassword(char *password)
9872 {
9873 	UCHAR *tmp;
9874 	UINT size;
9875 	char *key = "EncryptPassword";
9876 	CRYPT *c;
9877 	BUF *b;
9878 	// Validate arguments
9879 	if (password == NULL)
9880 	{
9881 		password = "";
9882 	}
9883 
9884 	size = StrLen(password) + 1;
9885 	tmp = ZeroMalloc(size);
9886 
9887 	c = NewCrypt(key, sizeof(key)); // NOTE by Daiyuu Nobori 2018-09-28: This is not a bug! Do not try to fix it!!
9888 	Encrypt(c, tmp, password, size - 1);
9889 	FreeCrypt(c);
9890 
9891 	b = NewBuf();
9892 	WriteBuf(b, tmp, size - 1);
9893 	SeekBuf(b, 0, 0);
9894 	Free(tmp);
9895 
9896 	return b;
9897 }
EncryptPassword2(char * password)9898 BUF *EncryptPassword2(char *password)
9899 {
9900 	UCHAR *tmp;
9901 	UINT size;
9902 	char *key = "EncryptPassword2";
9903 	CRYPT *c;
9904 	BUF *b;
9905 	// Validate arguments
9906 	if (password == NULL)
9907 	{
9908 		password = "";
9909 	}
9910 
9911 	size = StrLen(password) + 1;
9912 	tmp = ZeroMalloc(size);
9913 
9914 	c = NewCrypt(key, StrLen(key));
9915 	Encrypt(c, tmp, password, size - 1);
9916 	FreeCrypt(c);
9917 
9918 	b = NewBuf();
9919 	WriteBuf(b, tmp, size - 1);
9920 	SeekBuf(b, 0, 0);
9921 	Free(tmp);
9922 
9923 	return b;
9924 }
9925 
9926 // Write the account data
CiWriteAccountData(FOLDER * f,ACCOUNT * a)9927 void CiWriteAccountData(FOLDER *f, ACCOUNT *a)
9928 {
9929 	// Validate arguments
9930 	if (f == NULL || a == NULL)
9931 	{
9932 		return;
9933 	}
9934 
9935 	// Client Option
9936 	CiWriteClientOption(CfgCreateFolder(f, "ClientOption"), a->ClientOption);
9937 
9938 	// Client authentication data
9939 	CiWriteClientAuth(CfgCreateFolder(f, "ClientAuth"), a->ClientAuth);
9940 
9941 	// Startup account
9942 	CfgAddBool(f, "StartupAccount", a->StartupAccount);
9943 
9944 	// Server certificate check flag
9945 	CfgAddBool(f, "CheckServerCert", a->CheckServerCert);
9946 
9947 	// Retry on invalid server certificate flag
9948 	CfgAddBool(f, "RetryOnServerCert", a->RetryOnServerCert);
9949 
9950 	// Date and time
9951 	CfgAddInt64(f, "CreateDateTime", a->CreateDateTime);
9952 	CfgAddInt64(f, "UpdateDateTime", a->UpdateDateTime);
9953 	CfgAddInt64(f, "LastConnectDateTime", a->LastConnectDateTime);
9954 
9955 	// Server certificate body
9956 	if (a->ServerCert != NULL)
9957 	{
9958 		BUF *b = XToBuf(a->ServerCert, false);
9959 		if (b != NULL)
9960 		{
9961 			CfgAddBuf(f, "ServerCert", b);
9962 			FreeBuf(b);
9963 		}
9964 	}
9965 
9966 	// Shortcut Key
9967 	if (IsZero(a->ShortcutKey, SHA1_SIZE) == false)
9968 	{
9969 		char tmp[64];
9970 		BinToStr(tmp, sizeof(tmp), a->ShortcutKey, SHA1_SIZE);
9971 		CfgAddStr(f, "ShortcutKey", tmp);
9972 	}
9973 }
9974 
9975 // Write the account database
CiWriteAccountDatabase(CLIENT * c,FOLDER * f)9976 void CiWriteAccountDatabase(CLIENT *c, FOLDER *f)
9977 {
9978 	char name[MAX_SIZE];
9979 	// Validate arguments
9980 	if (c == NULL || f == NULL)
9981 	{
9982 		return;
9983 	}
9984 
9985 	LockList(c->AccountList);
9986 	{
9987 		UINT i;
9988 		for (i = 0;i < LIST_NUM(c->AccountList);i++)
9989 		{
9990 			ACCOUNT *a = LIST_DATA(c->AccountList, i);
9991 
9992 			{
9993 				Format(name, sizeof(name), "Account%u", i);
9994 				Lock(a->lock);
9995 				{
9996 					CiWriteAccountData(CfgCreateFolder(f, name), a);
9997 				}
9998 				Unlock(a->lock);
9999 			}
10000 		}
10001 	}
10002 	UnlockList(c->AccountList);
10003 }
10004 
10005 // Write the CA certificate
CiWriteCACert(CLIENT * c,FOLDER * f,X * x)10006 void CiWriteCACert(CLIENT *c, FOLDER *f, X *x)
10007 {
10008 	BUF *b;
10009 	// Validate arguments
10010 	if (c == NULL || f == NULL || x == NULL)
10011 	{
10012 		return;
10013 	}
10014 
10015 	b = XToBuf(x, false);
10016 	CfgAddBuf(f, "X509", b);
10017 	FreeBuf(b);
10018 }
10019 
10020 // Write a VLAN
CiWriteVLan(CLIENT * c,FOLDER * f,UNIX_VLAN * v)10021 void CiWriteVLan(CLIENT *c, FOLDER *f, UNIX_VLAN *v)
10022 {
10023 	char tmp[MAX_SIZE];
10024 	// Validate arguments
10025 	if (c == NULL || f == NULL || v == NULL)
10026 	{
10027 		return;
10028 	}
10029 
10030 	MacToStr(tmp, sizeof(tmp), v->MacAddress);
10031 	CfgAddStr(f, "MacAddress", tmp);
10032 	CfgAddBool(f, "Enabled", v->Enabled);
10033 }
10034 
10035 // Write a VLAN list
CiWriteVLanList(CLIENT * c,FOLDER * f)10036 void CiWriteVLanList(CLIENT *c, FOLDER *f)
10037 {
10038 	// Validate arguments
10039 	if (c == NULL || f == NULL)
10040 	{
10041 		return;
10042 	}
10043 
10044 	LockList(c->UnixVLanList);
10045 	{
10046 		UINT i;
10047 		for (i = 0;i < LIST_NUM(c->UnixVLanList);i++)
10048 		{
10049 			UNIX_VLAN *v = LIST_DATA(c->UnixVLanList, i);
10050 			CiWriteVLan(c, CfgCreateFolder(f, v->Name), v);
10051 		}
10052 	}
10053 	UnlockList(c->UnixVLanList);
10054 }
10055 
10056 // Write the CA list
CiWriteCAList(CLIENT * c,FOLDER * f)10057 void CiWriteCAList(CLIENT *c, FOLDER *f)
10058 {
10059 	CEDAR *cedar;
10060 	// Validate arguments
10061 	if (c == NULL || f == NULL)
10062 	{
10063 		return;
10064 	}
10065 
10066 	cedar = c->Cedar;
10067 
10068 	LockList(cedar->CaList);
10069 	{
10070 		UINT i;
10071 		for (i = 0;i < LIST_NUM(cedar->CaList);i++)
10072 		{
10073 			char tmp[MAX_SIZE];
10074 			X *x = LIST_DATA(cedar->CaList, i);
10075 			Format(tmp, sizeof(tmp), "Certificate%u", i);
10076 			CiWriteCACert(c, CfgCreateFolder(f, tmp), x);
10077 		}
10078 	}
10079 	UnlockList(cedar->CaList);
10080 }
10081 
10082 // Write the current settings to ROOT
CiWriteSettingToCfg(CLIENT * c,FOLDER * root)10083 void CiWriteSettingToCfg(CLIENT *c, FOLDER *root)
10084 {
10085 	FOLDER *cc;
10086 	FOLDER *account_database;
10087 	FOLDER *ca;
10088 	FOLDER *vlan;
10089 	FOLDER *cmsetting;
10090 	FOLDER *proxy;
10091 	// Validate arguments
10092 	if (c == NULL || root == NULL)
10093 	{
10094 		return;
10095 	}
10096 
10097 	cmsetting = CfgCreateFolder(root, "ClientManagerSetting");
10098 
10099 	// CLIENT_CONFIG
10100 	cc = CfgCreateFolder(root, "Config");
10101 	CiWriteClientConfig(cc, &c->Config);
10102 
10103 
10104 	// Eraser
10105 	CfgAddInt64(cc, "AutoDeleteCheckDiskFreeSpaceMin", c->Eraser->MinFreeSpace);
10106 
10107 	// Account Database
10108 	account_database = CfgCreateFolder(root, "AccountDatabase");
10109 	CiWriteAccountDatabase(c, account_database);
10110 
10111 	// Proxy
10112 	proxy = CfgCreateFolder(root, "CommonProxySetting");
10113 	if (proxy != NULL)
10114 	{
10115 		INTERNET_SETTING *t = &c->CommonProxySetting;
10116 		BUF *pw;
10117 
10118 		CfgAddInt(proxy, "ProxyType", t->ProxyType);
10119 		CfgAddStr(proxy, "ProxyHostName", t->ProxyHostName);
10120 		CfgAddInt(proxy, "ProxyPort", t->ProxyPort);
10121 		CfgAddStr(proxy, "ProxyUsername", t->ProxyUsername);
10122 
10123 		if (IsEmptyStr(t->ProxyPassword) == false)
10124 		{
10125 			pw = EncryptPassword(t->ProxyPassword);
10126 
10127 			CfgAddBuf(proxy, "ProxyPassword", pw);
10128 
10129 			FreeBuf(pw);
10130 		}
10131 
10132 		CfgAddStr(proxy, "CustomHttpHeader", t->CustomHttpHeader);
10133 	}
10134 
10135 	// CA
10136 	ca = CfgCreateFolder(root, "RootCA");
10137 	CiWriteCAList(c, ca);
10138 
10139 	// VLAN
10140 	if (OS_IS_UNIX(GetOsInfo()->OsType)
10141 #ifdef	NO_VLAN
10142 	    && GetOsInfo()->OsType != OSTYPE_MACOS_X
10143 #endif	// NO_VLAN
10144 	    )
10145 	{
10146 		vlan = CfgCreateFolder(root, "UnixVLan");
10147 		CiWriteVLanList(c, vlan);
10148 	}
10149 
10150 	// Password
10151 	CfgAddByte(root, "EncryptedPassword", c->EncryptedPassword, SHA1_SIZE);
10152 	CfgAddBool(root, "PasswordRemoteOnly", c->PasswordRemoteOnly);
10153 
10154 	// UseSecureDeviceId
10155 	CfgAddInt(root, "UseSecureDeviceId", c->UseSecureDeviceId);
10156 
10157 	// DontSavePassword
10158 	CfgAddBool(root, "DontSavePassword", c->DontSavePassword);
10159 
10160 	// UserAgent
10161 	if (c->Cedar != NULL)
10162 	{
10163 		CfgAddStr(root, "UserAgent", c->Cedar->HttpUserAgent);
10164 	}
10165 
10166 	if (cmsetting != NULL)
10167 	{
10168 		CM_SETTING *s = c->CmSetting;
10169 
10170 		CfgAddBool(cmsetting, "EasyMode", s->EasyMode);
10171 		CfgAddBool(cmsetting, "LockMode", s->LockMode);
10172 
10173 		if (IsZero(s->HashedPassword, sizeof(s->HashedPassword)) == false)
10174 		{
10175 			CfgAddByte(cmsetting, "HashedPassword", s->HashedPassword, sizeof(s->HashedPassword));
10176 		}
10177 	}
10178 }
10179 
10180 // Apply settings of Inner VPN Server
CiApplyInnerVPNServerConfig(CLIENT * c)10181 void CiApplyInnerVPNServerConfig(CLIENT *c)
10182 {
10183 }
10184 
10185 // Write to the configuration file
CiSaveConfigurationFile(CLIENT * c)10186 void CiSaveConfigurationFile(CLIENT *c)
10187 {
10188 	FOLDER *root;
10189 	// Validate arguments
10190 	if (c == NULL)
10191 	{
10192 		return;
10193 	}
10194 
10195 	// Do not save the configuration file
10196 	if(c->NoSaveConfig)
10197 	{
10198 		return;
10199 	}
10200 
10201 	root = CfgCreateFolder(NULL, TAG_ROOT);
10202 	CiWriteSettingToCfg(c, root);
10203 
10204 	SaveCfgRw(c->CfgRw, root);
10205 
10206 	CfgDeleteFolder(root);
10207 }
10208 
10209 // Set the CM_SETTING
CtSetCmSetting(CLIENT * c,CM_SETTING * s)10210 bool CtSetCmSetting(CLIENT *c, CM_SETTING *s)
10211 {
10212 	// Validate arguments
10213 	if (c == NULL || s == NULL)
10214 	{
10215 		return false;
10216 	}
10217 
10218 	Copy(c->CmSetting, s, sizeof(CM_SETTING));
10219 
10220 	CiSaveConfigurationFile(c);
10221 
10222 	return true;
10223 }
10224 
10225 // Get the CM_SETTING
CtGetCmSetting(CLIENT * c,CM_SETTING * s)10226 bool CtGetCmSetting(CLIENT *c, CM_SETTING *s)
10227 {
10228 	// Validate arguments
10229 	if (c == NULL || s == NULL)
10230 	{
10231 		return false;
10232 	}
10233 
10234 	Copy(s, c->CmSetting, sizeof(CM_SETTING));
10235 
10236 	return true;
10237 }
10238 
10239 // Get the client version
CtGetClientVersion(CLIENT * c,RPC_CLIENT_VERSION * ver)10240 bool CtGetClientVersion(CLIENT *c, RPC_CLIENT_VERSION *ver)
10241 {
10242 	// Validate arguments
10243 	if (ver == NULL)
10244 	{
10245 		return false;
10246 	}
10247 
10248 	Zero(ver, sizeof(RPC_CLIENT_VERSION));
10249 	StrCpy(ver->ClientProductName, sizeof(ver->ClientProductName), CEDAR_CLIENT_STR);
10250 	StrCpy(ver->ClientVersionString, sizeof(ver->ClientVersionString), c->Cedar->VerString);
10251 	StrCpy(ver->ClientBuildInfoString, sizeof(ver->ClientBuildInfoString), c->Cedar->BuildInfo);
10252 	ver->ClientVerInt = c->Cedar->Version;
10253 	ver->ClientBuildInt = c->Cedar->Build;
10254 
10255 
10256 #ifdef	OS_WIN32
10257 	ver->ProcessId = MsGetProcessId();
10258 	ver->IsVLanNameRegulated = MsIsInfCatalogRequired();
10259 
10260 #endif	// OS_WIN32
10261 
10262 	ver->OsType = GetOsInfo()->OsType;
10263 
10264 	return true;
10265 }
10266 
10267 // Creating a Client object
CiNewClient()10268 CLIENT *CiNewClient()
10269 {
10270 	CLIENT *c = ZeroMalloc(sizeof(CLIENT));
10271 
10272 //	StartCedarLog();
10273 
10274 	if (ci_active_sessions_lock == NULL)
10275 	{
10276 		ci_active_sessions_lock = NewLock();
10277 		ci_num_active_sessions = 0;
10278 	}
10279 
10280 #ifdef	OS_WIN32
10281 	if (MsIsWindows7())
10282 	{
10283 		c->MsSuspendHandler = MsNewSuspendHandler();
10284 	}
10285 #endif	// OS_WIN32
10286 
10287 
10288 	c->CmSetting = ZeroMalloc(sizeof(CM_SETTING));
10289 
10290 	c->SockList = NewSockList();
10291 
10292 	c->lock = NewLock();
10293 	c->lockForConnect = NewLock();
10294 	c->ref = NewRef();
10295 
10296 	c->Cedar = NewCedar(NULL, NULL);
10297 
10298 	c->Cedar->Client = c;
10299 
10300 	c->NotifyCancelList = NewList(NULL);
10301 
10302 	Sha0(c->EncryptedPassword, "", 0);
10303 
10304 #ifdef	OS_WIN32
10305 	c->GlobalPulse = MsOpenOrCreateGlobalPulse(CLIENT_GLOBAL_PULSE_NAME);
10306 #endif	// OS_WIN32
10307 
10308 	if (c->GlobalPulse != NULL)
10309 	{
10310 		c->PulseRecvThread = NewThread(CiPulseRecvThread, c);
10311 	}
10312 
10313 	CiLoadIniSettings(c);
10314 
10315 	// Log Settings
10316 	if(c->NoSaveLog == false)
10317 	{
10318 		MakeDir(CLIENT_LOG_DIR_NAME);
10319 		c->Logger = NewLog(CLIENT_LOG_DIR_NAME, CLIENT_LOG_PREFIX, LOG_SWITCH_DAY);
10320 	}
10321 
10322 	CLog(c, "L_LINE");
10323 	CLog(c, "LC_START_2", CEDAR_CLIENT_STR, c->Cedar->VerString);
10324 	CLog(c, "LC_START_3", c->Cedar->BuildInfo);
10325 	CLog(c, "LC_START_1");
10326 
10327 #ifdef	OS_WIN32
10328 	{
10329 		// Initialize the Win32 UI
10330 		wchar_t tmp[MAX_SIZE];
10331 		StrToUni(tmp, sizeof(tmp), CEDAR_CLIENT_STR);
10332 
10333 		InitWinUi(tmp, _SS("DEFAULT_FONT"), _II("DEFAULT_FONT_SIZE"));
10334 	}
10335 #endif	// OS_WIN32
10336 
10337 	// Initialize the settings
10338 	CiInitConfiguration(c);
10339 
10340 	// Raise the priority
10341 	OSSetHighPriority();
10342 
10343 	CiChangeAllVLanMacAddressIfMachineChanged(c);
10344 
10345 	CiChangeAllVLanMacAddressIfCleared(c);
10346 
10347 	// Initialize the internal VPN server
10348 	CiApplyInnerVPNServerConfig(c);
10349 
10350 	return c;
10351 }
10352 
10353 // Send a global pulse
CiSendGlobalPulse(CLIENT * c)10354 void CiSendGlobalPulse(CLIENT *c)
10355 {
10356 	// Validate arguments
10357 	if (c == NULL)
10358 	{
10359 		return;
10360 	}
10361 
10362 #ifdef	OS_WIN32
10363 	MsSendGlobalPulse(c->GlobalPulse);
10364 #endif	// OS_WIN32
10365 }
10366 
10367 // Pulse reception thread
CiPulseRecvThread(THREAD * thread,void * param)10368 void CiPulseRecvThread(THREAD *thread, void *param)
10369 {
10370 #ifdef	OS_WIN32
10371 	CLIENT *c = (CLIENT *)param;
10372 
10373 	if (c == NULL)
10374 	{
10375 		return;
10376 	}
10377 
10378 	while (true)
10379 	{
10380 		if (c->HaltPulseThread)
10381 		{
10382 			break;
10383 		}
10384 
10385 		MsWaitForGlobalPulse(c->GlobalPulse, INFINITE);
10386 
10387 		if (c->HaltPulseThread)
10388 		{
10389 			break;
10390 		}
10391 
10392 		CiNotifyInternal(c);
10393 	}
10394 #endif	// OS_WIN32
10395 }
10396 
10397 // Clean-up the client
CiCleanupClient(CLIENT * c)10398 void CiCleanupClient(CLIENT *c)
10399 {
10400 	// Validate arguments
10401 	if (c == NULL)
10402 	{
10403 		return;
10404 	}
10405 
10406 
10407 	// Release the settings
10408 	CiFreeConfiguration(c);
10409 
10410 #ifdef	OS_WIN32
10411 	// Release the Win32 UI
10412 	FreeWinUi();
10413 #endif	// OS_WIN32
10414 
10415 	CLog(c, "LC_END");
10416 	CLog(c, "L_LINE");
10417 	FreeEraser(c->Eraser);
10418 	FreeLog(c->Logger);
10419 	c->Logger = NULL;
10420 
10421 
10422 	ReleaseCedar(c->Cedar);
10423 
10424 	DeleteLock(c->lockForConnect);
10425 	DeleteLock(c->lock);
10426 
10427 	c->HaltPulseThread = true;
10428 
10429 	if (c->GlobalPulse != NULL)
10430 	{
10431 #ifdef	OS_WIN32
10432 		MsSendGlobalPulse(c->GlobalPulse);
10433 #endif	// OS_WIN32
10434 	}
10435 
10436 	if (c->PulseRecvThread != NULL)
10437 	{
10438 		WaitThread(c->PulseRecvThread, INFINITE);
10439 		ReleaseThread(c->PulseRecvThread);
10440 	}
10441 
10442 	if (c->GlobalPulse != NULL)
10443 	{
10444 #ifdef	OS_WIN32
10445 		MsCloseGlobalPulse(c->GlobalPulse);
10446 #endif	// OS_WIN32
10447 	}
10448 
10449 	ReleaseList(c->NotifyCancelList);
10450 
10451 	FreeSockList(c->SockList);
10452 
10453 	Free(c->CmSetting);
10454 
10455 
10456 #ifdef	OS_WIN32
10457 	if (c->MsSuspendHandler != NULL)
10458 	{
10459 		MsFreeSuspendHandler(c->MsSuspendHandler);
10460 	}
10461 #endif	// OS_WIN32
10462 
10463 	Free(c);
10464 
10465 	StopCedarLog();
10466 
10467 	if (ci_active_sessions_lock != NULL)
10468 	{
10469 		DeleteLock(ci_active_sessions_lock);
10470 		ci_active_sessions_lock = NULL;
10471 
10472 		ci_num_active_sessions = 0;
10473 	}
10474 }
10475 
10476 // Increment of the number of active sessions
CiIncrementNumActiveSessions()10477 void CiIncrementNumActiveSessions()
10478 {
10479 	Lock(ci_active_sessions_lock);
10480 	{
10481 		ci_num_active_sessions++;
10482 	}
10483 	Unlock(ci_active_sessions_lock);
10484 }
10485 
10486 // Decrement of the number of active sessions
CiDecrementNumActiveSessions()10487 void CiDecrementNumActiveSessions()
10488 {
10489 	Lock(ci_active_sessions_lock);
10490 	{
10491 		if (ci_num_active_sessions >= 1)
10492 		{
10493 			ci_num_active_sessions--;
10494 		}
10495 	}
10496 	Unlock(ci_active_sessions_lock);
10497 }
10498 
10499 // Release the client
CtReleaseClient(CLIENT * c)10500 void CtReleaseClient(CLIENT *c)
10501 {
10502 	// Validate arguments
10503 	if (c == NULL)
10504 	{
10505 		return;
10506 	}
10507 
10508 	if (Release(c->ref) == 0)
10509 	{
10510 		CiCleanupClient(c);
10511 	}
10512 }
10513 
10514 // Start the operation of the client program
CtStartClient()10515 void CtStartClient()
10516 {
10517 	UINT i;
10518 	LIST *o;
10519 	if (client != NULL)
10520 	{
10521 		// It is already in running
10522 		return;
10523 	}
10524 
10525 #ifdef	OS_WIN32
10526 	RegistWindowsFirewallAll();
10527 #endif
10528 
10529 	// Creating a client
10530 	client = CiNewClient();
10531 
10532 	// Start the Keep
10533 	CiInitKeep(client);
10534 
10535 	// Start the RPC server
10536 	CiStartRpcServer(client);
10537 
10538 	// Start the Saver
10539 	CiInitSaver(client);
10540 
10541 	// Start the startup connection
10542 	o = NewListFast(NULL);
10543 	LockList(client->AccountList);
10544 	{
10545 		for (i = 0;i < LIST_NUM(client->AccountList);i++)
10546 		{
10547 			ACCOUNT *a = LIST_DATA(client->AccountList, i);
10548 			Lock(a->lock);
10549 			{
10550 				if (a->StartupAccount)
10551 				{
10552 					Add(o, CopyUniStr(a->ClientOption->AccountName));
10553 				}
10554 			}
10555 			Unlock(a->lock);
10556 		}
10557 	}
10558 	UnlockList(client->AccountList);
10559 
10560 	for (i = 0;i < LIST_NUM(o);i++)
10561 	{
10562 		wchar_t *s = LIST_DATA(o, i);
10563 		RPC_CLIENT_CONNECT c;
10564 		Zero(&c, sizeof(c));
10565 		UniStrCpy(c.AccountName, sizeof(c.AccountName), s);
10566 		CtConnect(client, &c);
10567 		Free(s);
10568 	}
10569 	ReleaseList(o);
10570 }
10571 
10572 // Stop the operation of the client program
CtStopClient()10573 void CtStopClient()
10574 {
10575 	UINT i, num;
10576 	ACCOUNT **account_list;
10577 	if (client == NULL)
10578 	{
10579 		// It is not running yet
10580 		return;
10581 	}
10582 
10583 	// Halting flag
10584 	client->Halt = true;
10585 
10586 	// Disconnect all the RPC
10587 	CiStopRpcServer(client);
10588 
10589 	// Exit the client notification service
10590 	CncExit();
10591 
10592 	// Exit the Keep
10593 	CiFreeKeep(client);
10594 
10595 	// Disconnect all accounts connected
10596 	LockList(client->AccountList);
10597 	{
10598 		num = LIST_NUM(client->AccountList);
10599 		account_list = ToArray(client->AccountList);
10600 	}
10601 	UnlockList(client->AccountList);
10602 
10603 	for (i = 0;i < num;i++)
10604 	{
10605 		ACCOUNT *a = account_list[i];
10606 		SESSION *s = NULL;
10607 
10608 		Lock(a->lock);
10609 		{
10610 			if (a->ClientSession != NULL)
10611 			{
10612 				s = a->ClientSession;
10613 				AddRef(s->ref);
10614 			}
10615 		}
10616 		Unlock(a->lock);
10617 
10618 		if (s != NULL)
10619 		{
10620 			StopSession(s);
10621 			ReleaseSession(s);
10622 			Lock(a->lock);
10623 			{
10624 				if (a->ClientSession != NULL)
10625 				{
10626 					ReleaseSession(a->ClientSession);
10627 					a->ClientSession = NULL;
10628 				}
10629 			}
10630 			Unlock(a->lock);
10631 		}
10632 	}
10633 
10634 	Free(account_list);
10635 
10636 	// Stop the Saver
10637 	CiFreeSaver(client);
10638 
10639 	// Release the client
10640 	CtReleaseClient(client);
10641 	client = NULL;
10642 }
10643 
10644 // Client status indicator
CiClientStatusPrinter(SESSION * s,wchar_t * status)10645 void CiClientStatusPrinter(SESSION *s, wchar_t *status)
10646 {
10647 #ifdef	OS_WIN32
10648 	ACCOUNT *a;
10649 	// Validate arguments
10650 	if (s == NULL || status == NULL)
10651 	{
10652 		return;
10653 	}
10654 
10655 	a = s->Account;
10656 	if (a == NULL)
10657 	{
10658 		return;
10659 	}
10660 
10661 	if (UniStrCmpi(status, L"init") == 0)
10662 	{
10663 		if (a->StatusWindow == NULL && s->Win32HideConnectWindow == false)
10664 		{
10665 			a->StatusWindow = CncStatusPrinterWindowStart(s);
10666 		}
10667 	}
10668 	else if (UniStrCmpi(status, L"free") == 0)
10669 	{
10670 		if (a->StatusWindow != NULL)
10671 		{
10672 			CncStatusPrinterWindowStop(a->StatusWindow);
10673 			a->StatusWindow = NULL;
10674 		}
10675 	}
10676 	else
10677 	{
10678 		if (a->StatusWindow != NULL)
10679 		{
10680 			CncStatusPrinterWindowPrint(a->StatusWindow, status);
10681 		}
10682 	}
10683 #else	// OS_WIN32
10684 	UniPrint(L"Status: %s\n", status);
10685 #endif	// OS_WIN32
10686 }
10687 
10688 
10689