Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennetconnection.c
Go to the documentation of this file.
00001 /* 00002 * Wininet - networking layer. Uses unix sockets or OpenSSL. 00003 * 00004 * Copyright 2002 TransGaming Technologies Inc. 00005 * 00006 * David Hammerton 00007 * 00008 * This library is free software; you can redistribute it and/or 00009 * modify it under the terms of the GNU Lesser General Public 00010 * License as published by the Free Software Foundation; either 00011 * version 2.1 of the License, or (at your option) any later version. 00012 * 00013 * This library is distributed in the hope that it will be useful, 00014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00016 * Lesser General Public License for more details. 00017 * 00018 * You should have received a copy of the GNU Lesser General Public 00019 * License along with this library; if not, write to the Free Software 00020 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00021 */ 00022 00023 #include "config.h" 00024 #include "wine/port.h" 00025 00026 #define NONAMELESSUNION 00027 00028 #if defined(__MINGW32__) || defined (_MSC_VER) 00029 #include <ws2tcpip.h> 00030 #endif 00031 00032 #include <sys/types.h> 00033 #ifdef HAVE_POLL_H 00034 #include <poll.h> 00035 #endif 00036 #ifdef HAVE_SYS_POLL_H 00037 # include <sys/poll.h> 00038 #endif 00039 #ifdef HAVE_SYS_TIME_H 00040 # include <sys/time.h> 00041 #endif 00042 #ifdef HAVE_SYS_SOCKET_H 00043 # include <sys/socket.h> 00044 #endif 00045 #ifdef HAVE_SYS_FILIO_H 00046 # include <sys/filio.h> 00047 #endif 00048 #ifdef HAVE_UNISTD_H 00049 # include <unistd.h> 00050 #endif 00051 #ifdef HAVE_SYS_IOCTL_H 00052 # include <sys/ioctl.h> 00053 #endif 00054 #include <time.h> 00055 #ifdef HAVE_NETDB_H 00056 # include <netdb.h> 00057 #endif 00058 #ifdef HAVE_NETINET_IN_H 00059 # include <netinet/in.h> 00060 #endif 00061 #ifdef HAVE_NETINET_TCP_H 00062 # include <netinet/tcp.h> 00063 #endif 00064 #ifdef HAVE_OPENSSL_SSL_H 00065 # include <openssl/ssl.h> 00066 # include <openssl/opensslv.h> 00067 #undef FAR 00068 #undef DSA 00069 #endif 00070 00071 #include <stdarg.h> 00072 #include <stdlib.h> 00073 #include <string.h> 00074 #include <stdio.h> 00075 #include <errno.h> 00076 #include <assert.h> 00077 00078 #include "wine/library.h" 00079 #include "windef.h" 00080 #include "winbase.h" 00081 #include "wininet.h" 00082 #include "winerror.h" 00083 #include "wincrypt.h" 00084 00085 #include "wine/debug.h" 00086 #include "internet.h" 00087 00088 /* To avoid conflicts with the Unix socket headers. we only need it for 00089 * the error codes anyway. */ 00090 #define USE_WS_PREFIX 00091 #include "winsock2.h" 00092 00093 #define RESPONSE_TIMEOUT 30 /* FROM internet.c */ 00094 00095 00096 WINE_DEFAULT_DEBUG_CHANNEL(wininet); 00097 00098 /* FIXME!!!!!! 00099 * This should use winsock - To use winsock the functions will have to change a bit 00100 * as they are designed for unix sockets. 00101 * SSL stuff should use crypt32.dll 00102 */ 00103 00104 #ifdef SONAME_LIBSSL 00105 00106 #include <openssl/err.h> 00107 00108 static void *OpenSSL_ssl_handle; 00109 static void *OpenSSL_crypto_handle; 00110 00111 #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10000000) 00112 static const SSL_METHOD *meth; 00113 #else 00114 static SSL_METHOD *meth; 00115 #endif 00116 static SSL_CTX *ctx; 00117 static int hostname_idx; 00118 static int error_idx; 00119 static int conn_idx; 00120 00121 #define MAKE_FUNCPTR(f) static typeof(f) * p##f 00122 00123 /* OpenSSL functions that we use */ 00124 MAKE_FUNCPTR(SSL_library_init); 00125 MAKE_FUNCPTR(SSL_load_error_strings); 00126 MAKE_FUNCPTR(SSLv23_method); 00127 MAKE_FUNCPTR(SSL_CTX_free); 00128 MAKE_FUNCPTR(SSL_CTX_new); 00129 MAKE_FUNCPTR(SSL_new); 00130 MAKE_FUNCPTR(SSL_free); 00131 MAKE_FUNCPTR(SSL_set_fd); 00132 MAKE_FUNCPTR(SSL_connect); 00133 MAKE_FUNCPTR(SSL_shutdown); 00134 MAKE_FUNCPTR(SSL_write); 00135 MAKE_FUNCPTR(SSL_read); 00136 MAKE_FUNCPTR(SSL_pending); 00137 MAKE_FUNCPTR(SSL_get_error); 00138 MAKE_FUNCPTR(SSL_get_ex_new_index); 00139 MAKE_FUNCPTR(SSL_get_ex_data); 00140 MAKE_FUNCPTR(SSL_set_ex_data); 00141 MAKE_FUNCPTR(SSL_get_ex_data_X509_STORE_CTX_idx); 00142 MAKE_FUNCPTR(SSL_get_peer_certificate); 00143 MAKE_FUNCPTR(SSL_CTX_get_timeout); 00144 MAKE_FUNCPTR(SSL_CTX_set_timeout); 00145 MAKE_FUNCPTR(SSL_CTX_set_default_verify_paths); 00146 MAKE_FUNCPTR(SSL_CTX_set_verify); 00147 MAKE_FUNCPTR(SSL_get_current_cipher); 00148 MAKE_FUNCPTR(SSL_CIPHER_get_bits); 00149 00150 /* OpenSSL's libcrypto functions that we use */ 00151 MAKE_FUNCPTR(BIO_new_fp); 00152 MAKE_FUNCPTR(CRYPTO_num_locks); 00153 MAKE_FUNCPTR(CRYPTO_set_id_callback); 00154 MAKE_FUNCPTR(CRYPTO_set_locking_callback); 00155 MAKE_FUNCPTR(ERR_free_strings); 00156 MAKE_FUNCPTR(ERR_get_error); 00157 MAKE_FUNCPTR(ERR_error_string); 00158 MAKE_FUNCPTR(X509_STORE_CTX_get_ex_data); 00159 MAKE_FUNCPTR(X509_STORE_CTX_get_chain); 00160 MAKE_FUNCPTR(i2d_X509); 00161 MAKE_FUNCPTR(sk_num); 00162 MAKE_FUNCPTR(sk_value); 00163 #undef MAKE_FUNCPTR 00164 00165 static CRITICAL_SECTION *ssl_locks; 00166 static unsigned int num_ssl_locks; 00167 00168 static unsigned long ssl_thread_id(void) 00169 { 00170 return GetCurrentThreadId(); 00171 } 00172 00173 static void ssl_lock_callback(int mode, int type, const char *file, int line) 00174 { 00175 if (mode & CRYPTO_LOCK) 00176 EnterCriticalSection(&ssl_locks[type]); 00177 else 00178 LeaveCriticalSection(&ssl_locks[type]); 00179 } 00180 00181 static PCCERT_CONTEXT X509_to_cert_context(X509 *cert) 00182 { 00183 unsigned char* buffer,*p; 00184 INT len; 00185 BOOL malloced = FALSE; 00186 PCCERT_CONTEXT ret; 00187 00188 p = NULL; 00189 len = pi2d_X509(cert,&p); 00190 /* 00191 * SSL 0.9.7 and above malloc the buffer if it is null. 00192 * however earlier version do not and so we would need to alloc the buffer. 00193 * 00194 * see the i2d_X509 man page for more details. 00195 */ 00196 if (!p) 00197 { 00198 buffer = heap_alloc(len); 00199 p = buffer; 00200 len = pi2d_X509(cert,&p); 00201 } 00202 else 00203 { 00204 buffer = p; 00205 malloced = TRUE; 00206 } 00207 00208 ret = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len); 00209 00210 if (malloced) 00211 free(buffer); 00212 else 00213 HeapFree(GetProcessHeap(),0,buffer); 00214 00215 return ret; 00216 } 00217 00218 static DWORD netconn_verify_cert(PCCERT_CONTEXT cert, HCERTSTORE store, 00219 WCHAR *server, DWORD security_flags) 00220 { 00221 BOOL ret; 00222 CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } }; 00223 PCCERT_CHAIN_CONTEXT chain; 00224 char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH; 00225 char *server_auth[] = { oid_server_auth }; 00226 DWORD err = ERROR_SUCCESS, chainFlags = 0; 00227 00228 TRACE("verifying %s\n", debugstr_w(server)); 00229 chainPara.RequestedUsage.Usage.cUsageIdentifier = 1; 00230 chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth; 00231 if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION)) 00232 chainFlags |= CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT; 00233 if ((ret = CertGetCertificateChain(NULL, cert, NULL, store, &chainPara, 00234 chainFlags, NULL, &chain))) 00235 { 00236 if (chain->TrustStatus.dwErrorStatus) 00237 { 00238 static const DWORD supportedErrors = 00239 CERT_TRUST_IS_NOT_TIME_VALID | 00240 CERT_TRUST_IS_UNTRUSTED_ROOT | 00241 CERT_TRUST_IS_OFFLINE_REVOCATION | 00242 CERT_TRUST_REVOCATION_STATUS_UNKNOWN | 00243 CERT_TRUST_IS_REVOKED | 00244 CERT_TRUST_IS_NOT_VALID_FOR_USAGE; 00245 00246 if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID && 00247 !(security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)) 00248 err = ERROR_INTERNET_SEC_CERT_DATE_INVALID; 00249 else if (chain->TrustStatus.dwErrorStatus & 00250 CERT_TRUST_IS_UNTRUSTED_ROOT && 00251 !(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) 00252 err = ERROR_INTERNET_INVALID_CA; 00253 else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) && 00254 ((chain->TrustStatus.dwErrorStatus & 00255 CERT_TRUST_IS_OFFLINE_REVOCATION) || 00256 (chain->TrustStatus.dwErrorStatus & 00257 CERT_TRUST_REVOCATION_STATUS_UNKNOWN))) 00258 err = ERROR_INTERNET_SEC_CERT_NO_REV; 00259 else if (!(security_flags & SECURITY_FLAG_IGNORE_REVOCATION) && 00260 (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED)) 00261 err = ERROR_INTERNET_SEC_CERT_REVOKED; 00262 else if (!(security_flags & SECURITY_FLAG_IGNORE_WRONG_USAGE) && 00263 (chain->TrustStatus.dwErrorStatus & 00264 CERT_TRUST_IS_NOT_VALID_FOR_USAGE)) 00265 err = ERROR_INTERNET_SEC_INVALID_CERT; 00266 else if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) 00267 err = ERROR_INTERNET_SEC_INVALID_CERT; 00268 } 00269 if (!err) 00270 { 00271 CERT_CHAIN_POLICY_PARA policyPara; 00272 SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara; 00273 CERT_CHAIN_POLICY_STATUS policyStatus; 00274 CERT_CHAIN_CONTEXT chainCopy; 00275 00276 /* Clear chain->TrustStatus.dwErrorStatus so 00277 * CertVerifyCertificateChainPolicy will verify additional checks 00278 * rather than stopping with an existing, ignored error. 00279 */ 00280 memcpy(&chainCopy, chain, sizeof(chainCopy)); 00281 chainCopy.TrustStatus.dwErrorStatus = 0; 00282 sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara); 00283 sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER; 00284 sslExtraPolicyPara.pwszServerName = server; 00285 sslExtraPolicyPara.fdwChecks = security_flags; 00286 policyPara.cbSize = sizeof(policyPara); 00287 policyPara.dwFlags = 0; 00288 policyPara.pvExtraPolicyPara = &sslExtraPolicyPara; 00289 ret = CertVerifyCertificateChainPolicy(CERT_CHAIN_POLICY_SSL, 00290 &chainCopy, &policyPara, &policyStatus); 00291 /* Any error in the policy status indicates that the 00292 * policy couldn't be verified. 00293 */ 00294 if (ret && policyStatus.dwError) 00295 { 00296 if (policyStatus.dwError == CERT_E_CN_NO_MATCH) 00297 err = ERROR_INTERNET_SEC_CERT_CN_INVALID; 00298 else 00299 err = ERROR_INTERNET_SEC_INVALID_CERT; 00300 } 00301 } 00302 CertFreeCertificateChain(chain); 00303 } 00304 TRACE("returning %08x\n", err); 00305 return err; 00306 } 00307 00308 static int netconn_secure_verify(int preverify_ok, X509_STORE_CTX *ctx) 00309 { 00310 SSL *ssl; 00311 WCHAR *server; 00312 BOOL ret = FALSE; 00313 HCERTSTORE store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, 00314 CERT_STORE_CREATE_NEW_FLAG, NULL); 00315 netconn_t *conn; 00316 00317 ssl = pX509_STORE_CTX_get_ex_data(ctx, 00318 pSSL_get_ex_data_X509_STORE_CTX_idx()); 00319 server = pSSL_get_ex_data(ssl, hostname_idx); 00320 conn = pSSL_get_ex_data(ssl, conn_idx); 00321 if (store) 00322 { 00323 X509 *cert; 00324 int i; 00325 PCCERT_CONTEXT endCert = NULL; 00326 struct stack_st *chain = (struct stack_st *)pX509_STORE_CTX_get_chain( ctx ); 00327 00328 ret = TRUE; 00329 for (i = 0; ret && i < psk_num(chain); i++) 00330 { 00331 PCCERT_CONTEXT context; 00332 00333 cert = (X509 *)psk_value(chain, i); 00334 if ((context = X509_to_cert_context(cert))) 00335 { 00336 if (i == 0) 00337 ret = CertAddCertificateContextToStore(store, context, 00338 CERT_STORE_ADD_ALWAYS, &endCert); 00339 else 00340 ret = CertAddCertificateContextToStore(store, context, 00341 CERT_STORE_ADD_ALWAYS, NULL); 00342 CertFreeCertificateContext(context); 00343 } 00344 } 00345 if (!endCert) ret = FALSE; 00346 if (ret) 00347 { 00348 DWORD_PTR err = netconn_verify_cert(endCert, store, server, 00349 conn->security_flags); 00350 00351 if (err) 00352 { 00353 pSSL_set_ex_data(ssl, error_idx, (void *)err); 00354 ret = FALSE; 00355 } 00356 } 00357 CertFreeCertificateContext(endCert); 00358 CertCloseStore(store, 0); 00359 } 00360 return ret; 00361 } 00362 00363 #endif 00364 00365 static CRITICAL_SECTION init_ssl_cs; 00366 static CRITICAL_SECTION_DEBUG init_ssl_cs_debug = 00367 { 00368 0, 0, &init_ssl_cs, 00369 { &init_ssl_cs_debug.ProcessLocksList, 00370 &init_ssl_cs_debug.ProcessLocksList }, 00371 0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") } 00372 }; 00373 static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 }; 00374 00375 static DWORD init_openssl(void) 00376 { 00377 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO) 00378 int i; 00379 00380 if(OpenSSL_ssl_handle) 00381 return ERROR_SUCCESS; 00382 00383 OpenSSL_ssl_handle = wine_dlopen(SONAME_LIBSSL, RTLD_NOW, NULL, 0); 00384 if(!OpenSSL_ssl_handle) { 00385 ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL); 00386 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; 00387 } 00388 00389 OpenSSL_crypto_handle = wine_dlopen(SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0); 00390 if(!OpenSSL_crypto_handle) { 00391 ERR("trying to use a SSL connection, but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO); 00392 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; 00393 } 00394 00395 /* mmm nice ugly macroness */ 00396 #define DYNSSL(x) \ 00397 p##x = wine_dlsym(OpenSSL_ssl_handle, #x, NULL, 0); \ 00398 if (!p##x) { \ 00399 ERR("failed to load symbol %s\n", #x); \ 00400 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \ 00401 } 00402 00403 DYNSSL(SSL_library_init); 00404 DYNSSL(SSL_load_error_strings); 00405 DYNSSL(SSLv23_method); 00406 DYNSSL(SSL_CTX_free); 00407 DYNSSL(SSL_CTX_new); 00408 DYNSSL(SSL_new); 00409 DYNSSL(SSL_free); 00410 DYNSSL(SSL_set_fd); 00411 DYNSSL(SSL_connect); 00412 DYNSSL(SSL_shutdown); 00413 DYNSSL(SSL_write); 00414 DYNSSL(SSL_read); 00415 DYNSSL(SSL_pending); 00416 DYNSSL(SSL_get_error); 00417 DYNSSL(SSL_get_ex_new_index); 00418 DYNSSL(SSL_get_ex_data); 00419 DYNSSL(SSL_set_ex_data); 00420 DYNSSL(SSL_get_ex_data_X509_STORE_CTX_idx); 00421 DYNSSL(SSL_get_peer_certificate); 00422 DYNSSL(SSL_CTX_get_timeout); 00423 DYNSSL(SSL_CTX_set_timeout); 00424 DYNSSL(SSL_CTX_set_default_verify_paths); 00425 DYNSSL(SSL_CTX_set_verify); 00426 DYNSSL(SSL_get_current_cipher); 00427 DYNSSL(SSL_CIPHER_get_bits); 00428 #undef DYNSSL 00429 00430 #define DYNCRYPTO(x) \ 00431 p##x = wine_dlsym(OpenSSL_crypto_handle, #x, NULL, 0); \ 00432 if (!p##x) { \ 00433 ERR("failed to load symbol %s\n", #x); \ 00434 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; \ 00435 } 00436 00437 DYNCRYPTO(BIO_new_fp); 00438 DYNCRYPTO(CRYPTO_num_locks); 00439 DYNCRYPTO(CRYPTO_set_id_callback); 00440 DYNCRYPTO(CRYPTO_set_locking_callback); 00441 DYNCRYPTO(ERR_free_strings); 00442 DYNCRYPTO(ERR_get_error); 00443 DYNCRYPTO(ERR_error_string); 00444 DYNCRYPTO(X509_STORE_CTX_get_ex_data); 00445 DYNCRYPTO(X509_STORE_CTX_get_chain); 00446 DYNCRYPTO(i2d_X509); 00447 DYNCRYPTO(sk_num); 00448 DYNCRYPTO(sk_value); 00449 #undef DYNCRYPTO 00450 00451 pSSL_library_init(); 00452 pSSL_load_error_strings(); 00453 pBIO_new_fp(stderr, BIO_NOCLOSE); /* FIXME: should use winedebug stuff */ 00454 00455 meth = pSSLv23_method(); 00456 ctx = pSSL_CTX_new(meth); 00457 if(!pSSL_CTX_set_default_verify_paths(ctx)) { 00458 ERR("SSL_CTX_set_default_verify_paths failed: %s\n", 00459 pERR_error_string(pERR_get_error(), 0)); 00460 return ERROR_OUTOFMEMORY; 00461 } 00462 00463 hostname_idx = pSSL_get_ex_new_index(0, (void *)"hostname index", NULL, NULL, NULL); 00464 if(hostname_idx == -1) { 00465 ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0)); 00466 return ERROR_OUTOFMEMORY; 00467 } 00468 00469 error_idx = pSSL_get_ex_new_index(0, (void *)"error index", NULL, NULL, NULL); 00470 if(error_idx == -1) { 00471 ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0)); 00472 return ERROR_OUTOFMEMORY; 00473 } 00474 00475 conn_idx = pSSL_get_ex_new_index(0, (void *)"netconn index", NULL, NULL, NULL); 00476 if(conn_idx == -1) { 00477 ERR("SSL_get_ex_new_index failed; %s\n", pERR_error_string(pERR_get_error(), 0)); 00478 return ERROR_OUTOFMEMORY; 00479 } 00480 00481 pSSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, netconn_secure_verify); 00482 00483 pCRYPTO_set_id_callback(ssl_thread_id); 00484 num_ssl_locks = pCRYPTO_num_locks(); 00485 ssl_locks = HeapAlloc(GetProcessHeap(), 0, num_ssl_locks * sizeof(CRITICAL_SECTION)); 00486 if(!ssl_locks) 00487 return ERROR_OUTOFMEMORY; 00488 00489 for(i = 0; i < num_ssl_locks; i++) 00490 InitializeCriticalSection(&ssl_locks[i]); 00491 pCRYPTO_set_locking_callback(ssl_lock_callback); 00492 00493 return ERROR_SUCCESS; 00494 #else 00495 FIXME("can't use SSL, not compiled in.\n"); 00496 return ERROR_INTERNET_SECURITY_CHANNEL_ERROR; 00497 #endif 00498 } 00499 00500 DWORD create_netconn(BOOL useSSL, server_t *server, DWORD security_flags, netconn_t **ret) 00501 { 00502 netconn_t *netconn; 00503 int result, flag; 00504 00505 if(useSSL) { 00506 DWORD res; 00507 00508 TRACE("using SSL connection\n"); 00509 00510 EnterCriticalSection(&init_ssl_cs); 00511 res = init_openssl(); 00512 LeaveCriticalSection(&init_ssl_cs); 00513 if(res != ERROR_SUCCESS) 00514 return res; 00515 } 00516 00517 netconn = heap_alloc_zero(sizeof(*netconn)); 00518 if(!netconn) 00519 return ERROR_OUTOFMEMORY; 00520 00521 netconn->useSSL = useSSL; 00522 netconn->socketFD = -1; 00523 netconn->security_flags = security_flags; 00524 list_init(&netconn->pool_entry); 00525 00526 assert(server->addr_len); 00527 result = netconn->socketFD = socket(server->addr.ss_family, SOCK_STREAM, 0); 00528 if(result != -1) { 00529 result = connect(netconn->socketFD, (struct sockaddr*)&server->addr, server->addr_len); 00530 if(result == -1) 00531 closesocket(netconn->socketFD); 00532 } 00533 if(result == -1) { 00534 heap_free(netconn); 00535 return sock_get_error(errno); 00536 } 00537 00538 #ifdef TCP_NODELAY 00539 flag = 1; 00540 result = setsockopt(netconn->socketFD, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(flag)); 00541 if(result < 0) 00542 WARN("setsockopt(TCP_NODELAY) failed\n"); 00543 #endif 00544 00545 server_addref(server); 00546 netconn->server = server; 00547 00548 *ret = netconn; 00549 return ERROR_SUCCESS; 00550 } 00551 00552 void free_netconn(netconn_t *netconn) 00553 { 00554 server_release(netconn->server); 00555 00556 #ifdef SONAME_LIBSSL 00557 if (netconn->ssl_s) { 00558 pSSL_shutdown(netconn->ssl_s); 00559 pSSL_free(netconn->ssl_s); 00560 } 00561 #endif 00562 00563 closesocket(netconn->socketFD); 00564 heap_free(netconn); 00565 } 00566 00567 void NETCON_unload(void) 00568 { 00569 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO) 00570 if (OpenSSL_crypto_handle) 00571 { 00572 pERR_free_strings(); 00573 wine_dlclose(OpenSSL_crypto_handle, NULL, 0); 00574 } 00575 if (OpenSSL_ssl_handle) 00576 { 00577 if (ctx) 00578 pSSL_CTX_free(ctx); 00579 wine_dlclose(OpenSSL_ssl_handle, NULL, 0); 00580 } 00581 if (ssl_locks) 00582 { 00583 int i; 00584 for (i = 0; i < num_ssl_locks; i++) DeleteCriticalSection(&ssl_locks[i]); 00585 HeapFree(GetProcessHeap(), 0, ssl_locks); 00586 } 00587 #endif 00588 } 00589 00590 #if 0 00591 /* translate a unix error code into a winsock one */ 00592 int sock_get_error( int err ) 00593 { 00594 #if !defined(__MINGW32__) && !defined (_MSC_VER) 00595 switch (err) 00596 { 00597 case EINTR: return WSAEINTR; 00598 case EBADF: return WSAEBADF; 00599 case EPERM: 00600 case EACCES: return WSAEACCES; 00601 case EFAULT: return WSAEFAULT; 00602 case EINVAL: return WSAEINVAL; 00603 case EMFILE: return WSAEMFILE; 00604 case EWOULDBLOCK: return WSAEWOULDBLOCK; 00605 case EINPROGRESS: return WSAEINPROGRESS; 00606 case EALREADY: return WSAEALREADY; 00607 case ENOTSOCK: return WSAENOTSOCK; 00608 case EDESTADDRREQ: return WSAEDESTADDRREQ; 00609 case EMSGSIZE: return WSAEMSGSIZE; 00610 case EPROTOTYPE: return WSAEPROTOTYPE; 00611 case ENOPROTOOPT: return WSAENOPROTOOPT; 00612 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; 00613 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; 00614 case EOPNOTSUPP: return WSAEOPNOTSUPP; 00615 case EPFNOSUPPORT: return WSAEPFNOSUPPORT; 00616 case EAFNOSUPPORT: return WSAEAFNOSUPPORT; 00617 case EADDRINUSE: return WSAEADDRINUSE; 00618 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL; 00619 case ENETDOWN: return WSAENETDOWN; 00620 case ENETUNREACH: return WSAENETUNREACH; 00621 case ENETRESET: return WSAENETRESET; 00622 case ECONNABORTED: return WSAECONNABORTED; 00623 case EPIPE: 00624 case ECONNRESET: return WSAECONNRESET; 00625 case ENOBUFS: return WSAENOBUFS; 00626 case EISCONN: return WSAEISCONN; 00627 case ENOTCONN: return WSAENOTCONN; 00628 case ESHUTDOWN: return WSAESHUTDOWN; 00629 case ETOOMANYREFS: return WSAETOOMANYREFS; 00630 case ETIMEDOUT: return WSAETIMEDOUT; 00631 case ECONNREFUSED: return WSAECONNREFUSED; 00632 case ELOOP: return WSAELOOP; 00633 case ENAMETOOLONG: return WSAENAMETOOLONG; 00634 case EHOSTDOWN: return WSAEHOSTDOWN; 00635 case EHOSTUNREACH: return WSAEHOSTUNREACH; 00636 case ENOTEMPTY: return WSAENOTEMPTY; 00637 #ifdef EPROCLIM 00638 case EPROCLIM: return WSAEPROCLIM; 00639 #endif 00640 #ifdef EUSERS 00641 case EUSERS: return WSAEUSERS; 00642 #endif 00643 #ifdef EDQUOT 00644 case EDQUOT: return WSAEDQUOT; 00645 #endif 00646 #ifdef ESTALE 00647 case ESTALE: return WSAESTALE; 00648 #endif 00649 #ifdef EREMOTE 00650 case EREMOTE: return WSAEREMOTE; 00651 #endif 00652 default: errno=err; perror("sock_set_error"); return WSAEFAULT; 00653 } 00654 #endif 00655 return err; 00656 } 00657 #endif 00658 00659 /****************************************************************************** 00660 * NETCON_secure_connect 00661 * Initiates a secure connection over an existing plaintext connection. 00662 */ 00663 DWORD NETCON_secure_connect(netconn_t *connection, LPWSTR hostname) 00664 { 00665 void *ssl_s; 00666 DWORD res = ERROR_NOT_SUPPORTED; 00667 00668 #ifdef SONAME_LIBSSL 00669 /* can't connect if we are already connected */ 00670 if (connection->ssl_s) 00671 { 00672 ERR("already connected\n"); 00673 return ERROR_INTERNET_CANNOT_CONNECT; 00674 } 00675 00676 ssl_s = pSSL_new(ctx); 00677 if (!ssl_s) 00678 { 00679 ERR("SSL_new failed: %s\n", 00680 pERR_error_string(pERR_get_error(), 0)); 00681 return ERROR_OUTOFMEMORY; 00682 } 00683 00684 if (!pSSL_set_fd(ssl_s, connection->socketFD)) 00685 { 00686 ERR("SSL_set_fd failed: %s\n", 00687 pERR_error_string(pERR_get_error(), 0)); 00688 res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; 00689 goto fail; 00690 } 00691 00692 if (!pSSL_set_ex_data(ssl_s, hostname_idx, hostname)) 00693 { 00694 ERR("SSL_set_ex_data failed: %s\n", 00695 pERR_error_string(pERR_get_error(), 0)); 00696 res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; 00697 goto fail; 00698 } 00699 if (!pSSL_set_ex_data(ssl_s, conn_idx, connection)) 00700 { 00701 ERR("SSL_set_ex_data failed: %s\n", 00702 pERR_error_string(pERR_get_error(), 0)); 00703 res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; 00704 goto fail; 00705 } 00706 if (pSSL_connect(ssl_s) <= 0) 00707 { 00708 res = (DWORD_PTR)pSSL_get_ex_data(ssl_s, error_idx); 00709 if (!res) 00710 res = ERROR_INTERNET_SECURITY_CHANNEL_ERROR; 00711 ERR("SSL_connect failed: %d\n", res); 00712 goto fail; 00713 } 00714 00715 connection->ssl_s = ssl_s; 00716 return ERROR_SUCCESS; 00717 00718 fail: 00719 if (ssl_s) 00720 { 00721 pSSL_shutdown(ssl_s); 00722 pSSL_free(ssl_s); 00723 } 00724 #endif 00725 return res; 00726 } 00727 00728 /****************************************************************************** 00729 * NETCON_send 00730 * Basically calls 'send()' unless we should use SSL 00731 * number of chars send is put in *sent 00732 */ 00733 DWORD NETCON_send(netconn_t *connection, const void *msg, size_t len, int flags, 00734 int *sent /* out */) 00735 { 00736 if (!connection->useSSL) 00737 { 00738 *sent = send(connection->socketFD, msg, len, flags); 00739 if (*sent == -1) 00740 return sock_get_error(errno); 00741 return ERROR_SUCCESS; 00742 } 00743 else 00744 { 00745 #ifdef SONAME_LIBSSL 00746 if(!connection->ssl_s) { 00747 FIXME("not connected\n"); 00748 return ERROR_NOT_SUPPORTED; 00749 } 00750 if (flags) 00751 FIXME("SSL_write doesn't support any flags (%08x)\n", flags); 00752 *sent = pSSL_write(connection->ssl_s, msg, len); 00753 if (*sent < 1 && len) 00754 return ERROR_INTERNET_CONNECTION_ABORTED; 00755 return ERROR_SUCCESS; 00756 #else 00757 return ERROR_NOT_SUPPORTED; 00758 #endif 00759 } 00760 } 00761 00762 /****************************************************************************** 00763 * NETCON_recv 00764 * Basically calls 'recv()' unless we should use SSL 00765 * number of chars received is put in *recvd 00766 */ 00767 DWORD NETCON_recv(netconn_t *connection, void *buf, size_t len, int flags, 00768 int *recvd /* out */) 00769 { 00770 *recvd = 0; 00771 if (!len) 00772 return ERROR_SUCCESS; 00773 if (!connection->useSSL) 00774 { 00775 *recvd = recv(connection->socketFD, buf, len, flags); 00776 return *recvd == -1 ? sock_get_error(errno) : ERROR_SUCCESS; 00777 } 00778 else 00779 { 00780 #ifdef SONAME_LIBSSL 00781 if(!connection->ssl_s) { 00782 FIXME("not connected\n"); 00783 return ERROR_NOT_SUPPORTED; 00784 } 00785 *recvd = pSSL_read(connection->ssl_s, buf, len); 00786 00787 /* Check if EOF was received */ 00788 if(!*recvd && (pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_ZERO_RETURN 00789 || pSSL_get_error(connection->ssl_s, *recvd)==SSL_ERROR_SYSCALL)) 00790 return ERROR_SUCCESS; 00791 00792 return *recvd > 0 ? ERROR_SUCCESS : ERROR_INTERNET_CONNECTION_ABORTED; 00793 #else 00794 return ERROR_NOT_SUPPORTED; 00795 #endif 00796 } 00797 } 00798 00799 /****************************************************************************** 00800 * NETCON_query_data_available 00801 * Returns the number of bytes of peeked data plus the number of bytes of 00802 * queued, but unread data. 00803 */ 00804 BOOL NETCON_query_data_available(netconn_t *connection, DWORD *available) 00805 { 00806 *available = 0; 00807 00808 if (!connection->useSSL) 00809 { 00810 #ifdef FIONREAD 00811 int unread; 00812 int retval = ioctlsocket(connection->socketFD, FIONREAD, &unread); 00813 if (!retval) 00814 { 00815 TRACE("%d bytes of queued, but unread data\n", unread); 00816 *available += unread; 00817 } 00818 #endif 00819 } 00820 else 00821 { 00822 #ifdef SONAME_LIBSSL 00823 *available = connection->ssl_s ? pSSL_pending(connection->ssl_s) : 0; 00824 #endif 00825 } 00826 return TRUE; 00827 } 00828 00829 BOOL NETCON_is_alive(netconn_t *netconn) 00830 { 00831 #ifdef MSG_DONTWAIT 00832 ssize_t len; 00833 BYTE b; 00834 00835 len = recv(netconn->socketFD, &b, 1, MSG_PEEK|MSG_DONTWAIT); 00836 return len == 1 || (len == -1 && errno == EWOULDBLOCK); 00837 #elif defined(__MINGW32__) || defined(_MSC_VER) 00838 ULONG mode; 00839 int len; 00840 char b; 00841 00842 mode = 1; 00843 if(!ioctlsocket(netconn->socketFD, FIONBIO, &mode)) 00844 return FALSE; 00845 00846 len = recv(netconn->socketFD, &b, 1, MSG_PEEK); 00847 00848 mode = 0; 00849 if(!ioctlsocket(netconn->socketFD, FIONBIO, &mode)) 00850 return FALSE; 00851 00852 return len == 1 || (len == -1 && errno == WSAEWOULDBLOCK); 00853 #else 00854 FIXME("not supported on this platform\n"); 00855 return TRUE; 00856 #endif 00857 } 00858 00859 LPCVOID NETCON_GetCert(netconn_t *connection) 00860 { 00861 #ifdef SONAME_LIBSSL 00862 X509* cert; 00863 LPCVOID r = NULL; 00864 00865 if (!connection->ssl_s) 00866 return NULL; 00867 00868 cert = pSSL_get_peer_certificate(connection->ssl_s); 00869 r = X509_to_cert_context(cert); 00870 return r; 00871 #else 00872 return NULL; 00873 #endif 00874 } 00875 00876 int NETCON_GetCipherStrength(netconn_t *connection) 00877 { 00878 #ifdef SONAME_LIBSSL 00879 #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090707f) 00880 const SSL_CIPHER *cipher; 00881 #else 00882 SSL_CIPHER *cipher; 00883 #endif 00884 int bits = 0; 00885 00886 if (!connection->ssl_s) 00887 return 0; 00888 cipher = pSSL_get_current_cipher(connection->ssl_s); 00889 if (!cipher) 00890 return 0; 00891 pSSL_CIPHER_get_bits(cipher, &bits); 00892 return bits; 00893 #else 00894 return 0; 00895 #endif 00896 } 00897 00898 DWORD NETCON_set_timeout(netconn_t *connection, BOOL send, int value) 00899 { 00900 int result; 00901 struct timeval tv; 00902 00903 /* value is in milliseconds, convert to struct timeval */ 00904 tv.tv_sec = value / 1000; 00905 tv.tv_usec = (value % 1000) * 1000; 00906 00907 result = setsockopt(connection->socketFD, SOL_SOCKET, 00908 send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, 00909 sizeof(tv)); 00910 00911 if (result == -1) 00912 { 00913 WARN("setsockopt failed (%s)\n", strerror(errno)); 00914 return sock_get_error(errno); 00915 } 00916 00917 return ERROR_SUCCESS; 00918 } Generated on Fri May 25 2012 04:24:58 for ReactOS by
1.7.6.1
|