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_EtherIP.c
103 // EtherIP protocol stack
104
105 #include "CedarPch.h"
106
107 // IPC connection processing thread
EtherIPIpcConnectThread(THREAD * t,void * p)108 void EtherIPIpcConnectThread(THREAD *t, void *p)
109 {
110 ETHERIP_SERVER *s;
111 IPC *ipc = NULL;
112 UINT error_code = 0;
113 char tmp[MAX_SIZE];
114 ETHERIP_ID id;
115 // Validate arguments
116 if (t == NULL || p == NULL)
117 {
118 return;
119 }
120
121 s = (ETHERIP_SERVER *)p;
122
123 GetHostName(tmp, sizeof(tmp), &s->ClientIP);
124
125 // Get the setting of the virtual HUB to be connected based on the client ID presented
126 if (SearchEtherIPId(s->Ike->IPsec, &id, s->ClientId) == false &&
127 SearchEtherIPId(s->Ike->IPsec, &id, "*") == false)
128 {
129 // Failed to get the settings for the virtual HUB
130 Debug("Not Found: EtherIP Settings for Client ID \"%s\".\n", s->ClientId);
131
132 EtherIPLog(s, "LE_NO_SETTING", s->ClientId);
133 }
134 else
135 {
136 UINT mss = CalcEtherIPTcpMss(s);
137 char client_name[MAX_SIZE];
138
139 if (s->L2TPv3 == false)
140 {
141 StrCpy(client_name, sizeof(client_name), ETHERIP_CLIENT_NAME);
142 }
143 else
144 {
145 if (IsEmptyStr(s->VendorName))
146 {
147 StrCpy(client_name, sizeof(client_name), ETHERIP_L2TPV3_CLIENT_NAME);
148 }
149 else
150 {
151 Format(client_name, sizeof(client_name), ETHERIP_L2TPV3_CLIENT_NAME_EX, s->VendorName);
152 }
153 }
154
155 // Execution of IPC connection process
156 EtherIPLog(s, "LE_START_IPC", id.HubName, id.UserName, mss);
157 ipc = NewIPC(s->Cedar, client_name,
158 (s->L2TPv3 ? ETHERIP_L2TPV3_POSTFIX : ETHERIP_POSTFIX),
159 id.HubName, id.UserName, id.Password,
160 &error_code,
161 &s->ClientIP, s->ClientPort,
162 &s->ServerIP, s->ServerPort,
163 tmp,
164 s->CryptName, true, mss, NULL, NULL, IPC_LAYER_2);
165
166 if (ipc != NULL)
167 {
168 Copy(&s->CurrentEtherIPIdSetting, &id, sizeof(ETHERIP_ID));
169 EtherIPLog(s, "LE_IPC_CONNECT_OK", id.HubName);
170 }
171 else
172 {
173 EtherIPLog(s, "LE_IPC_CONNECT_ERROR", id.HubName, error_code, _E(error_code));
174 }
175 }
176
177 Lock(s->Lock);
178 {
179 // Set the results
180 ReleaseThread(s->IpcConnectThread);
181 s->IpcConnectThread = NULL;
182
183 s->Ipc = ipc;
184
185 s->LastConnectFailedTick = Tick64();
186 }
187 Unlock(s->Lock);
188
189 // Hit the event to cause interrupt
190 SetSockEvent(s->SockEvent);
191
192 // Release the EtherIP object that is hold by this thread
193 ReleaseEtherIPServer(s);
194 }
195
196 // Processing of the interrupt
EtherIPProcInterrupts(ETHERIP_SERVER * s)197 void EtherIPProcInterrupts(ETHERIP_SERVER *s)
198 {
199 // Validate arguments
200 if (s == NULL)
201 {
202 return;
203 }
204
205 // If EtherIP settings have been changed, and the change may effect to this connection, disconnect
206 if (s->Ipc != NULL)
207 {
208 if (s->Ike->IPsec->EtherIPIdListSettingVerNo != s->LastEtherIPSettingVerNo)
209 {
210 ETHERIP_ID id;
211 bool ok = true;
212
213 s->LastEtherIPSettingVerNo = s->Ike->IPsec->EtherIPIdListSettingVerNo;
214
215 if (SearchEtherIPId(s->IPsec, &id, s->ClientId) == false &&
216 SearchEtherIPId(s->IPsec, &id, "*") == false)
217 {
218 ok = false;
219 }
220 else
221 {
222 if (StrCmpi(s->CurrentEtherIPIdSetting.HubName, id.HubName) != 0 ||
223 StrCmpi(s->CurrentEtherIPIdSetting.UserName, id.UserName) != 0 ||
224 StrCmp(s->CurrentEtherIPIdSetting.Password, id.Password) != 0)
225 {
226 ok = false;
227 }
228 }
229
230 if (ok == false)
231 {
232 // Disconnect immediately since setting of EtherIP seems to have been changed
233 FreeIPC(s->Ipc);
234 s->Ipc = NULL;
235
236 EtherIPLog(s, "LE_RECONNECT");
237 }
238 }
239 }
240
241 // Connect if IPC connection is not completed
242 Lock(s->Lock);
243 {
244 if (s->Ipc == NULL)
245 {
246 if (s->IpcConnectThread == NULL)
247 {
248 if ((s->LastConnectFailedTick == 0) || ((s->LastConnectFailedTick + (UINT64)ETHERIP_VPN_CONNECT_RETRY_INTERVAL) <= s->Now))
249 {
250 Lock(s->IPsec->LockSettings);
251 {
252 Copy(&s->CurrentIPSecServiceSetting, &s->IPsec->Services, sizeof(IPSEC_SERVICES));
253 }
254 Unlock(s->IPsec->LockSettings);
255
256 s->IpcConnectThread = NewThread(EtherIPIpcConnectThread, s);
257 AddThreadToThreadList(s->Ike->ThreadList, s->IpcConnectThread);
258 AddRef(s->Ref);
259 }
260 }
261 }
262 }
263 Unlock(s->Lock);
264
265 if (s->Ipc != NULL)
266 {
267 // Set to get hit the SockEvent when a packet arrives via the IPC
268 IPCSetSockEventWhenRecvL2Packet(s->Ipc, s->SockEvent);
269
270 // IPC interrupt processing
271 IPCProcessInterrupts(s->Ipc);
272
273 // Receive the MAC frame which arrived via the IPC
274 while (true)
275 {
276 BLOCK *b = IPCRecvL2(s->Ipc);
277 UCHAR *dst;
278 UINT dst_size;
279
280 if (b == NULL)
281 {
282 break;
283 }
284
285 if (b->Size >= 14)
286 {
287 BLOCK *block;
288
289 // Store the arrived MAC frame by adding an EtherIP header to the reception packet queue
290
291 if (s->L2TPv3 == false)
292 {
293 dst_size = b->Size + 2;
294 dst = Malloc(dst_size);
295
296 dst[0] = 0x30;
297 dst[1] = 0x00;
298
299 Copy(dst + 2, b->Buf, b->Size);
300 }
301 else
302 {
303 dst = Clone(b->Buf, b->Size);
304 dst_size = b->Size;
305 }
306
307 block = NewBlock(dst, dst_size, 0);
308
309 Add(s->SendPacketList, block);
310 }
311
312 FreeBlock(b);
313 }
314
315 if (IsIPCConnected(s->Ipc) == false)
316 {
317 // IPC connection is disconnected
318 FreeIPC(s->Ipc);
319 s->Ipc = NULL;
320 }
321 }
322 }
323
324 // Process the received packet
EtherIPProcRecvPackets(ETHERIP_SERVER * s,BLOCK * b)325 void EtherIPProcRecvPackets(ETHERIP_SERVER *s, BLOCK *b)
326 {
327 UCHAR *src;
328 UINT src_size;
329 // Validate arguments
330 if (s == NULL || b == NULL)
331 {
332 return;
333 }
334
335 if (s->Ipc == NULL)
336 {
337 // Not connected to the Virtual HUB
338 return;
339 }
340
341 src = b->Buf;
342 src_size = b->Size;
343
344 if (s->L2TPv3 == false)
345 {
346 // EtherIP header confirmation
347 if (src_size < 2)
348 {
349 return;
350 }
351
352 if ((src[0] & 0xf0) != 0x30)
353 {
354 return;
355 }
356
357 src += 2;
358 src_size -= 2;
359 }
360
361 if (src_size < 14)
362 {
363 // The size of the MAC frame is less than 14 bytes
364 return;
365 }
366
367 // Send by IPC since a MAC frame has been received
368 IPCSendL2(s->Ipc, src, src_size);
369 }
370
371 // Create a new EtherIP server
NewEtherIPServer(CEDAR * cedar,IPSEC_SERVER * ipsec,IKE_SERVER * ike,IP * client_ip,UINT client_port,IP * server_ip,UINT server_port,char * crypt_name,bool is_tunnel_mode,UINT crypt_block_size,char * client_id,UINT id)372 ETHERIP_SERVER *NewEtherIPServer(CEDAR *cedar, IPSEC_SERVER *ipsec, IKE_SERVER *ike,
373 IP *client_ip, UINT client_port, IP *server_ip, UINT server_port, char *crypt_name,
374 bool is_tunnel_mode, UINT crypt_block_size,
375 char *client_id, UINT id)
376 {
377 ETHERIP_SERVER *s;
378 // Validate arguments
379 if (cedar == NULL || ipsec == NULL || ike == NULL || client_ip == NULL || server_ip == NULL || client_id == NULL)
380 {
381 return NULL;
382 }
383
384 s = ZeroMalloc(sizeof(ETHERIP_SERVER));
385
386 s->Ref = NewRef();
387
388 s->Id = id;
389
390 s->Cedar = cedar;
391 AddRef(s->Cedar->ref);
392 s->IPsec = ipsec;
393 s->Ike = ike;
394 s->IsTunnelMode = is_tunnel_mode;
395
396 StrCpy(s->ClientId, sizeof(s->ClientId), client_id);
397
398 s->SendPacketList = NewList(NULL);
399
400 s->Now = Tick64();
401
402 s->Lock = NewLock();
403
404 Copy(&s->ClientIP, client_ip, sizeof(IP));
405 s->ClientPort = client_port;
406
407 Copy(&s->ServerIP, server_ip, sizeof(IP));
408 s->ServerPort = server_port;
409
410 StrCpy(s->CryptName, sizeof(s->CryptName), crypt_name);
411 s->CryptBlockSize = crypt_block_size;
412
413 EtherIPLog(s, "LE_START_MODULE");
414
415 return s;
416 }
417
418 // Release the EtherIP server
ReleaseEtherIPServer(ETHERIP_SERVER * s)419 void ReleaseEtherIPServer(ETHERIP_SERVER *s)
420 {
421 // Validate arguments
422 if (s == NULL)
423 {
424 return;
425 }
426
427 if (Release(s->Ref) == 0)
428 {
429 CleanupEtherIPServer(s);
430 }
431 }
CleanupEtherIPServer(ETHERIP_SERVER * s)432 void CleanupEtherIPServer(ETHERIP_SERVER *s)
433 {
434 UINT i;
435 // Validate arguments
436 if (s == NULL)
437 {
438 return;
439 }
440
441 EtherIPLog(s, "LE_STOP");
442
443 if (s->IpcConnectThread != NULL)
444 {
445 ReleaseThread(s->IpcConnectThread);
446 }
447
448 if (s->Ipc != NULL)
449 {
450 FreeIPC(s->Ipc);
451 }
452
453 for (i = 0;i < LIST_NUM(s->SendPacketList);i++)
454 {
455 BLOCK *b = LIST_DATA(s->SendPacketList, i);
456
457 FreeBlock(b);
458 }
459
460 ReleaseList(s->SendPacketList);
461
462 ReleaseSockEvent(s->SockEvent);
463
464 ReleaseCedar(s->Cedar);
465
466 DeleteLock(s->Lock);
467
468 Free(s);
469 }
470
471
472 // Set SockEvent to EtherIP server
SetEtherIPServerSockEvent(ETHERIP_SERVER * s,SOCK_EVENT * e)473 void SetEtherIPServerSockEvent(ETHERIP_SERVER *s, SOCK_EVENT *e)
474 {
475 // Validate arguments
476 if (s == NULL)
477 {
478 return;
479 }
480
481 if (e != NULL)
482 {
483 AddRef(e->ref);
484 }
485
486 if (s->SockEvent != NULL)
487 {
488 ReleaseSockEvent(s->SockEvent);
489 s->SockEvent = NULL;
490 }
491
492 s->SockEvent = e;
493 }
494
495 // Calculate the proper TCP MSS in EtherIP communication
CalcEtherIPTcpMss(ETHERIP_SERVER * s)496 UINT CalcEtherIPTcpMss(ETHERIP_SERVER *s)
497 {
498 UINT ret = MTU_FOR_PPPOE;
499 // Validate arguments
500 if (s == NULL)
501 {
502 return 0;
503 }
504
505 // IPv4 / IPv6
506 if (IsIP4(&s->ClientIP))
507 {
508 ret -= 20;
509 }
510 else
511 {
512 ret -= 40;
513 }
514
515 // IPsec UDP
516 ret -= 8;
517
518 // IPsec ESP
519 ret -= 20;
520 ret -= s->CryptBlockSize * 2;
521
522 // IPsec Tunnel Mode IPv4 / IPv6 Header
523 if (s->IsTunnelMode)
524 {
525 if (IsIP4(&s->ClientIP))
526 {
527 ret -= 20;
528 }
529 else
530 {
531 ret -= 40;
532 }
533 }
534
535 if (s->L2TPv3 == false)
536 {
537 // EtherIP
538 ret -= 2;
539 }
540 else
541 {
542 // L2TPv3
543 ret -= 2;
544 }
545
546 // Ethernet
547 ret -= 14;
548
549 // IPv4
550 ret -= 20;
551
552 // TCP
553 ret -= 20;
554
555 return ret;
556 }
557