Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygennet.c
Go to the documentation of this file.
00001 /* 00002 * Copyright 2008 Hans Leidekker for CodeWeavers 00003 * 00004 * This library is free software; you can redistribute it and/or 00005 * modify it under the terms of the GNU Lesser General Public 00006 * License as published by the Free Software Foundation; either 00007 * version 2.1 of the License, or (at your option) any later version. 00008 * 00009 * This library is distributed in the hope that it will be useful, 00010 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00011 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00012 * Lesser General Public License for more details. 00013 * 00014 * You should have received a copy of the GNU Lesser General Public 00015 * License along with this library; if not, write to the Free Software 00016 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA 00017 */ 00018 00019 #include "config.h" 00020 #include "wine/port.h" 00021 00022 #include <stdarg.h> 00023 #include <stdio.h> 00024 #include <errno.h> 00025 00026 #include <sys/types.h> 00027 #ifdef HAVE_SYS_SOCKET_H 00028 # include <sys/socket.h> 00029 #endif 00030 #ifdef HAVE_SYS_IOCTL_H 00031 # include <sys/ioctl.h> 00032 #endif 00033 #ifdef HAVE_SYS_FILIO_H 00034 # include <sys/filio.h> 00035 #endif 00036 #ifdef HAVE_POLL_H 00037 # include <poll.h> 00038 #endif 00039 #ifdef HAVE_OPENSSL_SSL_H 00040 # include <openssl/ssl.h> 00041 # include <openssl/opensslv.h> 00042 #undef FAR 00043 #undef DSA 00044 #endif 00045 00046 #define NONAMELESSUNION 00047 00048 #include "wine/debug.h" 00049 #include "wine/library.h" 00050 00051 #include "windef.h" 00052 #include "winbase.h" 00053 #include "winhttp.h" 00054 #include "wincrypt.h" 00055 00056 #include "winhttp_private.h" 00057 00058 /* to avoid conflicts with the Unix socket headers */ 00059 #define USE_WS_PREFIX 00060 #include "winsock2.h" 00061 00062 WINE_DEFAULT_DEBUG_CHANNEL(winhttp); 00063 00064 #ifndef HAVE_GETADDRINFO 00065 00066 /* critical section to protect non-reentrant gethostbyname() */ 00067 static CRITICAL_SECTION cs_gethostbyname; 00068 static CRITICAL_SECTION_DEBUG critsect_debug = 00069 { 00070 0, 0, &cs_gethostbyname, 00071 { &critsect_debug.ProcessLocksList, &critsect_debug.ProcessLocksList }, 00072 0, 0, { (DWORD_PTR)(__FILE__ ": cs_gethostbyname") } 00073 }; 00074 static CRITICAL_SECTION cs_gethostbyname = { &critsect_debug, -1, 0, 0, 0, 0 }; 00075 00076 #endif 00077 00078 #ifdef SONAME_LIBSSL 00079 00080 #include <openssl/err.h> 00081 00082 static CRITICAL_SECTION init_ssl_cs; 00083 static CRITICAL_SECTION_DEBUG init_ssl_cs_debug = 00084 { 00085 0, 0, &init_ssl_cs, 00086 { &init_ssl_cs_debug.ProcessLocksList, 00087 &init_ssl_cs_debug.ProcessLocksList }, 00088 0, 0, { (DWORD_PTR)(__FILE__ ": init_ssl_cs") } 00089 }; 00090 static CRITICAL_SECTION init_ssl_cs = { &init_ssl_cs_debug, -1, 0, 0, 0, 0 }; 00091 00092 static void *libssl_handle; 00093 static void *libcrypto_handle; 00094 00095 #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10000000) 00096 static const SSL_METHOD *method; 00097 #else 00098 static SSL_METHOD *method; 00099 #endif 00100 static SSL_CTX *ctx; 00101 static int hostname_idx; 00102 static int error_idx; 00103 static int conn_idx; 00104 00105 #define MAKE_FUNCPTR(f) static typeof(f) * p##f 00106 00107 MAKE_FUNCPTR( SSL_library_init ); 00108 MAKE_FUNCPTR( SSL_load_error_strings ); 00109 MAKE_FUNCPTR( SSLv23_method ); 00110 MAKE_FUNCPTR( SSL_CTX_free ); 00111 MAKE_FUNCPTR( SSL_CTX_new ); 00112 MAKE_FUNCPTR( SSL_new ); 00113 MAKE_FUNCPTR( SSL_free ); 00114 MAKE_FUNCPTR( SSL_set_fd ); 00115 MAKE_FUNCPTR( SSL_connect ); 00116 MAKE_FUNCPTR( SSL_shutdown ); 00117 MAKE_FUNCPTR( SSL_write ); 00118 MAKE_FUNCPTR( SSL_read ); 00119 MAKE_FUNCPTR( SSL_get_error ); 00120 MAKE_FUNCPTR( SSL_get_ex_new_index ); 00121 MAKE_FUNCPTR( SSL_get_ex_data ); 00122 MAKE_FUNCPTR( SSL_set_ex_data ); 00123 MAKE_FUNCPTR( SSL_get_ex_data_X509_STORE_CTX_idx ); 00124 MAKE_FUNCPTR( SSL_get_peer_certificate ); 00125 MAKE_FUNCPTR( SSL_CTX_set_default_verify_paths ); 00126 MAKE_FUNCPTR( SSL_CTX_set_verify ); 00127 MAKE_FUNCPTR( SSL_get_current_cipher ); 00128 MAKE_FUNCPTR( SSL_CIPHER_get_bits ); 00129 00130 MAKE_FUNCPTR( CRYPTO_num_locks ); 00131 MAKE_FUNCPTR( CRYPTO_set_id_callback ); 00132 MAKE_FUNCPTR( CRYPTO_set_locking_callback ); 00133 MAKE_FUNCPTR( ERR_free_strings ); 00134 MAKE_FUNCPTR( ERR_get_error ); 00135 MAKE_FUNCPTR( ERR_error_string ); 00136 MAKE_FUNCPTR( X509_STORE_CTX_get_ex_data ); 00137 MAKE_FUNCPTR( X509_STORE_CTX_get_chain ); 00138 MAKE_FUNCPTR( i2d_X509 ); 00139 MAKE_FUNCPTR( sk_value ); 00140 MAKE_FUNCPTR( sk_num ); 00141 #undef MAKE_FUNCPTR 00142 00143 static CRITICAL_SECTION *ssl_locks; 00144 static unsigned int num_ssl_locks; 00145 00146 static unsigned long ssl_thread_id(void) 00147 { 00148 return GetCurrentThreadId(); 00149 } 00150 00151 static void ssl_lock_callback(int mode, int type, const char *file, int line) 00152 { 00153 if (mode & CRYPTO_LOCK) 00154 EnterCriticalSection( &ssl_locks[type] ); 00155 else 00156 LeaveCriticalSection( &ssl_locks[type] ); 00157 } 00158 00159 #endif 00160 00161 /* translate a unix error code into a winsock error code */ 00162 #if 0 00163 static int sock_get_error( int err ) 00164 { 00165 #if !defined(__MINGW32__) && !defined (_MSC_VER) 00166 switch (err) 00167 { 00168 case EINTR: return WSAEINTR; 00169 case EBADF: return WSAEBADF; 00170 case EPERM: 00171 case EACCES: return WSAEACCES; 00172 case EFAULT: return WSAEFAULT; 00173 case EINVAL: return WSAEINVAL; 00174 case EMFILE: return WSAEMFILE; 00175 case EWOULDBLOCK: return WSAEWOULDBLOCK; 00176 case EINPROGRESS: return WSAEINPROGRESS; 00177 case EALREADY: return WSAEALREADY; 00178 case ENOTSOCK: return WSAENOTSOCK; 00179 case EDESTADDRREQ: return WSAEDESTADDRREQ; 00180 case EMSGSIZE: return WSAEMSGSIZE; 00181 case EPROTOTYPE: return WSAEPROTOTYPE; 00182 case ENOPROTOOPT: return WSAENOPROTOOPT; 00183 case EPROTONOSUPPORT: return WSAEPROTONOSUPPORT; 00184 case ESOCKTNOSUPPORT: return WSAESOCKTNOSUPPORT; 00185 case EOPNOTSUPP: return WSAEOPNOTSUPP; 00186 case EPFNOSUPPORT: return WSAEPFNOSUPPORT; 00187 case EAFNOSUPPORT: return WSAEAFNOSUPPORT; 00188 case EADDRINUSE: return WSAEADDRINUSE; 00189 case EADDRNOTAVAIL: return WSAEADDRNOTAVAIL; 00190 case ENETDOWN: return WSAENETDOWN; 00191 case ENETUNREACH: return WSAENETUNREACH; 00192 case ENETRESET: return WSAENETRESET; 00193 case ECONNABORTED: return WSAECONNABORTED; 00194 case EPIPE: 00195 case ECONNRESET: return WSAECONNRESET; 00196 case ENOBUFS: return WSAENOBUFS; 00197 case EISCONN: return WSAEISCONN; 00198 case ENOTCONN: return WSAENOTCONN; 00199 case ESHUTDOWN: return WSAESHUTDOWN; 00200 case ETOOMANYREFS: return WSAETOOMANYREFS; 00201 case ETIMEDOUT: return WSAETIMEDOUT; 00202 case ECONNREFUSED: return WSAECONNREFUSED; 00203 case ELOOP: return WSAELOOP; 00204 case ENAMETOOLONG: return WSAENAMETOOLONG; 00205 case EHOSTDOWN: return WSAEHOSTDOWN; 00206 case EHOSTUNREACH: return WSAEHOSTUNREACH; 00207 case ENOTEMPTY: return WSAENOTEMPTY; 00208 #ifdef EPROCLIM 00209 case EPROCLIM: return WSAEPROCLIM; 00210 #endif 00211 #ifdef EUSERS 00212 case EUSERS: return WSAEUSERS; 00213 #endif 00214 #ifdef EDQUOT 00215 case EDQUOT: return WSAEDQUOT; 00216 #endif 00217 #ifdef ESTALE 00218 case ESTALE: return WSAESTALE; 00219 #endif 00220 #ifdef EREMOTE 00221 case EREMOTE: return WSAEREMOTE; 00222 #endif 00223 default: errno = err; perror( "sock_set_error" ); return WSAEFAULT; 00224 } 00225 #endif 00226 return err; 00227 } 00228 #else 00229 #define sock_get_error(x) WSAGetLastError() 00230 #endif 00231 00232 #ifdef SONAME_LIBSSL 00233 static PCCERT_CONTEXT X509_to_cert_context(X509 *cert) 00234 { 00235 unsigned char *buffer, *p; 00236 int len; 00237 BOOL malloc = FALSE; 00238 PCCERT_CONTEXT ret; 00239 00240 p = NULL; 00241 if ((len = pi2d_X509( cert, &p )) < 0) return NULL; 00242 /* 00243 * SSL 0.9.7 and above malloc the buffer if it is null. 00244 * however earlier version do not and so we would need to alloc the buffer. 00245 * 00246 * see the i2d_X509 man page for more details. 00247 */ 00248 if (!p) 00249 { 00250 if (!(buffer = heap_alloc( len ))) return NULL; 00251 p = buffer; 00252 len = pi2d_X509( cert, &p ); 00253 } 00254 else 00255 { 00256 buffer = p; 00257 malloc = TRUE; 00258 } 00259 00260 ret = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, len ); 00261 00262 if (malloc) free( buffer ); 00263 else heap_free( buffer ); 00264 00265 return ret; 00266 } 00267 00268 static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, HCERTSTORE store, 00269 WCHAR *server, DWORD security_flags ) 00270 { 00271 BOOL ret; 00272 CERT_CHAIN_PARA chainPara = { sizeof(chainPara), { 0 } }; 00273 PCCERT_CHAIN_CONTEXT chain; 00274 char oid_server_auth[] = szOID_PKIX_KP_SERVER_AUTH; 00275 char *server_auth[] = { oid_server_auth }; 00276 DWORD err = ERROR_SUCCESS; 00277 00278 TRACE("verifying %s\n", debugstr_w( server )); 00279 chainPara.RequestedUsage.Usage.cUsageIdentifier = 1; 00280 chainPara.RequestedUsage.Usage.rgpszUsageIdentifier = server_auth; 00281 if ((ret = CertGetCertificateChain( NULL, cert, NULL, store, &chainPara, 00282 CERT_CHAIN_REVOCATION_CHECK_CHAIN_EXCLUDE_ROOT, 00283 NULL, &chain ))) 00284 { 00285 if (chain->TrustStatus.dwErrorStatus) 00286 { 00287 static const DWORD supportedErrors = 00288 CERT_TRUST_IS_NOT_TIME_VALID | 00289 CERT_TRUST_IS_UNTRUSTED_ROOT | 00290 CERT_TRUST_IS_NOT_VALID_FOR_USAGE; 00291 00292 if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_NOT_TIME_VALID) 00293 { 00294 if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_DATE_INVALID)) 00295 err = ERROR_WINHTTP_SECURE_CERT_DATE_INVALID; 00296 } 00297 else if (chain->TrustStatus.dwErrorStatus & 00298 CERT_TRUST_IS_UNTRUSTED_ROOT) 00299 { 00300 if (!(security_flags & SECURITY_FLAG_IGNORE_UNKNOWN_CA)) 00301 err = ERROR_WINHTTP_SECURE_INVALID_CA; 00302 } 00303 else if ((chain->TrustStatus.dwErrorStatus & 00304 CERT_TRUST_IS_OFFLINE_REVOCATION) || 00305 (chain->TrustStatus.dwErrorStatus & 00306 CERT_TRUST_REVOCATION_STATUS_UNKNOWN)) 00307 err = ERROR_WINHTTP_SECURE_CERT_REV_FAILED; 00308 else if (chain->TrustStatus.dwErrorStatus & CERT_TRUST_IS_REVOKED) 00309 err = ERROR_WINHTTP_SECURE_CERT_REVOKED; 00310 else if (chain->TrustStatus.dwErrorStatus & 00311 CERT_TRUST_IS_NOT_VALID_FOR_USAGE) 00312 { 00313 if (!(security_flags & SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE)) 00314 err = ERROR_WINHTTP_SECURE_CERT_WRONG_USAGE; 00315 } 00316 else if (chain->TrustStatus.dwErrorStatus & ~supportedErrors) 00317 err = ERROR_WINHTTP_SECURE_INVALID_CERT; 00318 } 00319 if (!err) 00320 { 00321 CERT_CHAIN_POLICY_PARA policyPara; 00322 SSL_EXTRA_CERT_CHAIN_POLICY_PARA sslExtraPolicyPara; 00323 CERT_CHAIN_POLICY_STATUS policyStatus; 00324 CERT_CHAIN_CONTEXT chainCopy; 00325 00326 /* Clear chain->TrustStatus.dwErrorStatus so 00327 * CertVerifyCertificateChainPolicy will verify additional checks 00328 * rather than stopping with an existing, ignored error. 00329 */ 00330 memcpy(&chainCopy, chain, sizeof(chainCopy)); 00331 chainCopy.TrustStatus.dwErrorStatus = 0; 00332 sslExtraPolicyPara.u.cbSize = sizeof(sslExtraPolicyPara); 00333 sslExtraPolicyPara.dwAuthType = AUTHTYPE_SERVER; 00334 sslExtraPolicyPara.pwszServerName = server; 00335 sslExtraPolicyPara.fdwChecks = security_flags; 00336 policyPara.cbSize = sizeof(policyPara); 00337 policyPara.dwFlags = 0; 00338 policyPara.pvExtraPolicyPara = &sslExtraPolicyPara; 00339 ret = CertVerifyCertificateChainPolicy( CERT_CHAIN_POLICY_SSL, 00340 &chainCopy, &policyPara, 00341 &policyStatus ); 00342 /* Any error in the policy status indicates that the 00343 * policy couldn't be verified. 00344 */ 00345 if (ret && policyStatus.dwError) 00346 { 00347 if (policyStatus.dwError == CERT_E_CN_NO_MATCH) 00348 err = ERROR_WINHTTP_SECURE_CERT_CN_INVALID; 00349 else 00350 err = ERROR_WINHTTP_SECURE_INVALID_CERT; 00351 } 00352 } 00353 CertFreeCertificateChain( chain ); 00354 } 00355 else 00356 err = ERROR_WINHTTP_SECURE_CHANNEL_ERROR; 00357 TRACE("returning %08x\n", err); 00358 return err; 00359 } 00360 00361 static int netconn_secure_verify( int preverify_ok, X509_STORE_CTX *ctx ) 00362 { 00363 SSL *ssl; 00364 WCHAR *server; 00365 BOOL ret = FALSE; 00366 netconn_t *conn; 00367 HCERTSTORE store = CertOpenStore( CERT_STORE_PROV_MEMORY, 0, 0, 00368 CERT_STORE_CREATE_NEW_FLAG, NULL ); 00369 00370 ssl = pX509_STORE_CTX_get_ex_data( ctx, pSSL_get_ex_data_X509_STORE_CTX_idx() ); 00371 server = pSSL_get_ex_data( ssl, hostname_idx ); 00372 conn = pSSL_get_ex_data( ssl, conn_idx ); 00373 if (store) 00374 { 00375 X509 *cert; 00376 int i; 00377 PCCERT_CONTEXT endCert = NULL; 00378 struct stack_st *chain = (struct stack_st *)pX509_STORE_CTX_get_chain( ctx ); 00379 00380 ret = TRUE; 00381 for (i = 0; ret && i < psk_num(chain); i++) 00382 { 00383 PCCERT_CONTEXT context; 00384 00385 cert = (X509 *)psk_value(chain, i); 00386 if ((context = X509_to_cert_context( cert ))) 00387 { 00388 if (i == 0) 00389 ret = CertAddCertificateContextToStore( store, context, 00390 CERT_STORE_ADD_ALWAYS, &endCert ); 00391 else 00392 ret = CertAddCertificateContextToStore( store, context, 00393 CERT_STORE_ADD_ALWAYS, NULL ); 00394 CertFreeCertificateContext( context ); 00395 } 00396 } 00397 if (!endCert) ret = FALSE; 00398 if (ret) 00399 { 00400 DWORD_PTR err = netconn_verify_cert( endCert, store, server, 00401 conn->security_flags ); 00402 00403 if (err) 00404 { 00405 pSSL_set_ex_data( ssl, error_idx, (void *)err ); 00406 ret = FALSE; 00407 } 00408 } 00409 CertFreeCertificateContext( endCert ); 00410 CertCloseStore( store, 0 ); 00411 } 00412 return ret; 00413 } 00414 #endif 00415 00416 BOOL netconn_init( netconn_t *conn, BOOL secure ) 00417 { 00418 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO) 00419 int i; 00420 #endif 00421 00422 conn->socket = -1; 00423 if (!secure) return TRUE; 00424 00425 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO) 00426 EnterCriticalSection( &init_ssl_cs ); 00427 if (libssl_handle) 00428 { 00429 LeaveCriticalSection( &init_ssl_cs ); 00430 return TRUE; 00431 } 00432 if (!(libssl_handle = wine_dlopen( SONAME_LIBSSL, RTLD_NOW, NULL, 0 ))) 00433 { 00434 ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBSSL); 00435 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); 00436 LeaveCriticalSection( &init_ssl_cs ); 00437 return FALSE; 00438 } 00439 if (!(libcrypto_handle = wine_dlopen( SONAME_LIBCRYPTO, RTLD_NOW, NULL, 0 ))) 00440 { 00441 ERR("Trying to use SSL but couldn't load %s. Expect trouble.\n", SONAME_LIBCRYPTO); 00442 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); 00443 LeaveCriticalSection( &init_ssl_cs ); 00444 return FALSE; 00445 } 00446 #define LOAD_FUNCPTR(x) \ 00447 if (!(p##x = wine_dlsym( libssl_handle, #x, NULL, 0 ))) \ 00448 { \ 00449 ERR("Failed to load symbol %s\n", #x); \ 00450 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \ 00451 LeaveCriticalSection( &init_ssl_cs ); \ 00452 return FALSE; \ 00453 } 00454 LOAD_FUNCPTR( SSL_library_init ); 00455 LOAD_FUNCPTR( SSL_load_error_strings ); 00456 LOAD_FUNCPTR( SSLv23_method ); 00457 LOAD_FUNCPTR( SSL_CTX_free ); 00458 LOAD_FUNCPTR( SSL_CTX_new ); 00459 LOAD_FUNCPTR( SSL_new ); 00460 LOAD_FUNCPTR( SSL_free ); 00461 LOAD_FUNCPTR( SSL_set_fd ); 00462 LOAD_FUNCPTR( SSL_connect ); 00463 LOAD_FUNCPTR( SSL_shutdown ); 00464 LOAD_FUNCPTR( SSL_write ); 00465 LOAD_FUNCPTR( SSL_read ); 00466 LOAD_FUNCPTR( SSL_get_error ); 00467 LOAD_FUNCPTR( SSL_get_ex_new_index ); 00468 LOAD_FUNCPTR( SSL_get_ex_data ); 00469 LOAD_FUNCPTR( SSL_set_ex_data ); 00470 LOAD_FUNCPTR( SSL_get_ex_data_X509_STORE_CTX_idx ); 00471 LOAD_FUNCPTR( SSL_get_peer_certificate ); 00472 LOAD_FUNCPTR( SSL_CTX_set_default_verify_paths ); 00473 LOAD_FUNCPTR( SSL_CTX_set_verify ); 00474 LOAD_FUNCPTR( SSL_get_current_cipher ); 00475 LOAD_FUNCPTR( SSL_CIPHER_get_bits ); 00476 #undef LOAD_FUNCPTR 00477 00478 #define LOAD_FUNCPTR(x) \ 00479 if (!(p##x = wine_dlsym( libcrypto_handle, #x, NULL, 0 ))) \ 00480 { \ 00481 ERR("Failed to load symbol %s\n", #x); \ 00482 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); \ 00483 LeaveCriticalSection( &init_ssl_cs ); \ 00484 return FALSE; \ 00485 } 00486 LOAD_FUNCPTR( CRYPTO_num_locks ); 00487 LOAD_FUNCPTR( CRYPTO_set_id_callback ); 00488 LOAD_FUNCPTR( CRYPTO_set_locking_callback ); 00489 LOAD_FUNCPTR( ERR_free_strings ); 00490 LOAD_FUNCPTR( ERR_get_error ); 00491 LOAD_FUNCPTR( ERR_error_string ); 00492 LOAD_FUNCPTR( X509_STORE_CTX_get_ex_data ); 00493 LOAD_FUNCPTR( X509_STORE_CTX_get_chain ); 00494 LOAD_FUNCPTR( i2d_X509 ); 00495 LOAD_FUNCPTR( sk_value ); 00496 LOAD_FUNCPTR( sk_num ); 00497 #undef LOAD_FUNCPTR 00498 00499 pSSL_library_init(); 00500 pSSL_load_error_strings(); 00501 00502 method = pSSLv23_method(); 00503 ctx = pSSL_CTX_new( method ); 00504 if (!pSSL_CTX_set_default_verify_paths( ctx )) 00505 { 00506 ERR("SSL_CTX_set_default_verify_paths failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); 00507 set_last_error( ERROR_OUTOFMEMORY ); 00508 LeaveCriticalSection( &init_ssl_cs ); 00509 return FALSE; 00510 } 00511 hostname_idx = pSSL_get_ex_new_index( 0, (void *)"hostname index", NULL, NULL, NULL ); 00512 if (hostname_idx == -1) 00513 { 00514 ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); 00515 set_last_error( ERROR_OUTOFMEMORY ); 00516 LeaveCriticalSection( &init_ssl_cs ); 00517 return FALSE; 00518 } 00519 error_idx = pSSL_get_ex_new_index( 0, (void *)"error index", NULL, NULL, NULL ); 00520 if (error_idx == -1) 00521 { 00522 ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); 00523 set_last_error( ERROR_OUTOFMEMORY ); 00524 LeaveCriticalSection( &init_ssl_cs ); 00525 return FALSE; 00526 } 00527 conn_idx = pSSL_get_ex_new_index( 0, (void *)"netconn index", NULL, NULL, NULL ); 00528 if (conn_idx == -1) 00529 { 00530 ERR("SSL_get_ex_new_index failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); 00531 set_last_error( ERROR_OUTOFMEMORY ); 00532 LeaveCriticalSection( &init_ssl_cs ); 00533 return FALSE; 00534 } 00535 pSSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, netconn_secure_verify ); 00536 00537 pCRYPTO_set_id_callback(ssl_thread_id); 00538 num_ssl_locks = pCRYPTO_num_locks(); 00539 ssl_locks = HeapAlloc(GetProcessHeap(), 0, num_ssl_locks * sizeof(CRITICAL_SECTION)); 00540 if (!ssl_locks) 00541 { 00542 set_last_error( ERROR_OUTOFMEMORY ); 00543 LeaveCriticalSection( &init_ssl_cs ); 00544 return FALSE; 00545 } 00546 for (i = 0; i < num_ssl_locks; i++) InitializeCriticalSection( &ssl_locks[i] ); 00547 pCRYPTO_set_locking_callback(ssl_lock_callback); 00548 00549 LeaveCriticalSection( &init_ssl_cs ); 00550 #else 00551 WARN("SSL support not compiled in.\n"); 00552 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); 00553 return FALSE; 00554 #endif 00555 return TRUE; 00556 } 00557 00558 void netconn_unload( void ) 00559 { 00560 #if defined(SONAME_LIBSSL) && defined(SONAME_LIBCRYPTO) 00561 if (libcrypto_handle) 00562 { 00563 pERR_free_strings(); 00564 wine_dlclose( libcrypto_handle, NULL, 0 ); 00565 } 00566 if (libssl_handle) 00567 { 00568 if (ctx) 00569 pSSL_CTX_free( ctx ); 00570 wine_dlclose( libssl_handle, NULL, 0 ); 00571 } 00572 if (ssl_locks) 00573 { 00574 int i; 00575 for (i = 0; i < num_ssl_locks; i++) DeleteCriticalSection( &ssl_locks[i] ); 00576 HeapFree( GetProcessHeap(), 0, ssl_locks ); 00577 } 00578 #endif 00579 } 00580 00581 BOOL netconn_connected( netconn_t *conn ) 00582 { 00583 return (conn->socket != -1); 00584 } 00585 00586 BOOL netconn_create( netconn_t *conn, int domain, int type, int protocol ) 00587 { 00588 if ((conn->socket = socket( domain, type, protocol )) == -1) 00589 { 00590 WARN("unable to create socket (%s)\n", strerror(errno)); 00591 set_last_error( sock_get_error( errno ) ); 00592 return FALSE; 00593 } 00594 return TRUE; 00595 } 00596 00597 BOOL netconn_close( netconn_t *conn ) 00598 { 00599 int res; 00600 00601 #ifdef SONAME_LIBSSL 00602 if (conn->secure) 00603 { 00604 heap_free( conn->peek_msg_mem ); 00605 conn->peek_msg_mem = NULL; 00606 conn->peek_msg = NULL; 00607 conn->peek_len = 0; 00608 00609 pSSL_shutdown( conn->ssl_conn ); 00610 pSSL_free( conn->ssl_conn ); 00611 00612 conn->ssl_conn = NULL; 00613 conn->secure = FALSE; 00614 } 00615 #endif 00616 res = closesocket( conn->socket ); 00617 conn->socket = -1; 00618 if (res == -1) 00619 { 00620 set_last_error( sock_get_error( errno ) ); 00621 return FALSE; 00622 } 00623 return TRUE; 00624 } 00625 00626 BOOL netconn_connect( netconn_t *conn, const struct sockaddr *sockaddr, unsigned int addr_len, int timeout ) 00627 { 00628 BOOL ret = FALSE; 00629 int res = 0, state; 00630 00631 if (timeout > 0) 00632 { 00633 state = 1; 00634 ioctlsocket( conn->socket, FIONBIO, &state ); 00635 } 00636 if (connect( conn->socket, sockaddr, addr_len ) < 0) 00637 { 00638 res = sock_get_error( errno ); 00639 if (res == WSAEWOULDBLOCK || res == WSAEINPROGRESS) 00640 { 00641 fd_set outfd; 00642 struct timeval tv; 00643 00644 FD_ZERO(&outfd); 00645 FD_SET(conn->socket, &outfd); 00646 00647 tv.tv_sec = 0; 00648 tv.tv_usec = timeout * 1000; 00649 00650 if (select( 0, NULL, &outfd, NULL, &tv ) > 0) 00651 ret = TRUE; 00652 else 00653 res = sock_get_error( errno ); 00654 } 00655 } 00656 else 00657 ret = TRUE; 00658 if (timeout > 0) 00659 { 00660 state = 0; 00661 ioctlsocket( conn->socket, FIONBIO, &state ); 00662 } 00663 if (!ret) 00664 { 00665 WARN("unable to connect to host (%d)\n", res); 00666 set_last_error( res ); 00667 } 00668 return ret; 00669 } 00670 00671 BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname ) 00672 { 00673 #ifdef SONAME_LIBSSL 00674 if (!(conn->ssl_conn = pSSL_new( ctx ))) 00675 { 00676 ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); 00677 set_last_error( ERROR_OUTOFMEMORY ); 00678 goto fail; 00679 } 00680 if (!pSSL_set_ex_data( conn->ssl_conn, hostname_idx, hostname )) 00681 { 00682 ERR("SSL_set_ex_data failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); 00683 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); 00684 goto fail; 00685 } 00686 if (!pSSL_set_ex_data( conn->ssl_conn, conn_idx, conn )) 00687 { 00688 ERR("SSL_set_ex_data failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); 00689 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); 00690 return FALSE; 00691 } 00692 if (!pSSL_set_fd( conn->ssl_conn, conn->socket )) 00693 { 00694 ERR("SSL_set_fd failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); 00695 set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); 00696 goto fail; 00697 } 00698 if (pSSL_connect( conn->ssl_conn ) <= 0) 00699 { 00700 DWORD err; 00701 00702 err = (DWORD_PTR)pSSL_get_ex_data( conn->ssl_conn, error_idx ); 00703 if (!err) err = ERROR_WINHTTP_SECURE_CHANNEL_ERROR; 00704 ERR("couldn't verify server certificate (%d)\n", err); 00705 set_last_error( err ); 00706 goto fail; 00707 } 00708 TRACE("established SSL connection\n"); 00709 conn->secure = TRUE; 00710 return TRUE; 00711 00712 fail: 00713 if (conn->ssl_conn) 00714 { 00715 pSSL_shutdown( conn->ssl_conn ); 00716 pSSL_free( conn->ssl_conn ); 00717 conn->ssl_conn = NULL; 00718 } 00719 #endif 00720 return FALSE; 00721 } 00722 00723 BOOL netconn_send( netconn_t *conn, const void *msg, size_t len, int flags, int *sent ) 00724 { 00725 if (!netconn_connected( conn )) return FALSE; 00726 if (conn->secure) 00727 { 00728 #ifdef SONAME_LIBSSL 00729 if (flags) FIXME("SSL_write doesn't support any flags (%08x)\n", flags); 00730 *sent = pSSL_write( conn->ssl_conn, msg, len ); 00731 if (*sent < 1 && len) return FALSE; 00732 return TRUE; 00733 #else 00734 return FALSE; 00735 #endif 00736 } 00737 if ((*sent = send( conn->socket, msg, len, flags )) == -1) 00738 { 00739 set_last_error( sock_get_error( errno ) ); 00740 return FALSE; 00741 } 00742 return TRUE; 00743 } 00744 00745 BOOL netconn_recv( netconn_t *conn, void *buf, size_t len, int flags, int *recvd ) 00746 { 00747 int ret; 00748 00749 *recvd = 0; 00750 if (!netconn_connected( conn )) return FALSE; 00751 if (!len) return TRUE; 00752 00753 if (conn->secure) 00754 { 00755 #ifdef SONAME_LIBSSL 00756 if (flags & ~(MSG_PEEK | MSG_WAITALL)) 00757 FIXME("SSL_read does not support the following flags: %08x\n", flags); 00758 00759 /* this ugly hack is all for MSG_PEEK */ 00760 if (flags & MSG_PEEK && !conn->peek_msg) 00761 { 00762 if (!(conn->peek_msg = conn->peek_msg_mem = heap_alloc( len + 1 ))) return FALSE; 00763 } 00764 else if (flags & MSG_PEEK && conn->peek_msg) 00765 { 00766 if (len < conn->peek_len) FIXME("buffer isn't big enough, should we wrap?\n"); 00767 *recvd = min( len, conn->peek_len ); 00768 memcpy( buf, conn->peek_msg, *recvd ); 00769 return TRUE; 00770 } 00771 else if (conn->peek_msg) 00772 { 00773 *recvd = min( len, conn->peek_len ); 00774 memcpy( buf, conn->peek_msg, *recvd ); 00775 conn->peek_len -= *recvd; 00776 conn->peek_msg += *recvd; 00777 00778 if (conn->peek_len == 0) 00779 { 00780 heap_free( conn->peek_msg_mem ); 00781 conn->peek_msg_mem = NULL; 00782 conn->peek_msg = NULL; 00783 } 00784 /* check if we have enough data from the peek buffer */ 00785 if (!(flags & MSG_WAITALL) || (*recvd == len)) return TRUE; 00786 } 00787 ret = pSSL_read( conn->ssl_conn, (char *)buf + *recvd, len - *recvd ); 00788 if (ret < 0) 00789 return FALSE; 00790 00791 /* check if EOF was received */ 00792 if (!ret && (pSSL_get_error( conn->ssl_conn, ret ) == SSL_ERROR_ZERO_RETURN || 00793 pSSL_get_error( conn->ssl_conn, ret ) == SSL_ERROR_SYSCALL )) 00794 { 00795 netconn_close( conn ); 00796 return TRUE; 00797 } 00798 if (flags & MSG_PEEK) /* must copy into buffer */ 00799 { 00800 conn->peek_len = ret; 00801 if (!ret) 00802 { 00803 heap_free( conn->peek_msg_mem ); 00804 conn->peek_msg_mem = NULL; 00805 conn->peek_msg = NULL; 00806 } 00807 else memcpy( conn->peek_msg, buf, ret ); 00808 } 00809 *recvd = ret; 00810 return TRUE; 00811 #else 00812 return FALSE; 00813 #endif 00814 } 00815 if ((*recvd = recv( conn->socket, buf, len, flags )) == -1) 00816 { 00817 set_last_error( sock_get_error( errno ) ); 00818 return FALSE; 00819 } 00820 return TRUE; 00821 } 00822 00823 BOOL netconn_query_data_available( netconn_t *conn, DWORD *available ) 00824 { 00825 #ifdef FIONREAD 00826 int ret, unread; 00827 #endif 00828 *available = 0; 00829 if (!netconn_connected( conn )) return FALSE; 00830 00831 if (conn->secure) 00832 { 00833 #ifdef SONAME_LIBSSL 00834 if (conn->peek_msg) *available = conn->peek_len; 00835 #endif 00836 return TRUE; 00837 } 00838 #ifdef FIONREAD 00839 if (!(ret = ioctlsocket( conn->socket, FIONREAD, &unread ))) *available = unread; 00840 #endif 00841 return TRUE; 00842 } 00843 00844 BOOL netconn_get_next_line( netconn_t *conn, char *buffer, DWORD *buflen ) 00845 { 00846 fd_set infd; 00847 BOOL ret = FALSE; 00848 DWORD recvd = 0; 00849 00850 if (!netconn_connected( conn )) return FALSE; 00851 00852 if (conn->secure) 00853 { 00854 #ifdef SONAME_LIBSSL 00855 while (recvd < *buflen) 00856 { 00857 int dummy; 00858 if (!netconn_recv( conn, &buffer[recvd], 1, 0, &dummy )) 00859 { 00860 set_last_error( ERROR_CONNECTION_ABORTED ); 00861 break; 00862 } 00863 if (buffer[recvd] == '\n') 00864 { 00865 ret = TRUE; 00866 break; 00867 } 00868 if (buffer[recvd] != '\r') recvd++; 00869 } 00870 if (ret) 00871 { 00872 buffer[recvd++] = 0; 00873 *buflen = recvd; 00874 TRACE("received line %s\n", debugstr_a(buffer)); 00875 } 00876 return ret; 00877 #else 00878 return FALSE; 00879 #endif 00880 } 00881 00882 FD_ZERO(&infd); 00883 FD_SET(conn->socket, &infd); 00884 00885 while (recvd < *buflen) 00886 { 00887 int res; 00888 struct timeval tv, *ptv; 00889 socklen_t len = sizeof(tv); 00890 00891 if ((res = getsockopt( conn->socket, SOL_SOCKET, SO_RCVTIMEO, (void*)&tv, &len ) != -1)) 00892 ptv = &tv; 00893 else 00894 ptv = NULL; 00895 00896 if (select( 0, &infd, NULL, NULL, ptv ) > 0) 00897 { 00898 if ((res = recv( conn->socket, &buffer[recvd], 1, 0 )) <= 0) 00899 { 00900 if (res == -1) set_last_error( sock_get_error( errno ) ); 00901 break; 00902 } 00903 if (buffer[recvd] == '\n') 00904 { 00905 ret = TRUE; 00906 break; 00907 } 00908 if (buffer[recvd] != '\r') recvd++; 00909 } 00910 else 00911 { 00912 set_last_error( ERROR_WINHTTP_TIMEOUT ); 00913 break; 00914 } 00915 } 00916 if (ret) 00917 { 00918 buffer[recvd++] = 0; 00919 *buflen = recvd; 00920 TRACE("received line %s\n", debugstr_a(buffer)); 00921 } 00922 return ret; 00923 } 00924 00925 DWORD netconn_set_timeout( netconn_t *netconn, BOOL send, int value ) 00926 { 00927 int res; 00928 struct timeval tv; 00929 00930 /* value is in milliseconds, convert to struct timeval */ 00931 tv.tv_sec = value / 1000; 00932 tv.tv_usec = (value % 1000) * 1000; 00933 00934 if ((res = setsockopt( netconn->socket, SOL_SOCKET, send ? SO_SNDTIMEO : SO_RCVTIMEO, (void*)&tv, sizeof(tv) ) == -1)) 00935 { 00936 WARN("setsockopt failed (%s)\n", strerror( errno )); 00937 return sock_get_error( errno ); 00938 } 00939 return ERROR_SUCCESS; 00940 } 00941 00942 static DWORD resolve_hostname( WCHAR *hostnameW, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len ) 00943 { 00944 char *hostname; 00945 #ifdef HAVE_GETADDRINFO 00946 struct addrinfo *res, hints; 00947 int ret; 00948 #else 00949 struct hostent *he; 00950 struct sockaddr_in *sin = (struct sockaddr_in *)sa; 00951 #endif 00952 00953 if (!(hostname = strdupWA( hostnameW ))) return ERROR_OUTOFMEMORY; 00954 00955 #ifdef HAVE_GETADDRINFO 00956 memset( &hints, 0, sizeof(struct addrinfo) ); 00957 /* Prefer IPv4 to IPv6 addresses, since some web servers do not listen on 00958 * their IPv6 addresses even though they have IPv6 addresses in the DNS. 00959 */ 00960 hints.ai_family = AF_INET; 00961 00962 ret = getaddrinfo( hostname, NULL, &hints, &res ); 00963 if (ret != 0) 00964 { 00965 TRACE("failed to get IPv4 address of %s (%s), retrying with IPv6\n", debugstr_w(hostnameW), gai_strerror(ret)); 00966 hints.ai_family = AF_INET6; 00967 ret = getaddrinfo( hostname, NULL, &hints, &res ); 00968 if (ret != 0) 00969 { 00970 TRACE("failed to get address of %s (%s)\n", debugstr_w(hostnameW), gai_strerror(ret)); 00971 heap_free( hostname ); 00972 return ERROR_WINHTTP_NAME_NOT_RESOLVED; 00973 } 00974 } 00975 heap_free( hostname ); 00976 if (*sa_len < res->ai_addrlen) 00977 { 00978 WARN("address too small\n"); 00979 freeaddrinfo( res ); 00980 return ERROR_WINHTTP_NAME_NOT_RESOLVED; 00981 } 00982 *sa_len = res->ai_addrlen; 00983 memcpy( sa, res->ai_addr, res->ai_addrlen ); 00984 /* Copy port */ 00985 switch (res->ai_family) 00986 { 00987 case AF_INET: 00988 ((struct sockaddr_in *)sa)->sin_port = htons( port ); 00989 break; 00990 case AF_INET6: 00991 ((struct sockaddr_in6 *)sa)->sin6_port = htons( port ); 00992 break; 00993 } 00994 00995 freeaddrinfo( res ); 00996 return ERROR_SUCCESS; 00997 #else 00998 EnterCriticalSection( &cs_gethostbyname ); 00999 01000 he = gethostbyname( hostname ); 01001 heap_free( hostname ); 01002 if (!he) 01003 { 01004 TRACE("failed to get address of %s (%d)\n", debugstr_w(hostnameW), h_errno); 01005 LeaveCriticalSection( &cs_gethostbyname ); 01006 return ERROR_WINHTTP_NAME_NOT_RESOLVED; 01007 } 01008 if (*sa_len < sizeof(struct sockaddr_in)) 01009 { 01010 WARN("address too small\n"); 01011 LeaveCriticalSection( &cs_gethostbyname ); 01012 return ERROR_WINHTTP_NAME_NOT_RESOLVED; 01013 } 01014 *sa_len = sizeof(struct sockaddr_in); 01015 memset( sa, 0, sizeof(struct sockaddr_in) ); 01016 memcpy( &sin->sin_addr, he->h_addr, he->h_length ); 01017 sin->sin_family = he->h_addrtype; 01018 sin->sin_port = htons( port ); 01019 01020 LeaveCriticalSection( &cs_gethostbyname ); 01021 return ERROR_SUCCESS; 01022 #endif 01023 } 01024 01025 struct resolve_args 01026 { 01027 WCHAR *hostname; 01028 INTERNET_PORT port; 01029 struct sockaddr *sa; 01030 socklen_t *sa_len; 01031 }; 01032 01033 static DWORD CALLBACK resolve_proc( LPVOID arg ) 01034 { 01035 struct resolve_args *ra = arg; 01036 return resolve_hostname( ra->hostname, ra->port, ra->sa, ra->sa_len ); 01037 } 01038 01039 BOOL netconn_resolve( WCHAR *hostname, INTERNET_PORT port, struct sockaddr *sa, socklen_t *sa_len, int timeout ) 01040 { 01041 DWORD ret; 01042 01043 if (timeout) 01044 { 01045 DWORD status; 01046 HANDLE thread; 01047 struct resolve_args ra; 01048 01049 ra.hostname = hostname; 01050 ra.port = port; 01051 ra.sa = sa; 01052 ra.sa_len = sa_len; 01053 01054 thread = CreateThread( NULL, 0, resolve_proc, &ra, 0, NULL ); 01055 if (!thread) return FALSE; 01056 01057 status = WaitForSingleObject( thread, timeout ); 01058 if (status == WAIT_OBJECT_0) GetExitCodeThread( thread, &ret ); 01059 else ret = ERROR_WINHTTP_TIMEOUT; 01060 CloseHandle( thread ); 01061 } 01062 else ret = resolve_hostname( hostname, port, sa, sa_len ); 01063 01064 if (ret) 01065 { 01066 set_last_error( ret ); 01067 return FALSE; 01068 } 01069 return TRUE; 01070 } 01071 01072 const void *netconn_get_certificate( netconn_t *conn ) 01073 { 01074 #ifdef SONAME_LIBSSL 01075 X509 *cert; 01076 const CERT_CONTEXT *ret; 01077 01078 if (!conn->secure) return NULL; 01079 01080 if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL; 01081 ret = X509_to_cert_context( cert ); 01082 return ret; 01083 #else 01084 return NULL; 01085 #endif 01086 } 01087 01088 int netconn_get_cipher_strength( netconn_t *conn ) 01089 { 01090 #ifdef SONAME_LIBSSL 01091 #if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER >= 0x0090707f) 01092 const SSL_CIPHER *cipher; 01093 #else 01094 SSL_CIPHER *cipher; 01095 #endif 01096 int bits = 0; 01097 01098 if (!conn->secure) return 0; 01099 if (!(cipher = pSSL_get_current_cipher( conn->ssl_conn ))) return 0; 01100 pSSL_CIPHER_get_bits( cipher, &bits ); 01101 return bits; 01102 #else 01103 return 0; 01104 #endif 01105 } Generated on Fri May 25 2012 04:15:29 for ReactOS by
1.7.6.1
|