OSDN Git Service

Add routines for SSL root CA certificates.
[ffftp/ffftp.git] / socketwrapper.c
1 // socketwrapper.c\r
2 // Copyright (C) 2011 Suguru Kawamoto\r
3 // ソケットラッパー\r
4 // socket関連関数をOpenSSL用に置換\r
5 // コンパイルにはOpenSSLのヘッダーファイルが必要\r
6 // 実行にはOpenSSLのDLLが必要\r
7 \r
8 #include <windows.h>\r
9 #include <mmsystem.h>\r
10 #include <openssl/ssl.h>\r
11 \r
12 #include "socketwrapper.h"\r
13 #include "protectprocess.h"\r
14 \r
15 typedef void (__cdecl* _SSL_load_error_strings)();\r
16 typedef int (__cdecl* _SSL_library_init)();\r
17 typedef SSL_METHOD* (__cdecl* _SSLv23_method)();\r
18 typedef SSL_CTX* (__cdecl* _SSL_CTX_new)(SSL_METHOD*);\r
19 typedef void (__cdecl* _SSL_CTX_free)(SSL_CTX*);\r
20 typedef SSL* (__cdecl* _SSL_new)(SSL_CTX*);\r
21 typedef void (__cdecl* _SSL_free)(SSL*);\r
22 typedef int (__cdecl* _SSL_shutdown)(SSL*);\r
23 typedef int (__cdecl* _SSL_get_fd)(SSL*);\r
24 typedef int (__cdecl* _SSL_set_fd)(SSL*, int);\r
25 typedef int (__cdecl* _SSL_accept)(SSL*);\r
26 typedef int (__cdecl* _SSL_connect)(SSL*);\r
27 typedef int (__cdecl* _SSL_write)(SSL*, const void*, int);\r
28 typedef int (__cdecl* _SSL_peek)(SSL*, void*, int);\r
29 typedef int (__cdecl* _SSL_read)(SSL*, void*, int);\r
30 typedef int (__cdecl* _SSL_get_error)(SSL*, int);\r
31 typedef X509* (__cdecl* _SSL_get_peer_certificate)(const SSL*);\r
32 typedef long (__cdecl* _SSL_get_verify_result)(const SSL*);\r
33 typedef SSL_SESSION* (__cdecl* _SSL_get_session)(SSL*);\r
34 typedef int (__cdecl* _SSL_set_session)(SSL*, SSL_SESSION*);\r
35 typedef int (__cdecl* _SSL_CTX_use_certificate)(SSL_CTX*, X509*);\r
36 typedef BIO_METHOD* (__cdecl* _BIO_s_mem)();\r
37 typedef BIO* (__cdecl* _BIO_new)(BIO_METHOD*);\r
38 typedef int (__cdecl* _BIO_free)(BIO*);\r
39 typedef BIO* (__cdecl* _BIO_new_mem_buf)(void*, int);\r
40 typedef long (__cdecl* _BIO_ctrl)(BIO*, int, long, void*);\r
41 typedef void (__cdecl* _X509_free)(X509*);\r
42 typedef int (__cdecl* _X509_print_ex)(BIO*, X509*, unsigned long, unsigned long);\r
43 typedef X509_NAME* (__cdecl* _X509_get_subject_name)(X509*);\r
44 typedef int (__cdecl* _X509_NAME_print_ex)(BIO*, X509_NAME*, int, unsigned long);\r
45 typedef X509* (__cdecl* _PEM_read_bio_X509)(BIO*, X509**, pem_password_cb*, void*);\r
46 \r
47 _SSL_load_error_strings p_SSL_load_error_strings;\r
48 _SSL_library_init p_SSL_library_init;\r
49 _SSLv23_method p_SSLv23_method;\r
50 _SSL_CTX_new p_SSL_CTX_new;\r
51 _SSL_CTX_free p_SSL_CTX_free;\r
52 _SSL_new p_SSL_new;\r
53 _SSL_free p_SSL_free;\r
54 _SSL_shutdown p_SSL_shutdown;\r
55 _SSL_get_fd p_SSL_get_fd;\r
56 _SSL_set_fd p_SSL_set_fd;\r
57 _SSL_accept p_SSL_accept;\r
58 _SSL_connect p_SSL_connect;\r
59 _SSL_write p_SSL_write;\r
60 _SSL_peek p_SSL_peek;\r
61 _SSL_read p_SSL_read;\r
62 _SSL_get_error p_SSL_get_error;\r
63 _SSL_get_peer_certificate p_SSL_get_peer_certificate;\r
64 _SSL_get_verify_result p_SSL_get_verify_result;\r
65 _SSL_get_session p_SSL_get_session;\r
66 _SSL_set_session p_SSL_set_session;\r
67 _SSL_CTX_use_certificate p_SSL_CTX_use_certificate;\r
68 _BIO_s_mem p_BIO_s_mem;\r
69 _BIO_new p_BIO_new;\r
70 _BIO_free p_BIO_free;\r
71 _BIO_new_mem_buf p_BIO_new_mem_buf;\r
72 _BIO_ctrl p_BIO_ctrl;\r
73 _X509_free p_X509_free;\r
74 _X509_print_ex p_X509_print_ex;\r
75 _X509_get_subject_name p_X509_get_subject_name;\r
76 _X509_NAME_print_ex p_X509_NAME_print_ex;\r
77 _PEM_read_bio_X509 p_PEM_read_bio_X509;\r
78 \r
79 #define MAX_SSL_SOCKET 16\r
80 \r
81 BOOL g_bOpenSSLLoaded;\r
82 HMODULE g_hOpenSSL;\r
83 HMODULE g_hOpenSSLCommon;\r
84 CRITICAL_SECTION g_OpenSSLLock;\r
85 DWORD g_OpenSSLTimeout;\r
86 LPSSLTIMEOUTCALLBACK g_pOpenSSLTimeoutCallback;\r
87 LPSSLCONFIRMCALLBACK g_pOpenSSLConfirmCallback;\r
88 SSL_CTX* g_pOpenSSLCTX;\r
89 SSL* g_pOpenSSLHandle[MAX_SSL_SOCKET];\r
90 \r
91 BOOL __stdcall DefaultSSLTimeoutCallback(BOOL* pbAborted)\r
92 {\r
93         Sleep(100);\r
94         return *pbAborted;\r
95 }\r
96 \r
97 BOOL __stdcall DefaultSSLConfirmCallback(BOOL* pbAborted, BOOL bVerified, LPCSTR Certificate, LPCSTR CommonName)\r
98 {\r
99         return bVerified;\r
100 }\r
101 \r
102 // OpenSSLを初期化\r
103 BOOL LoadOpenSSL()\r
104 {\r
105         if(g_bOpenSSLLoaded)\r
106                 return FALSE;\r
107 #ifdef ENABLE_PROCESS_PROTECTION\r
108         // 同梱するOpenSSLのバージョンに合わせてSHA1ハッシュ値を変更すること\r
109         // ssleay32.dll 1.0.0e\r
110         // libssl32.dll 1.0.0e\r
111         RegisterTrustedModuleSHA1Hash("\x4E\xB7\xA0\x22\x14\x4B\x58\x6D\xBC\xF5\x21\x0D\x96\x78\x0D\x79\x7D\x66\xB2\xB0");\r
112         // libeay32.dll 1.0.0e\r
113         RegisterTrustedModuleSHA1Hash("\x01\x32\x7A\xAE\x69\x26\xE6\x58\xC7\x63\x22\x1E\x53\x5A\x78\xBC\x61\xC7\xB5\xC1");\r
114 #endif\r
115         g_hOpenSSL = LoadLibrary("ssleay32.dll");\r
116         // バージョン固定のためlibssl32.dllの読み込みは脆弱性の原因になり得るので廃止\r
117 //      if(!g_hOpenSSL)\r
118 //              g_hOpenSSL = LoadLibrary("libssl32.dll");\r
119         if(!g_hOpenSSL\r
120                 || !(p_SSL_load_error_strings = (_SSL_load_error_strings)GetProcAddress(g_hOpenSSL, "SSL_load_error_strings"))\r
121                 || !(p_SSL_library_init = (_SSL_library_init)GetProcAddress(g_hOpenSSL, "SSL_library_init"))\r
122                 || !(p_SSLv23_method = (_SSLv23_method)GetProcAddress(g_hOpenSSL, "SSLv23_method"))\r
123                 || !(p_SSL_CTX_new = (_SSL_CTX_new)GetProcAddress(g_hOpenSSL, "SSL_CTX_new"))\r
124                 || !(p_SSL_CTX_free = (_SSL_CTX_free)GetProcAddress(g_hOpenSSL, "SSL_CTX_free"))\r
125                 || !(p_SSL_new = (_SSL_new)GetProcAddress(g_hOpenSSL, "SSL_new"))\r
126                 || !(p_SSL_free = (_SSL_free)GetProcAddress(g_hOpenSSL, "SSL_free"))\r
127                 || !(p_SSL_shutdown = (_SSL_shutdown)GetProcAddress(g_hOpenSSL, "SSL_shutdown"))\r
128                 || !(p_SSL_get_fd = (_SSL_get_fd)GetProcAddress(g_hOpenSSL, "SSL_get_fd"))\r
129                 || !(p_SSL_set_fd = (_SSL_set_fd)GetProcAddress(g_hOpenSSL, "SSL_set_fd"))\r
130                 || !(p_SSL_accept = (_SSL_accept)GetProcAddress(g_hOpenSSL, "SSL_accept"))\r
131                 || !(p_SSL_connect = (_SSL_connect)GetProcAddress(g_hOpenSSL, "SSL_connect"))\r
132                 || !(p_SSL_write = (_SSL_write)GetProcAddress(g_hOpenSSL, "SSL_write"))\r
133                 || !(p_SSL_peek = (_SSL_peek)GetProcAddress(g_hOpenSSL, "SSL_peek"))\r
134                 || !(p_SSL_read = (_SSL_read)GetProcAddress(g_hOpenSSL, "SSL_read"))\r
135                 || !(p_SSL_get_error = (_SSL_get_error)GetProcAddress(g_hOpenSSL, "SSL_get_error"))\r
136                 || !(p_SSL_get_peer_certificate = (_SSL_get_peer_certificate)GetProcAddress(g_hOpenSSL, "SSL_get_peer_certificate"))\r
137                 || !(p_SSL_get_verify_result = (_SSL_get_verify_result)GetProcAddress(g_hOpenSSL, "SSL_get_verify_result"))\r
138                 || !(p_SSL_get_session = (_SSL_get_session)GetProcAddress(g_hOpenSSL, "SSL_get_session"))\r
139                 || !(p_SSL_set_session = (_SSL_set_session)GetProcAddress(g_hOpenSSL, "SSL_set_session"))\r
140                 || !(p_SSL_CTX_use_certificate = (_SSL_CTX_use_certificate)GetProcAddress(g_hOpenSSL, "SSL_CTX_use_certificate")))\r
141         {\r
142                 if(g_hOpenSSL)\r
143                         FreeLibrary(g_hOpenSSL);\r
144                 g_hOpenSSL = NULL;\r
145                 return FALSE;\r
146         }\r
147         g_hOpenSSLCommon = LoadLibrary("libeay32.dll");\r
148         if(!g_hOpenSSLCommon\r
149                 || !(p_BIO_s_mem = (_BIO_s_mem)GetProcAddress(g_hOpenSSLCommon, "BIO_s_mem"))\r
150                 || !(p_BIO_new = (_BIO_new)GetProcAddress(g_hOpenSSLCommon, "BIO_new"))\r
151                 || !(p_BIO_free = (_BIO_free)GetProcAddress(g_hOpenSSLCommon, "BIO_free"))\r
152                 || !(p_BIO_new_mem_buf = (_BIO_new_mem_buf)GetProcAddress(g_hOpenSSLCommon, "BIO_new_mem_buf"))\r
153                 || !(p_BIO_ctrl = (_BIO_ctrl)GetProcAddress(g_hOpenSSLCommon, "BIO_ctrl"))\r
154                 || !(p_X509_free = (_X509_free)GetProcAddress(g_hOpenSSLCommon, "X509_free"))\r
155                 || !(p_X509_print_ex = (_X509_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_print_ex"))\r
156                 || !(p_X509_get_subject_name = (_X509_get_subject_name)GetProcAddress(g_hOpenSSLCommon, "X509_get_subject_name"))\r
157                 || !(p_X509_NAME_print_ex = (_X509_NAME_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_NAME_print_ex"))\r
158                 || !(p_PEM_read_bio_X509 = (_PEM_read_bio_X509)GetProcAddress(g_hOpenSSLCommon, "PEM_read_bio_X509")))\r
159         {\r
160                 if(g_hOpenSSL)\r
161                         FreeLibrary(g_hOpenSSL);\r
162                 g_hOpenSSL = NULL;\r
163                 if(g_hOpenSSLCommon)\r
164                         FreeLibrary(g_hOpenSSLCommon);\r
165                 g_hOpenSSLCommon = NULL;\r
166                 return FALSE;\r
167         }\r
168         InitializeCriticalSection(&g_OpenSSLLock);\r
169         p_SSL_load_error_strings();\r
170         p_SSL_library_init();\r
171         SetSSLTimeoutCallback(60000, DefaultSSLTimeoutCallback);\r
172         SetSSLConfirmCallback(DefaultSSLConfirmCallback);\r
173         g_bOpenSSLLoaded = TRUE;\r
174         return TRUE;\r
175 }\r
176 \r
177 // OpenSSLを解放\r
178 void FreeOpenSSL()\r
179 {\r
180         int i;\r
181         if(!g_bOpenSSLLoaded)\r
182                 return;\r
183         EnterCriticalSection(&g_OpenSSLLock);\r
184         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
185         {\r
186                 if(g_pOpenSSLHandle[i])\r
187                 {\r
188                         p_SSL_shutdown(g_pOpenSSLHandle[i]);\r
189                         p_SSL_free(g_pOpenSSLHandle[i]);\r
190                         g_pOpenSSLHandle[i] = NULL;\r
191                 }\r
192         }\r
193         if(g_pOpenSSLCTX)\r
194                 p_SSL_CTX_free(g_pOpenSSLCTX);\r
195         g_pOpenSSLCTX = NULL;\r
196         FreeLibrary(g_hOpenSSL);\r
197         g_hOpenSSL = NULL;\r
198         FreeLibrary(g_hOpenSSLCommon);\r
199         g_hOpenSSLCommon = NULL;\r
200         LeaveCriticalSection(&g_OpenSSLLock);\r
201         DeleteCriticalSection(&g_OpenSSLLock);\r
202         g_bOpenSSLLoaded = FALSE;\r
203 }\r
204 \r
205 // OpenSSLが使用可能かどうか確認\r
206 BOOL IsOpenSSLLoaded()\r
207 {\r
208         return g_bOpenSSLLoaded;\r
209 }\r
210 \r
211 SSL** GetUnusedSSLPointer()\r
212 {\r
213         int i;\r
214         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
215         {\r
216                 if(!g_pOpenSSLHandle[i])\r
217                         return &g_pOpenSSLHandle[i];\r
218         }\r
219         return NULL;\r
220 }\r
221 \r
222 SSL** FindSSLPointerFromSocket(SOCKET s)\r
223 {\r
224         int i;\r
225         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
226         {\r
227                 if(g_pOpenSSLHandle[i])\r
228                 {\r
229                         if(p_SSL_get_fd(g_pOpenSSLHandle[i]) == s)\r
230                                 return &g_pOpenSSLHandle[i];\r
231                 }\r
232         }\r
233         return NULL;\r
234 }\r
235 \r
236 BOOL ConfirmSSLCertificate(SSL* pSSL, BOOL* pbAborted)\r
237 {\r
238         BOOL bResult;\r
239         BOOL bVerified;\r
240         char* pData;\r
241         char* pSubject;\r
242         X509* pX509;\r
243         BIO* pBIO;\r
244         long Length;\r
245         char* pBuffer;\r
246         char* pCN;\r
247         char* p;\r
248         bResult = FALSE;\r
249         bVerified = FALSE;\r
250         pData = NULL;\r
251         pSubject = NULL;\r
252         if(pX509 = p_SSL_get_peer_certificate(pSSL))\r
253         {\r
254                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
255                 {\r
256                         p_X509_print_ex(pBIO, pX509, 0, XN_FLAG_RFC2253);\r
257                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
258                         {\r
259                                 if(pData = (char*)malloc(Length + sizeof(char)))\r
260                                 {\r
261                                         memcpy(pData, pBuffer, Length);\r
262                                         *(char*)((size_t)pData + Length) = '\0';\r
263                                 }\r
264                         }\r
265                         p_BIO_free(pBIO);\r
266                 }\r
267                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
268                 {\r
269                         p_X509_NAME_print_ex(pBIO, p_X509_get_subject_name(pX509), 0, XN_FLAG_RFC2253);\r
270                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
271                         {\r
272                                 if(pSubject = (char*)malloc(Length + sizeof(char)))\r
273                                 {\r
274                                         memcpy(pSubject, pBuffer, Length);\r
275                                         *(char*)((size_t)pSubject + Length) = '\0';\r
276                                 }\r
277                         }\r
278                         p_BIO_free(pBIO);\r
279                 }\r
280                 p_X509_free(pX509);\r
281         }\r
282         if(p_SSL_get_verify_result(pSSL) == X509_V_OK)\r
283                 bVerified = TRUE;\r
284         pCN = pSubject;\r
285         while(pCN)\r
286         {\r
287                 if(strncmp(pCN, "CN=", strlen("CN=")) == 0)\r
288                 {\r
289                         pCN += strlen("CN=");\r
290                         if(p = strchr(pCN, ','))\r
291                                 *p = '\0';\r
292                         break;\r
293                 }\r
294                 if(pCN = strchr(pCN, ','))\r
295                         pCN++;\r
296         }\r
297         bResult = g_pOpenSSLConfirmCallback(pbAborted, bVerified, pData, pCN);\r
298         if(pData)\r
299                 free(pData);\r
300         if(pSubject)\r
301                 free(pSubject);\r
302         return bResult;\r
303 }\r
304 \r
305 void SetSSLTimeoutCallback(DWORD Timeout, LPSSLTIMEOUTCALLBACK pCallback)\r
306 {\r
307         if(!g_bOpenSSLLoaded)\r
308                 return;\r
309         EnterCriticalSection(&g_OpenSSLLock);\r
310         g_OpenSSLTimeout = Timeout;\r
311         g_pOpenSSLTimeoutCallback = pCallback;\r
312         LeaveCriticalSection(&g_OpenSSLLock);\r
313 }\r
314 \r
315 void SetSSLConfirmCallback(LPSSLCONFIRMCALLBACK pCallback)\r
316 {\r
317         if(!g_bOpenSSLLoaded)\r
318                 return;\r
319         EnterCriticalSection(&g_OpenSSLLock);\r
320         g_pOpenSSLConfirmCallback = pCallback;\r
321         LeaveCriticalSection(&g_OpenSSLLock);\r
322 }\r
323 \r
324 // SSLルート証明書を設定\r
325 BOOL SetSSLRootCertificate(void* pData, DWORD Length)\r
326 {\r
327         BOOL r;\r
328         BIO* pBIO;\r
329         X509* pX509;\r
330         if(!g_bOpenSSLLoaded)\r
331                 return FALSE;\r
332         r = FALSE;\r
333         EnterCriticalSection(&g_OpenSSLLock);\r
334         if(!g_pOpenSSLCTX)\r
335                 g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
336         if(g_pOpenSSLCTX)\r
337         {\r
338                 if(pBIO = p_BIO_new_mem_buf(pData, Length))\r
339                 {\r
340                         if(pX509 = p_PEM_read_bio_X509(pBIO, NULL, NULL, NULL))\r
341                         {\r
342                                 if(p_SSL_CTX_use_certificate(g_pOpenSSLCTX, pX509) == 1)\r
343                                         r = TRUE;\r
344                                 p_X509_free(pX509);\r
345                         }\r
346                         p_BIO_free(pBIO);\r
347                 }\r
348         }\r
349         LeaveCriticalSection(&g_OpenSSLLock);\r
350         return r;\r
351 }\r
352 \r
353 // ワイルドカードの比較\r
354 // 主にSSL証明書のCN確認用\r
355 BOOL IsHostNameMatched(LPCSTR HostName, LPCSTR CommonName)\r
356 {\r
357         BOOL bResult;\r
358         char* pAsterisk;\r
359         bResult = FALSE;\r
360         if(HostName && CommonName)\r
361         {\r
362                 if(pAsterisk = strchr(CommonName, '*'))\r
363                 {\r
364                         if(_strnicmp(HostName, CommonName, ((size_t)pAsterisk - (size_t)CommonName) / sizeof(char)) == 0)\r
365                         {\r
366                                 while(*pAsterisk == '*')\r
367                                 {\r
368                                         pAsterisk++;\r
369                                 }\r
370                                 if(_stricmp(HostName + strlen(HostName) - strlen(pAsterisk), pAsterisk) == 0)\r
371                                         bResult = TRUE;\r
372                         }\r
373                 }\r
374                 else if(_stricmp(HostName, CommonName) == 0)\r
375                         bResult = TRUE;\r
376         }\r
377         return bResult;\r
378 }\r
379 \r
380 // SSLセッションを開始\r
381 BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted)\r
382 {\r
383         BOOL r;\r
384         DWORD Time;\r
385         SSL** ppSSL;\r
386         SSL** ppSSLParent;\r
387         SSL_SESSION* pSession;\r
388         int Return;\r
389         int Error;\r
390         if(!g_bOpenSSLLoaded)\r
391                 return FALSE;\r
392         r = FALSE;\r
393         Time = timeGetTime();\r
394         EnterCriticalSection(&g_OpenSSLLock);\r
395         if(!g_pOpenSSLCTX)\r
396                 g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
397         if(g_pOpenSSLCTX)\r
398         {\r
399                 if(ppSSL = GetUnusedSSLPointer())\r
400                 {\r
401                         if(*ppSSL = p_SSL_new(g_pOpenSSLCTX))\r
402                         {\r
403                                 if(p_SSL_set_fd(*ppSSL, s) != 0)\r
404                                 {\r
405                                         if(parent != INVALID_SOCKET)\r
406                                         {\r
407                                                 if(ppSSLParent = FindSSLPointerFromSocket(parent))\r
408                                                 {\r
409                                                         if(pSession = p_SSL_get_session(*ppSSLParent))\r
410                                                         {\r
411                                                                 if(p_SSL_set_session(*ppSSL, pSession) == 1)\r
412                                                                 {\r
413                                                                 }\r
414                                                         }\r
415                                                 }\r
416                                         }\r
417                                         // SSLのネゴシエーションには時間がかかる場合がある\r
418                                         r = TRUE;\r
419                                         while(r)\r
420                                         {\r
421                                                 Return = p_SSL_connect(*ppSSL);\r
422                                                 if(Return == 1)\r
423                                                         break;\r
424                                                 Error = p_SSL_get_error(*ppSSL, Return);\r
425                                                 if(Error == SSL_ERROR_WANT_READ || Error == SSL_ERROR_WANT_WRITE)\r
426                                                 {\r
427                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
428                                                         if(g_pOpenSSLTimeoutCallback(pbAborted) || (g_OpenSSLTimeout > 0 && timeGetTime() - Time >= g_OpenSSLTimeout))\r
429                                                                 r = FALSE;\r
430                                                         EnterCriticalSection(&g_OpenSSLLock);\r
431                                                 }\r
432                                                 else\r
433                                                         r = FALSE;\r
434                                         }\r
435                                         if(r)\r
436                                         {\r
437                                                 if(ConfirmSSLCertificate(*ppSSL, pbAborted))\r
438                                                 {\r
439                                                 }\r
440                                                 else\r
441                                                 {\r
442                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
443                                                         DetachSSL(s);\r
444                                                         r = FALSE;\r
445                                                         EnterCriticalSection(&g_OpenSSLLock);\r
446                                                 }\r
447                                         }\r
448                                         else\r
449                                         {\r
450                                                 LeaveCriticalSection(&g_OpenSSLLock);\r
451                                                 DetachSSL(s);\r
452                                                 EnterCriticalSection(&g_OpenSSLLock);\r
453                                         }\r
454                                 }\r
455                                 else\r
456                                 {\r
457                                         LeaveCriticalSection(&g_OpenSSLLock);\r
458                                         DetachSSL(s);\r
459                                         EnterCriticalSection(&g_OpenSSLLock);\r
460                                 }\r
461                         }\r
462                 }\r
463         }\r
464         LeaveCriticalSection(&g_OpenSSLLock);\r
465         return r;\r
466 }\r
467 \r
468 // SSLセッションを終了\r
469 BOOL DetachSSL(SOCKET s)\r
470 {\r
471         BOOL r;\r
472         SSL** ppSSL;\r
473         if(!g_bOpenSSLLoaded)\r
474                 return FALSE;\r
475         r = FALSE;\r
476         EnterCriticalSection(&g_OpenSSLLock);\r
477         if(ppSSL = FindSSLPointerFromSocket(s))\r
478         {\r
479                 p_SSL_shutdown(*ppSSL);\r
480                 p_SSL_free(*ppSSL);\r
481                 *ppSSL = NULL;\r
482                 r = TRUE;\r
483         }\r
484         LeaveCriticalSection(&g_OpenSSLLock);\r
485         return r;\r
486 }\r
487 \r
488 // SSLとしてマークされているか確認\r
489 // マークされていればTRUEを返す\r
490 BOOL IsSSLAttached(SOCKET s)\r
491 {\r
492         SSL** ppSSL;\r
493         if(!g_bOpenSSLLoaded)\r
494                 return FALSE;\r
495         EnterCriticalSection(&g_OpenSSLLock);\r
496         ppSSL = FindSSLPointerFromSocket(s);\r
497         LeaveCriticalSection(&g_OpenSSLLock);\r
498         if(!ppSSL)\r
499                 return FALSE;\r
500         return TRUE;\r
501 }\r
502 \r
503 SOCKET socketS(int af, int type, int protocol)\r
504 {\r
505         return socket(af, type, protocol);\r
506 }\r
507 \r
508 int bindS(SOCKET s, const struct sockaddr *addr, int namelen)\r
509 {\r
510         return bind(s, addr, namelen);\r
511 }\r
512 \r
513 int listenS(SOCKET s, int backlog)\r
514 {\r
515         return listen(s, backlog);\r
516 }\r
517 \r
518 // accept相当の関数\r
519 // ただし初めからSSLのネゴシエーションを行う\r
520 SOCKET acceptS(SOCKET s, struct sockaddr *addr, int *addrlen)\r
521 {\r
522         SOCKET r;\r
523         BOOL bAborted;\r
524         r = accept(s, addr, addrlen);\r
525         bAborted = FALSE;\r
526         if(!AttachSSL(r, INVALID_SOCKET, &bAborted))\r
527         {\r
528                 closesocket(r);\r
529                 return INVALID_SOCKET;\r
530         }\r
531         return r;\r
532 }\r
533 \r
534 // connect相当の関数\r
535 // ただし初めからSSLのネゴシエーションを行う\r
536 int connectS(SOCKET s, const struct sockaddr *name, int namelen)\r
537 {\r
538         int r;\r
539         BOOL bAborted;\r
540         r = connect(s, name, namelen);\r
541         bAborted = FALSE;\r
542         if(!AttachSSL(r, INVALID_SOCKET, &bAborted))\r
543                 return SOCKET_ERROR;\r
544         return r;\r
545 }\r
546 \r
547 // closesocket相当の関数\r
548 int closesocketS(SOCKET s)\r
549 {\r
550         DetachSSL(s);\r
551         return closesocket(s);\r
552 }\r
553 \r
554 // send相当の関数\r
555 int sendS(SOCKET s, const char * buf, int len, int flags)\r
556 {\r
557         SSL** ppSSL;\r
558         if(!g_bOpenSSLLoaded)\r
559                 return send(s, buf, len, flags);\r
560         EnterCriticalSection(&g_OpenSSLLock);\r
561         ppSSL = FindSSLPointerFromSocket(s);\r
562         LeaveCriticalSection(&g_OpenSSLLock);\r
563         if(!ppSSL)\r
564                 return send(s, buf, len, flags);\r
565         return p_SSL_write(*ppSSL, buf, len);\r
566 }\r
567 \r
568 // recv相当の関数\r
569 int recvS(SOCKET s, char * buf, int len, int flags)\r
570 {\r
571         SSL** ppSSL;\r
572         if(!g_bOpenSSLLoaded)\r
573                 return recv(s, buf, len, flags);\r
574         EnterCriticalSection(&g_OpenSSLLock);\r
575         ppSSL = FindSSLPointerFromSocket(s);\r
576         LeaveCriticalSection(&g_OpenSSLLock);\r
577         if(!ppSSL)\r
578                 return recv(s, buf, len, flags);\r
579         if(flags & MSG_PEEK)\r
580                 return p_SSL_peek(*ppSSL, buf, len);\r
581         return p_SSL_read(*ppSSL, buf, len);\r
582 }\r
583 \r