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 // IPsec_PPP.c
103 // PPP protocol stack
104
105 #include "CedarPch.h"
106
107 // PPP thread
PPPThread(THREAD * thread,void * param)108 void PPPThread(THREAD *thread, void *param)
109 {
110 PPP_SESSION *p = (PPP_SESSION *)param;
111 UINT i;
112 PPP_LCP *c;
113 USHORT us;
114 UINT ui;
115 USHORT next_protocol = 0;
116 bool ret = false;
117 char ipstr1[128], ipstr2[128];
118 bool established = false;
119 // Validate arguments
120 if (thread == NULL || param == NULL)
121 {
122 return;
123 }
124
125 // Initialize
126 p->Mru1 = p->Mru2 = PPP_MRU_DEFAULT;
127 p->RecvPacketList = NewList(NULL);
128
129 p->MsChapV2_UseDoubleMsChapV2 = CedarIsThereAnyEapEnabledRadiusConfig(p->Cedar);
130
131 //// Link establishment phase
132 IPToStr(ipstr1, sizeof(ipstr1), &p->ClientIP);
133 IPToStr(ipstr2, sizeof(ipstr2), &p->ServerIP);
134 PPPLog(p, "LP_CONNECTED", p->Postfix, ipstr1, p->ClientHostname, p->ClientPort, ipstr2, p->ServerPort,
135 p->ClientSoftwareName, p->AdjustMss);
136
137 // Request the use of PAP
138 c = NewPPPLCP(PPP_LCP_CODE_REQ, 0);
139 us = Endian16(PPP_LCP_AUTH_PAP);
140 Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, &us, sizeof(USHORT)));
141 ret = PPPSendRequest(p, PPP_PROTOCOL_LCP, c);
142 FreePPPLCP(c);
143 if (ret == false)
144 {
145 if (IsTubeConnected(p->TubeRecv))
146 {
147 // PAP protocol is denied
148 p->DisconnectCauseCode = 15;
149 p->DisconnectCauseDirection = 1;
150 Debug("PPP: PAP Rejected.\n");
151
152 if (p->EnableMSCHAPv2)
153 {
154 // Try to request the use of MS-CHAPv2
155 UCHAR ms_chap_v2_code[3];
156 WRITE_USHORT(ms_chap_v2_code, PPP_LCP_AUTH_CHAP);
157 ms_chap_v2_code[2] = PPP_CHAP_ALG_MS_CHAP_V2;
158
159 c = NewPPPLCP(PPP_LCP_CODE_REQ, 0);
160 Add(c->OptionList, NewPPPOption(PPP_LCP_OPTION_AUTH, ms_chap_v2_code, sizeof(ms_chap_v2_code)));
161 ret = PPPSendRequest(p, PPP_PROTOCOL_LCP, c);
162 FreePPPLCP(c);
163
164 if (ret == false)
165 {
166 if (IsTubeConnected(p->TubeRecv))
167 {
168 // MS-CHAPv2 protocol was also rejected
169 p->DisconnectCauseCode = 15;
170 p->DisconnectCauseDirection = 1;
171 Debug("PPP: MS-CHAPv2 Rejected.\n");
172 PPPLog(p, "LP_PAP_MSCHAPV2_REJECTED");
173 }
174 }
175 else
176 {
177 // It is to be used for the MS-CHAPv2
178 p->AuthProtocol = PPP_PROTOCOL_CHAP;
179 }
180 }
181 else
182 {
183 PPPLog(p, "LP_PAP_REJECTED");
184 }
185 }
186
187 if (ret == false)
188 {
189 goto LABEL_CLEANUP;
190 }
191 }
192
193 //// Authentication phase
194
195 if (p->AuthProtocol == PPP_PROTOCOL_PAP)
196 {
197 // PAP
198 next_protocol = PPPContinueCurrentProtocolRequestListening(p, PPP_PROTOCOL_LCP);
199 if (next_protocol == 0)
200 {
201 goto LABEL_CLEANUP;
202 }
203
204 Debug("next_protocol = 0x%x\n", next_protocol);
205
206 if (next_protocol != PPP_PROTOCOL_PAP)
207 {
208 Debug("next_protocol is not PAP !!\n");
209 PPPLog(p, "LP_NEXT_PROTOCOL_IS_NOT_PAP", next_protocol);
210 goto LABEL_CLEANUP;
211 }
212
213 next_protocol = PPPContinueCurrentProtocolRequestListening(p, PPP_PROTOCOL_PAP);
214 if (next_protocol == 0 || p->AuthOk == false)
215 {
216 if (IsTubeConnected(p->TubeRecv))
217 {
218 // PAP authentication failed
219 p->DisconnectCauseCode = 15;
220 p->DisconnectCauseDirection = 1;
221 Debug("PPP: PAP Failed.\n");
222 PPPLog(p, "LP_PAP_FAILED");
223 }
224 goto LABEL_CLEANUP;
225 }
226 }
227 else
228 {
229 // MS-CHAP v2
230 PPP_PACKET *pp, *pp_ret;
231 BUF *b;
232 char machine_name[MAX_SIZE];
233 UINT64 start_tick = Tick64();
234 UINT64 timeout_tick = start_tick + (UINT64)PPP_PACKET_RECV_TIMEOUT;
235 UINT64 next_send_tick = 0;
236 USHORT pp_ret_protocol;
237
238 PPPContinueUntilFinishAllLCPOptionRequestsDetermined(p);
239
240 if (p->MsChapV2_UseDoubleMsChapV2)
241 {
242 // Use the double-MSCHAPv2 technieue
243 GetMachineHostName(machine_name, sizeof(machine_name));
244 MsChapV2Server_GenerateChallenge(p->MsChapV2_ServerChallenge);
245
246 pp = ZeroMalloc(sizeof(PPP_PACKET));
247 pp->Protocol = PPP_PROTOCOL_CHAP;
248 pp->IsControl = true;
249 pp->Lcp = NewPPPLCP(PPP_CHAP_CODE_CHALLENGE, 99);
250
251 b = NewBuf();
252 WriteBufChar(b, 16);
253 WriteBuf(b, p->MsChapV2_ServerChallenge, sizeof(p->MsChapV2_ServerChallenge));
254 WriteBuf(b, machine_name, StrLen(machine_name));
255 pp->Lcp->Data = Clone(b->Buf, b->Size);
256 pp->Lcp->DataSize = b->Size;
257 FreeBuf(b);
258
259 PPPSendPacket(p, pp);
260
261 pp_ret = PPPRecvResponsePacket(p, pp, 0, &pp_ret_protocol, false, true);
262
263 if (pp_ret != NULL)
264 {
265 // Extract the username from the first MS-CHAP v2 packet
266 if (pp_ret->Lcp != NULL && pp_ret->Lcp->DataSize >= 51)
267 {
268 BUF *b;
269
270 b = MemToBuf(pp_ret->Lcp->Data, pp_ret->Lcp->DataSize);
271
272 if (ReadBufChar(b) == 49)
273 {
274 UCHAR client_response_buffer[49];
275 char username_tmp[MAX_SIZE];
276 char id[MAX_SIZE];
277 char hub[MAX_SIZE];
278 char client_ip_tmp[256];
279 EAP_CLIENT *eap;
280 ETHERIP_ID d;
281
282 ReadBuf(b, client_response_buffer, 49);
283
284 Zero(username_tmp, sizeof(username_tmp));
285 ReadBuf(b, username_tmp, sizeof(username_tmp) - 1);
286
287 Debug("First MS-CHAPv2: id=%s\n", username_tmp);
288
289 Zero(id, sizeof(id));
290 Zero(hub, sizeof(hub));
291
292 // The user name is divided into the ID and the virtual HUB name
293 Zero(&d, sizeof(d));
294 PPPParseUsername(p->Cedar, username_tmp, &d);
295
296 StrCpy(id, sizeof(id), d.UserName);
297 StrCpy(hub, sizeof(hub), d.HubName);
298 Debug("First MS-CHAPv2: username=%s, hubname=%s\n", id, hub);
299
300 IPToStr(client_ip_tmp, sizeof(client_ip_tmp), &p->ClientIP);
301
302 eap = HubNewEapClient(p->Cedar, hub, client_ip_tmp, id, "L3:PPP");
303
304 if (eap)
305 {
306 p->EapClient = eap;
307 }
308 }
309
310 FreeBuf(b);
311 }
312
313 FreePPPPacket(pp_ret);
314 }
315
316 FreePPPPacket(pp);
317 }
318
319 // Generate a Server Challenge packet of MS-CHAP v2
320 GetMachineHostName(machine_name, sizeof(machine_name));
321
322 if (p->EapClient == NULL)
323 {
324 MsChapV2Server_GenerateChallenge(p->MsChapV2_ServerChallenge);
325 }
326 else
327 {
328 Copy(p->MsChapV2_ServerChallenge, p->EapClient->MsChapV2Challenge.Chap_ChallengeValue, 16);
329 }
330
331 pp = ZeroMalloc(sizeof(PPP_PACKET));
332 pp->Protocol = PPP_PROTOCOL_CHAP;
333 pp->IsControl = true;
334 pp->Lcp = NewPPPLCP(PPP_CHAP_CODE_CHALLENGE, 0);
335
336 b = NewBuf();
337 WriteBufChar(b, 16);
338 WriteBuf(b, p->MsChapV2_ServerChallenge, sizeof(p->MsChapV2_ServerChallenge));
339 WriteBuf(b, machine_name, StrLen(machine_name));
340 pp->Lcp->Data = Clone(b->Buf, b->Size);
341 pp->Lcp->DataSize = b->Size;
342 FreeBuf(b);
343
344 PPPSendPacket(p, pp);
345
346 pp_ret_protocol = 0;
347 pp_ret = PPPRecvResponsePacket(p, pp, 0, &pp_ret_protocol, false, false);
348
349 if (pp_ret != NULL)
350 {
351 FreePPPPacket(pp_ret);
352 }
353
354 FreePPPPacket(pp);
355
356 if (pp_ret_protocol == 0 || p->AuthOk == false)
357 {
358 if (IsTubeConnected(p->TubeRecv))
359 {
360 // MS-CHAPv2 authentication failed
361 p->DisconnectCauseCode = 15;
362 p->DisconnectCauseDirection = 1;
363 Debug("PPP: MS-CHAPv2 Failed.\n");
364 PPPLog(p, "LP_MSCHAPV2_FAILED");
365 }
366 goto LABEL_CLEANUP;
367 }
368
369 next_protocol = pp_ret_protocol;
370 }
371
372 Debug("next_protocol = 0x%x\n", next_protocol);
373
374 if (next_protocol != PPP_PROTOCOL_IPCP)
375 {
376 // Receive the protocol of non-IPCP
377 Debug("Not IPCP Protocol.\n");
378 PPPLog(p, "LP_NEXT_PROTOCOL_IS_NOT_IPCP", next_protocol);
379 goto LABEL_CLEANUP;
380 }
381
382 // Notify the IP address of the PPP server
383 c = NewPPPLCP(PPP_LCP_CODE_REQ, 0);
384 ui = Endian32(0x01000001); // 1.0.0.1
385 Add(c->OptionList, NewPPPOption(PPP_IPCP_OPTION_IP, &ui, sizeof(UINT)));
386 ret = PPPSendRequest(p, PPP_PROTOCOL_IPCP, c);
387 FreePPPLCP(c);
388 if (ret == false)
389 {
390 goto LABEL_CLEANUP;
391 }
392
393 next_protocol = PPPContinueCurrentProtocolRequestListening(p, PPP_PROTOCOL_IPCP);
394 Debug("next_protocol = 0x%x\n", next_protocol);
395
396 if (p->Ipc == NULL || IsZeroIP(&p->Ipc->ClientIPAddress))
397 {
398 // IP address is undetermined
399 PPPLog(p, "LP_IP_ADDRESS_NOT_DETERMIND");
400 goto LABEL_CLEANUP;
401 }
402
403 if (next_protocol == PPP_PROTOCOL_IP)
404 {
405 established = true;
406
407 // Do the IP communication
408 while (true)
409 {
410 TUBE *tubes[2];
411 UINT64 now = Tick64();
412 UINT r;
413
414 // Flush the ARP table of the IPC
415 IPCFlushArpTable(p->Ipc);
416
417 // Packet of client to server direction
418 while (true)
419 {
420 PPP_PACKET *pp = PPPRecvPacketForCommunication(p);
421 if (pp == NULL)
422 {
423 break;
424 }
425
426 if (pp->Protocol == PPP_PROTOCOL_IP)
427 {
428 // Since I want to send the IP packet, pass it to the IPC
429 IPCSendIPv4(p->Ipc, pp->Data, pp->DataSize);
430 }
431
432 FreePPPPacket(pp);
433 }
434
435 if (p->DhcpAllocated)
436 {
437 if (now >= p->DhcpNextRenewTime)
438 {
439 IP ip;
440
441 // DHCP renewal procedure
442 p->DhcpNextRenewTime = now + p->DhcpRenewInterval;
443
444 UINTToIP(&ip, p->ClientAddressOption.ServerAddress);
445
446 IPCDhcpRenewIP(p->Ipc, &ip);
447 }
448 }
449
450 // Happy procedure
451 IPCProcessL3Events(p->Ipc);
452
453 // Packet of server to client direction
454 while (true)
455 {
456 BLOCK *b = IPCRecvIPv4(p->Ipc);
457 PPP_PACKET *pp;
458 PPP_PACKET tmp;
459 if (b == NULL)
460 {
461 break;
462 }
463
464 // Since receiving the IP packet, send it to the client by PPP
465 pp = &tmp;
466 pp->IsControl = false;
467 pp->Protocol = PPP_PROTOCOL_IP;
468 pp->Lcp = NULL;
469 pp->Data = b->Buf;
470 pp->DataSize = b->Size;
471
472 PPPSendPacketEx(p, pp, true);
473
474 FreePPPPacketEx(pp, true);
475 Free(b);
476 }
477
478 FlushTubeFlushList(p->FlushList);
479
480 // PPP Echo Request
481 if (p->NextEchoSendTime == 0 || now >= p->NextEchoSendTime)
482 {
483 p->NextEchoSendTime = now + (UINT64)PPP_ECHO_SEND_INTERVAL;
484 AddInterrupt(p->Ipc->Interrupt, p->NextEchoSendTime);
485
486 PPPSendEchoRequest(p);
487 }
488
489 // Terminate if any tube is disconnected
490 if (IsTubeConnected(p->TubeRecv) == false || IsTubeConnected(p->TubeSend) == false)
491 {
492 // Higher-level protocol is disconnected
493 PPPLog(p, "LP_UPPER_PROTOCOL_DISCONNECTED", p->Postfix);
494 break;
495 }
496 if (IsIPCConnected(p->Ipc) == false)
497 {
498 // IPC VPN session is disconnected
499 PPPLog(p, "LP_VPN_SESSION_TERMINATED");
500 break;
501 }
502
503 // Time-out inspection
504 if ((p->LastRecvTime + (UINT64)PPP_DATA_TIMEOUT) <= now)
505 {
506 // Communication time-out occurs
507 PPPLog(p, "LP_DATA_TIMEOUT");
508 break;
509 }
510
511 // Terminate if the PPP disconnected
512 if (p->IsTerminateReceived)
513 {
514 PPPLog(p, "LP_NORMAL_TERMINATE");
515 break;
516 }
517
518 // Wait until the next packet arrives
519 tubes[0] = p->TubeRecv;
520 tubes[1] = p->Ipc->Sock->RecvTube;
521
522 r = GetNextIntervalForInterrupt(p->Ipc->Interrupt);
523 WaitForTubes(tubes, 2, MIN(r, 1234));
524 }
525
526 // Disconnected normally
527 PPPLog(p, "LP_DISCONNECTED");
528 }
529
530 if (p->DhcpAllocated)
531 {
532 // If any address is assigned from the DHCP, release it
533 IP ip;
534 char tmp[MAX_SIZE];
535
536 UINTToIP(&ip, p->ClientAddressOption.ServerAddress);
537
538 IPToStr(tmp, sizeof(tmp), &ip);
539 Debug("Releasing IP Address from DHCP Server %s...\n", tmp);
540
541 IPCDhcpFreeIP(p->Ipc, &ip);
542 IPCProcessL3Events(p->Ipc);
543
544 SleepThread(300);
545 }
546
547 LABEL_CLEANUP:
548
549 if (established == false)
550 {
551 // Disconnected Abnormally
552 PPPLog(p, "LP_DISCONNECTED_ABNORMAL");
553 }
554
555 // Disconnection process
556 PPPCleanTerminate(p);
557
558 // Release the memory
559 for (i = 0;i < LIST_NUM(p->RecvPacketList);i++)
560 {
561 PPP_PACKET *pp = LIST_DATA(p->RecvPacketList, i);
562
563 FreePPPPacket(pp);
564 }
565 ReleaseList(p->RecvPacketList);
566
567 // Release the PPP session
568 FreePPPSession(p);
569 }
570
571 // Disconnect the PPP cleanly
PPPCleanTerminate(PPP_SESSION * p)572 void PPPCleanTerminate(PPP_SESSION *p)
573 {
574 PPP_PACKET *pp;
575 PPP_PACKET *res;
576 UINT64 giveup_tick = Tick64() + (UINT64)PPP_TERMINATE_TIMEOUT;
577 // Validate arguments
578 if (p == NULL)
579 {
580 return;
581 }
582
583 // Send a Terminate Request
584 pp = ZeroMalloc(sizeof(PPP_PACKET));
585 pp->IsControl = true;
586 pp->Protocol = PPP_PROTOCOL_LCP;
587 pp->Lcp = NewPPPLCP(PPP_LCP_CODE_TERMINATE_REQ, p->NextId++);
588 Debug("PPP: Terminate Request is Sent.\n");
589 if (PPPSendPacket(p, pp) == false)
590 {
591 goto LABEL_CLEANUP;
592 }
593
594 // Wait for Terminate ACK
595 while (true)
596 {
597 UINT64 now = Tick64();
598 UINT interval;
599
600 if (now >= giveup_tick)
601 {
602 break;
603 }
604
605 while (true)
606 {
607 if (IsTubeConnected(p->TubeRecv) == false)
608 {
609 break;
610 }
611
612 res = PPPRecvPacket(p, true);
613
614 if (res == NULL)
615 {
616 break;
617 }
618
619 if (res->IsControl && res->Protocol == PPP_PROTOCOL_LCP && res->Lcp->Code == PPP_LCP_CODE_TERMINATE_ACK)
620 {
621 Debug("PPP: Terminate ACK is Received.\n");
622 FreePPPPacket(res);
623 goto LABEL_CLEANUP;
624 }
625
626 FreePPPPacket(res);
627 }
628
629 interval = (UINT)(giveup_tick - now);
630
631 Wait(p->TubeRecv->Event, interval);
632 }
633
634 LABEL_CLEANUP:
635 FreePPPPacket(pp);
636 }
637
638 // Wait until all pending LCP option are determined
PPPContinueUntilFinishAllLCPOptionRequestsDetermined(PPP_SESSION * p)639 bool PPPContinueUntilFinishAllLCPOptionRequestsDetermined(PPP_SESSION *p)
640 {
641 USHORT received_protocol = 0;
642 // Validate arguments
643 if (p == NULL)
644 {
645 return false;
646 }
647
648 PPPRecvResponsePacket(p, NULL, PPP_PROTOCOL_LCP, &received_protocol, true, false);
649
650 return p->ClientLCPOptionDetermined;
651 }
652
653 // Continue the processing of the request packet protocol on the current PPP
PPPContinueCurrentProtocolRequestListening(PPP_SESSION * p,USHORT protocol)654 USHORT PPPContinueCurrentProtocolRequestListening(PPP_SESSION *p, USHORT protocol)
655 {
656 USHORT received_protocol = 0;
657 // Validate arguments
658 if (p == NULL)
659 {
660 return 0;
661 }
662
663 PPPRecvResponsePacket(p, NULL, protocol, &received_protocol, false, false);
664
665 return received_protocol;
666 }
667
668 // Send the PPP Echo Request
PPPSendEchoRequest(PPP_SESSION * p)669 void PPPSendEchoRequest(PPP_SESSION *p)
670 {
671 PPP_PACKET *pp;
672 char echo_data[]= "\0\0\0\0Aho Baka Manuke";
673 // Validate arguments
674 if (p == NULL)
675 {
676 return;
677 }
678
679 pp = ZeroMalloc(sizeof(PPP_PACKET));
680 pp->Protocol = PPP_PROTOCOL_LCP;
681 pp->IsControl = true;
682 pp->Lcp = NewPPPLCP(PPP_LCP_CODE_ECHO_REQUEST, p->NextId++);
683
684 pp->Lcp->Data = Clone(echo_data, sizeof(echo_data));
685 pp->Lcp->DataSize = sizeof(echo_data);
686
687 PPPSendPacket(p, pp);
688
689 FreePPPPacket(pp);
690 }
691
692 // Send a request packet in the PPP
PPPSendRequest(PPP_SESSION * p,USHORT protocol,PPP_LCP * c)693 bool PPPSendRequest(PPP_SESSION *p, USHORT protocol, PPP_LCP *c)
694 {
695 PPP_PACKET *pp;
696 PPP_PACKET *pp2;
697 bool ret = false;
698 // Validate arguments
699 if (p == NULL || c == NULL)
700 {
701 return false;
702 }
703
704 pp = ZeroMalloc(sizeof(PPP_PACKET));
705 pp->Protocol = protocol;
706 pp->IsControl = true;
707 pp->Lcp = c;
708 pp->Lcp->Id = p->NextId++;
709
710 // Send the PPP packet
711 if (PPPSendPacket(p, pp) == false)
712 {
713 goto LABEL_ERROR;
714 }
715
716 // Receive a corresponding PPP packet
717 pp2 = PPPRecvResponsePacket(p, pp, 0, NULL, false, false);
718
719 if (pp2 != NULL)
720 {
721 if (protocol == PPP_PROTOCOL_LCP || protocol == PPP_PROTOCOL_IPCP)
722 {
723 if (!PPP_LCP_CODE_IS_NEGATIVE(pp2->Lcp->Code))
724 {
725 // A positive response is received
726 ret = true;
727 }
728 }
729 }
730
731 FreePPPPacket(pp2);
732 Free(pp);
733
734 return ret;
735
736 LABEL_ERROR:
737 Free(pp);
738 return false;
739 }
740
741 // Check whether the Virtual HUB with the specified name exist?
IsHubExistsWithLock(CEDAR * cedar,char * hubname)742 bool IsHubExistsWithLock(CEDAR *cedar, char *hubname)
743 {
744 bool ret = false;
745 // Validate arguments
746 if (cedar == NULL || hubname == NULL)
747 {
748 return false;
749 }
750
751 LockList(cedar->HubList);
752 {
753 ret = IsHub(cedar, hubname);
754 }
755 UnlockList(cedar->HubList);
756
757 return ret;
758 }
759
760 // Separate into the user name and the Virtual HUB name by analyzing the string
PPPParseUsername(CEDAR * cedar,char * src_username,ETHERIP_ID * dst)761 bool PPPParseUsername(CEDAR *cedar, char *src_username, ETHERIP_ID *dst)
762 {
763 UINT i, len, last_at, first_en;
764 char token1[MAX_SIZE]; // username
765 char token2[MAX_SIZE]; // hub_name
766 char src[MAX_SIZE];
767 // Validate arguments
768 Zero(dst, sizeof(ETHERIP_ID));
769 if (cedar == NULL || dst == NULL)
770 {
771 return false;
772 }
773
774 StrCpy(src, sizeof(src), src_username);
775 Trim(src);
776
777 // Search for the first "\\" in the string
778 len = StrLen(src);
779
780 first_en = SearchStrEx(src, "\\", 0, true);
781
782 if (first_en != INFINITE && first_en >= 1 && (first_en < (len - 1)))
783 {
784 StrCpy(token1, sizeof(token1), src + first_en + 1);
785 StrCpy(token2, sizeof(token2), src);
786 token2[first_en] = 0;
787
788 // Confirm whether the hubname exists if the virtual HUB name is
789 // specified like as hubname\username
790 if (IsHubExistsWithLock(cedar, token2) == false)
791 {
792 // If the hubname does not exist, restore to the original name
793 StrCpy(token1, sizeof(token1), src);
794 ClearStr(token2, sizeof(token2));
795 }
796 }
797 else
798 {
799 // Search for the last "@" in the string
800 len = StrLen(src);
801 last_at = INFINITE;
802 for (i = 0;i < len;i++)
803 {
804 char c = src[i];
805
806 if (c == '@')
807 {
808 last_at = i;
809 }
810 }
811
812 Zero(token1, sizeof(token1));
813 Zero(token2, sizeof(token2));
814
815 if (last_at == INFINITE)
816 {
817 // "@" is not specified
818 StrCpy(token1, sizeof(token1), src);
819 }
820 else
821 {
822 // Split with last "@"
823 StrCpy(token1, sizeof(token1), src);
824 token1[last_at] = 0;
825
826 StrCpy(token2, sizeof(token2), src + last_at + 1);
827 }
828
829 // Check whether such Virtual HUB exists If the virtual HUB name is specified
830 if (IsEmptyStr(token2) == false)
831 {
832 if (IsHubExistsWithLock(cedar, token2) == false)
833 {
834 // Because the specified virtual HUB name doesn't exist, it's considered to be a part of the user name
835 StrCpy(token1, sizeof(token1), src);
836
837 ClearStr(token2, sizeof(token2));
838 }
839 }
840 }
841
842 if (IsEmptyStr(token2))
843 {
844 // Select the default Virtual HUB if the Virtual HUB name is not specified
845 StrCpy(token2, sizeof(token2), SERVER_DEFAULT_HUB_NAME);
846 if (cedar->Server != NULL && cedar->Server->IPsecServer != NULL)
847 {
848 Lock(cedar->Server->IPsecServer->LockSettings);
849 {
850 IPsecNormalizeServiceSetting(cedar->Server->IPsecServer);
851
852 StrCpy(token2, sizeof(token2), cedar->Server->IPsecServer->Services.L2TP_DefaultHub);
853 }
854 Unlock(cedar->Server->IPsecServer->LockSettings);
855 }
856
857 }
858
859 // Return the results
860 StrCpy(dst->HubName, sizeof(dst->HubName), token2);
861 StrCpy(dst->UserName, sizeof(dst->UserName), token1);
862
863 return true;
864 }
865
866 // Process the PPP request packet
PPPProcessRequestPacket(PPP_SESSION * p,PPP_PACKET * req)867 PPP_PACKET *PPPProcessRequestPacket(PPP_SESSION *p, PPP_PACKET *req)
868 {
869 UINT i;
870 PPP_PACKET *ret = NULL;
871 UINT num_not_supported = 0;
872 UINT num_not_accepted = 0;
873 bool no_return_option_list = false;
874 UINT return_code = 0;
875 BUF *lcp_ret_data = NULL;
876 // Validate arguments
877 if (p == NULL || req == NULL || req->Lcp == NULL)
878 {
879 return NULL;
880 }
881
882 // Initialize
883 for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
884 {
885 PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
886
887 t->IsAccepted = false;
888 t->IsSupported = false;
889 t->AltDataSize = 0;
890 Zero(t->AltData, sizeof(t->AltData));
891 }
892
893 // Process by scanning the specified option value
894 if (req->Protocol == PPP_PROTOCOL_LCP)
895 {
896 // LCP
897 if (req->Lcp == NULL)
898 {
899 return NULL;
900 }
901 for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
902 {
903 PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
904
905 switch (t->Type)
906 {
907 case PPP_LCP_OPTION_MRU:
908 // MRU
909 t->IsSupported = true;
910 if (t->DataSize == sizeof(USHORT))
911 {
912 UINT value = READ_USHORT(t->Data);
913 if (value < PPP_MRU_MIN || value > PPP_MRU_MAX)
914 {
915 t->IsAccepted = false;
916 value = MAKESURE(value, PPP_MRU_MIN, PPP_MRU_MAX);
917 WRITE_USHORT(t->AltData, value);
918 t->AltDataSize = sizeof(USHORT);
919 }
920 else
921 {
922 p->Mru1 = value;
923 Debug("PPP: Client set %u as MRU\n", p->Mru1);
924 t->IsAccepted = true;
925 }
926 }
927 break;
928 }
929 }
930 }
931 else if (req->Protocol == PPP_PROTOCOL_CHAP)
932 {
933 bool ok = false;
934 char ret_str[MAX_SIZE];
935
936 no_return_option_list = true;
937
938 if (p->Ipc == NULL)
939 {
940 // MS-CHAPv2
941 if (req->Lcp->DataSize >= 51)
942 {
943 BUF *b;
944
945 b = NewBuf();
946
947 WriteBuf(b, req->Lcp->Data, req->Lcp->DataSize);
948 SeekBuf(b, 0, 0);
949
950 if (ReadBufChar(b) == 49)
951 {
952 UCHAR client_response_buffer[49];
953 UCHAR *client_challenge_16;
954 UCHAR *client_response_24;
955 char username_tmp[MAX_SIZE];
956 IPC *ipc = NULL;
957 char id[MAX_SIZE];
958 char hub[MAX_SIZE];
959 char password[MAX_SIZE];
960 char server_challenge_hex[MAX_SIZE];
961 char client_challenge_hex[MAX_SIZE];
962 char client_response_hex[MAX_SIZE];
963 char eap_client_hex[64];
964 ETHERIP_ID d;
965 UINT error_code;
966 UINT64 eap_client_ptr = (UINT64)p->EapClient;
967
968 ReadBuf(b, client_response_buffer, 49);
969
970 Zero(username_tmp, sizeof(username_tmp));
971 ReadBuf(b, username_tmp, sizeof(username_tmp) - 1);
972
973 client_challenge_16 = client_response_buffer + 0;
974 client_response_24 = client_response_buffer + 16 + 8;
975
976 Copy(p->MsChapV2_ClientChallenge, client_challenge_16, 16);
977 Copy(p->MsChapV2_ClientResponse, client_response_24, 24);
978
979 Debug("MS-CHAPv2: id=%s\n", username_tmp);
980
981 Zero(id, sizeof(id));
982 Zero(hub, sizeof(hub));
983
984 // The user name is divided into the ID and the virtual HUB name
985 Zero(&d, sizeof(d));
986 PPPParseUsername(p->Cedar, username_tmp, &d);
987
988 StrCpy(id, sizeof(id), d.UserName);
989 StrCpy(hub, sizeof(hub), d.HubName);
990
991 // Convert the MS-CHAPv2 data to a password string
992 BinToStr(server_challenge_hex, sizeof(server_challenge_hex),
993 p->MsChapV2_ServerChallenge, sizeof(p->MsChapV2_ServerChallenge));
994 BinToStr(client_challenge_hex, sizeof(client_challenge_hex),
995 p->MsChapV2_ClientChallenge, sizeof(p->MsChapV2_ClientChallenge));
996 BinToStr(client_response_hex, sizeof(client_response_hex),
997 p->MsChapV2_ClientResponse, sizeof(p->MsChapV2_ClientResponse));
998 BinToStr(eap_client_hex, sizeof(eap_client_hex),
999 &eap_client_ptr, 8);
1000
1001 Format(password, sizeof(password), "%s%s:%s:%s:%s:%s",
1002 IPC_PASSWORD_MSCHAPV2_TAG,
1003 username_tmp,
1004 server_challenge_hex,
1005 client_challenge_hex,
1006 client_response_hex,
1007 eap_client_hex);
1008
1009 // Attempt to connect with IPC
1010 ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
1011 &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
1012 p->ClientHostname, p->CryptName, false, p->AdjustMss, p->EapClient, NULL,
1013 IPC_LAYER_3);
1014
1015 if (ipc != NULL)
1016 {
1017 p->Ipc = ipc;
1018
1019 Copy(p->MsChapV2_ServerResponse, ipc->MsChapV2_ServerResponse, 20);
1020
1021 ok = true;
1022 }
1023 else
1024 {
1025 switch (error_code)
1026 {
1027 default:
1028 // Normal authentication error
1029 p->MsChapV2_ErrorCode = 691;
1030 break;
1031
1032 case ERR_MSCHAP2_PASSWORD_NEED_RESET:
1033 // Authentication errors due to compatibility issues of the password
1034 p->MsChapV2_ErrorCode = 942;
1035 break;
1036 }
1037 }
1038 }
1039
1040 FreeBuf(b);
1041 }
1042 }
1043 else
1044 {
1045 // Return success for a request from the second time when it is successfully authenticated once
1046 ok = true;
1047 }
1048
1049 // Generate a response options string
1050 if (ok == false)
1051 {
1052 // In the case of failure
1053 char hex[MAX_SIZE];
1054 BinToStr(hex, sizeof(hex), p->MsChapV2_ServerChallenge, 16);
1055
1056 Format(ret_str, sizeof(ret_str),
1057 "E=%u R=0 C=%s V=3", p->MsChapV2_ErrorCode, hex);
1058
1059 return_code = PPP_CHAP_CODE_FAILURE;
1060 }
1061 else
1062 {
1063 // In the case of success
1064 char hex[MAX_SIZE];
1065 BinToStr(hex, sizeof(hex), p->MsChapV2_ServerResponse, 20);
1066
1067 Format(ret_str, sizeof(ret_str),
1068 "S=%s", hex);
1069
1070 return_code = PPP_CHAP_CODE_SUCCESS;
1071
1072 p->AuthOk = true;
1073 }
1074
1075 lcp_ret_data = NewBuf();
1076 WriteBuf(lcp_ret_data, ret_str, StrLen(ret_str));
1077 }
1078 else if (req->Protocol == PPP_PROTOCOL_PAP)
1079 {
1080 UCHAR *data;
1081 UINT size;
1082 bool ok = false;
1083
1084 no_return_option_list = true;
1085
1086 if (p->Ipc == NULL)
1087 {
1088 // PAP
1089
1090 // Extract the ID and the password
1091 data = req->Lcp->Data;
1092 size = req->Lcp->DataSize;
1093
1094 if (size >= 1)
1095 {
1096 UCHAR len_id = data[0];
1097 data++;
1098 size--;
1099
1100 if (size >= len_id)
1101 {
1102 char username[256];
1103 char password[256];
1104
1105 Zero(username, sizeof(username));
1106 Zero(password, sizeof(password));
1107
1108 Copy(username, data, len_id);
1109 data += len_id;
1110 size -= len_id;
1111
1112 if (size >= 1)
1113 {
1114 UCHAR len_pass = data[0];
1115 data++;
1116 size--;
1117
1118 if (size >= len_pass)
1119 {
1120 IPC *ipc;
1121 char id[MAX_SIZE];
1122 char hub[MAX_SIZE];
1123 ETHERIP_ID d;
1124
1125 Zero(id, sizeof(id));
1126 Zero(hub, sizeof(hub));
1127
1128 Copy(password, data, len_pass);
1129
1130 Debug("PPP: id=%s, pw=%s\n", username, password);
1131
1132 // The user name is divided into the ID and the virtual HUB name
1133 Zero(&d, sizeof(d));
1134 PPPParseUsername(p->Cedar, username, &d);
1135
1136 StrCpy(id, sizeof(id), d.UserName);
1137 StrCpy(hub, sizeof(hub), d.HubName);
1138
1139 if (IsEmptyStr(id) == false)
1140 {
1141 // Attempt to connect with IPC
1142 UINT error_code;
1143
1144 ipc = NewIPC(p->Cedar, p->ClientSoftwareName, p->Postfix, hub, id, password,
1145 &error_code, &p->ClientIP, p->ClientPort, &p->ServerIP, p->ServerPort,
1146 p->ClientHostname, p->CryptName, false, p->AdjustMss, NULL, NULL,
1147 IPC_LAYER_3);
1148
1149 if (ipc != NULL)
1150 {
1151 p->Ipc = ipc;
1152 ok = true;
1153 }
1154 }
1155 }
1156 }
1157 }
1158 }
1159 }
1160 else
1161 {
1162 // Return success for a request from the second time when it is successfully authenticated once
1163 ok = true;
1164 }
1165
1166 if (ok == false)
1167 {
1168 // Authentication failure
1169 return_code = PPP_PAP_CODE_NAK;
1170 }
1171 else
1172 {
1173 // Authentication success
1174 return_code = PPP_PAP_CODE_ACK;
1175
1176 p->AuthOk = true;
1177 }
1178 }
1179 else if (req->Protocol == PPP_PROTOCOL_IPCP)
1180 {
1181 PPP_IPOPTION o;
1182 // Get the IP options data from the request data
1183 if (PPPGetIPOptionFromLCP(&o, req->Lcp))
1184 {
1185 PPP_IPOPTION res;
1186 IP subnet;
1187 IP gw;
1188
1189 if (IsZeroIP(&o.IpAddress) == false)
1190 {
1191 if (p->Ipc->Policy->DHCPForce == false)
1192 {
1193 if (p->DhcpAllocated == false)
1194 {
1195 if (p->UseStaticIPAddress == false)
1196 {
1197 DHCP_OPTION_LIST cao;
1198
1199 // The client specify an IP address
1200 Zero(&cao, sizeof(cao));
1201
1202 cao.ClientAddress = IPToUINT(&o.IpAddress);
1203
1204 Copy(&p->ClientAddressOption, &cao, sizeof(cao));
1205
1206 p->UseStaticIPAddress = true;
1207 }
1208 }
1209 }
1210 }
1211 else
1212 {
1213 p->UseStaticIPAddress = false;
1214 }
1215
1216 if (p->UseStaticIPAddress)
1217 {
1218 if (p->DhcpIpInformTried == false)
1219 {
1220 // Get additional information such as the subnet mask from the DHCP server
1221 DHCP_OPTION_LIST cao;
1222 IP client_ip;
1223
1224 IP subnet;
1225 IP zero;
1226
1227 SetIP(&subnet, 255, 0, 0, 0);
1228 Zero(&zero, sizeof(zero));
1229
1230 UINTToIP(&client_ip, p->ClientAddressOption.ClientAddress);
1231
1232 Zero(&cao, sizeof(cao));
1233
1234 IPCSetIPv4Parameters(p->Ipc, &client_ip, &subnet, &zero, NULL);
1235
1236 p->DhcpIpInformTried = true;
1237
1238 PPPLog(p, "LP_DHCP_INFORM_TRYING");
1239
1240 if (IPCDhcpRequestInformIP(p->Ipc, &cao, p->TubeRecv, &client_ip))
1241 {
1242 Debug("IPCDhcpRequestInformIP ok.\n");
1243 Copy(&p->ClientAddressOption, &cao, sizeof(cao));
1244 p->ClientAddressOption.ClientAddress = IPToUINT(&client_ip);
1245
1246 if (true)
1247 {
1248 char server_ip_str[64];
1249 char subnet_str[64], defgw_str[64];
1250 char dns1_str[64], dns2_str[64];
1251 char wins1_str[64], wins2_str[64];
1252
1253 IPToStr32(server_ip_str, sizeof(server_ip_str), cao.ServerAddress);
1254 IPToStr32(subnet_str, sizeof(subnet_str), cao.SubnetMask);
1255 IPToStr32(defgw_str, sizeof(defgw_str), cao.Gateway);
1256 IPToStr32(dns1_str, sizeof(dns1_str), cao.DnsServer);
1257 IPToStr32(dns2_str, sizeof(dns2_str), cao.DnsServer2);
1258 IPToStr32(wins1_str, sizeof(wins1_str), cao.WinsServer);
1259 IPToStr32(wins2_str, sizeof(wins2_str), cao.WinsServer2);
1260
1261 PPPLog(p, "LP_DHCP_INFORM_OK",
1262 subnet_str, defgw_str, cao.DomainName,
1263 dns1_str, dns2_str, wins1_str, wins2_str,
1264 server_ip_str);
1265 }
1266 }
1267 else
1268 {
1269 Debug("IPCDhcpRequestInformIP failed.\n");
1270
1271 PPPLog(p, "LP_DHCP_INFORM_NG");
1272 }
1273
1274 IPCSetIPv4Parameters(p->Ipc, &zero, &zero, &zero, NULL);
1275 }
1276 }
1277 else
1278 {
1279 // Get an IP address from a DHCP server
1280 if (p->DhcpIpAllocTried == false)
1281 {
1282 DHCP_OPTION_LIST cao;
1283
1284 Zero(&cao, sizeof(cao));
1285 p->DhcpIpAllocTried = true;
1286
1287 PPPLog(p, "LP_DHCP_REQUEST_TRYING");
1288
1289 if (IPCDhcpAllocateIP(p->Ipc, &cao, p->TubeRecv))
1290 {
1291 UINT t;
1292
1293 Debug("IPCDhcpAllocateIP ok.\n");
1294
1295 // IP address has been determined
1296 Copy(&p->ClientAddressOption, &cao, sizeof(cao));
1297
1298 p->DhcpAllocated = true;
1299
1300 // Determine the DHCP update interval
1301 t = cao.LeaseTime;
1302 if (t == 0)
1303 {
1304 t = 600;
1305 }
1306
1307 t = t / 3;
1308
1309 if (t == 0)
1310 {
1311 t = 1;
1312 }
1313
1314 p->DhcpRenewInterval = (UINT64)t * (UINT64)1000;
1315 p->DhcpNextRenewTime = Tick64() + p->DhcpRenewInterval;
1316
1317 if (true)
1318 {
1319 char client_ip_str[64], server_ip_str[64];
1320 char subnet_str[64], defgw_str[64];
1321 char dns1_str[64], dns2_str[64];
1322 char wins1_str[64], wins2_str[64];
1323
1324 IPToStr32(client_ip_str, sizeof(client_ip_str), cao.ClientAddress);
1325 IPToStr32(server_ip_str, sizeof(server_ip_str), cao.ServerAddress);
1326 IPToStr32(subnet_str, sizeof(subnet_str), cao.SubnetMask);
1327 IPToStr32(defgw_str, sizeof(defgw_str), cao.Gateway);
1328 IPToStr32(dns1_str, sizeof(dns1_str), cao.DnsServer);
1329 IPToStr32(dns2_str, sizeof(dns2_str), cao.DnsServer2);
1330 IPToStr32(wins1_str, sizeof(wins1_str), cao.WinsServer);
1331 IPToStr32(wins2_str, sizeof(wins2_str), cao.WinsServer2);
1332
1333 PPPLog(p, "LP_DHCP_REQUEST_OK",
1334 client_ip_str, subnet_str, defgw_str, cao.DomainName,
1335 dns1_str, dns2_str, wins1_str, wins2_str,
1336 server_ip_str, cao.LeaseTime);
1337 }
1338 }
1339 else
1340 {
1341 Debug("IPCDhcpAllocateIP failed.\n");
1342
1343 PPPLog(p, "LP_DHCP_REQUEST_NG");
1344 }
1345 }
1346 }
1347
1348 if (IsValidUnicastIPAddressUINT4(p->ClientAddressOption.ClientAddress) &&
1349 p->ClientAddressOption.SubnetMask != 0)
1350 {
1351 // Success to determine the address
1352 UINTToIP(&subnet, p->ClientAddressOption.SubnetMask);
1353 UINTToIP(&gw, p->ClientAddressOption.Gateway);
1354
1355 Zero(&res, sizeof(res));
1356 UINTToIP(&res.IpAddress, p->ClientAddressOption.ClientAddress);
1357 UINTToIP(&res.DnsServer1, p->ClientAddressOption.DnsServer);
1358 UINTToIP(&res.DnsServer2, p->ClientAddressOption.DnsServer2);
1359 UINTToIP(&res.WinsServer1, p->ClientAddressOption.WinsServer);
1360 UINTToIP(&res.WinsServer2, p->ClientAddressOption.WinsServer2);
1361
1362 if (IPCSetIPv4Parameters(p->Ipc, &res.IpAddress, &subnet, &gw, &p->ClientAddressOption.ClasslessRoute))
1363 {
1364 char client_ip_str[64];
1365 char subnet_str[64], defgw_str[64];
1366 char dns1_str[64], dns2_str[64];
1367 char wins1_str[64], wins2_str[64];
1368
1369 // IPv4 parameters have been set for the first time
1370 Debug("Param First Set.\n");
1371
1372 IPToStr(client_ip_str, sizeof(client_ip_str), &res.IpAddress);
1373 IPToStr(subnet_str, sizeof(subnet_str), &subnet);
1374 IPToStr(defgw_str, sizeof(defgw_str), &gw);
1375 IPToStr(dns1_str, sizeof(dns1_str), &res.DnsServer1);
1376 IPToStr(dns2_str, sizeof(dns2_str), &res.DnsServer2);
1377 IPToStr(wins1_str, sizeof(wins1_str), &res.WinsServer1);
1378 IPToStr(wins2_str, sizeof(wins2_str), &res.WinsServer2);
1379
1380 PPPLog(p, "LP_SET_IPV4_PARAM", client_ip_str, subnet_str,
1381 defgw_str, dns1_str, dns2_str, wins1_str, wins2_str);
1382 }
1383
1384 PPPSetIPOptionToLCP(&res, req->Lcp, true);
1385 }
1386 else
1387 {
1388 // Failed to determine the address
1389 Debug("IP Address Determination Failed.\n");
1390
1391 Zero(&res, sizeof(res));
1392
1393 PPPSetIPOptionToLCP(&res, req->Lcp, true);
1394 }
1395 }
1396 }
1397
1398 // Assemble the LCP response packet based on the results
1399 for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
1400 {
1401 PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
1402
1403 if (t->IsSupported == false)
1404 {
1405 num_not_supported++;
1406 }
1407
1408 if (t->IsAccepted == false)
1409 {
1410 num_not_accepted++;
1411 }
1412 }
1413
1414 // Create a PPP response packet
1415 ret = ZeroMalloc(sizeof(PPP_PACKET));
1416 ret->IsControl = true;
1417 ret->Protocol = req->Protocol;
1418
1419 if (no_return_option_list == false)
1420 {
1421 // Response by attaching an optional list
1422 if (num_not_supported >= 1)
1423 {
1424 // Return a Reject if there are unsupported parameters
1425 ret->Lcp = NewPPPLCP(PPP_LCP_CODE_REJECT, req->Lcp->Id);
1426
1427 for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
1428 {
1429 PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
1430
1431 if (t->IsSupported == false)
1432 {
1433 // Attach the original option value as is
1434 Add(ret->Lcp->OptionList, NewPPPOption(t->Type, t->Data, t->DataSize));
1435 }
1436 }
1437 }
1438 else if (num_not_accepted >= 1)
1439 {
1440 // Return a NAK if there are any unacceptable parameter
1441 // even that all parameters are supported
1442 ret->Lcp = NewPPPLCP(PPP_LCP_CODE_NAK, req->Lcp->Id);
1443
1444 for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
1445 {
1446 PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
1447
1448 if (t->IsAccepted == false)
1449 {
1450 // Replace the original option value with an acceptable value
1451 Add(ret->Lcp->OptionList, NewPPPOption(t->Type, t->AltData, t->AltDataSize));
1452 }
1453 }
1454 }
1455 else
1456 {
1457 // Return an ACK if all parameters are accepted
1458 ret->Lcp = NewPPPLCP(PPP_LCP_CODE_ACK, req->Lcp->Id);
1459
1460 for (i = 0;i < LIST_NUM(req->Lcp->OptionList);i++)
1461 {
1462 PPP_OPTION *t = LIST_DATA(req->Lcp->OptionList, i);
1463
1464 // Attach the original option value as is
1465 Add(ret->Lcp->OptionList, NewPPPOption(t->Type, t->Data, t->DataSize));
1466 }
1467
1468 if (req->Protocol == PPP_PROTOCOL_LCP)
1469 {
1470 p->ClientLCPOptionDetermined = true;
1471 }
1472 }
1473 }
1474 else
1475 {
1476 // Response without attaching a list of options
1477 ret->Lcp = NewPPPLCP(return_code, req->Lcp->Id);
1478
1479 if (lcp_ret_data != NULL && lcp_ret_data->Size >= 1)
1480 {
1481 ret->Lcp->Data = Clone(lcp_ret_data->Buf, lcp_ret_data->Size);
1482 ret->Lcp->DataSize = lcp_ret_data->Size;
1483 }
1484 }
1485
1486 if (lcp_ret_data != NULL)
1487 {
1488 FreeBuf(lcp_ret_data);
1489 }
1490
1491 return ret;
1492 }
1493
1494 // Set the IP options of PPP to LCP
PPPSetIPOptionToLCP(PPP_IPOPTION * o,PPP_LCP * c,bool only_modify)1495 bool PPPSetIPOptionToLCP(PPP_IPOPTION *o, PPP_LCP *c, bool only_modify)
1496 {
1497 bool ret = false;
1498 // Validate arguments
1499 if (c == NULL || o == NULL)
1500 {
1501 return false;
1502 }
1503
1504 ret = PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_IP, &o->IpAddress, only_modify);
1505
1506 PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_DNS1, &o->DnsServer1, only_modify);
1507 PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_DNS2, &o->DnsServer2, only_modify);
1508 PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_WINS1, &o->WinsServer1, only_modify);
1509 PPPSetIPAddressValueToLCP(c, PPP_IPCP_OPTION_WINS2, &o->WinsServer2, only_modify);
1510
1511 return ret;
1512 }
1513
1514 // Get the IP options of PPP from LCP
PPPGetIPOptionFromLCP(PPP_IPOPTION * o,PPP_LCP * c)1515 bool PPPGetIPOptionFromLCP(PPP_IPOPTION *o, PPP_LCP *c)
1516 {
1517 bool ret;
1518 // Validate arguments
1519 if (c == NULL || o == NULL)
1520 {
1521 return false;
1522 }
1523
1524 Zero(o, sizeof(PPP_IPOPTION));
1525
1526 ret = PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_IP, &o->IpAddress);
1527
1528 PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_DNS1, &o->DnsServer1);
1529 PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_DNS2, &o->DnsServer2);
1530 PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_WINS1, &o->WinsServer1);
1531 PPPGetIPAddressValueFromLCP(c, PPP_IPCP_OPTION_WINS2, &o->WinsServer2);
1532
1533 return ret;
1534 }
1535
1536 // Set the IP address data to the option list of the LCP
PPPSetIPAddressValueToLCP(PPP_LCP * c,UINT type,IP * ip,bool only_modify)1537 bool PPPSetIPAddressValueToLCP(PPP_LCP *c, UINT type, IP *ip, bool only_modify)
1538 {
1539 IP ip2;
1540 UINT ui;
1541 // Validate arguments
1542 if (c == NULL || ip == NULL)
1543 {
1544 return false;
1545 }
1546
1547 ui = IPToUINT(ip);
1548
1549 if (PPPGetIPAddressValueFromLCP(c, type, &ip2))
1550 {
1551 PPP_OPTION *opt;
1552 opt = GetOptionValue(c, type);
1553
1554 if (opt != NULL)
1555 {
1556 if (IsZeroIP(ip) == false)
1557 {
1558 if (CmpIpAddr(&ip2, ip) == 0)
1559 {
1560 // No change
1561 opt->IsAccepted = true;
1562 opt->IsSupported = true;
1563 }
1564 else
1565 {
1566 // Changed
1567 opt->IsAccepted = false;
1568 opt->IsSupported = true;
1569 opt->AltDataSize = 4;
1570 Copy(opt->AltData, &ui, 4);
1571 }
1572 }
1573 else
1574 {
1575 // The parameter itself is not supported
1576 // (if the IP address is 0.0.0.0)
1577 opt->IsSupported = false;
1578 opt->IsAccepted = false;
1579 }
1580 }
1581
1582 return true;
1583 }
1584 else
1585 {
1586 if (IsZeroIP(ip) == false)
1587 {
1588 // Add as a new item
1589 if (only_modify != false)
1590 {
1591 return false;
1592 }
1593 else
1594 {
1595 PPP_OPTION *opt2 = NewPPPOption(type, &ui, 4);
1596 opt2->IsAccepted = opt2->IsSupported = true;
1597
1598 Add(c->OptionList, opt2);
1599
1600 return true;
1601 }
1602 }
1603 else
1604 {
1605 return false;
1606 }
1607 }
1608 }
1609
1610 // Get the IP address data from the option list of the LCP
PPPGetIPAddressValueFromLCP(PPP_LCP * c,UINT type,IP * ip)1611 bool PPPGetIPAddressValueFromLCP(PPP_LCP *c, UINT type, IP *ip)
1612 {
1613 PPP_OPTION *opt;
1614 UINT ui;
1615 // Validate arguments
1616 if (c == NULL || ip == NULL)
1617 {
1618 return false;
1619 }
1620
1621 opt = GetOptionValue(c, type);
1622 if (opt == NULL)
1623 {
1624 return false;
1625 }
1626
1627 if (opt->DataSize != 4)
1628 {
1629 return false;
1630 }
1631
1632 opt->IsSupported = true;
1633
1634 ui = *((UINT *)opt->Data);
1635
1636 UINTToIP(ip, ui);
1637
1638 return true;
1639 }
1640
1641 // Process corresponding to the incoming request while receiving a PPP packet corresponding to the transmitted request.
1642 // (If req == NULL, process on that protocol while the protocol specified in expected_protocol have received.
1643 //If other protocols has arrived, without further processing, and then store that packet in the session context once,
1644 // return NULL by setting the received_protocol.)
PPPRecvResponsePacket(PPP_SESSION * p,PPP_PACKET * req,USHORT expected_protocol,USHORT * received_protocol,bool finish_when_all_lcp_acked,bool return_mschapv2_response_with_no_processing)1645 PPP_PACKET *PPPRecvResponsePacket(PPP_SESSION *p, PPP_PACKET *req, USHORT expected_protocol, USHORT *received_protocol, bool finish_when_all_lcp_acked,
1646 bool return_mschapv2_response_with_no_processing)
1647 {
1648 UINT64 giveup_tick = Tick64() + (UINT64)PPP_PACKET_RECV_TIMEOUT;
1649 UINT64 next_resend = Tick64() + (UINT64)PPP_PACKET_RESEND_INTERVAL;
1650 PPP_PACKET *ret = NULL;
1651 USHORT tmp_us = 0;
1652 // Validate arguments
1653 if (p == NULL || req != NULL && req->Lcp == NULL)
1654 {
1655 return NULL;
1656 }
1657
1658 if (received_protocol == NULL)
1659 {
1660 received_protocol = &tmp_us;
1661 }
1662
1663 if (req != NULL)
1664 {
1665 expected_protocol = req->Protocol;
1666 }
1667
1668 *received_protocol = 0;
1669
1670 // Receive the next packet (Retransmission repeatedly the last packet until the reception is completed)
1671 while (true)
1672 {
1673 UINT64 now = Tick64();
1674 UINT interval;
1675
1676 if (IsTubeConnected(p->TubeRecv) == false)
1677 {
1678 return NULL;
1679 }
1680
1681 while (true)
1682 {
1683 PPP_PACKET *pp;
1684 PPP_PACKET *response;
1685
1686 if (p->LastStoredPacket != NULL)
1687 {
1688 pp = p->LastStoredPacket;
1689 p->LastStoredPacket = NULL;
1690 }
1691 else
1692 {
1693 pp = PPPRecvPacketWithLowLayerProcessing(p, true);
1694 }
1695
1696 if (pp == NULL)
1697 {
1698 break;
1699 }
1700
1701 if (req != NULL)
1702 {
1703 // Determine whether the packet is corresponding to the request that was sent at the last
1704 if (pp->IsControl && pp->Protocol == req->Protocol && pp->Lcp->Id == req->Lcp->Id &&
1705 PPP_CODE_IS_RESPONSE(pp->Protocol, pp->Lcp->Code))
1706 {
1707 return pp;
1708 }
1709
1710 if (return_mschapv2_response_with_no_processing)
1711 {
1712 // For the double-MSCHAPv2 technique
1713 if (pp->IsControl && pp->Protocol == req->Protocol && pp->Lcp->Id == req->Lcp->Id &&
1714 pp->Protocol == PPP_PROTOCOL_CHAP && PPP_PAP_CODE_IS_RESPONSE(pp->Lcp->Code))
1715 {
1716 return pp;
1717 }
1718 }
1719 }
1720
1721 // Return a response immediately without processing if a protocol other than the expected received
1722 if ((pp->IsControl && pp->Protocol != expected_protocol) || pp->IsControl == false)
1723 {
1724 if (PPP_IS_SUPPORTED_PROTOCOL(pp->Protocol))
1725 {
1726 // This is another supported protocol
1727 // Store this packet
1728 PPPStoreLastPacket(p, pp);
1729
1730 *received_protocol = pp->Protocol;
1731 return NULL;
1732 }
1733 else
1734 {
1735 // Unsupported protocol
1736 Debug("Unsupported Protocol: 0x%x\n", pp->Protocol);
1737 FreePPPPacket(pp);
1738
1739 return NULL;
1740 }
1741 }
1742
1743 if (pp->IsControl && PPP_CODE_IS_REQUEST(pp->Protocol, pp->Lcp->Code))
1744 {
1745 // Record current resend because next steps may take a while
1746 UINT64 currentresend = next_resend - now;
1747
1748 // Process when the received packet is a request packet
1749 response = PPPProcessRequestPacket(p, pp);
1750
1751 // Increase next resend because this may have taken a while
1752 next_resend = Tick64() + currentresend;
1753
1754 FreePPPPacket(pp);
1755
1756 if (response == NULL)
1757 {
1758 return NULL;
1759 }
1760 else
1761 {
1762 bool is_pap_and_disconnect_now = false;
1763 bool is_chap_and_disconnect_now = false;
1764
1765 if (PPPSendPacket(p, response) == false)
1766 {
1767 FreePPPPacket(response);
1768 return NULL;
1769 }
1770
1771 if (response->Protocol == PPP_PROTOCOL_PAP && response->IsControl &&
1772 response->Lcp->Code != PPP_PAP_CODE_ACK)
1773 {
1774 is_pap_and_disconnect_now = true;
1775 }
1776
1777 if (response->Protocol == PPP_PROTOCOL_CHAP && response->IsControl &&
1778 response->Lcp->Code == PPP_CHAP_CODE_FAILURE)
1779 {
1780 is_chap_and_disconnect_now = true;
1781 }
1782
1783 FreePPPPacket(response);
1784
1785 if (is_pap_and_disconnect_now)
1786 {
1787 // Disconnect immediately if user authentication fails at least once in the PAP authentication protocol
1788 Debug("Disconnecting because PAP failed.\n");
1789 SleepThread(300);
1790 return NULL;
1791 }
1792
1793 if (is_chap_and_disconnect_now)
1794 {
1795 // Disconnect immediately if it fails to user authentication at least once in the CHAP authentication protocol
1796 Debug("Disconnecting because CHAP failed.\n");
1797 SleepThread(300);
1798 return NULL;
1799 }
1800 }
1801 }
1802 else
1803 {
1804 // Ignore in the case of the other packets
1805 FreePPPPacket(pp);
1806 }
1807 }
1808
1809 // Packet retransmission
1810 if (req != NULL)
1811 {
1812 if (now >= next_resend)
1813 {
1814 next_resend = now + PPP_PACKET_RESEND_INTERVAL;
1815
1816 if (PPPSendPacket(p, req) == false)
1817 {
1818 return NULL;
1819 }
1820 }
1821 }
1822
1823 if (req == NULL)
1824 {
1825 giveup_tick = now + (UINT64)PPP_PACKET_RECV_TIMEOUT;
1826 }
1827
1828 // Time-out decision
1829 if (now >= giveup_tick)
1830 {
1831 PPPLog(p, "LP_CONTROL_TIMEOUT");
1832 return NULL;
1833 }
1834
1835 // Wait
1836 if (req != NULL)
1837 {
1838 interval = MIN((UINT)(giveup_tick - now), (UINT)(next_resend - now));
1839 }
1840 else
1841 {
1842 interval = (UINT)(giveup_tick - now);
1843 }
1844
1845 if (finish_when_all_lcp_acked && p->ClientLCPOptionDetermined)
1846 {
1847 return NULL;
1848 }
1849
1850 Wait(p->TubeRecv->Event, interval);
1851 }
1852 }
1853
1854 // Store the last packet in the session (to be read the next time)
PPPStoreLastPacket(PPP_SESSION * p,PPP_PACKET * pp)1855 void PPPStoreLastPacket(PPP_SESSION *p, PPP_PACKET *pp)
1856 {
1857 // Validate arguments
1858 if (p == NULL)
1859 {
1860 return;
1861 }
1862
1863 if (p->LastStoredPacket != NULL)
1864 {
1865 FreePPPPacket(p->LastStoredPacket);
1866 }
1867
1868 p->LastStoredPacket = pp;
1869 }
1870
1871 // Receive a PPP communication packet
PPPRecvPacketForCommunication(PPP_SESSION * p)1872 PPP_PACKET *PPPRecvPacketForCommunication(PPP_SESSION *p)
1873 {
1874 // Validate arguments
1875 if (p == NULL)
1876 {
1877 return NULL;
1878 }
1879
1880 if (p->LastStoredPacket != NULL)
1881 {
1882 PPP_PACKET *pp = p->LastStoredPacket;
1883 p->LastStoredPacket = NULL;
1884 return pp;
1885 }
1886
1887 return PPPRecvPacketWithLowLayerProcessing(p, true);
1888 }
1889
1890 // Receive a PPP packet (Also performs low layer processing)
PPPRecvPacketWithLowLayerProcessing(PPP_SESSION * p,bool async)1891 PPP_PACKET *PPPRecvPacketWithLowLayerProcessing(PPP_SESSION *p, bool async)
1892 {
1893 PPP_PACKET *pp = NULL;
1894 // Validate arguments
1895 if (p == NULL)
1896 {
1897 return NULL;
1898 }
1899
1900 LABEL_LOOP:
1901 pp = PPPRecvPacket(p, async);
1902 if (pp == NULL)
1903 {
1904 return NULL;
1905 }
1906
1907 if (PPP_IS_SUPPORTED_PROTOCOL(pp->Protocol) == false)
1908 {
1909 // Unsupported algorithm
1910 PPP_PACKET *pp2 = ZeroMalloc(sizeof(PPP_PACKET));
1911 BUF *buf;
1912 UCHAR c;
1913 USHORT us;
1914
1915 pp2->Protocol = PPP_PROTOCOL_LCP;
1916 pp2->IsControl = false;
1917
1918 buf = NewBuf();
1919
1920 // Code
1921 c = PPP_LCP_CODE_PROTOCOL_REJECT;
1922 WriteBuf(buf, &c, 1);
1923
1924 // ID
1925 c = p->NextId++;
1926 WriteBuf(buf, &c, 1);
1927
1928 // Length
1929 us = Endian16(pp->DataSize + 6);
1930 WriteBuf(buf, &us, 2);
1931
1932 // Rejected Protocol
1933 us = Endian16(pp->Protocol);
1934 WriteBuf(buf, &us, 2);
1935
1936 // Packet Data
1937 WriteBuf(buf, pp->Data, pp->DataSize);
1938
1939 pp2->Data = Clone(buf->Buf, buf->Size);
1940 pp2->DataSize = buf->Size;
1941
1942 FreePPPPacket(pp);
1943
1944 FreeBuf(buf);
1945
1946 if (PPPSendPacket(p, pp2) == false)
1947 {
1948 FreePPPPacket(pp2);
1949 return NULL;
1950 }
1951
1952 FreePPPPacket(pp2);
1953 goto LABEL_LOOP;
1954 }
1955
1956 if (pp->IsControl && pp->Protocol == PPP_PROTOCOL_LCP)
1957 {
1958 if (pp->Lcp->Code == PPP_LCP_CODE_ECHO_REQUEST)
1959 {
1960 // Immediately return the echo response to the echo request
1961 PPP_PACKET *pp2 = ZeroMalloc(sizeof(PPP_PACKET));
1962
1963 pp2->IsControl = true;
1964 pp2->Protocol = PPP_PROTOCOL_LCP;
1965 pp2->Lcp = NewPPPLCP(PPP_LCP_CODE_ECHO_RESPONSE, pp->Lcp->Id);
1966 pp2->Lcp->Data = Clone(pp->Lcp->Data, pp->Lcp->DataSize);
1967 pp2->Lcp->DataSize = pp->Lcp->DataSize;
1968
1969 FreePPPPacket(pp);
1970
1971 if (PPPSendPacket(p, pp2) == false)
1972 {
1973 FreePPPPacket(pp2);
1974 return NULL;
1975 }
1976
1977 FreePPPPacket(pp2);
1978 goto LABEL_LOOP;
1979 }
1980 else if (pp->Lcp->Code == PPP_LCP_CODE_ECHO_RESPONSE)
1981 {
1982 // Ignore the Echo response packet
1983 FreePPPPacket(pp);
1984 goto LABEL_LOOP;
1985 }
1986 else if (pp->Lcp->Code == PPP_LCP_CODE_DROP)
1987 {
1988 // Ignore the Drop packet
1989 FreePPPPacket(pp);
1990 goto LABEL_LOOP;
1991 }
1992 else if (pp->Lcp->Code == PPP_LCP_CODE_IDENTIFICATION)
1993 {
1994 // Ignore the Identification packet
1995 FreePPPPacket(pp);
1996 WHERE;
1997 goto LABEL_LOOP;
1998 }
1999 else if (pp->Lcp->Code == PPP_LCP_CODE_TERMINATE_REQ)
2000 {
2001 // Return the Terminate ACK If a Terminate Request has been received
2002 PPP_PACKET *pp2 = ZeroMalloc(sizeof(PPP_PACKET));
2003
2004 pp2->IsControl = true;
2005 pp2->Protocol = PPP_PROTOCOL_LCP;
2006 pp2->Lcp = NewPPPLCP(PPP_LCP_CODE_TERMINATE_ACK, pp->Lcp->Id);
2007 pp2->Lcp->Data = Clone(pp->Lcp->Data, pp->Lcp->DataSize);
2008 pp2->Lcp->DataSize = pp->Lcp->DataSize;
2009
2010 p->IsTerminateReceived = true;
2011
2012 FreePPPPacket(pp);
2013
2014 if (PPPSendPacket(p, pp2) == false)
2015 {
2016 FreePPPPacket(pp2);
2017 return NULL;
2018 }
2019
2020 SleepThread(100);
2021
2022 FreePPPPacket(pp2);
2023 goto LABEL_LOOP;
2024 }
2025 }
2026
2027 return pp;
2028 }
2029
2030 // Receive a PPP packet
PPPRecvPacket(PPP_SESSION * p,bool async)2031 PPP_PACKET *PPPRecvPacket(PPP_SESSION *p, bool async)
2032 {
2033 TUBEDATA *d;
2034 PPP_PACKET *pp;
2035 // Validate arguments
2036 if (p == NULL)
2037 {
2038 return NULL;
2039 }
2040
2041 LABEL_LOOP:
2042
2043 if (async == false)
2044 {
2045 d = TubeRecvSync(p->TubeRecv, PPP_PACKET_RECV_TIMEOUT);
2046 }
2047 else
2048 {
2049 d = TubeRecvAsync(p->TubeRecv);
2050 }
2051
2052 if (d == NULL)
2053 {
2054 return NULL;
2055 }
2056
2057 pp = ParsePPPPacket(d->Data, d->DataSize);
2058 FreeTubeData(d);
2059
2060 if (pp == NULL)
2061 {
2062 // A broken packet is received
2063 goto LABEL_LOOP;
2064 }
2065
2066 p->LastRecvTime = Tick64();
2067
2068 return pp;
2069 }
2070
2071 // Send the PPP packet
PPPSendPacket(PPP_SESSION * p,PPP_PACKET * pp)2072 bool PPPSendPacket(PPP_SESSION *p, PPP_PACKET *pp)
2073 {
2074 return PPPSendPacketEx(p, pp, false);
2075 }
PPPSendPacketEx(PPP_SESSION * p,PPP_PACKET * pp,bool no_flush)2076 bool PPPSendPacketEx(PPP_SESSION *p, PPP_PACKET *pp, bool no_flush)
2077 {
2078 bool ret = false;
2079 BUF *b;
2080 // Validate arguments
2081 if (p == NULL || pp == NULL)
2082 {
2083 return false;
2084 }
2085
2086 b = BuildPPPPacketData(pp);
2087 if (b == NULL)
2088 {
2089 return false;
2090 }
2091
2092 ret = TubeSendEx(p->TubeSend, b->Buf, b->Size, NULL, no_flush);
2093
2094 if (no_flush)
2095 {
2096 AddTubeToFlushList(p->FlushList, p->TubeSend);
2097 }
2098
2099 FreeBuf(b);
2100
2101 return ret;
2102 }
2103
2104 // Create a new PPP options
NewPPPOption(UCHAR type,void * data,UINT size)2105 PPP_OPTION *NewPPPOption(UCHAR type, void *data, UINT size)
2106 {
2107 PPP_OPTION *o;
2108 // Validate arguments
2109 if (size != 0 && data == NULL)
2110 {
2111 return NULL;
2112 }
2113
2114 o = ZeroMalloc(sizeof(PPP_OPTION));
2115
2116 o->Type = type;
2117 Copy(o->Data, data, size);
2118 o->DataSize = size;
2119
2120 return o;
2121 }
2122
2123 // Analyse the PPP packet
ParsePPPPacket(void * data,UINT size)2124 PPP_PACKET *ParsePPPPacket(void *data, UINT size)
2125 {
2126 PPP_PACKET *pp;
2127 UCHAR *buf;
2128 // Validate arguments
2129 if (data == NULL || size == 0)
2130 {
2131 return NULL;
2132 }
2133
2134 pp = ZeroMalloc(sizeof(PPP_PACKET));
2135
2136 buf = (UCHAR *)data;
2137
2138 // Address
2139 if (buf[0] != 0xff)
2140 {
2141 goto LABEL_ERROR;
2142 }
2143 size--;
2144 buf++;
2145
2146 // Control
2147 if (size < 1)
2148 {
2149 goto LABEL_ERROR;
2150 }
2151 if (buf[0] != 0x03)
2152 {
2153 goto LABEL_ERROR;
2154 }
2155 size--;
2156 buf++;
2157
2158 // Protocol
2159 if (size < 2)
2160 {
2161 goto LABEL_ERROR;
2162 }
2163 pp->Protocol = READ_USHORT(buf);
2164 size -= 2;
2165 buf += 2;
2166
2167 if (pp->Protocol == PPP_PROTOCOL_LCP || pp->Protocol == PPP_PROTOCOL_PAP || pp->Protocol == PPP_PROTOCOL_CHAP || pp->Protocol == PPP_PROTOCOL_IPCP)
2168 {
2169 pp->IsControl = true;
2170 }
2171
2172 pp->Data = Clone(buf, size);
2173 pp->DataSize = size;
2174
2175 if (pp->IsControl)
2176 {
2177 pp->Lcp = ParseLCP(pp->Protocol, pp->Data, pp->DataSize);
2178 if (pp->Lcp == NULL)
2179 {
2180 goto LABEL_ERROR;
2181 }
2182 }
2183
2184 return pp;
2185
2186 LABEL_ERROR:
2187 FreePPPPacket(pp);
2188 return NULL;
2189 }
2190
2191 // Build a PPP packet data
BuildPPPPacketData(PPP_PACKET * pp)2192 BUF *BuildPPPPacketData(PPP_PACKET *pp)
2193 {
2194 BUF *ret;
2195 UCHAR c;
2196 USHORT us;
2197 // Validate arguments
2198 if (pp == NULL)
2199 {
2200 return NULL;
2201 }
2202
2203 ret = NewBuf();
2204
2205 // Address
2206 c = 0xff;
2207 WriteBuf(ret, &c, 1);
2208
2209 // Control
2210 c = 0x03;
2211 WriteBuf(ret, &c, 1);
2212
2213 // Protocol
2214 us = Endian16(pp->Protocol);
2215 WriteBuf(ret, &us, 2);
2216
2217 if (pp->IsControl)
2218 {
2219 // LCP
2220 BUF *b = BuildLCPData(pp->Lcp);
2221
2222 WriteBufBuf(ret, b);
2223
2224 FreeBuf(b);
2225 }
2226 else
2227 {
2228 // Data
2229 WriteBuf(ret, pp->Data, pp->DataSize);
2230 }
2231
2232 SeekBuf(ret, 0, 0);
2233
2234 return ret;
2235 }
2236
2237 // Build the LCP packet data
BuildLCPData(PPP_LCP * c)2238 BUF *BuildLCPData(PPP_LCP *c)
2239 {
2240 BUF *b;
2241 UCHAR zero = 0;
2242 UINT i;
2243 // Validate arguments
2244 if (c == NULL)
2245 {
2246 return NULL;
2247 }
2248
2249 b = NewBuf();
2250
2251 // Code
2252 WriteBuf(b, &c->Code, 1);
2253
2254 // ID
2255 WriteBuf(b, &c->Id, 1);
2256
2257 // Length (to be updated later)
2258 zero = 0;
2259 WriteBuf(b, &zero, 1);
2260 WriteBuf(b, &zero, 1);
2261
2262 if (c->Data == NULL)
2263 {
2264 // Option List
2265 for (i = 0;i < LIST_NUM(c->OptionList);i++)
2266 {
2267 PPP_OPTION *o = LIST_DATA(c->OptionList, i);
2268 UCHAR sz = o->DataSize + 2;
2269
2270 WriteBuf(b, &o->Type, 1);
2271 WriteBuf(b, &sz, 1);
2272
2273 WriteBuf(b, o->Data, o->DataSize);
2274 }
2275 }
2276 else
2277 {
2278 // Data
2279 WriteBuf(b, c->Data, c->DataSize);
2280 }
2281
2282 SeekBuf(b, 0, 0);
2283
2284 // Update Length
2285 WRITE_USHORT(((UCHAR *)b->Buf) + 2, b->Size);
2286
2287 return b;
2288 }
2289
2290 // Analyse the LCP data
ParseLCP(USHORT protocol,void * data,UINT size)2291 PPP_LCP *ParseLCP(USHORT protocol, void *data, UINT size)
2292 {
2293 UCHAR *buf;
2294 PPP_LCP *c;
2295 USHORT len;
2296 bool has_option_list = false;
2297 // Validate arguments
2298 if (data == NULL || size == 0)
2299 {
2300 return NULL;
2301 }
2302
2303 buf = (UCHAR *)data;
2304 c = ZeroMalloc(sizeof(PPP_LCP));
2305
2306 c->OptionList = NewListFast(NULL);
2307
2308 // Code
2309 if (size < 1)
2310 {
2311 goto LABEL_ERROR;
2312 }
2313 c->Code = buf[0];
2314 buf++;
2315 size--;
2316
2317 // ID
2318 if (size < 1)
2319 {
2320 goto LABEL_ERROR;
2321 }
2322 c->Id = buf[0];
2323 buf++;
2324 size--;
2325
2326 // Length
2327 if (size < 2)
2328 {
2329 goto LABEL_ERROR;
2330 }
2331 len = READ_USHORT(buf);
2332 if (len < 4)
2333 {
2334 goto LABEL_ERROR;
2335 }
2336 len -= 4;
2337 buf += 2;
2338 size -= 2;
2339
2340 // Options or Data
2341 if (size < len)
2342 {
2343 goto LABEL_ERROR;
2344 }
2345
2346 has_option_list = PPP_CODE_IS_WITH_OPTION_LIST(protocol, c->Code);
2347
2348 if (has_option_list == false)
2349 {
2350 c->Data = Clone(buf, size);
2351 c->DataSize = size;
2352 }
2353 else
2354 {
2355 // Option List
2356 while (len >= 1)
2357 {
2358 PPP_OPTION o;
2359
2360 Zero(&o, sizeof(o));
2361
2362 // Type
2363 if (len < 1)
2364 {
2365 goto LABEL_ERROR;
2366 }
2367 o.Type = buf[0];
2368 buf++;
2369 len--;
2370
2371 // Length
2372 if (len < 1)
2373 {
2374 goto LABEL_ERROR;
2375 }
2376 o.DataSize = buf[0];
2377 if (o.DataSize < 2)
2378 {
2379 goto LABEL_ERROR;
2380 }
2381 o.DataSize -= 2;
2382 buf++;
2383 len--;
2384
2385 // Data
2386 if (len < o.DataSize)
2387 {
2388 goto LABEL_ERROR;
2389 }
2390 Copy(o.Data, buf, o.DataSize);
2391 buf += o.DataSize;
2392 len -= o.DataSize;
2393
2394 Add(c->OptionList, Clone(&o, sizeof(o)));
2395 }
2396 }
2397
2398 return c;
2399
2400 LABEL_ERROR:
2401 FreePPPLCP(c);
2402 return NULL;
2403 }
2404
2405 // Release the PPP packet
FreePPPPacket(PPP_PACKET * pp)2406 void FreePPPPacket(PPP_PACKET *pp)
2407 {
2408 FreePPPPacketEx(pp, false);
2409 }
FreePPPPacketEx(PPP_PACKET * pp,bool no_free_struct)2410 void FreePPPPacketEx(PPP_PACKET *pp, bool no_free_struct)
2411 {
2412 // Validate arguments
2413 if (pp == NULL)
2414 {
2415 return;
2416 }
2417
2418 FreePPPLCP(pp->Lcp);
2419
2420 Free(pp->Data);
2421
2422 if (no_free_struct == false)
2423 {
2424 Free(pp);
2425 }
2426 }
2427
2428 // Release the PPP session
FreePPPSession(PPP_SESSION * p)2429 void FreePPPSession(PPP_SESSION *p)
2430 {
2431 // Validate arguments
2432 if (p == NULL)
2433 {
2434 return;
2435 }
2436
2437 if (p->TubeRecv != NULL)
2438 {
2439 // Record the PPP disconnect reason code for L2TP
2440 p->TubeRecv->IntParam1 = p->DisconnectCauseCode;
2441 p->TubeRecv->IntParam2 = p->DisconnectCauseDirection;
2442 }
2443
2444 FreeTubeFlushList(p->FlushList);
2445
2446 TubeDisconnect(p->TubeRecv);
2447 TubeDisconnect(p->TubeSend);
2448
2449 ReleaseCedar(p->Cedar);
2450
2451 ReleaseTube(p->TubeRecv);
2452 ReleaseTube(p->TubeSend);
2453
2454 PPPStoreLastPacket(p, NULL);
2455
2456 if (p->Ipc != NULL)
2457 {
2458 FreeIPC(p->Ipc);
2459 }
2460
2461 PPPFreeEapClient(p);
2462
2463 Free(p);
2464 }
2465
2466 // Free the associated EAP client
PPPFreeEapClient(PPP_SESSION * p)2467 void PPPFreeEapClient(PPP_SESSION *p)
2468 {
2469 if (p == NULL)
2470 {
2471 return;
2472 }
2473
2474 if (p->EapClient != NULL)
2475 {
2476 ReleaseEapClient(p->EapClient);
2477 p->EapClient = NULL;
2478 }
2479 }
2480
2481 // Get the option value
GetOptionValue(PPP_LCP * c,UCHAR type)2482 PPP_OPTION *GetOptionValue(PPP_LCP *c, UCHAR type)
2483 {
2484 UINT i;
2485 // Validate arguments
2486 if (c == NULL)
2487 {
2488 return NULL;
2489 }
2490
2491 for (i = 0;i < LIST_NUM(c->OptionList);i++)
2492 {
2493 PPP_OPTION *t = LIST_DATA(c->OptionList, i);
2494
2495 if (t->Type == type)
2496 {
2497 return t;
2498 }
2499 }
2500
2501 return NULL;
2502 }
2503
2504 // Create the LCP
NewPPPLCP(UCHAR code,UCHAR id)2505 PPP_LCP *NewPPPLCP(UCHAR code, UCHAR id)
2506 {
2507 PPP_LCP *c = ZeroMalloc(sizeof(PPP_LCP));
2508
2509 c->Code = code;
2510 c->Id = id;
2511 c->OptionList = NewListFast(NULL);
2512
2513 return c;
2514 }
2515
2516 // Release the LCP
FreePPPLCP(PPP_LCP * c)2517 void FreePPPLCP(PPP_LCP *c)
2518 {
2519 // Validate arguments
2520 if (c == NULL)
2521 {
2522 return;
2523 }
2524
2525 FreePPPOptionList(c->OptionList);
2526
2527 Free(c->Data);
2528
2529 Free(c);
2530 }
2531
2532 // Release the PPP options list
FreePPPOptionList(LIST * o)2533 void FreePPPOptionList(LIST *o)
2534 {
2535 UINT i;
2536 // Validate arguments
2537 if (o == NULL)
2538 {
2539 return;
2540 }
2541
2542 for (i = 0;i < LIST_NUM(o);i++)
2543 {
2544 PPP_OPTION *t = LIST_DATA(o, i);
2545
2546 Free(t);
2547 }
2548
2549 ReleaseList(o);
2550 }
2551
2552 // Create a new PPP session
NewPPPSession(CEDAR * cedar,IP * client_ip,UINT client_port,IP * server_ip,UINT server_port,TUBE * send_tube,TUBE * recv_tube,char * postfix,char * client_software_name,char * client_hostname,char * crypt_name,UINT adjust_mss)2553 THREAD *NewPPPSession(CEDAR *cedar, IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, TUBE *send_tube, TUBE *recv_tube, char *postfix, char *client_software_name, char *client_hostname, char *crypt_name, UINT adjust_mss)
2554 {
2555 PPP_SESSION *p;
2556 THREAD *t;
2557 // Validate arguments
2558 if (cedar == NULL || client_ip == NULL || server_ip == NULL || send_tube == NULL || recv_tube == NULL)
2559 {
2560 return NULL;
2561 }
2562 if (IsEmptyStr(postfix))
2563 {
2564 postfix = "PPP";
2565 }
2566 if (IsEmptyStr(crypt_name))
2567 {
2568 crypt_name = "";
2569 }
2570 if (IsEmptyStr(client_software_name))
2571 {
2572 client_software_name = "PPP VPN Client";
2573 }
2574
2575 // Data structure initialization
2576 p = ZeroMalloc(sizeof(PPP_SESSION));
2577
2578 p->EnableMSCHAPv2 = true;
2579 p->AuthProtocol = PPP_PROTOCOL_PAP;
2580 p->MsChapV2_ErrorCode = 691;
2581
2582 p->Cedar = cedar;
2583 AddRef(cedar->ref);
2584
2585 p->AdjustMss = adjust_mss;
2586
2587 StrCpy(p->CryptName, sizeof(p->CryptName), crypt_name);
2588
2589 Copy(&p->ClientIP, client_ip, sizeof(IP));
2590 p->ClientPort = client_port;
2591
2592 Copy(&p->ServerIP, server_ip, sizeof(IP));
2593 p->ServerPort = server_port;
2594
2595 p->TubeRecv = recv_tube;
2596 p->TubeSend = send_tube;
2597
2598 AddRef(p->TubeRecv->Ref);
2599 AddRef(p->TubeSend->Ref);
2600
2601 StrCpy(p->Postfix, sizeof(p->Postfix), postfix);
2602 StrCpy(p->ClientSoftwareName, sizeof(p->ClientSoftwareName), client_software_name);
2603
2604 if (IsEmptyStr(client_hostname))
2605 {
2606 IPToStr(p->ClientHostname, sizeof(p->ClientHostname), client_ip);
2607 }
2608 else
2609 {
2610 StrCpy(p->ClientHostname, sizeof(p->ClientHostname), client_hostname);
2611 }
2612
2613 p->FlushList = NewTubeFlushList();
2614
2615 // Thread creation
2616 t = NewThread(PPPThread, p);
2617
2618 return t;
2619 }
2620
2621 // Generate the NT hash of the password
GenerateNtPasswordHash(UCHAR * dst,char * password)2622 void GenerateNtPasswordHash(UCHAR *dst, char *password)
2623 {
2624 UCHAR *tmp;
2625 UINT tmp_size;
2626 UINT i, len;
2627 // Validate arguments
2628 if (dst == NULL || password == NULL)
2629 {
2630 return;
2631 }
2632
2633 // Generate a Unicode password
2634 len = StrLen(password);
2635 tmp_size = len * 2;
2636
2637 tmp = ZeroMalloc(tmp_size);
2638
2639 for (i = 0;i < len;i++)
2640 {
2641 tmp[i * 2] = password[i];
2642 }
2643
2644 // Hashing
2645 HashMd4(dst, tmp, tmp_size);
2646
2647 Free(tmp);
2648 }
2649
2650 // Generate the MS-CHAPv2 server-side challenge
MsChapV2Server_GenerateChallenge(UCHAR * dst)2651 void MsChapV2Server_GenerateChallenge(UCHAR *dst)
2652 {
2653 // Validate arguments
2654 if (dst == NULL)
2655 {
2656 return;
2657 }
2658
2659 Rand(dst, 16);
2660 }
2661
2662 // Generate the MS-CHAPv2 client-side challenge
MsChapV2Client_GenerateChallenge(UCHAR * dst)2663 void MsChapV2Client_GenerateChallenge(UCHAR *dst)
2664 {
2665 // Validate arguments
2666 if (dst == NULL)
2667 {
2668 return;
2669 }
2670
2671 Rand(dst, 16);
2672 }
2673
2674 // Generate a 8 bytes challenge
MsChapV2_GenerateChallenge8(UCHAR * dst,UCHAR * client_challenge,UCHAR * server_challenge,char * username)2675 void MsChapV2_GenerateChallenge8(UCHAR *dst, UCHAR *client_challenge, UCHAR *server_challenge, char *username)
2676 {
2677 BUF *b;
2678 UCHAR hash[SHA1_SIZE];
2679 char username2[MAX_SIZE];
2680 char domainname2[MAX_SIZE];
2681 // Validate arguments
2682 if (dst == NULL || client_challenge == NULL || server_challenge == NULL)
2683 {
2684 return;
2685 }
2686
2687 b = NewBuf();
2688
2689 WriteBuf(b, client_challenge, 16);
2690 WriteBuf(b, server_challenge, 16);
2691
2692 ParseNtUsername(username, username2, sizeof(username2), domainname2, sizeof(domainname2), true);
2693
2694 if (IsEmptyStr(username2) == false)
2695 {
2696 WriteBuf(b, username2, StrLen(username2));
2697 }
2698
2699 HashSha1(hash, b->Buf, b->Size);
2700
2701 FreeBuf(b);
2702
2703 Copy(dst, hash, 8);
2704 }
2705
2706 // Generate the MS-CHAPv2 client response
MsChapV2Client_GenerateResponse(UCHAR * dst,UCHAR * challenge8,UCHAR * nt_password_hash)2707 void MsChapV2Client_GenerateResponse(UCHAR *dst, UCHAR *challenge8, UCHAR *nt_password_hash)
2708 {
2709 UCHAR password_hash_2[21];
2710 UCHAR key1[8], key2[8], key3[8];
2711 // Validate arguments
2712 if (dst == NULL || challenge8 == NULL || nt_password_hash == NULL)
2713 {
2714 return;
2715 }
2716
2717 Zero(password_hash_2, sizeof(password_hash_2));
2718 Copy(password_hash_2, nt_password_hash, 16);
2719
2720 Zero(key1, sizeof(key1));
2721 Zero(key2, sizeof(key2));
2722 Zero(key3, sizeof(key3));
2723
2724 Copy(key1, password_hash_2 + 0, 7);
2725 Copy(key2, password_hash_2 + 7, 7);
2726 Copy(key3, password_hash_2 + 14, 7);
2727
2728 DesEcbEncrypt(dst + 0, challenge8, key1);
2729 DesEcbEncrypt(dst + 8, challenge8, key2);
2730 DesEcbEncrypt(dst + 16, challenge8, key3);
2731 }
2732
2733 // Generate a hash of the hash of the NT password
GenerateNtPasswordHashHash(UCHAR * dst_hash,UCHAR * src_hash)2734 void GenerateNtPasswordHashHash(UCHAR *dst_hash, UCHAR *src_hash)
2735 {
2736 // Validate arguments
2737 if (dst_hash == NULL || src_hash == NULL)
2738 {
2739 return;
2740 }
2741
2742 HashMd4(dst_hash, src_hash, 16);
2743 }
2744
2745 // Generate the MS-CHAPv2 server response
MsChapV2Server_GenerateResponse(UCHAR * dst,UCHAR * nt_password_hash_hash,UCHAR * client_response,UCHAR * challenge8)2746 void MsChapV2Server_GenerateResponse(UCHAR *dst, UCHAR *nt_password_hash_hash, UCHAR *client_response, UCHAR *challenge8)
2747 {
2748 UCHAR digest[SHA1_SIZE];
2749 BUF *b;
2750 char *magic1 = "Magic server to client signing constant";
2751 char *magic2 = "Pad to make it do more than one iteration";
2752 // Validate arguments
2753 if (dst == NULL || nt_password_hash_hash == NULL || client_response == NULL || challenge8 == NULL)
2754 {
2755 return;
2756 }
2757
2758 b = NewBuf();
2759 WriteBuf(b, nt_password_hash_hash, 16);
2760 WriteBuf(b, client_response, 24);
2761 WriteBuf(b, magic1, StrLen(magic1));
2762 HashSha1(digest, b->Buf, b->Size);
2763 FreeBuf(b);
2764
2765 b = NewBuf();
2766 WriteBuf(b, digest, sizeof(digest));
2767 WriteBuf(b, challenge8, 8);
2768 WriteBuf(b, magic2, StrLen(magic2));
2769 HashSha1(dst, b->Buf, b->Size);
2770 FreeBuf(b);
2771 }
2772
2773 // Verify whether the password matches one that is specified by the user in the MS-CHAPv2
MsChapV2VerityPassword(IPC_MSCHAP_V2_AUTHINFO * d,char * password)2774 bool MsChapV2VerityPassword(IPC_MSCHAP_V2_AUTHINFO *d, char *password)
2775 {
2776 UCHAR ntlm_hash[MD5_SIZE];
2777 UCHAR challenge8[8];
2778 UCHAR client_response[24];
2779 // Validate arguments
2780 if (d == NULL || password == NULL)
2781 {
2782 return false;
2783 }
2784
2785 GenerateNtPasswordHash(ntlm_hash, password);
2786 MsChapV2_GenerateChallenge8(challenge8, d->MsChapV2_ClientChallenge, d->MsChapV2_ServerChallenge, d->MsChapV2_PPPUsername);
2787 MsChapV2Client_GenerateResponse(client_response, challenge8, ntlm_hash);
2788
2789 if (Cmp(client_response, d->MsChapV2_ClientResponse, 24) != 0)
2790 {
2791 return false;
2792 }
2793
2794 return true;
2795 }
2796
2797 // Estimate the password in the brute force for the request packet of MS-CHAPv2
MsChapV2DoBruteForce(IPC_MSCHAP_V2_AUTHINFO * d,LIST * password_list)2798 char *MsChapV2DoBruteForce(IPC_MSCHAP_V2_AUTHINFO *d, LIST *password_list)
2799 {
2800 UINT i;
2801 // Validate arguments
2802 if (d == NULL || password_list == NULL)
2803 {
2804 return NULL;
2805 }
2806
2807 for (i = 0;i < LIST_NUM(password_list);i++)
2808 {
2809 char *s = LIST_DATA(password_list, i);
2810 char tmp[MAX_SIZE];
2811 UINT j, max;
2812 UINT len;
2813
2814 StrCpy(tmp, sizeof(tmp), s);
2815
2816 len = StrLen(tmp);
2817 max = Power(2, MIN(len, 9));
2818
2819 for (j = 0;j < max;j++)
2820 {
2821 SetStrCaseAccordingToBits(tmp, j);
2822 if (MsChapV2VerityPassword(d, tmp))
2823 {
2824 return CopyStr(tmp);
2825 }
2826 }
2827 }
2828
2829 return NULL;
2830 }
2831
2832
2833
2834