OSDN Git Service

b862175ac61e8ddf7faf54f3739e9f4da9acb7d8
[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 typedef void (__cdecl* _SSL_load_error_strings)();\r
22 typedef int (__cdecl* _SSL_library_init)();\r
23 typedef SSL_METHOD* (__cdecl* _SSLv23_method)();\r
24 typedef SSL* (__cdecl* _SSL_new)(SSL_CTX*);\r
25 typedef void (__cdecl* _SSL_free)(SSL*);\r
26 typedef long (__cdecl* _SSL_ctrl)(SSL*, int, long, void*);\r
27 typedef int (__cdecl* _SSL_shutdown)(SSL*);\r
28 typedef int (__cdecl* _SSL_get_fd)(SSL*);\r
29 typedef int (__cdecl* _SSL_set_fd)(SSL*, int);\r
30 typedef int (__cdecl* _SSL_accept)(SSL*);\r
31 typedef int (__cdecl* _SSL_connect)(SSL*);\r
32 typedef int (__cdecl* _SSL_write)(SSL*, const void*, int);\r
33 typedef int (__cdecl* _SSL_peek)(SSL*, void*, int);\r
34 typedef int (__cdecl* _SSL_read)(SSL*, void*, int);\r
35 typedef int (__cdecl* _SSL_get_error)(SSL*, int);\r
36 typedef X509* (__cdecl* _SSL_get_peer_certificate)(const SSL*);\r
37 typedef long (__cdecl* _SSL_get_verify_result)(const SSL*);\r
38 typedef SSL_SESSION* (__cdecl* _SSL_get_session)(SSL*);\r
39 typedef int (__cdecl* _SSL_set_session)(SSL*, SSL_SESSION*);\r
40 typedef int (__cdecl* _SSL_set_cipher_list)(SSL*, const char*);\r
41 typedef SSL_CTX* (__cdecl* _SSL_CTX_new)(SSL_METHOD*);\r
42 typedef void (__cdecl* _SSL_CTX_free)(SSL_CTX*);\r
43 typedef X509_STORE* (__cdecl* _SSL_CTX_get_cert_store)(const SSL_CTX*);\r
44 typedef long (__cdecl* _SSL_CTX_ctrl)(SSL_CTX*, int, long, void*);\r
45 typedef BIO_METHOD* (__cdecl* _BIO_s_mem)();\r
46 typedef BIO* (__cdecl* _BIO_new)(BIO_METHOD*);\r
47 typedef int (__cdecl* _BIO_free)(BIO*);\r
48 typedef BIO* (__cdecl* _BIO_new_mem_buf)(void*, int);\r
49 typedef long (__cdecl* _BIO_ctrl)(BIO*, int, long, void*);\r
50 typedef void (__cdecl* _X509_free)(X509*);\r
51 typedef int (__cdecl* _X509_print_ex)(BIO*, X509*, unsigned long, unsigned long);\r
52 typedef X509_NAME* (__cdecl* _X509_get_subject_name)(X509*);\r
53 typedef int (__cdecl* _X509_NAME_print_ex)(BIO*, X509_NAME*, int, unsigned long);\r
54 typedef void (__cdecl* _X509_CRL_free)(X509_CRL*);\r
55 typedef EVP_PKEY* (__cdecl* _PEM_read_bio_PUBKEY)(BIO*, EVP_PKEY**, pem_password_cb*, void*);\r
56 typedef X509* (__cdecl* _PEM_read_bio_X509)(BIO*, X509**, pem_password_cb*, void*);\r
57 typedef X509_CRL* (__cdecl* _PEM_read_bio_X509_CRL)(BIO*, X509_CRL**, pem_password_cb*, void*);\r
58 typedef int (__cdecl* _X509_STORE_add_cert)(X509_STORE*, X509*);\r
59 typedef int (__cdecl* _X509_STORE_add_crl)(X509_STORE*, X509_CRL*);\r
60 typedef void (__cdecl* _EVP_PKEY_free)(EVP_PKEY*);\r
61 typedef RSA* (__cdecl* _EVP_PKEY_get1_RSA)(EVP_PKEY*);\r
62 typedef void (__cdecl* _RSA_free)(RSA*);\r
63 typedef int (__cdecl* _RSA_size)(const RSA*);\r
64 typedef int (__cdecl* _RSA_public_decrypt)(int, const unsigned char*, unsigned char*, RSA*, int);\r
65 typedef unsigned char* (__cdecl* _SHA1)(const unsigned char*, size_t, unsigned char*);\r
66 typedef unsigned char* (__cdecl* _SHA224)(const unsigned char*, size_t, unsigned char*);\r
67 typedef unsigned char* (__cdecl* _SHA256)(const unsigned char*, size_t, unsigned char*);\r
68 typedef unsigned char* (__cdecl* _SHA384)(const unsigned char*, size_t, unsigned char*);\r
69 typedef unsigned char* (__cdecl* _SHA512)(const unsigned char*, size_t, unsigned char*);\r
70 \r
71 _SSL_load_error_strings p_SSL_load_error_strings;\r
72 _SSL_library_init p_SSL_library_init;\r
73 _SSLv23_method p_SSLv23_method;\r
74 _SSL_new p_SSL_new;\r
75 _SSL_free p_SSL_free;\r
76 _SSL_ctrl p_SSL_ctrl;\r
77 _SSL_shutdown p_SSL_shutdown;\r
78 _SSL_get_fd p_SSL_get_fd;\r
79 _SSL_set_fd p_SSL_set_fd;\r
80 _SSL_accept p_SSL_accept;\r
81 _SSL_connect p_SSL_connect;\r
82 _SSL_write p_SSL_write;\r
83 _SSL_peek p_SSL_peek;\r
84 _SSL_read p_SSL_read;\r
85 _SSL_get_error p_SSL_get_error;\r
86 _SSL_get_peer_certificate p_SSL_get_peer_certificate;\r
87 _SSL_get_verify_result p_SSL_get_verify_result;\r
88 _SSL_get_session p_SSL_get_session;\r
89 _SSL_set_session p_SSL_set_session;\r
90 _SSL_set_cipher_list p_SSL_set_cipher_list;\r
91 _SSL_CTX_new p_SSL_CTX_new;\r
92 _SSL_CTX_free p_SSL_CTX_free;\r
93 _SSL_CTX_get_cert_store p_SSL_CTX_get_cert_store;\r
94 _SSL_CTX_ctrl p_SSL_CTX_ctrl;\r
95 _BIO_s_mem p_BIO_s_mem;\r
96 _BIO_new p_BIO_new;\r
97 _BIO_free p_BIO_free;\r
98 _BIO_new_mem_buf p_BIO_new_mem_buf;\r
99 _BIO_ctrl p_BIO_ctrl;\r
100 _X509_free p_X509_free;\r
101 _X509_print_ex p_X509_print_ex;\r
102 _X509_get_subject_name p_X509_get_subject_name;\r
103 _X509_NAME_print_ex p_X509_NAME_print_ex;\r
104 _X509_CRL_free p_X509_CRL_free;\r
105 _PEM_read_bio_PUBKEY p_PEM_read_bio_PUBKEY;\r
106 _PEM_read_bio_X509 p_PEM_read_bio_X509;\r
107 _PEM_read_bio_X509_CRL p_PEM_read_bio_X509_CRL;\r
108 _X509_STORE_add_cert p_X509_STORE_add_cert;\r
109 _X509_STORE_add_crl p_X509_STORE_add_crl;\r
110 _EVP_PKEY_free p_EVP_PKEY_free;\r
111 _EVP_PKEY_get1_RSA p_EVP_PKEY_get1_RSA;\r
112 _RSA_free p_RSA_free;\r
113 _RSA_size p_RSA_size;\r
114 _RSA_public_decrypt p_RSA_public_decrypt;\r
115 _SHA1 p_SHA1;\r
116 _SHA224 p_SHA224;\r
117 _SHA256 p_SHA256;\r
118 _SHA384 p_SHA384;\r
119 _SHA512 p_SHA512;\r
120 \r
121 #define MAX_SSL_SOCKET 16\r
122 \r
123 BOOL g_bOpenSSLLoaded;\r
124 HMODULE g_hOpenSSL;\r
125 HMODULE g_hOpenSSLCommon;\r
126 CRITICAL_SECTION g_OpenSSLLock;\r
127 DWORD g_OpenSSLTimeout;\r
128 LPSSLTIMEOUTCALLBACK g_pOpenSSLTimeoutCallback;\r
129 LPSSLCONFIRMCALLBACK g_pOpenSSLConfirmCallback;\r
130 SSL_CTX* g_pOpenSSLCTX;\r
131 SSL* g_pOpenSSLHandle[MAX_SSL_SOCKET];\r
132 \r
133 BOOL __stdcall DefaultSSLTimeoutCallback(BOOL* pbAborted)\r
134 {\r
135         Sleep(100);\r
136         return *pbAborted;\r
137 }\r
138 \r
139 BOOL __stdcall DefaultSSLConfirmCallback(BOOL* pbAborted, BOOL bVerified, LPCSTR Certificate, LPCSTR CommonName)\r
140 {\r
141         return bVerified;\r
142 }\r
143 \r
144 // OpenSSLを初期化\r
145 BOOL LoadOpenSSL()\r
146 {\r
147         if(g_bOpenSSLLoaded)\r
148                 return FALSE;\r
149 #ifdef ENABLE_PROCESS_PROTECTION\r
150         // 同梱するOpenSSLのバージョンに合わせてSHA1ハッシュ値を変更すること\r
151 #if defined(_M_IX86)\r
152         // ssleay32.dll 1.0.1h\r
153         RegisterTrustedModuleSHA1Hash("\x1B\x27\x4E\x29\x14\x78\x72\x0D\x33\x73\xD5\x98\xCF\xEA\x32\x07\x2B\x35\x69\x66");\r
154         // libeay32.dll 1.0.1h\r
155         RegisterTrustedModuleSHA1Hash("\x1D\x2E\x70\x49\x84\x2C\xE9\x1F\x64\xE8\x84\xD4\x62\x5B\xF4\x34\x9A\x0F\x82\xFC");\r
156 #elif defined(_M_AMD64)\r
157         // ssleay32.dll 1.0.1h\r
158         RegisterTrustedModuleSHA1Hash("\xB7\x5C\x31\xF3\x28\x73\xA0\x3C\x33\xDD\xBC\xB5\x8F\xD1\x38\xB6\xCE\x67\x4C\x40");\r
159         // libeay32.dll 1.0.1h\r
160         RegisterTrustedModuleSHA1Hash("\x5E\xBF\x56\x8C\xED\x06\xE8\x90\xE3\xC0\x3B\x6C\x51\x66\x4F\xC9\x9F\x1F\xF5\x89");\r
161 #endif\r
162 #endif\r
163         g_hOpenSSL = LoadLibrary("ssleay32.dll");\r
164         // バージョン固定のためlibssl32.dllの読み込みは脆弱性の原因になり得るので廃止\r
165 //      if(!g_hOpenSSL)\r
166 //              g_hOpenSSL = LoadLibrary("libssl32.dll");\r
167         if(!g_hOpenSSL\r
168                 || !(p_SSL_load_error_strings = (_SSL_load_error_strings)GetProcAddress(g_hOpenSSL, "SSL_load_error_strings"))\r
169                 || !(p_SSL_library_init = (_SSL_library_init)GetProcAddress(g_hOpenSSL, "SSL_library_init"))\r
170                 || !(p_SSLv23_method = (_SSLv23_method)GetProcAddress(g_hOpenSSL, "SSLv23_method"))\r
171                 || !(p_SSL_new = (_SSL_new)GetProcAddress(g_hOpenSSL, "SSL_new"))\r
172                 || !(p_SSL_free = (_SSL_free)GetProcAddress(g_hOpenSSL, "SSL_free"))\r
173                 || !(p_SSL_ctrl = (_SSL_ctrl)GetProcAddress(g_hOpenSSL, "SSL_ctrl"))\r
174                 || !(p_SSL_shutdown = (_SSL_shutdown)GetProcAddress(g_hOpenSSL, "SSL_shutdown"))\r
175                 || !(p_SSL_get_fd = (_SSL_get_fd)GetProcAddress(g_hOpenSSL, "SSL_get_fd"))\r
176                 || !(p_SSL_set_fd = (_SSL_set_fd)GetProcAddress(g_hOpenSSL, "SSL_set_fd"))\r
177                 || !(p_SSL_accept = (_SSL_accept)GetProcAddress(g_hOpenSSL, "SSL_accept"))\r
178                 || !(p_SSL_connect = (_SSL_connect)GetProcAddress(g_hOpenSSL, "SSL_connect"))\r
179                 || !(p_SSL_write = (_SSL_write)GetProcAddress(g_hOpenSSL, "SSL_write"))\r
180                 || !(p_SSL_peek = (_SSL_peek)GetProcAddress(g_hOpenSSL, "SSL_peek"))\r
181                 || !(p_SSL_read = (_SSL_read)GetProcAddress(g_hOpenSSL, "SSL_read"))\r
182                 || !(p_SSL_get_error = (_SSL_get_error)GetProcAddress(g_hOpenSSL, "SSL_get_error"))\r
183                 || !(p_SSL_get_peer_certificate = (_SSL_get_peer_certificate)GetProcAddress(g_hOpenSSL, "SSL_get_peer_certificate"))\r
184                 || !(p_SSL_get_verify_result = (_SSL_get_verify_result)GetProcAddress(g_hOpenSSL, "SSL_get_verify_result"))\r
185                 || !(p_SSL_get_session = (_SSL_get_session)GetProcAddress(g_hOpenSSL, "SSL_get_session"))\r
186                 || !(p_SSL_set_session = (_SSL_set_session)GetProcAddress(g_hOpenSSL, "SSL_set_session"))\r
187                 || !(p_SSL_set_cipher_list = (_SSL_set_cipher_list)GetProcAddress(g_hOpenSSL, "SSL_set_cipher_list"))\r
188                 || !(p_SSL_CTX_new = (_SSL_CTX_new)GetProcAddress(g_hOpenSSL, "SSL_CTX_new"))\r
189                 || !(p_SSL_CTX_free = (_SSL_CTX_free)GetProcAddress(g_hOpenSSL, "SSL_CTX_free"))\r
190                 || !(p_SSL_CTX_get_cert_store = (_SSL_CTX_get_cert_store)GetProcAddress(g_hOpenSSL, "SSL_CTX_get_cert_store"))\r
191                 || !(p_SSL_CTX_ctrl = (_SSL_CTX_ctrl)GetProcAddress(g_hOpenSSL, "SSL_CTX_ctrl")))\r
192         {\r
193                 if(g_hOpenSSL)\r
194                         FreeLibrary(g_hOpenSSL);\r
195                 g_hOpenSSL = NULL;\r
196                 return FALSE;\r
197         }\r
198         g_hOpenSSLCommon = LoadLibrary("libeay32.dll");\r
199         if(!g_hOpenSSLCommon\r
200                 || !(p_BIO_s_mem = (_BIO_s_mem)GetProcAddress(g_hOpenSSLCommon, "BIO_s_mem"))\r
201                 || !(p_BIO_new = (_BIO_new)GetProcAddress(g_hOpenSSLCommon, "BIO_new"))\r
202                 || !(p_BIO_free = (_BIO_free)GetProcAddress(g_hOpenSSLCommon, "BIO_free"))\r
203                 || !(p_BIO_new_mem_buf = (_BIO_new_mem_buf)GetProcAddress(g_hOpenSSLCommon, "BIO_new_mem_buf"))\r
204                 || !(p_BIO_ctrl = (_BIO_ctrl)GetProcAddress(g_hOpenSSLCommon, "BIO_ctrl"))\r
205                 || !(p_X509_free = (_X509_free)GetProcAddress(g_hOpenSSLCommon, "X509_free"))\r
206                 || !(p_X509_print_ex = (_X509_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_print_ex"))\r
207                 || !(p_X509_get_subject_name = (_X509_get_subject_name)GetProcAddress(g_hOpenSSLCommon, "X509_get_subject_name"))\r
208                 || !(p_X509_NAME_print_ex = (_X509_NAME_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_NAME_print_ex"))\r
209                 || !(p_X509_CRL_free = (_X509_CRL_free)GetProcAddress(g_hOpenSSLCommon, "X509_CRL_free"))\r
210                 || !(p_PEM_read_bio_PUBKEY = (_PEM_read_bio_PUBKEY)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_PUBKEY"))\r
211                 || !(p_PEM_read_bio_X509 = (_PEM_read_bio_X509)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_X509"))\r
212                 || !(p_PEM_read_bio_X509_CRL = (_PEM_read_bio_X509_CRL)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_X509_CRL"))\r
213                 || !(p_X509_STORE_add_cert = (_X509_STORE_add_cert)GetProcAddress(g_hOpenSSLCommon, "X509_STORE_add_cert"))\r
214                 || !(p_X509_STORE_add_crl = (_X509_STORE_add_crl)GetProcAddress(g_hOpenSSLCommon, "X509_STORE_add_crl"))\r
215                 || !(p_EVP_PKEY_free = (_EVP_PKEY_free)GetProcAddress(g_hOpenSSLCommon, "EVP_PKEY_free"))\r
216                 || !(p_EVP_PKEY_get1_RSA = (_EVP_PKEY_get1_RSA)GetProcAddress(g_hOpenSSLCommon, "EVP_PKEY_get1_RSA"))\r
217                 || !(p_RSA_free = (_RSA_free)GetProcAddress(g_hOpenSSLCommon, "RSA_free"))\r
218                 || !(p_RSA_size = (_RSA_size)GetProcAddress(g_hOpenSSLCommon, "RSA_size"))\r
219                 || !(p_RSA_public_decrypt = (_RSA_public_decrypt)GetProcAddress(g_hOpenSSLCommon, "RSA_public_decrypt"))\r
220                 || !(p_SHA1 = (_SHA1)GetProcAddress(g_hOpenSSLCommon, "SHA1"))\r
221                 || !(p_SHA224 = (_SHA224)GetProcAddress(g_hOpenSSLCommon, "SHA224"))\r
222                 || !(p_SHA256 = (_SHA256)GetProcAddress(g_hOpenSSLCommon, "SHA256"))\r
223                 || !(p_SHA384 = (_SHA384)GetProcAddress(g_hOpenSSLCommon, "SHA384"))\r
224                 || !(p_SHA512 = (_SHA512)GetProcAddress(g_hOpenSSLCommon, "SHA512")))\r
225         {\r
226                 if(g_hOpenSSL)\r
227                         FreeLibrary(g_hOpenSSL);\r
228                 g_hOpenSSL = NULL;\r
229                 if(g_hOpenSSLCommon)\r
230                         FreeLibrary(g_hOpenSSLCommon);\r
231                 g_hOpenSSLCommon = NULL;\r
232                 return FALSE;\r
233         }\r
234         InitializeCriticalSection(&g_OpenSSLLock);\r
235         p_SSL_load_error_strings();\r
236         p_SSL_library_init();\r
237         SetSSLTimeoutCallback(60000, DefaultSSLTimeoutCallback);\r
238         SetSSLConfirmCallback(DefaultSSLConfirmCallback);\r
239         g_bOpenSSLLoaded = TRUE;\r
240         return TRUE;\r
241 }\r
242 \r
243 // OpenSSLを解放\r
244 void FreeOpenSSL()\r
245 {\r
246         int i;\r
247         if(!g_bOpenSSLLoaded)\r
248                 return;\r
249         EnterCriticalSection(&g_OpenSSLLock);\r
250         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
251         {\r
252                 if(g_pOpenSSLHandle[i])\r
253                 {\r
254                         p_SSL_shutdown(g_pOpenSSLHandle[i]);\r
255                         p_SSL_free(g_pOpenSSLHandle[i]);\r
256                         g_pOpenSSLHandle[i] = NULL;\r
257                 }\r
258         }\r
259         if(g_pOpenSSLCTX)\r
260                 p_SSL_CTX_free(g_pOpenSSLCTX);\r
261         g_pOpenSSLCTX = NULL;\r
262         FreeLibrary(g_hOpenSSL);\r
263         g_hOpenSSL = NULL;\r
264         FreeLibrary(g_hOpenSSLCommon);\r
265         g_hOpenSSLCommon = NULL;\r
266         LeaveCriticalSection(&g_OpenSSLLock);\r
267         DeleteCriticalSection(&g_OpenSSLLock);\r
268         g_bOpenSSLLoaded = FALSE;\r
269 }\r
270 \r
271 // OpenSSLが使用可能かどうか確認\r
272 BOOL IsOpenSSLLoaded()\r
273 {\r
274         return g_bOpenSSLLoaded;\r
275 }\r
276 \r
277 SSL** GetUnusedSSLPointer()\r
278 {\r
279         int i;\r
280         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
281         {\r
282                 if(!g_pOpenSSLHandle[i])\r
283                         return &g_pOpenSSLHandle[i];\r
284         }\r
285         return NULL;\r
286 }\r
287 \r
288 SSL** FindSSLPointerFromSocket(SOCKET s)\r
289 {\r
290         int i;\r
291         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
292         {\r
293                 if(g_pOpenSSLHandle[i])\r
294                 {\r
295                         if(p_SSL_get_fd(g_pOpenSSLHandle[i]) == s)\r
296                                 return &g_pOpenSSLHandle[i];\r
297                 }\r
298         }\r
299         return NULL;\r
300 }\r
301 \r
302 BOOL ConfirmSSLCertificate(SSL* pSSL, BOOL* pbAborted)\r
303 {\r
304         BOOL bResult;\r
305         BOOL bVerified;\r
306         char* pData;\r
307         char* pSubject;\r
308         X509* pX509;\r
309         BIO* pBIO;\r
310         long Length;\r
311         char* pBuffer;\r
312         char* pCN;\r
313         char* p;\r
314         bResult = FALSE;\r
315         bVerified = FALSE;\r
316         pData = NULL;\r
317         pSubject = NULL;\r
318         if(pX509 = p_SSL_get_peer_certificate(pSSL))\r
319         {\r
320                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
321                 {\r
322                         p_X509_print_ex(pBIO, pX509, 0, XN_FLAG_RFC2253);\r
323                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
324                         {\r
325                                 if(pData = (char*)malloc(Length + sizeof(char)))\r
326                                 {\r
327                                         memcpy(pData, pBuffer, Length);\r
328                                         *(char*)((size_t)pData + Length) = '\0';\r
329                                 }\r
330                         }\r
331                         p_BIO_free(pBIO);\r
332                 }\r
333                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
334                 {\r
335                         p_X509_NAME_print_ex(pBIO, p_X509_get_subject_name(pX509), 0, XN_FLAG_RFC2253);\r
336                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
337                         {\r
338                                 if(pSubject = (char*)malloc(Length + sizeof(char)))\r
339                                 {\r
340                                         memcpy(pSubject, pBuffer, Length);\r
341                                         *(char*)((size_t)pSubject + Length) = '\0';\r
342                                 }\r
343                         }\r
344                         p_BIO_free(pBIO);\r
345                 }\r
346                 p_X509_free(pX509);\r
347         }\r
348         if(pX509 && p_SSL_get_verify_result(pSSL) == X509_V_OK)\r
349                 bVerified = TRUE;\r
350         pCN = pSubject;\r
351         while(pCN)\r
352         {\r
353                 if(strncmp(pCN, "CN=", strlen("CN=")) == 0)\r
354                 {\r
355                         pCN += strlen("CN=");\r
356                         if(p = strchr(pCN, ','))\r
357                                 *p = '\0';\r
358                         break;\r
359                 }\r
360                 if(pCN = strchr(pCN, ','))\r
361                         pCN++;\r
362         }\r
363         bResult = g_pOpenSSLConfirmCallback(pbAborted, bVerified, pData, pCN);\r
364         if(pData)\r
365                 free(pData);\r
366         if(pSubject)\r
367                 free(pSubject);\r
368         return bResult;\r
369 }\r
370 \r
371 void SetSSLTimeoutCallback(DWORD Timeout, LPSSLTIMEOUTCALLBACK pCallback)\r
372 {\r
373         if(!g_bOpenSSLLoaded)\r
374                 return;\r
375         EnterCriticalSection(&g_OpenSSLLock);\r
376         g_OpenSSLTimeout = Timeout;\r
377         g_pOpenSSLTimeoutCallback = pCallback;\r
378         LeaveCriticalSection(&g_OpenSSLLock);\r
379 }\r
380 \r
381 void SetSSLConfirmCallback(LPSSLCONFIRMCALLBACK pCallback)\r
382 {\r
383         if(!g_bOpenSSLLoaded)\r
384                 return;\r
385         EnterCriticalSection(&g_OpenSSLLock);\r
386         g_pOpenSSLConfirmCallback = pCallback;\r
387         LeaveCriticalSection(&g_OpenSSLLock);\r
388 }\r
389 \r
390 // SSLルート証明書を設定\r
391 // PEM形式のみ指定可能\r
392 BOOL SetSSLRootCertificate(const void* pData, DWORD Length)\r
393 {\r
394         BOOL r;\r
395         X509_STORE* pStore;\r
396         BYTE* p;\r
397         BYTE* pBegin;\r
398         BYTE* pEnd;\r
399         DWORD Left;\r
400         BIO* pBIO;\r
401         X509* pX509;\r
402         X509_CRL* pX509_CRL;\r
403         if(!g_bOpenSSLLoaded)\r
404                 return FALSE;\r
405         r = FALSE;\r
406         EnterCriticalSection(&g_OpenSSLLock);\r
407         if(!g_pOpenSSLCTX)\r
408         {\r
409                 g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
410                 p_SSL_CTX_ctrl(g_pOpenSSLCTX, SSL_CTRL_MODE, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY, NULL);\r
411         }\r
412         if(g_pOpenSSLCTX)\r
413         {\r
414                 if(pStore = p_SSL_CTX_get_cert_store(g_pOpenSSLCTX))\r
415                 {\r
416                         p = (BYTE*)pData;\r
417                         pBegin = NULL;\r
418                         pEnd = NULL;\r
419                         Left = Length;\r
420                         while(Left > 0)\r
421                         {\r
422                                 if(!pBegin)\r
423                                 {\r
424                                         if(Left < 27)\r
425                                                 break;\r
426                                         if(memcmp(p, "-----BEGIN CERTIFICATE-----", 27) == 0)\r
427                                                 pBegin = p;\r
428                                 }\r
429                                 else if(!pEnd)\r
430                                 {\r
431                                         if(Left < 25)\r
432                                                 break;\r
433                                         if(memcmp(p, "-----END CERTIFICATE-----", 25) == 0)\r
434                                                 pEnd = p + 25;\r
435                                 }\r
436                                 if(pBegin && pEnd)\r
437                                 {\r
438                                         if(pBIO = p_BIO_new_mem_buf(pBegin, (int)((size_t)pEnd - (size_t)pBegin)))\r
439                                         {\r
440                                                 if(pX509 = p_PEM_read_bio_X509(pBIO, NULL, NULL, NULL))\r
441                                                 {\r
442                                                         if(p_X509_STORE_add_cert(pStore, pX509) == 1)\r
443                                                                 r = TRUE;\r
444                                                         p_X509_free(pX509);\r
445                                                 }\r
446                                                 p_BIO_free(pBIO);\r
447                                         }\r
448                                         pBegin = NULL;\r
449                                         pEnd = NULL;\r
450                                 }\r
451                                 p++;\r
452                                 Left--;\r
453                         }\r
454                         p = (BYTE*)pData;\r
455                         pBegin = NULL;\r
456                         pEnd = NULL;\r
457                         Left = Length;\r
458                         while(Left > 0)\r
459                         {\r
460                                 if(!pBegin)\r
461                                 {\r
462                                         if(Left < 24)\r
463                                                 break;\r
464                                         if(memcmp(p, "-----BEGIN X509 CRL-----", 24) == 0)\r
465                                                 pBegin = p;\r
466                                 }\r
467                                 else if(!pEnd)\r
468                                 {\r
469                                         if(Left < 22)\r
470                                                 break;\r
471                                         if(memcmp(p, "-----END X509 CRL-----", 22) == 0)\r
472                                                 pEnd = p + 22;\r
473                                 }\r
474                                 if(pBegin && pEnd)\r
475                                 {\r
476                                         if(pBIO = p_BIO_new_mem_buf(pBegin, (int)((size_t)pEnd - (size_t)pBegin)))\r
477                                         {\r
478                                                 if(pX509_CRL = p_PEM_read_bio_X509_CRL(pBIO, NULL, NULL, NULL))\r
479                                                 {\r
480                                                         if(p_X509_STORE_add_crl(pStore, pX509_CRL) == 1)\r
481                                                                 r = TRUE;\r
482                                                         p_X509_CRL_free(pX509_CRL);\r
483                                                 }\r
484                                                 p_BIO_free(pBIO);\r
485                                         }\r
486                                         pBegin = NULL;\r
487                                         pEnd = NULL;\r
488                                 }\r
489                                 p++;\r
490                                 Left--;\r
491                         }\r
492                 }\r
493         }\r
494         LeaveCriticalSection(&g_OpenSSLLock);\r
495         return r;\r
496 }\r
497 \r
498 // ワイルドカードの比較\r
499 // 主にSSL証明書のCN確認用\r
500 BOOL IsHostNameMatched(LPCSTR HostName, LPCSTR CommonName)\r
501 {\r
502         BOOL bResult;\r
503         const char* pAsterisk;\r
504         size_t BeforeAsterisk;\r
505         const char* pBeginAsterisk;\r
506         const char* pEndAsterisk;\r
507         const char* pDot;\r
508         bResult = FALSE;\r
509         if(HostName && CommonName)\r
510         {\r
511                 if(pAsterisk = strchr(CommonName, '*'))\r
512                 {\r
513                         BeforeAsterisk = ((size_t)pAsterisk - (size_t)CommonName) / sizeof(char);\r
514                         pBeginAsterisk = HostName + BeforeAsterisk;\r
515                         while(*pAsterisk == '*')\r
516                         {\r
517                                 pAsterisk++;\r
518                         }\r
519                         pEndAsterisk = HostName + strlen(HostName) - strlen(pAsterisk);\r
520                         // "*"より前は大文字小文字を無視して完全一致\r
521                         if(_strnicmp(HostName, CommonName, BeforeAsterisk) == 0)\r
522                         {\r
523                                 // "*"より後は大文字小文字を無視して完全一致\r
524                                 if(_stricmp(pEndAsterisk, pAsterisk) == 0)\r
525                                 {\r
526                                         // "*"と一致する範囲に"."が含まれてはならない\r
527                                         pDot = strchr(pBeginAsterisk, '.');\r
528                                         if(!pDot || pDot >= pEndAsterisk)\r
529                                                 bResult = TRUE;\r
530                                 }\r
531                         }\r
532                 }\r
533                 else if(_stricmp(HostName, CommonName) == 0)\r
534                         bResult = TRUE;\r
535         }\r
536         return bResult;\r
537 }\r
538 \r
539 // RSA復号化\r
540 // 主に自動更新ファイルのハッシュの改竄確認\r
541 BOOL DecryptSignature(const char* PublicKey, const void* pIn, DWORD InLength, void* pOut, DWORD OutLength, DWORD* pOutLength)\r
542 {\r
543         BOOL bResult;\r
544         BIO* pBIO;\r
545         EVP_PKEY* pPKEY;\r
546         RSA* pRSA;\r
547         int i;\r
548         if(!g_bOpenSSLLoaded)\r
549                 return FALSE;\r
550         bResult = FALSE;\r
551         if(pBIO = p_BIO_new_mem_buf((void*)PublicKey, sizeof(char) * strlen(PublicKey)))\r
552         {\r
553                 if(pPKEY = p_PEM_read_bio_PUBKEY(pBIO, NULL, NULL, NULL))\r
554                 {\r
555                         if(pRSA = p_EVP_PKEY_get1_RSA(pPKEY))\r
556                         {\r
557                                 if(p_RSA_size(pRSA) <= (int)OutLength)\r
558                                 {\r
559                                         i = p_RSA_public_decrypt((int)InLength, (const unsigned char*)pIn, (unsigned char*)pOut, pRSA, RSA_PKCS1_PADDING);\r
560                                         if(i >= 0)\r
561                                         {\r
562                                                 *pOutLength = (DWORD)i;\r
563                                                 bResult = TRUE;\r
564                                         }\r
565                                 }\r
566                                 p_RSA_free(pRSA);\r
567                         }\r
568                         p_EVP_PKEY_free(pPKEY);\r
569                 }\r
570                 p_BIO_free(pBIO);\r
571         }\r
572         return bResult;\r
573 }\r
574 \r
575 // ハッシュ計算\r
576 // 他にも同等の関数はあるが主にマルウェア対策のための冗長化\r
577 BOOL GetHashSHA1(const void* pData, DWORD Size, void* pHash)\r
578 {\r
579         if(!g_bOpenSSLLoaded)\r
580                 return FALSE;\r
581         p_SHA1((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
582         return TRUE;\r
583 }\r
584 \r
585 BOOL GetHashSHA224(const void* pData, DWORD Size, void* pHash)\r
586 {\r
587         if(!g_bOpenSSLLoaded)\r
588                 return FALSE;\r
589         p_SHA224((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
590         return TRUE;\r
591 }\r
592 \r
593 BOOL GetHashSHA256(const void* pData, DWORD Size, void* pHash)\r
594 {\r
595         if(!g_bOpenSSLLoaded)\r
596                 return FALSE;\r
597         p_SHA256((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
598         return TRUE;\r
599 }\r
600 \r
601 BOOL GetHashSHA384(const void* pData, DWORD Size, void* pHash)\r
602 {\r
603         if(!g_bOpenSSLLoaded)\r
604                 return FALSE;\r
605         p_SHA384((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
606         return TRUE;\r
607 }\r
608 \r
609 BOOL GetHashSHA512(const void* pData, DWORD Size, void* pHash)\r
610 {\r
611         if(!g_bOpenSSLLoaded)\r
612                 return FALSE;\r
613         p_SHA512((const unsigned char*)pData, (size_t)Size, (unsigned char*)pHash);\r
614         return TRUE;\r
615 }\r
616 \r
617 // SSLセッションを開始\r
618 BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted, BOOL bStrengthen)\r
619 {\r
620         BOOL r;\r
621         DWORD Time;\r
622         SSL** ppSSL;\r
623         BOOL bInherited;\r
624         SSL** ppSSLParent;\r
625         SSL_SESSION* pSession;\r
626         int Return;\r
627         int Error;\r
628         if(!g_bOpenSSLLoaded)\r
629                 return FALSE;\r
630         r = FALSE;\r
631         Time = timeGetTime();\r
632         EnterCriticalSection(&g_OpenSSLLock);\r
633         if(!g_pOpenSSLCTX)\r
634         {\r
635                 g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
636                 p_SSL_CTX_ctrl(g_pOpenSSLCTX, SSL_CTRL_MODE, SSL_MODE_ENABLE_PARTIAL_WRITE | SSL_MODE_AUTO_RETRY, NULL);\r
637         }\r
638         if(g_pOpenSSLCTX)\r
639         {\r
640                 if(ppSSL = GetUnusedSSLPointer())\r
641                 {\r
642                         if(*ppSSL = p_SSL_new(g_pOpenSSLCTX))\r
643                         {\r
644                                 if(p_SSL_set_fd(*ppSSL, s) != 0)\r
645                                 {\r
646                                         bInherited = FALSE;\r
647                                         if(parent != INVALID_SOCKET)\r
648                                         {\r
649                                                 if(ppSSLParent = FindSSLPointerFromSocket(parent))\r
650                                                 {\r
651                                                         if(pSession = p_SSL_get_session(*ppSSLParent))\r
652                                                         {\r
653                                                                 if(p_SSL_set_session(*ppSSL, pSession) == 1)\r
654                                                                         bInherited = TRUE;\r
655                                                         }\r
656                                                 }\r
657                                         }\r
658                                         if(!bInherited)\r
659                                         {\r
660                                                 if(bStrengthen)\r
661                                                 {\r
662                                                         p_SSL_ctrl(*ppSSL, SSL_CTRL_OPTIONS, SSL_OP_NO_SSLv2, NULL);\r
663                                                         p_SSL_set_cipher_list(*ppSSL, "HIGH");\r
664                                                 }\r
665                                         }\r
666                                         // SSLのネゴシエーションには時間がかかる場合がある\r
667                                         r = TRUE;\r
668                                         while(r)\r
669                                         {\r
670                                                 Return = p_SSL_connect(*ppSSL);\r
671                                                 if(Return == 1)\r
672                                                         break;\r
673                                                 Error = p_SSL_get_error(*ppSSL, Return);\r
674                                                 if(Error == SSL_ERROR_WANT_READ || Error == SSL_ERROR_WANT_WRITE)\r
675                                                 {\r
676                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
677                                                         if(g_pOpenSSLTimeoutCallback(pbAborted) || (g_OpenSSLTimeout > 0 && timeGetTime() - Time >= g_OpenSSLTimeout))\r
678                                                                 r = FALSE;\r
679                                                         EnterCriticalSection(&g_OpenSSLLock);\r
680                                                 }\r
681                                                 else\r
682                                                         r = FALSE;\r
683                                         }\r
684                                         if(r)\r
685                                         {\r
686                                                 if(ConfirmSSLCertificate(*ppSSL, pbAborted))\r
687                                                 {\r
688                                                 }\r
689                                                 else\r
690                                                 {\r
691                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
692                                                         DetachSSL(s);\r
693                                                         r = FALSE;\r
694                                                         EnterCriticalSection(&g_OpenSSLLock);\r
695                                                 }\r
696                                         }\r
697                                         else\r
698                                         {\r
699                                                 LeaveCriticalSection(&g_OpenSSLLock);\r
700                                                 DetachSSL(s);\r
701                                                 EnterCriticalSection(&g_OpenSSLLock);\r
702                                         }\r
703                                 }\r
704                                 else\r
705                                 {\r
706                                         LeaveCriticalSection(&g_OpenSSLLock);\r
707                                         DetachSSL(s);\r
708                                         EnterCriticalSection(&g_OpenSSLLock);\r
709                                 }\r
710                         }\r
711                 }\r
712         }\r
713         LeaveCriticalSection(&g_OpenSSLLock);\r
714         return r;\r
715 }\r
716 \r
717 // SSLセッションを終了\r
718 BOOL DetachSSL(SOCKET s)\r
719 {\r
720         BOOL r;\r
721         SSL** ppSSL;\r
722         if(!g_bOpenSSLLoaded)\r
723                 return FALSE;\r
724         r = FALSE;\r
725         EnterCriticalSection(&g_OpenSSLLock);\r
726         if(ppSSL = FindSSLPointerFromSocket(s))\r
727         {\r
728                 p_SSL_shutdown(*ppSSL);\r
729                 p_SSL_free(*ppSSL);\r
730                 *ppSSL = NULL;\r
731                 r = TRUE;\r
732         }\r
733         LeaveCriticalSection(&g_OpenSSLLock);\r
734         return r;\r
735 }\r
736 \r
737 // SSLとしてマークされているか確認\r
738 // マークされていればTRUEを返す\r
739 BOOL IsSSLAttached(SOCKET s)\r
740 {\r
741         SSL** ppSSL;\r
742         if(!g_bOpenSSLLoaded)\r
743                 return FALSE;\r
744         EnterCriticalSection(&g_OpenSSLLock);\r
745         ppSSL = FindSSLPointerFromSocket(s);\r
746         LeaveCriticalSection(&g_OpenSSLLock);\r
747         if(!ppSSL)\r
748                 return FALSE;\r
749         return TRUE;\r
750 }\r
751 \r
752 SOCKET FTPS_socket(int af, int type, int protocol)\r
753 {\r
754         return socket(af, type, protocol);\r
755 }\r
756 \r
757 int FTPS_bind(SOCKET s, const struct sockaddr *addr, int namelen)\r
758 {\r
759         return bind(s, addr, namelen);\r
760 }\r
761 \r
762 int FTPS_listen(SOCKET s, int backlog)\r
763 {\r
764         return listen(s, backlog);\r
765 }\r
766 \r
767 // accept相当の関数\r
768 // ただし初めからSSLのネゴシエーションを行う\r
769 SOCKET FTPS_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
770 {\r
771         SOCKET r;\r
772         BOOL bAborted;\r
773         r = accept(s, addr, addrlen);\r
774         bAborted = FALSE;\r
775         if(!AttachSSL(r, INVALID_SOCKET, &bAborted, TRUE))\r
776         {\r
777                 closesocket(r);\r
778                 return INVALID_SOCKET;\r
779         }\r
780         return r;\r
781 }\r
782 \r
783 // connect相当の関数\r
784 // ただし初めからSSLのネゴシエーションを行う\r
785 int FTPS_connect(SOCKET s, const struct sockaddr *name, int namelen)\r
786 {\r
787         int r;\r
788         BOOL bAborted;\r
789         r = connect(s, name, namelen);\r
790         bAborted = FALSE;\r
791         if(!AttachSSL(r, INVALID_SOCKET, &bAborted, TRUE))\r
792                 return SOCKET_ERROR;\r
793         return r;\r
794 }\r
795 \r
796 // closesocket相当の関数\r
797 int FTPS_closesocket(SOCKET s)\r
798 {\r
799         DetachSSL(s);\r
800         return closesocket(s);\r
801 }\r
802 \r
803 // send相当の関数\r
804 int FTPS_send(SOCKET s, const char * buf, int len, int flags)\r
805 {\r
806         int r;\r
807         SSL** ppSSL;\r
808         if(!g_bOpenSSLLoaded)\r
809                 return send(s, buf, len, flags);\r
810         EnterCriticalSection(&g_OpenSSLLock);\r
811         ppSSL = FindSSLPointerFromSocket(s);\r
812         LeaveCriticalSection(&g_OpenSSLLock);\r
813         if(!ppSSL)\r
814                 return send(s, buf, len, flags);\r
815         r = p_SSL_write(*ppSSL, buf, len);\r
816         if(r < 0)\r
817                 return SOCKET_ERROR;\r
818         return r;\r
819 }\r
820 \r
821 // recv相当の関数\r
822 int FTPS_recv(SOCKET s, char * buf, int len, int flags)\r
823 {\r
824         int r;\r
825         SSL** ppSSL;\r
826         if(!g_bOpenSSLLoaded)\r
827                 return recv(s, buf, len, flags);\r
828         EnterCriticalSection(&g_OpenSSLLock);\r
829         ppSSL = FindSSLPointerFromSocket(s);\r
830         LeaveCriticalSection(&g_OpenSSLLock);\r
831         if(!ppSSL)\r
832                 return recv(s, buf, len, flags);\r
833         if(flags & MSG_PEEK)\r
834                 r = p_SSL_peek(*ppSSL, buf, len);\r
835         else\r
836                 r = p_SSL_read(*ppSSL, buf, len);\r
837         if(r < 0)\r
838                 return SOCKET_ERROR;\r
839         return r;\r
840 }\r
841 \r
842 // IPv6対応\r
843 \r
844 const struct in6_addr IN6ADDR_NONE = {{0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}};\r
845 \r
846 typedef struct\r
847 {\r
848         HANDLE h;\r
849         HWND hWnd;\r
850         u_int wMsg;\r
851         char * name;\r
852         char * buf;\r
853         int buflen;\r
854         short Family;\r
855 } GETHOSTBYNAMEDATA;\r
856 \r
857 DWORD WINAPI WSAAsyncGetHostByNameIPv6ThreadProc(LPVOID lpParameter)\r
858 {\r
859         GETHOSTBYNAMEDATA* pData;\r
860         struct hostent* pHost;\r
861         struct addrinfo* pAddr;\r
862         struct addrinfo* p;\r
863         pHost = NULL;\r
864         pData = (GETHOSTBYNAMEDATA*)lpParameter;\r
865         if(getaddrinfo(pData->name, NULL, NULL, &pAddr) == 0)\r
866         {\r
867                 p = pAddr;\r
868                 while(p)\r
869                 {\r
870                         if(p->ai_family == pData->Family)\r
871                         {\r
872                                 switch(p->ai_family)\r
873                                 {\r
874                                 case AF_INET:\r
875                                         pHost = (struct hostent*)pData->buf;\r
876                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in_addr)\r
877                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in))\r
878                                         {\r
879                                                 pHost->h_name = NULL;\r
880                                                 pHost->h_aliases = NULL;\r
881                                                 pHost->h_addrtype = p->ai_family;\r
882                                                 pHost->h_length = sizeof(struct in_addr);\r
883                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
884                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
885                                                 pHost->h_addr_list[1] = NULL;\r
886                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in*)p->ai_addr)->sin_addr, sizeof(struct in_addr));\r
887                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in_addr)));\r
888                                         }\r
889                                         else\r
890                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
891                                         break;\r
892                                 case AF_INET6:\r
893                                         pHost = (struct hostent*)pData->buf;\r
894                                         if((size_t)pData->buflen >= sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in6_addr)\r
895                                                 && p->ai_addrlen >= sizeof(struct sockaddr_in6))\r
896                                         {\r
897                                                 pHost->h_name = NULL;\r
898                                                 pHost->h_aliases = NULL;\r
899                                                 pHost->h_addrtype = p->ai_family;\r
900                                                 pHost->h_length = sizeof(struct in6_addr);\r
901                                                 pHost->h_addr_list = (char**)(&pHost[1]);\r
902                                                 pHost->h_addr_list[0] = (char*)(&pHost->h_addr_list[2]);\r
903                                                 pHost->h_addr_list[1] = NULL;\r
904                                                 memcpy(pHost->h_addr_list[0], &((struct sockaddr_in6*)p->ai_addr)->sin6_addr, sizeof(struct in6_addr));\r
905                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(sizeof(struct hostent) + sizeof(char*) * 2 + sizeof(struct in6_addr)));\r
906                                         }\r
907                                         else\r
908                                                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(WSAENOBUFS << 16));\r
909                                         break;\r
910                                 }\r
911                         }\r
912                         if(pHost)\r
913                                 break;\r
914                         p = p->ai_next;\r
915                 }\r
916                 if(!p)\r
917                         PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
918                 freeaddrinfo(pAddr);\r
919         }\r
920         else\r
921                 PostMessage(pData->hWnd, pData->wMsg, (WPARAM)pData->h, (LPARAM)(ERROR_INVALID_FUNCTION << 16));\r
922         // CreateThreadが返すハンドルが重複するのを回避\r
923         Sleep(10000);\r
924         CloseHandle(pData->h);\r
925         free(pData->name);\r
926         free(pData);\r
927         return 0;\r
928 }\r
929 \r
930 // IPv6対応のWSAAsyncGetHostByName相当の関数\r
931 // FamilyにはAF_INETまたはAF_INET6を指定可能\r
932 // ただしANSI用\r
933 HANDLE WSAAsyncGetHostByNameIPv6(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
934 {\r
935         HANDLE hResult;\r
936         GETHOSTBYNAMEDATA* pData;\r
937         hResult = NULL;\r
938         if(pData = malloc(sizeof(GETHOSTBYNAMEDATA)))\r
939         {\r
940                 pData->hWnd = hWnd;\r
941                 pData->wMsg = wMsg;\r
942                 if(pData->name = malloc(sizeof(char) * (strlen(name) + 1)))\r
943                 {\r
944                         strcpy(pData->name, name);\r
945                         pData->buf = buf;\r
946                         pData->buflen = buflen;\r
947                         pData->Family = Family;\r
948                         if(pData->h = CreateThread(NULL, 0, WSAAsyncGetHostByNameIPv6ThreadProc, pData, CREATE_SUSPENDED, NULL))\r
949                         {\r
950                                 ResumeThread(pData->h);\r
951                                 hResult = pData->h;\r
952                         }\r
953                 }\r
954         }\r
955         if(!hResult)\r
956         {\r
957                 if(pData)\r
958                 {\r
959                         if(pData->name)\r
960                                 free(pData->name);\r
961                         free(pData);\r
962                 }\r
963         }\r
964         return hResult;\r
965 }\r
966 \r
967 // WSAAsyncGetHostByNameIPv6用のWSACancelAsyncRequest相当の関数\r
968 int WSACancelAsyncRequestIPv6(HANDLE hAsyncTaskHandle)\r
969 {\r
970         int Result;\r
971         Result = SOCKET_ERROR;\r
972         if(TerminateThread(hAsyncTaskHandle, 0))\r
973         {\r
974                 CloseHandle(hAsyncTaskHandle);\r
975                 Result = 0;\r
976         }\r
977         return Result;\r
978 }\r
979 \r
980 char* AddressToStringIPv4(char* str, void* in)\r
981 {\r
982         char* pResult;\r
983         unsigned char* p;\r
984         pResult = str;\r
985         p = (unsigned char*)in;\r
986         sprintf(str, "%u.%u.%u.%u", p[0], p[1], p[2], p[3]);\r
987         return pResult;\r
988 }\r
989 \r
990 char* AddressToStringIPv6(char* str, void* in6)\r
991 {\r
992         char* pResult;\r
993         unsigned char* p;\r
994         int MaxZero;\r
995         int MaxZeroLen;\r
996         int i;\r
997         int j;\r
998         char Tmp[5];\r
999         pResult = str;\r
1000         p = (unsigned char*)in6;\r
1001         MaxZero = 8;\r
1002         MaxZeroLen = 1;\r
1003         for(i = 0; i < 8; i++)\r
1004         {\r
1005                 for(j = i; j < 8; j++)\r
1006                 {\r
1007                         if(p[j * 2] != 0 || p[j * 2 + 1] != 0)\r
1008                                 break;\r
1009                 }\r
1010                 if(j - i > MaxZeroLen)\r
1011                 {\r
1012                         MaxZero = i;\r
1013                         MaxZeroLen = j - i;\r
1014                 }\r
1015         }\r
1016         strcpy(str, "");\r
1017         for(i = 0; i < 8; i++)\r
1018         {\r
1019                 if(i == MaxZero)\r
1020                 {\r
1021                         if(i == 0)\r
1022                                 strcat(str, ":");\r
1023                         strcat(str, ":");\r
1024                 }\r
1025                 else if(i < MaxZero || i >= MaxZero + MaxZeroLen)\r
1026                 {\r
1027                         sprintf(Tmp, "%x", (((int)p[i * 2] & 0xff) << 8) | ((int)p[i * 2 + 1] & 0xff));\r
1028                         strcat(str, Tmp);\r
1029                         if(i < 7)\r
1030                                 strcat(str, ":");\r
1031                 }\r
1032         }\r
1033         return pResult;\r
1034 }\r
1035 \r
1036 // IPv6対応のinet_ntoa相当の関数\r
1037 // ただしANSI用\r
1038 char* inet6_ntoa(struct in6_addr in6)\r
1039 {\r
1040         char* pResult;\r
1041         static char Adrs[40];\r
1042         pResult = NULL;\r
1043         memset(Adrs, 0, sizeof(Adrs));\r
1044         pResult = AddressToStringIPv6(Adrs, &in6);\r
1045         return pResult;\r
1046 }\r
1047 \r
1048 // IPv6対応のinet_addr相当の関数\r
1049 // ただしANSI用\r
1050 struct in6_addr inet6_addr(const char* cp)\r
1051 {\r
1052         struct in6_addr Result;\r
1053         int AfterZero;\r
1054         int i;\r
1055         char* p;\r
1056         memset(&Result, 0, sizeof(Result));\r
1057         AfterZero = 0;\r
1058         for(i = 0; i < 8; i++)\r
1059         {\r
1060                 if(!cp)\r
1061                 {\r
1062                         memcpy(&Result, &IN6ADDR_NONE, sizeof(struct in6_addr));\r
1063                         break;\r
1064                 }\r
1065                 if(i >= AfterZero)\r
1066                 {\r
1067                         if(strncmp(cp, ":", 1) == 0)\r
1068                         {\r
1069                                 cp = cp + 1;\r
1070                                 if(i == 0 && strncmp(cp, ":", 1) == 0)\r
1071                                         cp = cp + 1;\r
1072                                 p = (char*)cp;\r
1073                                 AfterZero = 7;\r
1074                                 while(p = strstr(p, ":"))\r
1075                                 {\r
1076                                         p = p + 1;\r
1077                                         AfterZero--;\r
1078                                 }\r
1079                         }\r
1080                         else\r
1081                         {\r
1082                                 Result.u.Word[i] = (USHORT)strtol(cp, &p, 16);\r
1083                                 Result.u.Word[i] = ((Result.u.Word[i] & 0xff00) >> 8) | ((Result.u.Word[i] & 0x00ff) << 8);\r
1084                                 if(strncmp(p, ":", 1) != 0 && strlen(p) > 0)\r
1085                                 {\r
1086                                         memcpy(&Result, &IN6ADDR_NONE, sizeof(struct in6_addr));\r
1087                                         break;\r
1088                                 }\r
1089                                 if(cp = strstr(cp, ":"))\r
1090                                         cp = cp + 1;\r
1091                         }\r
1092                 }\r
1093         }\r
1094         return Result;\r
1095 }\r
1096 \r
1097 BOOL ConvertDomainNameToPunycode(LPSTR Output, DWORD Count, LPCSTR Input)\r
1098 {\r
1099         BOOL bResult;\r
1100         punycode_uint* pUnicode;\r
1101         punycode_uint* p;\r
1102         BOOL bNeeded;\r
1103         LPCSTR InputString;\r
1104         punycode_uint Length;\r
1105         punycode_uint OutputLength;\r
1106         bResult = FALSE;\r
1107         if(pUnicode = malloc(sizeof(punycode_uint) * strlen(Input)))\r
1108         {\r
1109                 p = pUnicode;\r
1110                 bNeeded = FALSE;\r
1111                 InputString = Input;\r
1112                 Length = 0;\r
1113                 while(*InputString != '\0')\r
1114                 {\r
1115                         *p = (punycode_uint)GetNextCharM(InputString, NULL, &InputString);\r
1116                         if(*p >= 0x80)\r
1117                                 bNeeded = TRUE;\r
1118                         p++;\r
1119                         Length++;\r
1120                 }\r
1121                 if(bNeeded)\r
1122                 {\r
1123                         if(Count >= strlen("xn--") + 1)\r
1124                         {\r
1125                                 strcpy(Output, "xn--");\r
1126                                 OutputLength = Count - strlen("xn--");\r
1127                                 if(punycode_encode(Length, pUnicode, NULL, (punycode_uint*)&OutputLength, Output + strlen("xn--")) == punycode_success)\r
1128                                 {\r
1129                                         Output[strlen("xn--") + OutputLength] = '\0';\r
1130                                         bResult = TRUE;\r
1131                                 }\r
1132                         }\r
1133                 }\r
1134                 free(pUnicode);\r
1135         }\r
1136         if(!bResult)\r
1137         {\r
1138                 if(Count >= strlen(Input) + 1)\r
1139                 {\r
1140                         strcpy(Output, Input);\r
1141                         bResult = TRUE;\r
1142                 }\r
1143         }\r
1144         return bResult;\r
1145 }\r
1146 \r
1147 BOOL ConvertNameToPunycode(LPSTR Output, LPCSTR Input)\r
1148 {\r
1149         BOOL bResult;\r
1150         DWORD Length;\r
1151         char* pm0;\r
1152         char* pm1;\r
1153         char* p;\r
1154         char* pNext;\r
1155         bResult = FALSE;\r
1156         Length = strlen(Input);\r
1157         if(pm0 = AllocateStringM(Length + 1))\r
1158         {\r
1159                 if(pm1 = AllocateStringM(Length * 4 + 1))\r
1160                 {\r
1161                         strcpy(pm0, Input);\r
1162                         p = pm0;\r
1163                         while(p)\r
1164                         {\r
1165                                 if(pNext = strchr(p, '.'))\r
1166                                 {\r
1167                                         *pNext = '\0';\r
1168                                         pNext++;\r
1169                                 }\r
1170                                 if(ConvertDomainNameToPunycode(pm1, Length * 4, p))\r
1171                                         strcat(Output, pm1);\r
1172                                 if(pNext)\r
1173                                         strcat(Output, ".");\r
1174                                 p = pNext;\r
1175                         }\r
1176                         bResult = TRUE;\r
1177                         FreeDuplicatedString(pm1);\r
1178                 }\r
1179                 FreeDuplicatedString(pm0);\r
1180         }\r
1181         return bResult;\r
1182 }\r
1183 \r
1184 HANDLE WSAAsyncGetHostByNameM(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen)\r
1185 {\r
1186         HANDLE r = NULL;\r
1187         char* pa0 = NULL;\r
1188         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1189         {\r
1190                 if(ConvertNameToPunycode(pa0, name))\r
1191                         r = WSAAsyncGetHostByName(hWnd, wMsg, pa0, buf, buflen);\r
1192         }\r
1193         FreeDuplicatedString(pa0);\r
1194         return r;\r
1195 }\r
1196 \r
1197 HANDLE WSAAsyncGetHostByNameIPv6M(HWND hWnd, u_int wMsg, const char * name, char * buf, int buflen, short Family)\r
1198 {\r
1199         HANDLE r = NULL;\r
1200         char* pa0 = NULL;\r
1201         if(pa0 = AllocateStringA(strlen(name) * 4))\r
1202         {\r
1203                 if(ConvertNameToPunycode(pa0, name))\r
1204                         r = WSAAsyncGetHostByNameIPv6(hWnd, wMsg, pa0, buf, buflen, Family);\r
1205         }\r
1206         FreeDuplicatedString(pa0);\r
1207         return r;\r
1208 }\r
1209 \r
1210 // SFTP対応\r
1211 \r
1212 typedef void* (__cdecl* _SFTP_Create)();\r
1213 typedef void (__cdecl* _SFTP_Destroy)(void*);\r
1214 typedef BOOL (__cdecl* _SFTP_IsExited)(void*);\r
1215 typedef BOOL (__cdecl* _SFTP_SetTimeoutCallback)(void*, void*);\r
1216 typedef size_t (__cdecl* _SFTP_PeekStdOut)(void*, void*, size_t);\r
1217 typedef size_t (__cdecl* _SFTP_ReadStdOut)(void*, void*, size_t);\r
1218 typedef size_t (__cdecl* _SFTP_WriteStdIn)(void*, const void*, size_t);\r
1219 typedef size_t (__cdecl* _SFTP_PeekDataOut)(void*, void*, size_t);\r
1220 typedef size_t (__cdecl* _SFTP_ReadDataOut)(void*, void*, size_t);\r
1221 typedef size_t (__cdecl* _SFTP_WriteDataIn)(void*, const void*, size_t);\r
1222 typedef BOOL (__cdecl* _SFTP_SetFilePosition)(void*, LONGLONG);\r
1223 \r
1224 _SFTP_Create p_SFTP_Create;\r
1225 _SFTP_Destroy p_SFTP_Destroy;\r
1226 _SFTP_IsExited p_SFTP_IsExited;\r
1227 _SFTP_SetTimeoutCallback p_SFTP_SetTimeoutCallback;\r
1228 _SFTP_PeekStdOut p_SFTP_PeekStdOut;\r
1229 _SFTP_ReadStdOut p_SFTP_ReadStdOut;\r
1230 _SFTP_WriteStdIn p_SFTP_WriteStdIn;\r
1231 _SFTP_PeekDataOut p_SFTP_PeekDataOut;\r
1232 _SFTP_ReadDataOut p_SFTP_ReadDataOut;\r
1233 _SFTP_WriteDataIn p_SFTP_WriteDataIn;\r
1234 _SFTP_SetFilePosition p_SFTP_SetFilePosition;\r
1235 \r
1236 typedef struct\r
1237 {\r
1238         SOCKET Control;\r
1239         SOCKET Data;\r
1240         void* Handle;\r
1241         char Host[1024];\r
1242         int Port;\r
1243         char User[1024];\r
1244         char Password[1024];\r
1245 } SFTPDATA;\r
1246 \r
1247 #define MAX_SFTP_SOCKET 16\r
1248 \r
1249 BOOL g_bPuTTYLoaded;\r
1250 HMODULE g_hPuTTY;\r
1251 CRITICAL_SECTION g_PuTTYLock;\r
1252 SFTPDATA g_SFTPData[MAX_SFTP_SOCKET];\r
1253 \r
1254 // PuTTYを初期化\r
1255 BOOL LoadPuTTY()\r
1256 {\r
1257         int i;\r
1258         if(g_bPuTTYLoaded)\r
1259                 return FALSE;\r
1260 #ifdef ENABLE_PROCESS_PROTECTION\r
1261         // ビルドしたputty.dllに合わせてSHA1ハッシュ値を変更すること\r
1262 #if defined(_M_IX86)\r
1263         RegisterTrustedModuleSHA1Hash("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");\r
1264 #elif defined(_M_AMD64)\r
1265         RegisterTrustedModuleSHA1Hash("\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00");\r
1266 #endif\r
1267 #endif\r
1268         // デバッグ用\r
1269 #ifdef _DEBUG\r
1270         {\r
1271                 char Path[MAX_PATH];\r
1272                 GetModuleFileName(NULL, Path, MAX_PATH);\r
1273                 strcpy(strrchr(Path, '\\'), "\\..\\putty\\Debug\\PuTTY.dll");\r
1274                 g_hPuTTY = LoadLibrary(Path);\r
1275         }\r
1276 #else\r
1277         g_hPuTTY = LoadLibrary("putty.dll");\r
1278 #endif\r
1279         if(!g_hPuTTY\r
1280                 || !(p_SFTP_Create = (_SFTP_Create)GetProcAddress(g_hPuTTY, "SFTP_Create"))\r
1281                 || !(p_SFTP_Destroy = (_SFTP_Destroy)GetProcAddress(g_hPuTTY, "SFTP_Destroy"))\r
1282                 || !(p_SFTP_IsExited = (_SFTP_IsExited)GetProcAddress(g_hPuTTY, "SFTP_IsExited"))\r
1283                 || !(p_SFTP_SetTimeoutCallback = (_SFTP_SetTimeoutCallback)GetProcAddress(g_hPuTTY, "SFTP_SetTimeoutCallback"))\r
1284                 || !(p_SFTP_PeekStdOut = (_SFTP_PeekStdOut)GetProcAddress(g_hPuTTY, "SFTP_PeekStdOut"))\r
1285                 || !(p_SFTP_ReadStdOut = (_SFTP_ReadStdOut)GetProcAddress(g_hPuTTY, "SFTP_ReadStdOut"))\r
1286                 || !(p_SFTP_WriteStdIn = (_SFTP_WriteStdIn)GetProcAddress(g_hPuTTY, "SFTP_WriteStdIn"))\r
1287                 || !(p_SFTP_PeekDataOut = (_SFTP_PeekDataOut)GetProcAddress(g_hPuTTY, "SFTP_PeekDataOut"))\r
1288                 || !(p_SFTP_ReadDataOut = (_SFTP_ReadDataOut)GetProcAddress(g_hPuTTY, "SFTP_ReadDataOut"))\r
1289                 || !(p_SFTP_WriteDataIn = (_SFTP_WriteDataIn)GetProcAddress(g_hPuTTY, "SFTP_WriteDataIn"))\r
1290                 || !(p_SFTP_SetFilePosition = (_SFTP_SetFilePosition)GetProcAddress(g_hPuTTY, "SFTP_SetFilePosition")))\r
1291         {\r
1292                 if(g_hPuTTY)\r
1293                         FreeLibrary(g_hPuTTY);\r
1294                 g_hPuTTY = NULL;\r
1295                 return FALSE;\r
1296         }\r
1297         for(i = 0; i < MAX_SFTP_SOCKET; i++)\r
1298         {\r
1299                 g_SFTPData[i].Control = INVALID_SOCKET;\r
1300                 g_SFTPData[i].Data = INVALID_SOCKET;\r
1301         }\r
1302         InitializeCriticalSection(&g_PuTTYLock);\r
1303         g_bPuTTYLoaded = TRUE;\r
1304         return TRUE;\r
1305 }\r
1306 \r
1307 // PuTTYを解放\r
1308 void FreePuTTY()\r
1309 {\r
1310         int i;\r
1311         if(!g_bPuTTYLoaded)\r
1312                 return;\r
1313         EnterCriticalSection(&g_PuTTYLock);\r
1314         for(i = 0; i < MAX_SFTP_SOCKET; i++)\r
1315         {\r
1316                 if(g_SFTPData[i].Control != INVALID_SOCKET)\r
1317                 {\r
1318                         closesocket(g_SFTPData[i].Control);\r
1319                         g_SFTPData[i].Control = INVALID_SOCKET;\r
1320                         p_SFTP_Destroy(g_SFTPData[i].Handle);\r
1321                 }\r
1322                 if(g_SFTPData[i].Data != INVALID_SOCKET)\r
1323                 {\r
1324                         closesocket(g_SFTPData[i].Data);\r
1325                         g_SFTPData[i].Data = INVALID_SOCKET;\r
1326                 }\r
1327         }\r
1328         FreeLibrary(g_hPuTTY);\r
1329         g_hPuTTY = NULL;\r
1330         LeaveCriticalSection(&g_PuTTYLock);\r
1331         DeleteCriticalSection(&g_PuTTYLock);\r
1332         g_bPuTTYLoaded = FALSE;\r
1333 }\r
1334 \r
1335 // PuTTYが使用可能かどうか確認\r
1336 BOOL IsPuTTYLoaded()\r
1337 {\r
1338         return g_bPuTTYLoaded;\r
1339 }\r
1340 \r
1341 SFTPDATA* GetUnusedSFTPData()\r
1342 {\r
1343         int i;\r
1344         for(i = 0; i < MAX_SFTP_SOCKET; i++)\r
1345         {\r
1346                 if(g_SFTPData[i].Control == INVALID_SOCKET)\r
1347                 {\r
1348                         memset(&g_SFTPData[i], 0, sizeof(SFTPDATA));\r
1349                         return &g_SFTPData[i];\r
1350                 }\r
1351         }\r
1352         return NULL;\r
1353 }\r
1354 \r
1355 SFTPDATA* FindSFTPDataFromSocket(SOCKET s)\r
1356 {\r
1357         int i;\r
1358         for(i = 0; i < MAX_SFTP_SOCKET; i++)\r
1359         {\r
1360                 if(g_SFTPData[i].Control == s || g_SFTPData[i].Data == s)\r
1361                         return &g_SFTPData[i];\r
1362         }\r
1363         return NULL;\r
1364 }\r
1365 \r
1366 // SFTPとしてマークされているか確認\r
1367 // マークされていればTRUEを返す\r
1368 BOOL IsSFTPAttached(SOCKET s)\r
1369 {\r
1370         SFTPDATA* pSFTPData;\r
1371         if(!g_bPuTTYLoaded)\r
1372                 return FALSE;\r
1373         EnterCriticalSection(&g_PuTTYLock);\r
1374         pSFTPData = FindSFTPDataFromSocket(s);\r
1375         LeaveCriticalSection(&g_PuTTYLock);\r
1376         if(!pSFTPData)\r
1377                 return FALSE;\r
1378         return TRUE;\r
1379 }\r
1380 \r
1381 // コントロール用の仮想的なソケットを取得\r
1382 // 識別子としてダミーのソケットを返す\r
1383 SOCKET SFTP_socket(int af, int type, int protocol)\r
1384 {\r
1385         SOCKET r;\r
1386         SFTPDATA* pSFTPData;\r
1387         if(!g_bPuTTYLoaded)\r
1388                 return INVALID_SOCKET;\r
1389         r = INVALID_SOCKET;\r
1390         EnterCriticalSection(&g_PuTTYLock);\r
1391         if(pSFTPData = GetUnusedSFTPData())\r
1392         {\r
1393                 r = socket(af, type, protocol);\r
1394                 pSFTPData->Control = r;\r
1395                 pSFTPData->Data = INVALID_SOCKET;\r
1396                 pSFTPData->Handle = p_SFTP_Create();\r
1397         }\r
1398         LeaveCriticalSection(&g_PuTTYLock);\r
1399         return r;\r
1400 }\r
1401 \r
1402 int SFTP_bind(SOCKET s, const struct sockaddr *addr, int namelen)\r
1403 {\r
1404         return SOCKET_ERROR;\r
1405 }\r
1406 \r
1407 int SFTP_listen(SOCKET s, int backlog)\r
1408 {\r
1409         return SOCKET_ERROR;\r
1410 }\r
1411 \r
1412 // accept相当の関数\r
1413 SOCKET SFTP_accept(SOCKET s, struct sockaddr *addr, int *addrlen)\r
1414 {\r
1415         return INVALID_SOCKET;\r
1416 }\r
1417 \r
1418 // connect相当の関数\r
1419 int SFTP_connect(SOCKET s, const struct sockaddr *name, int namelen)\r
1420 {\r
1421         SFTPDATA* pSFTPData;\r
1422         if(!g_bPuTTYLoaded)\r
1423                 return SOCKET_ERROR;\r
1424         EnterCriticalSection(&g_PuTTYLock);\r
1425         pSFTPData = FindSFTPDataFromSocket(s);\r
1426         LeaveCriticalSection(&g_PuTTYLock);\r
1427         if(!pSFTPData)\r
1428                 return SOCKET_ERROR;\r
1429         if(namelen == sizeof(struct sockaddr_in))\r
1430         {\r
1431         }\r
1432         else if(namelen == sizeof(struct sockaddr_in6))\r
1433         {\r
1434         }\r
1435         else\r
1436                 return SOCKET_ERROR;\r
1437         return 0;\r
1438 }\r
1439 \r
1440 // closesocket相当の関数\r
1441 int SFTP_closesocket(SOCKET s)\r
1442 {\r
1443         SFTPDATA* pSFTPData;\r
1444         if(!g_bPuTTYLoaded)\r
1445                 return SOCKET_ERROR;\r
1446         EnterCriticalSection(&g_PuTTYLock);\r
1447         if(pSFTPData = FindSFTPDataFromSocket(s))\r
1448         {\r
1449                 if(pSFTPData->Control == s)\r
1450                 {\r
1451                         pSFTPData->Control = INVALID_SOCKET;\r
1452                         p_SFTP_Destroy(pSFTPData->Handle);\r
1453                 }\r
1454                 if(pSFTPData->Data == s)\r
1455                         pSFTPData->Data = INVALID_SOCKET;\r
1456         }\r
1457         LeaveCriticalSection(&g_PuTTYLock);\r
1458         return closesocket(s);\r
1459 }\r
1460 \r
1461 // send相当の関数\r
1462 int SFTP_send(SOCKET s, const char * buf, int len, int flags)\r
1463 {\r
1464         int r;\r
1465         SFTPDATA* pSFTPData;\r
1466         if(!g_bPuTTYLoaded)\r
1467                 return SOCKET_ERROR;\r
1468         EnterCriticalSection(&g_PuTTYLock);\r
1469         pSFTPData = FindSFTPDataFromSocket(s);\r
1470         LeaveCriticalSection(&g_PuTTYLock);\r
1471         if(!pSFTPData)\r
1472                 return SOCKET_ERROR;\r
1473         if(p_SFTP_IsExited(pSFTPData->Handle))\r
1474                 return SOCKET_ERROR;\r
1475         r = SOCKET_ERROR;\r
1476         if(pSFTPData->Control == s)\r
1477                 r = (int)p_SFTP_WriteStdIn(pSFTPData->Handle, buf, len);\r
1478         else if(pSFTPData->Data == s)\r
1479                 r = (int)p_SFTP_WriteDataIn(pSFTPData->Handle, buf, len);\r
1480         return r;\r
1481 }\r
1482 \r
1483 // recv相当の関数\r
1484 int SFTP_recv(SOCKET s, char * buf, int len, int flags)\r
1485 {\r
1486         int r;\r
1487         SFTPDATA* pSFTPData;\r
1488         if(!g_bPuTTYLoaded)\r
1489                 return SOCKET_ERROR;\r
1490         EnterCriticalSection(&g_PuTTYLock);\r
1491         pSFTPData = FindSFTPDataFromSocket(s);\r
1492         LeaveCriticalSection(&g_PuTTYLock);\r
1493         if(!pSFTPData)\r
1494                 return SOCKET_ERROR;\r
1495         if(p_SFTP_IsExited(pSFTPData->Handle))\r
1496                 return SOCKET_ERROR;\r
1497         r = SOCKET_ERROR;\r
1498         if(pSFTPData->Control == s)\r
1499         {\r
1500                 if(flags & MSG_PEEK)\r
1501                         r = (int)p_SFTP_PeekStdOut(pSFTPData->Handle, buf, len);\r
1502                 else\r
1503                         r = (int)p_SFTP_ReadStdOut(pSFTPData->Handle, buf, len);\r
1504         }\r
1505         else if(pSFTPData->Data == s)\r
1506         {\r
1507                 if(flags & MSG_PEEK)\r
1508                         r = (int)p_SFTP_PeekDataOut(pSFTPData->Handle, buf, len);\r
1509                 else\r
1510                         r = (int)p_SFTP_ReadDataOut(pSFTPData->Handle, buf, len);\r
1511         }\r
1512         return r;\r
1513 }\r
1514 \r
1515 BOOL SFTP_SetTimeoutCallback(SOCKET s, void* pCallback)\r
1516 {\r
1517         SFTPDATA* pSFTPData;\r
1518         if(!g_bPuTTYLoaded)\r
1519                 return FALSE;\r
1520         EnterCriticalSection(&g_PuTTYLock);\r
1521         pSFTPData = FindSFTPDataFromSocket(s);\r
1522         LeaveCriticalSection(&g_PuTTYLock);\r
1523         if(!pSFTPData)\r
1524                 return FALSE;\r
1525         return p_SFTP_SetTimeoutCallback(pSFTPData->Handle, pCallback);\r
1526 }\r
1527 \r
1528 // データ用の仮想的なソケットを取得\r
1529 // 識別子としてダミーのソケットを返す\r
1530 SOCKET SFTP_GetDataHandle(SOCKET s, int af, int type, int protocol)\r
1531 {\r
1532         SOCKET r;\r
1533         SFTPDATA* pSFTPData;\r
1534         if(!g_bPuTTYLoaded)\r
1535                 return INVALID_SOCKET;\r
1536         r = INVALID_SOCKET;\r
1537         EnterCriticalSection(&g_PuTTYLock);\r
1538         if(pSFTPData = FindSFTPDataFromSocket(s))\r
1539         {\r
1540                 r = socket(af, type, protocol);\r
1541                 pSFTPData->Data = r;\r
1542         }\r
1543         LeaveCriticalSection(&g_PuTTYLock);\r
1544         return r;\r
1545 }\r
1546 \r
1547 BOOL SFTP_SetFilePosition(SOCKET s, LONGLONG Position)\r
1548 {\r
1549         SFTPDATA* pSFTPData;\r
1550         if(!g_bPuTTYLoaded)\r
1551                 return FALSE;\r
1552         EnterCriticalSection(&g_PuTTYLock);\r
1553         pSFTPData = FindSFTPDataFromSocket(s);\r
1554         LeaveCriticalSection(&g_PuTTYLock);\r
1555         if(!pSFTPData)\r
1556                 return FALSE;\r
1557         return p_SFTP_SetFilePosition(pSFTPData->Handle, Position);\r
1558 }\r
1559 \r