OSDN Git Service

Enhanced routine for simultaneous connection and canceling or aborting.
[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 BIO_METHOD* (__cdecl* _BIO_s_mem)();\r
36 typedef BIO* (__cdecl* _BIO_new)(BIO_METHOD*);\r
37 typedef int (__cdecl* _BIO_free)(BIO*);\r
38 typedef long (__cdecl* _BIO_ctrl)(BIO*, int, long, void*);\r
39 typedef void (__cdecl* _X509_free)(X509*);\r
40 typedef int (__cdecl* _X509_print_ex)(BIO*, X509*, unsigned long, unsigned long);\r
41 typedef X509_NAME* (__cdecl* _X509_get_subject_name)(X509*);\r
42 typedef int (__cdecl* _X509_NAME_print_ex)(BIO*, X509_NAME*, int, unsigned long);\r
43 \r
44 _SSL_load_error_strings p_SSL_load_error_strings;\r
45 _SSL_library_init p_SSL_library_init;\r
46 _SSLv23_method p_SSLv23_method;\r
47 _SSL_CTX_new p_SSL_CTX_new;\r
48 _SSL_CTX_free p_SSL_CTX_free;\r
49 _SSL_new p_SSL_new;\r
50 _SSL_free p_SSL_free;\r
51 _SSL_shutdown p_SSL_shutdown;\r
52 _SSL_get_fd p_SSL_get_fd;\r
53 _SSL_set_fd p_SSL_set_fd;\r
54 _SSL_accept p_SSL_accept;\r
55 _SSL_connect p_SSL_connect;\r
56 _SSL_write p_SSL_write;\r
57 _SSL_peek p_SSL_peek;\r
58 _SSL_read p_SSL_read;\r
59 _SSL_get_error p_SSL_get_error;\r
60 _SSL_get_peer_certificate p_SSL_get_peer_certificate;\r
61 _SSL_get_verify_result p_SSL_get_verify_result;\r
62 _SSL_get_session p_SSL_get_session;\r
63 _SSL_set_session p_SSL_set_session;\r
64 _BIO_s_mem p_BIO_s_mem;\r
65 _BIO_new p_BIO_new;\r
66 _BIO_free p_BIO_free;\r
67 _BIO_ctrl p_BIO_ctrl;\r
68 _X509_free p_X509_free;\r
69 _X509_print_ex p_X509_print_ex;\r
70 _X509_get_subject_name p_X509_get_subject_name;\r
71 _X509_NAME_print_ex p_X509_NAME_print_ex;\r
72 \r
73 #define MAX_SSL_SOCKET 64\r
74 \r
75 BOOL g_bOpenSSLLoaded;\r
76 HMODULE g_hOpenSSL;\r
77 HMODULE g_hOpenSSLCommon;\r
78 CRITICAL_SECTION g_OpenSSLLock;\r
79 DWORD g_OpenSSLTimeout;\r
80 LPSSLTIMEOUTCALLBACK g_pOpenSSLTimeoutCallback;\r
81 LPSSLCONFIRMCALLBACK g_pOpenSSLConfirmCallback;\r
82 SSL_CTX* g_pOpenSSLCTX;\r
83 SSL* g_pOpenSSLHandle[MAX_SSL_SOCKET];\r
84 \r
85 BOOL __stdcall DefaultSSLTimeoutCallback(BOOL* pbAborted)\r
86 {\r
87         Sleep(100);\r
88         return *pbAborted;\r
89 }\r
90 \r
91 BOOL __stdcall DefaultSSLConfirmCallback(BOOL* pbAborted, BOOL bVerified, LPCSTR Certificate, LPCSTR CommonName)\r
92 {\r
93         return bVerified;\r
94 }\r
95 \r
96 BOOL LoadOpenSSL()\r
97 {\r
98         if(g_bOpenSSLLoaded)\r
99                 return FALSE;\r
100 #ifdef ENABLE_PROCESS_PROTECTION\r
101         // 同梱するOpenSSLのバージョンに合わせてSHA1ハッシュ値を変更すること\r
102         // ssleay32.dll 1.0.0e\r
103         // libssl32.dll 1.0.0e\r
104         RegisterTrustedModuleSHA1Hash("\x4E\xB7\xA0\x22\x14\x4B\x58\x6D\xBC\xF5\x21\x0D\x96\x78\x0D\x79\x7D\x66\xB2\xB0");\r
105         // libeay32.dll 1.0.0e\r
106         RegisterTrustedModuleSHA1Hash("\x01\x32\x7A\xAE\x69\x26\xE6\x58\xC7\x63\x22\x1E\x53\x5A\x78\xBC\x61\xC7\xB5\xC1");\r
107 #endif\r
108         g_hOpenSSL = LoadLibrary("ssleay32.dll");\r
109         if(!g_hOpenSSL)\r
110                 g_hOpenSSL = LoadLibrary("libssl32.dll");\r
111         if(!g_hOpenSSL\r
112                 || !(p_SSL_load_error_strings = (_SSL_load_error_strings)GetProcAddress(g_hOpenSSL, "SSL_load_error_strings"))\r
113                 || !(p_SSL_library_init = (_SSL_library_init)GetProcAddress(g_hOpenSSL, "SSL_library_init"))\r
114                 || !(p_SSLv23_method = (_SSLv23_method)GetProcAddress(g_hOpenSSL, "SSLv23_method"))\r
115                 || !(p_SSL_CTX_new = (_SSL_CTX_new)GetProcAddress(g_hOpenSSL, "SSL_CTX_new"))\r
116                 || !(p_SSL_CTX_free = (_SSL_CTX_free)GetProcAddress(g_hOpenSSL, "SSL_CTX_free"))\r
117                 || !(p_SSL_new = (_SSL_new)GetProcAddress(g_hOpenSSL, "SSL_new"))\r
118                 || !(p_SSL_free = (_SSL_free)GetProcAddress(g_hOpenSSL, "SSL_free"))\r
119                 || !(p_SSL_shutdown = (_SSL_shutdown)GetProcAddress(g_hOpenSSL, "SSL_shutdown"))\r
120                 || !(p_SSL_get_fd = (_SSL_get_fd)GetProcAddress(g_hOpenSSL, "SSL_get_fd"))\r
121                 || !(p_SSL_set_fd = (_SSL_set_fd)GetProcAddress(g_hOpenSSL, "SSL_set_fd"))\r
122                 || !(p_SSL_accept = (_SSL_accept)GetProcAddress(g_hOpenSSL, "SSL_accept"))\r
123                 || !(p_SSL_connect = (_SSL_connect)GetProcAddress(g_hOpenSSL, "SSL_connect"))\r
124                 || !(p_SSL_write = (_SSL_write)GetProcAddress(g_hOpenSSL, "SSL_write"))\r
125                 || !(p_SSL_peek = (_SSL_peek)GetProcAddress(g_hOpenSSL, "SSL_peek"))\r
126                 || !(p_SSL_read = (_SSL_read)GetProcAddress(g_hOpenSSL, "SSL_read"))\r
127                 || !(p_SSL_get_error = (_SSL_get_error)GetProcAddress(g_hOpenSSL, "SSL_get_error"))\r
128                 || !(p_SSL_get_peer_certificate = (_SSL_get_peer_certificate)GetProcAddress(g_hOpenSSL, "SSL_get_peer_certificate"))\r
129                 || !(p_SSL_get_verify_result = (_SSL_get_verify_result)GetProcAddress(g_hOpenSSL, "SSL_get_verify_result"))\r
130                 || !(p_SSL_get_session = (_SSL_get_session)GetProcAddress(g_hOpenSSL, "SSL_get_session"))\r
131                 || !(p_SSL_set_session = (_SSL_set_session)GetProcAddress(g_hOpenSSL, "SSL_set_session")))\r
132         {\r
133                 if(g_hOpenSSL)\r
134                         FreeLibrary(g_hOpenSSL);\r
135                 g_hOpenSSL = NULL;\r
136                 return FALSE;\r
137         }\r
138         g_hOpenSSLCommon = LoadLibrary("libeay32.dll");\r
139         if(!g_hOpenSSLCommon\r
140                 || !(p_BIO_s_mem = (_BIO_s_mem)GetProcAddress(g_hOpenSSLCommon, "BIO_s_mem"))\r
141                 || !(p_BIO_new = (_BIO_new)GetProcAddress(g_hOpenSSLCommon, "BIO_new"))\r
142                 || !(p_BIO_free = (_BIO_free)GetProcAddress(g_hOpenSSLCommon, "BIO_free"))\r
143                 || !(p_BIO_ctrl = (_BIO_ctrl)GetProcAddress(g_hOpenSSLCommon, "BIO_ctrl"))\r
144                 || !(p_X509_free = (_X509_free)GetProcAddress(g_hOpenSSLCommon, "X509_free"))\r
145                 || !(p_X509_print_ex = (_X509_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_print_ex"))\r
146                 || !(p_X509_get_subject_name = (_X509_get_subject_name)GetProcAddress(g_hOpenSSLCommon, "X509_get_subject_name"))\r
147                 || !(p_X509_NAME_print_ex = (_X509_NAME_print_ex)GetProcAddress(g_hOpenSSLCommon, "X509_NAME_print_ex")))\r
148         {\r
149                 if(g_hOpenSSL)\r
150                         FreeLibrary(g_hOpenSSL);\r
151                 g_hOpenSSL = NULL;\r
152                 if(g_hOpenSSLCommon)\r
153                         FreeLibrary(g_hOpenSSLCommon);\r
154                 g_hOpenSSLCommon = NULL;\r
155                 return FALSE;\r
156         }\r
157         InitializeCriticalSection(&g_OpenSSLLock);\r
158         p_SSL_load_error_strings();\r
159         p_SSL_library_init();\r
160         SetSSLTimeoutCallback(60000, DefaultSSLTimeoutCallback);\r
161         SetSSLConfirmCallback(DefaultSSLConfirmCallback);\r
162         g_bOpenSSLLoaded = TRUE;\r
163         return TRUE;\r
164 }\r
165 \r
166 void FreeOpenSSL()\r
167 {\r
168         int i;\r
169         if(!g_bOpenSSLLoaded)\r
170                 return;\r
171         EnterCriticalSection(&g_OpenSSLLock);\r
172         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
173         {\r
174                 if(g_pOpenSSLHandle[i])\r
175                 {\r
176                         p_SSL_shutdown(g_pOpenSSLHandle[i]);\r
177                         p_SSL_free(g_pOpenSSLHandle[i]);\r
178                         g_pOpenSSLHandle[i] = NULL;\r
179                 }\r
180         }\r
181         if(g_pOpenSSLCTX)\r
182                 p_SSL_CTX_free(g_pOpenSSLCTX);\r
183         g_pOpenSSLCTX = NULL;\r
184         FreeLibrary(g_hOpenSSL);\r
185         g_hOpenSSL = NULL;\r
186         FreeLibrary(g_hOpenSSLCommon);\r
187         g_hOpenSSLCommon = NULL;\r
188         LeaveCriticalSection(&g_OpenSSLLock);\r
189         DeleteCriticalSection(&g_OpenSSLLock);\r
190         g_bOpenSSLLoaded = FALSE;\r
191 }\r
192 \r
193 BOOL IsOpenSSLLoaded()\r
194 {\r
195         return g_bOpenSSLLoaded;\r
196 }\r
197 \r
198 SSL** GetUnusedSSLPointer()\r
199 {\r
200         int i;\r
201         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
202         {\r
203                 if(!g_pOpenSSLHandle[i])\r
204                         return &g_pOpenSSLHandle[i];\r
205         }\r
206         return NULL;\r
207 }\r
208 \r
209 SSL** FindSSLPointerFromSocket(SOCKET s)\r
210 {\r
211         int i;\r
212         for(i = 0; i < MAX_SSL_SOCKET; i++)\r
213         {\r
214                 if(g_pOpenSSLHandle[i])\r
215                 {\r
216                         if(p_SSL_get_fd(g_pOpenSSLHandle[i]) == s)\r
217                                 return &g_pOpenSSLHandle[i];\r
218                 }\r
219         }\r
220         return NULL;\r
221 }\r
222 \r
223 BOOL ConfirmSSLCertificate(SSL* pSSL, BOOL* pbAborted)\r
224 {\r
225         BOOL bResult;\r
226         BOOL bVerified;\r
227         char* pData;\r
228         char* pSubject;\r
229         X509* pX509;\r
230         BIO* pBIO;\r
231         long Length;\r
232         char* pBuffer;\r
233         char* pCN;\r
234         char* p;\r
235         bResult = FALSE;\r
236         bVerified = FALSE;\r
237         pData = NULL;\r
238         pSubject = NULL;\r
239         if(pX509 = p_SSL_get_peer_certificate(pSSL))\r
240         {\r
241                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
242                 {\r
243                         p_X509_print_ex(pBIO, pX509, 0, XN_FLAG_RFC2253);\r
244                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
245                         {\r
246                                 if(pData = (char*)malloc(Length + sizeof(char)))\r
247                                 {\r
248                                         memcpy(pData, pBuffer, Length);\r
249                                         *(char*)((size_t)pData + Length) = '\0';\r
250                                 }\r
251                         }\r
252                         p_BIO_free(pBIO);\r
253                 }\r
254                 if(pBIO = p_BIO_new(p_BIO_s_mem()))\r
255                 {\r
256                         p_X509_NAME_print_ex(pBIO, p_X509_get_subject_name(pX509), 0, XN_FLAG_RFC2253);\r
257                         if((Length = p_BIO_ctrl(pBIO, BIO_CTRL_INFO, 0, &pBuffer)) > 0)\r
258                         {\r
259                                 if(pSubject = (char*)malloc(Length + sizeof(char)))\r
260                                 {\r
261                                         memcpy(pSubject, pBuffer, Length);\r
262                                         *(char*)((size_t)pSubject + Length) = '\0';\r
263                                 }\r
264                         }\r
265                         p_BIO_free(pBIO);\r
266                 }\r
267                 p_X509_free(pX509);\r
268         }\r
269         if(p_SSL_get_verify_result(pSSL) == X509_V_OK)\r
270                 bVerified = TRUE;\r
271         pCN = pSubject;\r
272         while(pCN)\r
273         {\r
274                 if(strncmp(pCN, "CN=", strlen("CN=")) == 0)\r
275                 {\r
276                         pCN += strlen("CN=");\r
277                         if(p = strchr(pCN, ','))\r
278                                 *p = '\0';\r
279                         break;\r
280                 }\r
281                 if(pCN = strchr(pCN, ','))\r
282                         pCN++;\r
283         }\r
284         bResult = g_pOpenSSLConfirmCallback(pbAborted, bVerified, pData, pCN);\r
285         if(pData)\r
286                 free(pData);\r
287         if(pSubject)\r
288                 free(pSubject);\r
289         return bResult;\r
290 }\r
291 \r
292 void SetSSLTimeoutCallback(DWORD Timeout, LPSSLTIMEOUTCALLBACK pCallback)\r
293 {\r
294         if(!g_bOpenSSLLoaded)\r
295                 return;\r
296         EnterCriticalSection(&g_OpenSSLLock);\r
297         g_OpenSSLTimeout = Timeout;\r
298         g_pOpenSSLTimeoutCallback = pCallback;\r
299         LeaveCriticalSection(&g_OpenSSLLock);\r
300 }\r
301 \r
302 void SetSSLConfirmCallback(LPSSLCONFIRMCALLBACK pCallback)\r
303 {\r
304         if(!g_bOpenSSLLoaded)\r
305                 return;\r
306         EnterCriticalSection(&g_OpenSSLLock);\r
307         g_pOpenSSLConfirmCallback = pCallback;\r
308         LeaveCriticalSection(&g_OpenSSLLock);\r
309 }\r
310 \r
311 BOOL IsHostNameMatched(LPCSTR HostName, LPCSTR CommonName)\r
312 {\r
313         BOOL bResult;\r
314         char* pAsterisk;\r
315         bResult = FALSE;\r
316         if(HostName && CommonName)\r
317         {\r
318                 if(pAsterisk = strchr(CommonName, '*'))\r
319                 {\r
320                         if(_strnicmp(HostName, CommonName, ((size_t)pAsterisk - (size_t)CommonName) / sizeof(char)) == 0)\r
321                         {\r
322                                 while(*pAsterisk == '*')\r
323                                 {\r
324                                         pAsterisk++;\r
325                                 }\r
326                                 if(_stricmp(HostName + strlen(HostName) - strlen(pAsterisk), pAsterisk) == 0)\r
327                                         bResult = TRUE;\r
328                         }\r
329                 }\r
330                 else if(_stricmp(HostName, CommonName) == 0)\r
331                         bResult = TRUE;\r
332         }\r
333         return bResult;\r
334 }\r
335 \r
336 BOOL AttachSSL(SOCKET s, SOCKET parent, BOOL* pbAborted)\r
337 {\r
338         BOOL r;\r
339         DWORD Time;\r
340         SSL** ppSSL;\r
341         SSL** ppSSLParent;\r
342         SSL_SESSION* pSession;\r
343         int Return;\r
344         int Error;\r
345         if(!g_bOpenSSLLoaded)\r
346                 return FALSE;\r
347         r = FALSE;\r
348         Time = timeGetTime();\r
349         EnterCriticalSection(&g_OpenSSLLock);\r
350         if(!g_pOpenSSLCTX)\r
351                 g_pOpenSSLCTX = p_SSL_CTX_new(p_SSLv23_method());\r
352         if(g_pOpenSSLCTX)\r
353         {\r
354                 if(ppSSL = GetUnusedSSLPointer())\r
355                 {\r
356                         if(*ppSSL = p_SSL_new(g_pOpenSSLCTX))\r
357                         {\r
358                                 if(p_SSL_set_fd(*ppSSL, s) != 0)\r
359                                 {\r
360                                         if(parent != INVALID_SOCKET)\r
361                                         {\r
362                                                 if(ppSSLParent = FindSSLPointerFromSocket(parent))\r
363                                                 {\r
364                                                         if(pSession = p_SSL_get_session(*ppSSLParent))\r
365                                                         {\r
366                                                                 if(p_SSL_set_session(*ppSSL, pSession) == 1)\r
367                                                                 {\r
368                                                                 }\r
369                                                         }\r
370                                                 }\r
371                                         }\r
372                                         // SSLのネゴシエーションには時間がかかる場合がある\r
373                                         r = TRUE;\r
374                                         while(r)\r
375                                         {\r
376                                                 Return = p_SSL_connect(*ppSSL);\r
377                                                 if(Return == 1)\r
378                                                         break;\r
379                                                 Error = p_SSL_get_error(*ppSSL, Return);\r
380                                                 if(Error == SSL_ERROR_WANT_READ || Error == SSL_ERROR_WANT_WRITE)\r
381                                                 {\r
382                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
383                                                         if(g_pOpenSSLTimeoutCallback(pbAborted) || (g_OpenSSLTimeout > 0 && timeGetTime() - Time >= g_OpenSSLTimeout))\r
384                                                                 r = FALSE;\r
385                                                         EnterCriticalSection(&g_OpenSSLLock);\r
386                                                 }\r
387                                                 else\r
388                                                         r = FALSE;\r
389                                         }\r
390                                         if(r)\r
391                                         {\r
392                                                 if(ConfirmSSLCertificate(*ppSSL, pbAborted))\r
393                                                 {\r
394                                                 }\r
395                                                 else\r
396                                                 {\r
397                                                         LeaveCriticalSection(&g_OpenSSLLock);\r
398                                                         DetachSSL(s);\r
399                                                         r = FALSE;\r
400                                                         EnterCriticalSection(&g_OpenSSLLock);\r
401                                                 }\r
402                                         }\r
403                                         else\r
404                                         {\r
405                                                 LeaveCriticalSection(&g_OpenSSLLock);\r
406                                                 DetachSSL(s);\r
407                                                 EnterCriticalSection(&g_OpenSSLLock);\r
408                                         }\r
409                                 }\r
410                                 else\r
411                                 {\r
412                                         LeaveCriticalSection(&g_OpenSSLLock);\r
413                                         DetachSSL(s);\r
414                                         EnterCriticalSection(&g_OpenSSLLock);\r
415                                 }\r
416                         }\r
417                 }\r
418         }\r
419         LeaveCriticalSection(&g_OpenSSLLock);\r
420         return r;\r
421 }\r
422 \r
423 BOOL DetachSSL(SOCKET s)\r
424 {\r
425         BOOL r;\r
426         SSL** ppSSL;\r
427         if(!g_bOpenSSLLoaded)\r
428                 return FALSE;\r
429         r = FALSE;\r
430         EnterCriticalSection(&g_OpenSSLLock);\r
431         if(ppSSL = FindSSLPointerFromSocket(s))\r
432         {\r
433                 p_SSL_shutdown(*ppSSL);\r
434                 p_SSL_free(*ppSSL);\r
435                 *ppSSL = NULL;\r
436                 r = TRUE;\r
437         }\r
438         LeaveCriticalSection(&g_OpenSSLLock);\r
439         return r;\r
440 }\r
441 \r
442 BOOL IsSSLAttached(SOCKET s)\r
443 {\r
444         SSL** ppSSL;\r
445         if(!g_bOpenSSLLoaded)\r
446                 return FALSE;\r
447         EnterCriticalSection(&g_OpenSSLLock);\r
448         ppSSL = FindSSLPointerFromSocket(s);\r
449         LeaveCriticalSection(&g_OpenSSLLock);\r
450         if(!ppSSL)\r
451                 return FALSE;\r
452         return TRUE;\r
453 }\r
454 \r
455 SOCKET socketS(int af, int type, int protocol)\r
456 {\r
457         return socket(af, type, protocol);\r
458 }\r
459 \r
460 int bindS(SOCKET s, const struct sockaddr *addr, int namelen)\r
461 {\r
462         return bind(s, addr, namelen);\r
463 }\r
464 \r
465 int listenS(SOCKET s, int backlog)\r
466 {\r
467         return listen(s, backlog);\r
468 }\r
469 \r
470 SOCKET acceptS(SOCKET s, struct sockaddr *addr, int *addrlen)\r
471 {\r
472         SOCKET r;\r
473         BOOL bAborted;\r
474         r = accept(s, addr, addrlen);\r
475         bAborted = FALSE;\r
476         if(!AttachSSL(r, INVALID_SOCKET, &bAborted))\r
477         {\r
478                 closesocket(r);\r
479                 return INVALID_SOCKET;\r
480         }\r
481         return r;\r
482 }\r
483 \r
484 int connectS(SOCKET s, const struct sockaddr *name, int namelen)\r
485 {\r
486         int r;\r
487         BOOL bAborted;\r
488         r = connect(s, name, namelen);\r
489         bAborted = FALSE;\r
490         if(!AttachSSL(r, INVALID_SOCKET, &bAborted))\r
491                 return SOCKET_ERROR;\r
492         return r;\r
493 }\r
494 \r
495 int closesocketS(SOCKET s)\r
496 {\r
497         DetachSSL(s);\r
498         return closesocket(s);\r
499 }\r
500 \r
501 int sendS(SOCKET s, const char * buf, int len, int flags)\r
502 {\r
503         SSL** ppSSL;\r
504         if(!g_bOpenSSLLoaded)\r
505                 return send(s, buf, len, flags);\r
506         EnterCriticalSection(&g_OpenSSLLock);\r
507         ppSSL = FindSSLPointerFromSocket(s);\r
508         LeaveCriticalSection(&g_OpenSSLLock);\r
509         if(!ppSSL)\r
510                 return send(s, buf, len, flags);\r
511         return p_SSL_write(*ppSSL, buf, len);\r
512 }\r
513 \r
514 int recvS(SOCKET s, char * buf, int len, int flags)\r
515 {\r
516         SSL** ppSSL;\r
517         if(!g_bOpenSSLLoaded)\r
518                 return recv(s, buf, len, flags);\r
519         EnterCriticalSection(&g_OpenSSLLock);\r
520         ppSSL = FindSSLPointerFromSocket(s);\r
521         LeaveCriticalSection(&g_OpenSSLLock);\r
522         if(!ppSSL)\r
523                 return recv(s, buf, len, flags);\r
524         if(flags & MSG_PEEK)\r
525                 return p_SSL_peek(*ppSSL, buf, len);\r
526         return p_SSL_read(*ppSSL, buf, len);\r
527 }\r
528 \r