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