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