.Net assumes that Negotiate LSA package has index 0: https://github.com/dotnet/runtime/blob/f1d2be8f443a599a142506d622a35e1c2e683...
-- v4: secur32/tests: Add some tests for "Negotiate" LSA package. secur32: Add a better stub for LsaApCallPackageUntrusted(NegGetCallerName). secur32: Convert "Negotiate" to an LSA package.
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/secur32/lsa.c | 74 +++- dlls/secur32/negotiate.c | 700 +++++++++++++++--------------------- dlls/secur32/secur32.c | 4 - dlls/secur32/secur32_priv.h | 6 +- 4 files changed, 343 insertions(+), 441 deletions(-)
diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index 3cbd49e6b0e..857c7d451d0 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -71,6 +71,24 @@ static const char *debugstr_as(const LSA_STRING *str) return debugstr_an(str->Buffer, str->Length); }
+SECPKG_FUNCTION_TABLE *lsa_find_package(const char *name, SECPKG_USER_FUNCTION_TABLE **user_api) +{ + LSA_STRING package_name; + ULONG i; + + RtlInitString(&package_name, name); + + for (i = 0; i < loaded_packages_count; i++) + { + if (!RtlCompareString(loaded_packages[i].name, &package_name, FALSE)) + { + *user_api = loaded_packages[i].user_api; + return loaded_packages[i].lsa_api; + } + } + return NULL; +} + NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id, PVOID in_buffer, ULONG in_buffer_length, PVOID *out_buffer, PULONG out_buffer_length, PNTSTATUS status) @@ -860,17 +878,11 @@ static void add_package(struct lsa_package *package) } }
-static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id) +static BOOL initialize_package(struct lsa_package *package, void *lsa_mode_init, void *user_mode_init) { - NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG); - NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG); - - memset(package, 0, sizeof(*package)); + NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG) = lsa_mode_init; + NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG) = user_mode_init;
- package->mod = LoadLibraryW(name); - if (!package->mod) return FALSE; - - pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize"); if (pSpLsaModeInitialize) { NTSTATUS status; @@ -878,18 +890,16 @@ static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG p status = pSpLsaModeInitialize(SECPKG_INTERFACE_VERSION, &package->lsa_api_version, &package->lsa_api, &package->lsa_table_count); if (status == STATUS_SUCCESS) { - status = package->lsa_api->InitializePackage(package_id, &lsa_dispatch, NULL, NULL, &package->name); + status = package->lsa_api->InitializePackage(package->package_id, &lsa_dispatch, NULL, NULL, &package->name); if (status == STATUS_SUCCESS) { - TRACE("%s => %p, name %s, version %#lx, api table %p, table count %lu\n", - debugstr_w(name), package->mod, debugstr_an(package->name->Buffer, package->name->Length), + TRACE("name %s, version %#lx, api table %p, table count %lu\n", + debugstr_an(package->name->Buffer, package->name->Length), package->lsa_api_version, package->lsa_api, package->lsa_table_count); - package->package_id = package_id;
- status = package->lsa_api->Initialize(package_id, NULL /* FIXME: params */, NULL); + status = package->lsa_api->Initialize(package->package_id, NULL /* FIXME: params */, NULL); if (status == STATUS_SUCCESS) { - pSpUserModeInitialize = (void *)GetProcAddress(package->mod, "SpUserModeInitialize"); if (pSpUserModeInitialize) { status = pSpUserModeInitialize(SECPKG_INTERFACE_VERSION, &package->user_api_version, &package->user_api, &package->user_table_count); @@ -902,6 +912,26 @@ static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG p } }
+ return FALSE; +} + +static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id) +{ + NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG); + NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG); + + memset(package, 0, sizeof(*package)); + + package->package_id = package_id; + package->mod = LoadLibraryW(name); + if (!package->mod) return FALSE; + + pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize"); + pSpUserModeInitialize = (void *)GetProcAddress(package->mod, "SpUserModeInitialize"); + + if (initialize_package(package, pSpLsaModeInitialize, pSpUserModeInitialize)) + return TRUE; + FreeLibrary(package->mod); return FALSE; } @@ -913,6 +943,14 @@ void load_auth_packages(void) DWORD err, i; HKEY root; SecureProvider *provider; + struct lsa_package package; + + memset(&package, 0, sizeof(package)); + + /* "Negotiate" has package id 0, .Net depends on this. */ + package.package_id = 0; + if (initialize_package(&package, nego_SpLsaModeInitialize, nego_SpUserModeInitialize)) + add_package(&package);
err = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"System\CurrentControlSet\Control\Lsa", 0, KEY_READ, &root); if (err != ERROR_SUCCESS) return; @@ -921,19 +959,19 @@ void load_auth_packages(void) for (;;) { WCHAR name[MAX_SERVICE_NAME]; - struct lsa_package package;
- err = RegEnumKeyW(root, i++, name, MAX_SERVICE_NAME); + err = RegEnumKeyW(root, i, name, MAX_SERVICE_NAME); if (err == ERROR_NO_MORE_ITEMS) break;
if (err != ERROR_SUCCESS) continue;
- if (!load_package(name, &package, i)) + if (!load_package(name, &package, i + 1)) continue;
add_package(&package); + i++; }
RegCloseKey(root); diff --git a/dlls/secur32/negotiate.c b/dlls/secur32/negotiate.c index a63e458750f..c5d89a38228 100644 --- a/dlls/secur32/negotiate.c +++ b/dlls/secur32/negotiate.c @@ -19,88 +19,153 @@
#include <stdarg.h> #include <stdlib.h> + +#include "ntstatus.h" +#define WIN32_NO_STATUS #include "windef.h" #include "winbase.h" #include "sspi.h" #include "rpc.h" #include "wincred.h" +#include "ntsecapi.h" +#include "ntsecpkg.h" +#include "winternl.h"
#include "wine/debug.h" #include "secur32_priv.h"
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
-/*********************************************************************** - * QueryCredentialsAttributesA - */ -static SECURITY_STATUS SEC_ENTRY nego_QueryCredentialsAttributesA( - PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer) +struct sec_handle { - FIXME("%p, %lu, %p\n", phCredential, ulAttribute, pBuffer); + SECPKG_FUNCTION_TABLE *krb; + SECPKG_FUNCTION_TABLE *ntlm; + SECPKG_USER_FUNCTION_TABLE *user_krb; + SECPKG_USER_FUNCTION_TABLE *user_ntlm; + LSA_SEC_HANDLE handle_krb; + LSA_SEC_HANDLE handle_ntlm; +}; + +#define WINE_NO_CACHED_CREDENTIALS 0x10000000 +#define NEGO_MAX_TOKEN 12000 + +static WCHAR nego_name_W[] = {'N','e','g','o','t','i','a','t','e',0}; +static char nego_name_A[] = "Negotiate"; +static WCHAR negotiate_comment_W[] = + {'M','i','c','r','o','s','o','f','t',' ','P','a','c','k','a','g','e',' ', + 'N','e','g','o','t','i','a','t','o','r',0}; + +#define CAPS ( \ + SECPKG_FLAG_INTEGRITY | \ + SECPKG_FLAG_PRIVACY | \ + SECPKG_FLAG_CONNECTION | \ + SECPKG_FLAG_MULTI_REQUIRED | \ + SECPKG_FLAG_EXTENDED_ERROR | \ + SECPKG_FLAG_IMPERSONATION | \ + SECPKG_FLAG_ACCEPT_WIN32_NAME | \ + SECPKG_FLAG_NEGOTIABLE | \ + SECPKG_FLAG_GSS_COMPATIBLE | \ + SECPKG_FLAG_LOGON | \ + SECPKG_FLAG_RESTRICTED_TOKENS ) + +static NTSTATUS NTAPI nego_LsaApCallPackageUntrusted( PLSA_CLIENT_REQUEST req, void *in_buf, + void *client_buf_base, ULONG in_buf_len, void **out_buf, ULONG *out_buf_len, NTSTATUS *ret_status ) +{ + FIXME("%p, %p, %p, %lu, %p, %p, %p: stub\n", req, in_buf, client_buf_base, in_buf_len, out_buf, out_buf_len, ret_status); + return SEC_E_UNSUPPORTED_FUNCTION; }
-/*********************************************************************** - * QueryCredentialsAttributesW - */ -static SECURITY_STATUS SEC_ENTRY nego_QueryCredentialsAttributesW( - PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer) +static NTSTATUS NTAPI nego_LsaApInitializePackage( ULONG package_id, PLSA_DISPATCH_TABLE dispatch, + PLSA_STRING database, PLSA_STRING confidentiality, PLSA_STRING *package_name ) { - FIXME("%p, %lu, %p\n", phCredential, ulAttribute, pBuffer); - return SEC_E_UNSUPPORTED_FUNCTION; + char *name; + + name = dispatch->AllocateLsaHeap( sizeof(nego_name_A) ); + if (!name) return STATUS_NO_MEMORY; + + memcpy(name, nego_name_A, sizeof(nego_name_A)); + + *package_name = dispatch->AllocateLsaHeap( sizeof(**package_name) ); + if (!*package_name) + { + dispatch->FreeLsaHeap( name ); + return STATUS_NO_MEMORY; + } + + RtlInitString( *package_name, name ); + + return STATUS_SUCCESS; }
-struct sec_handle +static NTSTATUS NTAPI nego_SpInitialize( ULONG_PTR package_id, SECPKG_PARAMETERS *params, + LSA_SECPKG_FUNCTION_TABLE *lsa_function_table ) { - SecureProvider *krb; - SecureProvider *ntlm; - SecHandle handle_krb; - SecHandle handle_ntlm; -}; + TRACE( "%Iu, %p, %p\n", package_id, params, lsa_function_table ); + return STATUS_SUCCESS; +}
-#define WINE_NO_CACHED_CREDENTIALS 0x10000000 +static NTSTATUS NTAPI nego_SpShutdown( void ) +{ + TRACE( "\n" ); + return STATUS_SUCCESS; +}
-/*********************************************************************** - * AcquireCredentialsHandleW - */ -static SECURITY_STATUS SEC_ENTRY nego_AcquireCredentialsHandleW( - SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse, - PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, - PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry ) +static NTSTATUS NTAPI nego_SpGetInfo( SecPkgInfoW *info ) { - static SEC_WCHAR ntlmW[] = {'N','T','L','M',0}; - static SEC_WCHAR kerberosW[] = {'K','e','r','b','e','r','o','s',0}; - SECURITY_STATUS ret = SEC_E_NO_CREDENTIALS; + const SecPkgInfoW infoW = {CAPS, 1, RPC_C_AUTHN_GSS_NEGOTIATE, NEGO_MAX_TOKEN, + nego_name_W, negotiate_comment_W}; + + TRACE( "%p\n", info ); + + /* LSA will make a copy before forwarding the structure, so + * it's safe to put pointers to dynamic or constant data there. + */ + *info = infoW; + return STATUS_SUCCESS; +} + +static NTSTATUS NTAPI nego_SpAcquireCredentialsHandle( + UNICODE_STRING *principal_us, ULONG credential_use, LUID *logon_id, void *auth_data, + void *get_key_fn, void *get_key_arg, LSA_SEC_HANDLE *credential, TimeStamp *expiry ) +{ + NTSTATUS ret = SEC_E_NO_CREDENTIALS; struct sec_handle *cred; - SecurePackage *package; + SECPKG_FUNCTION_TABLE *package; + SECPKG_USER_FUNCTION_TABLE *user;
- TRACE("%s, %s, 0x%08lx, %p, %p, %p, %p, %p, %p\n", - debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse, - pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry); + TRACE( "%p, %#lx, %p, %p, %p, %p, %p, %p\n", principal_us, credential_use, + logon_id, auth_data, get_key_fn, get_key_arg, credential, expiry );
- if (!pszPackage) return SEC_E_SECPKG_NOT_FOUND; if (!(cred = calloc( 1, sizeof(*cred) ))) return SEC_E_INSUFFICIENT_MEMORY;
- if ((package = SECUR32_findPackageW( kerberosW ))) + if ((package = lsa_find_package( "Kerberos", &user ))) { - ret = package->provider->fnTableW.AcquireCredentialsHandleW( pszPrincipal, kerberosW, - fCredentialUse, pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, &cred->handle_krb, ptsExpiry ); - if (ret == SEC_E_OK) cred->krb = package->provider; + ret = package->SpAcquireCredentialsHandle( principal_us, credential_use, logon_id, auth_data, + get_key_fn, get_key_arg, &cred->handle_krb, expiry ); + if (ret == SEC_E_OK) + { + cred->krb = package; + cred->user_krb = user; + } }
- if ((package = SECUR32_findPackageW( ntlmW ))) + if ((package = lsa_find_package( "NTLM", &user ))) { - ULONG cred_use = pAuthData ? fCredentialUse : fCredentialUse | WINE_NO_CACHED_CREDENTIALS; + ULONG cred_use = auth_data ? credential_use : credential_use | WINE_NO_CACHED_CREDENTIALS;
- ret = package->provider->fnTableW.AcquireCredentialsHandleW( pszPrincipal, ntlmW, - cred_use, pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, &cred->handle_ntlm, ptsExpiry ); - if (ret == SEC_E_OK) cred->ntlm = package->provider; + ret = package->SpAcquireCredentialsHandle( principal_us, cred_use, logon_id, auth_data, + get_key_fn, get_key_arg, &cred->handle_ntlm, expiry ); + if (ret == SEC_E_OK) + { + cred->ntlm = package; + cred->user_ntlm = user; + } }
if (cred->krb || cred->ntlm) { - phCredential->dwLower = (ULONG_PTR)cred; - phCredential->dwUpper = 0; + *credential = (LSA_SEC_HANDLE)cred; return SEC_E_OK; }
@@ -108,78 +173,41 @@ static SECURITY_STATUS SEC_ENTRY nego_AcquireCredentialsHandleW( return ret; }
-/*********************************************************************** - * AcquireCredentialsHandleA - */ -static SECURITY_STATUS SEC_ENTRY nego_AcquireCredentialsHandleA( - SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse, - PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn, - PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry ) +static NTSTATUS NTAPI nego_SpFreeCredentialsHandle( LSA_SEC_HANDLE credential ) { - SECURITY_STATUS ret = SEC_E_INSUFFICIENT_MEMORY; - SEC_WCHAR *package = NULL; - SEC_WINNT_AUTH_IDENTITY_A *id = pAuthData; - SEC_WINNT_AUTH_IDENTITY_W idW = {}; - - TRACE("%s, %s, 0x%08lx, %p, %p, %p, %p, %p, %p\n", - debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse, - pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry); - - if (pszPackage) - { - int package_len = MultiByteToWideChar( CP_ACP, 0, pszPackage, -1, NULL, 0 ); - if (!(package = malloc( package_len * sizeof(SEC_WCHAR) ))) return SEC_E_INSUFFICIENT_MEMORY; - MultiByteToWideChar( CP_ACP, 0, pszPackage, -1, package, package_len ); - } - if (id && id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI) - { - idW.UserLength = MultiByteToWideChar( CP_ACP, 0, (const char *)id->User, id->UserLength, NULL, 0 ); - if (!(idW.User = malloc( idW.UserLength * sizeof(SEC_WCHAR) ))) goto done; - MultiByteToWideChar( CP_ACP, 0, (const char *)id->User, id->UserLength, idW.User, idW.UserLength ); + struct sec_handle *cred;
- idW.DomainLength = MultiByteToWideChar( CP_ACP, 0, (const char *)id->Domain, id->DomainLength, NULL, 0 ); - if (!(idW.Domain = malloc( idW.DomainLength * sizeof(SEC_WCHAR) ))) goto done; - MultiByteToWideChar( CP_ACP, 0, (const char *)id->Domain, id->DomainLength, idW.Domain, idW.DomainLength ); + TRACE( "%Ix\n", credential );
- idW.PasswordLength = MultiByteToWideChar( CP_ACP, 0, (const char *)id->Password, id->PasswordLength, NULL, 0 ); - if (!(idW.Password = malloc( idW.PasswordLength * sizeof(SEC_WCHAR) ))) goto done; - MultiByteToWideChar( CP_ACP, 0, (const char *)id->Password, id->PasswordLength, idW.Password, idW.PasswordLength ); + if (!credential) return SEC_E_INVALID_HANDLE;
- idW.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - pAuthData = &idW; - } + cred = (struct sec_handle *)credential; + if (cred->krb) cred->krb->FreeCredentialsHandle( cred->handle_krb ); + if (cred->ntlm) cred->ntlm->FreeCredentialsHandle( cred->handle_ntlm );
- ret = nego_AcquireCredentialsHandleW( NULL, package, fCredentialUse, pLogonID, pAuthData, - pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry ); -done: - free( package ); - return ret; + free( cred ); + return SEC_E_OK; }
-/*********************************************************************** - * InitializeSecurityContextW - */ -static SECURITY_STATUS SEC_ENTRY nego_InitializeSecurityContextW( - PCredHandle phCredential, PCtxtHandle phContext, SEC_WCHAR *pszTargetName, - ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry ) +static NTSTATUS NTAPI nego_SpInitLsaModeContext( LSA_SEC_HANDLE credential, LSA_SEC_HANDLE context, + UNICODE_STRING *target_name, ULONG context_req, ULONG target_data_rep, SecBufferDesc *input, + LSA_SEC_HANDLE *new_context, SecBufferDesc *output, ULONG *context_attr, TimeStamp *expiry, + BOOLEAN *mapped_context, SecBuffer *context_data ) { - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; + NTSTATUS ret = SEC_E_INVALID_HANDLE; struct sec_handle *handle = NULL, *ctxt, *new_ctxt = NULL, *cred = NULL;
- TRACE("%p, %p, %s, 0x%08lx, %lu, %lu, %p, %lu, %p, %p, %p, %p\n", - phCredential, phContext, debugstr_w(pszTargetName), fContextReq, - Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput, - pfContextAttr, ptsExpiry); + TRACE( "%Ix, %Ix, %p, %#lx, %lu, %p, %p, %p, %p, %p, %p, %p\n", credential, context, target_name, + context_req, target_data_rep, input, new_context, output, context_attr, expiry, + mapped_context, context_data );
- if (phContext) + if (context) { - handle = ctxt = (struct sec_handle *)phContext->dwLower; + handle = ctxt = (struct sec_handle *)context; } - else if (phCredential) + else if (credential) { - handle = cred = (struct sec_handle *)phCredential->dwLower; + handle = cred = (struct sec_handle *)credential; if (!(new_ctxt = ctxt = calloc( 1, sizeof(*ctxt) ))) return SEC_E_INSUFFICIENT_MEMORY; ctxt->krb = cred->krb; ctxt->ntlm = cred->ntlm; @@ -188,28 +216,26 @@ static SECURITY_STATUS SEC_ENTRY nego_InitializeSecurityContextW(
if (handle->krb) { - ret = handle->krb->fnTableW.InitializeSecurityContextW( phCredential ? &cred->handle_krb : NULL, - phContext ? &ctxt->handle_krb : NULL, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, - Reserved2, phNewContext ? &ctxt->handle_krb : NULL, pOutput, pfContextAttr, ptsExpiry ); - if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && phNewContext) + ret = handle->krb->InitLsaModeContext( credential ? cred->handle_krb : 0, + context ? ctxt->handle_krb : 0, target_name, context_req, target_data_rep, input, + new_context ? &ctxt->handle_krb : NULL, output, context_attr, expiry, mapped_context, context_data ); + if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && new_context) { ctxt->ntlm = NULL; - phNewContext->dwLower = (ULONG_PTR)ctxt; - phNewContext->dwUpper = 0; + *new_context = (LSA_SEC_HANDLE)ctxt; if (new_ctxt == ctxt) new_ctxt = NULL; } }
if (ret != SEC_E_OK && ret != SEC_I_CONTINUE_NEEDED && handle->ntlm) { - ret = handle->ntlm->fnTableW.InitializeSecurityContextW( phCredential ? &cred->handle_ntlm : NULL, - phContext ? &ctxt->handle_ntlm : NULL, pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, - Reserved2, phNewContext ? &ctxt->handle_ntlm : NULL, pOutput, pfContextAttr, ptsExpiry ); - if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && phNewContext) + ret = handle->ntlm->InitLsaModeContext( credential ? cred->handle_ntlm : 0, + context ? ctxt->handle_ntlm : 0, target_name, context_req, target_data_rep, input, + new_context ? &ctxt->handle_ntlm : NULL, output, context_attr, expiry, mapped_context, context_data ); + if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && new_context) { ctxt->krb = NULL; - phNewContext->dwLower = (ULONG_PTR)ctxt; - phNewContext->dwUpper = 0; + *new_context = (LSA_SEC_HANDLE)ctxt; if (new_ctxt == ctxt) new_ctxt = NULL; } } @@ -218,58 +244,23 @@ static SECURITY_STATUS SEC_ENTRY nego_InitializeSecurityContextW( return ret; }
-/*********************************************************************** - * InitializeSecurityContextA - */ -static SECURITY_STATUS SEC_ENTRY nego_InitializeSecurityContextA( - PCredHandle phCredential, PCtxtHandle phContext, SEC_CHAR *pszTargetName, - ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry ) -{ - SECURITY_STATUS ret; - SEC_WCHAR *target = NULL; - - TRACE("%p, %p, %s, 0x%08lx, %lu, %lu, %p, %lu, %p, %p, %p, %p\n", - phCredential, phContext, debugstr_a(pszTargetName), fContextReq, - Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput, - pfContextAttr, ptsExpiry); - - if (pszTargetName) - { - int target_len = MultiByteToWideChar( CP_ACP, 0, pszTargetName, -1, NULL, 0 ); - if (!(target = malloc( target_len * sizeof(SEC_WCHAR) ))) return SEC_E_INSUFFICIENT_MEMORY; - MultiByteToWideChar( CP_ACP, 0, pszTargetName, -1, target, target_len ); - } - ret = nego_InitializeSecurityContextW( phCredential, phContext, target, fContextReq, - Reserved1, TargetDataRep, pInput, Reserved2, - phNewContext, pOutput, pfContextAttr, ptsExpiry ); - free( target ); - return ret; -} - -/*********************************************************************** - * AcceptSecurityContext - */ -static SECURITY_STATUS SEC_ENTRY nego_AcceptSecurityContext( - PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput, - ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry) +static NTSTATUS NTAPI nego_SpAcceptLsaModeContext( LSA_SEC_HANDLE credential, LSA_SEC_HANDLE context, + SecBufferDesc *input, ULONG context_req, ULONG target_data_rep, LSA_SEC_HANDLE *new_context, + SecBufferDesc *output, ULONG *context_attr, TimeStamp *expiry, BOOLEAN *mapped_context, SecBuffer *context_data ) { SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; struct sec_handle *handle = NULL, *ctxt, *new_ctxt = NULL, *cred = NULL;
- TRACE("%p, %p, %p, 0x%08lx, %lu, %p, %p, %p, %p\n", phCredential, phContext, - pInput, fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr, - ptsExpiry); + TRACE( "%Ix, %Ix, %#lx, %lu, %p, %p, %p, %p, %p, %p, %p\n", credential, context, context_req, target_data_rep, + input, new_context, output, context_attr, expiry, mapped_context, context_data );
- if (phContext) + if (context) { - handle = ctxt = (struct sec_handle *)phContext->dwLower; + handle = ctxt = (struct sec_handle *)context; } - else if (phCredential) + else if (credential) { - handle = cred = (struct sec_handle *)phCredential->dwLower; + handle = cred = (struct sec_handle *)credential; if (!(new_ctxt = ctxt = calloc( 1, sizeof(*ctxt) ))) return SEC_E_INSUFFICIENT_MEMORY; ctxt->krb = cred->krb; ctxt->ntlm = cred->ntlm; @@ -278,28 +269,28 @@ static SECURITY_STATUS SEC_ENTRY nego_AcceptSecurityContext(
if (handle->krb) { - ret = handle->krb->fnTableW.AcceptSecurityContext( phCredential ? &cred->handle_krb : NULL, - phContext ? &ctxt->handle_krb : NULL, pInput, fContextReq, TargetDataRep, - phNewContext ? &ctxt->handle_krb : NULL, pOutput, pfContextAttr, ptsExpiry ); - if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && phNewContext) + ret = handle->krb->AcceptLsaModeContext( credential ? cred->handle_krb : 0, + context ? ctxt->handle_krb : 0, input, context_req, target_data_rep, + new_context ? &ctxt->handle_krb : NULL, + output, context_attr, expiry, mapped_context, context_data ); + if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && new_context) { ctxt->ntlm = NULL; - phNewContext->dwLower = (ULONG_PTR)ctxt; - phNewContext->dwUpper = 0; + *new_context = (LSA_SEC_HANDLE)ctxt; if (new_ctxt == ctxt) new_ctxt = NULL; } }
if (ret != SEC_E_OK && ret != SEC_I_CONTINUE_NEEDED && handle->ntlm) { - ret = handle->ntlm->fnTableW.AcceptSecurityContext( phCredential ? &cred->handle_ntlm : NULL, - phContext ? &ctxt->handle_ntlm : NULL, pInput, fContextReq, TargetDataRep, - phNewContext ? &ctxt->handle_ntlm : NULL, pOutput, pfContextAttr, ptsExpiry ); - if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && phNewContext) + ret = handle->ntlm->AcceptLsaModeContext( credential ? cred->handle_ntlm : 0, + context ? ctxt->handle_ntlm : 0, input, context_req, target_data_rep, + new_context ? &ctxt->handle_ntlm : NULL, + output, context_attr, expiry, mapped_context, context_data ); + if ((ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED) && new_context) { ctxt->krb = NULL; - phNewContext->dwLower = (ULONG_PTR)ctxt; - phNewContext->dwUpper = 0; + *new_context = (LSA_SEC_HANDLE)ctxt; if (new_ctxt == ctxt) new_ctxt = NULL; } } @@ -308,347 +299,220 @@ static SECURITY_STATUS SEC_ENTRY nego_AcceptSecurityContext( return ret; }
-/*********************************************************************** - * CompleteAuthToken - */ -static SECURITY_STATUS SEC_ENTRY nego_CompleteAuthToken(PCtxtHandle phContext, - PSecBufferDesc pToken) -{ - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; - - TRACE("%p %p\n", phContext, pToken); - - if (phContext) ret = SEC_E_UNSUPPORTED_FUNCTION; - return ret; -} - -/*********************************************************************** - * DeleteSecurityContext - */ -static SECURITY_STATUS SEC_ENTRY nego_DeleteSecurityContext(PCtxtHandle phContext) +static NTSTATUS NTAPI nego_SpDeleteContext( LSA_SEC_HANDLE context ) { SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; struct sec_handle *ctxt;
- TRACE("%p\n", phContext); + TRACE( "%Ix\n", context );
- if (!phContext) return SEC_E_INVALID_HANDLE; + if (!context) return SEC_E_INVALID_HANDLE;
- ctxt = (struct sec_handle *)phContext->dwLower; + ctxt = (struct sec_handle *)context; if (ctxt->krb) { - ret = ctxt->krb->fnTableW.DeleteSecurityContext( &ctxt->handle_krb ); + ret = ctxt->krb->DeleteContext( ctxt->handle_krb ); } else if (ctxt->ntlm) { - ret = ctxt->ntlm->fnTableW.DeleteSecurityContext( &ctxt->handle_ntlm ); + ret = ctxt->ntlm->DeleteContext( ctxt->handle_ntlm ); } TRACE( "freeing %p\n", ctxt ); free( ctxt ); return ret; }
-/*********************************************************************** - * ApplyControlToken - */ -static SECURITY_STATUS SEC_ENTRY nego_ApplyControlToken(PCtxtHandle phContext, - PSecBufferDesc pInput) -{ - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; - - TRACE("%p %p\n", phContext, pInput); - - if (phContext) ret = SEC_E_UNSUPPORTED_FUNCTION; - return ret; -} - -/*********************************************************************** - * QueryContextAttributesW - */ -static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesW( - PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer) +static NTSTATUS NTAPI nego_SpQueryContextAttributes( LSA_SEC_HANDLE context, ULONG attribute, void *buffer ) { SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; struct sec_handle *ctxt;
- TRACE("%p, %lu, %p\n", phContext, ulAttribute, pBuffer); + TRACE( "%Ix, %lu, %p\n", context, attribute, buffer );
- if (!phContext) return SEC_E_INVALID_HANDLE; + if (!context) return SEC_E_INVALID_HANDLE;
- ctxt = (struct sec_handle *)phContext->dwLower; + ctxt = (struct sec_handle *)context; if (ctxt->krb) { - ret = ctxt->krb->fnTableW.QueryContextAttributesW( &ctxt->handle_krb, ulAttribute, pBuffer ); + ret = ctxt->krb->SpQueryContextAttributes( ctxt->handle_krb, attribute, buffer ); } else if (ctxt->ntlm) { - ret = ctxt->ntlm->fnTableW.QueryContextAttributesW( &ctxt->handle_ntlm, ulAttribute, pBuffer ); + ret = ctxt->ntlm->SpQueryContextAttributes( ctxt->handle_ntlm, attribute, buffer ); } return ret; }
-/*********************************************************************** - * QueryContextAttributesA - */ -static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesA(PCtxtHandle phContext, - ULONG ulAttribute, void *pBuffer) +static SECPKG_FUNCTION_TABLE nego_lsa_table = { - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; - struct sec_handle *ctxt; - - TRACE("%p, %lu, %p\n", phContext, ulAttribute, pBuffer); - - if (!phContext) return SEC_E_INVALID_HANDLE; - - ctxt = (struct sec_handle *)phContext->dwLower; - if (ctxt->krb) - { - ret = ctxt->krb->fnTableA.QueryContextAttributesA( &ctxt->handle_krb, ulAttribute, pBuffer ); - } - else if (ctxt->ntlm) - { - ret = ctxt->ntlm->fnTableA.QueryContextAttributesA( &ctxt->handle_ntlm, ulAttribute, pBuffer ); - } - return ret; -} + nego_LsaApInitializePackage, + NULL, /* LsaLogonUser */ + NULL, /* CallPackage */ + NULL, /* LogonTerminated */ + nego_LsaApCallPackageUntrusted, + NULL, /* CallPackagePassthrough */ + NULL, /* LogonUserEx */ + NULL, /* LogonUserEx2 */ + nego_SpInitialize, + nego_SpShutdown, + nego_SpGetInfo, + NULL, /* AcceptCredentials */ + nego_SpAcquireCredentialsHandle, + NULL, /* SpQueryCredentialsAttributes */ + nego_SpFreeCredentialsHandle, + NULL, /* SaveCredentials */ + NULL, /* GetCredentials */ + NULL, /* DeleteCredentials */ + nego_SpInitLsaModeContext, + nego_SpAcceptLsaModeContext, + nego_SpDeleteContext, + NULL, /* ApplyControlToken */ + NULL, /* GetUserInfo */ + NULL, /* GetExtendedInformation */ + nego_SpQueryContextAttributes, + NULL, /* SpAddCredentials */ + NULL, /* SetExtendedInformation */ + NULL, /* SetContextAttributes */ + NULL, /* SetCredentialsAttributes */ + NULL, /* ChangeAccountPassword */ + NULL, /* QueryMetaData */ + NULL, /* ExchangeMetaData */ + NULL, /* GetCredUIContext */ + NULL, /* UpdateCredentials */ + NULL, /* ValidateTargetInfo */ + NULL, /* PostLogonUser */ +};
-/*********************************************************************** - * ImpersonateSecurityContext - */ -static SECURITY_STATUS SEC_ENTRY nego_ImpersonateSecurityContext(PCtxtHandle phContext) +NTSTATUS NTAPI nego_SpLsaModeInitialize(ULONG lsa_version, PULONG package_version, + PSECPKG_FUNCTION_TABLE *table, PULONG table_count) { - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; + TRACE("%#lx, %p, %p, %p\n", lsa_version, package_version, table, table_count);
- TRACE("%p\n", phContext); - - if (phContext) ret = SEC_E_UNSUPPORTED_FUNCTION; - return ret; + *package_version = SECPKG_INTERFACE_VERSION; + *table = &nego_lsa_table; + *table_count = 1; + return STATUS_SUCCESS; }
-/*********************************************************************** - * RevertSecurityContext - */ -static SECURITY_STATUS SEC_ENTRY nego_RevertSecurityContext(PCtxtHandle phContext) +static NTSTATUS NTAPI nego_SpInstanceInit(ULONG version, SECPKG_DLL_FUNCTIONS *dll_function_table, void **user_functions) { - SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; - - TRACE("%p\n", phContext); - - if (phContext) ret = SEC_E_UNSUPPORTED_FUNCTION; - return ret; + TRACE("%#lx, %p, %p\n", version, dll_function_table, user_functions); + return STATUS_SUCCESS; }
-/*********************************************************************** - * MakeSignature - */ -static SECURITY_STATUS SEC_ENTRY nego_MakeSignature(PCtxtHandle phContext, - ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +static NTSTATUS NTAPI nego_SpMakeSignature( LSA_SEC_HANDLE context, ULONG quality_of_protection, + SecBufferDesc *message, ULONG message_seq_no ) { SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; struct sec_handle *ctxt;
- TRACE("%p, 0x%08lx, %p, %lu\n", phContext, fQOP, pMessage, MessageSeqNo); + TRACE( "%Ix, %#lx, %p, %lu\n", context, quality_of_protection, message, message_seq_no );
- if (!phContext) return SEC_E_INVALID_HANDLE; + if (!context) return SEC_E_INVALID_HANDLE;
- ctxt = (struct sec_handle *)phContext->dwLower; - if (ctxt->krb) + ctxt = (struct sec_handle *)context; + if (ctxt->user_krb) { - ret = ctxt->krb->fnTableW.MakeSignature( &ctxt->handle_krb, fQOP, pMessage, MessageSeqNo ); + ret = ctxt->user_krb->MakeSignature( ctxt->handle_krb, quality_of_protection, message, message_seq_no ); } - else if (ctxt->ntlm) + else if (ctxt->user_ntlm) { - ret = ctxt->ntlm->fnTableW.MakeSignature( &ctxt->handle_ntlm, fQOP, pMessage, MessageSeqNo ); + ret = ctxt->user_ntlm->MakeSignature( ctxt->handle_ntlm, quality_of_protection, message, message_seq_no ); } return ret; }
-/*********************************************************************** - * VerifySignature - */ -static SECURITY_STATUS SEC_ENTRY nego_VerifySignature(PCtxtHandle phContext, - PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) +static NTSTATUS NTAPI nego_SpVerifySignature( LSA_SEC_HANDLE context, SecBufferDesc *message, + ULONG message_seq_no, ULONG *quality_of_protection ) { SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; struct sec_handle *ctxt;
- TRACE("%p, %p, %lu, %p\n", phContext, pMessage, MessageSeqNo, pfQOP); + TRACE( "%Ix, %p, %lu, %p\n", context, message, message_seq_no, quality_of_protection );
- if (!phContext) return SEC_E_INVALID_HANDLE; + if (!context) return SEC_E_INVALID_HANDLE;
- ctxt = (struct sec_handle *)phContext->dwLower; - if (ctxt->krb) + ctxt = (struct sec_handle *)context; + if (ctxt->user_krb) { - ret = ctxt->krb->fnTableW.VerifySignature( &ctxt->handle_krb, pMessage, MessageSeqNo, pfQOP ); + ret = ctxt->user_krb->VerifySignature( ctxt->handle_krb, message, message_seq_no, quality_of_protection ); } - else if (ctxt->ntlm) + else if (ctxt->user_ntlm) { - ret = ctxt->ntlm->fnTableW.VerifySignature( &ctxt->handle_ntlm, pMessage, MessageSeqNo, pfQOP ); + ret = ctxt->user_ntlm->VerifySignature( ctxt->handle_ntlm, message, message_seq_no, quality_of_protection ); } return ret; }
-/*********************************************************************** - * FreeCredentialsHandle - */ -static SECURITY_STATUS SEC_ENTRY nego_FreeCredentialsHandle(PCredHandle phCredential) -{ - struct sec_handle *cred; - - TRACE("%p\n", phCredential); - - if (!phCredential) return SEC_E_INVALID_HANDLE; - - cred = (struct sec_handle *)phCredential->dwLower; - if (cred->krb) cred->krb->fnTableW.FreeCredentialsHandle( &cred->handle_krb ); - if (cred->ntlm) cred->ntlm->fnTableW.FreeCredentialsHandle( &cred->handle_ntlm ); - - free( cred ); - return SEC_E_OK; -} - -/*********************************************************************** - * EncryptMessage - */ -static SECURITY_STATUS SEC_ENTRY nego_EncryptMessage(PCtxtHandle phContext, - ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +static NTSTATUS NTAPI nego_SpSealMessage( LSA_SEC_HANDLE context, ULONG quality_of_protection, + SecBufferDesc *message, ULONG message_seq_no ) { SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; struct sec_handle *ctxt;
- TRACE("%p, 0x%08lx, %p, %lu\n", phContext, fQOP, pMessage, MessageSeqNo); + TRACE( "%Ix, %#lx, %p, %lu\n", context, quality_of_protection, message, message_seq_no );
- if (!phContext) return SEC_E_INVALID_HANDLE; + if (!context) return SEC_E_INVALID_HANDLE;
- ctxt = (struct sec_handle *)phContext->dwLower; - if (ctxt->krb) + ctxt = (struct sec_handle *)context; + if (ctxt->user_krb) { - ret = ctxt->krb->fnTableW.EncryptMessage( &ctxt->handle_krb, fQOP, pMessage, MessageSeqNo ); + ret = ctxt->user_krb->SealMessage( ctxt->handle_krb, quality_of_protection, message, message_seq_no ); } - else if (ctxt->ntlm) + else if (ctxt->user_ntlm) { - ret = ctxt->ntlm->fnTableW.EncryptMessage( &ctxt->handle_ntlm, fQOP, pMessage, MessageSeqNo ); + ret = ctxt->user_ntlm->SealMessage( ctxt->handle_ntlm, quality_of_protection, message, message_seq_no ); } return ret; }
-/*********************************************************************** - * DecryptMessage - */ -static SECURITY_STATUS SEC_ENTRY nego_DecryptMessage(PCtxtHandle phContext, - PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) +static NTSTATUS NTAPI nego_SpUnsealMessage( LSA_SEC_HANDLE context, SecBufferDesc *message, + ULONG message_seq_no, ULONG *quality_of_protection ) { SECURITY_STATUS ret = SEC_E_INVALID_HANDLE; struct sec_handle *ctxt;
- TRACE("%p, %p, %lu, %p\n", phContext, pMessage, MessageSeqNo, pfQOP); + TRACE( "%Ix, %p, %lu, %p\n", context, message, message_seq_no, quality_of_protection );
- if (!phContext) return SEC_E_INVALID_HANDLE; + if (!context) return SEC_E_INVALID_HANDLE;
- ctxt = (struct sec_handle *)phContext->dwLower; - if (ctxt->krb) + ctxt = (struct sec_handle *)context; + if (ctxt->user_krb) { - ret = ctxt->krb->fnTableW.DecryptMessage( &ctxt->handle_krb, pMessage, MessageSeqNo, pfQOP ); + ret = ctxt->user_krb->UnsealMessage( ctxt->handle_krb, message, message_seq_no, quality_of_protection ); } - else if (ctxt->ntlm) + else if (ctxt->user_ntlm) { - ret = ctxt->ntlm->fnTableW.DecryptMessage( &ctxt->handle_ntlm, pMessage, MessageSeqNo, pfQOP ); + ret = ctxt->user_ntlm->UnsealMessage( ctxt->handle_ntlm, message, message_seq_no, quality_of_protection ); } return ret; }
-static const SecurityFunctionTableA negoTableA = { - 1, - NULL, /* EnumerateSecurityPackagesA */ - nego_QueryCredentialsAttributesA, /* QueryCredentialsAttributesA */ - nego_AcquireCredentialsHandleA, /* AcquireCredentialsHandleA */ - nego_FreeCredentialsHandle, /* FreeCredentialsHandle */ - NULL, /* Reserved2 */ - nego_InitializeSecurityContextA, /* InitializeSecurityContextA */ - nego_AcceptSecurityContext, /* AcceptSecurityContext */ - nego_CompleteAuthToken, /* CompleteAuthToken */ - nego_DeleteSecurityContext, /* DeleteSecurityContext */ - nego_ApplyControlToken, /* ApplyControlToken */ - nego_QueryContextAttributesA, /* QueryContextAttributesA */ - nego_ImpersonateSecurityContext, /* ImpersonateSecurityContext */ - nego_RevertSecurityContext, /* RevertSecurityContext */ - nego_MakeSignature, /* MakeSignature */ - nego_VerifySignature, /* VerifySignature */ - FreeContextBuffer, /* FreeContextBuffer */ - NULL, /* QuerySecurityPackageInfoA */ - NULL, /* Reserved3 */ - NULL, /* Reserved4 */ - NULL, /* ExportSecurityContext */ - NULL, /* ImportSecurityContextA */ - NULL, /* AddCredentialsA */ - NULL, /* Reserved8 */ - NULL, /* QuerySecurityContextToken */ - nego_EncryptMessage, /* EncryptMessage */ - nego_DecryptMessage, /* DecryptMessage */ - NULL, /* SetContextAttributesA */ -}; - -static const SecurityFunctionTableW negoTableW = { - 1, - NULL, /* EnumerateSecurityPackagesW */ - nego_QueryCredentialsAttributesW, /* QueryCredentialsAttributesW */ - nego_AcquireCredentialsHandleW, /* AcquireCredentialsHandleW */ - nego_FreeCredentialsHandle, /* FreeCredentialsHandle */ - NULL, /* Reserved2 */ - nego_InitializeSecurityContextW, /* InitializeSecurityContextW */ - nego_AcceptSecurityContext, /* AcceptSecurityContext */ - nego_CompleteAuthToken, /* CompleteAuthToken */ - nego_DeleteSecurityContext, /* DeleteSecurityContext */ - nego_ApplyControlToken, /* ApplyControlToken */ - nego_QueryContextAttributesW, /* QueryContextAttributesW */ - nego_ImpersonateSecurityContext, /* ImpersonateSecurityContext */ - nego_RevertSecurityContext, /* RevertSecurityContext */ - nego_MakeSignature, /* MakeSignature */ - nego_VerifySignature, /* VerifySignature */ - FreeContextBuffer, /* FreeContextBuffer */ - NULL, /* QuerySecurityPackageInfoW */ - NULL, /* Reserved3 */ - NULL, /* Reserved4 */ - NULL, /* ExportSecurityContext */ - NULL, /* ImportSecurityContextW */ - NULL, /* AddCredentialsW */ - NULL, /* Reserved8 */ - NULL, /* QuerySecurityContextToken */ - nego_EncryptMessage, /* EncryptMessage */ - nego_DecryptMessage, /* DecryptMessage */ - NULL, /* SetContextAttributesW */ +static SECPKG_USER_FUNCTION_TABLE nego_user_table = +{ + nego_SpInstanceInit, + NULL, /* SpInitUserModeContext */ + nego_SpMakeSignature, + nego_SpVerifySignature, + nego_SpSealMessage, + nego_SpUnsealMessage, + NULL, /* SpGetContextToken */ + NULL, /* SpQueryContextAttributes */ + NULL, /* SpCompleteAuthToken */ + NULL, /* SpDeleteContext */ + NULL, /* SpFormatCredentialsFn */ + NULL, /* SpMarshallSupplementalCreds */ + NULL, /* SpExportSecurityContext */ + NULL /* SpImportSecurityContext */ };
-#define NEGO_MAX_TOKEN 12000 - -static WCHAR nego_name_W[] = {'N','e','g','o','t','i','a','t','e',0}; -static char nego_name_A[] = "Negotiate"; - -static WCHAR negotiate_comment_W[] = - {'M','i','c','r','o','s','o','f','t',' ','P','a','c','k','a','g','e',' ', - 'N','e','g','o','t','i','a','t','o','r',0}; -static CHAR negotiate_comment_A[] = "Microsoft Package Negotiator"; - -#define CAPS ( \ - SECPKG_FLAG_INTEGRITY | \ - SECPKG_FLAG_PRIVACY | \ - SECPKG_FLAG_CONNECTION | \ - SECPKG_FLAG_MULTI_REQUIRED | \ - SECPKG_FLAG_EXTENDED_ERROR | \ - SECPKG_FLAG_IMPERSONATION | \ - SECPKG_FLAG_ACCEPT_WIN32_NAME | \ - SECPKG_FLAG_NEGOTIABLE | \ - SECPKG_FLAG_GSS_COMPATIBLE | \ - SECPKG_FLAG_LOGON | \ - SECPKG_FLAG_RESTRICTED_TOKENS ) - -void SECUR32_initNegotiateSP(void) +NTSTATUS NTAPI nego_SpUserModeInitialize(ULONG lsa_version, PULONG package_version, + PSECPKG_USER_FUNCTION_TABLE *table, PULONG table_count) { - SecureProvider *provider = SECUR32_addProvider(&negoTableA, &negoTableW, NULL); + TRACE("%#lx, %p, %p, %p\n", lsa_version, package_version, table, table_count);
- const SecPkgInfoW infoW = {CAPS, 1, RPC_C_AUTHN_GSS_NEGOTIATE, NEGO_MAX_TOKEN, - nego_name_W, negotiate_comment_W}; - const SecPkgInfoA infoA = {CAPS, 1, RPC_C_AUTHN_GSS_NEGOTIATE, NEGO_MAX_TOKEN, - nego_name_A, negotiate_comment_A}; - SECUR32_addPackages(provider, 1L, &infoA, &infoW); + *package_version = SECPKG_INTERFACE_VERSION; + *table = &nego_user_table; + *table_count = 1; + return STATUS_SUCCESS; } diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c index d703757bae7..46a80c9a76c 100644 --- a/dlls/secur32/secur32.c +++ b/dlls/secur32/secur32.c @@ -501,10 +501,6 @@ static void SECUR32_initializeProviders(void) SECUR32_initSchannelSP(); /* Load SSP/AP packages (Kerberos and others) */ load_auth_packages(); - /* Load the Negotiate provider last so apps stumble over the working NTLM - * provider first. Attempting to fix bug #16905 while keeping the - * application reported on wine-users on 2006-09-12 working. */ - SECUR32_initNegotiateSP(); /* Now load providers from registry */ apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"SYSTEM\CurrentControlSet\Control\SecurityProviders", 0, KEY_READ, &key); diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h index 1275a713896..0b410c9970c 100644 --- a/dlls/secur32/secur32_priv.h +++ b/dlls/secur32/secur32_priv.h @@ -24,6 +24,8 @@ #include <sys/types.h> #include <limits.h> #include "schannel.h" +#include "ntsecapi.h" +#include "ntsecpkg.h" #include "wine/list.h"
typedef struct _SecureProvider @@ -70,8 +72,10 @@ SecurePackage *SECUR32_findPackageA(PCSTR packageName) DECLSPEC_HIDDEN;
/* Initialization functions for built-in providers */ void SECUR32_initSchannelSP(void) DECLSPEC_HIDDEN; -void SECUR32_initNegotiateSP(void) DECLSPEC_HIDDEN; void load_auth_packages(void) DECLSPEC_HIDDEN; +NTSTATUS NTAPI nego_SpLsaModeInitialize(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG) DECLSPEC_HIDDEN; +NTSTATUS NTAPI nego_SpUserModeInitialize(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG) DECLSPEC_HIDDEN; +SECPKG_FUNCTION_TABLE *lsa_find_package(const char *name, SECPKG_USER_FUNCTION_TABLE **user_api) DECLSPEC_HIDDEN;
/* Cleanup functions for built-in providers */ void SECUR32_deinitSchannelSP(void) DECLSPEC_HIDDEN;
From: Dmitry Timoshkov dmitry@baikal.ru
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/secur32/lsa.c | 6 +++++- dlls/secur32/negotiate.c | 16 +++++++++++++++- 2 files changed, 20 insertions(+), 2 deletions(-)
diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index 857c7d451d0..745b97d35a9 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -98,6 +98,10 @@ NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id TRACE("%p,%lu,%p,%lu,%p,%p,%p\n", lsa_handle, package_id, in_buffer, in_buffer_length, out_buffer, out_buffer_length, status);
+ if (out_buffer) *out_buffer = NULL; + if (out_buffer_length) *out_buffer_length = 0; + if (status) *status = STATUS_SUCCESS; + for (i = 0; i < loaded_packages_count; i++) { if (loaded_packages[i].package_id == package_id) @@ -110,7 +114,7 @@ NTSTATUS WINAPI LsaCallAuthenticationPackage(HANDLE lsa_handle, ULONG package_id } }
- return STATUS_INVALID_PARAMETER; + return STATUS_NO_SUCH_PACKAGE; }
static struct lsa_handle *alloc_lsa_handle(ULONG magic) diff --git a/dlls/secur32/negotiate.c b/dlls/secur32/negotiate.c index c5d89a38228..323d14e9eaa 100644 --- a/dlls/secur32/negotiate.c +++ b/dlls/secur32/negotiate.c @@ -71,9 +71,23 @@ static WCHAR negotiate_comment_W[] = static NTSTATUS NTAPI nego_LsaApCallPackageUntrusted( PLSA_CLIENT_REQUEST req, void *in_buf, void *client_buf_base, ULONG in_buf_len, void **out_buf, ULONG *out_buf_len, NTSTATUS *ret_status ) { + ULONG *MessageType; + FIXME("%p, %p, %p, %lu, %p, %p, %p: stub\n", req, in_buf, client_buf_base, in_buf_len, out_buf, out_buf_len, ret_status);
- return SEC_E_UNSUPPORTED_FUNCTION; + if (!in_buf || in_buf_len < sizeof(*MessageType) || !out_buf || !out_buf_len || !ret_status) + return STATUS_INVALID_PARAMETER; + + MessageType = in_buf; + switch (*MessageType) + { + case 1: /* NegGetCallerName */ + *ret_status = STATUS_NO_SUCH_LOGON_SESSION; + return STATUS_SUCCESS; + + default: + return SEC_E_UNSUPPORTED_FUNCTION; + } }
static NTSTATUS NTAPI nego_LsaApInitializePackage( ULONG package_id, PLSA_DISPATCH_TABLE dispatch,
From: Dmitry Timoshkov dmitry@baikal.ru
Fixed test failures under some Windows versions.
Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/secur32/tests/negotiate.c | 78 ++++++++++++++++++++++++++++++++++ include/ntsecapi.h | 21 +++++++++ 2 files changed, 99 insertions(+)
diff --git a/dlls/secur32/tests/negotiate.c b/dlls/secur32/tests/negotiate.c index 22a0e7793df..dc470a332c7 100644 --- a/dlls/secur32/tests/negotiate.c +++ b/dlls/secur32/tests/negotiate.c @@ -21,6 +21,9 @@
#include <stdarg.h> #include <stdio.h> + +#include <ntstatus.h> +#define WIN32_NO_STATUS #include <windef.h> #include <winbase.h> #define SECURITY_WIN32 @@ -28,6 +31,9 @@ #include <rpc.h> #include <rpcdce.h> #include <secext.h> +#include <security.h> +#include <ntsecapi.h> +#include <winternl.h>
#include "wine/test.h"
@@ -346,6 +352,77 @@ done: } }
+static void test_Negotiate(void) +{ + HANDLE lsa; + NTSTATUS status, call_status; + LSA_STRING name; + ULONG size, id; + NEGOTIATE_CALLER_NAME_REQUEST req; + NEGOTIATE_CALLER_NAME_RESPONSE *resp; + + status = LsaConnectUntrusted(&lsa); + ok(!status, "got %08lx\n", status); + + RtlInitAnsiString(&name, "Negotiate"); + id = 0xdeadbeef; + status = LsaLookupAuthenticationPackage(lsa, &name, &id); + ok(!status, "got %08lx\n", status); + ok(id == 0, "got %lu\n", id); + + req.MessageType = NegGetCallerName; + req.LogonId.LowPart = 0; + req.LogonId.HighPart = 0; + resp = (void *)(ULONG_PTR)0xdeadbeef; + size = 0xdeadbeef; + call_status = 0xdeadbeef; + status = LsaCallAuthenticationPackage(lsa, 0, &req, sizeof(req), (void **)&resp, &size, &call_status); + ok(status == STATUS_SUCCESS, "got %08lx\n", status); + ok(call_status == STATUS_NO_SUCH_LOGON_SESSION || call_status == STATUS_SUCCESS, "got %08lx\n", call_status); + if (call_status == STATUS_NO_SUCH_LOGON_SESSION) + { + ok(size == 0, "got %lu\n", size); + ok(resp == NULL, "got %p\n", resp); + } + else /* STATUS_SUCCESS */ + { + if (resp && resp->CallerName) + trace("resp->CallerName = %s\n", debugstr_w(resp->CallerName)); + ok(resp != NULL, "got NULL\n"); + ok(resp->MessageType == NegGetCallerName, "got %lu\n", resp->MessageType); + ok((char *)resp->CallerName >= (char *)(resp + 1), "got %p/%p\n", resp, resp->CallerName); + ok(size >= sizeof(*resp) + (wcslen(resp->CallerName) + 1) * sizeof(WCHAR), "got %lu\n", size); + } + + size = 0xdeadbeef; + call_status = 0xdeadbeef; + status = LsaCallAuthenticationPackage(lsa, 0, NULL, 0, NULL, &size, &call_status); + ok(status == STATUS_INVALID_PARAMETER, "got %08lx\n", status); + ok(call_status == STATUS_SUCCESS, "got %08lx\n", call_status); + ok(size == 0, "got %08lx\n", size); + + size = 0xdeadbeef; + status = LsaCallAuthenticationPackage(lsa, 0, NULL, 0, NULL, &size, NULL); + ok(status == STATUS_INVALID_PARAMETER, "got %08lx\n", status); + ok(size == 0, "got %08lx\n", size); + + call_status = 0xdeadbeef; + status = LsaCallAuthenticationPackage(lsa, 0, NULL, 0, NULL, NULL, &call_status); + ok(status == STATUS_INVALID_PARAMETER, "got %08lx\n", status); + ok(call_status == STATUS_SUCCESS, "got %08lx\n", call_status); + + resp = (void *)(ULONG_PTR)0xdeadbeef; + size = 0xdeadbeef; + call_status = 0xdeadbeef; + status = LsaCallAuthenticationPackage(lsa, 0xdeadbeef, NULL, 0, (void **)&resp, &size, &call_status); + ok(status == STATUS_NO_SUCH_PACKAGE, "got %08lx\n", status); + ok(call_status == STATUS_SUCCESS, "got %08lx\n", call_status); + ok(size == 0, "got %08lx\n", size); + ok(resp == NULL, "got %p\n", resp); + + LsaDeregisterLogonProcess(lsa); +} + START_TEST(negotiate) { SecPkgInfoA *info; @@ -367,4 +444,5 @@ START_TEST(negotiate) FreeContextBuffer( info );
test_authentication(); + test_Negotiate(); } diff --git a/include/ntsecapi.h b/include/ntsecapi.h index 992aebf66d2..ded31b41e56 100644 --- a/include/ntsecapi.h +++ b/include/ntsecapi.h @@ -356,6 +356,27 @@ typedef struct _AUDIT_POLICY_INFORMATION GUID AuditCategoryGuid; } AUDIT_POLICY_INFORMATION, *PAUDIT_POLICY_INFORMATION;
+enum NEGOTIATE_MESSAGES +{ + NegEnumPackagePrefixes, + NegGetCallerName, + NegTransferCredentials, + NegMsgReserved1, + NegCallPackageMax +}; + +typedef struct _NEGOTIATE_CALLER_NAME_REQUEST +{ + ULONG MessageType; + LUID LogonId; +} NEGOTIATE_CALLER_NAME_REQUEST, *PNEGOTIATE_CALLER_NAME_REQUEST; + +typedef struct _NEGOTIATE_CALLER_NAME_RESPONSE +{ + ULONG MessageType; + PWSTR CallerName; +} NEGOTIATE_CALLER_NAME_RESPONSE, *PNEGOTIATE_CALLER_NAME_RESPONSE; + #define MICROSOFT_KERBEROS_NAME_A "Kerberos" #if defined(_MSC_VER) || defined(__MINGW32__) #define MICROSOFT_KERBEROS_NAME_W L"Kerberos"
Hans Leidekker (@hans) commented about dlls/secur32/lsa.c:
}
}
-static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id) +static BOOL initialize_package(struct lsa_package *package, void *lsa_mode_init, void *user_mode_init) {
- NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG);
- NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG);
- memset(package, 0, sizeof(*package));
- NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG) = lsa_mode_init;
- NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG) = user_mode_init;
``` static BOOL initialize_package(struct lsa_package *package, NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, ULONG *, SECPKG_FUNCTION_TABLE **, ULONG *), NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, ULONG *, SECPKG_USER_FUNCTION_TABLE **, ULONG *)) ```
Hans Leidekker (@hans) commented about dlls/secur32/lsa.c:
-static BOOL load_package(const WCHAR *name, struct lsa_package *package, ULONG package_id) +static BOOL initialize_package(struct lsa_package *package, void *lsa_mode_init, void *user_mode_init) {
- NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG);
- NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG);
- memset(package, 0, sizeof(*package));
- NTSTATUS (NTAPI *pSpLsaModeInitialize)(ULONG, PULONG, PSECPKG_FUNCTION_TABLE *, PULONG) = lsa_mode_init;
- NTSTATUS (NTAPI *pSpUserModeInitialize)(ULONG, PULONG, PSECPKG_USER_FUNCTION_TABLE *, PULONG) = user_mode_init;
- package->mod = LoadLibraryW(name);
- if (!package->mod) return FALSE;
- pSpLsaModeInitialize = (void *)GetProcAddress(package->mod, "SpLsaModeInitialize"); if (pSpLsaModeInitialize) {
While you're at it, you may want to invert this condition to reduce indentation.