>From 6d5fb811f56479c2b4500f0e38a508a718014ef3 Mon Sep 17 00:00:00 2001
From: Dmitry Timoshkov <dmitry@baikal.ru>
Date: Mon, 21 Aug 2017 15:43:25 +0800
Subject: [1/3] kerberos: Add a stub for Kerberos5 Authentication Package.
Content-Type: text/plain; charset=UTF-8
To: wine-patches@winehq.org

Signed-off-by: Dmitry Timoshkov <dmitry@baikal.ru>
---
 configure                   |  68 +++++++++++++++++
 configure.ac                |  10 +++
 dlls/kerberos/Makefile.in   |   4 +
 dlls/kerberos/kerberos.spec |   1 +
 dlls/kerberos/krb5_ap.c     | 180 ++++++++++++++++++++++++++++++++++++++++++++
 include/config.h.in         |   6 ++
 include/ntsecapi.h          |  12 +++
 7 files changed, 281 insertions(+)
 create mode 100644 dlls/kerberos/Makefile.in
 create mode 100644 dlls/kerberos/kerberos.spec
 create mode 100644 dlls/kerberos/krb5_ap.c

diff --git a/configure b/configure
index 302087e005..2660d5f840 100755
--- a/configure
+++ b/configure
@@ -6879,6 +6879,7 @@ for ac_header in \
 	ieeefp.h \
 	inet/mib2.h \
 	io.h \
+	krb5/krb5.h \
 	kstat.h \
 	libproc.h \
 	link.h \
@@ -13697,6 +13698,72 @@ esac
 
 fi
 
