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 // Sam.c
103 // Security Accounts Manager
104
105 #include "CedarPch.h"
106
107 // Password encryption
SecurePassword(void * secure_password,void * password,void * random)108 void SecurePassword(void *secure_password, void *password, void *random)
109 {
110 BUF *b;
111 // Validate arguments
112 if (secure_password == NULL || password == NULL || random == NULL)
113 {
114 return;
115 }
116
117 b = NewBuf();
118 WriteBuf(b, password, SHA1_SIZE);
119 WriteBuf(b, random, SHA1_SIZE);
120 Hash(secure_password, b->Buf, b->Size, true);
121
122 FreeBuf(b);
123 }
124
125 // Generate 160bit random number
GenRamdom(void * random)126 void GenRamdom(void *random)
127 {
128 // Validate arguments
129 if (random == NULL)
130 {
131 return;
132 }
133
134 Rand(random, SHA1_SIZE);
135 }
136
137 // Anonymous authentication of user
SamAuthUserByAnonymous(HUB * h,char * username)138 bool SamAuthUserByAnonymous(HUB *h, char *username)
139 {
140 bool b = false;
141 // Validate arguments
142 if (h == NULL || username == NULL)
143 {
144 return false;
145 }
146
147 AcLock(h);
148 {
149 USER *u = AcGetUser(h, username);
150 if (u)
151 {
152 Lock(u->lock);
153 {
154 if (u->AuthType == AUTHTYPE_ANONYMOUS)
155 {
156 b = true;
157 }
158 }
159 Unlock(u->lock);
160 }
161 ReleaseUser(u);
162 }
163 AcUnlock(h);
164
165 return b;
166 }
167
168 // Plaintext password authentication of user
SamAuthUserByPlainPassword(CONNECTION * c,HUB * hub,char * username,char * password,bool ast,UCHAR * mschap_v2_server_response_20,RADIUS_LOGIN_OPTION * opt)169 bool SamAuthUserByPlainPassword(CONNECTION *c, HUB *hub, char *username, char *password, bool ast, UCHAR *mschap_v2_server_response_20, RADIUS_LOGIN_OPTION *opt)
170 {
171 bool b = false;
172 wchar_t *name = NULL;
173 bool auth_by_nt = false;
174 HUB *h;
175 // Validate arguments
176 if (hub == NULL || c == NULL || username == NULL)
177 {
178 return false;
179 }
180
181 if (GetGlobalServerFlag(GSF_DISABLE_RADIUS_AUTH) != 0)
182 {
183 return false;
184 }
185
186 h = hub;
187
188 AddRef(h->ref);
189
190 // Get the user name on authentication system
191 AcLock(hub);
192 {
193 USER *u;
194 u = AcGetUser(hub, ast == false ? username : "*");
195 if (u)
196 {
197 Lock(u->lock);
198 {
199 if (u->AuthType == AUTHTYPE_RADIUS)
200 {
201 // Radius authentication
202 AUTHRADIUS *auth = (AUTHRADIUS *)u->AuthData;
203 if (ast || auth->RadiusUsername == NULL || UniStrLen(auth->RadiusUsername) == 0)
204 {
205 if( IsEmptyStr(h->RadiusRealm) == false )
206 {
207 char name_and_realm[MAX_SIZE];
208 StrCpy(name_and_realm, sizeof(name_and_realm), username);
209 StrCat(name_and_realm, sizeof(name_and_realm), "@");
210 StrCat(name_and_realm, sizeof(name_and_realm), h->RadiusRealm);
211 name = CopyStrToUni(name_and_realm);
212 }
213 else
214 {
215 name = CopyStrToUni(username);
216 }
217 }
218 else
219 {
220 name = CopyUniStr(auth->RadiusUsername);
221 }
222 auth_by_nt = false;
223 }
224 else if (u->AuthType == AUTHTYPE_NT)
225 {
226 // NT authentication
227 AUTHNT *auth = (AUTHNT *)u->AuthData;
228 if (ast || auth->NtUsername == NULL || UniStrLen(auth->NtUsername) == 0)
229 {
230 name = CopyStrToUni(username);
231 }
232 else
233 {
234 name = CopyUniStr(auth->NtUsername);
235 }
236 auth_by_nt = true;
237 }
238 }
239 Unlock(u->lock);
240 ReleaseUser(u);
241 }
242 }
243 AcUnlock(hub);
244
245 if (name != NULL)
246 {
247 if (auth_by_nt == false)
248 {
249 // Radius authentication
250 char radius_server_addr[MAX_SIZE];
251 UINT radius_server_port;
252 char radius_secret[MAX_SIZE];
253 char suffix_filter[MAX_SIZE];
254 wchar_t suffix_filter_w[MAX_SIZE];
255 UINT interval;
256
257 Zero(suffix_filter, sizeof(suffix_filter));
258 Zero(suffix_filter_w, sizeof(suffix_filter_w));
259
260 // Get the Radius server information
261 if (GetRadiusServerEx2(hub, radius_server_addr, sizeof(radius_server_addr), &radius_server_port, radius_secret, sizeof(radius_secret), &interval, suffix_filter, sizeof(suffix_filter)))
262 {
263 Unlock(hub->lock);
264
265 StrToUni(suffix_filter_w, sizeof(suffix_filter_w), suffix_filter);
266
267 if (UniIsEmptyStr(suffix_filter_w) || UniEndWith(name, suffix_filter_w))
268 {
269 // Attempt to login
270 b = RadiusLogin(c, radius_server_addr, radius_server_port,
271 radius_secret, StrLen(radius_secret),
272 name, password, interval, mschap_v2_server_response_20, opt, hub->Name);
273
274 if (b)
275 {
276 if (opt != NULL)
277 {
278 opt->Out_IsRadiusLogin = true;
279 }
280 }
281 }
282
283 Lock(hub->lock);
284 }
285 else
286 {
287 HLog(hub, "LH_NO_RADIUS_SETTING", name);
288 }
289 }
290 else
291 {
292 // NT authentication (Not available for non-Win32)
293 #ifdef OS_WIN32
294 IPC_MSCHAP_V2_AUTHINFO mschap;
295 Unlock(hub->lock);
296
297 if (ParseAndExtractMsChapV2InfoFromPassword(&mschap, password) == false)
298 {
299 // Plaintext password authentication
300 b = MsCheckLogon(name, password);
301 }
302 else
303 {
304 UCHAR challenge8[8];
305 UCHAR nt_pw_hash_hash[16];
306 char nt_name[MAX_SIZE];
307
308 UniToStr(nt_name, sizeof(nt_name), name);
309
310 // MS-CHAPv2 authentication
311 MsChapV2_GenerateChallenge8(challenge8, mschap.MsChapV2_ClientChallenge,
312 mschap.MsChapV2_ServerChallenge,
313 mschap.MsChapV2_PPPUsername);
314
315 Debug("MsChapV2_PPPUsername = %s, nt_name = %s\n", mschap.MsChapV2_PPPUsername, nt_name);
316
317 b = MsPerformMsChapV2AuthByLsa(nt_name, challenge8, mschap.MsChapV2_ClientResponse, nt_pw_hash_hash);
318
319 if (b)
320 {
321 if (mschap_v2_server_response_20 != NULL)
322 {
323 MsChapV2Server_GenerateResponse(mschap_v2_server_response_20, nt_pw_hash_hash,
324 mschap.MsChapV2_ClientResponse, challenge8);
325 }
326 }
327 }
328
329 Lock(hub->lock);
330 #else // OS_WIN32
331 // Nothing to do other than Win32
332 #endif // OS_WIN32
333 }
334
335 // Memory release
336 Free(name);
337 }
338
339 ReleaseHub(h);
340
341 return b;
342 }
343
344 // Certificate authentication of user
SamAuthUserByCert(HUB * h,char * username,X * x)345 bool SamAuthUserByCert(HUB *h, char *username, X *x)
346 {
347 bool b = false;
348 // Validate arguments
349 if (h == NULL || username == NULL || x == NULL)
350 {
351 return false;
352 }
353
354 if (GetGlobalServerFlag(GSF_DISABLE_CERT_AUTH) != 0)
355 {
356 return false;
357 }
358
359 // Check expiration date
360 if (CheckXDateNow(x) == false)
361 {
362 return false;
363 }
364
365 // Check the Certification Revocation List
366 if (IsValidCertInHub(h, x) == false)
367 {
368 // Bad
369 wchar_t tmp[MAX_SIZE * 2];
370
371 // Log the contents of the certificate
372 GetAllNameFromX(tmp, sizeof(tmp), x);
373
374 HLog(h, "LH_AUTH_NG_CERT", username, tmp);
375 return false;
376 }
377
378 AcLock(h);
379 {
380 USER *u;
381 u = AcGetUser(h, username);
382 if (u)
383 {
384 Lock(u->lock);
385 {
386 if (u->AuthType == AUTHTYPE_USERCERT)
387 {
388 // Check whether to matche with the registered certificate
389 AUTHUSERCERT *auth = (AUTHUSERCERT *)u->AuthData;
390 if (CompareX(auth->UserX, x))
391 {
392 b = true;
393 }
394 }
395 else if (u->AuthType == AUTHTYPE_ROOTCERT)
396 {
397 // Check whether the certificate has been signed by the root certificate
398 AUTHROOTCERT *auth = (AUTHROOTCERT *)u->AuthData;
399 if (h->HubDb != NULL)
400 {
401 LockList(h->HubDb->RootCertList);
402 {
403 X *root_cert;
404 root_cert = GetIssuerFromList(h->HubDb->RootCertList, x);
405 if (root_cert != NULL)
406 {
407 b = true;
408 if (auth->CommonName != NULL && UniIsEmptyStr(auth->CommonName) == false)
409 {
410 // Compare the CN
411 if (UniStrCmpi(x->subject_name->CommonName, auth->CommonName) != 0)
412 {
413 b = false;
414 }
415 }
416 if (auth->Serial != NULL && auth->Serial->size >= 1)
417 {
418 // Compare the serial number
419 if (CompareXSerial(x->serial, auth->Serial) == false)
420 {
421 b = false;
422 }
423 }
424 }
425 }
426 UnlockList(h->HubDb->RootCertList);
427 }
428 }
429 }
430 Unlock(u->lock);
431 ReleaseUser(u);
432 }
433 }
434 AcUnlock(h);
435
436 if (b)
437 {
438 wchar_t tmp[MAX_SIZE * 2];
439
440 // Log the contents of the certificate
441 GetAllNameFromX(tmp, sizeof(tmp), x);
442
443 HLog(h, "LH_AUTH_OK_CERT", username, tmp);
444 }
445
446 return b;
447 }
448
449 // Get the root certificate that signed the specified certificate from the list
GetIssuerFromList(LIST * cert_list,X * cert)450 X *GetIssuerFromList(LIST *cert_list, X *cert)
451 {
452 UINT i;
453 X *ret = NULL;
454 // Validate arguments
455 if (cert_list == NULL || cert == NULL)
456 {
457 return NULL;
458 }
459
460 for (i = 0;i < LIST_NUM(cert_list);i++)
461 {
462 X *x = LIST_DATA(cert_list, i);
463 // Name comparison
464 if (CheckXDateNow(x))
465 {
466 if (CompareName(x->subject_name, cert->issuer_name))
467 {
468 // Get the public key of the root certificate
469 K *k = GetKFromX(x);
470
471 if (k != NULL)
472 {
473 // Check the signature
474 if (CheckSignature(cert, k))
475 {
476 ret = x;
477 }
478 FreeK(k);
479 }
480 }
481 }
482 if (CompareX(x, cert))
483 {
484 // Complete identical
485 ret = x;
486 }
487 }
488
489 return ret;
490 }
491
492 // Get the policy to be applied for the user
SamGetUserPolicy(HUB * h,char * username)493 POLICY *SamGetUserPolicy(HUB *h, char *username)
494 {
495 POLICY *ret = NULL;
496 // Validate arguments
497 if (h == NULL || username == NULL)
498 {
499 return NULL;
500 }
501
502 AcLock(h);
503 {
504 USER *u;
505 u = AcGetUser(h, username);
506 if (u)
507 {
508 USERGROUP *g = NULL;
509 Lock(u->lock);
510 {
511 if (u->Policy != NULL)
512 {
513 ret = ClonePolicy(u->Policy);
514 }
515
516 g = u->Group;
517
518 if (g != NULL)
519 {
520 AddRef(g->ref);
521 }
522 }
523 Unlock(u->lock);
524
525 ReleaseUser(u);
526 u = NULL;
527
528 if (ret == NULL)
529 {
530 if (g != NULL)
531 {
532 Lock(g->lock);
533 {
534 ret = ClonePolicy(g->Policy);
535 }
536 Unlock(g->lock);
537 }
538 }
539
540 if (g != NULL)
541 {
542 ReleaseGroup(g);
543 }
544 }
545 }
546 AcUnlock(h);
547
548 return ret;
549 }
550
551 // Password authentication of user
SamAuthUserByPassword(HUB * h,char * username,void * random,void * secure_password,char * mschap_v2_password,UCHAR * mschap_v2_server_response_20,UINT * err)552 bool SamAuthUserByPassword(HUB *h, char *username, void *random, void *secure_password, char *mschap_v2_password, UCHAR *mschap_v2_server_response_20, UINT *err)
553 {
554 bool b = false;
555 UCHAR secure_password_check[SHA1_SIZE];
556 bool is_mschap = false;
557 IPC_MSCHAP_V2_AUTHINFO mschap;
558 UINT dummy = 0;
559 // Validate arguments
560 if (h == NULL || username == NULL || secure_password == NULL)
561 {
562 return false;
563 }
564 if (err == NULL)
565 {
566 err = &dummy;
567 }
568
569 *err = 0;
570
571 Zero(&mschap, sizeof(mschap));
572
573 is_mschap = ParseAndExtractMsChapV2InfoFromPassword(&mschap, mschap_v2_password);
574
575 if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0)
576 {
577 // Administrator mode
578 SecurePassword(secure_password_check, h->SecurePassword, random);
579 if (Cmp(secure_password_check, secure_password, SHA1_SIZE) == 0)
580 {
581 return true;
582 }
583 else
584 {
585 return false;
586 }
587 }
588
589 AcLock(h);
590 {
591 USER *u;
592 u = AcGetUser(h, username);
593 if (u)
594 {
595 Lock(u->lock);
596 {
597 if (u->AuthType == AUTHTYPE_PASSWORD)
598 {
599 AUTHPASSWORD *auth = (AUTHPASSWORD *)u->AuthData;
600
601 if (is_mschap == false)
602 {
603 // Normal password authentication
604 SecurePassword(secure_password_check, auth->HashedKey, random);
605 if (Cmp(secure_password_check, secure_password, SHA1_SIZE) == 0)
606 {
607 b = true;
608 }
609 }
610 else
611 {
612 // MS-CHAP v2 authentication via PPP
613 UCHAR challenge8[8];
614 UCHAR client_response[24];
615
616 if (IsZero(auth->NtLmSecureHash, MD5_SIZE))
617 {
618 // NTLM hash is not registered in the user account
619 *err = ERR_MSCHAP2_PASSWORD_NEED_RESET;
620 }
621 else
622 {
623 UCHAR nt_pw_hash_hash[16];
624 Zero(challenge8, sizeof(challenge8));
625 Zero(client_response, sizeof(client_response));
626
627 MsChapV2_GenerateChallenge8(challenge8, mschap.MsChapV2_ClientChallenge, mschap.MsChapV2_ServerChallenge,
628 mschap.MsChapV2_PPPUsername);
629
630 MsChapV2Client_GenerateResponse(client_response, challenge8, auth->NtLmSecureHash);
631
632 if (Cmp(client_response, mschap.MsChapV2_ClientResponse, 24) == 0)
633 {
634 // Hash matched
635 b = true;
636
637 // Calculate the response
638 GenerateNtPasswordHashHash(nt_pw_hash_hash, auth->NtLmSecureHash);
639 MsChapV2Server_GenerateResponse(mschap_v2_server_response_20, nt_pw_hash_hash,
640 client_response, challenge8);
641 }
642 }
643 }
644 }
645 }
646 Unlock(u->lock);
647 ReleaseUser(u);
648 }
649 }
650 AcUnlock(h);
651
652 return b;
653 }
654
655 // Make sure that the user exists
SamIsUser(HUB * h,char * username)656 bool SamIsUser(HUB *h, char *username)
657 {
658 bool b;
659 // Validate arguments
660 if (h == NULL || username == NULL)
661 {
662 return false;
663 }
664
665 AcLock(h);
666 {
667 b = AcIsUser(h, username);
668 }
669 AcUnlock(h);
670
671 return b;
672 }
673
674 // Get the type of authentication used by the user
SamGetUserAuthType(HUB * h,char * username)675 UINT SamGetUserAuthType(HUB *h, char *username)
676 {
677 UINT authtype;
678 // Validate arguments
679 if (h == NULL || username == NULL)
680 {
681 return INFINITE;
682 }
683
684 AcLock(h);
685 {
686 USER *u = AcGetUser(h, username);
687 if (u == NULL)
688 {
689 authtype = INFINITE;
690 }
691 else
692 {
693 authtype = u->AuthType;
694 ReleaseUser(u);
695 }
696 }
697 AcUnlock(h);
698
699 return authtype;
700 }
701
702