1 // SoftEther UT-VPN SourceCode
\r
3 // Copyright (C) 2004-2010 SoftEther Corporation.
\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.
\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.
\r
6 // All Rights Reserved.
\r
8 // http://utvpn.tsukuba.ac.jp/
\r
10 // This program is free software; you can redistribute it and/or
\r
11 // modify it under the terms of the GNU General Public License
\r
12 // version 2 as published by the Free Software Foundation.
\r
14 // This program is distributed in the hope that it will be useful,
\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
17 // GNU General Public License for more details.
\r
19 // You should have received a copy of the GNU General Public License version 2
\r
20 // along with this program; if not, write to the Free Software
\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
\r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。
\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の
\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
\r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
\r
34 // および、試験または研究のために利用が行われることを想定して配布
\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
\r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
\r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。
\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
\r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の
\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
\r
58 // 公益保護にご協力いただきますようお願い申し上げます。
\r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
\r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
\r
65 // 日本国内の脆弱性情報届出受付公的機関:
\r
67 // http://www.ipa.go.jp/security/vuln/report/
\r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/
\r
72 // -----------------------------------------------
\r
75 // 新規リリース by SoftEther
\r
76 // -----------------------------------------------
\r
79 // SoftEther プロトコル関係のルーチン
\r
81 #include "CedarPch.h"
\r
83 static char http_404_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>404 Not Found</TITLE>\r\n</HEAD><BODY>\r\n<H1>Not Found</H1>\r\nThe requested URL $TARGET$ was not found on this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
\r
84 static char http_403_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access $TARGET$\r\non this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
\r
85 static char http_501_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>501 Method Not Implemented</TITLE>\r\n</HEAD><BODY>\r\n<H1>Method Not Implemented</H1>\r\n$METHOD$ to $TARGET$ not supported.<P>\r\nInvalid method in request $METHOD$ $TARGET$ $VERSION$<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
\r
87 // マシンごとにユニークな ID を生成する
\r
88 void GenerateMachineUniqueHash(void *data)
\r
102 GetMachineName(name, sizeof(name));
\r
104 IPToStr(ip_str, sizeof(ip_str), &ip);
\r
106 osinfo = GetOsInfo();
\r
108 WriteBuf(b, name, StrLen(name));
\r
109 WriteBuf(b, ip_str, StrLen(ip_str));
\r
111 WriteBuf(b, &osinfo->OsType, sizeof(osinfo->OsType));
\r
112 WriteBuf(b, osinfo->KernelName, StrLen(osinfo->KernelName));
\r
113 WriteBuf(b, osinfo->KernelVersion, StrLen(osinfo->KernelVersion));
\r
114 WriteBuf(b, osinfo->OsProductName, StrLen(osinfo->OsProductName));
\r
115 WriteBuf(b, &osinfo->OsServicePack, sizeof(osinfo->OsServicePack));
\r
116 WriteBuf(b, osinfo->OsSystemName, StrLen(osinfo->OsSystemName));
\r
117 WriteBuf(b, osinfo->OsVendorName, StrLen(osinfo->OsVendorName));
\r
118 WriteBuf(b, osinfo->OsVersion, StrLen(osinfo->OsVersion));
\r
120 Hash(data, b->Buf, b->Size, true);
\r
126 void NodeInfoToStr(wchar_t *str, UINT size, NODE_INFO *info)
\r
128 char client_ip[128], server_ip[128], proxy_ip[128], unique_id[128];
\r
130 if (str == NULL || info == NULL)
\r
135 IPToStr4or6(client_ip, sizeof(client_ip), info->ClientIpAddress, info->ClientIpAddress6);
\r
136 IPToStr4or6(server_ip, sizeof(server_ip), info->ServerIpAddress, info->ServerIpAddress6);
\r
137 IPToStr4or6(proxy_ip, sizeof(proxy_ip), info->ProxyIpAddress, info->ProxyIpAddress6);
\r
138 BinToStr(unique_id, sizeof(unique_id), info->UniqueId, sizeof(info->UniqueId));
\r
140 UniFormat(str, size, _UU("LS_NODE_INFO_TAG"), info->ClientProductName,
\r
141 Endian32(info->ClientProductVer), Endian32(info->ClientProductBuild),
\r
142 info->ServerProductName, Endian32(info->ServerProductVer), Endian32(info->ServerProductBuild),
\r
143 info->ClientOsName, info->ClientOsVer, info->ClientOsProductId,
\r
144 info->ClientHostname, client_ip, Endian32(info->ClientPort),
\r
145 info->ServerHostname, server_ip, Endian32(info->ServerPort),
\r
146 info->ProxyHostname, proxy_ip, Endian32(info->ProxyPort),
\r
147 info->HubName, unique_id);
\r
151 bool CompareNodeInfo(NODE_INFO *a, NODE_INFO *b)
\r
154 if (a == NULL || b == NULL)
\r
159 // このあたりは急いで実装したのでコードがあまり美しくない。
\r
160 if (StrCmp(a->ClientProductName, b->ClientProductName) != 0)
\r
164 if (a->ClientProductVer != b->ClientProductVer)
\r
168 if (a->ClientProductBuild != b->ClientProductBuild)
\r
172 if (StrCmp(a->ServerProductName, b->ServerProductName) != 0)
\r
176 if (a->ServerProductVer != b->ServerProductVer)
\r
180 if (a->ServerProductBuild != b->ServerProductBuild)
\r
184 if (StrCmp(a->ClientOsName, b->ClientOsName) != 0)
\r
188 if (StrCmp(a->ClientOsVer, b->ClientOsVer) != 0)
\r
192 if (StrCmp(a->ClientOsProductId, b->ClientOsProductId) != 0)
\r
196 if (StrCmp(a->ClientHostname, b->ClientHostname) != 0)
\r
200 if (a->ClientIpAddress != b->ClientIpAddress)
\r
204 if (StrCmp(a->ServerHostname, b->ServerHostname) != 0)
\r
208 if (a->ServerIpAddress != b->ServerIpAddress)
\r
212 if (a->ServerPort != b->ServerPort)
\r
216 if (StrCmp(a->ProxyHostname, b->ProxyHostname) != 0)
\r
220 if (a->ProxyIpAddress != b->ProxyIpAddress)
\r
224 if (a->ProxyPort != b->ProxyPort)
\r
228 if (StrCmp(a->HubName, b->HubName) != 0)
\r
232 if (Cmp(a->UniqueId, b->UniqueId, 16) != 0)
\r
241 UINT ChangePasswordAccept(CONNECTION *c, PACK *p)
\r
244 UCHAR random[SHA1_SIZE];
\r
245 char hubname[MAX_HUBNAME_LEN + 1];
\r
246 char username[MAX_USERNAME_LEN + 1];
\r
247 UCHAR secure_old_password[SHA1_SIZE];
\r
248 UCHAR new_password[SHA1_SIZE];
\r
249 UCHAR check_secure_old_password[SHA1_SIZE];
\r
250 UINT ret = ERR_NO_ERROR;
\r
254 if (c == NULL || p == NULL)
\r
256 return ERR_INTERNAL_ERROR;
\r
259 Copy(random, c->Random, SHA1_SIZE);
\r
260 if (PackGetStr(p, "hubname", hubname, sizeof(hubname)) == false ||
\r
261 PackGetStr(p, "username", username, sizeof(username)) == false ||
\r
262 PackGetData2(p, "secure_old_password", secure_old_password, sizeof(secure_old_password)) == false ||
\r
263 PackGetData2(p, "new_password", new_password, sizeof(new_password)) == false)
\r
265 return ERR_PROTOCOL_ERROR;
\r
270 LockHubList(cedar);
\r
272 hub = GetHub(cedar, hubname);
\r
274 UnlockHubList(cedar);
\r
278 ret = ERR_HUB_NOT_FOUND;
\r
282 char tmp[MAX_SIZE];
\r
284 if (GetHubAdminOption(hub, "deny_change_user_password") != 0)
\r
287 return ERR_NOT_ENOUGH_RIGHT;
\r
290 IPToStr(tmp, sizeof(tmp), &c->FirstSock->RemoteIP);
\r
291 HLog(hub, "LH_CHANGE_PASSWORD_1", c->Name, tmp);
\r
295 USER *u = AcGetUser(hub, username);
\r
298 HLog(hub, "LH_CHANGE_PASSWORD_2", c->Name, username);
\r
299 ret = ERR_OLD_PASSWORD_WRONG;
\r
305 if (u->AuthType != AUTHTYPE_PASSWORD)
\r
308 HLog(hub, "LH_CHANGE_PASSWORD_3", c->Name, username);
\r
309 ret = ERR_USER_AUTHTYPE_NOT_PASSWORD;
\r
313 bool fix_password = false;
\r
314 if (u->Policy != NULL)
\r
316 fix_password = u->Policy->FixPassword;
\r
320 if (u->Group != NULL)
\r
322 if (u->Group->Policy != NULL)
\r
324 fix_password = u->Group->Policy->FixPassword;
\r
328 if (fix_password == false)
\r
331 AUTHPASSWORD *pw = (AUTHPASSWORD *)u->AuthData;
\r
333 SecurePassword(check_secure_old_password, pw->HashedKey, random);
\r
334 if (Cmp(check_secure_old_password, secure_old_password, SHA1_SIZE) != 0)
\r
337 ret = ERR_OLD_PASSWORD_WRONG;
\r
338 HLog(hub, "LH_CHANGE_PASSWORD_4", c->Name, username);
\r
343 Copy(pw->HashedKey, new_password, SHA1_SIZE);
\r
344 HLog(hub, "LH_CHANGE_PASSWORD_5", c->Name, username);
\r
351 ret = ERR_NOT_ENOUGH_RIGHT;
\r
368 UINT ChangePassword(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, char *username, char *old_pass, char *new_pass)
\r
370 UINT ret = ERR_NO_ERROR;
\r
371 UCHAR old_password[SHA1_SIZE];
\r
372 UCHAR secure_old_password[SHA1_SIZE];
\r
373 UCHAR new_password[SHA1_SIZE];
\r
377 if (cedar == NULL || o == NULL || hubname == NULL || username == NULL || old_pass == NULL || new_pass == NULL)
\r
379 return ERR_INTERNAL_ERROR;
\r
384 s = NewRpcSessionEx(cedar, o, &ret, NULL);
\r
388 PACK *p = NewPack();
\r
390 sock = s->Connection->FirstSock;
\r
392 HashPassword(old_password, username, old_pass);
\r
393 SecurePassword(secure_old_password, old_password, s->Connection->Random);
\r
394 HashPassword(new_password, username, new_pass);
\r
396 PackAddClientVersion(p, s->Connection);
\r
398 PackAddStr(p, "method", "password");
\r
399 PackAddStr(p, "hubname", hubname);
\r
400 PackAddStr(p, "username", username);
\r
401 PackAddData(p, "secure_old_password", secure_old_password, SHA1_SIZE);
\r
402 PackAddData(p, "new_password", new_password, SHA1_SIZE);
\r
404 if (HttpClientSend(sock, p))
\r
406 PACK *p = HttpClientRecv(sock);
\r
409 ret = ERR_DISCONNECTED;
\r
413 ret = GetErrorFromPack(p);
\r
419 ret = ERR_DISCONNECTED;
\r
430 TOKEN_LIST *EnumHub(SESSION *s)
\r
438 if (s == NULL || s->Connection == NULL)
\r
443 sock = s->Connection->FirstSock;
\r
450 SetTimeout(sock, 10000);
\r
453 PackAddStr(p, "method", "enum_hub");
\r
455 PackAddClientVersion(p, s->Connection);
\r
457 if (HttpClientSend(sock, p) == false)
\r
464 p = HttpClientRecv(sock);
\r
470 num = PackGetInt(p, "NumHub");
\r
471 ret = ZeroMalloc(sizeof(TOKEN_LIST));
\r
472 ret->NumTokens = num;
\r
473 ret->Token = ZeroMalloc(sizeof(char *) * num);
\r
474 for (i = 0;i < num;i++)
\r
476 char tmp[MAX_SIZE];
\r
477 if (PackGetStrEx(p, "HubName", tmp, sizeof(tmp), i))
\r
479 ret->Token[i] = CopyStr(tmp);
\r
487 // サーバーがクライアントからの接続を受け付ける
\r
488 bool ServerAccept(CONNECTION *c)
\r
493 char username_real[MAX_SIZE];
\r
494 char method[MAX_SIZE];
\r
495 char hubname[MAX_SIZE];
\r
496 char username[MAX_SIZE];
\r
497 char groupname[MAX_SIZE];
\r
498 UCHAR session_key[SHA1_SIZE];
\r
499 UCHAR ticket[SHA1_SIZE];
\r
500 RC4_KEY_PAIR key_pair;
\r
505 UINT64 user_expires = 0;
\r
508 bool half_connection;
\r
510 bool admin_mode = false;
\r
512 UINT max_connection;
\r
514 bool farm_controller = false;
\r
515 bool farm_member = false;
\r
516 bool farm_mode = false;
\r
517 bool require_bridge_routing_mode;
\r
518 bool require_monitor_mode;
\r
519 bool use_client_license = false, use_bridge_license = false;
\r
520 bool local_host_session = false;
\r
521 char sessionname[MAX_SESSION_NAME_LEN + 1];
\r
522 bool is_server_or_bridge = false;
\r
524 bool cluster_dynamic_secure_nat = false;
\r
525 bool no_save_password = false;
\r
527 wchar_t *msg = NULL;
\r
528 USER *loggedin_user_object = NULL;
\r
529 FARM_MEMBER *f = NULL;
\r
530 SERVER *server = NULL;
\r
531 POLICY ticketed_policy;
\r
533 UCHAR unique[SHA1_SIZE], unique2[SHA1_SIZE];
\r
534 LICENSE_STATUS license;
\r
538 bool no_more_users_in_server = false;
\r
546 Zero(&winver, sizeof(winver));
\r
548 StrCpy(groupname, sizeof(groupname), "");
\r
549 StrCpy(sessionname, sizeof(sessionname), "");
\r
554 Zero(&license, sizeof(license));
\r
555 if (c->Cedar->Server != NULL)
\r
557 LiParseCurrentLicenseStatus(c->Cedar->Server->LicenseSystem, &license);
\r
560 no_more_users_in_server = SiTooManyUserObjectsInServer(cedar->Server, true);
\r
562 c->Status = CONNECTION_STATUS_NEGOTIATION;
\r
564 if (c->Cedar->Server != NULL)
\r
566 SERVER *s = c->Cedar->Server;
\r
569 if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
\r
571 farm_member = true;
\r
575 if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
\r
577 farm_controller = true;
\r
583 Debug("Downloading Signature...\n");
\r
584 if (ServerDownloadSignature(c) == false)
\r
590 Debug("Uploading Hello...\n");
\r
591 if (ServerUploadHello(c) == false)
\r
597 Debug("Auth...\n");
\r
599 p = HttpServerRecv(c->FirstSock);
\r
603 c->Err = ERR_DISCONNECTED;
\r
607 if (err = GetErrorFromPack(p))
\r
616 if (GetMethodFromPack(p, method, sizeof(method)) == false)
\r
620 c->Err = ERR_PROTOCOL_ERROR;
\r
625 timestamp = PackGetInt64(p, "timestamp");
\r
626 if (timestamp != 0)
\r
628 UINT64 now = SystemTime64();
\r
630 if (now >= timestamp)
\r
632 abs = now - timestamp;
\r
636 abs = timestamp - now;
\r
639 if (abs > ALLOW_TIMESTAMP_DIFF)
\r
643 c->Err = ERR_BAD_CLOCK;
\r
649 PackGetStr(p, "client_str", c->ClientStr, sizeof(c->ClientStr));
\r
650 c->ClientVer = PackGetInt(p, "client_ver");
\r
651 c->ClientBuild = PackGetInt(p, "client_build");
\r
653 if (SearchStrEx(c->ClientStr, "server", 0, false) != INFINITE ||
\r
654 SearchStrEx(c->ClientStr, "bridge", 0, false) != INFINITE)
\r
656 is_server_or_bridge = true;
\r
659 // クライアント Windows バージョンの取得
\r
660 InRpcWinVer(&winver, p);
\r
662 DecrementNoSsl(c->Cedar, &c->FirstSock->RemoteIP, 2);
\r
664 if (StrCmpi(method, "login") == 0)
\r
666 bool auth_ret = false;
\r
668 Debug("Login...\n");
\r
669 c->Status = CONNECTION_STATUS_USERAUTH;
\r
671 c->Type = CONNECTION_TYPE_LOGIN;
\r
673 if (no_more_users_in_server)
\r
675 // VPN Server に許可されているよりも多くのユーザーが存在する
\r
677 c->Err = ERR_TOO_MANY_USER;
\r
682 if (PackGetStr(p, "hello", c->ClientStr, sizeof(c->ClientStr)) == false)
\r
684 StrCpy(c->ClientStr, sizeof(c->ClientStr), "Unknown");
\r
686 c->ServerVer = CEDAR_VER;
\r
687 c->ServerBuild = CEDAR_BUILD;
\r
690 Zero(&node, sizeof(node));
\r
691 InRpcNodeInfo(&node, p);
\r
694 c->Protocol = GetProtocolFromPack(p);
\r
695 if (c->Protocol == CONNECTION_UDP)
\r
700 ReleaseList(c->Tcp->TcpSockList);
\r
705 if (GetServerCapsBool(c->Cedar->Server, "b_vpn_client_connect") == false)
\r
707 // VPN クライアントが接続不可能である
\r
709 c->Err = ERR_NOT_SUPPORTED;
\r
714 if (GetHubnameAndUsernameFromPack(p, username, sizeof(username), hubname, sizeof(hubname)) == false)
\r
718 c->Err = ERR_PROTOCOL_ERROR;
\r
727 authtype = GetAuthTypeFromPack(p);
\r
728 if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 &&
\r
729 authtype == AUTHTYPE_PASSWORD)
\r
734 if (authtype == AUTHTYPE_TICKET)
\r
741 // サーバーファームメンバへの Administrators 以外の直接ログオンは
\r
744 SLog(c->Cedar, "LS_FARMMEMBER_NOT_ADMIN", c->Name, hubname, ADMINISTRATOR_USERNAME, username);
\r
745 c->Err = ERR_ACCESS_DENIED;
\r
750 Debug("Username = %s, HubName = %s\n", username, hubname);
\r
751 LockHubList(c->Cedar);
\r
753 hub = GetHub(c->Cedar, hubname);
\r
755 UnlockHubList(c->Cedar);
\r
760 c->Err = ERR_HUB_NOT_FOUND;
\r
761 SLog(c->Cedar, "LS_HUB_NOT_FOUND", c->Name, hubname);
\r
769 if (hub->Halt || hub->Offline)
\r
775 c->Err = ERR_HUB_STOPPING;
\r
780 use_encrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
\r
781 use_compress = PackGetInt(p, "use_compress") == 0 ? false : true;
\r
782 max_connection = PackGetInt(p, "max_connection");
\r
783 half_connection = PackGetInt(p, "half_connection") == 0 ? false : true;
\r
784 use_fast_rc4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
\r
785 qos = PackGetInt(p, "qos") ? true : false;
\r
786 client_id = PackGetInt(p, "client_id");
\r
789 require_bridge_routing_mode = PackGetBool(p, "require_bridge_routing_mode");
\r
790 require_monitor_mode = PackGetBool(p, "require_monitor_mode");
\r
791 if (require_monitor_mode)
\r
796 if (is_server_or_bridge)
\r
798 require_bridge_routing_mode = true;
\r
802 Zero(unique, sizeof(unique));
\r
803 if (PackGetDataSize(p, "unique_id") == SHA1_SIZE)
\r
805 PackGetData(p, "unique_id", unique);
\r
809 authtype = GetAuthTypeFromPack(p);
\r
814 char ip1[64], ip2[64], verstr[64];
\r
815 wchar_t *authtype_str = _UU("LH_AUTH_UNKNOWN");
\r
818 case CLIENT_AUTHTYPE_ANONYMOUS:
\r
819 authtype_str = _UU("LH_AUTH_ANONYMOUS");
\r
821 case CLIENT_AUTHTYPE_PASSWORD:
\r
822 authtype_str = _UU("LH_AUTH_PASSWORD");
\r
824 case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
\r
825 authtype_str = _UU("LH_AUTH_PLAIN_PASSWORD");
\r
827 case CLIENT_AUTHTYPE_CERT:
\r
828 authtype_str = _UU("LH_AUTH_CERT");
\r
830 case AUTHTYPE_TICKET:
\r
831 authtype_str = _UU("LH_AUTH_TICKET");
\r
834 IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
\r
835 IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
\r
837 Format(verstr, sizeof(verstr), "%u.%02u", c->ClientVer / 100, c->ClientVer % 100);
\r
839 HLog(hub, "LH_CONNECT_CLIENT", c->Name, ip1, c->FirstSock->RemoteHostname, c->FirstSock->RemotePort,
\r
840 c->ClientStr, verstr, c->ClientBuild, authtype_str, username);
\r
844 auth_ret = SamAuthUserByAnonymous(hub, username);
\r
849 HLog(hub, "LH_AUTH_OK", c->Name, username);
\r
852 if (auth_ret == false)
\r
854 // 匿名認証に失敗した場合は他の認証方法を試行する
\r
857 case CLIENT_AUTHTYPE_ANONYMOUS:
\r
858 // 匿名認証 (すでに試行している)
\r
861 case AUTHTYPE_TICKET:
\r
863 if (PackGetDataSize(p, "ticket") == SHA1_SIZE)
\r
865 PackGetData(p, "ticket", ticket);
\r
867 auth_ret = SiCheckTicket(hub, ticket, username, sizeof(username), username_real, sizeof(username_real),
\r
868 &ticketed_policy, sessionname, sizeof(sessionname), groupname, sizeof(groupname));
\r
872 case CLIENT_AUTHTYPE_PASSWORD:
\r
874 if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
\r
876 POLICY *pol = NULL;
\r
877 UCHAR secure_password[SHA1_SIZE];
\r
878 Zero(secure_password, sizeof(secure_password));
\r
879 if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
\r
881 PackGetData(p, "secure_password", secure_password);
\r
883 auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password);
\r
885 pol = SamGetUserPolicy(hub, username);
\r
888 no_save_password = pol->NoSavePassword;
\r
894 case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
\r
895 // 外部サーバーによる認証はサポートされていない
\r
896 HLog(hub, "LH_AUTH_RADIUS_NOT_SUPPORT", c->Name, username);
\r
900 c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
\r
903 case CLIENT_AUTHTYPE_CERT:
\r
904 // 証明書認証はサポートされていない
\r
905 HLog(hub, "LH_AUTH_CERT_NOT_SUPPORT", c->Name, username);
\r
909 c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
\r
917 c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
\r
921 if (auth_ret == false)
\r
924 HLog(hub, "LH_AUTH_NG", c->Name, username);
\r
929 HLog(hub, "LH_AUTH_OK", c->Name, username);
\r
933 if (auth_ret == false)
\r
939 c->Err = ERR_AUTH_FAILED;
\r
944 if (authtype == CLIENT_AUTHTYPE_PASSWORD)
\r
946 UCHAR test[SHA1_SIZE];
\r
947 HashPassword(test, username, "");
\r
948 if (Cmp(test, hub->SecurePassword, SHA1_SIZE) == 0)
\r
950 SOCK *s = c->FirstSock;
\r
953 if (GetHubAdminOption(hub, "deny_empty_password") != 0 ||
\r
954 (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 && s->RemoteIP.addr[0] != 127))
\r
956 // パスワードが空のとき、リモートから接続してはいけない
\r
957 HLog(hub, "LH_LOCAL_ONLY", c->Name, username);
\r
962 c->Err = ERR_NULL_PASSWORD_LOCAL_ONLY;
\r
975 if (StrCmpi(username, ADMINISTRATOR_USERNAME) != 0)
\r
978 if (farm_member == false)
\r
981 user = AcGetUser(hub, username);
\r
984 user = AcGetUser(hub, "*");
\r
990 c->Err = ERR_ACCESS_DENIED;
\r
1000 user_expires = user->ExpireTime;
\r
1002 StrCpy(username_real, sizeof(username_real), user->Name);
\r
1003 group = user->Group;
\r
1004 if (group != NULL)
\r
1006 AddRef(group->ref);
\r
1008 Lock(group->lock);
\r
1011 StrCpy(groupname, sizeof(groupname), group->Name);
\r
1013 Unlock(group->lock);
\r
1016 if (user->Policy != NULL)
\r
1018 policy = ClonePolicy(user->Policy);
\r
1024 Lock(group->lock);
\r
1026 if (group->Policy != NULL)
\r
1028 policy = ClonePolicy(group->Policy);
\r
1031 Unlock(group->lock);
\r
1035 if (group != NULL)
\r
1037 ReleaseGroup(group);
\r
1040 Unlock(user->lock);
\r
1041 loggedin_user_object = user;
\r
1046 policy = ClonePolicy(&ticketed_policy);
\r
1052 admin_mode = true;
\r
1053 StrCpy(username_real, sizeof(username_real), ADMINISTRATOR_USERNAME);
\r
1055 policy = ClonePolicy(GetDefaultPolicy());
\r
1056 policy->NoBroadcastLimiter = true;
\r
1057 policy->MonitorPort = true;
\r
1060 if (policy == NULL)
\r
1062 // デフォルトのポリシーを使用する
\r
1063 policy = ClonePolicy(GetDefaultPolicy());
\r
1066 if (policy->MaxConnection == 0)
\r
1068 policy->MaxConnection = MAX_TCP_CONNECTION;
\r
1071 if (policy->TimeOut == 0)
\r
1073 policy->TimeOut = 20;
\r
1079 if (policy->NoQoS)
\r
1084 if (GetServerCapsBool(c->Cedar->Server, "b_support_qos") == false)
\r
1088 policy->NoQoS = true;
\r
1090 if (GetHubAdminOption(hub, "deny_qos") != 0)
\r
1092 // 管理オプションで禁止されている
\r
1094 policy->NoQoS = true;
\r
1098 if (GetHubAdminOption(hub, "max_bitrates_download") != 0)
\r
1100 if (policy->MaxDownload == 0)
\r
1102 policy->MaxDownload = GetHubAdminOption(hub, "max_bitrates_download");
\r
1106 policy->MaxDownload = MIN(policy->MaxDownload, GetHubAdminOption(hub, "max_bitrates_download"));
\r
1110 if (GetHubAdminOption(hub, "max_bitrates_upload") != 0)
\r
1112 if (policy->MaxUpload == 0)
\r
1114 policy->MaxUpload = GetHubAdminOption(hub, "max_bitrates_upload");
\r
1118 policy->MaxUpload = MIN(policy->MaxUpload, GetHubAdminOption(hub, "max_bitrates_upload"));
\r
1122 if (GetHubAdminOption(hub, "deny_bridge") != 0)
\r
1124 policy->NoBridge = true;
\r
1127 if (GetHubAdminOption(hub, "deny_routing") != 0)
\r
1129 policy->NoRouting = true;
\r
1132 if (hub->Option->ClientMinimumRequiredBuild > c->ClientBuild &&
\r
1133 InStrEx(c->ClientStr, "client", false))
\r
1135 // クライアントのビルド番号が小さすぎる
\r
1136 HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, hub->Option->ClientMinimumRequiredBuild);
\r
1138 Unlock(hub->lock);
\r
1140 c->Err = ERR_VERSION_INVALID;
\r
1145 if (hub->Option->RequiredClientId != 0 &&
\r
1146 hub->Option->RequiredClientId != client_id &&
\r
1147 InStrEx(c->ClientStr, "client", false))
\r
1149 // クライアントのビルド番号が小さすぎる
\r
1150 HLog(hub, "LH_CLIENT_ID_REQUIRED", c->Name, client_id, hub->Option->RequiredClientId);
\r
1152 Unlock(hub->lock);
\r
1154 c->Err = ERR_CLIENT_ID_REQUIRED;
\r
1159 if ((policy->NoSavePassword) || (policy->AutoDisconnect != 0))
\r
1161 if (c->ClientBuild < 6560 && InStrEx(c->ClientStr, "client", false))
\r
1163 // NoSavePassword ポリシーが指定されている場合は対応クライアント
\r
1165 HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, 6560);
\r
1167 Unlock(hub->lock);
\r
1169 c->Err = ERR_VERSION_INVALID;
\r
1175 if (user_expires != 0 && user_expires <= SystemTime64())
\r
1179 HLog(hub, "LH_USER_EXPIRES", c->Name, username);
\r
1181 Unlock(hub->lock);
\r
1183 c->Err = ERR_ACCESS_DENIED;
\r
1188 if (policy->Access == false)
\r
1191 HLog(hub, "LH_POLICY_ACCESS_NG", c->Name, username);
\r
1193 Unlock(hub->lock);
\r
1195 c->Err = ERR_ACCESS_DENIED;
\r
1200 // ポリシーの内容をクライアントが要求したオプションと比較して
\r
1202 // 最初にモニタポートモードで接続できるかどうか確認する
\r
1203 if (require_monitor_mode && policy->MonitorPort == false)
\r
1205 // モニタポートモードで接続できない
\r
1206 HLog(hub, "LH_POLICY_MONITOR_MODE", c->Name);
\r
1208 Unlock(hub->lock);
\r
1210 c->Err = ERR_MONITOR_MODE_DENIED;
\r
1215 if (policy->MonitorPort)
\r
1217 if (require_monitor_mode == false)
\r
1219 policy->MonitorPort = false;
\r
1223 if (policy->MonitorPort)
\r
1228 // 次にブリッジ / ルーティングモードで接続できるか確認する
\r
1229 if (require_bridge_routing_mode &&
\r
1230 (policy->NoBridge && policy->NoRouting))
\r
1232 // ブリッジ / ルーティングモードで接続できない
\r
1233 HLog(hub, "LH_POLICY_BRIDGE_MODE", c->Name);
\r
1235 Unlock(hub->lock);
\r
1237 c->Err = ERR_BRIDGE_MODE_DENIED;
\r
1242 if (require_bridge_routing_mode == false)
\r
1244 policy->NoBridge = true;
\r
1245 policy->NoRouting = true;
\r
1248 // ライセンスが必要かどうかチェック
\r
1249 GenerateMachineUniqueHash(unique2);
\r
1251 if (Cmp(unique, unique2, SHA1_SIZE) == 0)
\r
1253 // ローカルホストセッションである
\r
1254 local_host_session = true;
\r
1258 if (license.NumUserLicense != INFINITE)
\r
1260 // ユーザー作成数が制限されているエディションでは多重ログイン禁止
\r
1261 policy->MultiLogins = 1;
\r
1264 if (policy->NoBridge == false || policy->NoRouting == false)
\r
1267 use_bridge_license = true;
\r
1272 use_client_license = true;
\r
1276 if (server != NULL && server->ServerType != SERVER_TYPE_FARM_MEMBER &&
\r
1277 (use_bridge_license || use_client_license))
\r
1279 // クラスタコントローラまたはスタンドアロンサーバーの場合で
\r
1280 // クライアントにライセンスが必要になった場合、ここでライセンス数が
\r
1283 if (use_client_license)
\r
1285 if (server->CurrentAssignedClientLicense >= license.NumClientLicense)
\r
1287 // クライアント接続ライセンスが足りない
\r
1288 Unlock(hub->lock);
\r
1291 HLog(hub, "LH_NOT_ENOUGH_CLIENT_LICENSE", c->Name,
\r
1292 license.NumClientLicense,
\r
1293 server->CurrentAssignedClientLicense + 1);
\r
1296 c->Err = ERR_CLIENT_LICENSE_NOT_ENOUGH;
\r
1301 if (use_bridge_license)
\r
1303 if (server->CurrentAssignedBridgeLicense >= license.NumBridgeLicense)
\r
1305 // ブリッジ接続ライセンス数が足りない
\r
1306 Unlock(hub->lock);
\r
1309 HLog(hub, "LH_NOT_ENOUGH_BRIDGE_LICENSE", c->Name,
\r
1310 license.NumBridgeLicense,
\r
1311 server->CurrentAssignedBridgeLicense + 1);
\r
1314 c->Err = ERR_BRIDGE_LICENSE_NOT_ENOUGH;
\r
1321 if (server != NULL && server->ServerType != SERVER_TYPE_FARM_MEMBER &&
\r
1324 if (GetServerCapsBool(hub->Cedar->Server, "b_support_limit_multilogin"))
\r
1326 // ポリシーで多重ログイン制限数が指定されている場合は確認する
\r
1327 RPC_ENUM_SESSION t;
\r
1329 UINT max_logins = policy->MultiLogins;
\r
1330 UINT ao = GetHubAdminOption(hub, "max_multilogins_per_user");
\r
1334 if (max_logins != 0)
\r
1336 max_logins = MIN(max_logins, ao);
\r
1344 if (max_logins != 0)
\r
1346 Zero(&t, sizeof(t));
\r
1347 StrCpy(t.HubName, sizeof(t.HubName), hub->Name);
\r
1349 Unlock(hub->lock);
\r
1351 SiEnumSessionMain(server, &t);
\r
1357 for (i = 0;i < t.NumSession;i++)
\r
1359 RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];
\r
1361 if (e->BridgeMode == false && e->Layer3Mode == false && e->LinkMode == false && e->CurrentNumTcp != 0)
\r
1363 if (StrCmpi(e->Username, username) == 0 &&
\r
1364 (IsZero(e->UniqueId, 16) || Cmp(e->UniqueId, node.UniqueId, 16) != 0))
\r
1371 FreeRpcEnumSession(&t);
\r
1373 if (num >= max_logins)
\r
1376 Unlock(hub->lock);
\r
1379 HLog(hub, license.NumUserLicense == INFINITE ? "LH_TOO_MANY_MULTILOGINS" : "LH_TOO_MANY_MULTILOGINS2",
\r
1381 username, max_logins, num);
\r
1384 c->Err = ERR_TOO_MANY_USER_SESSION;
\r
1392 if (loggedin_user_object != NULL)
\r
1395 Lock(loggedin_user_object->lock);
\r
1397 loggedin_user_object->NumLogin++;
\r
1398 loggedin_user_object->LastLoginTime = SystemTime64();
\r
1400 Unlock(loggedin_user_object->lock);
\r
1405 hub->LastCommTime = hub->LastLoginTime = SystemTime64();
\r
1407 if (farm_controller)
\r
1409 wchar_t *msg = GetHubMsg(hub);
\r
1411 Unlock(hub->lock);
\r
1413 Lock(cedar->CedarSuperLock);
\r
1415 // ファームコントローラの場合、この HUB をホスティングする
\r
1417 LockList(server->FarmMemberList);
\r
1419 HLog(hub, "LH_FARM_SELECT_1", c->Name);
\r
1420 f = SiGetHubHostingMember(server, hub, admin_mode);
\r
1425 HLog(hub, "LH_FARM_SELECT_2", c->Name);
\r
1426 UnlockList(server->FarmMemberList);
\r
1427 Unlock(cedar->CedarSuperLock);
\r
1429 c->Err = ERR_COULD_NOT_HOST_HUB_ON_FARM;
\r
1436 if (f->Me == false)
\r
1438 UCHAR ticket[SHA1_SIZE];
\r
1443 SLog(c->Cedar, "LH_FARM_SELECT_4", c->Name, f->hostname);
\r
1445 // 選定したサーバーファームメンバにセッションを作成する
\r
1446 Rand(ticket, sizeof(ticket));
\r
1447 SiCallCreateTicket(server, f, hub->Name,
\r
1448 username, username_real, policy, ticket, Inc(hub->SessionCounter), groupname);
\r
1451 PackAddInt(p, "Redirect", 1);
\r
1452 PackAddIp32(p, "Ip", f->Ip);
\r
1453 for (i = 0;i < f->NumPort;i++)
\r
1455 PackAddIntEx(p, "Port", f->Ports[i], i, f->NumPort);
\r
1457 PackAddData(p, "Ticket", ticket, sizeof(ticket));
\r
1461 char *utf = CopyUniToUtf(msg);
\r
1463 PackAddData(p, "Msg", utf, StrLen(utf));
\r
1468 b = XToBuf(f->ServerCert, false);
\r
1469 PackAddBuf(p, "Cert", b);
\r
1472 UnlockList(server->FarmMemberList);
\r
1473 Unlock(cedar->CedarSuperLock);
\r
1476 HttpServerSend(c->FirstSock, p);
\r
1482 FreePack(HttpServerRecv(c->FirstSock));
\r
1488 HLog(hub, "LH_FARM_SELECT_3", c->Name);
\r
1489 // 自分自身が選定されたのでこのまま続ける
\r
1490 UnlockList(server->FarmMemberList);
\r
1491 Unlock(cedar->CedarSuperLock);
\r
1492 f->Point = SiGetPoint(server);
\r
1500 if (admin_mode == false)
\r
1502 // HUB の最大接続数をチェック
\r
1503 if (hub->Option->MaxSession != 0 &&
\r
1504 hub->Option->MaxSession <= Count(hub->NumSessions))
\r
1507 Unlock(hub->lock);
\r
1509 HLog(hub, "LH_MAX_SESSION", c->Name, hub->Option->MaxSession);
\r
1512 c->Err = ERR_HUB_IS_BUSY;
\r
1518 if (use_client_license || use_bridge_license)
\r
1520 // 仮想 HUB 管理オプションで規定された同時接続セッション数
\r
1521 // の制限に抵触しないかどうか調べる
\r
1523 (GetHubAdminOption(hub, "max_sessions") != 0 &&
\r
1524 (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= GetHubAdminOption(hub, "max_sessions"))
\r
1526 (hub->Option->MaxSession != 0 &&
\r
1527 (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= hub->Option->MaxSession))
\r
1530 Unlock(hub->lock);
\r
1532 HLog(hub, "LH_MAX_SESSION", c->Name, GetHubAdminOption(hub, "max_sessions"));
\r
1535 c->Err = ERR_HUB_IS_BUSY;
\r
1541 if (use_client_license)
\r
1543 // 仮想 HUB 管理オプションで規定された同時接続セッション数 (クライアント)
\r
1544 // の制限に抵触しないかどうか調べる
\r
1545 if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0 || license.CarrierEdition) &&
\r
1546 Count(hub->NumSessionsClient) >= GetHubAdminOption(hub, "max_sessions_client") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
\r
1548 (hub->FarmMember_MaxSessionClientBridgeApply &&
\r
1549 Count(hub->NumSessionsClient) >= hub->FarmMember_MaxSessionClient))
\r
1552 Unlock(hub->lock);
\r
1554 HLog(hub, "LH_MAX_SESSION_CLIENT", c->Name, GetHubAdminOption(hub, "max_sessions_client"));
\r
1557 c->Err = ERR_HUB_IS_BUSY;
\r
1563 if (use_bridge_license)
\r
1565 // 仮想 HUB 管理オプションで規定された同時接続セッション数 (ブリッジ)
\r
1566 // の制限に抵触しないかどうか調べる
\r
1567 if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0 || license.CarrierEdition) &&
\r
1568 Count(hub->NumSessionsBridge) >= GetHubAdminOption(hub, "max_sessions_bridge") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
\r
1570 (hub->FarmMember_MaxSessionClientBridgeApply &&
\r
1571 Count(hub->NumSessionsBridge) >= hub->FarmMember_MaxSessionBridge))
\r
1574 Unlock(hub->lock);
\r
1576 HLog(hub, "LH_MAX_SESSION_BRIDGE", c->Name, GetHubAdminOption(hub, "max_sessions_bridge"));
\r
1579 c->Err = ERR_HUB_IS_BUSY;
\r
1585 if (Count(hub->Cedar->CurrentSessions) >= GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"))
\r
1588 Unlock(hub->lock);
\r
1590 HLog(hub, "LH_MAX_SESSION_2", c->Name, GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"));
\r
1593 c->Err = ERR_HUB_IS_BUSY;
\r
1599 Inc(hub->NumSessions);
\r
1600 if (use_bridge_license)
\r
1602 Inc(hub->NumSessionsBridge);
\r
1605 if (use_client_license)
\r
1607 Inc(hub->NumSessionsClient);
\r
1609 Inc(hub->Cedar->CurrentSessions);
\r
1612 timeout = policy->TimeOut * 1000; // ミリ秒 → 秒 に変換
\r
1615 timeout = TIMEOUT_DEFAULT;
\r
1617 timeout = MIN(timeout, TIMEOUT_MAX);
\r
1618 timeout = MAX(timeout, TIMEOUT_MIN);
\r
1620 // ポリシーに応じて max_connection を更新
\r
1621 max_connection = MIN(max_connection, policy->MaxConnection);
\r
1622 max_connection = MIN(max_connection, MAX_TCP_CONNECTION);
\r
1623 max_connection = MAX(max_connection, 1);
\r
1624 if (half_connection)
\r
1626 // Half Connection 時にはコネクション数は 2 以上とする
\r
1627 max_connection = MAX(max_connection, 2);
\r
1632 // VoIP / QoS 使用時にはコネクション数は 2 以上とする
\r
1633 max_connection = MAX(max_connection, 2);
\r
1634 if (half_connection)
\r
1636 max_connection = MAX(max_connection, 4);
\r
1640 c->Status = CONNECTION_STATUS_ESTABLISHED;
\r
1642 // コネクションを Cedar から削除
\r
1643 DelConnection(c->Cedar, c);
\r
1646 StrLower(username);
\r
1647 s = NewServerSession(c->Cedar, c, hub, username, policy);
\r
1649 if (server != NULL)
\r
1651 s->NoSendSignature = server->NoSendSignature;
\r
1654 s->UseClientLicense = use_client_license;
\r
1655 s->UseBridgeLicense = use_bridge_license;
\r
1657 s->IsBridgeMode = (policy->NoBridge == false) || (policy->NoRouting == false);
\r
1658 s->IsMonitorMode = policy->MonitorPort;
\r
1660 // IPv6 セッションかどうかの判定
\r
1661 s->IPv6Session = false;
\r
1663 if (node.ClientIpAddress == 0)
\r
1665 s->IPv6Session = true;
\r
1668 if (use_bridge_license)
\r
1670 Inc(s->Cedar->AssignedBridgeLicense);
\r
1673 if (use_client_license)
\r
1675 Inc(s->Cedar->AssignedClientLicense);
\r
1678 if (server != NULL)
\r
1680 // Server 構造体の合計割り当て済みライセンス数の更新
\r
1681 if (server->ServerType == SERVER_TYPE_STANDALONE)
\r
1684 // (クラスタコントローラモードでは定期的にポーリングしている)
\r
1685 server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
\r
1686 server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
\r
1690 if (StrLen(sessionname) != 0)
\r
1694 s->Name = CopyStr(sessionname);
\r
1699 IPToStr(ip, sizeof(ip), &c->FirstSock->RemoteIP);
\r
1700 HLog(hub, "LH_NEW_SESSION", c->Name, s->Name, ip, c->FirstSock->RemotePort);
\r
1704 s->AdministratorMode = admin_mode;
\r
1705 StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username_real);
\r
1706 StrCpy(s->GroupName, sizeof(s->GroupName), groupname);
\r
1709 Copy(session_key, s->SessionKey, SHA1_SIZE);
\r
1712 s->MaxConnection = max_connection;
\r
1713 s->UseEncrypt = use_encrypt;
\r
1714 if (s->UseEncrypt && use_fast_rc4)
\r
1716 s->UseFastRC4 = use_fast_rc4;
\r
1718 s->UseCompress = use_compress;
\r
1719 s->HalfConnection = half_connection;
\r
1720 s->Timeout = timeout;
\r
1723 if (policy != NULL)
\r
1725 s->VLanId = policy->VLanId;
\r
1729 s->Username = CopyStr(username);
\r
1731 HLog(hub, "LH_SET_SESSION", s->Name, s->MaxConnection,
\r
1732 s->UseEncrypt ? _UU("L_YES") : _UU("L_NO"),
\r
1733 s->UseCompress ? _UU("L_YES") : _UU("L_NO"),
\r
1734 s->HalfConnection ? _UU("L_YES") : _UU("L_NO"),
\r
1735 s->Timeout / 1000);
\r
1737 msg = GetHubMsg(hub);
\r
1739 Unlock(hub->lock);
\r
1741 // クライアントに Welcome パケットを送信
\r
1742 p = PackWelcome(s);
\r
1746 // VPN Client に表示するメッセージ
\r
1748 wchar_t winver_msg_client[3800];
\r
1749 wchar_t winver_msg_server[3800];
\r
1750 wchar_t *utvpn_msg;
\r
1753 RPC_WINVER server_winver;
\r
1755 GetWinVer(&server_winver);
\r
1757 Zero(winver_msg_client, sizeof(winver_msg_client));
\r
1758 Zero(winver_msg_server, sizeof(winver_msg_server));
\r
1760 utvpn_msg = _UU("UTVPN_MSG");
\r
1762 if (IsSupportedWinVer(&winver) == false)
\r
1768 UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),
\r
1769 _UU("WINVER_ERROR_PC_LOCAL"),
\r
1771 _UU("WINVER_ERROR_VPNSERVER"),
\r
1772 SUPPORTED_WINDOWS_LIST,
\r
1773 _UU("WINVER_ERROR_PC_LOCAL"),
\r
1774 _UU("WINVER_ERROR_VPNSERVER"),
\r
1775 _UU("WINVER_ERROR_VPNSERVER"),
\r
1776 _UU("WINVER_ERROR_VPNSERVER"),
\r
1777 st.wYear, st.wMonth);
\r
1780 if (IsSupportedWinVer(&server_winver) == false)
\r
1786 UniFormat(winver_msg_server, sizeof(winver_msg_server), _UU("WINVER_ERROR_FORMAT"),
\r
1787 _UU("WINVER_ERROR_PC_REMOTE"),
\r
1788 server_winver.Title,
\r
1789 _UU("WINVER_ERROR_VPNSERVER"),
\r
1790 SUPPORTED_WINDOWS_LIST,
\r
1791 _UU("WINVER_ERROR_PC_REMOTE"),
\r
1792 _UU("WINVER_ERROR_VPNSERVER"),
\r
1793 _UU("WINVER_ERROR_VPNSERVER"),
\r
1794 _UU("WINVER_ERROR_VPNSERVER"),
\r
1795 st.wYear, st.wMonth);
\r
1798 tmpsize = UniStrSize(winver_msg_client) + UniStrSize(winver_msg_server) + UniStrSize(utvpn_msg) + UniStrSize(msg) * 100;
\r
1800 tmp = ZeroMalloc(tmpsize);
\r
1802 if (IsURLMsg(msg, NULL, 0) == false)
\r
1804 UniStrCat(tmp, tmpsize, utvpn_msg);
\r
1805 UniStrCat(tmp, tmpsize, winver_msg_client);
\r
1806 UniStrCat(tmp, tmpsize, winver_msg_server);
\r
1808 UniStrCat(tmp, tmpsize, msg);
\r
1810 utf = CopyUniToUtf(tmp);
\r
1812 PackAddData(p, "Msg", utf, StrLen(utf));
\r
1820 if (s->UseFastRC4)
\r
1823 GenerateRC4KeyPair(&key_pair);
\r
1825 // Welcome パケットに追加
\r
1826 PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
\r
1827 PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
\r
1829 char key1[64], key2[64];
\r
1830 BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
\r
1831 BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
\r
1833 "Client to Server Key: %s\n"
\r
1834 "Server to Client Key: %s\n",
\r
1838 HttpServerSend(c->FirstSock, p);
\r
1841 Copy(&c->Session->NodeInfo, &node, sizeof(NODE_INFO));
\r
1843 wchar_t tmp[MAX_SIZE * 2];
\r
1844 NodeInfoToStr(tmp, sizeof(tmp), &s->NodeInfo);
\r
1846 HLog(hub, "LH_NODE_INFO", s->Name, tmp);
\r
1849 // コネクションをトンネリングモードに移行
\r
1850 StartTunnelingMode(c);
\r
1852 // ハーフコネクションモード時の処理
\r
1853 if (s->HalfConnection)
\r
1855 // 1 つ目のソケットはクライアント→サーバー 方向 とする
\r
1856 TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
\r
1857 ts->Direction = TCP_CLIENT_TO_SERVER;
\r
1860 if (s->UseFastRC4)
\r
1862 // 1 つ目の TCP コネクションに RC4 キー情報をセットする
\r
1863 TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
\r
1864 Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
\r
1866 InitTcpSockRc4Key(ts, true);
\r
1869 if (s->UseEncrypt && s->UseFastRC4 == false)
\r
1871 s->UseSSLDataEncryption = true;
\r
1875 s->UseSSLDataEncryption = false;
\r
1878 if (s->Hub->Type == HUB_TYPE_FARM_DYNAMIC && s->Cedar->Server != NULL && s->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
\r
1880 if (s->Hub->BeingOffline == false)
\r
1882 // ダイナミック仮想 HUB で SecureNAT を開始
\r
1883 EnableSecureNATEx(s->Hub, false, true);
\r
1885 cluster_dynamic_secure_nat = true;
\r
1893 Lock(s->Hub->lock);
\r
1895 if (use_bridge_license)
\r
1897 Dec(hub->NumSessionsBridge);
\r
1900 if (use_client_license)
\r
1902 Dec(hub->NumSessionsClient);
\r
1905 Dec(s->Hub->NumSessions);
\r
1906 Dec(s->Hub->Cedar->CurrentSessions);
\r
1909 if (use_bridge_license)
\r
1911 Dec(s->Cedar->AssignedBridgeLicense);
\r
1914 if (use_client_license)
\r
1916 Dec(s->Cedar->AssignedClientLicense);
\r
1919 if (server != NULL)
\r
1921 // Server 構造体の合計割り当て済みライセンス数の更新
\r
1922 if (server->ServerType == SERVER_TYPE_STANDALONE)
\r
1925 // (クラスタコントローラモードでは定期的にポーリングしている)
\r
1926 server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
\r
1927 server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
\r
1931 Unlock(s->Hub->lock);
\r
1933 PrintSessionTotalDataSize(s);
\r
1935 HLog(s->Hub, "LH_END_SESSION", s->Name, s->TotalSendSizeReal, s->TotalRecvSizeReal);
\r
1937 if (cluster_dynamic_secure_nat && s->Hub->BeingOffline == false)
\r
1939 // ダイナミック仮想 HUB で SecureNAT を停止
\r
1940 EnableSecureNATEx(s->Hub, false, true);
\r
1943 ReleaseSession(s);
\r
1946 c->Err = ERR_SESSION_REMOVED;
\r
1952 else if (StrCmpi(method, "additional_connect") == 0)
\r
1958 c->Type = CONNECTION_TYPE_ADDITIONAL;
\r
1962 if (GetSessionKeyFromPack(p, session_key, &dummy) == false)
\r
1965 c->Err = ERR_PROTOCOL_ERROR;
\r
1971 // セッションキーからセッションを取得
\r
1972 s = GetSessionFromKey(c->Cedar, session_key);
\r
1973 if (s == NULL || s->Halt)
\r
1976 Debug("Session Not Found.\n");
\r
1977 c->Err = ERR_SESSION_TIMEOUT;
\r
1982 Debug("Session Found: %s\n", s->Name);
\r
1987 if (s->Connection->Protocol != CONNECTION_TCP)
\r
1989 c->Err = ERR_INVALID_PROTOCOL;
\r
1993 // セッションの現在のコネクション数を調べる
\r
1994 Lock(s->Connection->lock);
\r
1997 if (Count(s->Connection->CurrentNumConnection) > s->MaxConnection)
\r
1999 c->Err = ERR_TOO_MANY_CONNECTION;
\r
2004 Unlock(s->Connection->lock);
\r
2005 if (c->Err == ERR_TOO_MANY_CONNECTION)
\r
2007 Debug("Session TOO MANY CONNECTIONS !!: %u\n",
\r
2008 Count(s->Connection->CurrentNumConnection));
\r
2012 Debug("Session Invalid Protocol.\n");
\r
2014 ReleaseSession(s);
\r
2019 if (s->UseFastRC4)
\r
2021 GenerateRC4KeyPair(&key_pair);
\r
2024 // セッションのコネクションリスト (TCP) にこのコネクションのソケットを追加する
\r
2025 sock = c->FirstSock;
\r
2026 ts = NewTcpSock(sock);
\r
2027 SetTimeout(sock, CONNECTING_TIMEOUT);
\r
2028 direction = TCP_BOTH;
\r
2029 LockList(s->Connection->Tcp->TcpSockList);
\r
2031 if (s->HalfConnection)
\r
2033 // ハーフコネクション時、現在のすべての TCP コネクションの方向を
\r
2037 for (i = 0;i < LIST_NUM(s->Connection->Tcp->TcpSockList);i++)
\r
2039 TCPSOCK *ts = (TCPSOCK *)LIST_DATA(s->Connection->Tcp->TcpSockList, i);
\r
2040 if (ts->Direction == TCP_SERVER_TO_CLIENT)
\r
2051 direction = TCP_CLIENT_TO_SERVER;
\r
2055 direction = TCP_SERVER_TO_CLIENT;
\r
2057 Debug("%u/%u\n", s2c, c2s);
\r
2058 ts->Direction = direction;
\r
2061 UnlockList(s->Connection->Tcp->TcpSockList);
\r
2063 if (s->UseFastRC4)
\r
2066 Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
\r
2068 InitTcpSockRc4Key(ts, true);
\r
2072 p = PackError(ERR_NO_ERROR);
\r
2073 PackAddInt(p, "direction", direction);
\r
2075 if (s->UseFastRC4)
\r
2078 PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
\r
2079 PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
\r
2081 char key1[64], key2[64];
\r
2082 BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
\r
2083 BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
\r
2085 "Client to Server Key: %s\n"
\r
2086 "Server to Client Key: %s\n",
\r
2091 HttpServerSend(c->FirstSock, p);
\r
2094 SetTimeout(sock, INFINITE);
\r
2096 LockList(s->Connection->Tcp->TcpSockList);
\r
2098 Add(s->Connection->Tcp->TcpSockList, ts);
\r
2100 UnlockList(s->Connection->Tcp->TcpSockList);
\r
2102 // コネクション数をインクリメントする
\r
2103 Inc(s->Connection->CurrentNumConnection);
\r
2104 Debug("TCP Connection Incremented: %u\n", Count(s->Connection->CurrentNumConnection));
\r
2106 // セッションの Cancel を発行する
\r
2107 Cancel(s->Cancel1);
\r
2109 Unlock(s->Connection->lock);
\r
2113 ReleaseSession(s);
\r
2117 else if (StrCmpi(method, "enum_hub") == 0)
\r
2122 o = NewListFast(NULL);
\r
2124 c->Type = CONNECTION_TYPE_ENUM_HUB;
\r
2128 LockList(c->Cedar->HubList);
\r
2130 num = LIST_NUM(c->Cedar->HubList);
\r
2131 for (i = 0;i < num;i++)
\r
2133 HUB *h = LIST_DATA(c->Cedar->HubList, i);
\r
2134 if (h->Option != NULL && h->Option->NoEnum == false)
\r
2136 Insert(o, CopyStr(h->Name));
\r
2140 UnlockList(c->Cedar->HubList);
\r
2142 num = LIST_NUM(o);
\r
2143 for (i = 0;i < num;i++)
\r
2145 char *name = LIST_DATA(o, i);
\r
2146 PackAddStrEx(p, "HubName", name, i, num);
\r
2150 PackAddInt(p, "NumHub", num);
\r
2152 HttpServerSend(c->FirstSock, p);
\r
2154 FreePack(HttpServerRecv(c->FirstSock));
\r
2157 SLog(c->Cedar, "LS_ENUM_HUB", c->Name, num);
\r
2161 else if (StrCmpi(method, "farm_connect") == 0)
\r
2164 CEDAR *cedar = c->Cedar;
\r
2165 c->Type = CONNECTION_TYPE_FARM_RPC;
\r
2167 if (c->Cedar->Server == NULL)
\r
2170 c->Err = ERR_NOT_FARM_CONTROLLER;
\r
2174 SERVER *s = c->Cedar->Server;
\r
2175 if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER || s->FarmControllerInited == false)
\r
2178 SLog(c->Cedar, "LS_FARM_ACCEPT_1", c->Name);
\r
2179 c->Err = ERR_NOT_FARM_CONTROLLER;
\r
2183 UCHAR check_secure_password[SHA1_SIZE];
\r
2184 UCHAR secure_password[SHA1_SIZE];
\r
2186 SecurePassword(check_secure_password, s->HashedPassword, c->Random);
\r
2187 if (PackGetDataSize(p, "SecurePassword") == sizeof(secure_password))
\r
2189 PackGetData(p, "SecurePassword", secure_password);
\r
2193 Zero(secure_password, sizeof(secure_password));
\r
2196 if (Cmp(secure_password, check_secure_password, SHA1_SIZE) != 0)
\r
2199 SLog(c->Cedar, "LS_FARM_ACCEPT_2", c->Name);
\r
2200 c->Err = ERR_ACCESS_DENIED;
\r
2208 SLog(c->Cedar, "LS_FARM_ACCEPT_3", c->Name);
\r
2209 b = PackGetBuf(p, "ServerCert");
\r
2212 c->Err = ERR_PROTOCOL_ERROR;
\r
2216 server_x = BufToX(b, false);
\r
2218 if (server_x == NULL)
\r
2220 c->Err = ERR_PROTOCOL_ERROR;
\r
2226 char hostname[MAX_SIZE];
\r
2229 MsSetThreadPriorityRealtime();
\r
2230 #endif // OS_WIN32
\r
2232 SetTimeout(c->FirstSock, SERVER_CONTROL_TCP_TIMEOUT);
\r
2234 ip = PackGetIp32(p, "PublicIp");
\r
2235 point = PackGetInt(p, "Point");
\r
2236 if (PackGetStr(p, "HostName", hostname, sizeof(hostname)))
\r
2238 UINT num_port = PackGetIndexCount(p, "PublicPort");
\r
2239 if (num_port >= 1 && num_port <= MAX_PUBLIC_PORT_NUM)
\r
2241 UINT *ports = ZeroMalloc(sizeof(UINT) * num_port);
\r
2244 for (i = 0;i < num_port;i++)
\r
2246 ports[i] = PackGetIntEx(p, "PublicPort", i);
\r
2249 SiFarmServ(s, c->FirstSock, server_x, ip, num_port, ports, hostname, point,
\r
2250 PackGetInt(p, "Weight"), PackGetInt(p, "MaxSessions"));
\r
2265 else if (StrCmpi(method, "admin") == 0 && c->Cedar->Server != NULL)
\r
2269 c->Type = CONNECTION_TYPE_ADMIN_RPC;
\r
2270 err = AdminAccept(c, p);
\r
2272 if (err != ERR_NO_ERROR)
\r
2274 PACK *p = PackError(err);
\r
2275 HttpServerSend(c->FirstSock, p);
\r
2280 else if (StrCmpi(method, "password") == 0)
\r
2284 c->Type = CONNECTION_TYPE_PASSWORD;
\r
2285 err = ChangePasswordAccept(c, p);
\r
2288 p = PackError(err);
\r
2289 HttpServerSend(c->FirstSock, p);
\r
2297 c->Err = ERR_PROTOCOL_ERROR;
\r
2303 if (loggedin_user_object != NULL)
\r
2305 ReleaseUser(loggedin_user_object);
\r
2309 p = PackError(c->Err);
\r
2310 PackAddBool(p, "no_save_password", no_save_password);
\r
2311 HttpServerSend(c->FirstSock, p);
\r
2314 SLog(c->Cedar, "LS_CONNECTION_ERROR", c->Name, GetUniErrorStr(c->Err), c->Err);
\r
2318 // シグネチャの送信 (TCP パケット) 用スレッド
\r
2319 void SendSignatureByTcpThread(THREAD *thread, void *param)
\r
2322 SEND_SIGNATURE_PARAM *p;
\r
2325 if (thread == NULL || param == NULL)
\r
2330 p = (SEND_SIGNATURE_PARAM *)param;
\r
2332 AddWaitThread(thread);
\r
2333 NoticeThreadInit(thread);
\r
2337 s = Connect(p->Hostname, p->Port);
\r
2341 SendAll(s, buf->Buf, buf->Size, false);
\r
2347 DelWaitThread(thread);
\r
2353 // シグネチャの送信 (TCP パケット)
\r
2354 void SendSignatureByTcp(CONNECTION *c, IP *ip)
\r
2358 SEND_SIGNATURE_PARAM *param;
\r
2361 if (c == NULL || ip == NULL)
\r
2366 if (c->Session == NULL || c->Session->ClientOption == NULL)
\r
2371 CreateNodeInfo(&info, c);
\r
2374 WriteBuf(b, CEDAR_SIGNATURE_STR, StrLen(CEDAR_SIGNATURE_STR));
\r
2377 param = ZeroMalloc(sizeof(SEND_SIGNATURE_PARAM));
\r
2378 param->Buffer = b;
\r
2380 if (c->Session != NULL && c->Session->ClientOption != NULL)
\r
2382 CLIENT_OPTION *o = c->Session->ClientOption;
\r
2384 if (o->ProxyType == PROXY_DIRECT)
\r
2386 IPToStr(param->Hostname, sizeof(param->Hostname), ip);
\r
2387 param->Port = o->Port;
\r
2391 StrCpy(param->Hostname, sizeof(param->Hostname), o->ProxyName);
\r
2392 param->Port = o->ProxyPort;
\r
2396 t = NewThread(SendSignatureByTcpThread, param);
\r
2397 WaitThreadInit(t);
\r
2402 void CreateNodeInfo(NODE_INFO *info, CONNECTION *c)
\r
2417 Zero(info, sizeof(NODE_INFO));
\r
2420 StrCpy(info->ClientProductName, sizeof(info->ClientProductName), c->ClientStr);
\r
2422 info->ClientProductVer = Endian32(c->ClientVer);
\r
2424 info->ClientProductBuild = Endian32(c->ClientBuild);
\r
2427 StrCpy(info->ServerProductName, sizeof(info->ServerProductName), c->ServerStr);
\r
2429 info->ServerProductVer = Endian32(c->ServerVer);
\r
2431 info->ServerProductBuild = Endian32(c->ServerBuild);
\r
2434 StrCpy(info->ClientOsName, sizeof(info->ClientOsName), os->OsProductName);
\r
2435 // クライアント OS バージョン
\r
2436 StrCpy(info->ClientOsVer, sizeof(info->ClientOsVer), os->OsVersion);
\r
2437 // クライアント OS プロダクト ID
\r
2438 product_id = OSGetProductId();
\r
2439 StrCpy(info->ClientOsProductId, sizeof(info->ClientOsProductId), product_id);
\r
2443 GetMachineName(info->ClientHostname, sizeof(info->ClientHostname));
\r
2445 if (IsIP6(&c->FirstSock->LocalIP) == false)
\r
2447 info->ClientIpAddress = IPToUINT(&c->FirstSock->LocalIP);
\r
2451 Copy(info->ClientIpAddress6, c->FirstSock->LocalIP.ipv6_addr, sizeof(info->ClientIpAddress6));
\r
2454 info->ClientPort = Endian32(c->FirstSock->LocalPort);
\r
2457 StrCpy(info->ServerHostname, sizeof(info->ServerHostname), c->ServerName);
\r
2459 if (GetIP(&ip, info->ServerHostname))
\r
2461 if (IsIP6(&ip) == false)
\r
2463 info->ServerIpAddress = IPToUINT(&ip);
\r
2467 Copy(info->ServerIpAddress6, ip.ipv6_addr, sizeof(info->ServerIpAddress6));
\r
2471 info->ServerPort = Endian32(c->ServerPort);
\r
2473 if (s->ClientOption->ProxyType == PROXY_SOCKS || s->ClientOption->ProxyType == PROXY_HTTP)
\r
2476 StrCpy(info->ProxyHostname, sizeof(info->ProxyHostname), s->ClientOption->ProxyName);
\r
2479 if (IsIP6(&c->FirstSock->RemoteIP) == false)
\r
2481 info->ProxyIpAddress = IPToUINT(&c->FirstSock->RemoteIP);
\r
2485 Copy(&info->ProxyIpAddress6, c->FirstSock->RemoteIP.ipv6_addr, sizeof(info->ProxyIpAddress6));
\r
2488 info->ProxyPort = Endian32(c->FirstSock->RemotePort);
\r
2492 StrCpy(info->HubName, sizeof(info->HubName), s->ClientOption->HubName);
\r
2495 Copy(info->UniqueId, c->Cedar->UniqueId, sizeof(info->UniqueId));
\r
2499 SOCK *ClientAdditionalConnectToServer(CONNECTION *c)
\r
2509 s = ClientConnectGetSocket(c, true);
\r
2517 LockList(c->ConnectingSocks);
\r
2519 Add(c->ConnectingSocks, s);
\r
2522 UnlockList(c->ConnectingSocks);
\r
2524 if (c->Session->Halt)
\r
2528 LockList(c->ConnectingSocks);
\r
2530 if (Delete(c->ConnectingSocks, s))
\r
2535 UnlockList(c->ConnectingSocks);
\r
2541 SetTimeout(s, CONNECTING_TIMEOUT);
\r
2544 if (StartSSLEx(s, NULL, NULL, (c->DontUseTls1 ? false : true)) == false)
\r
2548 LockList(c->ConnectingSocks);
\r
2550 if (Delete(c->ConnectingSocks, s))
\r
2555 UnlockList(c->ConnectingSocks);
\r
2561 if (CompareX(s->RemoteX, c->ServerX) == false)
\r
2565 c->Session->SessionTimeOuted = true;
\r
2571 // セキュアデバイス内の証明書と鍵を削除する
\r
2572 UINT SecureDelete(UINT device_id, char *pin, char *cert_name, char *key_name)
\r
2576 if (pin == NULL || device_id == 0)
\r
2578 return ERR_INTERNAL_ERROR;
\r
2582 sec = OpenSec(device_id);
\r
2585 return ERR_SECURE_DEVICE_OPEN_FAILED;
\r
2589 if (OpenSecSession(sec, 0) == false)
\r
2592 return ERR_SECURE_DEVICE_OPEN_FAILED;
\r
2596 if (LoginSec(sec, pin) == false)
\r
2598 CloseSecSession(sec);
\r
2600 return ERR_SECURE_PIN_LOGIN_FAILED;
\r
2604 if (cert_name != NULL)
\r
2606 DeleteSecCert(sec, cert_name);
\r
2610 if (key_name != NULL)
\r
2612 DeleteSecKey(sec, key_name);
\r
2619 CloseSecSession(sec);
\r
2624 return ERR_NO_ERROR;
\r
2627 // セキュアデバイス内の証明書と鍵を列挙する
\r
2628 UINT SecureEnum(UINT device_id, char *pin, TOKEN_LIST **cert_list, TOKEN_LIST **key_list)
\r
2632 LIST *cert_name_list, *key_name_list;
\r
2634 if (pin == NULL || device_id == 0 || cert_list == NULL || key_list == NULL)
\r
2636 return ERR_INTERNAL_ERROR;
\r
2640 sec = OpenSec(device_id);
\r
2643 return ERR_SECURE_DEVICE_OPEN_FAILED;
\r
2647 if (OpenSecSession(sec, 0) == false)
\r
2650 return ERR_SECURE_DEVICE_OPEN_FAILED;
\r
2654 if (LoginSec(sec, pin) == false)
\r
2656 CloseSecSession(sec);
\r
2658 return ERR_SECURE_PIN_LOGIN_FAILED;
\r
2662 if ((o = EnumSecObject(sec)) != NULL)
\r
2666 cert_name_list = NewList(CompareStr);
\r
2667 key_name_list = NewList(CompareStr);
\r
2669 for (i = 0;i < LIST_NUM(o);i++)
\r
2671 SEC_OBJ *obj = LIST_DATA(o, i);
\r
2673 if (obj->Type == SEC_X)
\r
2675 Add(cert_name_list, CopyStr(obj->Name));
\r
2677 else if (obj->Type == SEC_K)
\r
2679 Add(key_name_list, CopyStr(obj->Name));
\r
2683 Sort(cert_name_list);
\r
2684 Sort(key_name_list);
\r
2686 *cert_list = ListToTokenList(cert_name_list);
\r
2687 *key_list = ListToTokenList(key_name_list);
\r
2690 FreeStrList(cert_name_list);
\r
2691 FreeStrList(key_name_list);
\r
2692 FreeEnumSecObject(o);
\r
2696 *cert_list = NullToken();
\r
2697 *key_list = NullToken();
\r
2704 CloseSecSession(sec);
\r
2709 return ERR_NO_ERROR;
\r
2712 // セキュアデバイスに証明書と鍵を記録する
\r
2713 UINT SecureWrite(UINT device_id, char *cert_name, X *x, char *key_name, K *k, char *pin)
\r
2718 if (pin == NULL || device_id == 0 || cert_name == NULL || x == NULL || key_name == NULL || k == NULL)
\r
2720 return ERR_INTERNAL_ERROR;
\r
2724 sec = OpenSec(device_id);
\r
2727 return ERR_SECURE_DEVICE_OPEN_FAILED;
\r
2731 if (OpenSecSession(sec, 0) == false)
\r
2734 return ERR_SECURE_DEVICE_OPEN_FAILED;
\r
2738 if (LoginSec(sec, pin) == false)
\r
2740 CloseSecSession(sec);
\r
2742 return ERR_SECURE_PIN_LOGIN_FAILED;
\r
2749 if (WriteSecCert(sec, true, cert_name, x) == false)
\r
2755 if (WriteSecKey(sec, true, key_name, k) == false)
\r
2764 CloseSecSession(sec);
\r
2769 if (failed == false)
\r
2772 return ERR_NO_ERROR;
\r
2777 return ERR_SECURE_CANT_WRITE;
\r
2781 // セキュアデバイスによる署名を試行する
\r
2782 UINT SecureSign(SECURE_SIGN *sign, UINT device_id, char *pin)
\r
2787 if (sign == false || pin == NULL || device_id == 0)
\r
2789 return ERR_INTERNAL_ERROR;
\r
2793 sec = OpenSec(device_id);
\r
2796 return ERR_SECURE_DEVICE_OPEN_FAILED;
\r
2800 if (OpenSecSession(sec, 0) == false)
\r
2803 return ERR_SECURE_DEVICE_OPEN_FAILED;
\r
2807 if (LoginSec(sec, pin) == false)
\r
2809 CloseSecSession(sec);
\r
2811 return ERR_SECURE_PIN_LOGIN_FAILED;
\r
2815 x = ReadSecCert(sec, sign->SecurePublicCertName);
\r
2819 CloseSecSession(sec);
\r
2821 return ERR_SECURE_NO_CERT;
\r
2825 if (SignSec(sec, sign->SecurePrivateKeyName, sign->Signature, sign->Random, SHA1_SIZE) == false)
\r
2830 CloseSecSession(sec);
\r
2832 return ERR_SECURE_NO_PRIVATE_KEY;
\r
2836 sign->ClientCert = x;
\r
2842 CloseSecSession(sec);
\r
2848 return ERR_NO_ERROR;
\r
2851 // クライアントがサーバーに追加接続する
\r
2852 bool ClientAdditionalConnect(CONNECTION *c, THREAD *t)
\r
2859 RC4_KEY_PAIR key_pair;
\r
2867 s = ClientAdditionalConnectToServer(c);
\r
2880 Debug("Uploading Signature...\n");
\r
2881 if (ClientUploadSignature(s) == false)
\r
2893 Debug("Downloading Hello...\n");
\r
2894 if (ClientDownloadHello(c, s) == false)
\r
2906 if (ClientUploadAuth2(c, s) == false)
\r
2913 p = HttpClientRecv(s);
\r
2920 err = GetErrorFromPack(p);
\r
2921 direction = PackGetInt(p, "direction");
\r
2923 if (c->Session->UseFastRC4)
\r
2926 if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
\r
2928 PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
\r
2930 if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
\r
2932 PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
\r
2935 char key1[64], key2[64];
\r
2936 BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
\r
2937 BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
\r
2939 "Client to Server Key: %s\n"
\r
2940 "Server to Client Key: %s\n",
\r
2951 Debug("Additional Connect Error: %u\n", err);
\r
2952 if (err == ERR_SESSION_TIMEOUT || err == ERR_INVALID_PROTOCOL)
\r
2954 // 致命的なエラーなので再接続しなおすことにする
\r
2955 c->Session->SessionTimeOuted = true;
\r
2960 Debug("Additional Connect Succeed!\n");
\r
2963 // コネクションの TcpSockList に追加する
\r
2964 ts = NewTcpSock(s);
\r
2966 if (c->ServerMode == false)
\r
2968 if (c->Session->ClientOption->ConnectionDisconnectSpan != 0)
\r
2970 ts->DisconnectTick = Tick64() + c->Session->ClientOption->ConnectionDisconnectSpan * (UINT64)1000;
\r
2974 LockList(c->Tcp->TcpSockList);
\r
2976 ts->Direction = direction;
\r
2977 Add(c->Tcp->TcpSockList, ts);
\r
2979 UnlockList(c->Tcp->TcpSockList);
\r
2980 Debug("TCP Connection Incremented: %u\n", Count(c->CurrentNumConnection));
\r
2982 if (c->Session->HalfConnection)
\r
2984 Debug("New Half Connection: %s\n",
\r
2985 direction == TCP_SERVER_TO_CLIENT ? "TCP_SERVER_TO_CLIENT" : "TCP_CLIENT_TO_SERVER"
\r
2989 if (c->Session->UseFastRC4)
\r
2992 Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
\r
2994 InitTcpSockRc4Key(ts, false);
\r
2997 // セッションに Cancel を発行する
\r
2998 Cancel(c->Session->Cancel1);
\r
3000 // 接続中のソケット一覧からこのソケットを削除
\r
3001 LockList(c->ConnectingSocks);
\r
3003 if (Delete(c->ConnectingSocks, s))
\r
3008 UnlockList(c->ConnectingSocks);
\r
3015 LockList(c->ConnectingSocks);
\r
3017 if (Delete(c->ConnectingSocks, s))
\r
3023 UnlockList(c->ConnectingSocks);
\r
3029 void ClientSecureSignThread(THREAD *thread, void *param)
\r
3031 SECURE_SIGN_THREAD_PROC *p = (SECURE_SIGN_THREAD_PROC *)param;
\r
3033 if (thread == NULL || param == NULL)
\r
3038 NoticeThreadInit(thread);
\r
3040 p->Ok = p->SecureSignProc(p->Connection->Session, p->Connection, p->SecureSign);
\r
3041 p->UserFinished = true;
\r
3044 // セキュアデバイスを使用した署名
\r
3045 bool ClientSecureSign(CONNECTION *c, UCHAR *sign, UCHAR *random, X **x)
\r
3047 SECURE_SIGN_THREAD_PROC *p;
\r
3056 if (c == NULL || sign == NULL || random == NULL || x == NULL)
\r
3062 o = s->ClientOption;
\r
3063 a = s->ClientAuth;
\r
3065 p = ZeroMalloc(sizeof(SECURE_SIGN_THREAD_PROC));
\r
3066 p->Connection = c;
\r
3067 ss = p->SecureSign = ZeroMallocEx(sizeof(SECURE_SIGN), true);
\r
3068 StrCpy(ss->SecurePrivateKeyName, sizeof(ss->SecurePrivateKeyName),
\r
3069 a->SecurePrivateKeyName);
\r
3070 StrCpy(ss->SecurePublicCertName, sizeof(ss->SecurePublicCertName),
\r
3071 a->SecurePublicCertName);
\r
3072 ss->UseSecureDeviceId = c->Cedar->Client->UseSecureDeviceId;
\r
3073 Copy(ss->Random, random, SHA1_SIZE);
\r
3076 ss->BitmapId = CmGetSecureBitmapId(c->ServerName);
\r
3077 #endif // OS_WIN32
\r
3079 p->SecureSignProc = a->SecureSignProc;
\r
3082 thread = NewThread(ClientSecureSignThread, p);
\r
3083 WaitThreadInit(thread);
\r
3085 // 署名が完了するかキャンセルするまで 0.5 秒ごとにポーリングする
\r
3089 if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
\r
3091 // 切断防止のため一定期間ごとに NOOP を送信する
\r
3093 ClientUploadNoop(c);
\r
3095 if (p->UserFinished)
\r
3100 WaitThread(thread, 500);
\r
3102 ReleaseThread(thread);
\r
3108 Copy(sign, ss->Signature, 128);
\r
3109 *x = ss->ClientCert;
\r
3112 Free(p->SecureSign);
\r
3119 void ClientCheckServerCertThread(THREAD *thread, void *param)
\r
3121 CHECK_CERT_THREAD_PROC *p = (CHECK_CERT_THREAD_PROC *)param;
\r
3123 if (thread == NULL || param == NULL)
\r
3129 NoticeThreadInit(thread);
\r
3132 p->Ok = p->CheckCertProc(p->Connection->Session, p->Connection, p->ServerX, &p->Exipred);
\r
3133 p->UserSelected = true;
\r
3136 // クライアントがサーバーの証明書を確認する
\r
3137 bool ClientCheckServerCert(CONNECTION *c, bool *expired)
\r
3139 CLIENT_AUTH *auth;
\r
3141 CHECK_CERT_THREAD_PROC *p;
\r
3152 if (expired != NULL)
\r
3157 auth = c->Session->ClientAuth;
\r
3160 if (auth->CheckCertProc == NULL && c->Session->LinkModeClient == false)
\r
3166 if (c->Session->LinkModeClient && c->Session->Link->CheckServerCert == false)
\r
3168 // カスケード接続モードだがサーバー証明書はチェックしない
\r
3174 // リダイレクト先 VPN サーバーの証明書を確認する
\r
3175 if (CompareX(c->FirstSock->RemoteX, c->ServerX) == false)
\r
3185 x = CloneX(c->FirstSock->RemoteX);
\r
3192 if (CheckXDateNow(x))
\r
3194 // 信頼するルート証明書によって署名されているかどうか確認する
\r
3195 if (c->Session->LinkModeClient == false)
\r
3197 // 通常の VPN Client モード
\r
3198 if (CheckSignatureByCa(cedar, x))
\r
3200 // 署名されているのでこの証明書は信頼できる
\r
3208 if (CheckSignatureByCaLinkMode(c->Session, x))
\r
3210 // 署名されているのでこの証明書は信頼できる
\r
3217 if (c->Session->LinkModeClient)
\r
3219 if (CheckXDateNow(x))
\r
3221 Lock(c->Session->Link->lock);
\r
3223 if (c->Session->Link->ServerCert != NULL)
\r
3225 if (CompareX(c->Session->Link->ServerCert, x))
\r
3227 Unlock(c->Session->Link->lock);
\r
3228 // カスケード接続設定に登録されている証明書と完全一致
\r
3234 Unlock(c->Session->Link->lock);
\r
3238 if (expired != NULL)
\r
3244 // カスケード接続モードの場合はこの時点で検証失敗
\r
3249 p = ZeroMalloc(sizeof(CHECK_CERT_THREAD_PROC));
\r
3251 p->CheckCertProc = auth->CheckCertProc;
\r
3252 p->Connection = c;
\r
3255 thread = NewThread(ClientCheckServerCertThread, p);
\r
3256 WaitThreadInit(thread);
\r
3258 // ユーザーが接続の可否を選択するまで 0.5 秒間隔でポーリングする
\r
3262 if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
\r
3264 // 切断防止のため一定期間ごとに NOOP を送信する
\r
3266 ClientUploadNoop(c);
\r
3268 if (p->UserSelected)
\r
3273 WaitThread(thread, 500);
\r
3276 if (expired != NULL)
\r
3278 *expired = p->Exipred;
\r
3282 FreeX(p->ServerX);
\r
3284 ReleaseThread(thread);
\r
3289 // クライアントがサーバーに接続する
\r
3290 bool ClientConnect(CONNECTION *c)
\r
3297 UINT session_key_32;
\r
3299 char session_name[MAX_SESSION_NAME_LEN + 1];
\r
3300 char connection_name[MAX_CONNECTION_NAME_LEN + 1];
\r
3301 UCHAR session_key[SHA1_SIZE];
\r
3302 RC4_KEY_PAIR key_pair;
\r
3304 bool expired = false;
\r
3312 sess = c->Session;
\r
3314 PrintStatus(sess, L"init");
\r
3315 PrintStatus(sess, _UU("STATUS_1"));
\r
3320 c->Status = CONNECTION_STATUS_CONNECTING;
\r
3321 c->Session->ClientStatus = CLIENT_STATUS_CONNECTING;
\r
3323 s = ClientConnectToServer(c);
\r
3326 PrintStatus(sess, L"free");
\r
3330 Copy(&server_ip, &s->RemoteIP, sizeof(IP));
\r
3335 c->Err = ERR_USER_CANCEL;
\r
3340 c->Session->ClientStatus = CLIENT_STATUS_NEGOTIATION;
\r
3343 Debug("Uploading Signature...\n");
\r
3344 if (ClientUploadSignature(s) == false)
\r
3346 c->Err = ERR_DISCONNECTED;
\r
3353 c->Err = ERR_USER_CANCEL;
\r
3357 PrintStatus(sess, _UU("STATUS_5"));
\r
3360 Debug("Downloading Hello...\n");
\r
3361 if (ClientDownloadHello(c, s) == false)
\r
3366 if (c->Session->ClientOption != NULL && c->Session->ClientOption->FromAdminPack)
\r
3368 if (IsAdminPackSupportedServerProduct(c->ServerStr) == false)
\r
3370 c->Err = ERR_NOT_ADMINPACK_SERVER;
\r
3378 c->Err = ERR_USER_CANCEL;
\r
3382 Debug("Server Version : %u\n"
\r
3383 "Server String : %s\n"
\r
3384 "Server Build : %u\n"
\r
3385 "Client Version : %u\n"
\r
3386 "Client String : %s\n"
\r
3387 "Client Build : %u\n",
\r
3388 c->ServerVer, c->ServerStr, c->ServerBuild,
\r
3389 c->ClientVer, c->ClientStr, c->ClientBuild);
\r
3392 c->Session->ClientStatus = CLIENT_STATUS_AUTH;
\r
3394 // クライアントによるサーバー証明書の確認
\r
3395 if (ClientCheckServerCert(c, &expired) == false)
\r
3397 if (expired == false)
\r
3399 c->Err = ERR_CERT_NOT_TRUSTED;
\r
3403 c->Err = ERR_SERVER_CERT_EXPIRES;
\r
3406 if (c->Session->LinkModeClient == false && c->Err == ERR_CERT_NOT_TRUSTED)
\r
3408 c->Session->ForceStopFlag = true;
\r
3414 PrintStatus(sess, _UU("STATUS_6"));
\r
3417 if (ClientUploadAuth(c) == false)
\r
3425 c->Err = ERR_USER_CANCEL;
\r
3429 // Welcome パケットを受信
\r
3430 p = HttpClientRecv(s);
\r
3433 c->Err = ERR_DISCONNECTED;
\r
3438 err = GetErrorFromPack(p);
\r
3443 c->ClientConnectError_NoSavePassword = PackGetBool(p, "no_save_password");
\r
3447 // 接続制限のためのブランド化文字列チェック
\r
3450 char *branded_cfroms = _SS("BRANDED_C_FROM_S");
\r
3451 PackGetStr(p, "branded_cfroms", tmp, sizeof(tmp));
\r
3453 if(StrLen(branded_cfroms) > 0 && StrCmpi(branded_cfroms, tmp) != 0)
\r
3455 c->Err = ERR_BRANDED_C_FROM_S;
\r
3467 utf_size = PackGetDataSize(p, "Msg");
\r
3468 utf = ZeroMalloc(utf_size + 8);
\r
3469 PackGetData(p, "Msg", utf);
\r
3471 msg = CopyUtfToUni(utf);
\r
3473 if (IsEmptyUniStr(msg) == false)
\r
3475 if (c->Session->Client_Message != NULL)
\r
3477 Free(c->Session->Client_Message);
\r
3480 c->Session->Client_Message = msg;
\r
3490 if (PackGetInt(p, "Redirect") != 0)
\r
3496 UINT use_port = 0;
\r
3497 UINT current_port = c->ServerPort;
\r
3498 UCHAR ticket[SHA1_SIZE];
\r
3503 PrintStatus(sess, _UU("STATUS_8"));
\r
3505 ip = PackGetIp32(p, "Ip");
\r
3506 num_port = MAX(MIN(PackGetIndexCount(p, "Port"), MAX_PUBLIC_PORT_NUM), 1);
\r
3507 ports = ZeroMalloc(sizeof(UINT) * num_port);
\r
3508 for (i = 0;i < num_port;i++)
\r
3510 ports[i] = PackGetIntEx(p, "Port", i);
\r
3514 for (i = 0;i < num_port;i++)
\r
3516 if (ports[i] == current_port)
\r
3518 use_port = current_port;
\r
3521 if (use_port == 0)
\r
3523 use_port = ports[0];
\r
3528 if (PackGetDataSize(p, "Ticket") == SHA1_SIZE)
\r
3530 PackGetData(p, "Ticket", ticket);
\r
3533 b = PackGetBuf(p, "Cert");
\r
3536 server_cert = BufToX(b, false);
\r
3540 if (c->ServerX != NULL)
\r
3542 FreeX(c->ServerX);
\r
3544 c->ServerX = server_cert;
\r
3546 IPToStr32(c->ServerName, sizeof(c->ServerName), ip);
\r
3547 c->ServerPort = use_port;
\r
3549 c->UseTicket = true;
\r
3550 Copy(c->Ticket, ticket, SHA1_SIZE);
\r
3555 HttpClientSend(s, p);
\r
3560 c->FirstSock = NULL;
\r
3568 PrintStatus(sess, _UU("STATUS_7"));
\r
3570 // Welcome パケットをパース
\r
3571 if (ParseWelcomeFromPack(p, session_name, sizeof(session_name),
\r
3572 connection_name, sizeof(connection_name), &policy) == false)
\r
3575 c->Err = ERR_PROTOCOL_ERROR;
\r
3580 if (GetSessionKeyFromPack(p, session_key, &session_key_32) == false)
\r
3585 c->Err = ERR_PROTOCOL_ERROR;
\r
3589 Copy(c->Session->SessionKey, session_key, SHA1_SIZE);
\r
3590 c->Session->SessionKey32 = session_key_32;
\r
3592 // Welcome パケットの内容を保存
\r
3593 Debug("session_name: %s, connection_name: %s\n",
\r
3594 session_name, connection_name);
\r
3596 Lock(c->Session->lock);
\r
3599 c->Session->MaxConnection = PackGetInt(p, "max_connection");
\r
3600 c->Session->MaxConnection = MIN(c->Session->MaxConnection, c->Session->ClientOption->MaxConnection);
\r
3601 c->Session->MaxConnection = MIN(c->Session->MaxConnection, MAX_TCP_CONNECTION);
\r
3602 c->Session->MaxConnection = MAX(c->Session->MaxConnection, 1);
\r
3603 c->Session->UseCompress = PackGetInt(p, "use_compress") == 0 ? false : true;
\r
3604 c->Session->UseEncrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
\r
3605 c->Session->NoSendSignature = PackGetBool(p, "no_send_signature");
\r
3606 if (c->Session->UseEncrypt)
\r
3608 c->Session->UseFastRC4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
\r
3610 c->Session->HalfConnection = PackGetInt(p, "half_connection") == 0 ? false : true;
\r
3611 c->Session->Timeout = PackGetInt(p, "timeout");
\r
3612 c->Session->QoS = PackGetInt(p, "qos") == 0 ? false : true;
\r
3613 if (c->Session->QoS)
\r
3615 c->Session->MaxConnection = MAX(c->Session->MaxConnection, (UINT)(c->Session->HalfConnection ? 4 : 2));
\r
3617 c->Session->VLanId = PackGetInt(p, "vlan_id");
\r
3619 if (c->Protocol == CONNECTION_UDP)
\r
3621 // UDP プロトコルの場合、サーバーから鍵を受け取る
\r
3622 if (PackGetDataSize(p, "udp_send_key") == sizeof(c->Session->UdpSendKey))
\r
3624 PackGetData(p, "udp_send_key", c->Session->UdpSendKey);
\r
3627 if (PackGetDataSize(p, "udp_recv_key") == sizeof(c->Session->UdpRecvKey))
\r
3629 PackGetData(p, "udp_recv_key", c->Session->UdpRecvKey);
\r
3633 if (c->Session->UseFastRC4)
\r
3636 if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
\r
3638 PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
\r
3640 if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
\r
3642 PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
\r
3645 char key1[64], key2[64];
\r
3646 BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
\r
3647 BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
\r
3649 "Client to Server Key: %s\n"
\r
3650 "Server to Client Key: %s\n",
\r
3655 Unlock(c->Session->lock);
\r
3659 if (c->Name != NULL)
\r
3663 c->Name = CopyStr(connection_name);
\r
3666 if (c->CipherName != NULL)
\r
3668 Free(c->CipherName);
\r
3671 c->CipherName = CopyStr(c->FirstSock->CipherName);
\r
3675 Lock(c->Session->lock);
\r
3677 if (c->Session->Name != NULL)
\r
3679 Free(c->Session->Name);
\r
3681 c->Session->Name = CopyStr(session_name);
\r
3683 c->Session->Policy = policy;
\r
3685 Unlock(c->Session->lock);
\r
3687 // Welcome パケットを破棄
\r
3691 // server_ip に対して TCP でシグネチャを送信
\r
3692 if (c->Session->NoSendSignature == false)
\r
3694 SendSignatureByTcp(c, &server_ip);
\r
3698 c->Session->ClientStatus = CLIENT_STATUS_ESTABLISHED;
\r
3701 if (c->ServerX == NULL)
\r
3703 c->ServerX = CloneX(c->FirstSock->RemoteX);
\r
3706 PrintStatus(sess, _UU("STATUS_9"));
\r
3708 // コネクションをトンネリングモードに移行
\r
3709 StartTunnelingMode(c);
\r
3712 if (c->Session->HalfConnection)
\r
3715 TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
\r
3716 ts->Direction = TCP_CLIENT_TO_SERVER;
\r
3719 if (c->Session->UseFastRC4)
\r
3722 TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
\r
3723 Copy(&ts->Rc4KeyPair, &key_pair, sizeof(key_pair));
\r
3725 InitTcpSockRc4Key(ts, false);
\r
3729 if (c->Session->UseEncrypt && c->Session->UseFastRC4 == false)
\r
3731 c->Session->UseSSLDataEncryption = true;
\r
3735 c->Session->UseSSLDataEncryption = false;
\r
3738 PrintStatus(sess, L"free");
\r
3740 CLog(c->Cedar->Client, "LC_CONNECT_2", c->Session->ClientOption->AccountName,
\r
3743 if (c->Session->LinkModeClient && c->Session->Link != NULL)
\r
3745 HLog(c->Session->Link->Hub, "LH_CONNECT_2", c->Session->ClientOption->AccountName, session_name);
\r
3749 SessionMain(c->Session);
\r
3753 if (c->Err == ERR_USER_CANCEL)
\r
3759 c->FirstSock = NULL;
\r
3769 Debug("Error: %u\n", c->Err);
\r
3773 PrintStatus(sess, L"free");
\r
3779 // Welcome パケットのパース
\r
3780 bool ParseWelcomeFromPack(PACK *p, char *session_name, UINT session_name_size,
\r
3781 char *connection_name, UINT connection_name_size,
\r
3785 if (p == NULL || session_name == NULL || connection_name == NULL || policy == NULL)
\r
3791 if (PackGetStr(p, "session_name", session_name, session_name_size) == false)
\r
3797 if (PackGetStr(p, "connection_name", connection_name, connection_name_size) == false)
\r
3803 *policy = PackGetPolicy(p);
\r
3804 if (*policy == NULL)
\r
3812 // Welcome パケットの生成
\r
3813 PACK *PackWelcome(SESSION *s)
\r
3825 PackAddStr(p, "session_name", s->Name);
\r
3828 PackAddStr(p, "connection_name", s->Connection->Name);
\r
3831 PackAddInt(p, "max_connection", s->MaxConnection);
\r
3832 PackAddInt(p, "use_encrypt", s->UseEncrypt == false ? 0 : 1);
\r
3833 PackAddInt(p, "use_fast_rc4", s->UseFastRC4 == false ? 0 : 1);
\r
3834 PackAddInt(p, "use_compress", s->UseCompress == false ? 0 : 1);
\r
3835 PackAddInt(p, "half_connection", s->HalfConnection == false ? 0 : 1);
\r
3836 PackAddInt(p, "timeout", s->Timeout);
\r
3837 PackAddInt(p, "qos", s->QoS ? 1 : 0);
\r
3840 PackAddData(p, "session_key", s->SessionKey, SHA1_SIZE);
\r
3841 PackAddInt(p, "session_key_32", s->SessionKey32);
\r
3844 PackAddPolicy(p, s->Policy);
\r
3847 PackAddInt(p, "vlan_id", s->VLanId);
\r
3849 if (s->Connection->Protocol == CONNECTION_UDP)
\r
3851 // UDP プロトコルの場合、2 組のキーを生成する
\r
3852 Rand(s->UdpSendKey, sizeof(s->UdpSendKey));
\r
3853 Rand(s->UdpRecvKey, sizeof(s->UdpRecvKey));
\r
3855 // クライアントには鍵を反転して送る
\r
3856 PackAddData(p, "udp_send_key", s->UdpRecvKey, sizeof(s->UdpRecvKey));
\r
3857 PackAddData(p, "udp_recv_key", s->UdpSendKey, sizeof(s->UdpSendKey));
\r
3860 // no_send_signature
\r
3861 if (s->NoSendSignature)
\r
3863 PackAddBool(p, "no_send_signature", true);
\r
3869 #define PACK_ADD_POLICY_BOOL(name, value) \
\r
3870 PackAddInt(p, "policy:" name, y->value == false ? 0 : 1)
\r
3871 #define PACK_ADD_POLICY_UINT(name, value) \
\r
3872 PackAddInt(p, "policy:" name, y->value)
\r
3873 #define PACK_GET_POLICY_BOOL(name, value) \
\r
3874 y->value = (PackGetInt(p, "policy:" name) == 0 ? false : true)
\r
3875 #define PACK_GET_POLICY_UINT(name, value) \
\r
3876 y->value = PackGetInt(p, "policy:" name)
\r
3878 // セッションキーを PACK から取得
\r
3879 bool GetSessionKeyFromPack(PACK *p, UCHAR *session_key, UINT *session_key_32)
\r
3882 if (p == NULL || session_key == NULL || session_key_32 == NULL)
\r
3887 if (PackGetDataSize(p, "session_key") != SHA1_SIZE)
\r
3891 if (PackGetData(p, "session_key", session_key) == false)
\r
3895 *session_key_32 = PackGetInt(p, "session_key_32");
\r
3900 // ポリシーを PACK から取得
\r
3901 POLICY *PackGetPolicy(PACK *p)
\r
3903 // このあたりは急いで実装したのでコードがあまり美しくない。
\r
3911 y = ZeroMalloc(sizeof(POLICY));
\r
3915 PACK_GET_POLICY_BOOL("Access", Access);
\r
3916 PACK_GET_POLICY_BOOL("DHCPFilter", DHCPFilter);
\r
3917 PACK_GET_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
\r
3918 PACK_GET_POLICY_BOOL("DHCPForce", DHCPForce);
\r
3919 PACK_GET_POLICY_BOOL("NoBridge", NoBridge);
\r
3920 PACK_GET_POLICY_BOOL("NoRouting", NoRouting);
\r
3921 PACK_GET_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
\r
3922 PACK_GET_POLICY_BOOL("NoServer", NoServer);
\r
3923 PACK_GET_POLICY_BOOL("CheckMac", CheckMac);
\r
3924 PACK_GET_POLICY_BOOL("CheckIP", CheckIP);
\r
3925 PACK_GET_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
\r
3926 PACK_GET_POLICY_BOOL("MonitorPort", MonitorPort);
\r
3927 PACK_GET_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
\r
3928 PACK_GET_POLICY_BOOL("FixPassword", FixPassword);
\r
3929 PACK_GET_POLICY_BOOL("NoQoS", NoQoS);
\r
3931 PACK_GET_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
\r
3932 PACK_GET_POLICY_BOOL("RAFilter", RAFilter);
\r
3933 PACK_GET_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
\r
3934 PACK_GET_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
\r
3935 PACK_GET_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
\r
3936 PACK_GET_POLICY_BOOL("CheckIPv6", CheckIPv6);
\r
3937 PACK_GET_POLICY_BOOL("NoServerV6", NoServerV6);
\r
3938 PACK_GET_POLICY_BOOL("NoSavePassword", NoSavePassword);
\r
3939 PACK_GET_POLICY_BOOL("FilterIPv4", FilterIPv4);
\r
3940 PACK_GET_POLICY_BOOL("FilterIPv6", FilterIPv6);
\r
3941 PACK_GET_POLICY_BOOL("FilterNonIP", FilterNonIP);
\r
3942 PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
\r
3943 PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
\r
3947 PACK_GET_POLICY_UINT("MaxConnection", MaxConnection);
\r
3948 PACK_GET_POLICY_UINT("TimeOut", TimeOut);
\r
3949 PACK_GET_POLICY_UINT("MaxMac", MaxMac);
\r
3950 PACK_GET_POLICY_UINT("MaxIP", MaxIP);
\r
3951 PACK_GET_POLICY_UINT("MaxUpload", MaxUpload);
\r
3952 PACK_GET_POLICY_UINT("MaxDownload", MaxDownload);
\r
3953 PACK_GET_POLICY_UINT("MultiLogins", MultiLogins);
\r
3955 PACK_GET_POLICY_UINT("MaxIPv6", MaxIPv6);
\r
3956 PACK_GET_POLICY_UINT("AutoDisconnect", AutoDisconnect);
\r
3957 PACK_GET_POLICY_UINT("VLanId", VLanId);
\r
3960 PACK_GET_POLICY_BOOL("Ver3", Ver3);
\r
3966 void PackAddPolicy(PACK *p, POLICY *y)
\r
3968 // このあたりは急いで実装したのでコードがあまり美しくない。
\r
3970 if (p == NULL || y == NULL)
\r
3977 PACK_ADD_POLICY_BOOL("Access", Access);
\r
3978 PACK_ADD_POLICY_BOOL("DHCPFilter", DHCPFilter);
\r
3979 PACK_ADD_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
\r
3980 PACK_ADD_POLICY_BOOL("DHCPForce", DHCPForce);
\r
3981 PACK_ADD_POLICY_BOOL("NoBridge", NoBridge);
\r
3982 PACK_ADD_POLICY_BOOL("NoRouting", NoRouting);
\r
3983 PACK_ADD_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
\r
3984 PACK_ADD_POLICY_BOOL("NoServer", NoServer);
\r
3985 PACK_ADD_POLICY_BOOL("CheckMac", CheckMac);
\r
3986 PACK_ADD_POLICY_BOOL("CheckIP", CheckIP);
\r
3987 PACK_ADD_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
\r
3988 PACK_ADD_POLICY_BOOL("MonitorPort", MonitorPort);
\r
3989 PACK_ADD_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
\r
3990 PACK_ADD_POLICY_BOOL("FixPassword", FixPassword);
\r
3991 PACK_ADD_POLICY_BOOL("NoQoS", NoQoS);
\r
3993 PACK_ADD_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
\r
3994 PACK_ADD_POLICY_BOOL("RAFilter", RAFilter);
\r
3995 PACK_ADD_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
\r
3996 PACK_ADD_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
\r
3997 PACK_ADD_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
\r
3998 PACK_ADD_POLICY_BOOL("CheckIPv6", CheckIPv6);
\r
3999 PACK_ADD_POLICY_BOOL("NoServerV6", NoServerV6);
\r
4000 PACK_ADD_POLICY_BOOL("NoSavePassword", NoSavePassword);
\r
4001 PACK_ADD_POLICY_BOOL("FilterIPv4", FilterIPv4);
\r
4002 PACK_ADD_POLICY_BOOL("FilterIPv6", FilterIPv6);
\r
4003 PACK_ADD_POLICY_BOOL("FilterNonIP", FilterNonIP);
\r
4004 PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
\r
4005 PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
\r
4009 PACK_ADD_POLICY_UINT("MaxConnection", MaxConnection);
\r
4010 PACK_ADD_POLICY_UINT("TimeOut", TimeOut);
\r
4011 PACK_ADD_POLICY_UINT("MaxMac", MaxMac);
\r
4012 PACK_ADD_POLICY_UINT("MaxIP", MaxIP);
\r
4013 PACK_ADD_POLICY_UINT("MaxUpload", MaxUpload);
\r
4014 PACK_ADD_POLICY_UINT("MaxDownload", MaxDownload);
\r
4015 PACK_ADD_POLICY_UINT("MultiLogins", MultiLogins);
\r
4017 PACK_ADD_POLICY_UINT("MaxIPv6", MaxIPv6);
\r
4018 PACK_ADD_POLICY_UINT("AutoDisconnect", AutoDisconnect);
\r
4019 PACK_ADD_POLICY_UINT("VLanId", VLanId);
\r
4022 PackAddBool(p, "policy:Ver3", true);
\r
4025 // 追加接続用の認証データをアップロードする
\r
4026 bool ClientUploadAuth2(CONNECTION *c, SOCK *s)
\r
4035 p = PackAdditionalConnect(c->Session->SessionKey);
\r
4037 PackAddClientVersion(p, c);
\r
4039 if (HttpClientSend(s, p) == false)
\r
4050 void ClientUploadNoop(CONNECTION *c)
\r
4060 PackAddInt(p, "noop", 1);
\r
4061 HttpClientSend(c->FirstSock, p);
\r
4064 p = HttpClientRecv(c->FirstSock);
\r
4071 // クライアントのバージョン情報を PACK に追加する
\r
4072 void PackAddClientVersion(PACK *p, CONNECTION *c)
\r
4075 if (p == NULL || c == NULL)
\r
4080 PackAddStr(p, "client_str", c->ClientStr);
\r
4081 PackAddInt(p, "client_ver", c->ClientVer);
\r
4082 PackAddInt(p, "client_build", c->ClientBuild);
\r
4085 // 新規接続用の認証データをアップロードする
\r
4086 bool ClientUploadAuth(CONNECTION *c)
\r
4094 UCHAR secure_password[SHA1_SIZE];
\r
4095 UCHAR sign[4096 / 8];
\r
4096 UCHAR unique[SHA1_SIZE];
\r
4104 Zero(sign, sizeof(sign));
\r
4106 a = c->Session->ClientAuth;
\r
4107 o = c->Session->ClientOption;
\r
4109 if (c->UseTicket == false)
\r
4111 switch (a->AuthType)
\r
4113 case CLIENT_AUTHTYPE_ANONYMOUS:
\r
4115 p = PackLoginWithAnonymous(o->HubName, a->Username);
\r
4118 case CLIENT_AUTHTYPE_PASSWORD:
\r
4120 SecurePassword(secure_password, a->HashedPassword, c->Random);
\r
4121 p = PackLoginWithPassword(o->HubName, a->Username, secure_password);
\r
4124 case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
\r
4126 p = PackLoginWithPlainPassword(o->HubName, a->Username, a->PlainPassword);
\r
4129 case CLIENT_AUTHTYPE_CERT:
\r
4131 if (a->ClientX != NULL && a->ClientX->is_compatible_bit &&
\r
4132 a->ClientX->bits != 0 && (a->ClientX->bits / 8) <= sizeof(sign))
\r
4134 if (RsaSignEx(sign, c->Random, SHA1_SIZE, a->ClientK, a->ClientX->bits))
\r
4136 p = PackLoginWithCert(o->HubName, a->Username, a->ClientX, sign, a->ClientX->bits / 8);
\r
4137 c->ClientX = CloneX(a->ClientX);
\r
4142 case CLIENT_AUTHTYPE_SECURE:
\r
4144 if (ClientSecureSign(c, sign, c->Random, &x))
\r
4146 p = PackLoginWithCert(o->HubName, a->Username, x, sign, 128);
\r
4147 c->ClientX = CloneX(x);
\r
4152 c->Err = ERR_SECURE_DEVICE_OPEN_FAILED;
\r
4153 c->Session->ForceStopFlag = true;
\r
4162 PackAddStr(p, "method", "login");
\r
4163 PackAddStr(p, "hubname", o->HubName);
\r
4164 PackAddStr(p, "username", a->Username);
\r
4165 PackAddInt(p, "authtype", AUTHTYPE_TICKET);
\r
4166 PackAddData(p, "ticket", c->Ticket, SHA1_SIZE);
\r
4170 PackAddInt64(p, "timestamp", SystemTime64());
\r
4175 if (c->Err != ERR_SECURE_DEVICE_OPEN_FAILED)
\r
4177 c->Err = ERR_PROTOCOL_ERROR;
\r
4182 PackAddClientVersion(p, c);
\r
4185 PackAddInt(p, "protocol", c->Protocol);
\r
4188 PackAddStr(p, "hello", c->ClientStr);
\r
4189 PackAddInt(p, "version", c->ClientVer);
\r
4190 PackAddInt(p, "build", c->ClientBuild);
\r
4191 PackAddInt(p, "client_id", c->Cedar->ClientId);
\r
4194 PackAddInt(p, "max_connection", o->MaxConnection);
\r
4196 PackAddInt(p, "use_encrypt", o->UseEncrypt == false ? 0 : 1);
\r
4198 // PackAddInt(p, "use_fast_rc4", o->UseFastRC4 == false ? 0 : 1);
\r
4200 PackAddInt(p, "use_compress", o->UseCompress == false ? 0 : 1);
\r
4202 PackAddInt(p, "half_connection", o->HalfConnection == false ? 0 : 1);
\r
4204 // ブリッジ / ルーティングモードフラグ
\r
4205 PackAddBool(p, "require_bridge_routing_mode", o->RequireBridgeRoutingMode);
\r
4208 PackAddBool(p, "require_monitor_mode", o->RequireMonitorMode);
\r
4211 PackAddBool(p, "qos", o->DisableQoS ? false : true);
\r
4214 GenerateMachineUniqueHash(unique);
\r
4215 PackAddData(p, "unique_id", unique, SHA1_SIZE);
\r
4218 CreateNodeInfo(&info, c);
\r
4219 OutRpcNodeInfo(p, &info);
\r
4223 OutRpcWinVer(p, &v);
\r
4225 ret = HttpClientSend(c->FirstSock, p);
\r
4228 c->Err = ERR_DISCONNECTED;
\r
4236 // Hello パケットをアップロードする
\r
4237 bool ServerUploadHello(CONNECTION *c)
\r
4247 Rand(c->Random, SHA1_SIZE);
\r
4249 p = PackHello(c->Random, c->ServerVer, c->ServerBuild, c->ServerStr);
\r
4250 if (HttpServerSend(c->FirstSock, p) == false)
\r
4253 c->Err = ERR_DISCONNECTED;
\r
4262 // Hello パケットをダウンロードする
\r
4263 bool ClientDownloadHello(CONNECTION *c, SOCK *s)
\r
4267 UCHAR random[SHA1_SIZE];
\r
4275 p = HttpClientRecv(s);
\r
4278 c->Err = ERR_SERVER_IS_NOT_VPN;
\r
4282 if (err = GetErrorFromPack(p))
\r
4291 if (GetHello(p, random, &c->ServerVer, &c->ServerBuild, c->ServerStr, sizeof(c->ServerStr)) == false)
\r
4293 c->Err = ERR_SERVER_IS_NOT_VPN;
\r
4298 if (c->FirstSock == s)
\r
4300 Copy(c->Random, random, SHA1_SIZE);
\r
4309 bool ServerDownloadSignature(CONNECTION *c)
\r
4315 UINT num = 0, max = 19;
\r
4331 c->Err = ERR_CLIENT_IS_NOT_VPN;
\r
4335 h = RecvHttpHeader(s);
\r
4338 c->Err = ERR_CLIENT_IS_NOT_VPN;
\r
4343 if (StrCmpi(h->Method, "POST") == 0)
\r
4345 // POST なのでデータを受信する
\r
4346 data_size = GetContentLength(h);
\r
4347 if ((data_size > 3411 || data_size < 1411) && (data_size != StrLen(HTTP_VPN_TARGET_POSTDATA)))
\r
4350 HttpSendForbidden(s, h->Target, NULL);
\r
4351 FreeHttpHeader(h);
\r
4352 c->Err = ERR_CLIENT_IS_NOT_VPN;
\r
4355 data = Malloc(data_size);
\r
4356 if (RecvAll(s, data, data_size, s->SecureMode) == false)
\r
4360 FreeHttpHeader(h);
\r
4361 c->Err = ERR_DISCONNECTED;
\r
4365 if (StrCmpi(h->Target, HTTP_VPN_TARGET2) != 0)
\r
4368 HttpSendNotFound(s, h->Target);
\r
4370 FreeHttpHeader(h);
\r
4374 if (((data_size == StrLen(HTTP_VPN_TARGET_POSTDATA)) && (Cmp(data, HTTP_VPN_TARGET_POSTDATA, data_size) == 0)) || (data_size >= 1411))
\r
4376 // VPN Client が接続してきた
\r
4378 FreeHttpHeader(h);
\r
4383 // VPN Client 以外のソフトウェアが接続してきた
\r
4384 HttpSendForbidden(s, h->Target, NULL);
\r
4385 FreeHttpHeader(h);
\r
4391 // これ以上解釈しても VPN クライアントで無い可能性が高いが
\r
4393 if (StrCmpi(h->Method, "GET") != 0)
\r
4395 // サポートされていないメソッド呼び出し
\r
4396 HttpSendNotImplemented(s, h->Method, h->Target, h->Version);
\r
4400 if (StrCmpi(h->Target, "/") == 0)
\r
4403 HttpSendForbidden(c->FirstSock, h->Target, "");
\r
4408 HttpSendNotFound(s, h->Target);
\r
4411 FreeHttpHeader(h);
\r
4417 bool ClientUploadSignature(SOCK *s)
\r
4426 h = NewHttpHeader("POST", HTTP_VPN_TARGET2, "HTTP/1.1");
\r
4427 AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
\r
4428 AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
\r
4430 if (PostHttp(s, h, HTTP_VPN_TARGET_POSTDATA, StrLen(HTTP_VPN_TARGET_POSTDATA)) == false)
\r
4432 FreeHttpHeader(h);
\r
4436 FreeHttpHeader(h);
\r
4442 SOCK *ClientConnectToServer(CONNECTION *c)
\r
4455 c->Err = ERR_USER_CANCEL;
\r
4460 s = ClientConnectGetSocket(c, false);
\r
4471 c->Err = ERR_USER_CANCEL;
\r
4473 c->FirstSock = NULL;
\r
4478 SetTimeout(s, CONNECTING_TIMEOUT);
\r
4481 if (StartSSLEx(s, x, k, (c->DontUseTls1 ? false : true)) == false)
\r
4486 c->FirstSock = NULL;
\r
4487 c->Err = ERR_SERVER_IS_NOT_VPN;
\r
4491 if (s->RemoteX == NULL)
\r
4496 c->FirstSock = NULL;
\r
4497 c->Err = ERR_SERVER_IS_NOT_VPN;
\r
4504 // サーバーに接続しソケットを返す
\r
4505 SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
\r
4509 char *host_for_direct_connection;
\r
4510 UINT port_for_direct_connection;
\r
4511 wchar_t tmp[MAX_SIZE];
\r
4513 volatile bool *cancel_flag = NULL;
\r
4521 sess = c->Session;
\r
4525 cancel_flag = &sess->CancelConnect;
\r
4528 hWnd = c->hWndForUI;
\r
4530 o = c->Session->ClientOption;
\r
4532 if (c->RestoreServerNameAndPort && additional_connect)
\r
4534 // サーバー名とポート番号を元に戻す
\r
4535 c->RestoreServerNameAndPort = false;
\r
4537 StrCpy(c->ServerName, sizeof(c->ServerName), o->Hostname);
\r
4538 c->ServerPort = o->Port;
\r
4541 host_for_direct_connection = c->ServerName;
\r
4542 port_for_direct_connection = c->ServerPort;
\r
4544 if (o->PortUDP != 0)
\r
4547 goto UDP_CONNECTION;
\r
4550 switch (o->ProxyType)
\r
4552 case PROXY_DIRECT: // TCP/IP
\r
4554 UniFormat(tmp, sizeof(tmp), _UU("STATUS_4"), c->ServerName);
\r
4555 PrintStatus(sess, tmp);
\r
4557 s = TcpIpConnectEx(host_for_direct_connection, port_for_direct_connection,
\r
4558 (bool *)cancel_flag, hWnd);
\r
4562 c->Err = ERR_CONNECT_FAILED;
\r
4567 case PROXY_HTTP: // HTTP Proxy
\r
4568 host_for_direct_connection = o->ProxyName;
\r
4569 port_for_direct_connection = o->ProxyPort;
\r
4571 UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
\r
4572 PrintStatus(sess, tmp);
\r
4574 s = ProxyConnectEx(c, host_for_direct_connection, port_for_direct_connection,
\r
4575 c->ServerName, c->ServerPort, o->ProxyUsername, o->ProxyPassword,
\r
4576 additional_connect, (bool *)cancel_flag, hWnd);
\r
4584 case PROXY_SOCKS: // SOCKS Proxy
\r
4585 host_for_direct_connection = o->ProxyName;
\r
4587 port_for_direct_connection = o->ProxyPort;
\r
4589 UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
\r
4590 PrintStatus(sess, tmp);
\r
4592 s = SocksConnectEx(c, host_for_direct_connection, port_for_direct_connection,
\r
4593 c->ServerName, c->ServerPort, o->ProxyUsername,
\r
4594 additional_connect, (bool *)cancel_flag, hWnd);
\r
4606 c->Err = ERR_CONNECT_FAILED;
\r
4612 if (GetIP(&c->Session->ServerIP, host_for_direct_connection) == false)
\r
4614 Copy(&c->Session->ServerIP, &s->RemoteIP, sizeof(IP));
\r
4622 SOCK *SocksConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
\r
4623 char *server_host_name, UINT server_port,
\r
4624 char *username, bool additional_connect)
\r
4626 return SocksConnectEx(c, proxy_host_name, proxy_port,
\r
4627 server_host_name, server_port, username, additional_connect, NULL, NULL);
\r
4629 SOCK *SocksConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
\r
4630 char *server_host_name, UINT server_port,
\r
4631 char *username, bool additional_connect,
\r
4632 bool *cancel_flag, void *hWnd)
\r
4637 if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL
\r
4638 || server_port == 0)
\r
4640 c->Err = ERR_PROXY_CONNECT_FAILED;
\r
4644 // 接続先サーバーの IP アドレスを取得す
\r
4645 if (GetIP(&ip, server_host_name) == false)
\r
4648 c->Err = ERR_CONNECT_FAILED;
\r
4655 c->Err = ERR_USER_CANCEL;
\r
4660 s = TcpConnectEx2(proxy_host_name, proxy_port, 0, cancel_flag, hWnd);
\r
4664 c->Err = ERR_PROXY_CONNECT_FAILED;
\r
4669 SetTimeout(s, CONNECTING_TIMEOUT_PROXY);
\r
4671 if (additional_connect == false)
\r
4677 if (SocksSendRequestPacket(c, s, server_port, &ip, username) == false)
\r
4680 if (additional_connect == false)
\r
4682 c->FirstSock = NULL;
\r
4690 if (SocksRecvResponsePacket(c, s) == false)
\r
4693 if (additional_connect == false)
\r
4695 c->FirstSock = NULL;
\r
4702 SetTimeout(s, INFINITE);
\r
4707 // SOCKS 応答パケットを受信する
\r
4708 bool SocksRecvResponsePacket(CONNECTION *c, SOCK *s)
\r
4715 if (c == NULL || s == NULL)
\r
4720 if (RecvAll(s, tmp, sizeof(tmp), false) == false)
\r
4722 c->Err = ERR_DISCONNECTED;
\r
4727 WriteBuf(b, tmp, sizeof(tmp));
\r
4730 ReadBuf(b, &vn, 1);
\r
4731 ReadBuf(b, &cd, 1);
\r
4737 c->Err = ERR_PROXY_ERROR;
\r
4749 c->Err = ERR_PROXY_AUTH_FAILED;
\r
4754 c->Err = ERR_CONNECT_FAILED;
\r
4759 // SOCKS リクエストパケットを送信する
\r
4760 bool SocksSendRequestPacket(CONNECTION *c, SOCK *s, UINT dest_port, IP *dest_ip, char *userid)
\r
4768 if (s == NULL || dest_port == 0 || dest_ip == NULL || c == NULL)
\r
4772 if (userid == NULL)
\r
4780 WriteBuf(b, &vn, 1);
\r
4781 WriteBuf(b, &cd, 1);
\r
4782 port = Endian16((USHORT)dest_port);
\r
4783 ip = IPToUINT(dest_ip);
\r
4784 WriteBuf(b, &port, 2);
\r
4785 WriteBuf(b, &ip, 4);
\r
4786 WriteBuf(b, userid, StrLen(userid) + 1);
\r
4788 ret = SendAll(s, b->Buf, b->Size, false);
\r
4791 c->Err = ERR_DISCONNECTED;
\r
4800 SOCK *ProxyConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
\r
4801 char *server_host_name, UINT server_port,
\r
4802 char *username, char *password, bool additional_connect)
\r
4804 return ProxyConnectEx(c, proxy_host_name, proxy_port,
\r
4805 server_host_name, server_port, username, password, additional_connect, NULL, NULL);
\r
4807 SOCK *ProxyConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
\r
4808 char *server_host_name, UINT server_port,
\r
4809 char *username, char *password, bool additional_connect,
\r
4810 bool *cancel_flag, void *hWnd)
\r
4813 bool use_auth = false;
\r
4814 char tmp[MAX_SIZE];
\r
4815 char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2];
\r
4816 char basic_str[MAX_SIZE * 2];
\r
4817 UINT http_error_code;
\r
4820 if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL ||
\r
4823 c->Err = ERR_PROXY_CONNECT_FAILED;
\r
4826 if (username != NULL && password != NULL &&
\r
4827 (StrLen(username) != 0 || StrLen(password) != 0))
\r
4835 c->Err = ERR_USER_CANCEL;
\r
4840 s = TcpConnectEx2(proxy_host_name, proxy_port, 0, cancel_flag, hWnd);
\r
4844 c->Err = ERR_PROXY_CONNECT_FAILED;
\r
4849 SetTimeout(s, CONNECTING_TIMEOUT_PROXY);
\r
4851 if (additional_connect == false)
\r
4857 if (IsStrIPv6Address(server_host_name))
\r
4860 char iptmp[MAX_PATH];
\r
4862 StrToIP(&ip, server_host_name);
\r
4863 IPToStr(iptmp, sizeof(iptmp), &ip);
\r
4865 Format(tmp, sizeof(tmp), "[%s]:%u", iptmp, server_port);
\r
4869 Format(tmp, sizeof(tmp), "%s:%u", server_host_name, server_port);
\r
4872 h = NewHttpHeader("CONNECT", tmp, "HTTP/1.0");
\r
4873 AddHttpValue(h, NewHttpValue("User-Agent", c->Cedar->HttpUserAgent));
\r
4874 Debug("proxy user agent = %s\n", c->Cedar->HttpUserAgent);
\r
4875 AddHttpValue(h, NewHttpValue("Host", server_host_name));
\r
4876 AddHttpValue(h, NewHttpValue("Content-Length", "0"));
\r
4877 AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive"));
\r
4878 AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
\r
4882 wchar_t tmp[MAX_SIZE];
\r
4883 UniFormat(tmp, sizeof(tmp), _UU("STATUS_3"), server_host_name);
\r
4885 Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
\r
4886 username, password);
\r
4889 Zero(auth_b64_str, sizeof(auth_b64_str));
\r
4890 Encode64(auth_b64_str, auth_tmp_str);
\r
4891 Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str);
\r
4893 AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str));
\r
4897 if (SendHttpHeader(s, h) == false)
\r
4900 if (additional_connect == false)
\r
4902 c->FirstSock = NULL;
\r
4904 FreeHttpHeader(h);
\r
4907 c->Err = ERR_PROXY_ERROR;
\r
4911 FreeHttpHeader(h);
\r
4916 if (additional_connect == false)
\r
4918 c->FirstSock = NULL;
\r
4922 c->Err = ERR_USER_CANCEL;
\r
4927 h = RecvHttpHeader(s);
\r
4931 if (additional_connect == false)
\r
4933 c->FirstSock = NULL;
\r
4935 FreeHttpHeader(h);
\r
4938 c->Err = ERR_PROXY_ERROR;
\r
4942 http_error_code = 0;
\r
4943 if (StrLen(h->Method) == 8)
\r
4945 if (Cmp(h->Method, "HTTP/1.", 7) == 0)
\r
4947 http_error_code = ToInt(h->Target);
\r
4950 FreeHttpHeader(h);
\r
4953 switch (http_error_code)
\r
4959 if (additional_connect == false)
\r
4961 c->FirstSock = NULL;
\r
4965 c->Err = ERR_PROXY_AUTH_FAILED;
\r
4969 if ((http_error_code / 100) == 2)
\r
4972 SetTimeout(s, INFINITE);
\r
4978 if (additional_connect == false)
\r
4980 c->FirstSock = NULL;
\r
4984 c->Err = ERR_PROXY_ERROR;
\r
4991 SOCK *TcpConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd)
\r
4996 return ConnectEx2(hostname, port, timeout, cancel_flag);
\r
5000 return WinConnectEx2((HWND)hWnd, hostname, port, timeout, 0, NULL, NULL);
\r
5003 return ConnectEx2(hostname, port, timeout, cancel_flag);
\r
5004 #endif // OS_WIN32
\r
5008 SOCK *TcpIpConnect(char *hostname, UINT port)
\r
5010 return TcpIpConnectEx(hostname, port, NULL, NULL);
\r
5012 SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd)
\r
5016 if (hostname == NULL || port == 0)
\r
5021 s = TcpConnectEx2(hostname, port, 0, cancel_flag, hWnd);
\r
5030 // PACK にダミーのエントリを作成する
\r
5031 // Q. なぜランダムなサイズのランダムデータをここで挿入するのか?
\r
5032 // A. ネットワーク経路中の盗聴者によってこの SSL 通信が VPN 通信であること
\r
5033 // を検出しにくいようにするためである。
\r
5034 void CreateDummyValue(PACK *p)
\r
5044 size = Rand32() % HTTP_PACK_RAND_SIZE_MAX;
\r
5045 buf = Malloc(size);
\r
5048 PackAddData(p, "pencore", buf, size);
\r
5053 // サーバーがクライアントから PACK を受信する
\r
5054 PACK *HttpServerRecv(SOCK *s)
\r
5070 h = RecvHttpHeader(s);
\r
5076 if (StrCmpi(h->Method, "POST") != 0 ||
\r
5077 StrCmpi(h->Target, HTTP_VPN_TARGET) != 0 ||
\r
5078 StrCmpi(h->Version, "HTTP/1.1") != 0)
\r
5080 FreeHttpHeader(h);
\r
5084 v = GetHttpValue(h, "Content-Type");
\r
5085 if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
\r
5087 FreeHttpHeader(h);
\r
5091 size = GetContentLength(h);
\r
5092 if (size == 0 || size > MAX_PACK_SIZE)
\r
5094 FreeHttpHeader(h);
\r
5098 tmp = MallocEx(size, true);
\r
5099 if (RecvAll(s, tmp, size, s->SecureMode) == false)
\r
5102 FreeHttpHeader(h);
\r
5107 WriteBuf(b, tmp, size);
\r
5109 FreeHttpHeader(h);
\r
5116 if (PackGetInt(p, "noop") != 0)
\r
5118 Debug("recv: noop\n");
\r
5122 PackAddInt(p, "noop", 1);
\r
5123 if (HttpServerSend(s, p) == false)
\r
5143 // クライアントがサーバーから PACK を受信する
\r
5144 PACK *HttpClientRecv(SOCK *s)
\r
5158 h = RecvHttpHeader(s);
\r
5164 if (StrCmpi(h->Method, "HTTP/1.1") != 0 ||
\r
5165 StrCmpi(h->Target, "200") != 0)
\r
5167 FreeHttpHeader(h);
\r
5171 v = GetHttpValue(h, "Content-Type");
\r
5172 if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
\r
5174 FreeHttpHeader(h);
\r
5178 size = GetContentLength(h);
\r
5179 if (size == 0 || size > MAX_PACK_SIZE)
\r
5181 FreeHttpHeader(h);
\r
5185 tmp = MallocEx(size, true);
\r
5186 if (RecvAll(s, tmp, size, s->SecureMode) == false)
\r
5189 FreeHttpHeader(h);
\r
5194 WriteBuf(b, tmp, size);
\r
5196 FreeHttpHeader(h);
\r
5205 // クライアントからサーバーに PACK を送信する
\r
5206 bool HttpClientSend(SOCK *s, PACK *p)
\r
5211 char date_str[MAX_SIZE];
\r
5213 if (s == NULL || p == NULL)
\r
5218 CreateDummyValue(p);
\r
5226 h = NewHttpHeader("POST", HTTP_VPN_TARGET, "HTTP/1.1");
\r
5228 GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
\r
5229 AddHttpValue(h, NewHttpValue("Date", date_str));
\r
5230 AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
\r
5231 AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
\r
5232 AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
\r
5234 ret = PostHttp(s, h, b->Buf, b->Size);
\r
5236 FreeHttpHeader(h);
\r
5242 // サーバーからクライアントに PACK を送信する
\r
5243 bool HttpServerSend(SOCK *s, PACK *p)
\r
5248 char date_str[MAX_SIZE];
\r
5250 if (s == NULL || p == NULL)
\r
5255 CreateDummyValue(p);
\r
5263 h = NewHttpHeader("HTTP/1.1", "200", "OK");
\r
5265 GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
\r
5266 AddHttpValue(h, NewHttpValue("Date", date_str));
\r
5267 AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
\r
5268 AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
\r
5269 AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
\r
5271 ret = PostHttp(s, h, b->Buf, b->Size);
\r
5273 FreeHttpHeader(h);
\r
5279 // 501 Not Implemented エラーの送信
\r
5280 bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version)
\r
5283 char date_str[MAX_SIZE];
\r
5286 char port_str[MAX_SIZE];
\r
5288 char host[MAX_SIZE];
\r
5291 if (s == NULL || target == NULL)
\r
5297 GetMachineName(host, MAX_SIZE);
\r
5299 port = s->LocalPort;
\r
5302 GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
\r
5304 h = NewHttpHeader("HTTP/1.1", "501", "Method Not Implemented");
\r
5306 AddHttpValue(h, NewHttpValue("Date", date_str));
\r
5307 AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
\r
5308 AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
\r
5309 AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
\r
5312 str_size = sizeof(http_501_str) * 2 + StrLen(target) + StrLen(host) + StrLen(method) + StrLen(version);
\r
5313 str = Malloc(str_size);
\r
5314 StrCpy(str, str_size, http_501_str);
\r
5317 ReplaceStri(str, str_size, str, "$TARGET$", target);
\r
5320 ReplaceStri(str, str_size, str, "$HOST$", host);
\r
5323 ToStr(port_str, port);
\r
5324 ReplaceStri(str, str_size, str, "$PORT$", port_str);
\r
5327 ReplaceStri(str, str_size, str, "$METHOD$", method);
\r
5330 ReplaceStri(str, str_size, str, "$VERSION$", version);
\r
5333 ret = PostHttp(s, h, str, StrLen(str));
\r
5335 FreeHttpHeader(h);
\r
5341 // 404 Not Found エラーの送信
\r
5342 bool HttpSendNotFound(SOCK *s, char *target)
\r
5345 char date_str[MAX_SIZE];
\r
5348 char port_str[MAX_SIZE];
\r
5350 char host[MAX_SIZE];
\r
5353 if (s == NULL || target == NULL)
\r
5359 GetMachineName(host, MAX_SIZE);
\r
5361 port = s->LocalPort;
\r
5364 GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
\r
5366 h = NewHttpHeader("HTTP/1.1", "404", "Not Found");
\r
5368 AddHttpValue(h, NewHttpValue("Date", date_str));
\r
5369 AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
\r
5370 AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
\r
5371 AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
\r
5374 str_size = sizeof(http_404_str) * 2 + StrLen(target) + StrLen(host);
\r
5375 str = Malloc(str_size);
\r
5376 StrCpy(str, str_size, http_404_str);
\r
5379 ReplaceStri(str, str_size, str, "$TARGET$", target);
\r
5382 ReplaceStri(str, str_size, str, "$HOST$", host);
\r
5385 ToStr(port_str, port);
\r
5386 ReplaceStri(str, str_size, str, "$PORT$", port_str);
\r
5389 ret = PostHttp(s, h, str, StrLen(str));
\r
5391 FreeHttpHeader(h);
\r
5397 // 403 Forbidden エラーの送信
\r
5398 bool HttpSendForbidden(SOCK *s, char *target, char *server_id)
\r
5401 char date_str[MAX_SIZE];
\r
5404 char port_str[MAX_SIZE];
\r
5406 char host[MAX_SIZE];
\r
5409 if (s == NULL || target == NULL)
\r
5415 GetMachineName(host, MAX_SIZE);
\r
5417 port = s->LocalPort;
\r
5420 GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
\r
5422 h = NewHttpHeader("HTTP/1.1", "403", "Forbidden");
\r
5424 AddHttpValue(h, NewHttpValue("Date", date_str));
\r
5425 AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
\r
5426 AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
\r
5427 AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
\r
5430 str_size = sizeof(http_403_str) * 2 + StrLen(target) + StrLen(host);
\r
5431 str = Malloc(str_size);
\r
5432 StrCpy(str, str_size, http_403_str);
\r
5435 ReplaceStri(str, str_size, str, "$TARGET$", target);
\r
5438 ReplaceStri(str, str_size, str, "$HOST$", host);
\r
5441 ToStr(port_str, port);
\r
5442 ReplaceStri(str, str_size, str, "$PORT$", port_str);
\r
5445 ret = PostHttp(s, h, str, StrLen(str));
\r
5447 FreeHttpHeader(h);
\r
5453 // HTTP ヘッダ用の日時文字列を取得
\r
5454 void GetHttpDateStr(char *str, UINT size, UINT64 t)
\r
5457 static char *wday[] =
\r
5459 "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
\r
5461 static char *month[] =
\r
5463 "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
\r
5471 UINT64ToSystem(&s, t);
\r
5473 Format(str, size, "%s, %02u %s %04u %02u:%02u:%02u GMT",
\r
5474 wday[s.wDayOfWeek], s.wDay, month[s.wMonth - 1], s.wYear,
\r
5475 s.wHour, s.wMinute, s.wSecond);
\r
5478 // HTTP ヘッダからコンテンツ長を取得する
\r
5479 UINT GetContentLength(HTTP_HEADER *header)
\r
5484 if (header == NULL)
\r
5489 v = GetHttpValue(header, "Content-Length");
\r
5495 ret = ToInt(v->Data);
\r
5501 bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size)
\r
5507 if (s == NULL || header == NULL || post_data == NULL)
\r
5512 // Content-Lentgh が存在するかどうかチェック
\r
5513 if (GetHttpValue(header, "Content-Length") == NULL)
\r
5515 char tmp[MAX_SIZE];
\r
5517 ToStr(tmp, post_size);
\r
5518 AddHttpValue(header, NewHttpValue("Content-Length", tmp));
\r
5522 header_str = HttpHeaderToStr(header);
\r
5523 if (header_str == NULL)
\r
5528 WriteBuf(b, header_str, StrLen(header_str));
\r
5532 WriteBuf(b, post_data, post_size);
\r
5535 ret = SendAll(s, b->Buf, b->Size, s->SecureMode);
\r
5542 // HTTP ヘッダを文字列に変換
\r
5543 char *HttpHeaderToStr(HTTP_HEADER *header)
\r
5550 if (header == NULL)
\r
5555 tmp = Malloc(HTTP_HEADER_LINE_MAX_SIZE);
\r
5559 Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
\r
5560 "%s %s %s\r\n", header->Method, header->Target, header->Version);
\r
5561 WriteBuf(b, tmp, StrLen(tmp));
\r
5564 for (i = 0;i < LIST_NUM(header->ValueList);i++)
\r
5566 HTTP_VALUE *v = (HTTP_VALUE *)LIST_DATA(header->ValueList, i);
\r
5567 Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
\r
5568 "%s: %s\r\n", v->Name, v->Data);
\r
5569 WriteBuf(b, tmp, StrLen(tmp));
\r
5573 WriteBuf(b, "\r\n", 2);
\r
5574 s = Malloc(b->Size + 1);
\r
5575 Copy(s, b->Buf, b->Size);
\r
5585 bool SendHttpHeader(SOCK *s, HTTP_HEADER *header)
\r
5590 if (s == NULL || header == NULL)
\r
5596 str = HttpHeaderToStr(header);
\r
5599 ret = SendAll(s, str, StrLen(str), s->SecureMode);
\r
5607 HTTP_HEADER *RecvHttpHeader(SOCK *s)
\r
5609 TOKEN_LIST *token = NULL;
\r
5611 HTTP_HEADER *header = NULL;
\r
5619 str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
\r
5626 token = ParseToken(str, " ");
\r
5627 if (token->NumTokens < 3)
\r
5636 header = NewHttpHeader(token->Token[0], token->Token[1], token->Token[2]);
\r
5638 if (!StrCmpi(header->Version, "HTTP/1.0") || !StrCmpi(header->Version, "HTTP/0.9"))
\r
5649 char *value_name, *value_data;
\r
5650 str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
\r
5657 if (StrLen(str) == 0)
\r
5666 pos = SearchStr(str, ":", 0);
\r
5667 if (pos == INFINITE)
\r
5672 if ((pos + 1) >= StrLen(str))
\r
5678 // 名前とデータの 2 つに分ける
\r
5679 value_name = Malloc(pos + 1);
\r
5680 Copy(value_name, str, pos);
\r
5681 value_name[pos] = 0;
\r
5682 value_data = &str[pos + 1];
\r
5684 v = NewHttpValue(value_name, value_data);
\r
5693 AddHttpValue(header, v);
\r
5713 FreeHttpHeader(header);
\r
5719 char *RecvLine(SOCK *s, UINT max_size)
\r
5725 if (s == NULL || max_size == 0)
\r
5734 if (RecvAll(s, &c, sizeof(c), s->SecureMode) == false)
\r
5739 WriteBuf(b, &c, sizeof(c));
\r
5740 buf = (UCHAR *)b->Buf;
\r
5741 if (b->Size > max_size)
\r
5748 if (buf[b->Size - 1] == '\n')
\r
5753 if (buf[b->Size - 1] == '\r')
\r
5758 str = Malloc(b->Size + 1);
\r
5759 Copy(str, b->Buf, b->Size);
\r
5770 HTTP_VALUE *NewHttpValue(char *name, char *data)
\r
5774 if (name == NULL || data == NULL)
\r
5779 v = ZeroMalloc(sizeof(HTTP_VALUE));
\r
5781 v->Name = CopyStr(name);
\r
5782 v->Data = CopyStr(data);
\r
5791 void InitProtocol()
\r
5796 void FreeProtocol()
\r
5800 // HTTP ヘッダから HTTP 値を探す
\r
5801 HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name)
\r
5805 if (header == NULL || name == NULL)
\r
5811 v = Search(header->ValueList, &t);
\r
5820 // HTTP ヘッダに HTTP 値を追加
\r
5821 void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value)
\r
5824 if (header == NULL || value == NULL)
\r
5829 Insert(header->ValueList, value);
\r
5833 HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version)
\r
5835 HTTP_HEADER *header;
\r
5837 if (method == NULL || target == NULL || version == NULL)
\r
5842 header = ZeroMalloc(sizeof(HTTP_HEADER));
\r
5844 header->Method = CopyStr(method);
\r
5845 header->Target = CopyStr(target);
\r
5846 header->Version = CopyStr(version);
\r
5847 header->ValueList = NewListFast(CompareHttpValue);
\r
5853 int CompareHttpValue(void *p1, void *p2)
\r
5855 HTTP_VALUE *v1, *v2;
\r
5856 if (p1 == NULL || p2 == NULL)
\r
5860 v1 = *(HTTP_VALUE **)p1;
\r
5861 v2 = *(HTTP_VALUE **)p2;
\r
5862 if (v1 == NULL || v2 == NULL)
\r
5866 return StrCmpi(v1->Name, v2->Name);
\r
5870 void FreeHttpValue(HTTP_VALUE *value)
\r
5873 if (value == NULL)
\r
5878 Free(value->Data);
\r
5879 Free(value->Name);
\r
5885 void FreeHttpHeader(HTTP_HEADER *header)
\r
5888 HTTP_VALUE **values;
\r
5890 if (header == NULL)
\r
5895 Free(header->Method);
\r
5896 Free(header->Target);
\r
5897 Free(header->Version);
\r
5899 values = ToArray(header->ValueList);
\r
5900 for (i = 0;i < LIST_NUM(header->ValueList);i++)
\r
5902 FreeHttpValue(values[i]);
\r
5906 ReleaseList(header->ValueList);
\r
5912 PACK *RecvPack(SOCK *s)
\r
5919 if (s == NULL || s->Type != SOCK_TCP)
\r
5924 if (RecvAll(s, &sz, sizeof(UINT), s->SecureMode) == false)
\r
5928 sz = Endian32(sz);
\r
5929 if (sz > MAX_PACK_SIZE)
\r
5933 data = MallocEx(sz, true);
\r
5934 if (RecvAll(s, data, sz, s->SecureMode) == false)
\r
5941 WriteBuf(b, data, sz);
\r
5951 bool SendPack(SOCK *s, PACK *p)
\r
5956 if (s == NULL || p == NULL || s->Type != SOCK_TCP)
\r
5962 sz = Endian32(b->Size);
\r
5964 SendAdd(s, &sz, sizeof(UINT));
\r
5965 SendAdd(s, b->Buf, b->Size);
\r
5968 return SendNow(s, s->SecureMode);
\r
5972 PACK *PackHello(void *random, UINT ver, UINT build, char *server_str)
\r
5976 if (random == NULL || server_str == NULL)
\r
5982 PackAddStr(p, "hello", server_str);
\r
5983 PackAddInt(p, "version", ver);
\r
5984 PackAddInt(p, "build", build);
\r
5985 PackAddData(p, "random", random, SHA1_SIZE);
\r
5991 bool GetHello(PACK *p, void *random, UINT *ver, UINT *build, char *server_str, UINT server_str_size)
\r
5994 if (p == NULL || random == NULL || ver == NULL || server_str == NULL)
\r
5999 if (PackGetStr(p, "hello", server_str, server_str_size) == false)
\r
6003 *ver = PackGetInt(p, "version");
\r
6004 *build = PackGetInt(p, "build");
\r
6005 if (PackGetDataSize(p, "random") != SHA1_SIZE)
\r
6009 if (PackGetData(p, "random", random) == false)
\r
6018 PACK *PackError(UINT error)
\r
6023 PackAddInt(p, "error", error);
\r
6028 // エラー値を PACK から取得
\r
6029 UINT GetErrorFromPack(PACK *p)
\r
6037 return PackGetInt(p, "error");
\r
6040 // 認証方法を PACK から取得
\r
6041 UINT GetAuthTypeFromPack(PACK *p)
\r
6049 return PackGetInt(p, "authtype");
\r
6052 // ユーザー名と HUB 名を PACK から取得
\r
6053 bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
\r
6054 char *hubname, UINT hubname_size)
\r
6057 if (p == NULL || username == NULL || hubname == NULL)
\r
6062 if (PackGetStr(p, "username", username, username_size) == false)
\r
6066 if (PackGetStr(p, "hubname", hubname, hubname_size) == false)
\r
6073 // プロトコルを PACK から取得
\r
6074 UINT GetProtocolFromPack(PACK *p)
\r
6083 return PackGetInt(p, "protocol");
\r
6085 // 現バージョンでは TCP プロトコルに限定する
\r
6086 return CONNECTION_TCP;
\r
6090 // メソッドを PACK から取得
\r
6091 bool GetMethodFromPack(PACK *p, char *method, UINT size)
\r
6094 if (p == NULL || method == NULL || size == 0)
\r
6099 return PackGetStr(p, "method", method, size);
\r
6102 // 証明書認証ログイン用のパケットを生成
\r
6103 PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size)
\r
6108 if (hubname == NULL || username == NULL)
\r
6114 PackAddStr(p, "method", "login");
\r
6115 PackAddStr(p, "hubname", hubname);
\r
6116 PackAddStr(p, "username", username);
\r
6117 PackAddInt(p, "authtype", CLIENT_AUTHTYPE_CERT);
\r
6120 b = XToBuf(x, false);
\r
6121 PackAddData(p, "cert", b->Buf, b->Size);
\r
6125 PackAddData(p, "sign", sign, sign_size);
\r
6130 // 平文パスワード認証ログイン用のパケットを生成
\r
6131 PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password)
\r
6135 if (hubname == NULL || username == NULL)
\r
6141 PackAddStr(p, "method", "login");
\r
6142 PackAddStr(p, "hubname", hubname);
\r
6143 PackAddStr(p, "username", username);
\r
6144 PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PLAIN_PASSWORD);
\r
6145 PackAddStr(p, "plain_password", plain_password);
\r
6150 // パスワード認証ログイン用のパケットを作成
\r
6151 PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password)
\r
6155 if (hubname == NULL || username == NULL)
\r
6161 PackAddStr(p, "method", "login");
\r
6162 PackAddStr(p, "hubname", hubname);
\r
6163 PackAddStr(p, "username", username);
\r
6164 PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PASSWORD);
\r
6165 PackAddData(p, "secure_password", secure_password, SHA1_SIZE);
\r
6170 // 匿名ログイン用のパケットを作成
\r
6171 PACK *PackLoginWithAnonymous(char *hubname, char *username)
\r
6175 if (hubname == NULL || username == NULL)
\r
6181 PackAddStr(p, "method", "login");
\r
6182 PackAddStr(p, "hubname", hubname);
\r
6183 PackAddStr(p, "username", username);
\r
6184 PackAddInt(p, "authtype", CLIENT_AUTHTYPE_ANONYMOUS);
\r
6190 PACK *PackAdditionalConnect(UCHAR *session_key)
\r
6194 if (session_key == NULL)
\r
6200 PackAddStr(p, "method", "additional_connect");
\r
6201 PackAddData(p, "session_key", session_key, SHA1_SIZE);
\r
6207 K *PackGetK(PACK *p, char *name)
\r
6212 if (p == NULL || name == NULL)
\r
6217 b = PackGetBuf(p, name);
\r
6223 k = BufToK(b, true, false, NULL);
\r
6230 X *PackGetX(PACK *p, char *name)
\r
6235 if (p == NULL || name == NULL)
\r
6240 b = PackGetBuf(p, name);
\r
6246 x = BufToX(b, false);
\r
6253 void PackAddK(PACK *p, char *name, K *k)
\r
6257 if (p == NULL || name == NULL || k == NULL)
\r
6262 b = KToBuf(k, false, NULL);
\r
6268 PackAddBuf(p, name, b);
\r
6273 void PackAddX(PACK *p, char *name, X *x)
\r
6277 if (p == NULL || name == NULL || x == NULL)
\r
6282 b = XToBuf(x, false);
\r
6288 PackAddBuf(p, name, b);
\r
6293 BUF *PackGetBuf(PACK *p, char *name)
\r
6295 return PackGetBufEx(p, name, 0);
\r
6297 BUF *PackGetBufEx(PACK *p, char *name, UINT index)
\r
6303 if (p == NULL || name == NULL)
\r
6308 size = PackGetDataSizeEx(p, name, index);
\r
6309 tmp = MallocEx(size, true);
\r
6310 if (PackGetDataEx(p, name, tmp, index) == false)
\r
6317 WriteBuf(b, tmp, size);
\r
6326 bool PackGetData(PACK *p, char *name, void *data)
\r
6328 return PackGetDataEx(p, name, data, 0);
\r
6330 bool PackGetDataEx(PACK *p, char *name, void *data, UINT index)
\r
6334 if (p == NULL || name == NULL)
\r
6339 e = GetElement(p, name, VALUE_DATA);
\r
6344 Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
\r
6347 bool PackGetData2(PACK *p, char *name, void *data, UINT size)
\r
6349 return PackGetDataEx2(p, name, data, size, 0);
\r
6351 bool PackGetDataEx2(PACK *p, char *name, void *data, UINT size, UINT index)
\r
6355 if (p == NULL || name == NULL)
\r
6360 e = GetElement(p, name, VALUE_DATA);
\r
6365 if (GetDataValueSize(e, index) != size)
\r
6369 Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
\r
6373 // PACK からデータサイズを取得
\r
6374 UINT PackGetDataSize(PACK *p, char *name)
\r
6376 return PackGetDataSizeEx(p, name, 0);
\r
6378 UINT PackGetDataSizeEx(PACK *p, char *name, UINT index)
\r
6382 if (p == NULL || name == NULL)
\r
6387 e = GetElement(p, name, VALUE_DATA);
\r
6392 return GetDataValueSize(e, index);
\r
6396 UINT64 PackGetInt64(PACK *p, char *name)
\r
6398 return PackGetInt64Ex(p, name, 0);
\r
6400 UINT64 PackGetInt64Ex(PACK *p, char *name, UINT index)
\r
6404 if (p == NULL || name == NULL)
\r
6409 e = GetElement(p, name, VALUE_INT64);
\r
6414 return GetInt64Value(e, index);
\r
6417 // PACK からインデックス数を取得
\r
6418 UINT PackGetIndexCount(PACK *p, char *name)
\r
6422 if (p == NULL || name == NULL)
\r
6427 e = GetElement(p, name, INFINITE);
\r
6433 return e->num_value;
\r
6437 UINT PackGetNum(PACK *p, char *name)
\r
6439 return MIN(PackGetInt(p, name), 65536);
\r
6442 // PACK から bool 型を取得
\r
6443 bool PackGetBool(PACK *p, char *name)
\r
6445 return PackGetInt(p, name) == 0 ? false : true;
\r
6447 bool PackGetBoolEx(PACK *p, char *name, UINT index)
\r
6449 return PackGetIntEx(p, name, index) == 0 ? false : true;
\r
6452 // PACK に bool 型を追加
\r
6453 void PackAddBool(PACK *p, char *name, bool b)
\r
6455 PackAddInt(p, name, b ? 1 : 0);
\r
6457 void PackAddBoolEx(PACK *p, char *name, bool b, UINT index, UINT total)
\r
6459 PackAddIntEx(p, name, b ? 1 : 0, index, total);
\r
6462 // PACK に IPV6_ADDR を追加
\r
6463 void PackAddIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index, UINT total)
\r
6466 if (p == NULL || name == NULL || addr == NULL)
\r
6471 PackAddDataEx(p, name, addr, sizeof(IPV6_ADDR), index, total);
\r
6473 void PackAddIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
\r
6475 PackAddIp6AddrEx(p, name, addr, 0, 1);
\r
6478 // PACK から IPV6_ADDR を取得
\r
6479 bool PackGetIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index)
\r
6482 if (p == NULL || name == NULL || addr == NULL)
\r
6484 Zero(addr, sizeof(IPV6_ADDR));
\r
6488 return PackGetDataEx2(p, name, addr, sizeof(IPV6_ADDR), index);
\r
6490 bool PackGetIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
\r
6492 return PackGetIp6AddrEx(p, name, addr, 0);
\r
6496 void PackAddIp32Ex(PACK *p, char *name, UINT ip32, UINT index, UINT total)
\r
6500 if (p == NULL || name == NULL)
\r
6505 UINTToIP(&ip, ip32);
\r
6507 PackAddIpEx(p, name, &ip, index, total);
\r
6509 void PackAddIp32(PACK *p, char *name, UINT ip32)
\r
6511 PackAddIp32Ex(p, name, ip32, 0, 1);
\r
6513 void PackAddIpEx(PACK *p, char *name, IP *ip, UINT index, UINT total)
\r
6517 char tmp[MAX_PATH];
\r
6519 if (p == NULL || name == NULL || ip == NULL)
\r
6526 Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
\r
6527 PackAddBoolEx(p, tmp, b, index, total);
\r
6529 Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
\r
6532 PackAddDataEx(p, tmp, ip->ipv6_addr, sizeof(ip->ipv6_addr), index, total);
\r
6538 Zero(dummy, sizeof(dummy));
\r
6540 PackAddDataEx(p, tmp, dummy, sizeof(dummy), index, total);
\r
6543 Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
\r
6546 PackAddIntEx(p, tmp, ip->ipv6_scope_id, index, total);
\r
6550 PackAddIntEx(p, tmp, 0, index, total);
\r
6555 if (IsBigEndian())
\r
6560 PackAddIntEx(p, name, i, index, total);
\r
6562 void PackAddIp(PACK *p, char *name, IP *ip)
\r
6564 PackAddIpEx(p, name, ip, 0, 1);
\r
6568 UINT PackGetIp32Ex(PACK *p, char *name, UINT index)
\r
6572 if (p == NULL || name == NULL)
\r
6577 if (PackGetIpEx(p, name, &ip, index) == false)
\r
6582 return IPToUINT(&ip);
\r
6584 UINT PackGetIp32(PACK *p, char *name)
\r
6586 return PackGetIp32Ex(p, name, 0);
\r
6588 bool PackGetIpEx(PACK *p, char *name, IP *ip, UINT index)
\r
6591 char tmp[MAX_PATH];
\r
6593 if (p == NULL || ip == NULL || name == NULL)
\r
6598 Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
\r
6599 if (PackGetBoolEx(p, tmp, index))
\r
6604 Zero(data, sizeof(data));
\r
6606 Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
\r
6607 PackGetDataEx2(p, tmp, data, sizeof(data), index);
\r
6609 Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
\r
6610 scope_id = PackGetIntEx(p, tmp, index);
\r
6613 ip->ipv6_scope_id = scope_id;
\r
6617 if (GetElement(p, name, VALUE_INT) == NULL)
\r
6619 Zero(ip, sizeof(IP));
\r
6623 i = PackGetIntEx(p, name, index);
\r
6625 if (IsBigEndian())
\r
6635 bool PackGetIp(PACK *p, char *name, IP *ip)
\r
6637 return PackGetIpEx(p, name, ip, 0);
\r
6641 UINT PackGetInt(PACK *p, char *name)
\r
6643 return PackGetIntEx(p, name, 0);
\r
6645 UINT PackGetIntEx(PACK *p, char *name, UINT index)
\r
6649 if (p == NULL || name == NULL)
\r
6654 e = GetElement(p, name, VALUE_INT);
\r
6659 return GetIntValue(e, index);
\r
6662 // PACK から Unicode 文字列を取得
\r
6663 bool PackGetUniStr(PACK *p, char *name, wchar_t *unistr, UINT size)
\r
6665 return PackGetUniStrEx(p, name, unistr, size, 0);
\r
6667 bool PackGetUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT size, UINT index)
\r
6671 if (p == NULL || name == NULL || unistr == NULL || size == 0)
\r
6678 e = GetElement(p, name, VALUE_UNISTR);
\r
6683 UniStrCpy(unistr, size, GetUniStrValue(e, index));
\r
6688 bool PackGetStr(PACK *p, char *name, char *str, UINT size)
\r
6690 return PackGetStrEx(p, name, str, size, 0);
\r
6692 bool PackGetStrEx(PACK *p, char *name, char *str, UINT size, UINT index)
\r
6696 if (p == NULL || name == NULL || str == NULL || size == 0)
\r
6703 e = GetElement(p, name, VALUE_STR);
\r
6709 StrCpy(str, size, GetStrValue(e, index));
\r
6713 // バッファを PACK に追加 (配列)
\r
6714 void PackAddBufEx(PACK *p, char *name, BUF *b, UINT index, UINT total)
\r
6717 if (p == NULL || name == NULL || b == NULL || total == 0)
\r
6722 PackAddDataEx(p, name, b->Buf, b->Size, index, total);
\r
6725 // データを PACK に追加 (配列)
\r
6726 void PackAddDataEx(PACK *p, char *name, void *data, UINT size, UINT index, UINT total)
\r
6731 if (p == NULL || data == NULL || name == NULL || total == 0)
\r
6736 v = NewDataValue(data, size);
\r
6737 e = GetElement(p, name, VALUE_DATA);
\r
6740 if (e->num_value <= total)
\r
6742 e->values[index] = v;
\r
6746 FreeValue(v, VALUE_DATA);
\r
6751 e = ZeroMallocEx(sizeof(ELEMENT), true);
\r
6752 StrCpy(e->name, sizeof(e->name), name);
\r
6753 e->num_value = total;
\r
6754 e->type = VALUE_DATA;
\r
6755 e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
\r
6756 e->values[index] = v;
\r
6762 void PackAddBuf(PACK *p, char *name, BUF *b)
\r
6765 if (p == NULL || name == NULL || b == NULL)
\r
6770 PackAddData(p, name, b->Buf, b->Size);
\r
6774 void PackAddData(PACK *p, char *name, void *data, UINT size)
\r
6778 if (p == NULL || data == NULL || name == NULL)
\r
6783 v = NewDataValue(data, size);
\r
6784 AddElement(p, NewElement(name, VALUE_DATA, 1, &v));
\r
6787 // 64 bit 整数を PACK に追加 (配列)
\r
6788 void PackAddInt64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total)
\r
6793 if (p == NULL || name == NULL || total == 0)
\r
6798 v = NewInt64Value(i);
\r
6799 e = GetElement(p, name, VALUE_INT64);
\r
6802 if (e->num_value <= total)
\r
6804 e->values[index] = v;
\r
6808 FreeValue(v, VALUE_INT64);
\r
6813 e = ZeroMallocEx(sizeof(ELEMENT), true);
\r
6814 StrCpy(e->name, sizeof(e->name), name);
\r
6815 e->num_value = total;
\r
6816 e->type = VALUE_INT64;
\r
6817 e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
\r
6818 e->values[index] = v;
\r
6823 // 整数を PACK に追加 (配列)
\r
6824 void PackAddIntEx(PACK *p, char *name, UINT i, UINT index, UINT total)
\r
6829 if (p == NULL || name == NULL || total == 0)
\r
6834 v = NewIntValue(i);
\r
6835 e = GetElement(p, name, VALUE_INT);
\r
6838 if (e->num_value <= total)
\r
6840 e->values[index] = v;
\r
6844 FreeValue(v, VALUE_INT);
\r
6849 e = ZeroMallocEx(sizeof(ELEMENT), true);
\r
6850 StrCpy(e->name, sizeof(e->name), name);
\r
6851 e->num_value = total;
\r
6852 e->type = VALUE_INT;
\r
6853 e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
\r
6854 e->values[index] = v;
\r
6859 // 64 bit 整数を PACK に追加
\r
6860 void PackAddInt64(PACK *p, char *name, UINT64 i)
\r
6864 if (p == NULL || name == NULL)
\r
6869 v = NewInt64Value(i);
\r
6870 AddElement(p, NewElement(name, VALUE_INT64, 1, &v));
\r
6874 void PackAddNum(PACK *p, char *name, UINT num)
\r
6876 PackAddInt(p, name, num);
\r
6880 void PackAddInt(PACK *p, char *name, UINT i)
\r
6884 if (p == NULL || name == NULL)
\r
6889 v = NewIntValue(i);
\r
6890 AddElement(p, NewElement(name, VALUE_INT, 1, &v));
\r
6893 // Unicode 文字列を PACK に追加 (配列)
\r
6894 void PackAddUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT index, UINT total)
\r
6899 if (p == NULL || name == NULL || unistr == NULL || total == 0)
\r
6904 v = NewUniStrValue(unistr);
\r
6905 e = GetElement(p, name, VALUE_UNISTR);
\r
6908 if (e->num_value <= total)
\r
6910 e->values[index] = v;
\r
6914 FreeValue(v, VALUE_UNISTR);
\r
6919 e = ZeroMallocEx(sizeof(ELEMENT), true);
\r
6920 StrCpy(e->name, sizeof(e->name), name);
\r
6921 e->num_value = total;
\r
6922 e->type = VALUE_UNISTR;
\r
6923 e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
\r
6924 e->values[index] = v;
\r
6929 // Unicode 文字列を PACK に追加
\r
6930 void PackAddUniStr(PACK *p, char *name, wchar_t *unistr)
\r
6934 if (p == NULL || name == NULL || unistr == NULL)
\r
6939 v = NewUniStrValue(unistr);
\r
6940 AddElement(p, NewElement(name, VALUE_UNISTR, 1, &v));
\r
6943 // 文字列を PACK に追加 (配列)
\r
6944 void PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total)
\r
6949 if (p == NULL || name == NULL || str == NULL || total == 0)
\r
6954 v = NewStrValue(str);
\r
6955 e = GetElement(p, name, VALUE_STR);
\r
6958 if (e->num_value <= total)
\r
6960 e->values[index] = v;
\r
6964 FreeValue(v, VALUE_STR);
\r
6969 e = ZeroMallocEx(sizeof(ELEMENT), true);
\r
6970 StrCpy(e->name, sizeof(e->name), name);
\r
6971 e->num_value = total;
\r
6972 e->type = VALUE_STR;
\r
6973 e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
\r
6974 e->values[index] = v;
\r
6980 void PackAddStr(PACK *p, char *name, char *str)
\r
6984 if (p == NULL || name == NULL || str == NULL)
\r
6989 v = NewStrValue(str);
\r
6990 AddElement(p, NewElement(name, VALUE_STR, 1, &v));
\r
6994 void GenerateRC4KeyPair(RC4_KEY_PAIR *k)
\r
7002 Rand(k->ClientToServerKey, sizeof(k->ClientToServerKey));
\r
7003 Rand(k->ServerToClientKey, sizeof(k->ServerToClientKey));
\r