+if test "$ac_cv_header_krb5_krb5_h" = "yes"
+then
+    { $as_echo "$as_me:${as_lineno-$LINENO}: checking for -lkrb5" >&5
+$as_echo_n "checking for -lkrb5... " >&6; }
+if ${ac_cv_lib_soname_krb5+:} false; then :
+  $as_echo_n "(cached) " >&6
+else
+  ac_check_soname_save_LIBS=$LIBS
+LIBS="-lkrb5  $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 krb5_init_context ();
+int
+main ()
+{
+return krb5_init_context ();
+  ;
+  return 0;
+}
+_ACEOF
+if ac_fn_c_try_link "$LINENO"; then :
+  case "$LIBEXT" in
+    dll) ac_cv_lib_soname_krb5=`$ac_cv_path_LDD conftest.exe | grep "krb5" | sed -e "s/dll.*/dll/"';2,$d'` ;;
+    dylib) ac_cv_lib_soname_krb5=`$OTOOL -L conftest$ac_exeext | grep "libkrb5\\.[0-9A-Za-z.]*dylib" | sed -e "s/^.*\/\(libkrb5\.[0-9A-Za-z.]*dylib\).*$/\1/"';2,$d'` ;;
+    *) ac_cv_lib_soname_krb5=`$READELF -d conftest$ac_exeext | grep "NEEDED.*libkrb5\\.$LIBEXT" | sed -e "s/^.*\\[\\(libkrb5\\.$LIBEXT[^	 ]*\\)\\].*$/\1/"';2,$d'`
+       if ${ac_cv_lib_soname_krb5:+false} :; then :
+  ac_cv_lib_soname_krb5=`$LDD conftest$ac_exeext | grep "libkrb5\\.$LIBEXT" | sed -e "s/^.*\(libkrb5\.$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_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_krb5" >&5
+$as_echo "$ac_cv_lib_soname_krb5" >&6; }
+
+cat >>confdefs.h <<_ACEOF
+#define SONAME_LIBKRB5 "$ac_cv_lib_soname_krb5"
+_ACEOF
+
+
+fi
+fi
+if test "x$ac_cv_lib_soname_krb5" = "x"; then :
+  case "x$with_krb5" in
+  x)   as_fn_append wine_notices "|libkrb5 ${notice_platform}development files not found, krb5 won't be supported." ;;
+  xno) ;;
+  *)   as_fn_error $? "libkrb5 ${notice_platform}development files not found, krb5 won't be supported.
+This is an error since --with-krb5 was requested." "$LINENO" 5 ;;
+esac
+
+fi
+
 if test "x$with_jpeg" != "xno"
 then
     if ${JPEG_CFLAGS:+false} :; then :
@@ -18419,6 +18486,7 @@ wine_fn_config_dll jscript enable_jscript clean
 wine_fn_config_test dlls/jscript/tests jscript_test
 wine_fn_config_dll jsproxy enable_jsproxy implib
 wine_fn_config_test dlls/jsproxy/tests jsproxy_test
+wine_fn_config_dll kerberos enable_kerberos clean
 wine_fn_config_dll kernel32 enable_kernel32 clean,implib
 wine_fn_config_test dlls/kernel32/tests kernel32_test
 wine_fn_config_dll kernelbase enable_kernelbase
diff --git a/configure.ac b/configure.ac
index 9aeaf34710..f1e25fd3db 100644
--- a/configure.ac
+++ b/configure.ac
@@ -422,6 +422,7 @@ AC_CHECK_HEADERS(\
 	ieeefp.h \
 	inet/mib2.h \
 	io.h \
+	krb5/krb5.h \
 	kstat.h \
 	libproc.h \
 	link.h \
@@ -1625,6 +1626,14 @@ fi
 WINE_NOTICE_WITH(gsm,[test "x$ac_cv_lib_soname_gsm" = "x"],
                  [libgsm ${notice_platform}development files not found, gsm 06.10 codec won't be supported.])
 
+dnl **** Check for krb5 ****
+if test "$ac_cv_header_krb5_krb5_h" = "yes"
+then
+    WINE_CHECK_SONAME(krb5,krb5_init_context)
+fi
+WINE_NOTICE_WITH(krb5,[test "x$ac_cv_lib_soname_krb5" = "x"],
+                 [libkrb5 ${notice_platform}development files not found, krb5 won't be supported.])
+
 dnl **** Check for libjpeg ****
 if test "x$with_jpeg" != "xno"
 then
@@ -3200,6 +3209,7 @@ WINE_CONFIG_DLL(jscript,,[clean])
 WINE_CONFIG_TEST(dlls/jscript/tests)
 WINE_CONFIG_DLL(jsproxy,,[implib])
 WINE_CONFIG_TEST(dlls/jsproxy/tests)
+WINE_CONFIG_DLL(kerberos)
 WINE_CONFIG_DLL(kernel32,,[clean,implib])
 WINE_CONFIG_TEST(dlls/kernel32/tests)
 WINE_CONFIG_DLL(kernelbase)
diff --git a/dlls/kerberos/Makefile.in b/dlls/kerberos/Makefile.in
new file mode 100644
index 0000000000..db155f8e66
--- /dev/null
+++ b/dlls/kerberos/Makefile.in
@@ -0,0 +1,4 @@
+MODULE    = kerberos.dll
+
+C_SRCS = \
+	krb5_ap.c
diff --git a/dlls/kerberos/kerberos.spec b/dlls/kerberos/kerberos.spec
new file mode 100644
index 0000000000..d277ceee5b
--- /dev/null
+++ b/dlls/kerberos/kerberos.spec
@@ -0,0 +1 @@
+@ stdcall SpLsaModeInitialize(long ptr ptr ptr)
diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c
new file mode 100644
index 0000000000..39b6ee35b6
--- /dev/null
+++ b/dlls/kerberos/krb5_ap.c
@@ -0,0 +1,180 @@
+/*
+ * Copyright 2017 Dmitry Timoshkov
+ *
+ * Kerberos5 Authentication Package
+ *
+ * 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 "wine/port.h"
+
+#include <stdarg.h>
+#ifdef HAVE_KRB5_KRB5_H
+#include <krb5/krb5.h>
+#endif
+
+#include "ntstatus.h"
+#define WIN32_NO_STATUS
+#include "windef.h"
+#include "winbase.h"
+#include "sspi.h"
+#include "ntsecapi.h"
+#include "ntsecpkg.h"
+#include "winternl.h"
+#include "wine/library.h"
+#include "wine/debug.h"
+
+WINE_DEFAULT_DEBUG_CHANNEL(krb5);
+WINE_DECLARE_DEBUG_CHANNEL(winediag);
+
+static ULONG krb5_package_id;
+static LSA_DISPATCH_TABLE lsa_dispatch;
+
+#define MAKE_FUNCPTR(f) static typeof(f) * p_##f
+MAKE_FUNCPTR(krb5_init_context);
+#undef MAKE_FUNCPTR
+
+static BOOL load_krb5(void)
+{
+    void *libkrb5_handle;
+
+    if (!(libkrb5_handle = wine_dlopen(SONAME_LIBKRB5, RTLD_NOW, NULL, 0)))
+    {
+        ERR_(winediag)("failed to load libkrb5\n" );
+        return FALSE;
+    }
+
+#define LOAD_FUNCPTR(f) \
+    if (!(p_##f = wine_dlsym(libkrb5_handle, #f, NULL, 0))) \
+    { \
+        ERR("failed to load %s\n", #f); \
+        goto fail; \
+    }
+
+    LOAD_FUNCPTR(krb5_init_context)
+#undef LOAD_FUNCPTR
+
+    return TRUE;
+
+fail:
+    wine_dlclose(libkrb5_handle, NULL, 0);
+    return FALSE;
+}
+
+static NTSTATUS NTAPI krb5_LsaApInitializePackage(ULONG package_id, PLSA_DISPATCH_TABLE dispatch,
+    PLSA_STRING database, PLSA_STRING confidentiality, PLSA_STRING *package_name)
+{
+    char *krb5_name;
+
+    if (!load_krb5())
+        return STATUS_DLL_INIT_FAILED;
+
+    krb5_package_id = package_id;
+    lsa_dispatch = *dispatch;
+
+    krb5_name = lsa_dispatch.AllocateLsaHeap(sizeof(MICROSOFT_KERBEROS_NAME_A));
+    if (!krb5_name) return STATUS_NO_MEMORY;
+
+    memcpy(krb5_name, MICROSOFT_KERBEROS_NAME_A, sizeof(MICROSOFT_KERBEROS_NAME_A));
+
+    *package_name = lsa_dispatch.AllocateLsaHeap(sizeof(**package_name));
+    if (!*package_name)
+    {
+        lsa_dispatch.FreeLsaHeap(krb5_name);
+        return STATUS_NO_MEMORY;
+    }
+
+    RtlInitString(*package_name, krb5_name);
+
+    return STATUS_SUCCESS;
+}
+
+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,
+        in_buffer_length, out_buffer, out_buffer_length, status);
+
+    *status = STATUS_NOT_IMPLEMENTED;
+    return STATUS_NOT_IMPLEMENTED;
+}
+
+static SECPKG_FUNCTION_TABLE krb5_table =
+{
+    krb5_LsaApInitializePackage, /* InitializePackage */
+    NULL, /* LsaLogonUser */
+    NULL, /* CallPackage */
+    NULL, /* LogonTerminated */
+    krb5_LsaApCallPackageUntrusted, /* CallPackageUntrusted */
+    NULL, /* CallPackagePassthrough */
+    NULL, /* LogonUserEx */
+    NULL, /* LogonUserEx2 */
+    NULL, /* Initialize */
+    NULL, /* Shutdown */
+    NULL, /* SpGetInfoUnified */
+    NULL, /* AcceptCredentials */
+    NULL, /* SpAcquireCredentialsHandle */
+    NULL, /* SpQueryCredentialsAttributes */
+    NULL, /* FreeCredentialsHandle */
+    NULL, /* SaveCredentials */
+    NULL, /* GetCredentials */
+    NULL, /* DeleteCredentials */
+    NULL, /* InitLsaModeContext */
+    NULL, /* AcceptLsaModeContext */
+    NULL, /* DeleteContext */
+    NULL, /* ApplyControlToken */
+    NULL, /* GetUserInfo */
+    NULL, /* GetExtendedInformation */
+    NULL, /* SpQueryContextAttributes */
+    NULL, /* SpAddCredentials */
+    NULL, /* SetExtendedInformation */
+    NULL, /* SetContextAttributes */
+    NULL, /* SetCredentialsAttributes */
+    NULL, /* ChangeAccountPassword */
+    NULL, /* QueryMetaData */
+    NULL, /* ExchangeMetaData */
+    NULL, /* GetCredUIContext */
+    NULL, /* UpdateCredentials */
+    NULL, /* ValidateTargetInfo */
+    NULL, /* PostLogonUser */
+};
+
+NTSTATUS NTAPI SpLsaModeInitialize(ULONG lsa_version, PULONG package_version,
+    PSECPKG_FUNCTION_TABLE *table, PULONG table_count)
+{
+    TRACE("%#x,%p,%p,%p\n", lsa_version, package_version, table, table_count);
+
+    *package_version = SECPKG_INTERFACE_VERSION;
+    *table = &krb5_table;
+    *table_count = 1;
+
+    return STATUS_SUCCESS;
+}
+
+BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, LPVOID reserved)
+{
+    TRACE("%p,%u,%p\n", hinst, reason, reserved);
+
+    switch (reason)
+    {
+        case DLL_PROCESS_ATTACH:
+            DisableThreadLibraryCalls(hinst);
+            break;
+    }
+
+    return TRUE;
+}
diff --git a/include/config.h.in b/include/config.h.in
index b0b5925fa5..00503a371e 100644
--- a/include/config.h.in
+++ b/include/config.h.in
@@ -342,6 +342,9 @@
 /* Define to 1 if you have the `kqueue' function. */
 #undef HAVE_KQUEUE
 
