mmdevapi: Add AudioSimpleVolume stub.
[wine] / dlls / wininet / netconnection.c
1 /*
2  * Wininet - networking layer. Uses unix sockets or OpenSSL.
3  *
4  * Copyright 2002 TransGaming Technologies Inc.
5  *
6  * David Hammerton
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, write to the Free Software
20  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
21  */
22
23 #include "config.h"
24 #include "wine/port.h"
25
26 #define NONAMELESSUNION
27
28 #if defined(__MINGW32__) || defined (_MSC_VER)
29 #include <ws2tcpip.h>
30 #endif
31
32 #include <sys/types.h>
33 #ifdef HAVE_POLL_H
34 #include <poll.h>
35 #endif
36 #ifdef HAVE_SYS_POLL_H
37 # include <sys/poll.h>
38 #endif
39 #ifdef HAVE_SYS_TIME_H
40 # include <sys/time.h>
41 #endif
42 #ifdef HAVE_SYS_SOCKET_H
43 # include <sys/socket.h>
44 #endif
45 #ifdef HAVE_SYS_FILIO_H
46 # include <sys/filio.h>
47 #endif
48 #ifdef HAVE_UNISTD_H
49 # include <unistd.h>
50 #endif
51 #ifdef HAVE_SYS_IOCTL_H
52 # include <sys/ioctl.h>
53 #endif
54 #include <time.h>
55 #ifdef HAVE_NETDB_H
56 # include <netdb.h>
57 #endif
58 #ifdef HAVE_NETINET_IN_H
59 # include <netinet/in.h>
60 #endif
61 #ifdef HAVE_OPENSSL_SSL_H
62 # include <openssl/ssl.h>
63 #undef FAR
64 #undef DSA
65 #endif
66
67 #include <stdarg.h>
68 #include <stdlib.h>
69 #include <string.h>
70 #include <stdio.h>
71 #include <errno.h>
72
73 #include "wine/library.h"
74 #include "windef.h"
75 #include "winbase.h"
76 #include "wininet.h"
77 #include "winerror.h"
78 #include "wincrypt.h"
79
80 #include "wine/debug.h"
81 #include "internet.h"
82
83 /* To avoid conflicts with the Unix socket headers. we only need it for
84  * the error codes anyway. */
85 #define USE_WS_PREFIX
86 #include "winsock2.h"
87
88 #define RESPONSE_TIMEOUT        30            /* FROM internet.c */
89
90
91 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
92
93 /* FIXME!!!!!!
94  *    This should use winsock - To use winsock the functions will have to change a bit
95  *        as they are designed for unix sockets.
96  *    SSL stuff should use crypt32.dll
97  */
98
99 #ifdef SONAME_LIBSSL
100
101 #include <openssl/err.h>
102
103 static CRITICAL_SECTION init_ssl_cs;
104 static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
105 {
106     0, 0, &init_ssl_cs,
107     { &init_ssl_cs_debug.ProcessLocksList,
108       &init_ssl_cs_debug.ProcessLocksList },
109     0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
110 };
111 static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
112
113 static void *OpenSSL_ssl_handle;
114 static void *OpenSSL_crypto_handle;
115
116 static SSL_METHOD *meth;
117 static SSL_CTX *ctx;
118 static int hostname_idx;
119 static int error_idx;
120
121 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
122
123 /* OpenSSL functions that we use */
124 MAKE_FUNCPTR(SSL_library_init);
125 MAKE_FUNCPTR(SSL_load_error_strings);
126 MAKE_FUNCPTR(SSLv23_method);
127 MAKE_FUNCPTR(SSL_CTX_free);
128 MAKE_FUNCPTR(SSL_CTX_new);
129 MAKE_FUNCPTR(SSL_new);
130 MAKE_FUNCPTR(SSL_free);
131 MAKE_FUNCPTR(SSL_set_fd);
132 MAKE_FUNCPTR(SSL_connect);
133 MAKE_FUNCPTR(SSL_shutdown);
134 MAKE_FUNCPTR(SSL_write);
135 MAKE_FUNCPTR(SSL_read);
136 MAKE_FUNCPTR(SSL_pending);
137 MAKE_FUNCPTR(SSL_get_ex_new_index);
138 MAKE_FUNCPTR(SSL_get_ex_data);
139 MAKE_FUNCPTR(SSL_set_ex_data);
140 MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx);
141 MAKE_FUNCPTR(SSL_get_verify_result);
142 MAKE_FUNCPTR(SSL_get_peer_certificate);
143 MAKE_FUNCPTR(SSL_CTX_get_timeout);
144 MAKE_FUNCPTR(SSL_CTX_set_timeout);
145 MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths);
146 MAKE_FUNCPTR(SSL_CTX_set_verify);
147 MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data);
148
149 /* OpenSSL's libcrypto functions that we use */
150 MAKE_FUNCPTR(BIO_new_fp);
151 MAKE_FUNCPTR(CRYPTO_num_locks);
152 MAKE_FUNCPTR(CRYPTO_set_id_callback);
153 MAKE_FUNCPTR(CRYPTO_set_locking_callback);
154 MAKE_FUNCPTR(ERR_free_strings);
155 MAKE_FUNCPTR(ERR_get_error);
156 MAKE_FUNCPTR(ERR_error_string);
157 MAKE_FUNCPTR(i2d_X509);
158 MAKE_FUNCPTR(sk_num);
159 MAKE_FUNCPTR(sk_value);
160 #undef MAKE_FUNCPTR
161
162 static CRITICAL_SECTION *ssl_locks;
163 static unsigned int num_ssl_locks;
164
165 static unsigned long ssl_thread_id(void)
166 {
167     return GetCurrentThreadId();
168 }
169
170 static void ssl_lock_callback(int mode, int type, const char *file, int line)
171 {
172     if (mode & CRYPTO_LOCK)
173         EnterCriticalSection(&ssl_locks[type]);
174     else
175         LeaveCriticalSection(&ssl_locks[type]);
176 }
177
178 static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
179 {
180     unsigned char* buffer,*p;
181     INT len;
182     BOOL malloced = FALSE;
183     PCCERT_CONTEXT ret;
184
185     p = NULL;
186     len = pi2d_X509(cert,&p);
187     /*
188      * SSL 0.9.7 and above malloc the buffer if it is null.
189      * however earlier version do not and so we would need to alloc the buffer.
190      *
191      * see the i2d_X509 man page for more details.
192      */
193     if (!p)
194     {
195         buffer = HeapAlloc(GetProcessHeap(),0,len);
196         p = buffer;
197         len = pi2d_X509(cert,&p);
198     }
199     else
200     {
201         buffer = p;
202         malloced = TRUE;
203     }
204
205     ret = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
206
207     if (malloced)
208         free(buffer);
209     else
210         HeapFree(GetProcessHeap(),0,buffer);
211
212     return ret;
213 }
214
215 static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store,
216     WCHAR *server)
217 {
218     BOOL ret;
219     CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
220     PCCERT_CHAIN_CONTEXT chain;
221     char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
222     char *server_auth[] = { oid_server_auth };
223     DWORD err = ERROR_SUCCESS;
224
225     TRACE("verifying %s\n", debugstr_w(server));
226     chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
227     chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
228     if ((ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 0,
229         NULL, &chain)))
230     {
231         if (chain->TrustStatus.dwErrorStatus)
232         {
233             if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
234                 err = ERROR_INTERNET_SEC_CERT_DATE_INVALID;
235             else if (chain->TrustStatus.dwErrorStatus &
236                      CERT_TRUST_IS_UNTRUSTED_ROOT)
237                 err = ERROR_INTERNET_INVALID_CA;
238             else if ((chain->TrustStatus.dwErrorStatus &
239                       CERT_TRUST_IS_OFFLINE_REVOCATION) ||
240                      (chain->TrustStatus.dwErrorStatus &
241                       CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
242                 err = ERROR_INTERNET_SEC_CERT_NO_REV;
243             else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
244                 err = ERROR_INTERNET_SEC_CERT_REVOKED;
245             else if (chain->TrustStatus.dwErrorStatus &
246                 CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
247                 err = ERROR_INTERNET_SEC_INVALID_CERT;
248             else
249                 err = ERROR_INTERNET_SEC_INVALID_CERT;
250         }
251         else
252         {
253             CERT_CHAIN_POLICY_PARA policyPara;
254             SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
255             CERT_CHAIN_POLICY_STATUS policyStatus;
256
257             sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
258             sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
259             sslExtraPolicyPara.pwszServerName = server;
260             policyPara.cbSize = sizeof(policyPara);
261             policyPara.dwFlags = 0;
262             policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
263             ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
264                 chain, &policyPara, &policyStatus);
265             /* Any error in the policy status indicates that the
266              * policy couldn't be verified.
267              */
268             if (ret && policyStatus.dwError)
269             {
270                 if (policyStatus.dwError == CERT_E_CN_NO_MATCH)
271                     err = ERROR_INTERNET_SEC_CERT_CN_INVALID;
272                 else
273                     err = ERROR_INTERNET_SEC_INVALID_CERT;
274             }
275         }
276         CertFreeCertificateChain(chain);
277     }
278     TRACE("returning %08x\n", err);
279     return err;
280 }
281
282 static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
283 {
284     SSL *ssl;
285     WCHAR *server;
286     BOOL ret = FALSE;
287
288     ssl = pX509_STORE_CTX_get_ex_data(ctx,
289         pSSL_get_ex_data_X509_STORE_CTX_idx());
290     server = pSSL_get_ex_data(ssl, hostname_idx);
291     if (preverify_ok)
292     {
293         HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
294             CERT_STORE_CREATE_NEW_FLAG, NULL);
295
296         if (store)
297         {
298             X509 *cert;
299             int i;
300             PCCERT_CONTEXT endCert = NULL;
301
302             ret = TRUE;
303             for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++)
304             {
305                 PCCERT_CONTEXT context;
306
307                 cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i);
308                 if ((context = X509_to_cert_context(cert)))
309                 {
310                     if (i == 0)
311                         ret = CertAddCertificateContextToStore(store, context,
312                             CERT_STORE_ADD_ALWAYS, &endCert);
313                     else
314                         ret = CertAddCertificateContextToStore(store, context,
315                             CERT_STORE_ADD_ALWAYS, NULL);
316                     CertFreeCertificateContext(context);
317                 }
318             }
319             if (!endCert) ret = FALSE;
320             if (ret)
321             {
322                 DWORD_PTR err = netconn_verify_cert(endCert, store, server);
323
324                 if (err)
325                 {
326                     pSSL_set_ex_data(ssl, error_idx, (void *)err);
327                     ret = FALSE;
328                 }
329             }
330             CertFreeCertificateContext(endCert);
331             CertCloseStore(store, 0);
332         }
333     }
334     return ret;
335 }
336
337 #endif
338
339 DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
340 {
341     connection->useSSL = FALSE;
342     connection->socketFD = -1;
343     if (useSSL)
344     {
345 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
346         int i;
347
348         TRACE("using SSL connection\n");
349         EnterCriticalSection(&init_ssl_cs);
350         if (OpenSSL_ssl_handle) /* already initialized everything */
351         {
352             LeaveCriticalSection(&init_ssl_cs);
353             return ERROR_SUCCESS;
354         }
355         OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
356         if (!OpenSSL_ssl_handle)
357         {
358             ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
359                 SONAME_LIBSSL);
360             LeaveCriticalSection(&init_ssl_cs);
361             return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
362         }
363         OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
364         if (!OpenSSL_crypto_handle)
365         {
366             ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
367                 SONAME_LIBCRYPTO);
368             LeaveCriticalSection(&init_ssl_cs);
369             return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
370         }
371
372         /* mmm nice ugly macroness */
373 #define DYNSSL(x) \
374     p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \
375     if (!p##x) \
376     { \
377         ERR("failed to load symbol %s\n", #x); \
378         LeaveCriticalSection(&init_ssl_cs); \
379         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
380     }
381
382         DYNSSL(SSL_library_init);
383         DYNSSL(SSL_load_error_strings);
384         DYNSSL(SSLv23_method);
385         DYNSSL(SSL_CTX_free);
386         DYNSSL(SSL_CTX_new);
387         DYNSSL(SSL_new);
388         DYNSSL(SSL_free);
389         DYNSSL(SSL_set_fd);
390         DYNSSL(SSL_connect);
391         DYNSSL(SSL_shutdown);
392         DYNSSL(SSL_write);
393         DYNSSL(SSL_read);
394         DYNSSL(SSL_pending);
395         DYNSSL(SSL_get_ex_new_index);
396         DYNSSL(SSL_get_ex_data);
397         DYNSSL(SSL_set_ex_data);
398         DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx);
399         DYNSSL(SSL_get_verify_result);
400         DYNSSL(SSL_get_peer_certificate);
401         DYNSSL(SSL_CTX_get_timeout);
402         DYNSSL(SSL_CTX_set_timeout);
403         DYNSSL(SSL_CTX_set_default_verify_paths);
404         DYNSSL(SSL_CTX_set_verify);
405         DYNSSL(X509_STORE_CTX_get_ex_data);
406 #undef DYNSSL
407
408 #define DYNCRYPTO(x) \
409     p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \
410     if (!p##x) \
411     { \
412         ERR("failed to load symbol %s\n", #x); \
413         LeaveCriticalSection(&init_ssl_cs); \
414         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
415     }
416         DYNCRYPTO(BIO_new_fp);
417         DYNCRYPTO(CRYPTO_num_locks);
418         DYNCRYPTO(CRYPTO_set_id_callback);
419         DYNCRYPTO(CRYPTO_set_locking_callback);
420         DYNCRYPTO(ERR_free_strings);
421         DYNCRYPTO(ERR_get_error);
422         DYNCRYPTO(ERR_error_string);
423         DYNCRYPTO(i2d_X509);
424         DYNCRYPTO(sk_num);
425         DYNCRYPTO(sk_value);
426 #undef DYNCRYPTO
427
428         pSSL_library_init();
429         pSSL_load_error_strings();
430         pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
431
432         meth = pSSLv23_method();
433         ctx = pSSL_CTX_new(meth);
434         if (!pSSL_CTX_set_default_verify_paths(ctx))
435         {
436             ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
437                 pERR_error_string(pERR_get_error(), 0));
438             LeaveCriticalSection(&init_ssl_cs);
439             return ERROR_OUTOFMEMORY;
440         }
441         hostname_idx = pSSL_get_ex_new_index(0, (void *)"hostname index",
442                 NULL, NULL, NULL);
443         if (hostname_idx == -1)
444         {
445             ERR("SSL_get_ex_new_index failed; %s\n",
446                 pERR_error_string(pERR_get_error(), 0));
447             LeaveCriticalSection(&init_ssl_cs);
448             return ERROR_OUTOFMEMORY;
449         }
450         error_idx = pSSL_get_ex_new_index(0, (void *)"error index",
451                 NULL, NULL, NULL);
452         if (error_idx == -1)
453         {
454             ERR("SSL_get_ex_new_index failed; %s\n",
455                 pERR_error_string(pERR_get_error(), 0));
456             LeaveCriticalSection(&init_ssl_cs);
457             return ERROR_OUTOFMEMORY;
458         }
459         pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify);
460
461         pCRYPTO_set_id_callback(ssl_thread_id);
462         num_ssl_locks = pCRYPTO_num_locks();
463         ssl_locks = HeapAlloc(GetProcessHeap(), 0, num_ssl_locks * sizeof(CRITICAL_SECTION));
464         if (!ssl_locks)
465         {
466             LeaveCriticalSection(&init_ssl_cs);
467             return ERROR_OUTOFMEMORY;
468         }
469         for (i = 0; i < num_ssl_locks; i++)
470             InitializeCriticalSection(&ssl_locks[i]);
471         pCRYPTO_set_locking_callback(ssl_lock_callback);
472         LeaveCriticalSection(&init_ssl_cs);
473 #else
474         FIXME("can't use SSL, not compiled in.\n");
475         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
476 #endif
477     }
478     return ERROR_SUCCESS;
479 }
480
481 void NETCON_unload(void)
482 {
483 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
484     if (OpenSSL_crypto_handle)
485     {
486         pERR_free_strings();
487         wine_dlclose(OpenSSL_crypto_handle, NULL, 0);
488     }
489     if (OpenSSL_ssl_handle)
490     {
491         if (ctx)
492             pSSL_CTX_free(ctx);
493         wine_dlclose(OpenSSL_ssl_handle, NULL, 0);
494     }
495     if (ssl_locks)
496     {
497         int i;
498         for (i = 0; i < num_ssl_locks; i++) DeleteCriticalSection(&ssl_locks[i]);
499         HeapFree(GetProcessHeap(), 0, ssl_locks);
500     }
501 #endif
502 }
503
504 BOOL NETCON_connected(WININET_NETCONNECTION *connection)
505 {
506     if (connection->socketFD == -1)
507         return FALSE;
508     else
509         return TRUE;
510 }
511
512 /* translate a unix error code into a winsock one */
513 int sock_get_error( int err )
514 {
515 #if !defined(__MINGW32__) && !defined (_MSC_VER)
516     switch (err)
517     {
518         case EINTR:             return WSAEINTR;
519         case EBADF:             return WSAEBADF;
520         case EPERM:
521         case EACCES:            return WSAEACCES;
522         case EFAULT:            return WSAEFAULT;
523         case EINVAL:            return WSAEINVAL;
524         case EMFILE:            return WSAEMFILE;
525         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
526         case EINPROGRESS:       return WSAEINPROGRESS;
527         case EALREADY:          return WSAEALREADY;
528         case ENOTSOCK:          return WSAENOTSOCK;
529         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
530         case EMSGSIZE:          return WSAEMSGSIZE;
531         case EPROTOTYPE:        return WSAEPROTOTYPE;
532         case ENOPROTOOPT:       return WSAENOPROTOOPT;
533         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
534         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
535         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
536         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
537         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
538         case EADDRINUSE:        return WSAEADDRINUSE;
539         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
540         case ENETDOWN:          return WSAENETDOWN;
541         case ENETUNREACH:       return WSAENETUNREACH;
542         case ENETRESET:         return WSAENETRESET;
543         case ECONNABORTED:      return WSAECONNABORTED;
544         case EPIPE:
545         case ECONNRESET:        return WSAECONNRESET;
546         case ENOBUFS:           return WSAENOBUFS;
547         case EISCONN:           return WSAEISCONN;
548         case ENOTCONN:          return WSAENOTCONN;
549         case ESHUTDOWN:         return WSAESHUTDOWN;
550         case ETOOMANYREFS:      return WSAETOOMANYREFS;
551         case ETIMEDOUT:         return WSAETIMEDOUT;
552         case ECONNREFUSED:      return WSAECONNREFUSED;
553         case ELOOP:             return WSAELOOP;
554         case ENAMETOOLONG:      return WSAENAMETOOLONG;
555         case EHOSTDOWN:         return WSAEHOSTDOWN;
556         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
557         case ENOTEMPTY:         return WSAENOTEMPTY;
558 #ifdef EPROCLIM
559         case EPROCLIM:          return WSAEPROCLIM;
560 #endif
561 #ifdef EUSERS
562         case EUSERS:            return WSAEUSERS;
563 #endif
564 #ifdef EDQUOT
565         case EDQUOT:            return WSAEDQUOT;
566 #endif
567 #ifdef ESTALE
568         case ESTALE:            return WSAESTALE;
569 #endif
570 #ifdef EREMOTE
571         case EREMOTE:           return WSAEREMOTE;
572 #endif
573     default: errno=err; perror("sock_set_error"); return WSAEFAULT;
574     }
575 #endif
576     return err;
577 }
578
579 /******************************************************************************
580  * NETCON_create
581  * Basically calls 'socket()'
582  */
583 DWORD NETCON_create(WININET_NETCONNECTION *connection, int domain,
584               int type, int protocol)
585 {
586 #ifdef SONAME_LIBSSL
587     if (connection->useSSL)
588         return ERROR_NOT_SUPPORTED;
589 #endif
590
591     connection->socketFD = socket(domain, type, protocol);
592     if (connection->socketFD == -1)
593         return sock_get_error(errno);
594
595     return ERROR_SUCCESS;
596 }
597
598 /******************************************************************************
599  * NETCON_close
600  * Basically calls 'close()' unless we should use SSL
601  */
602 DWORD NETCON_close(WININET_NETCONNECTION *connection)
603 {
604     int result;
605
606     if (!NETCON_connected(connection)) return ERROR_SUCCESS;
607
608 #ifdef SONAME_LIBSSL
609     if (connection->useSSL)
610     {
611         pSSL_shutdown(connection->ssl_s);
612         pSSL_free(connection->ssl_s);
613         connection->ssl_s = NULL;
614
615         connection->useSSL = FALSE;
616     }
617 #endif
618
619     result = closesocket(connection->socketFD);
620     connection->socketFD = -1;
621
622     if (result == -1)
623         return sock_get_error(errno);
624     return ERROR_SUCCESS;
625 }
626
627 /******************************************************************************
628  * NETCON_secure_connect
629  * Initiates a secure connection over an existing plaintext connection.
630  */
631 DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
632 {
633     DWORD res = ERROR_NOT_SUPPORTED;
634 #ifdef SONAME_LIBSSL
635     long verify_res;
636     X509 *cert;
637
638     /* can't connect if we are already connected */
639     if (connection->useSSL)
640     {
641         ERR("already connected\n");
642         return ERROR_INTERNET_CANNOT_CONNECT;
643     }
644
645     connection->ssl_s = pSSL_new(ctx);
646     if (!connection->ssl_s)
647     {
648         ERR("SSL_new failed: %s\n",
649             pERR_error_string(pERR_get_error(), 0));
650         res = ERROR_OUTOFMEMORY;
651         goto fail;
652     }
653
654     if (!pSSL_set_fd(connection->ssl_s, connection->socketFD))
655     {
656         ERR("SSL_set_fd failed: %s\n",
657             pERR_error_string(pERR_get_error(), 0));
658         res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
659         goto fail;
660     }
661
662     if (pSSL_connect(connection->ssl_s) <= 0)
663     {
664         res = (DWORD_PTR)pSSL_get_ex_data(connection->ssl_s, error_idx);
665         if (!res)
666             res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
667         ERR("SSL_connect failed: %d\n", res);
668         goto fail;
669     }
670     pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname);
671     cert = pSSL_get_peer_certificate(connection->ssl_s);
672     if (!cert)
673     {
674         ERR("no certificate for server %s\n", debugstr_w(hostname));
675         /* FIXME: is this the best error? */
676         res = ERROR_INTERNET_INVALID_CA;
677         goto fail;
678     }
679     verify_res = pSSL_get_verify_result(connection->ssl_s);
680     if (verify_res != X509_V_OK)
681     {
682         ERR("couldn't verify the security of the connection, %ld\n", verify_res);
683         /* FIXME: we should set an error and return, but we only warn at
684          * the moment */
685     }
686
687     connection->useSSL = TRUE;
688     return ERROR_SUCCESS;
689
690 fail:
691     if (connection->ssl_s)
692     {
693         pSSL_shutdown(connection->ssl_s);
694         pSSL_free(connection->ssl_s);
695         connection->ssl_s = NULL;
696     }
697 #endif
698     return res;
699 }
700
701 /******************************************************************************
702  * NETCON_connect
703  * Connects to the specified address.
704  */
705 DWORD NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
706                     unsigned int addrlen)
707 {
708     int result;
709
710     result = connect(connection->socketFD, serv_addr, addrlen);
711     if (result == -1)
712     {
713         WARN("Unable to connect to host (%s)\n", strerror(errno));
714
715         closesocket(connection->socketFD);
716         connection->socketFD = -1;
717         return sock_get_error(errno);
718     }
719
720     return ERROR_SUCCESS;
721 }
722
723 /******************************************************************************
724  * NETCON_send
725  * Basically calls 'send()' unless we should use SSL
726  * number of chars send is put in *sent
727  */
728 DWORD NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
729                 int *sent /* out */)
730 {
731     if (!NETCON_connected(connection)) return ERROR_INTERNET_CONNECTION_ABORTED;
732     if (!connection->useSSL)
733     {
734         *sent = send(connection->socketFD, msg, len, flags);
735         if (*sent == -1)
736             return sock_get_error(errno);
737         return ERROR_SUCCESS;
738     }
739     else
740     {
741 #ifdef SONAME_LIBSSL
742         if (flags)
743             FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
744         *sent = pSSL_write(connection->ssl_s, msg, len);
745         if (*sent < 1 && len)
746             return ERROR_INTERNET_CONNECTION_ABORTED;
747         return ERROR_SUCCESS;
748 #else
749         return ERROR_NOT_SUPPORTED;
750 #endif
751     }
752 }
753
754 /******************************************************************************
755  * NETCON_recv
756  * Basically calls 'recv()' unless we should use SSL
757  * number of chars received is put in *recvd
758  */
759 DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
760                 int *recvd /* out */)
761 {
762     *recvd = 0;
763     if (!NETCON_connected(connection)) return ERROR_INTERNET_CONNECTION_ABORTED;
764     if (!len)
765         return ERROR_SUCCESS;
766     if (!connection->useSSL)
767     {
768         *recvd = recv(connection->socketFD, buf, len, flags);
769         return *recvd == -1 ? sock_get_error(errno) :  ERROR_SUCCESS;
770     }
771     else
772     {
773 #ifdef SONAME_LIBSSL
774         *recvd = pSSL_read(connection->ssl_s, buf, len);
775         return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
776 #else
777         return ERROR_NOT_SUPPORTED;
778 #endif
779     }
780 }
781
782 /******************************************************************************
783  * NETCON_query_data_available
784  * Returns the number of bytes of peeked data plus the number of bytes of
785  * queued, but unread data.
786  */
787 BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available)
788 {
789     *available = 0;
790     if (!NETCON_connected(connection))
791         return FALSE;
792
793     if (!connection->useSSL)
794     {
795 #ifdef FIONREAD
796         int unread;
797         int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread);
798         if (!retval)
799         {
800             TRACE("%d bytes of queued, but unread data\n", unread);
801             *available += unread;
802         }
803 #endif
804     }
805     else
806     {
807 #ifdef SONAME_LIBSSL
808         *available = pSSL_pending(connection->ssl_s);
809 #endif
810     }
811     return TRUE;
812 }
813
814 LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
815 {
816 #ifdef SONAME_LIBSSL
817     X509* cert;
818     LPCVOID r = NULL;
819
820     if (!connection->useSSL)
821         return NULL;
822
823     cert = pSSL_get_peer_certificate(connection->ssl_s);
824     r = X509_to_cert_context(cert);
825     return r;
826 #else
827     return NULL;
828 #endif
829 }
830
831 DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value)
832 {
833     int result;
834     struct timeval tv;
835
836     /* FIXME: we should probably store the timeout in the connection to set
837      * when we do connect */
838     if (!NETCON_connected(connection))
839         return ERROR_SUCCESS;
840
841     /* value is in milliseconds, convert to struct timeval */
842     tv.tv_sec = value / 1000;
843     tv.tv_usec = (value % 1000) * 1000;
844
845     result = setsockopt(connection->socketFD, SOL_SOCKET,
846                         send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv,
847                         sizeof(tv));
848
849     if (result == -1)
850     {
851         WARN("setsockopt failed (%s)\n", strerror(errno));
852         return sock_get_error(errno);
853     }
854
855     return ERROR_SUCCESS;
856 }