Synchronize with trunk r58457.
[reactos.git] / dll / win32 / winhttp / net.c
1 /*
2 * Copyright 2008 Hans Leidekker for CodeWeavers
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17 */
18
19 #define WIN32_NO_STATUS
20 #define _INC_WINDOWS
21 #define COM_NO_WINDOWS_H
22
23 #include <config.h>
24 //#include "wine/port.h"
25
26 //#include <stdarg.h>
27 //#include <stdio.h>
28 //#include <errno.h>
29
30 //#include <sys/types.h>
31 #ifdef HAVE_SYS_SOCKET_H
32 # include <sys/socket.h>
33 #endif
34 #ifdef HAVE_SYS_IOCTL_H
35 # include <sys/ioctl.h>
36 #endif
37 #ifdef HAVE_SYS_FILIO_H
38 # include <sys/filio.h>
39 #endif
40 #ifdef HAVE_POLL_H
41 # include <poll.h>
42 #endif
43 #ifdef HAVE_OPENSSL_SSL_H
44 # include <openssl/ssl.h>
45 # include <openssl/opensslv.h>
46 #undef FAR
47 #undef DSA
48 #endif
49
50 #define NONAMELESSUNION
51
52 #include <wine/debug.h>
53 #include <wine/library.h>
54
55 //#include "windef.h"
56 //#include "winbase.h"
57 #include <winhttp.h>
58 //#include "wincrypt.h"
59
60 #include "winhttp_private.h"
61
62 /* to avoid conflicts with the Unix socket headers */
63 #define USE_WS_PREFIX
64 //#include "winsock2.h"
65
66 WINE_DEFAULT_DEBUG_CHANNEL(winhttp);
67
68 #ifndef HAVE_GETADDRINFO
69
70 /* critical section to protect non-reentrant gethostbyname() */
71 static CRITICAL_SECTION cs_gethostbyname;
72 static CRITICAL_SECTION_DEBUG critsect_debug =
73 {
74 0, 0, &cs_gethostbyname,
75 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList },
76 0, 0, { (DWORD_PTR)(__FILE__ ": cs_gethostbyname") }
77 };
78 static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 };
79
80 #endif
81
82 #ifdef SONAME_LIBSSL
83
84 #include <openssl/err.h>
85
86 static CRITICAL_SECTION init_ssl_cs;
87 static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
88 {
89 0, 0, &init_ssl_cs,
90 { &init_ssl_cs_debug.ProcessLocksList,
91 &init_ssl_cs_debug.ProcessLocksList },
92 0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
93 };
94 static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
95
96 static void *libssl_handle;
97 static void *libcrypto_handle;
98
99 #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10000000)
100 static const SSL_METHOD *method;
101 #else
102 static SSL_METHOD *method;
103 #endif
104 static SSL_CTX *ctx;
105 static int hostname_idx;
106 static int error_idx;
107 static int conn_idx;
108
109 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
110
111 MAKE_FUNCPTR( SSL_library_init );
112 MAKE_FUNCPTR( SSL_load_error_strings );
113 MAKE_FUNCPTR( SSLv23_method );
114 MAKE_FUNCPTR( SSL_CTX_free );
115 MAKE_FUNCPTR( SSL_CTX_new );
116 MAKE_FUNCPTR( SSL_new );
117 MAKE_FUNCPTR( SSL_free );
118 MAKE_FUNCPTR( SSL_set_fd );
119 MAKE_FUNCPTR( SSL_connect );
120 MAKE_FUNCPTR( SSL_shutdown );
121 MAKE_FUNCPTR( SSL_write );
122 MAKE_FUNCPTR( SSL_read );
123 MAKE_FUNCPTR( SSL_pending );
124 MAKE_FUNCPTR( SSL_get_error );
125 MAKE_FUNCPTR( SSL_get_ex_new_index );
126 MAKE_FUNCPTR( SSL_get_ex_data );
127 MAKE_FUNCPTR( SSL_set_ex_data );
128 MAKE_FUNCPTR( SSL_get_ex_data_X509_STORE_CTX_idx );
129 MAKE_FUNCPTR( SSL_get_peer_certificate );
130 MAKE_FUNCPTR( SSL_CTX_set_default_verify_paths );
131 MAKE_FUNCPTR( SSL_CTX_set_verify );
132 MAKE_FUNCPTR( SSL_get_current_cipher );
133 MAKE_FUNCPTR( SSL_CIPHER_get_bits );
134
135 MAKE_FUNCPTR( CRYPTO_num_locks );
136 MAKE_FUNCPTR( CRYPTO_set_id_callback );
137 MAKE_FUNCPTR( CRYPTO_set_locking_callback );
138 MAKE_FUNCPTR( ERR_free_strings );
139 MAKE_FUNCPTR( ERR_get_error );
140 MAKE_FUNCPTR( ERR_error_string );
141 MAKE_FUNCPTR( X509_STORE_CTX_get_ex_data );
142 MAKE_FUNCPTR( X509_STORE_CTX_get_chain );
143 MAKE_FUNCPTR( i2d_X509 );
144 MAKE_FUNCPTR( sk_value );
145 MAKE_FUNCPTR( sk_num );
146 #undef MAKE_FUNCPTR
147
148 static CRITICAL_SECTION *ssl_locks;
149 static unsigned int num_ssl_locks;
150
151 static unsigned long ssl_thread_id(void)
152 {
153 return GetCurrentThreadId();
154 }
155
156 static void ssl_lock_callback(int mode, int type, const char *file, int line)
157 {
158 if (mode & CRYPTO_LOCK)
159 EnterCriticalSection( &ssl_locks[type] );
160 else
161 LeaveCriticalSection( &ssl_locks[type] );
162 }
163
164 #endif
165
166 /* translate a unix error code into a winsock error code */
167 #ifndef __REACTOS__
168 static int sock_get_error( int err )
169 {
170 #if !defined(__MINGW32__) && !defined (_MSC_VER)
171 switch (err)
172 {
173 case EINTR: return WSAEINTR;
174 case EBADF: return WSAEBADF;
175 case EPERM:
176 case EACCES: return WSAEACCES;
177 case EFAULT: return WSAEFAULT;
178 case EINVAL: return WSAEINVAL;
179 case EMFILE: return WSAEMFILE;
180 case EWOULDBLOCK: return WSAEWOULDBLOCK;
181 case EINPROGRESS: return WSAEINPROGRESS;
182 case EALREADY: return WSAEALREADY;
183 case ENOTSOCK: return WSAENOTSOCK;
184 case EDESTADDRREQ: return WSAEDESTADDRREQ;
185 case EMSGSIZE: return WSAEMSGSIZE;
186 case EPROTOTYPE: return WSAEPROTOTYPE;
187 case ENOPROTOOPT: return WSAENOPROTOOPT;
188 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT;
189 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT;
190 case EOPNOTSUPP: return WSAEOPNOTSUPP;
191 case EPFNOSUPPORT: return WSAEPFNOSUPPORT;
192 case EAFNOSUPPORT: return WSAEAFNOSUPPORT;
193 case EADDRINUSE: return WSAEADDRINUSE;
194 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL;
195 case ENETDOWN: return WSAENETDOWN;
196 case ENETUNREACH: return WSAENETUNREACH;
197 case ENETRESET: return WSAENETRESET;
198 case ECONNABORTED: return WSAECONNABORTED;
199 case EPIPE:
200 case ECONNRESET: return WSAECONNRESET;
201 case ENOBUFS: return WSAENOBUFS;
202 case EISCONN: return WSAEISCONN;
203 case ENOTCONN: return WSAENOTCONN;
204 case ESHUTDOWN: return WSAESHUTDOWN;
205 case ETOOMANYREFS: return WSAETOOMANYREFS;
206 case ETIMEDOUT: return WSAETIMEDOUT;
207 case ECONNREFUSED: return WSAECONNREFUSED;
208 case ELOOP: return WSAELOOP;
209 case ENAMETOOLONG: return WSAENAMETOOLONG;
210 case EHOSTDOWN: return WSAEHOSTDOWN;
211 case EHOSTUNREACH: return WSAEHOSTUNREACH;
212 case ENOTEMPTY: return WSAENOTEMPTY;
213 #ifdef EPROCLIM
214 case EPROCLIM: return WSAEPROCLIM;
215 #endif
216 #ifdef EUSERS
217 case EUSERS: return WSAEUSERS;
218 #endif
219 #ifdef EDQUOT
220 case EDQUOT: return WSAEDQUOT;
221 #endif
222 #ifdef ESTALE
223 case ESTALE: return WSAESTALE;
224 #endif
225 #ifdef EREMOTE
226 case EREMOTE: return WSAEREMOTE;
227 #endif
228 default: errno = err; perror( "sock_set_error" ); return WSAEFAULT;
229 }
230 #endif
231 return err;
232 }
233 #else
234 #define sock_get_error(x) WSAGetLastError()
235
236 static inline int unix_ioctl(int filedes, long request, void *arg)
237 {
238 return ioctlsocket(filedes, request, arg);
239 }
240 #define ioctlsocket unix_ioctl
241 #endif
242
243 #ifdef SONAME_LIBSSL
244 static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
245 {
246 unsigned char *buffer, *p;
247 int len;
248 BOOL malloc = FALSE;
249 PCCERT_CONTEXT ret;
250
251 p = NULL;
252 if ((len = pi2d_X509( cert, &p )) < 0) return NULL;
253 /*
254 * SSL 0.9.7 and above malloc the buffer if it is null.
255 * however earlier version do not and so we would need to alloc the buffer.
256 *
257 * see the i2d_X509 man page for more details.
258 */
259 if (!p)
260 {
261 if (!(buffer = heap_alloc( len ))) return NULL;
262 p = buffer;
263 len = pi2d_X509( cert, &p );
264 }
265 else
266 {
267 buffer = p;
268 malloc = TRUE;
269 }
270
271 ret = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, len );
272
273 if (malloc) free( buffer );
274 else heap_free( buffer );
275
276 return ret;
277 }
278
279 static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, HCERTSTORE store,
280 WCHAR *server, DWORD security_flags )
281 {
282 BOOL ret;
283 CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
284 PCCERT_CHAIN_CONTEXT chain;
285 char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
286 char *server_auth[] = { oid_server_auth };
287 DWORD err = ERROR_SUCCESS;
288
289 TRACE("verifying %s\n", debugstr_w( server ));
290 chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
291 chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
292 if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara,
293 CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT,
294 NULL, &chain )))
295 {
296 if (chain->TrustStatus.dwErrorStatus)
297 {
298 static const DWORD supportedErrors =
299 CERT_TRUST_IS_NOT_TIME_VALID |
300 CERT_TRUST_IS_UNTRUSTED_ROOT |
301 CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
302
303 if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
304 {
305 if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID))
306 err = ERROR_WINHTTP_SECURE_CERT_DATE_INVALID;
307 }
308 else if (chain->TrustStatus.dwErrorStatus &
309 CERT_TRUST_IS_UNTRUSTED_ROOT)
310 {
311 if (!(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA))
312 err = ERROR_WINHTTP_SECURE_INVALID_CA;
313 }
314 else if ((chain->TrustStatus.dwErrorStatus &
315 CERT_TRUST_IS_OFFLINE_REVOCATION) ||
316 (chain->TrustStatus.dwErrorStatus &
317 CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
318 err = ERROR_WINHTTP_SECURE_CERT_REV_FAILED;
319 else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
320 err = ERROR_WINHTTP_SECURE_CERT_REVOKED;
321 else if (chain->TrustStatus.dwErrorStatus &
322 CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
323 {
324 if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE))
325 err = ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE;
326 }
327 else if (chain->TrustStatus.dwErrorStatus & ~supportedErrors)
328 err = ERROR_WINHTTP_SECURE_INVALID_CERT;
329 }
330 if (!err)
331 {
332 CERT_CHAIN_POLICY_PARA policyPara;
333 SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
334 CERT_CHAIN_POLICY_STATUS policyStatus;
335 CERT_CHAIN_CONTEXT chainCopy;
336
337 /* Clear chain->TrustStatus.dwErrorStatus so
338 * CertVerifyCertificateChainPolicy will verify additional checks
339 * rather than stopping with an existing, ignored error.
340 */
341 memcpy(&chainCopy, chain, sizeof(chainCopy));
342 chainCopy.TrustStatus.dwErrorStatus = 0;
343 sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
344 sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
345 sslExtraPolicyPara.pwszServerName = server;
346 sslExtraPolicyPara.fdwChecks = security_flags;
347 policyPara.cbSize = sizeof(policyPara);
348 policyPara.dwFlags = 0;
349 policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
350 ret = CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL,
351 &chainCopy, &policyPara,
352 &policyStatus );
353 /* Any error in the policy status indicates that the
354 * policy couldn't be verified.
355 */
356 if (ret && policyStatus.dwError)
357 {
358 if (policyStatus.dwError == CERT_E_CN_NO_MATCH)
359 err = ERROR_WINHTTP_SECURE_CERT_CN_INVALID;
360 else
361 err = ERROR_WINHTTP_SECURE_INVALID_CERT;
362 }
363 }
364 CertFreeCertificateChain( chain );
365 }
366 else
367 err = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
368 TRACE("returning %08x\n", err);
369 return err;
370 }
371
372 static int netconn_secure_verify( int preverify_ok, X509_STORE_CTX *ctx )
373 {
374 SSL *ssl;
375 WCHAR *server;
376 BOOL ret = FALSE;
377 netconn_t *conn;
378 HCERTSTORE store = CertOpenStore( CERT_STORE_PROV_MEMORY, 0, 0,
379 CERT_STORE_CREATE_NEW_FLAG, NULL );
380
381 ssl = pX509_STORE_CTX_get_ex_data( ctx, pSSL_get_ex_data_X509_STORE_CTX_idx() );
382 server = pSSL_get_ex_data( ssl, hostname_idx );
383 conn = pSSL_get_ex_data( ssl, conn_idx );
384 if (store)
385 {
386 X509 *cert;
387 int i;
388 PCCERT_CONTEXT endCert = NULL;
389 struct stack_st *chain = (struct stack_st *)pX509_STORE_CTX_get_chain( ctx );
390
391 ret = TRUE;
392 for (i = 0; ret && i < psk_num(chain); i++)
393 {
394 PCCERT_CONTEXT context;
395
396 cert = (X509 *)psk_value(chain, i);
397 if ((context = X509_to_cert_context( cert )))
398 {
399 if (i == 0)
400 ret = CertAddCertificateContextToStore( store, context,
401 CERT_STORE_ADD_ALWAYS, &endCert );
402 else
403 ret = CertAddCertificateContextToStore( store, context,
404 CERT_STORE_ADD_ALWAYS, NULL );
405 CertFreeCertificateContext( context );
406 }
407 }
408 if (!endCert) ret = FALSE;
409 if (ret)
410 {
411 DWORD_PTR err = netconn_verify_cert( endCert, store, server,
412 conn->security_flags );
413
414 if (err)
415 {
416 pSSL_set_ex_data( ssl, error_idx, (void *)err );
417 ret = FALSE;
418 }
419 }
420 CertFreeCertificateContext( endCert );
421 CertCloseStore( store, 0 );
422 }
423 return ret;
424 }
425 #endif
426
427 BOOL netconn_init( netconn_t *conn, BOOL secure )
428 {
429 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
430 int i;
431 #endif
432
433 conn->socket = -1;
434 if (!secure) return TRUE;
435
436 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
437 EnterCriticalSection( &init_ssl_cs );
438 if (libssl_handle)
439 {
440 LeaveCriticalSection( &init_ssl_cs );
441 return TRUE;
442 }
443 if (!(libssl_handle = wine_dlopen( SONAME_LIBSSL, RTLD_NOW, NULL, 0 )))
444 {
445 ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL);
446 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
447 LeaveCriticalSection( &init_ssl_cs );
448 return FALSE;
449 }
450 if (!(libcrypto_handle = wine_dlopen( SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0 )))
451 {
452 ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO);
453 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
454 LeaveCriticalSection( &init_ssl_cs );
455 return FALSE;
456 }
457 #define LOAD_FUNCPTR(x) \
458 if (!(p##x = wine_dlsym( libssl_handle, #x, NULL, 0 ))) \
459 { \
460 ERR("Failed to load symbol %s\n", #x); \
461 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
462 LeaveCriticalSection( &init_ssl_cs ); \
463 return FALSE; \
464 }
465 LOAD_FUNCPTR( SSL_library_init );
466 LOAD_FUNCPTR( SSL_load_error_strings );
467 LOAD_FUNCPTR( SSLv23_method );
468 LOAD_FUNCPTR( SSL_CTX_free );
469 LOAD_FUNCPTR( SSL_CTX_new );
470 LOAD_FUNCPTR( SSL_new );
471 LOAD_FUNCPTR( SSL_free );
472 LOAD_FUNCPTR( SSL_set_fd );
473 LOAD_FUNCPTR( SSL_connect );
474 LOAD_FUNCPTR( SSL_shutdown );
475 LOAD_FUNCPTR( SSL_write );
476 LOAD_FUNCPTR( SSL_read );
477 LOAD_FUNCPTR( SSL_pending );
478 LOAD_FUNCPTR( SSL_get_error );
479 LOAD_FUNCPTR( SSL_get_ex_new_index );
480 LOAD_FUNCPTR( SSL_get_ex_data );
481 LOAD_FUNCPTR( SSL_set_ex_data );
482 LOAD_FUNCPTR( SSL_get_ex_data_X509_STORE_CTX_idx );
483 LOAD_FUNCPTR( SSL_get_peer_certificate );
484 LOAD_FUNCPTR( SSL_CTX_set_default_verify_paths );
485 LOAD_FUNCPTR( SSL_CTX_set_verify );
486 LOAD_FUNCPTR( SSL_get_current_cipher );
487 LOAD_FUNCPTR( SSL_CIPHER_get_bits );
488 #undef LOAD_FUNCPTR
489
490 #define LOAD_FUNCPTR(x) \
491 if (!(p##x = wine_dlsym( libcrypto_handle, #x, NULL, 0 ))) \
492 { \
493 ERR("Failed to load symbol %s\n", #x); \
494 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \
495 LeaveCriticalSection( &init_ssl_cs ); \
496 return FALSE; \
497 }
498 LOAD_FUNCPTR( CRYPTO_num_locks );
499 LOAD_FUNCPTR( CRYPTO_set_id_callback );
500 LOAD_FUNCPTR( CRYPTO_set_locking_callback );
501 LOAD_FUNCPTR( ERR_free_strings );
502 LOAD_FUNCPTR( ERR_get_error );
503 LOAD_FUNCPTR( ERR_error_string );
504 LOAD_FUNCPTR( X509_STORE_CTX_get_ex_data );
505 LOAD_FUNCPTR( X509_STORE_CTX_get_chain );
506 LOAD_FUNCPTR( i2d_X509 );
507 LOAD_FUNCPTR( sk_value );
508 LOAD_FUNCPTR( sk_num );
509 #undef LOAD_FUNCPTR
510
511 pSSL_library_init();
512 pSSL_load_error_strings();
513
514 method = pSSLv23_method();
515 ctx = pSSL_CTX_new( method );
516 if (!pSSL_CTX_set_default_verify_paths( ctx ))
517 {
518 ERR("SSL_CTX_set_default_verify_paths failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
519 set_last_error( ERROR_OUTOFMEMORY );
520 LeaveCriticalSection( &init_ssl_cs );
521 return FALSE;
522 }
523 hostname_idx = pSSL_get_ex_new_index( 0, (void *)"hostname index", NULL, NULL, NULL );
524 if (hostname_idx == -1)
525 {
526 ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
527 set_last_error( ERROR_OUTOFMEMORY );
528 LeaveCriticalSection( &init_ssl_cs );
529 return FALSE;
530 }
531 error_idx = pSSL_get_ex_new_index( 0, (void *)"error index", NULL, NULL, NULL );
532 if (error_idx == -1)
533 {
534 ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
535 set_last_error( ERROR_OUTOFMEMORY );
536 LeaveCriticalSection( &init_ssl_cs );
537 return FALSE;
538 }
539 conn_idx = pSSL_get_ex_new_index( 0, (void *)"netconn index", NULL, NULL, NULL );
540 if (conn_idx == -1)
541 {
542 ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
543 set_last_error( ERROR_OUTOFMEMORY );
544 LeaveCriticalSection( &init_ssl_cs );
545 return FALSE;
546 }
547 pSSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, netconn_secure_verify );
548
549 pCRYPTO_set_id_callback(ssl_thread_id);
550 num_ssl_locks = pCRYPTO_num_locks();
551 ssl_locks = heap_alloc(num_ssl_locks * sizeof(CRITICAL_SECTION));
552 if (!ssl_locks)
553 {
554 set_last_error( ERROR_OUTOFMEMORY );
555 LeaveCriticalSection( &init_ssl_cs );
556 return FALSE;
557 }
558 for (i = 0; i < num_ssl_locks; i++)
559 {
560 InitializeCriticalSection( &ssl_locks[i] );
561 ssl_locks[i].DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ssl_locks");
562 }
563 pCRYPTO_set_locking_callback(ssl_lock_callback);
564
565 LeaveCriticalSection( &init_ssl_cs );
566 #else
567 WARN("SSL support not compiled in.\n");
568 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
569 return FALSE;
570 #endif
571 return TRUE;
572 }
573
574 void netconn_unload( void )
575 {
576 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
577 if (libcrypto_handle)
578 {
579 pERR_free_strings();
580 wine_dlclose( libcrypto_handle, NULL, 0 );
581 }
582 if (libssl_handle)
583 {
584 if (ctx)
585 pSSL_CTX_free( ctx );
586 wine_dlclose( libssl_handle, NULL, 0 );
587 }
588 if (ssl_locks)
589 {
590 int i;
591 for (i = 0; i < num_ssl_locks; i++)
592 {
593 ssl_locks[i].DebugInfo->Spare[0] = 0;
594 DeleteCriticalSection( &ssl_locks[i] );
595 }
596 heap_free( ssl_locks );
597 }
598 DeleteCriticalSection(&init_ssl_cs);
599 #endif
600 #ifndef HAVE_GETADDRINFO
601 DeleteCriticalSection(&cs_gethostbyname);
602 #endif
603 }
604
605 BOOL netconn_connected( netconn_t *conn )
606 {
607 return (conn->socket != -1);
608 }
609
610 BOOL netconn_create( netconn_t *conn, int domain, int type, int protocol )
611 {
612 if ((conn->socket = socket( domain, type, protocol )) == -1)
613 {
614 WARN("unable to create socket (%s)\n", strerror(errno));
615 set_last_error( sock_get_error( errno ) );
616 return FALSE;
617 }
618 return TRUE;
619 }
620
621 BOOL netconn_close( netconn_t *conn )
622 {
623 int res;
624
625 #ifdef SONAME_LIBSSL
626 if (conn->secure)
627 {
628 heap_free( conn->peek_msg_mem );
629 conn->peek_msg_mem = NULL;
630 conn->peek_msg = NULL;
631 conn->peek_len = 0;
632
633 pSSL_shutdown( conn->ssl_conn );
634 pSSL_free( conn->ssl_conn );
635
636 conn->ssl_conn = NULL;
637 conn->secure = FALSE;
638 }
639 #endif
640 res = closesocket( conn->socket );
641 conn->socket = -1;
642 if (res == -1)
643 {
644 set_last_error( sock_get_error( errno ) );
645 return FALSE;
646 }
647 return TRUE;
648 }
649
650 BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len, int timeout )
651 {
652 BOOL ret = FALSE;
653 int res = 0, state;
654
655 if (timeout > 0)
656 {
657 state = 1;
658 ioctlsocket( conn->socket, FIONBIO, &state );
659 }
660 if (connect( conn->socket, sockaddr, addr_len ) < 0)
661 {
662 res = sock_get_error( errno );
663 if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS)
664 {
665 // ReactOS: use select instead of poll
666 fd_set outfd;
667 struct timeval tv;
668
669 FD_ZERO(&outfd);
670 FD_SET(conn->socket, &outfd);
671
672 tv.tv_sec = 0;
673 tv.tv_usec = timeout * 1000;
674
675 if (select( 0, NULL, &outfd, NULL, &tv ) > 0)
676 ret = TRUE;
677 else
678 res = sock_get_error( errno );
679 }
680 }
681 else
682 ret = TRUE;
683 if (timeout > 0)
684 {
685 state = 0;
686 ioctlsocket( conn->socket, FIONBIO, &state );
687 }
688 if (!ret)
689 {
690 WARN("unable to connect to host (%d)\n", res);
691 set_last_error( res );
692 }
693 return ret;
694 }
695
696 BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname )
697 {
698 #ifdef SONAME_LIBSSL
699 if (!(conn->ssl_conn = pSSL_new( ctx )))
700 {
701 ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
702 set_last_error( ERROR_OUTOFMEMORY );
703 goto fail;
704 }
705 if (!pSSL_set_ex_data( conn->ssl_conn, hostname_idx, hostname ))
706 {
707 ERR("SSL_set_ex_data failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
708 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
709 goto fail;
710 }
711 if (!pSSL_set_ex_data( conn->ssl_conn, conn_idx, conn ))
712 {
713 ERR("SSL_set_ex_data failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
714 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
715 return FALSE;
716 }
717 if (!pSSL_set_fd( conn->ssl_conn, conn->socket ))
718 {
719 ERR("SSL_set_fd failed: %s\n", pERR_error_string( pERR_get_error(), 0 ));
720 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR );
721 goto fail;
722 }
723 if (pSSL_connect( conn->ssl_conn ) <= 0)
724 {
725 DWORD err;
726
727 err = (DWORD_PTR)pSSL_get_ex_data( conn->ssl_conn, error_idx );
728 if (!err) err = ERROR_WINHTTP_SECURE_CHANNEL_ERROR;
729 ERR("couldn't verify server certificate (%d)\n", err);
730 set_last_error( err );
731 goto fail;
732 }
733 TRACE("established SSL connection\n");
734 conn->secure = TRUE;
735 return TRUE;
736
737 fail:
738 if (conn->ssl_conn)
739 {
740 pSSL_shutdown( conn->ssl_conn );
741 pSSL_free( conn->ssl_conn );
742 conn->ssl_conn = NULL;
743 }
744 #endif
745 return FALSE;
746 }
747
748 BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int flags, int *sent )
749 {
750 if (!netconn_connected( conn )) return FALSE;
751 if (conn->secure)
752 {
753 #ifdef SONAME_LIBSSL
754 if (flags) FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
755 *sent = pSSL_write( conn->ssl_conn, msg, len );
756 if (*sent < 1 && len) return FALSE;
757 return TRUE;
758 #else
759 return FALSE;
760 #endif
761 }
762 if ((*sent = send( conn->socket, msg, len, flags )) == -1)
763 {
764 set_last_error( sock_get_error( errno ) );
765 return FALSE;
766 }
767 return TRUE;
768 }
769
770 BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd )
771 {
772 *recvd = 0;
773 if (!netconn_connected( conn )) return FALSE;
774 if (!len) return TRUE;
775
776 if (conn->secure)
777 {
778 #ifdef SONAME_LIBSSL
779 int ret;
780
781 if (flags & ~(MSG_PEEK | MSG_WAITALL))
782 FIXME("SSL_read does not support the following flags: %08x\n", flags);
783
784 /* this ugly hack is all for MSG_PEEK */
785 if (flags & MSG_PEEK && !conn->peek_msg)
786 {
787 if (!(conn->peek_msg = conn->peek_msg_mem = heap_alloc( len + 1 ))) return FALSE;
788 }
789 else if (flags & MSG_PEEK && conn->peek_msg)
790 {
791 if (len < conn->peek_len) FIXME("buffer isn't big enough, should we wrap?\n");
792 *recvd = min( len, conn->peek_len );
793 memcpy( buf, conn->peek_msg, *recvd );
794 return TRUE;
795 }
796 else if (conn->peek_msg)
797 {
798 *recvd = min( len, conn->peek_len );
799 memcpy( buf, conn->peek_msg, *recvd );
800 conn->peek_len -= *recvd;
801 conn->peek_msg += *recvd;
802
803 if (conn->peek_len == 0)
804 {
805 heap_free( conn->peek_msg_mem );
806 conn->peek_msg_mem = NULL;
807 conn->peek_msg = NULL;
808 }
809 /* check if we have enough data from the peek buffer */
810 if (!(flags & MSG_WAITALL) || (*recvd == len)) return TRUE;
811 }
812 ret = pSSL_read( conn->ssl_conn, (char *)buf + *recvd, len - *recvd );
813 if (ret < 0)
814 return FALSE;
815
816 /* check if EOF was received */
817 if (!ret && (pSSL_get_error( conn->ssl_conn, ret ) == SSL_ERROR_ZERO_RETURN ||
818 pSSL_get_error( conn->ssl_conn, ret ) == SSL_ERROR_SYSCALL ))
819 {
820 netconn_close( conn );
821 return TRUE;
822 }
823 if (flags & MSG_PEEK) /* must copy into buffer */
824 {
825 conn->peek_len = ret;
826 if (!ret)
827 {
828 heap_free( conn->peek_msg_mem );
829 conn->peek_msg_mem = NULL;
830 conn->peek_msg = NULL;
831 }
832 else memcpy( conn->peek_msg, buf, ret );
833 }
834 *recvd += ret;
835 return TRUE;
836 #else
837 return FALSE;
838 #endif
839 }
840 if ((*recvd = recv( conn->socket, buf, len, flags )) == -1)
841 {
842 set_last_error( sock_get_error( errno ) );
843 return FALSE;
844 }
845 return TRUE;
846 }
847
848 BOOL netconn_query_data_available( netconn_t *conn, DWORD *available )
849 {
850 #ifdef FIONREAD
851 int ret, unread;
852 #endif
853 *available = 0;
854 if (!netconn_connected( conn )) return FALSE;
855
856 if (conn->secure)
857 {
858 #ifdef SONAME_LIBSSL
859 *available = pSSL_pending( conn->ssl_conn ) + conn->peek_len;
860 #endif
861 return TRUE;
862 }
863 #ifdef FIONREAD
864 if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread ))) *available = unread;
865 #endif
866 return TRUE;
867 }
868
869 BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen )
870 {
871 // ReactOS: use select instead of poll
872 fd_set infd;
873 BOOL ret = FALSE;
874 DWORD recvd = 0;
875
876 if (!netconn_connected( conn )) return FALSE;
877
878 if (conn->secure)
879 {
880 #ifdef SONAME_LIBSSL
881 while (recvd < *buflen)
882 {
883 int dummy;
884 if (!netconn_recv( conn, &buffer[recvd], 1, 0, &dummy ))
885 {
886 set_last_error( ERROR_CONNECTION_ABORTED );
887 break;
888 }
889 if (buffer[recvd] == '\n')
890 {
891 ret = TRUE;
892 break;
893 }
894 if (buffer[recvd] != '\r') recvd++;
895 }
896 if (ret)
897 {
898 buffer[recvd++] = 0;
899 *buflen = recvd;
900 TRACE("received line %s\n", debugstr_a(buffer));
901 }
902 return ret;
903 #else
904 return FALSE;
905 #endif
906 }
907
908 FD_ZERO(&infd);
909 FD_SET(conn->socket, &infd);
910
911 while (recvd < *buflen)
912 {
913 int res;
914 struct timeval tv, *ptv;
915 socklen_t len = sizeof(tv);
916
917 if ((res = getsockopt( conn->socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, &len ) != -1))
918 ptv = &tv;
919 else
920 ptv = NULL;
921
922 if (select( 0, &infd, NULL, NULL, ptv ) > 0)
923 {
924 if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0)
925 {
926 if (res == -1) set_last_error( sock_get_error( errno ) );
927 break;
928 }
929 if (buffer[recvd] == '\n')
930 {
931 ret = TRUE;
932 break;
933 }
934 if (buffer[recvd] != '\r') recvd++;
935 }
936 else
937 {
938 set_last_error( ERROR_WINHTTP_TIMEOUT );
939 break;
940 }
941 }
942 if (ret)
943 {
944 buffer[recvd++] = 0;
945 *buflen = recvd;
946 TRACE("received line %s\n", debugstr_a(buffer));
947 }
948 return ret;
949 }
950
951 DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value )
952 {
953 int res;
954 struct timeval tv;
955
956 /* value is in milliseconds, convert to struct timeval */
957 tv.tv_sec = value / 1000;
958 tv.tv_usec = (value % 1000) * 1000;
959
960 if ((res = setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv) ) == -1))
961 {
962 WARN("setsockopt failed (%s)\n", strerror( errno ));
963 return sock_get_error( errno );
964 }
965 return ERROR_SUCCESS;
966 }
967
968 static DWORD resolve_hostname( WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len )
969 {
970 char *hostname;
971 #ifdef HAVE_GETADDRINFO
972 struct addrinfo *res, hints;
973 int ret;
974 #else
975 struct hostent *he;
976 struct sockaddr_in *sin = (struct sockaddr_in *)sa;
977 #endif
978
979 if (!(hostname = strdupWA( hostnameW ))) return ERROR_OUTOFMEMORY;
980
981 #ifdef HAVE_GETADDRINFO
982 memset( &hints, 0, sizeof(struct addrinfo) );
983 /* Prefer IPv4 to IPv6 addresses, since some web servers do not listen on
984 * their IPv6 addresses even though they have IPv6 addresses in the DNS.
985 */
986 hints.ai_family = AF_INET;
987
988 ret = getaddrinfo( hostname, NULL, &hints, &res );
989 if (ret != 0)
990 {
991 TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(hostnameW), gai_strerror(ret));
992 hints.ai_family = AF_INET6;
993 ret = getaddrinfo( hostname, NULL, &hints, &res );
994 if (ret != 0)
995 {
996 TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret));
997 heap_free( hostname );
998 return ERROR_WINHTTP_NAME_NOT_RESOLVED;
999 }
1000 }
1001 heap_free( hostname );
1002 if (*sa_len < res->ai_addrlen)
1003 {
1004 WARN("address too small\n");
1005 freeaddrinfo( res );
1006 return ERROR_WINHTTP_NAME_NOT_RESOLVED;
1007 }
1008 *sa_len = res->ai_addrlen;
1009 memcpy( sa, res->ai_addr, res->ai_addrlen );
1010 /* Copy port */
1011 switch (res->ai_family)
1012 {
1013 case AF_INET:
1014 ((struct sockaddr_in *)sa)->sin_port = htons( port );
1015 break;
1016 case AF_INET6:
1017 ((struct sockaddr_in6 *)sa)->sin6_port = htons( port );
1018 break;
1019 }
1020
1021 freeaddrinfo( res );
1022 return ERROR_SUCCESS;
1023 #else
1024 EnterCriticalSection( &cs_gethostbyname );
1025
1026 he = gethostbyname( hostname );
1027 heap_free( hostname );
1028 if (!he)
1029 {
1030 TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno);
1031 LeaveCriticalSection( &cs_gethostbyname );
1032 return ERROR_WINHTTP_NAME_NOT_RESOLVED;
1033 }
1034 if (*sa_len < sizeof(struct sockaddr_in))
1035 {
1036 WARN("address too small\n");
1037 LeaveCriticalSection( &cs_gethostbyname );
1038 return ERROR_WINHTTP_NAME_NOT_RESOLVED;
1039 }
1040 *sa_len = sizeof(struct sockaddr_in);
1041 memset( sa, 0, sizeof(struct sockaddr_in) );
1042 memcpy( &sin->sin_addr, he->h_addr, he->h_length );
1043 sin->sin_family = he->h_addrtype;
1044 sin->sin_port = htons( port );
1045
1046 LeaveCriticalSection( &cs_gethostbyname );
1047 return ERROR_SUCCESS;
1048 #endif
1049 }
1050
1051 struct resolve_args
1052 {
1053 WCHAR *hostname;
1054 INTERNET_PORT port;
1055 struct sockaddr *sa;
1056 socklen_t *sa_len;
1057 };
1058
1059 static DWORD CALLBACK resolve_proc( LPVOID arg )
1060 {
1061 struct resolve_args *ra = arg;
1062 return resolve_hostname( ra->hostname, ra->port, ra->sa, ra->sa_len );
1063 }
1064
1065 BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len, int timeout )
1066 {
1067 DWORD ret;
1068
1069 if (timeout)
1070 {
1071 DWORD status;
1072 HANDLE thread;
1073 struct resolve_args ra;
1074
1075 ra.hostname = hostname;
1076 ra.port = port;
1077 ra.sa = sa;
1078 ra.sa_len = sa_len;
1079
1080 thread = CreateThread( NULL, 0, resolve_proc, &ra, 0, NULL );
1081 if (!thread) return FALSE;
1082
1083 status = WaitForSingleObject( thread, timeout );
1084 if (status == WAIT_OBJECT_0) GetExitCodeThread( thread, &ret );
1085 else ret = ERROR_WINHTTP_TIMEOUT;
1086 CloseHandle( thread );
1087 }
1088 else ret = resolve_hostname( hostname, port, sa, sa_len );
1089
1090 if (ret)
1091 {
1092 set_last_error( ret );
1093 return FALSE;
1094 }
1095 return TRUE;
1096 }
1097
1098 const void *netconn_get_certificate( netconn_t *conn )
1099 {
1100 #ifdef SONAME_LIBSSL
1101 X509 *cert;
1102 const CERT_CONTEXT *ret;
1103
1104 if (!conn->secure) return NULL;
1105
1106 if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL;
1107 ret = X509_to_cert_context( cert );
1108 return ret;
1109 #else
1110 return NULL;
1111 #endif
1112 }
1113
1114 int netconn_get_cipher_strength( netconn_t *conn )
1115 {
1116 #ifdef SONAME_LIBSSL
1117 #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090707f)
1118 const SSL_CIPHER *cipher;
1119 #else
1120 SSL_CIPHER *cipher;
1121 #endif
1122 int bits = 0;
1123
1124 if (!conn->secure) return 0;
1125 if (!(cipher = pSSL_get_current_cipher( conn->ssl_conn ))) return 0;
1126 pSSL_CIPHER_get_bits( cipher, &bits );
1127 return bits;
1128 #else
1129 return 0;
1130 #endif
1131 }