netconnection.c 31.2 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
/*
 * Wininet - networking layer. Uses unix sockets or OpenSSL.
 *
 * Copyright 2002 TransGaming Technologies Inc.
 *
 * David Hammerton
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * 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 24 25
 */

#include "config.h"
#include "wine/port.h"

26 27
#define NONAMELESSUNION

28 29 30 31
#if defined(__MINGW32__) || defined (_MSC_VER)
#include <ws2tcpip.h>
#endif

32
#include <sys/types.h>
33 34 35 36 37 38
#ifdef HAVE_POLL_H
#include <poll.h>
#endif
#ifdef HAVE_SYS_POLL_H
# include <sys/poll.h>
#endif
39 40 41
#ifdef HAVE_SYS_TIME_H
# include <sys/time.h>
#endif
42 43 44
#ifdef HAVE_SYS_SOCKET_H
# include <sys/socket.h>
#endif
45 46 47
#ifdef HAVE_SYS_FILIO_H
# include <sys/filio.h>
#endif
48 49 50
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
51 52 53
#ifdef HAVE_SYS_IOCTL_H
# include <sys/ioctl.h>
#endif
54 55 56 57 58 59 60
#include <time.h>
#ifdef HAVE_NETDB_H
# include <netdb.h>
#endif
#ifdef HAVE_NETINET_IN_H
# include <netinet/in.h>
#endif
61 62 63
#ifdef HAVE_NETINET_TCP_H
# include <netinet/tcp.h>
#endif
64 65
#ifdef HAVE_OPENSSL_SSL_H
# include <openssl/ssl.h>
66
# include <openssl/opensslv.h>
67 68 69 70
#undef FAR
#undef DSA
#endif

71
#include <stdarg.h>
72 73
#include <stdlib.h>
#include <string.h>
74 75
#include <stdio.h>
#include <errno.h>
76
#include <assert.h>
77 78 79 80 81 82 83

#include "wine/library.h"
#include "windef.h"
#include "winbase.h"
#include "wininet.h"
#include "winerror.h"

84 85 86
#include "wine/debug.h"
#include "internet.h"

87 88 89 90 91
/* To avoid conflicts with the Unix socket headers. we only need it for
 * the error codes anyway. */
#define USE_WS_PREFIX
#include "winsock2.h"

92 93 94 95 96 97
#define RESPONSE_TIMEOUT        30            /* FROM internet.c */


WINE_DEFAULT_DEBUG_CHANNEL(wininet);

/* FIXME!!!!!!
98
 *    This should use winsock - To use winsock the functions will have to change a bit
99 100 101 102
 *        as they are designed for unix sockets.
 *    SSL stuff should use crypt32.dll
 */

103
#ifdef SONAME_LIBSSL
104 105

#include <openssl/err.h>
106 107 108 109

static void *OpenSSL_ssl_handle;
static void *OpenSSL_crypto_handle;

110
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10000000)
111 112
static const SSL_METHOD *meth;
#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 120

#define MAKE_FUNCPTR(f) static typeof(f) * p##f

121
/* OpenSSL functions that we use */
122 123 124
MAKE_FUNCPTR(SSL_library_init);
MAKE_FUNCPTR(SSL_load_error_strings);
MAKE_FUNCPTR(SSLv23_method);
125
MAKE_FUNCPTR(SSL_CTX_free);
126 127
MAKE_FUNCPTR(SSL_CTX_new);
MAKE_FUNCPTR(SSL_new);
128 129
MAKE_FUNCPTR(SSL_free);
MAKE_FUNCPTR(SSL_set_fd);
130
MAKE_FUNCPTR(SSL_connect);
131
MAKE_FUNCPTR(SSL_shutdown);
132 133
MAKE_FUNCPTR(SSL_write);
MAKE_FUNCPTR(SSL_read);
134
MAKE_FUNCPTR(SSL_pending);
135
MAKE_FUNCPTR(SSL_get_error);
136
MAKE_FUNCPTR(SSL_get_ex_new_index);
137
MAKE_FUNCPTR(SSL_get_ex_data);
138
MAKE_FUNCPTR(SSL_set_ex_data);
139
MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx);
140
MAKE_FUNCPTR(SSL_get_peer_certificate);
141 142
MAKE_FUNCPTR(SSL_CTX_get_timeout);
MAKE_FUNCPTR(SSL_CTX_set_timeout);
143
MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths);
144
MAKE_FUNCPTR(SSL_CTX_set_verify);
145 146
MAKE_FUNCPTR(SSL_get_current_cipher);
MAKE_FUNCPTR(SSL_CIPHER_get_bits);
147 148 149

