* copy vendor drop to trunk
[lab.git] / Dev / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Link.c
1 // SoftEther UT-VPN SourceCode\r
2 // \r
3 // Copyright (C) 2004-2010 SoftEther Corporation.\r
4 // Copyright (C) 2004-2010 University of Tsukuba, Japan.\r
5 // Copyright (C) 2003-2010 Daiyuu Nobori.\r
6 // All Rights Reserved.\r
7 // \r
8 // http://utvpn.tsukuba.ac.jp/\r
9 // \r
10 // This program is free software; you can redistribute it and/or\r
11 // modify it under the terms of the GNU General Public License\r
12 // version 2 as published by the Free Software Foundation.\r
13 // \r
14 // This program is distributed in the hope that it will be useful,\r
15 // but WITHOUT ANY WARRANTY; without even the implied warranty of\r
16 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
17 // GNU General Public License for more details.\r
18 // \r
19 // You should have received a copy of the GNU General Public License version 2\r
20 // along with this program; if not, write to the Free Software\r
21 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.\r
22 // \r
23 // このファイルは GPL バージョン 2 ライセンスで公開されています。\r
24 // 誰でもこのファイルの内容を複製、改変したり、改変したバージョンを再配布\r
25 // することができます。ただし、原著作物を改変した場合は、原著作物の著作権表示\r
26 // を除去することはできません。改変した著作物を配布する場合は、改変実施者の\r
27 // 著作権表示を原著作物の著作権表示に付随して記載するようにしてください。\r
28 // \r
29 // この SoftEther UT-VPN オープンソース・プロジェクトは、日本国の\r
30 // ソフトイーサ株式会社 (SoftEther Corporation, http://www.softether.co.jp/ )\r
31 // および筑波大学 (University of Tsukuba, http://www.tsukuba.ac.jp/ ) によって\r
32 // ホストされています。\r
33 // 本プログラムの配布者は、本プログラムを、業としての利用以外のため、\r
34 // および、試験または研究のために利用が行われることを想定して配布\r
35 // しています。\r
36 // SoftEther UT-VPN プロジェクトの Web サイトは http://utvpn.tsukuba.ac.jp/ に\r
37 // あります。\r
38 // 本ソフトウェアの不具合の修正、機能改良、セキュリティホールの修復などのコード\r
39 // の改変を行った場合で、その成果物を SoftEther UT-VPN プロジェクトに提出して\r
40 // いただける場合は、 http://utvpn.tsukuba.ac.jp/ までソースコードを送付して\r
41 // ください。SoftEther UT-VPN プロジェクトの本体リリースまたはブランチリリース\r
42 // に組み込みさせていただきます。\r
43 // \r
44 // GPL に基づいて原著作物が提供される本ソフトウェアの改良版を配布、販売する\r
45 // 場合は、そのソースコードを GPL に基づいて誰にでも開示する義務が生じます。\r
46 // \r
47 // 本ソフトウェアに関連する著作権、特許権、商標権はソフトイーサ株式会社\r
48 // (SoftEther Corporation) およびその他の著作権保持者が保有しています。\r
49 // ソフトイーサ株式会社等はこれらの権利を放棄していません。本ソフトウェアの\r
50 // 二次著作物を配布、販売する場合は、これらの権利を侵害しないようにご注意\r
51 // ください。\r
52 // \r
53 // お願い: どのような通信ソフトウェアにも通常は必ず未発見の\r
54 // セキュリティホールが潜んでいます。本ソースコードをご覧いただいた結果、\r
55 // UT-VPN にセキュリティホールを発見された場合は、当該セキュリティホールの\r
56 // 情報を不特定多数に開示される前に、必ず、ソフトイーサ株式会社\r
57 // および脆弱性情報の届出を受け付ける公的機関まで通報いただき、\r
58 // 公益保護にご協力いただきますようお願い申し上げます。\r
59 // \r
60 // ソフトイーサ株式会社は、当該セキュリティホールについて迅速に対処を\r
61 // 行い、UT-VPN および UT-VPN に関連するソフトウェアのユーザー・顧客\r
62 // を保護するための努力を行います。\r
63 // \r
64 // ソフトイーサへの届出先: http://www.softether.co.jp/jp/contact/\r
65 // 日本国内の脆弱性情報届出受付公的機関:\r
66 //         独立行政法人 情報処理推進機構\r
67 //         http://www.ipa.go.jp/security/vuln/report/\r
68 // \r
69 // 上記各事項について不明な点は、ソフトイーサ株式会社までご連絡ください。\r
70 // 連絡先: http://www.softether.co.jp/jp/contact/\r
71 \r
72 // -----------------------------------------------\r
73 // [ChangeLog]\r
74 // 2010.05.20\r
75 //  新規リリース by SoftEther\r
76 // -----------------------------------------------\r
77 \r
78 // Link.c\r
79 // HUB 間リンク接続\r
80 \r
81 #include "CedarPch.h"\r
82 \r
83 // リンクサーバースレッド\r
84 void LinkServerSessionThread(THREAD *t, void *param)\r
85 {\r
86         LINK *k = (LINK *)param;\r
87         CONNECTION *c;\r
88         SESSION *s;\r
89         POLICY *policy;\r
90         wchar_t name[MAX_SIZE];\r
91         // 引数チェック\r
92         if (t == NULL || param == NULL)\r
93         {\r
94                 return;\r
95         }\r
96 \r
97         // サーバーコネクションの作成\r
98         c = NewServerConnection(k->Cedar, NULL, t);\r
99         c->Protocol = CONNECTION_HUB_LINK_SERVER;\r
100 \r
101         // ポリシーの作成\r
102         policy = ZeroMalloc(sizeof(POLICY));\r
103         Copy(policy, k->Policy, sizeof(POLICY));\r
104 \r
105         // サーバーセッションの作成\r
106         s = NewServerSession(k->Cedar, c, k->Hub, LINK_USER_NAME, policy);\r
107         s->LinkModeServer = true;\r
108         s->Link = k;\r
109         c->Session = s;\r
110         ReleaseConnection(c);\r
111 \r
112         // ユーザー名\r
113         s->Username = CopyStr(LINK_USER_NAME_PRINT);\r
114 \r
115         k->ServerSession = s;\r
116         AddRef(k->ServerSession->ref);\r
117 \r
118         // 初期化完了を通知\r
119         NoticeThreadInit(t);\r
120 \r
121         UniStrCpy(name, sizeof(name), k->Option->AccountName);\r
122         HLog(s->Hub, "LH_LINK_START", name, s->Name);\r
123 \r
124         // セッションのメイン関数\r
125         SessionMain(s);\r
126 \r
127         HLog(s->Hub, "LH_LINK_STOP", name);\r
128 \r
129         ReleaseSession(s);\r
130 }\r
131 \r
132 // パケットアダプタ初期化\r
133 bool LinkPaInit(SESSION *s)\r
134 {\r
135         LINK *k;\r
136         THREAD *t;\r
137         // 引数チェック\r
138         if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)\r
139         {\r
140                 return false;\r
141         }\r
142 \r
143         // 送信パケットキューの作成\r
144         k->SendPacketQueue = NewQueue();\r
145 \r
146         // リンクサーバースレッドの作成\r
147         t = NewThread(LinkServerSessionThread, (void *)k);\r
148         WaitThreadInit(t);\r
149 \r
150         ReleaseThread(t);\r
151 \r
152         return true;\r
153 }\r
154 \r
155 // キャンセルオブジェクトの取得\r
156 CANCEL *LinkPaGetCancel(SESSION *s)\r
157 {\r
158         LINK *k;\r
159         // 引数チェック\r
160         if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)\r
161         {\r
162                 return NULL;\r
163         }\r
164 \r
165         return NULL;\r
166 }\r
167 \r
168 // 次のパケットを取得\r
169 UINT LinkPaGetNextPacket(SESSION *s, void **data)\r
170 {\r
171         LINK *k;\r
172         UINT ret = 0;\r
173         // 引数チェック\r
174         if (s == NULL || data == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)\r
175         {\r
176                 return INFINITE;\r
177         }\r
178 \r
179         // キューにパケットが溜まっているかどうか調べる\r
180         LockQueue(k->SendPacketQueue);\r
181         {\r
182                 BLOCK *block = GetNext(k->SendPacketQueue);\r
183 \r
184                 if (block != NULL)\r
185                 {\r
186                         // パケットがあった\r
187                         *data = block->Buf;\r
188                         ret = block->Size;\r
189                         // 構造体のメモリは破棄する\r
190                         Free(block);\r
191                 }\r
192         }\r
193         UnlockQueue(k->SendPacketQueue);\r
194 \r
195         return ret;\r
196 }\r
197 \r
198 // 受信したパケットを書き込み\r
199 bool LinkPaPutPacket(SESSION *s, void *data, UINT size)\r
200 {\r
201         LINK *k;\r
202         BLOCK *block;\r
203         SESSION *server_session;\r
204         CONNECTION *server_connection;\r
205         // 引数チェック\r
206         if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)\r
207         {\r
208                 return false;\r
209         }\r
210 \r
211         server_session = k->ServerSession;\r
212         server_connection = server_session->Connection;\r
213 \r
214         // ここにはリンク接続先の HUB から届いたパケットが来るので\r
215         // サーバーセッションの ReceivedBlocks に届けてあげる\r
216         if (data != NULL)\r
217         {\r
218                 block = NewBlock(data, size, 0);\r
219 \r
220                 LockQueue(server_connection->ReceivedBlocks);\r
221                 {\r
222                         InsertQueue(server_connection->ReceivedBlocks, block);\r
223                 }\r
224                 UnlockQueue(server_connection->ReceivedBlocks);\r
225         }\r
226         else\r
227         {\r
228                 // data == NULL のとき、すべてのパケットを格納し終わったので\r
229                 // Cancel を発行する\r
230                 Cancel(server_session->Cancel1);\r
231 \r
232                 if (k->Hub != NULL && k->Hub->Option != NULL && k->Hub->Option->YieldAfterStorePacket)\r
233                 {\r
234                         YieldCpu();\r
235                 }\r
236         }\r
237 \r
238         return true;\r
239 }\r
240 \r
241 // パケットアダプタの解放\r
242 void LinkPaFree(SESSION *s)\r
243 {\r
244         LINK *k;\r
245         // 引数チェック\r
246         if (s == NULL || (k = (LINK *)s->PacketAdapter->Param) == NULL)\r
247         {\r
248                 return;\r
249         }\r
250 \r
251         // サーバーセッションの停止\r
252         StopSession(k->ServerSession);\r
253         ReleaseSession(k->ServerSession);\r
254 \r
255         // 送信パケットキューの解放\r
256         LockQueue(k->SendPacketQueue);\r
257         {\r
258                 BLOCK *block;\r
259                 while (block = GetNext(k->SendPacketQueue))\r
260                 {\r
261                         FreeBlock(block);\r
262                 }\r
263         }\r
264         UnlockQueue(k->SendPacketQueue);\r
265 \r
266         ReleaseQueue(k->SendPacketQueue);\r
267 }\r
268 \r
269 // パケットアダプタ\r
270 PACKET_ADAPTER *LinkGetPacketAdapter()\r
271 {\r
272         return NewPacketAdapter(LinkPaInit, LinkPaGetCancel, LinkPaGetNextPacket,\r
273                 LinkPaPutPacket, LinkPaFree);\r
274 }\r
275 \r
276 // すべてのリンクの解放\r
277 void ReleaseAllLink(HUB *h)\r
278 {\r
279         LINK **kk;\r
280         UINT num, i;\r
281         // 引数チェック\r
282         if (h == NULL)\r
283         {\r
284                 return;\r
285         }\r
286 \r
287         LockList(h->LinkList);\r
288         {\r
289                 num = LIST_NUM(h->LinkList);\r
290                 kk = ToArray(h->LinkList);\r
291                 DeleteAll(h->LinkList);\r
292         }\r
293         UnlockList(h->LinkList);\r
294 \r
295         for (i = 0;i < num;i++)\r
296         {\r
297                 LINK *k = kk[i];\r
298 \r
299                 ReleaseLink(k);\r
300         }\r
301 \r
302         Free(kk);\r
303 }\r
304 \r
305 // リンクの解放\r
306 void ReleaseLink(LINK *k)\r
307 {\r
308         // 引数チェック\r
309         if (k == NULL)\r
310         {\r
311                 return;\r
312         }\r
313 \r
314         if (Release(k->ref) == 0)\r
315         {\r
316                 CleanupLink(k);\r
317         }\r
318 }\r
319 \r
320 // リンクのクリーンアップ\r
321 void CleanupLink(LINK *k)\r
322 {\r
323         // 引数チェック\r
324         if (k == NULL)\r
325         {\r
326                 return;\r
327         }\r
328 \r
329         DeleteLock(k->lock);\r
330         if (k->ClientSession)\r
331         {\r
332                 ReleaseSession(k->ClientSession);\r
333         }\r
334         Free(k->Option);\r
335         CiFreeClientAuth(k->Auth);\r
336         Free(k->Policy);\r
337 \r
338         if (k->ServerCert != NULL)\r
339         {\r
340                 FreeX(k->ServerCert);\r
341         }\r
342 \r
343         Free(k);\r
344 }\r
345 \r
346 // リンクをオンラインにする\r
347 void SetLinkOnline(LINK *k)\r
348 {\r
349         // 引数チェック\r
350         if (k == NULL)\r
351         {\r
352                 return;\r
353         }\r
354 \r
355         if (k->Offline == false)\r
356         {\r
357                 return;\r
358         }\r
359 \r
360         k->Offline = false;\r
361         StartLink(k);\r
362 }\r
363 \r
364 // リンクをオフラインにする\r
365 void SetLinkOffline(LINK *k)\r
366 {\r
367         // 引数チェック\r
368         if (k == NULL)\r
369         {\r
370                 return;\r
371         }\r
372 \r
373         if (k->Offline)\r
374         {\r
375                 return;\r
376         }\r
377 \r
378         StopLink(k);\r
379         k->Offline = true;\r
380 }\r
381 \r
382 // リンクの削除\r
383 void DelLink(HUB *hub, LINK *k)\r
384 {\r
385         // 引数チェック\r
386         if (hub == NULL || k == NULL)\r
387         {\r
388                 return;\r
389         }\r
390 \r
391         LockList(hub->LinkList);\r
392         {\r
393                 if (Delete(hub->LinkList, k))\r
394                 {\r
395                         ReleaseLink(k);\r
396                 }\r
397         }\r
398         UnlockList(hub->LinkList);\r
399 }\r
400 \r
401 // すべてのリンクの開始\r
402 void StartAllLink(HUB *h)\r
403 {\r
404         // 引数チェック\r
405         if (h == NULL)\r
406         {\r
407                 return;\r
408         }\r
409 \r
410         LockList(h->LinkList);\r
411         {\r
412                 UINT i;\r
413                 for (i = 0;i < LIST_NUM(h->LinkList);i++)\r
414                 {\r
415                         LINK *k = (LINK *)LIST_DATA(h->LinkList, i);\r
416 \r
417                         if (k->Offline == false)\r
418                         {\r
419                                 StartLink(k);\r
420                         }\r
421                 }\r
422         }\r
423         UnlockList(h->LinkList);\r
424 }\r
425 \r
426 // すべてのリンクの停止\r
427 void StopAllLink(HUB *h)\r
428 {\r
429         LINK **link_list;\r
430         UINT num_link;\r
431         UINT i;\r
432         // 引数チェック\r
433         if (h == NULL)\r
434         {\r
435                 return;\r
436         }\r
437 \r
438         LockList(h->LinkList);\r
439         {\r
440                 link_list = ToArray(h->LinkList);\r
441                 num_link = LIST_NUM(h->LinkList);\r
442                 for (i = 0;i < num_link;i++)\r
443                 {\r
444                         AddRef(link_list[i]->ref);\r
445                 }\r
446         }\r
447         UnlockList(h->LinkList);\r
448 \r
449         for (i = 0;i < num_link;i++)\r
450         {\r
451                 StopLink(link_list[i]);\r
452                 ReleaseLink(link_list[i]);\r
453         }\r
454 \r
455         Free(link_list);\r
456 }\r
457 \r
458 // リンクの開始\r
459 void StartLink(LINK *k)\r
460 {\r
461         PACKET_ADAPTER *pa;\r
462         // 引数チェック\r
463         if (k == NULL)\r
464         {\r
465                 return;\r
466         }\r
467 \r
468         LockLink(k);\r
469         {\r
470                 if (k->Started || k->Halting)\r
471                 {\r
472                         UnlockLink(k);\r
473                         return;\r
474                 }\r
475                 k->Started = true;\r
476         }\r
477         UnlockLink(k);\r
478 \r
479         // クライアントセッション接続\r
480         pa = LinkGetPacketAdapter();\r
481         pa->Param = (void *)k;\r
482         LockLink(k);\r
483         {\r
484                 k->ClientSession = NewClientSession(k->Cedar, k->Option, k->Auth, pa);\r
485         }\r
486         UnlockLink(k);\r
487 }\r
488 \r
489 // リンクの停止\r
490 void StopLink(LINK *k)\r
491 {\r
492         // 引数チェック\r
493         if (k == NULL)\r
494         {\r
495                 return;\r
496         }\r
497 \r
498         LockLink(k);\r
499         {\r
500                 if (k->Started == false)\r
501                 {\r
502                         UnlockLink(k);\r
503                         return;\r
504                 }\r
505                 k->Started = false;\r
506                 k->Halting = true;\r
507         }\r
508         UnlockLink(k);\r
509 \r
510         if (k->ClientSession != NULL)\r
511         {\r
512                 // クライアントセッション切断\r
513                 StopSession(k->ClientSession);\r
514 \r
515                 LockLink(k);\r
516                 {\r
517                         ReleaseSession(k->ClientSession);\r
518                         k->ClientSession = NULL;\r
519                 }\r
520                 UnlockLink(k);\r
521         }\r
522 \r
523         LockLink(k);\r
524         {\r
525                 k->Halting = false;\r
526         }\r
527         UnlockLink(k);\r
528 }\r
529 \r
530 // リンクのロック\r
531 void LockLink(LINK *k)\r
532 {\r
533         // 引数チェック\r
534         if (k == NULL)\r
535         {\r
536                 return;\r
537         }\r
538 \r
539         Lock(k->lock);\r
540 }\r
541 \r
542 // ロックのリンク解除\r
543 void UnlockLink(LINK *k)\r
544 {\r
545         // 引数チェック\r
546         if (k == NULL)\r
547         {\r
548                 return;\r
549         }\r
550 \r
551         Unlock(k->lock);\r
552 }\r
553 \r
554 // リンク用ポリシーの正規化\r
555 void NormalizeLinkPolicy(POLICY *p)\r
556 {\r
557         // 引数チェック\r
558         if (p == NULL)\r
559         {\r
560                 return;\r
561         }\r
562 \r
563         p->Access = true;\r
564         p->NoBridge = p->NoRouting = p->PrivacyFilter =\r
565                 p->MonitorPort = false;\r
566         p->MaxConnection = 32;\r
567         p->TimeOut = 20;\r
568         p->FixPassword = false;\r
569 }\r
570 \r
571 // リンクの作成\r
572 LINK *NewLink(CEDAR *cedar, HUB *hub, CLIENT_OPTION *option, CLIENT_AUTH *auth, POLICY *policy)\r
573 {\r
574         CLIENT_OPTION *o;\r
575         LINK *k;\r
576         CLIENT_AUTH *a;\r
577         // 引数チェック\r
578         if (cedar == NULL || hub == NULL || option == NULL || auth == NULL || policy == NULL)\r
579         {\r
580                 return NULL;\r
581         }\r
582         if (hub->Halt)\r
583         {\r
584                 return NULL;\r
585         }\r
586 \r
587         if (LIST_NUM(hub->LinkList) >= MAX_HUB_LINKS)\r
588         {\r
589                 return NULL;\r
590         }\r
591 \r
592         if (UniIsEmptyStr(option->AccountName))\r
593         {\r
594                 return NULL;\r
595         }\r
596 \r
597         // 認証方法の制限\r
598         if (auth->AuthType != CLIENT_AUTHTYPE_ANONYMOUS && auth->AuthType != CLIENT_AUTHTYPE_PASSWORD &&\r
599                 auth->AuthType != CLIENT_AUTHTYPE_PLAIN_PASSWORD && auth->AuthType != CLIENT_AUTHTYPE_CERT)\r
600         {\r
601                 // 匿名認証、パスワード認証、プレーンパスワード、証明書認証以外の認証方法は使用できない\r
602                 return NULL;\r
603         }\r
604 \r
605         // クライアントオプションのコピー (改変用)\r
606         o = ZeroMalloc(sizeof(CLIENT_OPTION));\r
607         Copy(o, option, sizeof(CLIENT_OPTION));\r
608         StrCpy(o->DeviceName, sizeof(o->DeviceName), LINK_DEVICE_NAME);\r
609 \r
610         o->RequireBridgeRoutingMode = true;     // ブリッジモードを要求する\r
611         o->RequireMonitorMode = false;  // モニタモードは要求しない\r
612 \r
613         o->NumRetry = INFINITE;                 // 接続の再試行は無限に行う\r
614         o->RetryInterval = 10;                  // 再試行間隔は 10 秒\r
615         o->NoRoutingTracking = true;    // ルーティング追跡停止\r
616 \r
617         // 認証データのコピー\r
618         a = CopyClientAuth(auth);\r
619         a->SecureSignProc = NULL;\r
620         a->CheckCertProc = NULL;\r
621 \r
622         // リンク オブジェクト\r
623         k = ZeroMalloc(sizeof(LINK));\r
624         k->lock = NewLock();\r
625         k->ref = NewRef();\r
626 \r
627         k->Cedar = cedar;\r
628         k->Option = o;\r
629         k->Auth = a;\r
630         k->Hub = hub;\r
631 \r
632         // ポリシーのコピー\r
633         k->Policy = ZeroMalloc(sizeof(POLICY));\r
634         Copy(k->Policy, policy, sizeof(POLICY));\r
635 \r
636         // ポリシーの正規化\r
637         NormalizeLinkPolicy(k->Policy);\r
638 \r
639         // HUB のリンクリストに登録する\r
640         LockList(hub->LinkList);\r
641         {\r
642                 Add(hub->LinkList, k);\r
643                 AddRef(k->ref);\r
644         }\r
645         UnlockList(hub->LinkList);\r
646 \r
647         return k;\r
648 }\r
649 \r