wininet: Use schannel in NETCON_GetCipherStrength if OpenSSL is not available.
[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_NETINET_TCP_H
62 # include <netinet/tcp.h>
63 #endif
64 #ifdef HAVE_OPENSSL_SSL_H
65 # include <openssl/ssl.h>
66 # include <openssl/opensslv.h>
67 #undef FAR
68 #undef DSA
69 #endif
70
71 #include <stdarg.h>
72 #include <stdlib.h>
73 #include <string.h>
74 #include <stdio.h>
75 #include <errno.h>
76 #include <assert.h>
77
78 #include "wine/library.h"
79 #include "windef.h"
80 #include "winbase.h"
81 #include "wininet.h"
82 #include "winerror.h"
83
84 #include "wine/debug.h"
85 #include "internet.h"
86
87 /* To avoid conflicts with the Unix socket headers. we only need it for
88  * the error codes anyway. */
89 #define USE_WS_PREFIX
90 #include "winsock2.h"
91
92 #define RESPONSE_TIMEOUT        30            /* FROM internet.c */
93
94
95 WINE_DEFAULT_DEBUG_CHANNEL(wininet);
96
97 /* FIXME!!!!!!
98  *    This should use winsock - To use winsock the functions will have to change a bit
99  *        as they are designed for unix sockets.
100  *    SSL stuff should use crypt32.dll
101  */
102
103 #ifdef SONAME_LIBSSL
104
105 #include <openssl/err.h>
106
107 static void *OpenSSL_ssl_handle;
108 static void *OpenSSL_crypto_handle;
109
110 #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10000000)
111 static const SSL_METHOD *meth;
112 #else
113 static SSL_METHOD *meth;
114 #endif
115 static SSL_CTX *ctx;
116 static int error_idx;
117 static int conn_idx;
118
119 #define MAKE_FUNCPTR(f) static typeof(f) * p##f
120
121 /* OpenSSL functions that we use */
122 MAKE_FUNCPTR(SSL_library_init);
123 MAKE_FUNCPTR(SSL_load_error_strings);
124 MAKE_FUNCPTR(SSLv23_method);
125 MAKE_FUNCPTR(SSL_CTX_free);
126 MAKE_FUNCPTR(SSL_CTX_new);
127 MAKE_FUNCPTR(SSL_CTX_ctrl);
128 MAKE_FUNCPTR(SSL_new);
129 MAKE_FUNCPTR(SSL_free);
130 MAKE_FUNCPTR(SSL_ctrl);
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_error);
138 MAKE_FUNCPTR(SSL_get_ex_new_index);
139 MAKE_FUNCPTR(SSL_get_ex_data);
140 MAKE_FUNCPTR(SSL_set_ex_data);
141 MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx);
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(SSL_get_current_cipher);
148 MAKE_FUNCPTR(SSL_CIPHER_get_bits);
149
150 /* OpenSSL's libcrypto functions that we use */
151 MAKE_FUNCPTR(BIO_new_fp);
152 MAKE_FUNCPTR(CRYPTO_num_locks);
153 MAKE_FUNCPTR(CRYPTO_set_id_callback);
154 MAKE_FUNCPTR(CRYPTO_set_locking_callback);
155 MAKE_FUNCPTR(ERR_free_strings);
156 MAKE_FUNCPTR(ERR_get_error);
157 MAKE_FUNCPTR(ERR_error_string);
158 MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data);
159 MAKE_FUNCPTR(X509_STORE_CTX_get_chain);
160 MAKE_FUNCPTR(i2d_X509);
161 MAKE_FUNCPTR(sk_num);
162 MAKE_FUNCPTR(sk_value);
163 #undef MAKE_FUNCPTR
164
165 static CRITICAL_SECTION *ssl_locks;
166 static unsigned int num_ssl_locks;
167
168 static unsigned long ssl_thread_id(void)
169 {
170     return GetCurrentThreadId();
171 }
172
173 static void ssl_lock_callback(int mode, int type, const char *file, int line)
174 {
175     if (mode & CRYPTO_LOCK)
176         EnterCriticalSection(&ssl_locks[type]);
177     else
178         LeaveCriticalSection(&ssl_locks[type]);
179 }
180
181 static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
182 {
183     unsigned char* buffer,*p;
184     INT len;
185     BOOL malloced = FALSE;
186     PCCERT_CONTEXT ret;
187
188     p = NULL;
189     len = pi2d_X509(cert,&p);
190     /*
191      * SSL 0.9.7 and above malloc the buffer if it is null.
192      * however earlier version do not and so we would need to alloc the buffer.
193      *
194      * see the i2d_X509 man page for more details.
195      */
196     if (!p)
197     {
198         buffer = heap_alloc(len);
199         p = buffer;
200         len = pi2d_X509(cert,&p);
201     }
202     else
203     {
204         buffer = p;
205         malloced = TRUE;
206     }
207
208     ret = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);
209
210     if (malloced)
211         free(buffer);
212     else
213         heap_free(buffer);
214
215     return ret;
216 }
217 #endif /* SONAME_LIBSSL */
218
219 static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTORE store)
220 {
221     BOOL ret;
222     CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
223     PCCERT_CHAIN_CONTEXT chain;
224     char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
225     char *server_auth[] = { oid_server_auth };
226     DWORD err = ERROR_SUCCESS, errors;
227
228     static const DWORD supportedErrors =
229         CERT_TRUST_IS_NOT_TIME_VALID |
230         CERT_TRUST_IS_UNTRUSTED_ROOT |
231         CERT_TRUST_IS_PARTIAL_CHAIN |
232         CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
233
234     TRACE("verifying %s\n", debugstr_w(conn->server->name));
235
236     chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
237     chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
238     if (!(ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 0, NULL, &chain))) {
239         TRACE("failed\n");
240         return GetLastError();
241     }
242
243     errors = chain->TrustStatus.dwErrorStatus;
244
245     do {
246         /* This seems strange, but that's what tests show */
247         if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
248             WARN("ERROR_INTERNET_SEC_CERT_REV_FAILED\n");
249             err = ERROR_INTERNET_SEC_CERT_REV_FAILED;
250             if(conn->mask_errors)
251                 conn->security_flags |= _SECURITY_FLAG_CERT_REV_FAILED;
252             if(!(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION))
253                 break;
254         }
255
256         if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) {
257             WARN("error status %x\n", chain->TrustStatus.dwErrorStatus & ~supportedErrors);
258             err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
259             errors &= supportedErrors;
260             if(!conn->mask_errors)
261                 break;
262             WARN("unknown error flags\n");
263         }
264
265         if(errors & CERT_TRUST_IS_NOT_TIME_VALID) {
266             WARN("CERT_TRUST_IS_NOT_TIME_VALID\n");
267             if(!(conn->security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)) {
268                 err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_DATE_INVALID;
269                 if(!conn->mask_errors)
270                     break;
271                 conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_DATE;
272             }
273             errors &= ~CERT_TRUST_IS_NOT_TIME_VALID;
274         }
275
276         if(errors & CERT_TRUST_IS_UNTRUSTED_ROOT) {
277             WARN("CERT_TRUST_IS_UNTRUSTED_ROOT\n");
278             if(!(conn->security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) {
279                 err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_INVALID_CA;
280                 if(!conn->mask_errors)
281                     break;
282                 conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CA;
283             }
284             errors &= ~CERT_TRUST_IS_UNTRUSTED_ROOT;
285         }
286
287         if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
288             WARN("CERT_TRUST_IS_PARTIAL_CHAIN\n");
289             if(!(conn->security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) {
290                 err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_INVALID_CA;
291                 if(!conn->mask_errors)
292                     break;
293                 conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CA;
294             }
295             errors &= ~CERT_TRUST_IS_PARTIAL_CHAIN;
296         }
297
298         if(errors & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
299             WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE\n");
300             if(!(conn->security_flags & SECURITY_FLAG_IGNORE_WRONG_USAGE)) {
301                 err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
302                 if(!conn->mask_errors)
303                     break;
304                 WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE, unknown error flags\n");
305             }
306             errors &= ~CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
307         }
308
309         if(err == ERROR_INTERNET_SEC_CERT_REV_FAILED) {
310             assert(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION);
311             err = ERROR_SUCCESS;
312         }
313     }while(0);
314
315     if(!err || conn->mask_errors) {
316         CERT_CHAIN_POLICY_PARA policyPara;
317         SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
318         CERT_CHAIN_POLICY_STATUS policyStatus;
319         CERT_CHAIN_CONTEXT chainCopy;
320
321         /* Clear chain->TrustStatus.dwErrorStatus so
322          * CertVerifyCertificateChainPolicy will verify additional checks
323          * rather than stopping with an existing, ignored error.
324          */
325         memcpy(&chainCopy, chain, sizeof(chainCopy));
326         chainCopy.TrustStatus.dwErrorStatus = 0;
327         sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
328         sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
329         sslExtraPolicyPara.pwszServerName = conn->server->name;
330         sslExtraPolicyPara.fdwChecks = conn->security_flags;
331         policyPara.cbSize = sizeof(policyPara);
332         policyPara.dwFlags = 0;
333         policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
334         ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
335                 &chainCopy, &policyPara, &policyStatus);
336         /* Any error in the policy status indicates that the
337          * policy couldn't be verified.
338          */
339         if(ret) {
340             if(policyStatus.dwError == CERT_E_CN_NO_MATCH) {
341                 WARN("CERT_E_CN_NO_MATCH\n");
342                 if(conn->mask_errors)
343                     conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CN;
344                 err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_CN_INVALID;
345             }else if(policyStatus.dwError) {
346                 WARN("policyStatus.dwError %x\n", policyStatus.dwError);
347                 if(conn->mask_errors)
348                     WARN("unknown error flags for policy status %x\n", policyStatus.dwError);
349                 err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
350             }
351         }else {
352             err = GetLastError();
353         }
354     }
355
356     if(err) {
357         WARN("failed %u\n", err);
358         CertFreeCertificateChain(chain);
359         if(conn->server->cert_chain) {
360             CertFreeCertificateChain(conn->server->cert_chain);
361             conn->server->cert_chain = NULL;
362         }
363         if(conn->mask_errors)
364             conn->server->security_flags |= conn->security_flags & _SECURITY_ERROR_FLAGS_MASK;
365         return err;
366     }
367
368     /* FIXME: Reuse cached chain */
369     if(conn->server->cert_chain)
370         CertFreeCertificateChain(chain);
371     else
372         conn->server->cert_chain = chain;
373     return ERROR_SUCCESS;
374 }
375
376 #ifdef SONAME_LIBSSL
377 static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
378 {
379     SSL *ssl;
380     BOOL ret = FALSE;
381     HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
382         CERT_STORE_CREATE_NEW_FLAG, NULL);
383     netconn_t *conn;
384
385     ssl = pX509_STORE_CTX_get_ex_data(ctx,
386         pSSL_get_ex_data_X509_STORE_CTX_idx());
387     conn = pSSL_get_ex_data(ssl, conn_idx);
388     if (store)
389     {
390         X509 *cert;
391         int i;
392         PCCERT_CONTEXT endCert = NULL;
393         struct stack_st *chain = (struct stack_st *)pX509_STORE_CTX_get_chain( ctx );
394
395         ret = TRUE;
396         for (i = 0; ret && i < psk_num(chain); i++)
397         {
398             PCCERT_CONTEXT context;
399
400             cert = (X509 *)psk_value(chain, i);
401             if ((context = X509_to_cert_context(cert)))
402             {
403                 ret = CertAddCertificateContextToStore(store, context,
404                         CERT_STORE_ADD_ALWAYS, i ? NULL : &endCert);
405                 CertFreeCertificateContext(context);
406             }
407         }
408         if (!endCert) ret = FALSE;
409         if (ret)
410         {
411             DWORD_PTR err = netconn_verify_cert(conn, endCert, store);
412
413             if (err)
414             {
415                 pSSL_set_ex_data(ssl, error_idx, (void *)err);
416                 ret = FALSE;
417             }
418         }
419         CertFreeCertificateContext(endCert);
420         CertCloseStore(store, 0);
421     }
422     return ret;
423 }
424
425 static long get_tls_option(void) {
426     long tls_option = SSL_OP_NO_SSLv2; /* disable SSLv2 for security reason, secur32/Schannel(GnuTLS) don't support it */
427 #ifdef SSL_OP_NO_TLSv1_2
428     DWORD type, val, size;
429     HKEY hkey,tls12_client,tls11_client;
430     LONG res;
431     const WCHAR Schannel_Prot[] = {  /* SYSTEM\\CurrentControlSet\\Control\\SecurityProviders\\SCANNEL\\Protocols */
432               'S','Y','S','T','E','M','\\',
433               'C','u','r','r','e','n','t','C','o','n','t','r','o','l','S','e','t','\\',
434               'C','o','n','t','r','o','l','\\',
435               'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s','\\',
436               'S','C','H','A','N','N','E','L','\\',
437               'P','r','o','t','o','c','o','l','s',0 };
438      const WCHAR TLS12_Client[] = {'T','L','S',' ','1','.','2','\\','C','l','i','e','n','t',0};
439      const WCHAR TLS11_Client[] = {'T','L','S',' ','1','.','1','\\','C','l','i','e','n','t',0};
440      const WCHAR DisabledByDefault[] = {'D','i','s','a','b','l','e','d','B','y','D','e','f','a','u','l','t',0};
441
442     res = RegOpenKeyExW(HKEY_LOCAL_MACHINE,
443           Schannel_Prot,
444           0, KEY_READ, &hkey);
445     if (res != ERROR_SUCCESS) { /* enabled TLSv1.1/1.2 when no registry entry */
446         return tls_option;
447     }
448     if (RegOpenKeyExW(hkey, TLS12_Client, 0, KEY_READ, &tls12_client) == ERROR_SUCCESS) {
449         size = sizeof(DWORD);
450         if (RegQueryValueExW(tls12_client, DisabledByDefault, NULL, &type,  (LPBYTE) &val, &size) == ERROR_SUCCESS
451             && type == REG_DWORD) {
452             tls_option |= val?SSL_OP_NO_TLSv1_2:0;
453         }
454         RegCloseKey(tls12_client);
455     }
456     if (RegOpenKeyExW(hkey, TLS11_Client, 0, KEY_READ, &tls11_client) == ERROR_SUCCESS) {
457         size = sizeof(DWORD);
458         if (RegQueryValueExW(tls11_client, DisabledByDefault, NULL, &type,  (LPBYTE) &val, &size) == ERROR_SUCCESS
459             && type == REG_DWORD) {
460             tls_option |= val?SSL_OP_NO_TLSv1_1:0;
461         }
462         RegCloseKey(tls11_client);
463     }
464     RegCloseKey(hkey);
465 #endif
466     return tls_option;
467 }
468
469 static CRITICAL_SECTION init_ssl_cs;
470 static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
471 {
472     0, 0, &init_ssl_cs,
473     { &init_ssl_cs_debug.ProcessLocksList,
474       &init_ssl_cs_debug.ProcessLocksList },
475     0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
476 };
477 static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };
478
479 static DWORD init_openssl(void)
480 {
481 #ifdef SONAME_LIBCRYPTO
482     unsigned int i;
483
484     if(OpenSSL_ssl_handle)
485         return ERROR_SUCCESS;
486
487     OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
488     if(!OpenSSL_ssl_handle) {
489         ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL);
490         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
491     }
492
493     OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
494     if(!OpenSSL_crypto_handle) {
495         ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO);
496         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
497     }
498
499     /* mmm nice ugly macroness */
500 #define DYNSSL(x) \
501     p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \
502     if (!p##x) { \
503         ERR("failed to load symbol %s\n", #x); \
504         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
505     }
506
507     DYNSSL(SSL_library_init);
508     DYNSSL(SSL_load_error_strings);
509     DYNSSL(SSLv23_method);
510     DYNSSL(SSL_CTX_free);
511     DYNSSL(SSL_CTX_new);
512     DYNSSL(SSL_CTX_ctrl);
513     DYNSSL(SSL_new);
514     DYNSSL(SSL_free);
515     DYNSSL(SSL_ctrl);
516     DYNSSL(SSL_set_fd);
517     DYNSSL(SSL_connect);
518     DYNSSL(SSL_shutdown);
519     DYNSSL(SSL_write);
520     DYNSSL(SSL_read);
521     DYNSSL(SSL_pending);
522     DYNSSL(SSL_get_error);
523     DYNSSL(SSL_get_ex_new_index);
524     DYNSSL(SSL_get_ex_data);
525     DYNSSL(SSL_set_ex_data);
526     DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx);
527     DYNSSL(SSL_get_peer_certificate);
528     DYNSSL(SSL_CTX_get_timeout);
529     DYNSSL(SSL_CTX_set_timeout);
530     DYNSSL(SSL_CTX_set_default_verify_paths);
531     DYNSSL(SSL_CTX_set_verify);
532     DYNSSL(SSL_get_current_cipher);
533     DYNSSL(SSL_CIPHER_get_bits);
534 #undef DYNSSL
535
536 #define DYNCRYPTO(x) \
537     p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \
538     if (!p##x) { \
539         ERR("failed to load symbol %s\n", #x); \
540         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
541     }
542
543     DYNCRYPTO(BIO_new_fp);
544     DYNCRYPTO(CRYPTO_num_locks);
545     DYNCRYPTO(CRYPTO_set_id_callback);
546     DYNCRYPTO(CRYPTO_set_locking_callback);
547     DYNCRYPTO(ERR_free_strings);
548     DYNCRYPTO(ERR_get_error);
549     DYNCRYPTO(ERR_error_string);
550     DYNCRYPTO(X509_STORE_CTX_get_ex_data);
551     DYNCRYPTO(X509_STORE_CTX_get_chain);
552     DYNCRYPTO(i2d_X509);
553     DYNCRYPTO(sk_num);
554     DYNCRYPTO(sk_value);
555 #undef DYNCRYPTO
556
557 #define pSSL_CTX_set_options(ctx,op) \
558        pSSL_CTX_ctrl((ctx),SSL_CTRL_OPTIONS,(op),NULL)
559 #define pSSL_set_options(ssl,op) \
560        pSSL_ctrl((ssl),SSL_CTRL_OPTIONS,(op),NULL)
561
562     pSSL_library_init();
563     pSSL_load_error_strings();
564     pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
565
566     meth = pSSLv23_method();
567     ctx = pSSL_CTX_new(meth);
568     pSSL_CTX_set_options(ctx, get_tls_option());
569     if(!pSSL_CTX_set_default_verify_paths(ctx)) {
570         ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
571             pERR_error_string(pERR_get_error(), 0));
572         return ERROR_OUTOFMEMORY;
573     }
574
575     error_idx = pSSL_get_ex_new_index(0, (void *)"error index", NULL, NULL, NULL);
576     if(error_idx == -1) {
577         ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0));
578         return ERROR_OUTOFMEMORY;
579     }
580
581     conn_idx = pSSL_get_ex_new_index(0, (void *)"netconn index", NULL, NULL, NULL);
582     if(conn_idx == -1) {
583         ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0));
584         return ERROR_OUTOFMEMORY;
585     }
586
587     pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify);
588
589     pCRYPTO_set_id_callback(ssl_thread_id);
590     num_ssl_locks = pCRYPTO_num_locks();
591     ssl_locks = heap_alloc(num_ssl_locks * sizeof(CRITICAL_SECTION));
592     if(!ssl_locks)
593         return ERROR_OUTOFMEMORY;
594
595     for(i = 0; i < num_ssl_locks; i++)
596     {
597         InitializeCriticalSection(&ssl_locks[i]);
598         ssl_locks[i].DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ssl_locks");
599     }
600     pCRYPTO_set_locking_callback(ssl_lock_callback);
601
602     return ERROR_SUCCESS;
603 #else
604     FIXME("can't use SSL, libcrypto not compiled in.\n");
605     return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
606 #endif
607 }
608 #else
609
610 static SecHandle cred_handle, compat_cred_handle;
611 static BOOL cred_handle_initialized, have_compat_cred_handle;
612
613 static CRITICAL_SECTION init_sechandle_cs;
614 static CRITICAL_SECTION_DEBUG init_sechandle_cs_debug = {
615     0, 0, &init_sechandle_cs,
616     { &init_sechandle_cs_debug.ProcessLocksList,
617       &init_sechandle_cs_debug.ProcessLocksList },
618     0, 0, { (DWORD_PTR)(__FILE__ ": init_sechandle_cs") }
619 };
620 static CRITICAL_SECTION init_sechandle_cs = { &init_sechandle_cs_debug, -1, 0, 0, 0, 0 };
621
622 static BOOL ensure_cred_handle(void)
623 {
624     SECURITY_STATUS res = SEC_E_OK;
625
626     EnterCriticalSection(&init_sechandle_cs);
627
628     if(!cred_handle_initialized) {
629         SCHANNEL_CRED cred = {SCHANNEL_CRED_VERSION};
630         SecPkgCred_SupportedProtocols prots;
631
632         res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred,
633                 NULL, NULL, &cred_handle, NULL);
634         if(res == SEC_E_OK) {
635             res = QueryCredentialsAttributesA(&cred_handle, SECPKG_ATTR_SUPPORTED_PROTOCOLS, &prots);
636             if(res != SEC_E_OK || (prots.grbitProtocol & SP_PROT_TLS1_1PLUS_CLIENT)) {
637                 cred.grbitEnabledProtocols = prots.grbitProtocol & ~SP_PROT_TLS1_1PLUS_CLIENT;
638                 res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred,
639                        NULL, NULL, &compat_cred_handle, NULL);
640                 have_compat_cred_handle = res == SEC_E_OK;
641             }
642         }
643
644         cred_handle_initialized = res == SEC_E_OK;
645     }
646
647     LeaveCriticalSection(&init_sechandle_cs);
648
649     if(res != SEC_E_OK) {
650         WARN("Failed: %08x\n", res);
651         return FALSE;
652     }
653
654     return TRUE;
655 }
656
657 #endif /* SONAME_LIBSSL */
658
659 static DWORD create_netconn_socket(server_t *server, netconn_t *netconn, DWORD timeout)
660 {
661     int result;
662     ULONG flag;
663
664     assert(server->addr_len);
665     result = netconn->socket = socket(server->addr.ss_family, SOCK_STREAM, 0);
666     if(result != -1) {
667         flag = 1;
668         ioctlsocket(netconn->socket, FIONBIO, &flag);
669         result = connect(netconn->socket, (struct sockaddr*)&server->addr, server->addr_len);
670         if(result == -1)
671         {
672             if (sock_get_error(errno) == WSAEINPROGRESS) {
673                 struct pollfd pfd;
674                 int res;
675
676                 pfd.fd = netconn->socket;
677                 pfd.events = POLLOUT;
678                 res = poll(&pfd, 1, timeout);
679                 if (!res)
680                 {
681                     closesocket(netconn->socket);
682                     return ERROR_INTERNET_CANNOT_CONNECT;
683                 }
684                 else if (res > 0)
685                 {
686                     int err;
687                     socklen_t len = sizeof(err);
688                     if (!getsockopt(netconn->socket, SOL_SOCKET, SO_ERROR, (void *)&err, &len) && !err)
689                         result = 0;
690                 }
691             }
692         }
693         if(result == -1)
694             closesocket(netconn->socket);
695         else {
696             flag = 0;
697             ioctlsocket(netconn->socket, FIONBIO, &flag);
698         }
699     }
700     if(result == -1)
701         return ERROR_INTERNET_CANNOT_CONNECT;
702
703 #ifdef TCP_NODELAY
704     flag = 1;
705     result = setsockopt(netconn->socket, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag));
706     if(result < 0)
707         WARN("setsockopt(TCP_NODELAY) failed\n");
708 #endif
709
710     return ERROR_SUCCESS;
711 }
712
713 DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL mask_errors, DWORD timeout, netconn_t **ret)
714 {
715     netconn_t *netconn;
716     int result;
717
718 #ifdef SONAME_LIBSSL
719     if(useSSL) {
720         DWORD res;
721
722         TRACE("using SSL connection\n");
723
724         EnterCriticalSection(&init_ssl_cs);
725         res = init_openssl();
726         LeaveCriticalSection(&init_ssl_cs);
727         if(res != ERROR_SUCCESS)
728             return res;
729     }
730 #endif
731
732     netconn = heap_alloc_zero(sizeof(*netconn));
733     if(!netconn)
734         return ERROR_OUTOFMEMORY;
735
736     netconn->socket = -1;
737     netconn->security_flags = security_flags | server->security_flags;
738     netconn->mask_errors = mask_errors;
739     list_init(&netconn->pool_entry);
740
741     result = create_netconn_socket(server, netconn, timeout);
742     if (result != ERROR_SUCCESS) {
743         heap_free(netconn);
744         return result;
745     }
746
747     server_addref(server);
748     netconn->server = server;
749     *ret = netconn;
750     return result;
751 }
752
753 void free_netconn(netconn_t *netconn)
754 {
755     server_release(netconn->server);
756
757     if (netconn->secure) {
758 #ifdef SONAME_LIBSSL
759         pSSL_shutdown(netconn->ssl_s);
760         pSSL_free(netconn->ssl_s);
761 #else
762         heap_free(netconn->ssl_buf);
763         netconn->ssl_buf = NULL;
764         DeleteSecurityContext(&netconn->ssl_ctx);
765 #endif
766     }
767
768     closesocket(netconn->socket);
769     heap_free(netconn);
770 }
771
772 void NETCON_unload(void)
773 {
774 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
775     if (OpenSSL_crypto_handle)
776     {
777         pERR_free_strings();
778         wine_dlclose(OpenSSL_crypto_handle, NULL, 0);
779     }
780     if (OpenSSL_ssl_handle)
781     {
782         if (ctx)
783             pSSL_CTX_free(ctx);
784         wine_dlclose(OpenSSL_ssl_handle, NULL, 0);
785     }
786     if (ssl_locks)
787     {
788         unsigned int i;
789         for (i = 0; i < num_ssl_locks; i++)
790         {
791             ssl_locks[i].DebugInfo->Spare[0] = 0;
792             DeleteCriticalSection(&ssl_locks[i]);
793         }
794         heap_free(ssl_locks);
795     }
796 #else
797     if(cred_handle_initialized)
798         FreeCredentialsHandle(&cred_handle);
799     if(have_compat_cred_handle)
800         FreeCredentialsHandle(&compat_cred_handle);
801     DeleteCriticalSection(&init_sechandle_cs);
802 #endif
803 }
804
805 /* translate a unix error code into a winsock one */
806 int sock_get_error( int err )
807 {
808 #if !defined(__MINGW32__) && !defined (_MSC_VER)
809     switch (err)
810     {
811         case EINTR:             return WSAEINTR;
812         case EBADF:             return WSAEBADF;
813         case EPERM:
814         case EACCES:            return WSAEACCES;
815         case EFAULT:            return WSAEFAULT;
816         case EINVAL:            return WSAEINVAL;
817         case EMFILE:            return WSAEMFILE;
818         case EWOULDBLOCK:       return WSAEWOULDBLOCK;
819         case EINPROGRESS:       return WSAEINPROGRESS;
820         case EALREADY:          return WSAEALREADY;
821         case ENOTSOCK:          return WSAENOTSOCK;
822         case EDESTADDRREQ:      return WSAEDESTADDRREQ;
823         case EMSGSIZE:          return WSAEMSGSIZE;
824         case EPROTOTYPE:        return WSAEPROTOTYPE;
825         case ENOPROTOOPT:       return WSAENOPROTOOPT;
826         case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
827         case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
828         case EOPNOTSUPP:        return WSAEOPNOTSUPP;
829         case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
830         case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
831         case EADDRINUSE:        return WSAEADDRINUSE;
832         case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
833         case ENETDOWN:          return WSAENETDOWN;
834         case ENETUNREACH:       return WSAENETUNREACH;
835         case ENETRESET:         return WSAENETRESET;
836         case ECONNABORTED:      return WSAECONNABORTED;
837         case EPIPE:
838         case ECONNRESET:        return WSAECONNRESET;
839         case ENOBUFS:           return WSAENOBUFS;
840         case EISCONN:           return WSAEISCONN;
841         case ENOTCONN:          return WSAENOTCONN;
842         case ESHUTDOWN:         return WSAESHUTDOWN;
843         case ETOOMANYREFS:      return WSAETOOMANYREFS;
844         case ETIMEDOUT:         return WSAETIMEDOUT;
845         case ECONNREFUSED:      return WSAECONNREFUSED;
846         case ELOOP:             return WSAELOOP;
847         case ENAMETOOLONG:      return WSAENAMETOOLONG;
848         case EHOSTDOWN:         return WSAEHOSTDOWN;
849         case EHOSTUNREACH:      return WSAEHOSTUNREACH;
850         case ENOTEMPTY:         return WSAENOTEMPTY;
851 #ifdef EPROCLIM
852         case EPROCLIM:          return WSAEPROCLIM;
853 #endif
854 #ifdef EUSERS
855         case EUSERS:            return WSAEUSERS;
856 #endif
857 #ifdef EDQUOT
858         case EDQUOT:            return WSAEDQUOT;
859 #endif
860 #ifdef ESTALE
861         case ESTALE:            return WSAESTALE;
862 #endif
863 #ifdef EREMOTE
864         case EREMOTE:           return WSAEREMOTE;
865 #endif
866     default: errno=err; perror("sock_set_error"); return WSAEFAULT;
867     }
868 #endif
869     return err;
870 }
871
872 static DWORD netcon_secure_connect_setup(netconn_t *connection, BOOL compat_mode)
873 {
874 #ifdef SONAME_LIBSSL
875     long tls_option;
876     void *ssl_s;
877     DWORD res;
878     int bits;
879
880     tls_option = get_tls_option();
881
882     if(compat_mode) {
883 #ifdef SSL_OP_NO_TLSv1_2
884         tls_option |= SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2;
885         pSSL_CTX_set_options(ctx,SSL_OP_NO_TLSv1_1|SSL_OP_NO_TLSv1_2);
886 #else
887         return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
888 #endif
889     }
890
891     ssl_s = pSSL_new(ctx);
892     if (!ssl_s)
893     {
894         ERR("SSL_new failed: %s\n",
895             pERR_error_string(pERR_get_error(), 0));
896         return ERROR_OUTOFMEMORY;
897     }
898
899     pSSL_set_options(ssl_s, tls_option);
900     if (!pSSL_set_fd(ssl_s, connection->socket))
901     {
902         ERR("SSL_set_fd failed: %s\n",
903             pERR_error_string(pERR_get_error(), 0));
904         res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
905         goto fail;
906     }
907
908     if (!pSSL_set_ex_data(ssl_s, conn_idx, connection))
909     {
910         ERR("SSL_set_ex_data failed: %s\n",
911             pERR_error_string(pERR_get_error(), 0));
912         res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
913         goto fail;
914     }
915     if (pSSL_connect(ssl_s) <= 0)
916     {
917         res = (DWORD_PTR)pSSL_get_ex_data(ssl_s, error_idx);
918         if (!res)
919             res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
920         ERR("SSL_connect failed: %d\n", res);
921         goto fail;
922     }
923
924     connection->ssl_s = ssl_s;
925 #else
926     SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}};
927     SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs};
928     SecHandle *cred = &cred_handle;
929     BYTE *read_buf;
930     SIZE_T read_buf_size = 2048;
931     ULONG attrs = 0;
932     CtxtHandle ctx;
933     SSIZE_T size;
934     int bits;
935     const CERT_CONTEXT *cert;
936     SECURITY_STATUS status;
937     DWORD res = ERROR_SUCCESS;
938
939     const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY
940         |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION;
941
942     if(!ensure_cred_handle())
943         return FALSE;
944
945     if(compat_mode) {
946         if(!have_compat_cred_handle)
947             return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
948         cred = &compat_cred_handle;
949     }
950
951     read_buf = heap_alloc(read_buf_size);
952     if(!read_buf)
953         return ERROR_OUTOFMEMORY;
954
955     status = InitializeSecurityContextW(cred, NULL, connection->server->name, isc_req_flags, 0, 0, NULL, 0,
956             &ctx, &out_desc, &attrs, NULL);
957
958     assert(status != SEC_E_OK);
959
960     while(status == SEC_I_CONTINUE_NEEDED || status == SEC_E_INCOMPLETE_MESSAGE) {
961         if(out_buf.cbBuffer) {
962             assert(status == SEC_I_CONTINUE_NEEDED);
963
964             TRACE("sending %u bytes\n", out_buf.cbBuffer);
965
966             size = send(connection->socket, out_buf.pvBuffer, out_buf.cbBuffer, 0);
967             if(size != out_buf.cbBuffer) {
968                 ERR("send failed\n");
969                 status = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
970                 break;
971             }
972
973             FreeContextBuffer(out_buf.pvBuffer);
974             out_buf.pvBuffer = NULL;
975             out_buf.cbBuffer = 0;
976         }
977
978         if(status == SEC_I_CONTINUE_NEEDED) {
979             assert(in_bufs[1].cbBuffer < read_buf_size);
980
981             memmove(read_buf, (BYTE*)in_bufs[0].pvBuffer+in_bufs[0].cbBuffer-in_bufs[1].cbBuffer, in_bufs[1].cbBuffer);
982             in_bufs[0].cbBuffer = in_bufs[1].cbBuffer;
983
984             in_bufs[1].BufferType = SECBUFFER_EMPTY;
985             in_bufs[1].cbBuffer = 0;
986             in_bufs[1].pvBuffer = NULL;
987         }
988
989         assert(in_bufs[0].BufferType == SECBUFFER_TOKEN);
990         assert(in_bufs[1].BufferType == SECBUFFER_EMPTY);
991
992         if(in_bufs[0].cbBuffer + 1024 > read_buf_size) {
993             BYTE *new_read_buf;
994
995             new_read_buf = heap_realloc(read_buf, read_buf_size + 1024);
996             if(!new_read_buf) {
997                 status = E_OUTOFMEMORY;
998                 break;
999             }
1000
1001             in_bufs[0].pvBuffer = read_buf = new_read_buf;
1002             read_buf_size += 1024;
1003         }
1004
1005         size = recv(connection->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0);
1006         if(size < 1) {
1007             WARN("recv error\n");
1008             res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
1009             break;
1010         }
1011
1012         TRACE("recv %lu bytes\n", size);
1013
1014         in_bufs[0].cbBuffer += size;
1015         in_bufs[0].pvBuffer = read_buf;
1016         status = InitializeSecurityContextW(cred, &ctx, connection->server->name,  isc_req_flags, 0, 0, &in_desc,
1017                 0, NULL, &out_desc, &attrs, NULL);
1018         TRACE("InitializeSecurityContext ret %08x\n", status);
1019
1020         if(status == SEC_E_OK) {
1021             if(in_bufs[1].BufferType == SECBUFFER_EXTRA)
1022                 FIXME("SECBUFFER_EXTRA not supported\n");
1023
1024             status = QueryContextAttributesW(&ctx, SECPKG_ATTR_STREAM_SIZES, &connection->ssl_sizes);
1025             if(status != SEC_E_OK) {
1026                 WARN("Could not get sizes\n");
1027                 break;
1028             }
1029
1030             status = QueryContextAttributesW(&ctx, SECPKG_ATTR_REMOTE_CERT_CONTEXT, (void*)&cert);
1031             if(status == SEC_E_OK) {
1032                 res = netconn_verify_cert(connection, cert, cert->hCertStore);
1033                 CertFreeCertificateContext(cert);
1034                 if(res != ERROR_SUCCESS) {
1035                     WARN("cert verify failed: %u\n", res);
1036                     break;
1037                 }
1038             }else {
1039                 WARN("Could not get cert\n");
1040                 break;
1041             }
1042
1043             connection->ssl_buf = heap_alloc(connection->ssl_sizes.cbHeader + connection->ssl_sizes.cbMaximumMessage
1044                     + connection->ssl_sizes.cbTrailer);
1045             if(!connection->ssl_buf) {
1046                 res = GetLastError();
1047                 break;
1048             }
1049         }
1050     }
1051
1052
1053     if(status != SEC_E_OK || res != ERROR_SUCCESS) {
1054         WARN("Failed to initialize security context failed: %08x\n", status);
1055         heap_free(connection->ssl_buf);
1056         connection->ssl_buf = NULL;
1057         DeleteSecurityContext(&ctx);
1058         return res ? res : ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
1059     }
1060
1061
1062     TRACE("established SSL connection\n");
1063     connection->ssl_ctx = ctx;
1064 #endif
1065
1066     connection->secure = TRUE;
1067     connection->security_flags |= SECURITY_FLAG_SECURE;
1068
1069     bits = NETCON_GetCipherStrength(connection);
1070     if (bits >= 128)
1071         connection->security_flags |= SECURITY_FLAG_STRENGTH_STRONG;
1072     else if (bits >= 56)
1073         connection->security_flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
1074     else
1075         connection->security_flags |= SECURITY_FLAG_STRENGTH_WEAK;
1076
1077     if(connection->mask_errors)
1078         connection->server->security_flags = connection->security_flags;
1079     return ERROR_SUCCESS;
1080
1081 #ifdef SONAME_LIBSSL
1082 fail:
1083     if (ssl_s)
1084     {
1085         pSSL_shutdown(ssl_s);
1086         pSSL_free(ssl_s);
1087     }
1088     return res;
1089 #endif
1090 }
1091
1092 /******************************************************************************
1093  * NETCON_secure_connect
1094  * Initiates a secure connection over an existing plaintext connection.
1095  */
1096 DWORD NETCON_secure_connect(netconn_t *connection, server_t *server)
1097 {
1098     DWORD res;
1099
1100     /* can't connect if we are already connected */
1101     if(connection->secure) {
1102         ERR("already connected\n");
1103         return ERROR_INTERNET_CANNOT_CONNECT;
1104     }
1105
1106     if(server != connection->server) {
1107         server_release(connection->server);
1108         server_addref(server);
1109         connection->server = server;
1110     }
1111
1112     /* connect with given TLS options */
1113     res = netcon_secure_connect_setup(connection, FALSE);
1114     if (res == ERROR_SUCCESS)
1115         return res;
1116
1117     /* FIXME: when got version alert and FIN from server */
1118     /* fallback to connect without TLSv1.1/TLSv1.2        */
1119     if (res == ERROR_INTERNET_SECURITY_CHANNEL_ERROR)
1120     {
1121         closesocket(connection->socket);
1122         res = create_netconn_socket(connection->server, connection, 500);
1123         if (res != ERROR_SUCCESS)
1124             return res;
1125         res = netcon_secure_connect_setup(connection, TRUE);
1126     }
1127     return res;
1128 }
1129
1130 /******************************************************************************
1131  * NETCON_send
1132  * Basically calls 'send()' unless we should use SSL
1133  * number of chars send is put in *sent
1134  */
1135 DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
1136                 int *sent /* out */)
1137 {
1138     if(!connection->secure)
1139     {
1140         *sent = send(connection->socket, msg, len, flags);
1141         if (*sent == -1)
1142             return sock_get_error(errno);
1143         return ERROR_SUCCESS;
1144     }
1145     else
1146     {
1147 #ifdef SONAME_LIBSSL
1148         if(!connection->secure) {
1149             FIXME("not connected\n");
1150             return ERROR_NOT_SUPPORTED;
1151         }
1152         if (flags)
1153             FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
1154         *sent = pSSL_write(connection->ssl_s, msg, len);
1155         if (*sent < 1 && len)
1156             return ERROR_INTERNET_CONNECTION_ABORTED;
1157         return ERROR_SUCCESS;
1158 #else
1159         FIXME("not supported on this platform\n");
1160         return ERROR_NOT_SUPPORTED;
1161 #endif
1162     }
1163 }
1164
1165 /******************************************************************************
1166  * NETCON_recv
1167  * Basically calls 'recv()' unless we should use SSL
1168  * number of chars received is put in *recvd
1169  */
1170 DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, int *recvd)
1171 {
1172     *recvd = 0;
1173     if (!len)
1174         return ERROR_SUCCESS;
1175
1176     if (!connection->secure)
1177     {
1178         *recvd = recv(connection->socket, buf, len, flags);
1179         return *recvd == -1 ? sock_get_error(errno) :  ERROR_SUCCESS;
1180     }
1181     else
1182     {
1183 #ifdef SONAME_LIBSSL
1184         if(!connection->secure) {
1185             FIXME("not connected\n");
1186             return ERROR_NOT_SUPPORTED;
1187         }
1188         *recvd = pSSL_read(connection->ssl_s, buf, len);
1189
1190         /* Check if EOF was received */
1191         if(!*recvd && (pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_ZERO_RETURN
1192                     || pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL))
1193             return ERROR_SUCCESS;
1194
1195         return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
1196 #else
1197         FIXME("not supported on this platform\n");
1198         return ERROR_NOT_SUPPORTED;
1199 #endif
1200     }
1201 }
1202
1203 /******************************************************************************
1204  * NETCON_query_data_available
1205  * Returns the number of bytes of peeked data plus the number of bytes of
1206  * queued, but unread data.
1207  */
1208 BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available)
1209 {
1210     *available = 0;
1211
1212     if(!connection->secure)
1213     {
1214 #ifdef FIONREAD
1215         ULONG unread;
1216         int retval = ioctlsocket(connection->socket, FIONREAD, &unread);
1217         if (!retval)
1218         {
1219             TRACE("%d bytes of queued, but unread data\n", unread);
1220             *available += unread;
1221         }
1222 #endif
1223     }
1224     else
1225     {
1226 #ifdef SONAME_LIBSSL
1227         *available = pSSL_pending(connection->ssl_s);
1228 #else
1229         FIXME("not supported on this platform\n");
1230         return FALSE;
1231 #endif
1232     }
1233     return TRUE;
1234 }
1235
1236 BOOL NETCON_is_alive(netconn_t *netconn)
1237 {
1238 #ifdef MSG_DONTWAIT
1239     ssize_t len;
1240     BYTE b;
1241
1242     len = recv(netconn->socket, &b, 1, MSG_PEEK|MSG_DONTWAIT);
1243     return len == 1 || (len == -1 && errno == EWOULDBLOCK);
1244 #elif defined(__MINGW32__) || defined(_MSC_VER)
1245     ULONG mode;
1246     int len;
1247     char b;
1248
1249     mode = 1;
1250     if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
1251         return FALSE;
1252
1253     len = recv(netconn->socket, &b, 1, MSG_PEEK);
1254
1255     mode = 0;
1256     if(!ioctlsocket(netconn->socket, FIONBIO, &mode))
1257         return FALSE;
1258
1259     return len == 1 || (len == -1 && errno == WSAEWOULDBLOCK);
1260 #else
1261     FIXME("not supported on this platform\n");
1262     return TRUE;
1263 #endif
1264 }
1265
1266 LPCVOID NETCON_GetCert(netconn_t *connection)
1267 {
1268 #ifdef SONAME_LIBSSL
1269     X509* cert;
1270     LPCVOID r = NULL;
1271
1272     if (!connection->secure)
1273         return NULL;
1274
1275     cert = pSSL_get_peer_certificate(connection->ssl_s);
1276     r = X509_to_cert_context(cert);
1277     return r;
1278 #else
1279     FIXME("not supported on this platform\n");
1280     return NULL;
1281 #endif
1282 }
1283
1284 int NETCON_GetCipherStrength(netconn_t *connection)
1285 {
1286 #ifdef SONAME_LIBSSL
1287 #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090707f)
1288     const SSL_CIPHER *cipher;
1289 #else
1290     SSL_CIPHER *cipher;
1291 #endif
1292     int bits = 0;
1293
1294     if (!connection->secure)
1295         return 0;
1296     cipher = pSSL_get_current_cipher(connection->ssl_s);
1297     if (!cipher)
1298         return 0;
1299     pSSL_CIPHER_get_bits(cipher, &bits);
1300     return bits;
1301 #else
1302     SecPkgContext_ConnectionInfo conn_info;
1303     SECURITY_STATUS res;
1304
1305     if (!connection->secure)
1306         return 0;
1307
1308     res = QueryContextAttributesW(&connection->ssl_ctx, SECPKG_ATTR_CONNECTION_INFO, (void*)&conn_info);
1309     if(res != SEC_E_OK)
1310         WARN("QueryContextAttributesW failed: %08x\n", res);
1311     return res == SEC_E_OK ? conn_info.dwCipherStrength : 0;
1312 #endif
1313 }
1314
1315 DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value)
1316 {
1317     int result;
1318     struct timeval tv;
1319
1320     /* value is in milliseconds, convert to struct timeval */
1321     if (value == INFINITE)
1322     {
1323         tv.tv_sec = 0;
1324         tv.tv_usec = 0;
1325     }
1326     else
1327     {
1328         tv.tv_sec = value / 1000;
1329         tv.tv_usec = (value % 1000) * 1000;
1330     }
1331     result = setsockopt(connection->socket, SOL_SOCKET,
1332                         send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv,
1333                         sizeof(tv));
1334     if (result == -1)
1335     {
1336         WARN("setsockopt failed (%s)\n", strerror(errno));
1337         return sock_get_error(errno);
1338     }
1339     return ERROR_SUCCESS;
1340 }