/* OpenSSL's libcrypto functions that we use */
MAKE_FUNCPTR(BIO_new_fp);
150 151 152
MAKE_FUNCPTR(CRYPTO_num_locks);
MAKE_FUNCPTR(CRYPTO_set_id_callback);
MAKE_FUNCPTR(CRYPTO_set_locking_callback);
153
MAKE_FUNCPTR(ERR_free_strings);
154 155
MAKE_FUNCPTR(ERR_get_error);
MAKE_FUNCPTR(ERR_error_string);
156
MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data);
157
MAKE_FUNCPTR(X509_STORE_CTX_get_chain);
158
MAKE_FUNCPTR(i2d_X509);
159 160
MAKE_FUNCPTR(sk_num);
MAKE_FUNCPTR(sk_value);
161 162
#undef MAKE_FUNCPTR

163
static CRITICAL_SECTION *ssl_locks;
164
static unsigned int num_ssl_locks;
165 166 167 168 169 170 171 172 173 174 175 176 177 178

static unsigned long ssl_thread_id(void)
{
    return GetCurrentThreadId();
}

static void ssl_lock_callback(int mode, int type, const char *file, int line)
{
    if (mode & CRYPTO_LOCK)
        EnterCriticalSection(&ssl_locks[type]);
    else
        LeaveCriticalSection(&ssl_locks[type]);
}

179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195
static PCCERT_CONTEXT X509_to_cert_context(X509 *cert)
{
    unsigned char* buffer,*p;
    INT len;
    BOOL malloced = FALSE;
    PCCERT_CONTEXT ret;

    p = NULL;
    len = pi2d_X509(cert,&p);
    /*
     * SSL 0.9.7 and above malloc the buffer if it is null.
     * however earlier version do not and so we would need to alloc the buffer.
     *
     * see the i2d_X509 man page for more details.
     */
    if (!p)
    {
196
        buffer = heap_alloc(len);
197 198 199 200 201 202 203 204 205 206 207 208 209 210
        p = buffer;
        len = pi2d_X509(cert,&p);
    }
    else
    {
        buffer = p;
        malloced = TRUE;
    }

    ret = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len);

    if (malloced)
        free(buffer);
    else
211
        heap_free(buffer);
212 213 214 215

    return ret;
}

216
static DWORD netconn_verify_cert(netconn_t *conn, PCCERT_CONTEXT cert, HCERTSTORE store)
217 218 219 220 221 222
{
    BOOL ret;
    CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } };
    PCCERT_CHAIN_CONTEXT chain;
    char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH;
    char *server_auth[] = { oid_server_auth };
223 224 225 226 227 228 229 230 231 232 233 234
    DWORD err = ERROR_SUCCESS, chainFlags = 0, errors;

    static const DWORD supportedErrors =
        CERT_TRUST_IS_NOT_TIME_VALID |
        CERT_TRUST_IS_UNTRUSTED_ROOT |
        CERT_TRUST_IS_PARTIAL_CHAIN |
        CERT_TRUST_IS_OFFLINE_REVOCATION |
        CERT_TRUST_REVOCATION_STATUS_UNKNOWN |
        CERT_TRUST_IS_REVOKED |
        CERT_TRUST_IS_NOT_VALID_FOR_USAGE;

    TRACE("verifying %s\n", debugstr_w(conn->server->name));
235 236 237

    chainPara.RequestedUsage.Usage.cUsageIdentifier = 1;
    chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth;
238
    if (!(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION))
239
        chainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT;
240 241 242 243 244 245 246 247

    if (!(ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, chainFlags, NULL, &chain))) {
        TRACE("failed\n");
        return GetLastError();
    }

    errors = chain->TrustStatus.dwErrorStatus;

248 249 250 251 252 253 254 255 256 257
    do {
        /* This seems strange, but that's what tests show */
        if(errors & (CERT_TRUST_IS_PARTIAL_CHAIN|CERT_TRUST_IS_OFFLINE_REVOCATION)) {
            WARN("ERROR_INTERNET_SEC_CERT_REV_FAILED\n");
            err = ERROR_INTERNET_SEC_CERT_REV_FAILED;
            if(conn->mask_errors)
                conn->security_flags |= _SECURITY_FLAG_CERT_REV_FAILED;
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION))
                break;
        }
258

259 260 261 262 263 264 265 266
        if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) {
            WARN("error status %x\n", chain->TrustStatus.dwErrorStatus & ~supportedErrors);
            err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
            errors &= supportedErrors;
            if(!conn->mask_errors)
                break;
            WARN("unknown error flags\n");
        }
267

