Signed-off-by: Hans Leidekker <hans(a)codeweavers.com>
---
dlls/secur32/schannel.c | 252 ++++++++++++++++++-------
dlls/secur32/schannel_gnutls.c | 323 +++++++++++++--------------------
dlls/secur32/schannel_macosx.c | 210 ++++++++++++---------
dlls/secur32/secur32.c | 3 +
dlls/secur32/secur32_priv.h | 81 +++++----
5 files changed, 477 insertions(+), 392 deletions(-)
diff --git a/dlls/secur32/schannel.c b/dlls/secur32/schannel.c
index 1dd3a029401..5f6b96903c4 100644
--- a/dlls/secur32/schannel.c
+++ b/dlls/secur32/schannel.c
@@ -17,9 +17,8 @@
*
* This file implements the schannel provider, or, the SSL/TLS implementations.
*/
-#include "config.h"
-#include "wine/port.h"
+#include <assert.h>
#include <stdarg.h>
#include <errno.h>
@@ -28,6 +27,7 @@
#include "winbase.h"
#include "winreg.h"
#include "winnls.h"
+#include "lmcons.h"
#include "sspi.h"
#include "schannel.h"
#include "secur32_priv.h"
@@ -37,7 +37,7 @@
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
-#if defined(SONAME_LIBGNUTLS) || defined (HAVE_SECURITY_SECURITY_H)
+const struct schan_funcs *schan_funcs = NULL;
#define SCHAN_INVALID_HANDLE ~0UL
@@ -56,7 +56,7 @@ struct schan_handle
struct schan_context
{
- schan_imp_session session;
+ schan_session session;
struct schan_transport transport;
ULONG req_ctx_attr;
const CERT_CONTEXT *cert;
@@ -242,7 +242,7 @@ static void read_config(void)
RegCloseKey(protocols_key);
- config_enabled_protocols = enabled & schan_imp_enabled_protocols();
+ config_enabled_protocols = enabled & schan_funcs->get_enabled_protocols();
config_default_disabled_protocols = default_disabled;
config_read = TRUE;
@@ -389,6 +389,116 @@ static SECURITY_STATUS get_cert(const SCHANNEL_CRED *cred, CERT_CONTEXT const **
return status;
}
+static WCHAR *get_key_container_path(const CERT_CONTEXT *ctx)
+{
+ static const WCHAR rsabaseW[] =
+ {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','C','r','y','p','t','o','\\','R','S','A','\\',0};
+ CERT_KEY_CONTEXT keyctx;
+ DWORD size = sizeof(keyctx), prov_size = 0;
+ CRYPT_KEY_PROV_INFO *prov;
+ WCHAR username[UNLEN + 1], *ret = NULL;
+ DWORD len = ARRAY_SIZE(username);
+
+ if (CertGetCertificateContextProperty(ctx, CERT_KEY_CONTEXT_PROP_ID, &keyctx, &size))
+ {
+ char *str;
+ if (!CryptGetProvParam(keyctx.hCryptProv, PP_CONTAINER, NULL, &size, 0)) return NULL;
+ if (!(str = RtlAllocateHeap(GetProcessHeap(), 0, size))) return NULL;
+ if (!CryptGetProvParam(keyctx.hCryptProv, PP_CONTAINER, (BYTE *)str, &size, 0)) return NULL;
+
+ len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
+ if (!(ret = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(rsabaseW) + len * sizeof(WCHAR))))
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, str);
+ return NULL;
+ }
+ strcpyW(ret, rsabaseW);
+ MultiByteToWideChar(CP_ACP, 0, str, -1, ret + strlenW(ret), len);
+ RtlFreeHeap(GetProcessHeap(), 0, str);
+ }
+ else if (CertGetCertificateContextProperty(ctx, CERT_KEY_PROV_INFO_PROP_ID, NULL, &prov_size))
+ {
+ if (!(prov = RtlAllocateHeap(GetProcessHeap(), 0, prov_size))) return NULL;
+ if (!CertGetCertificateContextProperty(ctx, CERT_KEY_PROV_INFO_PROP_ID, prov, &prov_size))
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, prov);
+ return NULL;
+ }
+ if (!(ret = RtlAllocateHeap(GetProcessHeap(), 0,
+ sizeof(rsabaseW) + strlenW(prov->pwszContainerName) * sizeof(WCHAR))))
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, prov);
+ return NULL;
+ }
+ strcpyW(ret, rsabaseW);
+ strcatW(ret, prov->pwszContainerName);
+ RtlFreeHeap(GetProcessHeap(), 0, prov);
+ }
+
+ if (!ret && GetUserNameW(username, &len) && (ret = RtlAllocateHeap(GetProcessHeap(), 0,
+ sizeof(rsabaseW) + len * sizeof(WCHAR))))
+ {
+ strcpyW(ret, rsabaseW);
+ strcatW(ret, username);
+ }
+
+ return ret;
+}
+
+#define MAX_LEAD_BYTES 8
+static BYTE *get_key_blob(const CERT_CONTEXT *ctx, DWORD *size)
+{
+ static const WCHAR keyexchangeW[] =
+ {'K','e','y','E','x','c','h','a','n','g','e','K','e','y','P','a','i','r',0};
+ static const WCHAR signatureW[] =
+ {'S','i','g','n','a','t','u','r','e','K','e','y','P','a','i','r',0};
+ BYTE *buf, *ret = NULL;
+ DATA_BLOB blob_in, blob_out;
+ DWORD spec = 0, type, len;
+ WCHAR *path;
+ HKEY hkey;
+
+ if (!(path = get_key_container_path(ctx))) return NULL;
+ if (RegOpenKeyExW(HKEY_CURRENT_USER, path, 0, KEY_READ, &hkey))
+ {
+ RtlFreeHeap(GetProcessHeap(), 0, path);
+ return NULL;
+ }
+ RtlFreeHeap(GetProcessHeap(), 0, path);
+
+ if (!RegQueryValueExW(hkey, keyexchangeW, 0, &type, NULL, &len)) spec = AT_KEYEXCHANGE;
+ else if (!RegQueryValueExW(hkey, signatureW, 0, &type, NULL, &len)) spec = AT_SIGNATURE;
+ else
+ {
+ RegCloseKey(hkey);
+ return NULL;
+ }
+
+ if (!(buf = RtlAllocateHeap(GetProcessHeap(), 0, len + MAX_LEAD_BYTES)))
+ {
+ RegCloseKey(hkey);
+ return NULL;
+ }
+
+ if (!RegQueryValueExW(hkey, (spec == AT_KEYEXCHANGE) ? keyexchangeW : signatureW, 0, &type, buf, &len))
+ {
+ blob_in.pbData = buf;
+ blob_in.cbData = len;
+ if (CryptUnprotectData(&blob_in, NULL, NULL, NULL, NULL, 0, &blob_out))
+ {
+ assert(blob_in.cbData >= blob_out.cbData);
+ memcpy(buf, blob_out.pbData, blob_out.cbData);
+ LocalFree(blob_out.pbData);
+ *size = blob_out.cbData + MAX_LEAD_BYTES;
+ ret = buf;
+ }
+ }
+ else RtlFreeHeap(GetProcessHeap(), 0, buf);
+
+ RegCloseKey(hkey);
+ return ret;
+}
+
static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schanCred,
PCredHandle phCredential, PTimeStamp ptsExpiry)
{
@@ -397,6 +507,7 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan
ULONG_PTR handle;
SECURITY_STATUS status = SEC_E_OK;
const CERT_CONTEXT *cert = NULL;
+ DATA_BLOB key_blob = {0};
TRACE("schanCred %p, phCredential %p, ptsExpiry %p\n", schanCred, phCredential, ptsExpiry);
@@ -426,20 +537,17 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan
return SEC_E_NO_AUTHENTICATING_AUTHORITY;
}
- creds = heap_alloc(sizeof(*creds));
- if (!creds) return SEC_E_INSUFFICIENT_MEMORY;
+ if (!(creds = heap_alloc(sizeof(*creds)))) return SEC_E_INSUFFICIENT_MEMORY;
+ creds->credential_use = SECPKG_CRED_OUTBOUND;
+ creds->enabled_protocols = enabled_protocols;
+
+ if (cert && !(key_blob.pbData = get_key_blob(cert, &key_blob.cbData))) goto fail;
+ if (!schan_funcs->allocate_certificate_credentials(creds, cert, &key_blob)) goto fail;
+ RtlFreeHeap(GetProcessHeap(), 0, key_blob.pbData);
handle = schan_alloc_handle(creds, SCHAN_HANDLE_CRED);
if (handle == SCHAN_INVALID_HANDLE) goto fail;
- creds->credential_use = SECPKG_CRED_OUTBOUND;
- if (!schan_imp_allocate_certificate_credentials(creds, cert))
- {
- schan_free_handle(handle, SCHAN_HANDLE_CRED);
- goto fail;
- }
-
- creds->enabled_protocols = enabled_protocols;
phCredential->dwLower = handle;
phCredential->dwUpper = 0;
@@ -454,6 +562,7 @@ static SECURITY_STATUS schan_AcquireClientCredentials(const SCHANNEL_CRED *schan
fail:
heap_free(creds);
+ RtlFreeHeap(GetProcessHeap(), 0, key_blob.pbData);
return SEC_E_INTERNAL_ERROR;
}
@@ -542,10 +651,8 @@ static SECURITY_STATUS SEC_ENTRY schan_FreeCredentialsHandle(
creds = schan_free_handle(phCredential->dwLower, SCHAN_HANDLE_CRED);
if (!creds) return SEC_E_INVALID_HANDLE;
- if (creds->credential_use == SECPKG_CRED_OUTBOUND)
- schan_imp_free_certificate_credentials(creds);
+ if (creds->credential_use == SECPKG_CRED_OUTBOUND) schan_funcs->free_certificate_credentials(creds);
heap_free(creds);
-
return SEC_E_OK;
}
@@ -599,7 +706,7 @@ static void schan_resize_current_buffer(const struct schan_buffers *s, SIZE_T mi
b->pvBuffer = new_data;
}
-char *schan_get_buffer(const struct schan_transport *t, struct schan_buffers *s, SIZE_T *count)
+static char * CDECL schan_get_buffer(const struct schan_transport *t, struct schan_buffers *s, SIZE_T *count)
{
SIZE_T max_count;
PSecBuffer buffer;
@@ -672,7 +779,7 @@ char *schan_get_buffer(const struct schan_transport *t, struct schan_buffers *s,
* another errno-style error value on failure
*
*/
-int schan_pull(struct schan_transport *t, void *buff, size_t *buff_len)
+static int CDECL schan_pull(struct schan_transport *t, void *buff, size_t *buff_len)
{
char *b;
SIZE_T local_len = *buff_len;
@@ -711,7 +818,7 @@ int schan_pull(struct schan_transport *t, void *buff, size_t *buff_len)
* another errno-style error value on failure
*
*/
-int schan_push(struct schan_transport *t, const void *buff, size_t *buff_len)
+static int CDECL schan_push(struct schan_transport *t, const void *buff, size_t *buff_len)
{
char *b;
SIZE_T local_len = *buff_len;
@@ -733,7 +840,7 @@ int schan_push(struct schan_transport *t, const void *buff, size_t *buff_len)
return 0;
}
-schan_imp_session schan_session_for_transport(struct schan_transport* t)
+static schan_session CDECL schan_get_session_for_transport(struct schan_transport* t)
{
return t->ctx->session;
}
@@ -845,7 +952,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
return SEC_E_INTERNAL_ERROR;
}
- if (!schan_imp_create_session(&ctx->session, cred))
+ if (!schan_funcs->create_session(&ctx->session, cred))
{
schan_free_handle(handle, SCHAN_HANDLE_CTX);
heap_free(ctx);
@@ -858,7 +965,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
ctx->header_size = HEADER_SIZE_TLS;
ctx->transport.ctx = ctx;
- schan_imp_set_session_transport(ctx->session, &ctx->transport);
+ schan_funcs->set_session_transport(ctx->session, &ctx->transport);
if (pszTargetName && *pszTargetName)
{
@@ -868,7 +975,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
if (target)
{
WideCharToMultiByte( CP_UNIXCP, 0, pszTargetName, -1, target, len, NULL, NULL );
- schan_imp_set_session_target( ctx->session, target );
+ schan_funcs->set_session_target( ctx->session, target );
heap_free( target );
}
}
@@ -876,13 +983,13 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
if (pInput && (idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_APPLICATION_PROTOCOLS)) != -1)
{
buffer = &pInput->pBuffers[idx];
- schan_imp_set_application_protocols(ctx->session, buffer->pvBuffer, buffer->cbBuffer);
+ schan_funcs->set_application_protocols(ctx->session, buffer->pvBuffer, buffer->cbBuffer);
}
if (pInput && (idx = schan_find_sec_buffer_idx(pInput, 0, SECBUFFER_DTLS_MTU)) != -1)
{
buffer = &pInput->pBuffers[idx];
- if (buffer->cbBuffer >= sizeof(WORD)) schan_imp_set_dtls_mtu(ctx->session, *(WORD *)buffer->pvBuffer);
+ if (buffer->cbBuffer >= sizeof(WORD)) schan_funcs->set_dtls_mtu(ctx->session, *(WORD *)buffer->pvBuffer);
else WARN("invalid buffer size %u\n", buffer->cbBuffer);
}
@@ -935,7 +1042,7 @@ static SECURITY_STATUS SEC_ENTRY schan_InitializeSecurityContextW(
init_schan_buffers(&ctx->transport.out, pOutput, schan_init_sec_ctx_get_next_output_buffer);
/* Perform the TLS handshake */
- ret = schan_imp_handshake(ctx->session);
+ ret = schan_funcs->handshake(ctx->session);
out_buffers = &ctx->transport.out;
if (out_buffers->current_buffer_idx != -1)
@@ -1027,18 +1134,33 @@ static void *get_alg_name(ALG_ID id, BOOL wide)
static SECURITY_STATUS ensure_remote_cert(struct schan_context *ctx)
{
- HCERTSTORE cert_store;
+ HCERTSTORE store;
+ PCCERT_CONTEXT cert = NULL;
SECURITY_STATUS status;
+ struct schan_cert_list list;
- if(ctx->cert)
- return SEC_E_OK;
-
- cert_store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL);
- if(!cert_store)
+ if (ctx->cert) return SEC_E_OK;
+ if (!(store = CertOpenStore(CERT_STORE_PROV_MEMORY, 0, 0, CERT_STORE_CREATE_NEW_FLAG, NULL)))
return GetLastError();
- status = schan_imp_get_session_peer_certificate(ctx->session, cert_store, &ctx->cert);
- CertCloseStore(cert_store, 0);
+ if ((status = schan_funcs->get_session_peer_certificate(ctx->session, &list)) == SEC_E_OK)
+ {
+ unsigned int i;
+ for (i = 0; i < list.count; i++)
+ {
+ if (!CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, list.certs[i].pbData,
+ list.certs[i].cbData, CERT_STORE_ADD_REPLACE_EXISTING,
+ i ? NULL : &cert))
+ {
+ if (i) CertFreeCertificateContext(cert);
+ return GetLastError();
+ }
+ }
+ RtlFreeHeap(GetProcessHeap(), 0, list.certs);
+ }
+
+ ctx->cert = cert;
+ CertCloseStore(store, 0);
return status;
}
@@ -1059,13 +1181,13 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
case SECPKG_ATTR_STREAM_SIZES:
{
SecPkgContext_ConnectionInfo info;
- status = schan_imp_get_connection_info(ctx->session, &info);
+ status = schan_funcs->get_connection_info(ctx->session, &info);
if (status == SEC_E_OK)
{
SecPkgContext_StreamSizes *stream_sizes = buffer;
SIZE_T mac_size = info.dwHashStrength;
- unsigned int block_size = schan_imp_get_session_cipher_block_size(ctx->session);
- unsigned int message_size = schan_imp_get_max_message_size(ctx->session);
+ unsigned int block_size = schan_funcs->get_session_cipher_block_size(ctx->session);
+ unsigned int message_size = schan_funcs->get_max_message_size(ctx->session);
TRACE("Using header size %lu mac bytes %lu, message size %u, block size %u\n",
ctx->header_size, mac_size, message_size, block_size);
@@ -1083,12 +1205,12 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
case SECPKG_ATTR_KEY_INFO:
{
SecPkgContext_ConnectionInfo conn_info;
- status = schan_imp_get_connection_info(ctx->session, &conn_info);
+ status = schan_funcs->get_connection_info(ctx->session, &conn_info);
if (status == SEC_E_OK)
{
SecPkgContext_KeyInfoW *info = buffer;
info->KeySize = conn_info.dwCipherStrength;
- info->SignatureAlgorithm = schan_imp_get_key_signature_algorithm(ctx->session);
+ info->SignatureAlgorithm = schan_funcs->get_key_signature_algorithm(ctx->session);
info->EncryptAlgorithm = conn_info.aiCipher;
info->sSignatureAlgorithmName = get_alg_name(info->SignatureAlgorithm, TRUE);
info->sEncryptAlgorithmName = get_alg_name(info->EncryptAlgorithm, TRUE);
@@ -1109,7 +1231,7 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
case SECPKG_ATTR_CONNECTION_INFO:
{
SecPkgContext_ConnectionInfo *info = buffer;
- return schan_imp_get_connection_info(ctx->session, info);
+ return schan_funcs->get_connection_info(ctx->session, info);
}
case SECPKG_ATTR_ENDPOINT_BINDINGS:
{
@@ -1154,12 +1276,12 @@ static SECURITY_STATUS SEC_ENTRY schan_QueryContextAttributesW(
case SECPKG_ATTR_UNIQUE_BINDINGS:
{
SecPkgContext_Bindings *bindings = buffer;
- return schan_imp_get_unique_channel_binding(ctx->session, bindings);
+ return schan_funcs->get_unique_channel_binding(ctx->session, bindings);
}
case SECPKG_ATTR_APPLICATION_PROTOCOL:
{
SecPkgContext_ApplicationProtocol *protocol = buffer;
- return schan_imp_get_application_protocol(ctx->session, protocol);
+ return schan_funcs->get_application_protocol(ctx->session, protocol);
}
default:
@@ -1289,7 +1411,7 @@ static SECURITY_STATUS SEC_ENTRY schan_EncryptMessage(PCtxtHandle context_handle
init_schan_buffers(&ctx->transport.out, message, schan_encrypt_message_get_next_buffer_token);
length = data_size;
- status = schan_imp_send(ctx->session, data, &length);
+ status = schan_funcs->send(ctx->session, data, &length);
TRACE("Sent %ld bytes.\n", length);
@@ -1422,7 +1544,7 @@ static SECURITY_STATUS SEC_ENTRY schan_DecryptMessage(PCtxtHandle context_handle
while (received < data_size)
{
SIZE_T length = data_size - received;
- status = schan_imp_recv(ctx->session, data + received, &length);
+ status = schan_funcs->recv(ctx->session, data + received, &length);
if (status == SEC_I_RENEGOTIATE)
break;
@@ -1478,11 +1600,9 @@ static SECURITY_STATUS SEC_ENTRY schan_DeleteSecurityContext(PCtxtHandle context
ctx = schan_free_handle(context_handle->dwLower, SCHAN_HANDLE_CTX);
if (!ctx) return SEC_E_INVALID_HANDLE;
- if (ctx->cert)
- CertFreeCertificateContext(ctx->cert);
- schan_imp_dispose_session(ctx->session);
+ if (ctx->cert) CertFreeCertificateContext(ctx->cert);
+ schan_funcs->dispose_session(ctx->session);
heap_free(ctx);
-
return SEC_E_OK;
}
@@ -1552,6 +1672,14 @@ static const WCHAR schannelComment[] = { 'S','c','h','a','n','n','e','l',' ',
'S','e','c','u','r','i','t','y',' ','P','a','c','k','a','g','e',0 };
static const WCHAR schannelDllName[] = { 's','c','h','a','n','n','e','l','.','d','l','l',0 };
+const struct schan_callbacks schan_callbacks =
+{
+ schan_get_buffer,
+ schan_get_session_for_transport,
+ schan_pull,
+ schan_push,
+};
+
void SECUR32_initSchannelSP(void)
{
/* This is what Windows reports. This shouldn't break any applications
@@ -1578,8 +1706,11 @@ void SECUR32_initSchannelSP(void)
};
SecureProvider *provider;
- if (!schan_imp_init())
+ if (!schan_funcs && __wine_init_unix_lib(hsecur32, DLL_PROCESS_ATTACH, &schan_callbacks, &schan_funcs))
+ {
+ ERR( "no schannel support, expect problems\n" );
return;
+ }
schan_handle_table = heap_alloc(64 * sizeof(*schan_handle_table));
if (!schan_handle_table)
@@ -1597,13 +1728,11 @@ void SECUR32_initSchannelSP(void)
}
SECUR32_addPackages(provider, ARRAY_SIZE(info), NULL, info);
-
return;
fail:
heap_free(schan_handle_table);
schan_handle_table = NULL;
- schan_imp_deinit();
return;
}
@@ -1620,7 +1749,7 @@ void SECUR32_deinitSchannelSP(void)
if (schan_handle_table[i].type == SCHAN_HANDLE_CTX)
{
struct schan_context *ctx = schan_free_handle(i, SCHAN_HANDLE_CTX);
- schan_imp_dispose_session(ctx->session);
+ schan_funcs->dispose_session(ctx->session);
heap_free(ctx);
}
}
@@ -1631,21 +1760,12 @@ void SECUR32_deinitSchannelSP(void)
{
struct schan_credentials *cred;
cred = schan_free_handle(i, SCHAN_HANDLE_CRED);
- schan_imp_free_certificate_credentials(cred);
+ schan_funcs->free_certificate_credentials(cred);
heap_free(cred);
}
}
heap_free(schan_handle_table);
- schan_imp_deinit();
-}
-
-#else /* SONAME_LIBGNUTLS || HAVE_SECURITY_SECURITY_H */
-void SECUR32_initSchannelSP(void)
-{
- ERR("TLS library not found, SSL connections will fail\n");
+ __wine_init_unix_lib(hsecur32, DLL_PROCESS_DETACH, NULL, NULL);
+ schan_funcs = NULL;
}
-
-void SECUR32_deinitSchannelSP(void) {}
-
-#endif /* SONAME_LIBGNUTLS || HAVE_SECURITY_SECURITY_H */
diff --git a/dlls/secur32/schannel_gnutls.c b/dlls/secur32/schannel_gnutls.c
index 785430ddf58..76ab230137d 100644
--- a/dlls/secur32/schannel_gnutls.c
+++ b/dlls/secur32/schannel_gnutls.c
@@ -19,23 +19,27 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#if 0
+#pragma makedep unix
+#endif
+
#include "config.h"
#include "wine/port.h"
#include <stdarg.h>
#include <stdio.h>
-#include <assert.h>
#ifdef SONAME_LIBGNUTLS
#include <gnutls/gnutls.h>
#include <gnutls/crypto.h>
#include <gnutls/abstract.h>
#endif
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "sspi.h"
#include "schannel.h"
-#include "lmcons.h"
#include "winreg.h"
#include "secur32_priv.h"
@@ -47,6 +51,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
WINE_DECLARE_DEBUG_CHANNEL(winediag);
+static const struct schan_callbacks *callbacks;
+
/* Not present in gnutls version < 2.9.10. */
static int (*pgnutls_cipher_get_block_size)(gnutls_cipher_algorithm_t);
@@ -192,13 +198,12 @@ static void compat_gnutls_dtls_set_mtu(gnutls_session_t session, unsigned int mt
FIXME("\n");
}
-static ssize_t schan_pull_adapter(gnutls_transport_ptr_t transport,
- void *buff, size_t buff_len)
+static ssize_t pull_adapter(gnutls_transport_ptr_t transport, void *buff, size_t buff_len)
{
struct schan_transport *t = (struct schan_transport*)transport;
- gnutls_session_t s = (gnutls_session_t)schan_session_for_transport(t);
+ gnutls_session_t s = (gnutls_session_t)callbacks->get_session_for_transport(t);
- int ret = schan_pull(transport, buff, &buff_len);
+ int ret = callbacks->pull(transport, buff, &buff_len);
if (ret)
{
pgnutls_transport_set_errno(s, ret);
@@ -208,13 +213,12 @@ static ssize_t schan_pull_adapter(gnutls_transport_ptr_t transport,
return buff_len;
}
-static ssize_t schan_push_adapter(gnutls_transport_ptr_t transport,
- const void *buff, size_t buff_len)
+static ssize_t push_adapter(gnutls_transport_ptr_t transport, const void *buff, size_t buff_len)
{
struct schan_transport *t = (struct schan_transport*)transport;
- gnutls_session_t s = (gnutls_session_t)schan_session_for_transport(t);
+ gnutls_session_t s = (gnutls_session_t)callbacks->get_session_for_transport(t);
- int ret = schan_push(transport, buff, &buff_len);
+ int ret = callbacks->push(transport, buff, &buff_len);
if (ret)
{
pgnutls_transport_set_errno(s, ret);
@@ -270,21 +274,21 @@ static void check_supported_protocols(void)
pgnutls_deinit(session);
}
-DWORD schan_imp_enabled_protocols(void)
+static DWORD CDECL schan_get_enabled_protocols(void)
{
return supported_protocols;
}
-static int schan_pull_timeout(gnutls_transport_ptr_t transport, unsigned int timeout)
+static int pull_timeout(gnutls_transport_ptr_t transport, unsigned int timeout)
{
struct schan_transport *t = (struct schan_transport *)transport;
SIZE_T count = 0;
- if (schan_get_buffer(t, &t->in, &count)) return 1;
+ if (callbacks->get_buffer(t, &t->in, &count)) return 1;
return 0;
}
-BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
+static BOOL CDECL schan_create_session(schan_session *session, schan_credentials *cred)
{
gnutls_session_t *s = (gnutls_session_t*)session;
char priority[128] = "NORMAL:%LATEST_RECORD_VERSION", *p;
@@ -347,34 +351,32 @@ BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cre
return FALSE;
}
- pgnutls_transport_set_pull_function(*s, schan_pull_adapter);
- if (flags & GNUTLS_DATAGRAM) pgnutls_transport_set_pull_timeout_function(*s, schan_pull_timeout);
- pgnutls_transport_set_push_function(*s, schan_push_adapter);
+ pgnutls_transport_set_pull_function(*s, pull_adapter);
+ if (flags & GNUTLS_DATAGRAM) pgnutls_transport_set_pull_timeout_function(*s, pull_timeout);
+ pgnutls_transport_set_push_function(*s, push_adapter);
return TRUE;
}
-void schan_imp_dispose_session(schan_imp_session session)
+static void CDECL schan_dispose_session(schan_session session)
{
gnutls_session_t s = (gnutls_session_t)session;
pgnutls_deinit(s);
}
-void schan_imp_set_session_transport(schan_imp_session session,
- struct schan_transport *t)
+static void CDECL schan_set_session_transport(schan_session session, struct schan_transport *t)
{
gnutls_session_t s = (gnutls_session_t)session;
pgnutls_transport_set_ptr(s, (gnutls_transport_ptr_t)t);
}
-void schan_imp_set_session_target(schan_imp_session session, const char *target)
+static void CDECL schan_set_session_target(schan_session session, const char *target)
{
gnutls_session_t s = (gnutls_session_t)session;
-
pgnutls_server_name_set( s, GNUTLS_NAME_DNS, target, strlen(target) );
}
-SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
+static SECURITY_STATUS CDECL schan_handshake(schan_session session)
{
gnutls_session_t s = (gnutls_session_t)session;
int err;
@@ -422,7 +424,7 @@ SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
return SEC_E_OK;
}
-static DWORD schannel_get_protocol(gnutls_protocol_t proto)
+static DWORD get_protocol(gnutls_protocol_t proto)
{
/* FIXME: currently schannel only implements client connections, but
* there's no reason it couldn't be used for servers as well. The
@@ -442,7 +444,7 @@ static DWORD schannel_get_protocol(gnutls_protocol_t proto)
}
}
-static ALG_ID schannel_get_cipher_algid(gnutls_cipher_algorithm_t cipher)
+static ALG_ID get_cipher_algid(gnutls_cipher_algorithm_t cipher)
{
switch (cipher)
{
@@ -464,7 +466,7 @@ static ALG_ID schannel_get_cipher_algid(gnutls_cipher_algorithm_t cipher)
}
}
-static ALG_ID schannel_get_mac_algid(gnutls_mac_algorithm_t mac, gnutls_cipher_algorithm_t cipher)
+static ALG_ID get_mac_algid(gnutls_mac_algorithm_t mac, gnutls_cipher_algorithm_t cipher)
{
switch (mac)
{
@@ -493,7 +495,7 @@ static ALG_ID schannel_get_mac_algid(gnutls_mac_algorithm_t mac, gnutls_cipher_a
}
}
-static ALG_ID schannel_get_kx_algid(int kx)
+static ALG_ID get_kx_algid(int kx)
{
switch (kx)
{
@@ -513,19 +515,18 @@ static ALG_ID schannel_get_kx_algid(int kx)
}
}
-unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
+static unsigned int CDECL schan_get_session_cipher_block_size(schan_session session)
{
gnutls_session_t s = (gnutls_session_t)session;
return pgnutls_cipher_get_block_size(pgnutls_cipher_get(s));
}
-unsigned int schan_imp_get_max_message_size(schan_imp_session session)
+static unsigned int CDECL schan_get_max_message_size(schan_session session)
{
return pgnutls_record_get_max_size((gnutls_session_t)session);
}
-SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
- SecPkgContext_ConnectionInfo *info)
+static SECURITY_STATUS CDECL schan_get_connection_info(schan_session session, SecPkgContext_ConnectionInfo *info)
{
gnutls_session_t s = (gnutls_session_t)session;
gnutls_protocol_t proto = pgnutls_protocol_get_version(s);
@@ -533,19 +534,18 @@ SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
gnutls_mac_algorithm_t mac = pgnutls_mac_get(s);
gnutls_kx_algorithm_t kx = pgnutls_kx_get(s);
- info->dwProtocol = schannel_get_protocol(proto);
- info->aiCipher = schannel_get_cipher_algid(alg);
+ info->dwProtocol = get_protocol(proto);
+ info->aiCipher = get_cipher_algid(alg);
info->dwCipherStrength = pgnutls_cipher_get_key_size(alg) * 8;
- info->aiHash = schannel_get_mac_algid(mac, alg);
+ info->aiHash = get_mac_algid(mac, alg);
info->dwHashStrength = pgnutls_mac_get_key_size(mac) * 8;
- info->aiExch = schannel_get_kx_algid(kx);
+ info->aiExch = get_kx_algid(kx);
/* FIXME: info->dwExchStrength? */
info->dwExchStrength = 0;
return SEC_E_OK;
}
-SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session,
- SecPkgContext_Bindings *bindings)
+static SECURITY_STATUS CDECL schan_get_unique_channel_binding(schan_session session, SecPkgContext_Bindings *bindings)
{
static const char prefix[] = "tls-unique:";
gnutls_datum_t datum;
@@ -562,7 +562,7 @@ SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session,
}
bindings->BindingsLength = sizeof(SEC_CHANNEL_BINDINGS) + sizeof(prefix)-1 + datum.size;
- bindings->Bindings = heap_alloc_zero(bindings->BindingsLength);
+ bindings->Bindings = RtlAllocateHeap(GetProcessHeap(), HEAP_ZERO_MEMORY, bindings->BindingsLength);
if (!bindings->Bindings)
ret = SEC_E_INSUFFICIENT_MEMORY;
else
@@ -579,7 +579,7 @@ SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session,
return ret;
}
-ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session)
+static ALG_ID CDECL schan_get_key_signature_algorithm(schan_session session)
{
gnutls_session_t s = (gnutls_session_t)session;
gnutls_kx_algorithm_t kx = pgnutls_kx_get(s);
@@ -600,35 +600,32 @@ ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session)
}
}
-SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
- PCCERT_CONTEXT *ret)
+static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session session, struct schan_cert_list *list)
{
gnutls_session_t s = (gnutls_session_t)session;
- PCCERT_CONTEXT cert = NULL;
const gnutls_datum_t *datum;
- unsigned list_size, i;
- BOOL res;
+ unsigned int i, size;
+ BYTE *ptr;
- datum = pgnutls_certificate_get_peers(s, &list_size);
- if(!datum)
- return SEC_E_INTERNAL_ERROR;
+ if (!(datum = pgnutls_certificate_get_peers(s, &list->count))) return SEC_E_INTERNAL_ERROR;
- for(i = 0; i < list_size; i++) {
- res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, datum[i].data, datum[i].size,
- CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert);
- if(!res) {
- if(i)
- CertFreeCertificateContext(cert);
- return GetLastError();
- }
+ size = list->count * sizeof(list->certs[0]);
+ for (i = 0; i < list->count; i++) size += datum[i].size;
+ if (!(list->certs = RtlAllocateHeap(GetProcessHeap(), 0, size))) return SEC_E_INSUFFICIENT_MEMORY;
+
+ ptr = (BYTE *)&list->certs[list->count];
+ for (i = 0; i < list->count; i++)
+ {
+ list->certs[i].cbData = datum[i].size;
+ list->certs[i].pbData = ptr;
+ memcpy(list->certs[i].pbData, datum[i].data, datum[i].size);
+ ptr += datum[i].size;
}
- *ret = cert;
return SEC_E_OK;
}
-SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
- SIZE_T *length)
+static SECURITY_STATUS CDECL schan_send(schan_session session, const void *buffer, SIZE_T *length)
{
gnutls_session_t s = (gnutls_session_t)session;
SSIZE_T ret, total = 0;
@@ -647,7 +644,7 @@ SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s);
SIZE_T count = 0;
- if (schan_get_buffer(t, &t->out, &count)) continue;
+ if (callbacks->get_buffer(t, &t->out, &count)) continue;
return SEC_I_CONTINUE_NEEDED;
}
else
@@ -658,8 +655,7 @@ SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
}
}
-SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
- SIZE_T *length)
+static SECURITY_STATUS CDECL schan_recv(schan_session session, void *buffer, SIZE_T *length)
{
gnutls_session_t s = (gnutls_session_t)session;
ssize_t ret;
@@ -674,7 +670,7 @@ again:
struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s);
SIZE_T count = 0;
- if (schan_get_buffer(t, &t->in, &count))
+ if (callbacks->get_buffer(t, &t->in, &count))
goto again;
return SEC_I_CONTINUE_NEEDED;
@@ -715,7 +711,7 @@ static unsigned int parse_alpn_protocol_list(unsigned char *buffer, unsigned int
return count;
}
-void schan_imp_set_application_protocols(schan_imp_session session, unsigned char *buffer, unsigned int buflen)
+static void CDECL schan_set_application_protocols(schan_session session, unsigned char *buffer, unsigned int buflen)
{
gnutls_session_t s = (gnutls_session_t)session;
unsigned int extension_len, extension, count = 0, offset = 0;
@@ -742,7 +738,7 @@ void schan_imp_set_application_protocols(schan_imp_session session, unsigned cha
if (offset + list_len > buflen) return;
count = parse_alpn_protocol_list(&buffer[offset], list_len, NULL);
- if (!count || !(protocols = heap_alloc(count * sizeof(*protocols)))) return;
+ if (!count || !(protocols = RtlAllocateHeap(GetProcessHeap(), 0, count * sizeof(*protocols)))) return;
parse_alpn_protocol_list(&buffer[offset], list_len, protocols);
if ((ret = pgnutls_alpn_set_protocols(s, protocols, count, GNUTLS_ALPN_SERVER_PRECEDENCE) < 0))
@@ -750,11 +746,11 @@ void schan_imp_set_application_protocols(schan_imp_session session, unsigned cha
pgnutls_perror(ret);
}
- heap_free(protocols);
+ RtlFreeHeap(GetProcessHeap(), 0, protocols);
}
-SECURITY_STATUS schan_imp_get_application_protocol(schan_imp_session session,
- SecPkgContext_ApplicationProtocol *protocol)
+static SECURITY_STATUS CDECL schan_get_application_protocol(schan_session session,
+ SecPkgContext_ApplicationProtocol *protocol)
{
gnutls_session_t s = (gnutls_session_t)session;
gnutls_datum_t selected;
@@ -768,12 +764,12 @@ SECURITY_STATUS schan_imp_get_application_protocol(schan_imp_session session,
protocol->ProtoNegoExt = SecApplicationProtocolNegotiationExt_ALPN;
protocol->ProtocolIdSize = selected.size;
memcpy(protocol->ProtocolId, selected.data, selected.size);
- TRACE("returning %s\n", debugstr_an((const char *)selected.data, selected.size));
+ TRACE("returning %s\n", wine_dbgstr_an((const char *)selected.data, selected.size));
}
return SEC_E_OK;
}
-SECURITY_STATUS schan_imp_set_dtls_mtu(schan_imp_session session, unsigned int mtu)
+static SECURITY_STATUS CDECL schan_set_dtls_mtu(schan_session session, unsigned int mtu)
{
gnutls_session_t s = (gnutls_session_t)session;
@@ -782,114 +778,6 @@ SECURITY_STATUS schan_imp_set_dtls_mtu(schan_imp_session session, unsigned int m
return SEC_E_OK;
}
-static WCHAR *get_key_container_path(const CERT_CONTEXT *ctx)
-{
- static const WCHAR rsabaseW[] =
- {'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','C','r','y','p','t','o','\\','R','S','A','\\',0};
- CERT_KEY_CONTEXT keyctx;
- DWORD size = sizeof(keyctx), prov_size = 0;
- CRYPT_KEY_PROV_INFO *prov;
- WCHAR username[UNLEN + 1], *ret = NULL;
- DWORD len = ARRAY_SIZE(username);
-
- if (CertGetCertificateContextProperty(ctx, CERT_KEY_CONTEXT_PROP_ID, &keyctx, &size))
- {
- char *str;
- if (!CryptGetProvParam(keyctx.hCryptProv, PP_CONTAINER, NULL, &size, 0)) return NULL;
- if (!(str = heap_alloc(size))) return NULL;
- if (!CryptGetProvParam(keyctx.hCryptProv, PP_CONTAINER, (BYTE *)str, &size, 0)) return NULL;
-
- len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
- if (!(ret = heap_alloc(sizeof(rsabaseW) + len * sizeof(WCHAR))))
- {
- heap_free(str);
- return NULL;
- }
- strcpyW(ret, rsabaseW);
- MultiByteToWideChar(CP_ACP, 0, str, -1, ret + strlenW(ret), len);
- heap_free(str);
- }
- else if (CertGetCertificateContextProperty(ctx, CERT_KEY_PROV_INFO_PROP_ID, NULL, &prov_size))
- {
- if (!(prov = heap_alloc(prov_size))) return NULL;
- if (!CertGetCertificateContextProperty(ctx, CERT_KEY_PROV_INFO_PROP_ID, prov, &prov_size))
- {
- heap_free(prov);
- return NULL;
- }
- if (!(ret = heap_alloc(sizeof(rsabaseW) + strlenW(prov->pwszContainerName) * sizeof(WCHAR))))
- {
- heap_free(prov);
- return NULL;
- }
- strcpyW(ret, rsabaseW);
- strcatW(ret, prov->pwszContainerName);
- heap_free(prov);
- }
-
- if (!ret && GetUserNameW(username, &len) && (ret = heap_alloc(sizeof(rsabaseW) + len * sizeof(WCHAR))))
- {
- strcpyW(ret, rsabaseW);
- strcatW(ret, username);
- }
-
- return ret;
-}
-
-#define MAX_LEAD_BYTES 8
-static BYTE *get_key_blob(const CERT_CONTEXT *ctx, ULONG *size)
-{
- static const WCHAR keyexchangeW[] =
- {'K','e','y','E','x','c','h','a','n','g','e','K','e','y','P','a','i','r',0};
- static const WCHAR signatureW[] =
- {'S','i','g','n','a','t','u','r','e','K','e','y','P','a','i','r',0};
- BYTE *buf, *ret = NULL;
- DATA_BLOB blob_in, blob_out;
- DWORD spec = 0, type, len;
- WCHAR *path;
- HKEY hkey;
-
- if (!(path = get_key_container_path(ctx))) return NULL;
- if (RegOpenKeyExW(HKEY_CURRENT_USER, path, 0, KEY_READ, &hkey))
- {
- heap_free(path);
- return NULL;
- }
- heap_free(path);
-
- if (!RegQueryValueExW(hkey, keyexchangeW, 0, &type, NULL, &len)) spec = AT_KEYEXCHANGE;
- else if (!RegQueryValueExW(hkey, signatureW, 0, &type, NULL, &len)) spec = AT_SIGNATURE;
- else
- {
- RegCloseKey(hkey);
- return NULL;
- }
-
- if (!(buf = heap_alloc(len + MAX_LEAD_BYTES)))
- {
- RegCloseKey(hkey);
- return NULL;
- }
-
- if (!RegQueryValueExW(hkey, (spec == AT_KEYEXCHANGE) ? keyexchangeW : signatureW, 0, &type, buf, &len))
- {
- blob_in.pbData = buf;
- blob_in.cbData = len;
- if (CryptUnprotectData(&blob_in, NULL, NULL, NULL, NULL, 0, &blob_out))
- {
- assert(blob_in.cbData >= blob_out.cbData);
- memcpy(buf, blob_out.pbData, blob_out.cbData);
- LocalFree(blob_out.pbData);
- *size = blob_out.cbData + MAX_LEAD_BYTES;
- ret = buf;
- }
- }
- else heap_free(buf);
-
- RegCloseKey(hkey);
- return ret;
-}
-
static inline void reverse_bytes(BYTE *buf, ULONG len)
{
BYTE tmp;
@@ -917,20 +805,19 @@ static ULONG set_component(gnutls_datum_t *comp, BYTE *data, ULONG len, ULONG *b
return comp->size;
}
-static gnutls_x509_privkey_t get_x509_key(const CERT_CONTEXT *ctx)
+static gnutls_x509_privkey_t get_x509_key(const DATA_BLOB *key_blob)
{
gnutls_privkey_t key = NULL;
gnutls_x509_privkey_t x509key = NULL;
gnutls_datum_t m, e, d, p, q, u, e1, e2;
- BYTE *ptr, *buffer;
+ BYTE *ptr;
RSAPUBKEY *rsakey;
- DWORD size;
+ DWORD size = key_blob->cbData;
int ret;
- if (!(buffer = get_key_blob(ctx, &size))) return NULL;
- if (size < sizeof(BLOBHEADER)) goto done;
+ if (size < sizeof(BLOBHEADER)) return NULL;
- rsakey = (RSAPUBKEY *)(buffer + sizeof(BLOBHEADER));
+ rsakey = (RSAPUBKEY *)(key_blob->pbData + sizeof(BLOBHEADER));
TRACE("RSA key bitlen %u pubexp %u\n", rsakey->bitlen, rsakey->pubexp);
size -= sizeof(BLOBHEADER) + FIELD_OFFSET(RSAPUBKEY, pubexp);
@@ -948,23 +835,17 @@ static gnutls_x509_privkey_t get_x509_key(const CERT_CONTEXT *ctx)
if ((ret = pgnutls_privkey_init(&key)) < 0)
{
pgnutls_perror(ret);
- goto done;
- }
-
- if ((ret = pgnutls_privkey_import_rsa_raw(key, &m, &e, &d, &p, &q, &u, &e1, &e2)) < 0)
- {
- pgnutls_perror(ret);
- goto done;
+ return NULL;
}
- if ((ret = pgnutls_privkey_export_x509(key, &x509key)) < 0)
+ if (((ret = pgnutls_privkey_import_rsa_raw(key, &m, &e, &d, &p, &q, &u, &e1, &e2)) < 0) ||
+ (ret = pgnutls_privkey_export_x509(key, &x509key)) < 0)
{
pgnutls_perror(ret);
+ pgnutls_privkey_deinit(key);
+ return NULL;
}
-done:
- heap_free(buffer);
- pgnutls_privkey_deinit(key);
return x509key;
}
@@ -999,7 +880,8 @@ static gnutls_x509_crt_t get_x509_crt(const CERT_CONTEXT *ctx)
return crt;
}
-BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c, const CERT_CONTEXT *ctx)
+static BOOL CDECL schan_allocate_certificate_credentials(schan_credentials *c, const CERT_CONTEXT *ctx,
+ const DATA_BLOB *key_blob )
{
gnutls_certificate_credentials_t creds;
gnutls_x509_crt_t crt;
@@ -1025,7 +907,7 @@ BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c, const CERT
return FALSE;
}
- if (!(key = get_x509_key(ctx)))
+ if (!(key = get_x509_key(key_blob)))
{
pgnutls_x509_crt_deinit(crt);
pgnutls_certificate_free_credentials(creds);
@@ -1046,17 +928,17 @@ BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c, const CERT
return TRUE;
}
-void schan_imp_free_certificate_credentials(schan_credentials *c)
+static void CDECL schan_free_certificate_credentials(schan_credentials *c)
{
pgnutls_certificate_free_credentials(c->credentials);
}
-static void schan_gnutls_log(int level, const char *msg)
+static void gnutls_log(int level, const char *msg)
{
TRACE("<%d> %s", level, msg);
}
-BOOL schan_imp_init(void)
+static BOOL gnutls_initialize(void)
{
const char *env_str;
int ret;
@@ -1171,7 +1053,7 @@ BOOL schan_imp_init(void)
if (TRACE_ON(secur32))
{
pgnutls_global_set_log_level(4);
- pgnutls_global_set_log_function(schan_gnutls_log);
+ pgnutls_global_set_log_function(gnutls_log);
}
check_supported_protocols();
@@ -1183,11 +1065,50 @@ fail:
return FALSE;
}
-void schan_imp_deinit(void)
+static void gnutls_uninitialize(void)
{
pgnutls_global_deinit();
dlclose(libgnutls_handle);
libgnutls_handle = NULL;
}
+static const struct schan_funcs funcs =
+{
+ schan_allocate_certificate_credentials,
+ schan_create_session,
+ schan_dispose_session,
+ schan_free_certificate_credentials,
+ schan_get_application_protocol,
+ schan_get_connection_info,
+ schan_get_enabled_protocols,
+ schan_get_key_signature_algorithm,
+ schan_get_max_message_size,
+ schan_get_session_cipher_block_size,
+ schan_get_session_peer_certificate,
+ schan_get_unique_channel_binding,
+ schan_handshake,
+ schan_recv,
+ schan_send,
+ schan_set_application_protocols,
+ schan_set_dtls_mtu,
+ schan_set_session_target,
+ schan_set_session_transport,
+};
+
+NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
+{
+ switch (reason)
+ {
+ case DLL_PROCESS_ATTACH:
+ if (!gnutls_initialize()) return STATUS_DLL_NOT_FOUND;
+ callbacks = ptr_in;
+ *(const struct schan_funcs **)ptr_out = &funcs;
+ break;
+ case DLL_PROCESS_DETACH:
+ if (libgnutls_handle) gnutls_uninitialize();
+ break;
+ }
+ return STATUS_SUCCESS;
+}
+
#endif /* SONAME_LIBGNUTLS && !HAVE_SECURITY_SECURITY_H */
diff --git a/dlls/secur32/schannel_macosx.c b/dlls/secur32/schannel_macosx.c
index 841f928eef3..daf9d835835 100644
--- a/dlls/secur32/schannel_macosx.c
+++ b/dlls/secur32/schannel_macosx.c
@@ -19,6 +19,10 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
+#if 0
+#pragma makedep unix
+#endif
+
#include "config.h"
#include "wine/port.h"
@@ -33,10 +37,13 @@
#undef LoadResource
#endif
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "sspi.h"
#include "schannel.h"
+#include "winternl.h"
#include "secur32_priv.h"
#include "wine/debug.h"
@@ -44,6 +51,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
+static const struct schan_callbacks *callbacks;
+
#if MAC_OS_X_VERSION_MAX_ALLOWED < 1060
/* Defined in <Security/CipherSuite.h> in the 10.6 SDK or later. */
enum {
@@ -444,7 +453,7 @@ static const struct cipher_suite* get_cipher_suite(SSLCipherSuite cipher_suite)
}
-static DWORD schan_get_session_protocol(struct mac_session* s)
+static DWORD get_session_protocol(struct mac_session* s)
{
SSLProtocol protocol;
int status;
@@ -473,7 +482,7 @@ static DWORD schan_get_session_protocol(struct mac_session* s)
}
}
-static ALG_ID schan_get_cipher_algid(const struct cipher_suite* c)
+static ALG_ID get_cipher_algid(const struct cipher_suite* c)
{
TRACE("(%#x)\n", (unsigned int)c->suite);
@@ -503,7 +512,7 @@ static ALG_ID schan_get_cipher_algid(const struct cipher_suite* c)
}
}
-static unsigned int schan_get_cipher_key_size(const struct cipher_suite* c)
+static unsigned int get_cipher_key_size(const struct cipher_suite* c)
{
TRACE("(%#x)\n", (unsigned int)c->suite);
@@ -533,7 +542,7 @@ static unsigned int schan_get_cipher_key_size(const struct cipher_suite* c)
}
}
-static ALG_ID schan_get_mac_algid(const struct cipher_suite* c)
+static ALG_ID get_mac_algid(const struct cipher_suite* c)
{
TRACE("(%#x)\n", (unsigned int)c->suite);
@@ -551,7 +560,7 @@ static ALG_ID schan_get_mac_algid(const struct cipher_suite* c)
}
}
-static unsigned int schan_get_mac_key_size(const struct cipher_suite* c)
+static unsigned int get_mac_key_size(const struct cipher_suite* c)
{
TRACE("(%#x)\n", (unsigned int)c->suite);
@@ -569,7 +578,7 @@ static unsigned int schan_get_mac_key_size(const struct cipher_suite* c)
}
}
-static ALG_ID schan_get_kx_algid(const struct cipher_suite* c)
+static ALG_ID get_kx_algid(const struct cipher_suite* c)
{
TRACE("(%#x)\n", (unsigned int)c->suite);
@@ -608,7 +617,7 @@ static ALG_ID schan_get_kx_algid(const struct cipher_suite* c)
}
-/* schan_pull_adapter
+/* pull_adapter
* Callback registered with SSLSetIOFuncs as the read function for a
* session. Reads data from the session connection. Conforms to the
* SSLReadFunc type.
@@ -629,8 +638,7 @@ static ALG_ID schan_get_kx_algid(const struct cipher_suite* c)
* more data to be read.
* other error code for failure.
*/
-static OSStatus schan_pull_adapter(SSLConnectionRef transport, void *buff,
- SIZE_T *buff_len)
+static OSStatus pull_adapter(SSLConnectionRef transport, void *buff, SIZE_T *buff_len)
{
struct mac_session *s = (struct mac_session*)transport;
size_t requested = *buff_len;
@@ -645,7 +653,7 @@ static OSStatus schan_pull_adapter(SSLConnectionRef transport, void *buff,
return noErr;
}
- status = schan_pull(s->transport, buff, buff_len);
+ status = callbacks->pull(s->transport, buff, buff_len);
if (status == 0)
{
if (*buff_len == 0)
@@ -678,7 +686,7 @@ static OSStatus schan_pull_adapter(SSLConnectionRef transport, void *buff,
return ret;
}
-/* schan_push_adapter
+/* push_adapter
* Callback registered with SSLSetIOFuncs as the write function for a
* session. Writes data to the session connection. Conforms to the
* SSLWriteFunc type.
@@ -695,8 +703,7 @@ static OSStatus schan_pull_adapter(SSLConnectionRef transport, void *buff,
* caller should try again.
* other error code for failure.
*/
-static OSStatus schan_push_adapter(SSLConnectionRef transport, const void *buff,
- SIZE_T *buff_len)
+static OSStatus push_adapter(SSLConnectionRef transport, const void *buff, SIZE_T *buff_len)
{
struct mac_session *s = (struct mac_session*)transport;
int status;
@@ -710,7 +717,7 @@ static OSStatus schan_push_adapter(SSLConnectionRef transport, const void *buff,
return noErr;
}
- status = schan_push(s->transport, buff, buff_len);
+ status = callbacks->push(s->transport, buff, buff_len);
if (status == 0)
{
TRACE("Pushed %lu bytes\n", *buff_len);
@@ -743,12 +750,12 @@ static const struct {
static DWORD supported_protocols;
-DWORD schan_imp_enabled_protocols(void)
+static DWORD CDECL schan_get_enabled_protocols(void)
{
return supported_protocols;
}
-BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
+static BOOL CDECL schan_create_session(schan_session *session, schan_credentials *cred)
{
struct mac_session *s;
unsigned i;
@@ -756,9 +763,7 @@ BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cre
TRACE("(%p)\n", session);
- s = heap_alloc(sizeof(*s));
- if (!s)
- return FALSE;
+ if (!(s = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*s)))) return FALSE;
pthread_mutex_init(&s->mutex, NULL);
@@ -796,7 +801,7 @@ BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cre
}
}
- status = SSLSetIOFuncs(s->context, schan_pull_adapter, schan_push_adapter);
+ status = SSLSetIOFuncs(s->context, pull_adapter, push_adapter);
if (status != noErr)
{
ERR("Failed to set session I/O funcs: %d\n", status);
@@ -807,15 +812,15 @@ BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cre
TRACE(" -> %p/%p\n", s, s->context);
- *session = (schan_imp_session)s;
+ *session = (schan_session)s;
return TRUE;
fail:
- heap_free(s);
+ RtlFreeHeap(GetProcessHeap(), 0, s);
return FALSE;
}
-void schan_imp_dispose_session(schan_imp_session session)
+static void CDECL schan_dispose_session(schan_session session)
{
struct mac_session *s = (struct mac_session*)session;
int status;
@@ -826,11 +831,10 @@ void schan_imp_dispose_session(schan_imp_session session)
if (status != noErr)
ERR("Failed to dispose of session context: %d\n", status);
pthread_mutex_destroy(&s->mutex);
- heap_free(s);
+ RtlFreeHeap(GetProcessHeap(), 0, s);
}
-void schan_imp_set_session_transport(schan_imp_session session,
- struct schan_transport *t)
+static void CDECL schan_set_session_transport(schan_session session, struct schan_transport *t)
{
struct mac_session *s = (struct mac_session*)session;
@@ -839,7 +843,7 @@ void schan_imp_set_session_transport(schan_imp_session session,
s->transport = t;
}
-void schan_imp_set_session_target(schan_imp_session session, const char *target)
+static void CDECL schan_set_session_target(schan_session session, const char *target)
{
struct mac_session *s = (struct mac_session*)session;
@@ -848,7 +852,7 @@ void schan_imp_set_session_target(schan_imp_session session, const char *target)
SSLSetPeerDomainName( s->context, target, strlen(target) );
}
-SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
+static SECURITY_STATUS CDECL schan_handshake(schan_session session)
{
struct mac_session *s = (struct mac_session*)session;
int status;
@@ -885,7 +889,7 @@ SECURITY_STATUS schan_imp_handshake(schan_imp_session session)
return SEC_E_OK;
}
-unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
+static unsigned int CDECL schan_get_session_cipher_block_size(schan_session session)
{
struct mac_session* s = (struct mac_session*)session;
SSLCipherSuite cipherSuite;
@@ -934,13 +938,13 @@ unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
}
}
-unsigned int schan_imp_get_max_message_size(schan_imp_session session)
+static unsigned int CDECL schan_get_max_message_size(schan_session session)
{
FIXME("Returning 1 << 14.\n");
return 1 << 14;
}
-ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session)
+static ALG_ID CDECL schan_get_key_signature_algorithm(schan_session session)
{
struct mac_session* s = (struct mac_session*)session;
SSLCipherSuite cipherSuite;
@@ -1002,8 +1006,7 @@ ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session)
}
}
-SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
- SecPkgContext_ConnectionInfo *info)
+static SECURITY_STATUS CDECL schan_get_connection_info(schan_session session, SecPkgContext_ConnectionInfo *info)
{
struct mac_session* s = (struct mac_session*)session;
SSLCipherSuite cipherSuite;
@@ -1026,46 +1029,44 @@ SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
return SEC_E_INTERNAL_ERROR;
}
- info->dwProtocol = schan_get_session_protocol(s);
- info->aiCipher = schan_get_cipher_algid(c);
- info->dwCipherStrength = schan_get_cipher_key_size(c);
- info->aiHash = schan_get_mac_algid(c);
- info->dwHashStrength = schan_get_mac_key_size(c);
- info->aiExch = schan_get_kx_algid(c);
+ info->dwProtocol = get_session_protocol(s);
+ info->aiCipher = get_cipher_algid(c);
+ info->dwCipherStrength = get_cipher_key_size(c);
+ info->aiHash = get_mac_algid(c);
+ info->dwHashStrength = get_mac_key_size(c);
+ info->aiExch = get_kx_algid(c);
/* FIXME: info->dwExchStrength? */
info->dwExchStrength = 0;
return SEC_E_OK;
}
-SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session,
- SecPkgContext_Bindings *bindings)
+static SECURITY_STATUS CDECL schan_get_unique_channel_binding(schan_session session, SecPkgContext_Bindings *bindings)
{
FIXME("SECPKG_ATTR_UNIQUE_BINDINGS is unsupported on MacOS\n");
return SEC_E_UNSUPPORTED_FUNCTION;
}
#ifndef HAVE_SSLCOPYPEERCERTIFICATES
-static void schan_imp_cf_release(const void *arg, void *ctx)
+static void cf_release(const void *arg, void *ctx)
{
CFRelease(arg);
}
#endif
-SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
- PCCERT_CONTEXT *ret_cert)
+static SECURITY_STATUS CDECL schan_get_session_peer_certificate(schan_session session, struct schan_cert_list *list)
{
- struct mac_session* s = (struct mac_session*)session;
+ struct mac_session *s = (struct mac_session *)session;
SECURITY_STATUS ret = SEC_E_OK;
- PCCERT_CONTEXT cert = NULL;
- SecCertificateRef mac_cert;
+ SecCertificateRef cert;
CFArrayRef cert_array;
int status;
- CFIndex cnt, i;
+ unsigned int size;
+ CFIndex i;
CFDataRef data;
- BOOL res;
+ BYTE *ptr;
- TRACE("(%p/%p, %p)\n", s, s->context, cert);
+ TRACE("(%p/%p, %p)\n", s, s->context, list);
#ifdef HAVE_SSLCOPYPEERCERTIFICATES
status = SSLCopyPeerCertificates(s->context, &cert_array);
@@ -1078,45 +1079,55 @@ SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session
return SEC_E_INTERNAL_ERROR;
}
- cnt = CFArrayGetCount(cert_array);
- for (i=0; i < cnt; i++) {
- if (!(mac_cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
- (SecKeychainItemExport(mac_cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
+ list->count = CFArrayGetCount(cert_array);
+ size = list->count * sizeof(list->certs[0]);
+
+ for (i = 0; i < list->count; i++)
+ {
+ if (!(cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
+ (SecKeychainItemExport(cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
{
WARN("Couldn't extract certificate data\n");
ret = SEC_E_INTERNAL_ERROR;
- break;
+ goto done;
}
-
- res = CertAddEncodedCertificateToStore(store, X509_ASN_ENCODING, CFDataGetBytePtr(data), CFDataGetLength(data),
- CERT_STORE_ADD_REPLACE_EXISTING, i ? NULL : &cert);
+ size += CFDataGetLength(data);
CFRelease(data);
- if (!res)
+ }
+
+ if (!(list->certs = RtlAllocateHeap(GetProcessHeap(), 0, size)))
+ {
+ ret = SEC_E_INSUFFICIENT_MEMORY;
+ goto done;
+ }
+
+ ptr = (BYTE *)&list->certs[list->count];
+ for (i = 0; i < list->count; i++)
+ {
+ if (!(cert = (SecCertificateRef)CFArrayGetValueAtIndex(cert_array, i)) ||
+ (SecKeychainItemExport(cert, kSecFormatX509Cert, 0, NULL, &data) != noErr))
{
- ret = GetLastError();
- WARN("CertAddEncodedCertificateToStore failed: %x\n", ret);
- break;
+ WARN("Couldn't extract certificate data\n");
+ ret = SEC_E_INTERNAL_ERROR;
+ goto done;
}
+ list->certs[i].cbData = CFDataGetLength(data);
+ list->certs[i].pbData = ptr;
+ memcpy(list->certs[i].pbData, CFDataGetBytePtr(data), CFDataGetLength(data));
+ ptr += CFDataGetLength(data);
+ CFRelease(data);
}
+done:
#ifndef HAVE_SSLCOPYPEERCERTIFICATES
/* This is why SSLGetPeerCertificates was deprecated */
- CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)),
- schan_imp_cf_release, NULL);
+ CFArrayApplyFunction(cert_array, CFRangeMake(0, CFArrayGetCount(cert_array)), cf_release, NULL);
#endif
CFRelease(cert_array);
- if (ret != SEC_E_OK) {
- if(cert)
- CertFreeCertificateContext(cert);
- return ret;
- }
-
- *ret_cert = cert;
- return SEC_E_OK;
+ return ret;
}
-SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
- SIZE_T *length)
+static SECURITY_STATUS CDECL schan_send(schan_session session, const void *buffer, SIZE_T *length)
{
struct mac_session* s = (struct mac_session*)session;
int status;
@@ -1152,8 +1163,7 @@ SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
return SEC_E_OK;
}
-SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
- SIZE_T *length)
+static SECURITY_STATUS CDECL schan_recv(schan_session session, void *buffer, SIZE_T *length)
{
struct mac_session* s = (struct mac_session*)session;
int status;
@@ -1189,36 +1199,37 @@ SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
return SEC_E_OK;
}
-BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c, const CERT_CONTEXT *cert)
+static BOOL CDECL schan_allocate_certificate_credentials(schan_credentials *c, const CERT_CONTEXT *cert,
+ const DATA_BLOB *key_blob)
{
if (cert) FIXME("no support for certificate credentials on this platform\n");
c->credentials = NULL;
return TRUE;
}
-void schan_imp_free_certificate_credentials(schan_credentials *c)
+static void CDECL schan_free_certificate_credentials(schan_credentials *c)
{
}
-void schan_imp_set_application_protocols(schan_imp_session session, unsigned char *buffer, unsigned int buflen)
+static void CDECL schan_set_application_protocols(schan_session session, unsigned char *buffer, unsigned int buflen)
{
FIXME("no support for application protocols on this platform\n");
}
-SECURITY_STATUS schan_imp_get_application_protocol(schan_imp_session session,
- SecPkgContext_ApplicationProtocol *protocol)
+static SECURITY_STATUS CDECL schan_get_application_protocol(schan_session session,
+ SecPkgContext_ApplicationProtocol *protocol)
{
FIXME("no support for application protocols on this platform\n");
return SEC_E_UNSUPPORTED_FUNCTION;
}
-SECURITY_STATUS schan_imp_set_dtls_mtu(schan_imp_session session, unsigned int mtu)
+static SECURITY_STATUS CDECL schan_set_dtls_mtu(schan_session session, unsigned int mtu)
{
FIXME("no support for setting dtls mtu on this platform\n");
return SEC_E_UNSUPPORTED_FUNCTION;
}
-BOOL schan_imp_init(void)
+static void ssl_init(void)
{
TRACE("()\n");
@@ -1245,13 +1256,38 @@ BOOL schan_imp_init(void)
}
}
#endif
-
- return TRUE;
}
-void schan_imp_deinit(void)
+static const struct schan_funcs funcs =
{
- TRACE("()\n");
+ schan_allocate_certificate_credentials,
+ schan_create_session,
+ schan_dispose_session,
+ schan_free_certificate_credentials,
+ schan_get_application_protocol,
+ schan_get_connection_info,
+ schan_get_enabled_protocols,
+ schan_get_key_signature_algorithm,
+ schan_get_max_message_size,
+ schan_get_session_cipher_block_size,
+ schan_get_session_peer_certificate,
+ schan_get_unique_channel_binding,
+ schan_handshake,
+ schan_recv,
+ schan_send,
+ schan_set_application_protocols,
+ schan_set_dtls_mtu,
+ schan_set_session_target,
+ schan_set_session_transport,
+};
+
+NTSTATUS CDECL __wine_init_unix_lib( HMODULE module, DWORD reason, const void *ptr_in, void *ptr_out )
+{
+ if (reason != DLL_PROCESS_ATTACH) return STATUS_SUCCESS;
+ ssl_init();
+ callbacks = ptr_in;
+ *(const struct schan_funcs **)ptr_out = &funcs;
+ return STATUS_SUCCESS;
}
#endif /* HAVE_SECURITY_SECURITY_H */
diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c
index 4382ec55174..04cb52dbec9 100644
--- a/dlls/secur32/secur32.c
+++ b/dlls/secur32/secur32.c
@@ -40,6 +40,8 @@
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
+HINSTANCE hsecur32;
+
/**
* Type definitions
*/
@@ -1246,6 +1248,7 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD reason, LPVOID reserved)
switch (reason)
{
case DLL_PROCESS_ATTACH:
+ hsecur32 = hinstDLL;
DisableThreadLibraryCalls(hinstDLL);
SECUR32_initializeProviders();
break;
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h
index 5571ac290e1..9d191fc4872 100644
--- a/dlls/secur32/secur32_priv.h
+++ b/dlls/secur32/secur32_priv.h
@@ -27,6 +27,8 @@
#include "wine/list.h"
#include "schannel.h"
+extern HINSTANCE hsecur32 DECLSPEC_HIDDEN;
+
typedef struct _SecureProvider
{
struct list entry;
@@ -83,7 +85,7 @@ void load_auth_packages(void) DECLSPEC_HIDDEN;
void SECUR32_deinitSchannelSP(void) DECLSPEC_HIDDEN;
/* schannel internal interface */
-typedef struct schan_imp_session_opaque *schan_imp_session;
+typedef struct schan_session_opaque *schan_session;
typedef struct schan_credentials
{
@@ -111,40 +113,43 @@ struct schan_transport
struct schan_buffers out;
};
-char *schan_get_buffer(const struct schan_transport *t, struct schan_buffers *s, SIZE_T *count) DECLSPEC_HIDDEN;
-extern int schan_pull(struct schan_transport *t, void *buff, size_t *buff_len) DECLSPEC_HIDDEN;
-extern int schan_push(struct schan_transport *t, const void *buff, size_t *buff_len) DECLSPEC_HIDDEN;
-
-extern schan_imp_session schan_session_for_transport(struct schan_transport* t) DECLSPEC_HIDDEN;
-
-/* schannel implementation interface */
-extern BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred) DECLSPEC_HIDDEN;
-extern void schan_imp_dispose_session(schan_imp_session session) DECLSPEC_HIDDEN;
-extern void schan_imp_set_session_transport(schan_imp_session session,
- struct schan_transport *t) DECLSPEC_HIDDEN;
-extern void schan_imp_set_session_target(schan_imp_session session, const char *target) DECLSPEC_HIDDEN;
-extern SECURITY_STATUS schan_imp_handshake(schan_imp_session session) DECLSPEC_HIDDEN;
-extern unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session) DECLSPEC_HIDDEN;
-extern unsigned int schan_imp_get_max_message_size(schan_imp_session session) DECLSPEC_HIDDEN;
-extern ALG_ID schan_imp_get_key_signature_algorithm(schan_imp_session session) DECLSPEC_HIDDEN;
-extern SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
- SecPkgContext_ConnectionInfo *info) DECLSPEC_HIDDEN;
-extern SECURITY_STATUS schan_imp_get_unique_channel_binding(schan_imp_session session,
- SecPkgContext_Bindings *bindings) DECLSPEC_HIDDEN;
-extern SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE,
- PCCERT_CONTEXT *cert) DECLSPEC_HIDDEN;
-extern SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
- SIZE_T *length) DECLSPEC_HIDDEN;
-extern SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
- SIZE_T *length) DECLSPEC_HIDDEN;
-extern BOOL schan_imp_allocate_certificate_credentials(schan_credentials *, const CERT_CONTEXT *) DECLSPEC_HIDDEN;
-extern void schan_imp_free_certificate_credentials(schan_credentials*) DECLSPEC_HIDDEN;
-extern DWORD schan_imp_enabled_protocols(void) DECLSPEC_HIDDEN;
-extern BOOL schan_imp_init(void) DECLSPEC_HIDDEN;
-extern void schan_imp_deinit(void) DECLSPEC_HIDDEN;
-extern void schan_imp_set_application_protocols(schan_imp_session, unsigned char *, unsigned int) DECLSPEC_HIDDEN;
-extern SECURITY_STATUS schan_imp_get_application_protocol(schan_imp_session,
- SecPkgContext_ApplicationProtocol *) DECLSPEC_HIDDEN;
-extern SECURITY_STATUS schan_imp_set_dtls_mtu(schan_imp_session, unsigned int) DECLSPEC_HIDDEN;
-
-#endif /* ndef __SECUR32_PRIV_H__ */
+struct schan_cert_list
+{
+ unsigned int count;
+ CERT_BLOB *certs;
+};
+
+struct schan_funcs
+{
+ BOOL (CDECL *allocate_certificate_credentials)(schan_credentials *, const CERT_CONTEXT *, const DATA_BLOB *);
+ BOOL (CDECL *create_session)(schan_session *, schan_credentials *);
+ void (CDECL *dispose_session)(schan_session);
+ void (CDECL *free_certificate_credentials)(schan_credentials *);
+ SECURITY_STATUS (CDECL *get_application_protocol)(schan_session, SecPkgContext_ApplicationProtocol *);
+ SECURITY_STATUS (CDECL *get_connection_info)(schan_session, SecPkgContext_ConnectionInfo *);
+ DWORD (CDECL *get_enabled_protocols)(void);
+ ALG_ID (CDECL *get_key_signature_algorithm)(schan_session);
+ unsigned int (CDECL *get_max_message_size)(schan_session);
+ unsigned int (CDECL *get_session_cipher_block_size)(schan_session);
+ SECURITY_STATUS (CDECL *get_session_peer_certificate)(schan_session, struct schan_cert_list *);
+ SECURITY_STATUS (CDECL *get_unique_channel_binding)(schan_session, SecPkgContext_Bindings *);
+ SECURITY_STATUS (CDECL *handshake)(schan_session session);
+ SECURITY_STATUS (CDECL *recv)(schan_session, void *, SIZE_T *);
+ SECURITY_STATUS (CDECL *send)(schan_session, const void *, SIZE_T *);
+ void (CDECL *set_application_protocols)(schan_session, unsigned char *, unsigned int);
+ SECURITY_STATUS (CDECL *set_dtls_mtu)(schan_session, unsigned int);
+ void (CDECL *set_session_target)(schan_session, const char *);
+ void (CDECL *set_session_transport)(schan_session, struct schan_transport *);
+};
+
+struct schan_callbacks
+{
+ char * (CDECL *get_buffer)(const struct schan_transport *, struct schan_buffers *, SIZE_T *);
+ schan_session (CDECL *get_session_for_transport)(struct schan_transport *);
+ int CDECL (CDECL *pull)(struct schan_transport *, void *, size_t *);
+ int CDECL (CDECL *push)(struct schan_transport *, const void *, size_t *);
+};
+
+extern const struct schan_funcs *schan_funcs;
+
+#endif /* __SECUR32_PRIV_H__ */
--
2.30.2