source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Protocol.c @ 23aa5e1

trunk
Last change on this file since 23aa5e1 was a1bae3e, checked in by mitty <mitty@…>, 12 years ago
  • copy vendor drop to trunk

git-svn-id: https://lab.mitty.jp/svn/lab/trunk@147 7d2118f6-f56c-43e7-95a2-4bb3031d96e7

  • Property mode set to 100644
File size: 157.7 KB
Line 
1// SoftEther UT-VPN SourceCode
2//
3// Copyright (C) 2004-2010 SoftEther Corporation.
4// Copyright (C) 2004-2010 University of Tsukuba, Japan.
5// Copyright (C) 2003-2010 Daiyuu Nobori.
6// All Rights Reserved.
7//
8// http://utvpn.tsukuba.ac.jp/
9//
10// This program is free software; you can redistribute it and/or
11// modify it under the terms of the GNU General Public License
12// version 2 as published by the Free Software Foundation.
13//
14// This program is distributed in the hope that it will be useful,
15// but WITHOUT ANY WARRANTY; without even the implied warranty of
16// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17// GNU General Public License for more details.
18//
19// You should have received a copy of the GNU General Public License version 2
20// along with this program; if not, write to the Free Software
21// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
22//
23// このファイルは GPL バージョン 2 ライセンスで公開されています。
24// 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布
25// することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示
26// を除去することはできません。改変した著作物を配布する場合は、改変実施者の
27// 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。
28//
29// この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の
30// ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )
31// および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって
32// ホストされています。
33// 本プログラムの配布者は、本プログラムを、業としての利用以外のため、
34// および、試験または研究のために利用が行われることを想定して配布
35// しています。
36// SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に
37// あります。
38// 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード
39// の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して
40// いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して
41// ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース
42// に組み込みさせていただきます。
43//
44// GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する
45// 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。
46//
47// 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社
48// (SoftEther Corporation) およびその他の著作権保持者が保有しています。
49// ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの
50// 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意
51// ください。
52//
53// お願い: どのような通信ソフトウェアにも通常は必ず未発見の
54// セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、
55// UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの
56// 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社
57// および脆弱性情報の届出を受け付ける公的機関まで通報いただき、
58// 公益保護にご協力いただきますようお願い申し上げます。
59//
60// ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を
61// 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客
62// を保護するための努力を行います。
63//
64// ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/
65// 日本国内の脆弱性情報届出受付公的機関:
66//         独立行政法人 情報処理推進機構
67//         http://www.ipa.go.jp/security/vuln/report/
68//
69// 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。
70// 連絡先: http://www.softether.co.jp/jp/contact/
71
72// -----------------------------------------------
73// [ChangeLog]
74// 2010.05.20
75//  新規リリース by SoftEther
76// -----------------------------------------------
77
78// Protocol.c
79// SoftEther プロトコル関係のルーチン
80
81#include "CedarPch.h"
82
83static char http_404_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>404 Not Found</TITLE>\r\n</HEAD><BODY>\r\n<H1>Not Found</H1>\r\nThe requested URL $TARGET$ was not found on this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
84static char http_403_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>403 Forbidden</TITLE>\r\n</HEAD><BODY>\r\n<H1>Forbidden</H1>\r\nYou don't have permission to access $TARGET$\r\non this server.<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
85static char http_501_str[] = "<!DOCTYPE HTML PUBLIC \"-//IETF//DTD HTML 2.0//EN\">\r\n<HTML><HEAD>\r\n<TITLE>501 Method Not Implemented</TITLE>\r\n</HEAD><BODY>\r\n<H1>Method Not Implemented</H1>\r\n$METHOD$ to $TARGET$ not supported.<P>\r\nInvalid method in request $METHOD$ $TARGET$ $VERSION$<P>\r\n<HR>\r\n<ADDRESS>HTTP Server at $HOST$ Port $PORT$</ADDRESS>\r\n</BODY></HTML>\r\n";
86
87// マシンごとにユニークな ID を生成する
88void GenerateMachineUniqueHash(void *data)
89{
90    BUF *b;
91    char name[64];
92    char ip_str[64];
93    IP ip;
94    OS_INFO *osinfo;
95    // 引数チェック
96    if (data == NULL)
97    {
98        return;
99    }
100
101    b = NewBuf();
102    GetMachineName(name, sizeof(name));
103    GetMachineIp(&ip);
104    IPToStr(ip_str, sizeof(ip_str), &ip);
105
106    osinfo = GetOsInfo();
107
108    WriteBuf(b, name, StrLen(name));
109    WriteBuf(b, ip_str, StrLen(ip_str));
110
111    WriteBuf(b, &osinfo->OsType, sizeof(osinfo->OsType));
112    WriteBuf(b, osinfo->KernelName, StrLen(osinfo->KernelName));
113    WriteBuf(b, osinfo->KernelVersion, StrLen(osinfo->KernelVersion));
114    WriteBuf(b, osinfo->OsProductName, StrLen(osinfo->OsProductName));
115    WriteBuf(b, &osinfo->OsServicePack, sizeof(osinfo->OsServicePack));
116    WriteBuf(b, osinfo->OsSystemName, StrLen(osinfo->OsSystemName));
117    WriteBuf(b, osinfo->OsVendorName, StrLen(osinfo->OsVendorName));
118    WriteBuf(b, osinfo->OsVersion, StrLen(osinfo->OsVersion));
119
120    Hash(data, b->Buf, b->Size, true);
121
122    FreeBuf(b);
123}
124
125// ノード情報を文字列に変換する
126void NodeInfoToStr(wchar_t *str, UINT size, NODE_INFO *info)
127{
128    char client_ip[128], server_ip[128], proxy_ip[128], unique_id[128];
129    // 引数チェック
130    if (str == NULL || info == NULL)
131    {
132        return;
133    }
134
135    IPToStr4or6(client_ip, sizeof(client_ip), info->ClientIpAddress, info->ClientIpAddress6);
136    IPToStr4or6(server_ip, sizeof(server_ip), info->ServerIpAddress, info->ServerIpAddress6);
137    IPToStr4or6(proxy_ip, sizeof(proxy_ip), info->ProxyIpAddress, info->ProxyIpAddress6);
138    BinToStr(unique_id, sizeof(unique_id), info->UniqueId, sizeof(info->UniqueId));
139
140    UniFormat(str, size, _UU("LS_NODE_INFO_TAG"), info->ClientProductName,
141        Endian32(info->ClientProductVer), Endian32(info->ClientProductBuild),
142        info->ServerProductName, Endian32(info->ServerProductVer), Endian32(info->ServerProductBuild),
143        info->ClientOsName, info->ClientOsVer, info->ClientOsProductId,
144        info->ClientHostname, client_ip, Endian32(info->ClientPort),
145        info->ServerHostname, server_ip, Endian32(info->ServerPort),
146        info->ProxyHostname, proxy_ip, Endian32(info->ProxyPort),
147        info->HubName, unique_id);
148}
149
150// ノード情報の比較
151bool CompareNodeInfo(NODE_INFO *a, NODE_INFO *b)
152{
153    // 引数チェック
154    if (a == NULL || b == NULL)
155    {
156        return false;
157    }
158
159    // このあたりは急いで実装したのでコードがあまり美しくない。
160    if (StrCmp(a->ClientProductName, b->ClientProductName) != 0)
161    {
162        return false;
163    }
164    if (a->ClientProductVer != b->ClientProductVer)
165    {
166        return false;
167    }
168    if (a->ClientProductBuild != b->ClientProductBuild)
169    {
170        return false;
171    }
172    if (StrCmp(a->ServerProductName, b->ServerProductName) != 0)
173    {
174        return false;
175    }
176    if (a->ServerProductVer != b->ServerProductVer)
177    {
178        return false;
179    }
180    if (a->ServerProductBuild != b->ServerProductBuild)
181    {
182        return false;
183    }
184    if (StrCmp(a->ClientOsName, b->ClientOsName) != 0)
185    {
186        return false;
187    }
188    if (StrCmp(a->ClientOsVer, b->ClientOsVer) != 0)
189    {
190        return false;
191    }
192    if (StrCmp(a->ClientOsProductId, b->ClientOsProductId) != 0)
193    {
194        return false;
195    }
196    if (StrCmp(a->ClientHostname, b->ClientHostname) != 0)
197    {
198        return false;
199    }
200    if (a->ClientIpAddress != b->ClientIpAddress)
201    {
202        return false;
203    }
204    if (StrCmp(a->ServerHostname, b->ServerHostname) != 0)
205    {
206        return false;
207    }
208    if (a->ServerIpAddress != b->ServerIpAddress)
209    {
210        return false;
211    }
212    if (a->ServerPort != b->ServerPort)
213    {
214        return false;
215    }
216    if (StrCmp(a->ProxyHostname, b->ProxyHostname) != 0)
217    {
218        return false;
219    }
220    if (a->ProxyIpAddress != b->ProxyIpAddress)
221    {
222        return false;
223    }
224    if (a->ProxyPort != b->ProxyPort)
225    {
226        return false;
227    }
228    if (StrCmp(a->HubName, b->HubName) != 0)
229    {
230        return false;
231    }
232    if (Cmp(a->UniqueId, b->UniqueId, 16) != 0)
233    {
234        return false;
235    }
236
237    return true;
238}
239
240// パスワード変更受付
241UINT ChangePasswordAccept(CONNECTION *c, PACK *p)
242{
243    CEDAR *cedar;
244    UCHAR random[SHA1_SIZE];
245    char hubname[MAX_HUBNAME_LEN + 1];
246    char username[MAX_USERNAME_LEN + 1];
247    UCHAR secure_old_password[SHA1_SIZE];
248    UCHAR new_password[SHA1_SIZE];
249    UCHAR check_secure_old_password[SHA1_SIZE];
250    UINT ret = ERR_NO_ERROR;
251    HUB *hub;
252    bool save = false;
253    // 引数チェック
254    if (c == NULL || p == NULL)
255    {
256        return ERR_INTERNAL_ERROR;
257    }
258
259    Copy(random, c->Random, SHA1_SIZE);
260    if (PackGetStr(p, "hubname", hubname, sizeof(hubname)) == false ||
261        PackGetStr(p, "username", username, sizeof(username)) == false ||
262        PackGetData2(p, "secure_old_password", secure_old_password, sizeof(secure_old_password)) == false ||
263        PackGetData2(p, "new_password", new_password, sizeof(new_password)) == false)
264    {
265        return ERR_PROTOCOL_ERROR;
266    }
267
268    cedar = c->Cedar;
269
270    LockHubList(cedar);
271    {
272        hub = GetHub(cedar, hubname);
273    }
274    UnlockHubList(cedar);
275
276    if (hub == NULL)
277    {
278        ret = ERR_HUB_NOT_FOUND;
279    }
280    else
281    {
282        char tmp[MAX_SIZE];
283
284        if (GetHubAdminOption(hub, "deny_change_user_password") != 0)
285        {
286            ReleaseHub(hub);
287            return ERR_NOT_ENOUGH_RIGHT;
288        }
289
290        IPToStr(tmp, sizeof(tmp), &c->FirstSock->RemoteIP);
291        HLog(hub, "LH_CHANGE_PASSWORD_1", c->Name, tmp);
292
293        AcLock(hub);
294        {
295            USER *u = AcGetUser(hub, username);
296            if (u == NULL)
297            {
298                HLog(hub, "LH_CHANGE_PASSWORD_2", c->Name, username);
299                ret = ERR_OLD_PASSWORD_WRONG;
300            }
301            else
302            {
303                Lock(u->lock);
304                {
305                    if (u->AuthType != AUTHTYPE_PASSWORD)
306                    {
307                        // パスワード認証ではない
308                        HLog(hub, "LH_CHANGE_PASSWORD_3", c->Name, username);
309                        ret = ERR_USER_AUTHTYPE_NOT_PASSWORD;
310                    }
311                    else
312                    {
313                        bool fix_password = false;
314                        if (u->Policy != NULL)
315                        {
316                            fix_password = u->Policy->FixPassword;
317                        }
318                        else
319                        {
320                            if (u->Group != NULL)
321                            {
322                                if (u->Group->Policy != NULL)
323                                {
324                                    fix_password = u->Group->Policy->FixPassword;
325                                }
326                            }
327                        }
328                        if (fix_password == false)
329                        {
330                            // 古いパスワードの確認
331                            AUTHPASSWORD *pw = (AUTHPASSWORD *)u->AuthData;
332
333                            SecurePassword(check_secure_old_password, pw->HashedKey, random);
334                            if (Cmp(check_secure_old_password, secure_old_password, SHA1_SIZE) != 0)
335                            {
336                                // 古いパスワードが間違っている
337                                ret = ERR_OLD_PASSWORD_WRONG;
338                                HLog(hub, "LH_CHANGE_PASSWORD_4", c->Name, username);
339                            }
340                            else
341                            {
342                                // 新しいパスワードの書き込み
343                                Copy(pw->HashedKey, new_password, SHA1_SIZE);
344                                HLog(hub, "LH_CHANGE_PASSWORD_5", c->Name, username);
345                                save = true;
346                            }
347                        }
348                        else
349                        {
350                            // パスワード変更は禁止
351                            ret = ERR_NOT_ENOUGH_RIGHT;
352                        }
353                    }
354                }
355                Unlock(u->lock);
356
357                ReleaseUser(u);
358            }
359        }
360        AcUnlock(hub);
361        ReleaseHub(hub);
362    }
363
364    return ret;
365}
366
367// パスワードを変更する
368UINT ChangePassword(CEDAR *cedar, CLIENT_OPTION *o, char *hubname, char *username, char *old_pass, char *new_pass)
369{
370    UINT ret = ERR_NO_ERROR;
371    UCHAR old_password[SHA1_SIZE];
372    UCHAR secure_old_password[SHA1_SIZE];
373    UCHAR new_password[SHA1_SIZE];
374    SOCK *sock;
375    SESSION *s;
376    // 引数チェック
377    if (cedar == NULL || o == NULL || hubname == NULL || username == NULL || old_pass == NULL || new_pass == NULL)
378    {
379        return ERR_INTERNAL_ERROR;
380    }
381
382
383    // セッション作成
384    s = NewRpcSessionEx(cedar, o, &ret, NULL);
385
386    if (s != NULL)
387    {
388        PACK *p = NewPack();
389
390        sock = s->Connection->FirstSock;
391
392        HashPassword(old_password, username, old_pass);
393        SecurePassword(secure_old_password, old_password, s->Connection->Random);
394        HashPassword(new_password, username, new_pass);
395
396        PackAddClientVersion(p, s->Connection);
397
398        PackAddStr(p, "method", "password");
399        PackAddStr(p, "hubname", hubname);
400        PackAddStr(p, "username", username);
401        PackAddData(p, "secure_old_password", secure_old_password, SHA1_SIZE);
402        PackAddData(p, "new_password", new_password, SHA1_SIZE);
403
404        if (HttpClientSend(sock, p))
405        {
406            PACK *p = HttpClientRecv(sock);
407            if (p == NULL)
408            {
409                ret = ERR_DISCONNECTED;
410            }
411            else
412            {
413                ret = GetErrorFromPack(p);
414            }
415            FreePack(p);
416        }
417        else
418        {
419            ret = ERR_DISCONNECTED;
420        }
421        FreePack(p);
422
423        ReleaseSession(s);
424    }
425
426    return ret;
427}
428
429// HUB を列挙する
430TOKEN_LIST *EnumHub(SESSION *s)
431{
432    SOCK *sock;
433    TOKEN_LIST *ret;
434    PACK *p;
435    UINT num;
436    UINT i;
437    // 引数チェック
438    if (s == NULL || s->Connection == NULL)
439    {
440        return NULL;
441    }
442
443    sock = s->Connection->FirstSock;
444    if (sock == NULL)
445    {
446        return NULL;
447    }
448
449    // タイムアウトの設定
450    SetTimeout(sock, 10000);
451
452    p = NewPack();
453    PackAddStr(p, "method", "enum_hub");
454
455    PackAddClientVersion(p, s->Connection);
456
457    if (HttpClientSend(sock, p) == false)
458    {
459        FreePack(p);
460        return NULL;
461    }
462    FreePack(p);
463
464    p = HttpClientRecv(sock);
465    if (p == NULL)
466    {
467        return NULL;
468    }
469
470    num = PackGetInt(p, "NumHub");
471    ret = ZeroMalloc(sizeof(TOKEN_LIST));
472    ret->NumTokens = num;
473    ret->Token = ZeroMalloc(sizeof(char *) * num);
474    for (i = 0;i < num;i++)
475    {
476        char tmp[MAX_SIZE];
477        if (PackGetStrEx(p, "HubName", tmp, sizeof(tmp), i))
478        {
479            ret->Token[i] = CopyStr(tmp);
480        }
481    }
482    FreePack(p);
483
484    return ret;
485}
486
487// サーバーがクライアントからの接続を受け付ける
488bool ServerAccept(CONNECTION *c)
489{
490    bool ret = false;
491    UINT err;
492    PACK *p;
493    char username_real[MAX_SIZE];
494    char method[MAX_SIZE];
495    char hubname[MAX_SIZE];
496    char username[MAX_SIZE];
497    char groupname[MAX_SIZE];
498    UCHAR session_key[SHA1_SIZE];
499    UCHAR ticket[SHA1_SIZE];
500    RC4_KEY_PAIR key_pair;
501    UINT authtype;
502    POLICY *policy;
503    HUB *hub;
504    SESSION *s;
505    UINT64 user_expires = 0;
506    bool use_encrypt;
507    bool use_compress;
508    bool half_connection;
509    bool use_fast_rc4;
510    bool admin_mode = false;
511    UINT direction;
512    UINT max_connection;
513    UINT timeout;
514    bool farm_controller = false;
515    bool farm_member = false;
516    bool farm_mode = false;
517    bool require_bridge_routing_mode;
518    bool require_monitor_mode;
519    bool use_client_license = false, use_bridge_license = false;
520    bool local_host_session = false;
521    char sessionname[MAX_SESSION_NAME_LEN + 1];
522    bool is_server_or_bridge = false;
523    bool qos = false;
524    bool cluster_dynamic_secure_nat = false;
525    bool no_save_password = false;
526    NODE_INFO node;
527    wchar_t *msg = NULL;
528    USER *loggedin_user_object = NULL;
529    FARM_MEMBER *f = NULL;
530    SERVER *server = NULL;
531    POLICY ticketed_policy;
532    UINT64 timestamp;
533    UCHAR unique[SHA1_SIZE], unique2[SHA1_SIZE];
534    LICENSE_STATUS license;
535    CEDAR *cedar;
536    RPC_WINVER winver;
537    UINT client_id;
538    bool no_more_users_in_server = false;
539
540    // 引数チェック
541    if (c == NULL)
542    {
543        return false;
544    }
545
546    Zero(&winver, sizeof(winver));
547
548    StrCpy(groupname, sizeof(groupname), "");
549    StrCpy(sessionname, sizeof(sessionname), "");
550
551    cedar = c->Cedar;
552
553    // ライセンス状況の取得
554    Zero(&license, sizeof(license));
555    if (c->Cedar->Server != NULL)
556    {
557        LiParseCurrentLicenseStatus(c->Cedar->Server->LicenseSystem, &license);
558    }
559
560    no_more_users_in_server = SiTooManyUserObjectsInServer(cedar->Server, true);
561
562    c->Status = CONNECTION_STATUS_NEGOTIATION;
563
564    if (c->Cedar->Server != NULL)
565    {
566        SERVER *s = c->Cedar->Server;
567        server = s;
568
569        if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
570        {
571            farm_member = true;
572            farm_mode = true;
573        }
574
575        if (s->ServerType == SERVER_TYPE_FARM_CONTROLLER)
576        {
577            farm_controller = true;
578            farm_mode = true;
579        }
580    }
581
582    // シグネチャを受信
583    Debug("Downloading Signature...\n");
584    if (ServerDownloadSignature(c) == false)
585    {
586        goto CLEANUP;
587    }
588
589    // Hello パケットを送信
590    Debug("Uploading Hello...\n");
591    if (ServerUploadHello(c) == false)
592    {
593        goto CLEANUP;
594    }
595
596    // 認証データを受信
597    Debug("Auth...\n");
598
599    p = HttpServerRecv(c->FirstSock);
600    if (p == NULL)
601    {
602        // 通信切断
603        c->Err = ERR_DISCONNECTED;
604        goto CLEANUP;
605    }
606
607    if (err = GetErrorFromPack(p))
608    {
609        // エラー発生
610        FreePack(p);
611        c->Err = err;
612        goto CLEANUP;
613    }
614
615    // メソッド取得
616    if (GetMethodFromPack(p, method, sizeof(method)) == false)
617    {
618        // プロトコルエラー
619        FreePack(p);
620        c->Err = ERR_PROTOCOL_ERROR;
621        goto CLEANUP;
622    }
623
624    // 時刻検査
625    timestamp = PackGetInt64(p, "timestamp");
626    if (timestamp != 0)
627    {
628        UINT64 now = SystemTime64();
629        UINT64 abs;
630        if (now >= timestamp)
631        {
632            abs = now - timestamp;
633        }
634        else
635        {
636            abs = timestamp - now;
637        }
638
639        if (abs > ALLOW_TIMESTAMP_DIFF)
640        {
641            // 時差が大きすぎる
642            FreePack(p);
643            c->Err = ERR_BAD_CLOCK;
644            goto CLEANUP;
645        }
646    }
647
648    // クライアントバージョン取得
649    PackGetStr(p, "client_str", c->ClientStr, sizeof(c->ClientStr));
650    c->ClientVer = PackGetInt(p, "client_ver");
651    c->ClientBuild = PackGetInt(p, "client_build");
652
653    if (SearchStrEx(c->ClientStr, "server", 0, false) != INFINITE ||
654        SearchStrEx(c->ClientStr, "bridge", 0, false) != INFINITE)
655    {
656        is_server_or_bridge = true;
657    }
658
659    // クライアント Windows バージョンの取得
660    InRpcWinVer(&winver, p);
661
662    DecrementNoSsl(c->Cedar, &c->FirstSock->RemoteIP, 2);
663
664    if (StrCmpi(method, "login") == 0)
665    {
666        bool auth_ret = false;
667
668        Debug("Login...\n");
669        c->Status = CONNECTION_STATUS_USERAUTH;
670
671        c->Type = CONNECTION_TYPE_LOGIN;
672
673        if (no_more_users_in_server)
674        {
675            // VPN Server に許可されているよりも多くのユーザーが存在する
676            FreePack(p);
677            c->Err = ERR_TOO_MANY_USER;
678            goto CLEANUP;
679        }
680
681        // クライアント名など
682        if (PackGetStr(p, "hello", c->ClientStr, sizeof(c->ClientStr)) == false)
683        {
684            StrCpy(c->ClientStr, sizeof(c->ClientStr), "Unknown");
685        }
686        c->ServerVer = CEDAR_VER;
687        c->ServerBuild = CEDAR_BUILD;
688
689        // NODE_INFO を取得する
690        Zero(&node, sizeof(node));
691        InRpcNodeInfo(&node, p);
692
693        // プロトコル
694        c->Protocol = GetProtocolFromPack(p);
695        if (c->Protocol == CONNECTION_UDP)
696        {
697            // TCP 関係の構造体を解放する
698            if (c->Tcp)
699            {
700                ReleaseList(c->Tcp->TcpSockList);
701                Free(c->Tcp);
702            }
703        }
704
705        if (GetServerCapsBool(c->Cedar->Server, "b_vpn_client_connect") == false)
706        {
707            // VPN クライアントが接続不可能である
708            FreePack(p);
709            c->Err = ERR_NOT_SUPPORTED;
710            goto CLEANUP;
711        }
712
713        // ログイン
714        if (GetHubnameAndUsernameFromPack(p, username, sizeof(username), hubname, sizeof(hubname)) == false)
715        {
716            // プロトコルエラー
717            FreePack(p);
718            c->Err = ERR_PROTOCOL_ERROR;
719            goto CLEANUP;
720        }
721
722        if (farm_member)
723        {
724            bool ok = false;
725            UINT authtype;
726
727            authtype = GetAuthTypeFromPack(p);
728            if (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 &&
729                authtype == AUTHTYPE_PASSWORD)
730            {
731                ok = true;
732            }
733
734            if (authtype == AUTHTYPE_TICKET)
735            {
736                ok = true;
737            }
738
739            if (ok == false)
740            {
741                // サーバーファームメンバへの Administrators 以外の直接ログオンは
742                // 禁止されている
743                FreePack(p);
744                SLog(c->Cedar, "LS_FARMMEMBER_NOT_ADMIN", c->Name, hubname, ADMINISTRATOR_USERNAME, username);
745                c->Err = ERR_ACCESS_DENIED;
746                goto CLEANUP;
747            }
748        }
749
750        Debug("Username = %s, HubName = %s\n", username, hubname);
751        LockHubList(c->Cedar);
752        {
753            hub = GetHub(c->Cedar, hubname);
754        }
755        UnlockHubList(c->Cedar);
756        if (hub == NULL)
757        {
758            // HUB が存在しない
759            FreePack(p);
760            c->Err = ERR_HUB_NOT_FOUND;
761            SLog(c->Cedar, "LS_HUB_NOT_FOUND", c->Name, hubname);
762            goto CLEANUP;
763        }
764
765        Lock(hub->lock);
766        {
767            USER *user;
768            USERGROUP *group;
769            if (hub->Halt || hub->Offline)
770            {
771                // HUB は停止中
772                FreePack(p);
773                Unlock(hub->lock);
774                ReleaseHub(hub);
775                c->Err = ERR_HUB_STOPPING;
776                goto CLEANUP;
777            }
778
779            // 各種フラグの取得
780            use_encrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
781            use_compress = PackGetInt(p, "use_compress") == 0 ? false : true;
782            max_connection = PackGetInt(p, "max_connection");
783            half_connection = PackGetInt(p, "half_connection") == 0 ? false : true;
784            use_fast_rc4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
785            qos = PackGetInt(p, "qos") ? true : false;
786            client_id = PackGetInt(p, "client_id");
787
788            // 要求モード
789            require_bridge_routing_mode = PackGetBool(p, "require_bridge_routing_mode");
790            require_monitor_mode = PackGetBool(p, "require_monitor_mode");
791            if (require_monitor_mode)
792            {
793                qos = false;
794            }
795
796            if (is_server_or_bridge)
797            {
798                require_bridge_routing_mode = true;
799            }
800
801            // クライアントユニーク ID
802            Zero(unique, sizeof(unique));
803            if (PackGetDataSize(p, "unique_id") == SHA1_SIZE)
804            {
805                PackGetData(p, "unique_id", unique);
806            }
807
808            // 認証方法の取得
809            authtype = GetAuthTypeFromPack(p);
810
811            if (1)
812            {
813                // ログ
814                char ip1[64], ip2[64], verstr[64];
815                wchar_t *authtype_str = _UU("LH_AUTH_UNKNOWN");
816                switch (authtype)
817                {
818                case CLIENT_AUTHTYPE_ANONYMOUS:
819                    authtype_str = _UU("LH_AUTH_ANONYMOUS");
820                    break;
821                case CLIENT_AUTHTYPE_PASSWORD:
822                    authtype_str = _UU("LH_AUTH_PASSWORD");
823                    break;
824                case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
825                    authtype_str = _UU("LH_AUTH_PLAIN_PASSWORD");
826                    break;
827                case CLIENT_AUTHTYPE_CERT:
828                    authtype_str = _UU("LH_AUTH_CERT");
829                    break;
830                case AUTHTYPE_TICKET:
831                    authtype_str = _UU("LH_AUTH_TICKET");
832                    break;
833                }
834                IPToStr(ip1, sizeof(ip1), &c->FirstSock->RemoteIP);
835                IPToStr(ip2, sizeof(ip2), &c->FirstSock->LocalIP);
836
837                Format(verstr, sizeof(verstr), "%u.%02u", c->ClientVer / 100, c->ClientVer % 100);
838
839                HLog(hub, "LH_CONNECT_CLIENT", c->Name, ip1, c->FirstSock->RemoteHostname, c->FirstSock->RemotePort,
840                    c->ClientStr, verstr, c->ClientBuild, authtype_str, username);
841            }
842
843            // まず匿名認証を試行する
844            auth_ret = SamAuthUserByAnonymous(hub, username);
845
846            if (auth_ret)
847            {
848                // ユーザー認証成功
849                HLog(hub, "LH_AUTH_OK", c->Name, username);
850            }
851
852            if (auth_ret == false)
853            {
854                // 匿名認証に失敗した場合は他の認証方法を試行する
855                switch (authtype)
856                {
857                case CLIENT_AUTHTYPE_ANONYMOUS:
858                    // 匿名認証 (すでに試行している)
859                    break;
860
861                case AUTHTYPE_TICKET:
862                    // チケット認証
863                    if (PackGetDataSize(p, "ticket") == SHA1_SIZE)
864                    {
865                        PackGetData(p, "ticket", ticket);
866
867                        auth_ret = SiCheckTicket(hub, ticket, username, sizeof(username), username_real, sizeof(username_real),
868                            &ticketed_policy, sessionname, sizeof(sessionname), groupname, sizeof(groupname));
869                    }
870                    break;
871
872                case CLIENT_AUTHTYPE_PASSWORD:
873                    // パスワード認証
874                    if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
875                    {
876                        POLICY *pol = NULL;
877                        UCHAR secure_password[SHA1_SIZE];
878                        Zero(secure_password, sizeof(secure_password));
879                        if (PackGetDataSize(p, "secure_password") == SHA1_SIZE)
880                        {
881                            PackGetData(p, "secure_password", secure_password);
882                        }
883                        auth_ret = SamAuthUserByPassword(hub, username, c->Random, secure_password);
884
885                        pol = SamGetUserPolicy(hub, username);
886                        if (pol != NULL)
887                        {
888                            no_save_password = pol->NoSavePassword;
889                            Free(pol);
890                        }
891                    }
892                    break;
893
894                case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
895                    // 外部サーバーによる認証はサポートされていない
896                    HLog(hub, "LH_AUTH_RADIUS_NOT_SUPPORT", c->Name, username);
897                    Unlock(hub->lock);
898                    ReleaseHub(hub);
899                    FreePack(p);
900                    c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
901                    goto CLEANUP;
902
903                case CLIENT_AUTHTYPE_CERT:
904                    // 証明書認証はサポートされていない
905                    HLog(hub, "LH_AUTH_CERT_NOT_SUPPORT", c->Name, username);
906                    Unlock(hub->lock);
907                    ReleaseHub(hub);
908                    FreePack(p);
909                    c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
910                    goto CLEANUP;
911
912                default:
913                    // 不明な認証方法
914                    Unlock(hub->lock);
915                    ReleaseHub(hub);
916                    FreePack(p);
917                    c->Err = ERR_AUTHTYPE_NOT_SUPPORTED;
918                    goto CLEANUP;
919                }
920
921                if (auth_ret == false)
922                {
923                    // 認証失敗
924                    HLog(hub, "LH_AUTH_NG", c->Name, username);
925                }
926                else
927                {
928                    // 認証成功
929                    HLog(hub, "LH_AUTH_OK", c->Name, username);
930                }
931            }
932
933            if (auth_ret == false)
934            {
935                // 認証失敗
936                Unlock(hub->lock);
937                ReleaseHub(hub);
938                FreePack(p);
939                c->Err = ERR_AUTH_FAILED;
940                goto CLEANUP;
941            }
942            else
943            {
944                if (authtype == CLIENT_AUTHTYPE_PASSWORD)
945                {
946                    UCHAR test[SHA1_SIZE];
947                    HashPassword(test, username, "");
948                    if (Cmp(test, hub->SecurePassword, SHA1_SIZE) == 0)
949                    {
950                        SOCK *s = c->FirstSock;
951                        if (s != NULL)
952                        {
953                            if (GetHubAdminOption(hub, "deny_empty_password") != 0 ||
954                                (StrCmpi(username, ADMINISTRATOR_USERNAME) == 0 && s->RemoteIP.addr[0] != 127))
955                            {
956                                // パスワードが空のとき、リモートから接続してはいけない
957                                HLog(hub, "LH_LOCAL_ONLY", c->Name, username);
958
959                                Unlock(hub->lock);
960                                ReleaseHub(hub);
961                                FreePack(p);
962                                c->Err = ERR_NULL_PASSWORD_LOCAL_ONLY;
963                                goto CLEANUP;
964                            }
965                        }
966                    }
967                }
968            }
969
970            policy = NULL;
971
972            // 認証成功
973            FreePack(p);
974
975            if (StrCmpi(username, ADMINISTRATOR_USERNAME) != 0)
976            {
977                // ポリシーを取得
978                if (farm_member == false)
979                {
980                    // ファームメンバ以外の場合
981                    user = AcGetUser(hub, username);
982                    if (user == NULL)
983                    {
984                        user = AcGetUser(hub, "*");
985                        if (user == NULL)
986                        {
987                            // ユーザー取得失敗
988                            Unlock(hub->lock);
989                            ReleaseHub(hub);
990                            c->Err = ERR_ACCESS_DENIED;
991                            goto CLEANUP;
992                        }
993                    }
994
995                    policy = NULL;
996
997                    Lock(user->lock);
998                    {
999                        // 有効期限を取得
1000                        user_expires = user->ExpireTime;
1001
1002                        StrCpy(username_real, sizeof(username_real), user->Name);
1003                        group = user->Group;
1004                        if (group != NULL)
1005                        {
1006                            AddRef(group->ref);
1007
1008                            Lock(group->lock);
1009                            {
1010                                // グループ名を取得
1011                                StrCpy(groupname, sizeof(groupname), group->Name);
1012                            }
1013                            Unlock(group->lock);
1014                        }
1015
1016                        if (user->Policy != NULL)
1017                        {
1018                            policy = ClonePolicy(user->Policy);
1019                        }
1020                        else
1021                        {
1022                            if (group)
1023                            {
1024                                Lock(group->lock);
1025                                {
1026                                    if (group->Policy != NULL)
1027                                    {
1028                                        policy = ClonePolicy(group->Policy);
1029                                    }
1030                                }
1031                                Unlock(group->lock);
1032                            }
1033                        }
1034
1035                        if (group != NULL)
1036                        {
1037                            ReleaseGroup(group);
1038                        }
1039                    }
1040                    Unlock(user->lock);
1041                    loggedin_user_object = user;
1042                }
1043                else
1044                {
1045                    // ファームメンバの場合
1046                    policy = ClonePolicy(&ticketed_policy);
1047                }
1048            }
1049            else
1050            {
1051                // 管理者モード
1052                admin_mode = true;
1053                StrCpy(username_real, sizeof(username_real), ADMINISTRATOR_USERNAME);
1054
1055                policy = ClonePolicy(GetDefaultPolicy());
1056                policy->NoBroadcastLimiter = true;
1057                policy->MonitorPort = true;
1058            }
1059
1060            if (policy == NULL)
1061            {
1062                // デフォルトのポリシーを使用する
1063                policy = ClonePolicy(GetDefaultPolicy());
1064            }
1065
1066            if (policy->MaxConnection == 0)
1067            {
1068                policy->MaxConnection = MAX_TCP_CONNECTION;
1069            }
1070
1071            if (policy->TimeOut == 0)
1072            {
1073                policy->TimeOut = 20;
1074            }
1075
1076            if (qos)
1077            {
1078                // VoIP / QoS
1079                if (policy->NoQoS)
1080                {
1081                    // ポリシーが許可していない
1082                    qos = false;
1083                }
1084                if (GetServerCapsBool(c->Cedar->Server, "b_support_qos") == false)
1085                {
1086                    // サーバーがサポートしていない
1087                    qos = false;
1088                    policy->NoQoS = true;
1089                }
1090                if (GetHubAdminOption(hub, "deny_qos") != 0)
1091                {
1092                    // 管理オプションで禁止されている
1093                    qos = false;
1094                    policy->NoQoS = true;
1095                }
1096            }
1097
1098            if (GetHubAdminOption(hub, "max_bitrates_download") != 0)
1099            {
1100                if (policy->MaxDownload == 0)
1101                {
1102                    policy->MaxDownload = GetHubAdminOption(hub, "max_bitrates_download");
1103                }
1104                else
1105                {
1106                    policy->MaxDownload = MIN(policy->MaxDownload, GetHubAdminOption(hub, "max_bitrates_download"));
1107                }
1108            }
1109
1110            if (GetHubAdminOption(hub, "max_bitrates_upload") != 0)
1111            {
1112                if (policy->MaxUpload == 0)
1113                {
1114                    policy->MaxUpload = GetHubAdminOption(hub, "max_bitrates_upload");
1115                }
1116                else
1117                {
1118                    policy->MaxUpload = MIN(policy->MaxUpload, GetHubAdminOption(hub, "max_bitrates_upload"));
1119                }
1120            }
1121
1122            if (GetHubAdminOption(hub, "deny_bridge") != 0)
1123            {
1124                policy->NoBridge = true;
1125            }
1126
1127            if (GetHubAdminOption(hub, "deny_routing") != 0)
1128            {
1129                policy->NoRouting = true;
1130            }
1131
1132            if (hub->Option->ClientMinimumRequiredBuild > c->ClientBuild &&
1133                 InStrEx(c->ClientStr, "client", false))
1134            {
1135                // クライアントのビルド番号が小さすぎる
1136                HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, hub->Option->ClientMinimumRequiredBuild);
1137
1138                Unlock(hub->lock);
1139                ReleaseHub(hub);
1140                c->Err = ERR_VERSION_INVALID;
1141                Free(policy);
1142                goto CLEANUP;
1143            }
1144
1145            if (hub->Option->RequiredClientId != 0 &&
1146                hub->Option->RequiredClientId != client_id && 
1147                InStrEx(c->ClientStr, "client", false))
1148            {
1149                // クライアントのビルド番号が小さすぎる
1150                HLog(hub, "LH_CLIENT_ID_REQUIRED", c->Name, client_id, hub->Option->RequiredClientId);
1151
1152                Unlock(hub->lock);
1153                ReleaseHub(hub);
1154                c->Err = ERR_CLIENT_ID_REQUIRED;
1155                Free(policy);
1156                goto CLEANUP;
1157            }
1158
1159            if ((policy->NoSavePassword) || (policy->AutoDisconnect != 0))
1160            {
1161                if (c->ClientBuild < 6560 && InStrEx(c->ClientStr, "client", false))
1162                {
1163                    // NoSavePassword ポリシーが指定されている場合は対応クライアント
1164                    // でなければ接続できない
1165                    HLog(hub, "LH_CLIENT_VERSION_OLD", c->Name, c->ClientBuild, 6560);
1166
1167                    Unlock(hub->lock);
1168                    ReleaseHub(hub);
1169                    c->Err = ERR_VERSION_INVALID;
1170                    Free(policy);
1171                    goto CLEANUP;
1172                }
1173            }
1174
1175            if (user_expires != 0 && user_expires <= SystemTime64())
1176            {
1177                // 有効期限が切れている
1178                // アクセスが拒否されている
1179                HLog(hub, "LH_USER_EXPIRES", c->Name, username);
1180
1181                Unlock(hub->lock);
1182                ReleaseHub(hub);
1183                c->Err = ERR_ACCESS_DENIED;
1184                Free(policy);
1185                goto CLEANUP;
1186            }
1187
1188            if (policy->Access == false)
1189            {
1190                // アクセスが拒否されている
1191                HLog(hub, "LH_POLICY_ACCESS_NG", c->Name, username);
1192
1193                Unlock(hub->lock);
1194                ReleaseHub(hub);
1195                c->Err = ERR_ACCESS_DENIED;
1196                Free(policy);
1197                goto CLEANUP;
1198            }
1199
1200            // ポリシーの内容をクライアントが要求したオプションと比較して
1201            // 決定するか接続を拒否する
1202            // 最初にモニタポートモードで接続できるかどうか確認する
1203            if (require_monitor_mode && policy->MonitorPort == false)
1204            {
1205                // モニタポートモードで接続できない
1206                HLog(hub, "LH_POLICY_MONITOR_MODE", c->Name);
1207
1208                Unlock(hub->lock);
1209                ReleaseHub(hub);
1210                c->Err = ERR_MONITOR_MODE_DENIED;
1211                Free(policy);
1212                goto CLEANUP;
1213            }
1214
1215            if (policy->MonitorPort)
1216            {
1217                if (require_monitor_mode == false)
1218                {
1219                    policy->MonitorPort = false;
1220                }
1221            }
1222
1223            if (policy->MonitorPort)
1224            {
1225                qos = false;
1226            }
1227
1228            // 次にブリッジ / ルーティングモードで接続できるか確認する
1229            if (require_bridge_routing_mode &&
1230                (policy->NoBridge && policy->NoRouting))
1231            {
1232                // ブリッジ / ルーティングモードで接続できない
1233                HLog(hub, "LH_POLICY_BRIDGE_MODE", c->Name);
1234
1235                Unlock(hub->lock);
1236                ReleaseHub(hub);
1237                c->Err = ERR_BRIDGE_MODE_DENIED;
1238                Free(policy);
1239                goto CLEANUP;
1240            }
1241
1242            if (require_bridge_routing_mode == false)
1243            {
1244                policy->NoBridge = true;
1245                policy->NoRouting = true;
1246            }
1247
1248            // ライセンスが必要かどうかチェック
1249            GenerateMachineUniqueHash(unique2);
1250
1251            if (Cmp(unique, unique2, SHA1_SIZE) == 0)
1252            {
1253                // ローカルホストセッションである
1254                local_host_session = true;
1255            }
1256            else
1257            {
1258                if (license.NumUserLicense != INFINITE)
1259                {
1260                    // ユーザー作成数が制限されているエディションでは多重ログイン禁止
1261                    policy->MultiLogins = 1;
1262                }
1263
1264                if (policy->NoBridge == false || policy->NoRouting == false)
1265                {
1266                    // ブリッジライセンスを消費
1267                    use_bridge_license = true;
1268                }
1269                else
1270                {
1271                    // クライアントライセンスを消費
1272                    use_client_license = true;
1273                }
1274            }
1275
1276            if (server != NULL && server->ServerType != SERVER_TYPE_FARM_MEMBER &&
1277                (use_bridge_license || use_client_license))
1278            {
1279                // クラスタコントローラまたはスタンドアロンサーバーの場合で
1280                // クライアントにライセンスが必要になった場合、ここでライセンス数が
1281                // 足りているかどうかを計算する
1282
1283                if (use_client_license)
1284                {
1285                    if (server->CurrentAssignedClientLicense >= license.NumClientLicense)
1286                    {
1287                        // クライアント接続ライセンスが足りない
1288                        Unlock(hub->lock);
1289
1290                        // 詳細エラーログを吐く
1291                        HLog(hub, "LH_NOT_ENOUGH_CLIENT_LICENSE", c->Name,
1292                            license.NumClientLicense,
1293                            server->CurrentAssignedClientLicense + 1);
1294
1295                        ReleaseHub(hub);
1296                        c->Err = ERR_CLIENT_LICENSE_NOT_ENOUGH;
1297                        Free(policy);
1298                        goto CLEANUP;
1299                    }
1300                }
1301                if (use_bridge_license)
1302                {
1303                    if (server->CurrentAssignedBridgeLicense >= license.NumBridgeLicense)
1304                    {
1305                        // ブリッジ接続ライセンス数が足りない
1306                        Unlock(hub->lock);
1307
1308                        // 詳細エラーログを吐く
1309                        HLog(hub, "LH_NOT_ENOUGH_BRIDGE_LICENSE", c->Name,
1310                            license.NumBridgeLicense,
1311                            server->CurrentAssignedBridgeLicense + 1);
1312
1313                        ReleaseHub(hub);
1314                        c->Err = ERR_BRIDGE_LICENSE_NOT_ENOUGH;
1315                        Free(policy);
1316                        goto CLEANUP;
1317                    }
1318                }
1319            }
1320
1321            if (server != NULL && server->ServerType != SERVER_TYPE_FARM_MEMBER &&
1322                policy != NULL)
1323            {
1324                if (GetServerCapsBool(hub->Cedar->Server, "b_support_limit_multilogin"))
1325                {
1326                    // ポリシーで多重ログイン制限数が指定されている場合は確認する
1327                    RPC_ENUM_SESSION t;
1328                    UINT i, num;
1329                    UINT max_logins = policy->MultiLogins;
1330                    UINT ao = GetHubAdminOption(hub, "max_multilogins_per_user");
1331
1332                    if (ao != 0)
1333                    {
1334                        if (max_logins != 0)
1335                        {
1336                            max_logins = MIN(max_logins, ao);
1337                        }
1338                        else
1339                        {
1340                            max_logins = ao;
1341                        }
1342                    }
1343
1344                    if (max_logins != 0)
1345                    {
1346                        Zero(&t, sizeof(t));
1347                        StrCpy(t.HubName, sizeof(t.HubName), hub->Name);
1348
1349                        Unlock(hub->lock);
1350
1351                        SiEnumSessionMain(server, &t);
1352
1353                        Lock(hub->lock);
1354
1355                        num = 0;
1356
1357                        for (i = 0;i < t.NumSession;i++)
1358                        {
1359                            RPC_ENUM_SESSION_ITEM *e = &t.Sessions[i];
1360
1361                            if (e->BridgeMode == false && e->Layer3Mode == false && e->LinkMode == false && e->CurrentNumTcp != 0)
1362                            {
1363                                if (StrCmpi(e->Username, username) == 0 &&
1364                                    (IsZero(e->UniqueId, 16) || Cmp(e->UniqueId, node.UniqueId, 16) != 0))
1365                                {
1366                                    num++;
1367                                }
1368                            }
1369                        }
1370
1371                        FreeRpcEnumSession(&t);
1372
1373                        if (num >= max_logins)
1374                        {
1375                            // これ以上接続できない
1376                            Unlock(hub->lock);
1377
1378                            // 詳細エラーログを吐く
1379                            HLog(hub, license.NumUserLicense == INFINITE ? "LH_TOO_MANY_MULTILOGINS" : "LH_TOO_MANY_MULTILOGINS2",
1380                                c->Name,
1381                                username, max_logins, num);
1382
1383                            ReleaseHub(hub);
1384                            c->Err = ERR_TOO_MANY_USER_SESSION;
1385                            Free(policy);
1386                            goto CLEANUP;
1387                        }
1388                    }
1389                }
1390            }
1391
1392            if (loggedin_user_object != NULL)
1393            {
1394                // ユーザー情報の更新
1395                Lock(loggedin_user_object->lock);
1396                {
1397                    loggedin_user_object->NumLogin++;
1398                    loggedin_user_object->LastLoginTime = SystemTime64();
1399                }
1400                Unlock(loggedin_user_object->lock);
1401            }
1402
1403            // ログイン回数を更新する
1404            hub->NumLogin++;
1405            hub->LastCommTime = hub->LastLoginTime = SystemTime64();
1406
1407            if (farm_controller)
1408            {
1409                wchar_t *msg = GetHubMsg(hub);
1410
1411                Unlock(hub->lock);
1412
1413                Lock(cedar->CedarSuperLock);
1414
1415                // ファームコントローラの場合、この HUB をホスティングする
1416                // ファームメンバを選定する
1417                LockList(server->FarmMemberList);
1418                {
1419                    HLog(hub, "LH_FARM_SELECT_1", c->Name);
1420                    f = SiGetHubHostingMember(server, hub, admin_mode);
1421
1422                    if (f == NULL)
1423                    {
1424                        // 選定に失敗した
1425                        HLog(hub, "LH_FARM_SELECT_2", c->Name);
1426                        UnlockList(server->FarmMemberList);
1427                        Unlock(cedar->CedarSuperLock);
1428                        ReleaseHub(hub);
1429                        c->Err = ERR_COULD_NOT_HOST_HUB_ON_FARM;
1430                        Free(policy);
1431                        Free(msg);
1432                        goto CLEANUP;
1433                    }
1434                    else
1435                    {
1436                        if (f->Me == false)
1437                        {
1438                            UCHAR ticket[SHA1_SIZE];
1439                            PACK *p;
1440                            BUF *b;
1441                            UINT i;
1442
1443                            SLog(c->Cedar, "LH_FARM_SELECT_4", c->Name, f->hostname);
1444
1445                            // 選定したサーバーファームメンバにセッションを作成する
1446                            Rand(ticket, sizeof(ticket));
1447                            SiCallCreateTicket(server, f, hub->Name,
1448                                username, username_real, policy, ticket, Inc(hub->SessionCounter), groupname);
1449
1450                            p = NewPack();
1451                            PackAddInt(p, "Redirect", 1);
1452                            PackAddIp32(p, "Ip", f->Ip);
1453                            for (i = 0;i < f->NumPort;i++)
1454                            {
1455                                PackAddIntEx(p, "Port", f->Ports[i], i, f->NumPort);
1456                            }
1457                            PackAddData(p, "Ticket", ticket, sizeof(ticket));
1458
1459                            if (true)
1460                            {
1461                                char *utf = CopyUniToUtf(msg);
1462
1463                                PackAddData(p, "Msg", utf, StrLen(utf));
1464
1465                                Free(utf);
1466                            }
1467
1468                            b = XToBuf(f->ServerCert, false);
1469                            PackAddBuf(p, "Cert", b);
1470                            FreeBuf(b);
1471
1472                            UnlockList(server->FarmMemberList);
1473                            Unlock(cedar->CedarSuperLock);
1474                            ReleaseHub(hub);
1475
1476                            HttpServerSend(c->FirstSock, p);
1477                            FreePack(p);
1478
1479                            c->Err = 0;
1480                            Free(policy);
1481
1482                            FreePack(HttpServerRecv(c->FirstSock));
1483                            Free(msg);
1484                            goto CLEANUP;
1485                        }
1486                        else
1487                        {
1488                            HLog(hub, "LH_FARM_SELECT_3", c->Name);
1489                            // 自分自身が選定されたのでこのまま続ける
1490                            UnlockList(server->FarmMemberList);
1491                            Unlock(cedar->CedarSuperLock);
1492                            f->Point = SiGetPoint(server);
1493                            Lock(hub->lock);
1494                            Free(msg);
1495                        }
1496                    }
1497                }
1498            }
1499
1500            if (admin_mode == false)
1501            {
1502                // HUB の最大接続数をチェック
1503                if (hub->Option->MaxSession != 0 &&
1504                    hub->Option->MaxSession <= Count(hub->NumSessions))
1505                {
1506                    // これ以上接続できない
1507                    Unlock(hub->lock);
1508
1509                    HLog(hub, "LH_MAX_SESSION", c->Name, hub->Option->MaxSession);
1510
1511                    ReleaseHub(hub);
1512                    c->Err = ERR_HUB_IS_BUSY;
1513                    Free(policy);
1514                    goto CLEANUP;
1515                }
1516            }
1517
1518            if (use_client_license || use_bridge_license)
1519            {
1520                // 仮想 HUB 管理オプションで規定された同時接続セッション数
1521                // の制限に抵触しないかどうか調べる
1522                if (
1523                    (GetHubAdminOption(hub, "max_sessions") != 0 &&
1524                    (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= GetHubAdminOption(hub, "max_sessions"))
1525                    ||
1526                    (hub->Option->MaxSession != 0 &&
1527                    (Count(hub->NumSessionsClient) + Count(hub->NumSessionsBridge)) >= hub->Option->MaxSession))
1528                {
1529                    // これ以上接続できない
1530                    Unlock(hub->lock);
1531
1532                    HLog(hub, "LH_MAX_SESSION", c->Name, GetHubAdminOption(hub, "max_sessions"));
1533
1534                    ReleaseHub(hub);
1535                    c->Err = ERR_HUB_IS_BUSY;
1536                    Free(policy);
1537                    goto CLEANUP;
1538                }
1539            }
1540
1541            if (use_client_license)
1542            {
1543                // 仮想 HUB 管理オプションで規定された同時接続セッション数 (クライアント)
1544                // の制限に抵触しないかどうか調べる
1545                if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0 || license.CarrierEdition) &&
1546                    Count(hub->NumSessionsClient) >= GetHubAdminOption(hub, "max_sessions_client") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
1547                    ||
1548                    (hub->FarmMember_MaxSessionClientBridgeApply &&
1549                    Count(hub->NumSessionsClient) >= hub->FarmMember_MaxSessionClient))
1550                {
1551                    // これ以上接続できない
1552                    Unlock(hub->lock);
1553
1554                    HLog(hub, "LH_MAX_SESSION_CLIENT", c->Name, GetHubAdminOption(hub, "max_sessions_client"));
1555
1556                    ReleaseHub(hub);
1557                    c->Err = ERR_HUB_IS_BUSY;
1558                    Free(policy);
1559                    goto CLEANUP;
1560                }
1561            }
1562
1563            if (use_bridge_license)
1564            {
1565                // 仮想 HUB 管理オプションで規定された同時接続セッション数 (ブリッジ)
1566                // の制限に抵触しないかどうか調べる
1567                if (((GetHubAdminOption(hub, "max_sessions_client_bridge_apply") != 0 || license.CarrierEdition) &&
1568                    Count(hub->NumSessionsBridge) >= GetHubAdminOption(hub, "max_sessions_bridge") && hub->Cedar->Server != NULL && hub->Cedar->Server->ServerType != SERVER_TYPE_FARM_MEMBER)
1569                    ||
1570                    (hub->FarmMember_MaxSessionClientBridgeApply &&
1571                    Count(hub->NumSessionsBridge) >= hub->FarmMember_MaxSessionBridge))
1572                {
1573                    // これ以上接続できない
1574                    Unlock(hub->lock);
1575
1576                    HLog(hub, "LH_MAX_SESSION_BRIDGE", c->Name, GetHubAdminOption(hub, "max_sessions_bridge"));
1577
1578                    ReleaseHub(hub);
1579                    c->Err = ERR_HUB_IS_BUSY;
1580                    Free(policy);
1581                    goto CLEANUP;
1582                }
1583            }
1584
1585            if (Count(hub->Cedar->CurrentSessions) >= GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"))
1586            {
1587                // これ以上接続できない
1588                Unlock(hub->lock);
1589
1590                HLog(hub, "LH_MAX_SESSION_2", c->Name, GetServerCapsInt(hub->Cedar->Server, "i_max_sessions"));
1591
1592                ReleaseHub(hub);
1593                c->Err = ERR_HUB_IS_BUSY;
1594                Free(policy);
1595                goto CLEANUP;
1596            }
1597
1598            // 現在の接続数をインクリメント
1599            Inc(hub->NumSessions);
1600            if (use_bridge_license)
1601            {
1602                Inc(hub->NumSessionsBridge);
1603            }
1604
1605            if (use_client_license)
1606            {
1607                Inc(hub->NumSessionsClient);
1608            }
1609            Inc(hub->Cedar->CurrentSessions);
1610
1611            // タイムアウト時間を計算
1612            timeout = policy->TimeOut * 1000;   // ミリ秒 → 秒 に変換
1613            if (timeout == 0)
1614            {
1615                timeout = TIMEOUT_DEFAULT;
1616            }
1617            timeout = MIN(timeout, TIMEOUT_MAX);
1618            timeout = MAX(timeout, TIMEOUT_MIN);
1619
1620            // ポリシーに応じて max_connection を更新
1621            max_connection = MIN(max_connection, policy->MaxConnection);
1622            max_connection = MIN(max_connection, MAX_TCP_CONNECTION);
1623            max_connection = MAX(max_connection, 1);
1624            if (half_connection)
1625            {
1626                // Half Connection 時にはコネクション数は 2 以上とする
1627                max_connection = MAX(max_connection, 2);
1628            }
1629
1630            if (qos)
1631            {
1632                // VoIP / QoS 使用時にはコネクション数は 2 以上とする
1633                max_connection = MAX(max_connection, 2);
1634                if (half_connection)
1635                {
1636                    max_connection = MAX(max_connection, 4);
1637                }
1638            }
1639
1640            c->Status = CONNECTION_STATUS_ESTABLISHED;
1641
1642            // コネクションを Cedar から削除
1643            DelConnection(c->Cedar, c);
1644
1645            // セッションの作成
1646            StrLower(username);
1647            s = NewServerSession(c->Cedar, c, hub, username, policy);
1648
1649            if (server != NULL)
1650            {
1651                s->NoSendSignature = server->NoSendSignature;
1652            }
1653
1654            s->UseClientLicense = use_client_license;
1655            s->UseBridgeLicense = use_bridge_license;
1656
1657            s->IsBridgeMode = (policy->NoBridge == false) || (policy->NoRouting == false);
1658            s->IsMonitorMode = policy->MonitorPort;
1659
1660            // IPv6 セッションかどうかの判定
1661            s->IPv6Session = false;
1662
1663            if (node.ClientIpAddress == 0)
1664            {
1665                s->IPv6Session = true;
1666            }
1667
1668            if (use_bridge_license)
1669            {
1670                Inc(s->Cedar->AssignedBridgeLicense);
1671            }
1672
1673            if (use_client_license)
1674            {
1675                Inc(s->Cedar->AssignedClientLicense);
1676            }
1677
1678            if (server != NULL)
1679            {
1680                // Server 構造体の合計割り当て済みライセンス数の更新
1681                if (server->ServerType == SERVER_TYPE_STANDALONE)
1682                {
1683                    // スタンドアロンモードのみ更新
1684                    // (クラスタコントローラモードでは定期的にポーリングしている)
1685                    server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
1686                    server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
1687                }
1688            }
1689
1690            if (StrLen(sessionname) != 0)
1691            {
1692                // セッション名の指定
1693                Free(s->Name);
1694                s->Name = CopyStr(sessionname);
1695            }
1696
1697            {
1698                char ip[128];
1699                IPToStr(ip, sizeof(ip), &c->FirstSock->RemoteIP);
1700                HLog(hub, "LH_NEW_SESSION", c->Name, s->Name, ip, c->FirstSock->RemotePort);
1701            }
1702
1703            c->Session = s;
1704            s->AdministratorMode = admin_mode;
1705            StrCpy(s->UserNameReal, sizeof(s->UserNameReal), username_real);
1706            StrCpy(s->GroupName, sizeof(s->GroupName), groupname);
1707
1708            // セッションキーの取得
1709            Copy(session_key, s->SessionKey, SHA1_SIZE);
1710
1711            // パラメータをセット
1712            s->MaxConnection = max_connection;
1713            s->UseEncrypt = use_encrypt;
1714            if (s->UseEncrypt && use_fast_rc4)
1715            {
1716                s->UseFastRC4 = use_fast_rc4;
1717            }
1718            s->UseCompress = use_compress;
1719            s->HalfConnection = half_connection;
1720            s->Timeout = timeout;
1721            s->QoS = qos;
1722
1723            if (policy != NULL)
1724            {
1725                s->VLanId = policy->VLanId;
1726            }
1727
1728            // ユーザー名
1729            s->Username = CopyStr(username);
1730
1731            HLog(hub, "LH_SET_SESSION", s->Name, s->MaxConnection,
1732                s->UseEncrypt ? _UU("L_YES") : _UU("L_NO"),
1733                s->UseCompress ? _UU("L_YES") : _UU("L_NO"),
1734                s->HalfConnection ? _UU("L_YES") : _UU("L_NO"),
1735                s->Timeout / 1000);
1736
1737            msg = GetHubMsg(hub);
1738        }
1739        Unlock(hub->lock);
1740
1741        // クライアントに Welcome パケットを送信
1742        p = PackWelcome(s);
1743
1744        if (true)
1745        {
1746            // VPN Client に表示するメッセージ
1747            char *utf;
1748            wchar_t winver_msg_client[3800];
1749            wchar_t winver_msg_server[3800];
1750            wchar_t *utvpn_msg;
1751            UINT tmpsize;
1752            wchar_t *tmp;
1753            RPC_WINVER server_winver;
1754
1755            GetWinVer(&server_winver);
1756
1757            Zero(winver_msg_client, sizeof(winver_msg_client));
1758            Zero(winver_msg_server, sizeof(winver_msg_server));
1759
1760            utvpn_msg = _UU("UTVPN_MSG");
1761
1762            if (IsSupportedWinVer(&winver) == false)
1763            {
1764                SYSTEMTIME st;
1765
1766                LocalTime(&st);
1767
1768                UniFormat(winver_msg_client, sizeof(winver_msg_client), _UU("WINVER_ERROR_FORMAT"),
1769                    _UU("WINVER_ERROR_PC_LOCAL"),
1770                    winver.Title,
1771                    _UU("WINVER_ERROR_VPNSERVER"),
1772                    SUPPORTED_WINDOWS_LIST,
1773                    _UU("WINVER_ERROR_PC_LOCAL"),
1774                    _UU("WINVER_ERROR_VPNSERVER"),
1775                    _UU("WINVER_ERROR_VPNSERVER"),
1776                    _UU("WINVER_ERROR_VPNSERVER"),
1777                    st.wYear, st.wMonth);
1778            }
1779
1780            if (IsSupportedWinVer(&server_winver) == false)
1781            {
1782                SYSTEMTIME st;
1783
1784                LocalTime(&st);
1785
1786                UniFormat(winver_msg_server, sizeof(winver_msg_server), _UU("WINVER_ERROR_FORMAT"),
1787                    _UU("WINVER_ERROR_PC_REMOTE"),
1788                    server_winver.Title,
1789                    _UU("WINVER_ERROR_VPNSERVER"),
1790                    SUPPORTED_WINDOWS_LIST,
1791                    _UU("WINVER_ERROR_PC_REMOTE"),
1792                    _UU("WINVER_ERROR_VPNSERVER"),
1793                    _UU("WINVER_ERROR_VPNSERVER"),
1794                    _UU("WINVER_ERROR_VPNSERVER"),
1795                    st.wYear, st.wMonth);
1796            }
1797
1798            tmpsize = UniStrSize(winver_msg_client) + UniStrSize(winver_msg_server) + UniStrSize(utvpn_msg) + UniStrSize(msg) * 100;
1799
1800            tmp = ZeroMalloc(tmpsize);
1801
1802            if (IsURLMsg(msg, NULL, 0) == false)
1803            {
1804                UniStrCat(tmp, tmpsize, utvpn_msg);
1805                UniStrCat(tmp, tmpsize, winver_msg_client);
1806                UniStrCat(tmp, tmpsize, winver_msg_server);
1807            }
1808            UniStrCat(tmp, tmpsize, msg);
1809           
1810            utf = CopyUniToUtf(tmp);
1811
1812            PackAddData(p, "Msg", utf, StrLen(utf));
1813
1814            Free(tmp);
1815            Free(utf);
1816        }
1817
1818        Free(msg);
1819
1820        if (s->UseFastRC4)
1821        {
1822            // RC4 キーペアを生成
1823            GenerateRC4KeyPair(&key_pair);
1824
1825            // Welcome パケットに追加
1826            PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
1827            PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
1828            {
1829                char key1[64], key2[64];
1830                BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
1831                BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
1832                Debug(
1833                    "Client to Server Key: %s\n"
1834                    "Server to Client Key: %s\n",
1835                    key1, key2);
1836            }
1837        }
1838        HttpServerSend(c->FirstSock, p);
1839        FreePack(p);
1840
1841        Copy(&c->Session->NodeInfo, &node, sizeof(NODE_INFO));
1842        {
1843            wchar_t tmp[MAX_SIZE * 2];
1844            NodeInfoToStr(tmp, sizeof(tmp), &s->NodeInfo);
1845
1846            HLog(hub, "LH_NODE_INFO", s->Name, tmp);
1847        }
1848
1849        // コネクションをトンネリングモードに移行
1850        StartTunnelingMode(c);
1851
1852        // ハーフコネクションモード時の処理
1853        if (s->HalfConnection)
1854        {
1855            // 1 つ目のソケットはクライアント→サーバー 方向 とする
1856            TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
1857            ts->Direction = TCP_CLIENT_TO_SERVER;
1858        }
1859
1860        if (s->UseFastRC4)
1861        {
1862            // 1 つ目の TCP コネクションに RC4 キー情報をセットする
1863            TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
1864            Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
1865
1866            InitTcpSockRc4Key(ts, true);
1867        }
1868
1869        if (s->UseEncrypt && s->UseFastRC4 == false)
1870        {
1871            s->UseSSLDataEncryption = true;
1872        }
1873        else
1874        {
1875            s->UseSSLDataEncryption = false;
1876        }
1877
1878        if (s->Hub->Type == HUB_TYPE_FARM_DYNAMIC && s->Cedar->Server != NULL && s->Cedar->Server->ServerType == SERVER_TYPE_FARM_CONTROLLER)
1879        {
1880            if (s->Hub->BeingOffline == false)
1881            {
1882                // ダイナミック仮想 HUB で SecureNAT を開始
1883                EnableSecureNATEx(s->Hub, false, true);
1884
1885                cluster_dynamic_secure_nat = true;
1886            }
1887        }
1888
1889        // セッションのメインルーチン
1890        SessionMain(s);
1891
1892        // 現在の接続数をデクリメント
1893        Lock(s->Hub->lock);
1894        {
1895            if (use_bridge_license)
1896            {
1897                Dec(hub->NumSessionsBridge);
1898            }
1899
1900            if (use_client_license)
1901            {
1902                Dec(hub->NumSessionsClient);
1903            }
1904
1905            Dec(s->Hub->NumSessions);
1906            Dec(s->Hub->Cedar->CurrentSessions);
1907
1908            // ライセンス数のデクリメント
1909            if (use_bridge_license)
1910            {
1911                Dec(s->Cedar->AssignedBridgeLicense);
1912            }
1913
1914            if (use_client_license)
1915            {
1916                Dec(s->Cedar->AssignedClientLicense);
1917            }
1918
1919            if (server != NULL)
1920            {
1921                // Server 構造体の合計割り当て済みライセンス数の更新
1922                if (server->ServerType == SERVER_TYPE_STANDALONE)
1923                {
1924                    // スタンドアロンモードのみ更新
1925                    // (クラスタコントローラモードでは定期的にポーリングしている)
1926                    server->CurrentAssignedClientLicense = Count(s->Cedar->AssignedClientLicense);
1927                    server->CurrentAssignedBridgeLicense = Count(s->Cedar->AssignedBridgeLicense);
1928                }
1929            }
1930        }
1931        Unlock(s->Hub->lock);
1932
1933        PrintSessionTotalDataSize(s);
1934
1935        HLog(s->Hub, "LH_END_SESSION", s->Name, s->TotalSendSizeReal, s->TotalRecvSizeReal);
1936
1937        if (cluster_dynamic_secure_nat && s->Hub->BeingOffline == false)
1938        {
1939            // ダイナミック仮想 HUB で SecureNAT を停止
1940            EnableSecureNATEx(s->Hub, false, true);
1941        }
1942
1943        ReleaseSession(s);
1944
1945        ret = true;
1946        c->Err = ERR_SESSION_REMOVED;
1947
1948        ReleaseHub(hub);
1949
1950        goto CLEANUP;
1951    }
1952    else if (StrCmpi(method, "additional_connect") == 0)
1953    {
1954        SOCK *sock;
1955        TCPSOCK *ts;
1956        UINT dummy;
1957
1958        c->Type = CONNECTION_TYPE_ADDITIONAL;
1959
1960        // 追加接続
1961        // セッションキーを読み出し
1962        if (GetSessionKeyFromPack(p, session_key, &dummy) == false)
1963        {
1964            FreePack(p);
1965            c->Err = ERR_PROTOCOL_ERROR;
1966            goto CLEANUP;
1967        }
1968
1969        FreePack(p);
1970
1971        // セッションキーからセッションを取得
1972        s = GetSessionFromKey(c->Cedar, session_key);
1973        if (s == NULL || s->Halt)
1974        {
1975            // セッションが発見できない
1976            Debug("Session Not Found.\n");
1977            c->Err = ERR_SESSION_TIMEOUT;
1978            goto CLEANUP;
1979        }
1980
1981        // セッションが見つかった
1982        Debug("Session Found: %s\n", s->Name);
1983        // セッションのプロトコルを確認
1984        c->Err = 0;
1985        Lock(s->lock);
1986        {
1987            if (s->Connection->Protocol != CONNECTION_TCP)
1988            {
1989                c->Err = ERR_INVALID_PROTOCOL;
1990            }
1991        }
1992        Unlock(s->lock);
1993        // セッションの現在のコネクション数を調べる
1994        Lock(s->Connection->lock);
1995        if (c->Err == 0)
1996        {
1997            if (Count(s->Connection->CurrentNumConnection) > s->MaxConnection)
1998            {
1999                c->Err = ERR_TOO_MANY_CONNECTION;
2000            }
2001        }
2002        if (c->Err != 0)
2003        {
2004            Unlock(s->Connection->lock);
2005            if (c->Err == ERR_TOO_MANY_CONNECTION)
2006            {
2007                Debug("Session TOO MANY CONNECTIONS !!: %u\n",
2008                    Count(s->Connection->CurrentNumConnection));
2009            }
2010            else
2011            {
2012                Debug("Session Invalid Protocol.\n");
2013            }
2014            ReleaseSession(s);
2015            goto CLEANUP;
2016        }
2017
2018        // RC4 高速暗号化鍵の生成
2019        if (s->UseFastRC4)
2020        {
2021            GenerateRC4KeyPair(&key_pair);
2022        }
2023
2024        // セッションのコネクションリスト (TCP) にこのコネクションのソケットを追加する
2025        sock = c->FirstSock;
2026        ts = NewTcpSock(sock);
2027        SetTimeout(sock, CONNECTING_TIMEOUT);
2028        direction = TCP_BOTH;
2029        LockList(s->Connection->Tcp->TcpSockList);
2030        {
2031            if (s->HalfConnection)
2032            {
2033                // ハーフコネクション時、現在のすべての TCP コネクションの方向を
2034                // 調べて自動的に調整する
2035                UINT i, c2s, s2c;
2036                c2s = s2c = 0;
2037                for (i = 0;i < LIST_NUM(s->Connection->Tcp->TcpSockList);i++)
2038                {
2039                    TCPSOCK *ts = (TCPSOCK *)LIST_DATA(s->Connection->Tcp->TcpSockList, i);
2040                    if (ts->Direction == TCP_SERVER_TO_CLIENT)
2041                    {
2042                        s2c++;
2043                    }
2044                    else
2045                    {
2046                        c2s++;
2047                    }
2048                }
2049                if (s2c > c2s)
2050                {
2051                    direction = TCP_CLIENT_TO_SERVER;
2052                }
2053                else
2054                {
2055                    direction = TCP_SERVER_TO_CLIENT;
2056                }
2057                Debug("%u/%u\n", s2c, c2s);
2058                ts->Direction = direction;
2059            }
2060        }
2061        UnlockList(s->Connection->Tcp->TcpSockList);
2062
2063        if (s->UseFastRC4)
2064        {
2065            // RC4 鍵情報の設定
2066            Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
2067
2068            InitTcpSockRc4Key(ts, true);
2069        }
2070
2071        // 成功結果を返す
2072        p = PackError(ERR_NO_ERROR);
2073        PackAddInt(p, "direction", direction);
2074
2075        if (s->UseFastRC4)
2076        {
2077            // RC4 鍵情報の追加
2078            PackAddData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey, sizeof(key_pair.ClientToServerKey));
2079            PackAddData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey, sizeof(key_pair.ServerToClientKey));
2080            {
2081                char key1[64], key2[64];
2082                BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
2083                BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
2084                Debug(
2085                    "Client to Server Key: %s\n"
2086                    "Server to Client Key: %s\n",
2087                    key1, key2);
2088            }
2089        }
2090
2091        HttpServerSend(c->FirstSock, p);
2092        FreePack(p);
2093
2094        SetTimeout(sock, INFINITE);
2095
2096        LockList(s->Connection->Tcp->TcpSockList);
2097        {
2098            Add(s->Connection->Tcp->TcpSockList, ts);
2099        }
2100        UnlockList(s->Connection->Tcp->TcpSockList);
2101
2102        // コネクション数をインクリメントする
2103        Inc(s->Connection->CurrentNumConnection);
2104        Debug("TCP Connection Incremented: %u\n", Count(s->Connection->CurrentNumConnection));
2105
2106        // セッションの Cancel を発行する
2107        Cancel(s->Cancel1);
2108
2109        Unlock(s->Connection->lock);
2110
2111        c->flag1 = true;
2112
2113        ReleaseSession(s);
2114
2115        return true;
2116    }
2117    else if (StrCmpi(method, "enum_hub") == 0)
2118    {
2119        // 仮想 HUB の列挙
2120        UINT i, num;
2121        LIST *o;
2122        o = NewListFast(NULL);
2123
2124        c->Type = CONNECTION_TYPE_ENUM_HUB;
2125
2126        FreePack(p);
2127        p = NewPack();
2128        LockList(c->Cedar->HubList);
2129        {
2130            num = LIST_NUM(c->Cedar->HubList);
2131            for (i = 0;i < num;i++)
2132            {
2133                HUB *h = LIST_DATA(c->Cedar->HubList, i);
2134                if (h->Option != NULL && h->Option->NoEnum == false)
2135                {
2136                    Insert(o, CopyStr(h->Name));
2137                }
2138            }
2139        }
2140        UnlockList(c->Cedar->HubList);
2141
2142        num = LIST_NUM(o);
2143        for (i = 0;i < num;i++)
2144        {
2145            char *name = LIST_DATA(o, i);
2146            PackAddStrEx(p, "HubName", name, i, num);
2147            Free(name);
2148        }
2149        ReleaseList(o);
2150        PackAddInt(p, "NumHub", num);
2151
2152        HttpServerSend(c->FirstSock, p);
2153        FreePack(p);
2154        FreePack(HttpServerRecv(c->FirstSock));
2155        c->Err = 0;
2156
2157        SLog(c->Cedar, "LS_ENUM_HUB", c->Name, num);
2158
2159        goto CLEANUP;
2160    }
2161    else if (StrCmpi(method, "farm_connect") == 0)
2162    {
2163        // サーバーファーム接続要求
2164        CEDAR *cedar = c->Cedar;
2165        c->Type = CONNECTION_TYPE_FARM_RPC;
2166        c->Err = 0;
2167        if (c->Cedar->Server == NULL)
2168        {
2169            // サポートされていない
2170            c->Err = ERR_NOT_FARM_CONTROLLER;
2171        }
2172        else
2173        {
2174            SERVER *s = c->Cedar->Server;
2175            if (s->ServerType != SERVER_TYPE_FARM_CONTROLLER || s->FarmControllerInited == false)
2176            {
2177                // ファームコントローラではない
2178                SLog(c->Cedar, "LS_FARM_ACCEPT_1", c->Name);
2179                c->Err = ERR_NOT_FARM_CONTROLLER;
2180            }
2181            else
2182            {
2183                UCHAR check_secure_password[SHA1_SIZE];
2184                UCHAR secure_password[SHA1_SIZE];
2185                // ユーザー認証
2186                SecurePassword(check_secure_password, s->HashedPassword, c->Random);
2187                if (PackGetDataSize(p, "SecurePassword") == sizeof(secure_password))
2188                {
2189                    PackGetData(p, "SecurePassword", secure_password);
2190                }
2191                else
2192                {
2193                    Zero(secure_password, sizeof(secure_password));
2194                }
2195
2196                if (Cmp(secure_password, check_secure_password, SHA1_SIZE) != 0)
2197                {
2198                    // パスワードが違う
2199                    SLog(c->Cedar, "LS_FARM_ACCEPT_2", c->Name);
2200                    c->Err = ERR_ACCESS_DENIED;
2201                }
2202                else
2203                {
2204                    // 証明書を取得する
2205                    BUF *b;
2206                    X *server_x;
2207
2208                    SLog(c->Cedar, "LS_FARM_ACCEPT_3", c->Name);
2209                    b = PackGetBuf(p, "ServerCert");
2210                    if (b == NULL)
2211                    {
2212                        c->Err = ERR_PROTOCOL_ERROR;
2213                    }
2214                    else
2215                    {
2216                        server_x = BufToX(b, false);
2217                        FreeBuf(b);
2218                        if (server_x == NULL)
2219                        {
2220                            c->Err = ERR_PROTOCOL_ERROR;
2221                        }
2222                        else
2223                        {
2224                            UINT ip;
2225                            UINT point;
2226                            char hostname[MAX_SIZE];
2227
2228#ifdef  OS_WIN32
2229                            MsSetThreadPriorityRealtime();
2230#endif  // OS_WIN32
2231
2232                            SetTimeout(c->FirstSock, SERVER_CONTROL_TCP_TIMEOUT);
2233
2234                            ip = PackGetIp32(p, "PublicIp");
2235                            point = PackGetInt(p, "Point");
2236                            if (PackGetStr(p, "HostName", hostname, sizeof(hostname)))
2237                            {
2238                                UINT num_port = PackGetIndexCount(p, "PublicPort");
2239                                if (num_port >= 1 && num_port <= MAX_PUBLIC_PORT_NUM)
2240                                {
2241                                    UINT *ports = ZeroMalloc(sizeof(UINT) * num_port);
2242                                    UINT i;
2243
2244                                    for (i = 0;i < num_port;i++)
2245                                    {
2246                                        ports[i] = PackGetIntEx(p, "PublicPort", i);
2247                                    }
2248
2249                                    SiFarmServ(s, c->FirstSock, server_x, ip, num_port, ports, hostname, point,
2250                                        PackGetInt(p, "Weight"), PackGetInt(p, "MaxSessions"));
2251
2252                                    Free(ports);
2253                                }
2254                            }
2255
2256                            FreeX(server_x);
2257                        }
2258                    }
2259                }
2260            }
2261        }
2262        FreePack(p);
2263        goto CLEANUP;
2264    }
2265    else if (StrCmpi(method, "admin") == 0 && c->Cedar->Server != NULL)
2266    {
2267        UINT err;
2268        // 管理用 RPC 接続要求
2269        c->Type = CONNECTION_TYPE_ADMIN_RPC;
2270        err = AdminAccept(c, p);
2271        FreePack(p);
2272        if (err != ERR_NO_ERROR)
2273        {
2274            PACK *p = PackError(err);
2275            HttpServerSend(c->FirstSock, p);
2276            FreePack(p);
2277        }
2278        goto CLEANUP;
2279    }
2280    else if (StrCmpi(method, "password") == 0)
2281    {
2282        UINT err;
2283        // パスワード変更要求
2284        c->Type = CONNECTION_TYPE_PASSWORD;
2285        err = ChangePasswordAccept(c, p);
2286        FreePack(p);
2287
2288        p = PackError(err);
2289        HttpServerSend(c->FirstSock, p);
2290        FreePack(p);
2291        goto CLEANUP;
2292    }
2293    else
2294    {
2295        // 不明なメソッド
2296        FreePack(p);
2297        c->Err = ERR_PROTOCOL_ERROR;
2298        goto CLEANUP;
2299    }
2300
2301CLEANUP:
2302    // ユーザーオブジェクトの解放
2303    if (loggedin_user_object != NULL)
2304    {
2305        ReleaseUser(loggedin_user_object);
2306    }
2307
2308    // エラーパケット送信
2309    p = PackError(c->Err);
2310    PackAddBool(p, "no_save_password", no_save_password);
2311    HttpServerSend(c->FirstSock, p);
2312    FreePack(p);
2313
2314    SLog(c->Cedar, "LS_CONNECTION_ERROR", c->Name, GetUniErrorStr(c->Err), c->Err);
2315
2316    return ret;
2317}
2318// シグネチャの送信 (TCP パケット) 用スレッド
2319void SendSignatureByTcpThread(THREAD *thread, void *param)
2320{
2321    BUF *buf;
2322    SEND_SIGNATURE_PARAM *p;
2323    SOCK *s;
2324    // 引数チェック
2325    if (thread == NULL || param == NULL)
2326    {
2327        return;
2328    }
2329
2330    p = (SEND_SIGNATURE_PARAM *)param;
2331
2332    AddWaitThread(thread);
2333    NoticeThreadInit(thread);
2334
2335    buf = p->Buffer;
2336
2337    s = Connect(p->Hostname, p->Port);
2338
2339    if (s != NULL)
2340    {
2341        SendAll(s, buf->Buf, buf->Size, false);
2342
2343        Disconnect(s);
2344        ReleaseSock(s);
2345    }
2346
2347    DelWaitThread(thread);
2348
2349    FreeBuf(buf);
2350    Free(p);
2351}
2352
2353// シグネチャの送信 (TCP パケット)
2354void SendSignatureByTcp(CONNECTION *c, IP *ip)
2355{
2356    NODE_INFO info;
2357    BUF *b;
2358    SEND_SIGNATURE_PARAM *param;
2359    THREAD *t;
2360    // 引数チェック
2361    if (c == NULL || ip == NULL)
2362    {
2363        return;
2364    }
2365
2366    if (c->Session == NULL || c->Session->ClientOption == NULL)
2367    {
2368        return;
2369    }
2370
2371    CreateNodeInfo(&info, c);
2372
2373    b = NewBuf();
2374    WriteBuf(b, CEDAR_SIGNATURE_STR, StrLen(CEDAR_SIGNATURE_STR));
2375    SeekBuf(b, 0, 0);
2376
2377    param = ZeroMalloc(sizeof(SEND_SIGNATURE_PARAM));
2378    param->Buffer = b;
2379
2380    if (c->Session != NULL && c->Session->ClientOption != NULL)
2381    {
2382        CLIENT_OPTION *o = c->Session->ClientOption;
2383
2384        if (o->ProxyType == PROXY_DIRECT)
2385        {
2386            IPToStr(param->Hostname, sizeof(param->Hostname), ip);
2387            param->Port = o->Port;
2388        }
2389        else
2390        {
2391            StrCpy(param->Hostname, sizeof(param->Hostname), o->ProxyName);
2392            param->Port = o->ProxyPort;
2393        }
2394    }
2395
2396    t = NewThread(SendSignatureByTcpThread, param);
2397    WaitThreadInit(t);
2398    ReleaseThread(t);
2399}
2400
2401// ノード情報の作成
2402void CreateNodeInfo(NODE_INFO *info, CONNECTION *c)
2403{
2404    SESSION *s;
2405    OS_INFO *os;
2406    char *product_id;
2407    IP ip;
2408    // 引数チェック
2409    if (c == NULL)
2410    {
2411        return;
2412    }
2413
2414    s = c->Session;
2415    os = GetOsInfo();
2416
2417    Zero(info, sizeof(NODE_INFO));
2418
2419    // クライアント製品名
2420    StrCpy(info->ClientProductName, sizeof(info->ClientProductName), c->ClientStr);
2421    // クライアントバージョン
2422    info->ClientProductVer = Endian32(c->ClientVer);
2423    // クライアントビルド番号
2424    info->ClientProductBuild = Endian32(c->ClientBuild);
2425
2426    // サーバー製品名
2427    StrCpy(info->ServerProductName, sizeof(info->ServerProductName), c->ServerStr);
2428    // サーバーバージョン
2429    info->ServerProductVer = Endian32(c->ServerVer);
2430    // サーバービルド番号
2431    info->ServerProductBuild = Endian32(c->ServerBuild);
2432
2433    // クライアント OS 名
2434    StrCpy(info->ClientOsName, sizeof(info->ClientOsName), os->OsProductName);
2435    // クライアント OS バージョン
2436    StrCpy(info->ClientOsVer, sizeof(info->ClientOsVer), os->OsVersion);
2437    // クライアント OS プロダクト ID
2438    product_id = OSGetProductId();
2439    StrCpy(info->ClientOsProductId, sizeof(info->ClientOsProductId), product_id);
2440    Free(product_id);
2441
2442    // クライアントホスト名
2443    GetMachineName(info->ClientHostname, sizeof(info->ClientHostname));
2444    // クライアント IP アドレス
2445    if (IsIP6(&c->FirstSock->LocalIP) == false)
2446    {
2447        info->ClientIpAddress = IPToUINT(&c->FirstSock->LocalIP);
2448    }
2449    else
2450    {
2451        Copy(info->ClientIpAddress6, c->FirstSock->LocalIP.ipv6_addr, sizeof(info->ClientIpAddress6));
2452    }
2453    // クライアントポート番号
2454    info->ClientPort = Endian32(c->FirstSock->LocalPort);
2455
2456    // サーバーホスト名
2457    StrCpy(info->ServerHostname, sizeof(info->ServerHostname), c->ServerName);
2458    // サーバー IP アドレス
2459    if (GetIP(&ip, info->ServerHostname))
2460    {
2461        if (IsIP6(&ip) == false)
2462        {
2463            info->ServerIpAddress = IPToUINT(&ip);
2464        }
2465        else
2466        {
2467            Copy(info->ServerIpAddress6, ip.ipv6_addr, sizeof(info->ServerIpAddress6));
2468        }
2469    }
2470    // サーバーポート番号
2471    info->ServerPort = Endian32(c->ServerPort);
2472
2473    if (s->ClientOption->ProxyType == PROXY_SOCKS || s->ClientOption->ProxyType == PROXY_HTTP)
2474    {
2475        // プロキシホスト名
2476        StrCpy(info->ProxyHostname, sizeof(info->ProxyHostname), s->ClientOption->ProxyName);
2477
2478        // プロキシ IP アドレス
2479        if (IsIP6(&c->FirstSock->RemoteIP) == false)
2480        {
2481            info->ProxyIpAddress = IPToUINT(&c->FirstSock->RemoteIP);
2482        }
2483        else
2484        {
2485            Copy(&info->ProxyIpAddress6, c->FirstSock->RemoteIP.ipv6_addr, sizeof(info->ProxyIpAddress6));
2486        }
2487
2488        info->ProxyPort = Endian32(c->FirstSock->RemotePort);
2489    }
2490
2491    // HUB 名
2492    StrCpy(info->HubName, sizeof(info->HubName), s->ClientOption->HubName);
2493
2494    // ユニーク ID
2495    Copy(info->UniqueId, c->Cedar->UniqueId, sizeof(info->UniqueId));
2496}
2497
2498// ソケットを追加接続する
2499SOCK *ClientAdditionalConnectToServer(CONNECTION *c)
2500{
2501    SOCK *s;
2502    // 引数チェック
2503    if (c == NULL)
2504    {
2505        return NULL;
2506    }
2507
2508    // ソケット接続
2509    s = ClientConnectGetSocket(c, true);
2510    if (s == NULL)
2511    {
2512        // 接続失敗
2513        return NULL;
2514    }
2515
2516    // ソケットをリストに追加する
2517    LockList(c->ConnectingSocks);
2518    {
2519        Add(c->ConnectingSocks, s);
2520        AddRef(s->ref);
2521    }
2522    UnlockList(c->ConnectingSocks);
2523
2524    if (c->Session->Halt)
2525    {
2526        // 停止
2527        Disconnect(s);
2528        LockList(c->ConnectingSocks);
2529        {
2530            if (Delete(c->ConnectingSocks, s))
2531            {
2532                ReleaseSock(s);
2533            }
2534        }
2535        UnlockList(c->ConnectingSocks);
2536        ReleaseSock(s);
2537        return NULL;
2538    }
2539
2540    // タイムアウト
2541    SetTimeout(s, CONNECTING_TIMEOUT);
2542
2543    // SSL 通信開始
2544    if (StartSSLEx(s, NULL, NULL, (c->DontUseTls1 ? false : true)) == false)
2545    {
2546        // SSL 通信失敗
2547        Disconnect(s);
2548        LockList(c->ConnectingSocks);
2549        {
2550            if (Delete(c->ConnectingSocks, s))
2551            {
2552                ReleaseSock(s);
2553            }
2554        }
2555        UnlockList(c->ConnectingSocks);
2556        ReleaseSock(s);
2557        return NULL;
2558    }
2559
2560    // 証明書のチェック
2561    if (CompareX(s->RemoteX, c->ServerX) == false)
2562    {
2563        // 証明書が不正
2564        Disconnect(s);
2565        c->Session->SessionTimeOuted = true;
2566    }
2567
2568    return s;
2569}
2570
2571// セキュアデバイス内の証明書と鍵を削除する
2572UINT SecureDelete(UINT device_id, char *pin, char *cert_name, char *key_name)
2573{
2574    SECURE *sec;
2575    // 引数チェック
2576    if (pin == NULL || device_id == 0)
2577    {
2578        return ERR_INTERNAL_ERROR;
2579    }
2580
2581    // デバイスを開く
2582    sec = OpenSec(device_id);
2583    if (sec == NULL)
2584    {
2585        return ERR_SECURE_DEVICE_OPEN_FAILED;
2586    }
2587
2588    // セッションを開く
2589    if (OpenSecSession(sec, 0) == false)
2590    {
2591        CloseSec(sec);
2592        return ERR_SECURE_DEVICE_OPEN_FAILED;
2593    }
2594
2595    // ログイン
2596    if (LoginSec(sec, pin) == false)
2597    {
2598        CloseSecSession(sec);
2599        CloseSec(sec);
2600        return ERR_SECURE_PIN_LOGIN_FAILED;
2601    }
2602
2603    // 証明書削除
2604    if (cert_name != NULL)
2605    {
2606        DeleteSecCert(sec, cert_name);
2607    }
2608
2609    // 秘密鍵削除
2610    if (key_name != NULL)
2611    {
2612        DeleteSecKey(sec, key_name);
2613    }
2614
2615    // ログアウト
2616    LogoutSec(sec);
2617
2618    // セッションを閉じる
2619    CloseSecSession(sec);
2620
2621    // デバイスを閉じる
2622    CloseSec(sec);
2623
2624    return ERR_NO_ERROR;
2625}
2626
2627// セキュアデバイス内の証明書と鍵を列挙する
2628UINT SecureEnum(UINT device_id, char *pin, TOKEN_LIST **cert_list, TOKEN_LIST **key_list)
2629{
2630    SECURE *sec;
2631    LIST *o;
2632    LIST *cert_name_list, *key_name_list;
2633    // 引数チェック
2634    if (pin == NULL || device_id == 0 || cert_list == NULL || key_list == NULL)
2635    {
2636        return ERR_INTERNAL_ERROR;
2637    }
2638
2639    // デバイスを開く
2640    sec = OpenSec(device_id);
2641    if (sec == NULL)
2642    {
2643        return ERR_SECURE_DEVICE_OPEN_FAILED;
2644    }
2645
2646    // セッションを開く
2647    if (OpenSecSession(sec, 0) == false)
2648    {
2649        CloseSec(sec);
2650        return ERR_SECURE_DEVICE_OPEN_FAILED;
2651    }
2652
2653    // ログイン
2654    if (LoginSec(sec, pin) == false)
2655    {
2656        CloseSecSession(sec);
2657        CloseSec(sec);
2658        return ERR_SECURE_PIN_LOGIN_FAILED;
2659    }
2660
2661    // オブジェクトの列挙
2662    if ((o = EnumSecObject(sec)) != NULL)
2663    {
2664        UINT i;
2665
2666        cert_name_list = NewList(CompareStr);
2667        key_name_list = NewList(CompareStr);
2668
2669        for (i = 0;i < LIST_NUM(o);i++)
2670        {
2671            SEC_OBJ *obj = LIST_DATA(o, i);
2672
2673            if (obj->Type == SEC_X)
2674            {
2675                Add(cert_name_list, CopyStr(obj->Name));
2676            }
2677            else if (obj->Type == SEC_K)
2678            {
2679                Add(key_name_list, CopyStr(obj->Name));
2680            }
2681        }
2682
2683        Sort(cert_name_list);
2684        Sort(key_name_list);
2685
2686        *cert_list = ListToTokenList(cert_name_list);
2687        *key_list = ListToTokenList(key_name_list);
2688
2689        // メモリ解放
2690        FreeStrList(cert_name_list);
2691        FreeStrList(key_name_list);
2692        FreeEnumSecObject(o);
2693    }
2694    else
2695    {
2696        *cert_list = NullToken();
2697        *key_list = NullToken();
2698    }
2699
2700    // ログアウト
2701    LogoutSec(sec);
2702
2703    // セッションを閉じる
2704    CloseSecSession(sec);
2705
2706    // デバイスを閉じる
2707    CloseSec(sec);
2708
2709    return ERR_NO_ERROR;
2710}
2711
2712// セキュアデバイスに証明書と鍵を記録する
2713UINT SecureWrite(UINT device_id, char *cert_name, X *x, char *key_name, K *k, char *pin)
2714{
2715    SECURE *sec;
2716    bool failed;
2717    // 引数チェック
2718    if (pin == NULL || device_id == 0 || cert_name == NULL || x == NULL || key_name == NULL || k == NULL)
2719    {
2720        return ERR_INTERNAL_ERROR;
2721    }
2722
2723    // デバイスを開く
2724    sec = OpenSec(device_id);
2725    if (sec == NULL)
2726    {
2727        return ERR_SECURE_DEVICE_OPEN_FAILED;
2728    }
2729
2730    // セッションを開く
2731    if (OpenSecSession(sec, 0) == false)
2732    {
2733        CloseSec(sec);
2734        return ERR_SECURE_DEVICE_OPEN_FAILED;
2735    }
2736
2737    // ログイン
2738    if (LoginSec(sec, pin) == false)
2739    {
2740        CloseSecSession(sec);
2741        CloseSec(sec);
2742        return ERR_SECURE_PIN_LOGIN_FAILED;
2743    }
2744
2745    // 登録
2746    failed = false;
2747
2748    // 証明書の登録
2749    if (WriteSecCert(sec, true, cert_name, x) == false)
2750    {
2751        failed = true;
2752    }
2753
2754    // 秘密鍵の登録
2755    if (WriteSecKey(sec, true, key_name, k) == false)
2756    {
2757        failed = true;
2758    }
2759
2760    // ログアウト
2761    LogoutSec(sec);
2762
2763    // セッションを閉じる
2764    CloseSecSession(sec);
2765
2766    // デバイスを閉じる
2767    CloseSec(sec);
2768
2769    if (failed == false)
2770    {
2771        // 成功
2772        return ERR_NO_ERROR;
2773    }
2774    else
2775    {
2776        // 失敗
2777        return ERR_SECURE_CANT_WRITE;
2778    }
2779}
2780
2781// セキュアデバイスによる署名を試行する
2782UINT SecureSign(SECURE_SIGN *sign, UINT device_id, char *pin)
2783{
2784    SECURE *sec;
2785    X *x;
2786    // 引数チェック
2787    if (sign == false || pin == NULL || device_id == 0)
2788    {
2789        return ERR_INTERNAL_ERROR;
2790    }
2791
2792    // デバイスを開く
2793    sec = OpenSec(device_id);
2794    if (sec == NULL)
2795    {
2796        return ERR_SECURE_DEVICE_OPEN_FAILED;
2797    }
2798
2799    // セッションを開く
2800    if (OpenSecSession(sec, 0) == false)
2801    {
2802        CloseSec(sec);
2803        return ERR_SECURE_DEVICE_OPEN_FAILED;
2804    }
2805
2806    // ログイン
2807    if (LoginSec(sec, pin) == false)
2808    {
2809        CloseSecSession(sec);
2810        CloseSec(sec);
2811        return ERR_SECURE_PIN_LOGIN_FAILED;
2812    }
2813
2814    // 証明書の読み込み
2815    x = ReadSecCert(sec, sign->SecurePublicCertName);
2816    if (x == NULL)
2817    {
2818        LogoutSec(sec);
2819        CloseSecSession(sec);
2820        CloseSec(sec);
2821        return ERR_SECURE_NO_CERT;
2822    }
2823
2824    // 秘密鍵による署名
2825    if (SignSec(sec, sign->SecurePrivateKeyName, sign->Signature, sign->Random, SHA1_SIZE) == false)
2826    {
2827        // 署名失敗
2828        FreeX(x);
2829        LogoutSec(sec);
2830        CloseSecSession(sec);
2831        CloseSec(sec);
2832        return ERR_SECURE_NO_PRIVATE_KEY;
2833    }
2834
2835    // 証明書をバッファに変換
2836    sign->ClientCert = x;
2837
2838    // ログアウト
2839    LogoutSec(sec);
2840
2841    // セッションを閉じる
2842    CloseSecSession(sec);
2843
2844    // デバイスを閉じる
2845    CloseSec(sec);
2846
2847    // 成功
2848    return ERR_NO_ERROR;
2849}
2850
2851// クライアントがサーバーに追加接続する
2852bool ClientAdditionalConnect(CONNECTION *c, THREAD *t)
2853{
2854    SOCK *s;
2855    PACK *p;
2856    TCPSOCK *ts;
2857    UINT err;
2858    UINT direction;
2859    RC4_KEY_PAIR key_pair;
2860    // 引数チェック
2861    if (c == NULL)
2862    {
2863        return false;
2864    }
2865
2866    // サーバーにソケット接続
2867    s = ClientAdditionalConnectToServer(c);
2868    if (s == NULL)
2869    {
2870        // ソケット接続に失敗
2871        return false;
2872    }
2873
2874    if (c->Halt)
2875    {
2876        goto CLEANUP;
2877    }
2878
2879    // シグネチャを送信
2880    Debug("Uploading Signature...\n");
2881    if (ClientUploadSignature(s) == false)
2882    {
2883        goto CLEANUP;
2884    }
2885
2886    if (c->Halt)
2887    {
2888        // 停止
2889        goto CLEANUP;
2890    }
2891
2892    // Hello パケットを受信
2893    Debug("Downloading Hello...\n");
2894    if (ClientDownloadHello(c, s) == false)
2895    {
2896        goto CLEANUP;
2897    }
2898
2899    if (c->Halt)
2900    {
2901        // 停止
2902        goto CLEANUP;
2903    }
2904
2905    // 追加接続用の認証データを送信
2906    if (ClientUploadAuth2(c, s) == false)
2907    {
2908        // 切断された
2909        goto CLEANUP;
2910    }
2911
2912    // 応答を受信
2913    p = HttpClientRecv(s);
2914    if (p == NULL)
2915    {
2916        // 切断された
2917        goto CLEANUP;
2918    }
2919
2920    err = GetErrorFromPack(p);
2921    direction = PackGetInt(p, "direction");
2922
2923    if (c->Session->UseFastRC4)
2924    {
2925        // RC4 鍵情報の取得
2926        if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
2927        {
2928            PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
2929        }
2930        if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
2931        {
2932            PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
2933        }
2934        {
2935            char key1[64], key2[64];
2936            BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
2937            BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
2938            Debug(
2939                "Client to Server Key: %s\n"
2940                "Server to Client Key: %s\n",
2941                key1, key2);
2942        }
2943    }
2944
2945    FreePack(p);
2946    p = NULL;
2947
2948    if (err != 0)
2949    {
2950        // エラーが発生した
2951        Debug("Additional Connect Error: %u\n", err);
2952        if (err == ERR_SESSION_TIMEOUT || err == ERR_INVALID_PROTOCOL)
2953        {
2954            // 致命的なエラーなので再接続しなおすことにする
2955            c->Session->SessionTimeOuted = true;
2956        }
2957        goto CLEANUP;
2958    }
2959
2960    Debug("Additional Connect Succeed!\n");
2961
2962    // 追加接続成功
2963    // コネクションの TcpSockList に追加する
2964    ts = NewTcpSock(s);
2965
2966    if (c->ServerMode == false)
2967    {
2968        if (c->Session->ClientOption->ConnectionDisconnectSpan != 0)
2969        {
2970            ts->DisconnectTick = Tick64() + c->Session->ClientOption->ConnectionDisconnectSpan * (UINT64)1000;
2971        }
2972    }
2973
2974    LockList(c->Tcp->TcpSockList);
2975    {
2976        ts->Direction = direction;
2977        Add(c->Tcp->TcpSockList, ts);
2978    }
2979    UnlockList(c->Tcp->TcpSockList);
2980    Debug("TCP Connection Incremented: %u\n", Count(c->CurrentNumConnection));
2981
2982    if (c->Session->HalfConnection)
2983    {
2984        Debug("New Half Connection: %s\n",
2985            direction == TCP_SERVER_TO_CLIENT ? "TCP_SERVER_TO_CLIENT" : "TCP_CLIENT_TO_SERVER"
2986            );
2987    }
2988
2989    if (c->Session->UseFastRC4)
2990    {
2991        // RC4 暗号化鍵のセット
2992        Copy(&ts->Rc4KeyPair, &key_pair, sizeof(RC4_KEY_PAIR));
2993
2994        InitTcpSockRc4Key(ts, false);
2995    }
2996
2997    // セッションに Cancel を発行する
2998    Cancel(c->Session->Cancel1);
2999
3000    // 接続中のソケット一覧からこのソケットを削除
3001    LockList(c->ConnectingSocks);
3002    {
3003        if (Delete(c->ConnectingSocks, s))
3004        {
3005            ReleaseSock(s);
3006        }
3007    }
3008    UnlockList(c->ConnectingSocks);
3009    ReleaseSock(s);
3010    return true;
3011
3012CLEANUP:
3013    // 切断処理
3014    Disconnect(s);
3015    LockList(c->ConnectingSocks);
3016    {
3017        if (Delete(c->ConnectingSocks, s))
3018        {
3019            ReleaseSock(s);
3020
3021        }
3022    }
3023    UnlockList(c->ConnectingSocks);
3024    ReleaseSock(s);
3025    return false;
3026}
3027
3028// セキュアデバイス署名スレッド
3029void ClientSecureSignThread(THREAD *thread, void *param)
3030{
3031    SECURE_SIGN_THREAD_PROC *p = (SECURE_SIGN_THREAD_PROC *)param;
3032    // 引数チェック
3033    if (thread == NULL || param == NULL)
3034    {
3035        return;
3036    }
3037
3038    NoticeThreadInit(thread);
3039
3040    p->Ok = p->SecureSignProc(p->Connection->Session, p->Connection, p->SecureSign);
3041    p->UserFinished = true;
3042}
3043
3044// セキュアデバイスを使用した署名
3045bool ClientSecureSign(CONNECTION *c, UCHAR *sign, UCHAR *random, X **x)
3046{
3047    SECURE_SIGN_THREAD_PROC *p;
3048    SECURE_SIGN *ss;
3049    SESSION *s;
3050    CLIENT_OPTION *o;
3051    CLIENT_AUTH *a;
3052    THREAD *thread;
3053    UINT64 start;
3054    bool ret;
3055    // 引数チェック
3056    if (c == NULL || sign == NULL || random == NULL || x == NULL)
3057    {
3058        return false;
3059    }
3060
3061    s = c->Session;
3062    o = s->ClientOption;
3063    a = s->ClientAuth;
3064
3065    p = ZeroMalloc(sizeof(SECURE_SIGN_THREAD_PROC));
3066    p->Connection = c;
3067    ss = p->SecureSign = ZeroMallocEx(sizeof(SECURE_SIGN), true);
3068    StrCpy(ss->SecurePrivateKeyName, sizeof(ss->SecurePrivateKeyName),
3069        a->SecurePrivateKeyName);
3070    StrCpy(ss->SecurePublicCertName, sizeof(ss->SecurePublicCertName),
3071        a->SecurePublicCertName);
3072    ss->UseSecureDeviceId = c->Cedar->Client->UseSecureDeviceId;
3073    Copy(ss->Random, random, SHA1_SIZE);
3074
3075#ifdef  OS_WIN32
3076    ss->BitmapId = CmGetSecureBitmapId(c->ServerName);
3077#endif  // OS_WIN32
3078
3079    p->SecureSignProc = a->SecureSignProc;
3080
3081    // スレッド作成
3082    thread = NewThread(ClientSecureSignThread, p);
3083    WaitThreadInit(thread);
3084
3085    // 署名が完了するかキャンセルするまで 0.5 秒ごとにポーリングする
3086    start = Tick64();
3087    while (true)
3088    {
3089        if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
3090        {
3091            // 切断防止のため一定期間ごとに NOOP を送信する
3092            start = Tick64();
3093            ClientUploadNoop(c);
3094        }
3095        if (p->UserFinished)
3096        {
3097            // ユーザーが選択した
3098            break;
3099        }
3100        WaitThread(thread, 500);
3101    }
3102    ReleaseThread(thread);
3103
3104    ret = p->Ok;
3105
3106    if (ret)
3107    {
3108        Copy(sign, ss->Signature, 128);
3109        *x = ss->ClientCert;
3110    }
3111
3112    Free(p->SecureSign);
3113    Free(p);
3114
3115    return ret;
3116}
3117
3118// サーバー証明書確認用スレッド
3119void ClientCheckServerCertThread(THREAD *thread, void *param)
3120{
3121    CHECK_CERT_THREAD_PROC *p = (CHECK_CERT_THREAD_PROC *)param;
3122    // 引数チェック
3123    if (thread == NULL || param == NULL)
3124    {
3125        return;
3126    }
3127
3128    // 初期化完了を通知する
3129    NoticeThreadInit(thread);
3130
3131    // ユーザーに選択を問い合わせる
3132    p->Ok = p->CheckCertProc(p->Connection->Session, p->Connection, p->ServerX, &p->Exipred);
3133    p->UserSelected = true;
3134}
3135
3136// クライアントがサーバーの証明書を確認する
3137bool ClientCheckServerCert(CONNECTION *c, bool *expired)
3138{
3139    CLIENT_AUTH *auth;
3140    X *x;
3141    CHECK_CERT_THREAD_PROC *p;
3142    THREAD *thread;
3143    CEDAR *cedar;
3144    bool ret;
3145    UINT64 start;
3146    // 引数チェック
3147    if (c == NULL)
3148    {
3149        return false;
3150    }
3151
3152    if (expired != NULL)
3153    {
3154        *expired = false;
3155    }
3156
3157    auth = c->Session->ClientAuth;
3158    cedar = c->Cedar;
3159
3160    if (auth->CheckCertProc == NULL && c->Session->LinkModeClient == false)
3161    {
3162        // チェック関数無し
3163        return true;
3164    }
3165
3166    if (c->Session->LinkModeClient && c->Session->Link->CheckServerCert == false)
3167    {
3168        // カスケード接続モードだがサーバー証明書はチェックしない
3169        return true;
3170    }
3171
3172    if (c->UseTicket)
3173    {
3174        // リダイレクト先 VPN サーバーの証明書を確認する
3175        if (CompareX(c->FirstSock->RemoteX, c->ServerX) == false)
3176        {
3177            return false;
3178        }
3179        else
3180        {
3181            return true;
3182        }
3183    }
3184
3185    x = CloneX(c->FirstSock->RemoteX);
3186    if (x == NULL)
3187    {
3188        // 変なエラーが発生した
3189        return false;
3190    }
3191
3192    if (CheckXDateNow(x))
3193    {
3194        // 信頼するルート証明書によって署名されているかどうか確認する
3195        if (c->Session->LinkModeClient == false)
3196        {
3197            // 通常の VPN Client モード
3198            if (CheckSignatureByCa(cedar, x))
3199            {
3200                // 署名されているのでこの証明書は信頼できる
3201                FreeX(x);
3202                return true;
3203            }
3204        }
3205        else
3206        {
3207            // カスケード接続モード
3208            if (CheckSignatureByCaLinkMode(c->Session, x))
3209            {
3210                // 署名されているのでこの証明書は信頼できる
3211                FreeX(x);
3212                return true;
3213            }
3214        }
3215    }
3216
3217    if (c->Session->LinkModeClient)
3218    {
3219        if (CheckXDateNow(x))
3220        {
3221            Lock(c->Session->Link->lock);
3222            {
3223                if (c->Session->Link->ServerCert != NULL)
3224                {
3225                    if (CompareX(c->Session->Link->ServerCert, x))
3226                    {
3227                        Unlock(c->Session->Link->lock);
3228                        // カスケード接続設定に登録されている証明書と完全一致
3229                        FreeX(x);
3230                        return true;
3231                    }
3232                }
3233            }
3234            Unlock(c->Session->Link->lock);
3235        }
3236        else
3237        {
3238            if (expired != NULL)
3239            {
3240                *expired = true;
3241            }
3242        }
3243
3244        // カスケード接続モードの場合はこの時点で検証失敗
3245        FreeX(x);
3246        return false;
3247    }
3248
3249    p = ZeroMalloc(sizeof(CHECK_CERT_THREAD_PROC));
3250    p->ServerX = x;
3251    p->CheckCertProc = auth->CheckCertProc;
3252    p->Connection = c;
3253
3254    // スレッドを作成する
3255    thread = NewThread(ClientCheckServerCertThread, p);
3256    WaitThreadInit(thread);
3257
3258    // ユーザーが接続の可否を選択するまで 0.5 秒間隔でポーリングする
3259    start = Tick64();
3260    while (true)
3261    {
3262        if ((Tick64() - start) > CONNECTING_POOLING_SPAN)
3263        {
3264            // 切断防止のため一定期間ごとに NOOP を送信する
3265            start = Tick64();
3266            ClientUploadNoop(c);
3267        }
3268        if (p->UserSelected)
3269        {
3270            // ユーザーが選択した
3271            break;
3272        }
3273        WaitThread(thread, 500);
3274    }
3275
3276    if (expired != NULL)
3277    {
3278        *expired = p->Exipred;
3279    }
3280
3281    ret = p->Ok;
3282    FreeX(p->ServerX);
3283    Free(p);
3284    ReleaseThread(thread);
3285
3286    return ret;
3287}
3288
3289// クライアントがサーバーに接続する
3290bool ClientConnect(CONNECTION *c)
3291{
3292    bool ret = false;
3293    bool ok = false;
3294    UINT err;
3295    SOCK *s;
3296    PACK *p = NULL;
3297    UINT session_key_32;
3298    SESSION *sess;
3299    char session_name[MAX_SESSION_NAME_LEN + 1];
3300    char connection_name[MAX_CONNECTION_NAME_LEN + 1];
3301    UCHAR session_key[SHA1_SIZE];
3302    RC4_KEY_PAIR key_pair;
3303    POLICY *policy;
3304    bool expired = false;
3305    IP server_ip;
3306    // 引数チェック
3307    if (c == NULL)
3308    {
3309        return false;
3310    }
3311
3312    sess = c->Session;
3313
3314    PrintStatus(sess, L"init");
3315    PrintStatus(sess, _UU("STATUS_1"));
3316
3317REDIRECTED:
3318
3319    // [接続中]
3320    c->Status = CONNECTION_STATUS_CONNECTING;
3321    c->Session->ClientStatus = CLIENT_STATUS_CONNECTING;
3322
3323    s = ClientConnectToServer(c);
3324    if (s == NULL)
3325    {
3326        PrintStatus(sess, L"free");
3327        return false;
3328    }
3329
3330    Copy(&server_ip, &s->RemoteIP, sizeof(IP));
3331
3332    if (c->Halt)
3333    {
3334        // 停止
3335        c->Err = ERR_USER_CANCEL;
3336        goto CLEANUP;
3337    }
3338
3339    // [ネゴシエーション中]
3340    c->Session->ClientStatus = CLIENT_STATUS_NEGOTIATION;
3341
3342    // シグネチャを送信
3343    Debug("Uploading Signature...\n");
3344    if (ClientUploadSignature(s) == false)
3345    {
3346        c->Err = ERR_DISCONNECTED;
3347        goto CLEANUP;
3348    }
3349
3350    if (c->Halt)
3351    {
3352        // 停止
3353        c->Err = ERR_USER_CANCEL;
3354        goto CLEANUP;
3355    }
3356
3357    PrintStatus(sess, _UU("STATUS_5"));
3358
3359    // Hello パケットを受信
3360    Debug("Downloading Hello...\n");
3361    if (ClientDownloadHello(c, s) == false)
3362    {
3363        goto CLEANUP;
3364    }
3365
3366    if (c->Session->ClientOption != NULL && c->Session->ClientOption->FromAdminPack)
3367    {
3368        if (IsAdminPackSupportedServerProduct(c->ServerStr) == false)
3369        {
3370            c->Err = ERR_NOT_ADMINPACK_SERVER;
3371            goto CLEANUP;
3372        }
3373    }
3374
3375    if (c->Halt)
3376    {
3377        // 停止
3378        c->Err = ERR_USER_CANCEL;
3379        goto CLEANUP;
3380    }
3381
3382    Debug("Server Version : %u\n"
3383        "Server String  : %s\n"
3384        "Server Build   : %u\n"
3385        "Client Version : %u\n"
3386        "Client String  : %s\n"
3387        "Client Build   : %u\n",
3388        c->ServerVer, c->ServerStr, c->ServerBuild,
3389        c->ClientVer, c->ClientStr, c->ClientBuild);
3390
3391    // ユーザー認証中
3392    c->Session->ClientStatus = CLIENT_STATUS_AUTH;
3393
3394    // クライアントによるサーバー証明書の確認
3395    if (ClientCheckServerCert(c, &expired) == false)
3396    {
3397        if (expired == false)
3398        {
3399            c->Err = ERR_CERT_NOT_TRUSTED;
3400        }
3401        else
3402        {
3403            c->Err = ERR_SERVER_CERT_EXPIRES;
3404        }
3405
3406        if (c->Session->LinkModeClient == false && c->Err == ERR_CERT_NOT_TRUSTED)
3407        {
3408            c->Session->ForceStopFlag = true;
3409        }
3410
3411        goto CLEANUP;
3412    }
3413
3414    PrintStatus(sess, _UU("STATUS_6"));
3415
3416    // 認証データを送信
3417    if (ClientUploadAuth(c) == false)
3418    {
3419        goto CLEANUP;
3420    }
3421
3422    if (c->Halt)
3423    {
3424        // 停止
3425        c->Err = ERR_USER_CANCEL;
3426        goto CLEANUP;
3427    }
3428
3429    // Welcome パケットを受信
3430    p = HttpClientRecv(s);
3431    if (p == NULL)
3432    {
3433        c->Err = ERR_DISCONNECTED;
3434        goto CLEANUP;
3435    }
3436
3437    // エラーチェック
3438    err = GetErrorFromPack(p);
3439    if (err != 0)
3440    {
3441        // エラー発生
3442        c->Err = err;
3443        c->ClientConnectError_NoSavePassword = PackGetBool(p, "no_save_password");
3444        goto CLEANUP;
3445    }
3446
3447    // 接続制限のためのブランド化文字列チェック
3448    {
3449        char tmp[20];
3450        char *branded_cfroms = _SS("BRANDED_C_FROM_S");
3451        PackGetStr(p, "branded_cfroms", tmp, sizeof(tmp));
3452
3453        if(StrLen(branded_cfroms) > 0 && StrCmpi(branded_cfroms, tmp) != 0)
3454        {
3455            c->Err = ERR_BRANDED_C_FROM_S;
3456            goto CLEANUP;
3457        }
3458    }
3459
3460    if (true)
3461    {
3462        // メッセージ取得
3463        UINT utf_size;
3464        char *utf;
3465        wchar_t *msg;
3466
3467        utf_size = PackGetDataSize(p, "Msg");
3468        utf = ZeroMalloc(utf_size + 8);
3469        PackGetData(p, "Msg", utf);
3470
3471        msg = CopyUtfToUni(utf);
3472
3473        if (IsEmptyUniStr(msg) == false)
3474        {
3475            if (c->Session->Client_Message != NULL)
3476            {
3477                Free(c->Session->Client_Message);
3478            }
3479
3480            c->Session->Client_Message = msg;
3481        }
3482        else
3483        {
3484            Free(msg);
3485        }
3486
3487        Free(utf);
3488    }
3489
3490    if (PackGetInt(p, "Redirect") != 0)
3491    {
3492        UINT i;
3493        UINT ip;
3494        UINT num_port;
3495        UINT *ports;
3496        UINT use_port = 0;
3497        UINT current_port = c->ServerPort;
3498        UCHAR ticket[SHA1_SIZE];
3499        X *server_cert;
3500        BUF *b;
3501
3502        // リダイレクトモード
3503        PrintStatus(sess, _UU("STATUS_8"));
3504
3505        ip = PackGetIp32(p, "Ip");
3506        num_port = MAX(MIN(PackGetIndexCount(p, "Port"), MAX_PUBLIC_PORT_NUM), 1);
3507        ports = ZeroMalloc(sizeof(UINT) * num_port);
3508        for (i = 0;i < num_port;i++)
3509        {
3510            ports[i] = PackGetIntEx(p, "Port", i);
3511        }
3512
3513        // ポート番号を選定する
3514        for (i = 0;i < num_port;i++)
3515        {
3516            if (ports[i] == current_port)
3517            {
3518                use_port = current_port;
3519            }
3520        }
3521        if (use_port == 0)
3522        {
3523            use_port = ports[0];
3524        }
3525
3526        Free(ports);
3527
3528        if (PackGetDataSize(p, "Ticket") == SHA1_SIZE)
3529        {
3530            PackGetData(p, "Ticket", ticket);
3531        }
3532
3533        b = PackGetBuf(p, "Cert");
3534        if (b != NULL)
3535        {
3536            server_cert = BufToX(b, false);
3537            FreeBuf(b);
3538        }
3539
3540        if (c->ServerX != NULL)
3541        {
3542            FreeX(c->ServerX);
3543        }
3544        c->ServerX = server_cert;
3545
3546        IPToStr32(c->ServerName, sizeof(c->ServerName), ip);
3547        c->ServerPort = use_port;
3548
3549        c->UseTicket = true;
3550        Copy(c->Ticket, ticket, SHA1_SIZE);
3551
3552        FreePack(p);
3553
3554        p = NewPack();
3555        HttpClientSend(s, p);
3556        FreePack(p);
3557
3558        p = NULL;
3559
3560        c->FirstSock = NULL;
3561        Disconnect(s);
3562        ReleaseSock(s);
3563        s = NULL;
3564
3565        goto REDIRECTED;
3566    }
3567
3568    PrintStatus(sess, _UU("STATUS_7"));
3569
3570    // Welcome パケットをパース
3571    if (ParseWelcomeFromPack(p, session_name, sizeof(session_name),
3572        connection_name, sizeof(connection_name), &policy) == false)
3573    {
3574        // パース失敗
3575        c->Err = ERR_PROTOCOL_ERROR;
3576        goto CLEANUP;
3577    }
3578
3579    // セッションキーを取得
3580    if (GetSessionKeyFromPack(p, session_key, &session_key_32) == false)
3581    {
3582        // 取得失敗
3583        Free(policy);
3584        policy = NULL;
3585        c->Err = ERR_PROTOCOL_ERROR;
3586        goto CLEANUP;
3587    }
3588
3589    Copy(c->Session->SessionKey, session_key, SHA1_SIZE);
3590    c->Session->SessionKey32 = session_key_32;
3591
3592    // Welcome パケットの内容を保存
3593    Debug("session_name: %s, connection_name: %s\n",
3594        session_name, connection_name);
3595
3596    Lock(c->Session->lock);
3597    {
3598        // 接続パラメータの展開と更新
3599        c->Session->MaxConnection = PackGetInt(p, "max_connection");
3600        c->Session->MaxConnection = MIN(c->Session->MaxConnection, c->Session->ClientOption->MaxConnection);
3601        c->Session->MaxConnection = MIN(c->Session->MaxConnection, MAX_TCP_CONNECTION);
3602        c->Session->MaxConnection = MAX(c->Session->MaxConnection, 1);
3603        c->Session->UseCompress = PackGetInt(p, "use_compress") == 0 ? false : true;
3604        c->Session->UseEncrypt = PackGetInt(p, "use_encrypt") == 0 ? false : true;
3605        c->Session->NoSendSignature = PackGetBool(p, "no_send_signature");
3606        if (c->Session->UseEncrypt)
3607        {
3608            c->Session->UseFastRC4 = PackGetInt(p, "use_fast_rc4") == 0 ? false : true;
3609        }
3610        c->Session->HalfConnection = PackGetInt(p, "half_connection") == 0 ? false : true;
3611        c->Session->Timeout = PackGetInt(p, "timeout");
3612        c->Session->QoS = PackGetInt(p, "qos") == 0 ? false : true;
3613        if (c->Session->QoS)
3614        {
3615            c->Session->MaxConnection = MAX(c->Session->MaxConnection, (UINT)(c->Session->HalfConnection ? 4 : 2));
3616        }
3617        c->Session->VLanId = PackGetInt(p, "vlan_id");
3618
3619        if (c->Protocol == CONNECTION_UDP)
3620        {
3621            // UDP プロトコルの場合、サーバーから鍵を受け取る
3622            if (PackGetDataSize(p, "udp_send_key") == sizeof(c->Session->UdpSendKey))
3623            {
3624                PackGetData(p, "udp_send_key", c->Session->UdpSendKey);
3625            }
3626
3627            if (PackGetDataSize(p, "udp_recv_key") == sizeof(c->Session->UdpRecvKey))
3628            {
3629                PackGetData(p, "udp_recv_key", c->Session->UdpRecvKey);
3630            }
3631        }
3632
3633        if (c->Session->UseFastRC4)
3634        {
3635            // RC4 鍵情報の取得
3636            if (PackGetDataSize(p, "rc4_key_client_to_server") == 16)
3637            {
3638                PackGetData(p, "rc4_key_client_to_server", key_pair.ClientToServerKey);
3639            }
3640            if (PackGetDataSize(p, "rc4_key_server_to_client") == 16)
3641            {
3642                PackGetData(p, "rc4_key_server_to_client", key_pair.ServerToClientKey);
3643            }
3644            {
3645                char key1[64], key2[64];
3646                BinToStr(key1, sizeof(key1), key_pair.ClientToServerKey, 16);
3647                BinToStr(key2, sizeof(key2), key_pair.ServerToClientKey, 16);
3648                Debug(
3649                    "Client to Server Key: %s\n"
3650                    "Server to Client Key: %s\n",
3651                    key1, key2);
3652            }
3653        }
3654    }
3655    Unlock(c->Session->lock);
3656
3657    Lock(c->lock);
3658    {
3659        if (c->Name != NULL)
3660        {
3661            Free(c->Name);
3662        }
3663        c->Name = CopyStr(connection_name);
3664
3665        // 暗号化アルゴリズム名の保存
3666        if (c->CipherName != NULL)
3667        {
3668            Free(c->CipherName);
3669        }
3670
3671        c->CipherName = CopyStr(c->FirstSock->CipherName);
3672    }
3673    Unlock(c->lock);
3674
3675    Lock(c->Session->lock);
3676    {
3677        if (c->Session->Name != NULL)
3678        {
3679            Free(c->Session->Name);
3680        }
3681        c->Session->Name = CopyStr(session_name);
3682
3683        c->Session->Policy = policy;
3684    }
3685    Unlock(c->Session->lock);
3686
3687    // Welcome パケットを破棄
3688    FreePack(p);
3689    p = NULL;
3690
3691    // server_ip に対して TCP でシグネチャを送信
3692    if (c->Session->NoSendSignature == false)
3693    {
3694        SendSignatureByTcp(c, &server_ip);
3695    }
3696
3697    // コネクション確立
3698    c->Session->ClientStatus = CLIENT_STATUS_ESTABLISHED;
3699
3700    // サーバー証明書の保存
3701    if (c->ServerX == NULL)
3702    {
3703        c->ServerX = CloneX(c->FirstSock->RemoteX);
3704    }
3705
3706    PrintStatus(sess, _UU("STATUS_9"));
3707
3708    // コネクションをトンネリングモードに移行
3709    StartTunnelingMode(c);
3710    s = NULL;
3711
3712    if (c->Session->HalfConnection)
3713    {
3714        // ハーフコネクション時の処理
3715        TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
3716        ts->Direction = TCP_CLIENT_TO_SERVER;
3717    }
3718
3719    if (c->Session->UseFastRC4)
3720    {
3721        // RC4 高速暗号化鍵のセット
3722        TCPSOCK *ts = (TCPSOCK *)LIST_DATA(c->Tcp->TcpSockList, 0);
3723        Copy(&ts->Rc4KeyPair, &key_pair, sizeof(key_pair));
3724
3725        InitTcpSockRc4Key(ts, false);
3726    }
3727
3728    // SSL 暗号化フラグ
3729    if (c->Session->UseEncrypt && c->Session->UseFastRC4 == false)
3730    {
3731        c->Session->UseSSLDataEncryption = true;
3732    }
3733    else
3734    {
3735        c->Session->UseSSLDataEncryption = false;
3736    }
3737
3738    PrintStatus(sess, L"free");
3739
3740    CLog(c->Cedar->Client, "LC_CONNECT_2", c->Session->ClientOption->AccountName,
3741        session_name);
3742
3743    if (c->Session->LinkModeClient && c->Session->Link != NULL)
3744    {
3745        HLog(c->Session->Link->Hub, "LH_CONNECT_2", c->Session->ClientOption->AccountName, session_name);
3746    }
3747
3748    // セッションのメインルーチン
3749    SessionMain(c->Session);
3750
3751    ok = true;
3752
3753    if (c->Err == ERR_USER_CANCEL)
3754    {
3755        ret = true;
3756    }
3757
3758CLEANUP:
3759    c->FirstSock = NULL;
3760
3761    if (p != NULL)
3762    {
3763        FreePack(p);
3764    }
3765
3766    Disconnect(s);
3767    ReleaseSock(s);
3768
3769    Debug("Error: %u\n", c->Err);
3770
3771    if (ok == false)
3772    {
3773        PrintStatus(sess, L"free");
3774    }
3775
3776    return ret;
3777}
3778
3779// Welcome パケットのパース
3780bool ParseWelcomeFromPack(PACK *p, char *session_name, UINT session_name_size,
3781                          char *connection_name, UINT connection_name_size,
3782                          POLICY **policy)
3783{
3784    // 引数チェック
3785    if (p == NULL || session_name == NULL || connection_name == NULL || policy == NULL)
3786    {
3787        return false;
3788    }
3789
3790    // セッション名
3791    if (PackGetStr(p, "session_name", session_name, session_name_size) == false)
3792    {
3793        return false;
3794    }
3795
3796    // コネクション名
3797    if (PackGetStr(p, "connection_name", connection_name, connection_name_size) == false)
3798    {
3799        return false;
3800    }
3801
3802    // ポリシー
3803    *policy = PackGetPolicy(p);
3804    if (*policy == NULL)
3805    {
3806        return false;
3807    }
3808
3809    return true;
3810}
3811
3812// Welcome パケットの生成
3813PACK *PackWelcome(SESSION *s)
3814{
3815    PACK *p;
3816    // 引数チェック
3817    if (s == NULL)
3818    {
3819        return NULL;
3820    }
3821
3822    p = NewPack();
3823
3824    // セッション名
3825    PackAddStr(p, "session_name", s->Name);
3826
3827    // コネクション名
3828    PackAddStr(p, "connection_name", s->Connection->Name);
3829
3830    // パラメータ
3831    PackAddInt(p, "max_connection", s->MaxConnection);
3832    PackAddInt(p, "use_encrypt", s->UseEncrypt == false ? 0 : 1);
3833    PackAddInt(p, "use_fast_rc4", s->UseFastRC4 == false ? 0 : 1);
3834    PackAddInt(p, "use_compress", s->UseCompress == false ? 0 : 1);
3835    PackAddInt(p, "half_connection", s->HalfConnection == false ? 0 : 1);
3836    PackAddInt(p, "timeout", s->Timeout);
3837    PackAddInt(p, "qos", s->QoS ? 1 : 0);
3838
3839    // セッションキー
3840    PackAddData(p, "session_key", s->SessionKey, SHA1_SIZE);
3841    PackAddInt(p, "session_key_32", s->SessionKey32);
3842
3843    // ポリシー
3844    PackAddPolicy(p, s->Policy);
3845
3846    // VLAN ID
3847    PackAddInt(p, "vlan_id", s->VLanId);
3848
3849    if (s->Connection->Protocol == CONNECTION_UDP)
3850    {
3851        // UDP プロトコルの場合、2 組のキーを生成する
3852        Rand(s->UdpSendKey, sizeof(s->UdpSendKey));
3853        Rand(s->UdpRecvKey, sizeof(s->UdpRecvKey));
3854
3855        // クライアントには鍵を反転して送る
3856        PackAddData(p, "udp_send_key", s->UdpRecvKey, sizeof(s->UdpRecvKey));
3857        PackAddData(p, "udp_recv_key", s->UdpSendKey, sizeof(s->UdpSendKey));
3858    }
3859
3860    // no_send_signature
3861    if (s->NoSendSignature)
3862    {
3863        PackAddBool(p, "no_send_signature", true);
3864    }
3865
3866    return p;
3867}
3868
3869#define PACK_ADD_POLICY_BOOL(name, value)   \
3870    PackAddInt(p, "policy:" name, y->value == false ? 0 : 1)
3871#define PACK_ADD_POLICY_UINT(name, value)   \
3872    PackAddInt(p, "policy:" name, y->value)
3873#define PACK_GET_POLICY_BOOL(name, value)   \
3874    y->value = (PackGetInt(p, "policy:" name) == 0 ? false : true)
3875#define PACK_GET_POLICY_UINT(name, value)   \
3876    y->value = PackGetInt(p, "policy:" name)
3877
3878// セッションキーを PACK から取得
3879bool GetSessionKeyFromPack(PACK *p, UCHAR *session_key, UINT *session_key_32)
3880{
3881    // 引数チェック
3882    if (p == NULL || session_key == NULL || session_key_32 == NULL)
3883    {
3884        return false;
3885    }
3886
3887    if (PackGetDataSize(p, "session_key") != SHA1_SIZE)
3888    {
3889        return false;
3890    }
3891    if (PackGetData(p, "session_key", session_key) == false)
3892    {
3893        return false;
3894    }
3895    *session_key_32 = PackGetInt(p, "session_key_32");
3896
3897    return true;
3898}
3899
3900// ポリシーを PACK から取得
3901POLICY *PackGetPolicy(PACK *p)
3902{
3903    // このあたりは急いで実装したのでコードがあまり美しくない。
3904    POLICY *y;
3905    // 引数チェック
3906    if (p == NULL)
3907    {
3908        return NULL;
3909    }
3910
3911    y = ZeroMalloc(sizeof(POLICY));
3912
3913    // bool 値
3914    // Ver 2
3915    PACK_GET_POLICY_BOOL("Access", Access);
3916    PACK_GET_POLICY_BOOL("DHCPFilter", DHCPFilter);
3917    PACK_GET_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
3918    PACK_GET_POLICY_BOOL("DHCPForce", DHCPForce);
3919    PACK_GET_POLICY_BOOL("NoBridge", NoBridge);
3920    PACK_GET_POLICY_BOOL("NoRouting", NoRouting);
3921    PACK_GET_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
3922    PACK_GET_POLICY_BOOL("NoServer", NoServer);
3923    PACK_GET_POLICY_BOOL("CheckMac", CheckMac);
3924    PACK_GET_POLICY_BOOL("CheckIP", CheckIP);
3925    PACK_GET_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
3926    PACK_GET_POLICY_BOOL("MonitorPort", MonitorPort);
3927    PACK_GET_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
3928    PACK_GET_POLICY_BOOL("FixPassword", FixPassword);
3929    PACK_GET_POLICY_BOOL("NoQoS", NoQoS);
3930    // Ver 3
3931    PACK_GET_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
3932    PACK_GET_POLICY_BOOL("RAFilter", RAFilter);
3933    PACK_GET_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
3934    PACK_GET_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
3935    PACK_GET_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
3936    PACK_GET_POLICY_BOOL("CheckIPv6", CheckIPv6);
3937    PACK_GET_POLICY_BOOL("NoServerV6", NoServerV6);
3938    PACK_GET_POLICY_BOOL("NoSavePassword", NoSavePassword);
3939    PACK_GET_POLICY_BOOL("FilterIPv4", FilterIPv4);
3940    PACK_GET_POLICY_BOOL("FilterIPv6", FilterIPv6);
3941    PACK_GET_POLICY_BOOL("FilterNonIP", FilterNonIP);
3942    PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
3943    PACK_GET_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
3944
3945    // UINT 値
3946    // Ver 2
3947    PACK_GET_POLICY_UINT("MaxConnection", MaxConnection);
3948    PACK_GET_POLICY_UINT("TimeOut", TimeOut);
3949    PACK_GET_POLICY_UINT("MaxMac", MaxMac);
3950    PACK_GET_POLICY_UINT("MaxIP", MaxIP);
3951    PACK_GET_POLICY_UINT("MaxUpload", MaxUpload);
3952    PACK_GET_POLICY_UINT("MaxDownload", MaxDownload);
3953    PACK_GET_POLICY_UINT("MultiLogins", MultiLogins);
3954    // Ver 3
3955    PACK_GET_POLICY_UINT("MaxIPv6", MaxIPv6);
3956    PACK_GET_POLICY_UINT("AutoDisconnect", AutoDisconnect);
3957    PACK_GET_POLICY_UINT("VLanId", VLanId);
3958
3959    // Ver 3 フラグ
3960    PACK_GET_POLICY_BOOL("Ver3", Ver3);
3961
3962    return y;
3963}
3964
3965// ポリシーを PACK に挿入
3966void PackAddPolicy(PACK *p, POLICY *y)
3967{
3968    // このあたりは急いで実装したのでコードがあまり美しくない。
3969    // 引数チェック
3970    if (p == NULL || y == NULL)
3971    {
3972        return;
3973    }
3974
3975    // bool 値
3976    // Ver 2
3977    PACK_ADD_POLICY_BOOL("Access", Access);
3978    PACK_ADD_POLICY_BOOL("DHCPFilter", DHCPFilter);
3979    PACK_ADD_POLICY_BOOL("DHCPNoServer", DHCPNoServer);
3980    PACK_ADD_POLICY_BOOL("DHCPForce", DHCPForce);
3981    PACK_ADD_POLICY_BOOL("NoBridge", NoBridge);
3982    PACK_ADD_POLICY_BOOL("NoRouting", NoRouting);
3983    PACK_ADD_POLICY_BOOL("PrivacyFilter", PrivacyFilter);
3984    PACK_ADD_POLICY_BOOL("NoServer", NoServer);
3985    PACK_ADD_POLICY_BOOL("CheckMac", CheckMac);
3986    PACK_ADD_POLICY_BOOL("CheckIP", CheckIP);
3987    PACK_ADD_POLICY_BOOL("ArpDhcpOnly", ArpDhcpOnly);
3988    PACK_ADD_POLICY_BOOL("MonitorPort", MonitorPort);
3989    PACK_ADD_POLICY_BOOL("NoBroadcastLimiter", NoBroadcastLimiter);
3990    PACK_ADD_POLICY_BOOL("FixPassword", FixPassword);
3991    PACK_ADD_POLICY_BOOL("NoQoS", NoQoS);
3992    // Ver 3
3993    PACK_ADD_POLICY_BOOL("RSandRAFilter", RSandRAFilter);
3994    PACK_ADD_POLICY_BOOL("RAFilter", RAFilter);
3995    PACK_ADD_POLICY_BOOL("DHCPv6Filter", DHCPv6Filter);
3996    PACK_ADD_POLICY_BOOL("DHCPv6NoServer", DHCPv6NoServer);
3997    PACK_ADD_POLICY_BOOL("NoRoutingV6", NoRoutingV6);
3998    PACK_ADD_POLICY_BOOL("CheckIPv6", CheckIPv6);
3999    PACK_ADD_POLICY_BOOL("NoServerV6", NoServerV6);
4000    PACK_ADD_POLICY_BOOL("NoSavePassword", NoSavePassword);
4001    PACK_ADD_POLICY_BOOL("FilterIPv4", FilterIPv4);
4002    PACK_ADD_POLICY_BOOL("FilterIPv6", FilterIPv6);
4003    PACK_ADD_POLICY_BOOL("FilterNonIP", FilterNonIP);
4004    PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRA", NoIPv6DefaultRouterInRA);
4005    PACK_ADD_POLICY_BOOL("NoIPv6DefaultRouterInRAWhenIPv6", NoIPv6DefaultRouterInRAWhenIPv6);
4006
4007    // UINT 値
4008    // Ver 2
4009    PACK_ADD_POLICY_UINT("MaxConnection", MaxConnection);
4010    PACK_ADD_POLICY_UINT("TimeOut", TimeOut);
4011    PACK_ADD_POLICY_UINT("MaxMac", MaxMac);
4012    PACK_ADD_POLICY_UINT("MaxIP", MaxIP);
4013    PACK_ADD_POLICY_UINT("MaxUpload", MaxUpload);
4014    PACK_ADD_POLICY_UINT("MaxDownload", MaxDownload);
4015    PACK_ADD_POLICY_UINT("MultiLogins", MultiLogins);
4016    // Ver 3
4017    PACK_ADD_POLICY_UINT("MaxIPv6", MaxIPv6);
4018    PACK_ADD_POLICY_UINT("AutoDisconnect", AutoDisconnect);
4019    PACK_ADD_POLICY_UINT("VLanId", VLanId);
4020
4021    // Ver 3 フラグ
4022    PackAddBool(p, "policy:Ver3", true);
4023}
4024
4025// 追加接続用の認証データをアップロードする
4026bool ClientUploadAuth2(CONNECTION *c, SOCK *s)
4027{
4028    PACK *p = NULL;
4029    // 引数チェック
4030    if (c == NULL)
4031    {
4032        return false;
4033    }
4034
4035    p = PackAdditionalConnect(c->Session->SessionKey);
4036
4037    PackAddClientVersion(p, c);
4038
4039    if (HttpClientSend(s, p) == false)
4040    {
4041        FreePack(p);
4042        return false;
4043    }
4044    FreePack(p);
4045
4046    return true;
4047}
4048
4049// NOOP を送信する
4050void ClientUploadNoop(CONNECTION *c)
4051{
4052    PACK *p;
4053    // 引数チェック
4054    if (c == NULL)
4055    {
4056        return;
4057    }
4058
4059    p = PackError(0);
4060    PackAddInt(p, "noop", 1);
4061    HttpClientSend(c->FirstSock, p);
4062    FreePack(p);
4063
4064    p = HttpClientRecv(c->FirstSock);
4065    if (p != NULL)
4066    {
4067        FreePack(p);
4068    }
4069}
4070
4071// クライアントのバージョン情報を PACK に追加する
4072void PackAddClientVersion(PACK *p, CONNECTION *c)
4073{
4074    // 引数チェック
4075    if (p == NULL || c == NULL)
4076    {
4077        return;
4078    }
4079
4080    PackAddStr(p, "client_str", c->ClientStr);
4081    PackAddInt(p, "client_ver", c->ClientVer);
4082    PackAddInt(p, "client_build", c->ClientBuild);
4083}
4084
4085// 新規接続用の認証データをアップロードする
4086bool ClientUploadAuth(CONNECTION *c)
4087{
4088    PACK *p = NULL;
4089    CLIENT_AUTH *a;
4090    CLIENT_OPTION *o;
4091    X *x;
4092    bool ret;
4093    NODE_INFO info;
4094    UCHAR secure_password[SHA1_SIZE];
4095    UCHAR sign[4096 / 8];
4096    UCHAR unique[SHA1_SIZE];
4097    RPC_WINVER v;
4098    // 引数チェック
4099    if (c == NULL)
4100    {
4101        return false;
4102    }
4103
4104    Zero(sign, sizeof(sign));
4105
4106    a = c->Session->ClientAuth;
4107    o = c->Session->ClientOption;
4108
4109    if (c->UseTicket == false)
4110    {
4111        switch (a->AuthType)
4112        {
4113        case CLIENT_AUTHTYPE_ANONYMOUS:
4114            // 匿名認証
4115            p = PackLoginWithAnonymous(o->HubName, a->Username);
4116            break;
4117
4118        case CLIENT_AUTHTYPE_PASSWORD:
4119            // パスワード認証
4120            SecurePassword(secure_password, a->HashedPassword, c->Random);
4121            p = PackLoginWithPassword(o->HubName, a->Username, secure_password);
4122            break;
4123
4124        case CLIENT_AUTHTYPE_PLAIN_PASSWORD:
4125            // 平文パスワード認証
4126            p = PackLoginWithPlainPassword(o->HubName, a->Username, a->PlainPassword);
4127            break;
4128
4129        case CLIENT_AUTHTYPE_CERT:
4130            // 証明書認証
4131            if (a->ClientX != NULL && a->ClientX->is_compatible_bit &&
4132                a->ClientX->bits != 0 && (a->ClientX->bits / 8) <= sizeof(sign))
4133            {
4134                if (RsaSignEx(sign, c->Random, SHA1_SIZE, a->ClientK, a->ClientX->bits))
4135                {
4136                    p = PackLoginWithCert(o->HubName, a->Username, a->ClientX, sign, a->ClientX->bits / 8);
4137                    c->ClientX = CloneX(a->ClientX);
4138                }
4139            }
4140            break;
4141
4142        case CLIENT_AUTHTYPE_SECURE:
4143            // セキュアデバイスによる認証
4144            if (ClientSecureSign(c, sign, c->Random, &x))
4145            {
4146                p = PackLoginWithCert(o->HubName, a->Username, x, sign, 128);
4147                c->ClientX = CloneX(x);
4148                FreeX(x);
4149            }
4150            else
4151            {
4152                c->Err = ERR_SECURE_DEVICE_OPEN_FAILED;
4153                c->Session->ForceStopFlag = true;
4154            }
4155            break;
4156        }
4157    }
4158    else
4159    {
4160        // チケット
4161        p = NewPack();
4162        PackAddStr(p, "method", "login");
4163        PackAddStr(p, "hubname", o->HubName);
4164        PackAddStr(p, "username", a->Username);
4165        PackAddInt(p, "authtype", AUTHTYPE_TICKET);
4166        PackAddData(p, "ticket", c->Ticket, SHA1_SIZE);
4167    }
4168
4169    // 現在時刻
4170    PackAddInt64(p, "timestamp", SystemTime64());
4171
4172    if (p == NULL)
4173    {
4174        // エラー
4175        if (c->Err != ERR_SECURE_DEVICE_OPEN_FAILED)
4176        {
4177            c->Err = ERR_PROTOCOL_ERROR;
4178        }
4179        return false;
4180    }
4181
4182    PackAddClientVersion(p, c);
4183
4184    // プロトコル
4185    PackAddInt(p, "protocol", c->Protocol);
4186
4187    // バージョン等
4188    PackAddStr(p, "hello", c->ClientStr);
4189    PackAddInt(p, "version", c->ClientVer);
4190    PackAddInt(p, "build", c->ClientBuild);
4191    PackAddInt(p, "client_id", c->Cedar->ClientId);
4192
4193    // 最大コネクション数
4194    PackAddInt(p, "max_connection", o->MaxConnection);
4195    // 暗号化使用フラグ
4196    PackAddInt(p, "use_encrypt", o->UseEncrypt == false ? 0 : 1);
4197    // 高速暗号化使用フラグ
4198    //  PackAddInt(p, "use_fast_rc4", o->UseFastRC4 == false ? 0 : 1);
4199    // データ圧縮使用フラグ
4200    PackAddInt(p, "use_compress", o->UseCompress == false ? 0 : 1);
4201    // ハーフコネクションフラグ
4202    PackAddInt(p, "half_connection", o->HalfConnection == false ? 0 : 1);
4203
4204    // ブリッジ / ルーティングモードフラグ
4205    PackAddBool(p, "require_bridge_routing_mode", o->RequireBridgeRoutingMode);
4206
4207    // モニタモードフラグ
4208    PackAddBool(p, "require_monitor_mode", o->RequireMonitorMode);
4209
4210    // VoIP / QoS フラグ
4211    PackAddBool(p, "qos", o->DisableQoS ? false : true);
4212
4213    // ユニーク ID
4214    GenerateMachineUniqueHash(unique);
4215    PackAddData(p, "unique_id", unique, SHA1_SIZE);
4216
4217    // ノード情報
4218    CreateNodeInfo(&info, c);
4219    OutRpcNodeInfo(p, &info);
4220
4221    // OS 情報
4222    GetWinVer(&v);
4223    OutRpcWinVer(p, &v);
4224
4225    ret = HttpClientSend(c->FirstSock, p);
4226    if (ret == false)
4227    {
4228        c->Err = ERR_DISCONNECTED;
4229    }
4230
4231    FreePack(p);
4232
4233    return ret;
4234}
4235
4236// Hello パケットをアップロードする
4237bool ServerUploadHello(CONNECTION *c)
4238{
4239    PACK *p;
4240    // 引数チェック
4241    if (c == NULL)
4242    {
4243        return false;
4244    }
4245
4246    // 乱数生成
4247    Rand(c->Random, SHA1_SIZE);
4248
4249    p = PackHello(c->Random, c->ServerVer, c->ServerBuild, c->ServerStr);
4250    if (HttpServerSend(c->FirstSock, p) == false)
4251    {
4252        FreePack(p);
4253        c->Err = ERR_DISCONNECTED;
4254        return false;
4255    }
4256
4257    FreePack(p);
4258
4259    return true;
4260}
4261
4262// Hello パケットをダウンロードする
4263bool ClientDownloadHello(CONNECTION *c, SOCK *s)
4264{
4265    PACK *p;
4266    UINT err;
4267    UCHAR random[SHA1_SIZE];
4268    // 引数チェック
4269    if (c == NULL)
4270    {
4271        return false;
4272    }
4273
4274    // データ受信
4275    p = HttpClientRecv(s);
4276    if (p == NULL)
4277    {
4278        c->Err = ERR_SERVER_IS_NOT_VPN;
4279        return false;
4280    }
4281
4282    if (err = GetErrorFromPack(p))
4283    {
4284        // エラー発生
4285        c->Err = err;
4286        FreePack(p);
4287        return false;
4288    }
4289
4290    // パケット解釈
4291    if (GetHello(p, random, &c->ServerVer, &c->ServerBuild, c->ServerStr, sizeof(c->ServerStr)) == false)
4292    {
4293        c->Err = ERR_SERVER_IS_NOT_VPN;
4294        FreePack(p);
4295        return false;
4296    }
4297
4298    if (c->FirstSock == s)
4299    {
4300        Copy(c->Random, random, SHA1_SIZE);
4301    }
4302
4303    FreePack(p);
4304
4305    return true;
4306}
4307
4308// シグネチャをダウンロードする
4309bool ServerDownloadSignature(CONNECTION *c)
4310{
4311    HTTP_HEADER *h;
4312    UCHAR *data;
4313    UINT data_size;
4314    SOCK *s;
4315    UINT num = 0, max = 19;
4316    // 引数チェック
4317    if (c == NULL)
4318    {
4319        return false;
4320    }
4321
4322    s = c->FirstSock;
4323
4324    while (true)
4325    {
4326        num++;
4327        if (num > max)
4328        {
4329            // 切断
4330            Disconnect(s);
4331            c->Err = ERR_CLIENT_IS_NOT_VPN;
4332            return false;
4333        }
4334        // ヘッダを受信する
4335        h = RecvHttpHeader(s);
4336        if (h == NULL)
4337        {
4338            c->Err = ERR_CLIENT_IS_NOT_VPN;
4339            return false;
4340        }
4341
4342        // 解釈する
4343        if (StrCmpi(h->Method, "POST") == 0)
4344        {
4345            // POST なのでデータを受信する
4346            data_size = GetContentLength(h);
4347            if ((data_size > 3411 || data_size < 1411) && (data_size != StrLen(HTTP_VPN_TARGET_POSTDATA)))
4348            {
4349                // データが大きすぎる
4350                HttpSendForbidden(s, h->Target, NULL);
4351                FreeHttpHeader(h);
4352                c->Err = ERR_CLIENT_IS_NOT_VPN;
4353                return false;
4354            }
4355            data = Malloc(data_size);
4356            if (RecvAll(s, data, data_size, s->SecureMode) == false)
4357            {
4358                // データ受信失敗
4359                Free(data);
4360                FreeHttpHeader(h);
4361                c->Err = ERR_DISCONNECTED;
4362                return false;
4363            }
4364            // Target を確認する
4365            if (StrCmpi(h->Target, HTTP_VPN_TARGET2) != 0)
4366            {
4367                // ターゲットが不正
4368                HttpSendNotFound(s, h->Target);
4369                Free(data);
4370                FreeHttpHeader(h);
4371            }
4372            else
4373            {
4374                if (((data_size == StrLen(HTTP_VPN_TARGET_POSTDATA)) && (Cmp(data, HTTP_VPN_TARGET_POSTDATA, data_size) == 0)) || (data_size >= 1411))
4375                {
4376                    // VPN Client が接続してきた
4377                    Free(data);
4378                    FreeHttpHeader(h);
4379                    return true;
4380                }
4381                else
4382                {
4383                    // VPN Client 以外のソフトウェアが接続してきた
4384                    HttpSendForbidden(s, h->Target, NULL);
4385                    FreeHttpHeader(h);
4386                }
4387            }
4388        }
4389        else
4390        {
4391            // これ以上解釈しても VPN クライアントで無い可能性が高いが
4392            // 一応する
4393            if (StrCmpi(h->Method, "GET") != 0)
4394            {
4395                // サポートされていないメソッド呼び出し
4396                HttpSendNotImplemented(s, h->Method, h->Target, h->Version);
4397            }
4398            else
4399            {
4400                if (StrCmpi(h->Target, "/") == 0)
4401                {
4402                    // ルートディレクトリ
4403                    HttpSendForbidden(c->FirstSock, h->Target, "");
4404                }
4405                else
4406                {
4407                    // Not Found
4408                    HttpSendNotFound(s, h->Target);
4409                }
4410            }
4411            FreeHttpHeader(h);
4412        }
4413    }
4414}
4415
4416// シグネチャをアップロードする
4417bool ClientUploadSignature(SOCK *s)
4418{
4419    HTTP_HEADER *h;
4420    // 引数チェック
4421    if (s == NULL)
4422    {
4423        return false;
4424    }
4425
4426    h = NewHttpHeader("POST", HTTP_VPN_TARGET2, "HTTP/1.1");
4427    AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE3));
4428    AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
4429
4430    if (PostHttp(s, h, HTTP_VPN_TARGET_POSTDATA, StrLen(HTTP_VPN_TARGET_POSTDATA)) == false)
4431    {
4432        FreeHttpHeader(h);
4433        return false;
4434    }
4435
4436    FreeHttpHeader(h);
4437
4438    return true;
4439}
4440
4441// サーバーへの接続を確立する
4442SOCK *ClientConnectToServer(CONNECTION *c)
4443{
4444    SOCK *s = NULL;
4445    X *x = NULL;
4446    K *k = NULL;
4447    // 引数チェック
4448    if (c == NULL)
4449    {
4450        return NULL;
4451    }
4452
4453    if (c->Halt)
4454    {
4455        c->Err = ERR_USER_CANCEL;
4456        return NULL;
4457    }
4458
4459    // 接続してソケットを取得
4460    s = ClientConnectGetSocket(c, false);
4461    if (s == NULL)
4462    {
4463        // 接続失敗
4464        return NULL;
4465    }
4466
4467    c->FirstSock = s;
4468
4469    if (c->Halt)
4470    {
4471        c->Err = ERR_USER_CANCEL;
4472        ReleaseSock(s);
4473        c->FirstSock = NULL;
4474        return NULL;
4475    }
4476
4477    // タイムアウト
4478    SetTimeout(s, CONNECTING_TIMEOUT);
4479
4480    // SSL 通信の開始
4481    if (StartSSLEx(s, x, k, (c->DontUseTls1 ? false : true)) == false)
4482    {
4483        // SSL 通信開始失敗
4484        Disconnect(s);
4485        ReleaseSock(s);
4486        c->FirstSock = NULL;
4487        c->Err = ERR_SERVER_IS_NOT_VPN;
4488        return NULL;
4489    }
4490
4491    if (s->RemoteX == NULL)
4492    {
4493        // SSL 通信開始失敗
4494        Disconnect(s);
4495        ReleaseSock(s);
4496        c->FirstSock = NULL;
4497        c->Err = ERR_SERVER_IS_NOT_VPN;
4498        return NULL;
4499    }
4500
4501    return s;
4502}
4503
4504// サーバーに接続しソケットを返す
4505SOCK *ClientConnectGetSocket(CONNECTION *c, bool additional_connect)
4506{
4507    SOCK *s = NULL;
4508    CLIENT_OPTION *o;
4509    char *host_for_direct_connection;
4510    UINT port_for_direct_connection;
4511    wchar_t tmp[MAX_SIZE];
4512    SESSION *sess;
4513    volatile bool *cancel_flag = NULL;
4514    void *hWnd;
4515    // 引数チェック
4516    if (c == NULL)
4517    {
4518        return NULL;
4519    }
4520
4521    sess = c->Session;
4522
4523    if (sess != NULL)
4524    {
4525        cancel_flag = &sess->CancelConnect;
4526    }
4527
4528    hWnd = c->hWndForUI;
4529
4530    o = c->Session->ClientOption;
4531
4532    if (c->RestoreServerNameAndPort && additional_connect)
4533    {
4534        // サーバー名とポート番号を元に戻す
4535        c->RestoreServerNameAndPort = false;
4536
4537        StrCpy(c->ServerName, sizeof(c->ServerName), o->Hostname);
4538        c->ServerPort = o->Port;
4539    }
4540
4541    host_for_direct_connection = c->ServerName;
4542    port_for_direct_connection = c->ServerPort;
4543
4544    if (o->PortUDP != 0)
4545    {
4546        // UDP Connection
4547        goto UDP_CONNECTION;
4548    }
4549
4550    switch (o->ProxyType)
4551    {
4552    case PROXY_DIRECT:  // TCP/IP
4553UDP_CONNECTION:
4554        UniFormat(tmp, sizeof(tmp), _UU("STATUS_4"), c->ServerName);
4555        PrintStatus(sess, tmp);
4556        // 本番
4557        s = TcpIpConnectEx(host_for_direct_connection, port_for_direct_connection,
4558            (bool *)cancel_flag, hWnd);
4559        if (s == NULL)
4560        {
4561            // 接続失敗
4562            c->Err = ERR_CONNECT_FAILED;
4563            return NULL;
4564        }
4565        break;
4566
4567    case PROXY_HTTP:    // HTTP Proxy
4568        host_for_direct_connection = o->ProxyName;
4569        port_for_direct_connection = o->ProxyPort;
4570
4571        UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
4572        PrintStatus(sess, tmp);
4573        // プロキシ接続
4574        s = ProxyConnectEx(c, host_for_direct_connection, port_for_direct_connection,
4575            c->ServerName, c->ServerPort, o->ProxyUsername, o->ProxyPassword,
4576            additional_connect, (bool *)cancel_flag, hWnd);
4577        if (s == NULL)
4578        {
4579            // 接続失敗
4580            return NULL;
4581        }
4582        break;
4583
4584    case PROXY_SOCKS:   // SOCKS Proxy
4585        host_for_direct_connection = o->ProxyName;
4586
4587        port_for_direct_connection = o->ProxyPort;
4588
4589        UniFormat(tmp, sizeof(tmp), _UU("STATUS_2"), c->ServerName, o->ProxyName);
4590        PrintStatus(sess, tmp);
4591        // SOCKS 接続
4592        s = SocksConnectEx(c, host_for_direct_connection, port_for_direct_connection,
4593            c->ServerName, c->ServerPort, o->ProxyUsername,
4594            additional_connect, (bool *)cancel_flag, hWnd);
4595        if (s == NULL)
4596        {
4597            // 接続失敗
4598            return NULL;
4599        }
4600        break;
4601    }
4602
4603    if (s == NULL)
4604    {
4605        // 接続失敗
4606        c->Err = ERR_CONNECT_FAILED;
4607    }
4608    else
4609    {
4610        // 接続成功
4611        // IP アドレスを控えておく
4612        if (GetIP(&c->Session->ServerIP, host_for_direct_connection) == false)
4613        {
4614            Copy(&c->Session->ServerIP, &s->RemoteIP, sizeof(IP));
4615        }
4616    }
4617
4618    return s;
4619}
4620
4621// SOCKS 経由で接続する
4622SOCK *SocksConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
4623                   char *server_host_name, UINT server_port,
4624                   char *username, bool additional_connect)
4625{
4626    return SocksConnectEx(c, proxy_host_name, proxy_port,
4627        server_host_name, server_port, username, additional_connect, NULL, NULL);
4628}
4629SOCK *SocksConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
4630                   char *server_host_name, UINT server_port,
4631                   char *username, bool additional_connect,
4632                   bool *cancel_flag, void *hWnd)
4633{
4634    SOCK *s = NULL;
4635    IP ip;
4636    // 引数チェック
4637    if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL
4638        || server_port == 0)
4639    {
4640        c->Err = ERR_PROXY_CONNECT_FAILED;
4641        return NULL;
4642    }
4643
4644    // 接続先サーバーの IP アドレスを取得す
4645    if (GetIP(&ip, server_host_name) == false)
4646    {
4647        // 失敗
4648        c->Err = ERR_CONNECT_FAILED;
4649        return NULL;
4650    }
4651
4652    if (c->Halt)
4653    {
4654        // 停止
4655        c->Err = ERR_USER_CANCEL;
4656        return NULL;
4657    }
4658
4659    // 接続
4660    s = TcpConnectEx2(proxy_host_name, proxy_port, 0, cancel_flag, hWnd);
4661    if (s == NULL)
4662    {
4663        // 失敗
4664        c->Err = ERR_PROXY_CONNECT_FAILED;
4665        return NULL;
4666    }
4667
4668    // タイムアウト設定
4669    SetTimeout(s, CONNECTING_TIMEOUT_PROXY);
4670
4671    if (additional_connect == false)
4672    {
4673        c->FirstSock = s;
4674    }
4675
4676    // リクエストパケット送信
4677    if (SocksSendRequestPacket(c, s, server_port, &ip, username) == false)
4678    {
4679        // 失敗
4680        if (additional_connect == false)
4681        {
4682            c->FirstSock = NULL;
4683        }
4684        Disconnect(s);
4685        ReleaseSock(s);
4686        return NULL;
4687    }
4688
4689    // 応答パケット受信
4690    if (SocksRecvResponsePacket(c, s) == false)
4691    {
4692        // 失敗
4693        if (additional_connect == false)
4694        {
4695            c->FirstSock = NULL;
4696        }
4697        Disconnect(s);
4698        ReleaseSock(s);
4699        return NULL;
4700    }
4701
4702    SetTimeout(s, INFINITE);
4703
4704    return s;
4705}
4706
4707// SOCKS 応答パケットを受信する
4708bool SocksRecvResponsePacket(CONNECTION *c, SOCK *s)
4709{
4710    BUF *b;
4711    UINT size = 8;
4712    UCHAR tmp[8];
4713    UCHAR vn, cd;
4714    // 引数チェック
4715    if (c == NULL || s == NULL)
4716    {
4717        return false;
4718    }
4719
4720    if (RecvAll(s, tmp, sizeof(tmp), false) == false)
4721    {
4722        c->Err = ERR_DISCONNECTED;
4723        return false;
4724    }
4725
4726    b = NewBuf();
4727    WriteBuf(b, tmp, sizeof(tmp));
4728    SeekBuf(b, 0, 0);
4729
4730    ReadBuf(b, &vn, 1);
4731    ReadBuf(b, &cd, 1);
4732
4733    FreeBuf(b);
4734
4735    if (vn != 0)
4736    {
4737        c->Err = ERR_PROXY_ERROR;
4738        return false;
4739    }
4740
4741    switch (cd)
4742    {
4743    case 90:
4744        // 成功
4745        return true;
4746
4747    case 93:
4748        // 認証失敗
4749        c->Err = ERR_PROXY_AUTH_FAILED;
4750        return false;
4751
4752    default:
4753        // サーバーへの接続失敗
4754        c->Err = ERR_CONNECT_FAILED;
4755        return false;
4756    }
4757}
4758
4759// SOCKS リクエストパケットを送信する
4760bool SocksSendRequestPacket(CONNECTION *c, SOCK *s, UINT dest_port, IP *dest_ip, char *userid)
4761{
4762    BUF *b;
4763    UCHAR vn, cd;
4764    USHORT port;
4765    UINT ip;
4766    bool ret;
4767    // 引数チェック
4768    if (s == NULL || dest_port == 0 || dest_ip == NULL || c == NULL)
4769    {
4770        return false;
4771    }
4772    if (userid == NULL)
4773    {
4774        userid = "";
4775    }
4776
4777    b = NewBuf();
4778    vn = 4;
4779    cd = 1;
4780    WriteBuf(b, &vn, 1);
4781    WriteBuf(b, &cd, 1);
4782    port = Endian16((USHORT)dest_port);
4783    ip = IPToUINT(dest_ip);
4784    WriteBuf(b, &port, 2);
4785    WriteBuf(b, &ip, 4);
4786    WriteBuf(b, userid, StrLen(userid) + 1);
4787
4788    ret = SendAll(s, b->Buf, b->Size, false);
4789    if (ret == false)
4790    {
4791        c->Err = ERR_DISCONNECTED;
4792    }
4793
4794    FreeBuf(b);
4795
4796    return ret;
4797}
4798
4799// プロキシ経由で接続する
4800SOCK *ProxyConnect(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
4801                   char *server_host_name, UINT server_port,
4802                   char *username, char *password, bool additional_connect)
4803{
4804    return ProxyConnectEx(c, proxy_host_name, proxy_port,
4805        server_host_name, server_port, username, password, additional_connect, NULL, NULL);
4806}
4807SOCK *ProxyConnectEx(CONNECTION *c, char *proxy_host_name, UINT proxy_port,
4808                   char *server_host_name, UINT server_port,
4809                   char *username, char *password, bool additional_connect,
4810                   bool *cancel_flag, void *hWnd)
4811{
4812    SOCK *s = NULL;
4813    bool use_auth = false;
4814    char tmp[MAX_SIZE];
4815    char auth_tmp_str[MAX_SIZE], auth_b64_str[MAX_SIZE * 2];
4816    char basic_str[MAX_SIZE * 2];
4817    UINT http_error_code;
4818    HTTP_HEADER *h;
4819    // 引数チェック
4820    if (c == NULL || proxy_host_name == NULL || proxy_port == 0 || server_host_name == NULL ||
4821        server_port == 0)
4822    {
4823        c->Err = ERR_PROXY_CONNECT_FAILED;
4824        return NULL;
4825    }
4826    if (username != NULL && password != NULL &&
4827        (StrLen(username) != 0 || StrLen(password) != 0))
4828    {
4829        use_auth = true;
4830    }
4831
4832    if (c->Halt)
4833    {
4834        // 停止
4835        c->Err = ERR_USER_CANCEL;
4836        return NULL;
4837    }
4838
4839    // 接続
4840    s = TcpConnectEx2(proxy_host_name, proxy_port, 0, cancel_flag, hWnd);
4841    if (s == NULL)
4842    {
4843        // 失敗
4844        c->Err = ERR_PROXY_CONNECT_FAILED;
4845        return NULL;
4846    }
4847
4848    // タイムアウト設定
4849    SetTimeout(s, CONNECTING_TIMEOUT_PROXY);
4850
4851    if (additional_connect == false)
4852    {
4853        c->FirstSock = s;
4854    }
4855
4856    // HTTP ヘッダ生成
4857    if (IsStrIPv6Address(server_host_name))
4858    {
4859        IP ip;
4860        char iptmp[MAX_PATH];
4861
4862        StrToIP(&ip, server_host_name);
4863        IPToStr(iptmp, sizeof(iptmp), &ip);
4864
4865        Format(tmp, sizeof(tmp), "[%s]:%u", iptmp, server_port);
4866    }
4867    else
4868    {
4869        Format(tmp, sizeof(tmp), "%s:%u", server_host_name, server_port);
4870    }
4871
4872    h = NewHttpHeader("CONNECT", tmp, "HTTP/1.0");
4873    AddHttpValue(h, NewHttpValue("User-Agent", c->Cedar->HttpUserAgent));
4874    Debug("proxy user agent = %s\n", c->Cedar->HttpUserAgent);
4875    AddHttpValue(h, NewHttpValue("Host", server_host_name));
4876    AddHttpValue(h, NewHttpValue("Content-Length", "0"));
4877    AddHttpValue(h, NewHttpValue("Proxy-Connection", "Keep-Alive"));
4878    AddHttpValue(h, NewHttpValue("Pragma", "no-cache"));
4879
4880    if (use_auth)
4881    {
4882        wchar_t tmp[MAX_SIZE];
4883        UniFormat(tmp, sizeof(tmp), _UU("STATUS_3"), server_host_name);
4884        // 認証文字列の生成
4885        Format(auth_tmp_str, sizeof(auth_tmp_str), "%s:%s",
4886            username, password);
4887
4888        // Base64 エンコード
4889        Zero(auth_b64_str, sizeof(auth_b64_str));
4890        Encode64(auth_b64_str, auth_tmp_str);
4891        Format(basic_str, sizeof(basic_str), "Basic %s", auth_b64_str);
4892
4893        AddHttpValue(h, NewHttpValue("Proxy-Authorization", basic_str));
4894    }
4895
4896    // 送信
4897    if (SendHttpHeader(s, h) == false)
4898    {
4899        // 失敗
4900        if (additional_connect == false)
4901        {
4902            c->FirstSock = NULL;
4903        }
4904        FreeHttpHeader(h);
4905        Disconnect(s);
4906        ReleaseSock(s);
4907        c->Err = ERR_PROXY_ERROR;
4908        return NULL;
4909    }
4910
4911    FreeHttpHeader(h);
4912
4913    if (c->Halt)
4914    {
4915        // 停止
4916        if (additional_connect == false)
4917        {
4918            c->FirstSock = NULL;
4919        }
4920        Disconnect(s);
4921        ReleaseSock(s);
4922        c->Err = ERR_USER_CANCEL;
4923        return NULL;
4924    }
4925
4926    // 結果を受信
4927    h = RecvHttpHeader(s);
4928    if (h == NULL)
4929    {
4930        // 失敗
4931        if (additional_connect == false)
4932        {
4933            c->FirstSock = NULL;
4934        }
4935        FreeHttpHeader(h);
4936        Disconnect(s);
4937        ReleaseSock(s);
4938        c->Err = ERR_PROXY_ERROR;
4939        return NULL;
4940    }
4941
4942    http_error_code = 0;
4943    if (StrLen(h->Method) == 8)
4944    {
4945        if (Cmp(h->Method, "HTTP/1.", 7) == 0)
4946        {
4947            http_error_code = ToInt(h->Target);
4948        }
4949    }
4950    FreeHttpHeader(h);
4951
4952    // コードを確認
4953    switch (http_error_code)
4954    {
4955    case 401:
4956    case 403:
4957    case 407:
4958        // 認証失敗
4959        if (additional_connect == false)
4960        {
4961            c->FirstSock = NULL;
4962        }
4963        Disconnect(s);
4964        ReleaseSock(s);
4965        c->Err = ERR_PROXY_AUTH_FAILED;
4966        return NULL;
4967
4968    default:
4969        if ((http_error_code / 100) == 2)
4970        {
4971            // 成功
4972            SetTimeout(s, INFINITE);
4973            return s;
4974        }
4975        else
4976        {
4977            // 不明な結果を受信
4978            if (additional_connect == false)
4979            {
4980                c->FirstSock = NULL;
4981            }
4982            Disconnect(s);
4983            ReleaseSock(s);
4984            c->Err = ERR_PROXY_ERROR;
4985            return NULL;
4986        }
4987    }
4988}
4989
4990// TCP 接続関数
4991SOCK *TcpConnectEx2(char *hostname, UINT port, UINT timeout, bool *cancel_flag, void *hWnd)
4992{
4993#ifdef  OS_WIN32
4994    if (hWnd == NULL)
4995    {
4996        return ConnectEx2(hostname, port, timeout, cancel_flag);
4997    }
4998    else
4999    {
5000        return WinConnectEx2((HWND)hWnd, hostname, port, timeout, 0, NULL, NULL);
5001    }
5002#else   // OS_WIN32
5003    return ConnectEx2(hostname, port, timeout, cancel_flag);
5004#endif  // OS_WIN32
5005}
5006
5007// TCP/IP で接続する
5008SOCK *TcpIpConnect(char *hostname, UINT port)
5009{
5010    return TcpIpConnectEx(hostname, port, NULL, NULL);
5011}
5012SOCK *TcpIpConnectEx(char *hostname, UINT port, bool *cancel_flag, void *hWnd)
5013{
5014    SOCK *s = NULL;
5015    // 引数チェック
5016    if (hostname == NULL || port == 0)
5017    {
5018        return NULL;
5019    }
5020
5021    s = TcpConnectEx2(hostname, port, 0, cancel_flag, hWnd);
5022    if (s == NULL)
5023    {
5024        return NULL;
5025    }
5026
5027    return s;
5028}
5029
5030// PACK にダミーのエントリを作成する
5031// Q. なぜランダムなサイズのランダムデータをここで挿入するのか?
5032// A. ネットワーク経路中の盗聴者によってこの SSL 通信が VPN 通信であること
5033//    を検出しにくいようにするためである。
5034void CreateDummyValue(PACK *p)
5035{
5036    UINT size;
5037    UCHAR *buf;
5038    // 引数チェック
5039    if (p == NULL)
5040    {
5041        return;
5042    }
5043
5044    size = Rand32() % HTTP_PACK_RAND_SIZE_MAX;
5045    buf = Malloc(size);
5046    Rand(buf, size);
5047
5048    PackAddData(p, "pencore", buf, size);
5049
5050    Free(buf);
5051}
5052
5053// サーバーがクライアントから PACK を受信する
5054PACK *HttpServerRecv(SOCK *s)
5055{
5056    BUF *b;
5057    PACK *p;
5058    HTTP_HEADER *h;
5059    UINT size;
5060    UCHAR *tmp;
5061    HTTP_VALUE *v;
5062    // 引数チェック
5063    if (s == NULL)
5064    {
5065        return NULL;
5066    }
5067
5068START:
5069
5070    h = RecvHttpHeader(s);
5071    if (h == NULL)
5072    {
5073        goto BAD_REQUEST;
5074    }
5075
5076    if (StrCmpi(h->Method, "POST") != 0 ||
5077        StrCmpi(h->Target, HTTP_VPN_TARGET) != 0 ||
5078        StrCmpi(h->Version, "HTTP/1.1") != 0)
5079    {
5080        FreeHttpHeader(h);
5081        goto BAD_REQUEST;
5082    }
5083
5084    v = GetHttpValue(h, "Content-Type");
5085    if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
5086    {
5087        FreeHttpHeader(h);
5088        goto BAD_REQUEST;
5089    }
5090
5091    size = GetContentLength(h);
5092    if (size == 0 || size > MAX_PACK_SIZE)
5093    {
5094        FreeHttpHeader(h);
5095        goto BAD_REQUEST;
5096    }
5097
5098    tmp = MallocEx(size, true);
5099    if (RecvAll(s, tmp, size, s->SecureMode) == false)
5100    {
5101        Free(tmp);
5102        FreeHttpHeader(h);
5103        return NULL;
5104    }
5105
5106    b = NewBuf();
5107    WriteBuf(b, tmp, size);
5108    Free(tmp);
5109    FreeHttpHeader(h);
5110
5111    SeekBuf(b, 0, 0);
5112    p = BufToPack(b);
5113    FreeBuf(b);
5114
5115    // NOOP かどうか判断
5116    if (PackGetInt(p, "noop") != 0)
5117    {
5118        Debug("recv: noop\n");
5119        FreePack(p);
5120
5121        p = PackError(0);
5122        PackAddInt(p, "noop", 1);
5123        if (HttpServerSend(s, p) == false)
5124        {
5125            FreePack(p);
5126            return NULL;
5127        }
5128
5129        FreePack(p);
5130
5131        goto START;
5132    }
5133
5134    return p;
5135
5136BAD_REQUEST:
5137    // エラーを返す
5138
5139
5140    return NULL;
5141}
5142
5143// クライアントがサーバーから PACK を受信する
5144PACK *HttpClientRecv(SOCK *s)
5145{
5146    BUF *b;
5147    PACK *p;
5148    HTTP_HEADER *h;
5149    UINT size;
5150    UCHAR *tmp;
5151    HTTP_VALUE *v;
5152    // 引数チェック
5153    if (s == NULL)
5154    {
5155        return NULL;
5156    }
5157
5158    h = RecvHttpHeader(s);
5159    if (h == NULL)
5160    {
5161        return NULL;
5162    }
5163
5164    if (StrCmpi(h->Method, "HTTP/1.1") != 0 ||
5165        StrCmpi(h->Target, "200") != 0)
5166    {
5167        FreeHttpHeader(h);
5168        return NULL;
5169    }
5170
5171    v = GetHttpValue(h, "Content-Type");
5172    if (v == NULL || StrCmpi(v->Data, HTTP_CONTENT_TYPE2) != 0)
5173    {
5174        FreeHttpHeader(h);
5175        return NULL;
5176    }
5177
5178    size = GetContentLength(h);
5179    if (size == 0 || size > MAX_PACK_SIZE)
5180    {
5181        FreeHttpHeader(h);
5182        return NULL;
5183    }
5184
5185    tmp = MallocEx(size, true);
5186    if (RecvAll(s, tmp, size, s->SecureMode) == false)
5187    {
5188        Free(tmp);
5189        FreeHttpHeader(h);
5190        return NULL;
5191    }
5192
5193    b = NewBuf();
5194    WriteBuf(b, tmp, size);
5195    Free(tmp);
5196    FreeHttpHeader(h);
5197
5198    SeekBuf(b, 0, 0);
5199    p = BufToPack(b);
5200    FreeBuf(b);
5201
5202    return p;
5203}
5204
5205// クライアントからサーバーに PACK を送信する
5206bool HttpClientSend(SOCK *s, PACK *p)
5207{
5208    BUF *b;
5209    bool ret;
5210    HTTP_HEADER *h;
5211    char date_str[MAX_SIZE];
5212    // 引数チェック
5213    if (s == NULL || p == NULL)
5214    {
5215        return false;
5216    }
5217
5218    CreateDummyValue(p);
5219
5220    b = PackToBuf(p);
5221    if (b == NULL)
5222    {
5223        return false;
5224    }
5225
5226    h = NewHttpHeader("POST", HTTP_VPN_TARGET, "HTTP/1.1");
5227
5228    GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
5229    AddHttpValue(h, NewHttpValue("Date", date_str));
5230    AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
5231    AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
5232    AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
5233
5234    ret = PostHttp(s, h, b->Buf, b->Size);
5235
5236    FreeHttpHeader(h);
5237    FreeBuf(b);
5238
5239    return ret;
5240}
5241
5242// サーバーからクライアントに PACK を送信する
5243bool HttpServerSend(SOCK *s, PACK *p)
5244{
5245    BUF *b;
5246    bool ret;
5247    HTTP_HEADER *h;
5248    char date_str[MAX_SIZE];
5249    // 引数チェック
5250    if (s == NULL || p == NULL)
5251    {
5252        return false;
5253    }
5254
5255    CreateDummyValue(p);
5256
5257    b = PackToBuf(p);
5258    if (b == NULL)
5259    {
5260        return false;
5261    }
5262
5263    h = NewHttpHeader("HTTP/1.1", "200", "OK");
5264
5265    GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
5266    AddHttpValue(h, NewHttpValue("Date", date_str));
5267    AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
5268    AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
5269    AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE2));
5270
5271    ret = PostHttp(s, h, b->Buf, b->Size);
5272
5273    FreeHttpHeader(h);
5274    FreeBuf(b);
5275
5276    return ret;
5277}
5278
5279// 501 Not Implemented エラーの送信
5280bool HttpSendNotImplemented(SOCK *s, char *method, char *target, char *version)
5281{
5282    HTTP_HEADER *h;
5283    char date_str[MAX_SIZE];
5284    char *str;
5285    UINT str_size;
5286    char port_str[MAX_SIZE];
5287    bool ret;
5288    char host[MAX_SIZE];
5289    UINT port;
5290    // 引数チェック
5291    if (s == NULL || target == NULL)
5292    {
5293        return false;
5294    }
5295
5296    // ホスト名の取得
5297    GetMachineName(host, MAX_SIZE);
5298    // ポート番号の取得
5299    port = s->LocalPort;
5300
5301    // ヘッダの作成
5302    GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
5303
5304    h = NewHttpHeader("HTTP/1.1", "501", "Method Not Implemented");
5305
5306    AddHttpValue(h, NewHttpValue("Date", date_str));
5307    AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
5308    AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
5309    AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
5310
5311    // データの作成
5312    str_size = sizeof(http_501_str) * 2 + StrLen(target) + StrLen(host) + StrLen(method) + StrLen(version);
5313    str = Malloc(str_size);
5314    StrCpy(str, str_size, http_501_str);
5315
5316    // TARGET
5317    ReplaceStri(str, str_size, str, "$TARGET$", target);
5318
5319    // HOST
5320    ReplaceStri(str, str_size, str, "$HOST$", host);
5321
5322    // PORT
5323    ToStr(port_str, port);
5324    ReplaceStri(str, str_size, str, "$PORT$", port_str);
5325
5326    // METHOD
5327    ReplaceStri(str, str_size, str, "$METHOD$", method);
5328
5329    // VERSION
5330    ReplaceStri(str, str_size, str, "$VERSION$", version);
5331
5332    // 送信
5333    ret = PostHttp(s, h, str, StrLen(str));
5334
5335    FreeHttpHeader(h);
5336    Free(str);
5337
5338    return ret;
5339}
5340
5341// 404 Not Found エラーの送信
5342bool HttpSendNotFound(SOCK *s, char *target)
5343{
5344    HTTP_HEADER *h;
5345    char date_str[MAX_SIZE];
5346    char *str;
5347    UINT str_size;
5348    char port_str[MAX_SIZE];
5349    bool ret;
5350    char host[MAX_SIZE];
5351    UINT port;
5352    // 引数チェック
5353    if (s == NULL || target == NULL)
5354    {
5355        return false;
5356    }
5357
5358    // ホスト名の取得
5359    GetMachineName(host, MAX_SIZE);
5360    // ポート番号の取得
5361    port = s->LocalPort;
5362
5363    // ヘッダの作成
5364    GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
5365
5366    h = NewHttpHeader("HTTP/1.1", "404", "Not Found");
5367
5368    AddHttpValue(h, NewHttpValue("Date", date_str));
5369    AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
5370    AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
5371    AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
5372
5373    // データの作成
5374    str_size = sizeof(http_404_str) * 2 + StrLen(target) + StrLen(host);
5375    str = Malloc(str_size);
5376    StrCpy(str, str_size, http_404_str);
5377
5378    // TARGET
5379    ReplaceStri(str, str_size, str, "$TARGET$", target);
5380
5381    // HOST
5382    ReplaceStri(str, str_size, str, "$HOST$", host);
5383
5384    // PORT
5385    ToStr(port_str, port);
5386    ReplaceStri(str, str_size, str, "$PORT$", port_str);
5387
5388    // 送信
5389    ret = PostHttp(s, h, str, StrLen(str));
5390
5391    FreeHttpHeader(h);
5392    Free(str);
5393
5394    return ret;
5395}
5396
5397// 403 Forbidden エラーの送信
5398bool HttpSendForbidden(SOCK *s, char *target, char *server_id)
5399{
5400    HTTP_HEADER *h;
5401    char date_str[MAX_SIZE];
5402    char *str;
5403    UINT str_size;
5404    char port_str[MAX_SIZE];
5405    bool ret;
5406    char host[MAX_SIZE];
5407    UINT port;
5408    // 引数チェック
5409    if (s == NULL || target == NULL)
5410    {
5411        return false;
5412    }
5413
5414    // ホスト名の取得
5415    GetMachineName(host, MAX_SIZE);
5416    // ポート番号の取得
5417    port = s->LocalPort;
5418
5419    // ヘッダの作成
5420    GetHttpDateStr(date_str, sizeof(date_str), SystemTime64());
5421
5422    h = NewHttpHeader("HTTP/1.1", "403", "Forbidden");
5423
5424    AddHttpValue(h, NewHttpValue("Date", date_str));
5425    AddHttpValue(h, NewHttpValue("Keep-Alive", HTTP_KEEP_ALIVE));
5426    AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive"));
5427    AddHttpValue(h, NewHttpValue("Content-Type", HTTP_CONTENT_TYPE));
5428
5429    // データの作成
5430    str_size = sizeof(http_403_str) * 2 + StrLen(target) + StrLen(host);
5431    str = Malloc(str_size);
5432    StrCpy(str, str_size, http_403_str);
5433
5434    // TARGET
5435    ReplaceStri(str, str_size, str, "$TARGET$", target);
5436
5437    // HOST
5438    ReplaceStri(str, str_size, str, "$HOST$", host);
5439
5440    // PORT
5441    ToStr(port_str, port);
5442    ReplaceStri(str, str_size, str, "$PORT$", port_str);
5443
5444    // 送信
5445    ret = PostHttp(s, h, str, StrLen(str));
5446
5447    FreeHttpHeader(h);
5448    Free(str);
5449
5450    return ret;
5451}
5452
5453// HTTP ヘッダ用の日時文字列を取得
5454void GetHttpDateStr(char *str, UINT size, UINT64 t)
5455{
5456    SYSTEMTIME s;
5457    static char *wday[] =
5458    {
5459        "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat",
5460    };
5461    static char *month[] =
5462    {
5463        "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct",
5464        "Nov", "Dec",
5465    };
5466    // 引数チェック
5467    if (str == NULL)
5468    {
5469        return;
5470    }
5471    UINT64ToSystem(&s, t);
5472
5473    Format(str, size, "%s, %02u %s %04u %02u:%02u:%02u GMT",
5474        wday[s.wDayOfWeek], s.wDay, month[s.wMonth - 1], s.wYear,
5475        s.wHour, s.wMinute, s.wSecond);
5476}
5477
5478// HTTP ヘッダからコンテンツ長を取得する
5479UINT GetContentLength(HTTP_HEADER *header)
5480{
5481    UINT ret;
5482    HTTP_VALUE *v;
5483    // 引数チェック
5484    if (header == NULL)
5485    {
5486        return 0;
5487    }
5488
5489    v = GetHttpValue(header, "Content-Length");
5490    if (v == NULL)
5491    {
5492        return 0;
5493    }
5494
5495    ret = ToInt(v->Data);
5496
5497    return ret;
5498}
5499
5500// HTTP でデータを送信する
5501bool PostHttp(SOCK *s, HTTP_HEADER *header, void *post_data, UINT post_size)
5502{
5503    char *header_str;
5504    BUF *b;
5505    bool ret;
5506    // 引数チェック
5507    if (s == NULL || header == NULL || post_data == NULL)
5508    {
5509        return false;
5510    }
5511
5512    // Content-Lentgh が存在するかどうかチェック
5513    if (GetHttpValue(header, "Content-Length") == NULL)
5514    {
5515        char tmp[MAX_SIZE];
5516        // 存在しないので付加する
5517        ToStr(tmp, post_size);
5518        AddHttpValue(header, NewHttpValue("Content-Length", tmp));
5519    }
5520
5521    // ヘッダを文字列にする
5522    header_str = HttpHeaderToStr(header);
5523    if (header_str == NULL)
5524    {
5525        return false;
5526    }
5527    b = NewBuf();
5528    WriteBuf(b, header_str, StrLen(header_str));
5529    Free(header_str);
5530
5531    // データを追記する
5532    WriteBuf(b, post_data, post_size);
5533
5534    // 送信する
5535    ret = SendAll(s, b->Buf, b->Size, s->SecureMode);
5536
5537    FreeBuf(b);
5538
5539    return ret;
5540}
5541
5542// HTTP ヘッダを文字列に変換
5543char *HttpHeaderToStr(HTTP_HEADER *header)
5544{
5545    BUF *b;
5546    char *tmp;
5547    UINT i;
5548    char *s;
5549    // 引数チェック
5550    if (header == NULL)
5551    {
5552        return NULL;
5553    }
5554
5555    tmp = Malloc(HTTP_HEADER_LINE_MAX_SIZE);
5556    b = NewBuf();
5557
5558    // ヘッダ
5559    Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
5560        "%s %s %s\r\n", header->Method, header->Target, header->Version);
5561    WriteBuf(b, tmp, StrLen(tmp));
5562
5563    // 値
5564    for (i = 0;i < LIST_NUM(header->ValueList);i++)
5565    {
5566        HTTP_VALUE *v = (HTTP_VALUE *)LIST_DATA(header->ValueList, i);
5567        Format(tmp, HTTP_HEADER_LINE_MAX_SIZE,
5568            "%s: %s\r\n", v->Name, v->Data);
5569        WriteBuf(b, tmp, StrLen(tmp));
5570    }
5571
5572    // 最後の改行
5573    WriteBuf(b, "\r\n", 2);
5574    s = Malloc(b->Size + 1);
5575    Copy(s, b->Buf, b->Size);
5576    s[b->Size] = 0;
5577
5578    FreeBuf(b);
5579    Free(tmp);
5580
5581    return s;
5582}
5583
5584// HTTP ヘッダを送信
5585bool SendHttpHeader(SOCK *s, HTTP_HEADER *header)
5586{
5587    char *str;
5588    bool ret;
5589    // 引数チェック
5590    if (s == NULL || header == NULL)
5591    {
5592        return false;
5593    }
5594
5595    // 文字列に変換
5596    str = HttpHeaderToStr(header);
5597
5598    // 送信
5599    ret = SendAll(s, str, StrLen(str), s->SecureMode);
5600
5601    Free(str);
5602
5603    return ret;
5604}
5605
5606// HTTP ヘッダを受信
5607HTTP_HEADER *RecvHttpHeader(SOCK *s)
5608{
5609    TOKEN_LIST *token = NULL;
5610    char *str = NULL;
5611    HTTP_HEADER *header = NULL;
5612    // 引数チェック
5613    if (s == NULL)
5614    {
5615        return NULL;
5616    }
5617
5618    // 1 行目を取得する
5619    str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
5620    if (str == NULL)
5621    {
5622        goto ERROR;
5623    }
5624
5625    // トークンに分割する
5626    token = ParseToken(str, " ");
5627    if (token->NumTokens < 3)
5628    {
5629        goto ERROR;
5630    }
5631
5632    Free(str);
5633    str = NULL;
5634
5635    // ヘッダの作成
5636    header = NewHttpHeader(token->Token[0], token->Token[1], token->Token[2]);
5637
5638    if (!StrCmpi(header->Version, "HTTP/1.0") || !StrCmpi(header->Version, "HTTP/0.9"))
5639    {
5640        // この行で終わり
5641        return header;
5642    }
5643
5644    // 2 行目以降を取得する
5645    while (true)
5646    {
5647        UINT pos;
5648        HTTP_VALUE *v;
5649        char *value_name, *value_data;
5650        str = RecvLine(s, HTTP_HEADER_LINE_MAX_SIZE);
5651        if (str == NULL)
5652        {
5653            goto ERROR;
5654        }
5655        Trim(str);
5656
5657        if (StrLen(str) == 0)
5658        {
5659            // ヘッダの終了
5660            Free(str);
5661            str = NULL;
5662            break;
5663        }
5664
5665        // コロンの位置を取得する
5666        pos = SearchStr(str, ":", 0);
5667        if (pos == INFINITE)
5668        {
5669            // コロンが存在しない
5670            goto ERROR;
5671        }
5672        if ((pos + 1) >= StrLen(str))
5673        {
5674            // データが存在しない
5675            goto ERROR;
5676        }
5677
5678        // 名前とデータの 2 つに分ける
5679        value_name = Malloc(pos + 1);
5680        Copy(value_name, str, pos);
5681        value_name[pos] = 0;
5682        value_data = &str[pos + 1];
5683
5684        v = NewHttpValue(value_name, value_data);
5685        if (v == NULL)
5686        {
5687            Free(value_name);
5688            goto ERROR;
5689        }
5690
5691        Free(value_name);
5692
5693        AddHttpValue(header, v);
5694        Free(str);
5695    }
5696
5697    FreeToken(token);
5698
5699    return header;
5700
5701ERROR:
5702    // メモリ解放
5703    if (token)
5704    {
5705        FreeToken(token);
5706    }
5707    if (str)
5708    {
5709        Free(str);
5710    }
5711    if (header)
5712    {
5713        FreeHttpHeader(header);
5714    }
5715    return NULL;
5716}
5717
5718// 1 行を受信する
5719char *RecvLine(SOCK *s, UINT max_size)
5720{
5721    BUF *b;
5722    char c;
5723    char *str;
5724    // 引数チェック
5725    if (s == NULL || max_size == 0)
5726    {
5727        return NULL;
5728    }
5729
5730    b = NewBuf();
5731    while (true)
5732    {
5733        UCHAR *buf;
5734        if (RecvAll(s, &c, sizeof(c), s->SecureMode) == false)
5735        {
5736            FreeBuf(b);
5737            return NULL;
5738        }
5739        WriteBuf(b, &c, sizeof(c));
5740        buf = (UCHAR *)b->Buf;
5741        if (b->Size > max_size)
5742        {
5743            FreeBuf(b);
5744            return NULL;
5745        }
5746        if (b->Size >= 1)
5747        {
5748            if (buf[b->Size - 1] == '\n')
5749            {
5750                b->Size--;
5751                if (b->Size >= 1)
5752                {
5753                    if (buf[b->Size - 1] == '\r')
5754                    {
5755                        b->Size--;
5756                    }
5757                }
5758                str = Malloc(b->Size + 1);
5759                Copy(str, b->Buf, b->Size);
5760                str[b->Size] = 0;
5761                FreeBuf(b);
5762
5763                return str;
5764            }
5765        }
5766    }
5767}
5768
5769// 新しい HTTP 値の作成
5770HTTP_VALUE *NewHttpValue(char *name, char *data)
5771{
5772    HTTP_VALUE *v;
5773    // 引数チェック
5774    if (name == NULL || data == NULL)
5775    {
5776        return NULL;
5777    }
5778
5779    v = ZeroMalloc(sizeof(HTTP_VALUE));
5780
5781    v->Name = CopyStr(name);
5782    v->Data = CopyStr(data);
5783
5784    Trim(v->Name);
5785    Trim(v->Data);
5786
5787    return v;
5788}
5789
5790// プロトコルルーチンの初期化
5791void InitProtocol()
5792{
5793}
5794
5795// プロトコルルーチンの解放
5796void FreeProtocol()
5797{
5798}
5799
5800// HTTP ヘッダから HTTP 値を探す
5801HTTP_VALUE *GetHttpValue(HTTP_HEADER *header, char *name)
5802{
5803    HTTP_VALUE *v, t;
5804    // 引数チェック
5805    if (header == NULL || name == NULL)
5806    {
5807        return NULL;
5808    }
5809
5810    t.Name = name;
5811    v = Search(header->ValueList, &t);
5812    if (v == NULL)
5813    {
5814        return NULL;
5815    }
5816
5817    return v;
5818}
5819
5820// HTTP ヘッダに HTTP 値を追加
5821void AddHttpValue(HTTP_HEADER *header, HTTP_VALUE *value)
5822{
5823    // 引数チェック
5824    if (header == NULL || value == NULL)
5825    {
5826        return;
5827    }
5828
5829    Insert(header->ValueList, value);
5830}
5831
5832// HTTP ヘッダを作成
5833HTTP_HEADER *NewHttpHeader(char *method, char *target, char *version)
5834{
5835    HTTP_HEADER *header;
5836    // 引数チェック
5837    if (method == NULL || target == NULL || version == NULL)
5838    {
5839        return NULL;
5840    }
5841
5842    header = ZeroMalloc(sizeof(HTTP_HEADER));
5843
5844    header->Method = CopyStr(method);
5845    header->Target = CopyStr(target);
5846    header->Version = CopyStr(version);
5847    header->ValueList = NewListFast(CompareHttpValue);
5848
5849    return header;
5850}
5851
5852// HTTP 値の比較関数
5853int CompareHttpValue(void *p1, void *p2)
5854{
5855    HTTP_VALUE *v1, *v2;
5856    if (p1 == NULL || p2 == NULL)
5857    {
5858        return 0;
5859    }
5860    v1 = *(HTTP_VALUE **)p1;
5861    v2 = *(HTTP_VALUE **)p2;
5862    if (v1 == NULL || v2 == NULL)
5863    {
5864        return 0;
5865    }
5866    return StrCmpi(v1->Name, v2->Name);
5867}
5868
5869// HTTP 値を解放
5870void FreeHttpValue(HTTP_VALUE *value)
5871{
5872    // 引数チェック
5873    if (value == NULL)
5874    {
5875        return;
5876    }
5877
5878    Free(value->Data);
5879    Free(value->Name);
5880
5881    Free(value);
5882}
5883
5884// HTTP ヘッダを解放
5885void FreeHttpHeader(HTTP_HEADER *header)
5886{
5887    UINT i;
5888    HTTP_VALUE **values;
5889    // 引数チェック
5890    if (header == NULL)
5891    {
5892        return;
5893    }
5894
5895    Free(header->Method);
5896    Free(header->Target);
5897    Free(header->Version);
5898
5899    values = ToArray(header->ValueList);
5900    for (i = 0;i < LIST_NUM(header->ValueList);i++)
5901    {
5902        FreeHttpValue(values[i]);
5903    }
5904    Free(values);
5905
5906    ReleaseList(header->ValueList);
5907
5908    Free(header);
5909}
5910
5911// パケットを受信
5912PACK *RecvPack(SOCK *s)
5913{
5914    PACK *p;
5915    BUF *b;
5916    void *data;
5917    UINT sz;
5918    // 引数チェック
5919    if (s == NULL || s->Type != SOCK_TCP)
5920    {
5921        return false;
5922    }
5923
5924    if (RecvAll(s, &sz, sizeof(UINT), s->SecureMode) == false)
5925    {
5926        return false;
5927    }
5928    sz = Endian32(sz);
5929    if (sz > MAX_PACK_SIZE)
5930    {
5931        return false;
5932    }
5933    data = MallocEx(sz, true);
5934    if (RecvAll(s, data, sz, s->SecureMode) == false)
5935    {
5936        Free(data);
5937        return false;
5938    }
5939
5940    b = NewBuf();
5941    WriteBuf(b, data, sz);
5942    SeekBuf(b, 0, 0);
5943    p = BufToPack(b);
5944    FreeBuf(b);
5945    Free(data);
5946
5947    return p;
5948}
5949
5950// パケットを送信
5951bool SendPack(SOCK *s, PACK *p)
5952{
5953    BUF *b;
5954    UINT sz;
5955    // 引数チェック
5956    if (s == NULL || p == NULL || s->Type != SOCK_TCP)
5957    {
5958        return false;
5959    }
5960
5961    b = PackToBuf(p);
5962    sz = Endian32(b->Size);
5963
5964    SendAdd(s, &sz, sizeof(UINT));
5965    SendAdd(s, b->Buf, b->Size);
5966    FreeBuf(b);
5967
5968    return SendNow(s, s->SecureMode);
5969}
5970
5971// Hello パケットを作成
5972PACK *PackHello(void *random, UINT ver, UINT build, char *server_str)
5973{
5974    PACK *p;
5975    // 引数チェック
5976    if (random == NULL || server_str == NULL)
5977    {
5978        return NULL;
5979    }
5980
5981    p = NewPack();
5982    PackAddStr(p, "hello", server_str);
5983    PackAddInt(p, "version", ver);
5984    PackAddInt(p, "build", build);
5985    PackAddData(p, "random", random, SHA1_SIZE);
5986
5987    return p;
5988}
5989
5990// Hello パケットを解釈
5991bool GetHello(PACK *p, void *random, UINT *ver, UINT *build, char *server_str, UINT server_str_size)
5992{
5993    // 引数チェック
5994    if (p == NULL || random == NULL || ver == NULL || server_str == NULL)
5995    {
5996        return false;
5997    }
5998
5999    if (PackGetStr(p, "hello", server_str, server_str_size) == false)
6000    {
6001        return false;
6002    }
6003    *ver = PackGetInt(p, "version");
6004    *build = PackGetInt(p, "build");
6005    if (PackGetDataSize(p, "random") != SHA1_SIZE)
6006    {
6007        return false;
6008    }
6009    if (PackGetData(p, "random", random) == false)
6010    {
6011        return false;
6012    }
6013
6014    return true;
6015}
6016
6017// エラー値を PACK に格納
6018PACK *PackError(UINT error)
6019{
6020    PACK *p;
6021
6022    p = NewPack();
6023    PackAddInt(p, "error", error);
6024
6025    return p;
6026}
6027
6028// エラー値を PACK から取得
6029UINT GetErrorFromPack(PACK *p)
6030{
6031    // 引数チェック
6032    if (p == NULL)
6033    {
6034        return 0;
6035    }
6036
6037    return PackGetInt(p, "error");
6038}
6039
6040// 認証方法を PACK から取得
6041UINT GetAuthTypeFromPack(PACK *p)
6042{
6043    // 引数チェック
6044    if (p == NULL)
6045    {
6046        return 0;
6047    }
6048
6049    return PackGetInt(p, "authtype");
6050}
6051
6052// ユーザー名と HUB 名を PACK から取得
6053bool GetHubnameAndUsernameFromPack(PACK *p, char *username, UINT username_size,
6054                                   char *hubname, UINT hubname_size)
6055{
6056    // 引数チェック
6057    if (p == NULL || username == NULL || hubname == NULL)
6058    {
6059        return false;
6060    }
6061
6062    if (PackGetStr(p, "username", username, username_size) == false)
6063    {
6064        return false;
6065    }
6066    if (PackGetStr(p, "hubname", hubname, hubname_size) == false)
6067    {
6068        return false;
6069    }
6070    return true;
6071}
6072
6073// プロトコルを PACK から取得
6074UINT GetProtocolFromPack(PACK *p)
6075{
6076    // 引数チェック
6077    if (p == NULL)
6078    {
6079        return 0;
6080    }
6081
6082#if 0
6083    return PackGetInt(p, "protocol");
6084#else
6085    // 現バージョンでは TCP プロトコルに限定する
6086    return CONNECTION_TCP;
6087#endif
6088}
6089
6090// メソッドを PACK から取得
6091bool GetMethodFromPack(PACK *p, char *method, UINT size)
6092{
6093    // 引数チェック
6094    if (p == NULL || method == NULL || size == 0)
6095    {
6096        return false;
6097    }
6098
6099    return PackGetStr(p, "method", method, size);
6100}
6101
6102// 証明書認証ログイン用のパケットを生成
6103PACK *PackLoginWithCert(char *hubname, char *username, X *x, void *sign, UINT sign_size)
6104{
6105    PACK *p;
6106    BUF *b;
6107    // 引数チェック
6108    if (hubname == NULL || username == NULL)
6109    {
6110        return NULL;
6111    }
6112
6113    p = NewPack();
6114    PackAddStr(p, "method", "login");
6115    PackAddStr(p, "hubname", hubname);
6116    PackAddStr(p, "username", username);
6117    PackAddInt(p, "authtype", CLIENT_AUTHTYPE_CERT);
6118
6119    // 証明書
6120    b = XToBuf(x, false);
6121    PackAddData(p, "cert", b->Buf, b->Size);
6122    FreeBuf(b);
6123
6124    // 署名データ
6125    PackAddData(p, "sign", sign, sign_size);
6126
6127    return p;
6128}
6129
6130// 平文パスワード認証ログイン用のパケットを生成
6131PACK *PackLoginWithPlainPassword(char *hubname, char *username, void *plain_password)
6132{
6133    PACK *p;
6134    // 引数チェック
6135    if (hubname == NULL || username == NULL)
6136    {
6137        return NULL;
6138    }
6139
6140    p = NewPack();
6141    PackAddStr(p, "method", "login");
6142    PackAddStr(p, "hubname", hubname);
6143    PackAddStr(p, "username", username);
6144    PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PLAIN_PASSWORD);
6145    PackAddStr(p, "plain_password", plain_password);
6146
6147    return p;
6148}
6149
6150// パスワード認証ログイン用のパケットを作成
6151PACK *PackLoginWithPassword(char *hubname, char *username, void *secure_password)
6152{
6153    PACK *p;
6154    // 引数チェック
6155    if (hubname == NULL || username == NULL)
6156    {
6157        return NULL;
6158    }
6159
6160    p = NewPack();
6161    PackAddStr(p, "method", "login");
6162    PackAddStr(p, "hubname", hubname);
6163    PackAddStr(p, "username", username);
6164    PackAddInt(p, "authtype", CLIENT_AUTHTYPE_PASSWORD);
6165    PackAddData(p, "secure_password", secure_password, SHA1_SIZE);
6166
6167    return p;
6168}
6169
6170// 匿名ログイン用のパケットを作成
6171PACK *PackLoginWithAnonymous(char *hubname, char *username)
6172{
6173    PACK *p;
6174    // 引数チェック
6175    if (hubname == NULL || username == NULL)
6176    {
6177        return NULL;
6178    }
6179
6180    p = NewPack();
6181    PackAddStr(p, "method", "login");
6182    PackAddStr(p, "hubname", hubname);
6183    PackAddStr(p, "username", username);
6184    PackAddInt(p, "authtype", CLIENT_AUTHTYPE_ANONYMOUS);
6185
6186    return p;
6187}
6188
6189// 追加接続用のパケットを作成
6190PACK *PackAdditionalConnect(UCHAR *session_key)
6191{
6192    PACK *p;
6193    // 引数チェック
6194    if (session_key == NULL)
6195    {
6196        return NULL;
6197    }
6198
6199    p = NewPack();
6200    PackAddStr(p, "method", "additional_connect");
6201    PackAddData(p, "session_key", session_key, SHA1_SIZE);
6202
6203    return p;
6204}
6205
6206// PACK から K を取得
6207K *PackGetK(PACK *p, char *name)
6208{
6209    K *k;
6210    BUF *b;
6211    // 引数チェック
6212    if (p == NULL || name == NULL)
6213    {
6214        return NULL;
6215    }
6216
6217    b = PackGetBuf(p, name);
6218    if (b == NULL)
6219    {
6220        return NULL;
6221    }
6222
6223    k = BufToK(b, true, false, NULL);
6224    FreeBuf(b);
6225
6226    return k;
6227}
6228
6229// PACK から X を取得
6230X *PackGetX(PACK *p, char *name)
6231{
6232    X *x;
6233    BUF *b;
6234    // 引数チェック
6235    if (p == NULL || name == NULL)
6236    {
6237        return NULL;
6238    }
6239
6240    b = PackGetBuf(p, name);
6241    if (b == NULL)
6242    {
6243        return NULL;
6244    }
6245
6246    x = BufToX(b, false);
6247    FreeBuf(b);
6248
6249    return x;
6250}
6251
6252// PACK に K を追加
6253void PackAddK(PACK *p, char *name, K *k)
6254{
6255    BUF *b;
6256    // 引数チェック
6257    if (p == NULL || name == NULL || k == NULL)
6258    {
6259        return;
6260    }
6261
6262    b = KToBuf(k, false, NULL);
6263    if (b == NULL)
6264    {
6265        return;
6266    }
6267
6268    PackAddBuf(p, name, b);
6269    FreeBuf(b);
6270}
6271
6272// PACK に X を追加
6273void PackAddX(PACK *p, char *name, X *x)
6274{
6275    BUF *b;
6276    // 引数チェック
6277    if (p == NULL || name == NULL || x == NULL)
6278    {
6279        return;
6280    }
6281
6282    b = XToBuf(x, false);
6283    if (b == NULL)
6284    {
6285        return;
6286    }
6287
6288    PackAddBuf(p, name, b);
6289    FreeBuf(b);
6290}
6291
6292// PACK からバッファを取得
6293BUF *PackGetBuf(PACK *p, char *name)
6294{
6295    return PackGetBufEx(p, name, 0);
6296}
6297BUF *PackGetBufEx(PACK *p, char *name, UINT index)
6298{
6299    UINT size;
6300    void *tmp;
6301    BUF *b;
6302    // 引数チェック
6303    if (p == NULL || name == NULL)
6304    {
6305        return NULL;
6306    }
6307
6308    size = PackGetDataSizeEx(p, name, index);
6309    tmp = MallocEx(size, true);
6310    if (PackGetDataEx(p, name, tmp, index) == false)
6311    {
6312        Free(tmp);
6313        return NULL;
6314    }
6315
6316    b = NewBuf();
6317    WriteBuf(b, tmp, size);
6318    SeekBuf(b, 0, 0);
6319
6320    Free(tmp);
6321
6322    return b;
6323}
6324
6325// PACK からデータを取得
6326bool PackGetData(PACK *p, char *name, void *data)
6327{
6328    return PackGetDataEx(p, name, data, 0);
6329}
6330bool PackGetDataEx(PACK *p, char *name, void *data, UINT index)
6331{
6332    ELEMENT *e;
6333    // 引数チェック
6334    if (p == NULL || name == NULL)
6335    {
6336        return false;
6337    }
6338
6339    e = GetElement(p, name, VALUE_DATA);
6340    if (e == NULL)
6341    {
6342        return false;
6343    }
6344    Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
6345    return true;
6346}
6347bool PackGetData2(PACK *p, char *name, void *data, UINT size)
6348{
6349    return PackGetDataEx2(p, name, data, size, 0);
6350}
6351bool PackGetDataEx2(PACK *p, char *name, void *data, UINT size, UINT index)
6352{
6353    ELEMENT *e;
6354    // 引数チェック
6355    if (p == NULL || name == NULL)
6356    {
6357        return false;
6358    }
6359
6360    e = GetElement(p, name, VALUE_DATA);
6361    if (e == NULL)
6362    {
6363        return false;
6364    }
6365    if (GetDataValueSize(e, index) != size)
6366    {
6367        return false;
6368    }
6369    Copy(data, GetDataValue(e, index), GetDataValueSize(e, index));
6370    return true;
6371}
6372
6373// PACK からデータサイズを取得
6374UINT PackGetDataSize(PACK *p, char *name)
6375{
6376    return PackGetDataSizeEx(p, name, 0);
6377}
6378UINT PackGetDataSizeEx(PACK *p, char *name, UINT index)
6379{
6380    ELEMENT *e;
6381    // 引数チェック
6382    if (p == NULL || name == NULL)
6383    {
6384        return 0;
6385    }
6386
6387    e = GetElement(p, name, VALUE_DATA);
6388    if (e == NULL)
6389    {
6390        return 0;
6391    }
6392    return GetDataValueSize(e, index);
6393}
6394
6395// PACK から整数を取得
6396UINT64 PackGetInt64(PACK *p, char *name)
6397{
6398    return PackGetInt64Ex(p, name, 0);
6399}
6400UINT64 PackGetInt64Ex(PACK *p, char *name, UINT index)
6401{
6402    ELEMENT *e;
6403    // 引数チェック
6404    if (p == NULL || name == NULL)
6405    {
6406        return 0;
6407    }
6408
6409    e = GetElement(p, name, VALUE_INT64);
6410    if (e == NULL)
6411    {
6412        return 0;
6413    }
6414    return GetInt64Value(e, index);
6415}
6416
6417// PACK からインデックス数を取得
6418UINT PackGetIndexCount(PACK *p, char *name)
6419{
6420    ELEMENT *e;
6421    // 引数チェック
6422    if (p == NULL || name == NULL)
6423    {
6424        return 0;
6425    }
6426
6427    e = GetElement(p, name, INFINITE);
6428    if (e == NULL)
6429    {
6430        return 0;
6431    }
6432
6433    return e->num_value;
6434}
6435
6436// PACK から個数を取得
6437UINT PackGetNum(PACK *p, char *name)
6438{
6439    return MIN(PackGetInt(p, name), 65536);
6440}
6441
6442// PACK から bool 型を取得
6443bool PackGetBool(PACK *p, char *name)
6444{
6445    return PackGetInt(p, name) == 0 ? false : true;
6446}
6447bool PackGetBoolEx(PACK *p, char *name, UINT index)
6448{
6449    return PackGetIntEx(p, name, index) == 0 ? false : true;
6450}
6451
6452// PACK に bool 型を追加
6453void PackAddBool(PACK *p, char *name, bool b)
6454{
6455    PackAddInt(p, name, b ? 1 : 0);
6456}
6457void PackAddBoolEx(PACK *p, char *name, bool b, UINT index, UINT total)
6458{
6459    PackAddIntEx(p, name, b ? 1 : 0, index, total);
6460}
6461
6462// PACK に IPV6_ADDR を追加
6463void PackAddIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index, UINT total)
6464{
6465    // 引数チェック
6466    if (p == NULL || name == NULL || addr == NULL)
6467    {
6468        return;
6469    }
6470
6471    PackAddDataEx(p, name, addr, sizeof(IPV6_ADDR), index, total);
6472}
6473void PackAddIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
6474{
6475    PackAddIp6AddrEx(p, name, addr, 0, 1);
6476}
6477
6478// PACK から IPV6_ADDR を取得
6479bool PackGetIp6AddrEx(PACK *p, char *name, IPV6_ADDR *addr, UINT index)
6480{
6481    // 引数チェック
6482    if (p == NULL || name == NULL || addr == NULL)
6483    {
6484        Zero(addr, sizeof(IPV6_ADDR));
6485        return false;
6486    }
6487
6488    return PackGetDataEx2(p, name, addr, sizeof(IPV6_ADDR), index);
6489}
6490bool PackGetIp6Addr(PACK *p, char *name, IPV6_ADDR *addr)
6491{
6492    return PackGetIp6AddrEx(p, name, addr, 0);
6493}
6494
6495// PACK に IP を追加
6496void PackAddIp32Ex(PACK *p, char *name, UINT ip32, UINT index, UINT total)
6497{
6498    IP ip;
6499    // 引数チェック
6500    if (p == NULL || name == NULL)
6501    {
6502        return;
6503    }
6504
6505    UINTToIP(&ip, ip32);
6506
6507    PackAddIpEx(p, name, &ip, index, total);
6508}
6509void PackAddIp32(PACK *p, char *name, UINT ip32)
6510{
6511    PackAddIp32Ex(p, name, ip32, 0, 1);
6512}
6513void PackAddIpEx(PACK *p, char *name, IP *ip, UINT index, UINT total)
6514{
6515    UINT i;
6516    bool b = false;
6517    char tmp[MAX_PATH];
6518    // 引数チェック
6519    if (p == NULL || name == NULL || ip == NULL)
6520    {
6521        return;
6522    }
6523
6524    b = IsIP6(ip);
6525
6526    Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
6527    PackAddBoolEx(p, tmp, b, index, total);
6528
6529    Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
6530    if (b)
6531    {
6532        PackAddDataEx(p, tmp, ip->ipv6_addr, sizeof(ip->ipv6_addr), index, total);
6533    }
6534    else
6535    {
6536        UCHAR dummy[16];
6537
6538        Zero(dummy, sizeof(dummy));
6539
6540        PackAddDataEx(p, tmp, dummy, sizeof(dummy), index, total);
6541    }
6542
6543    Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
6544    if (b)
6545    {
6546        PackAddIntEx(p, tmp, ip->ipv6_scope_id, index, total);
6547    }
6548    else
6549    {
6550        PackAddIntEx(p, tmp, 0, index, total);
6551    }
6552
6553    i = IPToUINT(ip);
6554
6555    if (IsBigEndian())
6556    {
6557        i = Swap32(i);
6558    }
6559
6560    PackAddIntEx(p, name, i, index, total);
6561}
6562void PackAddIp(PACK *p, char *name, IP *ip)
6563{
6564    PackAddIpEx(p, name, ip, 0, 1);
6565}
6566
6567// PACK から IP を取得
6568UINT PackGetIp32Ex(PACK *p, char *name, UINT index)
6569{
6570    IP ip;
6571    // 引数チェック
6572    if (p == NULL || name == NULL)
6573    {
6574        return 0;
6575    }
6576
6577    if (PackGetIpEx(p, name, &ip, index) == false)
6578    {
6579        return 0;
6580    }
6581
6582    return IPToUINT(&ip);
6583}
6584UINT PackGetIp32(PACK *p, char *name)
6585{
6586    return PackGetIp32Ex(p, name, 0);
6587}
6588bool PackGetIpEx(PACK *p, char *name, IP *ip, UINT index)
6589{
6590    UINT i;
6591    char tmp[MAX_PATH];
6592    // 引数チェック
6593    if (p == NULL || ip == NULL || name == NULL)
6594    {
6595        return false;
6596    }
6597
6598    Format(tmp, sizeof(tmp), "%s@ipv6_bool", name);
6599    if (PackGetBoolEx(p, tmp, index))
6600    {
6601        UCHAR data[16];
6602        UINT scope_id;
6603
6604        Zero(data, sizeof(data));
6605
6606        Format(tmp, sizeof(tmp), "%s@ipv6_array", name);
6607        PackGetDataEx2(p, tmp, data, sizeof(data), index);
6608
6609        Format(tmp, sizeof(tmp), "%s@ipv6_scope_id", name);
6610        scope_id = PackGetIntEx(p, tmp, index);
6611
6612        SetIP6(ip, data);
6613        ip->ipv6_scope_id = scope_id;
6614    }
6615    else
6616    {
6617        if (GetElement(p, name, VALUE_INT) == NULL)
6618        {
6619            Zero(ip, sizeof(IP));
6620            return false;
6621        }
6622
6623        i = PackGetIntEx(p, name, index);
6624
6625        if (IsBigEndian())
6626        {
6627            i = Swap32(i);
6628        }
6629
6630        UINTToIP(ip, i);
6631    }
6632
6633    return true;
6634}
6635bool PackGetIp(PACK *p, char *name, IP *ip)
6636{
6637    return PackGetIpEx(p, name, ip, 0);
6638}
6639
6640// PACK から整数を取得
6641UINT PackGetInt(PACK *p, char *name)
6642{
6643    return PackGetIntEx(p, name, 0);
6644}
6645UINT PackGetIntEx(PACK *p, char *name, UINT index)
6646{
6647    ELEMENT *e;
6648    // 引数チェック
6649    if (p == NULL || name == NULL)
6650    {
6651        return 0;
6652    }
6653
6654    e = GetElement(p, name, VALUE_INT);
6655    if (e == NULL)
6656    {
6657        return 0;
6658    }
6659    return GetIntValue(e, index);
6660}
6661
6662// PACK から Unicode 文字列を取得
6663bool PackGetUniStr(PACK *p, char *name, wchar_t *unistr, UINT size)
6664{
6665    return PackGetUniStrEx(p, name, unistr, size, 0);
6666}
6667bool PackGetUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT size, UINT index)
6668{
6669    ELEMENT *e;
6670    // 引数チェック
6671    if (p == NULL || name == NULL || unistr == NULL || size == 0)
6672    {
6673        return false;
6674    }
6675
6676    unistr[0] = 0;
6677
6678    e = GetElement(p, name, VALUE_UNISTR);
6679    if (e == NULL)
6680    {
6681        return false;
6682    }
6683    UniStrCpy(unistr, size, GetUniStrValue(e, index));
6684    return true;
6685}
6686
6687// PACK から文字列を取得
6688bool PackGetStr(PACK *p, char *name, char *str, UINT size)
6689{
6690    return PackGetStrEx(p, name, str, size, 0);
6691}
6692bool PackGetStrEx(PACK *p, char *name, char *str, UINT size, UINT index)
6693{
6694    ELEMENT *e;
6695    // 引数チェック
6696    if (p == NULL || name == NULL || str == NULL || size == 0)
6697    {
6698        return false;
6699    }
6700
6701    str[0] = 0;
6702
6703    e = GetElement(p, name, VALUE_STR);
6704    if (e == NULL)
6705    {
6706        return false;
6707    }
6708
6709    StrCpy(str, size, GetStrValue(e, index));
6710    return true;
6711}
6712
6713// バッファを PACK に追加 (配列)
6714void PackAddBufEx(PACK *p, char *name, BUF *b, UINT index, UINT total)
6715{
6716    // 引数チェック
6717    if (p == NULL || name == NULL || b == NULL || total == 0)
6718    {
6719        return;
6720    }
6721
6722    PackAddDataEx(p, name, b->Buf, b->Size, index, total);
6723}
6724
6725// データを PACK に追加 (配列)
6726void PackAddDataEx(PACK *p, char *name, void *data, UINT size, UINT index, UINT total)
6727{
6728    VALUE *v;
6729    ELEMENT *e;
6730    // 引数チェック
6731    if (p == NULL || data == NULL || name == NULL || total == 0)
6732    {
6733        return;
6734    }
6735
6736    v = NewDataValue(data, size);
6737    e = GetElement(p, name, VALUE_DATA);
6738    if (e != NULL)
6739    {
6740        if (e->num_value <= total)
6741        {
6742            e->values[index] = v;
6743        }
6744        else
6745        {
6746            FreeValue(v, VALUE_DATA);
6747        }
6748    }
6749    else
6750    {
6751        e = ZeroMallocEx(sizeof(ELEMENT), true);
6752        StrCpy(e->name, sizeof(e->name), name);
6753        e->num_value = total;
6754        e->type = VALUE_DATA;
6755        e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
6756        e->values[index] = v;
6757        AddElement(p, e);
6758    }
6759}
6760
6761// バッファを PACK に追加
6762void PackAddBuf(PACK *p, char *name, BUF *b)
6763{
6764    // 引数チェック
6765    if (p == NULL || name == NULL || b == NULL)
6766    {
6767        return;
6768    }
6769
6770    PackAddData(p, name, b->Buf, b->Size);
6771}
6772
6773// データを PACK に追加
6774void PackAddData(PACK *p, char *name, void *data, UINT size)
6775{
6776    VALUE *v;
6777    // 引数チェック
6778    if (p == NULL || data == NULL || name == NULL)
6779    {
6780        return;
6781    }
6782
6783    v = NewDataValue(data, size);
6784    AddElement(p, NewElement(name, VALUE_DATA, 1, &v));
6785}
6786
6787// 64 bit 整数を PACK に追加 (配列)
6788void PackAddInt64Ex(PACK *p, char *name, UINT64 i, UINT index, UINT total)
6789{
6790    VALUE *v;
6791    ELEMENT *e;
6792    // 引数チェック
6793    if (p == NULL || name == NULL || total == 0)
6794    {
6795        return;
6796    }
6797
6798    v = NewInt64Value(i);
6799    e = GetElement(p, name, VALUE_INT64);
6800    if (e != NULL)
6801    {
6802        if (e->num_value <= total)
6803        {
6804            e->values[index] = v;
6805        }
6806        else
6807        {
6808            FreeValue(v, VALUE_INT64);
6809        }
6810    }
6811    else
6812    {
6813        e = ZeroMallocEx(sizeof(ELEMENT), true);
6814        StrCpy(e->name, sizeof(e->name), name);
6815        e->num_value = total;
6816        e->type = VALUE_INT64;
6817        e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
6818        e->values[index] = v;
6819        AddElement(p, e);
6820    }
6821}
6822
6823// 整数を PACK に追加 (配列)
6824void PackAddIntEx(PACK *p, char *name, UINT i, UINT index, UINT total)
6825{
6826    VALUE *v;
6827    ELEMENT *e;
6828    // 引数チェック
6829    if (p == NULL || name == NULL || total == 0)
6830    {
6831        return;
6832    }
6833
6834    v = NewIntValue(i);
6835    e = GetElement(p, name, VALUE_INT);
6836    if (e != NULL)
6837    {
6838        if (e->num_value <= total)
6839        {
6840            e->values[index] = v;
6841        }
6842        else
6843        {
6844            FreeValue(v, VALUE_INT);
6845        }
6846    }
6847    else
6848    {
6849        e = ZeroMallocEx(sizeof(ELEMENT), true);
6850        StrCpy(e->name, sizeof(e->name), name);
6851        e->num_value = total;
6852        e->type = VALUE_INT;
6853        e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
6854        e->values[index] = v;
6855        AddElement(p, e);
6856    }
6857}
6858
6859// 64 bit 整数を PACK に追加
6860void PackAddInt64(PACK *p, char *name, UINT64 i)
6861{
6862    VALUE *v;
6863    // 引数チェック
6864    if (p == NULL || name == NULL)
6865    {
6866        return;
6867    }
6868
6869    v = NewInt64Value(i);
6870    AddElement(p, NewElement(name, VALUE_INT64, 1, &v));
6871}
6872
6873// 個数を PACK に追加
6874void PackAddNum(PACK *p, char *name, UINT num)
6875{
6876    PackAddInt(p, name, num);
6877}
6878
6879// 整数を PACK に追加
6880void PackAddInt(PACK *p, char *name, UINT i)
6881{
6882    VALUE *v;
6883    // 引数チェック
6884    if (p == NULL || name == NULL)
6885    {
6886        return;
6887    }
6888
6889    v = NewIntValue(i);
6890    AddElement(p, NewElement(name, VALUE_INT, 1, &v));
6891}
6892
6893// Unicode 文字列を PACK に追加 (配列)
6894void PackAddUniStrEx(PACK *p, char *name, wchar_t *unistr, UINT index, UINT total)
6895{
6896    VALUE *v;
6897    ELEMENT *e;
6898    // 引数チェック
6899    if (p == NULL || name == NULL || unistr == NULL || total == 0)
6900    {
6901        return;
6902    }
6903
6904    v = NewUniStrValue(unistr);
6905    e = GetElement(p, name, VALUE_UNISTR);
6906    if (e != NULL)
6907    {
6908        if (e->num_value <= total)
6909        {
6910            e->values[index] = v;
6911        }
6912        else
6913        {
6914            FreeValue(v, VALUE_UNISTR);
6915        }
6916    }
6917    else
6918    {
6919        e = ZeroMallocEx(sizeof(ELEMENT), true);
6920        StrCpy(e->name, sizeof(e->name), name);
6921        e->num_value = total;
6922        e->type = VALUE_UNISTR;
6923        e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
6924        e->values[index] = v;
6925        AddElement(p, e);
6926    }
6927}
6928
6929// Unicode 文字列を PACK に追加
6930void PackAddUniStr(PACK *p, char *name, wchar_t *unistr)
6931{
6932    VALUE *v;
6933    // 引数チェック
6934    if (p == NULL || name == NULL || unistr == NULL)
6935    {
6936        return;
6937    }
6938
6939    v = NewUniStrValue(unistr);
6940    AddElement(p, NewElement(name, VALUE_UNISTR, 1, &v));
6941}
6942
6943// 文字列を PACK に追加 (配列)
6944void PackAddStrEx(PACK *p, char *name, char *str, UINT index, UINT total)
6945{
6946    VALUE *v;
6947    ELEMENT *e;
6948    // 引数チェック
6949    if (p == NULL || name == NULL || str == NULL || total == 0)
6950    {
6951        return;
6952    }
6953
6954    v = NewStrValue(str);
6955    e = GetElement(p, name, VALUE_STR);
6956    if (e != NULL)
6957    {
6958        if (e->num_value <= total)
6959        {
6960            e->values[index] = v;
6961        }
6962        else
6963        {
6964            FreeValue(v, VALUE_STR);
6965        }
6966    }
6967    else
6968    {
6969        e = ZeroMallocEx(sizeof(ELEMENT), true);
6970        StrCpy(e->name, sizeof(e->name), name);
6971        e->num_value = total;
6972        e->type = VALUE_STR;
6973        e->values = ZeroMallocEx(sizeof(VALUE *) * total, true);
6974        e->values[index] = v;
6975        AddElement(p, e);
6976    }
6977}
6978
6979// 文字列を PACK に追加
6980void PackAddStr(PACK *p, char *name, char *str)
6981{
6982    VALUE *v;
6983    // 引数チェック
6984    if (p == NULL || name == NULL || str == NULL)
6985    {
6986        return;
6987    }
6988
6989    v = NewStrValue(str);
6990    AddElement(p, NewElement(name, VALUE_STR, 1, &v));
6991}
6992
6993// RC4 キーペアを生成
6994void GenerateRC4KeyPair(RC4_KEY_PAIR *k)
6995{
6996    // 引数チェック
6997    if (k == NULL)
6998    {
6999        return;
7000    }
7001
7002    Rand(k->ClientToServerKey, sizeof(k->ClientToServerKey));
7003    Rand(k->ServerToClientKey, sizeof(k->ServerToClientKey));
7004}
7005
Note: See TracBrowser for help on using the repository browser.