268 269 270 271 272 273 274 275 276 277
        if(errors & CERT_TRUST_IS_NOT_TIME_VALID) {
            WARN("CERT_TRUST_IS_NOT_TIME_VALID\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_DATE_INVALID;
                if(!conn->mask_errors)
                    break;
                conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_DATE;
            }
            errors &= ~CERT_TRUST_IS_NOT_TIME_VALID;
        }
278

279 280 281 282 283 284 285 286 287
        if(errors & CERT_TRUST_IS_UNTRUSTED_ROOT) {
            WARN("CERT_TRUST_IS_UNTRUSTED_ROOT\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_INVALID_CA;
                if(!conn->mask_errors)
                    break;
                conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CA;
            }
            errors &= ~CERT_TRUST_IS_UNTRUSTED_ROOT;
288
        }
289 290 291 292 293 294 295

        if(errors & CERT_TRUST_IS_PARTIAL_CHAIN) {
            WARN("CERT_TRUST_IS_PARTIAL_CHAIN\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_INVALID_CA;
                if(!conn->mask_errors)
                    break;
296
                conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CA;
297 298
            }
            errors &= ~CERT_TRUST_IS_PARTIAL_CHAIN;
299
        }
300

301 302 303 304 305 306 307 308 309 310
        if(errors & (CERT_TRUST_IS_OFFLINE_REVOCATION | CERT_TRUST_REVOCATION_STATUS_UNKNOWN)) {
            WARN("CERT_TRUST_IS_OFFLINE_REVOCATION | CERT_TRUST_REVOCATION_STATUS_UNKNOWN\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_NO_REV;
                if(!conn->mask_errors)
                    break;
                conn->security_flags |= _SECURITY_FLAG_CERT_REV_FAILED;
            }
            errors &= ~(CERT_TRUST_IS_OFFLINE_REVOCATION | CERT_TRUST_REVOCATION_STATUS_UNKNOWN);
        }
311

312 313 314 315 316 317 318 319 320 321
        if(errors & CERT_TRUST_IS_REVOKED) {
            WARN("CERT_TRUST_IS_REVOKED\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_REVOKED;
                if(!conn->mask_errors)
                    break;
                WARN("TRUST_IS_OFFLINE_REVOCATION | CERT_TRUST_REVOCATION_STATUS_UNKNOWN, unknown error flags\n");
            }
            errors &= ~CERT_TRUST_IS_REVOKED;
        }
322

323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338
        if(errors & CERT_TRUST_IS_NOT_VALID_FOR_USAGE) {
            WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE\n");
            if(!(conn->security_flags & SECURITY_FLAG_IGNORE_WRONG_USAGE)) {
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
                if(!conn->mask_errors)
                    break;
                WARN("CERT_TRUST_IS_NOT_VALID_FOR_USAGE, unknown error flags\n");
            }
            errors &= ~CERT_TRUST_IS_NOT_VALID_FOR_USAGE;
        }

        if(err == ERROR_INTERNET_SEC_CERT_REV_FAILED) {
            assert(conn->security_flags & SECURITY_FLAG_IGNORE_REVOCATION);
            err = ERROR_SUCCESS;
        }
    }while(0);
339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359

    if(!err || conn->mask_errors) {
        CERT_CHAIN_POLICY_PARA policyPara;
        SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara;
        CERT_CHAIN_POLICY_STATUS policyStatus;
        CERT_CHAIN_CONTEXT chainCopy;

        /* Clear chain->TrustStatus.dwErrorStatus so
         * CertVerifyCertificateChainPolicy will verify additional checks
         * rather than stopping with an existing, ignored error.
         */
        memcpy(&chainCopy, chain, sizeof(chainCopy));
        chainCopy.TrustStatus.dwErrorStatus = 0;
        sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara);
        sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER;
        sslExtraPolicyPara.pwszServerName = conn->server->name;
        sslExtraPolicyPara.fdwChecks = conn->security_flags;
        policyPara.cbSize = sizeof(policyPara);
        policyPara.dwFlags = 0;
        policyPara.pvExtraPolicyPara = &sslExtraPolicyPara;
        ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL,
360
                &chainCopy, &policyPara, &policyStatus);
361 362 363 364 365
        /* Any error in the policy status indicates that the
         * policy couldn't be verified.
         */
        if(ret) {
            if(policyStatus.dwError == CERT_E_CN_NO_MATCH) {
366
                WARN("CERT_E_CN_NO_MATCH\n");
367 368
                if(conn->mask_errors)
                    conn->security_flags |= _SECURITY_FLAG_CERT_INVALID_CN;
369
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_CERT_CN_INVALID;
370
            }else if(policyStatus.dwError) {
371
                WARN("policyStatus.dwError %x\n", policyStatus.dwError);
372 373
                if(conn->mask_errors)
                    WARN("unknown error flags for policy status %x\n", policyStatus.dwError);
374
                err = conn->mask_errors && err ? ERROR_INTERNET_SEC_CERT_ERRORS : ERROR_INTERNET_SEC_INVALID_CERT;
375
            }
376 377
        }else {
            err = GetLastError();
378 379
        }
    }
