* tar xzf utvpn-src-unix-v101-7101-public-2010.06.27.tar.gz
[lab.git] / utvpn / utvpn-unix-v101-7101-public / src / Cedar / Account.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 // Account.c\r
79 // アカウントマネージャ\r
80 \r
81 #include "CedarPch.h"\r
82 \r
83 // ポリシー項目\r
84 POLICY_ITEM policy_item[] =\r
85 {\r
86 //  番号,   数値,   省略可能, 最小, 最大, デフォルト, 単位文字列\r
87 // Ver 2.0\r
88         {0,             false,  false,  0,      0,      0,              NULL},                  // Access\r
89         {1,             false,  false,  0,      0,      0,              NULL},                  // DHCPFilter\r
90         {2,             false,  false,  0,      0,      0,              NULL},                  // DHCPNoServer\r
91         {3,             false,  false,  0,      0,      0,              NULL},                  // DHCPForce\r
92         {4,             false,  false,  0,      0,      0,              NULL},                  // NoBridge\r
93         {5,             false,  false,  0,      0,      0,              NULL},                  // NoRouting\r
94         {6,             false,  false,  0,      0,      0,              NULL},                  // CheckMac\r
95         {7,             false,  false,  0,      0,      0,              NULL},                  // CheckIP\r
96         {8,             false,  false,  0,      0,      0,              NULL},                  // ArpDhcpOnly\r
97         {9,             false,  false,  0,      0,      0,              NULL},                  // PrivacyFilter\r
98         {10,    false,  false,  0,      0,      0,              NULL},                  // NoServer\r
99         {11,    false,  false,  0,      0,      0,              NULL},                  // NoBroadcastLimiter\r
100         {12,    false,  false,  0,      0,      0,              NULL},                  // MonitorPort\r
101         {13,    true,   false,  1,      32,     32,             "POL_INT_COUNT"},       // MaxConnection\r
102         {14,    true,   false,  5,      60,     20,             "POL_INT_SEC"}, // TimeOut\r
103         {15,    true,   true,   1,      65535,  0,      "POL_INT_COUNT"},       // MaxMac\r
104         {16,    true,   true,   1,      65535,  0,      "POL_INT_COUNT"},       // MaxIP\r
105         {17,    true,   true,   1,      4294967295UL,   0,      "POL_INT_BPS"}, // MaxUpload\r
106         {18,    true,   true,   1,      4294967295UL,   0,      "POL_INT_BPS"}, // MaxDownload\r
107         {19,    false,  false,  0,      0,      0,              NULL},                  // FixPassword\r
108         {20,    true,   true,   1,      65535,  0,      "POL_INT_COUNT"},       // MultiLogins\r
109         {21,    false,  false,  0,      0,      0,              NULL},                  // NoQoS\r
110 // Ver 3.0\r
111         {22,    false,  false,  0,      0,      0,              NULL},                  // RSandRAFilter\r
112         {23,    false,  false,  0,      0,      0,              NULL},                  // RAFilter\r
113         {24,    false,  false,  0,      0,      0,              NULL},                  // DHCPv6Filter\r
114         {25,    false,  false,  0,      0,      0,              NULL},                  // DHCPv6NoServer\r
115         {26,    false,  false,  0,      0,      0,              NULL},                  // NoRoutingV6\r
116         {27,    false,  false,  0,      0,      0,              NULL},                  // CheckIPv6\r
117         {28,    false,  false,  0,      0,      0,              NULL},                  // NoServerV6\r
118         {29,    true,   true,   1,      65535,  0,      "POL_INT_COUNT"},       // MaxIPv6\r
119         {30,    false,  false,  0,      0,      0,              NULL},                  // NoSavePassword\r
120         {31,    true,   true,   1,      4294967295UL,   0,      "POL_INT_SEC"}, // AutoDisconnect\r
121         {32,    false,  false,  0,      0,      0,              NULL},                  // FilterIPv4\r
122         {33,    false,  false,  0,      0,      0,              NULL},                  // FilterIPv6\r
123         {34,    false,  false,  0,      0,      0,              NULL},                  // FilterNonIP\r
124         {35,    false,  false,  0,      0,      0,              NULL},                  // NoIPv6DefaultRouterInRA\r
125         {36,    false,  false,  0,      0,      0,              NULL},                  // NoIPv6DefaultRouterInRAWhenIPv6\r
126         {37,    true,   true,   1,      4095,   0,      "POL_INT_VLAN"},        // VLanId\r
127 };\r
128 \r
129 // ポリシー名を正規化する\r
130 char *NormalizePolicyName(char *name)\r
131 {\r
132         // 引数チェック\r
133         if (name == NULL)\r
134         {\r
135                 return NULL;\r
136         }\r
137 \r
138         return PolicyIdToStr(PolicyStrToId(name));\r
139 }\r
140 \r
141 // ポリシーの値をフォーマット\r
142 void FormatPolicyValue(wchar_t *str, UINT size, UINT id, UINT value)\r
143 {\r
144         POLICY_ITEM *p;\r
145         // 引数チェック\r
146         if (str == NULL)\r
147         {\r
148                 return;\r
149         }\r
150 \r
151         p = GetPolicyItem(id);\r
152 \r
153         if (p->TypeInt == false)\r
154         {\r
155                 // bool 型\r
156                 if (value == 0)\r
157                 {\r
158                         UniStrCpy(str, size, L"No");\r
159                 }\r
160                 else\r
161                 {\r
162                         UniStrCpy(str, size, L"Yes");\r
163                 }\r
164         }\r
165         else\r
166         {\r
167                 // int 型\r
168                 if (value == 0 && p->AllowZero)\r
169                 {\r
170                         UniStrCpy(str, size, _UU("CMD_NO_SETTINGS"));\r
171                 }\r
172                 else\r
173                 {\r
174                         UniFormat(str, size, _UU(p->FormatStr), value);\r
175                 }\r
176         }\r
177 }\r
178 \r
179 // ポリシーとして設定可能な値の範囲を説明する文字列を取得\r
180 void GetPolicyValueRangeStr(wchar_t *str, UINT size, UINT id)\r
181 {\r
182         POLICY_ITEM *p;\r
183         // 引数チェック\r
184         if (str == NULL)\r
185         {\r
186                 return;\r
187         }\r
188 \r
189         p = GetPolicyItem(id);\r
190 \r
191         if (p->TypeInt == false)\r
192         {\r
193                 // bool 型\r
194                 UniStrCpy(str, size, _UU("CMD_PolicyList_Range_Bool"));\r
195         }\r
196         else\r
197         {\r
198                 wchar_t *tag;\r
199                 wchar_t tmp1[256], tmp2[256];\r
200 \r
201                 // int 型\r
202                 if (p->AllowZero)\r
203                 {\r
204                         tag = _UU("CMD_PolicyList_Range_Int_2");\r
205                 }\r
206                 else\r
207                 {\r
208                         tag = _UU("CMD_PolicyList_Range_Int_1");\r
209                 }\r
210 \r
211                 UniFormat(tmp1, sizeof(tmp1), _UU(p->FormatStr), p->MinValue);\r
212                 UniFormat(tmp2, sizeof(tmp2), _UU(p->FormatStr), p->MaxValue);\r
213 \r
214                 UniFormat(str, size, tag, tmp1, tmp2);\r
215         }\r
216 }\r
217 \r
218 // ポリシーアイテムの取得\r
219 POLICY_ITEM *GetPolicyItem(UINT id)\r
220 {\r
221         return &policy_item[id];\r
222 }\r
223 \r
224 // 指定されたポリシーがカスケード接続でサポートされているかどうか\r
225 bool PolicyIsSupportedForCascade(UINT i)\r
226 {\r
227         // このあたりは急いで実装したのでコードがあまり美しくない。\r
228         if (i == 0 || i == 4 || i == 5 || i == 9 || i == 12 || i == 13 ||\r
229                 i == 14 || i == 19 || i == 20 || i == 21 || i == 26 || i == 30 || i == 31 || i == 36)\r
230         {\r
231                 // これらの項目はカスケード接続でサポートされていない\r
232                 return false;\r
233         }\r
234 \r
235         return true;\r
236 }\r
237 \r
238 // ID をポリシーの名前に変換\r
239 char *PolicyIdToStr(UINT i)\r
240 {\r
241         // このあたりは急いで実装したのでコードがあまり美しくない。\r
242         switch (i)\r
243         {\r
244         // Ver 2.0\r
245         case 0:         return "Access";\r
246         case 1:         return "DHCPFilter";\r
247         case 2:         return "DHCPNoServer";\r
248         case 3:         return "DHCPForce";\r
249         case 4:         return "NoBridge";\r
250         case 5:         return "NoRouting";\r
251         case 6:         return "CheckMac";\r
252         case 7:         return "CheckIP";\r
253         case 8:         return "ArpDhcpOnly";\r
254         case 9:         return "PrivacyFilter";\r
255         case 10:        return "NoServer";\r
256         case 11:        return "NoBroadcastLimiter";\r
257         case 12:        return "MonitorPort";\r
258         case 13:        return "MaxConnection";\r
259         case 14:        return "TimeOut";\r
260         case 15:        return "MaxMac";\r
261         case 16:        return "MaxIP";\r
262         case 17:        return "MaxUpload";\r
263         case 18:        return "MaxDownload";\r
264         case 19:        return "FixPassword";\r
265         case 20:        return "MultiLogins";\r
266         case 21:        return "NoQoS";\r
267 \r
268         // Ver 3.0\r
269         case 22:        return "RSandRAFilter";\r
270         case 23:        return "RAFilter";\r
271         case 24:        return "DHCPv6Filter";\r
272         case 25:        return "DHCPv6NoServer";\r
273         case 26:        return "NoRoutingV6";\r
274         case 27:        return "CheckIPv6";\r
275         case 28:        return "NoServerV6";\r
276         case 29:        return "MaxIPv6";\r
277         case 30:        return "NoSavePassword";\r
278         case 31:        return "AutoDisconnect";\r
279         case 32:        return "FilterIPv4";\r
280         case 33:        return "FilterIPv6";\r
281         case 34:        return "FilterNonIP";\r
282         case 35:        return "NoIPv6DefaultRouterInRA";\r
283         case 36:        return "NoIPv6DefaultRouterInRAWhenIPv6";\r
284         case 37:        return "VLanId";\r
285         }\r
286 \r
287         return NULL;\r
288 }\r
289 \r
290 // ポリシーの名前を ID に変換\r
291 UINT PolicyStrToId(char *name)\r
292 {\r
293         UINT i;\r
294         // 引数チェック\r
295         if (name == NULL)\r
296         {\r
297                 return INFINITE;\r
298         }\r
299 \r
300         for (i = 0;i < NUM_POLICY_ITEM;i++)\r
301         {\r
302                 if (StartWith(PolicyIdToStr(i), name))\r
303                 {\r
304                         return i;\r
305                 }\r
306         }\r
307 \r
308         return INFINITE;\r
309 }\r
310 \r
311 // ポリシーの総数を取得\r
312 UINT PolicyNum()\r
313 {\r
314         return NUM_POLICY_ITEM;\r
315 }\r
316 \r
317 // 指定した名前をアカウント名として使用できるかどうか確認する\r
318 bool IsUserName(char *name)\r
319 {\r
320         // このあたりは急いで実装したのでコードがあまり美しくない。\r
321         char tmp[MAX_SIZE];\r
322         // 引数チェック\r
323         if (name == NULL)\r
324         {\r
325                 return false;\r
326         }\r
327 \r
328         StrCpy(tmp, sizeof(tmp), name);\r
329         name = tmp;\r
330 \r
331         Trim(name);\r
332 \r
333         if (StrLen(name) == 0)\r
334         {\r
335                 return false;\r
336         }\r
337 \r
338         if (StrCmpi(name, "*") == 0)\r
339         {\r
340                 return true;\r
341         }\r
342 \r
343         if (IsSafeStr(name) == false)\r
344         {\r
345                 return false;\r
346         }\r
347 \r
348         if (StrCmpi(name, LINK_USER_NAME) == 0)\r
349         {\r
350                 return false;\r
351         }\r
352 \r
353         if (StartWith(name, L3_USERNAME))\r
354         {\r
355                 return false;\r
356         }\r
357 \r
358         if (StrCmpi(name, LINK_USER_NAME_PRINT) == 0)\r
359         {\r
360                 return false;\r
361         }\r
362 \r
363         if (StrCmpi(name, SNAT_USER_NAME) == 0)\r
364         {\r
365                 return false;\r
366         }\r
367 \r
368         if (StrCmpi(name, SNAT_USER_NAME_PRINT) == 0)\r
369         {\r
370                 return false;\r
371         }\r
372 \r
373         if (StrCmpi(name, BRIDGE_USER_NAME) == 0)\r
374         {\r
375                 return false;\r
376         }\r
377 \r
378         if (StrCmpi(name, BRIDGE_USER_NAME_PRINT) == 0)\r
379         {\r
380                 return false;\r
381         }\r
382 \r
383         if (StrCmpi(name, ADMINISTRATOR_USERNAME) == 0)\r
384         {\r
385                 return false;\r
386         }\r
387 \r
388         return true;\r
389 }\r
390 \r
391 // ポリシーのタイトルを取得する\r
392 wchar_t *GetPolicyTitle(UINT id)\r
393 {\r
394         char tmp[MAX_SIZE];\r
395         Format(tmp, sizeof(tmp), "POL_%u", id);\r
396 \r
397         return _UU(tmp);\r
398 }\r
399 \r
400 // ポリシーの説明を取得する\r
401 wchar_t *GetPolicyDescription(UINT id)\r
402 {\r
403         char tmp[MAX_SIZE];\r
404         Format(tmp, sizeof(tmp), "POL_EX_%u", id);\r
405 \r
406         return _UU(tmp);\r
407 }\r
408 \r
409 // ポリシーデータのクローン\r
410 POLICY *ClonePolicy(POLICY *policy)\r
411 {\r
412         POLICY *ret;\r
413         // 引数チェック\r
414         if (policy == NULL)\r
415         {\r
416                 return NULL;\r
417         }\r
418 \r
419         ret = ZeroMalloc(sizeof(POLICY));\r
420         Copy(ret, policy, sizeof(POLICY));\r
421 \r
422         return ret;\r
423 }\r
424 \r
425 // ポリシーを上書きする (古いバージョンを上書きする場合は新しいバージョンのデータは残す)\r
426 void OverwritePolicy(POLICY **target, POLICY *p)\r
427 {\r
428         // 引数チェック\r
429         if (target == NULL)\r
430         {\r
431                 return;\r
432         }\r
433 \r
434         if (p == NULL)\r
435         {\r
436                 // ポリシー消去\r
437                 if (*target != NULL)\r
438                 {\r
439                         Free(*target);\r
440                         *target = NULL;\r
441                 }\r
442         }\r
443         else\r
444         {\r
445                 if (p->Ver3)\r
446                 {\r
447                         // Ver 3\r
448                         if (*target != NULL)\r
449                         {\r
450                                 Free(*target);\r
451                                 *target = NULL;\r
452                         }\r
453 \r
454                         *target = ClonePolicy(p);\r
455                 }\r
456                 else\r
457                 {\r
458                         // Ver 2\r
459                         if (*target == NULL)\r
460                         {\r
461                                 *target = ClonePolicy(p);\r
462                         }\r
463                         else\r
464                         {\r
465                                 Copy(*target, p, NUM_POLICY_ITEM_FOR_VER2 * sizeof(UINT));\r
466                         }\r
467                 }\r
468         }\r
469 }\r
470 \r
471 // ユーザーポリシーの設定\r
472 void SetUserPolicy(USER *u, POLICY *policy)\r
473 {\r
474         // 引数チェック\r
475         if (u == NULL)\r
476         {\r
477                 return;\r
478         }\r
479 \r
480         Lock(u->lock);\r
481         {\r
482                 OverwritePolicy(&u->Policy, policy);\r
483         }\r
484         Unlock(u->lock);\r
485 }\r
486 \r
487 // ユーザーポリシーの取得\r
488 POLICY *GetUserPolicy(USER *u)\r
489 {\r
490         POLICY *ret;\r
491         // 引数チェック\r
492         if (u == NULL)\r
493         {\r
494                 return NULL;\r
495         }\r
496 \r
497         Lock(u->lock);\r
498         {\r
499                 if (u->Policy == NULL)\r
500                 {\r
501                         ret = NULL;\r
502                 }\r
503                 else\r
504                 {\r
505                         ret = ClonePolicy(u->Policy);\r
506                 }\r
507         }\r
508         Unlock(u->lock);\r
509 \r
510         return ret;\r
511 }\r
512 \r
513 // グループポリシーの設定\r
514 void SetGroupPolicy(USERGROUP *g, POLICY *policy)\r
515 {\r
516         // 引数チェック\r
517         if (g == NULL)\r
518         {\r
519                 return;\r
520         }\r
521 \r
522         Lock(g->lock);\r
523         {\r
524                 OverwritePolicy(&g->Policy, policy);\r
525         }\r
526         Unlock(g->lock);\r
527 }\r
528 \r
529 // グループポリシーの取得\r
530 POLICY *GetGroupPolicy(USERGROUP *g)\r
531 {\r
532         POLICY *ret;\r
533         // 引数チェック\r
534         if (g == NULL)\r
535         {\r
536                 return NULL;\r
537         }\r
538 \r
539         Lock(g->lock);\r
540         {\r
541                 if (g->Policy == NULL)\r
542                 {\r
543                         ret = NULL;\r
544                 }\r
545                 else\r
546                 {\r
547                         ret = ClonePolicy(g->Policy);\r
548                 }\r
549         }\r
550         Unlock(g->lock);\r
551 \r
552         return ret;\r
553 }\r
554 \r
555 // デフォルトのポリシーを返す\r
556 POLICY *GetDefaultPolicy()\r
557 {\r
558         // このあたりは急いで実装したのでコードがあまり美しくない。\r
559         static POLICY def_policy =\r
560         {\r
561                 true,\r
562                 false,\r
563                 false,\r
564                 false,\r
565                 false,\r
566                 false,\r
567                 false,\r
568                 false,\r
569                 false,\r
570                 false,\r
571                 false,\r
572                 false,\r
573                 false,\r
574                 32,\r
575                 20,\r
576                 0,\r
577                 0,\r
578                 0,\r
579                 0,\r
580                 false,\r
581                 0,\r
582                 false,\r
583                 false,\r
584                 false,\r
585                 false,\r
586                 false,\r
587                 false,\r
588                 false,\r
589                 false,\r
590                 0,\r
591                 false,\r
592                 0,\r
593                 false,\r
594                 false,\r
595                 false,\r
596                 false,\r
597                 false,\r
598         };\r
599 \r
600         return &def_policy;\r
601 }\r
602 \r
603 // NT 認証データの作成\r
604 void *NewNTAuthData(wchar_t *username)\r
605 {\r
606         AUTHNT *a;\r
607         // 引数チェック\r
608         a = ZeroMallocEx(sizeof(AUTHNT), true);\r
609         a->NtUsername = CopyUniStr(username);\r
610 \r
611         return a;\r
612 }\r
613 \r
614 // Radius 認証データの作成\r
615 void *NewRadiusAuthData(wchar_t *username)\r
616 {\r
617         AUTHRADIUS *a;\r
618         // 引数チェック\r
619         a = ZeroMallocEx(sizeof(AUTHRADIUS), true);\r
620         a->RadiusUsername = CopyUniStr(username);\r
621 \r
622         return a;\r
623 }\r
624 \r
625 // ルート証明書による認証データの作成\r
626 void *NewRootCertAuthData(X_SERIAL *serial, wchar_t *common_name)\r
627 {\r
628         AUTHROOTCERT *a;\r
629 \r
630         a = ZeroMallocEx(sizeof(AUTHROOTCERT), true);\r
631         if (common_name != NULL && UniIsEmptyStr(common_name) == false)\r
632         {\r
633                 a->CommonName = CopyUniStr(common_name);\r
634         }\r
635         if (serial != NULL && serial->size >= 1)\r
636         {\r
637                 a->Serial = CloneXSerial(serial);\r
638         }\r
639 \r
640         return a;\r
641 }\r
642 \r
643 // ユーザー証明書認証データの作成\r
644 void *NewUserCertAuthData(X *x)\r
645 {\r
646         AUTHUSERCERT *a;\r
647 \r
648         a = ZeroMalloc(sizeof(AUTHUSERCERT));\r
649         a->UserX = CloneX(x);\r
650 \r
651         return a;\r
652 }\r
653 \r
654 // パスワードのハッシュ\r
655 void HashPassword(void *dst, char *username, char *password)\r
656 {\r
657         BUF *b;\r
658         char *username_upper;\r
659         // 引数チェック\r
660         if (dst == NULL || username == NULL || password == NULL)\r
661         {\r
662                 return;\r
663         }\r
664 \r
665         b = NewBuf();\r
666         username_upper = CopyStr(username);\r
667         StrUpper(username_upper);\r
668         WriteBuf(b, password, StrLen(password));\r
669         WriteBuf(b, username_upper, StrLen(username_upper));\r
670         Hash(dst, b->Buf, b->Size, true);\r
671 \r
672         FreeBuf(b);\r
673         Free(username_upper);\r
674 }\r
675 \r
676 // パスワード認証データの作成\r
677 void *NewPasswordAuthData(char *username, char *password)\r
678 {\r
679         AUTHPASSWORD *pw;\r
680         // 引数チェック\r
681         if (username == NULL || password == NULL)\r
682         {\r
683                 return NULL;\r
684         }\r
685 \r
686         pw = ZeroMalloc(sizeof(AUTHPASSWORD));\r
687         HashPassword(pw->HashedKey, username, password);\r
688 \r
689         return pw;\r
690 }\r
691 void *NewPasswordAuthDataRaw(UCHAR *hashed_password)\r
692 {\r
693         AUTHPASSWORD *pw;\r
694         // 引数チェック\r
695         if (hashed_password == NULL)\r
696         {\r
697                 return NULL;\r
698         }\r
699 \r
700         pw = ZeroMalloc(sizeof(AUTHPASSWORD));\r
701         Copy(pw->HashedKey, hashed_password, SHA1_SIZE);\r
702 \r
703         return pw;\r
704 }\r
705 \r
706 // ユーザーの認証データのコピー\r
707 void *CopyAuthData(void *authdata, UINT authtype)\r
708 {\r
709         AUTHPASSWORD *pw = (AUTHPASSWORD *)authdata;\r
710         AUTHUSERCERT *usercert = (AUTHUSERCERT *)authdata;\r
711         AUTHROOTCERT *rootcert = (AUTHROOTCERT *)authdata;\r
712         AUTHRADIUS *radius = (AUTHRADIUS *)authdata;\r
713         AUTHNT *nt = (AUTHNT *)authdata;\r
714         // 引数チェック\r
715         if (authdata == NULL || authtype == AUTHTYPE_ANONYMOUS)\r
716         {\r
717                 return NULL;\r
718         }\r
719 \r
720         switch (authtype)\r
721         {\r
722         case AUTHTYPE_PASSWORD:\r
723                 {\r
724                         AUTHPASSWORD *ret = ZeroMalloc(sizeof(AUTHPASSWORD));\r
725                         Copy(ret, pw, sizeof(AUTHPASSWORD));\r
726                         return ret;\r
727                 }\r
728                 break;\r
729 \r
730         case AUTHTYPE_USERCERT:\r
731                 {\r
732                         AUTHUSERCERT *ret = ZeroMalloc(sizeof(AUTHUSERCERT));\r
733                         ret->UserX = CloneX(usercert->UserX);\r
734                         return ret;\r
735                 }\r
736                 break;\r
737 \r
738         case AUTHTYPE_ROOTCERT:\r
739                 {\r
740                         AUTHROOTCERT *ret = ZeroMalloc(sizeof(AUTHROOTCERT));\r
741                         ret->CommonName = CopyUniStr(rootcert->CommonName);\r
742                         ret->Serial = CloneXSerial(rootcert->Serial);\r
743                         return ret;\r
744                 }\r
745                 break;\r
746 \r
747         case AUTHTYPE_RADIUS:\r
748                 {\r
749                         AUTHRADIUS *ret = ZeroMalloc(sizeof(AUTHRADIUS));\r
750                         ret->RadiusUsername = UniCopyStr(radius->RadiusUsername);\r
751                         return ret;\r
752                 }\r
753                 break;\r
754 \r
755         case AUTHTYPE_NT:\r
756                 {\r
757                         AUTHNT *ret = ZeroMalloc(sizeof(AUTHNT));\r
758                         ret->NtUsername = UniCopyStr(nt->NtUsername);\r
759                         return ret;\r
760                 }\r
761                 break;\r
762         }\r
763 \r
764         return NULL;\r
765 }\r
766 \r
767 // ユーザーの認証データのセット\r
768 void SetUserAuthData(USER *u, UINT authtype, void *authdata)\r
769 {\r
770         // 引数チェック\r
771         if (u == NULL)\r
772         {\r
773                 return;\r
774         }\r
775         if (authtype != AUTHTYPE_ANONYMOUS && authdata == NULL)\r
776         {\r
777                 return;\r
778         }\r
779 \r
780         Lock(u->lock);\r
781         {\r
782                 if (u->AuthType != AUTHTYPE_ANONYMOUS)\r
783                 {\r
784                         // 現在の認証データの解放\r
785                         FreeAuthData(u->AuthType, u->AuthData);\r
786                 }\r
787                 // 新しい認証データの設定\r
788                 u->AuthType = authtype;\r
789                 u->AuthData = authdata;\r
790         }\r
791         Unlock(u->lock);\r
792 }\r
793 \r
794 // グループのトラフィックデータを加算\r
795 void AddGroupTraffic(USERGROUP *g, TRAFFIC *diff)\r
796 {\r
797         // 引数チェック\r
798         if (g == NULL || diff == NULL)\r
799         {\r
800                 return;\r
801         }\r
802 \r
803         Lock(g->lock);\r
804         {\r
805                 AddTraffic(g->Traffic, diff);\r
806         }\r
807         Unlock(g->lock);\r
808 }\r
809 \r
810 // ユーザーのトラフィックデータを加算\r
811 void AddUserTraffic(USER *u, TRAFFIC *diff)\r
812 {\r
813         // 引数チェック\r
814         if (u == NULL || diff == NULL)\r
815         {\r
816                 return;\r
817         }\r
818 \r
819         Lock(u->lock);\r
820         {\r
821                 AddTraffic(u->Traffic, diff);\r
822         }\r
823         Unlock(u->lock);\r
824 }\r
825 \r
826 // グループのトラフィック情報をセット\r
827 void SetGroupTraffic(USERGROUP *g, TRAFFIC *t)\r
828 {\r
829         // 引数チェック\r
830         if (g == NULL)\r
831         {\r
832                 return;\r
833         }\r
834 \r
835         Lock(g->lock);\r
836         {\r
837                 if (t != NULL)\r
838                 {\r
839                         Copy(g->Traffic, t, sizeof(TRAFFIC));\r
840                 }\r
841                 else\r
842                 {\r
843                         Zero(g->Traffic, sizeof(TRAFFIC));\r
844                 }\r
845         }\r
846         Unlock(g->lock);\r
847 }\r
848 \r
849 // ユーザーのトラフィック情報をセット\r
850 void SetUserTraffic(USER *u, TRAFFIC *t)\r
851 {\r
852         // 引数チェック\r
853         if (u == NULL)\r
854         {\r
855                 return;\r
856         }\r
857 \r
858         Lock(u->lock);\r
859         {\r
860                 if (t != NULL)\r
861                 {\r
862                         Copy(u->Traffic, t, sizeof(TRAFFIC));\r
863                 }\r
864                 else\r
865                 {\r
866                         Zero(u->Traffic, sizeof(TRAFFIC));\r
867                 }\r
868         }\r
869         Unlock(u->lock);\r
870 }\r
871 \r
872 // ユーザーをグループに所属させる\r
873 void JoinUserToGroup(USER *u, USERGROUP *g)\r
874 {\r
875         // 引数チェック\r
876         if (u == NULL)\r
877         {\r
878                 return;\r
879         }\r
880 \r
881         if (g != NULL)\r
882         {\r
883                 // 参加\r
884                 Lock(u->lock);\r
885                 {\r
886                         Lock(g->lock);\r
887                         {\r
888                                 if (u->Group != NULL)\r
889                                 {\r
890                                         // まずユーザーをグループから外す\r
891                                         ReleaseGroup(u->Group);\r
892                                         u->Group = NULL;\r
893                                         Free(u->GroupName);\r
894                                         u->GroupName = NULL;\r
895                                 }\r
896                                 // ユーザーをグループに追加する\r
897                                 u->GroupName = CopyStr(g->Name);\r
898                                 u->Group = g;\r
899                                 AddRef(g->ref);\r
900                         }\r
901                         Unlock(g->lock);\r
902                 }\r
903                 Unlock(u->lock);\r
904         }\r
905         else\r
906         {\r
907                 // 脱退\r
908                 Lock(u->lock);\r
909                 {\r
910                         if (u->Group != NULL)\r
911                         {\r
912                                 // ユーザーをグループから外す\r
913                                 ReleaseGroup(u->Group);\r
914                                 u->Group = NULL;\r
915                                 Free(u->GroupName);\r
916                                 u->GroupName = NULL;\r
917                         }\r
918                 }\r
919                 Unlock(u->lock);\r
920         }\r
921 }\r
922 \r
923 // グループ名チェック\r
924 bool AcIsGroup(HUB *h, char *name)\r
925 {\r
926         USERGROUP *g;\r
927         // 引数チェック\r
928         if (h == NULL || name == NULL || NO_ACCOUNT_DB(h))\r
929         {\r
930                 return false;\r
931         }\r
932 \r
933         g = AcGetGroup(h, name);\r
934         if (g == NULL)\r
935         {\r
936                 return false;\r
937         }\r
938         ReleaseGroup(g);\r
939 \r
940         return true;\r
941 }\r
942 \r
943 // ユーザー名チェック\r
944 bool AcIsUser(HUB *h, char *name)\r
945 {\r
946         USER *u;\r
947         // 引数チェック\r
948         if (h == NULL || name == NULL || NO_ACCOUNT_DB(h))\r
949         {\r
950                 return false;\r
951         }\r
952 \r
953         u = AcGetUser(h, name);\r
954         if (u == NULL)\r
955         {\r
956                 return false;\r
957         }\r
958         ReleaseUser(u);\r
959 \r
960         return true;\r
961 }\r
962 \r
963 // グループの取得\r
964 USERGROUP *AcGetGroup(HUB *h, char *name)\r
965 {\r
966         USERGROUP *g, t;\r
967         // 引数チェック\r
968         if (h == NULL || name == NULL || NO_ACCOUNT_DB(h))\r
969         {\r
970                 return NULL;\r
971         }\r
972 \r
973         t.Name = name;\r
974         g = Search(h->HubDb->GroupList, &t);\r
975         if (g == NULL)\r
976         {\r
977                 return NULL;\r
978         }\r
979         AddRef(g->ref);\r
980 \r
981         return g;\r
982 }\r
983 \r
984 // ユーザーの取得\r
985 USER *AcGetUser(HUB *h, char *name)\r
986 {\r
987         USER *u, t;\r
988         // 引数チェック\r
989         if (h == NULL || name == NULL || NO_ACCOUNT_DB(h))\r
990         {\r
991                 return NULL;\r
992         }\r
993 \r
994         t.Name = name;\r
995         u = Search(h->HubDb->UserList, &t);\r
996         if (u == NULL)\r
997         {\r
998                 return NULL;\r
999         }\r
1000         AddRef(u->ref);\r
1001 \r
1002         return u;\r
1003 }\r
1004 \r
1005 // ユーザーの削除\r
1006 bool AcDeleteUser(HUB *h, char *name)\r
1007 {\r
1008         USER *u;\r
1009         // 引数チェック\r
1010         if (h == NULL || name == NULL)\r
1011         {\r
1012                 return false;\r
1013         }\r
1014 \r
1015         u = AcGetUser(h, name);\r
1016         if (u == NULL)\r
1017         {\r
1018                 return false;\r
1019         }\r
1020 \r
1021         if (Delete(h->HubDb->UserList, u))\r
1022         {\r
1023                 ReleaseUser(u);\r
1024         }\r
1025 \r
1026         ReleaseUser(u);\r
1027 \r
1028         return true;\r
1029 }\r
1030 \r
1031 // グループの削除\r
1032 bool AcDeleteGroup(HUB *h, char *name)\r
1033 {\r
1034         USERGROUP *g;\r
1035         UINT i;\r
1036         // 引数チェック\r
1037         if (h == NULL || name == NULL)\r
1038         {\r
1039                 return false;\r
1040         }\r
1041 \r
1042         g = AcGetGroup(h, name);\r
1043         if (g == NULL)\r
1044         {\r
1045                 return false;\r
1046         }\r
1047 \r
1048         if (Delete(h->HubDb->GroupList, g))\r
1049         {\r
1050                 ReleaseGroup(g);\r
1051         }\r
1052 \r
1053         for (i = 0;i < LIST_NUM(h->HubDb->UserList);i++)\r
1054         {\r
1055                 USER *u = LIST_DATA(h->HubDb->UserList, i);\r
1056                 Lock(u->lock);\r
1057                 {\r
1058                         if (u->Group == g)\r
1059                         {\r
1060                                 JoinUserToGroup(u, NULL);\r
1061                         }\r
1062                 }\r
1063                 Unlock(u->lock);\r
1064         }\r
1065 \r
1066         ReleaseGroup(g);\r
1067 \r
1068         return true;\r
1069 }\r
1070 \r
1071 // グループの追加\r
1072 bool AcAddGroup(HUB *h, USERGROUP *g)\r
1073 {\r
1074         // 引数チェック\r
1075         if (h == NULL || g == NULL || NO_ACCOUNT_DB(h))\r
1076         {\r
1077                 return false;\r
1078         }\r
1079 \r
1080         if (LIST_NUM(h->HubDb->GroupList) >= MAX_GROUPS)\r
1081         {\r
1082                 return false;\r
1083         }\r
1084 \r
1085         if (AcIsGroup(h, g->Name) != false)\r
1086         {\r
1087                 return false;\r
1088         }\r
1089 \r
1090         Insert(h->HubDb->GroupList, g);\r
1091         AddRef(g->ref);\r
1092 \r
1093         return true;\r
1094 }\r
1095 \r
1096 // ユーザーの追加\r
1097 bool AcAddUser(HUB *h, USER *u)\r
1098 {\r
1099         // 引数チェック\r
1100         if (h == NULL || u == NULL || NO_ACCOUNT_DB(h))\r
1101         {\r
1102                 return false;\r
1103         }\r
1104 \r
1105         if (LIST_NUM(h->HubDb->UserList) >= MAX_USERS)\r
1106         {\r
1107                 return false;\r
1108         }\r
1109 \r
1110         if (AcIsUser(h, u->Name) != false)\r
1111         {\r
1112                 return false;\r
1113         }\r
1114 \r
1115         Insert(h->HubDb->UserList, u);\r
1116         AddRef(u->ref);\r
1117 \r
1118         return true;\r
1119 }\r
1120 \r
1121 // ユーザーの解放\r
1122 void ReleaseUser(USER *u)\r
1123 {\r
1124         // 引数チェック\r
1125         if (u == NULL)\r
1126         {\r
1127                 return;\r
1128         }\r
1129 \r
1130         if (Release(u->ref) == 0)\r
1131         {\r
1132                 CleanupUser(u);\r
1133         }\r
1134 }\r
1135 \r
1136 // ユーザーのクリーンアップ\r
1137 void CleanupUser(USER *u)\r
1138 {\r
1139         // 引数チェック\r
1140         if (u == NULL)\r
1141         {\r
1142                 return;\r
1143         }\r
1144 \r
1145         DeleteLock(u->lock);\r
1146         Free(u->Name);\r
1147         Free(u->RealName);\r
1148         Free(u->Note);\r
1149         Free(u->GroupName);\r
1150         if (u->Group != NULL)\r
1151         {\r
1152                 ReleaseGroup(u->Group);\r
1153         }\r
1154 \r
1155         // 認証データの解放\r
1156         FreeAuthData(u->AuthType, u->AuthData);\r
1157 \r
1158         if (u->Policy)\r
1159         {\r
1160                 // ポリシー解放\r
1161                 Free(u->Policy);\r
1162         }\r
1163 \r
1164         FreeTraffic(u->Traffic);\r
1165 \r
1166         Free(u);\r
1167 }\r
1168 \r
1169 // 認証データの解放\r
1170 void FreeAuthData(UINT authtype, void *authdata)\r
1171 {\r
1172         AUTHPASSWORD *pw = (AUTHPASSWORD *)authdata;\r
1173         AUTHUSERCERT *uc = (AUTHUSERCERT *)authdata;\r
1174         AUTHROOTCERT *rc = (AUTHROOTCERT *)authdata;\r
1175         AUTHRADIUS *rd = (AUTHRADIUS *)authdata;\r
1176         AUTHNT *nt = (AUTHNT *)authdata;\r
1177         // 引数チェック\r
1178         if (authtype == AUTHTYPE_ANONYMOUS || authdata == NULL)\r
1179         {\r
1180                 return;\r
1181         }\r
1182 \r
1183         switch (authtype)\r
1184         {\r
1185         case AUTHTYPE_PASSWORD:\r
1186                 // パスワード認証\r
1187                 // 何も解放しない\r
1188                 break;\r
1189 \r
1190         case AUTHTYPE_USERCERT:\r
1191                 // ユーザー証明書\r
1192                 FreeX(uc->UserX);\r
1193                 break;\r
1194 \r
1195         case AUTHTYPE_ROOTCERT:\r
1196                 // ルート証明書\r
1197                 if (rc->Serial != NULL)\r
1198                 {\r
1199                         FreeXSerial(rc->Serial);\r
1200                 }\r
1201                 if (rc->CommonName != NULL)\r
1202                 {\r
1203                         Free(rc->CommonName);\r
1204                 }\r
1205                 break;\r
1206 \r
1207         case AUTHTYPE_RADIUS:\r
1208                 // Radius 認証\r
1209                 Free(rd->RadiusUsername);\r
1210                 break;\r
1211 \r
1212         case AUTHTYPE_NT:\r
1213                 // Windows NT 認証\r
1214                 Free(nt->NtUsername);\r
1215                 break;\r
1216         }\r
1217 \r
1218         Free(authdata);\r
1219 }\r
1220 \r
1221 // ユーザーの作成\r
1222 USER *NewUser(char *name, wchar_t *realname, wchar_t *note, UINT authtype, void *authdata)\r
1223 {\r
1224         USER *u;\r
1225         // 引数チェック\r
1226         if (name == NULL || realname == NULL || note == NULL)\r
1227         {\r
1228                 return NULL;\r
1229         }\r
1230         if (authtype != AUTHTYPE_ANONYMOUS && authdata == NULL)\r
1231         {\r
1232                 return NULL;\r
1233         }\r
1234 \r
1235         u = ZeroMalloc(sizeof(USER));\r
1236         u->lock = NewLock();\r
1237         u->ref = NewRef();\r
1238         u->Name = CopyStr(name);\r
1239         u->RealName = CopyUniStr(realname);\r
1240         u->Note = CopyUniStr(note);\r
1241         u->GroupName = NULL;\r
1242         u->Group = NULL;\r
1243         u->AuthType = authtype;\r
1244         u->AuthData = authdata;\r
1245         u->CreatedTime = SystemTime64();\r
1246         u->UpdatedTime = SystemTime64();\r
1247 \r
1248         u->Policy = NULL;\r
1249         u->Traffic = NewTraffic();\r
1250 \r
1251         return u;\r
1252 }\r
1253 \r
1254 // グループの解放\r
1255 void ReleaseGroup(USERGROUP *g)\r
1256 {\r
1257         // 引数チェック\r
1258         if (g == NULL)\r
1259         {\r
1260                 return;\r
1261         }\r
1262 \r
1263         if (Release(g->ref) == 0)\r
1264         {\r
1265                 CleanupGroup(g);\r
1266         }\r
1267 }\r
1268 \r
1269 // グループのクリーンアップ\r
1270 void CleanupGroup(USERGROUP *g)\r
1271 {\r
1272         // 引数チェック\r
1273         if (g == NULL)\r
1274         {\r
1275                 return;\r
1276         }\r
1277 \r
1278         Free(g->Name);\r
1279         Free(g->RealName);\r
1280         Free(g->Note);\r
1281 \r
1282         if (g->Policy)\r
1283         {\r
1284                 // ポリシー解放\r
1285                 Free(g->Policy);\r
1286         }\r
1287 \r
1288 \r
1289         FreeTraffic(g->Traffic);\r
1290 \r
1291         DeleteLock(g->lock);\r
1292         Free(g);\r
1293 }\r
1294 \r
1295 // 新しいグループを作成\r
1296 USERGROUP *NewGroup(char *name, wchar_t *realname, wchar_t *note)\r
1297 {\r
1298         USERGROUP *g;\r
1299         // 引数チェック\r
1300         if (name == NULL || realname == NULL || note == NULL)\r
1301         {\r
1302                 return NULL;\r
1303         }\r
1304 \r
1305         g = ZeroMalloc(sizeof(USERGROUP));\r
1306         g->lock = NewLock();\r
1307         g->ref = NewRef();\r
1308         g->Name = CopyStr(name);\r
1309         g->RealName = CopyUniStr(realname);\r
1310         g->Note = CopyUniStr(note);\r
1311         g->Policy = NULL;\r
1312         g->Traffic = NewTraffic();\r
1313 \r
1314         return g;\r
1315 }\r
1316 \r
1317 // HUB のアカウントデータベースのロック\r
1318 void AcLock(HUB *h)\r
1319 {\r
1320         // 引数チェック\r
1321         if (h == NULL)\r
1322         {\r
1323                 return;\r
1324         }\r
1325         if (NO_ACCOUNT_DB(h))\r
1326         {\r
1327                 return;\r
1328         }\r
1329 \r
1330         // グループとユーザーをロック\r
1331         LockList(h->HubDb->GroupList);\r
1332         LockList(h->HubDb->UserList);\r
1333 }\r
1334 \r
1335 // HUB のアカウントデータベースのロック解除\r
1336 void AcUnlock(HUB *h)\r
1337 {\r
1338         // 引数チェック\r
1339         if (h == NULL)\r
1340         {\r
1341                 return;\r
1342         }\r
1343         if (NO_ACCOUNT_DB(h))\r
1344         {\r
1345                 return;\r
1346         }\r
1347 \r
1348         // グループとユーザーをロック解除\r
1349         UnlockList(h->HubDb->UserList);\r
1350         UnlockList(h->HubDb->GroupList);\r
1351 }\r
1352 \r
1353 // グループ名比較関数\r
1354 int CompareGroupName(void *p1, void *p2)\r
1355 {\r
1356         USERGROUP *g1, *g2;\r
1357         // 引数チェック\r
1358         if (p1 == NULL || p2 == NULL)\r
1359         {\r
1360                 return 0;\r
1361         }\r
1362         g1 = *(USERGROUP **)p1;\r
1363         g2 = *(USERGROUP **)p2;\r
1364         if (g1 == NULL || g2 == NULL)\r
1365         {\r
1366                 return 0;\r
1367         }\r
1368 \r
1369         return StrCmpi(g1->Name, g2->Name);\r
1370 }\r
1371 \r
1372 // ユーザー名比較関数\r
1373 int CompareUserName(void *p1, void *p2)\r
1374 {\r
1375         USER *u1, *u2;\r
1376         // 引数チェック\r
1377         if (p1 == NULL || p2 == NULL)\r
1378         {\r
1379                 return 0;\r
1380         }\r
1381         u1 = *(USER **)p1;\r
1382         u2 = *(USER **)p2;\r
1383         if (u1 == NULL || u2 == NULL)\r
1384         {\r
1385                 return 0;\r
1386         }\r
1387 \r
1388         return StrCmpi(u1->Name, u2->Name);\r
1389 }\r
1390 \r