>From cfec0ed59a864f414db6ce6d1d8b89ffd474d06d Mon Sep 17 00:00:00 2001 From: George Popoff Date: Wed, 11 Oct 2017 14:53:11 +0300 Subject: [PATCH 7/8] create new kerberos ssp based on GSSAPI ssp. Delete old. --- wine/configure | 69 +- wine/configure.ac | 10 + wine/dlls/kerberos/Makefile.in | 3 +- wine/dlls/kerberos/kerberos.spec | 2 + wine/dlls/kerberos/krb5_ssp.c | 1304 ++++++++++++++++++++++++++++++++++++++ wine/dlls/secur32/Makefile.in | 1 - wine/dlls/secur32/kerberos.c | 323 ---------- wine/dlls/secur32/secur32.c | 33 +- wine/include/config.h.in | 6 + wine/loader/wine.inf.in | 2 + 10 files changed, 1411 insertions(+), 342 deletions(-) create mode 100644 wine/dlls/kerberos/krb5_ssp.c delete mode 100644 wine/dlls/secur32/kerberos.c diff --git a/wine/configure b/wine/configure index 82ba566..e7ebf89 100755 --- a/wine/configure +++ b/wine/configure @@ -6877,6 +6877,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 \ @@ -13765,6 +13767,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 : @@ -20531,4 +20599,3 @@ IFS="$ac_save_IFS" $as_echo " $as_me: Finished. Do '${ac_make}' to compile Wine. " >&6 - diff --git a/wine/configure.ac b/wine/configure.ac index c19ad60..35a2830 100644 --- a/wine/configure.ac +++ b/wine/configure.ac @@ -419,6 +419,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 \ @@ -1634,6 +1636,14 @@ 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 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/wine/dlls/kerberos/Makefile.in b/wine/dlls/kerberos/Makefile.in index db155f8..e14a218 100644 --- a/wine/dlls/kerberos/Makefile.in +++ b/wine/dlls/kerberos/Makefile.in @@ -1,4 +1,5 @@ MODULE = kerberos.dll C_SRCS = \ - krb5_ap.c + krb5_ap.c \ + krb5_ssp.c diff --git a/wine/dlls/kerberos/kerberos.spec b/wine/dlls/kerberos/kerberos.spec index d277cee..e92516f 100644 --- a/wine/dlls/kerberos/kerberos.spec +++ b/wine/dlls/kerberos/kerberos.spec @@ -1 +1,3 @@ @ stdcall SpLsaModeInitialize(long ptr ptr ptr) +@ stdcall InitSecurityInterfaceA() +@ stdcall InitSecurityInterfaceW() diff --git a/wine/dlls/kerberos/krb5_ssp.c b/wine/dlls/kerberos/krb5_ssp.c new file mode 100644 index 0000000..cfb408e --- /dev/null +++ b/wine/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 +#include +#include + +#ifdef HAVE_GSSAPI_GSSAPI_KRB5_H +#include +#include +#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/wine/dlls/secur32/Makefile.in b/wine/dlls/secur32/Makefile.in index 6548521..c9acdee 100644 --- a/wine/dlls/secur32/Makefile.in +++ b/wine/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/wine/dlls/secur32/kerberos.c b/wine/dlls/secur32/kerberos.c deleted file mode 100644 index 753e974..0000000 --- a/wine/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 -#include -#include - -#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/wine/dlls/secur32/secur32.c b/wine/dlls/secur32/secur32.c index f5d5746..b5bdaf2 100644 --- a/wine/dlls/secur32/secur32.c +++ b/wine/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/wine/include/config.h.in b/wine/include/config.h.in index 00503a3..7e4ddc5 100644 --- a/wine/include/config.h.in +++ b/wine/include/config.h.in @@ -285,6 +285,9 @@ /* Define to 1 if you have the header file. */ #undef HAVE_GSM_H +/* Define to 1 if you have the header file. */ +#undef HAVE_GSSAPI_GSSAPI_KRB5_H + /* Define to 1 if you have the header file. */ #undef HAVE_IEEEFP_H @@ -1475,6 +1478,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 libhal library. */ #undef SONAME_LIBHAL diff --git a/wine/loader/wine.inf.in b/wine/loader/wine.inf.in index 787ad7f..0a9f8c3 100644 --- a/wine/loader/wine.inf.in +++ b/wine/loader/wine.inf.in @@ -683,6 +683,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.10.4