380 381 382

    if(err) {
        WARN("failed %u\n", err);
383 384 385 386 387
        CertFreeCertificateChain(chain);
        if(conn->server->cert_chain) {
            CertFreeCertificateChain(conn->server->cert_chain);
            conn->server->cert_chain = NULL;
        }
388
        if(conn->mask_errors)
389
            conn->server->security_flags |= conn->security_flags & _SECURITY_ERROR_FLAGS_MASK;
390 391 392
        return err;
    }

393 394 395 396 397
    /* FIXME: Reuse cached chain */
    if(conn->server->cert_chain)
        CertFreeCertificateChain(chain);
    else
        conn->server->cert_chain = chain;
398
    return ERROR_SUCCESS;
399 400
}

401 402 403
static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx)
{
    SSL *ssl;
404
    BOOL ret = FALSE;
405 406
    HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0,
        CERT_STORE_CREATE_NEW_FLAG, NULL);
407
    netconn_t *conn;
408 409 410

    ssl = pX509_STORE_CTX_get_ex_data(ctx,
        pSSL_get_ex_data_X509_STORE_CTX_idx());
411
    conn = pSSL_get_ex_data(ssl, conn_idx);
412
    if (store)
413
    {
414 415 416
        X509 *cert;
        int i;
        PCCERT_CONTEXT endCert = NULL;
417
        struct stack_st *chain = (struct stack_st *)pX509_STORE_CTX_get_chain( ctx );
418

419
        ret = TRUE;
420
        for (i = 0; ret && i < psk_num(chain); i++)
421
        {
422
            PCCERT_CONTEXT context;
423

424
            cert = (X509 *)psk_value(chain, i);
425
            if ((context = X509_to_cert_context(cert)))
426
            {
427 428
                ret = CertAddCertificateContextToStore(store, context,
                        CERT_STORE_ADD_ALWAYS, i ? NULL : &endCert);
429
                CertFreeCertificateContext(context);
430
            }
431 432 433 434
        }
        if (!endCert) ret = FALSE;
        if (ret)
        {
435
            DWORD_PTR err = netconn_verify_cert(conn, endCert, store);
436

437 438 439 440
            if (err)
            {
                pSSL_set_ex_data(ssl, error_idx, (void *)err);
                ret = FALSE;
441
            }
442
        }
443 444 445
        CertFreeCertificateContext(endCert);
        CertCloseStore(store, 0);
    }
446
    return ret;
447 448
}

449 450
#endif

451 452 453 454 455 456 457 458 459 460 461
static CRITICAL_SECTION init_ssl_cs;
static CRITICAL_SECTION_DEBUG init_ssl_cs_debug =
{
    0, 0, &init_ssl_cs,
    { &init_ssl_cs_debug.ProcessLocksList,
      &init_ssl_cs_debug.ProcessLocksList },
    0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") }
};
static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 };

static DWORD init_openssl(void)
462
{
463
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
464
    int i;
465

466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481
    if(OpenSSL_ssl_handle)
        return ERROR_SUCCESS;

    OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0);
    if(!OpenSSL_ssl_handle) {
        ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL);
        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
    }

    OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0);
    if(!OpenSSL_crypto_handle) {
        ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO);
        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
    }

    /* mmm nice ugly macroness */
482 483
#define DYNSSL(x) \
    p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \
484
    if (!p##x) { \
485
        ERR("failed to load symbol %s\n", #x); \
486
        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
487 488
    }

489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513
    DYNSSL(SSL_library_init);
    DYNSSL(SSL_load_error_strings);
    DYNSSL(SSLv23_method);
    DYNSSL(SSL_CTX_free);
    DYNSSL(SSL_CTX_new);
    DYNSSL(SSL_new);
    DYNSSL(SSL_free);
    DYNSSL(SSL_set_fd);
    DYNSSL(SSL_connect);
    DYNSSL(SSL_shutdown);
    DYNSSL(SSL_write);
    DYNSSL(SSL_read);
    DYNSSL(SSL_pending);
    DYNSSL(SSL_get_error);
    DYNSSL(SSL_get_ex_new_index);
    DYNSSL(SSL_get_ex_data);
    DYNSSL(SSL_set_ex_data);
    DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx);
    DYNSSL(SSL_get_peer_certificate);
    DYNSSL(SSL_CTX_get_timeout);
    DYNSSL(SSL_CTX_set_timeout);
    DYNSSL(SSL_CTX_set_default_verify_paths);
    DYNSSL(SSL_CTX_set_verify);
    DYNSSL(SSL_get_current_cipher);
    DYNSSL(SSL_CIPHER_get_bits);
