1 // SoftEther VPN Source Code - Stable Edition Repository
2 // Cedar Communication Module
3 //
4 // SoftEther VPN Server, Client and Bridge are free software under the Apache License, Version 2.0.
5 //
6 // Copyright (c) Daiyuu Nobori.
7 // Copyright (c) SoftEther VPN Project, University of Tsukuba, Japan.
8 // Copyright (c) SoftEther Corporation.
9 // Copyright (c) all contributors on SoftEther VPN project in GitHub.
10 //
11 // All Rights Reserved.
12 //
13 // http://www.softether.org/
14 //
15 // This stable branch is officially managed by Daiyuu Nobori, the owner of SoftEther VPN Project.
16 // Pull requests should be sent to the Developer Edition Master Repository on https://github.com/SoftEtherVPN/SoftEtherVPN
17 //
18 // License: The Apache License, Version 2.0
19 // https://www.apache.org/licenses/LICENSE-2.0
20 //
21 // DISCLAIMER
22 // ==========
23 //
24 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
25 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
26 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
27 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
28 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
29 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
30 // SOFTWARE.
31 //
32 // THIS SOFTWARE IS DEVELOPED IN JAPAN, AND DISTRIBUTED FROM JAPAN, UNDER
33 // JAPANESE LAWS. YOU MUST AGREE IN ADVANCE TO USE, COPY, MODIFY, MERGE, PUBLISH,
34 // DISTRIBUTE, SUBLICENSE, AND/OR SELL COPIES OF THIS SOFTWARE, THAT ANY
35 // JURIDICAL DISPUTES WHICH ARE CONCERNED TO THIS SOFTWARE OR ITS CONTENTS,
36 // AGAINST US (SOFTETHER PROJECT, SOFTETHER CORPORATION, DAIYUU NOBORI OR OTHER
37 // SUPPLIERS), OR ANY JURIDICAL DISPUTES AGAINST US WHICH ARE CAUSED BY ANY KIND
38 // OF USING, COPYING, MODIFYING, MERGING, PUBLISHING, DISTRIBUTING, SUBLICENSING,
39 // AND/OR SELLING COPIES OF THIS SOFTWARE SHALL BE REGARDED AS BE CONSTRUED AND
40 // CONTROLLED BY JAPANESE LAWS, AND YOU MUST FURTHER CONSENT TO EXCLUSIVE
41 // JURISDICTION AND VENUE IN THE COURTS SITTING IN TOKYO, JAPAN. YOU MUST WAIVE
42 // ALL DEFENSES OF LACK OF PERSONAL JURISDICTION AND FORUM NON CONVENIENS.
43 // PROCESS MAY BE SERVED ON EITHER PARTY IN THE MANNER AUTHORIZED BY APPLICABLE
44 // LAW OR COURT RULE.
45 //
46 // USE ONLY IN JAPAN. DO NOT USE THIS SOFTWARE IN ANOTHER COUNTRY UNLESS YOU HAVE
47 // A CONFIRMATION THAT THIS SOFTWARE DOES NOT VIOLATE ANY CRIMINAL LAWS OR CIVIL
48 // RIGHTS IN THAT PARTICULAR COUNTRY. USING THIS SOFTWARE IN OTHER COUNTRIES IS
49 // COMPLETELY AT YOUR OWN RISK. THE SOFTETHER VPN PROJECT HAS DEVELOPED AND
50 // DISTRIBUTED THIS SOFTWARE TO COMPLY ONLY WITH THE JAPANESE LAWS AND EXISTING
51 // CIVIL RIGHTS INCLUDING PATENTS WHICH ARE SUBJECTS APPLY IN JAPAN. OTHER
52 // COUNTRIES' LAWS OR CIVIL RIGHTS ARE NONE OF OUR CONCERNS NOR RESPONSIBILITIES.
53 // WE HAVE NEVER INVESTIGATED ANY CRIMINAL REGULATIONS, CIVIL LAWS OR
54 // INTELLECTUAL PROPERTY RIGHTS INCLUDING PATENTS IN ANY OF OTHER 200+ COUNTRIES
55 // AND TERRITORIES. BY NATURE, THERE ARE 200+ REGIONS IN THE WORLD, WITH
56 // DIFFERENT LAWS. IT IS IMPOSSIBLE TO VERIFY EVERY COUNTRIES' LAWS, REGULATIONS
57 // AND CIVIL RIGHTS TO MAKE THE SOFTWARE COMPLY WITH ALL COUNTRIES' LAWS BY THE
58 // PROJECT. EVEN IF YOU WILL BE SUED BY A PRIVATE ENTITY OR BE DAMAGED BY A
59 // PUBLIC SERVANT IN YOUR COUNTRY, THE DEVELOPERS OF THIS SOFTWARE WILL NEVER BE
60 // LIABLE TO RECOVER OR COMPENSATE SUCH DAMAGES, CRIMINAL OR CIVIL
61 // RESPONSIBILITIES. NOTE THAT THIS LINE IS NOT LICENSE RESTRICTION BUT JUST A
62 // STATEMENT FOR WARNING AND DISCLAIMER.
63 //
64 // READ AND UNDERSTAND THE 'WARNING.TXT' FILE BEFORE USING THIS SOFTWARE.
65 // SOME SOFTWARE PROGRAMS FROM THIRD PARTIES ARE INCLUDED ON THIS SOFTWARE WITH
66 // LICENSE CONDITIONS WHICH ARE DESCRIBED ON THE 'THIRD_PARTY.TXT' FILE.
67 //
68 //
69 // SOURCE CODE CONTRIBUTION
70 // ------------------------
71 //
72 // Your contribution to SoftEther VPN Project is much appreciated.
73 // Please send patches to us through GitHub.
74 // Read the SoftEther VPN Patch Acceptance Policy in advance:
75 // http://www.softether.org/5-download/src/9.patch
76 //
77 //
78 // DEAR SECURITY EXPERTS
79 // ---------------------
80 //
81 // If you find a bug or a security vulnerability please kindly inform us
82 // about the problem immediately so that we can fix the security problem
83 // to protect a lot of users around the world as soon as possible.
84 //
85 // Our e-mail address for security reports is:
86 // softether-vpn-security [at] softether.org
87 //
88 // Please note that the above e-mail address is not a technical support
89 // inquiry address. If you need technical assistance, please visit
90 // http://www.softether.org/ and ask your question on the users forum.
91 //
92 // Thank you for your cooperation.
93 //
94 //
95 // NO MEMORY OR RESOURCE LEAKS
96 // ---------------------------
97 //
98 // The memory-leaks and resource-leaks verification under the stress
99 // test has been passed before release this source code.
100 
101 
102 // Session.c
103 // Session Manager
104 
105 #include "CedarPch.h"
106 
107 // Main routine of the session
SessionMain(SESSION * s)108 void SessionMain(SESSION *s)
109 {
110 	CONNECTION *c;
111 	POLICY *policy;
112 	UINT64 now;
113 	UINT i = 0;
114 	PACKET_ADAPTER *pa;
115 	bool pa_inited = false;
116 	UINT packet_size;
117 	void *packet;
118 	bool packet_put;
119 	bool pa_fail = false;
120 	UINT test = 0;
121 	bool update_hub_last_comm = false;
122 	UINT err = ERR_SESSION_TIMEOUT;
123 	UINT64 next_black_list_check = 0;
124 	UINT64 next_update_hub_last_comm = 0;
125 	UINT64 auto_disconnect_tick = 0;
126 	bool block_all_packets = false;
127 	UINT64 next_check_block_all_packets = 0;
128 	TRAFFIC t;
129 	SOCK *msgdlg_sock = NULL;
130 	SOCK *nicinfo_sock = NULL;
131 	bool is_server_session = false;
132 	bool lock_receive_blocks_queue = false;
133 	// Validate arguments
134 	if (s == NULL)
135 	{
136 		return;
137 	}
138 
139 	Debug("SessionMain: %s\n", s->Name);
140 
141 	Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
142 
143 	// Generate a string from the session key
144 	BinToStr(s->SessionKeyStr, sizeof(s->SessionKeyStr), s->SessionKey, sizeof(s->SessionKey));
145 
146 	// Reset the number of retries
147 	s->CurrentRetryCount = 0;
148 	s->ConnectSucceed = true;
149 	s->SessionTimeOuted = false;
150 	s->NumDisconnected = 0;
151 
152 	c = s->Connection;
153 	policy = s->Policy;
154 
155 	// Initialize the packet adapter
156 #ifdef	OS_WIN32
157 	if (s->IsVPNClientAndVLAN_Win32)
158 	{
159 		MsBeginVLanCard();
160 
161 		if (MsIsVLanCardShouldStop())
162 		{
163 			err = ERR_SUSPENDING;
164 			goto CLEANUP;
165 		}
166 	}
167 #endif	// OS_WIN32
168 
169 	pa = s->PacketAdapter;
170 	if (pa->Init(s) == false)
171 	{
172 		// Initialization Failed
173 		if (s->VLanDeviceErrorCount >= 2)
174 		{
175 			s->ForceStopFlag = true;
176 		}
177 		else
178 		{
179 			s->VLanDeviceErrorCount++;
180 		}
181 		err = ERR_DEVICE_DRIVER_ERROR;
182 		goto CLEANUP;
183 	}
184 	pa_inited = true;
185 
186 	if (s->BridgeMode == false)
187 	{
188 		s->Cancel2 = pa->GetCancel(s);
189 	}
190 	else
191 	{
192 		CANCEL *c = pa->GetCancel(s);
193 		CANCEL *old = s->Cancel1;
194 		s->Cancel1 = c;
195 		ReleaseCancel(old);
196 	}
197 
198 	s->RetryFlag = false;
199 
200 	s->LastCommTime = Tick64();
201 	if (s->ServerMode == false)
202 	{
203 		s->NextConnectionTime = Tick64() + (UINT64)((UINT64)s->ClientOption->AdditionalConnectionInterval * (UINT64)1000);
204 	}
205 
206 	s->NumConnectionsEatablished++;
207 	s->CurrentConnectionEstablishTime = Tick64();
208 	if (s->FirstConnectionEstablisiedTime == 0)
209 	{
210 		s->FirstConnectionEstablisiedTime = Tick64();
211 	}
212 
213 	if (s->ServerMode == false && s->Cedar->Client != NULL)
214 	{
215 		if (s->Policy != NULL)
216 		{
217 			if (s->Policy->AutoDisconnect)
218 			{
219 				auto_disconnect_tick = s->CurrentConnectionEstablishTime +
220 					(UINT64)s->Policy->AutoDisconnect * 1000ULL;
221 			}
222 		}
223 	}
224 
225 	s->LastIncrementTraffic = Tick64();
226 
227 	c->Err = ERR_SESSION_TIMEOUT;
228 	s->VLanDeviceErrorCount = 0;
229 
230 	s->LastTryAddConnectTime = Tick64();
231 
232 	Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
233 
234 	if (policy != NULL)
235 	{
236 		// Determine the mode by referencing the contents of the policy
237 		if (policy->MonitorPort)
238 		{
239 			s->IsMonitorMode = true;
240 		}
241 
242 		if (policy->NoRouting == false || policy->NoBridge == false)
243 		{
244 			s->IsBridgeMode = true;
245 		}
246 	}
247 
248 	if (s->ServerMode == false && s->Cedar->Client != NULL)
249 	{
250 		if (IsEmptyUniStr(s->Client_Message) == false)
251 		{
252 			UI_MSG_DLG dlg;
253 
254 			Zero(&dlg, sizeof(dlg));
255 			if (s->ClientOption != NULL)
256 			{
257 				StrCpy(dlg.HubName, sizeof(dlg.HubName), s->ClientOption->HubName);
258 				StrCpy(dlg.ServerName, sizeof(dlg.ServerName), s->ClientOption->Hostname);
259 			}
260 
261 			dlg.Msg = s->Client_Message;
262 
263 			msgdlg_sock = CncMsgDlg(&dlg);
264 		}
265 
266 		if (s->Win32HideNicInfoWindow == false)
267 		{
268 			UI_NICINFO info;
269 
270 			Zero(&info, sizeof(info));
271 			if (s->ClientOption != NULL)
272 			{
273 				StrCpy(info.NicName, sizeof(info.NicName), s->ClientOption->DeviceName);
274 				UniStrCpy(info.AccountName, sizeof(info.AccountName), s->ClientOption->AccountName);
275 			}
276 
277 			nicinfo_sock = CncNicInfo(&info);
278 		}
279 	}
280 
281 	is_server_session = s->ServerMode;
282 
283 	lock_receive_blocks_queue = s->LinkModeServer;
284 
285 	now = Tick64();
286 
287 	while (true)
288 	{
289 		Zero(&t, sizeof(t));
290 
291 
292 		if (next_update_hub_last_comm == 0 ||
293 			(next_update_hub_last_comm <= now))
294 		{
295 			next_update_hub_last_comm = now + 1000;
296 
297 			if (s->Hub != NULL)
298 			{
299 				if (update_hub_last_comm)
300 				{
301 					Lock(s->Hub->lock);
302 					{
303 						s->Hub->LastCommTime = SystemTime64();
304 					}
305 					Unlock(s->Hub->lock);
306 
307 					update_hub_last_comm = false;
308 				}
309 			}
310 		}
311 
312 
313 		if (is_server_session && s->LinkModeServer == false && s->SecureNATMode == false && s->BridgeMode == false && s->L3SwitchMode == false)
314 		{
315 			if (s->Hub != NULL && s->Hub->ForceDisableComm)
316 			{
317 				// Disconnect the session forcibly because the ForceDisableComm flag is set
318 				err = ERR_SERVER_CANT_ACCEPT;
319 				pa_fail = true;
320 			}
321 		}
322 
323 		if (s->InProcMode)
324 		{
325 			if (c->TubeSock == NULL || IsTubeConnected(c->TubeSock->SendTube) == false || IsTubeConnected(c->TubeSock->RecvTube) == false)
326 			{
327 				// Disconnection occurs in the in-process mode
328 				err = ERR_DISCONNECTED;
329 				pa_fail = true;
330 			}
331 		}
332 
333 		if (s->IsRUDPSession)
334 		{
335 			if (s->NumDisconnected >= 1 && s->EnableUdpRecovery == false)
336 			{
337 				// Disconnection occurs in the R-UDP session (UDP recovery is invalid)
338 				err = ERR_DISCONNECTED;
339 				pa_fail = true;
340 			}
341 		}
342 
343 		// Chance of additional connection
344 		if (is_server_session == false)
345 		{
346 			if (GetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT) == false)
347 			{
348 				ClientAdditionalConnectChance(s);
349 			}
350 		}
351 
352 		// Receive a block
353 		ConnectionReceive(c, s->Cancel1, s->Cancel2);
354 
355 		// Get the current time
356 		now = Tick64();
357 
358 		if (s->UseUdpAcceleration && s->UdpAccel != NULL && s->UdpAccel->FatalError)
359 		{
360 			// A serious error occurs during sending any data on UDP socket
361 			// in the case of using UDP acceleration function
362 			err = ERR_DISCONNECTED;
363 			pa_fail = true;
364 		}
365 
366 #ifdef	OS_WIN32
367 		if (s->IsVPNClientAndVLAN_Win32)
368 		{
369 			if (MsIsVLanCardShouldStop())
370 			{
371 				// System is suspending
372 				err = ERR_SUSPENDING;
373 				pa_fail = true;
374 			}
375 		}
376 #endif	// OS_WIN32
377 
378 		// Pass the received block to the PacketAdapter
379 		if (lock_receive_blocks_queue)
380 		{
381 			LockQueue(c->ReceivedBlocks);
382 		}
383 		{
384 			BLOCK *b;
385 			packet_put = false;
386 			while (true)
387 			{
388 				b = GetNext(c->ReceivedBlocks);
389 				if (b == NULL)
390 				{
391 					break;
392 				}
393 
394 				PROBE_DATA2("GetNext", b->Buf, b->Size);
395 
396 				update_hub_last_comm = true;
397 
398 				if (b->Size >= 14)
399 				{
400 					if (b->Buf[0] & 0x01)
401 					{
402 						if (is_server_session == false)
403 						{
404 							t.Recv.BroadcastCount++;
405 							t.Recv.BroadcastBytes += (UINT64)b->Size;
406 						}
407 						else
408 						{
409 							t.Send.BroadcastCount++;
410 							t.Send.BroadcastBytes += (UINT64)b->Size;
411 						}
412 					}
413 					else
414 					{
415 						if (is_server_session == false)
416 						{
417 							t.Recv.UnicastCount++;
418 							t.Recv.UnicastBytes += (UINT64)b->Size;
419 						}
420 						else
421 						{
422 							t.Send.UnicastCount++;
423 							t.Send.UnicastBytes += (UINT64)b->Size;
424 						}
425 					}
426 				}
427 
428 				packet_put = true;
429 				PROBE_DATA2("pa->PutPacket", b->Buf, b->Size);
430 				if (pa->PutPacket(s, b->Buf, b->Size) == false)
431 				{
432 					pa_fail = true;
433 					err = ERR_DEVICE_DRIVER_ERROR;
434 					Free(b->Buf);
435 					Debug("  Error: pa->PutPacket(Packet) Failed.\n");
436 				}
437 				Free(b);
438 			}
439 
440 			if (true /* packet_put || is_server_session 2014.7.23 for optimizing */)
441 			{
442 				PROBE_DATA2("pa->PutPacket", NULL, 0);
443 				if (pa->PutPacket(s, NULL, 0) == false)
444 				{
445 					Debug("  Error: pa->PutPacket(NULL) Failed.\n");
446 					pa_fail = true;
447 					err = ERR_DEVICE_DRIVER_ERROR;
448 				}
449 			}
450 		}
451 		if (lock_receive_blocks_queue)
452 		{
453 			UnlockQueue(c->ReceivedBlocks);
454 		}
455 
456 		// Add the packet to be transmitted to SendBlocks by acquiring from PacketAdapter
457 		{
458 			UINT i, max_num = MAX_SEND_SOCKET_QUEUE_NUM;
459 			i = 0;
460 			while (packet_size = pa->GetNextPacket(s, &packet))
461 			{
462 				BLOCK *b;
463 				if (packet_size == INFINITE)
464 				{
465 					err = ERR_DEVICE_DRIVER_ERROR;
466 					pa_fail = true;
467 					Debug("  Error: pa->GetNextPacket() Failed.\n");
468 					break;
469 				}
470 
471 				update_hub_last_comm = true;
472 
473 				if ((c->CurrentSendQueueSize > MAX_BUFFERING_PACKET_SIZE) ||
474 					block_all_packets)
475 				{
476 //					WHERE;
477 					// Discard because it exceeded the buffer size limit
478 					Free(packet);
479 				}
480 				else
481 				{
482 					bool priority;
483 					QUEUE *q = NULL;
484 					// Buffering
485 					if (packet_size >= 14)
486 					{
487 						UCHAR *buf = (UCHAR *)packet;
488 						if (buf[0] & 0x01)
489 						{
490 							if (is_server_session == false)
491 							{
492 								t.Send.BroadcastCount++;
493 								t.Send.BroadcastBytes += (UINT64)packet_size;
494 							}
495 							else
496 							{
497 								t.Recv.BroadcastCount++;
498 								t.Recv.BroadcastBytes += (UINT64)packet_size;
499 							}
500 						}
501 						else
502 						{
503 							if (is_server_session == false)
504 							{
505 								t.Send.UnicastCount++;
506 								t.Send.UnicastBytes += (UINT64)packet_size;
507 							}
508 							else
509 							{
510 								t.Recv.UnicastCount++;
511 								t.Recv.UnicastBytes += (UINT64)packet_size;
512 							}
513 						}
514 					}
515 					priority = IsPriorityHighestPacketForQoS(packet, packet_size);
516 
517 					b = NewBlock(packet, packet_size, s->UseCompress ? 1 : 0);
518 					b->PriorityQoS = priority;
519 
520 					if (b->PriorityQoS && c->Protocol == CONNECTION_TCP && s->QoS)
521 					{
522 						q = c->SendBlocks2;
523 					}
524 					else
525 					{
526 						q = c->SendBlocks;
527 					}
528 
529 					if (q->num_item > MAX_STORED_QUEUE_NUM)
530 					{
531 						q = NULL;
532 					}
533 
534 					if (q != NULL)
535 					{
536 						c->CurrentSendQueueSize += b->Size;
537 						InsertQueue(q, b);
538 					}
539 					else
540 					{
541 						FreeBlock(b);
542 					}
543 				}
544 
545 				if ((i % 16) == 0)
546 				{
547 					int diff = ((int)c->CurrentSendQueueSize) - ((int)c->LastPacketQueueSize);
548 					CedarAddCurrentTcpQueueSize(c->Cedar, diff);
549 					c->LastPacketQueueSize = c->CurrentSendQueueSize;
550 				}
551 
552 				i++;
553 				if (i >= max_num)
554 				{
555 					break;
556 				}
557 			}
558 		}
559 
560 		AddTrafficForSession(s, &t);
561 
562 		if (true)
563 		{
564 			int diff = ((int)c->CurrentSendQueueSize) - ((int)c->LastPacketQueueSize);
565 			CedarAddCurrentTcpQueueSize(c->Cedar, diff);
566 			c->LastPacketQueueSize = c->CurrentSendQueueSize;
567 		}
568 
569 		now = Tick64();
570 
571 		// Send a block
572 		ConnectionSend(c, now);
573 
574 		// Determine the automatic disconnection
575 		if (auto_disconnect_tick != 0 && auto_disconnect_tick <= now)
576 		{
577 			err = ERR_AUTO_DISCONNECTED;
578 			s->CurrentRetryCount = INFINITE;
579 			break;
580 		}
581 
582 		// Stop determination
583 		if (s->Halt)
584 		{
585 			if (s->ForceStopFlag)
586 			{
587 				err = ERR_USER_CANCEL;
588 			}
589 			break;
590 		}
591 
592 		// Increments the number of logins for user object and Virtual HUB object.
593 		// (It's incremented only if the time 30 seconds passed after connection.
594 		// If not do this, it will be incremented on DoS attacks or any error.)
595 		if (s->NumLoginIncrementTick != 0 && s->NumLoginIncrementTick <= now)
596 		{
597 			s->NumLoginIncrementTick = 0;
598 
599 			if (s->NumLoginIncrementHubObject != NULL)
600 			{
601 				s->NumLoginIncrementHubObject->NumLogin++;
602 			}
603 
604 			if (s->NumLoginIncrementUserObject != NULL)
605 			{
606 				s->NumLoginIncrementUserObject->NumLogin++;
607 			}
608 		}
609 
610 		if (is_server_session)
611 		{
612 			HUB *hub;
613 
614 			// Update of traffic data of the user
615 			if ((s->LastIncrementTraffic + INCREMENT_TRAFFIC_INTERVAL) <= now)
616 			{
617 				IncrementUserTraffic(s->Hub, s->UserNameReal, s);
618 				s->LastIncrementTraffic = now;
619 			}
620 
621 			hub = s->Hub;
622 
623 			if (hub != NULL)
624 			{
625 				if ((hub->LastIncrementTraffic + INCREMENT_TRAFFIC_INTERVAL) <= now)
626 				{
627 					hub->LastIncrementTraffic = now;
628 					IncrementHubTraffic(s->Hub);
629 				}
630 			}
631 		}
632 
633 		if (s->LinkModeServer == false && s->SecureNATMode == false && s->BridgeMode == false && s->L3SwitchMode == false && s->InProcMode == false)
634 		{
635 			bool timeouted = false;
636 
637 			if ((now > s->LastCommTime) && ((now - s->LastCommTime) >= ((UINT64)s->Timeout)))
638 			{
639 				// When communication is not possible for the predetermined time
640 				timeouted = true;
641 				WHERE;
642 			}
643 
644 			if (c->Protocol == CONNECTION_TCP)
645 			{
646 				if (GetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT))
647 				{
648 					UINT num_tcp_connections = Count(c->CurrentNumConnection);
649 
650 					if (num_tcp_connections == 0)
651 					{
652 						// All TCP connections are disconnected.
653 						// Terminate the session immediately.
654 						timeouted = true;
655 					}
656 				}
657 			}
658 
659 			if (is_server_session == false && s->ClientOption != NULL && s->ClientOption->ConnectionDisconnectSpan == 0)
660 			{
661 				if (LIST_NUM(s->Connection->Tcp->TcpSockList) < s->MaxConnection)
662 				{
663 					if ((s->LastTryAddConnectTime +
664 						(UINT64)(s->ClientOption->AdditionalConnectionInterval * 1000 * 2 + CONNECTING_TIMEOUT * 2))
665 						<= Tick64())
666 					{
667 						if (s->IsRUDPSession == false ||  LIST_NUM(s->Connection->Tcp->TcpSockList) == 0)
668 						{
669 							timeouted = true;
670 							WHERE;
671 						}
672 					}
673 				}
674 			}
675 
676 			if (timeouted)
677 			{
678 				// Timeout occurs
679 				Debug("** Session Timeouted.\n");
680 				s->SessionTimeOuted = true;
681 				err = ERR_SESSION_TIMEOUT;
682 			}
683 		}
684 
685 		// Time-out decision
686 		if (pa_fail || s->SessionTimeOuted)
687 		{
688 			s->Halt = true;
689 			s->RetryFlag = true;	// Retry flag
690 			break;
691 		}
692 	}
693 
694 CLEANUP:
695 	Debug("Session %s Finishing...\n", s->Name);
696 
697 	// Remove from the session list of the HUB
698 	if (s->ServerMode)
699 	{
700 		// Update the user information
701 		IncrementUserTraffic(s->Hub, s->UserNameReal, s);
702 
703 		DelSession(s->Hub, s);
704 	}
705 
706 	s->ConnectSucceed = false;
707 	Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
708 
709 	if (s->Connection)
710 	{
711 		int diff =  -((int)s->Connection->LastTcpQueueSize);
712 		s->Connection->LastTcpQueueSize = 0;
713 		s->Connection->Halt = true;
714 		CedarAddCurrentTcpQueueSize(s->Cedar, diff);
715 
716 		diff = ((int)c->CurrentSendQueueSize) - ((int)c->LastPacketQueueSize);
717 		CedarAddCurrentTcpQueueSize(c->Cedar, diff);
718 		c->LastPacketQueueSize = c->CurrentSendQueueSize;
719 	}
720 
721 	// Release the packet adapter
722 	if (pa_inited)
723 	{
724 		pa->Free(s);
725 	}
726 
727 #ifdef	OS_WIN32
728 	if (s->IsVPNClientAndVLAN_Win32)
729 	{
730 		MsEndVLanCard();
731 	}
732 #endif	// OS_WIN32
733 
734 	if (s->ServerMode == false)
735 	{
736 		// Cancel to make all additional connection
737 		StopAllAdditionalConnectThread(s->Connection);
738 	}
739 
740 	if (s->BridgeMode)
741 	{
742 		// Terminate the bridge
743 		if (s->Bridge->Active)
744 		{
745 			CloseEth(s->Bridge->Eth);
746 			s->Bridge->Eth = NULL;
747 		}
748 	}
749 
750 	if (s->Cancel2 != NULL)
751 	{
752 		// Release the Cancel 2
753 		ReleaseCancel(s->Cancel2);
754 		s->Cancel2 = NULL;
755 	}
756 
757 	// Terminate the connection
758 	EndTunnelingMode(c);
759 
760 	if (nicinfo_sock != NULL)
761 	{
762 		CncNicInfoFree(nicinfo_sock);
763 	}
764 
765 	if (msgdlg_sock != NULL)
766 	{
767 		CndMsgDlgFree(msgdlg_sock);
768 	}
769 
770 	c->Err = err;
771 }
772 
773 // Get the time for the next delayed packet
GetNextDelayedPacketTickDiff(SESSION * s)774 UINT GetNextDelayedPacketTickDiff(SESSION *s)
775 {
776 	UINT i;
777 	UINT ret = 0x7fffffff;
778 	UINT64 now;
779 	// Validate arguments
780 	if (s == NULL)
781 	{
782 		return 0;
783 	}
784 
785 	if (LIST_NUM(s->DelayedPacketList) >= 1)
786 	{
787 		now = TickHighres64();
788 
789 		LockList(s->DelayedPacketList);
790 		{
791 			for (i = 0;i < LIST_NUM(s->DelayedPacketList);i++)
792 			{
793 				PKT *p = LIST_DATA(s->DelayedPacketList, i);
794 				UINT64 t = p->DelayedForwardTick;
795 				UINT d = 0x7fffffff;
796 
797 				if (now >= t)
798 				{
799 					d = 0;
800 				}
801 				else
802 				{
803 					d = (UINT)(t - now);
804 				}
805 
806 				ret = MIN(ret, d);
807 			}
808 		}
809 		UnlockList(s->DelayedPacketList);
810 	}
811 
812 	return ret;
813 }
814 
815 // Determine whether the packet have priority in the VoIP / QoS function
IsPriorityHighestPacketForQoS(void * data,UINT size)816 bool IsPriorityHighestPacketForQoS(void *data, UINT size)
817 {
818 	UCHAR *buf;
819 	// Validate arguments
820 	if (data == NULL)
821 	{
822 		return false;
823 	}
824 
825 	buf = (UCHAR *)data;
826 	if (size >= 16)
827 	{
828 		if (buf[12] == 0x08 && buf[13] == 0x00 && buf[15] != 0x00 && buf[15] != 0x08)
829 		{
830 			// IPv4 packet and ToS != 0
831 			return true;
832 		}
833 
834 		if (size >= 34 && size <= 128)
835 		{
836 			if (buf[12] == 0x08 && buf[13] == 0x00 && buf[23] == 0x01)
837 			{
838 				// IMCPv4 packet
839 				return true;
840 			}
841 		}
842 	}
843 
844 	return false;
845 }
846 
847 // Update the traffic information of the user
IncrementUserTraffic(HUB * hub,char * username,SESSION * s)848 void IncrementUserTraffic(HUB *hub, char *username, SESSION *s)
849 {
850 	TRAFFIC report_traffic;
851 	// Validate arguments
852 	if (hub == NULL || username == NULL || s == NULL)
853 	{
854 		return;
855 	}
856 
857 	Lock(s->TrafficLock);
858 	{
859 		// Calculate the traffic information (difference between last time) to be reported
860 		report_traffic.Send.BroadcastBytes =
861 			s->Traffic->Send.BroadcastBytes - s->OldTraffic->Send.BroadcastBytes;
862 		report_traffic.Send.BroadcastCount =
863 			s->Traffic->Send.BroadcastCount - s->OldTraffic->Send.BroadcastCount;
864 		report_traffic.Send.UnicastBytes =
865 			s->Traffic->Send.UnicastBytes - s->OldTraffic->Send.UnicastBytes;
866 		report_traffic.Send.UnicastCount =
867 			s->Traffic->Send.UnicastCount - s->OldTraffic->Send.UnicastCount;
868 		report_traffic.Recv.BroadcastBytes =
869 			s->Traffic->Recv.BroadcastBytes - s->OldTraffic->Recv.BroadcastBytes;
870 		report_traffic.Recv.BroadcastCount =
871 			s->Traffic->Recv.BroadcastCount - s->OldTraffic->Recv.BroadcastCount;
872 		report_traffic.Recv.UnicastBytes =
873 			s->Traffic->Recv.UnicastBytes - s->OldTraffic->Recv.UnicastBytes;
874 		report_traffic.Recv.UnicastCount =
875 			s->Traffic->Recv.UnicastCount - s->OldTraffic->Recv.UnicastCount;
876 		Copy(s->OldTraffic, s->Traffic, sizeof(TRAFFIC));
877 
878 		if (hub->FarmMember == false)
879 		{
880 			// Update the user information in the local database if it is not a farm member
881 			AcLock(hub);
882 			{
883 				USER *u = AcGetUser(hub, username);
884 				if (u != NULL)
885 				{
886 					Lock(u->lock);
887 					{
888 						AddTraffic(u->Traffic, &report_traffic);
889 					}
890 					Unlock(u->lock);
891 					if (u->Group != NULL)
892 					{
893 						Lock(u->Group->lock);
894 						{
895 							AddTraffic(u->Group->Traffic, &report_traffic);
896 						}
897 						Unlock(u->Group->lock);
898 					}
899 					ReleaseUser(u);
900 				}
901 			}
902 			AcUnlock(hub);
903 		}
904 		else
905 		{
906 			// Update the traffic difference report list in the case of farm member
907 			AddTrafficDiff(hub, username, TRAFFIC_DIFF_USER, &report_traffic);
908 		}
909 	}
910 	Unlock(s->TrafficLock);
911 }
912 
913 // Cummulate the traffic information of the connection
AddTrafficForSession(SESSION * s,TRAFFIC * t)914 void AddTrafficForSession(SESSION *s, TRAFFIC *t)
915 {
916 	HUB *h;
917 	TRAFFIC t2;
918 	// Validate arguments
919 	if (s == NULL || t == NULL)
920 	{
921 		return;
922 	}
923 
924 	Lock(s->TrafficLock);
925 	{
926 		AddTraffic(s->Traffic, t);
927 	}
928 	Unlock(s->TrafficLock);
929 
930 	if (s->ServerMode)
931 	{
932 		Copy(&t2.Recv, &t->Send, sizeof(TRAFFIC_ENTRY));
933 		Copy(&t2.Send, &t->Recv, sizeof(TRAFFIC_ENTRY));
934 		Lock(s->Cedar->TrafficLock);
935 		{
936 			AddTraffic(s->Cedar->Traffic, &t2);
937 		}
938 		Unlock(s->Cedar->TrafficLock);
939 
940 		h = s->Hub;
941 		Lock(h->TrafficLock);
942 		{
943 			AddTraffic(h->Traffic, &t2);
944 		}
945 		Unlock(h->TrafficLock);
946 	}
947 }
948 
949 // A chance to establish an additional connection for client
ClientAdditionalConnectChance(SESSION * s)950 void ClientAdditionalConnectChance(SESSION *s)
951 {
952 	// Validate arguments
953 	if (s == NULL)
954 	{
955 		return;
956 	}
957 
958 	if (s->ServerMode)
959 	{
960 		// Do not connect additionally in the server mode
961 		return;
962 	}
963 	if (s->Connection->Protocol != CONNECTION_TCP)
964 	{
965 		// Connect additionally only in the case of TCP protocol
966 		return;
967 	}
968 	if (s->IsRUDPSession && s->EnableUdpRecovery == false)
969 	{
970 		// Do not connect additionally if the UDP recovery is disabled in the case of R-UDP session
971 		return;
972 	}
973 
974 	if (s->IsRUDPSession && (s->Connection->AdditionalConnectionFailedCounter > MAX_ADDITONAL_CONNECTION_FAILED_COUNTER))
975 	{
976 		// Not to make a large amount of repeated connection retry within a certain time in the case of R-UDP session
977 		return;
978 	}
979 
980 	while (true)
981 	{
982 		if (s->Halt)
983 		{
984 			return;
985 		}
986 		// Consider whether there is a need to put an additional connection
987 		// by examining the number of current connections and MaxConnection property
988 		if (Count(s->Connection->CurrentNumConnection) < s->MaxConnection)
989 		{
990 			// Get the current time
991 			UINT64 now = Tick64();
992 
993 			// Examine the NextConnectionTime, and if the time passed,
994 			// attempt to make a connection
995 			if (s->NextConnectionTime == 0 ||
996 				s->ClientOption->AdditionalConnectionInterval == 0 ||
997 				(s->NextConnectionTime <= now))
998 			{
999 				// Start the work to put an additional connection
1000 				s->NextConnectionTime = now + ((UINT64)s->ClientOption->AdditionalConnectionInterval * (UINT64)1000);
1001 				SessionAdditionalConnect(s);
1002 			}
1003 			else
1004 			{
1005 				break;
1006 			}
1007 		}
1008 		else
1009 		{
1010 			break;
1011 		}
1012 	}
1013 }
1014 
1015 // Release the packet adapter
FreePacketAdapter(PACKET_ADAPTER * pa)1016 void FreePacketAdapter(PACKET_ADAPTER *pa)
1017 {
1018 	// Validate arguments
1019 	if (pa == NULL)
1020 	{
1021 		return;
1022 	}
1023 
1024 	Free(pa);
1025 }
1026 
1027 // Create a new packet adapter
NewPacketAdapter(PA_INIT * init,PA_GETCANCEL * getcancel,PA_GETNEXTPACKET * getnext,PA_PUTPACKET * put,PA_FREE * free)1028 PACKET_ADAPTER *NewPacketAdapter(PA_INIT *init, PA_GETCANCEL *getcancel, PA_GETNEXTPACKET *getnext,
1029 								 PA_PUTPACKET *put, PA_FREE *free)
1030 {
1031 	PACKET_ADAPTER *pa;
1032 	// Validate arguments
1033 	if (init == NULL || getcancel == NULL || getnext == NULL || put == NULL || free == NULL)
1034 	{
1035 		return NULL;
1036 	}
1037 
1038 	pa = ZeroMalloc(sizeof(PACKET_ADAPTER));
1039 
1040 	pa->Init = init;
1041 	pa->Free = free;
1042 	pa->GetCancel = getcancel;
1043 	pa->GetNextPacket = getnext;
1044 	pa->PutPacket = put;
1045 
1046 	return pa;
1047 }
1048 
1049 // Thread for putting an additional connection
ClientAdditionalThread(THREAD * t,void * param)1050 void ClientAdditionalThread(THREAD *t, void *param)
1051 {
1052 	SESSION *s;
1053 	CONNECTION *c;
1054 	// Validate arguments
1055 	if (t == NULL || param == NULL)
1056 	{
1057 		return;
1058 	}
1059 
1060 	s = (SESSION *)param;
1061 
1062 	s->LastTryAddConnectTime = Tick64();
1063 
1064 	c = s->Connection;
1065 	// Increment of connection counter
1066 	Inc(c->CurrentNumConnection);
1067 	LockList(c->ConnectingThreads);
1068 	{
1069 		// Add to processing thread
1070 		Add(c->ConnectingThreads, t);
1071 		AddRef(t->ref);
1072 	}
1073 	UnlockList(c->ConnectingThreads);
1074 
1075 	// Notify the completion of initialization
1076 	NoticeThreadInit(t);
1077 
1078 	Debug("Additional Connection #%u\n", Count(c->CurrentNumConnection));
1079 
1080 	// Put an additional connection
1081 	if (ClientAdditionalConnect(c, t) == false)
1082 	{
1083 		// Decrement the counter which is currently processing
1084 		Dec(c->CurrentNumConnection);
1085 
1086 		if (c->AdditionalConnectionFailedCounter == 0)
1087 		{
1088 			c->LastCounterResetTick = Tick64();
1089 		}
1090 
1091 		c->AdditionalConnectionFailedCounter++;
1092 
1093 		if ((c->LastCounterResetTick + (UINT64)ADDITIONAL_CONNECTION_COUNTER_RESET_INTERVAL) <= Tick64())
1094 		{
1095 			// Reset the number of failures periodically
1096 			c->AdditionalConnectionFailedCounter = 0;
1097 			c->LastCounterResetTick = Tick64();
1098 		}
1099 	}
1100 	else
1101 	{
1102 		s->LastTryAddConnectTime = Tick64();
1103 		c->AdditionalConnectionFailedCounter = 0;
1104 		c->LastCounterResetTick = Tick64();
1105 	}
1106 
1107 	// Remove from the processing thread
1108 	LockList(c->ConnectingThreads);
1109 	{
1110 		// Remove from the processing thread
1111 		if (Delete(c->ConnectingThreads, t))
1112 		{
1113 			ReleaseThread(t);
1114 		}
1115 	}
1116 	UnlockList(c->ConnectingThreads);
1117 	ReleaseSession(s);
1118 }
1119 
1120 // Put an additional connection from the client to the server
SessionAdditionalConnect(SESSION * s)1121 void SessionAdditionalConnect(SESSION *s)
1122 {
1123 	THREAD *t;
1124 	// Validate arguments
1125 	if (s == NULL)
1126 	{
1127 		return;
1128 	}
1129 
1130 	// s->LastTryAddConnectTime = Tick64();
1131 
1132 	AddRef(s->ref);
1133 	t = NewThread(ClientAdditionalThread, (void *)s);
1134 	WaitThreadInit(t);
1135 	ReleaseThread(t);
1136 }
1137 
1138 // Connect the client session to the server
SessionConnect(SESSION * s)1139 bool SessionConnect(SESSION *s)
1140 {
1141 	CONNECTION *c;
1142 	bool ret = false;
1143 	// Validate arguments
1144 	if (s == NULL)
1145 	{
1146 		return false;
1147 	}
1148 
1149 	s->ClientStatus = CLIENT_STATUS_CONNECTING;
1150 
1151 	Debug("SessionConnect() Started.\n");
1152 
1153 	// Initialize the session
1154 	Lock(s->lock);
1155 	{
1156 		s->Err = ERR_NO_ERROR;
1157 		if (s->Policy != NULL)
1158 		{
1159 			Free(s->Policy);
1160 			s->Policy = NULL;
1161 		}
1162 	}
1163 	Unlock(s->lock);
1164 
1165 	s->CancelConnect = false;
1166 
1167 	// Create a Client Connection
1168 	c = NewClientConnection(s);
1169 	s->Connection = c;
1170 
1171 	// Connect the client to the server
1172 	ret = ClientConnect(c);
1173 	s->Err = c->Err;
1174 
1175 	s->CancelConnect = false;
1176 
1177 	if (s->Cedar->Client != NULL)
1178 	{
1179 		if (s->Policy != NULL)
1180 		{
1181 			if (s->Policy->NoSavePassword)
1182 			{
1183 				s->Client_NoSavePassword = true;
1184 
1185 				if (s->Account != NULL)
1186 				{
1187 					Lock(s->Account->lock);
1188 					{
1189 						if (s->Account->ClientAuth != NULL)
1190 						{
1191 							if (s->Account->ClientAuth->AuthType == AUTHTYPE_PASSWORD ||
1192 								s->Account->ClientAuth->AuthType == AUTHTYPE_RADIUS)
1193 							{
1194 								Zero(s->Account->ClientAuth->HashedPassword, sizeof(s->Account->ClientAuth->HashedPassword));
1195 								Zero(s->Account->ClientAuth->PlainPassword, sizeof(s->Account->ClientAuth->PlainPassword));
1196 							}
1197 						}
1198 					}
1199 					Unlock(s->Account->lock);
1200 
1201 					CiSaveConfigurationFile(s->Cedar->Client);
1202 				}
1203 			}
1204 		}
1205 	}
1206 
1207 	if (c->ClientConnectError_NoSavePassword)
1208 	{
1209 		s->Client_NoSavePassword = true;
1210 	}
1211 
1212 	// Release the client connection
1213 	s->Connection = NULL;
1214 	ReleaseConnection(c);
1215 
1216 	Lock(s->lock);
1217 	{
1218 		if (s->Policy != NULL)
1219 		{
1220 			Free(s->Policy);
1221 			s->Policy = NULL;
1222 		}
1223 	}
1224 	Unlock(s->lock);
1225 
1226 	return ret;
1227 }
1228 
1229 // Stop the session
StopSession(SESSION * s)1230 void StopSession(SESSION *s)
1231 {
1232 	StopSessionEx(s, false);
1233 }
StopSessionEx(SESSION * s,bool no_wait)1234 void StopSessionEx(SESSION *s, bool no_wait)
1235 {
1236 	// Validate arguments
1237 	if (s == NULL)
1238 	{
1239 		return;
1240 	}
1241 
1242 	// Halting flag
1243 	s->UserCanceled = true;
1244 	s->CancelConnect = true;
1245 	s->Halt = true;
1246 
1247 	Debug("Stop Session %s\n", s->Name);
1248 
1249 	// Cancel
1250 	Cancel(s->Cancel1);
1251 
1252 	// Event
1253 	Set(s->HaltEvent);
1254 
1255 	if (s->ServerMode == false)
1256 	{
1257 		// Client mode
1258 		if (s->Connection)
1259 		{
1260 			CONNECTION *c = s->Connection;
1261 			AddRef(c->ref);
1262 			StopConnection(c, no_wait);
1263 			ReleaseConnection(c);
1264 		}
1265 	}
1266 	else
1267 	{
1268 		// Server mode
1269 		if (s->Connection)
1270 		{
1271 			CONNECTION *c = s->Connection;
1272 			AddRef(c->ref);
1273 			StopConnection(c, no_wait);
1274 			ReleaseConnection(c);
1275 		}
1276 	}
1277 
1278 	// Wait until the stop
1279 	if (no_wait == false)
1280 	{
1281 		while (true)
1282 		{
1283 			s->ForceStopFlag = true;
1284 			s->Halt = true;
1285 			if (WaitThread(s->Thread, 20))
1286 			{
1287 				break;
1288 			}
1289 		}
1290 	}
1291 	else
1292 	{
1293 		s->ForceStopFlag = true;
1294 		s->Halt = true;
1295 	}
1296 }
1297 
1298 // Cleanup the session
CleanupSession(SESSION * s)1299 void CleanupSession(SESSION *s)
1300 {
1301 	// Validate arguments
1302 	if (s == NULL)
1303 	{
1304 		return;
1305 	}
1306 
1307 	// Release the delayed packet list
1308 	if (s->DelayedPacketList != NULL)
1309 	{
1310 		UINT i;
1311 		for (i = 0;i < LIST_NUM(s->DelayedPacketList);i++)
1312 		{
1313 			PKT *p = LIST_DATA(s->DelayedPacketList, i);
1314 
1315 			Free(p->PacketData);
1316 			FreePacket(p);
1317 		}
1318 
1319 		ReleaseList(s->DelayedPacketList);
1320 	}
1321 
1322 	// Release the client connection options
1323 	if (s->ClientOption != NULL)
1324 	{
1325 		Free(s->ClientOption);
1326 	}
1327 
1328 	// Release the client authentication data
1329 	if (s->ClientAuth != NULL)
1330 	{
1331 		if (s->ClientAuth->ClientX != NULL)
1332 		{
1333 			FreeX(s->ClientAuth->ClientX);
1334 		}
1335 		if (s->ClientAuth->ClientX != NULL)
1336 		{
1337 			FreeK(s->ClientAuth->ClientK);
1338 		}
1339 		Free(s->ClientAuth);
1340 	}
1341 
1342 	FreeTraffic(s->Traffic);
1343 	Free(s->Name);
1344 
1345 	if (s->Thread != NULL)
1346 	{
1347 		ReleaseThread(s->Thread);
1348 	}
1349 
1350 	DeleteLock(s->lock);
1351 
1352 	ReleaseEvent(s->HaltEvent);
1353 
1354 	if (s->Cancel1)
1355 	{
1356 		ReleaseCancel(s->Cancel1);
1357 	}
1358 
1359 	if (s->Cancel2)
1360 	{
1361 		ReleaseCancel(s->Cancel2);
1362 	}
1363 
1364 	if (s->Policy)
1365 	{
1366 		Free(s->Policy);
1367 	}
1368 
1369 	if (s->Connection)
1370 	{
1371 		ReleaseConnection(s->Connection);
1372 	}
1373 
1374 	Free(s->Username);
1375 
1376 	if (s->PacketAdapter)
1377 	{
1378 		FreePacketAdapter(s->PacketAdapter);
1379 	}
1380 
1381 	if (s->OldTraffic != NULL)
1382 	{
1383 		FreeTraffic(s->OldTraffic);
1384 	}
1385 
1386 	DeleteLock(s->TrafficLock);
1387 
1388 	if (s->CancelList != NULL)
1389 	{
1390 		ReleaseCancelList(s->CancelList);
1391 	}
1392 
1393 	if (s->Client_Message != NULL)
1394 	{
1395 		Free(s->Client_Message);
1396 	}
1397 
1398 	DeleteCounter(s->LoggingRecordCount);
1399 
1400 	ReleaseSharedBuffer(s->IpcSessionSharedBuffer);
1401 
1402 
1403 	Free(s);
1404 }
1405 
1406 // Release the session
ReleaseSession(SESSION * s)1407 void ReleaseSession(SESSION *s)
1408 {
1409 	// Validate arguments
1410 	if (s == NULL)
1411 	{
1412 		return;
1413 	}
1414 
1415 	if (Release(s->ref) == 0)
1416 	{
1417 		CleanupSession(s);
1418 	}
1419 }
1420 
1421 // Display the total data transfer size of the session
PrintSessionTotalDataSize(SESSION * s)1422 void PrintSessionTotalDataSize(SESSION *s)
1423 {
1424 	// Validate arguments
1425 	if (s == NULL)
1426 	{
1427 		return;
1428 	}
1429 
1430 	Debug(
1431 		"-- SESSION TOTAL PKT INFORMATION --\n\n"
1432 		"      TotalSendSize: %I64u\n"
1433 		"  TotalSendSizeReal: %I64u\n"
1434 		"      TotalRecvSize: %I64u\n"
1435 		"  TotalRecvSizeReal: %I64u\n"
1436 		"   Compression Rate: %.2f%% (Send)\n"
1437 		"                     %.2f%% (Recv)\n",
1438 		s->TotalSendSize, s->TotalSendSizeReal,
1439 		s->TotalRecvSize, s->TotalRecvSizeReal,
1440 		(float)((double)s->TotalSendSizeReal / (double)s->TotalSendSize * 100.0f),
1441 		(float)((double)s->TotalRecvSizeReal / (double)s->TotalRecvSize * 100.0f)
1442 		);
1443 
1444 }
1445 
1446 // Client thread
ClientThread(THREAD * t,void * param)1447 void ClientThread(THREAD *t, void *param)
1448 {
1449 	SESSION *s;
1450 	bool use_password_dlg;
1451 	bool no_save_password = false;
1452 	bool is_vpngate_connection = false;
1453 	CEDAR *cedar;
1454 	bool num_active_sessions_incremented = false;
1455 	// Validate arguments
1456 	if (t == NULL || param == NULL)
1457 	{
1458 		return;
1459 	}
1460 
1461 	Debug("ClientThread 0x%x Started.\n", t);
1462 
1463 	s = (SESSION *)param;
1464 	AddRef(s->ref);
1465 	s->Thread = t;
1466 	AddRef(t->ref);
1467 
1468 	if (s->LinkModeClient == false)
1469 	{
1470 		CiIncrementNumActiveSessions();
1471 		num_active_sessions_incremented = true;
1472 	}
1473 
1474 	NoticeThreadInit(t);
1475 
1476 	cedar = s->Cedar;
1477 
1478 	s->ClientStatus = CLIENT_STATUS_CONNECTING;
1479 	s->RetryFlag = true;
1480 	s->CurrentRetryCount = 0;
1481 
1482 	Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
1483 
1484 	if (s->Cedar->Client != NULL)
1485 	{
1486 		no_save_password = s->Cedar->Client->DontSavePassword;
1487 	}
1488 
1489 	s->Win32HideConnectWindow = s->ClientOption->HideStatusWindow;
1490 	s->Win32HideNicInfoWindow = s->ClientOption->HideNicInfoWindow;
1491 
1492 
1493 	while (true)
1494 	{
1495 		Zero(&s->ServerIP_CacheForNextConnect, sizeof(IP));
1496 
1497 		if (s->Link != NULL && ((*s->Link->StopAllLinkFlag) || s->Link->Halting))
1498 		{
1499 			s->Err = ERR_USER_CANCEL;
1500 			break;
1501 		}
1502 
1503 		CLog(s->Cedar->Client, "LC_CONNECT_1", s->ClientOption->AccountName, s->CurrentRetryCount + 1);
1504 		if (s->LinkModeClient && s->Link != NULL)
1505 		{
1506 			HLog(s->Link->Hub, "LH_CONNECT_1", s->ClientOption->AccountName, s->CurrentRetryCount + 1);
1507 		}
1508 
1509 		Debug("Trying to Connect to Server... (%u / %u)\n", s->CurrentRetryCount + 0,
1510 			s->ClientOption->NumRetry);
1511 
1512 		// Initialize
1513 //		s->TotalRecvSize = s->TotalRecvSizeReal =
1514 //			s->TotalSendSize = s->TotalSendSizeReal = 0;
1515 		s->NextConnectionTime = 0;
1516 
1517 		// Connect
1518 		s->ClientStatus = CLIENT_STATUS_CONNECTING;
1519 		s->Halt = false;
1520 		SessionConnect(s);
1521 		if (s->UserCanceled)
1522 		{
1523 			s->Err = ERR_USER_CANCEL;
1524 		}
1525 		Debug("Disconnected. Err = %u : %S\n", s->Err, _E(s->Err));
1526 
1527 		PrintSessionTotalDataSize(s);
1528 
1529 		CLog(s->Cedar->Client, "LC_CONNECT_ERROR", s->ClientOption->AccountName,
1530 			GetUniErrorStr(s->Err), s->Err);
1531 
1532 		if (s->LinkModeClient && s->Link != NULL)
1533 		{
1534 			HLog(s->Link->Hub, "LH_CONNECT_ERROR", s->ClientOption->AccountName,
1535 				GetUniErrorStr(s->Err), s->Err);
1536 		}
1537 
1538 		s->ClientStatus = CLIENT_STATUS_RETRY;
1539 
1540 		if (s->Link != NULL)
1541 		{
1542 			((LINK *)s->Link)->LastError = s->Err;
1543 		}
1544 
1545 		if (s->Halt && (s->RetryFlag == false) || s->ForceStopFlag)
1546 		{
1547 			// Must be aborted
1548 			if (s->Err == ERR_DEVICE_DRIVER_ERROR)
1549 			{
1550 #ifdef	OS_WIN32
1551 				wchar_t tmp[MAX_SIZE];
1552 				if (s->Account != NULL && s->Cedar->Client != NULL)
1553 				{
1554 					UniFormat(tmp, sizeof(tmp), _UU("ERRDLG_DEVICE_ERROR"), s->ClientOption->DeviceName,
1555 						s->Err, _E(s->Err));
1556 					MsgBox(NULL, 0x10000 | 0x40000 | 0x200000 | 0x30, tmp);
1557 				}
1558 #endif	// OS_WIN32
1559 			}
1560 			break;
1561 		}
1562 		// Determine whether to display the password re-entry dialog
1563 		use_password_dlg = false;
1564 
1565 		if (s->Account != NULL && s->Cedar->Client != NULL)
1566 		{
1567 #ifdef	OS_WIN32
1568 			if (s->ClientAuth->AuthType == CLIENT_AUTHTYPE_PASSWORD || s->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
1569 			{
1570 				if (s->Err == ERR_AUTH_FAILED || s->Err == ERR_PROXY_AUTH_FAILED)
1571 				{
1572 					use_password_dlg = true;
1573 				}
1574 			}
1575 #endif	// OS_WIN32
1576 		}
1577 
1578 		// Failed to connect or the connection is disconnected
1579 		// Wait for retry interval
1580 		if (use_password_dlg == false)
1581 		{
1582 			UINT retry_interval = s->RetryInterval;
1583 
1584 			if (s->LinkModeClient)
1585 			{
1586 				UINT current_num_links = Count(s->Cedar->CurrentActiveLinks);
1587 				UINT max_retry_interval = MAX(1000 * current_num_links, retry_interval);
1588 
1589 				retry_interval += retry_interval * MIN(s->CurrentRetryCount, 1000);
1590 				retry_interval = MIN(retry_interval, max_retry_interval);
1591 
1592 				// On the cascade client, adjust the retry_interval. (+/- 20%)
1593 				if (retry_interval >= 1000 && retry_interval <= (60 * 60 * 1000))
1594 				{
1595 					retry_interval = (retry_interval * 8 / 10) + (Rand32() % (retry_interval * 4 / 10));
1596 				}
1597 			}
1598 
1599 			if (s->Err == ERR_HUB_IS_BUSY || s->Err == ERR_LICENSE_ERROR ||
1600 				s->Err == ERR_HUB_STOPPING || s->Err == ERR_TOO_MANY_USER_SESSION)
1601 			{
1602 				retry_interval = RETRY_INTERVAL_SPECIAL;
1603 			}
1604 
1605 			if (s->CurrentRetryCount >= s->ClientOption->NumRetry)
1606 			{
1607 				// Retry count excess
1608 
1609 #ifndef	OS_WIN32
1610 
1611 				break;
1612 
1613 #else	// OS_WIN32
1614 
1615 				if (s->Win32HideConnectWindow == false &&
1616 					s->Cedar->Client != NULL && s->Account != NULL)
1617 				{
1618 					// Show a reconnection dialog
1619 					UI_CONNECTERROR_DLG p;
1620 					Zero(&p, sizeof(p));
1621 					UniStrCpy(p.AccountName, sizeof(p.AccountName), s->ClientOption->AccountName);
1622 					StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption->Hostname);
1623 					p.Err = s->Err;
1624 					p.CurrentRetryCount = s->CurrentRetryCount + 1;
1625 					s->Halt = false;
1626 					p.RetryLimit = 0;
1627 					p.RetryIntervalSec = 0;
1628 					p.CancelEvent = s->HaltEvent;
1629 					p.HideWindow = s->Win32HideConnectWindow;
1630 					if (CncConnectErrorDlg(s, &p) == false)
1631 					{
1632 						// Abort
1633 						break;
1634 					}
1635 					else
1636 					{
1637 						s->Win32HideConnectWindow = p.HideWindow;
1638 						goto SKIP;
1639 					}
1640 				}
1641 				else
1642 				{
1643 					break;
1644 				}
1645 
1646 #endif
1647 			}
1648 
1649 #ifndef	OS_WIN32
1650 
1651 			// Simple wait
1652 			Wait(s->HaltEvent, retry_interval);
1653 
1654 #else	// OS_WIN32
1655 
1656 			if (s->Win32HideConnectWindow == false &&
1657 				s->Cedar->Client != NULL && s->Account != NULL)
1658 			{
1659 				// Show a reconnection dialog
1660 				UI_CONNECTERROR_DLG p;
1661 				Zero(&p, sizeof(p));
1662 				UniStrCpy(p.AccountName, sizeof(p.AccountName), s->ClientOption->AccountName);
1663 				StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption->Hostname);
1664 				p.Err = s->Err;
1665 				p.CurrentRetryCount = s->CurrentRetryCount + 1;
1666 				p.RetryLimit = s->ClientOption->NumRetry;
1667 				p.RetryIntervalSec = retry_interval;
1668 				p.CancelEvent = s->HaltEvent;
1669 				s->Halt = false;
1670 				p.HideWindow = s->Win32HideConnectWindow;
1671 				if (CncConnectErrorDlg(s, &p) == false)
1672 				{
1673 					// Abort
1674 					break;
1675 				}
1676 				s->Win32HideConnectWindow = p.HideWindow;
1677 			}
1678 			else
1679 			{
1680 				// Simple wait
1681 				Wait(s->HaltEvent, s->RetryInterval);
1682 			}
1683 
1684 #endif	// OS_WIN32
1685 		}
1686 		else
1687 		{
1688 #ifdef	OS_WIN32
1689 			// Wait for re-entry the password
1690 			UI_PASSWORD_DLG p;
1691 			Zero(&p, sizeof(p));
1692 			if (s->Client_NoSavePassword == false)
1693 			{
1694 				p.ShowNoSavePassword = true;
1695 			}
1696 			p.NoSavePassword = no_save_password;
1697 			p.CancelEvent = s->HaltEvent;
1698 			if (s->Err == ERR_PROXY_AUTH_FAILED)
1699 			{
1700 				p.ProxyServer = true;
1701 			}
1702 
1703 			if (p.ProxyServer)
1704 			{
1705 				StrCpy(p.Username, sizeof(p.Username), s->ClientOption->ProxyUsername);
1706 				StrCpy(p.Password, sizeof(p.Password), s->ClientOption->ProxyPassword);
1707 				StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption->ProxyName);
1708 			}
1709 			else
1710 			{
1711 				bool empty = false;
1712 
1713 				StrCpy(p.Username, sizeof(p.Username), s->ClientAuth->Username);
1714 				if (s->ClientAuth->AuthType == AUTHTYPE_RADIUS)
1715 				{
1716 					if (StrLen(s->ClientAuth->PlainPassword) == 0)
1717 					{
1718 						empty = true;
1719 					}
1720 				}
1721 				else if (s->ClientAuth->AuthType == AUTHTYPE_PASSWORD)
1722 				{
1723 					if (IsZero(s->ClientAuth->HashedPassword, sizeof(s->ClientAuth->HashedPassword)))
1724 					{
1725 						empty = true;
1726 					}
1727 				}
1728 
1729 				StrCpy(p.Password, sizeof(p.Password), empty ? "" : HIDDEN_PASSWORD);
1730 				StrCpy(p.ServerName, sizeof(p.ServerName), s->ClientOption->Hostname);
1731 			}
1732 
1733 			p.RetryIntervalSec = s->RetryInterval / 1000;
1734 			p.Type = s->ClientAuth->AuthType;
1735 
1736 			// Display the password re-entry dialog
1737 			if (CncPasswordDlg(s, &p) == false)
1738 			{
1739 				// Abort the connection
1740 				break;
1741 			}
1742 			else
1743 			{
1744 				// Overwrite the user name
1745 				if (p.ProxyServer)
1746 				{
1747 					// User name of the proxy
1748 					StrCpy(s->ClientOption->ProxyUsername, sizeof(s->ClientOption->ProxyUsername), p.Username);
1749 				}
1750 				else
1751 				{
1752 					// The user name for connecting to the server
1753 					StrCpy(s->ClientAuth->Username, sizeof(s->ClientAuth->Username), p.Username);
1754 					s->ClientAuth->AuthType = p.Type;
1755 				}
1756 
1757 				if (StrCmp(p.Password, HIDDEN_PASSWORD) != 0)
1758 				{
1759 					// Password is re-entered
1760 					if (p.ProxyServer)
1761 					{
1762 						// Password for the proxy server
1763 						StrCpy(s->ClientOption->ProxyPassword, sizeof(s->ClientOption->ProxyPassword), p.Password);
1764 					}
1765 					else
1766 					{
1767 						if (s->ClientAuth->AuthType == CLIENT_AUTHTYPE_PLAIN_PASSWORD)
1768 						{
1769 							// Plaintext password authentication
1770 							StrCpy(s->ClientAuth->PlainPassword, sizeof(s->ClientAuth->PlainPassword), p.Password);
1771 						}
1772 						else
1773 						{
1774 							// Encrypted password authentication
1775 							HashPassword(s->ClientAuth->HashedPassword, s->ClientAuth->Username, p.Password);
1776 						}
1777 					}
1778 				}
1779 
1780 				no_save_password = p.NoSavePassword;
1781 
1782 				if (s->Account != NULL && s->Cedar->Client != NULL)
1783 				{
1784 					s->Cedar->Client->DontSavePassword = no_save_password;
1785 					if (p.NoSavePassword == false)
1786 					{
1787 						// Update the account database of the client
1788 						if (p.ProxyServer == false)
1789 						{
1790 							// Update the Server connection information
1791 							ACCOUNT *a = s->Account;
1792 							Lock(a->lock);
1793 							{
1794 								CiFreeClientAuth(a->ClientAuth);
1795 								a->ClientAuth = CopyClientAuth(s->ClientAuth);
1796 							}
1797 							Unlock(a->lock);
1798 							CiSaveConfigurationFile(s->Cedar->Client);
1799 						}
1800 						else
1801 						{
1802 							// Update the proxy connection information
1803 							ACCOUNT *a = s->Account;
1804 							Lock(a->lock);
1805 							{
1806 								Copy(a->ClientOption, s->ClientOption, sizeof(CLIENT_OPTION));
1807 							}
1808 							Unlock(a->lock);
1809 							CiSaveConfigurationFile(s->Cedar->Client);
1810 						}
1811 					}
1812 				}
1813 			}
1814 #endif	// OS_WIN32
1815 		}
1816 
1817 SKIP:
1818 		// Increase the number of retries
1819 		if (s->ConnectSucceed == false)
1820 		{
1821 			s->CurrentRetryCount++;
1822 		}
1823 
1824 		if (s->ForceStopFlag)
1825 		{
1826 			break;
1827 		}
1828 	}
1829 
1830 	Debug("Session Halt.\n");
1831 
1832 	s->ClientStatus = CLIENT_STATUS_IDLE;
1833 
1834 	// Regard as that the session is ended here
1835 	if (s->Account != NULL)
1836 	{
1837 		s->Account->ClientSession = NULL;
1838 		ReleaseSession(s);
1839 	}
1840 
1841 	Notify(s, CLIENT_NOTIFY_ACCOUNT_CHANGED);
1842 
1843 
1844 	ReleaseSession(s);
1845 
1846 	if (num_active_sessions_incremented)
1847 	{
1848 		CiDecrementNumActiveSessions();
1849 	}
1850 }
1851 
1852 // Name comparison of sessions
CompareSession(void * p1,void * p2)1853 int CompareSession(void *p1, void *p2)
1854 {
1855 	SESSION *s1, *s2;
1856 	if (p1 == NULL || p2 == NULL)
1857 	{
1858 		return 0;
1859 	}
1860 	s1 = *(SESSION **)p1;
1861 	s2 = *(SESSION **)p2;
1862 	if (s1 == NULL || s2 == NULL)
1863 	{
1864 		return 0;
1865 	}
1866 	return StrCmpi(s1->Name, s2->Name);
1867 }
1868 
1869 // Create an RPC session
NewRpcSession(CEDAR * cedar,CLIENT_OPTION * option)1870 SESSION *NewRpcSession(CEDAR *cedar, CLIENT_OPTION *option)
1871 {
1872 	return NewRpcSessionEx(cedar, option, NULL, NULL);
1873 }
NewRpcSessionEx(CEDAR * cedar,CLIENT_OPTION * option,UINT * err,char * client_str)1874 SESSION *NewRpcSessionEx(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str)
1875 {
1876 	return NewRpcSessionEx2(cedar, option, err, client_str, NULL);
1877 }
NewRpcSessionEx2(CEDAR * cedar,CLIENT_OPTION * option,UINT * err,char * client_str,void * hWnd)1878 SESSION *NewRpcSessionEx2(CEDAR *cedar, CLIENT_OPTION *option, UINT *err, char *client_str, void *hWnd)
1879 {
1880 	SESSION *s;
1881 	CONNECTION *c;
1882 	SOCK *sock;
1883 	// Validate arguments
1884 	if (cedar == NULL || option == NULL)
1885 	{
1886 		return NULL;
1887 	}
1888 
1889 	s = ZeroMalloc(sizeof(SESSION));
1890 
1891 	s->LoggingRecordCount = NewCounter();
1892 	s->lock = NewLock();
1893 	s->ref = NewRef();
1894 	s->Cedar = cedar;
1895 	s->ServerMode = false;
1896 	s->Name = CopyStr("CLIENT_RPC_SESSION");
1897 	s->CreatedTime = s->LastCommTime = Tick64();
1898 	s->Traffic = NewTraffic();
1899 	s->HaltEvent = NewEvent();
1900 	s->TrafficLock = NewLock();
1901 	s->Cancel1 = NewCancel();
1902 
1903 	// Copy the client connection options
1904 	s->ClientOption = Malloc(sizeof(CLIENT_OPTION));
1905 	Copy(s->ClientOption, option, sizeof(CLIENT_OPTION));
1906 
1907 	s->MaxConnection = option->MaxConnection;
1908 	s->UseEncrypt = option->UseEncrypt;
1909 	s->UseCompress = option->UseCompress;
1910 
1911 	// Create a connection
1912 	c = s->Connection = NewClientConnectionEx(s, client_str, cedar->Version, cedar->Build);
1913 	c->hWndForUI = hWnd;
1914 
1915 	// Connect to the server
1916 	sock = ClientConnectToServer(c);
1917 	if (sock == NULL)
1918 	{
1919 		// Connection failure
1920 		if (err != NULL)
1921 		{
1922 			*err = c->Err;
1923 		}
1924 		ReleaseSession(s);
1925 		return NULL;
1926 	}
1927 
1928 	// Send a signature
1929 	if (ClientUploadSignature(sock) == false)
1930 	{
1931 		// Failure
1932 		if (err != NULL)
1933 		{
1934 			*err = c->Err;
1935 		}
1936 		ReleaseSession(s);
1937 		return NULL;
1938 	}
1939 
1940 	// Receive a Hello packet
1941 	if (ClientDownloadHello(c, sock) == false)
1942 	{
1943 		// Failure
1944 		if (err != NULL)
1945 		{
1946 			*err = c->Err;
1947 		}
1948 		ReleaseSession(s);
1949 		return NULL;
1950 	}
1951 
1952 	return s;
1953 }
1954 
1955 // Create a client session
NewClientSessionEx(CEDAR * cedar,CLIENT_OPTION * option,CLIENT_AUTH * auth,PACKET_ADAPTER * pa,ACCOUNT * account)1956 SESSION *NewClientSessionEx(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa, ACCOUNT *account)
1957 {
1958 	SESSION *s;
1959 	THREAD *t;
1960 	// Validate arguments
1961 	if (cedar == NULL || option == NULL || auth == NULL || pa == NULL ||
1962 		(auth->AuthType == CLIENT_AUTHTYPE_SECURE && auth->SecureSignProc == NULL))
1963 	{
1964 		return NULL;
1965 	}
1966 
1967 	// Initialize the SESSION object
1968 	s = ZeroMalloc(sizeof(SESSION));
1969 
1970 	s->LoggingRecordCount = NewCounter();
1971 
1972 	s->lock = NewLock();
1973 	s->ref = NewRef();
1974 	s->Cedar = cedar;
1975 	s->ServerMode = false;
1976 	s->Name = CopyStr("CLIENT_SESSION");
1977 	s->CreatedTime = s->LastCommTime = Tick64();
1978 	s->Traffic = NewTraffic();
1979 	s->HaltEvent = NewEvent();
1980 	s->PacketAdapter = pa;
1981 	s->TrafficLock = NewLock();
1982 	s->OldTraffic = NewTraffic();
1983 	s->Cancel1 = NewCancel();
1984 	s->CancelList = NewCancelList();
1985 
1986 	// Copy the client connection options
1987 	s->ClientOption = Malloc(sizeof(CLIENT_OPTION));
1988 	Copy(s->ClientOption, option, sizeof(CLIENT_OPTION));
1989 
1990 	if (GetGlobalServerFlag(GSF_DISABLE_SESSION_RECONNECT))
1991 	{
1992 		s->ClientOption->DisableQoS = true;
1993 		s->ClientOption->MaxConnection = 1;
1994 		s->ClientOption->HalfConnection = false;
1995 	}
1996 
1997 	s->MaxConnection = option->MaxConnection;
1998 	s->UseEncrypt = option->UseEncrypt;
1999 	s->UseCompress = option->UseCompress;
2000 
2001 	// Set the retry interval
2002 	s->RetryInterval = MAKESURE(option->RetryInterval, 0, 4000000) * 1000;
2003 	s->RetryInterval = MAKESURE(s->RetryInterval, MIN_RETRY_INTERVAL, MAX_RETRY_INTERVAL);
2004 
2005 	// Interval for additional connection creation is at least 1 second
2006 	s->ClientOption->AdditionalConnectionInterval = MAX(s->ClientOption->AdditionalConnectionInterval, 1);
2007 
2008 	// Hold whether the virtual LAN card is used in client mode
2009 	s->ClientModeAndUseVLan = (StrLen(s->ClientOption->DeviceName) == 0) ? false : true;
2010 
2011 	if (s->ClientOption->NoRoutingTracking)
2012 	{
2013 		s->ClientModeAndUseVLan = false;
2014 	}
2015 
2016 	if (pa->Id == PACKET_ADAPTER_ID_VLAN_WIN32)
2017 	{
2018 		s->IsVPNClientAndVLAN_Win32 = true;
2019 	}
2020 
2021 	if (StrLen(option->DeviceName) == 0)
2022 	{
2023 		// NAT mode
2024 		s->ClientModeAndUseVLan = false;
2025 		s->VirtualHost = true;
2026 	}
2027 
2028 	if (OS_IS_WINDOWS_9X(GetOsInfo()->OsType))
2029 	{
2030 		// Prohibit the half-duplex mode in the case of Win9x
2031 		s->ClientOption->HalfConnection = false;
2032 	}
2033 
2034 	// Copy the client authentication data
2035 	s->ClientAuth = Malloc(sizeof(CLIENT_AUTH));
2036 	Copy(s->ClientAuth, auth, sizeof(CLIENT_AUTH));
2037 
2038 	// Clone the certificate and the private key
2039 	if (s->ClientAuth->ClientX != NULL)
2040 	{
2041 		s->ClientAuth->ClientX = CloneX(s->ClientAuth->ClientX);
2042 	}
2043 	if (s->ClientAuth->ClientK != NULL)
2044 	{
2045 		s->ClientAuth->ClientK = CloneK(s->ClientAuth->ClientK);
2046 	}
2047 
2048 	if (StrCmpi(s->ClientOption->DeviceName, LINK_DEVICE_NAME) == 0)
2049 	{
2050 		// Link client mode
2051 		s->LinkModeClient = true;
2052 		s->Link = (LINK *)s->PacketAdapter->Param;
2053 	}
2054 
2055 	if (StrCmpi(s->ClientOption->DeviceName, SNAT_DEVICE_NAME) == 0)
2056 	{
2057 		// SecureNAT mode
2058 		s->SecureNATMode = true;
2059 	}
2060 
2061 	if (StrCmpi(s->ClientOption->DeviceName, BRIDGE_DEVICE_NAME) == 0)
2062 	{
2063 		// Bridge mode
2064 		s->BridgeMode = true;
2065 	}
2066 
2067 	if (s->VirtualHost)
2068 	{
2069 		VH *v = (VH *)s->PacketAdapter->Param;
2070 
2071 		// Add the session object to VH
2072 		v->Session = s;
2073 		AddRef(s->ref);
2074 	}
2075 
2076 	s->Account = account;
2077 
2078 	if (s->ClientAuth->AuthType == CLIENT_AUTHTYPE_SECURE)
2079 	{
2080 		// Do not retry in the case of a smart card authentication
2081 		s->ClientOption->NumRetry = 0;
2082 	}
2083 
2084 	// Create a client thread
2085 	t = NewThread(ClientThread, (void *)s);
2086 	WaitThreadInit(t);
2087 	ReleaseThread(t);
2088 
2089 	return s;
2090 }
NewClientSession(CEDAR * cedar,CLIENT_OPTION * option,CLIENT_AUTH * auth,PACKET_ADAPTER * pa)2091 SESSION *NewClientSession(CEDAR *cedar, CLIENT_OPTION *option, CLIENT_AUTH *auth, PACKET_ADAPTER *pa)
2092 {
2093 	return NewClientSessionEx(cedar, option, auth, pa, NULL);
2094 }
2095 
2096 // Get the session from the 32bit session key
GetSessionFromKey32(CEDAR * cedar,UINT key32)2097 SESSION *GetSessionFromKey32(CEDAR *cedar, UINT key32)
2098 {
2099 	HUB *h;
2100 	UINT i, j;
2101 	// Validate arguments
2102 	if (cedar == NULL)
2103 	{
2104 		return NULL;
2105 	}
2106 
2107 	LockList(cedar->HubList);
2108 	{
2109 		for (i = 0;i < LIST_NUM(cedar->HubList);i++)
2110 		{
2111 			h = LIST_DATA(cedar->HubList, i);
2112 			LockList(h->SessionList);
2113 			{
2114 				for (j = 0;j < LIST_NUM(h->SessionList);j++)
2115 				{
2116 					SESSION *s = LIST_DATA(h->SessionList, j);
2117 					Lock(s->lock);
2118 					{
2119 						if (s->SessionKey32 == key32)
2120 						{
2121 							// Session found
2122 							AddRef(s->ref);
2123 
2124 							// Unlock
2125 							Unlock(s->lock);
2126 							UnlockList(h->SessionList);
2127 							UnlockList(cedar->HubList);
2128 							return s;
2129 						}
2130 					}
2131 					Unlock(s->lock);
2132 				}
2133 			}
2134 			UnlockList(h->SessionList);
2135 		}
2136 	}
2137 	UnlockList(cedar->HubList);
2138 
2139 	return NULL;
2140 }
2141 
2142 // Get the session from the session key
GetSessionFromKey(CEDAR * cedar,UCHAR * session_key)2143 SESSION *GetSessionFromKey(CEDAR *cedar, UCHAR *session_key)
2144 {
2145 	HUB *h;
2146 	UINT i, j;
2147 	// Validate arguments
2148 	if (cedar == NULL || session_key == NULL)
2149 	{
2150 		return NULL;
2151 	}
2152 
2153 	LockList(cedar->HubList);
2154 	{
2155 		for (i = 0;i < LIST_NUM(cedar->HubList);i++)
2156 		{
2157 			h = LIST_DATA(cedar->HubList, i);
2158 			LockList(h->SessionList);
2159 			{
2160 				for (j = 0;j < LIST_NUM(h->SessionList);j++)
2161 				{
2162 					SESSION *s = LIST_DATA(h->SessionList, j);
2163 					Lock(s->lock);
2164 					{
2165 						if (Cmp(s->SessionKey, session_key, SHA1_SIZE) == 0)
2166 						{
2167 							// Session found
2168 							AddRef(s->ref);
2169 
2170 							// Unlock
2171 							Unlock(s->lock);
2172 							UnlockList(h->SessionList);
2173 							UnlockList(cedar->HubList);
2174 							return s;
2175 						}
2176 					}
2177 					Unlock(s->lock);
2178 				}
2179 			}
2180 			UnlockList(h->SessionList);
2181 		}
2182 	}
2183 	UnlockList(cedar->HubList);
2184 
2185 	return NULL;
2186 }
2187 
2188 // Create a new session key
NewSessionKey(CEDAR * cedar,UCHAR * session_key,UINT * session_key_32)2189 void NewSessionKey(CEDAR *cedar, UCHAR *session_key, UINT *session_key_32)
2190 {
2191 	// Validate arguments
2192 	if (cedar == NULL || session_key == NULL || session_key_32 == NULL)
2193 	{
2194 		return;
2195 	}
2196 
2197 	Rand(session_key, SHA1_SIZE);
2198 	*session_key_32 = Rand32();
2199 }
2200 
2201 bool if_init(SESSION *s);
2202 CANCEL *if_getcancel(SESSION *s);
2203 UINT if_getnext(SESSION *s, void **data);
2204 bool if_putpacket(SESSION *s, void *data, UINT size);
2205 void if_free(SESSION *s);
2206 
2207 
2208 // Create a server session
NewServerSession(CEDAR * cedar,CONNECTION * c,HUB * h,char * username,POLICY * policy)2209 SESSION *NewServerSession(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy)
2210 {
2211 	return NewServerSessionEx(cedar, c, h, username, policy, false, NULL);
2212 }
NewServerSessionEx(CEDAR * cedar,CONNECTION * c,HUB * h,char * username,POLICY * policy,bool inproc_mode,UCHAR * ipc_mac_address)2213 SESSION *NewServerSessionEx(CEDAR *cedar, CONNECTION *c, HUB *h, char *username, POLICY *policy, bool inproc_mode, UCHAR *ipc_mac_address)
2214 {
2215 	SESSION *s;
2216 	char name[MAX_SIZE];
2217 	char hub_name_upper[MAX_SIZE];
2218 	char user_name_upper[MAX_USERNAME_LEN + 1];
2219 	// Validate arguments
2220 	if (cedar == NULL || c == NULL || h == NULL || username == NULL || policy == NULL)
2221 	{
2222 		return NULL;
2223 	}
2224 
2225 	// Initialize the SESSION object
2226 	s = ZeroMalloc(sizeof(SESSION));
2227 
2228 	s->LoggingRecordCount = NewCounter();
2229 	s->lock = NewLock();
2230 	s->ref = NewRef();
2231 	s->Cedar = cedar;
2232 	s->ServerMode = true;
2233 	s->CreatedTime = s->LastCommTime = Tick64();
2234 	s->Traffic = NewTraffic();
2235 	s->HaltEvent = NewEvent();
2236 	s->Cancel1 = NewCancel();
2237 	s->CancelList = NewCancelList();
2238 	s->Thread = c->Thread;
2239 	s->TrafficLock = NewLock();
2240 	s->OldTraffic = NewTraffic();
2241 	s->QoS = GetServerCapsBool(cedar->Server, "b_support_qos");
2242 	AddRef(s->Thread->ref);
2243 	s->Hub = h;
2244 	s->ClientStatus = CLIENT_STATUS_ESTABLISHED;
2245 
2246 	// Delayed packet list
2247 	s->DelayedPacketList = NewList(NULL);
2248 
2249 	// Packet adapter for the HUB
2250 	s->PacketAdapter = GetHubPacketAdapter();
2251 
2252 	s->Connection = c;
2253 	AddRef(c->ref);
2254 
2255 	// Determine the new session name
2256 	StrCpy(hub_name_upper, sizeof(hub_name_upper), h->Name);
2257 	StrUpper(hub_name_upper);
2258 	StrCpy(user_name_upper, sizeof(user_name_upper), username);
2259 	StrUpper(user_name_upper);
2260 
2261 	if ((StrCmpi(username, ADMINISTRATOR_USERNAME) != 0) && (StrCmpi(username, BRIDGE_USER_NAME) != 0) || (cedar->Server == NULL || cedar->Server->ServerType == SERVER_TYPE_STANDALONE))
2262 	{
2263 		if (IsEmptyStr(c->InProcPrefix))
2264 		{
2265 			Format(name, sizeof(name), "SID-%s-%u", user_name_upper, Inc(h->SessionCounter));
2266 		}
2267 		else
2268 		{
2269 			Format(name, sizeof(name), "SID-%s-[%s]-%u", user_name_upper, c->InProcPrefix, Inc(h->SessionCounter));
2270 		}
2271 
2272 		if (h->IsVgsHub || h->IsVgsSuperRelayHub)
2273 		{
2274 			UCHAR rand[5];
2275 			char tmp[32];
2276 
2277 			Rand(rand, sizeof(rand));
2278 
2279 			BinToStr(tmp, sizeof(tmp), rand, sizeof(rand));
2280 
2281 			StrCat(name, sizeof(name), "-");
2282 			StrCat(name, sizeof(name), tmp);
2283 		}
2284 	}
2285 	else
2286 	{
2287 		UCHAR rand[SHA1_SIZE];
2288 		char tmp[MAX_SIZE];
2289 		Rand(rand, sizeof(rand));
2290 		BinToStr(tmp, sizeof(tmp), rand, 3);
2291 
2292 		if (StrCmpi(username, BRIDGE_USER_NAME) != 0)
2293 		{
2294 			Format(name, sizeof(name), "SID-%s-%s", user_name_upper,
2295 				tmp);
2296 		}
2297 		else
2298 		{
2299 			char pc_name[MAX_SIZE];
2300 			TOKEN_LIST *t;
2301 
2302 			GetMachineName(tmp, sizeof(tmp));
2303 			t = ParseToken(tmp, ".");
2304 			if (t->NumTokens >= 1)
2305 			{
2306 				StrCpy(pc_name, sizeof(pc_name), t->Token[0]);
2307 			}
2308 			else
2309 			{
2310 				StrCpy(pc_name, sizeof(pc_name), "pc");
2311 			}
2312 			FreeToken(t);
2313 
2314 			StrUpper(pc_name);
2315 
2316 			Format(name, sizeof(name), "SID-%s-%s-%u", user_name_upper, pc_name,
2317 				Inc(h->SessionCounter));
2318 		}
2319 	}
2320 
2321 	s->Name = CopyStr(name);
2322 	s->Policy = policy;
2323 	s->InProcMode = inproc_mode;
2324 
2325 	// Add a SESSION to the HUB
2326 	AddSession(h, s);
2327 
2328 	// Create a key
2329 	NewSessionKey(cedar, s->SessionKey, &s->SessionKey32);
2330 
2331 	// Generate a MAC address for IPC
2332 	if (s->InProcMode)
2333 	{
2334 		if (ipc_mac_address != NULL)
2335 		{
2336 			Copy(s->IpcMacAddress, ipc_mac_address, 6);
2337 		}
2338 		else
2339 		{
2340 			char tmp[MAX_SIZE];
2341 			char machine[MAX_SIZE];
2342 			UCHAR hash[SHA1_SIZE];
2343 
2344 			GetMachineName(machine, sizeof(machine));
2345 
2346 			Format(tmp, sizeof(tmp), "%s@%s@%u", machine, h->Name, s->UniqueId);
2347 
2348 			StrUpper(tmp);
2349 			Trim(tmp);
2350 
2351 			Hash(hash, tmp, StrLen(tmp), true);
2352 
2353 			s->IpcMacAddress[0] = 0xCA;
2354 			s->IpcMacAddress[1] = hash[1];
2355 			s->IpcMacAddress[2] = hash[2];
2356 			s->IpcMacAddress[3] = hash[3];
2357 			s->IpcMacAddress[4] = hash[4];
2358 			s->IpcMacAddress[5] = hash[5];
2359 
2360 			MacToStr(tmp, sizeof(tmp), s->IpcMacAddress);
2361 			Debug("MAC Address for IPC: %s\n", tmp);
2362 		}
2363 	}
2364 
2365 
2366 	return s;
2367 }
2368 
2369 // Check whether the specified MAC address is IPC address
IsIpcMacAddress(UCHAR * mac)2370 bool IsIpcMacAddress(UCHAR *mac)
2371 {
2372 	// Validate arguments
2373 	if (mac == NULL)
2374 	{
2375 		return false;
2376 	}
2377 
2378 	if (mac[0] == 0xCA)
2379 	{
2380 		return true;
2381 	}
2382 
2383 	return false;
2384 }
2385 
2386 // Display the session key for debugging
DebugPrintSessionKey(UCHAR * session_key)2387 void DebugPrintSessionKey(UCHAR *session_key)
2388 {
2389 	char tmp[MAX_SIZE];
2390 	// Validate arguments
2391 	if (session_key == NULL)
2392 	{
2393 		return;
2394 	}
2395 
2396 	Bit160ToStr(tmp, session_key);
2397 	Debug("SessionKey: %s\n", tmp);
2398 }
2399 
2400 // Display the status on the client
PrintStatus(SESSION * s,wchar_t * str)2401 void PrintStatus(SESSION *s, wchar_t *str)
2402 {
2403 	// Validate arguments
2404 	if (s == NULL || str == NULL || s->Account == NULL || s->Cedar->Client == NULL
2405 		|| s->Account->StatusPrinter == NULL)
2406 	{
2407 		return;
2408 	}
2409 
2410 	// Inform the status to the callback function
2411 	s->Account->StatusPrinter(s, str);
2412 }
2413 
2414 // Create a cancellation list
NewCancelList()2415 LIST *NewCancelList()
2416 {
2417 	return NewList(NULL);
2418 }
2419 
2420 // Add a Cancel to the cancellation list
AddCancelList(LIST * o,CANCEL * c)2421 void AddCancelList(LIST *o, CANCEL *c)
2422 {
2423 	UINT i;
2424 	// Validate arguments
2425 	if (o == NULL || c == NULL)
2426 	{
2427 		return;
2428 	}
2429 
2430 	for (i = 0;i < LIST_NUM(o);i++)
2431 	{
2432 		CANCEL *t = LIST_DATA(o, i);
2433 		if (t == c)
2434 		{
2435 			return;
2436 		}
2437 	}
2438 
2439 	AddRef(c->ref);
2440 	Add(o, c);
2441 }
2442 
2443 // Issue all cancellations in the cancellation list
CancelList(LIST * o)2444 void CancelList(LIST *o)
2445 {
2446 	UINT i;
2447 	// Validate arguments
2448 	if (o == NULL)
2449 	{
2450 		return;
2451 	}
2452 
2453 	for (i = 0;i < LIST_NUM(o);i++)
2454 	{
2455 		CANCEL *c = LIST_DATA(o, i);
2456 		Cancel(c);
2457 		ReleaseCancel(c);
2458 	}
2459 
2460 	DeleteAll(o);
2461 }
2462 
2463 // Release the cancellation list
ReleaseCancelList(LIST * o)2464 void ReleaseCancelList(LIST *o)
2465 {
2466 	UINT i;
2467 	// Validate arguments
2468 	if (o == NULL)
2469 	{
2470 		return;
2471 	}
2472 
2473 	for (i = 0;i < LIST_NUM(o);i++)
2474 	{
2475 		CANCEL *c = LIST_DATA(o, i);
2476 		ReleaseCancel(c);
2477 	}
2478 
2479 	ReleaseList(o);
2480 }
2481 
2482 // Notify to the client
Notify(SESSION * s,UINT code)2483 void Notify(SESSION *s, UINT code)
2484 {
2485 	// Validate arguments
2486 	if (s == NULL || s->Account == NULL || s->Cedar->Client == NULL)
2487 	{
2488 		return;
2489 	}
2490 
2491 	CiNotify(s->Cedar->Client);
2492 }
2493 
2494 
2495