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