514 515 516 517
#undef DYNSSL

#define DYNCRYPTO(x) \
    p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \
518
    if (!p##x) { \
519
        ERR("failed to load symbol %s\n", #x); \
520
        return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \
521
    }
522 523 524 525 526 527 528 529 530 531 532 533 534

    DYNCRYPTO(BIO_new_fp);
    DYNCRYPTO(CRYPTO_num_locks);
    DYNCRYPTO(CRYPTO_set_id_callback);
    DYNCRYPTO(CRYPTO_set_locking_callback);
    DYNCRYPTO(ERR_free_strings);
    DYNCRYPTO(ERR_get_error);
    DYNCRYPTO(ERR_error_string);
    DYNCRYPTO(X509_STORE_CTX_get_ex_data);
    DYNCRYPTO(X509_STORE_CTX_get_chain);
    DYNCRYPTO(i2d_X509);
    DYNCRYPTO(sk_num);
    DYNCRYPTO(sk_value);
535 536
#undef DYNCRYPTO

537 538 539
    pSSL_library_init();
    pSSL_load_error_strings();
    pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */
540

541 542 543 544 545 546 547
    meth = pSSLv23_method();
    ctx = pSSL_CTX_new(meth);
    if(!pSSL_CTX_set_default_verify_paths(ctx)) {
        ERR("SSL_CTX_set_default_verify_paths failed: %s\n",
            pERR_error_string(pERR_get_error(), 0));
        return ERROR_OUTOFMEMORY;
    }
548

549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
    error_idx = pSSL_get_ex_new_index(0, (void *)"error index", NULL, NULL, NULL);
    if(error_idx == -1) {
        ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0));
        return ERROR_OUTOFMEMORY;
    }

    conn_idx = pSSL_get_ex_new_index(0, (void *)"netconn index", NULL, NULL, NULL);
    if(conn_idx == -1) {
        ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0));
        return ERROR_OUTOFMEMORY;
    }

    pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify);

    pCRYPTO_set_id_callback(ssl_thread_id);
    num_ssl_locks = pCRYPTO_num_locks();
565
    ssl_locks = heap_alloc(num_ssl_locks * sizeof(CRITICAL_SECTION));
566 567 568 569
    if(!ssl_locks)
        return ERROR_OUTOFMEMORY;

    for(i = 0; i < num_ssl_locks; i++)
570
    {
571
        InitializeCriticalSection(&ssl_locks[i]);
572 573
        ssl_locks[i].DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ssl_locks");
    }
574 575 576
    pCRYPTO_set_locking_callback(ssl_lock_callback);

    return ERROR_SUCCESS;
577
#else
578 579
    FIXME("can't use SSL, not compiled in.\n");
    return ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
580
#endif
581 582
}

583
DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, BOOL mask_errors, DWORD timeout, netconn_t **ret)
584
{
585
    netconn_t *netconn;
586
    int result, flag;
587

588 589
    if(useSSL) {
        DWORD res;
590 591 592 593 594 595

        TRACE("using SSL connection\n");

        EnterCriticalSection(&init_ssl_cs);
        res = init_openssl();
        LeaveCriticalSection(&init_ssl_cs);
596 597
        if(res != ERROR_SUCCESS)
            return res;
598
    }
599

600 601 602 603 604 605
    netconn = heap_alloc_zero(sizeof(*netconn));
    if(!netconn)
        return ERROR_OUTOFMEMORY;

    netconn->useSSL = useSSL;
    netconn->socketFD = -1;
606
    netconn->security_flags = security_flags | server->security_flags;
607
    netconn->mask_errors = mask_errors;
608 609 610 611 612
    list_init(&netconn->pool_entry);

    assert(server->addr_len);
    result = netconn->socketFD = socket(server->addr.ss_family, SOCK_STREAM, 0);
    if(result != -1) {
613 614
        flag = 1;
        ioctlsocket(netconn->socketFD, FIONBIO, &flag);
615
        result = connect(netconn->socketFD, (struct sockaddr*)&server->addr, server->addr_len);
616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639
        if(result == -1)
        {
            if (sock_get_error(errno) == WSAEINPROGRESS) {
                struct pollfd pfd;
                int res;

                pfd.fd = netconn->socketFD;
                pfd.events = POLLOUT;
                res = poll(&pfd, 1, timeout);
                if (!res)
                {
                    closesocket(netconn->socketFD);
                    heap_free(netconn);
                    return ERROR_INTERNET_CANNOT_CONNECT;
                }
                else if (res > 0)
                {
                    int err;
                    socklen_t len = sizeof(err);
                    if (!getsockopt(netconn->socketFD, SOL_SOCKET, SO_ERROR, &err, &len) && !err)
                        result = 0;
                }
            }
        }
640 641
        if(result == -1)
            closesocket(netconn->socketFD);
642 643 644 645
        else {
            flag = 0;
            ioctlsocket(netconn->socketFD, FIONBIO, &flag);
        }
646 647 648 649 650 651
    }
    if(result == -1) {
        heap_free(netconn);
        return sock_get_error(errno);
    }

652 653 654 655 656 657 658
#ifdef TCP_NODELAY
    flag = 1;
    result = setsockopt(netconn->socketFD, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag));
    if(result < 0)
        WARN("setsockopt(TCP_NODELAY) failed\n");
