OSDN Git Service

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