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