#endif

659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678
    server_addref(server);
    netconn->server = server;

    *ret = netconn;
    return ERROR_SUCCESS;
}

void free_netconn(netconn_t *netconn)
{
    server_release(netconn->server);

#ifdef SONAME_LIBSSL
    if (netconn->ssl_s) {
        pSSL_shutdown(netconn->ssl_s);
        pSSL_free(netconn->ssl_s);
    }
#endif

    closesocket(netconn->socketFD);
    heap_free(netconn);
679 680
}

681 682 683 684
void NETCON_unload(void)
{
#if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO)
    if (OpenSSL_crypto_handle)
685
    {
686
        pERR_free_strings();
687
        wine_dlclose(OpenSSL_crypto_handle, NULL, 0);
688
    }
689 690 691 692 693 694
    if (OpenSSL_ssl_handle)
    {
        if (ctx)
            pSSL_CTX_free(ctx);
        wine_dlclose(OpenSSL_ssl_handle, NULL, 0);
    }
695 696 697
    if (ssl_locks)
    {
        int i;
698 699 700 701 702
        for (i = 0; i < num_ssl_locks; i++)
        {
            ssl_locks[i].DebugInfo->Spare[0] = 0;
            DeleteCriticalSection(&ssl_locks[i]);
        }
703
        heap_free(ssl_locks);
704
    }
705 706 707
#endif
}

708
/* translate a unix error code into a winsock one */
709
int sock_get_error( int err )
710
{
711
#if !defined(__MINGW32__) && !defined (_MSC_VER)
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770
    switch (err)
    {
        case EINTR:             return WSAEINTR;
        case EBADF:             return WSAEBADF;
        case EPERM:
        case EACCES:            return WSAEACCES;
        case EFAULT:            return WSAEFAULT;
        case EINVAL:            return WSAEINVAL;
        case EMFILE:            return WSAEMFILE;
        case EWOULDBLOCK:       return WSAEWOULDBLOCK;
        case EINPROGRESS:       return WSAEINPROGRESS;
        case EALREADY:          return WSAEALREADY;
        case ENOTSOCK:          return WSAENOTSOCK;
        case EDESTADDRREQ:      return WSAEDESTADDRREQ;
        case EMSGSIZE:          return WSAEMSGSIZE;
        case EPROTOTYPE:        return WSAEPROTOTYPE;
        case ENOPROTOOPT:       return WSAENOPROTOOPT;
        case EPROTONOSUPPORT:   return WSAEPROTONOSUPPORT;
        case ESOCKTNOSUPPORT:   return WSAESOCKTNOSUPPORT;
        case EOPNOTSUPP:        return WSAEOPNOTSUPP;
        case EPFNOSUPPORT:      return WSAEPFNOSUPPORT;
        case EAFNOSUPPORT:      return WSAEAFNOSUPPORT;
        case EADDRINUSE:        return WSAEADDRINUSE;
        case EADDRNOTAVAIL:     return WSAEADDRNOTAVAIL;
        case ENETDOWN:          return WSAENETDOWN;
        case ENETUNREACH:       return WSAENETUNREACH;
        case ENETRESET:         return WSAENETRESET;
        case ECONNABORTED:      return WSAECONNABORTED;
        case EPIPE:
        case ECONNRESET:        return WSAECONNRESET;
        case ENOBUFS:           return WSAENOBUFS;
        case EISCONN:           return WSAEISCONN;
        case ENOTCONN:          return WSAENOTCONN;
        case ESHUTDOWN:         return WSAESHUTDOWN;
        case ETOOMANYREFS:      return WSAETOOMANYREFS;
        case ETIMEDOUT:         return WSAETIMEDOUT;
        case ECONNREFUSED:      return WSAECONNREFUSED;
        case ELOOP:             return WSAELOOP;
        case ENAMETOOLONG:      return WSAENAMETOOLONG;
        case EHOSTDOWN:         return WSAEHOSTDOWN;
        case EHOSTUNREACH:      return WSAEHOSTUNREACH;
        case ENOTEMPTY:         return WSAENOTEMPTY;
#ifdef EPROCLIM
        case EPROCLIM:          return WSAEPROCLIM;
#endif
#ifdef EUSERS
        case EUSERS:            return WSAEUSERS;
#endif
#ifdef EDQUOT
        case EDQUOT:            return WSAEDQUOT;
#endif
#ifdef ESTALE
        case ESTALE:            return WSAESTALE;
#endif
#ifdef EREMOTE
        case EREMOTE:           return WSAEREMOTE;
#endif
    default: errno=err; perror("sock_set_error"); return WSAEFAULT;
    }
771 772
#endif
    return err;
773 774
}

