wininet: Don't use INTERNET_SetLastError in HttpSendRequestA.
[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
164 static unsigned long ssl_thread_id(void)
165 {
166     return GetCurrentThreadId();
167 }
168
169 static void ssl_lock_callback(int mode, int type, const char *file, int line)
170 {
171     if (mode & CRYPTO_LOCK)
172         EnterCriticalSection(&ssl_locks[type]);
173     else
174         LeaveCriticalSection(&ssl_locks[type]);
175 }
176
177 static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
178 {
179     unsigned char* buffer,*p;
180     INT len;
181     BOOL malloced = FALSE;
182     PCCERT_CONTEXT ret;
183
184     p = NULL;
185     len = pi2d_X509(cert,&p);
186     /*
187      * SSL 0.9.7 and above malloc the buffer if it is null.
188      * however earlier version do not and so we would need to alloc the buffer.
189      *
190      * see the i2d_X509 man page for more details.
191      */
192     if (!p)
193     {
194         buffer = HeapAlloc(GetProcessHeap(),0,len);
195         p = buffer;
196         len = pi2d_X509(cert,&p);
197     }
198     else
199     {
200         buffer = p;
201         malloced = TRUE;
202     }
203
204     ret = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
205
206     if (malloced)
207         free(buffer);
208     else
209         HeapFree(GetProcessHeap(),0,buffer);
210
211     return ret;
212 }
213
214 static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store,
215     WCHAR *server)
216 {
217     BOOL ret;
218     CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
219     PCCERT_CHAIN_CONTEXT chain;
220     char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
221     char *server_auth[] = { oid_server_auth };
222     DWORD err = ERROR_SUCCESS;
223
224     TRACE("verifying %s\n", debugstr_w(server));
225     chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
226     chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
227     if ((ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 0,
228         NULL, &chain)))
229     {
230         if (chain->TrustStatus.dwErrorStatus)
231         {
232             if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID)
233                 err = ERROR_INTERNET_SEC_CERT_DATE_INVALID;
234             else if (chain->TrustStatus.dwErrorStatus &
235                      CERT_TRUST_IS_UNTRUSTED_ROOT)
236                 err = ERROR_INTERNET_INVALID_CA;
237             else if ((chain->TrustStatus.dwErrorStatus &
238                       CERT_TRUST_IS_OFFLINE_REVOCATION) ||
239                      (chain->TrustStatus.dwErrorStatus &
240                       CERT_TRUST_REVOCATION_STATUS_UNKNOWN))
241                 err = ERROR_INTERNET_SEC_CERT_NO_REV;
242             else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)
243                 err = ERROR_INTERNET_SEC_CERT_REVOKED;
244             else if (chain->TrustStatus.dwErrorStatus &
245                 CERT_TRUST_IS_NOT_VALID_FOR_USAGE)
246                 err = ERROR_INTERNET_SEC_INVALID_CERT;
247             else
248                 err = ERROR_INTERNET_SEC_INVALID_CERT;
249         }
250         else
251         {
252             CERT_CHAIN_POLICY_PARA policyPara;
253             SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
254             CERT_CHAIN_POLICY_STATUS policyStatus;
255
256             sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
257             sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
258             sslExtraPolicyPara.pwszServerName = server;
259             policyPara.cbSize = sizeof(policyPara);
260             policyPara.dwFlags = 0;
261             policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
262             ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
263                 chain, &policyPara, &policyStatus);
264             /* Any error in the policy status indicates that the
265              * policy couldn't be verified.
266              */
267             if (ret && policyStatus.dwError)
268             {
269                 if (policyStatus.dwError == CERT_E_CN_NO_MATCH)
270                     err = ERROR_INTERNET_SEC_CERT_CN_INVALID;
271                 else
272                     err = ERROR_INTERNET_SEC_INVALID_CERT;
273             }
274         }
275         CertFreeCertificateChain(chain);
276     }
277     TRACE("returning %08x\n", err);
278     return err;
279 }
280
281 static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
282 {
283     SSL *ssl;
284     WCHAR *server;
285     BOOL ret = FALSE;
286
287     ssl = pX509_STORE_CTX_get_ex_data(ctx,
288         pSSL_get_ex_data_X509_STORE_CTX_idx());
289     server = pSSL_get_ex_data(ssl, hostname_idx);
290     if (preverify_ok)
291     {
292         HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
293             CERT_STORE_CREATE_NEW_FLAG, NULL);
294
295         if (store)
296         {
297             X509 *cert;
298             int i;
299             PCCERT_CONTEXT endCert = NULL;
300
301             ret = TRUE;
302             for (i = 0; ret && i < psk_num((struct stack_st *)ctx->chain); i++)
303             {
304                 PCCERT_CONTEXT context;
305
306                 cert = (X509 *)psk_value((struct stack_st *)ctx->chain, i);
307                 if ((context = X509_to_cert_context(cert)))
308                 {
309                     if (i == 0)
310                         ret = CertAddCertificateContextToStore(store, context,
311                             CERT_STORE_ADD_ALWAYS, &endCert);
312                     else
313                         ret = CertAddCertificateContextToStore(store, context,
314                             CERT_STORE_ADD_ALWAYS, NULL);
315                     CertFreeCertificateContext(context);
316                 }
317             }
318             if (!endCert) ret = FALSE;
319             if (ret)
320             {
321                 DWORD err = netconn_verify_cert(endCert, store, server);
322
323                 if (err)
324                 {
325                     pSSL_set_ex_data(ssl, error_idx, (void *)err);
326                     ret = FALSE;
327                 }
328             }
329             CertFreeCertificateContext(endCert);
330             CertCloseStore(store, 0);
331         }
332     }
333     return ret;
334 }
335
336 #endif
337
338 DWORD NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL)
339 {
340     connection->useSSL = FALSE;
341     connection->socketFD = -1;
342     if (useSSL)
343     {
344 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
345         int i;
346
347         TRACE("using SSL connection\n");
348         EnterCriticalSection(&init_ssl_cs);
349         if (OpenSSL_ssl_handle) /* already initialized everything */
350         {
351             LeaveCriticalSection(&init_ssl_cs);
352             return ERROR_SUCCESS;
353         }
354         OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
355         if (!OpenSSL_ssl_handle)
356         {
357             ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
358                 SONAME_LIBSSL);
359             LeaveCriticalSection(&init_ssl_cs);
360             return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
361         }
362         OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
363         if (!OpenSSL_crypto_handle)
364         {
365             ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n",
366                 SONAME_LIBCRYPTO);
367             LeaveCriticalSection(&init_ssl_cs);
368             return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
369         }
370
371         /* mmm nice ugly macroness */
372 #define DYNSSL(x) \
373     p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \
374     if (!p##x) \
375     { \
376         ERR("failed to load symbol %s\n", #x); \
377         LeaveCriticalSection(&init_ssl_cs); \
378         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
379     }
380
381         DYNSSL(SSL_library_init);
382         DYNSSL(SSL_load_error_strings);
383         DYNSSL(SSLv23_method);
384         DYNSSL(SSL_CTX_free);
385         DYNSSL(SSL_CTX_new);
386         DYNSSL(SSL_new);
387         DYNSSL(SSL_free);
388         DYNSSL(SSL_set_fd);
389         DYNSSL(SSL_connect);
390         DYNSSL(SSL_shutdown);
391         DYNSSL(SSL_write);
392         DYNSSL(SSL_read);
393         DYNSSL(SSL_pending);
394         DYNSSL(SSL_get_ex_new_index);
395         DYNSSL(SSL_get_ex_data);
396         DYNSSL(SSL_set_ex_data);
397         DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx);
398         DYNSSL(SSL_get_verify_result);
399         DYNSSL(SSL_get_peer_certificate);
400         DYNSSL(SSL_CTX_get_timeout);
401         DYNSSL(SSL_CTX_set_timeout);
402         DYNSSL(SSL_CTX_set_default_verify_paths);
403         DYNSSL(SSL_CTX_set_verify);
404         DYNSSL(X509_STORE_CTX_get_ex_data);
405 #undef DYNSSL
406
407 #define DYNCRYPTO(x) \
408     p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \
409     if (!p##x) \
410     { \
411         ERR("failed to load symbol %s\n", #x); \
412         LeaveCriticalSection(&init_ssl_cs); \
413         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
414     }
415         DYNCRYPTO(BIO_new_fp);
416         DYNCRYPTO(CRYPTO_num_locks);
417         DYNCRYPTO(CRYPTO_set_id_callback);
418         DYNCRYPTO(CRYPTO_set_locking_callback);
419         DYNCRYPTO(ERR_free_strings);
420         DYNCRYPTO(ERR_get_error);
421         DYNCRYPTO(ERR_error_string);
422         DYNCRYPTO(i2d_X509);
423         DYNCRYPTO(sk_num);
424         DYNCRYPTO(sk_value);
425 #undef DYNCRYPTO
426
427         pSSL_library_init();
428         pSSL_load_error_strings();
429         pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
430
431         meth = pSSLv23_method();
432         ctx = pSSL_CTX_new(meth);
433         if (!pSSL_CTX_set_default_verify_paths(ctx))
434         {
435             ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
436                 pERR_error_string(pERR_get_error(), 0));
437             LeaveCriticalSection(&init_ssl_cs);
438             return ERROR_OUTOFMEMORY;
439         }
440         hostname_idx = pSSL_get_ex_new_index(0, (void *)"hostname index",
441                 NULL, NULL, NULL);
442         if (hostname_idx == -1)
443         {
444             ERR("SSL_get_ex_new_index failed; %s\n",
445                 pERR_error_string(pERR_get_error(), 0));
446             LeaveCriticalSection(&init_ssl_cs);
447             return ERROR_OUTOFMEMORY;
448         }
449         error_idx = pSSL_get_ex_new_index(0, (void *)"error index",
450                 NULL, NULL, NULL);
451         if (error_idx == -1)
452         {
453             ERR("SSL_get_ex_new_index failed; %s\n",
454                 pERR_error_string(pERR_get_error(), 0));
455             LeaveCriticalSection(&init_ssl_cs);
456             return ERROR_OUTOFMEMORY;
457         }
458         pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify);
459
460         pCRYPTO_set_id_callback(ssl_thread_id);
461         ssl_locks = HeapAlloc(GetProcessHeap(), 0,
462                 pCRYPTO_num_locks() * sizeof(CRITICAL_SECTION));
463         if (!ssl_locks)
464         {
465             LeaveCriticalSection(&init_ssl_cs);
466             return ERROR_OUTOFMEMORY;
467         }
468         for (i = 0; i < pCRYPTO_num_locks(); i++)
469             InitializeCriticalSection(&ssl_locks[i]);
470         pCRYPTO_set_locking_callback(ssl_lock_callback);
471         LeaveCriticalSection(&init_ssl_cs);
472 #else
473         FIXME("can't use SSL, not compiled in.\n");
474         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
475 #endif
476     }
477     return ERROR_SUCCESS;
478 }
479
480 void NETCON_unload(void)
481 {
482 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
483     if (OpenSSL_crypto_handle)
484     {
485         pERR_free_strings();
486         wine_dlclose(OpenSSL_crypto_handle, NULL, 0);
487     }
488     if (OpenSSL_ssl_handle)
489     {
490         if (ctx)
491             pSSL_CTX_free(ctx);
492         wine_dlclose(OpenSSL_ssl_handle, NULL, 0);
493     }
494     if (ssl_locks)
495     {
496         int i;
497         for (i = 0; i < pCRYPTO_num_locks(); i++) DeleteCriticalSection(&ssl_locks[i]);
498         HeapFree(GetProcessHeap(), 0, ssl_locks);
499     }
500 #endif
501 }
502
503 BOOL NETCON_connected(WININET_NETCONNECTION *connection)
504 {
505     if (connection->socketFD == -1)
506         return FALSE;
507     else
508         return TRUE;
509 }
510
511 /* translate a unix error code into a winsock one */
512 int sock_get_error( int err )
513 {
514 #if !defined(__MINGW32__) && !defined (_MSC_VER)
515     switch (err)
516     {
517         case EINTR:             return WSAEINTR;
518         case EBADF:             return WSAEBADF;
519         case EPERM:
520         case EACCES:            return WSAEACCES;
521         case EFAULT:            return WSAEFAULT;
522         case EINVAL:            return WSAEINVAL;
523         case EMFILE:            return WSAEMFILE;
524         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
525         case EINPROGRESS:       return WSAEINPROGRESS;
526         case EALREADY:          return WSAEALREADY;
527         case ENOTSOCK:          return WSAENOTSOCK;
528         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
529         case EMSGSIZE:          return WSAEMSGSIZE;
530         case EPROTOTYPE:        return WSAEPROTOTYPE;
531         case ENOPROTOOPT:       return WSAENOPROTOOPT;
532         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
533         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
534         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
535         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
536         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
537         case EADDRINUSE:        return WSAEADDRINUSE;
538         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
539         case ENETDOWN:          return WSAENETDOWN;
540         case ENETUNREACH:       return WSAENETUNREACH;
541         case ENETRESET:         return WSAENETRESET;
542         case ECONNABORTED:      return WSAECONNABORTED;
543         case EPIPE:
544         case ECONNRESET:        return WSAECONNRESET;
545         case ENOBUFS:           return WSAENOBUFS;
546         case EISCONN:           return WSAEISCONN;
547         case ENOTCONN:          return WSAENOTCONN;
548         case ESHUTDOWN:         return WSAESHUTDOWN;
549         case ETOOMANYREFS:      return WSAETOOMANYREFS;
550         case ETIMEDOUT:         return WSAETIMEDOUT;
551         case ECONNREFUSED:      return WSAECONNREFUSED;
552         case ELOOP:             return WSAELOOP;
553         case ENAMETOOLONG:      return WSAENAMETOOLONG;
554         case EHOSTDOWN:         return WSAEHOSTDOWN;
555         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
556         case ENOTEMPTY:         return WSAENOTEMPTY;
557 #ifdef EPROCLIM
558         case EPROCLIM:          return WSAEPROCLIM;
559 #endif
560 #ifdef EUSERS
561         case EUSERS:            return WSAEUSERS;
562 #endif
563 #ifdef EDQUOT
564         case EDQUOT:            return WSAEDQUOT;
565 #endif
566 #ifdef ESTALE
567         case ESTALE:            return WSAESTALE;
568 #endif
569 #ifdef EREMOTE
570         case EREMOTE:           return WSAEREMOTE;
571 #endif
572     default: errno=err; perror("sock_set_error"); return WSAEFAULT;
573     }
574 #endif
575     return err;
576 }
577
578 /******************************************************************************
579  * NETCON_create
580  * Basically calls 'socket()'
581  */
582 DWORD NETCON_create(WININET_NETCONNECTION *connection, int domain,
583               int type, int protocol)
584 {
585 #ifdef SONAME_LIBSSL
586     if (connection->useSSL)
587         return ERROR_NOT_SUPPORTED;
588 #endif
589
590     connection->socketFD = socket(domain, type, protocol);
591     if (connection->socketFD == -1)
592         return sock_get_error(errno);
593
594     return ERROR_SUCCESS;
595 }
596
597 /******************************************************************************
598  * NETCON_close
599  * Basically calls 'close()' unless we should use SSL
600  */
601 DWORD NETCON_close(WININET_NETCONNECTION *connection)
602 {
603     int result;
604
605     if (!NETCON_connected(connection)) return ERROR_SUCCESS;
606
607 #ifdef SONAME_LIBSSL
608     if (connection->useSSL)
609     {
610         pSSL_shutdown(connection->ssl_s);
611         pSSL_free(connection->ssl_s);
612         connection->ssl_s = NULL;
613
614         connection->useSSL = FALSE;
615     }
616 #endif
617
618     result = closesocket(connection->socketFD);
619     connection->socketFD = -1;
620
621     if (result == -1)
622         return sock_get_error(errno);
623     return ERROR_SUCCESS;
624 }
625
626 /******************************************************************************
627  * NETCON_secure_connect
628  * Initiates a secure connection over an existing plaintext connection.
629  */
630 DWORD NETCON_secure_connect(WININET_NETCONNECTION *connection, LPWSTR hostname)
631 {
632     DWORD res = ERROR_NOT_SUPPORTED;
633 #ifdef SONAME_LIBSSL
634     long verify_res;
635     X509 *cert;
636
637     /* can't connect if we are already connected */
638     if (connection->useSSL)
639     {
640         ERR("already connected\n");
641         return ERROR_INTERNET_CANNOT_CONNECT;
642     }
643
644     connection->ssl_s = pSSL_new(ctx);
645     if (!connection->ssl_s)
646     {
647         ERR("SSL_new failed: %s\n",
648             pERR_error_string(pERR_get_error(), 0));
649         res = ERROR_OUTOFMEMORY;
650         goto fail;
651     }
652
653     if (!pSSL_set_fd(connection->ssl_s, connection->socketFD))
654     {
655         ERR("SSL_set_fd failed: %s\n",
656             pERR_error_string(pERR_get_error(), 0));
657         res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
658         goto fail;
659     }
660
661     if (pSSL_connect(connection->ssl_s) <= 0)
662     {
663         res = (DWORD)pSSL_get_ex_data(connection->ssl_s, error_idx);
664         if (!res)
665             res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
666         ERR("SSL_connect failed: %d\n", res);
667         goto fail;
668     }
669     pSSL_set_ex_data(connection->ssl_s, hostname_idx, hostname);
670     cert = pSSL_get_peer_certificate(connection->ssl_s);
671     if (!cert)
672     {
673         ERR("no certificate for server %s\n", debugstr_w(hostname));
674         /* FIXME: is this the best error? */
675         res = ERROR_INTERNET_INVALID_CA;
676         goto fail;
677     }
678     verify_res = pSSL_get_verify_result(connection->ssl_s);
679     if (verify_res != X509_V_OK)
680     {
681         ERR("couldn't verify the security of the connection, %ld\n", verify_res);
682         /* FIXME: we should set an error and return, but we only warn at
683          * the moment */
684     }
685
686     connection->useSSL = TRUE;
687     return ERROR_SUCCESS;
688
689 fail:
690     if (connection->ssl_s)
691     {
692         pSSL_shutdown(connection->ssl_s);
693         pSSL_free(connection->ssl_s);
694         connection->ssl_s = NULL;
695     }
696 #endif
697     return res;
698 }
699
700 /******************************************************************************
701  * NETCON_connect
702  * Connects to the specified address.
703  */
704 DWORD NETCON_connect(WININET_NETCONNECTION *connection, const struct sockaddr *serv_addr,
705                     unsigned int addrlen)
706 {
707     int result;
708
709     result = connect(connection->socketFD, serv_addr, addrlen);
710     if (result == -1)
711     {
712         WARN("Unable to connect to host (%s)\n", strerror(errno));
713
714         closesocket(connection->socketFD);
715         connection->socketFD = -1;
716         return sock_get_error(errno);
717     }
718
719     return ERROR_SUCCESS;
720 }
721
722 /******************************************************************************
723  * NETCON_send
724  * Basically calls 'send()' unless we should use SSL
725  * number of chars send is put in *sent
726  */
727 DWORD NETCON_send(WININET_NETCONNECTION *connection, const void *msg, size_t len, int flags,
728                 int *sent /* out */)
729 {
730     if (!NETCON_connected(connection)) return ERROR_INTERNET_CONNECTION_ABORTED;
731     if (!connection->useSSL)
732     {
733         *sent = send(connection->socketFD, msg, len, flags);
734         if (*sent == -1)
735             return sock_get_error(errno);
736         return ERROR_SUCCESS;
737     }
738     else
739     {
740 #ifdef SONAME_LIBSSL
741         if (flags)
742             FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
743         *sent = pSSL_write(connection->ssl_s, msg, len);
744         if (*sent < 1 && len)
745             return ERROR_INTERNET_CONNECTION_ABORTED;
746         return ERROR_SUCCESS;
747 #else
748         return ERROR_NOT_SUPPORTED;
749 #endif
750     }
751 }
752
753 /******************************************************************************
754  * NETCON_recv
755  * Basically calls 'recv()' unless we should use SSL
756  * number of chars received is put in *recvd
757  */
758 DWORD NETCON_recv(WININET_NETCONNECTION *connection, void *buf, size_t len, int flags,
759                 int *recvd /* out */)
760 {
761     *recvd = 0;
762     if (!NETCON_connected(connection)) return ERROR_INTERNET_CONNECTION_ABORTED;
763     if (!len)
764         return ERROR_SUCCESS;
765     if (!connection->useSSL)
766     {
767         *recvd = recv(connection->socketFD, buf, len, flags);
768         return *recvd == -1 ? sock_get_error(errno) :  ERROR_SUCCESS;
769     }
770     else
771     {
772 #ifdef SONAME_LIBSSL
773         *recvd = pSSL_read(connection->ssl_s, buf, len);
774         return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
775 #else
776         return ERROR_NOT_SUPPORTED;
777 #endif
778     }
779 }
780
781 /******************************************************************************
782  * NETCON_query_data_available
783  * Returns the number of bytes of peeked data plus the number of bytes of
784  * queued, but unread data.
785  */
786 BOOL NETCON_query_data_available(WININET_NETCONNECTION *connection, DWORD *available)
787 {
788     *available = 0;
789     if (!NETCON_connected(connection))
790         return FALSE;
791
792     if (!connection->useSSL)
793     {
794 #ifdef FIONREAD
795         int unread;
796         int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread);
797         if (!retval)
798         {
799             TRACE("%d bytes of queued, but unread data\n", unread);
800             *available += unread;
801         }
802 #endif
803     }
804     else
805     {
806 #ifdef SONAME_LIBSSL
807         *available = pSSL_pending(connection->ssl_s);
808 #endif
809     }
810     return TRUE;
811 }
812
813 LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection)
814 {
815 #ifdef SONAME_LIBSSL
816     X509* cert;
817     LPCVOID r = NULL;
818
819     if (!connection->useSSL)
820         return NULL;
821
822     cert = pSSL_get_peer_certificate(connection->ssl_s);
823     r = X509_to_cert_context(cert);
824     return r;
825 #else
826     return NULL;
827 #endif
828 }
829
830 DWORD NETCON_set_timeout(WININET_NETCONNECTION *connection, BOOL send, int value)
831 {
832     int result;
833     struct timeval tv;
834
835     /* FIXME: we should probably store the timeout in the connection to set
836      * when we do connect */
837     if (!NETCON_connected(connection))
838         return ERROR_SUCCESS;
839
840     /* value is in milliseconds, convert to struct timeval */
841     tv.tv_sec = value / 1000;
842     tv.tv_usec = (value % 1000) * 1000;
843
844     result = setsockopt(connection->socketFD, SOL_SOCKET,
845                         send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv,
846                         sizeof(tv));
847
848     if (result == -1)
849     {
850         WARN("setsockopt failed (%s)\n", strerror(errno));
851         return sock_get_error(errno);
852     }
853
854     return ERROR_SUCCESS;
855 }