BOOL NETCON_init(WININET_NETCONNECTION *connection, BOOL useSSL) { connection->useSSL = FALSE; connection->socketFD = -1; if (useSSL) { #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO) TRACE("using SSL connection\n"); if (OpenSSL_ssl_handle) /* already initialized everything */ return TRUE; 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); INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); return FALSE; } 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); INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); return FALSE; } /* mmm nice ugly macroness */ #define DYNSSL(x) \ p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \ if (!p##x) \ { \ ERR("failed to load symbol %s\n", #x); \ INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); \ return FALSE; \ } DYNSSL(SSL_library_init); DYNSSL(SSL_load_error_strings); DYNSSL(SSLv23_method); 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_get_verify_result); DYNSSL(SSL_get_peer_certificate); DYNSSL(SSL_CTX_get_timeout); DYNSSL(SSL_CTX_set_timeout); DYNSSL(SSL_CTX_set_default_verify_paths); DYNSSL(i2d_X509); #undef DYNSSL #define DYNCRYPTO(x) \ p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \ if (!p##x) \ { \ ERR("failed to load symbol %s\n", #x); \ INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); \ return FALSE; \ } DYNCRYPTO(BIO_new_fp); DYNCRYPTO(ERR_get_error); DYNCRYPTO(ERR_error_string); #undef DYNCRYPTO pSSL_library_init(); pSSL_load_error_strings(); pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */ meth = pSSLv23_method(); connection->peek_msg = NULL; connection->peek_msg_mem = NULL; #else FIXME("can't use SSL, not compiled in.\n"); INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); return FALSE; #endif } return TRUE; }
static DWORD init_openssl(void) { #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO) int i; 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 */ #define DYNSSL(x) \ p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \ if (!p##x) { \ ERR("failed to load symbol %s\n", #x); \ return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \ } 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); #undef DYNSSL #define DYNCRYPTO(x) \ p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \ if (!p##x) { \ ERR("failed to load symbol %s\n", #x); \ return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \ } 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); #undef DYNCRYPTO pSSL_library_init(); pSSL_load_error_strings(); pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */ 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; } hostname_idx = pSSL_get_ex_new_index(0, (void *)"hostname index", NULL, NULL, NULL); if(hostname_idx == -1) { ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0)); return ERROR_OUTOFMEMORY; } 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(); ssl_locks = heap_alloc(num_ssl_locks * sizeof(CRITICAL_SECTION)); if(!ssl_locks) return ERROR_OUTOFMEMORY; for(i = 0; i < num_ssl_locks; i++) { InitializeCriticalSection(&ssl_locks[i]); ssl_locks[i].DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ssl_locks"); } pCRYPTO_set_locking_callback(ssl_lock_callback); return ERROR_SUCCESS; #else FIXME("can't use SSL, not compiled in.\n"); return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; #endif }