OSDN Git Service

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