1 // SoftEther VPN Source Code - Developer Edition Master Branch
2 // Cedar Communication Module
3 
4 
5 // Proto_IPsec.c
6 // IPsec module
7 
8 #include "Proto_IPsec.h"
9 
10 #include "Hub.h"
11 #include "Proto_IKE.h"
12 #include "Proto_L2TP.h"
13 #include "Proto_Win7.h"
14 #include "Server.h"
15 
16 #include "Mayaqua/Kernel.h"
17 #include "Mayaqua/Memory.h"
18 #include "Mayaqua/Microsoft.h"
19 #include "Mayaqua/Object.h"
20 #include "Mayaqua/Str.h"
21 #include "Mayaqua/Tick64.h"
22 #include "Mayaqua/Unix.h"
23 
24 static bool ipsec_disable = false;
25 
26 // Monitor the IPsec service of the OS, and stop it if it will conflict
IPsecOsServiceCheckThread(THREAD * t,void * p)27 void IPsecOsServiceCheckThread(THREAD *t, void *p)
28 {
29 	UINT interval = IPSEC_CHECK_OS_SERVICE_INTERVAL_INITIAL;
30 	IPSEC_SERVER *s = (IPSEC_SERVER *)p;
31 	// Validate arguments
32 	if (t == NULL || p == NULL)
33 	{
34 		return;
35 	}
36 
37 	s->HostIPAddressListChanged = true;
38 	s->OsServiceStoped = false;
39 
40 	while (s->Halt == false)
41 	{
42 		if (IPsecCheckOsService(s))
43 		{
44 			interval = IPSEC_CHECK_OS_SERVICE_INTERVAL_INITIAL;
45 		}
46 
47 		if (Wait(s->OsServiceCheckThreadEvent, interval) == false)
48 		{
49 			interval = MIN(interval * 2, IPSEC_CHECK_OS_SERVICE_INTERVAL_MAX);
50 		}
51 		else
52 		{
53 			interval = IPSEC_CHECK_OS_SERVICE_INTERVAL_INITIAL;
54 		}
55 	}
56 
57 	IPsecCheckOsService(s);
58 }
59 
60 // Monitoring process main
IPsecCheckOsService(IPSEC_SERVER * s)61 bool IPsecCheckOsService(IPSEC_SERVER *s)
62 {
63 	bool b_ipsec;
64 	IPSEC_SERVICES sl;
65 	bool ret = false;
66 	// Validate arguments
67 	if (s == NULL)
68 	{
69 		return false;
70 	}
71 
72 	IPsecServerGetServices(s, &sl);
73 
74 	b_ipsec = (sl.EtherIP_IPsec || sl.L2TP_IPsec);
75 
76 	if (b_ipsec != s->Check_LastEnabledStatus)
77 	{
78 		s->Check_LastEnabledStatus = b_ipsec;
79 
80 		if (b_ipsec)
81 		{
82 			// Use of IPsec has been started
83 #ifdef	OS_WIN32
84 			if (s->Win7 == NULL)
85 			{
86 				s->Win7 = IPsecWin7Init();
87 				s->HostIPAddressListChanged = true;
88 			}
89 
90 			s->OsServiceStoped = false;
91 #else	// OS_WIN32
92 #endif	// OS_WIN32
93 		}
94 		else
95 		{
96 			// Use of IPsec is stopped
97 #ifdef	OS_WIN32
98 			if (s->Win7 != NULL)
99 			{
100 				IPsecWin7Free(s->Win7);
101 				s->Win7 = NULL;
102 			}
103 
104 			if (s->OsServiceStoped)
105 			{
106 				MsStartIPsecService();
107 				s->OsServiceStoped = false;
108 			}
109 #else	// OS_WIN32
110 			UnixSetEnableKernelEspProcessing(true);
111 #endif	// OS_WIN32
112 		}
113 	}
114 
115 	if (b_ipsec)
116 	{
117 #ifdef	OS_WIN32
118 		if (MsStopIPsecService())
119 		{
120 			s->OsServiceStoped = true;
121 			ret = true;
122 		}
123 #else	// OS_WIN32
124 		UnixSetEnableKernelEspProcessing(false);
125 #endif	// OS_WIN32
126 	}
127 
128 #ifdef	OS_WIN32
129 	if (s->Win7 != NULL)
130 	{
131 		IPsecWin7UpdateHostIPAddressList(s->Win7);
132 		s->HostIPAddressListChanged = false;
133 	}
134 #endif	// OS_WIN32
135 
136 	return ret;
137 }
138 
139 // Processing of UDP packets (one by one)
IPsecProcPacket(IPSEC_SERVER * s,UDPPACKET * p)140 void IPsecProcPacket(IPSEC_SERVER *s, UDPPACKET *p)
141 {
142 	L2TP_SERVER *l2tp;
143 	IKE_SERVER *ike;
144 	void *old_data_ptr;
145 	UINT old_data_size;
146 	bool proc_this_packet = true;
147 	// Validate arguments
148 	if (s == NULL || p == NULL)
149 	{
150 		return;
151 	}
152 
153 	old_data_ptr = p->Data;
154 	old_data_size = p->Size;
155 
156 	l2tp = s->L2TP;
157 	ike = s->Ike;
158 
159 	// UDP decapsulation process
160 	if (p->DestPort == IPSEC_PORT_IPSEC_ESP_UDP)
161 	{
162 #ifdef	OS_WIN32
163 		if (p->Size >= 12 && IsZero(p->Data, 4))
164 		{
165 			if (((*((UINT *)(((UCHAR *)p->Data) + sizeof(UINT) * 1))) == WFP_ESP_PACKET_TAG_1) &&
166 				((*((UINT *)(((UCHAR *)p->Data) + sizeof(UINT) * 2))) == WFP_ESP_PACKET_TAG_2))
167 			{
168 				// Truncate the head because the packet was modified by WFP
169 				p->Data = ((UCHAR *)p->Data) + 12;
170 				p->Size -= 12;
171 			}
172 		}
173 #endif	// OS_WIN32
174 
175 		if (p->Size >= 4 && IsZero(p->Data, 4))
176 		{
177 			// Truncate the Non-ESP Marker
178 			p->Data = ((UCHAR *)p->Data) + 4;
179 			p->Size -= 4;
180 
181 			p->Type = IKE_UDP_TYPE_ISAKMP;
182 		}
183 		else
184 		{
185 			p->Type = IKE_UDP_TYPE_ESP;
186 		}
187 	}
188 	else if (p->DestPort == IPSEC_PORT_IPSEC_ISAKMP)
189 	{
190 		if (p->Size >= 8 && IsZero(p->Data, 8))
191 		{
192 			// Truncate the Non-IKE Maker
193 			p->Data = ((UCHAR *)p->Data) + 8;
194 			p->Size -= 8;
195 
196 			p->Type = IKE_UDP_TYPE_ESP;
197 		}
198 		else
199 		{
200 			p->Type = IKE_UDP_TYPE_ISAKMP;
201 		}
202 	}
203 	else if (p->DestPort == IPSEC_PORT_IPSEC_ESP_RAW)
204 	{
205 		// Raw ESP
206 		p->Type = IKE_UDP_TYPE_ESP;
207 	}
208 
209 
210 	if (proc_this_packet)
211 	{
212 		switch (p->DestPort)
213 		{
214 		case IPSEC_PORT_L2TP:
215 			// L2TP
216 			ProcL2TPPacketRecv(l2tp, p);
217 			break;
218 
219 		case IPSEC_PORT_IPSEC_ISAKMP:
220 		case IPSEC_PORT_IPSEC_ESP_UDP:
221 		case IPSEC_PORT_IPSEC_ESP_RAW:
222 			// IPsec
223 			ProcIKEPacketRecv(ike, p);
224 			break;
225 		}
226 	}
227 
228 	p->Data = old_data_ptr;
229 	p->Size = old_data_size;
230 }
231 
232 // Packet reception procedure of UDP listener
IPsecServerUdpPacketRecvProc(UDPLISTENER * u,LIST * packet_list)233 void IPsecServerUdpPacketRecvProc(UDPLISTENER *u, LIST *packet_list)
234 {
235 	UINT i;
236 	IPSEC_SERVER *s;
237 	L2TP_SERVER *l2tp;
238 	IKE_SERVER *ike;
239 	UINT64 now;
240 	static UCHAR zero8[8] = {0, 0, 0, 0, 0, 0, 0, 0, };
241 	// Validate arguments
242 	if (u == NULL || packet_list == NULL)
243 	{
244 		return;
245 	}
246 	s = (IPSEC_SERVER *)u->Param;
247 	if (s == NULL)
248 	{
249 		return;
250 	}
251 
252 	if (u->HostIPAddressListChanged)
253 	{
254 		u->HostIPAddressListChanged = false;
255 
256 		s->HostIPAddressListChanged = true;
257 
258 		Set(s->OsServiceCheckThreadEvent);
259 	}
260 
261 	now = Tick64();
262 
263 	// Adjustment about L2TP server timing
264 	l2tp = s->L2TP;
265 
266 	if (l2tp->Interrupts == NULL)
267 	{
268 		l2tp->Interrupts = u->Interrupts;
269 	}
270 
271 	if (l2tp->SockEvent == NULL)
272 	{
273 		SetL2TPServerSockEvent(l2tp, u->Event);
274 	}
275 
276 	l2tp->Now = now;
277 
278 	// Adjustment about IKE server timing
279 	ike = s->Ike;
280 
281 	if (ike->Interrupts == NULL)
282 	{
283 		ike->Interrupts = u->Interrupts;
284 	}
285 
286 	if (ike->SockEvent == NULL)
287 	{
288 		SetIKEServerSockEvent(ike, u->Event);
289 	}
290 
291 	ike->Now = now;
292 
293 	if (ipsec_disable == false)
294 	{
295 		{
296 			// Process the received packet
297 			for (i = 0;i < LIST_NUM(packet_list);i++)
298 			{
299 				UDPPACKET *p = LIST_DATA(packet_list, i);
300 
301 				IPsecProcPacket(s, p);
302 			}
303 		}
304 	}
305 
306 	// Interrupt processing of L2TP server
307 	L2TPProcessInterrupts(l2tp);
308 
309 	// L2TP packet transmission processing
310 	UdpListenerSendPackets(u, l2tp->SendPacketList);
311 	DeleteAll(l2tp->SendPacketList);
312 
313 	// Interrupt processing of IKE server
314 	ProcessIKEInterrupts(ike);
315 
316 	// UDP encapsulation process of IKE server packet scheduled for transmission
317 	for (i = 0;i < LIST_NUM(ike->SendPacketList);i++)
318 	{
319 		UDPPACKET *p = LIST_DATA(ike->SendPacketList, i);
320 
321 		if (p->Type == IKE_UDP_TYPE_ISAKMP && p->SrcPort == IPSEC_PORT_IPSEC_ESP_UDP)
322 		{
323 			// Add the Non-ESP Marker
324 			void *old_data = p->Data;
325 
326 			p->Data = AddHead(p->Data, p->Size, zero8, 4);
327 			p->Size += 4;
328 
329 			Free(old_data);
330 		}
331 		else if (p->Type == IKE_UDP_TYPE_ESP && p->SrcPort == IPSEC_PORT_IPSEC_ISAKMP)
332 		{
333 			// Add the Non-IKE Marker
334 			void *old_data = p->Data;
335 
336 			p->Data = AddHead(p->Data, p->Size, zero8, 8);
337 			p->Size += 8;
338 
339 			Free(old_data);
340 		}
341 	}
342 
343 	// IKE server packet transmission processing
344 	UdpListenerSendPackets(u, ike->SendPacketList);
345 	DeleteAll(ike->SendPacketList);
346 }
347 
348 // Get the service list
IPsecServerGetServices(IPSEC_SERVER * s,IPSEC_SERVICES * sl)349 void IPsecServerGetServices(IPSEC_SERVER *s, IPSEC_SERVICES *sl)
350 {
351 	// Validate arguments
352 	if (s == NULL || sl == NULL)
353 	{
354 		return;
355 	}
356 
357 	Lock(s->LockSettings);
358 	{
359 		IPsecNormalizeServiceSetting(s);
360 
361 		Copy(sl, &s->Services, sizeof(IPSEC_SERVICES));
362 	}
363 	Unlock(s->LockSettings);
364 }
365 
366 // Normalize the IPsec service setttings
IPsecNormalizeServiceSetting(IPSEC_SERVER * s)367 void IPsecNormalizeServiceSetting(IPSEC_SERVER *s)
368 {
369 	CEDAR *c;
370 	// Validate arguments
371 	if (s == NULL)
372 	{
373 		return;
374 	}
375 
376 	c = s->Cedar;
377 
378 	Lock(s->LockSettings);
379 	{
380 		bool reset_hub_setting = false;
381 
382 		if (IsEmptyStr(s->Services.IPsec_Secret))
383 		{
384 			// If the secret is not set, set the default one
385 			StrCpy(s->Services.IPsec_Secret, sizeof(s->Services.IPsec_Secret), IPSEC_DEFAULT_SECRET);
386 		}
387 
388 		LockList(c->HubList);
389 		{
390 			if (IsEmptyStr(s->Services.L2TP_DefaultHub))
391 			{
392 				reset_hub_setting = true;
393 			}
394 			else
395 			{
396 				if (IsHub(c, s->Services.L2TP_DefaultHub) == false)
397 				{
398 					reset_hub_setting = true;
399 				}
400 			}
401 
402 			if (reset_hub_setting)
403 			{
404 				// Select the first Virtual HUB if there is no HUB
405 				HUB *h = NULL;
406 
407 				if (LIST_NUM(c->HubList) >= 1)
408 				{
409 					h = LIST_DATA(c->HubList, 0);
410 				}
411 
412 				if (h != NULL)
413 				{
414 					StrCpy(s->Services.L2TP_DefaultHub, sizeof(s->Services.L2TP_DefaultHub), h->Name);
415 				}
416 				else
417 				{
418 					StrCpy(s->Services.L2TP_DefaultHub, sizeof(s->Services.L2TP_DefaultHub), "");
419 				}
420 			}
421 		}
422 		UnlockList(c->HubList);
423 	}
424 	Unlock(s->LockSettings);
425 }
426 
427 // Set the service list
IPsecServerSetServices(IPSEC_SERVER * s,IPSEC_SERVICES * sl)428 void IPsecServerSetServices(IPSEC_SERVER *s, IPSEC_SERVICES *sl)
429 {
430 	// Validate arguments
431 	if (s == NULL || sl == NULL)
432 	{
433 		return;
434 	}
435 
436 	if (IsZero(sl, sizeof(IPSEC_SERVICES)) == false)
437 	{
438 		if (s->NoMoreChangeSettings)
439 		{
440 			return;
441 		}
442 	}
443 
444 	Lock(s->LockSettings);
445 	{
446 		Copy(&s->Services, sl, sizeof(IPSEC_SERVICES));
447 
448 		Copy(&s->UdpListener->ListenIP, &s->Cedar->Server->ListenIP, sizeof(IP));
449 
450 		if (sl->L2TP_Raw)
451 		{
452 			AddPortToUdpListener(s->UdpListener, IPSEC_PORT_L2TP);
453 		}
454 		else
455 		{
456 			DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_L2TP);
457 		}
458 
459 		if (sl->L2TP_IPsec || sl->EtherIP_IPsec)
460 		{
461 			AddPortToUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ISAKMP);
462 			AddPortToUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_UDP);
463 			AddPortToUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_RAW);
464 			AddPortToUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_RAW_WPF);
465 		}
466 		else
467 		{
468 			DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ISAKMP);
469 			DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_UDP);
470 			DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_RAW);
471 			DeletePortFromUdpListener(s->UdpListener, IPSEC_PORT_IPSEC_ESP_RAW_WPF);
472 		}
473 
474 		if (IsEmptyStr(sl->IPsec_Secret) == false)
475 		{
476 			StrCpy(s->Ike->Secret, sizeof(s->Ike->Secret), sl->IPsec_Secret);
477 		}
478 
479 		IPsecNormalizeServiceSetting(s);
480 	}
481 	Unlock(s->LockSettings);
482 
483 	Set(s->OsServiceCheckThreadEvent);
484 }
485 
486 // Add the EtherIP key
AddEtherIPId(IPSEC_SERVER * s,ETHERIP_ID * id)487 void AddEtherIPId(IPSEC_SERVER *s, ETHERIP_ID *id)
488 {
489 	// Validate arguments
490 	if (s == NULL || id == NULL)
491 	{
492 		return;
493 	}
494 
495 	Lock(s->LockSettings);
496 	{
497 		// If there is the same key, remove them
498 		ETHERIP_ID t, *k;
499 
500 		Zero(&t, sizeof(t));
501 
502 		StrCpy(t.Id, sizeof(t.Id), id->Id);
503 
504 		k = Search(s->EtherIPIdList, &t);
505 
506 		if (k != NULL)
507 		{
508 			Delete(s->EtherIPIdList, k);
509 
510 			Free(k);
511 		}
512 
513 		// Add
514 		k = Clone(id, sizeof(ETHERIP_ID));
515 
516 		Insert(s->EtherIPIdList, k);
517 
518 		s->EtherIPIdListSettingVerNo++;
519 	}
520 	Unlock(s->LockSettings);
521 }
522 
523 // Delete the EtherIP key
DeleteEtherIPId(IPSEC_SERVER * s,char * id_str)524 bool DeleteEtherIPId(IPSEC_SERVER *s, char *id_str)
525 {
526 	bool ret = false;
527 	// Validate arguments
528 	if (s == NULL || id_str == NULL)
529 	{
530 		return false;
531 	}
532 
533 	Lock(s->LockSettings);
534 	{
535 		// If there is the same key, remove them
536 		ETHERIP_ID t, *k;
537 
538 		Zero(&t, sizeof(t));
539 
540 		StrCpy(t.Id, sizeof(t.Id), id_str);
541 
542 		k = Search(s->EtherIPIdList, &t);
543 
544 		if (k != NULL)
545 		{
546 			Delete(s->EtherIPIdList, k);
547 
548 			Free(k);
549 
550 			ret = true;
551 
552 			s->EtherIPIdListSettingVerNo++;
553 		}
554 	}
555 	Unlock(s->LockSettings);
556 
557 	return ret;
558 }
559 
560 // Search the EtherIP key
SearchEtherIPId(IPSEC_SERVER * s,ETHERIP_ID * id,char * id_str)561 bool SearchEtherIPId(IPSEC_SERVER *s, ETHERIP_ID *id, char *id_str)
562 {
563 	bool ret = false;
564 	// Validate arguments
565 	if (s == NULL || id == NULL || id_str == NULL)
566 	{
567 		return false;
568 	}
569 
570 	Lock(s->LockSettings);
571 	{
572 		ETHERIP_ID t, *k;
573 
574 		Zero(&t, sizeof(t));
575 
576 		StrCpy(t.Id, sizeof(t.Id), id_str);
577 
578 		k = Search(s->EtherIPIdList, &t);
579 
580 		if (k != NULL)
581 		{
582 			Copy(id, k, sizeof(ETHERIP_ID));
583 
584 			ret = true;
585 		}
586 	}
587 	Unlock(s->LockSettings);
588 
589 	return ret;
590 }
591 
592 // Comparison of key EtherIP list entries
CmpEtherIPId(void * p1,void * p2)593 int CmpEtherIPId(void *p1, void *p2)
594 {
595 	ETHERIP_ID *k1, *k2;
596 	// Validate arguments
597 	if (p1 == NULL || p2 == NULL)
598 	{
599 		return 0;
600 	}
601 	k1 = *(ETHERIP_ID **)p1;
602 	k2 = *(ETHERIP_ID **)p2;
603 	if (k1 == NULL || k2 == NULL)
604 	{
605 		return 0;
606 	}
607 
608 	return StrCmpi(k1->Id, k2->Id);
609 }
610 
611 // Release and stop the IPsec server
FreeIPsecServer(IPSEC_SERVER * s)612 void FreeIPsecServer(IPSEC_SERVER *s)
613 {
614 	UINT i;
615 	IPSEC_SERVICES sl;
616 	// Validate arguments
617 	if (s == NULL)
618 	{
619 		return;
620 	}
621 
622 	s->NoMoreChangeSettings = true;
623 
624 	// Stopp the L2TP server
625 	StopL2TPServer(s->L2TP, false);
626 
627 	// Stop the IKE server
628 	StopIKEServer(s->Ike);
629 
630 	// Stop all the services explicitly
631 	Zero(&sl, sizeof(sl));
632 	IPsecServerSetServices(s, &sl);
633 
634 	// Releasing process
635 	FreeUdpListener(s->UdpListener);
636 
637 	ReleaseCedar(s->Cedar);
638 
639 	FreeL2TPServer(s->L2TP);
640 
641 	FreeIKEServer(s->Ike);
642 
643 	for (i = 0;i < LIST_NUM(s->EtherIPIdList);i++)
644 	{
645 		ETHERIP_ID *k = LIST_DATA(s->EtherIPIdList, i);
646 
647 		Free(k);
648 	}
649 
650 	ReleaseList(s->EtherIPIdList);
651 
652 	// Stop the OS monitoring thread
653 	s->Halt = true;
654 	Set(s->OsServiceCheckThreadEvent);
655 	WaitThread(s->OsServiceCheckThread, INFINITE);
656 	ReleaseThread(s->OsServiceCheckThread);
657 	ReleaseEvent(s->OsServiceCheckThreadEvent);
658 
659 	DeleteLock(s->LockSettings);
660 
661 	Free(s);
662 }
663 
664 // Initialize the IPsec server
NewIPsecServer(CEDAR * cedar)665 IPSEC_SERVER *NewIPsecServer(CEDAR *cedar)
666 {
667 	IPSEC_SERVER *s;
668 	// Validate arguments
669 	if (cedar == NULL)
670 	{
671 		return NULL;
672 	}
673 
674 	s = ZeroMalloc(sizeof(IPSEC_SERVER));
675 
676 	s->LockSettings = NewLock();
677 
678 	s->Cedar = cedar;
679 
680 	AddRef(s->Cedar->ref);
681 
682 	s->L2TP = NewL2TPServer(cedar);
683 
684 	s->Ike = NewIKEServer(cedar, s);
685 	StrCpy(s->Ike->Secret, sizeof(s->Ike->Secret), IPSEC_DEFAULT_SECRET);
686 
687 	s->UdpListener = NewUdpListener(IPsecServerUdpPacketRecvProc, s, &cedar->Server->ListenIP);
688 
689 	s->EtherIPIdList = NewList(CmpEtherIPId);
690 
691 	// Start an OS service monitoring thread
692 	s->OsServiceCheckThreadEvent = NewEvent();
693 	s->OsServiceCheckThread = NewThread(IPsecOsServiceCheckThread, s);
694 
695 	return s;
696 }
697 
698