OSDN Git Service

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