+/* Define to 1 if you have the <krb5/krb5.h> header file. */
+#undef HAVE_KRB5_KRB5_H
+
 /* Define to 1 if you have the <kstat.h> header file. */
 #undef HAVE_KSTAT_H
 
@@ -1478,6 +1481,9 @@
 /* Define to the soname of the libjpeg library. */
 #undef SONAME_LIBJPEG
 
+/* Define to the soname of the libkrb5 library. */
+#undef SONAME_LIBKRB5
+
 /* Define to the soname of the libncurses library. */
 #undef SONAME_LIBNCURSES
 
diff --git a/include/ntsecapi.h b/include/ntsecapi.h
index 2bb3d312e4..36357c61b4 100644
--- a/include/ntsecapi.h
+++ b/include/ntsecapi.h
@@ -340,6 +340,18 @@ typedef enum _POLICY_NOTIFICATION_INFORMATION_CLASS
     PolicyNotifyMachineAccountPasswordInformation
 } POLICY_NOTIFICATION_INFORMATION_CLASS, *PPOLICY_NOTIFICATION_INFORMATION_CLASS;
 
+#ifdef UNICODE
+#if defined(_MSC_VER)
+#define MICROSOFT_KERBEROS_NAME_W L"Kerberos"
+#elif defined(__GNUC__)
+#define MICROSOFT_KERBEROS_NAME_W (const WCHAR []){ 'K','e','r','b','e','r','o','s',0 }
+#else /* _MSC_VER/__GNUC__ */
+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"
+#endif
+
 #define RtlGenRandom                    SystemFunction036
 #define RtlEncryptMemory                SystemFunction040
 #define RtlDecryptMemory                SystemFunction041
-- 
2.14.1

