X-Git-Url: http://lab.mitty.jp/git/?a=blobdiff_plain;f=Dev%2Futvpn%2Futvpn-unix-v101-7101-public%2Fsrc%2FCedar%2FProtocol.c;fp=Dev%2Futvpn%2Futvpn-unix-v101-7101-public%2Fsrc%2FCedar%2FProtocol.c;h=260dc43a56d5609049716e23d399841a138d50ec;hb=a1bae3ebcd5b813618d88ce3886ee70f73cc87c0;hp=0000000000000000000000000000000000000000;hpb=ce3a7e23f6b6f18970643cb9c4561f20f293e622;p=lab.git
diff --git a/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Protocol.c b/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Protocol.c
new file mode 100644
index 0000000..260dc43
--- /dev/null
+++ b/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Protocol.c
@@ -0,0 +1,7005 @@
+// SoftEther UT-VPN SourceCode
+//
+// Copyright (C) 2004-2010 SoftEther Corporation.
+// Copyright (C) 2004-2010 University of Tsukuba, Japan.
+// Copyright (C) 2003-2010 Daiyuu Nobori.
+// All Rights Reserved.
+//
+// http://utvpn.tsukuba.ac.jp/
+//
+// This program is free software; you can redistribute it and/or
+// modify it under the terms of the GNU General Public License
+// version 2 as published by the Free Software Foundation.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License version 2
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+//
+// ãã®ãã¡ã¤ã«ã¯ GPL ãã¼ã¸ã§ã³ 2 ã©ã¤ã»ã³ã¹ã§å
¬éããã¦ãã¾ãã
+// 誰ã§ããã®ãã¡ã¤ã«ã®å
容ãè¤è£½ãæ¹å¤ããããæ¹å¤ãããã¼ã¸ã§ã³ãåé
å¸
+// ãããã¨ãã§ãã¾ãããã ããåèä½ç©ãæ¹å¤ããå ´åã¯ãåèä½ç©ã®èä½æ¨©è¡¨ç¤º
+// ãé¤å»ãããã¨ã¯ã§ãã¾ãããæ¹å¤ããèä½ç©ãé
å¸ããå ´åã¯ãæ¹å¤å®æ½è
ã®
+// èä½æ¨©è¡¨ç¤ºãåèä½ç©ã®èä½æ¨©è¡¨ç¤ºã«ä»éãã¦è¨è¼ããããã«ãã¦ãã ããã
+//
+// ãã® SoftEther UT-VPN ãªã¼ãã³ã½ã¼ã¹ã»ããã¸ã§ã¯ãã¯ãæ¥æ¬å½ã®
+// ã½ããã¤ã¼ãµæ ªå¼ä¼ç¤¾ (SoftEther Corporation, http://www.softether.co.jp/ )
+// ããã³çæ³¢å¤§å¦ (University of Tsukuba, http://www.tsukuba.ac.jp/ ) ã«ãã£ã¦
+// ãã¹ãããã¦ãã¾ãã
+// æ¬ããã°ã©ã ã®é
å¸è
ã¯ãæ¬ããã°ã©ã ããæ¥ã¨ãã¦ã®å©ç¨ä»¥å¤ã®ããã
+// ããã³ã試é¨ã¾ãã¯ç 究ã®ããã«å©ç¨ãè¡ããããã¨ãæ³å®ãã¦é
å¸
+// ãã¦ãã¾ãã
+// SoftEther UT-VPN ããã¸ã§ã¯ãã® Web ãµã¤ã㯠http://utvpn.tsukuba.ac.jp/ ã«
+// ããã¾ãã
+// æ¬ã½ããã¦ã§ã¢ã®ä¸å
·åã®ä¿®æ£ãæ©è½æ¹è¯ãã»ãã¥ãªãã£ãã¼ã«ã®ä¿®å¾©ãªã©ã®ã³ã¼ã
+// ã®æ¹å¤ãè¡ã£ãå ´åã§ããã®ææç©ã SoftEther UT-VPN ããã¸ã§ã¯ãã«æåºãã¦
+// ããã ããå ´åã¯ã http://utvpn.tsukuba.ac.jp/ ã¾ã§ã½ã¼ã¹ã³ã¼ããéä»ãã¦
+// ãã ãããSoftEther UT-VPN ããã¸ã§ã¯ãã®æ¬ä½ãªãªã¼ã¹ã¾ãã¯ãã©ã³ããªãªã¼ã¹
+// ã«çµã¿è¾¼ã¿ããã¦ããã ãã¾ãã
+//
+// GPL ã«åºã¥ãã¦åèä½ç©ãæä¾ãããæ¬ã½ããã¦ã§ã¢ã®æ¹è¯çãé
å¸ã販売ãã
+// å ´åã¯ããã®ã½ã¼ã¹ã³ã¼ãã GPL ã«åºã¥ãã¦èª°ã«ã§ãé示ãã義åãçãã¾ãã
+//
+// æ¬ã½ããã¦ã§ã¢ã«é¢é£ããèä½æ¨©ãç¹è¨±æ¨©ãåæ¨æ¨©ã¯ã½ããã¤ã¼ãµæ ªå¼ä¼ç¤¾
+// (SoftEther Corporation) ããã³ãã®ä»ã®èä½æ¨©ä¿æè
ãä¿æãã¦ãã¾ãã
+// ã½ããã¤ã¼ãµæ ªå¼ä¼ç¤¾çã¯ãããã®æ¨©å©ãæ¾æ£ãã¦ãã¾ãããæ¬ã½ããã¦ã§ã¢ã®
+// äºæ¬¡èä½ç©ãé
å¸ã販売ããå ´åã¯ããããã®æ¨©å©ã侵害ããªãããã«ã注æ
+// ãã ããã
+//
+// ãé¡ã: ã©ã®ãããªéä¿¡ã½ããã¦ã§ã¢ã«ãé常ã¯å¿
ãæªçºè¦ã®
+// ã»ãã¥ãªãã£ãã¼ã«ãæ½ãã§ãã¾ããæ¬ã½ã¼ã¹ã³ã¼ããã覧ããã ããçµæã
+// UT-VPN ã«ã»ãã¥ãªãã£ãã¼ã«ãçºè¦ãããå ´åã¯ãå½è©²ã»ãã¥ãªãã£ãã¼ã«ã®
+// æ
å ±ãä¸ç¹å®å¤æ°ã«é示ãããåã«ãå¿
ããã½ããã¤ã¼ãµæ ªå¼ä¼ç¤¾
+// ããã³èå¼±æ§æ
å ±ã®å±åºãåãä»ããå
¬çæ©é¢ã¾ã§éå ±ããã ãã
+// å
¬çä¿è·ã«ãååããã ãã¾ããããé¡ãç³ãä¸ãã¾ãã
+//
+// ã½ããã¤ã¼ãµæ ªå¼ä¼ç¤¾ã¯ãå½è©²ã»ãã¥ãªãã£ãã¼ã«ã«ã¤ãã¦è¿
éã«å¯¾å¦ã
+// è¡ããUT-VPN ããã³ UT-VPN ã«é¢é£ããã½ããã¦ã§ã¢ã®ã¦ã¼ã¶ã¼ã»é¡§å®¢
+// ãä¿è·ããããã®åªåãè¡ãã¾ãã
+//
+// ã½ããã¤ã¼ãµã¸ã®å±åºå
: http://www.softether.co.jp/jp/contact/
+// æ¥æ¬å½å
ã®èå¼±æ§æ
å ±å±åºåä»å
¬çæ©é¢:
+// ç¬ç«è¡æ¿æ³äºº æ
å ±å¦çæ¨é²æ©æ§
+// http://www.ipa.go.jp/security/vuln/report/
+//
+// ä¸è¨åäºé
ã«ã¤ãã¦ä¸æãªç¹ã¯ãã½ããã¤ã¼ãµæ ªå¼ä¼ç¤¾ã¾ã§ãé£çµ¡ãã ããã
+// é£çµ¡å
: http://www.softether.co.jp/jp/contact/
+
+// -----------------------------------------------
+// [ChangeLog]
+// 2010.05.20
+// æ°è¦ãªãªã¼ã¹ by SoftEther
+// -----------------------------------------------
+
+// Protocol.c
+// SoftEther ãããã³ã«é¢ä¿ã®ã«ã¼ãã³
+
+#include "CedarPch.h"
+
+static char http_404_str[] = "\r\n
\r\n404 Not Found\r\n\r\nNot Found
\r\nThe requested URL $TARGET$ was not found on this server.\r\n
\r\nHTTP Server at $HOST$ Port $PORT$\r\n\r\n";
+static char http_403_str[] = "\r\n\r\n403 Forbidden\r\n\r\nForbidden
\r\nYou don't have permission to access $TARGET$\r\non this server.\r\n
\r\nHTTP Server at $HOST$ Port $PORT$\r\n\r\n";
+static char http_501_str[] = "\r\n\r\n501 Method Not Implemented\r\n\r\nMethod Not Implemented
\r\n$METHOD$ to $TARGET$ not supported.\r\nInvalid method in request $METHOD$ $TARGET$ $VERSION$
\r\n
\r\nHTTP Server at $HOST$ Port $PORT$\r\n\r\n";
+
+// ãã·ã³ãã¨ã«ã¦ãã¼ã¯ãª ID ãçæãã
+void GenerateMachineUniqueHash(void *data)
+{
+ BUF *b;
+ char name[64];
+ char ip_str[64];
+ IP ip;
+ OS_INFO *osinfo;
+ // å¼æ°ãã§ãã¯
+ if (data == NULL)
+ {
+ return;
+ }
+
+ b = NewBuf();
+ GetMachineName(name, sizeof(name));
+ GetMachineIp(&ip);
+ IPToStr(ip_str, sizeof(ip_str), &ip);
+
+ osinfo = GetOsInfo();
+
+ WriteBuf(b, name, StrLen(name));
+ WriteBuf(b, ip_str, StrLen(ip_str));
+
+ WriteBuf(b, &osinfo->OsType, sizeof(osinfo->OsType));
+ WriteBuf(b, osinfo->KernelName, StrLen(osinfo->KernelName));
+ WriteBuf(b, osinfo->KernelVersion, StrLen(osinfo->KernelVersion));
+ WriteBuf(b, osinfo->OsProductName, StrLen(osinfo->OsProductName));
+ WriteBuf(b, &osinfo->OsServicePack, sizeof(osinfo->OsServicePack));
+ WriteBuf(b, osinfo->OsSystemName, StrLen(osinfo->OsSystemName));
+ WriteBuf(b, osinfo->OsVendorName, StrLen(osinfo->OsVendorName));
+ WriteBuf(b, osinfo->OsVersion, StrLen(osinfo->OsVersion));
+
+ Hash(data, b->Buf, b->Size, true);
+
+ FreeBuf(b);
+}
+
+// ãã¼ãæ
å ±ãæååã«å¤æãã
+void NodeInfoToStr(wchar_t *str, UINT size, NODE_INFO *info)
+{
+ char client_ip[128], server_ip[128], proxy_ip[128], unique_id[128];
+ // å¼æ°ãã§ãã¯
+ if (str == NULL || info == NULL)
+ {
+ return;
+ }
+
+ IPToStr4or6(client_ip, sizeof(client_ip), info->ClientIpAddress, info->ClientIpAddress6);
+ IPToStr4or6(server_ip, sizeof(server_ip), info->ServerIpAddress, info->ServerIpAddress6);
+ IPToStr4or6(proxy_ip, sizeof(proxy_ip), info->ProxyIpAddress, info->ProxyIpAddress6);
+ BinToStr(unique_id, sizeof(unique_id), info->UniqueId, sizeof(info->UniqueId));
+
+ UniFormat(str, size, _UU("LS_NODE_INFO_TAG"), info->ClientProductName,
+ Endian32(info->ClientProductVer), Endian32(info->ClientProductBuild),
+ info->ServerProductName, Endian32(info->ServerProductVer), Endian32(info->ServerProductBuild),
+ info->ClientOsName, info->ClientOsVer, info->ClientOsProductId,
+ info->ClientHostname, client_ip, Endian32(info->ClientPort),
+ info->ServerHostname, server_ip, Endian32(info->ServerPort),
+ info->ProxyHostname, proxy_ip, Endian32(info->ProxyPort),
+ info->HubName, unique_id);
+}
+
+// ãã¼ãæ
å ±ã®æ¯è¼
+bool CompareNodeInfo(NODE_INFO *a, NODE_INFO *b)
+{
+ // å¼æ°ãã§ãã¯
+ if (a == NULL || b == NULL)
+ {
+ return false;
+ }
+
+ // ãã®ãããã¯æ¥ãã§å®è£
ããã®ã§ã³ã¼ãããã¾ãç¾ãããªãã
+ if (StrCmp(a->ClientProductName, b->ClientProductName) != 0)
+ {
+ return false;
+ }
+ if (a->ClientProductVer != b->ClientProductVer)
+ {
+ return false;
+ }
+ if (a->ClientProductBuild != b->ClientProductBuild)
+ {
+ return false;
+ }
+ if (StrCmp(a->ServerProductName, b->ServerProductName) != 0)
+ {
+ return false;
+ }
+ if (a->ServerProductVer != b->ServerProductVer)
+ {
+ return false;
+ }
+ if (a->ServerProductBuild != b->ServerProductBuild)
+ {
+ return false;
+ }
+ if (StrCmp(a->ClientOsName, b->ClientOsName) != 0)
+ {
+ return false;
+ }
+ if (StrCmp(a->ClientOsVer, b->ClientOsVer) != 0)
+ {
+ return false;
+ }
+ if (StrCmp(a->ClientOsProductId, b->ClientOsProductId) != 0)
+ {
+ return false;
+ }
+ if (StrCmp(a->ClientHostname, b->ClientHostname) != 0)
+ {
+ return false;
+ }
+ if (a->ClientIpAddress != b->ClientIpAddress)
+ {
+ return false;
+ }
+ if (StrCmp(a->ServerHostname, b->ServerHostname) != 0)
+ {
+ return false;
+ }
+ if (a->ServerIpAddress != b->ServerIpAddress)
+ {
+ return false;
+ }
+ if (a->ServerPort != b->ServerPort)
+ {
+ return false;
+ }
+ if (StrCmp(a->ProxyHostname, b->ProxyHostname) != 0)
+ {
+ return false;
+ }
+ if (a->ProxyIpAddress != b->ProxyIpAddress)
+ {
+ return false;
+ }
+ if (a->ProxyPort != b->ProxyPort)
+ {
+ return false;
+ }
+ if (StrCmp(a->HubName, b->HubName) != 0)
+ {
+ return false;
+ }
+ if (Cmp(a->UniqueId, b->UniqueId, 16) != 0)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// ãã¹ã¯ã¼ãå¤æ´åä»
+UINT ChangePasswordAccept(CONNECTION *c, PACK *p)
+{
+ CEDAR *cedar;
+ UCHAR random[SHA1_SIZE];
+ char hubname[MAX_HUBNAME_LEN + 1];
+ char username[MAX_USERNAME_LEN + 1];
+ UCHAR secure_old_password[SHA1_SIZE];
+ UCHAR new_password[SHA1_SIZE];
+ UCHAR check_secure_old_password[SHA1_SIZE];
+ UINT ret = ERR_NO_ERROR;
+ HUB *hub;
+ bool save = false;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL || p == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ Copy(random, c->Random, SHA1_SIZE);
+ if (PackGetStr(p, "hubname", hubname, sizeof(hubname)) == false ||
+ PackGetStr(p, "username", username, sizeof(username)) == false ||
+ PackGetData2(p, "secure_old_password", secure_old_password, sizeof(secure_old_password)) == false ||
+ PackGetData2(p, "new_password", new_password, sizeof(new_password)) == false)
+ {
+ return ERR_PROTOCOL_ERROR;
+ }
+
+ cedar = c->Cedar;
+
+ LockHubList(cedar);
+ {
+ hub = GetHub(cedar, hubname);
+ }
+ UnlockHubList(cedar);
+
+ if (hub == NULL)
+ {
+ ret = ERR_HUB_NOT_FOUND;
+ }
+ else
+ {
+ char tmp[MAX_SIZE];
+
+ if (GetHubAdminOption(hub, "deny_change_user_password") != 0)
+ {
+ ReleaseHub(hub);
+ return ERR_NOT_ENOUGH_RIGHT;
+ }
+
+ IPToStr(tmp, sizeof(tmp), &c->FirstSock->RemoteIP);
+ HLog(hub, "LH_CHANGE_PASSWORD_1", c->Name, tmp);
+
+ AcLock(hub);
+ {
+ USER *u = AcGetUser(hub, username);
+ if (u == NULL)
+ {
+ HLog(hub, "LH_CHANGE_PASSWORD_2", c->Name, username);
+ ret = ERR_OLD_PASSWORD_WRONG;
+ }
+ else
+ {
+ Lock(u->lock);
+ {
+ if (u->AuthType != AUTHTYPE_PASSWORD)
+ {
+ // ãã¹ã¯ã¼ãèªè¨¼ã§ã¯ãªã
+ HLog(hub, "LH_CHANGE_PASSWORD_3", c->Name, username);
+ ret = ERR_USER_AUTHTYPE_NOT_PASSWORD;
+ }
+ else
+ {
+ bool fix_password = false;
+ if (u->Policy != NULL)
+ {
+ fix_password = u->Policy->FixPassword;
+ }
+ else
+ {
+ if (u->Group != NULL)
+ {
+ if (u->Group->Policy != NULL)
+ {
+ fix_password = u->Group->Policy->FixPassword;
+ }
+ }
+ }
+ if (fix_password == false)
+ {
+ // å¤ããã¹ã¯ã¼ãã®ç¢ºèª
+ AUTHPASSWORD *pw = (AUTHPASSWORD *)u->AuthData;
+
+ SecurePassword(check_secure_old_password, pw->HashedKey, random);
+ if (Cmp(check_secure_old_password, secure_old_password, SHA1_SIZE) != 0)
+ {
+ // å¤ããã¹ã¯ã¼ããééã£ã¦ãã
+ ret = ERR_OLD_PASSWORD_WRONG;
+ HLog(hub, "LH_CHANGE_PASSWORD_4", c->Name, username);
+ }
+ else
+ {
+ // æ°ãããã¹ã¯ã¼ãã®æ¸ãè¾¼ã¿
+ Copy(pw->HashedKey, new_password, SHA1_SIZE);
+ HLog(hub, "LH_CHANGE_PASSWORD_5", c->Name, username);
+ save = true;
+ }
+ }
+ else
+ {
+ // ãã¹ã¯ã¼ãå¤æ´ã¯ç¦æ¢
+ ret = ERR_NOT_ENOUGH_RIGHT;
+ }
+ }
+ }
+ Unlock(u->lock);
+
+ ReleaseUser(u);
+ }
+ }
+ AcUnlock(hub);
+ ReleaseHub(hub);
+ }
+
+ return ret;
+}
+
+// ãã¹ã¯ã¼ããå¤æ´ãã
+UINT ChangePassword(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, char *username, char *old_pass, char *new_pass)
+{
+ UINT ret = ERR_NO_ERROR;
+ UCHAR old_password[SHA1_SIZE];
+ UCHAR secure_old_password[SHA1_SIZE];
+ UCHAR new_password[SHA1_SIZE];
+ SOCK *sock;
+ SESSION *s;
+ // å¼æ°ãã§ãã¯
+ if (cedar == NULL || o == NULL || hubname == NULL || username == NULL || old_pass == NULL || new_pass == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+
+ // ã»ãã·ã§ã³ä½æ
+ s = NewRpcSessionEx(cedar, o, &ret, NULL);
+
+ if (s != NULL)
+ {
+ PACK *p = NewPack();
+
+ sock = s->Connection->FirstSock;
+
+ HashPassword(old_password, username, old_pass);
+ SecurePassword(secure_old_password, old_password, s->Connection->Random);
+ HashPassword(new_password, username, new_pass);
+
+ PackAddClientVersion(p, s->Connection);
+
+ PackAddStr(p, "method", "password");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddData(p, "secure_old_password", secure_old_password, SHA1_SIZE);
+ PackAddData(p, "new_password", new_password, SHA1_SIZE);
+
+ if (HttpClientSend(sock, p))
+ {
+ PACK *p = HttpClientRecv(sock);
+ if (p == NULL)
+ {
+ ret = ERR_DISCONNECTED;
+ }
+ else
+ {
+ ret = GetErrorFromPack(p);
+ }
+ FreePack(p);
+ }
+ else
+ {
+ ret = ERR_DISCONNECTED;
+ }
+ FreePack(p);
+
+ ReleaseSession(s);
+ }
+
+ return ret;
+}
+
+// HUB ãåæãã
+TOKEN_LIST *EnumHub(SESSION *s)
+{
+ SOCK *sock;
+ TOKEN_LIST *ret;
+ PACK *p;
+ UINT num;
+ UINT i;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || s->Connection == NULL)
+ {
+ return NULL;
+ }
+
+ sock = s->Connection->FirstSock;
+ if (sock == NULL)
+ {
+ return NULL;
+ }
+
+ // ã¿ã¤ã ã¢ã¦ãã®è¨å®
+ SetTimeout(sock, 10000);
+
+ p = NewPack();
+ PackAddStr(p, "method", "enum_hub");
+
+ PackAddClientVersion(p, s->Connection);
+
+ if (HttpClientSend(sock, p) == false)
+ {
+ FreePack(p);
+ return NULL;
+ }
+ FreePack(p);
+
+ p = HttpClientRecv(sock);
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ num = PackGetInt(p, "NumHub");
+ ret = ZeroMalloc(sizeof(TOKEN_LIST));
+ ret->NumTokens = num;
+ ret->Token = ZeroMalloc(sizeof(char *) * num);
+ for (i = 0;i < num;i++)
+ {
+ char tmp[MAX_SIZE];
+ if (PackGetStrEx(p, "HubName", tmp, sizeof(tmp), i))
+ {
+ ret->Token[i] = CopyStr(tmp);
+ }
+ }
+ FreePack(p);
+
+ return ret;
+}
+
+// ãµã¼ãã¼ãã¯ã©ã¤ã¢ã³ãããã®æ¥ç¶ãåãä»ãã
+bool ServerAccept(CONNECTION *c)
+{
+ bool ret = false;
+ UINT err;
+ PACK *p;
+ char username_real[MAX_SIZE];
+ char method[MAX_SIZE];
+ char hubname[MAX_SIZE];
+ char username[MAX_SIZE];
+ char groupname[MAX_SIZE];
+ UCHAR session_key[SHA1_SIZE];
+ UCHAR ticket[SHA1_SIZE];
+ RC4_KEY_PAIR key_pair;
+ UINT authtype;
+ POLICY *policy;
+ HUB *hub;
+ SESSION *s;
+ UINT64 user_expires = 0;
+ bool use_encrypt;
+ bool use_compress;
+ bool half_connection;
+ bool use_fast_rc4;
+ bool admin_mode = false;
+ UINT direction;
+ UINT max_connection;
+ UINT timeout;
+ bool farm_controller = false;
+ bool farm_member = false;
+ bool farm_mode = false;
+ bool require_bridge_routing_mode;
+ bool require_monitor_mode;
+ bool use_client_license = false, use_bridge_license = false;
+ bool local_host_session = false;
+ char sessionname[MAX_SESSION_NAME_LEN + 1];
+ bool is_server_or_bridge = false;
+ bool qos = false;
+ bool cluster_dynamic_secure_nat = false;
+ bool no_save_password = false;
+ NODE_INFO node;
+ wchar_t *msg = NULL;
+ USER *loggedin_user_object = NULL;
+ FARM_MEMBER *f = NULL;
+ SERVER *server = NULL;
+ POLICY ticketed_policy;
+ UINT64 timestamp;
+ UCHAR unique[SHA1_SIZE], unique2[SHA1_SIZE];
+ LICENSE_STATUS license;
+ CEDAR *cedar;
+ RPC_WINVER winver;
+ UINT client_id;
+ bool no_more_users_in_server = false;
+
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ Zero(&winver, sizeof(winver));
+
+ StrCpy(groupname, sizeof(groupname), "");
+ StrCpy(sessionname, sizeof(sessionname), "");
+
+ cedar = c->Cedar;
+
+ // ã©ã¤ã»ã³ã¹ç¶æ³ã®åå¾
+ Zero(&license, sizeof(license));
+ if (c->Cedar->Server != NULL)
+ {
+ LiParseCurrentLicenseStatus(c->Cedar->Server->LicenseSystem, &license);
+ }
+
+ no_more_users_in_server = SiTooManyUserObjectsInServer(cedar->Server, true);
+
+ c->Status = CONNECTION_STATUS_NEGOTIATION;
+
+ if (c->Cedar->Server != NULL)
+ {
+ SERVER *s = c->Cedar->Server;
+ server = s;
+
+ if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
+ {
+ farm_member = true;
+ farm_mode = true;
+ }
+
+ if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ farm_controller = true;
+ farm_mode = true;
+ }
+ }
+
+ // ã·ã°ããã£ãåä¿¡
+ Debug("Downloading Signature...\n");
+ if (ServerDownloadSignature(c) == false)
+ {
+ goto CLEANUP;
+ }
+
+ // Hello ãã±ãããéä¿¡
+ Debug("Uploading Hello...\n");
+ if (ServerUploadHello(c) == false)
+ {
+ goto CLEANUP;
+ }
+
+ // èªè¨¼ãã¼ã¿ãåä¿¡
+ Debug("Auth...\n");
+
+ p = HttpServerRecv(c->FirstSock);
+ if (p == NULL)
+ {
+ // éä¿¡åæ
+ c->Err = ERR_DISCONNECTED;
+ goto CLEANUP;
+ }
+
+ if (err = GetErrorFromPack(p))
+ {
+ // ã¨ã©ã¼çºç
+ FreePack(p);
+ c->Err = err;
+ goto CLEANUP;
+ }
+
+ // ã¡ã½ããåå¾
+ if (GetMethodFromPack(p, method, sizeof(method)) == false)
+ {
+ // ãããã³ã«ã¨ã©ã¼
+ FreePack(p);
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+ // æå»æ¤æ»
+ timestamp = PackGetInt64(p, "timestamp");
+ if (timestamp != 0)
+ {
+ UINT64 now = SystemTime64();
+ UINT64 abs;
+ if (now >= timestamp)
+ {
+ abs = now - timestamp;
+ }
+ else
+ {
+ abs = timestamp - now;
+ }
+
+ if (abs > ALLOW_TIMESTAMP_DIFF)
+ {
+ // æå·®ã大ãããã
+ FreePack(p);
+ c->Err = ERR_BAD_CLOCK;
+ goto CLEANUP;
+ }
+ }
+
+ // ã¯ã©ã¤ã¢ã³ããã¼ã¸ã§ã³åå¾
+ PackGetStr(p, "client_str", c->ClientStr, sizeof(c->ClientStr));
+ c->ClientVer = PackGetInt(p, "client_ver");
+ c->ClientBuild = PackGetInt(p, "client_build");
+
+ if (SearchStrEx(c->ClientStr, "server", 0, false) != INFINITE ||
+ SearchStrEx(c->ClientStr, "bridge", 0, false) != INFINITE)
+ {
+ is_server_or_bridge = true;
+ }
+
+ // ã¯ã©ã¤ã¢ã³ã Windows ãã¼ã¸ã§ã³ã®åå¾
+ InRpcWinVer(&winver, p);
+
+ DecrementNoSsl(c->Cedar, &c->FirstSock->RemoteIP, 2);
+
+ if (StrCmpi(method, "login") == 0)
+ {
+ bool auth_ret = false;
+
+ Debug("Login...\n");
+ c->Status = CONNECTION_STATUS_USERAUTH;
+
+ c->Type = CONNECTION_TYPE_LOGIN;
+
+ if (no_more_users_in_server)
+ {
+ // VPN Server ã«è¨±å¯ããã¦ãããããå¤ãã®ã¦ã¼ã¶ã¼ãåå¨ãã
+ FreePack(p);
+ c->Err = ERR_TOO_MANY_USER;
+ goto CLEANUP;
+ }
+
+ // ã¯ã©ã¤ã¢ã³ãåãªã©
+ if (PackGetStr(p, "hello", c->ClientStr, sizeof(c->ClientStr)) == false)
+ {
+ StrCpy(c->ClientStr, sizeof(c->ClientStr), "Unknown");
+ }
+ c->ServerVer = CEDAR_VER;
+ c->ServerBuild = CEDAR_BUILD;
+
+ // NODE_INFO ãåå¾ãã
+ Zero(&node, sizeof(node));
+ InRpcNodeInfo(&node, p);
+
+ // ãããã³ã«
+ c->Protocol = GetProtocolFromPack(p);
+ if (c->Protocol == CONNECTION_UDP)
+ {
+ // TCP é¢ä¿ã®æ§é ä½ã解æ¾ãã
+ if (c->Tcp)
+ {
+ ReleaseList(c->Tcp->TcpSockList);
+ Free(c->Tcp);
+ }
+ }
+
+ if (GetServerCapsBool(c->Cedar->Server, "b_vpn_client_connect") == false)
+ {
+ // VPN ã¯ã©ã¤ã¢ã³ããæ¥ç¶ä¸å¯è½ã§ãã
+ FreePack(p);
+ c->Err = ERR_NOT_SUPPORTED;
+ goto CLEANUP;
+ }
+
+ // ãã°ã¤ã³
+ if (GetHubnameAndUsernameFromPack(p, username, sizeof(username), hubname, sizeof(hubname)) == false)
+ {
+ // ãããã³ã«ã¨ã©ã¼
+ FreePack(p);
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+ if (farm_member)
+ {
+ bool ok = false;
+ UINT authtype;
+
+ authtype = GetAuthTypeFromPack(p);
+ if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 &&
+ authtype == AUTHTYPE_PASSWORD)
+ {
+ ok = true;
+ }
+
+ if (authtype == AUTHTYPE_TICKET)
+ {
+ ok = true;
+ }
+
+ if (ok == false)
+ {
+ // ãµã¼ãã¼ãã¡ã¼ã ã¡ã³ãã¸ã® Administrators 以å¤ã®ç´æ¥ãã°ãªã³ã¯
+ // ç¦æ¢ããã¦ãã
+ FreePack(p);
+ SLog(c->Cedar, "LS_FARMMEMBER_NOT_ADMIN", c->Name, hubname, ADMINISTRATOR_USERNAME, username);
+ c->Err = ERR_ACCESS_DENIED;
+ goto CLEANUP;
+ }
+ }
+
+ Debug("Username = %s, HubName = %s\n", username, hubname);
+ LockHubList(c->Cedar);
+ {
+ hub = GetHub(c->Cedar, hubname);
+ }
+ UnlockHubList(c->Cedar);
+ if (hub == NULL)
+ {
+ // HUB ãåå¨ããªã
+ FreePack(p);
+ c->Err = ERR_HUB_NOT_FOUND;
+ SLog(c->Cedar, "LS_HUB_NOT_FOUND", c->Name, hubname);
+ goto CLEANUP;
+ }
+
+ Lock(hub->lock);
+ {
+ USER *user;
+ USERGROUP *group;
+ if (hub->Halt || hub->Offline)
+ {
+ // HUB ã¯åæ¢ä¸
+ FreePack(p);
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_STOPPING;
+ goto CLEANUP;
+ }
+
+ // å種ãã©ã°ã®åå¾
+ use_encrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
+ use_compress = PackGetInt(p, "use_compress") == 0 ? false : true;
+ max_connection = PackGetInt(p, "max_connection");
+ half_connection = PackGetInt(p, "half_connection") == 0 ? false : true;
+ use_fast_rc4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
+ qos = PackGetInt(p, "qos") ? true : false;
+ client_id = PackGetInt(p, "client_id");
+
+ // è¦æ±ã¢ã¼ã
+ require_bridge_routing_mode = PackGetBool(p, "require_bridge_routing_mode");
+ require_monitor_mode = PackGetBool(p, "require_monitor_mode");
+ if (require_monitor_mode)
+ {
+ qos = false;
+ }
+
+ if (is_server_or_bridge)
+ {
+ require_bridge_routing_mode = true;
+ }
+
+ // ã¯ã©ã¤ã¢ã³ãã¦ãã¼ã¯ ID
+ Zero(unique, sizeof(unique));
+ if (PackGetDataSize(p, "unique_id") == SHA1_SIZE)
+ {
+ PackGetData(p, "unique_id", unique);
+ }
+
+ // èªè¨¼æ¹æ³ã®åå¾
+ authtype = GetAuthTypeFromPack(p);
+
+ if (1)
+ {
+ // ãã°
+ char ip1[64], ip2[64], verstr[64];
+ wchar_t *authtype_str = _UU("LH_AUTH_UNKNOWN");
+ switch (authtype)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ authtype_str = _UU("LH_AUTH_ANONYMOUS");
+ break;
+ case CLIENT_AUTHTYPE_PASSWORD:
+ authtype_str = _UU("LH_AUTH_PASSWORD");
+ break;
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ authtype_str = _UU("LH_AUTH_PLAIN_PASSWORD");
+ break;
+ case CLIENT_AUTHTYPE_CERT:
+ authtype_str = _UU("LH_AUTH_CERT");
+ break;
+ case AUTHTYPE_TICKET:
+ authtype_str = _UU("LH_AUTH_TICKET");
+ break;
+ }
+ IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
+ IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
+
+ Format(verstr, sizeof(verstr), "%u.%02u", c->ClientVer / 100, c->ClientVer % 100);
+
+ HLog(hub, "LH_CONNECT_CLIENT", c->Name, ip1, c->FirstSock->RemoteHostname, c->FirstSock->RemotePort,
+ c->ClientStr, verstr, c->ClientBuild, authtype_str, username);
+ }
+
+ // ã¾ãå¿åèªè¨¼ã試è¡ãã
+ auth_ret = SamAuthUserByAnonymous(hub, username);
+
+ if (auth_ret)
+ {
+ // ã¦ã¼ã¶ã¼èªè¨¼æå
+ HLog(hub, "LH_AUTH_OK", c->Name, username);
+ }
+
+ if (auth_ret == false)
+ {
+ // å¿åèªè¨¼ã«å¤±æããå ´åã¯ä»ã®èªè¨¼æ¹æ³ã試è¡ãã
+ switch (authtype)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ // å¿åèªè¨¼ (ãã§ã«è©¦è¡ãã¦ãã)
+ break;
+
+ case AUTHTYPE_TICKET:
+ // ãã±ããèªè¨¼
+ if (PackGetDataSize(p, "ticket") == SHA1_SIZE)
+ {
+ PackGetData(p, "ticket", ticket);
+
+ auth_ret = SiCheckTicket(hub, ticket, username, sizeof(username), username_real, sizeof(username_real),
+ &ticketed_policy, sessionname, sizeof(sessionname), groupname, sizeof(groupname));
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ // ãã¹ã¯ã¼ãèªè¨¼
+ if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
+ {
+ POLICY *pol = NULL;
+ UCHAR secure_password[SHA1_SIZE];
+ Zero(secure_password, sizeof(secure_password));
+ if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
+ {
+ PackGetData(p, "secure_password", secure_password);
+ }
+ auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password);
+
+ pol = SamGetUserPolicy(hub, username);
+ if (pol != NULL)
+ {
+ no_save_password = pol->NoSavePassword;
+ Free(pol);
+ }
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ // å¤é¨ãµã¼ãã¼ã«ããèªè¨¼ã¯ãµãã¼ãããã¦ããªã
+ HLog(hub, "LH_AUTH_RADIUS_NOT_SUPPORT", c->Name, username);
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
+ goto CLEANUP;
+
+ case CLIENT_AUTHTYPE_CERT:
+ // 証ææ¸èªè¨¼ã¯ãµãã¼ãããã¦ããªã
+ HLog(hub, "LH_AUTH_CERT_NOT_SUPPORT", c->Name, username);
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
+ goto CLEANUP;
+
+ default:
+ // ä¸æãªèªè¨¼æ¹æ³
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
+ goto CLEANUP;
+ }
+
+ if (auth_ret == false)
+ {
+ // èªè¨¼å¤±æ
+ HLog(hub, "LH_AUTH_NG", c->Name, username);
+ }
+ else
+ {
+ // èªè¨¼æå
+ HLog(hub, "LH_AUTH_OK", c->Name, username);
+ }
+ }
+
+ if (auth_ret == false)
+ {
+ // èªè¨¼å¤±æ
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_AUTH_FAILED;
+ goto CLEANUP;
+ }
+ else
+ {
+ if (authtype == CLIENT_AUTHTYPE_PASSWORD)
+ {
+ UCHAR test[SHA1_SIZE];
+ HashPassword(test, username, "");
+ if (Cmp(test, hub->SecurePassword, SHA1_SIZE) == 0)
+ {
+ SOCK *s = c->FirstSock;
+ if (s != NULL)
+ {
+ if (GetHubAdminOption(hub, "deny_empty_password") != 0 ||
+ (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 && s->RemoteIP.addr[0] != 127))
+ {
+ // ãã¹ã¯ã¼ãã空ã®ã¨ãããªã¢ã¼ãããæ¥ç¶ãã¦ã¯ãããªã
+ HLog(hub, "LH_LOCAL_ONLY", c->Name, username);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ FreePack(p);
+ c->Err = ERR_NULL_PASSWORD_LOCAL_ONLY;
+ goto CLEANUP;
+ }
+ }
+ }
+ }
+ }
+
+ policy = NULL;
+
+ // èªè¨¼æå
+ FreePack(p);
+
+ if (StrCmpi(username, ADMINISTRATOR_USERNAME) != 0)
+ {
+ // ããªã·ã¼ãåå¾
+ if (farm_member == false)
+ {
+ // ãã¡ã¼ã ã¡ã³ã以å¤ã®å ´å
+ user = AcGetUser(hub, username);
+ if (user == NULL)
+ {
+ user = AcGetUser(hub, "*");
+ if (user == NULL)
+ {
+ // ã¦ã¼ã¶ã¼åå¾å¤±æ
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_ACCESS_DENIED;
+ goto CLEANUP;
+ }
+ }
+
+ policy = NULL;
+
+ Lock(user->lock);
+ {
+ // æå¹æéãåå¾
+ user_expires = user->ExpireTime;
+
+ StrCpy(username_real, sizeof(username_real), user->Name);
+ group = user->Group;
+ if (group != NULL)
+ {
+ AddRef(group->ref);
+
+ Lock(group->lock);
+ {
+ // ã°ã«ã¼ãåãåå¾
+ StrCpy(groupname, sizeof(groupname), group->Name);
+ }
+ Unlock(group->lock);
+ }
+
+ if (user->Policy != NULL)
+ {
+ policy = ClonePolicy(user->Policy);
+ }
+ else
+ {
+ if (group)
+ {
+ Lock(group->lock);
+ {
+ if (group->Policy != NULL)
+ {
+ policy = ClonePolicy(group->Policy);
+ }
+ }
+ Unlock(group->lock);
+ }
+ }
+
+ if (group != NULL)
+ {
+ ReleaseGroup(group);
+ }
+ }
+ Unlock(user->lock);
+ loggedin_user_object = user;
+ }
+ else
+ {
+ // ãã¡ã¼ã ã¡ã³ãã®å ´å
+ policy = ClonePolicy(&ticketed_policy);
+ }
+ }
+ else
+ {
+ // 管çè
ã¢ã¼ã
+ admin_mode = true;
+ StrCpy(username_real, sizeof(username_real), ADMINISTRATOR_USERNAME);
+
+ policy = ClonePolicy(GetDefaultPolicy());
+ policy->NoBroadcastLimiter = true;
+ policy->MonitorPort = true;
+ }
+
+ if (policy == NULL)
+ {
+ // ããã©ã«ãã®ããªã·ã¼ã使ç¨ãã
+ policy = ClonePolicy(GetDefaultPolicy());
+ }
+
+ if (policy->MaxConnection == 0)
+ {
+ policy->MaxConnection = MAX_TCP_CONNECTION;
+ }
+
+ if (policy->TimeOut == 0)
+ {
+ policy->TimeOut = 20;
+ }
+
+ if (qos)
+ {
+ // VoIP / QoS
+ if (policy->NoQoS)
+ {
+ // ããªã·ã¼ã許å¯ãã¦ããªã
+ qos = false;
+ }
+ if (GetServerCapsBool(c->Cedar->Server, "b_support_qos") == false)
+ {
+ // ãµã¼ãã¼ããµãã¼ããã¦ããªã
+ qos = false;
+ policy->NoQoS = true;
+ }
+ if (GetHubAdminOption(hub, "deny_qos") != 0)
+ {
+ // 管çãªãã·ã§ã³ã§ç¦æ¢ããã¦ãã
+ qos = false;
+ policy->NoQoS = true;
+ }
+ }
+
+ if (GetHubAdminOption(hub, "max_bitrates_download") != 0)
+ {
+ if (policy->MaxDownload == 0)
+ {
+ policy->MaxDownload = GetHubAdminOption(hub, "max_bitrates_download");
+ }
+ else
+ {
+ policy->MaxDownload = MIN(policy->MaxDownload, GetHubAdminOption(hub, "max_bitrates_download"));
+ }
+ }
+
+ if (GetHubAdminOption(hub, "max_bitrates_upload") != 0)
+ {
+ if (policy->MaxUpload == 0)
+ {
+ policy->MaxUpload = GetHubAdminOption(hub, "max_bitrates_upload");
+ }
+ else
+ {
+ policy->MaxUpload = MIN(policy->MaxUpload, GetHubAdminOption(hub, "max_bitrates_upload"));
+ }
+ }
+
+ if (GetHubAdminOption(hub, "deny_bridge") != 0)
+ {
+ policy->NoBridge = true;
+ }
+
+ if (GetHubAdminOption(hub, "deny_routing") != 0)
+ {
+ policy->NoRouting = true;
+ }
+
+ if (hub->Option->ClientMinimumRequiredBuild > c->ClientBuild &&
+ InStrEx(c->ClientStr, "client", false))
+ {
+ // ã¯ã©ã¤ã¢ã³ãã®ãã«ãçªå·ãå°ãããã
+ HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, hub->Option->ClientMinimumRequiredBuild);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_VERSION_INVALID;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ if (hub->Option->RequiredClientId != 0 &&
+ hub->Option->RequiredClientId != client_id &&
+ InStrEx(c->ClientStr, "client", false))
+ {
+ // ã¯ã©ã¤ã¢ã³ãã®ãã«ãçªå·ãå°ãããã
+ HLog(hub, "LH_CLIENT_ID_REQUIRED", c->Name, client_id, hub->Option->RequiredClientId);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_CLIENT_ID_REQUIRED;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ if ((policy->NoSavePassword) || (policy->AutoDisconnect != 0))
+ {
+ if (c->ClientBuild < 6560 && InStrEx(c->ClientStr, "client", false))
+ {
+ // NoSavePassword ããªã·ã¼ãæå®ããã¦ããå ´åã¯å¯¾å¿ã¯ã©ã¤ã¢ã³ã
+ // ã§ãªããã°æ¥ç¶ã§ããªã
+ HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, 6560);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_VERSION_INVALID;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (user_expires != 0 && user_expires <= SystemTime64())
+ {
+ // æå¹æéãåãã¦ãã
+ // ã¢ã¯ã»ã¹ãæå¦ããã¦ãã
+ HLog(hub, "LH_USER_EXPIRES", c->Name, username);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_ACCESS_DENIED;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ if (policy->Access == false)
+ {
+ // ã¢ã¯ã»ã¹ãæå¦ããã¦ãã
+ HLog(hub, "LH_POLICY_ACCESS_NG", c->Name, username);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_ACCESS_DENIED;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ // ããªã·ã¼ã®å
容ãã¯ã©ã¤ã¢ã³ããè¦æ±ãããªãã·ã§ã³ã¨æ¯è¼ãã¦
+ // 決å®ãããæ¥ç¶ãæå¦ãã
+ // æåã«ã¢ãã¿ãã¼ãã¢ã¼ãã§æ¥ç¶ã§ãããã©ãã確èªãã
+ if (require_monitor_mode && policy->MonitorPort == false)
+ {
+ // ã¢ãã¿ãã¼ãã¢ã¼ãã§æ¥ç¶ã§ããªã
+ HLog(hub, "LH_POLICY_MONITOR_MODE", c->Name);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_MONITOR_MODE_DENIED;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ if (policy->MonitorPort)
+ {
+ if (require_monitor_mode == false)
+ {
+ policy->MonitorPort = false;
+ }
+ }
+
+ if (policy->MonitorPort)
+ {
+ qos = false;
+ }
+
+ // 次ã«ããªã㸠/ ã«ã¼ãã£ã³ã°ã¢ã¼ãã§æ¥ç¶ã§ããã確èªãã
+ if (require_bridge_routing_mode &&
+ (policy->NoBridge && policy->NoRouting))
+ {
+ // ããªã㸠/ ã«ã¼ãã£ã³ã°ã¢ã¼ãã§æ¥ç¶ã§ããªã
+ HLog(hub, "LH_POLICY_BRIDGE_MODE", c->Name);
+
+ Unlock(hub->lock);
+ ReleaseHub(hub);
+ c->Err = ERR_BRIDGE_MODE_DENIED;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ if (require_bridge_routing_mode == false)
+ {
+ policy->NoBridge = true;
+ policy->NoRouting = true;
+ }
+
+ // ã©ã¤ã»ã³ã¹ãå¿
è¦ãã©ãããã§ãã¯
+ GenerateMachineUniqueHash(unique2);
+
+ if (Cmp(unique, unique2, SHA1_SIZE) == 0)
+ {
+ // ãã¼ã«ã«ãã¹ãã»ãã·ã§ã³ã§ãã
+ local_host_session = true;
+ }
+ else
+ {
+ if (license.NumUserLicense != INFINITE)
+ {
+ // ã¦ã¼ã¶ã¼ä½ææ°ãå¶éããã¦ããã¨ãã£ã·ã§ã³ã§ã¯å¤éãã°ã¤ã³ç¦æ¢
+ policy->MultiLogins = 1;
+ }
+
+ if (policy->NoBridge == false || policy->NoRouting == false)
+ {
+ // ããªãã¸ã©ã¤ã»ã³ã¹ãæ¶è²»
+ use_bridge_license = true;
+ }
+ else
+ {
+ // ã¯ã©ã¤ã¢ã³ãã©ã¤ã»ã³ã¹ãæ¶è²»
+ use_client_license = true;
+ }
+ }
+
+ if (server != NULL && server->ServerType != SERVER_TYPE_FARM_MEMBER &&
+ (use_bridge_license || use_client_license))
+ {
+ // ã¯ã©ã¹ã¿ã³ã³ããã¼ã©ã¾ãã¯ã¹ã¿ã³ãã¢ãã³ãµã¼ãã¼ã®å ´åã§
+ // ã¯ã©ã¤ã¢ã³ãã«ã©ã¤ã»ã³ã¹ãå¿
è¦ã«ãªã£ãå ´åãããã§ã©ã¤ã»ã³ã¹æ°ã
+ // 足ãã¦ãããã©ãããè¨ç®ãã
+
+ if (use_client_license)
+ {
+ if (server->CurrentAssignedClientLicense >= license.NumClientLicense)
+ {
+ // ã¯ã©ã¤ã¢ã³ãæ¥ç¶ã©ã¤ã»ã³ã¹ã足ããªã
+ Unlock(hub->lock);
+
+ // 詳細ã¨ã©ã¼ãã°ãåã
+ HLog(hub, "LH_NOT_ENOUGH_CLIENT_LICENSE", c->Name,
+ license.NumClientLicense,
+ server->CurrentAssignedClientLicense + 1);
+
+ ReleaseHub(hub);
+ c->Err = ERR_CLIENT_LICENSE_NOT_ENOUGH;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+ if (use_bridge_license)
+ {
+ if (server->CurrentAssignedBridgeLicense >= license.NumBridgeLicense)
+ {
+ // ããªãã¸æ¥ç¶ã©ã¤ã»ã³ã¹æ°ã足ããªã
+ Unlock(hub->lock);
+
+ // 詳細ã¨ã©ã¼ãã°ãåã
+ HLog(hub, "LH_NOT_ENOUGH_BRIDGE_LICENSE", c->Name,
+ license.NumBridgeLicense,
+ server->CurrentAssignedBridgeLicense + 1);
+
+ ReleaseHub(hub);
+ c->Err = ERR_BRIDGE_LICENSE_NOT_ENOUGH;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+ }
+
+ if (server != NULL && server->ServerType != SERVER_TYPE_FARM_MEMBER &&
+ policy != NULL)
+ {
+ if (GetServerCapsBool(hub->Cedar->Server, "b_support_limit_multilogin"))
+ {
+ // ããªã·ã¼ã§å¤éãã°ã¤ã³å¶éæ°ãæå®ããã¦ããå ´åã¯ç¢ºèªãã
+ RPC_ENUM_SESSION t;
+ UINT i, num;
+ UINT max_logins = policy->MultiLogins;
+ UINT ao = GetHubAdminOption(hub, "max_multilogins_per_user");
+
+ if (ao != 0)
+ {
+ if (max_logins != 0)
+ {
+ max_logins = MIN(max_logins, ao);
+ }
+ else
+ {
+ max_logins = ao;
+ }
+ }
+
+ if (max_logins != 0)
+ {
+ Zero(&t, sizeof(t));
+ StrCpy(t.HubName, sizeof(t.HubName), hub->Name);
+
+ Unlock(hub->lock);
+
+ SiEnumSessionMain(server, &t);
+
+ Lock(hub->lock);
+
+ num = 0;
+
+ for (i = 0;i < t.NumSession;i++)
+ {
+ RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];
+
+ if (e->BridgeMode == false && e->Layer3Mode == false && e->LinkMode == false && e->CurrentNumTcp != 0)
+ {
+ if (StrCmpi(e->Username, username) == 0 &&
+ (IsZero(e->UniqueId, 16) || Cmp(e->UniqueId, node.UniqueId, 16) != 0))
+ {
+ num++;
+ }
+ }
+ }
+
+ FreeRpcEnumSession(&t);
+
+ if (num >= max_logins)
+ {
+ // ãã以ä¸æ¥ç¶ã§ããªã
+ Unlock(hub->lock);
+
+ // 詳細ã¨ã©ã¼ãã°ãåã
+ HLog(hub, license.NumUserLicense == INFINITE ? "LH_TOO_MANY_MULTILOGINS" : "LH_TOO_MANY_MULTILOGINS2",
+ c->Name,
+ username, max_logins, num);
+
+ ReleaseHub(hub);
+ c->Err = ERR_TOO_MANY_USER_SESSION;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+ }
+ }
+
+ if (loggedin_user_object != NULL)
+ {
+ // ã¦ã¼ã¶ã¼æ
å ±ã®æ´æ°
+ Lock(loggedin_user_object->lock);
+ {
+ loggedin_user_object->NumLogin++;
+ loggedin_user_object->LastLoginTime = SystemTime64();
+ }
+ Unlock(loggedin_user_object->lock);
+ }
+
+ // ãã°ã¤ã³åæ°ãæ´æ°ãã
+ hub->NumLogin++;
+ hub->LastCommTime = hub->LastLoginTime = SystemTime64();
+
+ if (farm_controller)
+ {
+ wchar_t *msg = GetHubMsg(hub);
+
+ Unlock(hub->lock);
+
+ Lock(cedar->CedarSuperLock);
+
+ // ãã¡ã¼ã ã³ã³ããã¼ã©ã®å ´åããã® HUB ããã¹ãã£ã³ã°ãã
+ // ãã¡ã¼ã ã¡ã³ããé¸å®ãã
+ LockList(server->FarmMemberList);
+ {
+ HLog(hub, "LH_FARM_SELECT_1", c->Name);
+ f = SiGetHubHostingMember(server, hub, admin_mode);
+
+ if (f == NULL)
+ {
+ // é¸å®ã«å¤±æãã
+ HLog(hub, "LH_FARM_SELECT_2", c->Name);
+ UnlockList(server->FarmMemberList);
+ Unlock(cedar->CedarSuperLock);
+ ReleaseHub(hub);
+ c->Err = ERR_COULD_NOT_HOST_HUB_ON_FARM;
+ Free(policy);
+ Free(msg);
+ goto CLEANUP;
+ }
+ else
+ {
+ if (f->Me == false)
+ {
+ UCHAR ticket[SHA1_SIZE];
+ PACK *p;
+ BUF *b;
+ UINT i;
+
+ SLog(c->Cedar, "LH_FARM_SELECT_4", c->Name, f->hostname);
+
+ // é¸å®ãããµã¼ãã¼ãã¡ã¼ã ã¡ã³ãã«ã»ãã·ã§ã³ãä½æãã
+ Rand(ticket, sizeof(ticket));
+ SiCallCreateTicket(server, f, hub->Name,
+ username, username_real, policy, ticket, Inc(hub->SessionCounter), groupname);
+
+ p = NewPack();
+ PackAddInt(p, "Redirect", 1);
+ PackAddIp32(p, "Ip", f->Ip);
+ for (i = 0;i < f->NumPort;i++)
+ {
+ PackAddIntEx(p, "Port", f->Ports[i], i, f->NumPort);
+ }
+ PackAddData(p, "Ticket", ticket, sizeof(ticket));
+
+ if (true)
+ {
+ char *utf = CopyUniToUtf(msg);
+
+ PackAddData(p, "Msg", utf, StrLen(utf));
+
+ Free(utf);
+ }
+
+ b = XToBuf(f->ServerCert, false);
+ PackAddBuf(p, "Cert", b);
+ FreeBuf(b);
+
+ UnlockList(server->FarmMemberList);
+ Unlock(cedar->CedarSuperLock);
+ ReleaseHub(hub);
+
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+
+ c->Err = 0;
+ Free(policy);
+
+ FreePack(HttpServerRecv(c->FirstSock));
+ Free(msg);
+ goto CLEANUP;
+ }
+ else
+ {
+ HLog(hub, "LH_FARM_SELECT_3", c->Name);
+ // èªåèªèº«ãé¸å®ãããã®ã§ãã®ã¾ã¾ç¶ãã
+ UnlockList(server->FarmMemberList);
+ Unlock(cedar->CedarSuperLock);
+ f->Point = SiGetPoint(server);
+ Lock(hub->lock);
+ Free(msg);
+ }
+ }
+ }
+ }
+
+ if (admin_mode == false)
+ {
+ // HUB ã®æ大æ¥ç¶æ°ããã§ãã¯
+ if (hub->Option->MaxSession != 0 &&
+ hub->Option->MaxSession <= Count(hub->NumSessions))
+ {
+ // ãã以ä¸æ¥ç¶ã§ããªã
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION", c->Name, hub->Option->MaxSession);
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (use_client_license || use_bridge_license)
+ {
+ // ä»®æ³ HUB 管çãªãã·ã§ã³ã§è¦å®ãããåææ¥ç¶ã»ãã·ã§ã³æ°
+ // ã®å¶éã«æµè§¦ããªããã©ãã調ã¹ã
+ if (
+ (GetHubAdminOption(hub, "max_sessions") != 0 &&
+ (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= GetHubAdminOption(hub, "max_sessions"))
+ ||
+ (hub->Option->MaxSession != 0 &&
+ (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= hub->Option->MaxSession))
+ {
+ // ãã以ä¸æ¥ç¶ã§ããªã
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION", c->Name, GetHubAdminOption(hub, "max_sessions"));
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (use_client_license)
+ {
+ // ä»®æ³ HUB 管çãªãã·ã§ã³ã§è¦å®ãããåææ¥ç¶ã»ãã·ã§ã³æ° (ã¯ã©ã¤ã¢ã³ã)
+ // ã®å¶éã«æµè§¦ããªããã©ãã調ã¹ã
+ if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0 || license.CarrierEdition) &&
+ Count(hub->NumSessionsClient) >= GetHubAdminOption(hub, "max_sessions_client") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
+ ||
+ (hub->FarmMember_MaxSessionClientBridgeApply &&
+ Count(hub->NumSessionsClient) >= hub->FarmMember_MaxSessionClient))
+ {
+ // ãã以ä¸æ¥ç¶ã§ããªã
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION_CLIENT", c->Name, GetHubAdminOption(hub, "max_sessions_client"));
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (use_bridge_license)
+ {
+ // ä»®æ³ HUB 管çãªãã·ã§ã³ã§è¦å®ãããåææ¥ç¶ã»ãã·ã§ã³æ° (ããªãã¸)
+ // ã®å¶éã«æµè§¦ããªããã©ãã調ã¹ã
+ if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0 || license.CarrierEdition) &&
+ Count(hub->NumSessionsBridge) >= GetHubAdminOption(hub, "max_sessions_bridge") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
+ ||
+ (hub->FarmMember_MaxSessionClientBridgeApply &&
+ Count(hub->NumSessionsBridge) >= hub->FarmMember_MaxSessionBridge))
+ {
+ // ãã以ä¸æ¥ç¶ã§ããªã
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION_BRIDGE", c->Name, GetHubAdminOption(hub, "max_sessions_bridge"));
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+ }
+
+ if (Count(hub->Cedar->CurrentSessions) >= GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"))
+ {
+ // ãã以ä¸æ¥ç¶ã§ããªã
+ Unlock(hub->lock);
+
+ HLog(hub, "LH_MAX_SESSION_2", c->Name, GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"));
+
+ ReleaseHub(hub);
+ c->Err = ERR_HUB_IS_BUSY;
+ Free(policy);
+ goto CLEANUP;
+ }
+
+ // ç¾å¨ã®æ¥ç¶æ°ãã¤ã³ã¯ãªã¡ã³ã
+ Inc(hub->NumSessions);
+ if (use_bridge_license)
+ {
+ Inc(hub->NumSessionsBridge);
+ }
+
+ if (use_client_license)
+ {
+ Inc(hub->NumSessionsClient);
+ }
+ Inc(hub->Cedar->CurrentSessions);
+
+ // ã¿ã¤ã ã¢ã¦ãæéãè¨ç®
+ timeout = policy->TimeOut * 1000; // ããªç§ â ç§ ã«å¤æ
+ if (timeout == 0)
+ {
+ timeout = TIMEOUT_DEFAULT;
+ }
+ timeout = MIN(timeout, TIMEOUT_MAX);
+ timeout = MAX(timeout, TIMEOUT_MIN);
+
+ // ããªã·ã¼ã«å¿ã㦠max_connection ãæ´æ°
+ max_connection = MIN(max_connection, policy->MaxConnection);
+ max_connection = MIN(max_connection, MAX_TCP_CONNECTION);
+ max_connection = MAX(max_connection, 1);
+ if (half_connection)
+ {
+ // Half Connection æã«ã¯ã³ãã¯ã·ã§ã³æ°ã¯ 2 以ä¸ã¨ãã
+ max_connection = MAX(max_connection, 2);
+ }
+
+ if (qos)
+ {
+ // VoIP / QoS 使ç¨æã«ã¯ã³ãã¯ã·ã§ã³æ°ã¯ 2 以ä¸ã¨ãã
+ max_connection = MAX(max_connection, 2);
+ if (half_connection)
+ {
+ max_connection = MAX(max_connection, 4);
+ }
+ }
+
+ c->Status = CONNECTION_STATUS_ESTABLISHED;
+
+ // ã³ãã¯ã·ã§ã³ã Cedar ããåé¤
+ DelConnection(c->Cedar, c);
+
+ // ã»ãã·ã§ã³ã®ä½æ
+ StrLower(username);
+ s = NewServerSession(c->Cedar, c, hub, username, policy);
+
+ if (server != NULL)
+ {
+ s->NoSendSignature = server->NoSendSignature;
+ }
+
+ s->UseClientLicense = use_client_license;
+ s->UseBridgeLicense = use_bridge_license;
+
+ s->IsBridgeMode = (policy->NoBridge == false) || (policy->NoRouting == false);
+ s->IsMonitorMode = policy->MonitorPort;
+
+ // IPv6 ã»ãã·ã§ã³ãã©ããã®å¤å®
+ s->IPv6Session = false;
+
+ if (node.ClientIpAddress == 0)
+ {
+ s->IPv6Session = true;
+ }
+
+ if (use_bridge_license)
+ {
+ Inc(s->Cedar->AssignedBridgeLicense);
+ }
+
+ if (use_client_license)
+ {
+ Inc(s->Cedar->AssignedClientLicense);
+ }
+
+ if (server != NULL)
+ {
+ // Server æ§é ä½ã®åè¨å²ãå½ã¦æ¸ã¿ã©ã¤ã»ã³ã¹æ°ã®æ´æ°
+ if (server->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ // ã¹ã¿ã³ãã¢ãã³ã¢ã¼ãã®ã¿æ´æ°
+ // (ã¯ã©ã¹ã¿ã³ã³ããã¼ã©ã¢ã¼ãã§ã¯å®æçã«ãã¼ãªã³ã°ãã¦ãã)
+ server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
+ server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
+ }
+ }
+
+ if (StrLen(sessionname) != 0)
+ {
+ // ã»ãã·ã§ã³åã®æå®
+ Free(s->Name);
+ s->Name = CopyStr(sessionname);
+ }
+
+ {
+ char ip[128];
+ IPToStr(ip, sizeof(ip), &c->FirstSock->RemoteIP);
+ HLog(hub, "LH_NEW_SESSION", c->Name, s->Name, ip, c->FirstSock->RemotePort);
+ }
+
+ c->Session = s;
+ s->AdministratorMode = admin_mode;
+ StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username_real);
+ StrCpy(s->GroupName, sizeof(s->GroupName), groupname);
+
+ // ã»ãã·ã§ã³ãã¼ã®åå¾
+ Copy(session_key, s->SessionKey, SHA1_SIZE);
+
+ // ãã©ã¡ã¼ã¿ãã»ãã
+ s->MaxConnection = max_connection;
+ s->UseEncrypt = use_encrypt;
+ if (s->UseEncrypt && use_fast_rc4)
+ {
+ s->UseFastRC4 = use_fast_rc4;
+ }
+ s->UseCompress = use_compress;
+ s->HalfConnection = half_connection;
+ s->Timeout = timeout;
+ s->QoS = qos;
+
+ if (policy != NULL)
+ {
+ s->VLanId = policy->VLanId;
+ }
+
+ // ã¦ã¼ã¶ã¼å
+ s->Username = CopyStr(username);
+
+ HLog(hub, "LH_SET_SESSION", s->Name, s->MaxConnection,
+ s->UseEncrypt ? _UU("L_YES") : _UU("L_NO"),
+ s->UseCompress ? _UU("L_YES") : _UU("L_NO"),
+ s->HalfConnection ? _UU("L_YES") : _UU("L_NO"),
+ s->Timeout / 1000);
+
+ msg = GetHubMsg(hub);
+ }
+ Unlock(hub->lock);
+
+ // ã¯ã©ã¤ã¢ã³ãã« Welcome ãã±ãããéä¿¡
+ p = PackWelcome(s);
+
+ if (true)
+ {
+ // VPN Client ã«è¡¨ç¤ºããã¡ãã»ã¼ã¸
+ char *utf;
+ wchar_t winver_msg_client[3800];
+ wchar_t winver_msg_server[3800];
+ wchar_t *utvpn_msg;
+ UINT tmpsize;
+ wchar_t *tmp;
+ RPC_WINVER server_winver;
+
+ GetWinVer(&server_winver);
+
+ Zero(winver_msg_client, sizeof(winver_msg_client));
+ Zero(winver_msg_server, sizeof(winver_msg_server));
+
+ utvpn_msg = _UU("UTVPN_MSG");
+
+ if (IsSupportedWinVer(&winver) == false)
+ {
+ SYSTEMTIME st;
+
+ LocalTime(&st);
+
+ UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),
+ _UU("WINVER_ERROR_PC_LOCAL"),
+ winver.Title,
+ _UU("WINVER_ERROR_VPNSERVER"),
+ SUPPORTED_WINDOWS_LIST,
+ _UU("WINVER_ERROR_PC_LOCAL"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ st.wYear, st.wMonth);
+ }
+
+ if (IsSupportedWinVer(&server_winver) == false)
+ {
+ SYSTEMTIME st;
+
+ LocalTime(&st);
+
+ UniFormat(winver_msg_server, sizeof(winver_msg_server), _UU("WINVER_ERROR_FORMAT"),
+ _UU("WINVER_ERROR_PC_REMOTE"),
+ server_winver.Title,
+ _UU("WINVER_ERROR_VPNSERVER"),
+ SUPPORTED_WINDOWS_LIST,
+ _UU("WINVER_ERROR_PC_REMOTE"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ _UU("WINVER_ERROR_VPNSERVER"),
+ st.wYear, st.wMonth);
+ }
+
+ tmpsize = UniStrSize(winver_msg_client) + UniStrSize(winver_msg_server) + UniStrSize(utvpn_msg) + UniStrSize(msg) * 100;
+
+ tmp = ZeroMalloc(tmpsize);
+
+ if (IsURLMsg(msg, NULL, 0) == false)
+ {
+ UniStrCat(tmp, tmpsize, utvpn_msg);
+ UniStrCat(tmp, tmpsize, winver_msg_client);
+ UniStrCat(tmp, tmpsize, winver_msg_server);
+ }
+ UniStrCat(tmp, tmpsize, msg);
+
+ utf = CopyUniToUtf(tmp);
+
+ PackAddData(p, "Msg", utf, StrLen(utf));
+
+ Free(tmp);
+ Free(utf);
+ }
+
+ Free(msg);
+
+ if (s->UseFastRC4)
+ {
+ // RC4 ãã¼ãã¢ãçæ
+ GenerateRC4KeyPair(&key_pair);
+
+ // Welcome ãã±ããã«è¿½å
+ PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
+ PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
+ {
+ char key1[64], key2[64];
+ BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
+ BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
+ Debug(
+ "Client to Server Key: %s\n"
+ "Server to Client Key: %s\n",
+ key1, key2);
+ }
+ }
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+
+ Copy(&c->Session->NodeInfo, &node, sizeof(NODE_INFO));
+ {
+ wchar_t tmp[MAX_SIZE * 2];
+ NodeInfoToStr(tmp, sizeof(tmp), &s->NodeInfo);
+
+ HLog(hub, "LH_NODE_INFO", s->Name, tmp);
+ }
+
+ // ã³ãã¯ã·ã§ã³ããã³ããªã³ã°ã¢ã¼ãã«ç§»è¡
+ StartTunnelingMode(c);
+
+ // ãã¼ãã³ãã¯ã·ã§ã³ã¢ã¼ãæã®å¦ç
+ if (s->HalfConnection)
+ {
+ // 1 ã¤ç®ã®ã½ã±ããã¯ã¯ã©ã¤ã¢ã³ãâãµã¼ãã¼ æ¹å ã¨ãã
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
+ ts->Direction = TCP_CLIENT_TO_SERVER;
+ }
+
+ if (s->UseFastRC4)
+ {
+ // 1 ã¤ç®ã® TCP ã³ãã¯ã·ã§ã³ã« RC4 ãã¼æ
å ±ãã»ãããã
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
+ Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
+
+ InitTcpSockRc4Key(ts, true);
+ }
+
+ if (s->UseEncrypt && s->UseFastRC4 == false)
+ {
+ s->UseSSLDataEncryption = true;
+ }
+ else
+ {
+ s->UseSSLDataEncryption = false;
+ }
+
+ if (s->Hub->Type == HUB_TYPE_FARM_DYNAMIC && s->Cedar->Server != NULL && s->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
+ {
+ if (s->Hub->BeingOffline == false)
+ {
+ // ãã¤ãããã¯ä»®æ³ HUB 㧠SecureNAT ãéå§
+ EnableSecureNATEx(s->Hub, false, true);
+
+ cluster_dynamic_secure_nat = true;
+ }
+ }
+
+ // ã»ãã·ã§ã³ã®ã¡ã¤ã³ã«ã¼ãã³
+ SessionMain(s);
+
+ // ç¾å¨ã®æ¥ç¶æ°ããã¯ãªã¡ã³ã
+ Lock(s->Hub->lock);
+ {
+ if (use_bridge_license)
+ {
+ Dec(hub->NumSessionsBridge);
+ }
+
+ if (use_client_license)
+ {
+ Dec(hub->NumSessionsClient);
+ }
+
+ Dec(s->Hub->NumSessions);
+ Dec(s->Hub->Cedar->CurrentSessions);
+
+ // ã©ã¤ã»ã³ã¹æ°ã®ãã¯ãªã¡ã³ã
+ if (use_bridge_license)
+ {
+ Dec(s->Cedar->AssignedBridgeLicense);
+ }
+
+ if (use_client_license)
+ {
+ Dec(s->Cedar->AssignedClientLicense);
+ }
+
+ if (server != NULL)
+ {
+ // Server æ§é ä½ã®åè¨å²ãå½ã¦æ¸ã¿ã©ã¤ã»ã³ã¹æ°ã®æ´æ°
+ if (server->ServerType == SERVER_TYPE_STANDALONE)
+ {
+ // ã¹ã¿ã³ãã¢ãã³ã¢ã¼ãã®ã¿æ´æ°
+ // (ã¯ã©ã¹ã¿ã³ã³ããã¼ã©ã¢ã¼ãã§ã¯å®æçã«ãã¼ãªã³ã°ãã¦ãã)
+ server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
+ server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
+ }
+ }
+ }
+ Unlock(s->Hub->lock);
+
+ PrintSessionTotalDataSize(s);
+
+ HLog(s->Hub, "LH_END_SESSION", s->Name, s->TotalSendSizeReal, s->TotalRecvSizeReal);
+
+ if (cluster_dynamic_secure_nat && s->Hub->BeingOffline == false)
+ {
+ // ãã¤ãããã¯ä»®æ³ HUB 㧠SecureNAT ãåæ¢
+ EnableSecureNATEx(s->Hub, false, true);
+ }
+
+ ReleaseSession(s);
+
+ ret = true;
+ c->Err = ERR_SESSION_REMOVED;
+
+ ReleaseHub(hub);
+
+ goto CLEANUP;
+ }
+ else if (StrCmpi(method, "additional_connect") == 0)
+ {
+ SOCK *sock;
+ TCPSOCK *ts;
+ UINT dummy;
+
+ c->Type = CONNECTION_TYPE_ADDITIONAL;
+
+ // 追å æ¥ç¶
+ // ã»ãã·ã§ã³ãã¼ãèªã¿åºã
+ if (GetSessionKeyFromPack(p, session_key, &dummy) == false)
+ {
+ FreePack(p);
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+ FreePack(p);
+
+ // ã»ãã·ã§ã³ãã¼ããã»ãã·ã§ã³ãåå¾
+ s = GetSessionFromKey(c->Cedar, session_key);
+ if (s == NULL || s->Halt)
+ {
+ // ã»ãã·ã§ã³ãçºè¦ã§ããªã
+ Debug("Session Not Found.\n");
+ c->Err = ERR_SESSION_TIMEOUT;
+ goto CLEANUP;
+ }
+
+ // ã»ãã·ã§ã³ãè¦ã¤ãã£ã
+ Debug("Session Found: %s\n", s->Name);
+ // ã»ãã·ã§ã³ã®ãããã³ã«ã確èª
+ c->Err = 0;
+ Lock(s->lock);
+ {
+ if (s->Connection->Protocol != CONNECTION_TCP)
+ {
+ c->Err = ERR_INVALID_PROTOCOL;
+ }
+ }
+ Unlock(s->lock);
+ // ã»ãã·ã§ã³ã®ç¾å¨ã®ã³ãã¯ã·ã§ã³æ°ã調ã¹ã
+ Lock(s->Connection->lock);
+ if (c->Err == 0)
+ {
+ if (Count(s->Connection->CurrentNumConnection) > s->MaxConnection)
+ {
+ c->Err = ERR_TOO_MANY_CONNECTION;
+ }
+ }
+ if (c->Err != 0)
+ {
+ Unlock(s->Connection->lock);
+ if (c->Err == ERR_TOO_MANY_CONNECTION)
+ {
+ Debug("Session TOO MANY CONNECTIONS !!: %u\n",
+ Count(s->Connection->CurrentNumConnection));
+ }
+ else
+ {
+ Debug("Session Invalid Protocol.\n");
+ }
+ ReleaseSession(s);
+ goto CLEANUP;
+ }
+
+ // RC4 é«éæå·åéµã®çæ
+ if (s->UseFastRC4)
+ {
+ GenerateRC4KeyPair(&key_pair);
+ }
+
+ // ã»ãã·ã§ã³ã®ã³ãã¯ã·ã§ã³ãªã¹ã (TCP) ã«ãã®ã³ãã¯ã·ã§ã³ã®ã½ã±ããã追å ãã
+ sock = c->FirstSock;
+ ts = NewTcpSock(sock);
+ SetTimeout(sock, CONNECTING_TIMEOUT);
+ direction = TCP_BOTH;
+ LockList(s->Connection->Tcp->TcpSockList);
+ {
+ if (s->HalfConnection)
+ {
+ // ãã¼ãã³ãã¯ã·ã§ã³æãç¾å¨ã®ãã¹ã¦ã® TCP ã³ãã¯ã·ã§ã³ã®æ¹åã
+ // 調ã¹ã¦èªåçã«èª¿æ´ãã
+ UINT i, c2s, s2c;
+ c2s = s2c = 0;
+ for (i = 0;i < LIST_NUM(s->Connection->Tcp->TcpSockList);i++)
+ {
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(s->Connection->Tcp->TcpSockList, i);
+ if (ts->Direction == TCP_SERVER_TO_CLIENT)
+ {
+ s2c++;
+ }
+ else
+ {
+ c2s++;
+ }
+ }
+ if (s2c > c2s)
+ {
+ direction = TCP_CLIENT_TO_SERVER;
+ }
+ else
+ {
+ direction = TCP_SERVER_TO_CLIENT;
+ }
+ Debug("%u/%u\n", s2c, c2s);
+ ts->Direction = direction;
+ }
+ }
+ UnlockList(s->Connection->Tcp->TcpSockList);
+
+ if (s->UseFastRC4)
+ {
+ // RC4 éµæ
å ±ã®è¨å®
+ Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
+
+ InitTcpSockRc4Key(ts, true);
+ }
+
+ // æåçµæãè¿ã
+ p = PackError(ERR_NO_ERROR);
+ PackAddInt(p, "direction", direction);
+
+ if (s->UseFastRC4)
+ {
+ // RC4 éµæ
å ±ã®è¿½å
+ PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
+ PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
+ {
+ char key1[64], key2[64];
+ BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
+ BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
+ Debug(
+ "Client to Server Key: %s\n"
+ "Server to Client Key: %s\n",
+ key1, key2);
+ }
+ }
+
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+
+ SetTimeout(sock, INFINITE);
+
+ LockList(s->Connection->Tcp->TcpSockList);
+ {
+ Add(s->Connection->Tcp->TcpSockList, ts);
+ }
+ UnlockList(s->Connection->Tcp->TcpSockList);
+
+ // ã³ãã¯ã·ã§ã³æ°ãã¤ã³ã¯ãªã¡ã³ããã
+ Inc(s->Connection->CurrentNumConnection);
+ Debug("TCP Connection Incremented: %u\n", Count(s->Connection->CurrentNumConnection));
+
+ // ã»ãã·ã§ã³ã® Cancel ãçºè¡ãã
+ Cancel(s->Cancel1);
+
+ Unlock(s->Connection->lock);
+
+ c->flag1 = true;
+
+ ReleaseSession(s);
+
+ return true;
+ }
+ else if (StrCmpi(method, "enum_hub") == 0)
+ {
+ // ä»®æ³ HUB ã®åæ
+ UINT i, num;
+ LIST *o;
+ o = NewListFast(NULL);
+
+ c->Type = CONNECTION_TYPE_ENUM_HUB;
+
+ FreePack(p);
+ p = NewPack();
+ LockList(c->Cedar->HubList);
+ {
+ num = LIST_NUM(c->Cedar->HubList);
+ for (i = 0;i < num;i++)
+ {
+ HUB *h = LIST_DATA(c->Cedar->HubList, i);
+ if (h->Option != NULL && h->Option->NoEnum == false)
+ {
+ Insert(o, CopyStr(h->Name));
+ }
+ }
+ }
+ UnlockList(c->Cedar->HubList);
+
+ num = LIST_NUM(o);
+ for (i = 0;i < num;i++)
+ {
+ char *name = LIST_DATA(o, i);
+ PackAddStrEx(p, "HubName", name, i, num);
+ Free(name);
+ }
+ ReleaseList(o);
+ PackAddInt(p, "NumHub", num);
+
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+ FreePack(HttpServerRecv(c->FirstSock));
+ c->Err = 0;
+
+ SLog(c->Cedar, "LS_ENUM_HUB", c->Name, num);
+
+ goto CLEANUP;
+ }
+ else if (StrCmpi(method, "farm_connect") == 0)
+ {
+ // ãµã¼ãã¼ãã¡ã¼ã æ¥ç¶è¦æ±
+ CEDAR *cedar = c->Cedar;
+ c->Type = CONNECTION_TYPE_FARM_RPC;
+ c->Err = 0;
+ if (c->Cedar->Server == NULL)
+ {
+ // ãµãã¼ãããã¦ããªã
+ c->Err = ERR_NOT_FARM_CONTROLLER;
+ }
+ else
+ {
+ SERVER *s = c->Cedar->Server;
+ if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER || s->FarmControllerInited == false)
+ {
+ // ãã¡ã¼ã ã³ã³ããã¼ã©ã§ã¯ãªã
+ SLog(c->Cedar, "LS_FARM_ACCEPT_1", c->Name);
+ c->Err = ERR_NOT_FARM_CONTROLLER;
+ }
+ else
+ {
+ UCHAR check_secure_password[SHA1_SIZE];
+ UCHAR secure_password[SHA1_SIZE];
+ // ã¦ã¼ã¶ã¼èªè¨¼
+ SecurePassword(check_secure_password, s->HashedPassword, c->Random);
+ if (PackGetDataSize(p, "SecurePassword") == sizeof(secure_password))
+ {
+ PackGetData(p, "SecurePassword", secure_password);
+ }
+ else
+ {
+ Zero(secure_password, sizeof(secure_password));
+ }
+
+ if (Cmp(secure_password, check_secure_password, SHA1_SIZE) != 0)
+ {
+ // ãã¹ã¯ã¼ããéã
+ SLog(c->Cedar, "LS_FARM_ACCEPT_2", c->Name);
+ c->Err = ERR_ACCESS_DENIED;
+ }
+ else
+ {
+ // 証ææ¸ãåå¾ãã
+ BUF *b;
+ X *server_x;
+
+ SLog(c->Cedar, "LS_FARM_ACCEPT_3", c->Name);
+ b = PackGetBuf(p, "ServerCert");
+ if (b == NULL)
+ {
+ c->Err = ERR_PROTOCOL_ERROR;
+ }
+ else
+ {
+ server_x = BufToX(b, false);
+ FreeBuf(b);
+ if (server_x == NULL)
+ {
+ c->Err = ERR_PROTOCOL_ERROR;
+ }
+ else
+ {
+ UINT ip;
+ UINT point;
+ char hostname[MAX_SIZE];
+
+#ifdef OS_WIN32
+ MsSetThreadPriorityRealtime();
+#endif // OS_WIN32
+
+ SetTimeout(c->FirstSock, SERVER_CONTROL_TCP_TIMEOUT);
+
+ ip = PackGetIp32(p, "PublicIp");
+ point = PackGetInt(p, "Point");
+ if (PackGetStr(p, "HostName", hostname, sizeof(hostname)))
+ {
+ UINT num_port = PackGetIndexCount(p, "PublicPort");
+ if (num_port >= 1 && num_port <= MAX_PUBLIC_PORT_NUM)
+ {
+ UINT *ports = ZeroMalloc(sizeof(UINT) * num_port);
+ UINT i;
+
+ for (i = 0;i < num_port;i++)
+ {
+ ports[i] = PackGetIntEx(p, "PublicPort", i);
+ }
+
+ SiFarmServ(s, c->FirstSock, server_x, ip, num_port, ports, hostname, point,
+ PackGetInt(p, "Weight"), PackGetInt(p, "MaxSessions"));
+
+ Free(ports);
+ }
+ }
+
+ FreeX(server_x);
+ }
+ }
+ }
+ }
+ }
+ FreePack(p);
+ goto CLEANUP;
+ }
+ else if (StrCmpi(method, "admin") == 0 && c->Cedar->Server != NULL)
+ {
+ UINT err;
+ // 管çç¨ RPC æ¥ç¶è¦æ±
+ c->Type = CONNECTION_TYPE_ADMIN_RPC;
+ err = AdminAccept(c, p);
+ FreePack(p);
+ if (err != ERR_NO_ERROR)
+ {
+ PACK *p = PackError(err);
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+ }
+ goto CLEANUP;
+ }
+ else if (StrCmpi(method, "password") == 0)
+ {
+ UINT err;
+ // ãã¹ã¯ã¼ãå¤æ´è¦æ±
+ c->Type = CONNECTION_TYPE_PASSWORD;
+ err = ChangePasswordAccept(c, p);
+ FreePack(p);
+
+ p = PackError(err);
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+ goto CLEANUP;
+ }
+ else
+ {
+ // ä¸æãªã¡ã½ãã
+ FreePack(p);
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+CLEANUP:
+ // ã¦ã¼ã¶ã¼ãªãã¸ã§ã¯ãã®è§£æ¾
+ if (loggedin_user_object != NULL)
+ {
+ ReleaseUser(loggedin_user_object);
+ }
+
+ // ã¨ã©ã¼ãã±ããéä¿¡
+ p = PackError(c->Err);
+ PackAddBool(p, "no_save_password", no_save_password);
+ HttpServerSend(c->FirstSock, p);
+ FreePack(p);
+
+ SLog(c->Cedar, "LS_CONNECTION_ERROR", c->Name, GetUniErrorStr(c->Err), c->Err);
+
+ return ret;
+}
+// ã·ã°ããã£ã®éä¿¡ (TCP ãã±ãã) ç¨ã¹ã¬ãã
+void SendSignatureByTcpThread(THREAD *thread, void *param)
+{
+ BUF *buf;
+ SEND_SIGNATURE_PARAM *p;
+ SOCK *s;
+ // å¼æ°ãã§ãã¯
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ p = (SEND_SIGNATURE_PARAM *)param;
+
+ AddWaitThread(thread);
+ NoticeThreadInit(thread);
+
+ buf = p->Buffer;
+
+ s = Connect(p->Hostname, p->Port);
+
+ if (s != NULL)
+ {
+ SendAll(s, buf->Buf, buf->Size, false);
+
+ Disconnect(s);
+ ReleaseSock(s);
+ }
+
+ DelWaitThread(thread);
+
+ FreeBuf(buf);
+ Free(p);
+}
+
+// ã·ã°ããã£ã®éä¿¡ (TCP ãã±ãã)
+void SendSignatureByTcp(CONNECTION *c, IP *ip)
+{
+ NODE_INFO info;
+ BUF *b;
+ SEND_SIGNATURE_PARAM *param;
+ THREAD *t;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ if (c->Session == NULL || c->Session->ClientOption == NULL)
+ {
+ return;
+ }
+
+ CreateNodeInfo(&info, c);
+
+ b = NewBuf();
+ WriteBuf(b, CEDAR_SIGNATURE_STR, StrLen(CEDAR_SIGNATURE_STR));
+ SeekBuf(b, 0, 0);
+
+ param = ZeroMalloc(sizeof(SEND_SIGNATURE_PARAM));
+ param->Buffer = b;
+
+ if (c->Session != NULL && c->Session->ClientOption != NULL)
+ {
+ CLIENT_OPTION *o = c->Session->ClientOption;
+
+ if (o->ProxyType == PROXY_DIRECT)
+ {
+ IPToStr(param->Hostname, sizeof(param->Hostname), ip);
+ param->Port = o->Port;
+ }
+ else
+ {
+ StrCpy(param->Hostname, sizeof(param->Hostname), o->ProxyName);
+ param->Port = o->ProxyPort;
+ }
+ }
+
+ t = NewThread(SendSignatureByTcpThread, param);
+ WaitThreadInit(t);
+ ReleaseThread(t);
+}
+
+// ãã¼ãæ
å ±ã®ä½æ
+void CreateNodeInfo(NODE_INFO *info, CONNECTION *c)
+{
+ SESSION *s;
+ OS_INFO *os;
+ char *product_id;
+ IP ip;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return;
+ }
+
+ s = c->Session;
+ os = GetOsInfo();
+
+ Zero(info, sizeof(NODE_INFO));
+
+ // ã¯ã©ã¤ã¢ã³ã製åå
+ StrCpy(info->ClientProductName, sizeof(info->ClientProductName), c->ClientStr);
+ // ã¯ã©ã¤ã¢ã³ããã¼ã¸ã§ã³
+ info->ClientProductVer = Endian32(c->ClientVer);
+ // ã¯ã©ã¤ã¢ã³ããã«ãçªå·
+ info->ClientProductBuild = Endian32(c->ClientBuild);
+
+ // ãµã¼ãã¼è£½åå
+ StrCpy(info->ServerProductName, sizeof(info->ServerProductName), c->ServerStr);
+ // ãµã¼ãã¼ãã¼ã¸ã§ã³
+ info->ServerProductVer = Endian32(c->ServerVer);
+ // ãµã¼ãã¼ãã«ãçªå·
+ info->ServerProductBuild = Endian32(c->ServerBuild);
+
+ // ã¯ã©ã¤ã¢ã³ã OS å
+ StrCpy(info->ClientOsName, sizeof(info->ClientOsName), os->OsProductName);
+ // ã¯ã©ã¤ã¢ã³ã OS ãã¼ã¸ã§ã³
+ StrCpy(info->ClientOsVer, sizeof(info->ClientOsVer), os->OsVersion);
+ // ã¯ã©ã¤ã¢ã³ã OS ãããã¯ã ID
+ product_id = OSGetProductId();
+ StrCpy(info->ClientOsProductId, sizeof(info->ClientOsProductId), product_id);
+ Free(product_id);
+
+ // ã¯ã©ã¤ã¢ã³ããã¹ãå
+ GetMachineName(info->ClientHostname, sizeof(info->ClientHostname));
+ // ã¯ã©ã¤ã¢ã³ã IP ã¢ãã¬ã¹
+ if (IsIP6(&c->FirstSock->LocalIP) == false)
+ {
+ info->ClientIpAddress = IPToUINT(&c->FirstSock->LocalIP);
+ }
+ else
+ {
+ Copy(info->ClientIpAddress6, c->FirstSock->LocalIP.ipv6_addr, sizeof(info->ClientIpAddress6));
+ }
+ // ã¯ã©ã¤ã¢ã³ããã¼ãçªå·
+ info->ClientPort = Endian32(c->FirstSock->LocalPort);
+
+ // ãµã¼ãã¼ãã¹ãå
+ StrCpy(info->ServerHostname, sizeof(info->ServerHostname), c->ServerName);
+ // ãµã¼ãã¼ IP ã¢ãã¬ã¹
+ if (GetIP(&ip, info->ServerHostname))
+ {
+ if (IsIP6(&ip) == false)
+ {
+ info->ServerIpAddress = IPToUINT(&ip);
+ }
+ else
+ {
+ Copy(info->ServerIpAddress6, ip.ipv6_addr, sizeof(info->ServerIpAddress6));
+ }
+ }
+ // ãµã¼ãã¼ãã¼ãçªå·
+ info->ServerPort = Endian32(c->ServerPort);
+
+ if (s->ClientOption->ProxyType == PROXY_SOCKS || s->ClientOption->ProxyType == PROXY_HTTP)
+ {
+ // ãããã·ãã¹ãå
+ StrCpy(info->ProxyHostname, sizeof(info->ProxyHostname), s->ClientOption->ProxyName);
+
+ // ãããã· IP ã¢ãã¬ã¹
+ if (IsIP6(&c->FirstSock->RemoteIP) == false)
+ {
+ info->ProxyIpAddress = IPToUINT(&c->FirstSock->RemoteIP);
+ }
+ else
+ {
+ Copy(&info->ProxyIpAddress6, c->FirstSock->RemoteIP.ipv6_addr, sizeof(info->ProxyIpAddress6));
+ }
+
+ info->ProxyPort = Endian32(c->FirstSock->RemotePort);
+ }
+
+ // HUB å
+ StrCpy(info->HubName, sizeof(info->HubName), s->ClientOption->HubName);
+
+ // ã¦ãã¼ã¯ ID
+ Copy(info->UniqueId, c->Cedar->UniqueId, sizeof(info->UniqueId));
+}
+
+// ã½ã±ããã追å æ¥ç¶ãã
+SOCK *ClientAdditionalConnectToServer(CONNECTION *c)
+{
+ SOCK *s;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ // ã½ã±ããæ¥ç¶
+ s = ClientConnectGetSocket(c, true);
+ if (s == NULL)
+ {
+ // æ¥ç¶å¤±æ
+ return NULL;
+ }
+
+ // ã½ã±ããããªã¹ãã«è¿½å ãã
+ LockList(c->ConnectingSocks);
+ {
+ Add(c->ConnectingSocks, s);
+ AddRef(s->ref);
+ }
+ UnlockList(c->ConnectingSocks);
+
+ if (c->Session->Halt)
+ {
+ // åæ¢
+ Disconnect(s);
+ LockList(c->ConnectingSocks);
+ {
+ if (Delete(c->ConnectingSocks, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ // ã¿ã¤ã ã¢ã¦ã
+ SetTimeout(s, CONNECTING_TIMEOUT);
+
+ // SSL éä¿¡éå§
+ if (StartSSLEx(s, NULL, NULL, (c->DontUseTls1 ? false : true)) == false)
+ {
+ // SSL é信失æ
+ Disconnect(s);
+ LockList(c->ConnectingSocks);
+ {
+ if (Delete(c->ConnectingSocks, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ // 証ææ¸ã®ãã§ãã¯
+ if (CompareX(s->RemoteX, c->ServerX) == false)
+ {
+ // 証ææ¸ãä¸æ£
+ Disconnect(s);
+ c->Session->SessionTimeOuted = true;
+ }
+
+ return s;
+}
+
+// ã»ãã¥ã¢ããã¤ã¹å
ã®è¨¼ææ¸ã¨éµãåé¤ãã
+UINT SecureDelete(UINT device_id, char *pin, char *cert_name, char *key_name)
+{
+ SECURE *sec;
+ // å¼æ°ãã§ãã¯
+ if (pin == NULL || device_id == 0)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // ããã¤ã¹ãéã
+ sec = OpenSec(device_id);
+ if (sec == NULL)
+ {
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // ã»ãã·ã§ã³ãéã
+ if (OpenSecSession(sec, 0) == false)
+ {
+ CloseSec(sec);
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // ãã°ã¤ã³
+ if (LoginSec(sec, pin) == false)
+ {
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_PIN_LOGIN_FAILED;
+ }
+
+ // 証ææ¸åé¤
+ if (cert_name != NULL)
+ {
+ DeleteSecCert(sec, cert_name);
+ }
+
+ // ç§å¯éµåé¤
+ if (key_name != NULL)
+ {
+ DeleteSecKey(sec, key_name);
+ }
+
+ // ãã°ã¢ã¦ã
+ LogoutSec(sec);
+
+ // ã»ãã·ã§ã³ãéãã
+ CloseSecSession(sec);
+
+ // ããã¤ã¹ãéãã
+ CloseSec(sec);
+
+ return ERR_NO_ERROR;
+}
+
+// ã»ãã¥ã¢ããã¤ã¹å
ã®è¨¼ææ¸ã¨éµãåæãã
+UINT SecureEnum(UINT device_id, char *pin, TOKEN_LIST **cert_list, TOKEN_LIST **key_list)
+{
+ SECURE *sec;
+ LIST *o;
+ LIST *cert_name_list, *key_name_list;
+ // å¼æ°ãã§ãã¯
+ if (pin == NULL || device_id == 0 || cert_list == NULL || key_list == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // ããã¤ã¹ãéã
+ sec = OpenSec(device_id);
+ if (sec == NULL)
+ {
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // ã»ãã·ã§ã³ãéã
+ if (OpenSecSession(sec, 0) == false)
+ {
+ CloseSec(sec);
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // ãã°ã¤ã³
+ if (LoginSec(sec, pin) == false)
+ {
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_PIN_LOGIN_FAILED;
+ }
+
+ // ãªãã¸ã§ã¯ãã®åæ
+ if ((o = EnumSecObject(sec)) != NULL)
+ {
+ UINT i;
+
+ cert_name_list = NewList(CompareStr);
+ key_name_list = NewList(CompareStr);
+
+ for (i = 0;i < LIST_NUM(o);i++)
+ {
+ SEC_OBJ *obj = LIST_DATA(o, i);
+
+ if (obj->Type == SEC_X)
+ {
+ Add(cert_name_list, CopyStr(obj->Name));
+ }
+ else if (obj->Type == SEC_K)
+ {
+ Add(key_name_list, CopyStr(obj->Name));
+ }
+ }
+
+ Sort(cert_name_list);
+ Sort(key_name_list);
+
+ *cert_list = ListToTokenList(cert_name_list);
+ *key_list = ListToTokenList(key_name_list);
+
+ // ã¡ã¢ãªè§£æ¾
+ FreeStrList(cert_name_list);
+ FreeStrList(key_name_list);
+ FreeEnumSecObject(o);
+ }
+ else
+ {
+ *cert_list = NullToken();
+ *key_list = NullToken();
+ }
+
+ // ãã°ã¢ã¦ã
+ LogoutSec(sec);
+
+ // ã»ãã·ã§ã³ãéãã
+ CloseSecSession(sec);
+
+ // ããã¤ã¹ãéãã
+ CloseSec(sec);
+
+ return ERR_NO_ERROR;
+}
+
+// ã»ãã¥ã¢ããã¤ã¹ã«è¨¼ææ¸ã¨éµãè¨é²ãã
+UINT SecureWrite(UINT device_id, char *cert_name, X *x, char *key_name, K *k, char *pin)
+{
+ SECURE *sec;
+ bool failed;
+ // å¼æ°ãã§ãã¯
+ if (pin == NULL || device_id == 0 || cert_name == NULL || x == NULL || key_name == NULL || k == NULL)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // ããã¤ã¹ãéã
+ sec = OpenSec(device_id);
+ if (sec == NULL)
+ {
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // ã»ãã·ã§ã³ãéã
+ if (OpenSecSession(sec, 0) == false)
+ {
+ CloseSec(sec);
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // ãã°ã¤ã³
+ if (LoginSec(sec, pin) == false)
+ {
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_PIN_LOGIN_FAILED;
+ }
+
+ // ç»é²
+ failed = false;
+
+ // 証ææ¸ã®ç»é²
+ if (WriteSecCert(sec, true, cert_name, x) == false)
+ {
+ failed = true;
+ }
+
+ // ç§å¯éµã®ç»é²
+ if (WriteSecKey(sec, true, key_name, k) == false)
+ {
+ failed = true;
+ }
+
+ // ãã°ã¢ã¦ã
+ LogoutSec(sec);
+
+ // ã»ãã·ã§ã³ãéãã
+ CloseSecSession(sec);
+
+ // ããã¤ã¹ãéãã
+ CloseSec(sec);
+
+ if (failed == false)
+ {
+ // æå
+ return ERR_NO_ERROR;
+ }
+ else
+ {
+ // 失æ
+ return ERR_SECURE_CANT_WRITE;
+ }
+}
+
+// ã»ãã¥ã¢ããã¤ã¹ã«ããç½²åã試è¡ãã
+UINT SecureSign(SECURE_SIGN *sign, UINT device_id, char *pin)
+{
+ SECURE *sec;
+ X *x;
+ // å¼æ°ãã§ãã¯
+ if (sign == false || pin == NULL || device_id == 0)
+ {
+ return ERR_INTERNAL_ERROR;
+ }
+
+ // ããã¤ã¹ãéã
+ sec = OpenSec(device_id);
+ if (sec == NULL)
+ {
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // ã»ãã·ã§ã³ãéã
+ if (OpenSecSession(sec, 0) == false)
+ {
+ CloseSec(sec);
+ return ERR_SECURE_DEVICE_OPEN_FAILED;
+ }
+
+ // ãã°ã¤ã³
+ if (LoginSec(sec, pin) == false)
+ {
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_PIN_LOGIN_FAILED;
+ }
+
+ // 証ææ¸ã®èªã¿è¾¼ã¿
+ x = ReadSecCert(sec, sign->SecurePublicCertName);
+ if (x == NULL)
+ {
+ LogoutSec(sec);
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_NO_CERT;
+ }
+
+ // ç§å¯éµã«ããç½²å
+ if (SignSec(sec, sign->SecurePrivateKeyName, sign->Signature, sign->Random, SHA1_SIZE) == false)
+ {
+ // ç½²å失æ
+ FreeX(x);
+ LogoutSec(sec);
+ CloseSecSession(sec);
+ CloseSec(sec);
+ return ERR_SECURE_NO_PRIVATE_KEY;
+ }
+
+ // 証ææ¸ããããã¡ã«å¤æ
+ sign->ClientCert = x;
+
+ // ãã°ã¢ã¦ã
+ LogoutSec(sec);
+
+ // ã»ãã·ã§ã³ãéãã
+ CloseSecSession(sec);
+
+ // ããã¤ã¹ãéãã
+ CloseSec(sec);
+
+ // æå
+ return ERR_NO_ERROR;
+}
+
+// ã¯ã©ã¤ã¢ã³ãããµã¼ãã¼ã«è¿½å æ¥ç¶ãã
+bool ClientAdditionalConnect(CONNECTION *c, THREAD *t)
+{
+ SOCK *s;
+ PACK *p;
+ TCPSOCK *ts;
+ UINT err;
+ UINT direction;
+ RC4_KEY_PAIR key_pair;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ // ãµã¼ãã¼ã«ã½ã±ããæ¥ç¶
+ s = ClientAdditionalConnectToServer(c);
+ if (s == NULL)
+ {
+ // ã½ã±ããæ¥ç¶ã«å¤±æ
+ return false;
+ }
+
+ if (c->Halt)
+ {
+ goto CLEANUP;
+ }
+
+ // ã·ã°ããã£ãéä¿¡
+ Debug("Uploading Signature...\n");
+ if (ClientUploadSignature(s) == false)
+ {
+ goto CLEANUP;
+ }
+
+ if (c->Halt)
+ {
+ // åæ¢
+ goto CLEANUP;
+ }
+
+ // Hello ãã±ãããåä¿¡
+ Debug("Downloading Hello...\n");
+ if (ClientDownloadHello(c, s) == false)
+ {
+ goto CLEANUP;
+ }
+
+ if (c->Halt)
+ {
+ // åæ¢
+ goto CLEANUP;
+ }
+
+ // 追å æ¥ç¶ç¨ã®èªè¨¼ãã¼ã¿ãéä¿¡
+ if (ClientUploadAuth2(c, s) == false)
+ {
+ // åæããã
+ goto CLEANUP;
+ }
+
+ // å¿çãåä¿¡
+ p = HttpClientRecv(s);
+ if (p == NULL)
+ {
+ // åæããã
+ goto CLEANUP;
+ }
+
+ err = GetErrorFromPack(p);
+ direction = PackGetInt(p, "direction");
+
+ if (c->Session->UseFastRC4)
+ {
+ // RC4 éµæ
å ±ã®åå¾
+ if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
+ {
+ PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
+ }
+ if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
+ {
+ PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
+ }
+ {
+ char key1[64], key2[64];
+ BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
+ BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
+ Debug(
+ "Client to Server Key: %s\n"
+ "Server to Client Key: %s\n",
+ key1, key2);
+ }
+ }
+
+ FreePack(p);
+ p = NULL;
+
+ if (err != 0)
+ {
+ // ã¨ã©ã¼ãçºçãã
+ Debug("Additional Connect Error: %u\n", err);
+ if (err == ERR_SESSION_TIMEOUT || err == ERR_INVALID_PROTOCOL)
+ {
+ // è´å½çãªã¨ã©ã¼ãªã®ã§åæ¥ç¶ããªãããã¨ã«ãã
+ c->Session->SessionTimeOuted = true;
+ }
+ goto CLEANUP;
+ }
+
+ Debug("Additional Connect Succeed!\n");
+
+ // 追å æ¥ç¶æå
+ // ã³ãã¯ã·ã§ã³ã® TcpSockList ã«è¿½å ãã
+ ts = NewTcpSock(s);
+
+ if (c->ServerMode == false)
+ {
+ if (c->Session->ClientOption->ConnectionDisconnectSpan != 0)
+ {
+ ts->DisconnectTick = Tick64() + c->Session->ClientOption->ConnectionDisconnectSpan * (UINT64)1000;
+ }
+ }
+
+ LockList(c->Tcp->TcpSockList);
+ {
+ ts->Direction = direction;
+ Add(c->Tcp->TcpSockList, ts);
+ }
+ UnlockList(c->Tcp->TcpSockList);
+ Debug("TCP Connection Incremented: %u\n", Count(c->CurrentNumConnection));
+
+ if (c->Session->HalfConnection)
+ {
+ Debug("New Half Connection: %s\n",
+ direction == TCP_SERVER_TO_CLIENT ? "TCP_SERVER_TO_CLIENT" : "TCP_CLIENT_TO_SERVER"
+ );
+ }
+
+ if (c->Session->UseFastRC4)
+ {
+ // RC4 æå·åéµã®ã»ãã
+ Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
+
+ InitTcpSockRc4Key(ts, false);
+ }
+
+ // ã»ãã·ã§ã³ã« Cancel ãçºè¡ãã
+ Cancel(c->Session->Cancel1);
+
+ // æ¥ç¶ä¸ã®ã½ã±ããä¸è¦§ãããã®ã½ã±ãããåé¤
+ LockList(c->ConnectingSocks);
+ {
+ if (Delete(c->ConnectingSocks, s))
+ {
+ ReleaseSock(s);
+ }
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseSock(s);
+ return true;
+
+CLEANUP:
+ // åæå¦ç
+ Disconnect(s);
+ LockList(c->ConnectingSocks);
+ {
+ if (Delete(c->ConnectingSocks, s))
+ {
+ ReleaseSock(s);
+
+ }
+ }
+ UnlockList(c->ConnectingSocks);
+ ReleaseSock(s);
+ return false;
+}
+
+// ã»ãã¥ã¢ããã¤ã¹ç½²åã¹ã¬ãã
+void ClientSecureSignThread(THREAD *thread, void *param)
+{
+ SECURE_SIGN_THREAD_PROC *p = (SECURE_SIGN_THREAD_PROC *)param;
+ // å¼æ°ãã§ãã¯
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ NoticeThreadInit(thread);
+
+ p->Ok = p->SecureSignProc(p->Connection->Session, p->Connection, p->SecureSign);
+ p->UserFinished = true;
+}
+
+// ã»ãã¥ã¢ããã¤ã¹ã使ç¨ããç½²å
+bool ClientSecureSign(CONNECTION *c, UCHAR *sign, UCHAR *random, X **x)
+{
+ SECURE_SIGN_THREAD_PROC *p;
+ SECURE_SIGN *ss;
+ SESSION *s;
+ CLIENT_OPTION *o;
+ CLIENT_AUTH *a;
+ THREAD *thread;
+ UINT64 start;
+ bool ret;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL || sign == NULL || random == NULL || x == NULL)
+ {
+ return false;
+ }
+
+ s = c->Session;
+ o = s->ClientOption;
+ a = s->ClientAuth;
+
+ p = ZeroMalloc(sizeof(SECURE_SIGN_THREAD_PROC));
+ p->Connection = c;
+ ss = p->SecureSign = ZeroMallocEx(sizeof(SECURE_SIGN), true);
+ StrCpy(ss->SecurePrivateKeyName, sizeof(ss->SecurePrivateKeyName),
+ a->SecurePrivateKeyName);
+ StrCpy(ss->SecurePublicCertName, sizeof(ss->SecurePublicCertName),
+ a->SecurePublicCertName);
+ ss->UseSecureDeviceId = c->Cedar->Client->UseSecureDeviceId;
+ Copy(ss->Random, random, SHA1_SIZE);
+
+#ifdef OS_WIN32
+ ss->BitmapId = CmGetSecureBitmapId(c->ServerName);
+#endif // OS_WIN32
+
+ p->SecureSignProc = a->SecureSignProc;
+
+ // ã¹ã¬ããä½æ
+ thread = NewThread(ClientSecureSignThread, p);
+ WaitThreadInit(thread);
+
+ // ç½²åãå®äºããããã£ã³ã»ã«ããã¾ã§ 0.5 ç§ãã¨ã«ãã¼ãªã³ã°ãã
+ start = Tick64();
+ while (true)
+ {
+ if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
+ {
+ // åæé²æ¢ã®ããä¸å®æéãã¨ã« NOOP ãéä¿¡ãã
+ start = Tick64();
+ ClientUploadNoop(c);
+ }
+ if (p->UserFinished)
+ {
+ // ã¦ã¼ã¶ã¼ãé¸æãã
+ break;
+ }
+ WaitThread(thread, 500);
+ }
+ ReleaseThread(thread);
+
+ ret = p->Ok;
+
+ if (ret)
+ {
+ Copy(sign, ss->Signature, 128);
+ *x = ss->ClientCert;
+ }
+
+ Free(p->SecureSign);
+ Free(p);
+
+ return ret;
+}
+
+// ãµã¼ãã¼è¨¼ææ¸ç¢ºèªç¨ã¹ã¬ãã
+void ClientCheckServerCertThread(THREAD *thread, void *param)
+{
+ CHECK_CERT_THREAD_PROC *p = (CHECK_CERT_THREAD_PROC *)param;
+ // å¼æ°ãã§ãã¯
+ if (thread == NULL || param == NULL)
+ {
+ return;
+ }
+
+ // åæåå®äºãéç¥ãã
+ NoticeThreadInit(thread);
+
+ // ã¦ã¼ã¶ã¼ã«é¸æãåãåããã
+ p->Ok = p->CheckCertProc(p->Connection->Session, p->Connection, p->ServerX, &p->Exipred);
+ p->UserSelected = true;
+}
+
+// ã¯ã©ã¤ã¢ã³ãããµã¼ãã¼ã®è¨¼ææ¸ã確èªãã
+bool ClientCheckServerCert(CONNECTION *c, bool *expired)
+{
+ CLIENT_AUTH *auth;
+ X *x;
+ CHECK_CERT_THREAD_PROC *p;
+ THREAD *thread;
+ CEDAR *cedar;
+ bool ret;
+ UINT64 start;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ if (expired != NULL)
+ {
+ *expired = false;
+ }
+
+ auth = c->Session->ClientAuth;
+ cedar = c->Cedar;
+
+ if (auth->CheckCertProc == NULL && c->Session->LinkModeClient == false)
+ {
+ // ãã§ãã¯é¢æ°ç¡ã
+ return true;
+ }
+
+ if (c->Session->LinkModeClient && c->Session->Link->CheckServerCert == false)
+ {
+ // ã«ã¹ã±ã¼ãæ¥ç¶ã¢ã¼ãã ããµã¼ãã¼è¨¼ææ¸ã¯ãã§ãã¯ããªã
+ return true;
+ }
+
+ if (c->UseTicket)
+ {
+ // ãªãã¤ã¬ã¯ãå
VPN ãµã¼ãã¼ã®è¨¼ææ¸ã確èªãã
+ if (CompareX(c->FirstSock->RemoteX, c->ServerX) == false)
+ {
+ return false;
+ }
+ else
+ {
+ return true;
+ }
+ }
+
+ x = CloneX(c->FirstSock->RemoteX);
+ if (x == NULL)
+ {
+ // å¤ãªã¨ã©ã¼ãçºçãã
+ return false;
+ }
+
+ if (CheckXDateNow(x))
+ {
+ // ä¿¡é ¼ããã«ã¼ã証ææ¸ã«ãã£ã¦ç½²åããã¦ãããã©ãã確èªãã
+ if (c->Session->LinkModeClient == false)
+ {
+ // é常㮠VPN Client ã¢ã¼ã
+ if (CheckSignatureByCa(cedar, x))
+ {
+ // ç½²åããã¦ããã®ã§ãã®è¨¼ææ¸ã¯ä¿¡é ¼ã§ãã
+ FreeX(x);
+ return true;
+ }
+ }
+ else
+ {
+ // ã«ã¹ã±ã¼ãæ¥ç¶ã¢ã¼ã
+ if (CheckSignatureByCaLinkMode(c->Session, x))
+ {
+ // ç½²åããã¦ããã®ã§ãã®è¨¼ææ¸ã¯ä¿¡é ¼ã§ãã
+ FreeX(x);
+ return true;
+ }
+ }
+ }
+
+ if (c->Session->LinkModeClient)
+ {
+ if (CheckXDateNow(x))
+ {
+ Lock(c->Session->Link->lock);
+ {
+ if (c->Session->Link->ServerCert != NULL)
+ {
+ if (CompareX(c->Session->Link->ServerCert, x))
+ {
+ Unlock(c->Session->Link->lock);
+ // ã«ã¹ã±ã¼ãæ¥ç¶è¨å®ã«ç»é²ããã¦ãã証ææ¸ã¨å®å
¨ä¸è´
+ FreeX(x);
+ return true;
+ }
+ }
+ }
+ Unlock(c->Session->Link->lock);
+ }
+ else
+ {
+ if (expired != NULL)
+ {
+ *expired = true;
+ }
+ }
+
+ // ã«ã¹ã±ã¼ãæ¥ç¶ã¢ã¼ãã®å ´åã¯ãã®æç¹ã§æ¤è¨¼å¤±æ
+ FreeX(x);
+ return false;
+ }
+
+ p = ZeroMalloc(sizeof(CHECK_CERT_THREAD_PROC));
+ p->ServerX = x;
+ p->CheckCertProc = auth->CheckCertProc;
+ p->Connection = c;
+
+ // ã¹ã¬ãããä½æãã
+ thread = NewThread(ClientCheckServerCertThread, p);
+ WaitThreadInit(thread);
+
+ // ã¦ã¼ã¶ã¼ãæ¥ç¶ã®å¯å¦ãé¸æããã¾ã§ 0.5 ç§ééã§ãã¼ãªã³ã°ãã
+ start = Tick64();
+ while (true)
+ {
+ if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
+ {
+ // åæé²æ¢ã®ããä¸å®æéãã¨ã« NOOP ãéä¿¡ãã
+ start = Tick64();
+ ClientUploadNoop(c);
+ }
+ if (p->UserSelected)
+ {
+ // ã¦ã¼ã¶ã¼ãé¸æãã
+ break;
+ }
+ WaitThread(thread, 500);
+ }
+
+ if (expired != NULL)
+ {
+ *expired = p->Exipred;
+ }
+
+ ret = p->Ok;
+ FreeX(p->ServerX);
+ Free(p);
+ ReleaseThread(thread);
+
+ return ret;
+}
+
+// ã¯ã©ã¤ã¢ã³ãããµã¼ãã¼ã«æ¥ç¶ãã
+bool ClientConnect(CONNECTION *c)
+{
+ bool ret = false;
+ bool ok = false;
+ UINT err;
+ SOCK *s;
+ PACK *p = NULL;
+ UINT session_key_32;
+ SESSION *sess;
+ char session_name[MAX_SESSION_NAME_LEN + 1];
+ char connection_name[MAX_CONNECTION_NAME_LEN + 1];
+ UCHAR session_key[SHA1_SIZE];
+ RC4_KEY_PAIR key_pair;
+ POLICY *policy;
+ bool expired = false;
+ IP server_ip;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ sess = c->Session;
+
+ PrintStatus(sess, L"init");
+ PrintStatus(sess, _UU("STATUS_1"));
+
+REDIRECTED:
+
+ // [æ¥ç¶ä¸]
+ c->Status = CONNECTION_STATUS_CONNECTING;
+ c->Session->ClientStatus = CLIENT_STATUS_CONNECTING;
+
+ s = ClientConnectToServer(c);
+ if (s == NULL)
+ {
+ PrintStatus(sess, L"free");
+ return false;
+ }
+
+ Copy(&server_ip, &s->RemoteIP, sizeof(IP));
+
+ if (c->Halt)
+ {
+ // åæ¢
+ c->Err = ERR_USER_CANCEL;
+ goto CLEANUP;
+ }
+
+ // [ãã´ã·ã¨ã¼ã·ã§ã³ä¸]
+ c->Session->ClientStatus = CLIENT_STATUS_NEGOTIATION;
+
+ // ã·ã°ããã£ãéä¿¡
+ Debug("Uploading Signature...\n");
+ if (ClientUploadSignature(s) == false)
+ {
+ c->Err = ERR_DISCONNECTED;
+ goto CLEANUP;
+ }
+
+ if (c->Halt)
+ {
+ // åæ¢
+ c->Err = ERR_USER_CANCEL;
+ goto CLEANUP;
+ }
+
+ PrintStatus(sess, _UU("STATUS_5"));
+
+ // Hello ãã±ãããåä¿¡
+ Debug("Downloading Hello...\n");
+ if (ClientDownloadHello(c, s) == false)
+ {
+ goto CLEANUP;
+ }
+
+ if (c->Session->ClientOption != NULL && c->Session->ClientOption->FromAdminPack)
+ {
+ if (IsAdminPackSupportedServerProduct(c->ServerStr) == false)
+ {
+ c->Err = ERR_NOT_ADMINPACK_SERVER;
+ goto CLEANUP;
+ }
+ }
+
+ if (c->Halt)
+ {
+ // åæ¢
+ c->Err = ERR_USER_CANCEL;
+ goto CLEANUP;
+ }
+
+ Debug("Server Version : %u\n"
+ "Server String : %s\n"
+ "Server Build : %u\n"
+ "Client Version : %u\n"
+ "Client String : %s\n"
+ "Client Build : %u\n",
+ c->ServerVer, c->ServerStr, c->ServerBuild,
+ c->ClientVer, c->ClientStr, c->ClientBuild);
+
+ // ã¦ã¼ã¶ã¼èªè¨¼ä¸
+ c->Session->ClientStatus = CLIENT_STATUS_AUTH;
+
+ // ã¯ã©ã¤ã¢ã³ãã«ãããµã¼ãã¼è¨¼ææ¸ã®ç¢ºèª
+ if (ClientCheckServerCert(c, &expired) == false)
+ {
+ if (expired == false)
+ {
+ c->Err = ERR_CERT_NOT_TRUSTED;
+ }
+ else
+ {
+ c->Err = ERR_SERVER_CERT_EXPIRES;
+ }
+
+ if (c->Session->LinkModeClient == false && c->Err == ERR_CERT_NOT_TRUSTED)
+ {
+ c->Session->ForceStopFlag = true;
+ }
+
+ goto CLEANUP;
+ }
+
+ PrintStatus(sess, _UU("STATUS_6"));
+
+ // èªè¨¼ãã¼ã¿ãéä¿¡
+ if (ClientUploadAuth(c) == false)
+ {
+ goto CLEANUP;
+ }
+
+ if (c->Halt)
+ {
+ // åæ¢
+ c->Err = ERR_USER_CANCEL;
+ goto CLEANUP;
+ }
+
+ // Welcome ãã±ãããåä¿¡
+ p = HttpClientRecv(s);
+ if (p == NULL)
+ {
+ c->Err = ERR_DISCONNECTED;
+ goto CLEANUP;
+ }
+
+ // ã¨ã©ã¼ãã§ãã¯
+ err = GetErrorFromPack(p);
+ if (err != 0)
+ {
+ // ã¨ã©ã¼çºç
+ c->Err = err;
+ c->ClientConnectError_NoSavePassword = PackGetBool(p, "no_save_password");
+ goto CLEANUP;
+ }
+
+ // æ¥ç¶å¶éã®ããã®ãã©ã³ãåæååãã§ãã¯
+ {
+ char tmp[20];
+ char *branded_cfroms = _SS("BRANDED_C_FROM_S");
+ PackGetStr(p, "branded_cfroms", tmp, sizeof(tmp));
+
+ if(StrLen(branded_cfroms) > 0 && StrCmpi(branded_cfroms, tmp) != 0)
+ {
+ c->Err = ERR_BRANDED_C_FROM_S;
+ goto CLEANUP;
+ }
+ }
+
+ if (true)
+ {
+ // ã¡ãã»ã¼ã¸åå¾
+ UINT utf_size;
+ char *utf;
+ wchar_t *msg;
+
+ utf_size = PackGetDataSize(p, "Msg");
+ utf = ZeroMalloc(utf_size + 8);
+ PackGetData(p, "Msg", utf);
+
+ msg = CopyUtfToUni(utf);
+
+ if (IsEmptyUniStr(msg) == false)
+ {
+ if (c->Session->Client_Message != NULL)
+ {
+ Free(c->Session->Client_Message);
+ }
+
+ c->Session->Client_Message = msg;
+ }
+ else
+ {
+ Free(msg);
+ }
+
+ Free(utf);
+ }
+
+ if (PackGetInt(p, "Redirect") != 0)
+ {
+ UINT i;
+ UINT ip;
+ UINT num_port;
+ UINT *ports;
+ UINT use_port = 0;
+ UINT current_port = c->ServerPort;
+ UCHAR ticket[SHA1_SIZE];
+ X *server_cert;
+ BUF *b;
+
+ // ãªãã¤ã¬ã¯ãã¢ã¼ã
+ PrintStatus(sess, _UU("STATUS_8"));
+
+ ip = PackGetIp32(p, "Ip");
+ num_port = MAX(MIN(PackGetIndexCount(p, "Port"), MAX_PUBLIC_PORT_NUM), 1);
+ ports = ZeroMalloc(sizeof(UINT) * num_port);
+ for (i = 0;i < num_port;i++)
+ {
+ ports[i] = PackGetIntEx(p, "Port", i);
+ }
+
+ // ãã¼ãçªå·ãé¸å®ãã
+ for (i = 0;i < num_port;i++)
+ {
+ if (ports[i] == current_port)
+ {
+ use_port = current_port;
+ }
+ }
+ if (use_port == 0)
+ {
+ use_port = ports[0];
+ }
+
+ Free(ports);
+
+ if (PackGetDataSize(p, "Ticket") == SHA1_SIZE)
+ {
+ PackGetData(p, "Ticket", ticket);
+ }
+
+ b = PackGetBuf(p, "Cert");
+ if (b != NULL)
+ {
+ server_cert = BufToX(b, false);
+ FreeBuf(b);
+ }
+
+ if (c->ServerX != NULL)
+ {
+ FreeX(c->ServerX);
+ }
+ c->ServerX = server_cert;
+
+ IPToStr32(c->ServerName, sizeof(c->ServerName), ip);
+ c->ServerPort = use_port;
+
+ c->UseTicket = true;
+ Copy(c->Ticket, ticket, SHA1_SIZE);
+
+ FreePack(p);
+
+ p = NewPack();
+ HttpClientSend(s, p);
+ FreePack(p);
+
+ p = NULL;
+
+ c->FirstSock = NULL;
+ Disconnect(s);
+ ReleaseSock(s);
+ s = NULL;
+
+ goto REDIRECTED;
+ }
+
+ PrintStatus(sess, _UU("STATUS_7"));
+
+ // Welcome ãã±ããããã¼ã¹
+ if (ParseWelcomeFromPack(p, session_name, sizeof(session_name),
+ connection_name, sizeof(connection_name), &policy) == false)
+ {
+ // ãã¼ã¹å¤±æ
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+ // ã»ãã·ã§ã³ãã¼ãåå¾
+ if (GetSessionKeyFromPack(p, session_key, &session_key_32) == false)
+ {
+ // åå¾å¤±æ
+ Free(policy);
+ policy = NULL;
+ c->Err = ERR_PROTOCOL_ERROR;
+ goto CLEANUP;
+ }
+
+ Copy(c->Session->SessionKey, session_key, SHA1_SIZE);
+ c->Session->SessionKey32 = session_key_32;
+
+ // Welcome ãã±ããã®å
容ãä¿å
+ Debug("session_name: %s, connection_name: %s\n",
+ session_name, connection_name);
+
+ Lock(c->Session->lock);
+ {
+ // æ¥ç¶ãã©ã¡ã¼ã¿ã®å±éã¨æ´æ°
+ c->Session->MaxConnection = PackGetInt(p, "max_connection");
+ c->Session->MaxConnection = MIN(c->Session->MaxConnection, c->Session->ClientOption->MaxConnection);
+ c->Session->MaxConnection = MIN(c->Session->MaxConnection, MAX_TCP_CONNECTION);
+ c->Session->MaxConnection = MAX(c->Session->MaxConnection, 1);
+ c->Session->UseCompress = PackGetInt(p, "use_compress") == 0 ? false : true;
+ c->Session->UseEncrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
+ c->Session->NoSendSignature = PackGetBool(p, "no_send_signature");
+ if (c->Session->UseEncrypt)
+ {
+ c->Session->UseFastRC4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
+ }
+ c->Session->HalfConnection = PackGetInt(p, "half_connection") == 0 ? false : true;
+ c->Session->Timeout = PackGetInt(p, "timeout");
+ c->Session->QoS = PackGetInt(p, "qos") == 0 ? false : true;
+ if (c->Session->QoS)
+ {
+ c->Session->MaxConnection = MAX(c->Session->MaxConnection, (UINT)(c->Session->HalfConnection ? 4 : 2));
+ }
+ c->Session->VLanId = PackGetInt(p, "vlan_id");
+
+ if (c->Protocol == CONNECTION_UDP)
+ {
+ // UDP ãããã³ã«ã®å ´åããµã¼ãã¼ããéµãåãåã
+ if (PackGetDataSize(p, "udp_send_key") == sizeof(c->Session->UdpSendKey))
+ {
+ PackGetData(p, "udp_send_key", c->Session->UdpSendKey);
+ }
+
+ if (PackGetDataSize(p, "udp_recv_key") == sizeof(c->Session->UdpRecvKey))
+ {
+ PackGetData(p, "udp_recv_key", c->Session->UdpRecvKey);
+ }
+ }
+
+ if (c->Session->UseFastRC4)
+ {
+ // RC4 éµæ
å ±ã®åå¾
+ if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
+ {
+ PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
+ }
+ if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
+ {
+ PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
+ }
+ {
+ char key1[64], key2[64];
+ BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
+ BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
+ Debug(
+ "Client to Server Key: %s\n"
+ "Server to Client Key: %s\n",
+ key1, key2);
+ }
+ }
+ }
+ Unlock(c->Session->lock);
+
+ Lock(c->lock);
+ {
+ if (c->Name != NULL)
+ {
+ Free(c->Name);
+ }
+ c->Name = CopyStr(connection_name);
+
+ // æå·åã¢ã«ã´ãªãºã åã®ä¿å
+ if (c->CipherName != NULL)
+ {
+ Free(c->CipherName);
+ }
+
+ c->CipherName = CopyStr(c->FirstSock->CipherName);
+ }
+ Unlock(c->lock);
+
+ Lock(c->Session->lock);
+ {
+ if (c->Session->Name != NULL)
+ {
+ Free(c->Session->Name);
+ }
+ c->Session->Name = CopyStr(session_name);
+
+ c->Session->Policy = policy;
+ }
+ Unlock(c->Session->lock);
+
+ // Welcome ãã±ãããç ´æ£
+ FreePack(p);
+ p = NULL;
+
+ // server_ip ã«å¯¾ã㦠TCP ã§ã·ã°ããã£ãéä¿¡
+ if (c->Session->NoSendSignature == false)
+ {
+ SendSignatureByTcp(c, &server_ip);
+ }
+
+ // ã³ãã¯ã·ã§ã³ç¢ºç«
+ c->Session->ClientStatus = CLIENT_STATUS_ESTABLISHED;
+
+ // ãµã¼ãã¼è¨¼ææ¸ã®ä¿å
+ if (c->ServerX == NULL)
+ {
+ c->ServerX = CloneX(c->FirstSock->RemoteX);
+ }
+
+ PrintStatus(sess, _UU("STATUS_9"));
+
+ // ã³ãã¯ã·ã§ã³ããã³ããªã³ã°ã¢ã¼ãã«ç§»è¡
+ StartTunnelingMode(c);
+ s = NULL;
+
+ if (c->Session->HalfConnection)
+ {
+ // ãã¼ãã³ãã¯ã·ã§ã³æã®å¦ç
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
+ ts->Direction = TCP_CLIENT_TO_SERVER;
+ }
+
+ if (c->Session->UseFastRC4)
+ {
+ // RC4 é«éæå·åéµã®ã»ãã
+ TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
+ Copy(&ts->Rc4KeyPair, &key_pair, sizeof(key_pair));
+
+ InitTcpSockRc4Key(ts, false);
+ }
+
+ // SSL æå·åãã©ã°
+ if (c->Session->UseEncrypt && c->Session->UseFastRC4 == false)
+ {
+ c->Session->UseSSLDataEncryption = true;
+ }
+ else
+ {
+ c->Session->UseSSLDataEncryption = false;
+ }
+
+ PrintStatus(sess, L"free");
+
+ CLog(c->Cedar->Client, "LC_CONNECT_2", c->Session->ClientOption->AccountName,
+ session_name);
+
+ if (c->Session->LinkModeClient && c->Session->Link != NULL)
+ {
+ HLog(c->Session->Link->Hub, "LH_CONNECT_2", c->Session->ClientOption->AccountName, session_name);
+ }
+
+ // ã»ãã·ã§ã³ã®ã¡ã¤ã³ã«ã¼ãã³
+ SessionMain(c->Session);
+
+ ok = true;
+
+ if (c->Err == ERR_USER_CANCEL)
+ {
+ ret = true;
+ }
+
+CLEANUP:
+ c->FirstSock = NULL;
+
+ if (p != NULL)
+ {
+ FreePack(p);
+ }
+
+ Disconnect(s);
+ ReleaseSock(s);
+
+ Debug("Error: %u\n", c->Err);
+
+ if (ok == false)
+ {
+ PrintStatus(sess, L"free");
+ }
+
+ return ret;
+}
+
+// Welcome ãã±ããã®ãã¼ã¹
+bool ParseWelcomeFromPack(PACK *p, char *session_name, UINT session_name_size,
+ char *connection_name, UINT connection_name_size,
+ POLICY **policy)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || session_name == NULL || connection_name == NULL || policy == NULL)
+ {
+ return false;
+ }
+
+ // ã»ãã·ã§ã³å
+ if (PackGetStr(p, "session_name", session_name, session_name_size) == false)
+ {
+ return false;
+ }
+
+ // ã³ãã¯ã·ã§ã³å
+ if (PackGetStr(p, "connection_name", connection_name, connection_name_size) == false)
+ {
+ return false;
+ }
+
+ // ããªã·ã¼
+ *policy = PackGetPolicy(p);
+ if (*policy == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// Welcome ãã±ããã®çæ
+PACK *PackWelcome(SESSION *s)
+{
+ PACK *p;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+
+ // ã»ãã·ã§ã³å
+ PackAddStr(p, "session_name", s->Name);
+
+ // ã³ãã¯ã·ã§ã³å
+ PackAddStr(p, "connection_name", s->Connection->Name);
+
+ // ãã©ã¡ã¼ã¿
+ PackAddInt(p, "max_connection", s->MaxConnection);
+ PackAddInt(p, "use_encrypt", s->UseEncrypt == false ? 0 : 1);
+ PackAddInt(p, "use_fast_rc4", s->UseFastRC4 == false ? 0 : 1);
+ PackAddInt(p, "use_compress", s->UseCompress == false ? 0 : 1);
+ PackAddInt(p, "half_connection", s->HalfConnection == false ? 0 : 1);
+ PackAddInt(p, "timeout", s->Timeout);
+ PackAddInt(p, "qos", s->QoS ? 1 : 0);
+
+ // ã»ãã·ã§ã³ãã¼
+ PackAddData(p, "session_key", s->SessionKey, SHA1_SIZE);
+ PackAddInt(p, "session_key_32", s->SessionKey32);
+
+ // ããªã·ã¼
+ PackAddPolicy(p, s->Policy);
+
+ // VLAN ID
+ PackAddInt(p, "vlan_id", s->VLanId);
+
+ if (s->Connection->Protocol == CONNECTION_UDP)
+ {
+ // UDP ãããã³ã«ã®å ´åã2 çµã®ãã¼ãçæãã
+ Rand(s->UdpSendKey, sizeof(s->UdpSendKey));
+ Rand(s->UdpRecvKey, sizeof(s->UdpRecvKey));
+
+ // ã¯ã©ã¤ã¢ã³ãã«ã¯éµãå転ãã¦éã
+ PackAddData(p, "udp_send_key", s->UdpRecvKey, sizeof(s->UdpRecvKey));
+ PackAddData(p, "udp_recv_key", s->UdpSendKey, sizeof(s->UdpSendKey));
+ }
+
+ // no_send_signature
+ if (s->NoSendSignature)
+ {
+ PackAddBool(p, "no_send_signature", true);
+ }
+
+ return p;
+}
+
+#define PACK_ADD_POLICY_BOOL(name, value) \
+ PackAddInt(p, "policy:" name, y->value == false ? 0 : 1)
+#define PACK_ADD_POLICY_UINT(name, value) \
+ PackAddInt(p, "policy:" name, y->value)
+#define PACK_GET_POLICY_BOOL(name, value) \
+ y->value = (PackGetInt(p, "policy:" name) == 0 ? false : true)
+#define PACK_GET_POLICY_UINT(name, value) \
+ y->value = PackGetInt(p, "policy:" name)
+
+// ã»ãã·ã§ã³ãã¼ã PACK ããåå¾
+bool GetSessionKeyFromPack(PACK *p, UCHAR *session_key, UINT *session_key_32)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || session_key == NULL || session_key_32 == NULL)
+ {
+ return false;
+ }
+
+ if (PackGetDataSize(p, "session_key") != SHA1_SIZE)
+ {
+ return false;
+ }
+ if (PackGetData(p, "session_key", session_key) == false)
+ {
+ return false;
+ }
+ *session_key_32 = PackGetInt(p, "session_key_32");
+
+ return true;
+}
+
+// ããªã·ã¼ã PACK ããåå¾
+POLICY *PackGetPolicy(PACK *p)
+{
+ // ãã®ãããã¯æ¥ãã§å®è£
ããã®ã§ã³ã¼ãããã¾ãç¾ãããªãã
+ POLICY *y;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL)
+ {
+ return NULL;
+ }
+
+ y = ZeroMalloc(sizeof(POLICY));
+
+ // bool å¤
+ // Ver 2
+ PACK_GET_POLICY_BOOL("Access", Access);
+ PACK_GET_POLICY_BOOL("DHCPFilter", DHCPFilter);
+ PACK_GET_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
+ PACK_GET_POLICY_BOOL("DHCPForce", DHCPForce);
+ PACK_GET_POLICY_BOOL("NoBridge", NoBridge);
+ PACK_GET_POLICY_BOOL("NoRouting", NoRouting);
+ PACK_GET_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
+ PACK_GET_POLICY_BOOL("NoServer", NoServer);
+ PACK_GET_POLICY_BOOL("CheckMac", CheckMac);
+ PACK_GET_POLICY_BOOL("CheckIP", CheckIP);
+ PACK_GET_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
+ PACK_GET_POLICY_BOOL("MonitorPort", MonitorPort);
+ PACK_GET_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
+ PACK_GET_POLICY_BOOL("FixPassword", FixPassword);
+ PACK_GET_POLICY_BOOL("NoQoS", NoQoS);
+ // Ver 3
+ PACK_GET_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
+ PACK_GET_POLICY_BOOL("RAFilter", RAFilter);
+ PACK_GET_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
+ PACK_GET_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
+ PACK_GET_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
+ PACK_GET_POLICY_BOOL("CheckIPv6", CheckIPv6);
+ PACK_GET_POLICY_BOOL("NoServerV6", NoServerV6);
+ PACK_GET_POLICY_BOOL("NoSavePassword", NoSavePassword);
+ PACK_GET_POLICY_BOOL("FilterIPv4", FilterIPv4);
+ PACK_GET_POLICY_BOOL("FilterIPv6", FilterIPv6);
+ PACK_GET_POLICY_BOOL("FilterNonIP", FilterNonIP);
+ PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
+ PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
+
+ // UINT å¤
+ // Ver 2
+ PACK_GET_POLICY_UINT("MaxConnection", MaxConnection);
+ PACK_GET_POLICY_UINT("TimeOut", TimeOut);
+ PACK_GET_POLICY_UINT("MaxMac", MaxMac);
+ PACK_GET_POLICY_UINT("MaxIP", MaxIP);
+ PACK_GET_POLICY_UINT("MaxUpload", MaxUpload);
+ PACK_GET_POLICY_UINT("MaxDownload", MaxDownload);
+ PACK_GET_POLICY_UINT("MultiLogins", MultiLogins);
+ // Ver 3
+ PACK_GET_POLICY_UINT("MaxIPv6", MaxIPv6);
+ PACK_GET_POLICY_UINT("AutoDisconnect", AutoDisconnect);
+ PACK_GET_POLICY_UINT("VLanId", VLanId);
+
+ // Ver 3 ãã©ã°
+ PACK_GET_POLICY_BOOL("Ver3", Ver3);
+
+ return y;
+}
+
+// ããªã·ã¼ã PACK ã«æ¿å
¥
+void PackAddPolicy(PACK *p, POLICY *y)
+{
+ // ãã®ãããã¯æ¥ãã§å®è£
ããã®ã§ã³ã¼ãããã¾ãç¾ãããªãã
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || y == NULL)
+ {
+ return;
+ }
+
+ // bool å¤
+ // Ver 2
+ PACK_ADD_POLICY_BOOL("Access", Access);
+ PACK_ADD_POLICY_BOOL("DHCPFilter", DHCPFilter);
+ PACK_ADD_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
+ PACK_ADD_POLICY_BOOL("DHCPForce", DHCPForce);
+ PACK_ADD_POLICY_BOOL("NoBridge", NoBridge);
+ PACK_ADD_POLICY_BOOL("NoRouting", NoRouting);
+ PACK_ADD_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
+ PACK_ADD_POLICY_BOOL("NoServer", NoServer);
+ PACK_ADD_POLICY_BOOL("CheckMac", CheckMac);
+ PACK_ADD_POLICY_BOOL("CheckIP", CheckIP);
+ PACK_ADD_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
+ PACK_ADD_POLICY_BOOL("MonitorPort", MonitorPort);
+ PACK_ADD_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
+ PACK_ADD_POLICY_BOOL("FixPassword", FixPassword);
+ PACK_ADD_POLICY_BOOL("NoQoS", NoQoS);
+ // Ver 3
+ PACK_ADD_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
+ PACK_ADD_POLICY_BOOL("RAFilter", RAFilter);
+ PACK_ADD_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
+ PACK_ADD_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
+ PACK_ADD_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
+ PACK_ADD_POLICY_BOOL("CheckIPv6", CheckIPv6);
+ PACK_ADD_POLICY_BOOL("NoServerV6", NoServerV6);
+ PACK_ADD_POLICY_BOOL("NoSavePassword", NoSavePassword);
+ PACK_ADD_POLICY_BOOL("FilterIPv4", FilterIPv4);
+ PACK_ADD_POLICY_BOOL("FilterIPv6", FilterIPv6);
+ PACK_ADD_POLICY_BOOL("FilterNonIP", FilterNonIP);
+ PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
+ PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
+
+ // UINT å¤
+ // Ver 2
+ PACK_ADD_POLICY_UINT("MaxConnection", MaxConnection);
+ PACK_ADD_POLICY_UINT("TimeOut", TimeOut);
+ PACK_ADD_POLICY_UINT("MaxMac", MaxMac);
+ PACK_ADD_POLICY_UINT("MaxIP", MaxIP);
+ PACK_ADD_POLICY_UINT("MaxUpload", MaxUpload);
+ PACK_ADD_POLICY_UINT("MaxDownload", MaxDownload);
+ PACK_ADD_POLICY_UINT("MultiLogins", MultiLogins);
+ // Ver 3
+ PACK_ADD_POLICY_UINT("MaxIPv6", MaxIPv6);
+ PACK_ADD_POLICY_UINT("AutoDisconnect", AutoDisconnect);
+ PACK_ADD_POLICY_UINT("VLanId", VLanId);
+
+ // Ver 3 ãã©ã°
+ PackAddBool(p, "policy:Ver3", true);
+}
+
+// 追å æ¥ç¶ç¨ã®èªè¨¼ãã¼ã¿ãã¢ãããã¼ããã
+bool ClientUploadAuth2(CONNECTION *c, SOCK *s)
+{
+ PACK *p = NULL;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ p = PackAdditionalConnect(c->Session->SessionKey);
+
+ PackAddClientVersion(p, c);
+
+ if (HttpClientSend(s, p) == false)
+ {
+ FreePack(p);
+ return false;
+ }
+ FreePack(p);
+
+ return true;
+}
+
+// NOOP ãéä¿¡ãã
+void ClientUploadNoop(CONNECTION *c)
+{
+ PACK *p;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return;
+ }
+
+ p = PackError(0);
+ PackAddInt(p, "noop", 1);
+ HttpClientSend(c->FirstSock, p);
+ FreePack(p);
+
+ p = HttpClientRecv(c->FirstSock);
+ if (p != NULL)
+ {
+ FreePack(p);
+ }
+}
+
+// ã¯ã©ã¤ã¢ã³ãã®ãã¼ã¸ã§ã³æ
å ±ã PACK ã«è¿½å ãã
+void PackAddClientVersion(PACK *p, CONNECTION *c)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || c == NULL)
+ {
+ return;
+ }
+
+ PackAddStr(p, "client_str", c->ClientStr);
+ PackAddInt(p, "client_ver", c->ClientVer);
+ PackAddInt(p, "client_build", c->ClientBuild);
+}
+
+// æ°è¦æ¥ç¶ç¨ã®èªè¨¼ãã¼ã¿ãã¢ãããã¼ããã
+bool ClientUploadAuth(CONNECTION *c)
+{
+ PACK *p = NULL;
+ CLIENT_AUTH *a;
+ CLIENT_OPTION *o;
+ X *x;
+ bool ret;
+ NODE_INFO info;
+ UCHAR secure_password[SHA1_SIZE];
+ UCHAR sign[4096 / 8];
+ UCHAR unique[SHA1_SIZE];
+ RPC_WINVER v;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ Zero(sign, sizeof(sign));
+
+ a = c->Session->ClientAuth;
+ o = c->Session->ClientOption;
+
+ if (c->UseTicket == false)
+ {
+ switch (a->AuthType)
+ {
+ case CLIENT_AUTHTYPE_ANONYMOUS:
+ // å¿åèªè¨¼
+ p = PackLoginWithAnonymous(o->HubName, a->Username);
+ break;
+
+ case CLIENT_AUTHTYPE_PASSWORD:
+ // ãã¹ã¯ã¼ãèªè¨¼
+ SecurePassword(secure_password, a->HashedPassword, c->Random);
+ p = PackLoginWithPassword(o->HubName, a->Username, secure_password);
+ break;
+
+ case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
+ // å¹³æãã¹ã¯ã¼ãèªè¨¼
+ p = PackLoginWithPlainPassword(o->HubName, a->Username, a->PlainPassword);
+ break;
+
+ case CLIENT_AUTHTYPE_CERT:
+ // 証ææ¸èªè¨¼
+ if (a->ClientX != NULL && a->ClientX->is_compatible_bit &&
+ a->ClientX->bits != 0 && (a->ClientX->bits / 8) <= sizeof(sign))
+ {
+ if (RsaSignEx(sign, c->Random, SHA1_SIZE, a->ClientK, a->ClientX->bits))
+ {
+ p = PackLoginWithCert(o->HubName, a->Username, a->ClientX, sign, a->ClientX->bits / 8);
+ c->ClientX = CloneX(a->ClientX);
+ }
+ }
+ break;
+
+ case CLIENT_AUTHTYPE_SECURE:
+ // ã»ãã¥ã¢ããã¤ã¹ã«ããèªè¨¼
+ if (ClientSecureSign(c, sign, c->Random, &x))
+ {
+ p = PackLoginWithCert(o->HubName, a->Username, x, sign, 128);
+ c->ClientX = CloneX(x);
+ FreeX(x);
+ }
+ else
+ {
+ c->Err = ERR_SECURE_DEVICE_OPEN_FAILED;
+ c->Session->ForceStopFlag = true;
+ }
+ break;
+ }
+ }
+ else
+ {
+ // ãã±ãã
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", o->HubName);
+ PackAddStr(p, "username", a->Username);
+ PackAddInt(p, "authtype", AUTHTYPE_TICKET);
+ PackAddData(p, "ticket", c->Ticket, SHA1_SIZE);
+ }
+
+ // ç¾å¨æå»
+ PackAddInt64(p, "timestamp", SystemTime64());
+
+ if (p == NULL)
+ {
+ // ã¨ã©ã¼
+ if (c->Err != ERR_SECURE_DEVICE_OPEN_FAILED)
+ {
+ c->Err = ERR_PROTOCOL_ERROR;
+ }
+ return false;
+ }
+
+ PackAddClientVersion(p, c);
+
+ // ãããã³ã«
+ PackAddInt(p, "protocol", c->Protocol);
+
+ // ãã¼ã¸ã§ã³ç
+ PackAddStr(p, "hello", c->ClientStr);
+ PackAddInt(p, "version", c->ClientVer);
+ PackAddInt(p, "build", c->ClientBuild);
+ PackAddInt(p, "client_id", c->Cedar->ClientId);
+
+ // æ大ã³ãã¯ã·ã§ã³æ°
+ PackAddInt(p, "max_connection", o->MaxConnection);
+ // æå·å使ç¨ãã©ã°
+ PackAddInt(p, "use_encrypt", o->UseEncrypt == false ? 0 : 1);
+ // é«éæå·å使ç¨ãã©ã°
+ // PackAddInt(p, "use_fast_rc4", o->UseFastRC4 == false ? 0 : 1);
+ // ãã¼ã¿å§ç¸®ä½¿ç¨ãã©ã°
+ PackAddInt(p, "use_compress", o->UseCompress == false ? 0 : 1);
+ // ãã¼ãã³ãã¯ã·ã§ã³ãã©ã°
+ PackAddInt(p, "half_connection", o->HalfConnection == false ? 0 : 1);
+
+ // ããªã㸠/ ã«ã¼ãã£ã³ã°ã¢ã¼ããã©ã°
+ PackAddBool(p, "require_bridge_routing_mode", o->RequireBridgeRoutingMode);
+
+ // ã¢ãã¿ã¢ã¼ããã©ã°
+ PackAddBool(p, "require_monitor_mode", o->RequireMonitorMode);
+
+ // VoIP / QoS ãã©ã°
+ PackAddBool(p, "qos", o->DisableQoS ? false : true);
+
+ // ã¦ãã¼ã¯ ID
+ GenerateMachineUniqueHash(unique);
+ PackAddData(p, "unique_id", unique, SHA1_SIZE);
+
+ // ãã¼ãæ
å ±
+ CreateNodeInfo(&info, c);
+ OutRpcNodeInfo(p, &info);
+
+ // OS æ
å ±
+ GetWinVer(&v);
+ OutRpcWinVer(p, &v);
+
+ ret = HttpClientSend(c->FirstSock, p);
+ if (ret == false)
+ {
+ c->Err = ERR_DISCONNECTED;
+ }
+
+ FreePack(p);
+
+ return ret;
+}
+
+// Hello ãã±ãããã¢ãããã¼ããã
+bool ServerUploadHello(CONNECTION *c)
+{
+ PACK *p;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ // ä¹±æ°çæ
+ Rand(c->Random, SHA1_SIZE);
+
+ p = PackHello(c->Random, c->ServerVer, c->ServerBuild, c->ServerStr);
+ if (HttpServerSend(c->FirstSock, p) == false)
+ {
+ FreePack(p);
+ c->Err = ERR_DISCONNECTED;
+ return false;
+ }
+
+ FreePack(p);
+
+ return true;
+}
+
+// Hello ãã±ããããã¦ã³ãã¼ããã
+bool ClientDownloadHello(CONNECTION *c, SOCK *s)
+{
+ PACK *p;
+ UINT err;
+ UCHAR random[SHA1_SIZE];
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ // ãã¼ã¿åä¿¡
+ p = HttpClientRecv(s);
+ if (p == NULL)
+ {
+ c->Err = ERR_SERVER_IS_NOT_VPN;
+ return false;
+ }
+
+ if (err = GetErrorFromPack(p))
+ {
+ // ã¨ã©ã¼çºç
+ c->Err = err;
+ FreePack(p);
+ return false;
+ }
+
+ // ãã±ãã解é
+ if (GetHello(p, random, &c->ServerVer, &c->ServerBuild, c->ServerStr, sizeof(c->ServerStr)) == false)
+ {
+ c->Err = ERR_SERVER_IS_NOT_VPN;
+ FreePack(p);
+ return false;
+ }
+
+ if (c->FirstSock == s)
+ {
+ Copy(c->Random, random, SHA1_SIZE);
+ }
+
+ FreePack(p);
+
+ return true;
+}
+
+// ã·ã°ããã£ããã¦ã³ãã¼ããã
+bool ServerDownloadSignature(CONNECTION *c)
+{
+ HTTP_HEADER *h;
+ UCHAR *data;
+ UINT data_size;
+ SOCK *s;
+ UINT num = 0, max = 19;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return false;
+ }
+
+ s = c->FirstSock;
+
+ while (true)
+ {
+ num++;
+ if (num > max)
+ {
+ // åæ
+ Disconnect(s);
+ c->Err = ERR_CLIENT_IS_NOT_VPN;
+ return false;
+ }
+ // ããããåä¿¡ãã
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ c->Err = ERR_CLIENT_IS_NOT_VPN;
+ return false;
+ }
+
+ // 解éãã
+ if (StrCmpi(h->Method, "POST") == 0)
+ {
+ // POST ãªã®ã§ãã¼ã¿ãåä¿¡ãã
+ data_size = GetContentLength(h);
+ if ((data_size > 3411 || data_size < 1411) && (data_size != StrLen(HTTP_VPN_TARGET_POSTDATA)))
+ {
+ // ãã¼ã¿ã大ãããã
+ HttpSendForbidden(s, h->Target, NULL);
+ FreeHttpHeader(h);
+ c->Err = ERR_CLIENT_IS_NOT_VPN;
+ return false;
+ }
+ data = Malloc(data_size);
+ if (RecvAll(s, data, data_size, s->SecureMode) == false)
+ {
+ // ãã¼ã¿å信失æ
+ Free(data);
+ FreeHttpHeader(h);
+ c->Err = ERR_DISCONNECTED;
+ return false;
+ }
+ // Target ã確èªãã
+ if (StrCmpi(h->Target, HTTP_VPN_TARGET2) != 0)
+ {
+ // ã¿ã¼ã²ãããä¸æ£
+ HttpSendNotFound(s, h->Target);
+ Free(data);
+ FreeHttpHeader(h);
+ }
+ else
+ {
+ if (((data_size == StrLen(HTTP_VPN_TARGET_POSTDATA)) && (Cmp(data, HTTP_VPN_TARGET_POSTDATA, data_size) == 0)) || (data_size >= 1411))
+ {
+ // VPN Client ãæ¥ç¶ãã¦ãã
+ Free(data);
+ FreeHttpHeader(h);
+ return true;
+ }
+ else
+ {
+ // VPN Client 以å¤ã®ã½ããã¦ã§ã¢ãæ¥ç¶ãã¦ãã
+ HttpSendForbidden(s, h->Target, NULL);
+ FreeHttpHeader(h);
+ }
+ }
+ }
+ else
+ {
+ // ãã以ä¸è§£éãã¦ã VPN ã¯ã©ã¤ã¢ã³ãã§ç¡ãå¯è½æ§ãé«ãã
+ // ä¸å¿ãã
+ if (StrCmpi(h->Method, "GET") != 0)
+ {
+ // ãµãã¼ãããã¦ããªãã¡ã½ããå¼ã³åºã
+ HttpSendNotImplemented(s, h->Method, h->Target, h->Version);
+ }
+ else
+ {
+ if (StrCmpi(h->Target, "/") == 0)
+ {
+ // ã«ã¼ããã£ã¬ã¯ããª
+ HttpSendForbidden(c->FirstSock, h->Target, "");
+ }
+ else
+ {
+ // Not Found
+ HttpSendNotFound(s, h->Target);
+ }
+ }
+ FreeHttpHeader(h);
+ }
+ }
+}
+
+// ã·ã°ããã£ãã¢ãããã¼ããã
+bool ClientUploadSignature(SOCK *s)
+{
+ HTTP_HEADER *h;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL)
+ {
+ return false;
+ }
+
+ h = NewHttpHeader("POST", HTTP_VPN_TARGET2, "HTTP/1.1");
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+
+ if (PostHttp(s, h, HTTP_VPN_TARGET_POSTDATA, StrLen(HTTP_VPN_TARGET_POSTDATA)) == false)
+ {
+ FreeHttpHeader(h);
+ return false;
+ }
+
+ FreeHttpHeader(h);
+
+ return true;
+}
+
+// ãµã¼ãã¼ã¸ã®æ¥ç¶ã確ç«ãã
+SOCK *ClientConnectToServer(CONNECTION *c)
+{
+ SOCK *s = NULL;
+ X *x = NULL;
+ K *k = NULL;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ if (c->Halt)
+ {
+ c->Err = ERR_USER_CANCEL;
+ return NULL;
+ }
+
+ // æ¥ç¶ãã¦ã½ã±ãããåå¾
+ s = ClientConnectGetSocket(c, false);
+ if (s == NULL)
+ {
+ // æ¥ç¶å¤±æ
+ return NULL;
+ }
+
+ c->FirstSock = s;
+
+ if (c->Halt)
+ {
+ c->Err = ERR_USER_CANCEL;
+ ReleaseSock(s);
+ c->FirstSock = NULL;
+ return NULL;
+ }
+
+ // ã¿ã¤ã ã¢ã¦ã
+ SetTimeout(s, CONNECTING_TIMEOUT);
+
+ // SSL éä¿¡ã®éå§
+ if (StartSSLEx(s, x, k, (c->DontUseTls1 ? false : true)) == false)
+ {
+ // SSL éä¿¡éå§å¤±æ
+ Disconnect(s);
+ ReleaseSock(s);
+ c->FirstSock = NULL;
+ c->Err = ERR_SERVER_IS_NOT_VPN;
+ return NULL;
+ }
+
+ if (s->RemoteX == NULL)
+ {
+ // SSL éä¿¡éå§å¤±æ
+ Disconnect(s);
+ ReleaseSock(s);
+ c->FirstSock = NULL;
+ c->Err = ERR_SERVER_IS_NOT_VPN;
+ return NULL;
+ }
+
+ return s;
+}
+
+// ãµã¼ãã¼ã«æ¥ç¶ãã½ã±ãããè¿ã
+SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
+{
+ SOCK *s = NULL;
+ CLIENT_OPTION *o;
+ char *host_for_direct_connection;
+ UINT port_for_direct_connection;
+ wchar_t tmp[MAX_SIZE];
+ SESSION *sess;
+ volatile bool *cancel_flag = NULL;
+ void *hWnd;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL)
+ {
+ return NULL;
+ }
+
+ sess = c->Session;
+
+ if (sess != NULL)
+ {
+ cancel_flag = &sess->CancelConnect;
+ }
+
+ hWnd = c->hWndForUI;
+
+ o = c->Session->ClientOption;
+
+ if (c->RestoreServerNameAndPort && additional_connect)
+ {
+ // ãµã¼ãã¼åã¨ãã¼ãçªå·ãå
ã«æ»ã
+ c->RestoreServerNameAndPort = false;
+
+ StrCpy(c->ServerName, sizeof(c->ServerName), o->Hostname);
+ c->ServerPort = o->Port;
+ }
+
+ host_for_direct_connection = c->ServerName;
+ port_for_direct_connection = c->ServerPort;
+
+ if (o->PortUDP != 0)
+ {
+ // UDP Connection
+ goto UDP_CONNECTION;
+ }
+
+ switch (o->ProxyType)
+ {
+ case PROXY_DIRECT: // TCP/IP
+UDP_CONNECTION:
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_4"), c->ServerName);
+ PrintStatus(sess, tmp);
+ // æ¬çª
+ s = TcpIpConnectEx(host_for_direct_connection, port_for_direct_connection,
+ (bool *)cancel_flag, hWnd);
+ if (s == NULL)
+ {
+ // æ¥ç¶å¤±æ
+ c->Err = ERR_CONNECT_FAILED;
+ return NULL;
+ }
+ break;
+
+ case PROXY_HTTP: // HTTP Proxy
+ host_for_direct_connection = o->ProxyName;
+ port_for_direct_connection = o->ProxyPort;
+
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
+ PrintStatus(sess, tmp);
+ // ãããã·æ¥ç¶
+ s = ProxyConnectEx(c, host_for_direct_connection, port_for_direct_connection,
+ c->ServerName, c->ServerPort, o->ProxyUsername, o->ProxyPassword,
+ additional_connect, (bool *)cancel_flag, hWnd);
+ if (s == NULL)
+ {
+ // æ¥ç¶å¤±æ
+ return NULL;
+ }
+ break;
+
+ case PROXY_SOCKS: // SOCKS Proxy
+ host_for_direct_connection = o->ProxyName;
+
+ port_for_direct_connection = o->ProxyPort;
+
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
+ PrintStatus(sess, tmp);
+ // SOCKS æ¥ç¶
+ s = SocksConnectEx(c, host_for_direct_connection, port_for_direct_connection,
+ c->ServerName, c->ServerPort, o->ProxyUsername,
+ additional_connect, (bool *)cancel_flag, hWnd);
+ if (s == NULL)
+ {
+ // æ¥ç¶å¤±æ
+ return NULL;
+ }
+ break;
+ }
+
+ if (s == NULL)
+ {
+ // æ¥ç¶å¤±æ
+ c->Err = ERR_CONNECT_FAILED;
+ }
+ else
+ {
+ // æ¥ç¶æå
+ // IP ã¢ãã¬ã¹ãæ§ãã¦ãã
+ if (GetIP(&c->Session->ServerIP, host_for_direct_connection) == false)
+ {
+ Copy(&c->Session->ServerIP, &s->RemoteIP, sizeof(IP));
+ }
+ }
+
+ return s;
+}
+
+// SOCKS çµç±ã§æ¥ç¶ãã
+SOCK *SocksConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, bool additional_connect)
+{
+ return SocksConnectEx(c, proxy_host_name, proxy_port,
+ server_host_name, server_port, username, additional_connect, NULL, NULL);
+}
+SOCK *SocksConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, bool additional_connect,
+ bool *cancel_flag, void *hWnd)
+{
+ SOCK *s = NULL;
+ IP ip;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL
+ || server_port == 0)
+ {
+ c->Err = ERR_PROXY_CONNECT_FAILED;
+ return NULL;
+ }
+
+ // æ¥ç¶å
ãµã¼ãã¼ã® IP ã¢ãã¬ã¹ãåå¾ã
+ if (GetIP(&ip, server_host_name) == false)
+ {
+ // 失æ
+ c->Err = ERR_CONNECT_FAILED;
+ return NULL;
+ }
+
+ if (c->Halt)
+ {
+ // åæ¢
+ c->Err = ERR_USER_CANCEL;
+ return NULL;
+ }
+
+ // æ¥ç¶
+ s = TcpConnectEx2(proxy_host_name, proxy_port, 0, cancel_flag, hWnd);
+ if (s == NULL)
+ {
+ // 失æ
+ c->Err = ERR_PROXY_CONNECT_FAILED;
+ return NULL;
+ }
+
+ // ã¿ã¤ã ã¢ã¦ãè¨å®
+ SetTimeout(s, CONNECTING_TIMEOUT_PROXY);
+
+ if (additional_connect == false)
+ {
+ c->FirstSock = s;
+ }
+
+ // ãªã¯ã¨ã¹ããã±ããéä¿¡
+ if (SocksSendRequestPacket(c, s, server_port, &ip, username) == false)
+ {
+ // 失æ
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ // å¿çãã±ããåä¿¡
+ if (SocksRecvResponsePacket(c, s) == false)
+ {
+ // 失æ
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ return NULL;
+ }
+
+ SetTimeout(s, INFINITE);
+
+ return s;
+}
+
+// SOCKS å¿çãã±ãããåä¿¡ãã
+bool SocksRecvResponsePacket(CONNECTION *c, SOCK *s)
+{
+ BUF *b;
+ UINT size = 8;
+ UCHAR tmp[8];
+ UCHAR vn, cd;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL || s == NULL)
+ {
+ return false;
+ }
+
+ if (RecvAll(s, tmp, sizeof(tmp), false) == false)
+ {
+ c->Err = ERR_DISCONNECTED;
+ return false;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, sizeof(tmp));
+ SeekBuf(b, 0, 0);
+
+ ReadBuf(b, &vn, 1);
+ ReadBuf(b, &cd, 1);
+
+ FreeBuf(b);
+
+ if (vn != 0)
+ {
+ c->Err = ERR_PROXY_ERROR;
+ return false;
+ }
+
+ switch (cd)
+ {
+ case 90:
+ // æå
+ return true;
+
+ case 93:
+ // èªè¨¼å¤±æ
+ c->Err = ERR_PROXY_AUTH_FAILED;
+ return false;
+
+ default:
+ // ãµã¼ãã¼ã¸ã®æ¥ç¶å¤±æ
+ c->Err = ERR_CONNECT_FAILED;
+ return false;
+ }
+}
+
+// SOCKS ãªã¯ã¨ã¹ããã±ãããéä¿¡ãã
+bool SocksSendRequestPacket(CONNECTION *c, SOCK *s, UINT dest_port, IP *dest_ip, char *userid)
+{
+ BUF *b;
+ UCHAR vn, cd;
+ USHORT port;
+ UINT ip;
+ bool ret;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || dest_port == 0 || dest_ip == NULL || c == NULL)
+ {
+ return false;
+ }
+ if (userid == NULL)
+ {
+ userid = "";
+ }
+
+ b = NewBuf();
+ vn = 4;
+ cd = 1;
+ WriteBuf(b, &vn, 1);
+ WriteBuf(b, &cd, 1);
+ port = Endian16((USHORT)dest_port);
+ ip = IPToUINT(dest_ip);
+ WriteBuf(b, &port, 2);
+ WriteBuf(b, &ip, 4);
+ WriteBuf(b, userid, StrLen(userid) + 1);
+
+ ret = SendAll(s, b->Buf, b->Size, false);
+ if (ret == false)
+ {
+ c->Err = ERR_DISCONNECTED;
+ }
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// ãããã·çµç±ã§æ¥ç¶ãã
+SOCK *ProxyConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, char *password, bool additional_connect)
+{
+ return ProxyConnectEx(c, proxy_host_name, proxy_port,
+ server_host_name, server_port, username, password, additional_connect, NULL, NULL);
+}
+SOCK *ProxyConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
+ char *server_host_name, UINT server_port,
+ char *username, char *password, bool additional_connect,
+ bool *cancel_flag, void *hWnd)
+{
+ SOCK *s = NULL;
+ bool use_auth = false;
+ char tmp[MAX_SIZE];
+ char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2];
+ char basic_str[MAX_SIZE * 2];
+ UINT http_error_code;
+ HTTP_HEADER *h;
+ // å¼æ°ãã§ãã¯
+ if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL ||
+ server_port == 0)
+ {
+ c->Err = ERR_PROXY_CONNECT_FAILED;
+ return NULL;
+ }
+ if (username != NULL && password != NULL &&
+ (StrLen(username) != 0 || StrLen(password) != 0))
+ {
+ use_auth = true;
+ }
+
+ if (c->Halt)
+ {
+ // åæ¢
+ c->Err = ERR_USER_CANCEL;
+ return NULL;
+ }
+
+ // æ¥ç¶
+ s = TcpConnectEx2(proxy_host_name, proxy_port, 0, cancel_flag, hWnd);
+ if (s == NULL)
+ {
+ // 失æ
+ c->Err = ERR_PROXY_CONNECT_FAILED;
+ return NULL;
+ }
+
+ // ã¿ã¤ã ã¢ã¦ãè¨å®
+ SetTimeout(s, CONNECTING_TIMEOUT_PROXY);
+
+ if (additional_connect == false)
+ {
+ c->FirstSock = s;
+ }
+
+ // HTTP ãããçæ
+ if (IsStrIPv6Address(server_host_name))
+ {
+ IP ip;
+ char iptmp[MAX_PATH];
+
+ StrToIP(&ip, server_host_name);
+ IPToStr(iptmp, sizeof(iptmp), &ip);
+
+ Format(tmp, sizeof(tmp), "[%s]:%u", iptmp, server_port);
+ }
+ else
+ {
+ Format(tmp, sizeof(tmp), "%s:%u", server_host_name, server_port);
+ }
+
+ h = NewHttpHeader("CONNECT", tmp, "HTTP/1.0");
+ AddHttpValue(h, NewHttpValue("User-Agent", c->Cedar->HttpUserAgent));
+ Debug("proxy user agent = %s\n", c->Cedar->HttpUserAgent);
+ AddHttpValue(h, NewHttpValue("Host", server_host_name));
+ AddHttpValue(h, NewHttpValue("Content-Length", "0"));
+ AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
+
+ if (use_auth)
+ {
+ wchar_t tmp[MAX_SIZE];
+ UniFormat(tmp, sizeof(tmp), _UU("STATUS_3"), server_host_name);
+ // èªè¨¼æååã®çæ
+ Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
+ username, password);
+
+ // Base64 ã¨ã³ã³ã¼ã
+ Zero(auth_b64_str, sizeof(auth_b64_str));
+ Encode64(auth_b64_str, auth_tmp_str);
+ Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str);
+
+ AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str));
+ }
+
+ // éä¿¡
+ if (SendHttpHeader(s, h) == false)
+ {
+ // 失æ
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ FreeHttpHeader(h);
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_PROXY_ERROR;
+ return NULL;
+ }
+
+ FreeHttpHeader(h);
+
+ if (c->Halt)
+ {
+ // åæ¢
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_USER_CANCEL;
+ return NULL;
+ }
+
+ // çµæãåä¿¡
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ // 失æ
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ FreeHttpHeader(h);
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_PROXY_ERROR;
+ return NULL;
+ }
+
+ http_error_code = 0;
+ if (StrLen(h->Method) == 8)
+ {
+ if (Cmp(h->Method, "HTTP/1.", 7) == 0)
+ {
+ http_error_code = ToInt(h->Target);
+ }
+ }
+ FreeHttpHeader(h);
+
+ // ã³ã¼ãã確èª
+ switch (http_error_code)
+ {
+ case 401:
+ case 403:
+ case 407:
+ // èªè¨¼å¤±æ
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_PROXY_AUTH_FAILED;
+ return NULL;
+
+ default:
+ if ((http_error_code / 100) == 2)
+ {
+ // æå
+ SetTimeout(s, INFINITE);
+ return s;
+ }
+ else
+ {
+ // ä¸æãªçµæãåä¿¡
+ if (additional_connect == false)
+ {
+ c->FirstSock = NULL;
+ }
+ Disconnect(s);
+ ReleaseSock(s);
+ c->Err = ERR_PROXY_ERROR;
+ return NULL;
+ }
+ }
+}
+
+// TCP æ¥ç¶é¢æ°
+SOCK *TcpConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd)
+{
+#ifdef OS_WIN32
+ if (hWnd == NULL)
+ {
+ return ConnectEx2(hostname, port, timeout, cancel_flag);
+ }
+ else
+ {
+ return WinConnectEx2((HWND)hWnd, hostname, port, timeout, 0, NULL, NULL);
+ }
+#else // OS_WIN32
+ return ConnectEx2(hostname, port, timeout, cancel_flag);
+#endif // OS_WIN32
+}
+
+// TCP/IP ã§æ¥ç¶ãã
+SOCK *TcpIpConnect(char *hostname, UINT port)
+{
+ return TcpIpConnectEx(hostname, port, NULL, NULL);
+}
+SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd)
+{
+ SOCK *s = NULL;
+ // å¼æ°ãã§ãã¯
+ if (hostname == NULL || port == 0)
+ {
+ return NULL;
+ }
+
+ s = TcpConnectEx2(hostname, port, 0, cancel_flag, hWnd);
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ return s;
+}
+
+// PACK ã«ããã¼ã®ã¨ã³ããªãä½æãã
+// Q. ãªãã©ã³ãã ãªãµã¤ãºã®ã©ã³ãã ãã¼ã¿ãããã§æ¿å
¥ããã®ã?
+// A. ãããã¯ã¼ã¯çµè·¯ä¸ã®çè´è
ã«ãã£ã¦ãã® SSL éä¿¡ã VPN éä¿¡ã§ãããã¨
+// ãæ¤åºãã«ããããã«ããããã§ããã
+void CreateDummyValue(PACK *p)
+{
+ UINT size;
+ UCHAR *buf;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL)
+ {
+ return;
+ }
+
+ size = Rand32() % HTTP_PACK_RAND_SIZE_MAX;
+ buf = Malloc(size);
+ Rand(buf, size);
+
+ PackAddData(p, "pencore", buf, size);
+
+ Free(buf);
+}
+
+// ãµã¼ãã¼ãã¯ã©ã¤ã¢ã³ããã PACK ãåä¿¡ãã
+PACK *HttpServerRecv(SOCK *s)
+{
+ BUF *b;
+ PACK *p;
+ HTTP_HEADER *h;
+ UINT size;
+ UCHAR *tmp;
+ HTTP_VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+START:
+
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ goto BAD_REQUEST;
+ }
+
+ if (StrCmpi(h->Method, "POST") != 0 ||
+ StrCmpi(h->Target, HTTP_VPN_TARGET) != 0 ||
+ StrCmpi(h->Version, "HTTP/1.1") != 0)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ v = GetHttpValue(h, "Content-Type");
+ if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ size = GetContentLength(h);
+ if (size == 0 || size > MAX_PACK_SIZE)
+ {
+ FreeHttpHeader(h);
+ goto BAD_REQUEST;
+ }
+
+ tmp = MallocEx(size, true);
+ if (RecvAll(s, tmp, size, s->SecureMode) == false)
+ {
+ Free(tmp);
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+ FreeHttpHeader(h);
+
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+
+ // NOOP ãã©ããå¤æ
+ if (PackGetInt(p, "noop") != 0)
+ {
+ Debug("recv: noop\n");
+ FreePack(p);
+
+ p = PackError(0);
+ PackAddInt(p, "noop", 1);
+ if (HttpServerSend(s, p) == false)
+ {
+ FreePack(p);
+ return NULL;
+ }
+
+ FreePack(p);
+
+ goto START;
+ }
+
+ return p;
+
+BAD_REQUEST:
+ // ã¨ã©ã¼ãè¿ã
+
+
+ return NULL;
+}
+
+// ã¯ã©ã¤ã¢ã³ãããµã¼ãã¼ãã PACK ãåä¿¡ãã
+PACK *HttpClientRecv(SOCK *s)
+{
+ BUF *b;
+ PACK *p;
+ HTTP_HEADER *h;
+ UINT size;
+ UCHAR *tmp;
+ HTTP_VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ h = RecvHttpHeader(s);
+ if (h == NULL)
+ {
+ return NULL;
+ }
+
+ if (StrCmpi(h->Method, "HTTP/1.1") != 0 ||
+ StrCmpi(h->Target, "200") != 0)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ v = GetHttpValue(h, "Content-Type");
+ if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ size = GetContentLength(h);
+ if (size == 0 || size > MAX_PACK_SIZE)
+ {
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ tmp = MallocEx(size, true);
+ if (RecvAll(s, tmp, size, s->SecureMode) == false)
+ {
+ Free(tmp);
+ FreeHttpHeader(h);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ Free(tmp);
+ FreeHttpHeader(h);
+
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+
+ return p;
+}
+
+// ã¯ã©ã¤ã¢ã³ããããµã¼ãã¼ã« PACK ãéä¿¡ãã
+bool HttpClientSend(SOCK *s, PACK *p)
+{
+ BUF *b;
+ bool ret;
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ CreateDummyValue(p);
+
+ b = PackToBuf(p);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ h = NewHttpHeader("POST", HTTP_VPN_TARGET, "HTTP/1.1");
+
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
+
+ ret = PostHttp(s, h, b->Buf, b->Size);
+
+ FreeHttpHeader(h);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// ãµã¼ãã¼ããã¯ã©ã¤ã¢ã³ãã« PACK ãéä¿¡ãã
+bool HttpServerSend(SOCK *s, PACK *p)
+{
+ BUF *b;
+ bool ret;
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || p == NULL)
+ {
+ return false;
+ }
+
+ CreateDummyValue(p);
+
+ b = PackToBuf(p);
+ if (b == NULL)
+ {
+ return false;
+ }
+
+ h = NewHttpHeader("HTTP/1.1", "200", "OK");
+
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
+
+ ret = PostHttp(s, h, b->Buf, b->Size);
+
+ FreeHttpHeader(h);
+ FreeBuf(b);
+
+ return ret;
+}
+
+// 501 Not Implemented ã¨ã©ã¼ã®éä¿¡
+bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // ãã¹ãåã®åå¾
+ GetMachineName(host, MAX_SIZE);
+ // ãã¼ãçªå·ã®åå¾
+ port = s->LocalPort;
+
+ // ãããã®ä½æ
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "501", "Method Not Implemented");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // ãã¼ã¿ã®ä½æ
+ str_size = sizeof(http_501_str) * 2 + StrLen(target) + StrLen(host) + StrLen(method) + StrLen(version);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_501_str);
+
+ // TARGET
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // METHOD
+ ReplaceStri(str, str_size, str, "$METHOD$", method);
+
+ // VERSION
+ ReplaceStri(str, str_size, str, "$VERSION$", version);
+
+ // éä¿¡
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// 404 Not Found ã¨ã©ã¼ã®éä¿¡
+bool HttpSendNotFound(SOCK *s, char *target)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // ãã¹ãåã®åå¾
+ GetMachineName(host, MAX_SIZE);
+ // ãã¼ãçªå·ã®åå¾
+ port = s->LocalPort;
+
+ // ãããã®ä½æ
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "404", "Not Found");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // ãã¼ã¿ã®ä½æ
+ str_size = sizeof(http_404_str) * 2 + StrLen(target) + StrLen(host);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_404_str);
+
+ // TARGET
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // éä¿¡
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// 403 Forbidden ã¨ã©ã¼ã®éä¿¡
+bool HttpSendForbidden(SOCK *s, char *target, char *server_id)
+{
+ HTTP_HEADER *h;
+ char date_str[MAX_SIZE];
+ char *str;
+ UINT str_size;
+ char port_str[MAX_SIZE];
+ bool ret;
+ char host[MAX_SIZE];
+ UINT port;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || target == NULL)
+ {
+ return false;
+ }
+
+ // ãã¹ãåã®åå¾
+ GetMachineName(host, MAX_SIZE);
+ // ãã¼ãçªå·ã®åå¾
+ port = s->LocalPort;
+
+ // ãããã®ä½æ
+ GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
+
+ h = NewHttpHeader("HTTP/1.1", "403", "Forbidden");
+
+ AddHttpValue(h, NewHttpValue("Date", date_str));
+ AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
+ AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
+ AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
+
+ // ãã¼ã¿ã®ä½æ
+ str_size = sizeof(http_403_str) * 2 + StrLen(target) + StrLen(host);
+ str = Malloc(str_size);
+ StrCpy(str, str_size, http_403_str);
+
+ // TARGET
+ ReplaceStri(str, str_size, str, "$TARGET$", target);
+
+ // HOST
+ ReplaceStri(str, str_size, str, "$HOST$", host);
+
+ // PORT
+ ToStr(port_str, port);
+ ReplaceStri(str, str_size, str, "$PORT$", port_str);
+
+ // éä¿¡
+ ret = PostHttp(s, h, str, StrLen(str));
+
+ FreeHttpHeader(h);
+ Free(str);
+
+ return ret;
+}
+
+// HTTP ãããç¨ã®æ¥ææååãåå¾
+void GetHttpDateStr(char *str, UINT size, UINT64 t)
+{
+ SYSTEMTIME s;
+ static char *wday[] =
+ {
+ "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
+ };
+ static char *month[] =
+ {
+ "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
+ "Nov", "Dec",
+ };
+ // å¼æ°ãã§ãã¯
+ if (str == NULL)
+ {
+ return;
+ }
+ UINT64ToSystem(&s, t);
+
+ Format(str, size, "%s, %02u %s %04u %02u:%02u:%02u GMT",
+ wday[s.wDayOfWeek], s.wDay, month[s.wMonth - 1], s.wYear,
+ s.wHour, s.wMinute, s.wSecond);
+}
+
+// HTTP ãããããã³ã³ãã³ãé·ãåå¾ãã
+UINT GetContentLength(HTTP_HEADER *header)
+{
+ UINT ret;
+ HTTP_VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (header == NULL)
+ {
+ return 0;
+ }
+
+ v = GetHttpValue(header, "Content-Length");
+ if (v == NULL)
+ {
+ return 0;
+ }
+
+ ret = ToInt(v->Data);
+
+ return ret;
+}
+
+// HTTP ã§ãã¼ã¿ãéä¿¡ãã
+bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size)
+{
+ char *header_str;
+ BUF *b;
+ bool ret;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || header == NULL || post_data == NULL)
+ {
+ return false;
+ }
+
+ // Content-Lentgh ãåå¨ãããã©ãããã§ãã¯
+ if (GetHttpValue(header, "Content-Length") == NULL)
+ {
+ char tmp[MAX_SIZE];
+ // åå¨ããªãã®ã§ä»å ãã
+ ToStr(tmp, post_size);
+ AddHttpValue(header, NewHttpValue("Content-Length", tmp));
+ }
+
+ // ããããæååã«ãã
+ header_str = HttpHeaderToStr(header);
+ if (header_str == NULL)
+ {
+ return false;
+ }
+ b = NewBuf();
+ WriteBuf(b, header_str, StrLen(header_str));
+ Free(header_str);
+
+ // ãã¼ã¿ã追è¨ãã
+ WriteBuf(b, post_data, post_size);
+
+ // éä¿¡ãã
+ ret = SendAll(s, b->Buf, b->Size, s->SecureMode);
+
+ FreeBuf(b);
+
+ return ret;
+}
+
+// HTTP ããããæååã«å¤æ
+char *HttpHeaderToStr(HTTP_HEADER *header)
+{
+ BUF *b;
+ char *tmp;
+ UINT i;
+ char *s;
+ // å¼æ°ãã§ãã¯
+ if (header == NULL)
+ {
+ return NULL;
+ }
+
+ tmp = Malloc(HTTP_HEADER_LINE_MAX_SIZE);
+ b = NewBuf();
+
+ // ããã
+ Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
+ "%s %s %s\r\n", header->Method, header->Target, header->Version);
+ WriteBuf(b, tmp, StrLen(tmp));
+
+ // å¤
+ for (i = 0;i < LIST_NUM(header->ValueList);i++)
+ {
+ HTTP_VALUE *v = (HTTP_VALUE *)LIST_DATA(header->ValueList, i);
+ Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
+ "%s: %s\r\n", v->Name, v->Data);
+ WriteBuf(b, tmp, StrLen(tmp));
+ }
+
+ // æå¾ã®æ¹è¡
+ WriteBuf(b, "\r\n", 2);
+ s = Malloc(b->Size + 1);
+ Copy(s, b->Buf, b->Size);
+ s[b->Size] = 0;
+
+ FreeBuf(b);
+ Free(tmp);
+
+ return s;
+}
+
+// HTTP ããããéä¿¡
+bool SendHttpHeader(SOCK *s, HTTP_HEADER *header)
+{
+ char *str;
+ bool ret;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || header == NULL)
+ {
+ return false;
+ }
+
+ // æååã«å¤æ
+ str = HttpHeaderToStr(header);
+
+ // éä¿¡
+ ret = SendAll(s, str, StrLen(str), s->SecureMode);
+
+ Free(str);
+
+ return ret;
+}
+
+// HTTP ããããåä¿¡
+HTTP_HEADER *RecvHttpHeader(SOCK *s)
+{
+ TOKEN_LIST *token = NULL;
+ char *str = NULL;
+ HTTP_HEADER *header = NULL;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL)
+ {
+ return NULL;
+ }
+
+ // 1 è¡ç®ãåå¾ãã
+ str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
+ if (str == NULL)
+ {
+ goto ERROR;
+ }
+
+ // ãã¼ã¯ã³ã«åå²ãã
+ token = ParseToken(str, " ");
+ if (token->NumTokens < 3)
+ {
+ goto ERROR;
+ }
+
+ Free(str);
+ str = NULL;
+
+ // ãããã®ä½æ
+ header = NewHttpHeader(token->Token[0], token->Token[1], token->Token[2]);
+
+ if (!StrCmpi(header->Version, "HTTP/1.0") || !StrCmpi(header->Version, "HTTP/0.9"))
+ {
+ // ãã®è¡ã§çµãã
+ return header;
+ }
+
+ // 2 è¡ç®ä»¥éãåå¾ãã
+ while (true)
+ {
+ UINT pos;
+ HTTP_VALUE *v;
+ char *value_name, *value_data;
+ str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
+ if (str == NULL)
+ {
+ goto ERROR;
+ }
+ Trim(str);
+
+ if (StrLen(str) == 0)
+ {
+ // ãããã®çµäº
+ Free(str);
+ str = NULL;
+ break;
+ }
+
+ // ã³ãã³ã®ä½ç½®ãåå¾ãã
+ pos = SearchStr(str, ":", 0);
+ if (pos == INFINITE)
+ {
+ // ã³ãã³ãåå¨ããªã
+ goto ERROR;
+ }
+ if ((pos + 1) >= StrLen(str))
+ {
+ // ãã¼ã¿ãåå¨ããªã
+ goto ERROR;
+ }
+
+ // ååã¨ãã¼ã¿ã® 2 ã¤ã«åãã
+ value_name = Malloc(pos + 1);
+ Copy(value_name, str, pos);
+ value_name[pos] = 0;
+ value_data = &str[pos + 1];
+
+ v = NewHttpValue(value_name, value_data);
+ if (v == NULL)
+ {
+ Free(value_name);
+ goto ERROR;
+ }
+
+ Free(value_name);
+
+ AddHttpValue(header, v);
+ Free(str);
+ }
+
+ FreeToken(token);
+
+ return header;
+
+ERROR:
+ // ã¡ã¢ãªè§£æ¾
+ if (token)
+ {
+ FreeToken(token);
+ }
+ if (str)
+ {
+ Free(str);
+ }
+ if (header)
+ {
+ FreeHttpHeader(header);
+ }
+ return NULL;
+}
+
+// 1 è¡ãåä¿¡ãã
+char *RecvLine(SOCK *s, UINT max_size)
+{
+ BUF *b;
+ char c;
+ char *str;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || max_size == 0)
+ {
+ return NULL;
+ }
+
+ b = NewBuf();
+ while (true)
+ {
+ UCHAR *buf;
+ if (RecvAll(s, &c, sizeof(c), s->SecureMode) == false)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+ WriteBuf(b, &c, sizeof(c));
+ buf = (UCHAR *)b->Buf;
+ if (b->Size > max_size)
+ {
+ FreeBuf(b);
+ return NULL;
+ }
+ if (b->Size >= 1)
+ {
+ if (buf[b->Size - 1] == '\n')
+ {
+ b->Size--;
+ if (b->Size >= 1)
+ {
+ if (buf[b->Size - 1] == '\r')
+ {
+ b->Size--;
+ }
+ }
+ str = Malloc(b->Size + 1);
+ Copy(str, b->Buf, b->Size);
+ str[b->Size] = 0;
+ FreeBuf(b);
+
+ return str;
+ }
+ }
+ }
+}
+
+// æ°ãã HTTP å¤ã®ä½æ
+HTTP_VALUE *NewHttpValue(char *name, char *data)
+{
+ HTTP_VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (name == NULL || data == NULL)
+ {
+ return NULL;
+ }
+
+ v = ZeroMalloc(sizeof(HTTP_VALUE));
+
+ v->Name = CopyStr(name);
+ v->Data = CopyStr(data);
+
+ Trim(v->Name);
+ Trim(v->Data);
+
+ return v;
+}
+
+// ãããã³ã«ã«ã¼ãã³ã®åæå
+void InitProtocol()
+{
+}
+
+// ãããã³ã«ã«ã¼ãã³ã®è§£æ¾
+void FreeProtocol()
+{
+}
+
+// HTTP ããããã HTTP å¤ãæ¢ã
+HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name)
+{
+ HTTP_VALUE *v, t;
+ // å¼æ°ãã§ãã¯
+ if (header == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ t.Name = name;
+ v = Search(header->ValueList, &t);
+ if (v == NULL)
+ {
+ return NULL;
+ }
+
+ return v;
+}
+
+// HTTP ãããã« HTTP å¤ã追å
+void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value)
+{
+ // å¼æ°ãã§ãã¯
+ if (header == NULL || value == NULL)
+ {
+ return;
+ }
+
+ Insert(header->ValueList, value);
+}
+
+// HTTP ããããä½æ
+HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version)
+{
+ HTTP_HEADER *header;
+ // å¼æ°ãã§ãã¯
+ if (method == NULL || target == NULL || version == NULL)
+ {
+ return NULL;
+ }
+
+ header = ZeroMalloc(sizeof(HTTP_HEADER));
+
+ header->Method = CopyStr(method);
+ header->Target = CopyStr(target);
+ header->Version = CopyStr(version);
+ header->ValueList = NewListFast(CompareHttpValue);
+
+ return header;
+}
+
+// HTTP å¤ã®æ¯è¼é¢æ°
+int CompareHttpValue(void *p1, void *p2)
+{
+ HTTP_VALUE *v1, *v2;
+ if (p1 == NULL || p2 == NULL)
+ {
+ return 0;
+ }
+ v1 = *(HTTP_VALUE **)p1;
+ v2 = *(HTTP_VALUE **)p2;
+ if (v1 == NULL || v2 == NULL)
+ {
+ return 0;
+ }
+ return StrCmpi(v1->Name, v2->Name);
+}
+
+// HTTP å¤ã解æ¾
+void FreeHttpValue(HTTP_VALUE *value)
+{
+ // å¼æ°ãã§ãã¯
+ if (value == NULL)
+ {
+ return;
+ }
+
+ Free(value->Data);
+ Free(value->Name);
+
+ Free(value);
+}
+
+// HTTP ãããã解æ¾
+void FreeHttpHeader(HTTP_HEADER *header)
+{
+ UINT i;
+ HTTP_VALUE **values;
+ // å¼æ°ãã§ãã¯
+ if (header == NULL)
+ {
+ return;
+ }
+
+ Free(header->Method);
+ Free(header->Target);
+ Free(header->Version);
+
+ values = ToArray(header->ValueList);
+ for (i = 0;i < LIST_NUM(header->ValueList);i++)
+ {
+ FreeHttpValue(values[i]);
+ }
+ Free(values);
+
+ ReleaseList(header->ValueList);
+
+ Free(header);
+}
+
+// ãã±ãããåä¿¡
+PACK *RecvPack(SOCK *s)
+{
+ PACK *p;
+ BUF *b;
+ void *data;
+ UINT sz;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ if (RecvAll(s, &sz, sizeof(UINT), s->SecureMode) == false)
+ {
+ return false;
+ }
+ sz = Endian32(sz);
+ if (sz > MAX_PACK_SIZE)
+ {
+ return false;
+ }
+ data = MallocEx(sz, true);
+ if (RecvAll(s, data, sz, s->SecureMode) == false)
+ {
+ Free(data);
+ return false;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, data, sz);
+ SeekBuf(b, 0, 0);
+ p = BufToPack(b);
+ FreeBuf(b);
+ Free(data);
+
+ return p;
+}
+
+// ãã±ãããéä¿¡
+bool SendPack(SOCK *s, PACK *p)
+{
+ BUF *b;
+ UINT sz;
+ // å¼æ°ãã§ãã¯
+ if (s == NULL || p == NULL || s->Type != SOCK_TCP)
+ {
+ return false;
+ }
+
+ b = PackToBuf(p);
+ sz = Endian32(b->Size);
+
+ SendAdd(s, &sz, sizeof(UINT));
+ SendAdd(s, b->Buf, b->Size);
+ FreeBuf(b);
+
+ return SendNow(s, s->SecureMode);
+}
+
+// Hello ãã±ãããä½æ
+PACK *PackHello(void *random, UINT ver, UINT build, char *server_str)
+{
+ PACK *p;
+ // å¼æ°ãã§ãã¯
+ if (random == NULL || server_str == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "hello", server_str);
+ PackAddInt(p, "version", ver);
+ PackAddInt(p, "build", build);
+ PackAddData(p, "random", random, SHA1_SIZE);
+
+ return p;
+}
+
+// Hello ãã±ããã解é
+bool GetHello(PACK *p, void *random, UINT *ver, UINT *build, char *server_str, UINT server_str_size)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || random == NULL || ver == NULL || server_str == NULL)
+ {
+ return false;
+ }
+
+ if (PackGetStr(p, "hello", server_str, server_str_size) == false)
+ {
+ return false;
+ }
+ *ver = PackGetInt(p, "version");
+ *build = PackGetInt(p, "build");
+ if (PackGetDataSize(p, "random") != SHA1_SIZE)
+ {
+ return false;
+ }
+ if (PackGetData(p, "random", random) == false)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+// ã¨ã©ã¼å¤ã PACK ã«æ ¼ç´
+PACK *PackError(UINT error)
+{
+ PACK *p;
+
+ p = NewPack();
+ PackAddInt(p, "error", error);
+
+ return p;
+}
+
+// ã¨ã©ã¼å¤ã PACK ããåå¾
+UINT GetErrorFromPack(PACK *p)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ return PackGetInt(p, "error");
+}
+
+// èªè¨¼æ¹æ³ã PACK ããåå¾
+UINT GetAuthTypeFromPack(PACK *p)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+ return PackGetInt(p, "authtype");
+}
+
+// ã¦ã¼ã¶ã¼å㨠HUB åã PACK ããåå¾
+bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
+ char *hubname, UINT hubname_size)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || username == NULL || hubname == NULL)
+ {
+ return false;
+ }
+
+ if (PackGetStr(p, "username", username, username_size) == false)
+ {
+ return false;
+ }
+ if (PackGetStr(p, "hubname", hubname, hubname_size) == false)
+ {
+ return false;
+ }
+ return true;
+}
+
+// ãããã³ã«ã PACK ããåå¾
+UINT GetProtocolFromPack(PACK *p)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL)
+ {
+ return 0;
+ }
+
+#if 0
+ return PackGetInt(p, "protocol");
+#else
+ // ç¾ãã¼ã¸ã§ã³ã§ã¯ TCP ãããã³ã«ã«éå®ãã
+ return CONNECTION_TCP;
+#endif
+}
+
+// ã¡ã½ããã PACK ããåå¾
+bool GetMethodFromPack(PACK *p, char *method, UINT size)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || method == NULL || size == 0)
+ {
+ return false;
+ }
+
+ return PackGetStr(p, "method", method, size);
+}
+
+// 証ææ¸èªè¨¼ãã°ã¤ã³ç¨ã®ãã±ãããçæ
+PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size)
+{
+ PACK *p;
+ BUF *b;
+ // å¼æ°ãã§ãã¯
+ if (hubname == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddInt(p, "authtype", CLIENT_AUTHTYPE_CERT);
+
+ // 証ææ¸
+ b = XToBuf(x, false);
+ PackAddData(p, "cert", b->Buf, b->Size);
+ FreeBuf(b);
+
+ // ç½²åãã¼ã¿
+ PackAddData(p, "sign", sign, sign_size);
+
+ return p;
+}
+
+// å¹³æãã¹ã¯ã¼ãèªè¨¼ãã°ã¤ã³ç¨ã®ãã±ãããçæ
+PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password)
+{
+ PACK *p;
+ // å¼æ°ãã§ãã¯
+ if (hubname == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PLAIN_PASSWORD);
+ PackAddStr(p, "plain_password", plain_password);
+
+ return p;
+}
+
+// ãã¹ã¯ã¼ãèªè¨¼ãã°ã¤ã³ç¨ã®ãã±ãããä½æ
+PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password)
+{
+ PACK *p;
+ // å¼æ°ãã§ãã¯
+ if (hubname == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PASSWORD);
+ PackAddData(p, "secure_password", secure_password, SHA1_SIZE);
+
+ return p;
+}
+
+// å¿åãã°ã¤ã³ç¨ã®ãã±ãããä½æ
+PACK *PackLoginWithAnonymous(char *hubname, char *username)
+{
+ PACK *p;
+ // å¼æ°ãã§ãã¯
+ if (hubname == NULL || username == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "login");
+ PackAddStr(p, "hubname", hubname);
+ PackAddStr(p, "username", username);
+ PackAddInt(p, "authtype", CLIENT_AUTHTYPE_ANONYMOUS);
+
+ return p;
+}
+
+// 追å æ¥ç¶ç¨ã®ãã±ãããä½æ
+PACK *PackAdditionalConnect(UCHAR *session_key)
+{
+ PACK *p;
+ // å¼æ°ãã§ãã¯
+ if (session_key == NULL)
+ {
+ return NULL;
+ }
+
+ p = NewPack();
+ PackAddStr(p, "method", "additional_connect");
+ PackAddData(p, "session_key", session_key, SHA1_SIZE);
+
+ return p;
+}
+
+// PACK ãã K ãåå¾
+K *PackGetK(PACK *p, char *name)
+{
+ K *k;
+ BUF *b;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ b = PackGetBuf(p, name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ k = BufToK(b, true, false, NULL);
+ FreeBuf(b);
+
+ return k;
+}
+
+// PACK ãã X ãåå¾
+X *PackGetX(PACK *p, char *name)
+{
+ X *x;
+ BUF *b;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ b = PackGetBuf(p, name);
+ if (b == NULL)
+ {
+ return NULL;
+ }
+
+ x = BufToX(b, false);
+ FreeBuf(b);
+
+ return x;
+}
+
+// PACK ã« K ã追å
+void PackAddK(PACK *p, char *name, K *k)
+{
+ BUF *b;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || k == NULL)
+ {
+ return;
+ }
+
+ b = KToBuf(k, false, NULL);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ PackAddBuf(p, name, b);
+ FreeBuf(b);
+}
+
+// PACK ã« X ã追å
+void PackAddX(PACK *p, char *name, X *x)
+{
+ BUF *b;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || x == NULL)
+ {
+ return;
+ }
+
+ b = XToBuf(x, false);
+ if (b == NULL)
+ {
+ return;
+ }
+
+ PackAddBuf(p, name, b);
+ FreeBuf(b);
+}
+
+// PACK ãããããã¡ãåå¾
+BUF *PackGetBuf(PACK *p, char *name)
+{
+ return PackGetBufEx(p, name, 0);
+}
+BUF *PackGetBufEx(PACK *p, char *name, UINT index)
+{
+ UINT size;
+ void *tmp;
+ BUF *b;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return NULL;
+ }
+
+ size = PackGetDataSizeEx(p, name, index);
+ tmp = MallocEx(size, true);
+ if (PackGetDataEx(p, name, tmp, index) == false)
+ {
+ Free(tmp);
+ return NULL;
+ }
+
+ b = NewBuf();
+ WriteBuf(b, tmp, size);
+ SeekBuf(b, 0, 0);
+
+ Free(tmp);
+
+ return b;
+}
+
+// PACK ãããã¼ã¿ãåå¾
+bool PackGetData(PACK *p, char *name, void *data)
+{
+ return PackGetDataEx(p, name, data, 0);
+}
+bool PackGetDataEx(PACK *p, char *name, void *data, UINT index)
+{
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return false;
+ }
+ Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
+ return true;
+}
+bool PackGetData2(PACK *p, char *name, void *data, UINT size)
+{
+ return PackGetDataEx2(p, name, data, size, 0);
+}
+bool PackGetDataEx2(PACK *p, char *name, void *data, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return false;
+ }
+ if (GetDataValueSize(e, index) != size)
+ {
+ return false;
+ }
+ Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
+ return true;
+}
+
+// PACK ãããã¼ã¿ãµã¤ãºãåå¾
+UINT PackGetDataSize(PACK *p, char *name)
+{
+ return PackGetDataSizeEx(p, name, 0);
+}
+UINT PackGetDataSizeEx(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_DATA);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetDataValueSize(e, index);
+}
+
+// PACK ããæ´æ°ãåå¾
+UINT64 PackGetInt64(PACK *p, char *name)
+{
+ return PackGetInt64Ex(p, name, 0);
+}
+UINT64 PackGetInt64Ex(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_INT64);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetInt64Value(e, index);
+}
+
+// PACK ããã¤ã³ããã¯ã¹æ°ãåå¾
+UINT PackGetIndexCount(PACK *p, char *name)
+{
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, INFINITE);
+ if (e == NULL)
+ {
+ return 0;
+ }
+
+ return e->num_value;
+}
+
+// PACK ããåæ°ãåå¾
+UINT PackGetNum(PACK *p, char *name)
+{
+ return MIN(PackGetInt(p, name), 65536);
+}
+
+// PACK ãã bool åãåå¾
+bool PackGetBool(PACK *p, char *name)
+{
+ return PackGetInt(p, name) == 0 ? false : true;
+}
+bool PackGetBoolEx(PACK *p, char *name, UINT index)
+{
+ return PackGetIntEx(p, name, index) == 0 ? false : true;
+}
+
+// PACK ã« bool åã追å
+void PackAddBool(PACK *p, char *name, bool b)
+{
+ PackAddInt(p, name, b ? 1 : 0);
+}
+void PackAddBoolEx(PACK *p, char *name, bool b, UINT index, UINT total)
+{
+ PackAddIntEx(p, name, b ? 1 : 0, index, total);
+}
+
+// PACK ã« IPV6_ADDR ã追å
+void PackAddIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index, UINT total)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || addr == NULL)
+ {
+ return;
+ }
+
+ PackAddDataEx(p, name, addr, sizeof(IPV6_ADDR), index, total);
+}
+void PackAddIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
+{
+ PackAddIp6AddrEx(p, name, addr, 0, 1);
+}
+
+// PACK ãã IPV6_ADDR ãåå¾
+bool PackGetIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || addr == NULL)
+ {
+ Zero(addr, sizeof(IPV6_ADDR));
+ return false;
+ }
+
+ return PackGetDataEx2(p, name, addr, sizeof(IPV6_ADDR), index);
+}
+bool PackGetIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
+{
+ return PackGetIp6AddrEx(p, name, addr, 0);
+}
+
+// PACK ã« IP ã追å
+void PackAddIp32Ex(PACK *p, char *name, UINT ip32, UINT index, UINT total)
+{
+ IP ip;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ UINTToIP(&ip, ip32);
+
+ PackAddIpEx(p, name, &ip, index, total);
+}
+void PackAddIp32(PACK *p, char *name, UINT ip32)
+{
+ PackAddIp32Ex(p, name, ip32, 0, 1);
+}
+void PackAddIpEx(PACK *p, char *name, IP *ip, UINT index, UINT total)
+{
+ UINT i;
+ bool b = false;
+ char tmp[MAX_PATH];
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || ip == NULL)
+ {
+ return;
+ }
+
+ b = IsIP6(ip);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
+ PackAddBoolEx(p, tmp, b, index, total);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
+ if (b)
+ {
+ PackAddDataEx(p, tmp, ip->ipv6_addr, sizeof(ip->ipv6_addr), index, total);
+ }
+ else
+ {
+ UCHAR dummy[16];
+
+ Zero(dummy, sizeof(dummy));
+
+ PackAddDataEx(p, tmp, dummy, sizeof(dummy), index, total);
+ }
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
+ if (b)
+ {
+ PackAddIntEx(p, tmp, ip->ipv6_scope_id, index, total);
+ }
+ else
+ {
+ PackAddIntEx(p, tmp, 0, index, total);
+ }
+
+ i = IPToUINT(ip);
+
+ if (IsBigEndian())
+ {
+ i = Swap32(i);
+ }
+
+ PackAddIntEx(p, name, i, index, total);
+}
+void PackAddIp(PACK *p, char *name, IP *ip)
+{
+ PackAddIpEx(p, name, ip, 0, 1);
+}
+
+// PACK ãã IP ãåå¾
+UINT PackGetIp32Ex(PACK *p, char *name, UINT index)
+{
+ IP ip;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ if (PackGetIpEx(p, name, &ip, index) == false)
+ {
+ return 0;
+ }
+
+ return IPToUINT(&ip);
+}
+UINT PackGetIp32(PACK *p, char *name)
+{
+ return PackGetIp32Ex(p, name, 0);
+}
+bool PackGetIpEx(PACK *p, char *name, IP *ip, UINT index)
+{
+ UINT i;
+ char tmp[MAX_PATH];
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || ip == NULL || name == NULL)
+ {
+ return false;
+ }
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
+ if (PackGetBoolEx(p, tmp, index))
+ {
+ UCHAR data[16];
+ UINT scope_id;
+
+ Zero(data, sizeof(data));
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
+ PackGetDataEx2(p, tmp, data, sizeof(data), index);
+
+ Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
+ scope_id = PackGetIntEx(p, tmp, index);
+
+ SetIP6(ip, data);
+ ip->ipv6_scope_id = scope_id;
+ }
+ else
+ {
+ if (GetElement(p, name, VALUE_INT) == NULL)
+ {
+ Zero(ip, sizeof(IP));
+ return false;
+ }
+
+ i = PackGetIntEx(p, name, index);
+
+ if (IsBigEndian())
+ {
+ i = Swap32(i);
+ }
+
+ UINTToIP(ip, i);
+ }
+
+ return true;
+}
+bool PackGetIp(PACK *p, char *name, IP *ip)
+{
+ return PackGetIpEx(p, name, ip, 0);
+}
+
+// PACK ããæ´æ°ãåå¾
+UINT PackGetInt(PACK *p, char *name)
+{
+ return PackGetIntEx(p, name, 0);
+}
+UINT PackGetIntEx(PACK *p, char *name, UINT index)
+{
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return 0;
+ }
+
+ e = GetElement(p, name, VALUE_INT);
+ if (e == NULL)
+ {
+ return 0;
+ }
+ return GetIntValue(e, index);
+}
+
+// PACK ãã Unicode æååãåå¾
+bool PackGetUniStr(PACK *p, char *name, wchar_t *unistr, UINT size)
+{
+ return PackGetUniStrEx(p, name, unistr, size, 0);
+}
+bool PackGetUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || unistr == NULL || size == 0)
+ {
+ return false;
+ }
+
+ unistr[0] = 0;
+
+ e = GetElement(p, name, VALUE_UNISTR);
+ if (e == NULL)
+ {
+ return false;
+ }
+ UniStrCpy(unistr, size, GetUniStrValue(e, index));
+ return true;
+}
+
+// PACK ããæååãåå¾
+bool PackGetStr(PACK *p, char *name, char *str, UINT size)
+{
+ return PackGetStrEx(p, name, str, size, 0);
+}
+bool PackGetStrEx(PACK *p, char *name, char *str, UINT size, UINT index)
+{
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || str == NULL || size == 0)
+ {
+ return false;
+ }
+
+ str[0] = 0;
+
+ e = GetElement(p, name, VALUE_STR);
+ if (e == NULL)
+ {
+ return false;
+ }
+
+ StrCpy(str, size, GetStrValue(e, index));
+ return true;
+}
+
+// ãããã¡ã PACK ã«è¿½å (é
å)
+void PackAddBufEx(PACK *p, char *name, BUF *b, UINT index, UINT total)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || b == NULL || total == 0)
+ {
+ return;
+ }
+
+ PackAddDataEx(p, name, b->Buf, b->Size, index, total);
+}
+
+// ãã¼ã¿ã PACK ã«è¿½å (é
å)
+void PackAddDataEx(PACK *p, char *name, void *data, UINT size, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || data == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewDataValue(data, size);
+ e = GetElement(p, name, VALUE_DATA);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_DATA);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_DATA;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// ãããã¡ã PACK ã«è¿½å
+void PackAddBuf(PACK *p, char *name, BUF *b)
+{
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || b == NULL)
+ {
+ return;
+ }
+
+ PackAddData(p, name, b->Buf, b->Size);
+}
+
+// ãã¼ã¿ã PACK ã«è¿½å
+void PackAddData(PACK *p, char *name, void *data, UINT size)
+{
+ VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || data == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewDataValue(data, size);
+ AddElement(p, NewElement(name, VALUE_DATA, 1, &v));
+}
+
+// 64 bit æ´æ°ã PACK ã«è¿½å (é
å)
+void PackAddInt64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewInt64Value(i);
+ e = GetElement(p, name, VALUE_INT64);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_INT64);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_INT64;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// æ´æ°ã PACK ã«è¿½å (é
å)
+void PackAddIntEx(PACK *p, char *name, UINT i, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewIntValue(i);
+ e = GetElement(p, name, VALUE_INT);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_INT);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_INT;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// 64 bit æ´æ°ã PACK ã«è¿½å
+void PackAddInt64(PACK *p, char *name, UINT64 i)
+{
+ VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewInt64Value(i);
+ AddElement(p, NewElement(name, VALUE_INT64, 1, &v));
+}
+
+// åæ°ã PACK ã«è¿½å
+void PackAddNum(PACK *p, char *name, UINT num)
+{
+ PackAddInt(p, name, num);
+}
+
+// æ´æ°ã PACK ã«è¿½å
+void PackAddInt(PACK *p, char *name, UINT i)
+{
+ VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL)
+ {
+ return;
+ }
+
+ v = NewIntValue(i);
+ AddElement(p, NewElement(name, VALUE_INT, 1, &v));
+}
+
+// Unicode æååã PACK ã«è¿½å (é
å)
+void PackAddUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || unistr == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewUniStrValue(unistr);
+ e = GetElement(p, name, VALUE_UNISTR);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_UNISTR);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_UNISTR;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// Unicode æååã PACK ã«è¿½å
+void PackAddUniStr(PACK *p, char *name, wchar_t *unistr)
+{
+ VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || unistr == NULL)
+ {
+ return;
+ }
+
+ v = NewUniStrValue(unistr);
+ AddElement(p, NewElement(name, VALUE_UNISTR, 1, &v));
+}
+
+// æååã PACK ã«è¿½å (é
å)
+void PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total)
+{
+ VALUE *v;
+ ELEMENT *e;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || str == NULL || total == 0)
+ {
+ return;
+ }
+
+ v = NewStrValue(str);
+ e = GetElement(p, name, VALUE_STR);
+ if (e != NULL)
+ {
+ if (e->num_value <= total)
+ {
+ e->values[index] = v;
+ }
+ else
+ {
+ FreeValue(v, VALUE_STR);
+ }
+ }
+ else
+ {
+ e = ZeroMallocEx(sizeof(ELEMENT), true);
+ StrCpy(e->name, sizeof(e->name), name);
+ e->num_value = total;
+ e->type = VALUE_STR;
+ e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
+ e->values[index] = v;
+ AddElement(p, e);
+ }
+}
+
+// æååã PACK ã«è¿½å
+void PackAddStr(PACK *p, char *name, char *str)
+{
+ VALUE *v;
+ // å¼æ°ãã§ãã¯
+ if (p == NULL || name == NULL || str == NULL)
+ {
+ return;
+ }
+
+ v = NewStrValue(str);
+ AddElement(p, NewElement(name, VALUE_STR, 1, &v));
+}
+
+// RC4 ãã¼ãã¢ãçæ
+void GenerateRC4KeyPair(RC4_KEY_PAIR *k)
+{
+ // å¼æ°ãã§ãã¯
+ if (k == NULL)
+ {
+ return;
+ }
+
+ Rand(k->ClientToServerKey, sizeof(k->ClientToServerKey));
+ Rand(k->ServerToClientKey, sizeof(k->ServerToClientKey));
+}
+