mirror of
https://github.com/reactos/reactos.git
synced 2025-08-03 18:15:58 +00:00
[SCHANNEL]
- Import TLS/SSL support on top of GNUTLS from wine Won't work until we ship the gnutls DLLs svn path=/trunk/; revision=63996
This commit is contained in:
parent
cccf98d172
commit
57108b7872
9 changed files with 2675 additions and 20 deletions
|
@ -1,12 +1,20 @@
|
|||
|
||||
include_directories(${REACTOS_SOURCE_DIR}/include/reactos/wine)
|
||||
add_definitions(-D__WINESRC__)
|
||||
include_directories(
|
||||
${REACTOS_SOURCE_DIR}/include/reactos/wine
|
||||
${REACTOS_SOURCE_DIR}/include/reactos/libs/gnutls)
|
||||
|
||||
|
||||
add_definitions(-D__WINESRC__ -D_WINE)
|
||||
spec2def(schannel.dll schannel.spec)
|
||||
|
||||
list(APPEND SOURCE
|
||||
lsamode.c
|
||||
schannel_gnutls.c
|
||||
schannel_main.c
|
||||
schannel_wine.c
|
||||
secur32_wine.c
|
||||
usermode.c
|
||||
stubs.c
|
||||
precomp.h
|
||||
${CMAKE_CURRENT_BINARY_DIR}/schannel_stubs.c)
|
||||
|
||||
|
@ -17,6 +25,6 @@ add_library(schannel SHARED
|
|||
|
||||
set_module_type(schannel win32dll)
|
||||
target_link_libraries(schannel wine)
|
||||
add_importlibs(schannel secur32 msvcrt kernel32 ntdll)
|
||||
add_importlibs(schannel crypt32 advapi32 msvcrt kernel32 ntdll)
|
||||
add_pch(schannel precomp.h SOURCE)
|
||||
add_cd_file(TARGET schannel DESTINATION reactos/system32 FOR all)
|
||||
|
|
|
@ -10,11 +10,20 @@
|
|||
#define WIN32_NO_STATUS
|
||||
#include <windef.h>
|
||||
#include <winbase.h>
|
||||
#include <winnls.h>
|
||||
#include <winreg.h>
|
||||
#include <sspi.h>
|
||||
#include <ntsecapi.h>
|
||||
#include <ntsecpkg.h>
|
||||
|
||||
#include <schannel.h>
|
||||
|
||||
#include <wine/list.h>
|
||||
#include "schannel_priv.h"
|
||||
|
||||
#include <wine/debug.h>
|
||||
#include <wine/unicode.h>
|
||||
|
||||
WINE_DEFAULT_DEBUG_CHANNEL(schannel);
|
||||
|
||||
#endif /* _SCHANNEL_PCH_ */
|
||||
|
|
|
@ -1,24 +1,24 @@
|
|||
@ stdcall AcceptSecurityContext(ptr ptr ptr long long ptr ptr ptr ptr) secur32.AcceptSecurityContext
|
||||
@ stdcall AcquireCredentialsHandleA(str str long ptr ptr ptr ptr ptr ptr) secur32.AcquireCredentialsHandleA
|
||||
@ stdcall AcquireCredentialsHandleW(wstr wstr long ptr ptr ptr ptr ptr ptr) secur32.AcquireCredentialsHandleW
|
||||
@ stdcall ApplyControlToken(ptr ptr) secur32.ApplyControlToken
|
||||
@ stdcall AcceptSecurityContext(ptr ptr ptr long long ptr ptr ptr ptr) schan_AcceptSecurityContext
|
||||
@ stdcall AcquireCredentialsHandleA(str str long ptr ptr ptr ptr ptr ptr) schan_AcquireCredentialsHandleA
|
||||
@ stdcall AcquireCredentialsHandleW(wstr wstr long ptr ptr ptr ptr ptr ptr) schan_AcquireCredentialsHandleW
|
||||
@ stdcall ApplyControlToken(ptr ptr) schan_ApplyControlToken
|
||||
@ stub CloseSslPerformanceData
|
||||
@ stub CollectSslPerformanceData
|
||||
@ stdcall CompleteAuthToken(ptr ptr) secur32.CompleteAuthToken
|
||||
@ stdcall DeleteSecurityContext(ptr) secur32.DeleteSecurityContext
|
||||
@ stdcall EnumerateSecurityPackagesA(ptr ptr) secur32.EnumerateSecurityPackagesA
|
||||
@ stdcall EnumerateSecurityPackagesW(ptr ptr) secur32.EnumerateSecurityPackagesW
|
||||
@ stdcall FreeContextBuffer(ptr) secur32.FreeContextBuffer
|
||||
@ stdcall FreeCredentialsHandle(ptr) secur32.FreeCredentialsHandle
|
||||
@ stdcall ImpersonateSecurityContext(ptr) secur32.ImpersonateSecurityContext
|
||||
@ stdcall InitSecurityInterfaceA() secur32.InitSecurityInterfaceA
|
||||
@ stdcall InitSecurityInterfaceW() secur32.InitSecurityInterfaceW
|
||||
@ stdcall InitializeSecurityContextA(ptr ptr str long long long ptr long ptr ptr ptr ptr) secur32.InitializeSecurityContextA
|
||||
@ stdcall InitializeSecurityContextW(ptr ptr wstr long long long ptr long ptr ptr ptr ptr) secur32.InitializeSecurityContextW
|
||||
@ stdcall CompleteAuthToken(ptr ptr) schan_CompleteAuthToken
|
||||
@ stdcall DeleteSecurityContext(ptr) schan_DeleteSecurityContext
|
||||
@ stdcall EnumerateSecurityPackagesA(ptr ptr) schan_EnumerateSecurityPackagesA
|
||||
@ stdcall EnumerateSecurityPackagesW(ptr ptr) schan_EnumerateSecurityPackagesW
|
||||
@ stdcall FreeContextBuffer(ptr) schan_FreeContextBuffer
|
||||
@ stdcall FreeCredentialsHandle(ptr) schan_FreeCredentialsHandle
|
||||
@ stdcall ImpersonateSecurityContext(ptr) schan_ImpersonateSecurityContext
|
||||
@ stdcall InitSecurityInterfaceA() schan_InitSecurityInterfaceA
|
||||
@ stdcall InitSecurityInterfaceW() schan_InitSecurityInterfaceW
|
||||
@ stdcall InitializeSecurityContextA(ptr ptr str long long long ptr long ptr ptr ptr ptr) schan_InitializeSecurityContextA
|
||||
@ stdcall InitializeSecurityContextW(ptr ptr wstr long long long ptr long ptr ptr ptr ptr) schan_InitializeSecurityContextW
|
||||
@ stdcall MakeSignature(ptr long ptr long) secur32.MakeSignature
|
||||
@ stub OpenSslPerformanceData
|
||||
@ stdcall QueryContextAttributesA(ptr long ptr) secur32.QueryContextAttributesA
|
||||
@ stdcall QueryContextAttributesW(ptr long ptr) secur32.QueryContextAttributesW
|
||||
@ stdcall QueryContextAttributesA(ptr long ptr) schan_QueryContextAttributesA
|
||||
@ stdcall QueryContextAttributesW(ptr long ptr) schan_QueryContextAttributesW
|
||||
@ stdcall QuerySecurityPackageInfoA(str ptr) secur32.QuerySecurityPackageInfoA
|
||||
@ stdcall QuerySecurityPackageInfoW(wstr ptr) secur32.QuerySecurityPackageInfoW
|
||||
@ stdcall RevertSecurityContext(ptr) secur32.RevertSecurityContext
|
||||
|
|
593
reactos/dll/win32/schannel/schannel_gnutls.c
Normal file
593
reactos/dll/win32/schannel/schannel_gnutls.c
Normal file
|
@ -0,0 +1,593 @@
|
|||
/*
|
||||
* GnuTLS-based implementation of the schannel (SSL/TLS) provider.
|
||||
*
|
||||
* Copyright 2005 Juan Lang
|
||||
* Copyright 2008 Henri Verbeet
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#include <wine/config.h>
|
||||
#include <wine/port.h>
|
||||
#include <strsafe.h>
|
||||
|
||||
#ifdef SONAME_LIBGNUTLS
|
||||
#include <gnutls/gnutls.h>
|
||||
#include <gnutls/crypto.h>
|
||||
#endif
|
||||
|
||||
#define __wine_dbch_secur32 __wine_dbch_schannel
|
||||
|
||||
#if defined(SONAME_LIBGNUTLS) && !defined(HAVE_SECURITY_SECURITY_H)
|
||||
|
||||
static void *libgnutls_handle;
|
||||
#define MAKE_FUNCPTR(f) static typeof(f) * p##f
|
||||
MAKE_FUNCPTR(gnutls_alert_get);
|
||||
MAKE_FUNCPTR(gnutls_alert_get_name);
|
||||
MAKE_FUNCPTR(gnutls_certificate_allocate_credentials);
|
||||
MAKE_FUNCPTR(gnutls_certificate_free_credentials);
|
||||
MAKE_FUNCPTR(gnutls_certificate_get_peers);
|
||||
MAKE_FUNCPTR(gnutls_cipher_get);
|
||||
MAKE_FUNCPTR(gnutls_cipher_get_key_size);
|
||||
MAKE_FUNCPTR(gnutls_credentials_set);
|
||||
MAKE_FUNCPTR(gnutls_deinit);
|
||||
MAKE_FUNCPTR(gnutls_global_deinit);
|
||||
MAKE_FUNCPTR(gnutls_global_init);
|
||||
MAKE_FUNCPTR(gnutls_global_set_log_function);
|
||||
MAKE_FUNCPTR(gnutls_global_set_log_level);
|
||||
MAKE_FUNCPTR(gnutls_handshake);
|
||||
MAKE_FUNCPTR(gnutls_init);
|
||||
MAKE_FUNCPTR(gnutls_kx_get);
|
||||
MAKE_FUNCPTR(gnutls_mac_get);
|
||||
MAKE_FUNCPTR(gnutls_mac_get_key_size);
|
||||
MAKE_FUNCPTR(gnutls_perror);
|
||||
MAKE_FUNCPTR(gnutls_protocol_get_version);
|
||||
MAKE_FUNCPTR(gnutls_priority_set_direct);
|
||||
MAKE_FUNCPTR(gnutls_record_get_max_size);
|
||||
MAKE_FUNCPTR(gnutls_record_recv);
|
||||
MAKE_FUNCPTR(gnutls_record_send);
|
||||
MAKE_FUNCPTR(gnutls_server_name_set);
|
||||
MAKE_FUNCPTR(gnutls_transport_get_ptr);
|
||||
MAKE_FUNCPTR(gnutls_transport_set_errno);
|
||||
MAKE_FUNCPTR(gnutls_transport_set_ptr);
|
||||
MAKE_FUNCPTR(gnutls_transport_set_pull_function);
|
||||
MAKE_FUNCPTR(gnutls_transport_set_push_function);
|
||||
#undef MAKE_FUNCPTR
|
||||
|
||||
|
||||
|
||||
static ssize_t schan_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);
|
||||
|
||||
int ret = schan_pull(transport, buff, &buff_len);
|
||||
if (ret)
|
||||
{
|
||||
pgnutls_transport_set_errno(s, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return buff_len;
|
||||
}
|
||||
|
||||
static ssize_t schan_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);
|
||||
|
||||
int ret = schan_push(transport, buff, &buff_len);
|
||||
if (ret)
|
||||
{
|
||||
pgnutls_transport_set_errno(s, ret);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return buff_len;
|
||||
}
|
||||
|
||||
static const struct {
|
||||
DWORD enable_flag;
|
||||
const char *gnutls_flag;
|
||||
} protocol_priority_flags[] = {
|
||||
{SP_PROT_TLS1_2_CLIENT, "VERS-TLS1.2"},
|
||||
{SP_PROT_TLS1_1_CLIENT, "VERS-TLS1.1"},
|
||||
{SP_PROT_TLS1_0_CLIENT, "VERS-TLS1.0"},
|
||||
{SP_PROT_SSL3_CLIENT, "VERS-SSL3.0"}
|
||||
/* {SP_PROT_SSL2_CLIENT} is not supported by GnuTLS */
|
||||
};
|
||||
|
||||
DWORD schan_imp_enabled_protocols(void)
|
||||
{
|
||||
/* NOTE: No support for SSL 2.0 */
|
||||
return SP_PROT_SSL3_CLIENT | SP_PROT_TLS1_0_CLIENT | SP_PROT_TLS1_1_CLIENT | SP_PROT_TLS1_2_CLIENT;
|
||||
}
|
||||
|
||||
BOOL schan_imp_create_session(schan_imp_session *session, schan_credentials *cred)
|
||||
{
|
||||
gnutls_session_t *s = (gnutls_session_t*)session;
|
||||
char priority[64] = "NORMAL", *p;
|
||||
unsigned i;
|
||||
|
||||
int err = pgnutls_init(s, cred->credential_use == SECPKG_CRED_INBOUND ? GNUTLS_SERVER : GNUTLS_CLIENT);
|
||||
if (err != GNUTLS_E_SUCCESS)
|
||||
{
|
||||
pgnutls_perror(err);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
p = priority + strlen(priority);
|
||||
for(i=0; i < sizeof(protocol_priority_flags)/sizeof(*protocol_priority_flags); i++) {
|
||||
*p++ = ':';
|
||||
*p++ = (cred->enabled_protocols & protocol_priority_flags[i].enable_flag) ? '+' : '-';
|
||||
strcpy(p, protocol_priority_flags[i].gnutls_flag);
|
||||
p += strlen(p);
|
||||
}
|
||||
|
||||
TRACE("Using %s priority\n", debugstr_a(priority));
|
||||
err = pgnutls_priority_set_direct(*s, priority, NULL);
|
||||
if (err != GNUTLS_E_SUCCESS)
|
||||
{
|
||||
pgnutls_perror(err);
|
||||
pgnutls_deinit(*s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
err = pgnutls_credentials_set(*s, GNUTLS_CRD_CERTIFICATE,
|
||||
(gnutls_certificate_credentials_t)cred->credentials);
|
||||
if (err != GNUTLS_E_SUCCESS)
|
||||
{
|
||||
pgnutls_perror(err);
|
||||
pgnutls_deinit(*s);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
pgnutls_transport_set_pull_function(*s, schan_pull_adapter);
|
||||
pgnutls_transport_set_push_function(*s, schan_push_adapter);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
void schan_imp_dispose_session(schan_imp_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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
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)
|
||||
{
|
||||
gnutls_session_t s = (gnutls_session_t)session;
|
||||
int err;
|
||||
|
||||
while(1) {
|
||||
err = pgnutls_handshake(s);
|
||||
switch(err) {
|
||||
case GNUTLS_E_SUCCESS:
|
||||
TRACE("Handshake completed\n");
|
||||
return SEC_E_OK;
|
||||
|
||||
case GNUTLS_E_AGAIN:
|
||||
TRACE("Continue...\n");
|
||||
return SEC_I_CONTINUE_NEEDED;
|
||||
|
||||
case GNUTLS_E_WARNING_ALERT_RECEIVED:
|
||||
{
|
||||
gnutls_alert_description_t alert = pgnutls_alert_get(s);
|
||||
|
||||
WARN("WARNING ALERT: %d %s\n", alert, pgnutls_alert_get_name(alert));
|
||||
|
||||
switch(alert) {
|
||||
case GNUTLS_A_UNRECOGNIZED_NAME:
|
||||
TRACE("Ignoring\n");
|
||||
continue;
|
||||
default:
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
case GNUTLS_E_FATAL_ALERT_RECEIVED:
|
||||
{
|
||||
gnutls_alert_description_t alert = pgnutls_alert_get(s);
|
||||
WARN("FATAL ALERT: %d %s\n", alert, pgnutls_alert_get_name(alert));
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
default:
|
||||
pgnutls_perror(err);
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* Never reached */
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
static unsigned int schannel_get_cipher_block_size(gnutls_cipher_algorithm_t cipher)
|
||||
{
|
||||
const struct
|
||||
{
|
||||
gnutls_cipher_algorithm_t cipher;
|
||||
unsigned int block_size;
|
||||
}
|
||||
algorithms[] =
|
||||
{
|
||||
{GNUTLS_CIPHER_3DES_CBC, 8},
|
||||
{GNUTLS_CIPHER_AES_128_CBC, 16},
|
||||
{GNUTLS_CIPHER_AES_256_CBC, 16},
|
||||
{GNUTLS_CIPHER_ARCFOUR_128, 1},
|
||||
{GNUTLS_CIPHER_ARCFOUR_40, 1},
|
||||
{GNUTLS_CIPHER_DES_CBC, 8},
|
||||
{GNUTLS_CIPHER_NULL, 1},
|
||||
{GNUTLS_CIPHER_RC2_40_CBC, 8},
|
||||
};
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < sizeof(algorithms) / sizeof(*algorithms); ++i)
|
||||
{
|
||||
if (algorithms[i].cipher == cipher)
|
||||
return algorithms[i].block_size;
|
||||
}
|
||||
|
||||
FIXME("Unknown cipher %#x, returning 1\n", cipher);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static DWORD schannel_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
|
||||
* context doesn't tell us which it is, so assume client for now.
|
||||
*/
|
||||
switch (proto)
|
||||
{
|
||||
case GNUTLS_SSL3: return SP_PROT_SSL3_CLIENT;
|
||||
case GNUTLS_TLS1_0: return SP_PROT_TLS1_0_CLIENT;
|
||||
case GNUTLS_TLS1_1: return SP_PROT_TLS1_1_CLIENT;
|
||||
case GNUTLS_TLS1_2: return SP_PROT_TLS1_2_CLIENT;
|
||||
default:
|
||||
FIXME("unknown protocol %d\n", proto);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ALG_ID schannel_get_cipher_algid(gnutls_cipher_algorithm_t cipher)
|
||||
{
|
||||
switch (cipher)
|
||||
{
|
||||
case GNUTLS_CIPHER_UNKNOWN:
|
||||
case GNUTLS_CIPHER_NULL: return 0;
|
||||
case GNUTLS_CIPHER_ARCFOUR_40:
|
||||
case GNUTLS_CIPHER_ARCFOUR_128: return CALG_RC4;
|
||||
case GNUTLS_CIPHER_DES_CBC:
|
||||
case GNUTLS_CIPHER_3DES_CBC: return CALG_DES;
|
||||
case GNUTLS_CIPHER_AES_128_CBC:
|
||||
case GNUTLS_CIPHER_AES_256_CBC: return CALG_AES;
|
||||
case GNUTLS_CIPHER_RC2_40_CBC: return CALG_RC2;
|
||||
default:
|
||||
FIXME("unknown algorithm %d\n", cipher);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ALG_ID schannel_get_mac_algid(gnutls_mac_algorithm_t mac)
|
||||
{
|
||||
switch (mac)
|
||||
{
|
||||
case GNUTLS_MAC_UNKNOWN:
|
||||
case GNUTLS_MAC_NULL: return 0;
|
||||
case GNUTLS_MAC_MD5: return CALG_MD5;
|
||||
case GNUTLS_MAC_SHA1:
|
||||
case GNUTLS_MAC_SHA256:
|
||||
case GNUTLS_MAC_SHA384:
|
||||
case GNUTLS_MAC_SHA512: return CALG_SHA;
|
||||
default:
|
||||
FIXME("unknown algorithm %d\n", mac);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
static ALG_ID schannel_get_kx_algid(gnutls_kx_algorithm_t kx)
|
||||
{
|
||||
switch (kx)
|
||||
{
|
||||
case GNUTLS_KX_RSA: return CALG_RSA_KEYX;
|
||||
case GNUTLS_KX_DHE_DSS:
|
||||
case GNUTLS_KX_DHE_RSA: return CALG_DH_EPHEM;
|
||||
default:
|
||||
FIXME("unknown algorithm %d\n", kx);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
unsigned int schan_imp_get_session_cipher_block_size(schan_imp_session session)
|
||||
{
|
||||
gnutls_session_t s = (gnutls_session_t)session;
|
||||
gnutls_cipher_algorithm_t cipher = pgnutls_cipher_get(s);
|
||||
return schannel_get_cipher_block_size(cipher);
|
||||
}
|
||||
|
||||
unsigned int schan_imp_get_max_message_size(schan_imp_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)
|
||||
{
|
||||
gnutls_session_t s = (gnutls_session_t)session;
|
||||
gnutls_protocol_t proto = pgnutls_protocol_get_version(s);
|
||||
gnutls_cipher_algorithm_t alg = pgnutls_cipher_get(s);
|
||||
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->dwCipherStrength = pgnutls_cipher_get_key_size(alg) * 8;
|
||||
info->aiHash = schannel_get_mac_algid(mac);
|
||||
info->dwHashStrength = pgnutls_mac_get_key_size(mac) * 8;
|
||||
info->aiExch = schannel_get_kx_algid(kx);
|
||||
/* FIXME: info->dwExchStrength? */
|
||||
info->dwExchStrength = 0;
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
SECURITY_STATUS schan_imp_get_session_peer_certificate(schan_imp_session session, HCERTSTORE store,
|
||||
PCCERT_CONTEXT *ret)
|
||||
{
|
||||
gnutls_session_t s = (gnutls_session_t)session;
|
||||
PCCERT_CONTEXT cert = NULL;
|
||||
const gnutls_datum_t *datum;
|
||||
unsigned list_size, i;
|
||||
BOOL res;
|
||||
|
||||
datum = pgnutls_certificate_get_peers(s, &list_size);
|
||||
if(!datum)
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
||||
*ret = cert;
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
SECURITY_STATUS schan_imp_send(schan_imp_session session, const void *buffer,
|
||||
SIZE_T *length)
|
||||
{
|
||||
gnutls_session_t s = (gnutls_session_t)session;
|
||||
ssize_t ret;
|
||||
|
||||
again:
|
||||
ret = pgnutls_record_send(s, buffer, *length);
|
||||
|
||||
if (ret >= 0)
|
||||
*length = ret;
|
||||
else if (ret == GNUTLS_E_AGAIN)
|
||||
{
|
||||
struct schan_transport *t = (struct schan_transport *)pgnutls_transport_get_ptr(s);
|
||||
SIZE_T count = 0;
|
||||
|
||||
if (schan_get_buffer(t, &t->out, &count))
|
||||
goto again;
|
||||
|
||||
return SEC_I_CONTINUE_NEEDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
pgnutls_perror(ret);
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
SECURITY_STATUS schan_imp_recv(schan_imp_session session, void *buffer,
|
||||
SIZE_T *length)
|
||||
{
|
||||
gnutls_session_t s = (gnutls_session_t)session;
|
||||
ssize_t ret;
|
||||
|
||||
again:
|
||||
ret = pgnutls_record_recv(s, buffer, *length);
|
||||
|
||||
if (ret >= 0)
|
||||
*length = ret;
|
||||
else if (ret == GNUTLS_E_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))
|
||||
goto again;
|
||||
|
||||
return SEC_I_CONTINUE_NEEDED;
|
||||
}
|
||||
else
|
||||
{
|
||||
pgnutls_perror(ret);
|
||||
return SEC_E_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
BOOL schan_imp_allocate_certificate_credentials(schan_credentials *c)
|
||||
{
|
||||
int ret = pgnutls_certificate_allocate_credentials((gnutls_certificate_credentials_t*)&c->credentials);
|
||||
if (ret != GNUTLS_E_SUCCESS)
|
||||
pgnutls_perror(ret);
|
||||
return (ret == GNUTLS_E_SUCCESS);
|
||||
}
|
||||
|
||||
void schan_imp_free_certificate_credentials(schan_credentials *c)
|
||||
{
|
||||
pgnutls_certificate_free_credentials(c->credentials);
|
||||
}
|
||||
|
||||
static void schan_gnutls_log(int level, const char *msg)
|
||||
{
|
||||
TRACE("<%d> %s", level, msg);
|
||||
}
|
||||
|
||||
BOOL schan_imp_init(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
#ifndef __REACTOS__
|
||||
libgnutls_handle = wine_dlopen(SONAME_LIBGNUTLS, RTLD_NOW, NULL, 0);
|
||||
if (!libgnutls_handle)
|
||||
{
|
||||
WARN("Failed to load libgnutls.\n");
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define LOAD_FUNCPTR(f) \
|
||||
if (!(p##f = wine_dlsym(libgnutls_handle, #f, NULL, 0))) \
|
||||
{ \
|
||||
ERR("Failed to load %s\n", #f); \
|
||||
goto fail; \
|
||||
}
|
||||
#else
|
||||
/*
|
||||
static const WCHAR RosSchannelKey[] = L"Software\\ReactOS\\Schannel";
|
||||
static const WCHAR PathValue[] = L"GnuTLSPath";
|
||||
WCHAR Path[MAX_PATH];
|
||||
DWORD PathSize = sizeof(Path), ValueType;
|
||||
HKEY Key;
|
||||
DWORD Error;
|
||||
|
||||
Error = RegOpenKeyW(HKEY_LOCAL_MACHINE, RosSchannelKey, &Key);
|
||||
if(Error != ERROR_SUCCESS)
|
||||
return FALSE;
|
||||
|
||||
Error = RegQueryValueExW(Key, PathValue, NULL, &ValueType, (LPBYTE)Path, &PathSize);
|
||||
RegCloseKey(Key);
|
||||
if ((Error != ERROR_SUCCESS) || (ValueType != REG_SZ))
|
||||
return FALSE;
|
||||
wcscat(Path, L"\\");
|
||||
wcscat(Path, SONAME_LIBGNUTLS);
|
||||
*/
|
||||
static const WCHAR Path[] = L"C:\\Reactos\\system32\\gnutls\\libgnutls-28.dll";
|
||||
|
||||
libgnutls_handle = LoadLibraryExW(Path, NULL, LOAD_WITH_ALTERED_SEARCH_PATH);
|
||||
if (!libgnutls_handle)
|
||||
{
|
||||
ERR("Could not load %S.\n", Path);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
#define LOAD_FUNCPTR(f) \
|
||||
if (!(p##f = (void*)GetProcAddress(libgnutls_handle, #f))) \
|
||||
{ \
|
||||
ERR("Failed to load %s\n", #f); \
|
||||
goto fail; \
|
||||
}
|
||||
#endif // __REACTOS__
|
||||
|
||||
LOAD_FUNCPTR(gnutls_alert_get)
|
||||
LOAD_FUNCPTR(gnutls_alert_get_name)
|
||||
LOAD_FUNCPTR(gnutls_certificate_allocate_credentials)
|
||||
LOAD_FUNCPTR(gnutls_certificate_free_credentials)
|
||||
LOAD_FUNCPTR(gnutls_certificate_get_peers)
|
||||
LOAD_FUNCPTR(gnutls_cipher_get)
|
||||
LOAD_FUNCPTR(gnutls_cipher_get_key_size)
|
||||
LOAD_FUNCPTR(gnutls_credentials_set)
|
||||
LOAD_FUNCPTR(gnutls_deinit)
|
||||
LOAD_FUNCPTR(gnutls_global_deinit)
|
||||
LOAD_FUNCPTR(gnutls_global_init)
|
||||
LOAD_FUNCPTR(gnutls_global_set_log_function)
|
||||
LOAD_FUNCPTR(gnutls_global_set_log_level)
|
||||
LOAD_FUNCPTR(gnutls_handshake)
|
||||
LOAD_FUNCPTR(gnutls_init)
|
||||
LOAD_FUNCPTR(gnutls_kx_get)
|
||||
LOAD_FUNCPTR(gnutls_mac_get)
|
||||
LOAD_FUNCPTR(gnutls_mac_get_key_size)
|
||||
LOAD_FUNCPTR(gnutls_perror)
|
||||
LOAD_FUNCPTR(gnutls_protocol_get_version)
|
||||
LOAD_FUNCPTR(gnutls_priority_set_direct)
|
||||
LOAD_FUNCPTR(gnutls_record_get_max_size);
|
||||
LOAD_FUNCPTR(gnutls_record_recv);
|
||||
LOAD_FUNCPTR(gnutls_record_send);
|
||||
LOAD_FUNCPTR(gnutls_server_name_set)
|
||||
LOAD_FUNCPTR(gnutls_transport_get_ptr)
|
||||
LOAD_FUNCPTR(gnutls_transport_set_errno)
|
||||
LOAD_FUNCPTR(gnutls_transport_set_ptr)
|
||||
LOAD_FUNCPTR(gnutls_transport_set_pull_function)
|
||||
LOAD_FUNCPTR(gnutls_transport_set_push_function)
|
||||
#undef LOAD_FUNCPTR
|
||||
|
||||
ret = pgnutls_global_init();
|
||||
if (ret != GNUTLS_E_SUCCESS)
|
||||
{
|
||||
pgnutls_perror(ret);
|
||||
goto fail;
|
||||
}
|
||||
|
||||
if (TRACE_ON(secur32))
|
||||
{
|
||||
pgnutls_global_set_log_level(4);
|
||||
pgnutls_global_set_log_function(schan_gnutls_log);
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
|
||||
fail:
|
||||
#ifndef __REACTOS__
|
||||
wine_dlclose(libgnutls_handle, NULL, 0);
|
||||
#else
|
||||
FreeLibrary(libgnutls_handle);
|
||||
#endif
|
||||
libgnutls_handle = NULL;
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
void schan_imp_deinit(void)
|
||||
{
|
||||
pgnutls_global_deinit();
|
||||
#ifndef __REACTOS__
|
||||
wine_dlclose(libgnutls_handle, NULL, 0);
|
||||
#else
|
||||
FreeLibrary(libgnutls_handle);
|
||||
#endif
|
||||
libgnutls_handle = NULL;
|
||||
}
|
||||
|
||||
#endif /* SONAME_LIBGNUTLS && !HAVE_SECURITY_SECURITY_H */
|
|
@ -27,7 +27,10 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved)
|
|||
if (fdwReason == DLL_WINE_PREATTACH) return FALSE; /* prefer native version */
|
||||
|
||||
if (fdwReason == DLL_PROCESS_ATTACH)
|
||||
{
|
||||
DisableThreadLibraryCalls(hinstDLL);
|
||||
SECUR32_initSchannelSP();
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
@ -43,3 +46,19 @@ BOOL WINAPI SslEmptyCacheW(LPWSTR target, DWORD flags)
|
|||
FIXME("%s %x\n", debugstr_w(target), flags);
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
PSecurityFunctionTableW
|
||||
WINAPI
|
||||
schan_InitSecurityInterfaceW(VOID)
|
||||
{
|
||||
TRACE("InitSecurityInterfaceW() called\n");
|
||||
return &schanTableW;
|
||||
}
|
||||
|
||||
PSecurityFunctionTableA
|
||||
WINAPI
|
||||
schan_InitSecurityInterfaceA(VOID)
|
||||
{
|
||||
TRACE("InitSecurityInterfaceA() called\n");
|
||||
return &schanTableA;
|
||||
}
|
||||
|
|
130
reactos/dll/win32/schannel/schannel_priv.h
Normal file
130
reactos/dll/win32/schannel/schannel_priv.h
Normal file
|
@ -0,0 +1,130 @@
|
|||
/*
|
||||
* secur32 private definitions.
|
||||
*
|
||||
* Copyright (C) 2004 Juan Lang
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#ifndef __SCHANNEL_PRIV_H__
|
||||
#define __SCHANNEL_PRIV_H__
|
||||
|
||||
typedef struct _SecureProvider
|
||||
{
|
||||
struct list entry;
|
||||
BOOL loaded;
|
||||
PWSTR moduleName;
|
||||
HMODULE lib;
|
||||
} SecureProvider;
|
||||
|
||||
typedef struct _SecurePackage
|
||||
{
|
||||
struct list entry;
|
||||
SecPkgInfoW infoW;
|
||||
SecureProvider *provider;
|
||||
} SecurePackage;
|
||||
|
||||
/* Allocates space for and initializes a new provider. If fnTableA or fnTableW
|
||||
* is non-NULL, assumes the provider is built-in, and if moduleName is non-NULL,
|
||||
* means must load the LSA/user mode functions tables from external SSP/AP module.
|
||||
* Otherwise moduleName must not be NULL.
|
||||
* Returns a pointer to the stored provider entry, for use adding packages.
|
||||
*/
|
||||
SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
|
||||
const SecurityFunctionTableW *fnTableW, PCWSTR moduleName) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Allocates space for and adds toAdd packages with the given provider.
|
||||
* provider must not be NULL, and either infoA or infoW may be NULL, but not
|
||||
* both.
|
||||
*/
|
||||
void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
|
||||
const SecPkgInfoA *infoA, const SecPkgInfoW *infoW) DECLSPEC_HIDDEN;
|
||||
|
||||
/* Initialization functions for built-in providers */
|
||||
void SECUR32_initSchannelSP(void) DECLSPEC_HIDDEN;
|
||||
|
||||
/* schannel internal interface */
|
||||
typedef struct schan_imp_session_opaque *schan_imp_session;
|
||||
|
||||
typedef struct schan_credentials
|
||||
{
|
||||
ULONG credential_use;
|
||||
void *credentials;
|
||||
DWORD enabled_protocols;
|
||||
} schan_credentials;
|
||||
|
||||
struct schan_transport;
|
||||
|
||||
struct schan_buffers
|
||||
{
|
||||
SIZE_T offset;
|
||||
SIZE_T limit;
|
||||
const SecBufferDesc *desc;
|
||||
int current_buffer_idx;
|
||||
BOOL allow_buffer_resize;
|
||||
int (*get_next_buffer)(const struct schan_transport *, struct schan_buffers *);
|
||||
};
|
||||
|
||||
struct schan_transport
|
||||
{
|
||||
struct schan_context *ctx;
|
||||
struct schan_buffers in;
|
||||
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 SECURITY_STATUS schan_imp_get_connection_info(schan_imp_session session,
|
||||
SecPkgContext_ConnectionInfo *info) 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*) 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;
|
||||
|
||||
SECURITY_STATUS
|
||||
WINAPI
|
||||
schan_FreeContextBuffer (
|
||||
PVOID pvoid
|
||||
);
|
||||
SECURITY_STATUS WINAPI schan_EnumerateSecurityPackagesA(PULONG pcPackages,
|
||||
PSecPkgInfoA *ppPackageInfo);
|
||||
SECURITY_STATUS WINAPI schan_EnumerateSecurityPackagesW(PULONG pcPackages,
|
||||
PSecPkgInfoW *ppPackageInfo);
|
||||
extern SecurityFunctionTableA schanTableA;
|
||||
extern SecurityFunctionTableW schanTableW;
|
||||
|
||||
#endif /* ndef __SCHANNEL_PRIV_H__ */
|
||||
|
||||
|
1469
reactos/dll/win32/schannel/schannel_wine.c
Normal file
1469
reactos/dll/win32/schannel/schannel_wine.c
Normal file
File diff suppressed because it is too large
Load diff
399
reactos/dll/win32/schannel/secur32_wine.c
Normal file
399
reactos/dll/win32/schannel/secur32_wine.c
Normal file
|
@ -0,0 +1,399 @@
|
|||
/* Copyright (C) 2004 Juan Lang
|
||||
*
|
||||
* This file implements loading of SSP DLLs.
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Lesser General Public
|
||||
* License as published by the Free Software Foundation; either
|
||||
* version 2.1 of the License, or (at your option) any later version.
|
||||
*
|
||||
* This library is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
||||
* Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public
|
||||
* License along with this library; if not, write to the Free Software
|
||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
||||
*/
|
||||
|
||||
#include "precomp.h"
|
||||
|
||||
#include <assert.h>
|
||||
|
||||
typedef struct _SecurePackageTable
|
||||
{
|
||||
DWORD numPackages;
|
||||
DWORD numAllocated;
|
||||
struct list table;
|
||||
} SecurePackageTable;
|
||||
|
||||
typedef struct _SecureProviderTable
|
||||
{
|
||||
DWORD numProviders;
|
||||
DWORD numAllocated;
|
||||
struct list table;
|
||||
} SecureProviderTable;
|
||||
|
||||
/**
|
||||
* Globals
|
||||
*/
|
||||
|
||||
static CRITICAL_SECTION cs;
|
||||
static CRITICAL_SECTION_DEBUG cs_debug =
|
||||
{
|
||||
0, 0, &cs,
|
||||
{ &cs_debug.ProcessLocksList, &cs_debug.ProcessLocksList },
|
||||
0, 0, { (DWORD_PTR)(__FILE__ ": cs") }
|
||||
};
|
||||
static CRITICAL_SECTION cs = { &cs_debug, -1, 0, 0, 0, 0 };
|
||||
static SecurePackageTable *packageTable = NULL;
|
||||
static SecureProviderTable *providerTable = NULL;
|
||||
|
||||
/***********************************************************************
|
||||
* EnumerateSecurityPackagesW (SECUR32.@)
|
||||
*/
|
||||
SECURITY_STATUS WINAPI schan_EnumerateSecurityPackagesW(PULONG pcPackages,
|
||||
PSecPkgInfoW *ppPackageInfo)
|
||||
{
|
||||
SECURITY_STATUS ret = SEC_E_OK;
|
||||
|
||||
TRACE("(%p, %p)\n", pcPackages, ppPackageInfo);
|
||||
|
||||
/* windows just crashes if pcPackages or ppPackageInfo is NULL, so will I */
|
||||
*pcPackages = 0;
|
||||
EnterCriticalSection(&cs);
|
||||
if (packageTable)
|
||||
{
|
||||
SecurePackage *package;
|
||||
size_t bytesNeeded;
|
||||
|
||||
bytesNeeded = packageTable->numPackages * sizeof(SecPkgInfoW);
|
||||
LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
|
||||
{
|
||||
if (package->infoW.Name)
|
||||
bytesNeeded += (lstrlenW(package->infoW.Name) + 1) * sizeof(WCHAR);
|
||||
if (package->infoW.Comment)
|
||||
bytesNeeded += (lstrlenW(package->infoW.Comment) + 1) * sizeof(WCHAR);
|
||||
}
|
||||
if (bytesNeeded)
|
||||
{
|
||||
*ppPackageInfo = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
|
||||
if (*ppPackageInfo)
|
||||
{
|
||||
ULONG i = 0;
|
||||
PWSTR nextString;
|
||||
|
||||
*pcPackages = packageTable->numPackages;
|
||||
nextString = (PWSTR)((PBYTE)*ppPackageInfo +
|
||||
packageTable->numPackages * sizeof(SecPkgInfoW));
|
||||
LIST_FOR_EACH_ENTRY(package, &packageTable->table, SecurePackage, entry)
|
||||
{
|
||||
PSecPkgInfoW pkgInfo = *ppPackageInfo + i++;
|
||||
|
||||
*pkgInfo = package->infoW;
|
||||
if (package->infoW.Name)
|
||||
{
|
||||
TRACE("Name[%d] = %S\n", i - 1, package->infoW.Name);
|
||||
pkgInfo->Name = nextString;
|
||||
lstrcpyW(nextString, package->infoW.Name);
|
||||
nextString += lstrlenW(nextString) + 1;
|
||||
}
|
||||
else
|
||||
pkgInfo->Name = NULL;
|
||||
if (package->infoW.Comment)
|
||||
{
|
||||
TRACE("Comment[%d] = %S\n", i - 1, package->infoW.Comment);
|
||||
pkgInfo->Comment = nextString;
|
||||
lstrcpyW(nextString, package->infoW.Comment);
|
||||
nextString += lstrlenW(nextString) + 1;
|
||||
}
|
||||
else
|
||||
pkgInfo->Comment = NULL;
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = SEC_E_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
}
|
||||
LeaveCriticalSection(&cs);
|
||||
TRACE("<-- 0x%08x\n", ret);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Converts info (which is assumed to be an array of cPackages SecPkgInfoW
|
||||
* structures) into an array of SecPkgInfoA structures, which it returns.
|
||||
*/
|
||||
static PSecPkgInfoA thunk_PSecPkgInfoWToA(ULONG cPackages,
|
||||
const SecPkgInfoW *info)
|
||||
{
|
||||
PSecPkgInfoA ret;
|
||||
|
||||
if (info)
|
||||
{
|
||||
size_t bytesNeeded = cPackages * sizeof(SecPkgInfoA);
|
||||
ULONG i;
|
||||
|
||||
for (i = 0; i < cPackages; i++)
|
||||
{
|
||||
if (info[i].Name)
|
||||
bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Name,
|
||||
-1, NULL, 0, NULL, NULL);
|
||||
if (info[i].Comment)
|
||||
bytesNeeded += WideCharToMultiByte(CP_ACP, 0, info[i].Comment,
|
||||
-1, NULL, 0, NULL, NULL);
|
||||
}
|
||||
ret = HeapAlloc(GetProcessHeap(), 0, bytesNeeded);
|
||||
if (ret)
|
||||
{
|
||||
PSTR nextString;
|
||||
|
||||
nextString = (PSTR)((PBYTE)ret + cPackages * sizeof(SecPkgInfoA));
|
||||
for (i = 0; i < cPackages; i++)
|
||||
{
|
||||
PSecPkgInfoA pkgInfo = ret + i;
|
||||
int bytes;
|
||||
|
||||
memcpy(pkgInfo, &info[i], sizeof(SecPkgInfoA));
|
||||
if (info[i].Name)
|
||||
{
|
||||
pkgInfo->Name = nextString;
|
||||
/* just repeat back to WideCharToMultiByte how many bytes
|
||||
* it requires, since we asked it earlier
|
||||
*/
|
||||
bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
|
||||
NULL, 0, NULL, NULL);
|
||||
WideCharToMultiByte(CP_ACP, 0, info[i].Name, -1,
|
||||
pkgInfo->Name, bytes, NULL, NULL);
|
||||
nextString += lstrlenA(nextString) + 1;
|
||||
}
|
||||
else
|
||||
pkgInfo->Name = NULL;
|
||||
if (info[i].Comment)
|
||||
{
|
||||
pkgInfo->Comment = nextString;
|
||||
/* just repeat back to WideCharToMultiByte how many bytes
|
||||
* it requires, since we asked it earlier
|
||||
*/
|
||||
bytes = WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
|
||||
NULL, 0, NULL, NULL);
|
||||
WideCharToMultiByte(CP_ACP, 0, info[i].Comment, -1,
|
||||
pkgInfo->Comment, bytes, NULL, NULL);
|
||||
nextString += lstrlenA(nextString) + 1;
|
||||
}
|
||||
else
|
||||
pkgInfo->Comment = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
ret = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/***********************************************************************
|
||||
* EnumerateSecurityPackagesA (SECUR32.@)
|
||||
*/
|
||||
SECURITY_STATUS WINAPI schan_EnumerateSecurityPackagesA(PULONG pcPackages,
|
||||
PSecPkgInfoA *ppPackageInfo)
|
||||
{
|
||||
SECURITY_STATUS ret;
|
||||
PSecPkgInfoW info;
|
||||
|
||||
ret = schan_EnumerateSecurityPackagesW(pcPackages, &info);
|
||||
if (ret == SEC_E_OK && *pcPackages && info)
|
||||
{
|
||||
*ppPackageInfo = thunk_PSecPkgInfoWToA(*pcPackages, info);
|
||||
if (*pcPackages && !*ppPackageInfo)
|
||||
{
|
||||
*pcPackages = 0;
|
||||
ret = SEC_E_INSUFFICIENT_MEMORY;
|
||||
}
|
||||
schan_FreeContextBuffer(info);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
SECURITY_STATUS
|
||||
WINAPI
|
||||
schan_FreeContextBuffer (
|
||||
PVOID pvoid
|
||||
)
|
||||
{
|
||||
HeapFree(GetProcessHeap(), 0, pvoid);
|
||||
return SEC_E_OK;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static PWSTR SECUR32_strdupW(PCWSTR str)
|
||||
{
|
||||
PWSTR ret;
|
||||
|
||||
if (str)
|
||||
{
|
||||
ret = HeapAlloc(GetProcessHeap(), 0, (lstrlenW(str) + 1) * sizeof(WCHAR));
|
||||
if (ret)
|
||||
lstrcpyW(ret, str);
|
||||
}
|
||||
else
|
||||
ret = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PWSTR SECUR32_AllocWideFromMultiByte(PCSTR str)
|
||||
{
|
||||
PWSTR ret;
|
||||
|
||||
if (str)
|
||||
{
|
||||
int charsNeeded = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
|
||||
|
||||
if (charsNeeded)
|
||||
{
|
||||
ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded * sizeof(WCHAR));
|
||||
if (ret)
|
||||
MultiByteToWideChar(CP_ACP, 0, str, -1, ret, charsNeeded);
|
||||
}
|
||||
else
|
||||
ret = NULL;
|
||||
}
|
||||
else
|
||||
ret = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str)
|
||||
{
|
||||
PSTR ret;
|
||||
|
||||
if (str)
|
||||
{
|
||||
int charsNeeded = WideCharToMultiByte(CP_ACP, 0, str, -1, NULL, 0,
|
||||
NULL, NULL);
|
||||
|
||||
if (charsNeeded)
|
||||
{
|
||||
ret = HeapAlloc(GetProcessHeap(), 0, charsNeeded);
|
||||
if (ret)
|
||||
WideCharToMultiByte(CP_ACP, 0, str, -1, ret, charsNeeded,
|
||||
NULL, NULL);
|
||||
}
|
||||
else
|
||||
ret = NULL;
|
||||
}
|
||||
else
|
||||
ret = NULL;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void _copyPackageInfo(PSecPkgInfoW info, const SecPkgInfoA *inInfoA,
|
||||
const SecPkgInfoW *inInfoW)
|
||||
{
|
||||
if (info && (inInfoA || inInfoW))
|
||||
{
|
||||
/* odd, I know, but up until Name and Comment the structures are
|
||||
* identical
|
||||
*/
|
||||
memcpy(info, inInfoW ? inInfoW : (const SecPkgInfoW *)inInfoA, sizeof(*info));
|
||||
if (inInfoW)
|
||||
{
|
||||
info->Name = SECUR32_strdupW(inInfoW->Name);
|
||||
info->Comment = SECUR32_strdupW(inInfoW->Comment);
|
||||
}
|
||||
else
|
||||
{
|
||||
info->Name = SECUR32_AllocWideFromMultiByte(inInfoA->Name);
|
||||
info->Comment = SECUR32_AllocWideFromMultiByte(inInfoA->Comment);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
|
||||
const SecurityFunctionTableW *fnTableW, PCWSTR moduleName)
|
||||
{
|
||||
SecureProvider *ret;
|
||||
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
if (!providerTable)
|
||||
{
|
||||
providerTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProviderTable));
|
||||
if (!providerTable)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_init(&providerTable->table);
|
||||
}
|
||||
|
||||
ret = HeapAlloc(GetProcessHeap(), 0, sizeof(SecureProvider));
|
||||
if (!ret)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list_add_tail(&providerTable->table, &ret->entry);
|
||||
ret->lib = NULL;
|
||||
|
||||
#ifndef __REACTOS__
|
||||
if (fnTableA || fnTableW)
|
||||
{
|
||||
ret->moduleName = moduleName ? SECUR32_strdupW(moduleName) : NULL;
|
||||
_makeFnTableA(&ret->fnTableA, fnTableA, fnTableW);
|
||||
_makeFnTableW(&ret->fnTableW, fnTableA, fnTableW);
|
||||
ret->loaded = !moduleName;
|
||||
}
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ret->moduleName = SECUR32_strdupW(moduleName);
|
||||
ret->loaded = FALSE;
|
||||
}
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
return ret;
|
||||
}
|
||||
|
||||
void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
|
||||
const SecPkgInfoA *infoA, const SecPkgInfoW *infoW)
|
||||
{
|
||||
ULONG i;
|
||||
|
||||
assert(provider);
|
||||
assert(infoA || infoW);
|
||||
|
||||
EnterCriticalSection(&cs);
|
||||
|
||||
if (!packageTable)
|
||||
{
|
||||
packageTable = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackageTable));
|
||||
if (!packageTable)
|
||||
{
|
||||
LeaveCriticalSection(&cs);
|
||||
return;
|
||||
}
|
||||
|
||||
packageTable->numPackages = 0;
|
||||
list_init(&packageTable->table);
|
||||
}
|
||||
|
||||
for (i = 0; i < toAdd; i++)
|
||||
{
|
||||
SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
|
||||
if (!package)
|
||||
continue;
|
||||
|
||||
list_add_tail(&packageTable->table, &package->entry);
|
||||
|
||||
package->provider = provider;
|
||||
_copyPackageInfo(&package->infoW,
|
||||
infoA ? &infoA[i] : NULL,
|
||||
infoW ? &infoW[i] : NULL);
|
||||
}
|
||||
packageTable->numPackages += toAdd;
|
||||
|
||||
LeaveCriticalSection(&cs);
|
||||
}
|
28
reactos/dll/win32/schannel/stubs.c
Normal file
28
reactos/dll/win32/schannel/stubs.c
Normal file
|
@ -0,0 +1,28 @@
|
|||
|
||||
#include "precomp.h"
|
||||
|
||||
SECURITY_STATUS WINAPI schan_AcceptSecurityContext(
|
||||
PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
|
||||
ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
|
||||
PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
|
||||
{
|
||||
return SEC_E_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
||||
SECURITY_STATUS WINAPI schan_ApplyControlToken(PCtxtHandle phContext,
|
||||
PSecBufferDesc pInput)
|
||||
{
|
||||
return SEC_E_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
||||
SECURITY_STATUS WINAPI schan_CompleteAuthToken(PCtxtHandle phContext,
|
||||
PSecBufferDesc pToken)
|
||||
{
|
||||
return SEC_E_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
||||
SECURITY_STATUS WINAPI schan_ImpersonateSecurityContext(PCtxtHandle phContext)
|
||||
{
|
||||
return SEC_E_UNSUPPORTED_FUNCTION;
|
||||
}
|
||||
|
Loading…
Add table
Add a link
Reference in a new issue