775 776 777 778
/******************************************************************************
 * NETCON_secure_connect
 * Initiates a secure connection over an existing plaintext connection.
 */
779
DWORD NETCON_secure_connect(netconn_t *connection)
780
{
781
    DWORD res = ERROR_NOT_SUPPORTED;
782
#ifdef SONAME_LIBSSL
783
    void *ssl_s;
784
    int bits;
785

786
    /* can't connect if we are already connected */
787
    if (connection->ssl_s)
788 789
    {
        ERR("already connected\n");
790
        return ERROR_INTERNET_CANNOT_CONNECT;
791
    }
792

793 794
    ssl_s = pSSL_new(ctx);
    if (!ssl_s)
795 796 797
    {
        ERR("SSL_new failed: %s\n",
            pERR_error_string(pERR_get_error(), 0));
798
        return ERROR_OUTOFMEMORY;
799 800
    }

801
    if (!pSSL_set_fd(ssl_s, connection->socketFD))
802 803 804
    {
        ERR("SSL_set_fd failed: %s\n",
            pERR_error_string(pERR_get_error(), 0));
805
        res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
806 807
        goto fail;
    }
808

809
    if (!pSSL_set_ex_data(ssl_s, conn_idx, connection))
810 811 812 813 814 815
    {
        ERR("SSL_set_ex_data failed: %s\n",
            pERR_error_string(pERR_get_error(), 0));
        res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
        goto fail;
    }
816
    if (pSSL_connect(ssl_s) <= 0)
817
    {
818
        res = (DWORD_PTR)pSSL_get_ex_data(ssl_s, error_idx);
819 820 821 822 823
        if (!res)
            res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR;
        ERR("SSL_connect failed: %d\n", res);
        goto fail;
    }
824

825
    connection->ssl_s = ssl_s;
826

827 828 829 830 831 832 833
    bits = NETCON_GetCipherStrength(connection);
    if (bits >= 128)
        connection->security_flags |= SECURITY_FLAG_STRENGTH_STRONG;
    else if (bits >= 56)
        connection->security_flags |= SECURITY_FLAG_STRENGTH_MEDIUM;
    else
        connection->security_flags |= SECURITY_FLAG_STRENGTH_WEAK;
834
    connection->security_flags |= SECURITY_FLAG_SECURE;
835

836 837
    if(connection->mask_errors)
        connection->server->security_flags = connection->security_flags;
838
    return ERROR_SUCCESS;
839 840

fail:
841
    if (ssl_s)
842
    {
843 844
        pSSL_shutdown(ssl_s);
        pSSL_free(ssl_s);
845
    }
846
#endif
847
    return res;
848 849
}

850 851 852 853 854
/******************************************************************************
 * NETCON_send
 * Basically calls 'send()' unless we should use SSL
 * number of chars send is put in *sent
 */
855
DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags,
856 857 858 859 860 861
		int *sent /* out */)
{
    if (!connection->useSSL)
    {
	*sent = send(connection->socketFD, msg, len, flags);
	if (*sent == -1)
862 863
	    return sock_get_error(errno);
        return ERROR_SUCCESS;
864 865 866
    }
    else
    {
867
#ifdef SONAME_LIBSSL
868 869 870 871
        if(!connection->ssl_s) {
            FIXME("not connected\n");
            return ERROR_NOT_SUPPORTED;
        }
872 873 874 875
	if (flags)
            FIXME("SSL_write doesn't support any flags (%08x)\n", flags);
	*sent = pSSL_write(connection->ssl_s, msg, len);
	if (*sent < 1 && len)
876 877
	    return ERROR_INTERNET_CONNECTION_ABORTED;
        return ERROR_SUCCESS;
878
#else
879
	return ERROR_NOT_SUPPORTED;
880 881 882 883 884 885 886
#endif
    }
}

/******************************************************************************
 * NETCON_recv
 * Basically calls 'recv()' unless we should use SSL
Francois Gouget's avatar
Francois Gouget committed
887
 * number of chars received is put in *recvd
888
 */
