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 // Bridge.c
103 // Ethernet Bridge Program (Local Bridge)
104 
105 #include <GlobalConst.h>
106 
107 #define	BRIDGE_C
108 
109 #ifdef	WIN32
110 #define	OS_WIN32
111 #endif
112 
113 #ifdef	OS_WIN32
114 
115 // Win32
116 #include "BridgeWin32.c"
117 
118 #else
119 
120 // Unix
121 #include "BridgeUnix.c"
122 
123 #endif	// OS_WIN32
124 
125 // Hash the list of current Ethernet devices
GetEthDeviceHash()126 UINT GetEthDeviceHash()
127 {
128 #ifdef	OS_UNIX
129 	// UNIX
130 	UINT num;
131 	UINT i;
132 	char tmp[4096];
133 	UCHAR hash[SHA1_SIZE];
134 	TOKEN_LIST *t = GetEthList();
135 
136 	num = t->NumTokens;
137 	tmp[0] = 0;
138 	for (i = 0;i < t->NumTokens;i++)
139 	{
140 		StrCat(tmp, sizeof(tmp), t->Token[i]);
141 	}
142 	FreeToken(t);
143 
144 	Hash(hash, tmp, StrLen(tmp), true);
145 
146 	Copy(&num, hash, sizeof(UINT));
147 
148 	return num;
149 #else	// OS_UNIX
150 	// Win32
151 	UINT ret = 0;
152 	MS_ADAPTER_LIST *a = MsCreateAdapterListEx(true);
153 	UINT num;
154 	UINT i;
155 	char tmp[4096];
156 	UCHAR hash[SHA1_SIZE];
157 
158 	tmp[0] = 0;
159 	if (a != NULL)
160 	{
161 		for (i = 0;i < a->Num;i++)
162 		{
163 			StrCat(tmp, sizeof(tmp), a->Adapters[i]->Title);
164 		}
165 	}
166 	MsFreeAdapterList(a);
167 
168 	Hash(hash, tmp, StrLen(tmp), true);
169 
170 	Copy(&num, hash, sizeof(UINT));
171 
172 	return num;
173 #endif	// OS_UNIX
174 }
175 
176 // Get whether WinPcap is needed
IsNeedWinPcap()177 bool IsNeedWinPcap()
178 {
179 	if (IsBridgeSupported() == false)
180 	{
181 		// Not in Windows
182 		return false;
183 	}
184 	else
185 	{
186 		// Windows
187 		if (IsEthSupported())
188 		{
189 			// Already success to access the Ethernet device
190 			return false;
191 		}
192 		else
193 		{
194 			// Failed to access the Ethernet device
195 			return true;
196 		}
197 	}
198 }
199 
200 // Get whether the local-bridging is supported by current OS
IsBridgeSupported()201 bool IsBridgeSupported()
202 {
203 	UINT type = GetOsInfo()->OsType;
204 
205 	if (OS_IS_WINDOWS(type))
206 	{
207 		if (IsEthSupported())
208 		{
209 			return true;
210 		}
211 		else
212 		{
213 			bool ret = false;
214 
215 #ifdef	OS_WIN32
216 			ret = MsIsAdmin();
217 #endif	// OS_WIN32
218 
219 			return ret;
220 		}
221 	}
222 	else
223 	{
224 		return IsEthSupported();
225 	}
226 }
227 
228 // Delete a local-bridge
DeleteLocalBridge(CEDAR * c,char * hubname,char * devicename)229 bool DeleteLocalBridge(CEDAR *c, char *hubname, char *devicename)
230 {
231 	bool ret = false;
232 	// Validate arguments
233 	if (c == NULL || hubname == NULL || devicename == NULL)
234 	{
235 		return false;
236 	}
237 
238 	LockList(c->HubList);
239 	{
240 		LockList(c->LocalBridgeList);
241 		{
242 			UINT i;
243 
244 			for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
245 			{
246 				LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
247 
248 				if (StrCmpi(br->HubName, hubname) == 0)
249 				{
250 					if (StrCmpi(br->DeviceName, devicename) == 0)
251 					{
252 						if (br->Bridge != NULL)
253 						{
254 							BrFreeBridge(br->Bridge);
255 							br->Bridge = NULL;
256 						}
257 
258 						Delete(c->LocalBridgeList, br);
259 						Free(br);
260 
261 						ret = true;
262 						break;
263 					}
264 				}
265 			}
266 		}
267 		UnlockList(c->LocalBridgeList);
268 	}
269 	UnlockList(c->HubList);
270 
271 	return ret;
272 }
273 
274 // Add a local-bridge
AddLocalBridge(CEDAR * c,char * hubname,char * devicename,bool local,bool monitor,bool tapmode,char * tapaddr,bool limit_broadcast)275 void AddLocalBridge(CEDAR *c, char *hubname, char *devicename, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast)
276 {
277 	UINT i;
278 	HUB *h = NULL;
279 	LOCALBRIDGE *br = NULL;
280 	// Validate arguments
281 	if (c == NULL || hubname == NULL || devicename == NULL)
282 	{
283 		return;
284 	}
285 
286 	if (OS_IS_UNIX(GetOsInfo()->OsType) == false)
287 	{
288 		tapmode = false;
289 	}
290 
291 	LockList(c->HubList);
292 	{
293 		LockList(c->LocalBridgeList);
294 		{
295 			bool exists = false;
296 
297 			// Ensure that the same configuration local-bridge doesn't exist already
298 			for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
299 			{
300 				LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
301 				if (StrCmpi(br->DeviceName, devicename) == 0)
302 				{
303 					if (StrCmpi(br->HubName, hubname) == 0)
304 					{
305 						if (br->TapMode == tapmode)
306 						{
307 							exists = true;
308 						}
309 					}
310 				}
311 			}
312 
313 			if (exists == false)
314 			{
315 				// Add configuration
316 				br = ZeroMalloc(sizeof(LOCALBRIDGE));
317 				StrCpy(br->HubName, sizeof(br->HubName), hubname);
318 				StrCpy(br->DeviceName, sizeof(br->DeviceName), devicename);
319 				br->Bridge = NULL;
320 				br->Local = local;
321 				br->TapMode = tapmode;
322 				br->LimitBroadcast = limit_broadcast;
323 				br->Monitor = monitor;
324 				if (br->TapMode)
325 				{
326 					if (tapaddr != NULL && IsZero(tapaddr, 6) == false)
327 					{
328 						Copy(br->TapMacAddress, tapaddr, 6);
329 					}
330 					else
331 					{
332 						GenMacAddress(br->TapMacAddress);
333 					}
334 				}
335 
336 				Add(c->LocalBridgeList, br);
337 
338 				// Find the hub
339 				for (i = 0;i < LIST_NUM(c->HubList);i++)
340 				{
341 					HUB *hub = LIST_DATA(c->HubList, i);
342 					if (StrCmpi(hub->Name, br->HubName) == 0)
343 					{
344 						h = hub;
345 						AddRef(h->ref);
346 						break;
347 					}
348 				}
349 			}
350 		}
351 		UnlockList(c->LocalBridgeList);
352 	}
353 	UnlockList(c->HubList);
354 
355 	// Start the local-bridge immediately
356 	if (h != NULL && br != NULL && h->Type != HUB_TYPE_FARM_DYNAMIC)
357 	{
358 		Lock(h->lock_online);
359 		{
360 			if (h->Offline == false)
361 			{
362 				LockList(c->LocalBridgeList);
363 				{
364 					if (IsInList(c->LocalBridgeList, br))
365 					{
366 						if (br->Bridge == NULL)
367 						{
368 							br->Bridge = BrNewBridge(h, br->DeviceName, NULL, br->Local, br->Monitor, br->TapMode, br->TapMacAddress, br->LimitBroadcast, br);
369 						}
370 					}
371 				}
372 				UnlockList(c->LocalBridgeList);
373 			}
374 		}
375 		Unlock(h->lock_online);
376 	}
377 
378 	ReleaseHub(h);
379 }
380 
381 // Initialize the local-bridge list
InitLocalBridgeList(CEDAR * c)382 void InitLocalBridgeList(CEDAR *c)
383 {
384 	// Validate arguments
385 	if (c == NULL)
386 	{
387 		return;
388 	}
389 
390 	c->LocalBridgeList = NewList(NULL);
391 }
392 
393 // Free the local-bridge list
FreeLocalBridgeList(CEDAR * c)394 void FreeLocalBridgeList(CEDAR *c)
395 {
396 	UINT i;
397 	// Validate arguments
398 	if (c == NULL)
399 	{
400 		return;
401 	}
402 
403 	for (i = 0;i < LIST_NUM(c->LocalBridgeList);i++)
404 	{
405 		LOCALBRIDGE *br = LIST_DATA(c->LocalBridgeList, i);
406 		Free(br);
407 	}
408 
409 	ReleaseList(c->LocalBridgeList);
410 	c->LocalBridgeList = NULL;
411 }
412 
413 // Bridging thread
BrBridgeThread(THREAD * thread,void * param)414 void BrBridgeThread(THREAD *thread, void *param)
415 {
416 	BRIDGE *b;
417 	CONNECTION *c;
418 	SESSION *s;
419 	HUB *h;
420 	char name[MAX_SIZE];
421 	// Validate arguments
422 	if (thread == NULL || param == NULL)
423 	{
424 		return;
425 	}
426 
427 	b = (BRIDGE *)param;
428 
429 	// Create a connection object
430 	c = NewServerConnection(b->Cedar, NULL, thread);
431 	c->Protocol = CONNECTION_HUB_BRIDGE;
432 
433 	// Create a session object
434 	s = NewServerSession(b->Cedar, c, b->Hub, BRIDGE_USER_NAME, b->Policy);
435 	HLog(b->Hub, "LH_START_BRIDGE", b->Name, s->Name);
436 	StrCpy(name, sizeof(name), b->Name);
437 	h = b->Hub;
438 	AddRef(h->ref);
439 	s->BridgeMode = true;
440 	s->Bridge = b;
441 	c->Session = s;
442 	ReleaseConnection(c);
443 
444 	// Dummy user name for local-bridge
445 	s->Username = CopyStr(BRIDGE_USER_NAME_PRINT);
446 
447 	b->Session = s;
448 	AddRef(s->ref);
449 
450 	// Notify completion
451 	NoticeThreadInit(thread);
452 
453 	// Main procedure of the session
454 	Debug("Bridge %s Start.\n", b->Name);
455 	SessionMain(s);
456 	Debug("Bridge %s Stop.\n", b->Name);
457 
458 	HLog(h, "LH_STOP_BRIDGE", name);
459 
460 	ReleaseHub(h);
461 
462 	ReleaseSession(s);
463 }
464 
465 // Free the local-bridge object
BrFreeBridge(BRIDGE * b)466 void BrFreeBridge(BRIDGE *b)
467 {
468 	// Validate arguments
469 	if (b == NULL)
470 	{
471 		return;
472 	}
473 
474 	if (b->ParentLocalBridge != NULL)
475 	{
476 		b->ParentLocalBridge = NULL;
477 	}
478 
479 	// Stop session thread
480 	StopSession(b->Session);
481 	ReleaseSession(b->Session);
482 
483 	Free(b);
484 }
485 
486 // Create new local-bridge
BrNewBridge(HUB * h,char * name,POLICY * p,bool local,bool monitor,bool tapmode,char * tapaddr,bool limit_broadcast,LOCALBRIDGE * parent_local_bridge)487 BRIDGE *BrNewBridge(HUB *h, char *name, POLICY *p, bool local, bool monitor, bool tapmode, char *tapaddr, bool limit_broadcast, LOCALBRIDGE *parent_local_bridge)
488 {
489 	BRIDGE *b;
490 	POLICY *policy;
491 	THREAD *t;
492 	// Validate arguments
493 	if (h == NULL || name == NULL || parent_local_bridge == NULL)
494 	{
495 		return NULL;
496 	}
497 
498 	if (p == NULL)
499 	{
500 		policy = ClonePolicy(GetDefaultPolicy());
501 	}
502 	else
503 	{
504 		policy = ClonePolicy(p);
505 	}
506 
507 	b = ZeroMalloc(sizeof(BRIDGE));
508 	b->Cedar = h->Cedar;
509 	b->Hub = h;
510 	StrCpy(b->Name, sizeof(b->Name), name);
511 	b->Policy = policy;
512 	b->Local = local;
513 	b->Monitor = monitor;
514 	b->TapMode = tapmode;
515 	b->LimitBroadcast = limit_broadcast;
516 	b->ParentLocalBridge = parent_local_bridge;
517 
518 	if (b->TapMode)
519 	{
520 		if (tapaddr != NULL && IsZero(tapaddr, 6) == false)
521 		{
522 			Copy(b->TapMacAddress, tapaddr, 6);
523 		}
524 		else
525 		{
526 			GenMacAddress(b->TapMacAddress);
527 		}
528 	}
529 
530 	if (monitor)
531 	{
532 		// Enabling monitoring mode
533 		policy->MonitorPort = true;
534 	}
535 
536 	if (b->LimitBroadcast == false)
537 	{
538 		// Disable broadcast limiter
539 		policy->NoBroadcastLimiter = true;
540 	}
541 
542 	// Start thread
543 	t = NewThread(BrBridgeThread, b);
544 	WaitThreadInit(t);
545 	ReleaseThread(t);
546 
547 	return b;
548 }
549 
550 // Raw IP bridge is supported only on Linux
IsRawIpBridgeSupported()551 bool IsRawIpBridgeSupported()
552 {
553 #ifdef	UNIX_LINUX
554 	return true;
555 #else	// UNIX_LINUX
556 	return false;
557 #endif	// UNIX_LINUX
558 }
559 
560