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