889
DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags,
890 891
		int *recvd /* out */)
{
892
    *recvd = 0;
893
    if (!len)
894
        return ERROR_SUCCESS;
895 896 897
    if (!connection->useSSL)
    {
	*recvd = recv(connection->socketFD, buf, len, flags);
898
	return *recvd == -1 ? sock_get_error(errno) :  ERROR_SUCCESS;
899 900 901
    }
    else
    {
902
#ifdef SONAME_LIBSSL
903 904 905 906
        if(!connection->ssl_s) {
            FIXME("not connected\n");
            return ERROR_NOT_SUPPORTED;
        }
907
	*recvd = pSSL_read(connection->ssl_s, buf, len);
908 909 910

        /* Check if EOF was received */
        if(!*recvd && (pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_ZERO_RETURN
911
                    || pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL))
912 913
            return ERROR_SUCCESS;

914
        return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED;
915
#else
916
	return ERROR_NOT_SUPPORTED;
917 918 919 920
#endif
    }
}

921 922 923 924 925
/******************************************************************************
 * NETCON_query_data_available
 * Returns the number of bytes of peeked data plus the number of bytes of
 * queued, but unread data.
 */
926
BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available)
927
{
928
    *available = 0;
929 930 931

    if (!connection->useSSL)
    {
932
#ifdef FIONREAD
933
        int unread;
934
        int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread);
935 936 937 938 939 940
        if (!retval)
        {
            TRACE("%d bytes of queued, but unread data\n", unread);
            *available += unread;
        }
#endif
941 942 943
    }
    else
    {
944
#ifdef SONAME_LIBSSL
945
        *available = connection->ssl_s ? pSSL_pending(connection->ssl_s) : 0;
946 947
#endif
    }
948
    return TRUE;
949
}
950

951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980
BOOL NETCON_is_alive(netconn_t *netconn)
{
#ifdef MSG_DONTWAIT
    ssize_t len;
    BYTE b;

    len = recv(netconn->socketFD, &b, 1, MSG_PEEK|MSG_DONTWAIT);
    return len == 1 || (len == -1 && errno == EWOULDBLOCK);
#elif defined(__MINGW32__) || defined(_MSC_VER)
    ULONG mode;
    int len;
    char b;

    mode = 1;
    if(!ioctlsocket(netconn->socketFD, FIONBIO, &mode))
        return FALSE;

    len = recv(netconn->socketFD, &b, 1, MSG_PEEK);

    mode = 0;
    if(!ioctlsocket(netconn->socketFD, FIONBIO, &mode))
        return FALSE;

    return len == 1 || (len == -1 && errno == WSAEWOULDBLOCK);
#else
    FIXME("not supported on this platform\n");
    return TRUE;
#endif
}

981
LPCVOID NETCON_GetCert(netconn_t *connection)
982
{
983
#ifdef SONAME_LIBSSL
984 985 986
    X509* cert;
    LPCVOID r = NULL;

987
    if (!connection->ssl_s)
988 989 990
        return NULL;

    cert = pSSL_get_peer_certificate(connection->ssl_s);
991
    r = X509_to_cert_context(cert);
992 993 994 995 996
    return r;
#else
    return NULL;
#endif
}
997

998
int NETCON_GetCipherStrength(netconn_t *connection)
999 1000
{
#ifdef SONAME_LIBSSL
1001 1002 1003
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090707f)
    const SSL_CIPHER *cipher;
#else
1004
    SSL_CIPHER *cipher;
1005
#endif
1006 1007
    int bits = 0;

1008
    if (!connection->ssl_s)
1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019
        return 0;
    cipher = pSSL_get_current_cipher(connection->ssl_s);
    if (!cipher)
        return 0;
    pSSL_CIPHER_get_bits(cipher, &bits);
    return bits;
#else
    return 0;
#endif
}

1020
DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, DWORD value)
1021 1022 1023 1024 1025
{
    int result;
    struct timeval tv;

    /* value is in milliseconds, convert to struct timeval */
1026 1027 1028 1029 1030 1031 1032 1033 1034 1035
    if (value == INFINITE)
    {
        tv.tv_sec = 0;
        tv.tv_usec = 0;
    }
    else
    {
        tv.tv_sec = value / 1000;
        tv.tv_usec = (value % 1000) * 1000;
    }
1036
    result = setsockopt(connection->socketFD, SOL_SOCKET,
1037
                        send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv,
1038 1039 1040 1041
                        sizeof(tv));
    if (result == -1)
    {
        WARN("setsockopt failed (%s)\n", strerror(errno));
1042
        return sock_get_error(errno);
1043
    }
1044
    return ERROR_SUCCESS;
1045
}