OSDN Git Service

Update OpenSSL to 1.1.0.
[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 // FTPS対応\r
20 \r
21 // OpenSSL 1.1.0対応\r
22 //typedef void (__cdecl* _SSL_load_error_strings)();\r
23 //typedef int (__cdecl* _SSL_library_init)();\r
24 typedef int (__cdecl* _OPENSSL_init_ssl)(uint64_t, OPENSSL_INIT_SETTINGS*);\r
25 // OpenSSL 1.1.0対応\r
26 //typedef SSL_METHOD* (__cdecl* _SSLv23_method)();\r
27 typedef SSL_METHOD* (__cdecl* _TLS_method)();\r
28 typedef SSL* (__cdecl* _SSL_new)(SSL_CTX*);\r
29 typedef void (__cdecl* _SSL_free)(SSL*);\r
30 typedef long (__cdecl* _SSL_ctrl)(SSL*, int, long, void*);\r
31 typedef int (__cdecl* _SSL_shutdown)(SSL*);\r
32 typedef int (__cdecl* _SSL_get_fd)(SSL*);\r
33 typedef int (__cdecl* _SSL_set_fd)(SSL*, int);\r
34 typedef int (__cdecl* _SSL_accept)(SSL*);\r
35 typedef int (__cdecl* _SSL_connect)(SSL*);\r
36 typedef int (__cdecl* _SSL_write)(SSL*, const void*, int);\r
37 typedef int (__cdecl* _SSL_peek)(SSL*, void*, int);\r
38 typedef int (__cdecl* _SSL_read)(SSL*, void*, int);\r
39 typedef int (__cdecl* _SSL_get_error)(SSL*, int);\r
40 typedef X509* (__cdecl* _SSL_get_peer_certificate)(const SSL*);\r
41 typedef long (__cdecl* _SSL_get_verify_result)(const SSL*);\r
42 typedef SSL_SESSION* (__cdecl* _SSL_get_session)(SSL*);\r
43 typedef int (__cdecl* _SSL_set_session)(SSL*, SSL_SESSION*);\r
44 typedef int (__cdecl* _SSL_set_cipher_list)(SSL*, const char*);\r
45 typedef SSL_CTX* (__cdecl* _SSL_CTX_new)(SSL_METHOD*);\r
46 typedef void (__cdecl* _SSL_CTX_free)(SSL_CTX*);\r
47 typedef X509_STORE* (__cdecl* _SSL_CTX_get_cert_store)(const SSL_CTX*);\r
48 typedef long (__cdecl* _SSL_CTX_ctrl)(SSL_CTX*, int, long, void*);\r
49 typedef BIO_METHOD* (__cdecl* _BIO_s_mem)();\r
50 typedef BIO* (__cdecl* _BIO_new)(BIO_METHOD*);\r
51 typedef int (__cdecl* _BIO_free)(BIO*);\r
52 typedef BIO* (__cdecl* _BIO_new_mem_buf)(void*, int);\r
53 typedef long (__cdecl* _BIO_ctrl)(BIO*, int, long, void*);\r
54 typedef void (__cdecl* _X509_free)(X509*);\r
55 typedef int (__cdecl* _X509_print_ex)(BIO*, X509*, unsigned long, unsigned long);\r
56 typedef X509_NAME* (__cdecl* _X509_get_subject_name)(X509*);\r
57 typedef int (__cdecl* _X509_NAME_print_ex)(BIO*, X509_NAME*, int, unsigned long);\r
58 typedef void (__cdecl* _X509_CRL_free)(X509_CRL*);\r
59 typedef EVP_PKEY* (__cdecl* _PEM_read_bio_PrivateKey)(BIO*, EVP_PKEY**, pem_password_cb*, void*);\r
60 typedef EVP_PKEY* (__cdecl* _PEM_read_bio_PUBKEY)(BIO*, EVP_PKEY**, pem_password_cb*, void*);\r
61 typedef X509* (__cdecl* _PEM_read_bio_X509)(BIO*, X509**, pem_password_cb*, void*);\r
62 typedef X509_CRL* (__cdecl* _PEM_read_bio_X509_CRL)(BIO*, X509_CRL**, pem_password_cb*, void*);\r
63 typedef int (__cdecl* _X509_STORE_add_cert)(X509_STORE*, X509*);\r
64 typedef int (__cdecl* _X509_STORE_add_crl)(X509_STORE*, X509_CRL*);\r
65 typedef void (__cdecl* _EVP_PKEY_free)(EVP_PKEY*);\r
66 typedef RSA* (__cdecl* _EVP_PKEY_get1_RSA)(EVP_PKEY*);\r
67 typedef void (__cdecl* _RSA_free)(RSA*);\r
68 typedef int (__cdecl* _RSA_size)(const RSA*);\r
69 typedef int (__cdecl* _RSA_private_encrypt)(int, const unsigned char*, unsigned char*, RSA*, int);\r
70 typedef int (__cdecl* _RSA_public_decrypt)(int, const unsigned char*, unsigned char*, RSA*, int);\r
71 typedef unsigned char* (__cdecl* _SHA1)(const unsigned char*, size_t, unsigned char*);\r
72 typedef unsigned char* (__cdecl* _SHA224)(const unsigned char*, size_t, unsigned char*);\r
73 typedef unsigned char* (__cdecl* _SHA256)(const unsigned char*, size_t, unsigned char*);\r
74 typedef unsigned char* (__cdecl* _SHA384)(const unsigned char*, size_t, unsigned char*);\r
75 typedef unsigned char* (__cdecl* _SHA512)(const unsigned char*, size_t, unsigned char*);\r
76 \r
77 // OpenSSL 1.1.0対応\r
78 //_SSL_load_error_strings p_SSL_load_error_strings;\r
79 //_SSL_library_init p_SSL_library_init;\r
80 _OPENSSL_init_ssl p_OPENSSL_init_ssl;\r
81 // OpenSSL 1.1.0対応\r
82 //_SSLv23_method p_SSLv23_method;\r
83 _TLS_method p_TLS_method;\r
84 _SSL_new p_SSL_new;\r
85 _SSL_free p_SSL_free;\r
86 _SSL_ctrl p_SSL_ctrl;\r
87 _SSL_shutdown p_SSL_shutdown;\r
88 _SSL_get_fd p_SSL_get_fd;\r
89 _SSL_set_fd p_SSL_set_fd;\r
90 _SSL_accept p_SSL_accept;\r
91 _SSL_connect p_SSL_connect;\r
92 _SSL_write p_SSL_write;\r
93 _SSL_peek p_SSL_peek;\r
94 _SSL_read p_SSL_read;\r
95 _SSL_get_error p_SSL_get_error;\r
96 _SSL_get_peer_certificate p_SSL_get_peer_certificate;\r
97 _SSL_get_verify_result p_SSL_get_verify_result;\r
98 _SSL_get_session p_SSL_get_session;\r
99 _SSL_set_session p_SSL_set_session;\r
100 _SSL_set_cipher_list p_SSL_set_cipher_list;\r
101 _SSL_CTX_new p_SSL_CTX_new;\r
102 _SSL_CTX_free p_SSL_CTX_free;\r
103 _SSL_CTX_get_cert_store p_SSL_CTX_get_cert_store;\r
104 _SSL_CTX_ctrl p_SSL_CTX_ctrl;\r
105 _BIO_s_mem p_BIO_s_mem;\r
106 _BIO_new p_BIO_new;\r
107 _BIO_free p_BIO_free;\r
108 _BIO_new_mem_buf p_BIO_new_mem_buf;\r
109 _BIO_ctrl p_BIO_ctrl;\r
110 _X509_free p_X509_free;\r
111 _X509_print_ex p_X509_print_ex;\r
112 _X509_get_subject_name p_X509_get_subject_name;\r
113 _X509_NAME_print_ex p_X509_NAME_print_ex;\r
114 _X509_CRL_free p_X509_CRL_free;\r
115 _PEM_read_bio_PrivateKey p_PEM_read_bio_PrivateKey;\r
116 _PEM_read_bio_PUBKEY p_PEM_read_bio_PUBKEY;\r
117 _PEM_read_bio_X509 p_PEM_read_bio_X509;\r
118 _PEM_read_bio_X509_CRL p_PEM_read_bio_X509_CRL;\r
119 _X509_STORE_add_cert p_X509_STORE_add_cert;\r
120 _X509_STORE_add_crl p_X509_STORE_add_crl;\r
121 _EVP_PKEY_free p_EVP_PKEY_free;\r
122 _EVP_PKEY_get1_RSA p_EVP_PKEY_get1_RSA;\r
123 _RSA_free p_RSA_free;\r
124 _RSA_size p_RSA_size;\r
125 _RSA_private_encrypt p_RSA_private_encrypt;\r
126 _RSA_public_decrypt p_RSA_public_decrypt;\r
127 _SHA1 p_SHA1;\r
128 _SHA224 p_SHA224;\r
129 _SHA256 p_SHA256;\r
130 _SHA384 p_SHA384;\r
131 _SHA512 p_SHA512;\r
132 \r
133 #define MAX_SSL_SOCKET 16\r
134 \r
135 BOOL g_bOpenSSLLoaded;\r
136 HMODULE g_hOpenSSL;\r
137 HMODULE g_hOpenSSLCommon;\r
138 CRITICAL_SECTION g_OpenSSLLock;\r
139 DWORD g_OpenSSLTimeout;\r
140 LPSSLTIMEOUTCALLBACK g_pOpenSSLTimeoutCallback;\r
141 LPSSLCONFIRMCALLBACK g_pOpenSSLConfirmCallback;\r
142 SSL_CTX* g_pOpenSSLCTX;\r
143 SSL* g_pOpenSSLHandle[MAX_SSL_SOCKET];\r
144 \r
145 BOOL __stdcall DefaultSSLTimeoutCallback(BOOL* pbAborted)\r
146 {\r
147         Sleep(100);\r
148         return *pbAborted;\r
149 }\r
150 \r
151 BOOL __stdcall DefaultSSLConfirmCallback(BOOL* pbAborted, BOOL bVerified, LPCSTR Certificate, LPCSTR CommonName)\r
152 {\r
153         return bVerified;\r
154 }\r
155 \r
156 // OpenSSLを初期化\r
157 BOOL LoadOpenSSL()\r
158 {\r
159         if(g_bOpenSSLLoaded)\r
160                 return FALSE;\r
161 #ifdef ENABLE_PROCESS_PROTECTION\r
162         // 同梱するOpenSSLのバージョンに合わせてSHA1ハッシュ値を変更すること\r
163 #if defined(_M_IX86)\r
164         // ssleay32.dll 1.1.0h\r
165         RegisterTrustedModuleSHA1Hash("\x36\xFA\x98\xA1\xBE\x62\xB2\x07\xF0\xB8\x20\xE0\xB2\x86\x41\x68\xE2\x8D\x8B\x0F");\r
166         // libeay32.dll 1.1.0h\r
167         RegisterTrustedModuleSHA1Hash("\x2C\xD5\x65\x74\x2A\x8D\xE3\x22\x8F\xFE\xA9\x6D\xB5\x9D\x34\xFB\xBB\x23\x73\xFD");\r
168 #elif defined(_M_AMD64)\r
169         // ssleay32.dll 1.1.0h\r
170         RegisterTrustedModuleSHA1Hash("\x1A\xA5\x43\xC8\x19\x85\x16\xC0\x19\x04\x8D\xD2\xE0\xF3\xF8\x73\x4D\x9E\xA0\x2F");\r
171         // libeay32.dll 1.1.0h\r
172         RegisterTrustedModuleSHA1Hash("\xC4\x4E\xD4\x5B\xEF\xA6\xC0\x9F\x6A\x45\xEC\x26\xDE\xEC\x3A\xC0\x24\x00\xF1\x66");\r
173 #endif\r
174 #endif\r
175         g_hOpenSSL = LoadLibrary("ssleay32.dll");\r
176         // バージョン固定のためlibssl32.dllの読み込みは脆弱性の原因になり得るので廃止\r
177 //      if(!g_hOpenSSL)\r
178 //              g_hOpenSSL = LoadLibrary("libssl32.dll");\r
179         if(!g_hOpenSSL\r
180                 // OpenSSL 1.1.0対応\r
181 //              || !(p_SSL_load_error_strings = (_SSL_load_error_strings)GetProcAddress(g_hOpenSSL, "SSL_load_error_strings"))\r
182 //              || !(p_SSL_library_init = (_SSL_library_init)GetProcAddress(g_hOpenSSL, "SSL_library_init"))\r
183                 || !(p_OPENSSL_init_ssl = (_OPENSSL_init_ssl)GetProcAddress(g_hOpenSSL, "OPENSSL_init_ssl"))\r
184                 // OpenSSL 1.1.0対応\r
185 //              || !(p_SSLv23_method = (_SSLv23_method)GetProcAddress(g_hOpenSSL, "SSLv23_method"))\r
186                 || !(p_TLS_method = (_TLS_method)GetProcAddress(g_hOpenSSL, "TLS_method"))\r
187                 || !(p_SSL_new = (_SSL_new)GetProcAddress(g_hOpenSSL, "SSL_new"))\r
188                 || !(p_SSL_free = (_SSL_free)GetProcAddress(g_hOpenSSL, "SSL_free"))\r
189                 || !(p_SSL_ctrl = (_SSL_ctrl)GetProcAddress(g_hOpenSSL, "SSL_ctrl"))\r
190                 || !(p_SSL_shutdown = (_SSL_shutdown)GetProcAddress(g_hOpenSSL, "SSL_shutdown"))\r
191                 || !(p_SSL_get_fd = (_SSL_get_fd)GetProcAddress(g_hOpenSSL, "SSL_get_fd"))\r
192                 || !(p_SSL_set_fd = (_SSL_set_fd)GetProcAddress(g_hOpenSSL, "SSL_set_fd"))\r
193                 || !(p_SSL_accept = (_SSL_accept)GetProcAddress(g_hOpenSSL, "SSL_accept"))\r
194                 || !(p_SSL_connect = (_SSL_connect)GetProcAddress(g_hOpenSSL, "SSL_connect"))\r
195                 || !(p_SSL_write = (_SSL_write)GetProcAddress(g_hOpenSSL, "SSL_write"))\r
196                 || !(p_SSL_peek = (_SSL_peek)GetProcAddress(g_hOpenSSL, "SSL_peek"))\r
197                 || !(p_SSL_read = (_SSL_read)GetProcAddress(g_hOpenSSL, "SSL_read"))\r
198                 || !(p_SSL_get_error = (_SSL_get_error)GetProcAddress(g_hOpenSSL, "SSL_get_error"))\r
199                 || !(p_SSL_get_peer_certificate = (_SSL_get_peer_certificate)GetProcAddress(g_hOpenSSL, "SSL_get_peer_certificate"))\r
200                 || !(p_SSL_get_verify_result = (_SSL_get_verify_result)GetProcAddress(g_hOpenSSL, "SSL_get_verify_result"))\r
201                 || !(p_SSL_get_session = (_SSL_get_session)GetProcAddress(g_hOpenSSL, "SSL_get_session"))\r
202                 || !(p_SSL_set_session = (_SSL_set_session)GetProcAddress(g_hOpenSSL, "SSL_set_session"))\r
203                 || !(p_SSL_set_cipher_list = (_SSL_set_cipher_list)GetProcAddress(g_hOpenSSL, "SSL_set_cipher_list"))\r
204                 || !(p_SSL_CTX_new = (_SSL_CTX_new)GetProcAddress(g_hOpenSSL, "SSL_CTX_new"))\r
205                 || !(p_SSL_CTX_free = (_SSL_CTX_free)GetProcAddress(g_hOpenSSL, "SSL_CTX_free"))\r
206                 || !(p_SSL_CTX_get_cert_store = (_SSL_CTX_get_cert_store)GetProcAddress(g_hOpenSSL, "SSL_CTX_get_cert_store"))\r
207                 || !(p_SSL_CTX_ctrl = (_SSL_CTX_ctrl)GetProcAddress(g_hOpenSSL, "SSL_CTX_ctrl")))\r
208         {\r
209                 if(g_hOpenSSL)\r
210                         FreeLibrary(g_hOpenSSL);\r
211                 g_hOpenSSL = NULL;\r
212                 return FALSE;\r
213         }\r
214         g_hOpenSSLCommon = LoadLibrary("libeay32.dll");\r
215         if(!g_hOpenSSLCommon\r
216                 || !(p_BIO_s_mem = (_BIO_s_mem)GetProcAddress(g_hOpenSSLCommon, "BIO_s_mem"))\r
217                 || !(p_BIO_new = (_BIO_new)GetProcAddress(g_hOpenSSLCommon, "BIO_new"))\r
218                 || !(p_BIO_free = (_BIO_free)GetProcAddress(g_hOpenSSLCommon, "BIO_free"))\r
219                 || !(p_BIO_new_mem_buf = (_BIO_new_mem_buf)GetProcAddress(g_hOpenSSLCommon, "BIO_new_mem_buf"))\r
220                 || !(p_BIO_ctrl = (_BIO_ctrl)GetProcAddress(g_hOpenSSLCommon, "BIO_ctrl"))\r
221                 || !(p_X509_free = (_X509_free)GetProcAddress(g_hOpenSSLCommon, "X509_free"))\r
222                 || !(p_X509_print_ex = (_X509_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_print_ex"))\r
223                 || !(p_X509_get_subject_name = (_X509_get_subject_name)GetProcAddress(g_hOpenSSLCommon, "X509_get_subject_name"))\r
224                 || !(p_X509_NAME_print_ex = (_X509_NAME_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_NAME_print_ex"))\r
225                 || !(p_X509_CRL_free = (_X509_CRL_free)GetProcAddress(g_hOpenSSLCommon, "X509_CRL_free"))\r
226                 || !(p_PEM_read_bio_PrivateKey = (_PEM_read_bio_PrivateKey)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_PrivateKey"))\r
227                 || !(p_PEM_read_bio_PUBKEY = (_PEM_read_bio_PUBKEY)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_PUBKEY"))\r
228                 || !(p_PEM_read_bio_X509 = (_PEM_read_bio_X509)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_X509"))\r
229                 || !(p_PEM_read_bio_X509_CRL = (_PEM_read_bio_X509_CRL)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_X509_CRL"))\r
230                 || !(p_X509_STORE_add_cert = (_X509_STORE_add_cert)GetProcAddress(g_hOpenSSLCommon, "X509_STORE_add_cert"))\r
231                 || !(p_X509_STORE_add_crl = (_X509_STORE_add_crl)GetProcAddress(g_hOpenSSLCommon, "X509_STORE_add_crl"))\r
232                 || !(p_EVP_PKEY_free = (_EVP_PKEY_free)GetProcAddress(g_hOpenSSLCommon, "EVP_PKEY_free"))\r
233                 || !(p_EVP_PKEY_get1_RSA = (_EVP_PKEY_get1_RSA)GetProcAddress(g_hOpenSSLCommon, "EVP_PKEY_get1_RSA"))\r
234                 || !(p_RSA_free = (_RSA_free)GetProcAddress(g_hOpenSSLCommon, "RSA_free"))\r
235                 || !(p_RSA_size = (_RSA_size)GetProcAddress(g_hOpenSSLCommon, "RSA_size"))\r
236                 || !(p_RSA_private_encrypt = (_RSA_private_encrypt)GetProcAddress(g_hOpenSSLCommon, "RSA_private_encrypt"))\r
237                 || !(p_RSA_public_decrypt = (_RSA_public_decrypt)GetProcAddress(g_hOpenSSLCommon, "RSA_public_decrypt"))\r
238                 || !(p_SHA1 = (_SHA1)GetProcAddress(g_hOpenSSLCommon, "SHA1"))\r
239                 || !(p_SHA224 = (_SHA224)GetProcAddress(g_hOpenSSLCommon, "SHA224"))\r
240                 || !(p_SHA256 = (_SHA256)GetProcAddress(g_hOpenSSLCommon, "SHA256"))\r
241                 || !(p_SHA384 = (_SHA384)GetProcAddress(g_hOpenSSLCommon, "SHA384"))\r
242                 || !(p_SHA512 = (_SHA512)GetProcAddress(g_hOpenSSLCommon, "SHA512")))\r
243         {\r
244                 if(g_hOpenSSL)\r
245                         FreeLibrary(g_hOpenSSL);\r
246                 g_hOpenSSL = NULL;\r
247                 if(g_hOpenSSLCommon)\r
248                         FreeLibrary(g_hOpenSSLCommon);\r
249                 g_hOpenSSLCommon = NULL;\r
250                 return FALSE;\r
251         }\r
252         InitializeCriticalSection(&g_OpenSSLLock);\r
253         // OpenSSL 1.1.0対応\r
254 //      p_SSL_load_error_strings();\r
255         p_OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CRYPTO_STRINGS | OPENSSL_INIT_LOAD_SSL_STRINGS, NULL);\r
256 //      p_SSL_library_init();\r
257         p_OPENSSL_init_ssl(0, NULL);\r
258         SetSSLTimeoutCallback(60000, DefaultSSLTimeoutCallback);\r
259         SetSSLConfirmCallback(DefaultSSLConfirmCallback);\r
260         g_bOpenSSLLoaded = TRUE;\r
261         return TRUE;\r
262 }\r
263 \r
264 // OpenSSLを解放\r
265 void FreeOpenSSL()\r
266 {\r
267         int i;\r
268         if(!g_bOpenSSLLoaded)\r
269                 return;\r
270         EnterCriticalSection(&g_OpenSSLLock);\r
271         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
272         {\r
273                 if(g_pOpenSSLHandle[i])\r
274                 {\r
275                         p_SSL_shutdown(g_pOpenSSLHandle[i]);\r
276                         p_SSL_free(g_pOpenSSLHandle[i]);\r
277                         g_pOpenSSLHandle[i] = NULL;\r
278                 }\r
279         }\r
280         if(g_pOpenSSLCTX)\r
281                 p_SSL_CTX_free(g_pOpenSSLCTX);\r
282         g_pOpenSSLCTX = NULL;\r
283         // OpenSSL 1.1.0対応\r
284 //      FreeLibrary(g_hOpenSSL);\r
285 //      g_hOpenSSL = NULL;\r
286 //      FreeLibrary(g_hOpenSSLCommon);\r
287 //      g_hOpenSSLCommon = NULL;\r
288         FreeLibrary(g_hOpenSSLCommon);\r
289         g_hOpenSSLCommon = NULL;\r
290         FreeLibrary(g_hOpenSSL);\r
291         g_hOpenSSL = NULL;\r
292         LeaveCriticalSection(&g_OpenSSLLock);\r
293         DeleteCriticalSection(&g_OpenSSLLock);\r
294         g_bOpenSSLLoaded = FALSE;\r
295 }\r
296 \r
297 // OpenSSLが使用可能かどうか確認\r
298 BOOL IsOpenSSLLoaded()\r
299 {\r
300         return g_bOpenSSLLoaded;\r
301 }\r
302 \r
303 SSL** GetUnusedSSLPointer()\r
304 {\r
305         int i;\r
306         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
307         {\r
308                 if(!g_pOpenSSLHandle[i])\r
309                         return &g_pOpenSSLHandle[i];\r
310         }\r
311         return NULL;\r
312 }\r
313 \r
314 SSL** FindSSLPointerFromSocket(SOCKET s)\r
315 {\r
316         int i;\r
317         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
318         {\r
319                 if(g_pOpenSSLHandle[i])\r
320                 {\r
321                         if(p_SSL_get_fd(g_pOpenSSLHandle[i]) == s)\r
322                                 return &g_pOpenSSLHandle[i];\r
323                 }\r
324         }\r
325         return NULL;\r
326 }\r
327 \r
328 BOOL ConfirmSSLCertificate(SSL* pSSL, BOOL* pbAborted)\r
329 {\r
330         BOOL bResult;\r
331         BOOL bVerified;\r
332         char* pData;\r
333         char* pSubject;\r
334         X509* pX509;\r
335         BIO* pBIO;\r
336         long Length;\r
337         char* pBuffer;\r
338         char* pCN;\r
339         char* p;\r
340         bResult = FALSE;\r
341         bVerified = FALSE;\r
342         pData = NULL;\r
343         pSubject = NULL;\r
344         if(pX509 = p_SSL_get_peer_certificate(pSSL))\r
345         {\r
346                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
347                 {\r
348                         p_X509_print_ex(pBIO, pX509, 0, XN_FLAG_RFC2253);\r
349                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
350                         {\r
351                                 if(pData = (char*)malloc(Length + sizeof(char)))\r
352                                 {\r
353                                         memcpy(pData, pBuffer, Length);\r
354                                         *(char*)((size_t)pData + Length) = '\0';\r
355                                 }\r
356                         }\r
357                         p_BIO_free(pBIO);\r
358                 }\r
359                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
360                 {\r
361                         p_X509_NAME_print_ex(pBIO, p_X509_get_subject_name(pX509), 0, XN_FLAG_RFC2253);\r
362                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
363                         {\r
364                                 if(pSubject = (char*)malloc(Length + sizeof(char)))\r
365                                 {\r
366                                         memcpy(pSubject, pBuffer, Length);\r
367                                         *(char*)((size_t)pSubject + Length) = '\0';\r
368                                 }\r
369                         }\r
370                         p_BIO_free(pBIO);\r
371                 }\r
372                 p_X509_free(pX509);\r
373         }\r
374         if(pX509 && p_SSL_get_verify_result(pSSL) == X509_V_OK)\r
375                 bVerified = TRUE;\r
376         pCN = pSubject;\r
377         while(pCN)\r
378         {\r
379                 if(strncmp(pCN, "CN=", strlen("CN=")) == 0)\r
380                 {\r
381                         pCN += strlen("CN=");\r
382                         if(p = strchr(pCN, ','))\r
383                                 *p = '\0';\r
384                         break;\r
385                 }\r
386                 if(pCN = strchr(pCN, ','))\r
387                         pCN++;\r
388         }\r
389         bResult = g_pOpenSSLConfirmCallback(pbAborted, bVerified, pData, pCN);\r
390         if(pData)\r
391                 free(pData);\r
392         if(pSubject)\r
393                 free(pSubject);\r
394         return bResult;\r
395 }\r
396 \r
397 void SetSSLTimeoutCallback(DWORD Timeout, LPSSLTIMEOUTCALLBACK pCallback)\r
398 {\r
399         if(!g_bOpenSSLLoaded)\r
400                 return;\r
401         EnterCriticalSection(&g_OpenSSLLock);\r
402         g_OpenSSLTimeout = Timeout;\r
403         g_pOpenSSLTimeoutCallback = pCallback;\r
404         LeaveCriticalSection(&g_OpenSSLLock);\r
405 }\r
406 \r
407 void SetSSLConfirmCallback(LPSSLCONFIRMCALLBACK pCallback)\r
408 {\r
409         if(!g_bOpenSSLLoaded)\r
410                 return;\r
411         EnterCriticalSection(&g_OpenSSLLock);\r
412         g_pOpenSSLConfirmCallback = pCallback;\r
413         LeaveCriticalSection(&g_OpenSSLLock);\r
414 }\r
415 \r
416 // SSLルート証明書を設定\r
417 // PEM形式のみ指定可能\r
418 BOOL SetSSLRootCertificate(const void* pData, DWORD Length)\r
419 {\r
420         BOOL r;\r
421         X509_STORE* pStore;\r
422         BYTE* p;\r
423         BYTE* pBegin;\r
424         BYTE* pEnd;\r
425         DWORD Left;\r
426         BIO* pBIO;\r
427         X509* pX509;\r
428         X509_CRL* pX509_CRL;\r
429         if(!g_bOpenSSLLoaded)\r
430                 return FALSE;\r
431         r = FALSE;\r
432         EnterCriticalSection(&g_OpenSSLLock);\r
433         if(!g_pOpenSSLCTX)\r
434         {\r
435                 // OpenSSL 1.1.0対応\r
436 //              g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
437                 g_pOpenSSLCTX = p_SSL_CTX_new(p_TLS_method());\r
438                 p_SSL_CTX_ctrl(g_pOpenSSLCTX, SSL_CTRL_MODE, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY, NULL);\r
439         }\r
440         if(g_pOpenSSLCTX)\r
441         {\r
442                 if(pStore = p_SSL_CTX_get_cert_store(g_pOpenSSLCTX))\r
443                 {\r
444                         p = (BYTE*)pData;\r
445                         pBegin = NULL;\r
446                         pEnd = NULL;\r
447                         Left = Length;\r
448                         while(Left > 0)\r
449                         {\r
450                                 if(!pBegin)\r
451                                 {\r
452                                         if(Left < 27)\r
453                                                 break;\r
454                                         if(memcmp(p, "-----BEGIN CERTIFICATE-----", 27) == 0)\r
455                                                 pBegin = p;\r
456                                 }\r
457                                 else if(!pEnd)\r
458                                 {\r
459                                         if(Left < 25)\r
460                                                 break;\r
461                                         if(memcmp(p, "-----END CERTIFICATE-----", 25) == 0)\r
462                                                 pEnd = p + 25;\r
463                                 }\r
464                                 if(pBegin && pEnd)\r
465                                 {\r
466                                         if(pBIO = p_BIO_new_mem_buf(pBegin, (int)((size_t)pEnd - (size_t)pBegin)))\r
467                                         {\r
468                                                 if(pX509 = p_PEM_read_bio_X509(pBIO, NULL, NULL, NULL))\r
469                                                 {\r
470                                                         if(p_X509_STORE_add_cert(pStore, pX509) == 1)\r
471                                                                 r = TRUE;\r
472                                                         p_X509_free(pX509);\r
473                                                 }\r
474                                                 p_BIO_free(pBIO);\r
475                                         }\r
476                                         pBegin = NULL;\r
477                                         pEnd = NULL;\r
478                                 }\r
479                                 p++;\r
480                                 Left--;\r
481                         }\r
482                         p = (BYTE*)pData;\r
483                         pBegin = NULL;\r
484                         pEnd = NULL;\r
485                         Left = Length;\r
486                         while(Left > 0)\r
487                         {\r
488                                 if(!pBegin)\r
489                                 {\r
490                                         if(Left < 24)\r
491                                                 break;\r
492                                         if(memcmp(p, "-----BEGIN X509 CRL-----", 24) == 0)\r
493                                                 pBegin = p;\r
494                                 }\r
495                                 else if(!pEnd)\r
496                                 {\r
497                                         if(Left < 22)\r
498                                                 break;\r
499                                         if(memcmp(p, "-----END X509 CRL-----", 22) == 0)\r
500                                                 pEnd = p + 22;\r
501                                 }\r
502                                 if(pBegin && pEnd)\r
503                                 {\r
504                                         if(pBIO = p_BIO_new_mem_buf(pBegin, (int)((size_t)pEnd - (size_t)pBegin)))\r
505                                         {\r
506                                                 if(pX509_CRL = p_PEM_read_bio_X509_CRL(pBIO, NULL, NULL, NULL))\r
507                                                 {\r
508                                                         if(p_X509_STORE_add_crl(pStore, pX509_CRL) == 1)\r
509                                                                 r = TRUE;\r
510                                                         p_X509_CRL_free(pX509_CRL);\r
511                                                 }\r
512                                                 p_BIO_free(pBIO);\r
513                                         }\r
514                                         pBegin = NULL;\r
515                                         pEnd = NULL;\r
516                                 }\r
517                                 p++;\r
518                                 Left--;\r
519                         }\r
520                 }\r
521         }\r
522         LeaveCriticalSection(&g_OpenSSLLock);\r
523         return r;\r
524 }\r
525 \r
526 // ワイルドカードの比較\r
527 // 主にSSL証明書のCN確認用\r
528 BOOL IsHostNameMatched(LPCSTR HostName, LPCSTR CommonName)\r
529 {\r
530         BOOL bResult;\r
531         const char* pAsterisk;\r
532         size_t BeforeAsterisk;\r
533         const char* pBeginAsterisk;\r
534         const char* pEndAsterisk;\r
535         const char* pDot;\r
536         bResult = FALSE;\r
537         if(HostName && CommonName)\r
538         {\r
539                 if(pAsterisk = strchr(CommonName, '*'))\r
540                 {\r
541                         BeforeAsterisk = ((size_t)pAsterisk - (size_t)CommonName) / sizeof(char);\r
542                         pBeginAsterisk = HostName + BeforeAsterisk;\r
543                         while(*pAsterisk == '*')\r
544                         {\r
545                                 pAsterisk++;\r
546                         }\r
547                         pEndAsterisk = HostName + strlen(HostName) - strlen(pAsterisk);\r
548                         // "*"より前は大文字小文字を無視して完全一致\r
549                         if(_strnicmp(HostName, CommonName, BeforeAsterisk) == 0)\r
550                         {\r
551                                 // "*"より後は大文字小文字を無視して完全一致\r
552                                 if(_stricmp(pEndAsterisk, pAsterisk) == 0)\r
553                                 {\r
554                                         // "*"と一致する範囲に"."が含まれてはならない\r
555                                         pDot = strchr(pBeginAsterisk, '.');\r
556                                         if(!pDot || pDot >= pEndAsterisk)\r
557                                                 bResult = TRUE;\r
558                                 }\r
559                         }\r
560                 }\r
561                 else if(_stricmp(HostName, CommonName) == 0)\r
562                         bResult = TRUE;\r
563         }\r
564         return bResult;\r
565 }\r
566 \r
567 #pragma warning(push)\r
568 #pragma warning(disable:4090)\r
569 \r
570 // RSA暗号化\r
571 BOOL EncryptSignature(const char* PrivateKey, const char* Password, const void* pIn, DWORD InLength, void* pOut, DWORD OutLength, DWORD* pOutLength)\r
572 {\r
573         BOOL bResult;\r
574         BIO* pBIO;\r
575         EVP_PKEY* pPKEY;\r
576         RSA* pRSA;\r
577         int i;\r
578         if(!g_bOpenSSLLoaded)\r
579                 return FALSE;\r
580         bResult = FALSE;\r
581         if(pBIO = p_BIO_new_mem_buf((void*)PrivateKey, sizeof(char) * strlen(PrivateKey)))\r
582         {\r
583                 if(pPKEY = p_PEM_read_bio_PrivateKey(pBIO, NULL, NULL, (void*)Password))\r
584                 {\r
585                         if(pRSA = p_EVP_PKEY_get1_RSA(pPKEY))\r
586                         {\r
587                                 if(p_RSA_size(pRSA) <= (int)OutLength)\r
588                                 {\r
589                                         i = p_RSA_private_encrypt((int)InLength, (const unsigned char*)pIn, (unsigned char*)pOut, pRSA, RSA_PKCS1_PADDING);\r
590                                         if(i >= 0)\r
591                                         {\r
592                                                 *pOutLength = (DWORD)i;\r
593                                                 bResult = TRUE;\r
594                                         }\r
595                                 }\r
596                                 p_RSA_free(pRSA);\r
597                         }\r
598                         p_EVP_PKEY_free(pPKEY);\r
599                 }\r
600                 p_BIO_free(pBIO);\r
601         }\r
602         return bResult;\r
603 }\r
604 \r
605 // RSA復号化\r
606 // 主に自動更新ファイルのハッシュの改竄確認\r
607 BOOL DecryptSignature(const char* PublicKey, const char* Password, const void* pIn, DWORD InLength, void* pOut, DWORD OutLength, DWORD* pOutLength)\r
608 {\r
609         BOOL bResult;\r
610         BIO* pBIO;\r
611         EVP_PKEY* pPKEY;\r
612         RSA* pRSA;\r
613         int i;\r
614         if(!g_bOpenSSLLoaded)\r
615                 return FALSE;\r
616         bResult = FALSE;\r
617         if(pBIO = p_BIO_new_mem_buf((void*)PublicKey, sizeof(char) * strlen(PublicKey)))\r
618         {\r
619                 if(pPKEY = p_PEM_read_bio_PUBKEY(pBIO, NULL, NULL, Password))\r
620                 {\r
621                         if(pRSA = p_EVP_PKEY_get1_RSA(pPKEY))\r
622                         {\r
623                                 if(p_RSA_size(pRSA) <= (int)OutLength)\r
624                                 {\r
625                                         i = p_RSA_public_decrypt((int)InLength, (const unsigned char*)pIn, (unsigned char*)pOut, pRSA, RSA_PKCS1_PADDING);\r
626                                         if(i >= 0)\r
627                                         {\r
628                                                 *pOutLength = (DWORD)i;\r
629                                                 bResult = TRUE;\r
630                                         }\r
631                                 }\r
632                                 p_RSA_free(pRSA);\r
633                         }\r
634                         p_EVP_PKEY_free(pPKEY);\r
635                 }\r
636                 p_BIO_free(pBIO);\r
637         }\r
638         return bResult;\r
639 }\r
640 \r
641 #pragma warning(pop)\r
642 \r
643 // ハッシュ計算\r
644 // 他にも同等の関数はあるが主にマルウェア対策のための冗長化\r
645 BOOL GetHashSHA1(const void* pData, DWORD Size, void* pHash)\r
646 {\r
647         if(!g_bOpenSSLLoaded)\r
648                 return FALSE;\r
649         p_SHA1((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
650         return TRUE;\r
651 }\r
652 \r
653 BOOL GetHashSHA224(const void* pData, DWORD Size, void* pHash)\r
654 {\r
655         if(!g_bOpenSSLLoaded)\r
656                 return FALSE;\r
657         p_SHA224((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
658         return TRUE;\r
659 }\r
660 \r
661 BOOL GetHashSHA256(const void* pData, DWORD Size, void* pHash)\r
662 {\r
663         if(!g_bOpenSSLLoaded)\r
664                 return FALSE;\r
665         p_SHA256((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
666         return TRUE;\r
667 }\r
668 \r
669 BOOL GetHashSHA384(const void* pData, DWORD Size, void* pHash)\r
670 {\r
671         if(!g_bOpenSSLLoaded)\r
672                 return FALSE;\r
673         p_SHA384((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
674         return TRUE;\r
675 }\r
676 \r
677 BOOL GetHashSHA512(const void* pData, DWORD Size, void* pHash)\r
678 {\r
679         if(!g_bOpenSSLLoaded)\r
680                 return FALSE;\r
681         p_SHA512((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
682         return TRUE;\r
683 }\r
684 \r
685 // SSLセッションを開始\r
686 BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted, BOOL bStrengthen)\r
687 {\r
688         BOOL r;\r
689         DWORD Time;\r
690         SSL** ppSSL;\r
691         BOOL bInherited;\r
692         SSL** ppSSLParent;\r
693         SSL_SESSION* pSession;\r
694         int Return;\r
695         int Error;\r
696         if(!g_bOpenSSLLoaded)\r
697                 return FALSE;\r
698         r = FALSE;\r
699         Time = timeGetTime();\r
700         EnterCriticalSection(&g_OpenSSLLock);\r
701         if(!g_pOpenSSLCTX)\r
702         {\r
703                 // OpenSSL 1.1.0対応\r
704 //              g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
705                 g_pOpenSSLCTX = p_SSL_CTX_new(p_TLS_method());\r
706                 p_SSL_CTX_ctrl(g_pOpenSSLCTX, SSL_CTRL_MODE, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY, NULL);\r
707         }\r
708         if(g_pOpenSSLCTX)\r
709         {\r
710                 if(ppSSL = GetUnusedSSLPointer())\r
711                 {\r
712                         if(*ppSSL = p_SSL_new(g_pOpenSSLCTX))\r
713                         {\r
714                                 if(p_SSL_set_fd(*ppSSL, s) != 0)\r
715                                 {\r
716                                         bInherited = FALSE;\r
717                                         if(parent != INVALID_SOCKET)\r
718                                         {\r
719                                                 if(ppSSLParent = FindSSLPointerFromSocket(parent))\r
720                                                 {\r
721                                                         if(pSession = p_SSL_get_session(*ppSSLParent))\r
722                                                         {\r
723                                                                 if(p_SSL_set_session(*ppSSL, pSession) == 1)\r
724                                                                         bInherited = TRUE;\r
725                                                         }\r
726                                                 }\r
727                                         }\r
728                                         if(!bInherited)\r
729                                         {\r
730                                                 if(bStrengthen)\r
731                                                 {\r
732                                                         // OpenSSL 1.1.0対応\r
733 //                                                      p_SSL_ctrl(*ppSSL, SSL_CTRL_OPTIONS, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3, NULL);\r
734                                                         p_SSL_set_cipher_list(*ppSSL, "HIGH");\r
735                                                 }\r
736                                         }\r
737                                         // SSLのネゴシエーションには時間がかかる場合がある\r
738                                         r = TRUE;\r
739                                         while(r)\r
740                                         {\r
741                                                 Return = p_SSL_connect(*ppSSL);\r
742                                                 if(Return == 1)\r
743                                                         break;\r
744                                                 Error = p_SSL_get_error(*ppSSL, Return);\r
745                                                 if(Error == SSL_ERROR_WANT_READ || Error == SSL_ERROR_WANT_WRITE)\r
746                                                 {\r
747                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
748                                                         if(g_pOpenSSLTimeoutCallback(pbAborted) || (g_OpenSSLTimeout > 0 && timeGetTime() - Time >= g_OpenSSLTimeout))\r
749                                                                 r = FALSE;\r
750                                                         EnterCriticalSection(&g_OpenSSLLock);\r
751                                                 }\r
752                                                 else\r
753                                                         r = FALSE;\r
754                                         }\r
755                                         if(r)\r
756                                         {\r
757                                                 if(ConfirmSSLCertificate(*ppSSL, pbAborted))\r
758                                                 {\r
759                                                 }\r
760                                                 else\r
761                                                 {\r
762                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
763                                                         DetachSSL(s);\r
764                                                         r = FALSE;\r
765                                                         EnterCriticalSection(&g_OpenSSLLock);\r
766                                                 }\r
767                                         }\r
768                                         else\r
769                                         {\r
770                                                 LeaveCriticalSection(&g_OpenSSLLock);\r
771                                                 DetachSSL(s);\r
772                                                 EnterCriticalSection(&g_OpenSSLLock);\r
773                                         }\r
774                                 }\r
775                                 else\r
776                                 {\r
777                                         LeaveCriticalSection(&g_OpenSSLLock);\r
778                                         DetachSSL(s);\r
779                                         EnterCriticalSection(&g_OpenSSLLock);\r
780                                 }\r
781                         }\r
782                 }\r
783         }\r
784         LeaveCriticalSection(&g_OpenSSLLock);\r
785         return r;\r
786 }\r
787 \r
788 // SSLセッションを終了\r
789 BOOL DetachSSL(SOCKET s)\r
790 {\r
791         BOOL r;\r
792         SSL** ppSSL;\r
793         if(!g_bOpenSSLLoaded)\r
794                 return FALSE;\r
795         r = FALSE;\r
796         EnterCriticalSection(&g_OpenSSLLock);\r
797         if(ppSSL = FindSSLPointerFromSocket(s))\r
798         {\r
799                 p_SSL_shutdown(*ppSSL);\r
800                 p_SSL_free(*ppSSL);\r
801                 *ppSSL = NULL;\r
802                 r = TRUE;\r
803         }\r
804         LeaveCriticalSection(&g_OpenSSLLock);\r
805         return r;\r
806 }\r
807 \r
808 // SSLとしてマークされているか確認\r
809 // マークされていればTRUEを返す\r
810 BOOL IsSSLAttached(SOCKET s)\r
811 {\r
812         SSL** ppSSL;\r
813         if(!g_bOpenSSLLoaded)\r
814                 return FALSE;\r
815         EnterCriticalSection(&g_OpenSSLLock);\r
816         ppSSL = FindSSLPointerFromSocket(s);\r
817         LeaveCriticalSection(&g_OpenSSLLock);\r
818         if(!ppSSL)\r
819                 return FALSE;\r
820         return TRUE;\r
821 }\r
822 \r
823 SOCKET FTPS_socket(int af, int type, int protocol)\r
824 {\r
825         return socket(af, type, protocol);\r
826 }\r
827 \r
828 int FTPS_bind(SOCKET s, const struct sockaddr *addr, int namelen)\r
829 {\r
830         return bind(s, addr, namelen);\r
831 }\r
832 \r
833 int FTPS_listen(SOCKET s, int backlog)\r
834 {\r
835         return listen(s, backlog);\r
836 }\r
837 \r
838 // accept相当の関数\r
839 // ただし初めからSSLのネゴシエーションを行う\r
840 SOCKET FTPS_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
841 {\r
842         SOCKET r;\r
843         BOOL bAborted;\r
844         r = accept(s, addr, addrlen);\r
845         bAborted = FALSE;\r
846         if(!AttachSSL(r, INVALID_SOCKET, &bAborted, TRUE))\r
847         {\r
848                 closesocket(r);\r
849                 return INVALID_SOCKET;\r
850         }\r
851         return r;\r
852 }\r
853 \r
854 // connect相当の関数\r
855 // ただし初めからSSLのネゴシエーションを行う\r
856 int FTPS_connect(SOCKET s, const struct sockaddr *name, int namelen)\r
857 {\r
858         int r;\r
859         BOOL bAborted;\r
860         r = connect(s, name, namelen);\r
861         bAborted = FALSE;\r
862         if(!AttachSSL(r, INVALID_SOCKET, &bAborted, TRUE))\r
863                 return SOCKET_ERROR;\r
864         return r;\r
865 }\r
866 \r
867 // closesocket相当の関数\r
868 int FTPS_closesocket(SOCKET s)\r
869 {\r
870         DetachSSL(s);\r
871         return closesocket(s);\r
872 }\r
873 \r
874 // send相当の関数\r
875 int FTPS_send(SOCKET s, const char * buf, int len, int flags)\r
876 {\r
877         int r;\r
878         SSL** ppSSL;\r
879         if(!g_bOpenSSLLoaded)\r
880                 return send(s, buf, len, flags);\r
881         EnterCriticalSection(&g_OpenSSLLock);\r
882         ppSSL = FindSSLPointerFromSocket(s);\r
883         LeaveCriticalSection(&g_OpenSSLLock);\r
884         if(!ppSSL)\r
885                 return send(s, buf, len, flags);\r
886         r = p_SSL_write(*ppSSL, buf, len);\r
887         if(r < 0)\r
888                 return SOCKET_ERROR;\r
889         return r;\r
890 }\r
891 \r
892 // recv相当の関数\r
893 int FTPS_recv(SOCKET s, char * buf, int len, int flags)\r
894 {\r
895         int r;\r
896         SSL** ppSSL;\r
897         if(!g_bOpenSSLLoaded)\r
898                 return recv(s, buf, len, flags);\r
899         EnterCriticalSection(&g_OpenSSLLock);\r
900         ppSSL = FindSSLPointerFromSocket(s);\r
901         LeaveCriticalSection(&g_OpenSSLLock);\r
902         if(!ppSSL)\r
903                 return recv(s, buf, len, flags);\r
904         if(flags & MSG_PEEK)\r
905                 r = p_SSL_peek(*ppSSL, buf, len);\r
906         else\r
907                 r = p_SSL_read(*ppSSL, buf, len);\r
908         if(r < 0)\r
909                 return SOCKET_ERROR;\r
910         return r;\r
911 }\r
912 \r
913 // IPv6対応\r
914 \r
915 const struct in6_addr IN6ADDR_NONE = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};\r
916 \r
917 typedef struct\r
918 {\r
919         HANDLE h;\r
920         HWND hWnd;\r
921         u_int wMsg;\r
922         char * name;\r
923         char * buf;\r
924         int buflen;\r
925         short Family;\r
926 } GETHOSTBYNAMEDATA;\r
927 \r
928 DWORD WINAPI WSAAsyncGetHostByNameIPv6ThreadProc(LPVOID lpParameter)\r
929 {\r
930         GETHOSTBYNAMEDATA* pData;\r
931         struct hostent* pHost;\r
932         struct addrinfo* pAddr;\r
933         struct addrinfo* p;\r
934         pHost = NULL;\r
935         pData = (GETHOSTBYNAMEDATA*)lpParameter;\r
936         if(getaddrinfo(pData->name, NULL, NULL, &pAddr) == 0)\r
937         {\r
938                 p = pAddr;\r
939                 while(p)\r
940                 {\r
941                         if(p->ai_family == pData->Family)\r
942                         {\r
943                                 switch(p->ai_family)\r
944                                 {\r
945                                 case AF_INET:\r
946                                         pHost = (struct hostent*)pData->buf;\r
947                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in_addr)\r
948                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in))\r
949                                         {\r
950                                                 pHost->h_name = NULL;\r
951                                                 pHost->h_aliases = NULL;\r
952                                                 pHost->h_addrtype = p->ai_family;\r
953                                                 pHost->h_length = sizeof(struct in_addr);\r
954                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
955                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
956                                                 pHost->h_addr_list[1] = NULL;\r
957                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in*)p->ai_addr)->sin_addr, sizeof(struct in_addr));\r
958                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in_addr)));\r
959                                         }\r
960                                         else\r
961                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
962                                         break;\r
963                                 case AF_INET6:\r
964                                         pHost = (struct hostent*)pData->buf;\r
965                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in6_addr)\r
966                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in6))\r
967                                         {\r
968                                                 pHost->h_name = NULL;\r
969                                                 pHost->h_aliases = NULL;\r
970                                                 pHost->h_addrtype = p->ai_family;\r
971                                                 pHost->h_length = sizeof(struct in6_addr);\r
972                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
973                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
974                                                 pHost->h_addr_list[1] = NULL;\r
975                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in6*)p->ai_addr)->sin6_addr, sizeof(struct in6_addr));\r
976                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in6_addr)));\r
977                                         }\r
978                                         else\r
979                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
980                                         break;\r
981                                 }\r
982                         }\r
983                         if(pHost)\r
984                                 break;\r
985                         p = p->ai_next;\r
986                 }\r
987                 if(!p)\r
988                         PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
989                 freeaddrinfo(pAddr);\r
990         }\r
991         else\r
992                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
993         // CreateThreadが返すハンドルが重複するのを回避\r
994         Sleep(10000);\r
995         CloseHandle(pData->h);\r
996         free(pData->name);\r
997         free(pData);\r
998         return 0;\r
999 }\r
1000 \r
1001 // IPv6対応のWSAAsyncGetHostByName相当の関数\r
1002 // FamilyにはAF_INETまたはAF_INET6を指定可能\r
1003 // ただしANSI用\r
1004 HANDLE WSAAsyncGetHostByNameIPv6(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
1005 {\r
1006         HANDLE hResult;\r
1007         GETHOSTBYNAMEDATA* pData;\r
1008         hResult = NULL;\r
1009         if(pData = malloc(sizeof(GETHOSTBYNAMEDATA)))\r
1010         {\r
1011                 pData->hWnd = hWnd;\r
1012                 pData->wMsg = wMsg;\r
1013                 if(pData->name = malloc(sizeof(char) * (strlen(name) + 1)))\r
1014                 {\r
1015                         strcpy(pData->name, name);\r
1016                         pData->buf = buf;\r
1017                         pData->buflen = buflen;\r
1018                         pData->Family = Family;\r
1019                         if(pData->h = CreateThread(NULL, 0, WSAAsyncGetHostByNameIPv6ThreadProc, pData, CREATE_SUSPENDED, NULL))\r
1020                         {\r
1021                                 ResumeThread(pData->h);\r
1022                                 hResult = pData->h;\r
1023                         }\r
1024                 }\r
1025         }\r
1026         if(!hResult)\r
1027         {\r
1028                 if(pData)\r
1029                 {\r
1030                         if(pData->name)\r
1031                                 free(pData->name);\r
1032                         free(pData);\r
1033                 }\r
1034         }\r
1035         return hResult;\r
1036 }\r
1037 \r
1038 // WSAAsyncGetHostByNameIPv6用のWSACancelAsyncRequest相当の関数\r
1039 int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle)\r
1040 {\r
1041         int Result;\r
1042         Result = SOCKET_ERROR;\r
1043         if(TerminateThread(hAsyncTaskHandle, 0))\r
1044         {\r
1045                 CloseHandle(hAsyncTaskHandle);\r
1046                 Result = 0;\r
1047         }\r
1048         return Result;\r
1049 }\r
1050 \r
1051 char* AddressToStringIPv4(char* str, void* in)\r
1052 {\r
1053         char* pResult;\r
1054         unsigned char* p;\r
1055         pResult = str;\r
1056         p = (unsigned char*)in;\r
1057         sprintf(str, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);\r
1058         return pResult;\r
1059 }\r
1060 \r
1061 char* AddressToStringIPv6(char* str, void* in6)\r
1062 {\r
1063         char* pResult;\r
1064         unsigned char* p;\r
1065         int MaxZero;\r
1066         int MaxZeroLen;\r
1067         int i;\r
1068         int j;\r
1069         char Tmp[5];\r
1070         pResult = str;\r
1071         p = (unsigned char*)in6;\r
1072         MaxZero = 8;\r
1073         MaxZeroLen = 1;\r
1074         for(i = 0; i < 8; i++)\r
1075         {\r
1076                 for(j = i; j < 8; j++)\r
1077                 {\r
1078                         if(p[j * 2] != 0 || p[j * 2 + 1] != 0)\r
1079                                 break;\r
1080                 }\r
1081                 if(j - i > MaxZeroLen)\r
1082                 {\r
1083                         MaxZero = i;\r
1084                         MaxZeroLen = j - i;\r
1085                 }\r
1086         }\r
1087         strcpy(str, "");\r
1088         for(i = 0; i < 8; i++)\r
1089         {\r
1090                 if(i == MaxZero)\r
1091                 {\r
1092                         if(i == 0)\r
1093                                 strcat(str, ":");\r
1094                         strcat(str, ":");\r
1095                 }\r
1096                 else if(i < MaxZero || i >= MaxZero + MaxZeroLen)\r
1097                 {\r
1098                         sprintf(Tmp, "%x", (((int)p[i * 2] & 0xff) << 8) | ((int)p[i * 2 + 1] & 0xff));\r
1099                         strcat(str, Tmp);\r
1100                         if(i < 7)\r
1101                                 strcat(str, ":");\r
1102                 }\r
1103         }\r
1104         return pResult;\r
1105 }\r
1106 \r
1107 // IPv6対応のinet_ntoa相当の関数\r
1108 // ただしANSI用\r
1109 char* inet6_ntoa(struct in6_addr in6)\r
1110 {\r
1111         char* pResult;\r
1112         static char Adrs[40];\r
1113         pResult = NULL;\r
1114         memset(Adrs, 0, sizeof(Adrs));\r
1115         pResult = AddressToStringIPv6(Adrs, &in6);\r
1116         return pResult;\r
1117 }\r
1118 \r
1119 // IPv6対応のinet_addr相当の関数\r
1120 // ただしANSI用\r
1121 struct in6_addr inet6_addr(const char* cp)\r
1122 {\r
1123         struct in6_addr Result;\r
1124         int AfterZero;\r
1125         int i;\r
1126         char* p;\r
1127         memset(&Result, 0, sizeof(Result));\r
1128         AfterZero = 0;\r
1129         for(i = 0; i < 8; i++)\r
1130         {\r
1131                 if(!cp)\r
1132                 {\r
1133                         memcpy(&Result, &IN6ADDR_NONE, sizeof(struct in6_addr));\r
1134                         break;\r
1135                 }\r
1136                 if(i >= AfterZero)\r
1137                 {\r
1138                         if(strncmp(cp, ":", 1) == 0)\r
1139                         {\r
1140                                 cp = cp + 1;\r
1141                                 if(i == 0 && strncmp(cp, ":", 1) == 0)\r
1142                                         cp = cp + 1;\r
1143                                 p = (char*)cp;\r
1144                                 AfterZero = 7;\r
1145                                 while(p = strstr(p, ":"))\r
1146                                 {\r
1147                                         p = p + 1;\r
1148                                         AfterZero--;\r
1149                                 }\r
1150                         }\r
1151                         else\r
1152                         {\r
1153                                 Result.u.Word[i] = (USHORT)strtol(cp, &p, 16);\r
1154                                 Result.u.Word[i] = ((Result.u.Word[i] & 0xff00) >> 8) | ((Result.u.Word[i] & 0x00ff) << 8);\r
1155                                 if(strncmp(p, ":", 1) != 0 && strlen(p) > 0)\r
1156                                 {\r
1157                                         memcpy(&Result, &IN6ADDR_NONE, sizeof(struct in6_addr));\r
1158                                         break;\r
1159                                 }\r
1160                                 if(cp = strstr(cp, ":"))\r
1161                                         cp = cp + 1;\r
1162                         }\r
1163                 }\r
1164         }\r
1165         return Result;\r
1166 }\r
1167 \r
1168 BOOL ConvertDomainNameToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
1169 {\r
1170         BOOL bResult;\r
1171         punycode_uint* pUnicode;\r
1172         punycode_uint* p;\r
1173         BOOL bNeeded;\r
1174         LPCSTR InputString;\r
1175         punycode_uint Length;\r
1176         punycode_uint OutputLength;\r
1177         bResult = FALSE;\r
1178         if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
1179         {\r
1180                 p = pUnicode;\r
1181                 bNeeded = FALSE;\r
1182                 InputString = Input;\r
1183                 Length = 0;\r
1184                 while(*InputString != '\0')\r
1185                 {\r
1186                         *p = (punycode_uint)GetNextCharM(InputString, NULL, &InputString);\r
1187                         if(*p >= 0x80)\r
1188                                 bNeeded = TRUE;\r
1189                         p++;\r
1190                         Length++;\r
1191                 }\r
1192                 if(bNeeded)\r
1193                 {\r
1194                         if(Count >= strlen("xn--") + 1)\r
1195                         {\r
1196                                 strcpy(Output, "xn--");\r
1197                                 OutputLength = Count - strlen("xn--");\r
1198                                 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
1199                                 {\r
1200                                         Output[strlen("xn--") + OutputLength] = '\0';\r
1201                                         bResult = TRUE;\r
1202                                 }\r
1203                         }\r
1204                 }\r
1205                 free(pUnicode);\r
1206         }\r
1207         if(!bResult)\r
1208         {\r
1209                 if(Count >= strlen(Input) + 1)\r
1210                 {\r
1211                         strcpy(Output, Input);\r
1212                         bResult = TRUE;\r
1213                 }\r
1214         }\r
1215         return bResult;\r
1216 }\r
1217 \r
1218 BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
1219 {\r
1220         BOOL bResult;\r
1221         DWORD Length;\r
1222         char* pm0;\r
1223         char* pm1;\r
1224         char* p;\r
1225         char* pNext;\r
1226         bResult = FALSE;\r
1227         Length = strlen(Input);\r
1228         if(pm0 = AllocateStringM(Length + 1))\r
1229         {\r
1230                 if(pm1 = AllocateStringM(Length * 4 + 1))\r
1231                 {\r
1232                         strcpy(pm0, Input);\r
1233                         p = pm0;\r
1234                         while(p)\r
1235                         {\r
1236                                 if(pNext = strchr(p, '.'))\r
1237                                 {\r
1238                                         *pNext = '\0';\r
1239                                         pNext++;\r
1240                                 }\r
1241                                 if(ConvertDomainNameToPunycode(pm1, Length * 4, p))\r
1242                                         strcat(Output, pm1);\r
1243                                 if(pNext)\r
1244                                         strcat(Output, ".");\r
1245                                 p = pNext;\r
1246                         }\r
1247                         bResult = TRUE;\r
1248                         FreeDuplicatedString(pm1);\r
1249                 }\r
1250                 FreeDuplicatedString(pm0);\r
1251         }\r
1252         return bResult;\r
1253 }\r
1254 \r
1255 HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
1256 {\r
1257         HANDLE r = NULL;\r
1258         char* pa0 = NULL;\r
1259         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1260         {\r
1261                 if(ConvertNameToPunycode(pa0, name))\r
1262                         r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
1263         }\r
1264         FreeDuplicatedString(pa0);\r
1265         return r;\r
1266 }\r
1267 \r
1268 HANDLE WSAAsyncGetHostByNameIPv6M(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
1269 {\r
1270         HANDLE r = NULL;\r
1271         char* pa0 = NULL;\r
1272         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1273         {\r
1274                 if(ConvertNameToPunycode(pa0, name))\r
1275                         r = WSAAsyncGetHostByNameIPv6(hWnd, wMsg, pa0, buf, buflen, Family);\r
1276         }\r
1277         FreeDuplicatedString(pa0);\r
1278         return r;\r
1279 }\r
1280 \r