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