BOOL netconn_secure_connect( netconn_t *conn ) { #ifdef SONAME_LIBSSL X509 *cert; long res; ctx = pSSL_CTX_new( method ); 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 )); set_last_error( ERROR_OUTOFMEMORY ); return FALSE; } if (!(conn->ssl_conn = pSSL_new( ctx ))) { ERR("SSL_new failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); set_last_error( ERROR_OUTOFMEMORY ); goto fail; } if (!pSSL_set_fd( conn->ssl_conn, conn->socket )) { ERR("SSL_set_fd failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); goto fail; } if (pSSL_connect( conn->ssl_conn ) <= 0) { ERR("SSL_connect failed: %s\n", pERR_error_string( pERR_get_error(), 0 )); set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); goto fail; } if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) { ERR("No certificate for server: %s\n", pERR_error_string( pERR_get_error(), 0 )); set_last_error( ERROR_WINHTTP_SECURE_CHANNEL_ERROR ); goto fail; } if ((res = pSSL_get_verify_result( conn->ssl_conn )) != X509_V_OK) { /* FIXME: we should set an error and return, but we only print an error at the moment */ ERR("couldn't verify server certificate (%ld)\n", res); } TRACE("established SSL connection\n"); conn->secure = TRUE; return TRUE; fail: if (conn->ssl_conn) { pSSL_shutdown( conn->ssl_conn ); pSSL_free( conn->ssl_conn ); conn->ssl_conn = NULL; } #endif return FALSE; }
const void *netconn_get_certificate( netconn_t *conn ) { #ifdef SONAME_LIBSSL X509 *cert; const CERT_CONTEXT *ret; if (!conn->secure) return NULL; if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL; ret = X509_to_cert_context( cert ); return ret; #else return NULL; #endif }
LPCVOID NETCON_GetCert(netconn_t *connection) { #ifdef SONAME_LIBSSL X509* cert; LPCVOID r = NULL; if (!connection->ssl_s) return NULL; cert = pSSL_get_peer_certificate(connection->ssl_s); r = X509_to_cert_context(cert); return r; #else return NULL; #endif }
LPCVOID NETCON_GetCert(WININET_NETCONNECTION *connection) { #ifdef SONAME_LIBSSL X509* cert; unsigned char* buffer,*p; INT len; BOOL malloced = FALSE; LPCVOID r = NULL; if (!connection->useSSL) return NULL; cert = pSSL_get_peer_certificate(connection->ssl_s); 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) { buffer = HeapAlloc(GetProcessHeap(),0,len); p = buffer; len = pi2d_X509(cert,&p); } else { buffer = p; malloced = TRUE; } r = CertCreateCertificateContext(X509_ASN_ENCODING,buffer,len); if (malloced) free(buffer); else HeapFree(GetProcessHeap(),0,buffer); return r; #else return NULL; #endif }
const void *netconn_get_certificate( netconn_t *conn ) { #ifdef SONAME_LIBSSL X509 *cert; unsigned char *buffer, *p; int len; BOOL malloc = FALSE; const CERT_CONTEXT *ret; if (!conn->secure) return NULL; if (!(cert = pSSL_get_peer_certificate( conn->ssl_conn ))) return NULL; p = NULL; if ((len = pi2d_X509( cert, &p )) < 0) return NULL; /* * 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) { if (!(buffer = heap_alloc( len ))) return NULL; p = buffer; len = pi2d_X509( cert, &p ); } else { buffer = p; malloc = TRUE; } ret = CertCreateCertificateContext( X509_ASN_ENCODING, buffer, len ); if (malloc) free( buffer ); else heap_free( buffer ); return ret; #else return NULL; #endif }
/****************************************************************************** * NETCON_secure_connect * Initiates a secure connection over an existing plaintext connection. */ BOOL NETCON_secure_connect(WININET_NETCONNECTION *connection, LPCWSTR hostname) { #ifdef SONAME_LIBSSL long verify_res; X509 *cert; int len; char *hostname_unix; /* can't connect if we are already connected */ if (connection->useSSL) { ERR("already connected\n"); return FALSE; } 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)); INTERNET_SetLastError(ERROR_OUTOFMEMORY); return FALSE; } connection->ssl_s = pSSL_new(ctx); if (!connection->ssl_s) { ERR("SSL_new failed: %s\n", pERR_error_string(pERR_get_error(), 0)); INTERNET_SetLastError(ERROR_OUTOFMEMORY); goto fail; } if (!pSSL_set_fd(connection->ssl_s, connection->socketFD)) { ERR("SSL_set_fd failed: %s\n", pERR_error_string(pERR_get_error(), 0)); INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); goto fail; } if (pSSL_connect(connection->ssl_s) <= 0) { ERR("SSL_connect failed: %s\n", pERR_error_string(pERR_get_error(), 0)); INTERNET_SetLastError(ERROR_INTERNET_SECURITY_CHANNEL_ERROR); goto fail; } cert = pSSL_get_peer_certificate(connection->ssl_s); if (!cert) { ERR("no certificate for server %s\n", debugstr_w(hostname)); /* FIXME: is this the best error? */ INTERNET_SetLastError(ERROR_INTERNET_INVALID_CA); goto fail; } verify_res = pSSL_get_verify_result(connection->ssl_s); if (verify_res != X509_V_OK) { ERR("couldn't verify the security of the connection, %ld\n", verify_res); /* FIXME: we should set an error and return, but we only warn at * the moment */ } len = WideCharToMultiByte(CP_UNIXCP, 0, hostname, -1, NULL, 0, NULL, NULL); hostname_unix = HeapAlloc(GetProcessHeap(), 0, len); if (!hostname_unix) { INTERNET_SetLastError(ERROR_OUTOFMEMORY); goto fail; } WideCharToMultiByte(CP_UNIXCP, 0, hostname, -1, hostname_unix, len, NULL, NULL); if (!check_hostname(cert, hostname_unix)) { HeapFree(GetProcessHeap(), 0, hostname_unix); INTERNET_SetLastError(ERROR_INTERNET_SEC_CERT_CN_INVALID); goto fail; } HeapFree(GetProcessHeap(), 0, hostname_unix); connection->useSSL = TRUE; return TRUE; fail: if (connection->ssl_s) { pSSL_shutdown(connection->ssl_s); pSSL_free(connection->ssl_s); connection->ssl_s = NULL; } #endif return FALSE; }