Репозитории ALT
S: | 8.15.1-alt1 |
5.1: | 1.1.44-alt1.M50P.1 |
4.1: | 1.0.9-alt0.M41.35 |
4.0: | 1.0.9-alt0.M40.35 |
+backports: | 1.0.9-alt0.M40.16 |
3.0: | 20050715-alt0.1 |
+backports: | 20061212-alt0.M30.1 |
Группа :: Эмуляторы
Пакет: wine
Главная Изменения Спек Патчи Sources Загрузить Gear Bugs and FR Repocop
Патч: 0001-kerberos.patch
Скачать
Скачать
From 4f2fafdec8cd6d517ac01d259f112a61a41c62f7 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Mon, 4 Sep 2017 15:54:34 +0300
Subject: [3/9] kerberos: Add support for KerbQueryTicketCacheMessage.
Content-Type: text/plain; charset=UTF-8
Based on the code written by George Popoff.
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
---
dlls/kerberos/krb5_ap.c | 299 +++++++++++++++++++++++++++++++++++++++++++++++-
include/ntsecapi.h | 96 ++++++++++++++++
2 files changed, 392 insertions(+), 3 deletions(-)
diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c
index 0134b94f6d..a0b6053af4 100644
--- a/dlls/kerberos/krb5_ap.c
+++ b/dlls/kerberos/krb5_ap.c
@@ -1,5 +1,6 @@
/*
* Copyright 2017 Dmitry Timoshkov
+ * Copyright 2017 George Popoff
*
* Kerberos5 Authentication Package
*
@@ -30,6 +31,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "winnls.h"
#include "sspi.h"
#include "ntsecapi.h"
#include "ntsecpkg.h"
@@ -48,8 +50,36 @@ static void *libkrb5_handle;
#define MAKE_FUNCPTR(f) static typeof(f) * p_##f
MAKE_FUNCPTR(krb5_init_context);
+MAKE_FUNCPTR(krb5_free_context);
+MAKE_FUNCPTR(krb5_cccol_cursor_new);
+MAKE_FUNCPTR(krb5_cccol_cursor_next);
+MAKE_FUNCPTR(krb5_cc_close);
+MAKE_FUNCPTR(krb5_cc_start_seq_get);
+MAKE_FUNCPTR(krb5_cc_end_seq_get);
+MAKE_FUNCPTR(krb5_cc_next_cred);
+MAKE_FUNCPTR(krb5_is_config_principal);
+MAKE_FUNCPTR(krb5_decode_ticket);
+MAKE_FUNCPTR(krb5_unparse_name);
+MAKE_FUNCPTR(krb5_unparse_name_flags);
+MAKE_FUNCPTR(krb5_free_unparsed_name);
+MAKE_FUNCPTR(krb5_free_cred_contents);
#undef MAKE_FUNCPTR
+static void *heap_alloc(SIZE_T size)
+{
+ return HeapAlloc(GetProcessHeap(), 0, size);
+}
+
+static void *heap_realloc(void *p, SIZE_T size)
+{
+ return HeapReAlloc(GetProcessHeap(), 0, p, size);
+}
+
+static void heap_free(void *p)
+{
+ HeapFree(GetProcessHeap(), 0, p);
+}
+
static void load_krb5(void)
{
if (!(libkrb5_handle = wine_dlopen(SONAME_LIBKRB5, RTLD_NOW, NULL, 0)))
@@ -66,6 +96,19 @@ static void load_krb5(void)
}
LOAD_FUNCPTR(krb5_init_context)
+ LOAD_FUNCPTR(krb5_free_context)
+ LOAD_FUNCPTR(krb5_cccol_cursor_new)
+ LOAD_FUNCPTR(krb5_cccol_cursor_next)
+ LOAD_FUNCPTR(krb5_cc_close)
+ LOAD_FUNCPTR(krb5_cc_start_seq_get)
+ LOAD_FUNCPTR(krb5_cc_end_seq_get)
+ LOAD_FUNCPTR(krb5_cc_next_cred)
+ LOAD_FUNCPTR(krb5_is_config_principal)
+ LOAD_FUNCPTR(krb5_decode_ticket)
+ LOAD_FUNCPTR(krb5_unparse_name)
+ LOAD_FUNCPTR(krb5_unparse_name_flags)
+ LOAD_FUNCPTR(krb5_free_unparsed_name)
+ LOAD_FUNCPTR(krb5_free_cred_contents)
#undef LOAD_FUNCPTR
return;
@@ -111,15 +154,265 @@ static NTSTATUS NTAPI krb5_LsaApInitializePackage(ULONG package_id, PLSA_DISPATC
return STATUS_SUCCESS;
}
+static NTSTATUS krb5_error_to_status(krb5_error_code error)
+{
+ switch (error)
+ {
+ case 0: return STATUS_SUCCESS;
+
+ default:
+ /* FIXME */
+ return STATUS_UNSUCCESSFUL;
+ }
+}
+
+static WCHAR *utf8_to_wstr(const char *utf8)
+{
+ int size;
+ WCHAR *wstr;
+
+ size = MultiByteToWideChar(CP_UTF8, 0, utf8, -1, NULL, 0);
+ wstr = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
+ if (wstr)
+ MultiByteToWideChar(CP_UTF8, 0, utf8, -1, wstr, size);
+
+ return wstr;
+}
+
+static NTSTATUS copy_ticket_info(krb5_context context, krb5_ccache cache, KERB_TICKET_CACHE_INFO *ticket_info)
+{
+ NTSTATUS status;
+ krb5_cc_cursor cursor;
+ krb5_error_code error;
+ krb5_creds credentials;
+ krb5_ticket *ticket;
+ char *name_with_realm;
+ char *name_without_realm;
+ char *realm_name;
+ WCHAR *realm_nameW;
+ WCHAR *name_without_realmW;
+
+ error = p_krb5_cc_start_seq_get(context, cache, &cursor);
+ if (error) return krb5_error_to_status(error);
+
+ status = STATUS_SUCCESS;
+
+ for (;;)
+ {
+ error = p_krb5_cc_next_cred(context, cache, &cursor, &credentials);
+ if (error)
+ {
+ status = krb5_error_to_status(error);
+ break;
+ }
+
+ if (p_krb5_is_config_principal(context, credentials.server))
+ {
+ p_krb5_free_cred_contents(context, &credentials);
+ continue;
+ }
+
+ error = p_krb5_unparse_name(context, credentials.server, &name_with_realm);
+ if (error)
+ {
+ p_krb5_free_cred_contents(context, &credentials);
+ status = krb5_error_to_status(error);
+ break;
+ }
+
+ TRACE("name_with_realm: %s\n", debugstr_a(name_with_realm));
+
+ error = p_krb5_unparse_name_flags(context, credentials.server,
+ KRB5_PRINCIPAL_UNPARSE_NO_REALM, &name_without_realm);
+ if (error)
+ {
+ p_krb5_free_unparsed_name(context, name_with_realm);
+ p_krb5_free_cred_contents(context, &credentials);
+ status = krb5_error_to_status(error);
+ break;
+ }
+
+ TRACE("name_without_realm: %s\n", debugstr_a(name_without_realm));
+
+ name_without_realmW = utf8_to_wstr(name_without_realm);
+ RtlInitUnicodeString(&ticket_info->ServerName, name_without_realmW);
+
+ realm_name = name_with_realm;
+
+ /* Increment pointer while not contain realm name */
+ do {
+ ++realm_name;
+ } while (*realm_name != '@' && *realm_name != '\0');
+ ++realm_name;
+
+ /* realm_name - now contains only realm! */
+
+ realm_nameW = utf8_to_wstr(realm_name);
+ RtlInitUnicodeString(&ticket_info->RealmName, realm_nameW);
+
+ if (!credentials.times.starttime)
+ credentials.times.starttime = credentials.times.authtime;
+
+ /* TODO: if krb5_is_config_principal = true */
+ RtlSecondsSince1970ToTime(credentials.times.starttime, &ticket_info->StartTime);
+ RtlSecondsSince1970ToTime(credentials.times.endtime, &ticket_info->EndTime);
+ RtlSecondsSince1970ToTime(credentials.times.renew_till, &ticket_info->RenewTime);
+
+ ticket_info->TicketFlags = credentials.ticket_flags;
+
+ error = p_krb5_decode_ticket(&credentials.ticket, &ticket);
+ if (error)
+ status = krb5_error_to_status(error);
+ else
+ {
+ ticket_info->EncryptionType = ticket->enc_part.enctype;
+ status = STATUS_SUCCESS;
+ }
+
+ p_krb5_free_unparsed_name(context, name_with_realm);
+ p_krb5_free_unparsed_name(context, name_without_realm);
+ p_krb5_free_cred_contents(context, &credentials);
+
+ break;
+ }
+
+ p_krb5_cc_end_seq_get(context, cache, &cursor);
+
+ return status;
+}
+
+static NTSTATUS query_ticket_cache(PLSA_CLIENT_REQUEST lsa_req, void *in, ULONG in_len, void **out, ULONG *out_len)
+{
+ NTSTATUS status;
+ KERB_QUERY_TKT_CACHE_REQUEST *query;
+ KERB_QUERY_TKT_CACHE_RESPONSE *resp;
+ ULONG tickets_allocated;
+ krb5_error_code error;
+ krb5_context context = NULL;
+ krb5_cccol_cursor cursor;
+ krb5_ccache cache;
+
+ if (!in || in_len != sizeof(KERB_QUERY_TKT_CACHE_REQUEST) || !out || !out_len)
+ return STATUS_INVALID_PARAMETER;
+
+ query = (KERB_QUERY_TKT_CACHE_REQUEST *)in;
+
+ if (query->LogonId.HighPart != 0 || query->LogonId.LowPart != 0)
+ return STATUS_ACCESS_DENIED;
+
+ tickets_allocated = 16;
+ resp = heap_alloc(sizeof(*resp) + sizeof(resp->Tickets[0]) * (tickets_allocated - 1));
+ if (!resp) return STATUS_NO_MEMORY;
+
+ resp->MessageType = KerbQueryTicketCacheMessage;
+ resp->CountOfTickets = 0;
+
+ error = p_krb5_init_context(&context);
+ if (error)
+ {
+ status = krb5_error_to_status(error);
+ goto done;
+ }
+
+ error = p_krb5_cccol_cursor_new(context, &cursor);
+ if (error)
+ {
+ status = krb5_error_to_status(error);
+ goto done;
+ }
+
+ for (;;)
+ {
+ error = p_krb5_cccol_cursor_next(context, cursor, &cache);
+ if (error || !cache)
+ {
+ status = krb5_error_to_status(error);
+ break;
+ }
+
+ if (resp->CountOfTickets == tickets_allocated)
+ {
+ KERB_QUERY_TKT_CACHE_RESPONSE *new_resp;
+
+ tickets_allocated *= 2;
+ new_resp = heap_realloc(resp, sizeof(*resp) + sizeof(resp->Tickets[0]) * (tickets_allocated - 1));
+ if (!new_resp)
+ {
+ status = STATUS_NO_MEMORY;
+ p_krb5_cc_close(context, cache);
+ break;
+ }
+
+ resp = new_resp;
+ }
+
+ status = copy_ticket_info(context, cache, &resp->Tickets[resp->CountOfTickets]);
+ if (status == STATUS_SUCCESS)
+ resp->CountOfTickets++;
+
+ p_krb5_cc_close(context, cache);
+ }
+
+ if (status) goto done;
+
+ /* FIXME: copy server/realm names to client space as well.
+ * As long as LSA works in current process space it's OK.
+ */
+
+ *out_len = sizeof(*resp);
+ if (resp->CountOfTickets > 1)
+ *out_len += sizeof(resp->Tickets[0]) * (resp->CountOfTickets - 1);
+ status = lsa_dispatch.AllocateClientBuffer(lsa_req, *out_len, out);
+ if (status) goto done;
+
+ status = lsa_dispatch.CopyToClientBuffer(lsa_req, *out_len, *out, resp);
+ if (status)
+ lsa_dispatch.FreeClientBuffer(lsa_req, *out);
+
+done:
+ if (context)
+ p_krb5_free_context(context);
+ heap_free(resp);
+ return status;
+}
+
static NTSTATUS NTAPI krb5_LsaApCallPackageUntrusted(PLSA_CLIENT_REQUEST request,
PVOID in_buffer, PVOID client_buffer_base, ULONG in_buffer_length,
PVOID *out_buffer, PULONG out_buffer_length, PNTSTATUS status)
{
- FIXME("%p,%p,%p,%u,%p,%p,%p: stub\n", request, in_buffer, client_buffer_base,
+ KERB_PROTOCOL_MESSAGE_TYPE msg;
+
+ TRACE("%p,%p,%p,%u,%p,%p,%p\n", request, in_buffer, client_buffer_base,
in_buffer_length, out_buffer, out_buffer_length, status);
- *status = STATUS_NOT_IMPLEMENTED;
- return STATUS_NOT_IMPLEMENTED;
+ if (!in_buffer || in_buffer_length < sizeof(msg))
+ return STATUS_INVALID_PARAMETER;
+
+ msg = *(KERB_PROTOCOL_MESSAGE_TYPE *)in_buffer;
+
+ switch(msg)
+ {
+ case KerbQueryTicketCacheMessage:
+ *status = query_ticket_cache(request, in_buffer, in_buffer_length, out_buffer, out_buffer_length);
+ break;
+
+ case KerbRetrieveTicketMessage:
+ FIXME("KerbRetrieveTicketMessage stub\n");
+ *status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ case KerbPurgeTicketCacheMessage:
+ FIXME("KerbPurgeTicketCacheMessage stub\n");
+ *status = STATUS_NOT_IMPLEMENTED;
+ break;
+
+ default: /* All other requests should call LsaApCallPackage */
+ WARN("%u => access denied\n", msg);
+ *status = STATUS_ACCESS_DENIED;
+ break;
+ }
+
+ return *status;
}
static SECPKG_FUNCTION_TABLE krb5_table =
diff --git a/include/ntsecapi.h b/include/ntsecapi.h
index 36357c61b4..3193b10f42 100644
--- a/include/ntsecapi.h
+++ b/include/ntsecapi.h
@@ -352,6 +352,102 @@ static const WCHAR MICROSOFT_KERBEROS_NAME_W[] = { 'K','e','r','b','e','r','o','
#define MICROSOFT_KERBEROS_NAME_A "Kerberos"
#endif
+#define KERB_TICKET_FLAGS_reserved 0x80000000
+#define KERB_TICKET_FLAGS_forwardable 0x40000000
+#define KERB_TICKET_FLAGS_forwarded 0x20000000
+#define KERB_TICKET_FLAGS_proxiable 0x10000000
+#define KERB_TICKET_FLAGS_proxy 0x08000000
+#define KERB_TICKET_FLAGS_may_postdate 0x04000000
+#define KERB_TICKET_FLAGS_postdated 0x02000000
+#define KERB_TICKET_FLAGS_invalid 0x01000000
+#define KERB_TICKET_FLAGS_renewable 0x00800000
+#define KERB_TICKET_FLAGS_initial 0x00400000
+#define KERB_TICKET_FLAGS_pre_authent 0x00200000
+#define KERB_TICKET_FLAGS_hw_authent 0x00100000
+#define KERB_TICKET_FLAGS_ok_as_delegate 0x00040000
+#define KERB_TICKET_FLAGS_name_canonicalize 0x00010000
+#define KERB_TICKET_FLAGS_cname_in_pa_data 0x00040000
+#define KERB_TICKET_FLAGS_reserved1 0x00000001
+
+typedef enum _KERB_PROTOCOL_MESSAGE_TYPE
+{
+ KerbDebugRequestMessage = 0,
+ KerbQueryTicketCacheMessage,
+ KerbChangeMachinePasswordMessage,
+ KerbVerifyPacMessage,
+ KerbRetrieveTicketMessage,
+ KerbUpdateAddressesMessage,
+ KerbPurgeTicketCacheMessage,
+ KerbChangePasswordMessage,
+ KerbRetrieveEncodedTicketMessage,
+ KerbDecryptDataMessage,
+ KerbAddBindingCacheEntryMessage,
+ KerbSetPasswordMessage,
+ KerbSetPasswordExMessage,
+ KerbVerifyCredentialsMessage,
+ KerbQueryTicketCacheExMessage,
+ KerbPurgeTicketCacheExMessage,
+ KerbRefreshSmartcardCredentialsMessage,
+ KerbAddExtraCredentialsMessage,
+ KerbQuerySupplementalCredentialsMessage,
+ KerbTransferCredentialsMessage,
+ KerbQueryTicketCacheEx2Message,
+ KerbSubmitTicketMessage,
+ KerbAddExtraCredentialsExMessage,
+ KerbQueryKdcProxyCacheMessage,
+ KerbPurgeKdcProxyCacheMessage,
+ KerbQueryTicketCacheEx3Message,
+ KerbCleanupMachinePkinitCredsMessage,
+ KerbAddBindingCacheEntryExMessage,
+ KerbQueryBindingCacheMessage,
+ KerbPurgeBindingCacheMessage,
+ KerbQueryDomainExtendedPoliciesMessage,
+ KerbQueryS4U2ProxyCacheMessage
+} KERB_PROTOCOL_MESSAGE_TYPE, *PKERB_PROTOCOL_MESSAGE_TYPE;
+
+typedef struct _KERB_TICKET_CACHE_INFO
+{
+ UNICODE_STRING ServerName;
+ UNICODE_STRING RealmName;
+ LARGE_INTEGER StartTime;
+ LARGE_INTEGER EndTime;
+ LARGE_INTEGER RenewTime;
+ LONG EncryptionType;
+ ULONG TicketFlags;
+} KERB_TICKET_CACHE_INFO, *PKERB_TICKET_CACHE_INFO;
+
+typedef struct _KERB_QUERY_TKT_CACHE_REQUEST
+{
+ KERB_PROTOCOL_MESSAGE_TYPE MessageType;
+ LUID LogonId;
+} KERB_QUERY_TKT_CACHE_REQUEST, *PKERB_QUERY_TKT_CACHE_REQUEST;
+
+typedef struct _KERB_QUERY_TKT_CACHE_RESPONSE
+{
+ KERB_PROTOCOL_MESSAGE_TYPE MessageType;
+ ULONG CountOfTickets;
+ KERB_TICKET_CACHE_INFO Tickets[ANYSIZE_ARRAY];
+} KERB_QUERY_TKT_CACHE_RESPONSE, *PKERB_QUERY_TKT_CACHE_RESPONSE;
+
+typedef struct _KERB_RETRIEVE_TKT_REQUEST
+{
+ KERB_PROTOCOL_MESSAGE_TYPE MessageType;
+ LUID LogonId;
+ UNICODE_STRING TargetName;
+ ULONG TicketFlags;
+ ULONG CacheOptions;
+ LONG EncryptionType;
+ SecHandle CredentialsHandle;
+} KERB_RETRIEVE_TKT_REQUEST, *PKERB_RETRIEVE_TKT_REQUEST;
+
+typedef struct _KERB_PURGE_TKT_CACHE_REQUEST
+{
+ KERB_PROTOCOL_MESSAGE_TYPE MessageType;
+ LUID LogonId;
+ UNICODE_STRING ServerName;
+ UNICODE_STRING RealmName;
+} KERB_PURGE_TKT_CACHE_REQUEST, *PKERB_PURGE_TKT_CACHE_REQUEST;
+
#define RtlGenRandom SystemFunction036
#define RtlEncryptMemory SystemFunction040
#define RtlDecryptMemory SystemFunction041
--
2.15.0
From 59a89a2d862dd456335f1b0a30a4f914422caf7d Mon Sep 17 00:00:00 2001
From: George Popoff <ambulance@etersoft.ru>
Date: Wed, 11 Oct 2017 14:25:15 +0300
Subject: [4/9] add wincred.h include for missing SecHandle definition
Content-Type: text/plain; charset=UTF-8
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
---
dlls/advapi32/advapi32_misc.h | 1 +
dlls/advapi32/tests/lsa.c | 1 +
dlls/advapi32/tests/security.c | 1 +
dlls/bcrypt/bcrypt_main.c | 1 +
dlls/jscript/math.c | 1 +
dlls/kerberos/krb5_ap.c | 1 +
dlls/msvcrt/misc.c | 1 +
dlls/netapi32/netapi32.c | 1 +
dlls/rpcrt4/rpcrt4_main.c | 1 +
dlls/rpcrt4/tests/rpc.c | 1 +
dlls/schannel/lsamode.c | 1 +
dlls/schannel/tests/main.c | 1 +
dlls/schannel/usermode.c | 1 +
dlls/scrrun/filesystem.c | 1 +
dlls/secur32/lsa.c | 1 +
dlls/secur32/secur32.c | 1 +
dlls/wbemprox/builtin.c | 1 +
programs/services/rpc.c | 1 +
18 files changed, 18 insertions(+)
diff --git a/dlls/advapi32/advapi32_misc.h b/dlls/advapi32/advapi32_misc.h
index 7fc02a4a2e..b55ecf4072 100644
--- a/dlls/advapi32/advapi32_misc.h
+++ b/dlls/advapi32/advapi32_misc.h
@@ -20,6 +20,7 @@
#ifndef __WINE_ADVAPI32MISC_H
#define __WINE_ADVAPI32MISC_H
+#include "wincred.h"
#include "ntsecapi.h"
#include "winsvc.h"
#include "winnls.h"
diff --git a/dlls/advapi32/tests/lsa.c b/dlls/advapi32/tests/lsa.c
index d7f2e498ef..939fd488ee 100644
--- a/dlls/advapi32/tests/lsa.c
+++ b/dlls/advapi32/tests/lsa.c
@@ -25,6 +25,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "winreg.h"
#include "ntsecapi.h"
#include "sddl.h"
diff --git a/dlls/advapi32/tests/security.c b/dlls/advapi32/tests/security.c
index 446c98fd07..9a31a36f49 100644
--- a/dlls/advapi32/tests/security.c
+++ b/dlls/advapi32/tests/security.c
@@ -26,6 +26,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "winerror.h"
#include "winternl.h"
#include "aclapi.h"
diff --git a/dlls/bcrypt/bcrypt_main.c b/dlls/bcrypt/bcrypt_main.c
index 2aecfb9a22..02b4328ab3 100644
--- a/dlls/bcrypt/bcrypt_main.c
+++ b/dlls/bcrypt/bcrypt_main.c
@@ -34,6 +34,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "ntsecapi.h"
#include "bcrypt.h"
diff --git a/dlls/jscript/math.c b/dlls/jscript/math.c
index ef906f5439..dedadeb23d 100644
--- a/dlls/jscript/math.c
+++ b/dlls/jscript/math.c
@@ -24,6 +24,7 @@
#include <limits.h>
#include "jscript.h"
+#include "wincred.h"
#include "ntsecapi.h"
#include "wine/debug.h"
diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c
index a0b6053af4..38708ab60a 100644
--- a/dlls/kerberos/krb5_ap.c
+++ b/dlls/kerberos/krb5_ap.c
@@ -31,6 +31,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "winnls.h"
#include "sspi.h"
#include "ntsecapi.h"
diff --git a/dlls/msvcrt/misc.c b/dlls/msvcrt/misc.c
index ba9dd10838..531367edcb 100644
--- a/dlls/msvcrt/misc.c
+++ b/dlls/msvcrt/misc.c
@@ -25,6 +25,7 @@
#include "msvcrt.h"
#include "wine/debug.h"
+#include "wincred.h"
#include "ntsecapi.h"
WINE_DEFAULT_DEBUG_CHANNEL(msvcrt);
diff --git a/dlls/netapi32/netapi32.c b/dlls/netapi32/netapi32.c
index 1c5f110b82..945995661e 100644
--- a/dlls/netapi32/netapi32.c
+++ b/dlls/netapi32/netapi32.c
@@ -37,6 +37,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "lm.h"
#include "lmaccess.h"
#include "lmat.h"
diff --git a/dlls/rpcrt4/rpcrt4_main.c b/dlls/rpcrt4/rpcrt4_main.c
index d5d349dc58..4775d68526 100644
--- a/dlls/rpcrt4/rpcrt4_main.c
+++ b/dlls/rpcrt4/rpcrt4_main.c
@@ -40,6 +40,7 @@
#include "windef.h"
#include "winerror.h"
#include "winbase.h"
+#include "wincred.h"
#include "winuser.h"
#include "winnt.h"
#include "winternl.h"
diff --git a/dlls/rpcrt4/tests/rpc.c b/dlls/rpcrt4/tests/rpc.c
index f026e99de2..9ed2584f45 100644
--- a/dlls/rpcrt4/tests/rpc.c
+++ b/dlls/rpcrt4/tests/rpc.c
@@ -28,6 +28,7 @@
#include "wine/test.h"
#include <windef.h>
#include <winbase.h>
+#include <wincred.h>
#include <winnt.h>
#include <winerror.h>
#include <ole2.h>
diff --git a/dlls/schannel/lsamode.c b/dlls/schannel/lsamode.c
index 96ca240c08..258266c6f0 100644
--- a/dlls/schannel/lsamode.c
+++ b/dlls/schannel/lsamode.c
@@ -24,6 +24,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "sspi.h"
#include "ntsecapi.h"
#include "ntsecpkg.h"
diff --git a/dlls/schannel/tests/main.c b/dlls/schannel/tests/main.c
index 4240dd76cb..9c1f827f58 100644
--- a/dlls/schannel/tests/main.c
+++ b/dlls/schannel/tests/main.c
@@ -24,6 +24,7 @@
#define WIN32_NO_STATUS
#include <windef.h>
#include <winbase.h>
+#include <wincred.h>
#define SECURITY_WIN32
#include <security.h>
#include <schannel.h>
diff --git a/dlls/schannel/usermode.c b/dlls/schannel/usermode.c
index 0713f822f9..1afa5d5ae6 100644
--- a/dlls/schannel/usermode.c
+++ b/dlls/schannel/usermode.c
@@ -24,6 +24,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "sspi.h"
#include "ntsecapi.h"
#include "ntsecpkg.h"
diff --git a/dlls/scrrun/filesystem.c b/dlls/scrrun/filesystem.c
index 2acef849fa..b6381a62d8 100644
--- a/dlls/scrrun/filesystem.c
+++ b/dlls/scrrun/filesystem.c
@@ -24,6 +24,7 @@
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "ole2.h"
#include "olectl.h"
#include "dispex.h"
diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c
index 1028c18e71..56d574ea4d 100644
--- a/dlls/secur32/lsa.c
+++ b/dlls/secur32/lsa.c
@@ -26,6 +26,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "winreg.h"
#include "sspi.h"
#include "ntsecapi.h"
diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c
index 1e12f3c543..f5d5746171 100644
--- a/dlls/secur32/secur32.c
+++ b/dlls/secur32/secur32.c
@@ -23,6 +23,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#include "winnls.h"
#include "winreg.h"
#include "winternl.h"
diff --git a/dlls/wbemprox/builtin.c b/dlls/wbemprox/builtin.c
index 826ec4b086..04739649f9 100644
--- a/dlls/wbemprox/builtin.c
+++ b/dlls/wbemprox/builtin.c
@@ -34,6 +34,7 @@
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
+#include "wincred.h"
#ifdef __MINGW32__
# include "winsock2.h"
# include "ws2tcpip.h"
diff --git a/programs/services/rpc.c b/programs/services/rpc.c
index 20c5a2761f..fb70eef561 100644
--- a/programs/services/rpc.c
+++ b/programs/services/rpc.c
@@ -25,6 +25,7 @@
#include <windows.h>
#include <winternl.h>
#include <winsvc.h>
+#include <wincred.h>
#include <ntsecapi.h>
#include <rpc.h>
--
2.15.0
From 484c150d69beec217686fd8d2c17374ec075e75d Mon Sep 17 00:00:00 2001
From: George Popoff <ambulance@etersoft.ru>
Date: Wed, 11 Oct 2017 14:36:36 +0300
Subject: [5/9] kerberos: fix KerbQueryTicketCacheMessage to return all tickets
in all ccaches
Content-Type: text/plain; charset=UTF-8
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
---
dlls/kerberos/krb5_ap.c | 53 +++++++++++++++++++++++++++++++++++--------------
1 file changed, 38 insertions(+), 15 deletions(-)
diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c
index 38708ab60a..5238d5a77b 100644
--- a/dlls/kerberos/krb5_ap.c
+++ b/dlls/kerberos/krb5_ap.c
@@ -54,6 +54,7 @@ MAKE_FUNCPTR(krb5_init_context);
MAKE_FUNCPTR(krb5_free_context);
MAKE_FUNCPTR(krb5_cccol_cursor_new);
MAKE_FUNCPTR(krb5_cccol_cursor_next);
+MAKE_FUNCPTR(krb5_cccol_cursor_free);
MAKE_FUNCPTR(krb5_cc_close);
MAKE_FUNCPTR(krb5_cc_start_seq_get);
MAKE_FUNCPTR(krb5_cc_end_seq_get);
@@ -100,6 +101,7 @@ static void load_krb5(void)
LOAD_FUNCPTR(krb5_free_context)
LOAD_FUNCPTR(krb5_cccol_cursor_new)
LOAD_FUNCPTR(krb5_cccol_cursor_next)
+ LOAD_FUNCPTR(krb5_cccol_cursor_free)
LOAD_FUNCPTR(krb5_cc_close)
LOAD_FUNCPTR(krb5_cc_start_seq_get)
LOAD_FUNCPTR(krb5_cc_end_seq_get)
@@ -160,7 +162,6 @@ static NTSTATUS krb5_error_to_status(krb5_error_code error)
switch (error)
{
case 0: return STATUS_SUCCESS;
-
default:
/* FIXME */
return STATUS_UNSUCCESSFUL;
@@ -180,7 +181,8 @@ static WCHAR *utf8_to_wstr(const char *utf8)
return wstr;
}
-static NTSTATUS copy_ticket_info(krb5_context context, krb5_ccache cache, KERB_TICKET_CACHE_INFO *ticket_info)
+static NTSTATUS copy_tickets_info(krb5_context context, krb5_ccache cache,
+ KERB_TICKET_CACHE_INFO *tickets_info, ULONG tickets_allocated, ULONG *tickets_in_cache)
{
NTSTATUS status;
krb5_cc_cursor cursor;
@@ -198,14 +200,13 @@ static NTSTATUS copy_ticket_info(krb5_context context, krb5_ccache cache, KERB_T
status = STATUS_SUCCESS;
+ *tickets_in_cache = 0;
+
for (;;)
{
error = p_krb5_cc_next_cred(context, cache, &cursor, &credentials);
if (error)
- {
- status = krb5_error_to_status(error);
break;
- }
if (p_krb5_is_config_principal(context, credentials.server))
{
@@ -213,6 +214,16 @@ static NTSTATUS copy_ticket_info(krb5_context context, krb5_ccache cache, KERB_T
continue;
}
+ TRACE("credential has more tickets!\n");
+
+ (*tickets_in_cache)++;
+ if (*tickets_in_cache > tickets_allocated)
+ {
+ p_krb5_free_cred_contents(context, &credentials);
+ /* Indicate that we fill out a ticket_info buffer */
+ status = SEC_E_BUFFER_TOO_SMALL;
+ }
+
error = p_krb5_unparse_name(context, credentials.server, &name_with_realm);
if (error)
{
@@ -236,7 +247,7 @@ static NTSTATUS copy_ticket_info(krb5_context context, krb5_ccache cache, KERB_T
TRACE("name_without_realm: %s\n", debugstr_a(name_without_realm));
name_without_realmW = utf8_to_wstr(name_without_realm);
- RtlInitUnicodeString(&ticket_info->ServerName, name_without_realmW);
+ RtlInitUnicodeString(&tickets_info->ServerName, name_without_realmW);
realm_name = name_with_realm;
@@ -249,24 +260,24 @@ static NTSTATUS copy_ticket_info(krb5_context context, krb5_ccache cache, KERB_T
/* realm_name - now contains only realm! */
realm_nameW = utf8_to_wstr(realm_name);
- RtlInitUnicodeString(&ticket_info->RealmName, realm_nameW);
+ RtlInitUnicodeString(&tickets_info->RealmName, realm_nameW);
if (!credentials.times.starttime)
credentials.times.starttime = credentials.times.authtime;
/* TODO: if krb5_is_config_principal = true */
- RtlSecondsSince1970ToTime(credentials.times.starttime, &ticket_info->StartTime);
- RtlSecondsSince1970ToTime(credentials.times.endtime, &ticket_info->EndTime);
- RtlSecondsSince1970ToTime(credentials.times.renew_till, &ticket_info->RenewTime);
+ RtlSecondsSince1970ToTime(credentials.times.starttime, &tickets_info->StartTime);
+ RtlSecondsSince1970ToTime(credentials.times.endtime, &tickets_info->EndTime);
+ RtlSecondsSince1970ToTime(credentials.times.renew_till, &tickets_info->RenewTime);
- ticket_info->TicketFlags = credentials.ticket_flags;
+ tickets_info->TicketFlags = credentials.ticket_flags;
error = p_krb5_decode_ticket(&credentials.ticket, &ticket);
if (error)
status = krb5_error_to_status(error);
else
{
- ticket_info->EncryptionType = ticket->enc_part.enctype;
+ tickets_info->EncryptionType = ticket->enc_part.enctype;
status = STATUS_SUCCESS;
}
@@ -274,7 +285,8 @@ static NTSTATUS copy_ticket_info(krb5_context context, krb5_ccache cache, KERB_T
p_krb5_free_unparsed_name(context, name_without_realm);
p_krb5_free_cred_contents(context, &credentials);
- break;
+ /* fill next ticket in ccache */
+ tickets_info++;
}
p_krb5_cc_end_seq_get(context, cache, &cursor);
@@ -288,6 +300,7 @@ static NTSTATUS query_ticket_cache(PLSA_CLIENT_REQUEST lsa_req, void *in, ULONG
KERB_QUERY_TKT_CACHE_REQUEST *query;
KERB_QUERY_TKT_CACHE_RESPONSE *resp;
ULONG tickets_allocated;
+ ULONG tickets_in_cache;
krb5_error_code error;
krb5_context context = NULL;
krb5_cccol_cursor cursor;
@@ -331,6 +344,8 @@ static NTSTATUS query_ticket_cache(PLSA_CLIENT_REQUEST lsa_req, void *in, ULONG
break;
}
+ TRACE("Found another ccache!\n");
+
if (resp->CountOfTickets == tickets_allocated)
{
KERB_QUERY_TKT_CACHE_RESPONSE *new_resp;
@@ -347,15 +362,22 @@ static NTSTATUS query_ticket_cache(PLSA_CLIENT_REQUEST lsa_req, void *in, ULONG
resp = new_resp;
}
- status = copy_ticket_info(context, cache, &resp->Tickets[resp->CountOfTickets]);
+ tickets_in_cache = 0;
+ status = copy_tickets_info(context, cache, &resp->Tickets[resp->CountOfTickets],
+ tickets_allocated - resp->CountOfTickets, &tickets_in_cache);
+
if (status == STATUS_SUCCESS)
- resp->CountOfTickets++;
+ resp->CountOfTickets += tickets_in_cache;
+ else if (status == STATUS_BUFFER_TOO_SMALL)
+ FIXME("Too many tickets in ccache, some tickets may be ommited\n");
p_krb5_cc_close(context, cache);
}
if (status) goto done;
+ p_krb5_cccol_cursor_free(context, &cursor);
+
/* FIXME: copy server/realm names to client space as well.
* As long as LSA works in current process space it's OK.
*/
@@ -373,6 +395,7 @@ static NTSTATUS query_ticket_cache(PLSA_CLIENT_REQUEST lsa_req, void *in, ULONG
done:
if (context)
p_krb5_free_context(context);
+
heap_free(resp);
return status;
}
--
2.15.0
From f0c2b891d3271472fa9cf424c7c643ee13eeb0b7 Mon Sep 17 00:00:00 2001
From: George Popoff <ambulance@etersoft.ru>
Date: Wed, 11 Oct 2017 14:38:48 +0300
Subject: [6/9] add terminating null to kerberos name variable
Content-Type: text/plain; charset=UTF-8
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
---
include/ntsecapi.h | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/include/ntsecapi.h b/include/ntsecapi.h
index 3193b10f42..f7c8a5451c 100644
--- a/include/ntsecapi.h
+++ b/include/ntsecapi.h
@@ -349,7 +349,7 @@ typedef enum _POLICY_NOTIFICATION_INFORMATION_CLASS
static const WCHAR MICROSOFT_KERBEROS_NAME_W[] = { 'K','e','r','b','e','r','o','s',0 };
#endif
#else /* UNICODE */
-#define MICROSOFT_KERBEROS_NAME_A "Kerberos"
+static const char MICROSOFT_KERBEROS_NAME_A[] = { 'K','e','r','b','e','r','o','s',0 };
#endif
#define KERB_TICKET_FLAGS_reserved 0x80000000
--
2.15.0
From 0cb7ea40c604071f003b2f548bf732fb33bf3f75 Mon Sep 17 00:00:00 2001
From: George Popoff <ambulance@etersoft.ru>
Date: Wed, 11 Oct 2017 14:53:11 +0300
Subject: [7/9] create new kerberos ssp based on GSSAPI ssp. Delete old.
Content-Type: text/plain; charset=UTF-8
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
---
configure | 68 +++
configure.ac | 10 +
dlls/kerberos/Makefile.in | 3 +-
dlls/kerberos/kerberos.spec | 2 +
dlls/kerberos/krb5_ssp.c | 1304 +++++++++++++++++++++++++++++++++++++++++++
dlls/secur32/Makefile.in | 1 -
dlls/secur32/kerberos.c | 323 -----------
dlls/secur32/secur32.c | 33 +-
include/config.h.in | 6 +
loader/wine.inf.in | 2 +
10 files changed, 1411 insertions(+), 341 deletions(-)
create mode 100644 dlls/kerberos/krb5_ssp.c
delete mode 100644 dlls/secur32/kerberos.c
diff --git a/configure b/configure
index 0f6a849c58..8a6c2315e5 100755
--- a/configure
+++ b/configure
@@ -7024,6 +7024,8 @@ for ac_header in \
grp.h \
gsm.h \
gsm/gsm.h \
+ gssapi/gssapi.h \
+ gssapi/gssapi_krb5.h \
ieeefp.h \
inet/mib2.h \
io.h \
@@ -14576,6 +14578,72 @@ esac
fi
+if test "$ac_cv_header_gssapi_gssapi_krb5_h" = "yes"
+then
+ { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -lgssapi_krb5" >&5
+$as_echo_n "checking for -lgssapi_krb5... " >&6; }
+if ${ac_cv_lib_soname_gssapi_krb5+:} false; then :
+ $as_echo_n "(cached) " >&6
+else
+ ac_check_soname_save_LIBS=$LIBS
+LIBS="-lgssapi_krb5 $LIBS"
+ cat confdefs.h - <<_ACEOF >conftest.$ac_ext
+/* end confdefs.h. */
+
+/* Override any GCC internal prototype to avoid an error.
+ Use char because int might match the return type of a GCC
+ builtin and then its argument prototype would still apply. */
+#ifdef __cplusplus
+extern "C"
+#endif
+char gss_init_sec_context ();
+int
+main ()
+{
+return gss_init_sec_context ();
+ ;
+ return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+ case "$LIBEXT" in
+ dll) ac_cv_lib_soname_gssapi_krb5=`$ac_cv_path_LDD conftest.exe | grep "gssapi_krb5" | sed -e "s/dll.*/dll/"';2,$d'` ;;
+ dylib) ac_cv_lib_soname_gssapi_krb5=`$OTOOL -L conftest$ac_exeext | grep "libgssapi_krb5\\.[0-9A-Za-z.]*dylib" | sed -e "s/^.*\/\(libgssapi_krb5\.[0-9A-Za-z.]*dylib\).*$/\1/"';2,$d'` ;;
+ *) ac_cv_lib_soname_gssapi_krb5=`$READELF -d conftest$ac_exeext | grep "NEEDED.*libgssapi_krb5\\.$LIBEXT" | sed -e "s/^.*\\[\\(libgssapi_krb5\\.$LIBEXT[^ ]*\\)\\].*$/\1/"';2,$d'`
+ if ${ac_cv_lib_soname_gssapi_krb5:+false} :; then :
+ ac_cv_lib_soname_gssapi_krb5=`$LDD conftest$ac_exeext | grep "libgssapi_krb5\\.$LIBEXT" | sed -e "s/^.*\(libgssapi_krb5\.$LIBEXT[^ ]*\).*$/\1/"';2,$d'`
+fi ;;
+ esac
+fi
+rm -f core conftest.err conftest.$ac_objext \
+ conftest$ac_exeext conftest.$ac_ext
+ LIBS=$ac_check_soname_save_LIBS
+fi
+if ${ac_cv_lib_soname_gssapi_krb5:+false} :; then :
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: not found" >&5
+$as_echo "not found" >&6; }
+
+else
+ { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_soname_gssapi_krb5" >&5
+$as_echo "$ac_cv_lib_soname_gssapi_krb5" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define SONAME_LIBGSSAPI_KRB5 "$ac_cv_lib_soname_gssapi_krb5"
+_ACEOF
+
+
+fi
+fi
+if test "x$ac_cv_lib_soname_gssapi_krb5" = "x"; then :
+ case "x$with_gssapi_krb5" in
+ x) as_fn_append wine_notices "|libgssapi_krb5 ${notice_platform}development files not found gssapi won't be supported." ;;
+ xno) ;;
+ *) as_fn_error $? "libgssapi_krb5 ${notice_platform}development files not found gssapi won't be supported.
+This is an error since --with-gssapi_krb5 was requested." "$LINENO" 5 ;;
+esac
+
+fi
+
if test "x$with_jpeg" != "xno"
then
if ${JPEG_CFLAGS:+false} :; then :
diff --git a/configure.ac b/configure.ac
index 0e1a0a1ee7..4c2a1b46bc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -437,6 +437,8 @@ AC_CHECK_HEADERS(\
grp.h \
gsm.h \
gsm/gsm.h \
+ gssapi/gssapi.h \
+ gssapi/gssapi_krb5.h \
ieeefp.h \
inet/mib2.h \
io.h \
@@ -1732,6 +1734,14 @@ fi
WINE_NOTICE_WITH(krb5,[test "x$ac_cv_lib_soname_krb5" = "x"],
[libkrb5 ${notice_platform}development files not found, Kerberos won't be supported.])
+dnl **** Check for libgssapi_krb5 ****
+if test "$ac_cv_header_gssapi_gssapi_krb5_h" = "yes"
+then
+ WINE_CHECK_SONAME(gssapi_krb5,gss_init_sec_context)
+fi
+WINE_NOTICE_WITH(gssapi_krb5,[test "x$ac_cv_lib_soname_gssapi_krb5" = "x"],
+ [libgssapi_krb5 ${notice_platform}development files not found gssapi won't be supported.])
+
dnl **** Check for libjpeg ****
if test "x$with_jpeg" != "xno"
then
diff --git a/dlls/kerberos/Makefile.in b/dlls/kerberos/Makefile.in
index 253e944716..ec095efd87 100644
--- a/dlls/kerberos/Makefile.in
+++ b/dlls/kerberos/Makefile.in
@@ -2,4 +2,5 @@ MODULE = kerberos.dll
EXTRAINCL = $(KRB5_CFLAGS)
C_SRCS = \
- krb5_ap.c
+ krb5_ap.c \
+ krb5_ssp.c
diff --git a/dlls/kerberos/kerberos.spec b/dlls/kerberos/kerberos.spec
index c41b830e46..8bb2fa1c8d 100644
--- a/dlls/kerberos/kerberos.spec
+++ b/dlls/kerberos/kerberos.spec
@@ -1,4 +1,6 @@
1 stub SpInitialize
+@ stdcall InitSecurityInterfaceA()
+@ stdcall InitSecurityInterfaceW()
2 stub KerbDomainChangeCallback
3 stdcall SpLsaModeInitialize(long ptr ptr ptr)
4 stub SpUserModeInitialize
diff --git a/dlls/kerberos/krb5_ssp.c b/dlls/kerberos/krb5_ssp.c
new file mode 100644
index 0000000000..cfb408edbb
--- /dev/null
+++ b/dlls/kerberos/krb5_ssp.c
@@ -0,0 +1,1304 @@
+/*
+ * Kerberos API based on GSSAPI SSP
+ *
+ * Copyright 2005, 2006 Kai Blin
+ * Copyright 2008 Robert Shearman for CodeWeavers
+ * Copyright 2016 Jacek Caban for CodeWeavers
+ * Copyright 2017 George Popoff
+ *
+ * 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 "config.h"
+#include <stdarg.h>
+#include <stdio.h>
+#include <dlfcn.h>
+
+#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H
+#include <gssapi/gssapi.h>
+#include <gssapi/gssapi_krb5.h>
+#endif
+
+#include "windef.h"
+#include "winbase.h"
+#include "winnls.h"
+#include "wincred.h"
+#include "rpc.h"
+#include "sspi.h"
+#include "lm.h"
+#include "wine/unicode.h"
+#include "wine/library.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(kerberos);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+#define MAKE_FUNCPTR(f) static typeof(f) * p_##f
+MAKE_FUNCPTR(gss_import_name);
+MAKE_FUNCPTR(gss_acquire_cred);
+MAKE_FUNCPTR(gss_release_name);
+MAKE_FUNCPTR(gss_init_sec_context);
+MAKE_FUNCPTR(gss_accept_sec_context);
+MAKE_FUNCPTR(gss_delete_sec_context);
+MAKE_FUNCPTR(gss_get_mic);
+MAKE_FUNCPTR(gss_verify_mic);
+MAKE_FUNCPTR(gss_release_cred);
+MAKE_FUNCPTR(gss_wrap);
+MAKE_FUNCPTR(gss_unwrap);
+#undef MAKE_FUNCPTR
+
+#define GSS_KERBEROS_MAX_BUF 1904
+
+#define KERBEROS_MAGIC ('K' << 24 | 'E' << 16 | 'R' << 8 | 'B')
+
+#define GSS_KERBEROS_COMMENT \
+ { 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', ' ', \
+ 'S', 'e', 'c', 'u', 'r', 'i', 't', 'y', ' ', \
+ 'P', 'a', 'c', 'k', 'a', 'g', 'e', 0}
+
+static CHAR kerberos_comment_A[] = GSS_KERBEROS_COMMENT;
+static WCHAR kerberos_comment_W[] = GSS_KERBEROS_COMMENT;
+
+#define GSS_KERBEROS_NAME {'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', 0}
+
+static char kerberos_name_A[] = GSS_KERBEROS_NAME;
+static WCHAR kerberos_name_W[] = GSS_KERBEROS_NAME;
+
+/* FIXME */
+#define CAPS ( \
+ SECPKG_FLAG_INTEGRITY | \
+ SECPKG_FLAG_PRIVACY | \
+ SECPKG_FLAG_TOKEN_ONLY | \
+ SECPKG_FLAG_CONNECTION | \
+ SECPKG_FLAG_MULTI_REQUIRED | \
+ SECPKG_FLAG_IMPERSONATION | \
+ SECPKG_FLAG_ACCEPT_WIN32_NAME | \
+ SECPKG_FLAG_READONLY_WITH_CHECKSUM)
+
+
+static SecPkgInfoW infoW = {
+ CAPS,
+ 1,
+ RPC_C_AUTHN_GSS_KERBEROS,
+ GSS_KERBEROS_MAX_BUF,
+ kerberos_name_W,
+ kerberos_comment_W
+};
+
+static SecPkgInfoA infoA = {
+ CAPS,
+ 1,
+ RPC_C_AUTHN_GSS_KERBEROS,
+ GSS_KERBEROS_MAX_BUF,
+ kerberos_name_A,
+ kerberos_comment_A
+};
+
+
+SecPkgInfoA *kerberos_package_infoA = (SecPkgInfoA *)&infoA;
+SecPkgInfoW *kerberos_package_infoW = (SecPkgInfoW *)&infoW;
+
+static BOOL load_gssapi(void)
+{
+ void *libgssapi_handle;
+
+ if (!(libgssapi_handle = wine_dlopen(SONAME_LIBGSSAPI_KRB5, RTLD_NOW, NULL, 0)))
+ {
+ ERR_(winediag)("failed to load libgssapi\n" );
+ return FALSE;
+ }
+
+#define LOAD_FUNCPTR(f) \
+ if (!(p_##f = wine_dlsym(libgssapi_handle, #f, NULL, 0))) \
+ { \
+ ERR("failed to load %s\n", #f); \
+ goto fail; \
+ }
+
+ LOAD_FUNCPTR(gss_import_name);
+ LOAD_FUNCPTR(gss_acquire_cred);
+ LOAD_FUNCPTR(gss_release_name);
+ LOAD_FUNCPTR(gss_init_sec_context);
+ LOAD_FUNCPTR(gss_accept_sec_context);
+ LOAD_FUNCPTR(gss_delete_sec_context);
+ LOAD_FUNCPTR(gss_get_mic);
+ LOAD_FUNCPTR(gss_verify_mic);
+ LOAD_FUNCPTR(gss_release_cred);
+ LOAD_FUNCPTR(gss_wrap);
+ LOAD_FUNCPTR(gss_unwrap);
+#undef LOAD_FUNCPTR
+
+ return TRUE;
+
+fail:
+ wine_dlclose(libgssapi_handle, NULL, 0);
+ return FALSE;
+}
+
+static inline gss_cred_id_t kerberos_CredHandleSSPItoGSSAPI(const CredHandle *phCredential)
+{
+ return (gss_cred_id_t)phCredential->dwLower;
+}
+
+static inline void kerberos_CredHandleGSSAPItoSSPI(gss_cred_id_t cred_handle, PCredHandle phCredential)
+{
+ phCredential->dwLower = (DWORD)cred_handle;
+ phCredential->dwUpper = KERBEROS_MAGIC;
+}
+
+static inline gss_ctx_id_t kerberos_CtxtHandleSSPItoGSSAPI(const CtxtHandle *phCredential)
+{
+ return (gss_ctx_id_t)phCredential->dwLower;
+}
+
+static inline void kerberos_CtxtHandleGSSAPItoSSPI(gss_ctx_id_t ctx_handle, PCtxtHandle phCredential)
+{
+ phCredential->dwLower = (DWORD)ctx_handle;
+ phCredential->dwUpper = KERBEROS_MAGIC;
+}
+
+static inline void kerberos_CtxtAttrsGSSPItoSSPI(OM_uint32 ret_flags, PULONG pfContextAttr)
+{
+ *pfContextAttr = 0;
+
+ if (ret_flags & GSS_C_DELEG_FLAG)
+ *pfContextAttr |= ISC_RET_DELEGATE;
+ if (ret_flags & GSS_C_MUTUAL_FLAG)
+ *pfContextAttr |= ISC_RET_MUTUAL_AUTH;
+ if (ret_flags & GSS_C_REPLAY_FLAG)
+ *pfContextAttr |= ISC_RET_REPLAY_DETECT;
+ if (ret_flags & GSS_C_SEQUENCE_FLAG)
+ *pfContextAttr |= ISC_RET_SEQUENCE_DETECT;
+ if (ret_flags & GSS_C_CONF_FLAG)
+ *pfContextAttr |= ISC_RET_CONFIDENTIALITY;
+ if (ret_flags & GSS_C_INTEG_FLAG)
+ *pfContextAttr |= ISC_RET_INTEGRITY;
+ if (ret_flags & GSS_C_ANON_FLAG)
+ *pfContextAttr |= ISC_RET_NULL_SESSION;
+}
+
+static inline OM_uint32 kerberos_CtxtAttrsSSPItoGSSAPI(ULONG fContextAttr)
+{
+ OM_uint32 ret_flags = 0;
+
+ if (fContextAttr & ISC_RET_DELEGATE)
+ ret_flags |= GSS_C_DELEG_FLAG;
+ if (fContextAttr & ISC_RET_MUTUAL_AUTH)
+ ret_flags |= GSS_C_MUTUAL_FLAG;
+ if (fContextAttr & ISC_RET_REPLAY_DETECT)
+ ret_flags |= GSS_C_REPLAY_FLAG;
+ if (fContextAttr & ISC_RET_SEQUENCE_DETECT)
+ ret_flags |= GSS_C_SEQUENCE_FLAG;
+ if (fContextAttr & ISC_RET_CONFIDENTIALITY)
+ ret_flags |= GSS_C_CONF_FLAG;
+ if (fContextAttr & ISC_RET_INTEGRITY)
+ ret_flags |= GSS_C_INTEG_FLAG;
+ if (fContextAttr & ISC_RET_NULL_SESSION)
+ ret_flags |= GSS_C_ANON_FLAG;
+
+ return ret_flags;
+}
+
+static inline OM_uint32 kerberos_CtxtReqsSSPItoGSSAPI(ULONG fRequirements)
+{
+ OM_uint32 req_flags = 0;
+
+ if (fRequirements & ISC_REQ_DELEGATE)
+ req_flags |= GSS_C_DELEG_FLAG;
+ if (fRequirements & ISC_REQ_MUTUAL_AUTH)
+ req_flags |= GSS_C_MUTUAL_FLAG;
+ if (fRequirements & ISC_REQ_REPLAY_DETECT)
+ req_flags |= GSS_C_REPLAY_FLAG;
+ if (fRequirements & ISC_REQ_SEQUENCE_DETECT)
+ req_flags |= GSS_C_SEQUENCE_FLAG;
+ if (fRequirements & ISC_REQ_CONFIDENTIALITY)
+ req_flags |= GSS_C_CONF_FLAG;
+ if (fRequirements & ISC_REQ_INTEGRITY)
+ req_flags |= GSS_C_INTEG_FLAG;
+ if (fRequirements & ISC_REQ_NULL_SESSION)
+ req_flags |= GSS_C_ANON_FLAG;
+
+ return req_flags;
+}
+
+static inline void kerberos_CtxtReqsGSSAPItoSSPI(OM_uint32 req_flags, PULONG pfRequirements)
+{
+ *pfRequirements = 0;
+
+ if (req_flags & GSS_C_DELEG_FLAG)
+ *pfRequirements |= ISC_REQ_DELEGATE;
+ if (req_flags & GSS_C_MUTUAL_FLAG)
+ *pfRequirements |= ISC_REQ_MUTUAL_AUTH;
+ if (req_flags & GSS_C_REPLAY_FLAG)
+ *pfRequirements |= ISC_REQ_REPLAY_DETECT;
+ if (req_flags & GSS_C_SEQUENCE_FLAG)
+ *pfRequirements |= ISC_REQ_SEQUENCE_DETECT;
+ if (req_flags & GSS_C_CONF_FLAG)
+ *pfRequirements |= ISC_REQ_CONFIDENTIALITY;
+ if (req_flags & GSS_C_INTEG_FLAG)
+ *pfRequirements |= ISC_REQ_INTEGRITY;
+ if (req_flags & GSS_C_ANON_FLAG)
+ *pfRequirements |= ISC_REQ_NULL_SESSION;
+}
+
+static SECURITY_STATUS kerberos_GSSAPIStatusToSecurityStatus(OM_uint32 status)
+{
+ switch (status)
+ {
+ case GSS_S_COMPLETE: return SEC_E_OK;
+ case GSS_S_BAD_MECH: return SEC_E_SECPKG_NOT_FOUND;
+ case GSS_S_BAD_SIG: return SEC_E_MESSAGE_ALTERED;
+ case GSS_S_NO_CRED: return SEC_E_NO_CREDENTIALS;
+ case GSS_S_NO_CONTEXT: return SEC_E_INVALID_HANDLE;
+ case GSS_S_DEFECTIVE_TOKEN: return SEC_E_MESSAGE_ALTERED;
+ case GSS_S_DEFECTIVE_CREDENTIAL: return SEC_E_INVALID_TOKEN;
+ case GSS_S_CREDENTIALS_EXPIRED: return SEC_E_CONTEXT_EXPIRED;
+ case GSS_S_CONTEXT_EXPIRED: return SEC_E_CONTEXT_EXPIRED;
+ case GSS_S_BAD_QOP: return SEC_E_QOP_NOT_SUPPORTED;
+
+ case GSS_S_CONTINUE_NEEDED: return SEC_I_CONTINUE_NEEDED;
+ case GSS_S_DUPLICATE_TOKEN: return SEC_E_INVALID_TOKEN;
+ case GSS_S_OLD_TOKEN: return SEC_E_INVALID_TOKEN;
+ case GSS_S_UNSEQ_TOKEN: return SEC_E_OUT_OF_SEQUENCE;
+ case GSS_S_GAP_TOKEN: return SEC_E_OUT_OF_SEQUENCE;
+
+ default:
+ FIXME("couldn't convert status 0x%x to SECURITY_STATUS\n", status);
+
+ return SEC_E_INTERNAL_ERROR;
+ }
+}
+
+/***********************************************************************
+ * EnumerateSecurityPackagesW
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_EnumerateSecurityPackagesW(
+ PULONG pcPackages, PSecPkgInfoW *ppPackageInfo)
+{
+ *pcPackages = 1;
+ *ppPackageInfo = &infoW;
+
+ return SEC_E_OK;
+}
+
+/***********************************************************************
+ * EnumerateSecurityPackagesA
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_EnumerateSecurityPackagesA(
+ PULONG pcPackages, PSecPkgInfoA *ppPackageInfo)
+{
+ *pcPackages = 1;
+ *ppPackageInfo = &infoA;
+
+ return SEC_E_OK;
+}
+
+/***********************************************************************
+ * QueryCredentialsAttributesA
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesA(
+ PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
+{
+ SECURITY_STATUS ret;
+
+ TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
+
+ if(ulAttribute == SECPKG_ATTR_NAMES)
+ {
+ FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
+ ret = SEC_E_UNSUPPORTED_FUNCTION;
+ }
+ else
+ ret = SEC_E_UNSUPPORTED_FUNCTION;
+
+ return ret;
+}
+
+/***********************************************************************
+ * QueryCredentialsAttributesW
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesW(
+ PCredHandle phCredential, ULONG ulAttribute, PVOID pBuffer)
+{
+ SECURITY_STATUS ret;
+
+ TRACE("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
+
+ if(ulAttribute == SECPKG_ATTR_NAMES)
+ {
+ FIXME("SECPKG_CRED_ATTR_NAMES: stub\n");
+ ret = SEC_E_UNSUPPORTED_FUNCTION;
+ }
+ else
+ ret = SEC_E_UNSUPPORTED_FUNCTION;
+
+ return ret;
+}
+
+static void kerberos_ExpiryTimeToTimeStamp(OM_uint32 expiry_time, PTimeStamp ptsExpiry)
+{
+ SYSTEMTIME current_local_time;
+ FILETIME current_local_filetime;
+ ULARGE_INTEGER temp;
+ GetLocalTime(¤t_local_time);
+ SystemTimeToFileTime(¤t_local_time, ¤t_local_filetime);
+ temp.QuadPart = ((ULONGLONG)current_local_filetime.dwLowDateTime |
+ (ULONGLONG)current_local_filetime.dwHighDateTime << 32) +
+ expiry_time;
+ ptsExpiry->LowPart = temp.QuadPart;
+ ptsExpiry->HighPart = temp.QuadPart >> 32;
+}
+
+/***********************************************************************
+ * AcquireCredentialsHandleW
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleW(
+ SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse,
+ PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
+ PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
+{
+ OM_uint32 ret;
+ OM_uint32 minor_status;
+ gss_name_t principal_name = GSS_C_NO_NAME;
+ gss_cred_usage_t cred_usage;
+ gss_cred_id_t cred_handle;
+ OM_uint32 expiry_time;
+
+ TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
+ debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
+ pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
+
+ if (pAuthData)
+ {
+ /* gssapi has no way to specify the credentials to use, so we just
+ * return an error when the caller tries to do so */
+ FIXME("specific credentials not supported\n");
+ return SEC_E_UNKNOWN_CREDENTIALS;
+ }
+
+ switch (fCredentialUse)
+ {
+ case SECPKG_CRED_INBOUND:
+ cred_usage = GSS_C_ACCEPT;
+ break;
+ case SECPKG_CRED_OUTBOUND:
+ cred_usage = GSS_C_INITIATE;
+ break;
+ case SECPKG_CRED_BOTH:
+ cred_usage = GSS_C_BOTH;
+ break;
+ default:
+ phCredential = NULL;
+ return SEC_E_UNKNOWN_CREDENTIALS;
+ }
+
+ if (pszPrincipal)
+ {
+ char *principal_name_str;
+ int len;
+ gss_buffer_desc name_buffer;
+
+ len = WideCharToMultiByte(CP_UNIXCP, 0, pszPrincipal, -1, NULL, 0, NULL, NULL);
+ principal_name_str = HeapAlloc(GetProcessHeap(), 0, len);
+ if (!principal_name_str)
+ return SEC_E_INSUFFICIENT_MEMORY;
+ WideCharToMultiByte(CP_UNIXCP, 0, pszPrincipal, -1, principal_name_str, len, NULL, NULL);
+
+ name_buffer.length = len-1;
+ name_buffer.value = principal_name_str;
+
+ ret = p_gss_import_name(&minor_status, &name_buffer,
+ GSS_C_NULL_OID /* FIXME: detect the appropriate value for this ourselves? */,
+ &principal_name);
+ HeapFree(GetProcessHeap(), 0, principal_name_str);
+
+ if (ret != GSS_S_COMPLETE)
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+ }
+
+ ret = p_gss_acquire_cred(&minor_status, principal_name, GSS_C_INDEFINITE,
+ GSS_C_NULL_OID_SET /* FIXME: gss_mech_set_krb5 */, cred_usage, &cred_handle,
+ NULL, &expiry_time);
+
+ if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED)
+ {
+ if (ptsExpiry != NULL) {
+ kerberos_ExpiryTimeToTimeStamp(expiry_time, ptsExpiry);
+ kerberos_CredHandleGSSAPItoSSPI(cred_handle, phCredential);
+ }
+ }
+
+ if (principal_name != GSS_C_NO_NAME)
+ p_gss_release_name(&minor_status, &principal_name);
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+}
+
+/***********************************************************************
+ * AcquireCredentialsHandleA
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleA(
+ SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse,
+ PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
+ PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
+{
+ SECURITY_STATUS ret;
+ int user_sizeW, domain_sizeW, passwd_sizeW;
+
+ SEC_WCHAR *user = NULL, *domain = NULL, *passwd = NULL, *package = NULL;
+
+ PSEC_WINNT_AUTH_IDENTITY_W pAuthDataW = NULL;
+ PSEC_WINNT_AUTH_IDENTITY_A identity = NULL;
+
+ TRACE("(%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p)\n",
+ debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse,
+ pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
+
+ if(pszPackage != NULL)
+ {
+ int package_sizeW = MultiByteToWideChar(CP_ACP, 0, pszPackage, -1,
+ NULL, 0);
+
+ package = HeapAlloc(GetProcessHeap(), 0, package_sizeW *
+ sizeof(SEC_WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, pszPackage, -1, package, package_sizeW);
+ }
+
+
+ if(pAuthData != NULL)
+ {
+ identity = (PSEC_WINNT_AUTH_IDENTITY_A)pAuthData;
+
+ if(identity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
+ {
+ pAuthDataW = HeapAlloc(GetProcessHeap(), 0,
+ sizeof(SEC_WINNT_AUTH_IDENTITY_W));
+
+ if(identity->UserLength != 0)
+ {
+ user_sizeW = MultiByteToWideChar(CP_ACP, 0,
+ (LPCSTR)identity->User, identity->UserLength, NULL, 0);
+ user = HeapAlloc(GetProcessHeap(), 0, user_sizeW *
+ sizeof(SEC_WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, (LPCSTR)identity->User,
+ identity->UserLength, user, user_sizeW);
+ }
+ else
+ {
+ user_sizeW = 0;
+ }
+
+ if(identity->DomainLength != 0)
+ {
+ domain_sizeW = MultiByteToWideChar(CP_ACP, 0,
+ (LPCSTR)identity->Domain, identity->DomainLength, NULL, 0);
+ domain = HeapAlloc(GetProcessHeap(), 0, domain_sizeW
+ * sizeof(SEC_WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, (LPCSTR)identity->Domain,
+ identity->DomainLength, domain, domain_sizeW);
+ }
+ else
+ {
+ domain_sizeW = 0;
+ }
+
+ if(identity->PasswordLength != 0)
+ {
+ passwd_sizeW = MultiByteToWideChar(CP_ACP, 0,
+ (LPCSTR)identity->Password, identity->PasswordLength,
+ NULL, 0);
+ passwd = HeapAlloc(GetProcessHeap(), 0, passwd_sizeW
+ * sizeof(SEC_WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, (LPCSTR)identity->Password,
+ identity->PasswordLength, passwd, passwd_sizeW);
+ }
+ else
+ {
+ passwd_sizeW = 0;
+ }
+
+ pAuthDataW->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+ pAuthDataW->User = user;
+ pAuthDataW->UserLength = user_sizeW;
+ pAuthDataW->Domain = domain;
+ pAuthDataW->DomainLength = domain_sizeW;
+ pAuthDataW->Password = passwd;
+ pAuthDataW->PasswordLength = passwd_sizeW;
+ }
+ else
+ {
+ pAuthDataW = (PSEC_WINNT_AUTH_IDENTITY_W)identity;
+ }
+ }
+
+ ret = kerberos_AcquireCredentialsHandleW(NULL, package, fCredentialUse,
+ pLogonID, pAuthDataW, pGetKeyFn, pGetKeyArgument, phCredential,
+ ptsExpiry);
+
+ HeapFree(GetProcessHeap(), 0, package);
+ HeapFree(GetProcessHeap(), 0, user);
+ HeapFree(GetProcessHeap(), 0, domain);
+ HeapFree(GetProcessHeap(), 0, passwd);
+ if(pAuthDataW != (PSEC_WINNT_AUTH_IDENTITY_W)identity)
+ HeapFree(GetProcessHeap(), 0, pAuthDataW);
+
+ return ret;
+}
+
+/*************************************************************************
+ * kerberos_GetTokenBufferIndex
+ * Calculates the index of the secbuffer with BufferType == SECBUFFER_TOKEN
+ * Returns index if found or -1 if not found.
+ */
+static int kerberos_GetTokenBufferIndex(PSecBufferDesc pMessage)
+{
+ UINT i;
+
+ TRACE("%p\n", pMessage);
+
+ for( i = 0; i < pMessage->cBuffers; ++i )
+ {
+ if(pMessage->pBuffers[i].BufferType == SECBUFFER_TOKEN)
+ return i;
+ }
+
+ return -1;
+}
+
+/*************************************************************************
+ * kerberos_GetDataBufferIndex
+ * Calculates the index of the first secbuffer with BufferType == SECBUFFER_DATA
+ * Returns index if found or -1 if not found.
+ */
+static int kerberos_GetDataBufferIndex(PSecBufferDesc pMessage)
+{
+ UINT i;
+
+ TRACE("%p\n", pMessage);
+
+ for( i = 0; i < pMessage->cBuffers; ++i )
+ {
+ if(pMessage->pBuffers[i].BufferType == SECBUFFER_DATA)
+ return i;
+ }
+
+ return -1;
+}
+
+/***********************************************************************
+ * InitializeSecurityContextW
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_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)
+{
+ int output_token_idx;
+ OM_uint32 ret;
+ OM_uint32 minor_status;
+ gss_cred_id_t cred_handle;
+ gss_ctx_id_t context_handle = GSS_C_NO_CONTEXT;
+ OM_uint32 req_flags = 0;
+ OM_uint32 ret_flags;
+ gss_buffer_desc input_token;
+ gss_buffer_desc output_token;
+ OM_uint32 expiry_time;
+ gss_name_t target_name = GSS_C_NO_NAME;
+
+ TRACE("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
+ debugstr_w(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
+ Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
+
+ if (!phContext && !pInput)
+ {
+ if (!phCredential)
+ return SEC_E_INVALID_HANDLE;
+ cred_handle = kerberos_CredHandleSSPItoGSSAPI(phCredential);
+ }
+ else
+ {
+ cred_handle = GSS_C_NO_CREDENTIAL;
+
+ if (phContext)
+ {
+ context_handle = kerberos_CtxtHandleSSPItoGSSAPI(phContext);
+ }
+ }
+
+ input_token.length = 0;
+ if (pInput)
+ {
+ int input_token_idx = kerberos_GetTokenBufferIndex(pInput);
+ if (input_token_idx == -1)
+ return SEC_E_INVALID_TOKEN;
+ input_token.length = pInput->pBuffers[input_token_idx].cbBuffer;
+ input_token.value = pInput->pBuffers[input_token_idx].pvBuffer;
+ }
+
+ req_flags = kerberos_CtxtReqsSSPItoGSSAPI(fContextReq);
+
+ output_token_idx = kerberos_GetTokenBufferIndex(pOutput);
+ if (output_token_idx == -1)
+ return SEC_E_INVALID_TOKEN;
+
+ output_token.length = pOutput->pBuffers[output_token_idx].cbBuffer;
+ output_token.value = pOutput->pBuffers[output_token_idx].pvBuffer;
+
+ if (pszTargetName)
+ {
+ char *target_name_str;
+ int len;
+ gss_buffer_desc name_buffer;
+
+ len = WideCharToMultiByte(CP_UNIXCP, 0, pszTargetName, -1, NULL, 0, NULL, NULL);
+ target_name_str = HeapAlloc(GetProcessHeap(), 0, len);
+ if (!target_name_str)
+ return SEC_E_INSUFFICIENT_MEMORY;
+ WideCharToMultiByte(CP_UNIXCP, 0, pszTargetName, -1, target_name_str, len, NULL, NULL);
+
+ name_buffer.length = len-1;
+ name_buffer.value = target_name_str;
+
+ ret = p_gss_import_name(&minor_status, &name_buffer,
+ GSS_C_NULL_OID /* FIXME: detect the appropriate value for this ourselves? */,
+ &target_name);
+ HeapFree(GetProcessHeap(), 0, target_name_str);
+
+ if (ret != GSS_S_COMPLETE)
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+ }
+
+ ret = p_gss_init_sec_context(&minor_status, cred_handle, &context_handle,
+ target_name, GSS_C_NO_OID, req_flags, 0,
+ GSS_C_NO_CHANNEL_BINDINGS, &input_token, NULL,
+ &output_token, &ret_flags, &expiry_time);
+
+ if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED)
+ {
+ kerberos_ExpiryTimeToTimeStamp(expiry_time, ptsExpiry);
+ kerberos_CtxtHandleGSSAPItoSSPI(context_handle, phNewContext);
+
+ if (pfContextAttr)
+ {
+ kerberos_CtxtAttrsGSSPItoSSPI(ret_flags, pfContextAttr);
+ }
+ }
+
+ if (target_name != GSS_C_NO_NAME)
+ p_gss_release_name(&minor_status, &target_name);
+
+ pOutput->pBuffers[output_token_idx].cbBuffer = (ULONG) output_token.length;
+ pOutput->pBuffers[output_token_idx].pvBuffer = output_token.value;
+
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+}
+
+/***********************************************************************
+ * InitializeSecurityContextA
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_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 %d %d %d %p %d %p %p %p %p\n", phCredential, phContext,
+ debugstr_a(pszTargetName), fContextReq, Reserved1, TargetDataRep, pInput,
+ Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
+
+ if(pszTargetName != NULL)
+ {
+ int target_size = MultiByteToWideChar(CP_ACP, 0, pszTargetName,
+ strlen(pszTargetName)+1, NULL, 0);
+ target = HeapAlloc(GetProcessHeap(), 0, target_size *
+ sizeof(SEC_WCHAR));
+ MultiByteToWideChar(CP_ACP, 0, pszTargetName, strlen(pszTargetName)+1,
+ target, target_size);
+ }
+
+ ret = kerberos_InitializeSecurityContextW(phCredential, phContext, target,
+ fContextReq, Reserved1, TargetDataRep, pInput, Reserved2,
+ phNewContext, pOutput, pfContextAttr, ptsExpiry);
+
+ HeapFree(GetProcessHeap(), 0, target);
+ return ret;
+}
+
+/***********************************************************************
+ * AcceptSecurityContext
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_AcceptSecurityContext(
+ PCredHandle phCredential, PCtxtHandle phContext, PSecBufferDesc pInput,
+ ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
+ PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry)
+{
+ int output_token_idx;
+ OM_uint32 ret;
+ OM_uint32 minor_status;
+ gss_cred_id_t cred_handle;
+ gss_ctx_id_t context_handle;
+ OM_uint32 ret_flags;
+ gss_buffer_desc input_token;
+ gss_buffer_desc output_token;
+ OM_uint32 expiry_time;
+
+ TRACE("%p %p %p %d %d %p %p %p %p\n", phCredential, phContext, pInput,
+ fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr,
+ ptsExpiry);
+
+ if (!phContext && !pInput)
+ {
+ if (!phCredential)
+ return SEC_E_INVALID_HANDLE;
+ cred_handle = kerberos_CredHandleSSPItoGSSAPI(phCredential);
+ }
+ else
+ cred_handle = GSS_C_NO_CREDENTIAL;
+
+ if (pInput)
+ {
+ int input_token_idx = kerberos_GetTokenBufferIndex(pInput);
+ if (input_token_idx == -1)
+ return SEC_E_INVALID_TOKEN;
+ input_token.length = pInput->pBuffers[input_token_idx].cbBuffer;
+ input_token.value = pInput->pBuffers[input_token_idx].pvBuffer;
+ }
+
+ output_token_idx = kerberos_GetTokenBufferIndex(pOutput);
+ if (output_token_idx == -1)
+ return SEC_E_INVALID_TOKEN;
+ output_token.length = pOutput->pBuffers[output_token_idx].cbBuffer;
+ output_token.value = pOutput->pBuffers[output_token_idx].pvBuffer;
+
+ /* FIXME: get target_name */
+ ret = p_gss_accept_sec_context(&minor_status, &context_handle, cred_handle,
+ &input_token, GSS_C_NO_CHANNEL_BINDINGS,
+ NULL, NULL, &output_token, &ret_flags,
+ &expiry_time, NULL);
+
+ if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED)
+ {
+ kerberos_ExpiryTimeToTimeStamp(expiry_time, ptsExpiry);
+ kerberos_CtxtHandleGSSAPItoSSPI(context_handle, phContext);
+ }
+
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+}
+
+/***********************************************************************
+ * CompleteAuthToken
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_CompleteAuthToken(PCtxtHandle phContext,
+ PSecBufferDesc pToken)
+{
+ /* We never need to call CompleteAuthToken anyway */
+ TRACE("%p %p\n", phContext, pToken);
+ if (!phContext)
+ return SEC_E_INVALID_HANDLE;
+
+ return SEC_E_OK;
+}
+
+/***********************************************************************
+ * DeleteSecurityContext
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_DeleteSecurityContext(PCtxtHandle phContext)
+{
+ OM_uint32 ret;
+ OM_uint32 minor_status;
+ gss_buffer_desc output_buffer;
+ gss_ctx_id_t context_handle;
+
+ TRACE("%p\n", phContext);
+ if (!phContext)
+ return SEC_E_INVALID_HANDLE;
+
+ /* FIXME: is this correct? */
+ output_buffer.length = 0;
+ output_buffer.value = NULL;
+
+ context_handle = kerberos_CtxtHandleSSPItoGSSAPI(phContext);
+ ret = p_gss_delete_sec_context(&minor_status, &context_handle, &output_buffer);
+
+ phContext->dwUpper = 0;
+ phContext->dwLower = 0;
+
+ /* From https://docs.oracle.com/cd/E19683-01/816-0214/6m6nf1opf/index.html
+
+ * This function is provided for compatibility with the GSS-API version 1.
+ * Because gss_delete_sec_context() no longer returns a valid output_token
+ * to be sent to gss_process_context_token(), applications using a newer
+ * version of the GSS-API do not need to rely on this function.
+ *
+ *
+ if (ret == GSS_S_COMPLETE)
+ {
+
+ ret = gss_process_context_token(&minor_status, context_handle,
+ &output_buffer);
+ }*/
+
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+}
+
+/***********************************************************************
+ * QueryContextAttributesW
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesW(PCtxtHandle phContext,
+ ULONG ulAttribute, void *pBuffer)
+{
+ TRACE("%p %d %p\n", phContext, ulAttribute, pBuffer);
+ if (!phContext)
+ return SEC_E_INVALID_HANDLE;
+
+ switch(ulAttribute)
+ {
+#define _x(x) case (x) : FIXME(#x" stub\n"); break
+ _x(SECPKG_ATTR_ACCESS_TOKEN);
+ _x(SECPKG_ATTR_AUTHORITY);
+ _x(SECPKG_ATTR_DCE_INFO);
+#if 0
+ case SECPKG_ATTR_FLAGS:
+ {
+ PSecPkgContext_Flags spcf = (PSecPkgContext_Flags)pBuffer;
+ PNegoHelper helper = (PNegoHelper)phContext->dwLower;
+
+ spcf->Flags = 0;
+ if(helper->neg_flags & NTLMSSP_NEGOTIATE_SIGN)
+ spcf->Flags |= ISC_RET_INTEGRITY;
+ if(helper->neg_flags & NTLMSSP_NEGOTIATE_SEAL)
+ spcf->Flags |= ISC_RET_CONFIDENTIALITY;
+ return SEC_E_OK;
+ }
+#endif
+ _x(SECPKG_ATTR_KEY_INFO);
+ _x(SECPKG_ATTR_LIFESPAN);
+ _x(SECPKG_ATTR_NAMES);
+ _x(SECPKG_ATTR_NATIVE_NAMES);
+ _x(SECPKG_ATTR_NEGOTIATION_INFO);
+ _x(SECPKG_ATTR_PACKAGE_INFO);
+ _x(SECPKG_ATTR_PASSWORD_EXPIRY);
+ _x(SECPKG_ATTR_SESSION_KEY);
+#if 0
+ case SECPKG_ATTR_SIZES:
+ {
+ PSecPkgContext_Sizes spcs = (PSecPkgContext_Sizes)pBuffer;
+ spcs->cbMaxToken = NTLM_MAX_BUF;
+ spcs->cbMaxSignature = 16;
+ spcs->cbBlockSize = 0;
+ spcs->cbSecurityTrailer = 16;
+ return SEC_E_OK;
+ }
+#endif
+ _x(SECPKG_ATTR_STREAM_SIZES);
+ _x(SECPKG_ATTR_TARGET_INFORMATION);
+#undef _x
+ default:
+ TRACE("Unknown value %d passed for ulAttribute\n", ulAttribute);
+ }
+
+ return SEC_E_UNSUPPORTED_FUNCTION;
+}
+
+/***********************************************************************
+ * QueryContextAttributesA
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesA(PCtxtHandle phContext,
+ ULONG ulAttribute, void *pBuffer)
+{
+ return kerberos_QueryContextAttributesW(phContext, ulAttribute, pBuffer);
+}
+
+/***********************************************************************
+ * ImpersonateSecurityContext
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_ImpersonateSecurityContext(PCtxtHandle phContext)
+{
+ SECURITY_STATUS ret;
+
+ TRACE("%p\n", phContext);
+ if (phContext)
+ {
+ ret = SEC_E_UNSUPPORTED_FUNCTION;
+ }
+ else
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ }
+ return ret;
+}
+
+/***********************************************************************
+ * RevertSecurityContext
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_RevertSecurityContext(PCtxtHandle phContext)
+{
+ SECURITY_STATUS ret;
+
+ TRACE("%p\n", phContext);
+ if (phContext)
+ {
+ ret = SEC_E_UNSUPPORTED_FUNCTION;
+ }
+ else
+ {
+ ret = SEC_E_INVALID_HANDLE;
+ }
+ return ret;
+}
+
+/***********************************************************************
+ * MakeSignature
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
+ PSecBufferDesc pMessage, ULONG MessageSeqNo)
+{
+ int token_idx, message_idx;
+ OM_uint32 minor_status;
+ OM_uint32 ret;
+ gss_buffer_desc token_buffer;
+ gss_buffer_desc message_buffer;
+ gss_ctx_id_t context_handle;
+ OM_uint32 qop = GSS_C_QOP_DEFAULT;
+
+ TRACE("%p %d %p %d\n", phContext, fQOP, pMessage, MessageSeqNo);
+
+ if (!phContext)
+ return SEC_E_INVALID_HANDLE;
+
+ context_handle = kerberos_CtxtHandleSSPItoGSSAPI(phContext);
+
+ if(fQOP)
+ FIXME("Ignoring fQOP 0x%08x\n", fQOP);
+
+ if(MessageSeqNo)
+ FIXME("Ignoring MessageSeqNo\n");
+
+ if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
+ return SEC_E_INVALID_TOKEN;
+
+ /* If we didn't find a SECBUFFER_TOKEN type buffer */
+ if((token_idx = kerberos_GetTokenBufferIndex(pMessage)) == -1)
+ return SEC_E_INVALID_TOKEN;
+
+ token_buffer.length = pMessage->pBuffers[token_idx].cbBuffer;
+ token_buffer.value = pMessage->pBuffers[token_idx].pvBuffer;
+
+ /* Note: gssapi doesn't support multiple buffers like SSPI does, so we only
+ * takes the first buffer */
+ for (message_idx = 0; message_idx < pMessage->cBuffers; ++message_idx)
+ {
+ if (pMessage->pBuffers[message_idx].BufferType & SECBUFFER_DATA)
+ break;
+ }
+ if (message_idx == pMessage->cBuffers)
+ return SEC_E_INVALID_TOKEN;
+
+ message_buffer.length = pMessage->pBuffers[token_idx].cbBuffer;
+ message_buffer.value = pMessage->pBuffers[token_idx].pvBuffer;
+
+ ret = p_gss_get_mic(&minor_status, context_handle, qop, &message_buffer, &token_buffer);
+
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+}
+
+/***********************************************************************
+ * VerifySignature
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_VerifySignature(PCtxtHandle phContext,
+ PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
+{
+ int token_idx, message_idx;
+ OM_uint32 minor_status;
+ OM_uint32 ret;
+ gss_buffer_desc token_buffer;
+ gss_buffer_desc message_buffer;
+ gss_ctx_id_t context_handle;
+ gss_qop_t qop_state;
+
+ TRACE("%p %p %d %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
+
+ if(!phContext)
+ return SEC_E_INVALID_HANDLE;
+
+ context_handle = kerberos_CtxtHandleSSPItoGSSAPI(phContext);
+
+ if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
+ return SEC_E_INVALID_TOKEN;
+
+ if((token_idx = kerberos_GetTokenBufferIndex(pMessage)) == -1)
+ return SEC_E_INVALID_TOKEN;
+
+ if(MessageSeqNo)
+ FIXME("Ignoring MessageSeqNo\n");
+
+ /* If we didn't find a SECBUFFER_TOKEN type buffer */
+ if((token_idx = kerberos_GetTokenBufferIndex(pMessage)) == -1)
+ return SEC_E_INVALID_TOKEN;
+
+ token_buffer.length = pMessage->pBuffers[token_idx].cbBuffer;
+ token_buffer.value = pMessage->pBuffers[token_idx].pvBuffer;
+
+ /* Note: gssapi doesn't support multiple buffers like SSPI does, so we only
+ * takes the first buffer */
+ for (message_idx = 0; message_idx < pMessage->cBuffers; ++message_idx)
+ {
+ if (pMessage->pBuffers[message_idx].BufferType & SECBUFFER_DATA)
+ break;
+ }
+ if (message_idx == pMessage->cBuffers)
+ return SEC_E_INVALID_TOKEN;
+
+ message_buffer.length = pMessage->pBuffers[token_idx].cbBuffer;
+ message_buffer.value = pMessage->pBuffers[token_idx].pvBuffer;
+
+ ret = p_gss_verify_mic(&minor_status, context_handle, &message_buffer,
+ &token_buffer, &qop_state);
+
+ *pfQOP = 0;
+
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+}
+
+/***********************************************************************
+ * FreeCredentialsHandle
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_FreeCredentialsHandle(
+ PCredHandle phCredential)
+{
+ OM_uint32 ret;
+ OM_uint32 minor_status;
+
+ TRACE("(%p)\n", phCredential);
+
+ if (phCredential)
+ {
+ gss_cred_id_t cred_handle = kerberos_CredHandleSSPItoGSSAPI(phCredential);
+
+ HeapFree(GetProcessHeap(), 0, cred_handle);
+
+ phCredential->dwUpper = 0;
+ phCredential->dwLower = 0;
+
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+ }
+ else
+ return SEC_E_OK;
+}
+
+/***********************************************************************
+ * FreeContextBuffer (KERBEROS.@)
+ */
+SECURITY_STATUS WINAPI kerberos_FreeContextBuffer(PVOID pv)
+{
+ HeapFree(GetProcessHeap(), 0, pv);
+
+ return SEC_E_OK;
+}
+
+/***********************************************************************
+ * EncryptMessage
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_EncryptMessage(PCtxtHandle phContext,
+ ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
+{
+ gss_ctx_id_t context_handle;
+ int token_idx, data_idx;
+ gss_qop_t qop_req = GSS_C_QOP_DEFAULT;
+ int conf_state;
+ gss_buffer_desc input_message_buffer;
+ gss_buffer_desc output_message_buffer;
+ OM_uint32 ret;
+ OM_uint32 minor_status;
+
+ TRACE("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo);
+
+ if(!phContext)
+ return SEC_E_INVALID_HANDLE;
+ context_handle = kerberos_CtxtHandleSSPItoGSSAPI(phContext);
+
+ if(fQOP && (fQOP != SECQOP_WRAP_NO_ENCRYPT))
+ FIXME("Ignoring fQOP 0x%x\n", fQOP);
+
+ if(MessageSeqNo)
+ FIXME("Ignoring MessageSeqNo\n");
+
+ if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
+ return SEC_E_INVALID_TOKEN;
+
+ if((token_idx = kerberos_GetTokenBufferIndex(pMessage)) == -1)
+ return SEC_E_INVALID_TOKEN;
+
+ if((data_idx = kerberos_GetDataBufferIndex(pMessage)) ==-1 )
+ return SEC_E_INVALID_TOKEN;
+
+ input_message_buffer.length = pMessage->pBuffers[data_idx].cbBuffer;
+ input_message_buffer.value = pMessage->pBuffers[data_idx].pvBuffer;
+
+ /* FIXME: does gss_wrap allow overlapping buffers? */
+ output_message_buffer.length = pMessage->pBuffers[data_idx].cbBuffer;
+ output_message_buffer.value = pMessage->pBuffers[data_idx].pvBuffer;
+
+ /* FIXME: sign data and store it in token */
+
+ ret = p_gss_wrap(&minor_status, context_handle,
+ (fQOP == SECQOP_WRAP_NO_ENCRYPT) ? FALSE : TRUE, qop_req,
+ &input_message_buffer, &conf_state, &output_message_buffer);
+
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+}
+
+/***********************************************************************
+ * DecryptMessage
+ */
+static SECURITY_STATUS SEC_ENTRY kerberos_DecryptMessage(PCtxtHandle phContext,
+ PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
+{
+ gss_ctx_id_t context_handle;
+ OM_uint32 ret;
+ OM_uint32 minor_status;
+ int token_idx, data_idx;
+ gss_buffer_desc input_message_buffer;
+ gss_buffer_desc output_message_buffer;
+ gss_qop_t qop_req;
+ int conf_state;
+
+ TRACE("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
+
+ if(!phContext)
+ return SEC_E_INVALID_HANDLE;
+
+ context_handle = kerberos_CtxtHandleSSPItoGSSAPI(phContext);
+
+ if(MessageSeqNo)
+ FIXME("Ignoring MessageSeqNo\n");
+
+ if(!pMessage || !pMessage->pBuffers || pMessage->cBuffers < 2)
+ return SEC_E_INVALID_TOKEN;
+
+ if((token_idx = kerberos_GetTokenBufferIndex(pMessage)) == -1)
+ return SEC_E_INVALID_TOKEN;
+
+ if((data_idx = kerberos_GetDataBufferIndex(pMessage)) ==-1)
+ return SEC_E_INVALID_TOKEN;
+
+ input_message_buffer.length = pMessage->pBuffers[data_idx].cbBuffer;
+ input_message_buffer.value = pMessage->pBuffers[data_idx].pvBuffer;
+
+ /* FIXME: does gss_wrap allow overlapping buffers? */
+ output_message_buffer.length = pMessage->pBuffers[data_idx].cbBuffer;
+ output_message_buffer.value = pMessage->pBuffers[data_idx].pvBuffer;
+
+ ret = p_gss_unwrap(&minor_status, context_handle, &input_message_buffer,
+ &output_message_buffer, &conf_state, &qop_req);
+
+ *pfQOP = 0;
+
+ /* FIXME: verify data using token */
+
+ return kerberos_GSSAPIStatusToSecurityStatus(ret);
+}
+
+static SecurityFunctionTableA gssKerberosTableA = {
+ SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
+ kerberos_EnumerateSecurityPackagesA, /* EnumerateSecurityPackagesA */
+ kerberos_QueryCredentialsAttributesA, /* QueryCredentialsAttributesA */
+ kerberos_AcquireCredentialsHandleA, /* AcquireCredentialsHandleA */
+ kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */
+ NULL, /* Reserved2 */
+ kerberos_InitializeSecurityContextA, /* InitializeSecurityContextA */
+ kerberos_AcceptSecurityContext, /* AcceptSecurityContext */
+ kerberos_CompleteAuthToken, /* CompleteAuthToken */
+ kerberos_DeleteSecurityContext, /* DeleteSecurityContext */
+ NULL, /* ApplyControlToken */
+ kerberos_QueryContextAttributesA, /* QueryContextAttributesA */
+ kerberos_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
+ kerberos_RevertSecurityContext, /* RevertSecurityContext */
+ kerberos_MakeSignature, /* MakeSignature */
+ kerberos_VerifySignature, /* VerifySignature */
+ kerberos_FreeContextBuffer, /* FreeContextBuffer */
+ NULL, /* QuerySecurityPackageInfoA */
+ NULL, /* Reserved3 */
+ NULL, /* Reserved4 */
+ NULL, /* ExportSecurityContext */
+ NULL, /* ImportSecurityContextA */
+ NULL, /* AddCredentialsA */
+ NULL, /* Reserved8 */
+ NULL, /* QuerySecurityContextToken */
+ kerberos_EncryptMessage, /* EncryptMessage */
+ kerberos_DecryptMessage, /* DecryptMessage */
+ NULL, /* SetContextAttributesA */
+};
+
+static SecurityFunctionTableW gssKerberosTableW = {
+ SECURITY_SUPPORT_PROVIDER_INTERFACE_VERSION,
+ kerberos_EnumerateSecurityPackagesW, /* EnumerateSecurityPackagesW */
+ kerberos_QueryCredentialsAttributesW, /* QueryCredentialsAttributesW */
+ kerberos_AcquireCredentialsHandleW, /* AcquireCredentialsHandleW */
+ kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */
+ NULL, /* Reserved2 */
+ kerberos_InitializeSecurityContextW, /* InitializeSecurityContextW */
+ kerberos_AcceptSecurityContext, /* AcceptSecurityContext */
+ kerberos_CompleteAuthToken, /* CompleteAuthToken */
+ kerberos_DeleteSecurityContext, /* DeleteSecurityContext */
+ NULL, /* ApplyControlToken */
+ kerberos_QueryContextAttributesW, /* QueryContextAttributesW */
+ kerberos_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
+ kerberos_RevertSecurityContext, /* RevertSecurityContext */
+ kerberos_MakeSignature, /* MakeSignature */
+ kerberos_VerifySignature, /* VerifySignature */
+ kerberos_FreeContextBuffer, /* FreeContextBuffer */
+ NULL, /* QuerySecurityPackageInfoW */
+ NULL, /* Reserved3 */
+ NULL, /* Reserved4 */
+ NULL, /* ExportSecurityContext */
+ NULL, /* ImportSecurityContextW */
+ NULL, /* AddCredentialsW */
+ NULL, /* Reserved8 */
+ NULL, /* QuerySecurityContextToken */
+ kerberos_EncryptMessage, /* EncryptMessage */
+ kerberos_DecryptMessage, /* DecryptMessage */
+ NULL, /* SetContextAttributesW */
+};
+
+
+/***********************************************************************
+ * InitSecurityInterfaceA (KERBEROS.@)
+ */
+PSecurityFunctionTableA WINAPI InitSecurityInterfaceA(void)
+{
+ if (!load_gssapi())
+ {
+ return NULL;
+ }
+
+ return &gssKerberosTableA;
+}
+
+/***********************************************************************
+ * InitSecurityInterfaceW (KERBEROS.@)
+ */
+PSecurityFunctionTableW WINAPI InitSecurityInterfaceW(void)
+{
+ if (!load_gssapi())
+ {
+ return NULL;
+ }
+
+ return &gssKerberosTableW;
+}
diff --git a/dlls/secur32/Makefile.in b/dlls/secur32/Makefile.in
index 6548521f53..c9acdee457 100644
--- a/dlls/secur32/Makefile.in
+++ b/dlls/secur32/Makefile.in
@@ -9,7 +9,6 @@ C_SRCS = \
base64_codec.c \
dispatcher.c \
hmac_md5.c \
- kerberos.c \
lsa.c \
negotiate.c \
ntlm.c \
diff --git a/dlls/secur32/kerberos.c b/dlls/secur32/kerberos.c
deleted file mode 100644
index 753e9748d2..0000000000
--- a/dlls/secur32/kerberos.c
+++ /dev/null
@@ -1,323 +0,0 @@
-/*
- * Copyright 2005, 2006 Kai Blin
- * Copyright 2016 Jacek Caban for CodeWeavers
- *
- * 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 <assert.h>
-#include <stdarg.h>
-#include <stdio.h>
-
-#include "windef.h"
-#include "winbase.h"
-#include "rpc.h"
-#include "sspi.h"
-
-#include "secur32_priv.h"
-
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(secur32);
-
-#define KERBEROS_MAX_BUF 12000
-
-/***********************************************************************
- * QueryCredentialsAttributesA
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesA(CredHandle *phCredential, ULONG ulAttribute, void *pBuffer)
-{
- FIXME("(%p %d %p)\n", phCredential, ulAttribute, pBuffer);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * QueryCredentialsAttributesW
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesW(CredHandle *phCredential, ULONG ulAttribute, void *pBuffer)
-{
- FIXME("(%p, %d, %p)\n", phCredential, ulAttribute, pBuffer);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * AcquireCredentialsHandleW
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleW(SEC_WCHAR *pszPrincipal, SEC_WCHAR *pszPackage, ULONG fCredentialUse,
- LUID *pLogonID, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pGetKeyArgument, CredHandle *phCredential, TimeStamp *ptsExpiry)
-{
- FIXME("(%s %s 0x%08x %p %p %p %p %p %p)\n", debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
- pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
- return SEC_E_NO_CREDENTIALS;
-}
-
-/***********************************************************************
- * AcquireCredentialsHandleA
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleA(SEC_CHAR *pszPrincipal, SEC_CHAR *pszPackage, ULONG fCredentialUse,
- LUID *pLogonID, void *pAuthData, SEC_GET_KEY_FN pGetKeyFn, void *pGetKeyArgument, CredHandle *phCredential, TimeStamp *ptsExpiry)
-{
- FIXME("(%s %s 0x%08x %p %p %p %p %p %p)\n", debugstr_a(pszPrincipal), debugstr_a(pszPackage), fCredentialUse,
- pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * InitializeSecurityContextW
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_InitializeSecurityContextW(CredHandle *phCredential, CtxtHandle *phContext, SEC_WCHAR *pszTargetName,
- ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, SecBufferDesc *pInput, ULONG Reserved2, CtxtHandle *phNewContext,
- SecBufferDesc *pOutput, ULONG *pfContextAttr, TimeStamp *ptsExpiry)
-{
- FIXME("(%p %p %s 0x%08x %d %d %p %d %p %p %p %p)\n", phCredential, phContext, debugstr_w(pszTargetName),
- fContextReq, Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * InitializeSecurityContextA
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_InitializeSecurityContextA(CredHandle *phCredential, CtxtHandle *phContext, SEC_CHAR *pszTargetName,
- ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, SecBufferDesc *pInput, ULONG Reserved2, CtxtHandle *phNewContext,
- SecBufferDesc *pOutput, ULONG *pfContextAttr, TimeStamp *ptsExpiry)
-{
- FIXME("%p %p %s %d %d %d %p %d %p %p %p %p\n", phCredential, phContext, debugstr_a(pszTargetName), fContextReq,
- Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput, pfContextAttr, ptsExpiry);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * AcceptSecurityContext
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_AcceptSecurityContext(CredHandle *phCredential, CtxtHandle *phContext, SecBufferDesc *pInput,
- ULONG fContextReq, ULONG TargetDataRep, CtxtHandle *phNewContext, SecBufferDesc *pOutput, ULONG *pfContextAttr, TimeStamp *ptsExpiry)
-{
- FIXME("(%p %p %p %d %d %p %p %p %p)\n", phCredential, phContext, pInput, fContextReq, TargetDataRep, phNewContext, pOutput,
- pfContextAttr, ptsExpiry);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * CompleteAuthToken
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_CompleteAuthToken(CtxtHandle *phContext, SecBufferDesc *pToken)
-{
- FIXME("(%p %p)\n", phContext, pToken);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * DeleteSecurityContext
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_DeleteSecurityContext(CtxtHandle *phContext)
-{
- FIXME("(%p)\n", phContext);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * QueryContextAttributesW
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesW(CtxtHandle *phContext, ULONG ulAttribute, void *pBuffer)
-{
- FIXME("(%p %d %p)\n", phContext, ulAttribute, pBuffer);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * QueryContextAttributesA
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesA(CtxtHandle *phContext, ULONG ulAttribute, void *pBuffer)
-{
- FIXME("(%p %d %p)\n", phContext, ulAttribute, pBuffer);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * ImpersonateSecurityContext
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_ImpersonateSecurityContext(CtxtHandle *phContext)
-{
- FIXME("(%p)\n", phContext);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * RevertSecurityContext
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_RevertSecurityContext(CtxtHandle *phContext)
-{
- FIXME("(%p)\n", phContext);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * MakeSignature
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_MakeSignature(CtxtHandle *phContext, ULONG fQOP, SecBufferDesc *pMessage, ULONG MessageSeqNo)
-{
- FIXME("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * VerifySignature
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_VerifySignature(CtxtHandle *phContext, SecBufferDesc *pMessage, ULONG MessageSeqNo, PULONG pfQOP)
-{
- FIXME("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * FreeCredentialsHandle
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_FreeCredentialsHandle(PCredHandle phCredential)
-{
- FIXME("(%p)\n", phCredential);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * EncryptMessage
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_EncryptMessage(CtxtHandle *phContext, ULONG fQOP, SecBufferDesc *pMessage, ULONG MessageSeqNo)
-{
- FIXME("(%p %d %p %d)\n", phContext, fQOP, pMessage, MessageSeqNo);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-/***********************************************************************
- * DecryptMessage
- */
-static SECURITY_STATUS SEC_ENTRY kerberos_DecryptMessage(CtxtHandle *phContext, SecBufferDesc *pMessage, ULONG MessageSeqNo, PULONG pfQOP)
-{
- FIXME("(%p %p %d %p)\n", phContext, pMessage, MessageSeqNo, pfQOP);
- return SEC_E_UNSUPPORTED_FUNCTION;
-}
-
-static const SecurityFunctionTableA kerberosTableA = {
- 1,
- NULL, /* EnumerateSecurityPackagesA */
- kerberos_QueryCredentialsAttributesA, /* QueryCredentialsAttributesA */
- kerberos_AcquireCredentialsHandleA, /* AcquireCredentialsHandleA */
- kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */
- NULL, /* Reserved2 */
- kerberos_InitializeSecurityContextA, /* InitializeSecurityContextA */
- kerberos_AcceptSecurityContext, /* AcceptSecurityContext */
- kerberos_CompleteAuthToken, /* CompleteAuthToken */
- kerberos_DeleteSecurityContext, /* DeleteSecurityContext */
- NULL, /* ApplyControlToken */
- kerberos_QueryContextAttributesA, /* QueryContextAttributesA */
- kerberos_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
- kerberos_RevertSecurityContext, /* RevertSecurityContext */
- kerberos_MakeSignature, /* MakeSignature */
- kerberos_VerifySignature, /* VerifySignature */
- FreeContextBuffer, /* FreeContextBuffer */
- NULL, /* QuerySecurityPackageInfoA */
- NULL, /* Reserved3 */
- NULL, /* Reserved4 */
- NULL, /* ExportSecurityContext */
- NULL, /* ImportSecurityContextA */
- NULL, /* AddCredentialsA */
- NULL, /* Reserved8 */
- NULL, /* QuerySecurityContextToken */
- kerberos_EncryptMessage, /* EncryptMessage */
- kerberos_DecryptMessage, /* DecryptMessage */
- NULL, /* SetContextAttributesA */
-};
-
-static const SecurityFunctionTableW kerberosTableW = {
- 1,
- NULL, /* EnumerateSecurityPackagesW */
- kerberos_QueryCredentialsAttributesW, /* QueryCredentialsAttributesW */
- kerberos_AcquireCredentialsHandleW, /* AcquireCredentialsHandleW */
- kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */
- NULL, /* Reserved2 */
- kerberos_InitializeSecurityContextW, /* InitializeSecurityContextW */
- kerberos_AcceptSecurityContext, /* AcceptSecurityContext */
- kerberos_CompleteAuthToken, /* CompleteAuthToken */
- kerberos_DeleteSecurityContext, /* DeleteSecurityContext */
- NULL, /* ApplyControlToken */
- kerberos_QueryContextAttributesW, /* QueryContextAttributesW */
- kerberos_ImpersonateSecurityContext, /* ImpersonateSecurityContext */
- kerberos_RevertSecurityContext, /* RevertSecurityContext */
- kerberos_MakeSignature, /* MakeSignature */
- kerberos_VerifySignature, /* VerifySignature */
- FreeContextBuffer, /* FreeContextBuffer */
- NULL, /* QuerySecurityPackageInfoW */
- NULL, /* Reserved3 */
- NULL, /* Reserved4 */
- NULL, /* ExportSecurityContext */
- NULL, /* ImportSecurityContextW */
- NULL, /* AddCredentialsW */
- NULL, /* Reserved8 */
- NULL, /* QuerySecurityContextToken */
- kerberos_EncryptMessage, /* EncryptMessage */
- kerberos_DecryptMessage, /* DecryptMessage */
- NULL, /* SetContextAttributesW */
-};
-
-#define KERBEROS_COMMENT \
- {'M','i','c','r','o','s','o','f','t',' ','K','e','r','b','e','r','o','s',' ','V','1','.','0',0}
-static CHAR kerberos_comment_A[] = KERBEROS_COMMENT;
-static WCHAR kerberos_comment_W[] = KERBEROS_COMMENT;
-
-#define KERBEROS_NAME {'K','e','r','b','e','r','o','s',0}
-static char kerberos_name_A[] = KERBEROS_NAME;
-static WCHAR kerberos_name_W[] = KERBEROS_NAME;
-
-#define CAPS \
- ( SECPKG_FLAG_INTEGRITY \
- | SECPKG_FLAG_PRIVACY \
- | SECPKG_FLAG_TOKEN_ONLY \
- | SECPKG_FLAG_DATAGRAM \
- | 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_MUTUAL_AUTH \
- | SECPKG_FLAG_DELEGATION \
- | SECPKG_FLAG_READONLY_WITH_CHECKSUM \
- | SECPKG_FLAG_RESTRICTED_TOKENS \
- | SECPKG_FLAG_APPCONTAINER_CHECKS)
-
-static const SecPkgInfoW infoW = {
- CAPS,
- 1,
- RPC_C_AUTHN_GSS_KERBEROS,
- KERBEROS_MAX_BUF,
- kerberos_name_W,
- kerberos_comment_W
-};
-
-static const SecPkgInfoA infoA = {
- CAPS,
- 1,
- RPC_C_AUTHN_GSS_KERBEROS,
- KERBEROS_MAX_BUF,
- kerberos_name_A,
- kerberos_comment_A
-};
-
-void SECUR32_initKerberosSP(void)
-{
- SecureProvider *provider = SECUR32_addProvider(&kerberosTableA, &kerberosTableW, NULL);
- SECUR32_addPackages(provider, 1, &infoA, &infoW);
-}
diff --git a/dlls/secur32/secur32.c b/dlls/secur32/secur32.c
index f5d5746171..b5bdaf2fdd 100644
--- a/dlls/secur32/secur32.c
+++ b/dlls/secur32/secur32.c
@@ -439,7 +439,7 @@ SecureProvider *SECUR32_addProvider(const SecurityFunctionTableA *fnTableA,
ret->moduleName = SECUR32_strdupW(moduleName);
ret->loaded = FALSE;
}
-
+
LeaveCriticalSection(&cs);
return ret;
}
@@ -466,7 +466,7 @@ void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
packageTable->numPackages = 0;
list_init(&packageTable->table);
}
-
+
for (i = 0; i < toAdd; i++)
{
SecurePackage *package = HeapAlloc(GetProcessHeap(), 0, sizeof(SecurePackage));
@@ -488,7 +488,6 @@ void SECUR32_addPackages(SecureProvider *provider, ULONG toAdd,
static void _tryLoadProvider(PWSTR moduleName)
{
HMODULE lib = LoadLibraryW(moduleName);
-
if (lib)
{
INIT_SECURITY_INTERFACE_W pInitSecurityInterfaceW =
@@ -555,7 +554,7 @@ static const WCHAR securityProvidersKeyW[] = {
static const WCHAR securityProvidersW[] = {
'S','e','c','u','r','i','t','y','P','r','o','v','i','d','e','r','s',0
};
-
+
static void SECUR32_initializeProviders(void)
{
HKEY key;
@@ -565,12 +564,9 @@ static void SECUR32_initializeProviders(void)
/* First load built-in providers */
SECUR32_initSchannelSP();
SECUR32_initNTLMSP();
- SECUR32_initKerberosSP();
- /* 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 */
+ TRACE("Loading providers from registry...\n");
apiRet = RegOpenKeyExW(HKEY_LOCAL_MACHINE, securityProvidersKeyW, 0,
KEY_READ, &key);
if (apiRet == ERROR_SUCCESS)
@@ -604,6 +600,11 @@ static void SECUR32_initializeProviders(void)
}
RegCloseKey(key);
}
+
+ /* 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();
}
SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
@@ -616,14 +617,14 @@ SecurePackage *SECUR32_findPackageW(PCWSTR packageName)
LIST_FOR_EACH_ENTRY(ret, &packageTable->table, SecurePackage, entry)
{
matched = !lstrcmpiW(ret->infoW.Name, packageName);
- if (matched)
- break;
+ if (matched)
+ break;
}
-
- if (!matched)
- return NULL;
- if (ret->provider && !ret->provider->loaded)
+ if (!matched)
+ return NULL;
+
+ if (ret->provider && !ret->provider->loaded)
{
ret->provider->lib = LoadLibraryW(ret->provider->moduleName);
if (ret->provider->lib)
@@ -913,7 +914,7 @@ SECURITY_STATUS WINAPI EnumerateSecurityPackagesA(PULONG pcPackages,
* nSize returns the number of characters written when lpNameBuffer is not
* NULL or the size of the buffer needed to hold the name when the buffer
* is too short or lpNameBuffer is NULL.
- *
+ *
* It the buffer is too short, ERROR_INSUFFICIENT_BUFFER error will be set.
*/
BOOLEAN WINAPI GetComputerObjectNameA(
diff --git a/include/config.h.in b/include/config.h.in
index 6596571b29..909d21e32d 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -288,6 +288,9 @@
/* Define to 1 if you have the <gsm.h> header file. */
#undef HAVE_GSM_H
+/* Define to 1 if you have the <gssapi/gssapi_krb5.h> header file. */
+#undef HAVE_GSSAPI_GSSAPI_KRB5_H
+
/* Define if GTK 3 is installed */
#undef HAVE_GTK3
@@ -1508,6 +1511,9 @@
/* Define to the soname of the libgsm library. */
#undef SONAME_LIBGSM
+/* Define to the soname of the libgssapi_krb5 library. */
+#undef SONAME_LIBGSSAPI_KRB5
+
/* Define to the soname of the libgtk-3 library. */
#undef SONAME_LIBGTK_3
diff --git a/loader/wine.inf.in b/loader/wine.inf.in
index 2b0668a837..09e29fa86d 100644
--- a/loader/wine.inf.in
+++ b/loader/wine.inf.in
@@ -743,6 +743,8 @@ HKLM,Software\Policies,,16
HKLM,Software\Registered Applications,,16
HKLM,System\CurrentControlSet\Control\hivelist,,16
HKLM,System\CurrentControlSet\Control\Lsa\Kerberos,,16
+HKLM,System\CurrentControlSet\Control\Lsa\Kerberos,,16
+HKLM,System\CurrentControlSet\Control\SecurityProviders,"SecurityProviders",,"kerberos"
HKLM,System\CurrentControlSet\Control\SecurityProviders\Schannel\Protocols\SSL 2.0\Client,"DisabledByDefault",0x10003,1
HKLM,System\CurrentControlSet\Control\ServiceGroupOrder,"List",0x00010000,"TDI"
HKLM,System\CurrentControlSet\Control\TimeZoneInformation,"StandardName",2,""
--
2.15.0
From e20dce3032d5f8fc3b52df0e495ddb788f1e9d8d Mon Sep 17 00:00:00 2001
From: George Popoff <ambulance@etersoft.ru>
Date: Wed, 11 Oct 2017 14:58:09 +0300
Subject: [8/9] fix negotiate ssp to choose between kerberberos and ntlm ssp
Content-Type: text/plain; charset=UTF-8
Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
---
dlls/secur32/negotiate.c | 213 +++++++++++++++++++++++++++++++++++++-------
dlls/secur32/secur32_priv.h | 20 +----
2 files changed, 181 insertions(+), 52 deletions(-)
diff --git a/dlls/secur32/negotiate.c b/dlls/secur32/negotiate.c
index bf16258fc2..8d635818c6 100644
--- a/dlls/secur32/negotiate.c
+++ b/dlls/secur32/negotiate.c
@@ -33,6 +33,14 @@
WINE_DEFAULT_DEBUG_CHANNEL(secur32);
+static SEC_WCHAR ntlm_name_W[] = {'N','T','L','M',0};
+static SEC_WCHAR kerberos_name_W[] = {'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', 0};
+
+static SecurePackage *ntlm_package;
+static SecurePackage *kerberos_package;
+static SecureProvider *ntlm_provider;
+static SecureProvider *kerberos_provider;
+
/***********************************************************************
* QueryCredentialsAttributesA
*/
@@ -61,22 +69,50 @@ static SECURITY_STATUS SEC_ENTRY nego_AcquireCredentialsHandleW(
PLUID pLogonID, PVOID pAuthData, SEC_GET_KEY_FN pGetKeyFn,
PVOID pGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry )
{
- static SEC_WCHAR ntlmW[] = {'N','T','L','M',0};
SECURITY_STATUS ret;
TRACE("%s, %s, 0x%08x, %p, %p, %p, %p, %p, %p\n",
debugstr_w(pszPrincipal), debugstr_w(pszPackage), fCredentialUse,
pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument, phCredential, ptsExpiry);
- FIXME("forwarding to NTLM\n");
- ret = ntlm_AcquireCredentialsHandleW( pszPrincipal, ntlmW, fCredentialUse,
+ /* Assume this */
+ ret = SEC_E_INTERNAL_ERROR;
+
+ /* First we need to try kerberos */
+
+ if (kerberos_provider)
+ {
+ ret = kerberos_provider->fnTableW.
+ AcquireCredentialsHandleW(pszPrincipal, kerberos_name_W, fCredentialUse,
pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument,
- phCredential, ptsExpiry );
+ phCredential, ptsExpiry);
+ }
+
if (ret == SEC_E_OK)
{
+ /* FIXME: create KerberosCredentials */
NtlmCredentials *cred = (NtlmCredentials *)phCredential->dwLower;
cred->no_cached_credentials = (pAuthData == NULL);
+ return ret;
+ }
+
+ FIXME("Failed to AcquireCredentialHandle via Kerberos.\n");
+
+ /* Maybe ntlm? */
+ if (ntlm_provider)
+ {
+ ret = ntlm_provider->fnTableW.
+ AcquireCredentialsHandleW(pszPrincipal, ntlm_name_W, fCredentialUse,
+ pLogonID, pAuthData, pGetKeyFn, pGetKeyArgument,
+ phCredential, ptsExpiry );
}
+
+ if (ret == SEC_E_OK)
+ {
+ NtlmCredentials *cred = (NtlmCredentials *)phCredential->dwLower;
+ cred->no_cached_credentials = (pAuthData == NULL);
+ }
+
return ret;
}
@@ -173,15 +209,41 @@ static SECURITY_STATUS SEC_ENTRY nego_InitializeSecurityContextW(
PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
PSecBufferDesc pOutput, ULONG *pfContextAttr, PTimeStamp ptsExpiry )
{
+ SECURITY_STATUS ret;
+
TRACE("%p, %p, %s, 0x%08x, %u, %u, %p, %u, %p, %p, %p, %p\n",
phCredential, phContext, debugstr_w(pszTargetName), fContextReq,
Reserved1, TargetDataRep, pInput, Reserved1, phNewContext, pOutput,
pfContextAttr, ptsExpiry);
- return ntlm_InitializeSecurityContextW( phCredential, phContext, pszTargetName,
+ /* Assume this */
+ ret = SEC_E_INTERNAL_ERROR;
+
+ if (kerberos_provider)
+ {
+ ret = kerberos_provider->fnTableW.
+ InitializeSecurityContextW( phCredential, phContext, pszTargetName,
+ fContextReq, Reserved1, TargetDataRep,
+ pInput, Reserved2, phNewContext,
+ pOutput, pfContextAttr, ptsExpiry );
+ }
+
+ if (ret == SEC_E_OK || ret == SEC_I_CONTINUE_NEEDED)
+ {
+ return ret;
+ }
+
+
+ if (ntlm_provider)
+ {
+ ret = ntlm_provider->fnTableW.
+ InitializeSecurityContextW( phCredential, phContext, pszTargetName,
fContextReq, Reserved1, TargetDataRep,
pInput, Reserved2, phNewContext,
pOutput, pfContextAttr, ptsExpiry );
+ }
+
+ return ret;
}
/***********************************************************************
@@ -227,9 +289,16 @@ static SECURITY_STATUS SEC_ENTRY nego_AcceptSecurityContext(
pInput, fContextReq, TargetDataRep, phNewContext, pOutput, pfContextAttr,
ptsExpiry);
- return ntlm_AcceptSecurityContext( phCredential, phContext, pInput,
+ /* FIXME: add kerberos invocation */
+ if (ntlm_provider)
+ {
+ return ntlm_provider->fnTableW.
+ AcceptSecurityContext( phCredential, phContext, pInput,
fContextReq, TargetDataRep, phNewContext,
pOutput, pfContextAttr, ptsExpiry );
+ }
+
+ return SEC_E_INTERNAL_ERROR;
}
/***********************************************************************
@@ -259,7 +328,13 @@ static SECURITY_STATUS SEC_ENTRY nego_DeleteSecurityContext(PCtxtHandle phContex
{
TRACE("%p\n", phContext);
- return ntlm_DeleteSecurityContext( phContext );
+ if (phContext->dwUpper == KERBEROS_MAGIC && kerberos_provider)
+ return kerberos_provider->fnTableW.DeleteSecurityContext( phContext );
+
+ if (ntlm_provider)
+ return kerberos_provider->fnTableW.DeleteSecurityContext( phContext );
+
+ return SEC_E_INTERNAL_ERROR;
}
/***********************************************************************
@@ -288,28 +363,33 @@ static SECURITY_STATUS SEC_ENTRY nego_ApplyControlToken(PCtxtHandle phContext,
static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesW(
PCtxtHandle phContext, ULONG ulAttribute, void *pBuffer)
{
+ PSecPkgInfoW package_info_w;
+ SecureProvider *provider;
+
TRACE("%p, %u, %p\n", phContext, ulAttribute, pBuffer);
- switch (ulAttribute)
+ if (phContext->dwUpper == KERBEROS_MAGIC)
{
- case SECPKG_ATTR_SIZES:
+ package_info_w = &kerberos_package->infoW;
+ provider = kerberos_provider;
+ }
+ else
{
- SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)pBuffer;
- sizes->cbMaxToken = 2888;
- sizes->cbMaxSignature = 16;
- sizes->cbSecurityTrailer = 16;
- sizes->cbBlockSize = 0;
- return SEC_E_OK;
+ package_info_w = &ntlm_package->infoW;
+ provider = ntlm_provider;
}
+
+ switch (ulAttribute)
+ {
case SECPKG_ATTR_NEGOTIATION_INFO:
{
SecPkgContext_NegotiationInfoW *info = (SecPkgContext_NegotiationInfoW *)pBuffer;
- info->PackageInfo = ntlm_package_infoW;
+ info->PackageInfo = package_info_w;
info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE;
return SEC_E_OK;
}
default:
- return ntlm_QueryContextAttributesW( phContext, ulAttribute, pBuffer );
+ return provider->fnTableW.QueryContextAttributesW( phContext, ulAttribute, pBuffer );
}
}
@@ -319,29 +399,59 @@ static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesW(
static SECURITY_STATUS SEC_ENTRY nego_QueryContextAttributesA(PCtxtHandle phContext,
ULONG ulAttribute, void *pBuffer)
{
+ SECURITY_STATUS ret;
+ PSecPkgInfoW package_info_W;
+ PSecPkgInfoA package_info_A;
+ SecureProvider *provider;
+ /* int cbSize; */
+
TRACE("%p, %u, %p\n", phContext, ulAttribute, pBuffer);
- switch (ulAttribute)
+ if (phContext->dwUpper == KERBEROS_MAGIC)
{
- case SECPKG_ATTR_SIZES:
+ package_info_W = &kerberos_package->infoW;
+ provider = kerberos_provider;
+ }
+ else
{
- SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)pBuffer;
- sizes->cbMaxToken = 2888;
- sizes->cbMaxSignature = 16;
- sizes->cbSecurityTrailer = 16;
- sizes->cbBlockSize = 0;
- return SEC_E_OK;
+ package_info_W = &ntlm_package->infoW;
+ provider = ntlm_provider;
}
+
+ /* Convert package info from Widechar to ANSI */
+
+ /* package_info_A = (PSecPkgInfoA) HeapAlloc(GetProcessHeap(), 0, sizeof(*package_info_A));
+
+ cbSize = WideCharToMultiByte(CP_ACP, 0, package_info_W->Name, -1, NULL, 0, NULL, NULL);
+ package_info_A->Name = (SEC_CHAR *) HeapAlloc(GetProcessHeap(), 0, cbSize);
+ WideCharToMultiByte(CP_ACP, 0, package_info_W->Name, -1, &package_info_A->Name, cbSize, NULL, NULL);
+
+ cbSize = WideCharToMultiByte(CP_ACP, 0, package_info_W->Comment, -1, NULL, 0, NULL, NULL);
+ package_info_A->Comment = (SEC_CHAR *) HeapAlloc(GetProcessHeap(), 0, cbSize);
+ WideCharToMultiByte(CP_ACP, 0, package_info_W->Comment, -1, &package_info_A->Comment, cbSize, NULL, NULL);
+ */
+
+ switch (ulAttribute)
+ {
case SECPKG_ATTR_NEGOTIATION_INFO:
{
+ /* FIXME: Where we need to free the memory? */
+ /* SecurityPackage does not contains ANSI version of info */
+ /* Maybe we need to expand SecurityPackage structure? */
SecPkgContext_NegotiationInfoA *info = (SecPkgContext_NegotiationInfoA *)pBuffer;
- info->PackageInfo = ntlm_package_infoA;
+ info->PackageInfo = package_info_A;
info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE;
- return SEC_E_OK;
+ return SEC_E_UNSUPPORTED_FUNCTION;
}
default:
- return ntlm_QueryContextAttributesA( phContext, ulAttribute, pBuffer );
+ ret = provider->fnTableA.QueryContextAttributesA( phContext, ulAttribute, pBuffer );
}
+
+ HeapFree(GetProcessHeap(), 0, package_info_A->Name);
+ HeapFree(GetProcessHeap(), 0, package_info_A->Comment);
+ HeapFree(GetProcessHeap(), 0, package_info_A);
+
+ return ret;
}
/***********************************************************************
@@ -390,7 +500,10 @@ static SECURITY_STATUS SEC_ENTRY nego_MakeSignature(PCtxtHandle phContext,
{
TRACE("%p, 0x%08x, %p, %u\n", phContext, fQOP, pMessage, MessageSeqNo);
- return ntlm_MakeSignature( phContext, fQOP, pMessage, MessageSeqNo );
+ if (ntlm_provider)
+ return ntlm_provider->fnTableW.MakeSignature( phContext, fQOP, pMessage, MessageSeqNo );
+
+ return SEC_E_INTERNAL_ERROR;
}
/***********************************************************************
@@ -401,7 +514,10 @@ static SECURITY_STATUS SEC_ENTRY nego_VerifySignature(PCtxtHandle phContext,
{
TRACE("%p, %p, %u, %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
- return ntlm_VerifySignature( phContext, pMessage, MessageSeqNo, pfQOP );
+ if (ntlm_provider)
+ return ntlm_provider->fnTableW.VerifySignature( phContext, pMessage, MessageSeqNo, pfQOP );
+
+ return SEC_E_INTERNAL_ERROR;
}
/***********************************************************************
@@ -411,7 +527,18 @@ static SECURITY_STATUS SEC_ENTRY nego_FreeCredentialsHandle(PCredHandle phCreden
{
TRACE("%p\n", phCredential);
- return ntlm_FreeCredentialsHandle( phCredential );
+ if (phCredential->dwUpper == KERBEROS_MAGIC)
+ {
+ if (kerberos_provider)
+ return kerberos_provider->fnTableW.FreeCredentialsHandle( phCredential );
+ }
+ else
+ {
+ if (ntlm_provider)
+ return ntlm_provider->fnTableW.FreeCredentialsHandle( phCredential );
+ }
+
+ return SEC_E_INTERNAL_ERROR;
}
/***********************************************************************
@@ -422,7 +549,10 @@ static SECURITY_STATUS SEC_ENTRY nego_EncryptMessage(PCtxtHandle phContext,
{
TRACE("%p, 0x%08x, %p, %u\n", phContext, fQOP, pMessage, MessageSeqNo);
- return ntlm_EncryptMessage( phContext, fQOP, pMessage, MessageSeqNo );
+ if (ntlm_provider)
+ return ntlm_provider->fnTableW.EncryptMessage( phContext, fQOP, pMessage, MessageSeqNo );
+
+ return SEC_E_INTERNAL_ERROR;
}
/***********************************************************************
@@ -433,7 +563,10 @@ static SECURITY_STATUS SEC_ENTRY nego_DecryptMessage(PCtxtHandle phContext,
{
TRACE("%p, %p, %u, %p\n", phContext, pMessage, MessageSeqNo, pfQOP);
- return ntlm_DecryptMessage( phContext, pMessage, MessageSeqNo, pfQOP );
+ if (ntlm_provider)
+ return ntlm_provider->fnTableW.DecryptMessage( phContext, pMessage, MessageSeqNo, pfQOP );
+
+ return SEC_E_INTERNAL_ERROR;
}
static const SecurityFunctionTableA negoTableA = {
@@ -521,6 +654,7 @@ static CHAR negotiate_comment_A[] = "Microsoft Package Negotiator";
SECPKG_FLAG_LOGON | \
SECPKG_FLAG_RESTRICTED_TOKENS )
+
void SECUR32_initNegotiateSP(void)
{
SecureProvider *provider = SECUR32_addProvider(&negoTableA, &negoTableW, NULL);
@@ -530,4 +664,17 @@ void SECUR32_initNegotiateSP(void)
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);
+
+ ntlm_package = SECUR32_findPackageW(ntlm_name_W);
+ kerberos_package = SECUR32_findPackageW(kerberos_name_W);
+
+ if (ntlm_package)
+ ntlm_provider = ntlm_package->provider;
+ else
+ FIXME("SECUR32_findPackageW(ntlm) = null\n");
+
+ if (kerberos_package)
+ kerberos_provider = kerberos_package->provider;
+ else
+ FIXME("SECUR32_findPackageW(kerberos) = null\n");
}
diff --git a/dlls/secur32/secur32_priv.h b/dlls/secur32/secur32_priv.h
index 9a60d65788..212d19c753 100644
--- a/dlls/secur32/secur32_priv.h
+++ b/dlls/secur32/secur32_priv.h
@@ -136,7 +136,6 @@ PSTR SECUR32_AllocMultiByteFromWide(PCWSTR str) DECLSPEC_HIDDEN;
void SECUR32_initSchannelSP(void) DECLSPEC_HIDDEN;
void SECUR32_initNegotiateSP(void) DECLSPEC_HIDDEN;
void SECUR32_initNTLMSP(void) DECLSPEC_HIDDEN;
-void SECUR32_initKerberosSP(void) DECLSPEC_HIDDEN;
/* Cleanup functions for built-in providers */
void SECUR32_deinitSchannelSP(void) DECLSPEC_HIDDEN;
@@ -189,24 +188,7 @@ void SECUR32_arc4Cleanup(arc4_info *a4i) DECLSPEC_HIDDEN;
#define NTLMSSP_NEGOTIATE_KEY_EXCHANGE 0x40000000
#define NTLMSSP_NEGOTIATE_56 0x80000000
-SECURITY_STATUS SEC_ENTRY ntlm_AcquireCredentialsHandleW(SEC_WCHAR *, SEC_WCHAR *,
- ULONG, PLUID, PVOID, SEC_GET_KEY_FN, PVOID, PCredHandle, PTimeStamp) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_InitializeSecurityContextW(PCredHandle, PCtxtHandle,
- SEC_WCHAR *, ULONG fContextReq, ULONG, ULONG, PSecBufferDesc, ULONG, PCtxtHandle,
- PSecBufferDesc, ULONG *, PTimeStamp) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_AcceptSecurityContext(PCredHandle, PCtxtHandle, PSecBufferDesc,
- ULONG, ULONG, PCtxtHandle, PSecBufferDesc, ULONG *, PTimeStamp) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesA(PCtxtHandle, ULONG, void *) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle, ULONG, void *) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_EncryptMessage(PCtxtHandle, ULONG, PSecBufferDesc, ULONG) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_DecryptMessage(PCtxtHandle, PSecBufferDesc, ULONG, PULONG) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_FreeCredentialsHandle(PCredHandle) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_DeleteSecurityContext(PCtxtHandle) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_MakeSignature(PCtxtHandle, ULONG, PSecBufferDesc, ULONG) DECLSPEC_HIDDEN;
-SECURITY_STATUS SEC_ENTRY ntlm_VerifySignature(PCtxtHandle, PSecBufferDesc, ULONG, PULONG) DECLSPEC_HIDDEN;
-
-SecPkgInfoW *ntlm_package_infoW DECLSPEC_HIDDEN;
-SecPkgInfoA *ntlm_package_infoA DECLSPEC_HIDDEN;
+#define KERBEROS_MAGIC ('K' << 24 | 'E' << 16 | 'R' << 8 | 'B')
/* schannel internal interface */
typedef struct schan_imp_session_opaque *schan_imp_session;
--
2.15.0
From cae0f12b60023ecc15e0d517f9e16ab4f89b7154 Mon Sep 17 00:00:00 2001
From: Vitaly Lipatov <lav@etersoft.ru>
Date: Wed, 8 Nov 2017 01:41:24 +0300
Subject: [9/9] add-wincred.h-include: add patch for wineboot (needed only in
staging)
Content-Type: text/plain; charset=UTF-8
---
programs/wineboot/wineboot.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/programs/wineboot/wineboot.c b/programs/wineboot/wineboot.c
index c2c5792fc6..26519c1000 100644
--- a/programs/wineboot/wineboot.c
+++ b/programs/wineboot/wineboot.c
@@ -81,6 +81,7 @@
#include <shobjidl.h>
#include <shlwapi.h>
#include <shellapi.h>
+#include <wincred.h>
#include <ntsecapi.h>
#include <wininet.h>
#include "resource.h"
--
2.15.0