source: lab.git/Dev/utvpn/utvpn-unix-v101-7101-public/src/Cedar/Cedar.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: 30.0 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// Cedar.c
79// Cedar 通信モジュールプログラムコード
80
81// Build 7101
82
83
84#include "CedarPch.h"
85
86static UINT init_cedar_counter = 0;
87static REF *cedar_log_ref = NULL;
88static LOG *cedar_log;
89
90// 現在サポートされている Windows のバージョンかどうか取得する
91// (以前、XP までしか想定していないコードを Vista (Longhorn) で動作させたときに
92//  OS ごと大変おかしくなってしまったことがあるので、バージョンチェックは
93//  必ず行うようにした。ただし、警告メッセージを画面に表示するだけであり、
94//  動作は一応できるようにしている。)
95bool IsSupportedWinVer(RPC_WINVER *v)
96{
97    // 引数チェック
98    if (v == NULL)
99    {
100        return false;
101    }
102
103    if (v->IsWindows == false)
104    {
105        return true;
106    }
107
108    if (v->IsNT == false)
109    {
110        return true;
111    }
112
113    if (v->IsBeta)
114    {
115        return true;
116    }
117
118    if (v->VerMajor <= 4)
119    {
120        // Windows NT
121        return true;
122    }
123
124    if (v->VerMajor == 5 && v->VerMinor == 0)
125    {
126        // Windows 2000
127        if (v->ServicePack <= 4)
128        {
129            // SP4 までサポート
130            return true;
131        }
132    }
133
134    if (v->VerMajor == 5 && v->VerMinor == 1)
135    {
136        // Windows XP x86
137        if (v->ServicePack <= 3)
138        {
139            // SP3 までサポート
140            return true;
141        }
142    }
143
144    if (v->VerMajor == 5 && v->VerMinor == 2)
145    {
146        // Windows XP x64, Windows Server 2003
147        if (v->ServicePack <= 2)
148        {
149            // SP2 までサポート
150            return true;
151        }
152    }
153
154    if (v->VerMajor == 6 && v->VerMinor == 0)
155    {
156        // Windows Vista, Server 2008
157        if (v->ServicePack <= 2)
158        {
159            // SP2 までサポート
160            return true;
161        }
162    }
163
164    if (v->VerMajor == 6 && v->VerMinor == 1)
165    {
166        // Windows 7, Server 2008 R2
167        if (v->ServicePack <= 0)
168        {
169            // SP0 までサポート
170            return true;
171        }
172    }
173
174    return false;
175}
176
177// Windows のバージョンを取得する
178void GetWinVer(RPC_WINVER *v)
179{
180    // 引数チェック
181    if (v == NULL)
182    {
183        return;
184    }
185
186#ifdef  OS_WIN32
187    Win32GetWinVer(v);
188#else   // OS_WIN32
189    Zero(v, sizeof(RPC_WINVER));
190    StrCpy(v->Title, sizeof(v->Title), GetOsInfo()->OsProductName);
191#endif  // OS_WIN32
192}
193
194// 簡易ログを閉じる
195void FreeTinyLog(TINY_LOG *t)
196{
197    // 引数チェック
198    if (t == NULL)
199    {
200        return;
201    }
202
203    FileClose(t->io);
204    DeleteLock(t->Lock);
205    Free(t);
206}
207
208// 簡易ログの書き込み
209void WriteTinyLog(TINY_LOG *t, char *str)
210{
211    BUF *b;
212    char dt[MAX_PATH];
213    // 引数チェック
214    if (t == NULL)
215    {
216        return;
217    }
218
219    GetDateTimeStrMilli64(dt, sizeof(dt), LocalTime64());
220    StrCat(dt, sizeof(dt), ": ");
221
222    b = NewBuf();
223
224    WriteBuf(b, dt, StrLen(dt));
225    WriteBuf(b, str, StrLen(str));
226    WriteBuf(b, "\r\n", 2);
227
228    Lock(t->Lock);
229    {
230        FileWrite(t->io, b->Buf, b->Size);
231        FileFlush(t->io);
232    }
233    Unlock(t->Lock);
234
235    FreeBuf(b);
236}
237
238// 簡易ログの初期化
239TINY_LOG *NewTinyLog()
240{
241    char name[MAX_PATH];
242    SYSTEMTIME st;
243    TINY_LOG *t;
244
245    LocalTime(&st);
246
247    MakeDir(TINY_LOG_DIRNAME);
248
249    Format(name, sizeof(name), TINY_LOG_FILENAME,
250        st.wYear, st.wMonth, st.wDay, st.wHour, st.wMinute, st.wSecond);
251
252    t = ZeroMalloc(sizeof(TINY_LOG));
253
254    StrCpy(t->FileName, sizeof(t->FileName), name);
255    t->io = FileCreate(name);
256    t->Lock = NewLock();
257
258    return t;
259}
260
261// 非 SSL リストのエントリの比較
262int CompareNoSslList(void *p1, void *p2)
263{
264    NON_SSL *n1, *n2;
265    if (p1 == NULL || p2 == NULL)
266    {
267        return 0;
268    }
269    n1 = *(NON_SSL **)p1;
270    n2 = *(NON_SSL **)p2;
271    if (n1 == NULL || n2 == NULL)
272    {
273        return 0;
274    }
275    return CmpIpAddr(&n1->IpAddress, &n2->IpAddress);
276}
277
278// 指定された IP アドレスが非 SSL リストに存在するかどうかチェック
279bool IsInNoSsl(CEDAR *c, IP *ip)
280{
281    bool ret = false;
282    // 引数チェック
283    if (c == NULL || ip == NULL)
284    {
285        return false;
286    }
287
288    LockList(c->NonSslList);
289    {
290        NON_SSL *n = SearchNoSslList(c, ip);
291
292        if (n != NULL)
293        {
294            if (n->EntryExpires > Tick64() && n->Count > NON_SSL_MIN_COUNT)
295            {
296                n->EntryExpires = Tick64() + (UINT64)NON_SSL_ENTRY_EXPIRES;
297                ret = true;
298            }
299        }
300    }
301    UnlockList(c->NonSslList);
302
303    return ret;
304}
305
306// 非 SSL リストのエントリをデクリメント
307void DecrementNoSsl(CEDAR *c, IP *ip, UINT num_dec)
308{
309    // 引数チェック
310    if (c == NULL || ip == NULL)
311    {
312        return;
313    }
314
315    LockList(c->NonSslList);
316    {
317        NON_SSL *n = SearchNoSslList(c, ip);
318
319        if (n != NULL)
320        {
321            if (n->Count >= num_dec)
322            {
323                n->Count -= num_dec;
324            }
325        }
326    }
327    UnlockList(c->NonSslList);
328}
329
330// 非 SSL リストにエントリを追加
331bool AddNoSsl(CEDAR *c, IP *ip)
332{
333    NON_SSL *n;
334    bool ret = true;
335    // 引数チェック
336    if (c == NULL || ip == NULL)
337    {
338        return true;
339    }
340
341    LockList(c->NonSslList);
342    {
343        DeleteOldNoSsl(c);
344
345        n = SearchNoSslList(c, ip);
346
347        if (n == NULL)
348        {
349            n = ZeroMalloc(sizeof(NON_SSL));
350            Copy(&n->IpAddress, ip, sizeof(IP));
351            n->Count = 0;
352
353            Add(c->NonSslList, n);
354        }
355
356        n->EntryExpires = Tick64() + (UINT64)NON_SSL_ENTRY_EXPIRES;
357
358        n->Count++;
359
360        if (n->Count > NON_SSL_MIN_COUNT)
361        {
362            ret = false;
363        }
364    }
365    UnlockList(c->NonSslList);
366
367    return ret;
368}
369
370// 古い非 SSL リストの削除
371void DeleteOldNoSsl(CEDAR *c)
372{
373    UINT i;
374    LIST *o;
375    // 引数チェック
376    if (c == NULL)
377    {
378        return;
379    }
380
381    o = NewListFast(NULL);
382
383    for (i = 0;i < LIST_NUM(c->NonSslList);i++)
384    {
385        NON_SSL *n = LIST_DATA(c->NonSslList, i);
386
387        if (n->EntryExpires <= Tick64())
388        {
389            Add(o, n);
390        }
391    }
392
393    for (i = 0;i < LIST_NUM(o);i++)
394    {
395        NON_SSL *n = LIST_DATA(o, i);
396
397        Delete(c->NonSslList, n);
398        Free(n);
399    }
400
401    ReleaseList(o);
402}
403
404// 非 SSL リストの検索
405NON_SSL *SearchNoSslList(CEDAR *c, IP *ip)
406{
407    NON_SSL *n, t;
408    // 引数チェック
409    if (c == NULL || ip == NULL)
410    {
411        return NULL;
412    }
413
414    Zero(&t, sizeof(t));
415    Copy(&t.IpAddress, ip, sizeof(IP));
416
417    n = Search(c->NonSslList, &t);
418
419    if (n == NULL)
420    {
421        return NULL;
422    }
423
424    return n;
425}
426
427// 非 SSL リストの初期化
428void InitNoSslList(CEDAR *c)
429{
430    // 引数チェック
431    if (c == NULL)
432    {
433        return;
434    }
435
436    c->NonSslList = NewList(CompareNoSslList);
437}
438
439// 非 SSL リストの解放
440void FreeNoSslList(CEDAR *c)
441{
442    UINT i;
443    // 引数チェック
444    if (c == NULL)
445    {
446        return;
447    }
448
449    for (i = 0;i < LIST_NUM(c->NonSslList);i++)
450    {
451        NON_SSL *n = LIST_DATA(c->NonSslList, i);
452
453        Free(n);
454    }
455
456    ReleaseList(c->NonSslList);
457    c->NonSslList = NULL;
458}
459
460// Cedar ログをとる
461void CedarLog(char *str)
462{
463    char *tmp;
464    // 引数チェック
465    if (str == NULL)
466    {
467        return;
468    }
469    if (cedar_log_ref == NULL)
470    {
471        return;
472    }
473
474    tmp = CopyStr(str);
475
476    // このあたりは急いで実装したのでコードがあまり美しくない。
477    if (StrLen(tmp) > 1)
478    {
479        if (tmp[StrLen(tmp) - 1] == '\n')
480        {
481            tmp[StrLen(tmp) - 1] = 0;
482        }
483        if (StrLen(tmp) > 1)
484        {
485            if (tmp[StrLen(tmp) - 1] == '\r')
486            {
487                tmp[StrLen(tmp) - 1] = 0;
488            }
489        }
490    }
491
492    InsertStringRecord(cedar_log, tmp);
493
494    Free(tmp);
495}
496
497// ログを開始する
498void StartCedarLog()
499{
500    if (cedar_log_ref == NULL)
501    {
502        cedar_log_ref = NewRef();
503    }
504    else
505    {
506        AddRef(cedar_log_ref);
507    }
508
509    cedar_log = NewLog("debug_log", "debug", LOG_SWITCH_DAY);
510}
511
512// ログを停止する
513void StopCedarLog()
514{
515    if (cedar_log_ref == NULL)
516    {
517        return;
518    }
519
520    if (Release(cedar_log_ref) == 0)
521    {
522        FreeLog(cedar_log);
523        cedar_log = NULL;
524        cedar_log_ref = NULL;
525    }
526}
527
528// トラフィックのパケットサイズを取得する
529UINT64 GetTrafficPacketSize(TRAFFIC *t)
530{
531    // 引数チェック
532    if (t == NULL)
533    {
534        return 0;
535    }
536
537    return t->Recv.BroadcastBytes + t->Recv.UnicastBytes +
538        t->Send.BroadcastBytes + t->Send.UnicastBytes;
539}
540
541// トラフィックのパケット数を取得する
542UINT64 GetTrafficPacketNum(TRAFFIC *t)
543{
544    // 引数チェック
545    if (t == NULL)
546    {
547        return 0;
548    }
549
550    return t->Recv.BroadcastCount + t->Recv.UnicastCount +
551        t->Send.BroadcastCount + t->Send.UnicastCount;
552}
553
554// 非表示パスワードの内容が変更されたかどうかチェックする
555bool IsHiddenPasswordChanged(char *str)
556{
557    // 引数チェック
558    if (str == NULL)
559    {
560        return true;
561    }
562
563    if (StrCmpi(str, HIDDEN_PASSWORD) == 0)
564    {
565        return true;
566    }
567    else
568    {
569        return false;
570    }
571}
572
573// 非表示パスワードを初期化する
574void InitHiddenPassword(char *str, UINT size)
575{
576    // 引数チェック
577    if (str == NULL)
578    {
579        return;
580    }
581
582    StrCpy(str, size, HIDDEN_PASSWORD);
583}
584
585// 証明書が仮想 HUB に登録されている CA によって署名されているかどうか確認する
586bool CheckSignatureByCaLinkMode(SESSION *s, X *x)
587{
588    LINK *k;
589    HUB *h;
590    bool ret = false;
591    // 引数チェック
592    if (s == NULL || x == NULL)
593    {
594        return false;
595    }
596
597    if (s->LinkModeClient == false || (k = s->Link) == NULL)
598    {
599        return false;
600    }
601
602    h = k->Hub;
603
604    if (h->HubDb != NULL)
605    {
606        LockList(h->HubDb->RootCertList);
607        {
608            X *root_cert;
609            root_cert = GetIssuerFromList(h->HubDb->RootCertList, x);
610            if (root_cert != NULL)
611            {
612                ret = true;
613            }
614        }
615        UnlockList(h->HubDb->RootCertList);
616    }
617
618    return ret;
619}
620
621// 証明書が Cedar に登録されている CA によって署名されているかどうか確認する
622bool CheckSignatureByCa(CEDAR *cedar, X *x)
623{
624    X *ca;
625    // 引数チェック
626    if (cedar == NULL || x == NULL)
627    {
628        return false;
629    }
630
631    // 指定された証明書を署名した CA を取得
632    ca = FindCaSignedX(cedar->CaList, x);
633    if (ca == NULL)
634    {
635        // 発見できなかった
636        return false;
637    }
638
639    // 発見した
640    FreeX(ca);
641    return true;
642}
643
644// 指定された証明書を署名した CA を取得
645X *FindCaSignedX(LIST *o, X *x)
646{
647    X *ret;
648    // 引数チェック
649    if (o == NULL || x == NULL)
650    {
651        return NULL;
652    }
653
654    ret = NULL;
655
656    LockList(o);
657    {
658        UINT i;
659        for (i = 0;i < LIST_NUM(o);i++)
660        {
661            X *ca = LIST_DATA(o, i);
662            if (CheckXDateNow(ca))
663            {
664                if (CompareName(ca->subject_name, x->issuer_name))
665                {
666                    K *k = GetKFromX(ca);
667                    if (k != NULL)
668                    {
669                        if (CheckSignature(x, k))
670                        {
671                            ret = CloneX(ca);
672                        }
673                        FreeK(k);
674                    }
675                }
676                else if (CompareX(ca, x))
677                {
678                    ret = CloneX(ca);
679                }
680            }
681
682            if (ret != NULL)
683            {
684                break;
685            }
686        }
687    }
688    UnlockList(o);
689
690    return ret;
691}
692
693// Cedar から CA を削除する
694bool DeleteCa(CEDAR *cedar, UINT ptr)
695{
696    bool b = false;
697    // 引数チェック
698    if (cedar == NULL || ptr == 0)
699    {
700        return false;
701    }
702
703    LockList(cedar->CaList);
704    {
705        UINT i;
706
707        for (i = 0;i < LIST_NUM(cedar->CaList);i++)
708        {
709            X *x = LIST_DATA(cedar->CaList, i);
710
711            if (POINTER_TO_KEY(x) == ptr)
712            {
713                Delete(cedar->CaList, x);
714                FreeX(x);
715
716                b = true;
717
718                break;
719            }
720        }
721    }
722    UnlockList(cedar->CaList);
723
724    return b;
725}
726
727// Cedar に CA を追加する
728void AddCa(CEDAR *cedar, X *x)
729{
730    // 引数チェック
731    if (cedar == NULL || x == NULL)
732    {
733        return;
734    }
735
736    LockList(cedar->CaList);
737    {
738        UINT i;
739        bool ok = true;
740
741        for (i = 0;i < LIST_NUM(cedar->CaList);i++)
742        {
743            X *exist_x = LIST_DATA(cedar->CaList, i);
744            if (CompareX(exist_x, x))
745            {
746                ok = false;
747                break;
748            }
749        }
750
751        if (ok)
752        {
753            Insert(cedar->CaList, CloneX(x));
754        }
755    }
756    UnlockList(cedar->CaList);
757}
758
759// Cedar からコネクションを削除する
760void DelConnection(CEDAR *cedar, CONNECTION *c)
761{
762    // 引数チェック
763    if (cedar == NULL || c == NULL)
764    {
765        return;
766    }
767
768    LockList(cedar->ConnectionList);
769    {
770        Debug("Connection %s Deleted from Cedar.\n", c->Name);
771        if (Delete(cedar->ConnectionList, c))
772        {
773            ReleaseConnection(c);
774        }
775    }
776    UnlockList(cedar->ConnectionList);
777}
778
779// 現在の未確立コネクション数を取得する
780UINT GetUnestablishedConnections(CEDAR *cedar)
781{
782    UINT i, ret;
783    // 引数チェック
784    if (cedar == NULL)
785    {
786        return 0;
787    }
788
789    ret = 0;
790
791    LockList(cedar->ConnectionList);
792    {
793        for (i = 0;i < LIST_NUM(cedar->ConnectionList);i++)
794        {
795            CONNECTION *c = LIST_DATA(cedar->ConnectionList, i);
796
797            switch (c->Type)
798            {
799            case CONNECTION_TYPE_CLIENT:
800            case CONNECTION_TYPE_INIT:
801            case CONNECTION_TYPE_LOGIN:
802            case CONNECTION_TYPE_ADDITIONAL:
803                switch (c->Status)
804                {
805                case CONNECTION_STATUS_ACCEPTED:
806                case CONNECTION_STATUS_NEGOTIATION:
807                case CONNECTION_STATUS_USERAUTH:
808                    ret++;
809                    break;
810                }
811                break;
812            }
813        }
814    }
815    UnlockList(cedar->ConnectionList);
816
817    return ret + Count(cedar->AcceptingSockets);
818}
819
820// Cedar にコネクションを追加する
821void AddConnection(CEDAR *cedar, CONNECTION *c)
822{
823    char tmp[MAX_SIZE];
824    UINT i;
825    // 引数チェック
826    if (cedar == NULL || c == NULL)
827    {
828        return;
829    }
830
831    //新しいコネクションの名前を決定する
832    i = Inc(cedar->ConnectionIncrement);
833    Format(tmp, sizeof(tmp), "CID-%u", i);
834    Lock(c->lock);
835    {
836        Free(c->Name);
837        c->Name = CopyStr(tmp);
838    }
839    Unlock(c->lock);
840
841    LockList(cedar->ConnectionList);
842    {
843        Add(cedar->ConnectionList, c);
844        AddRef(c->ref);
845        Debug("Connection %s Inserted to Cedar.\n", c->Name);
846    }
847    UnlockList(cedar->ConnectionList);
848}
849
850// すべてのコネクションを停止
851void StopAllConnection(CEDAR *c)
852{
853    UINT num;
854    UINT i;
855    CONNECTION **connections;
856    // 引数チェック
857    if (c == NULL)
858    {
859        return;
860    }
861
862    LockList(c->ConnectionList);
863    {
864        connections = ToArray(c->ConnectionList);
865        num = LIST_NUM(c->ConnectionList);
866        DeleteAll(c->ConnectionList);
867    }
868    UnlockList(c->ConnectionList);
869
870    for (i = 0;i < num;i++)
871    {
872        StopConnection(connections[i], false);
873        ReleaseConnection(connections[i]);
874    }
875    Free(connections);
876}
877
878// CEDAR から HUB を削除
879void DelHub(CEDAR *c, HUB *h)
880{
881    DelHubEx(c, h, false);
882}
883void DelHubEx(CEDAR *c, HUB *h, bool no_lock)
884{
885    // 引数チェック
886    if (c == NULL || h == NULL)
887    {
888        return;
889    }
890
891    if (no_lock == false)
892    {
893        LockHubList(c);
894    }
895
896    if (Delete(c->HubList, h))
897    {
898        ReleaseHub(h);
899    }
900
901    if (no_lock == false)
902    {
903        UnlockHubList(c);
904    }
905}
906
907// CEDAR に HUB を追加
908void AddHub(CEDAR *c, HUB *h)
909{
910    // 引数チェック
911    if (c == NULL || h == NULL)
912    {
913        return;
914    }
915
916    LockHubList(c);
917    {
918#if 0
919        // HUB 数はここではチェックしないことにする
920        if (LIST_NUM(c->HubList) >= MAX_HUBS)
921        {
922            // 上限数超過
923            UnlockHubList(c);
924            return;
925        }
926#endif
927
928        // 同一名の HUB が存在しないかどうかチェック
929        if (IsHub(c, h->Name))
930        {
931            // 存在する
932            UnlockHubList(c);
933            return;
934        }
935
936        // HUB を登録する
937        Insert(c->HubList, h);
938        AddRef(h->ref);
939    }
940    UnlockHubList(c);
941}
942
943// CEDAR のすべての HUB を停止
944void StopAllHub(CEDAR *c)
945{
946    HUB **hubs;
947    UINT i, num;
948    // 引数チェック
949    if (c == NULL)
950    {
951        return;
952    }
953
954    LockHubList(c);
955    {
956        hubs = ToArray(c->HubList);
957        num = LIST_NUM(c->HubList);
958        DeleteAll(c->HubList);
959    }
960    UnlockHubList(c);
961
962    for (i = 0;i < num;i++)
963    {
964        StopHub(hubs[i]);
965        ReleaseHub(hubs[i]);
966    }
967
968    Free(hubs);
969}
970
971// CEDAR にリスナーを追加
972void AddListener(CEDAR *c, LISTENER *r)
973{
974    // 引数チェック
975    if (c == NULL || r == NULL)
976    {
977        return;
978    }
979
980    LockList(c->ListenerList);
981    {
982        Add(c->ListenerList, r);
983        AddRef(r->ref);
984    }
985    UnlockList(c->ListenerList);
986}
987
988// CEDAR のすべてのリスナーを停止
989void StopAllListener(CEDAR *c)
990{
991    LISTENER **array;
992    UINT i, num;
993    // 引数チェック
994    if (c == NULL)
995    {
996        return;
997    }
998
999    LockList(c->ListenerList);
1000    {
1001        array = ToArray(c->ListenerList);
1002        num = LIST_NUM(c->ListenerList);
1003        DeleteAll(c->ListenerList);
1004    }
1005    UnlockList(c->ListenerList);
1006
1007    for (i = 0;i < num;i++)
1008    {
1009        StopListener(array[i]);
1010        ReleaseListener(array[i]);
1011    }
1012    Free(array);
1013}
1014
1015// CEDAR の停止
1016void StopCedar(CEDAR *c)
1017{
1018    // 引数チェック
1019    if (c == NULL)
1020    {
1021        return;
1022    }
1023
1024    // 停止フラグ
1025    c->Halt = true;
1026
1027    // すべてのリスナーを停止
1028    StopAllListener(c);
1029    // すべてのコネクションを停止
1030    StopAllConnection(c);
1031    // すべての HUB を停止
1032    StopAllHub(c);
1033    // すべての L3 スイッチを解放
1034    L3FreeAllSw(c);
1035}
1036
1037// CEDAR のクリーンアップ
1038void CleanupCedar(CEDAR *c)
1039{
1040    UINT i;
1041    // 引数チェック
1042    if (c == NULL)
1043    {
1044        return;
1045    }
1046
1047    FreeCedarLayer3(c);
1048
1049/*
1050    for (i = 0;i < LIST_NUM(c->HubList);i++)
1051    {
1052        HUB *h = LIST_DATA(c->HubList, i);
1053    }
1054*/
1055    for (i = 0;i < LIST_NUM(c->CaList);i++)
1056    {
1057        X *x = LIST_DATA(c->CaList, i);
1058        FreeX(x);
1059    }
1060    ReleaseList(c->CaList);
1061
1062    ReleaseList(c->ListenerList);
1063    ReleaseList(c->HubList);
1064    ReleaseList(c->ConnectionList);
1065    //CleanupUDPEntry(c);
1066    ReleaseList(c->UDPEntryList);
1067    DeleteLock(c->lock);
1068    DeleteCounter(c->ConnectionIncrement);
1069    DeleteCounter(c->CurrentSessions);
1070
1071    if (c->DebugLog != NULL)
1072    {
1073        FreeLog(c->DebugLog);
1074    }
1075
1076    if (c->ServerX)
1077    {
1078        FreeX(c->ServerX);
1079    }
1080    if (c->ServerK)
1081    {
1082        FreeK(c->ServerK);
1083    }
1084
1085    if (c->CipherList)
1086    {
1087        Free(c->CipherList);
1088    }
1089
1090    for (i = 0;i < LIST_NUM(c->TrafficDiffList);i++)
1091    {
1092        TRAFFIC_DIFF *d = LIST_DATA(c->TrafficDiffList, i);
1093        Free(d->Name);
1094        Free(d->HubName);
1095        Free(d);
1096    }
1097
1098    ReleaseList(c->TrafficDiffList);
1099
1100    Free(c->ServerStr);
1101    Free(c->MachineName);
1102
1103    Free(c->HttpUserAgent);
1104    Free(c->HttpAccept);
1105    Free(c->HttpAcceptLanguage);
1106    Free(c->HttpAcceptEncoding);
1107
1108    FreeTraffic(c->Traffic);
1109
1110    DeleteLock(c->TrafficLock);
1111
1112    FreeNetSvcList(c);
1113
1114    Free(c->VerString);
1115    Free(c->BuildInfo);
1116
1117    FreeLocalBridgeList(c);
1118
1119    DeleteCounter(c->AssignedBridgeLicense);
1120    DeleteCounter(c->AssignedClientLicense);
1121
1122    FreeNoSslList(c);
1123
1124    DeleteLock(c->CedarSuperLock);
1125
1126    DeleteCounter(c->AcceptingSockets);
1127
1128    Free(c);
1129}
1130
1131// CEDAR の解放
1132void ReleaseCedar(CEDAR *c)
1133{
1134    // 引数チェック
1135    if (c == NULL)
1136    {
1137        return;
1138    }
1139
1140    if (Release(c->ref) == 0)
1141    {
1142        CleanupCedar(c);
1143    }
1144}
1145
1146// CipherList のセット
1147void SetCedarCipherList(CEDAR *cedar, char *name)
1148{
1149    // 引数チェック
1150    if (cedar == NULL)
1151    {
1152        return;
1153    }
1154
1155    if (cedar->CipherList != NULL)
1156    {
1157        Free(cedar->CipherList);
1158    }
1159    if (name != NULL)
1160    {
1161        cedar->CipherList = CopyStr(name);
1162    }
1163    else
1164    {
1165        cedar->CipherList = NULL;
1166    }
1167}
1168
1169// ネットサービスリストのソート
1170int CompareNetSvc(void *p1, void *p2)
1171{
1172    NETSVC *n1, *n2;
1173    if (p1 == NULL || p2 == NULL)
1174    {
1175        return 0;
1176    }
1177    n1 = *(NETSVC **)p1;
1178    n2 = *(NETSVC **)p2;
1179    if (n1 == NULL || n2 == NULL)
1180    {
1181        return 0;
1182    }
1183    if (n1->Port > n2->Port)
1184    {
1185        return 1;
1186    }
1187    else if (n1->Port < n2->Port)
1188    {
1189        return -1;
1190    }
1191    else if (n1->Udp > n2->Udp)
1192    {
1193        return 1;
1194    }
1195    else if (n1->Udp < n2->Udp)
1196    {
1197        return -1;
1198    }
1199    return 0;
1200}
1201
1202// ネットサービスリストの初期化
1203void InitNetSvcList(CEDAR *cedar)
1204{
1205    char filename[MAX_PATH] = "/etc/services";
1206    BUF *b;
1207    // 引数チェック
1208    if (cedar == NULL)
1209    {
1210        return;
1211    }
1212
1213#ifdef  OS_WIN32
1214    // 自力でがんばって読む
1215    Format(filename, sizeof(filename), "%s\\drivers\\etc\\services", MsGetSystem32Dir());
1216#endif
1217
1218    cedar->NetSvcList = NewList(CompareNetSvc);
1219
1220    b = ReadDump(filename);
1221    if (b == NULL)
1222    {
1223        return;
1224    }
1225
1226    while (true)
1227    {
1228        char *s = CfgReadNextLine(b);
1229        if (s == NULL)
1230        {
1231            break;
1232        }
1233
1234        Trim(s);
1235        if (s[0] != '#')
1236        {
1237            TOKEN_LIST *t = ParseToken(s, " \t/");
1238            if (t->NumTokens >= 3)
1239            {
1240                NETSVC *n = ZeroMalloc(sizeof(NETSVC));
1241                n->Name = CopyStr(t->Token[0]);
1242                n->Udp = (StrCmpi(t->Token[2], "udp") == 0 ? true : false);
1243                n->Port = ToInt(t->Token[1]);
1244                Add(cedar->NetSvcList, n);
1245            }
1246            FreeToken(t);
1247        }
1248        Free(s);
1249    }
1250
1251    FreeBuf(b);
1252}
1253
1254// ネットサービス名の取得
1255char *GetSvcName(CEDAR *cedar, bool udp, UINT port)
1256{
1257    char *ret = NULL;
1258    NETSVC t;
1259    // 引数チェック
1260    if (cedar == NULL)
1261    {
1262        return NULL;
1263    }
1264
1265    t.Udp = (udp == 0 ? false : true);
1266    t.Port = port;
1267
1268    LockList(cedar->NetSvcList);
1269    {
1270        NETSVC *n = Search(cedar->NetSvcList, &t);
1271        if (n != NULL)
1272        {
1273            ret = n->Name;
1274        }
1275    }
1276    UnlockList(cedar->NetSvcList);
1277
1278    return ret;
1279}
1280
1281// ネットサービスリストの解放
1282void FreeNetSvcList(CEDAR *cedar)
1283{
1284    UINT i;
1285    // 引数チェック
1286    if (cedar == NULL)
1287    {
1288        return;
1289    }
1290
1291    for (i = 0;i < LIST_NUM(cedar->NetSvcList);i++)
1292    {
1293        NETSVC *n = LIST_DATA(cedar->NetSvcList, i);
1294        Free(n->Name);
1295        Free(n);
1296    }
1297    ReleaseList(cedar->NetSvcList);
1298}
1299
1300// CEDAR の証明書の変更
1301void SetCedarCert(CEDAR *c, X *server_x, K *server_k)
1302{
1303    // 引数チェック
1304    if (server_x == NULL || server_k == NULL)
1305    {
1306        return;
1307    }
1308
1309    Lock(c->lock);
1310    {
1311        if (c->ServerX != NULL)
1312        {
1313            FreeX(c->ServerX);
1314        }
1315
1316        if (c->ServerK != NULL)
1317        {
1318            FreeK(c->ServerK);
1319        }
1320
1321        c->ServerX = CloneX(server_x);
1322        c->ServerK = CloneK(server_k);
1323    }
1324    Unlock(c->lock);
1325}
1326
1327// デバッグログを有効にする
1328void EnableDebugLog(CEDAR *c)
1329{
1330    // 引数チェック
1331    if (c == NULL || c->DebugLog != NULL)
1332    {
1333        return;
1334    }
1335
1336    c->DebugLog = NewLog("cedar_debug_log", "cedar", LOG_SWITCH_NO);
1337}
1338
1339// CEDAR を VPN Bridge にする
1340void SetCedarVpnBridge(CEDAR *c)
1341{
1342    // 引数チェック
1343    if (c == NULL)
1344    {
1345        return;
1346    }
1347
1348    c->Bridge = true;
1349
1350    Free(c->ServerStr);
1351    c->ServerStr = CopyStr(CEDAR_BRIDGE_STR);
1352}
1353
1354// CEDAR の作成
1355CEDAR *NewCedar(X *server_x, K *server_k)
1356{
1357    CEDAR *c;
1358    char tmp[MAX_SIZE];
1359    char tmp2[MAX_SIZE];
1360    char *beta_str;
1361
1362    c = ZeroMalloc(sizeof(CEDAR));
1363
1364    c->AcceptingSockets = NewCounter();
1365
1366    c->CedarSuperLock = NewLock();
1367
1368#ifdef  BETA_NUMBER
1369    c->Beta = BETA_NUMBER;
1370#endif  // BETA_NUMBER
1371
1372    InitNoSslList(c);
1373
1374    c->AssignedBridgeLicense = NewCounter();
1375    c->AssignedClientLicense = NewCounter();
1376
1377    Rand(c->UniqueId, sizeof(c->UniqueId));
1378
1379    c->CreatedTick = Tick64();
1380
1381    c->lock = NewLock();
1382    c->ref = NewRef();
1383
1384    c->CurrentTcpConnections = GetNumTcpConnectionsCounter();
1385
1386    c->ListenerList = NewList(CompareListener);
1387    c->UDPEntryList = NewList(CompareUDPEntry);
1388    c->HubList = NewList(CompareHub);
1389    c->ConnectionList = NewList(CompareConnection);
1390
1391    c->ConnectionIncrement = NewCounter();
1392    c->CurrentSessions = NewCounter();
1393
1394    if (server_k && server_x)
1395    {
1396        c->ServerK = CloneK(server_k);
1397        c->ServerX = CloneX(server_x);
1398    }
1399
1400    c->Version = CEDAR_VER;
1401    c->Build = CEDAR_BUILD;
1402    c->ServerStr = CopyStr(CEDAR_SERVER_STR);
1403
1404    GetMachineName(tmp, sizeof(tmp));
1405    c->MachineName = CopyStr(tmp);
1406
1407    c->HttpUserAgent = CopyStr(DEFAULT_USER_AGENT);
1408    c->HttpAccept = CopyStr(DEFAULT_ACCEPT);
1409    c->HttpAcceptLanguage = CopyStr("ja");
1410    c->HttpAcceptEncoding = CopyStr(DEFAULT_ENCODING);
1411
1412    c->Traffic = NewTraffic();
1413    c->TrafficLock = NewLock();
1414    c->CaList = NewList(CompareCert);
1415
1416    c->TrafficDiffList = NewList(NULL);
1417
1418    SetCedarCipherList(c, "RC4-MD5");
1419
1420    c->ClientId = _II("CLIENT_ID");
1421
1422    InitNetSvcList(c);
1423
1424    InitLocalBridgeList(c);
1425
1426    InitCedarLayer3(c);
1427
1428#ifdef  ALPHA_VERSION
1429    beta_str = "Alpha";
1430#else   // ALPHA_VERSION
1431    beta_str = "Release Candidate";
1432#endif  // ALPHA_VERSION
1433
1434    ToStr(tmp2, c->Beta);
1435
1436    Format(tmp, sizeof(tmp), "Version %u.%02u Build %u %s %s (%s)",
1437        CEDAR_VER / 100, CEDAR_VER - (CEDAR_VER / 100) * 100,
1438        CEDAR_BUILD,
1439        c->Beta == 0 ? "" : beta_str,
1440        c->Beta == 0 ? "" : tmp2,
1441        _SS("LANGSTR"));
1442    Trim(tmp);
1443
1444    if (true)
1445    {
1446        SYSTEMTIME st;
1447        Zero(&st, sizeof(st));
1448
1449        st.wYear = BUILD_DATE_Y;
1450        st.wMonth = BUILD_DATE_M;
1451        st.wDay = BUILD_DATE_D;
1452
1453        c->BuiltDate = SystemToUINT64(&st);
1454    }
1455
1456    c->VerString = CopyStr(tmp);
1457
1458    Format(tmp, sizeof(tmp), "Compiled %04u/%02u/%02u %02u:%02u:%02u by %s at %s",
1459        BUILD_DATE_Y, BUILD_DATE_M, BUILD_DATE_D, BUILD_DATE_HO, BUILD_DATE_MI, BUILD_DATE_SE, BUILDER_NAME, BUILD_PLACE);
1460
1461    c->BuildInfo = CopyStr(tmp);
1462
1463    return c;
1464}
1465
1466// 指定した日付よりも遅い日付にビルドされたものであるかどうか取得
1467bool IsLaterBuild(CEDAR *c, UINT64 t)
1468{
1469    SYSTEMTIME sb, st;
1470    UINT64 b;
1471    // 引数チェック
1472    if (c == NULL)
1473    {
1474        return false;
1475    }
1476
1477    Zero(&sb, sizeof(sb));
1478    Zero(&st, sizeof(st));
1479
1480    UINT64ToSystem(&sb, c->BuiltDate);
1481    UINT64ToSystem(&st, t);
1482
1483    // 時刻データを無視
1484    sb.wHour = sb.wMinute = sb.wSecond = sb.wMilliseconds = 0;
1485    st.wHour = st.wMinute = st.wSecond = st.wMilliseconds = 0;
1486
1487    b = SystemToUINT64(&sb);
1488    t = SystemToUINT64(&st);
1489
1490    if (b > t)
1491    {
1492        return true;
1493    }
1494    else
1495    {
1496        return false;
1497    }
1498}
1499
1500// トラフィック情報の加算
1501void AddTraffic(TRAFFIC *dst, TRAFFIC *diff)
1502{
1503    // 引数チェック
1504    if (dst == NULL || diff == NULL)
1505    {
1506        return;
1507    }
1508
1509    dst->Recv.BroadcastBytes += diff->Recv.BroadcastBytes;
1510    dst->Recv.BroadcastCount += diff->Recv.BroadcastCount;
1511    dst->Recv.UnicastBytes += diff->Recv.UnicastBytes;
1512    dst->Recv.UnicastCount += diff->Recv.UnicastCount;
1513
1514    dst->Send.BroadcastBytes += diff->Send.BroadcastBytes;
1515    dst->Send.BroadcastCount += diff->Send.BroadcastCount;
1516    dst->Send.UnicastBytes += diff->Send.UnicastBytes;
1517    dst->Send.UnicastCount += diff->Send.UnicastCount;
1518}
1519
1520// トラフィック情報の作成
1521TRAFFIC *NewTraffic()
1522{
1523    TRAFFIC *t;
1524
1525    // メモリ確保
1526    t = ZeroMalloc(sizeof(TRAFFIC));
1527    return t;
1528}
1529
1530// トラフィック情報の解放
1531void FreeTraffic(TRAFFIC *t)
1532{
1533    // 引数チェック
1534    if (t == NULL)
1535    {
1536        return;
1537    }
1538
1539    // メモリ解放
1540    Free(t);
1541}
1542
1543// Cedar 通信モジュールの初期化
1544void InitCedar()
1545{
1546    if ((init_cedar_counter++) > 0)
1547    {
1548        return;
1549    }
1550
1551    // プロトコル初期化
1552    InitProtocol();
1553}
1554
1555// Cedar 通信モジュールの解放
1556void FreeCedar()
1557{
1558    if ((--init_cedar_counter) > 0)
1559    {
1560        return;
1561    }
1562
1563    // プロトコル解放
1564    FreeProtocol();
1565}
1566
Note: See TracBrowser for help on using the repository browser.