OSDN Git Service

Fix bugs of routines for IPv6.
[ffftp/ffftp.git] / socketwrapper.c
1 // socketwrapper.c\r
2 // Copyright (C) 2011 Suguru Kawamoto\r
3 // ソケットラッパー\r
4 // socket関連関数をOpenSSL用に置換\r
5 // socket関連関数のIPv6対応\r
6 // コンパイルにはOpenSSLのヘッダーファイルが必要\r
7 // 実行にはOpenSSLのDLLが必要\r
8 \r
9 #include <ws2tcpip.h>\r
10 #include <windows.h>\r
11 #include <mmsystem.h>\r
12 #include <openssl/ssl.h>\r
13 \r
14 #include "socketwrapper.h"\r
15 #include "protectprocess.h"\r
16 #include "mbswrapper.h"\r
17 #include "punycode.h"\r
18 \r
19 typedef void (__cdecl* _SSL_load_error_strings)();\r
20 typedef int (__cdecl* _SSL_library_init)();\r
21 typedef SSL_METHOD* (__cdecl* _SSLv23_method)();\r
22 typedef SSL_CTX* (__cdecl* _SSL_CTX_new)(SSL_METHOD*);\r
23 typedef void (__cdecl* _SSL_CTX_free)(SSL_CTX*);\r
24 typedef SSL* (__cdecl* _SSL_new)(SSL_CTX*);\r
25 typedef void (__cdecl* _SSL_free)(SSL*);\r
26 typedef int (__cdecl* _SSL_shutdown)(SSL*);\r
27 typedef int (__cdecl* _SSL_get_fd)(SSL*);\r
28 typedef int (__cdecl* _SSL_set_fd)(SSL*, int);\r
29 typedef int (__cdecl* _SSL_accept)(SSL*);\r
30 typedef int (__cdecl* _SSL_connect)(SSL*);\r
31 typedef int (__cdecl* _SSL_write)(SSL*, const void*, int);\r
32 typedef int (__cdecl* _SSL_peek)(SSL*, void*, int);\r
33 typedef int (__cdecl* _SSL_read)(SSL*, void*, int);\r
34 typedef int (__cdecl* _SSL_get_error)(SSL*, int);\r
35 typedef X509* (__cdecl* _SSL_get_peer_certificate)(const SSL*);\r
36 typedef long (__cdecl* _SSL_get_verify_result)(const SSL*);\r
37 typedef SSL_SESSION* (__cdecl* _SSL_get_session)(SSL*);\r
38 typedef int (__cdecl* _SSL_set_session)(SSL*, SSL_SESSION*);\r
39 typedef int (__cdecl* _SSL_CTX_use_certificate)(SSL_CTX*, X509*);\r
40 typedef BIO_METHOD* (__cdecl* _BIO_s_mem)();\r
41 typedef BIO* (__cdecl* _BIO_new)(BIO_METHOD*);\r
42 typedef int (__cdecl* _BIO_free)(BIO*);\r
43 typedef BIO* (__cdecl* _BIO_new_mem_buf)(void*, int);\r
44 typedef long (__cdecl* _BIO_ctrl)(BIO*, int, long, void*);\r
45 typedef void (__cdecl* _X509_free)(X509*);\r
46 typedef int (__cdecl* _X509_print_ex)(BIO*, X509*, unsigned long, unsigned long);\r
47 typedef X509_NAME* (__cdecl* _X509_get_subject_name)(X509*);\r
48 typedef int (__cdecl* _X509_NAME_print_ex)(BIO*, X509_NAME*, int, unsigned long);\r
49 typedef X509* (__cdecl* _PEM_read_bio_X509)(BIO*, X509**, pem_password_cb*, void*);\r
50 \r
51 _SSL_load_error_strings p_SSL_load_error_strings;\r
52 _SSL_library_init p_SSL_library_init;\r
53 _SSLv23_method p_SSLv23_method;\r
54 _SSL_CTX_new p_SSL_CTX_new;\r
55 _SSL_CTX_free p_SSL_CTX_free;\r
56 _SSL_new p_SSL_new;\r
57 _SSL_free p_SSL_free;\r
58 _SSL_shutdown p_SSL_shutdown;\r
59 _SSL_get_fd p_SSL_get_fd;\r
60 _SSL_set_fd p_SSL_set_fd;\r
61 _SSL_accept p_SSL_accept;\r
62 _SSL_connect p_SSL_connect;\r
63 _SSL_write p_SSL_write;\r
64 _SSL_peek p_SSL_peek;\r
65 _SSL_read p_SSL_read;\r
66 _SSL_get_error p_SSL_get_error;\r
67 _SSL_get_peer_certificate p_SSL_get_peer_certificate;\r
68 _SSL_get_verify_result p_SSL_get_verify_result;\r
69 _SSL_get_session p_SSL_get_session;\r
70 _SSL_set_session p_SSL_set_session;\r
71 _SSL_CTX_use_certificate p_SSL_CTX_use_certificate;\r
72 _BIO_s_mem p_BIO_s_mem;\r
73 _BIO_new p_BIO_new;\r
74 _BIO_free p_BIO_free;\r
75 _BIO_new_mem_buf p_BIO_new_mem_buf;\r
76 _BIO_ctrl p_BIO_ctrl;\r
77 _X509_free p_X509_free;\r
78 _X509_print_ex p_X509_print_ex;\r
79 _X509_get_subject_name p_X509_get_subject_name;\r
80 _X509_NAME_print_ex p_X509_NAME_print_ex;\r
81 _PEM_read_bio_X509 p_PEM_read_bio_X509;\r
82 \r
83 #define MAX_SSL_SOCKET 16\r
84 \r
85 BOOL g_bOpenSSLLoaded;\r
86 HMODULE g_hOpenSSL;\r
87 HMODULE g_hOpenSSLCommon;\r
88 CRITICAL_SECTION g_OpenSSLLock;\r
89 DWORD g_OpenSSLTimeout;\r
90 LPSSLTIMEOUTCALLBACK g_pOpenSSLTimeoutCallback;\r
91 LPSSLCONFIRMCALLBACK g_pOpenSSLConfirmCallback;\r
92 SSL_CTX* g_pOpenSSLCTX;\r
93 SSL* g_pOpenSSLHandle[MAX_SSL_SOCKET];\r
94 \r
95 BOOL __stdcall DefaultSSLTimeoutCallback(BOOL* pbAborted)\r
96 {\r
97         Sleep(100);\r
98         return *pbAborted;\r
99 }\r
100 \r
101 BOOL __stdcall DefaultSSLConfirmCallback(BOOL* pbAborted, BOOL bVerified, LPCSTR Certificate, LPCSTR CommonName)\r
102 {\r
103         return bVerified;\r
104 }\r
105 \r
106 // OpenSSLを初期化\r
107 BOOL LoadOpenSSL()\r
108 {\r
109         if(g_bOpenSSLLoaded)\r
110                 return FALSE;\r
111 #ifdef ENABLE_PROCESS_PROTECTION\r
112         // 同梱するOpenSSLのバージョンに合わせてSHA1ハッシュ値を変更すること\r
113         // ssleay32.dll 1.0.0e\r
114         // libssl32.dll 1.0.0e\r
115         RegisterTrustedModuleSHA1Hash("\x4E\xB7\xA0\x22\x14\x4B\x58\x6D\xBC\xF5\x21\x0D\x96\x78\x0D\x79\x7D\x66\xB2\xB0");\r
116         // libeay32.dll 1.0.0e\r
117         RegisterTrustedModuleSHA1Hash("\x01\x32\x7A\xAE\x69\x26\xE6\x58\xC7\x63\x22\x1E\x53\x5A\x78\xBC\x61\xC7\xB5\xC1");\r
118 #endif\r
119         g_hOpenSSL = LoadLibrary("ssleay32.dll");\r
120         // バージョン固定のためlibssl32.dllの読み込みは脆弱性の原因になり得るので廃止\r
121 //      if(!g_hOpenSSL)\r
122 //              g_hOpenSSL = LoadLibrary("libssl32.dll");\r
123         if(!g_hOpenSSL\r
124                 || !(p_SSL_load_error_strings = (_SSL_load_error_strings)GetProcAddress(g_hOpenSSL, "SSL_load_error_strings"))\r
125                 || !(p_SSL_library_init = (_SSL_library_init)GetProcAddress(g_hOpenSSL, "SSL_library_init"))\r
126                 || !(p_SSLv23_method = (_SSLv23_method)GetProcAddress(g_hOpenSSL, "SSLv23_method"))\r
127                 || !(p_SSL_CTX_new = (_SSL_CTX_new)GetProcAddress(g_hOpenSSL, "SSL_CTX_new"))\r
128                 || !(p_SSL_CTX_free = (_SSL_CTX_free)GetProcAddress(g_hOpenSSL, "SSL_CTX_free"))\r
129                 || !(p_SSL_new = (_SSL_new)GetProcAddress(g_hOpenSSL, "SSL_new"))\r
130                 || !(p_SSL_free = (_SSL_free)GetProcAddress(g_hOpenSSL, "SSL_free"))\r
131                 || !(p_SSL_shutdown = (_SSL_shutdown)GetProcAddress(g_hOpenSSL, "SSL_shutdown"))\r
132                 || !(p_SSL_get_fd = (_SSL_get_fd)GetProcAddress(g_hOpenSSL, "SSL_get_fd"))\r
133                 || !(p_SSL_set_fd = (_SSL_set_fd)GetProcAddress(g_hOpenSSL, "SSL_set_fd"))\r
134                 || !(p_SSL_accept = (_SSL_accept)GetProcAddress(g_hOpenSSL, "SSL_accept"))\r
135                 || !(p_SSL_connect = (_SSL_connect)GetProcAddress(g_hOpenSSL, "SSL_connect"))\r
136                 || !(p_SSL_write = (_SSL_write)GetProcAddress(g_hOpenSSL, "SSL_write"))\r
137                 || !(p_SSL_peek = (_SSL_peek)GetProcAddress(g_hOpenSSL, "SSL_peek"))\r
138                 || !(p_SSL_read = (_SSL_read)GetProcAddress(g_hOpenSSL, "SSL_read"))\r
139                 || !(p_SSL_get_error = (_SSL_get_error)GetProcAddress(g_hOpenSSL, "SSL_get_error"))\r
140                 || !(p_SSL_get_peer_certificate = (_SSL_get_peer_certificate)GetProcAddress(g_hOpenSSL, "SSL_get_peer_certificate"))\r
141                 || !(p_SSL_get_verify_result = (_SSL_get_verify_result)GetProcAddress(g_hOpenSSL, "SSL_get_verify_result"))\r
142                 || !(p_SSL_get_session = (_SSL_get_session)GetProcAddress(g_hOpenSSL, "SSL_get_session"))\r
143                 || !(p_SSL_set_session = (_SSL_set_session)GetProcAddress(g_hOpenSSL, "SSL_set_session"))\r
144                 || !(p_SSL_CTX_use_certificate = (_SSL_CTX_use_certificate)GetProcAddress(g_hOpenSSL, "SSL_CTX_use_certificate")))\r
145         {\r
146                 if(g_hOpenSSL)\r
147                         FreeLibrary(g_hOpenSSL);\r
148                 g_hOpenSSL = NULL;\r
149                 return FALSE;\r
150         }\r
151         g_hOpenSSLCommon = LoadLibrary("libeay32.dll");\r
152         if(!g_hOpenSSLCommon\r
153                 || !(p_BIO_s_mem = (_BIO_s_mem)GetProcAddress(g_hOpenSSLCommon, "BIO_s_mem"))\r
154                 || !(p_BIO_new = (_BIO_new)GetProcAddress(g_hOpenSSLCommon, "BIO_new"))\r
155                 || !(p_BIO_free = (_BIO_free)GetProcAddress(g_hOpenSSLCommon, "BIO_free"))\r
156                 || !(p_BIO_new_mem_buf = (_BIO_new_mem_buf)GetProcAddress(g_hOpenSSLCommon, "BIO_new_mem_buf"))\r
157                 || !(p_BIO_ctrl = (_BIO_ctrl)GetProcAddress(g_hOpenSSLCommon, "BIO_ctrl"))\r
158                 || !(p_X509_free = (_X509_free)GetProcAddress(g_hOpenSSLCommon, "X509_free"))\r
159                 || !(p_X509_print_ex = (_X509_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_print_ex"))\r
160                 || !(p_X509_get_subject_name = (_X509_get_subject_name)GetProcAddress(g_hOpenSSLCommon, "X509_get_subject_name"))\r
161                 || !(p_X509_NAME_print_ex = (_X509_NAME_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_NAME_print_ex"))\r
162                 || !(p_PEM_read_bio_X509 = (_PEM_read_bio_X509)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_X509")))\r
163         {\r
164                 if(g_hOpenSSL)\r
165                         FreeLibrary(g_hOpenSSL);\r
166                 g_hOpenSSL = NULL;\r
167                 if(g_hOpenSSLCommon)\r
168                         FreeLibrary(g_hOpenSSLCommon);\r
169                 g_hOpenSSLCommon = NULL;\r
170                 return FALSE;\r
171         }\r
172         InitializeCriticalSection(&g_OpenSSLLock);\r
173         p_SSL_load_error_strings();\r
174         p_SSL_library_init();\r
175         SetSSLTimeoutCallback(60000, DefaultSSLTimeoutCallback);\r
176         SetSSLConfirmCallback(DefaultSSLConfirmCallback);\r
177         g_bOpenSSLLoaded = TRUE;\r
178         return TRUE;\r
179 }\r
180 \r
181 // OpenSSLを解放\r
182 void FreeOpenSSL()\r
183 {\r
184         int i;\r
185         if(!g_bOpenSSLLoaded)\r
186                 return;\r
187         EnterCriticalSection(&g_OpenSSLLock);\r
188         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
189         {\r
190                 if(g_pOpenSSLHandle[i])\r
191                 {\r
192                         p_SSL_shutdown(g_pOpenSSLHandle[i]);\r
193                         p_SSL_free(g_pOpenSSLHandle[i]);\r
194                         g_pOpenSSLHandle[i] = NULL;\r
195                 }\r
196         }\r
197         if(g_pOpenSSLCTX)\r
198                 p_SSL_CTX_free(g_pOpenSSLCTX);\r
199         g_pOpenSSLCTX = NULL;\r
200         FreeLibrary(g_hOpenSSL);\r
201         g_hOpenSSL = NULL;\r
202         FreeLibrary(g_hOpenSSLCommon);\r
203         g_hOpenSSLCommon = NULL;\r
204         LeaveCriticalSection(&g_OpenSSLLock);\r
205         DeleteCriticalSection(&g_OpenSSLLock);\r
206         g_bOpenSSLLoaded = FALSE;\r
207 }\r
208 \r
209 // OpenSSLが使用可能かどうか確認\r
210 BOOL IsOpenSSLLoaded()\r
211 {\r
212         return g_bOpenSSLLoaded;\r
213 }\r
214 \r
215 SSL** GetUnusedSSLPointer()\r
216 {\r
217         int i;\r
218         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
219         {\r
220                 if(!g_pOpenSSLHandle[i])\r
221                         return &g_pOpenSSLHandle[i];\r
222         }\r
223         return NULL;\r
224 }\r
225 \r
226 SSL** FindSSLPointerFromSocket(SOCKET s)\r
227 {\r
228         int i;\r
229         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
230         {\r
231                 if(g_pOpenSSLHandle[i])\r
232                 {\r
233                         if(p_SSL_get_fd(g_pOpenSSLHandle[i]) == s)\r
234                                 return &g_pOpenSSLHandle[i];\r
235                 }\r
236         }\r
237         return NULL;\r
238 }\r
239 \r
240 BOOL ConfirmSSLCertificate(SSL* pSSL, BOOL* pbAborted)\r
241 {\r
242         BOOL bResult;\r
243         BOOL bVerified;\r
244         char* pData;\r
245         char* pSubject;\r
246         X509* pX509;\r
247         BIO* pBIO;\r
248         long Length;\r
249         char* pBuffer;\r
250         char* pCN;\r
251         char* p;\r
252         bResult = FALSE;\r
253         bVerified = FALSE;\r
254         pData = NULL;\r
255         pSubject = NULL;\r
256         if(pX509 = p_SSL_get_peer_certificate(pSSL))\r
257         {\r
258                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
259                 {\r
260                         p_X509_print_ex(pBIO, pX509, 0, XN_FLAG_RFC2253);\r
261                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
262                         {\r
263                                 if(pData = (char*)malloc(Length + sizeof(char)))\r
264                                 {\r
265                                         memcpy(pData, pBuffer, Length);\r
266                                         *(char*)((size_t)pData + Length) = '\0';\r
267                                 }\r
268                         }\r
269                         p_BIO_free(pBIO);\r
270                 }\r
271                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
272                 {\r
273                         p_X509_NAME_print_ex(pBIO, p_X509_get_subject_name(pX509), 0, XN_FLAG_RFC2253);\r
274                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
275                         {\r
276                                 if(pSubject = (char*)malloc(Length + sizeof(char)))\r
277                                 {\r
278                                         memcpy(pSubject, pBuffer, Length);\r
279                                         *(char*)((size_t)pSubject + Length) = '\0';\r
280                                 }\r
281                         }\r
282                         p_BIO_free(pBIO);\r
283                 }\r
284                 p_X509_free(pX509);\r
285         }\r
286         if(p_SSL_get_verify_result(pSSL) == X509_V_OK)\r
287                 bVerified = TRUE;\r
288         pCN = pSubject;\r
289         while(pCN)\r
290         {\r
291                 if(strncmp(pCN, "CN=", strlen("CN=")) == 0)\r
292                 {\r
293                         pCN += strlen("CN=");\r
294                         if(p = strchr(pCN, ','))\r
295                                 *p = '\0';\r
296                         break;\r
297                 }\r
298                 if(pCN = strchr(pCN, ','))\r
299                         pCN++;\r
300         }\r
301         bResult = g_pOpenSSLConfirmCallback(pbAborted, bVerified, pData, pCN);\r
302         if(pData)\r
303                 free(pData);\r
304         if(pSubject)\r
305                 free(pSubject);\r
306         return bResult;\r
307 }\r
308 \r
309 void SetSSLTimeoutCallback(DWORD Timeout, LPSSLTIMEOUTCALLBACK pCallback)\r
310 {\r
311         if(!g_bOpenSSLLoaded)\r
312                 return;\r
313         EnterCriticalSection(&g_OpenSSLLock);\r
314         g_OpenSSLTimeout = Timeout;\r
315         g_pOpenSSLTimeoutCallback = pCallback;\r
316         LeaveCriticalSection(&g_OpenSSLLock);\r
317 }\r
318 \r
319 void SetSSLConfirmCallback(LPSSLCONFIRMCALLBACK pCallback)\r
320 {\r
321         if(!g_bOpenSSLLoaded)\r
322                 return;\r
323         EnterCriticalSection(&g_OpenSSLLock);\r
324         g_pOpenSSLConfirmCallback = pCallback;\r
325         LeaveCriticalSection(&g_OpenSSLLock);\r
326 }\r
327 \r
328 // SSLルート証明書を設定\r
329 BOOL SetSSLRootCertificate(void* pData, DWORD Length)\r
330 {\r
331         BOOL r;\r
332         BIO* pBIO;\r
333         X509* pX509;\r
334         if(!g_bOpenSSLLoaded)\r
335                 return FALSE;\r
336         r = FALSE;\r
337         EnterCriticalSection(&g_OpenSSLLock);\r
338         if(!g_pOpenSSLCTX)\r
339                 g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
340         if(g_pOpenSSLCTX)\r
341         {\r
342                 if(pBIO = p_BIO_new_mem_buf(pData, Length))\r
343                 {\r
344                         if(pX509 = p_PEM_read_bio_X509(pBIO, NULL, NULL, NULL))\r
345                         {\r
346                                 if(p_SSL_CTX_use_certificate(g_pOpenSSLCTX, pX509) == 1)\r
347                                         r = TRUE;\r
348                                 p_X509_free(pX509);\r
349                         }\r
350                         p_BIO_free(pBIO);\r
351                 }\r
352         }\r
353         LeaveCriticalSection(&g_OpenSSLLock);\r
354         return r;\r
355 }\r
356 \r
357 // ワイルドカードの比較\r
358 // 主にSSL証明書のCN確認用\r
359 BOOL IsHostNameMatched(LPCSTR HostName, LPCSTR CommonName)\r
360 {\r
361         BOOL bResult;\r
362         char* pAsterisk;\r
363         bResult = FALSE;\r
364         if(HostName && CommonName)\r
365         {\r
366                 if(pAsterisk = strchr(CommonName, '*'))\r
367                 {\r
368                         if(_strnicmp(HostName, CommonName, ((size_t)pAsterisk - (size_t)CommonName) / sizeof(char)) == 0)\r
369                         {\r
370                                 while(*pAsterisk == '*')\r
371                                 {\r
372                                         pAsterisk++;\r
373                                 }\r
374                                 if(_stricmp(HostName + strlen(HostName) - strlen(pAsterisk), pAsterisk) == 0)\r
375                                         bResult = TRUE;\r
376                         }\r
377                 }\r
378                 else if(_stricmp(HostName, CommonName) == 0)\r
379                         bResult = TRUE;\r
380         }\r
381         return bResult;\r
382 }\r
383 \r
384 // SSLセッションを開始\r
385 BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted)\r
386 {\r
387         BOOL r;\r
388         DWORD Time;\r
389         SSL** ppSSL;\r
390         SSL** ppSSLParent;\r
391         SSL_SESSION* pSession;\r
392         int Return;\r
393         int Error;\r
394         if(!g_bOpenSSLLoaded)\r
395                 return FALSE;\r
396         r = FALSE;\r
397         Time = timeGetTime();\r
398         EnterCriticalSection(&g_OpenSSLLock);\r
399         if(!g_pOpenSSLCTX)\r
400                 g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
401         if(g_pOpenSSLCTX)\r
402         {\r
403                 if(ppSSL = GetUnusedSSLPointer())\r
404                 {\r
405                         if(*ppSSL = p_SSL_new(g_pOpenSSLCTX))\r
406                         {\r
407                                 if(p_SSL_set_fd(*ppSSL, s) != 0)\r
408                                 {\r
409                                         if(parent != INVALID_SOCKET)\r
410                                         {\r
411                                                 if(ppSSLParent = FindSSLPointerFromSocket(parent))\r
412                                                 {\r
413                                                         if(pSession = p_SSL_get_session(*ppSSLParent))\r
414                                                         {\r
415                                                                 if(p_SSL_set_session(*ppSSL, pSession) == 1)\r
416                                                                 {\r
417                                                                 }\r
418                                                         }\r
419                                                 }\r
420                                         }\r
421                                         // SSLのネゴシエーションには時間がかかる場合がある\r
422                                         r = TRUE;\r
423                                         while(r)\r
424                                         {\r
425                                                 Return = p_SSL_connect(*ppSSL);\r
426                                                 if(Return == 1)\r
427                                                         break;\r
428                                                 Error = p_SSL_get_error(*ppSSL, Return);\r
429                                                 if(Error == SSL_ERROR_WANT_READ || Error == SSL_ERROR_WANT_WRITE)\r
430                                                 {\r
431                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
432                                                         if(g_pOpenSSLTimeoutCallback(pbAborted) || (g_OpenSSLTimeout > 0 && timeGetTime() - Time >= g_OpenSSLTimeout))\r
433                                                                 r = FALSE;\r
434                                                         EnterCriticalSection(&g_OpenSSLLock);\r
435                                                 }\r
436                                                 else\r
437                                                         r = FALSE;\r
438                                         }\r
439                                         if(r)\r
440                                         {\r
441                                                 if(ConfirmSSLCertificate(*ppSSL, pbAborted))\r
442                                                 {\r
443                                                 }\r
444                                                 else\r
445                                                 {\r
446                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
447                                                         DetachSSL(s);\r
448                                                         r = FALSE;\r
449                                                         EnterCriticalSection(&g_OpenSSLLock);\r
450                                                 }\r
451                                         }\r
452                                         else\r
453                                         {\r
454                                                 LeaveCriticalSection(&g_OpenSSLLock);\r
455                                                 DetachSSL(s);\r
456                                                 EnterCriticalSection(&g_OpenSSLLock);\r
457                                         }\r
458                                 }\r
459                                 else\r
460                                 {\r
461                                         LeaveCriticalSection(&g_OpenSSLLock);\r
462                                         DetachSSL(s);\r
463                                         EnterCriticalSection(&g_OpenSSLLock);\r
464                                 }\r
465                         }\r
466                 }\r
467         }\r
468         LeaveCriticalSection(&g_OpenSSLLock);\r
469         return r;\r
470 }\r
471 \r
472 // SSLセッションを終了\r
473 BOOL DetachSSL(SOCKET s)\r
474 {\r
475         BOOL r;\r
476         SSL** ppSSL;\r
477         if(!g_bOpenSSLLoaded)\r
478                 return FALSE;\r
479         r = FALSE;\r
480         EnterCriticalSection(&g_OpenSSLLock);\r
481         if(ppSSL = FindSSLPointerFromSocket(s))\r
482         {\r
483                 p_SSL_shutdown(*ppSSL);\r
484                 p_SSL_free(*ppSSL);\r
485                 *ppSSL = NULL;\r
486                 r = TRUE;\r
487         }\r
488         LeaveCriticalSection(&g_OpenSSLLock);\r
489         return r;\r
490 }\r
491 \r
492 // SSLとしてマークされているか確認\r
493 // マークされていればTRUEを返す\r
494 BOOL IsSSLAttached(SOCKET s)\r
495 {\r
496         SSL** ppSSL;\r
497         if(!g_bOpenSSLLoaded)\r
498                 return FALSE;\r
499         EnterCriticalSection(&g_OpenSSLLock);\r
500         ppSSL = FindSSLPointerFromSocket(s);\r
501         LeaveCriticalSection(&g_OpenSSLLock);\r
502         if(!ppSSL)\r
503                 return FALSE;\r
504         return TRUE;\r
505 }\r
506 \r
507 SOCKET socketS(int af, int type, int protocol)\r
508 {\r
509         return socket(af, type, protocol);\r
510 }\r
511 \r
512 int bindS(SOCKET s, const struct sockaddr *addr, int namelen)\r
513 {\r
514         return bind(s, addr, namelen);\r
515 }\r
516 \r
517 int listenS(SOCKET s, int backlog)\r
518 {\r
519         return listen(s, backlog);\r
520 }\r
521 \r
522 // accept相当の関数\r
523 // ただし初めからSSLのネゴシエーションを行う\r
524 SOCKET acceptS(SOCKET s, struct sockaddr *addr, int *addrlen)\r
525 {\r
526         SOCKET r;\r
527         BOOL bAborted;\r
528         r = accept(s, addr, addrlen);\r
529         bAborted = FALSE;\r
530         if(!AttachSSL(r, INVALID_SOCKET, &bAborted))\r
531         {\r
532                 closesocket(r);\r
533                 return INVALID_SOCKET;\r
534         }\r
535         return r;\r
536 }\r
537 \r
538 // connect相当の関数\r
539 // ただし初めからSSLのネゴシエーションを行う\r
540 int connectS(SOCKET s, const struct sockaddr *name, int namelen)\r
541 {\r
542         int r;\r
543         BOOL bAborted;\r
544         r = connect(s, name, namelen);\r
545         bAborted = FALSE;\r
546         if(!AttachSSL(r, INVALID_SOCKET, &bAborted))\r
547                 return SOCKET_ERROR;\r
548         return r;\r
549 }\r
550 \r
551 // closesocket相当の関数\r
552 int closesocketS(SOCKET s)\r
553 {\r
554         DetachSSL(s);\r
555         return closesocket(s);\r
556 }\r
557 \r
558 // send相当の関数\r
559 int sendS(SOCKET s, const char * buf, int len, int flags)\r
560 {\r
561         SSL** ppSSL;\r
562         if(!g_bOpenSSLLoaded)\r
563                 return send(s, buf, len, flags);\r
564         EnterCriticalSection(&g_OpenSSLLock);\r
565         ppSSL = FindSSLPointerFromSocket(s);\r
566         LeaveCriticalSection(&g_OpenSSLLock);\r
567         if(!ppSSL)\r
568                 return send(s, buf, len, flags);\r
569         return p_SSL_write(*ppSSL, buf, len);\r
570 }\r
571 \r
572 // recv相当の関数\r
573 int recvS(SOCKET s, char * buf, int len, int flags)\r
574 {\r
575         SSL** ppSSL;\r
576         if(!g_bOpenSSLLoaded)\r
577                 return recv(s, buf, len, flags);\r
578         EnterCriticalSection(&g_OpenSSLLock);\r
579         ppSSL = FindSSLPointerFromSocket(s);\r
580         LeaveCriticalSection(&g_OpenSSLLock);\r
581         if(!ppSSL)\r
582                 return recv(s, buf, len, flags);\r
583         if(flags & MSG_PEEK)\r
584                 return p_SSL_peek(*ppSSL, buf, len);\r
585         return p_SSL_read(*ppSSL, buf, len);\r
586 }\r
587 \r
588 // IPv6対応\r
589 \r
590 typedef struct\r
591 {\r
592         HANDLE h;\r
593         HWND hWnd;\r
594         u_int wMsg;\r
595         char * name;\r
596         char * buf;\r
597         int buflen;\r
598         short Family;\r
599 } GETHOSTBYNAMEDATA;\r
600 \r
601 DWORD WINAPI WSAAsyncGetHostByNameIPv6ThreadProc(LPVOID lpParameter)\r
602 {\r
603         GETHOSTBYNAMEDATA* pData;\r
604         struct hostent* pHost;\r
605         struct addrinfo* pAddr;\r
606         struct addrinfo* p;\r
607         pHost = NULL;\r
608         pData = (GETHOSTBYNAMEDATA*)lpParameter;\r
609         if(getaddrinfo(pData->name, NULL, NULL, &pAddr) == 0)\r
610         {\r
611                 p = pAddr;\r
612                 while(p)\r
613                 {\r
614                         if(p->ai_family == pData->Family)\r
615                         {\r
616                                 switch(p->ai_family)\r
617                                 {\r
618                                 case AF_INET:\r
619                                         pHost = (struct hostent*)pData->buf;\r
620                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in_addr)\r
621                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in))\r
622                                         {\r
623                                                 pHost->h_name = NULL;\r
624                                                 pHost->h_aliases = NULL;\r
625                                                 pHost->h_addrtype = p->ai_family;\r
626                                                 pHost->h_length = sizeof(struct in_addr);\r
627                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
628                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
629                                                 pHost->h_addr_list[1] = NULL;\r
630                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in*)p->ai_addr)->sin_addr, sizeof(struct in_addr));\r
631                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + p->ai_addrlen));\r
632                                         }\r
633                                         else\r
634                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
635                                         break;\r
636                                 case AF_INET6:\r
637                                         pHost = (struct hostent*)pData->buf;\r
638                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in6_addr)\r
639                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in6))\r
640                                         {\r
641                                                 pHost->h_name = NULL;\r
642                                                 pHost->h_aliases = NULL;\r
643                                                 pHost->h_addrtype = p->ai_family;\r
644                                                 pHost->h_length = sizeof(struct in6_addr);\r
645                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
646                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
647                                                 pHost->h_addr_list[1] = NULL;\r
648                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in6*)p->ai_addr)->sin6_addr, sizeof(struct in6_addr));\r
649                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + p->ai_addrlen));\r
650                                         }\r
651                                         else\r
652                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
653                                         break;\r
654                                 }\r
655                         }\r
656                         if(pHost)\r
657                                 break;\r
658                         p = p->ai_next;\r
659                 }\r
660                 if(!p)\r
661                         PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
662                 freeaddrinfo(pAddr);\r
663         }\r
664         else\r
665                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
666         free(pData->name);\r
667         free(pData);\r
668         // CreateThreadが返すハンドルが重複するのを回避\r
669         Sleep(10000);\r
670         return 0;\r
671 }\r
672 \r
673 // IPv6対応のWSAAsyncGetHostByName相当の関数\r
674 // FamilyにはAF_INETまたはAF_INET6を指定可能\r
675 // ただしANSI用\r
676 HANDLE WSAAsyncGetHostByNameIPv6(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
677 {\r
678         HANDLE hResult;\r
679         GETHOSTBYNAMEDATA* pData;\r
680         hResult = NULL;\r
681         if(pData = malloc(sizeof(GETHOSTBYNAMEDATA)))\r
682         {\r
683                 pData->hWnd = hWnd;\r
684                 pData->wMsg = wMsg;\r
685                 if(pData->name = malloc(sizeof(char) * (strlen(name) + 1)))\r
686                 {\r
687                         strcpy(pData->name, name);\r
688                         pData->buf = buf;\r
689                         pData->buflen = buflen;\r
690                         pData->Family = Family;\r
691                         if(pData->h = CreateThread(NULL, 0, WSAAsyncGetHostByNameIPv6ThreadProc, pData, CREATE_SUSPENDED, NULL))\r
692                         {\r
693                                 ResumeThread(pData->h);\r
694                                 hResult = pData->h;\r
695                         }\r
696                 }\r
697         }\r
698         if(!hResult)\r
699         {\r
700                 if(pData)\r
701                 {\r
702                         if(pData->name)\r
703                                 free(pData->name);\r
704                         free(pData);\r
705                 }\r
706         }\r
707         return hResult;\r
708 }\r
709 \r
710 // WSAAsyncGetHostByNameIPv6用のWSACancelAsyncRequest相当の関数\r
711 int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle)\r
712 {\r
713         int Result;\r
714         Result = SOCKET_ERROR;\r
715         if(TerminateThread(hAsyncTaskHandle, 0))\r
716                 Result = 0;\r
717         return Result;\r
718 }\r
719 \r
720 char* AddressToStringIPv6(char* str, void* in6)\r
721 {\r
722         char* pResult;\r
723         unsigned char* p;\r
724         int MaxZero;\r
725         int MaxZeroLen;\r
726         int i;\r
727         int j;\r
728         char Tmp[5];\r
729         pResult = str;\r
730         p = (unsigned char*)in6;\r
731         MaxZero = 8;\r
732         MaxZeroLen = 1;\r
733         for(i = 0; i < 8; i++)\r
734         {\r
735                 for(j = i; j < 8; j++)\r
736                 {\r
737                         if(p[j * 2] != 0 || p[j * 2 + 1] != 0)\r
738                                 break;\r
739                 }\r
740                 if(j - i > MaxZeroLen)\r
741                 {\r
742                         MaxZero = i;\r
743                         MaxZeroLen = j - i;\r
744                 }\r
745         }\r
746         strcpy(str, "");\r
747         for(i = 0; i < 8; i++)\r
748         {\r
749                 if(i == MaxZero)\r
750                 {\r
751                         if(i == 0)\r
752                                 strcat(str, ":");\r
753                         strcat(str, ":");\r
754                 }\r
755                 else if(i < MaxZero || i >= MaxZero + MaxZeroLen)\r
756                 {\r
757                         sprintf(Tmp, "%x", (((int)p[i * 2] & 0xff) << 8) | ((int)p[i * 2 + 1] & 0xff));\r
758                         strcat(str, Tmp);\r
759                         if(i < 7)\r
760                                 strcat(str, ":");\r
761                 }\r
762         }\r
763         return pResult;\r
764 }\r
765 \r
766 // IPv6対応のinet_ntoa相当の関数\r
767 // ただしANSI用\r
768 char* inet6_ntoa(struct in6_addr in6)\r
769 {\r
770         char* pResult;\r
771         static char Adrs[40];\r
772         pResult = NULL;\r
773         memset(Adrs, 0, sizeof(Adrs));\r
774         pResult = AddressToStringIPv6(Adrs, &in6);\r
775         return pResult;\r
776 }\r
777 \r
778 // IPv6対応のinet_addr相当の関数\r
779 // ただしANSI用\r
780 struct in6_addr inet6_addr(const char* cp)\r
781 {\r
782         struct in6_addr Result;\r
783         int AfterZero;\r
784         int i;\r
785         char* p;\r
786         memset(&Result, 0, sizeof(Result));\r
787         AfterZero = 0;\r
788         for(i = 0; i < 8; i++)\r
789         {\r
790                 if(!cp)\r
791                 {\r
792                         memset(&Result, 0xff, sizeof(Result));\r
793                         break;\r
794                 }\r
795                 if(i >= AfterZero)\r
796                 {\r
797                         if(strncmp(cp, ":", 1) == 0)\r
798                         {\r
799                                 cp = cp + 1;\r
800                                 if(i == 0 && strncmp(cp, ":", 1) == 0)\r
801                                         cp = cp + 1;\r
802                                 p = (char*)cp;\r
803                                 AfterZero = 7;\r
804                                 while(p = strstr(p, ":"))\r
805                                 {\r
806                                         p = p + 1;\r
807                                         AfterZero--;\r
808                                 }\r
809                         }\r
810                         else\r
811                         {\r
812                                 Result.u.Word[i] = (USHORT)strtol(cp, &p, 16);\r
813                                 Result.u.Word[i] = ((Result.u.Word[i] & 0xff00) >> 8) | ((Result.u.Word[i] & 0x00ff) << 8);\r
814                                 if(strncmp(p, ":", 1) != 0 && strlen(p) > 0)\r
815                                 {\r
816                                         memset(&Result, 0xff, sizeof(Result));\r
817                                         break;\r
818                                 }\r
819                                 if(cp = strstr(cp, ":"))\r
820                                         cp = cp + 1;\r
821                         }\r
822                 }\r
823         }\r
824         return Result;\r
825 }\r
826 \r
827 BOOL ConvertDomainNameToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
828 {\r
829         BOOL bResult;\r
830         punycode_uint* pUnicode;\r
831         punycode_uint* p;\r
832         BOOL bNeeded;\r
833         LPCSTR InputString;\r
834         punycode_uint Length;\r
835         punycode_uint OutputLength;\r
836         bResult = FALSE;\r
837         if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
838         {\r
839                 p = pUnicode;\r
840                 bNeeded = FALSE;\r
841                 InputString = Input;\r
842                 Length = 0;\r
843                 while(*InputString != '\0')\r
844                 {\r
845                         *p = (punycode_uint)GetNextCharM(InputString, &InputString);\r
846                         if(*p >= 0x80)\r
847                                 bNeeded = TRUE;\r
848                         p++;\r
849                         Length++;\r
850                 }\r
851                 if(bNeeded)\r
852                 {\r
853                         if(Count >= strlen("xn--") + 1)\r
854                         {\r
855                                 strcpy(Output, "xn--");\r
856                                 OutputLength = Count - strlen("xn--");\r
857                                 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
858                                 {\r
859                                         Output[strlen("xn--") + OutputLength] = '\0';\r
860                                         bResult = TRUE;\r
861                                 }\r
862                         }\r
863                 }\r
864                 free(pUnicode);\r
865         }\r
866         if(!bResult)\r
867         {\r
868                 if(Count >= strlen(Input) + 1)\r
869                 {\r
870                         strcpy(Output, Input);\r
871                         bResult = TRUE;\r
872                 }\r
873         }\r
874         return bResult;\r
875 }\r
876 \r
877 BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
878 {\r
879         BOOL bResult;\r
880         DWORD Length;\r
881         char* pm0;\r
882         char* pm1;\r
883         char* p;\r
884         char* pNext;\r
885         bResult = FALSE;\r
886         Length = strlen(Input);\r
887         if(pm0 = AllocateStringM(Length + 1))\r
888         {\r
889                 if(pm1 = AllocateStringM(Length * 4 + 1))\r
890                 {\r
891                         strcpy(pm0, Input);\r
892                         p = pm0;\r
893                         while(p)\r
894                         {\r
895                                 if(pNext = strchr(p, '.'))\r
896                                 {\r
897                                         *pNext = '\0';\r
898                                         pNext++;\r
899                                 }\r
900                                 if(ConvertDomainNameToPunycode(pm1, Length * 4, p))\r
901                                         strcat(Output, pm1);\r
902                                 if(pNext)\r
903                                         strcat(Output, ".");\r
904                                 p = pNext;\r
905                         }\r
906                         bResult = TRUE;\r
907                         FreeDuplicatedString(pm1);\r
908                 }\r
909                 FreeDuplicatedString(pm0);\r
910         }\r
911         return bResult;\r
912 }\r
913 \r
914 HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
915 {\r
916         HANDLE r = NULL;\r
917         char* pa0 = NULL;\r
918         if(pa0 = AllocateStringA(strlen(name) * 4))\r
919         {\r
920                 if(ConvertNameToPunycode(pa0, name))\r
921                         r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
922         }\r
923         FreeDuplicatedString(pa0);\r
924         return r;\r
925 }\r
926 \r
927 HANDLE WSAAsyncGetHostByNameIPv6M(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
928 {\r
929         HANDLE r = NULL;\r
930         char* pa0 = NULL;\r
931         if(pa0 = AllocateStringA(strlen(name) * 4))\r
932         {\r
933                 if(ConvertNameToPunycode(pa0, name))\r
934                         r = WSAAsyncGetHostByNameIPv6(hWnd, wMsg, pa0, buf, buflen, Family);\r
935         }\r
936         FreeDuplicatedString(pa0);\r
937         return r;\r
938 }\r
939 \r