[01/10] secur32: Implement AcquireCredentialsHandle for Kerberos.
Hans Leidekker
hans at codeweavers.com
Mon Oct 16 03:04:54 CDT 2017
This series is based on a patch by Rob Shearman.
Signed-off-by: Hans Leidekker <hans at codeweavers.com>
---
configure.ac | 17 ++++
dlls/secur32/Makefile.in | 4 +-
dlls/secur32/kerberos.c | 205 ++++++++++++++++++++++++++++++++++++++++++++---
3 files changed, 213 insertions(+), 13 deletions(-)
diff --git a/configure.ac b/configure.ac
index 0966420120..81d62aed1c 100644
--- a/configure.ac
+++ b/configure.ac
@@ -53,6 +53,7 @@ AC_ARG_WITH(glu, AS_HELP_STRING([--without-glu],[do not use the GLU librar
AC_ARG_WITH(gnutls, AS_HELP_STRING([--without-gnutls],[do not use GnuTLS (schannel support)]))
AC_ARG_WITH(gsm, AS_HELP_STRING([--without-gsm],[do not use libgsm (GSM 06.10 codec support)]),
[if test "x$withval" = "xno"; then ac_cv_header_gsm_h=no; ac_cv_header_gsm_gsm_h=no; fi])
+AC_ARG_WITH(gssapi, AS_HELP_STRING([--without-gssapi],[do not use GSSAPI (Kerberos support)]))
AC_ARG_WITH(gstreamer, AS_HELP_STRING([--without-gstreamer],[do not use GStreamer (codecs support)]))
AC_ARG_WITH(hal, AS_HELP_STRING([--without-hal],[do not use HAL (dynamic device support)]))
AC_ARG_WITH(jpeg, AS_HELP_STRING([--without-jpeg],[do not use JPEG]))
@@ -1417,6 +1418,22 @@ fi
WINE_NOTICE_WITH(cms,[test "$ac_cv_lib_lcms2_cmsOpenProfileFromFile" != "yes"],
[liblcms2 ${notice_platform}development files not found, Color Management won't be supported.])
+dnl **** Check for GSSAPI ****
+if test "x$with_gssapi" != "xno"
+then
+ WINE_PACKAGE_FLAGS(GSSAPI,[krb5-gssapi],,,,
+ [AC_CHECK_HEADERS([gssapi/gssapi.h gssapi/gssapi_ext.h])
+ if test "$ac_cv_header_gssapi_gssapi_h" = "yes" -a "$ac_cv_header_gssapi_gssapi_ext_h" = "yes"
+ then
+ AC_CHECK_LIB(gssapi_krb5, gss_init_sec_context,
+ [AC_DEFINE(HAVE_GSSAPI, 1, [Define if you have the GSSAPI development environment])],[GSSAPI_LIBS=""],[$GSSAPI_LIBS])
+ else
+ GSSAPI_CFLAGS=""
+ fi])
+fi
+WINE_WARNING_WITH(gssapi,[test "x$ac_cv_lib_gssapi_krb5_gss_init_sec_context" = "x"],
+ [libgssapi_krb5 ${notice_platform}development files not found (or too old), no Kerberos support.])
+
dnl **** Check for FreeType 2 ****
if test "x$with_freetype" != "xno"
then
diff --git a/dlls/secur32/Makefile.in b/dlls/secur32/Makefile.in
index 6548521f53..0676f094e4 100644
--- a/dlls/secur32/Makefile.in
+++ b/dlls/secur32/Makefile.in
@@ -2,8 +2,8 @@ MODULE = secur32.dll
IMPORTLIB = secur32
IMPORTS = netapi32 advapi32
DELAYIMPORTS = crypt32
-EXTRAINCL = $(GNUTLS_CFLAGS)
-EXTRALIBS = $(SECURITY_LIBS)
+EXTRAINCL = $(GNUTLS_CFLAGS) $(GSSAPI_CFLAGS)
+EXTRALIBS = $(SECURITY_LIBS) $(GSSAPI_LIBS)
C_SRCS = \
base64_codec.c \
diff --git a/dlls/secur32/kerberos.c b/dlls/secur32/kerberos.c
index 753e9748d2..50d2cea102 100644
--- a/dlls/secur32/kerberos.c
+++ b/dlls/secur32/kerberos.c
@@ -1,6 +1,8 @@
/*
* Copyright 2005, 2006 Kai Blin
+ * Copyright 2008 Robert Shearman for CodeWeavers
* Copyright 2016 Jacek Caban for CodeWeavers
+ * Copyright 2017 Hans Leidekker for CodeWeavers
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
@@ -17,9 +19,13 @@
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
-#include <assert.h>
+#include "config.h"
#include <stdarg.h>
#include <stdio.h>
+#ifdef HAVE_GSSAPI
+# include <gssapi/gssapi.h>
+# include <gssapi/gssapi_ext.h>
+#endif
#include "windef.h"
#include "winbase.h"
@@ -34,6 +40,71 @@ WINE_DEFAULT_DEBUG_CHANNEL(secur32);
#define KERBEROS_MAX_BUF 12000
+#ifdef HAVE_GSSAPI
+static inline void credhandle_gss_to_sspi( gss_cred_id_t handle, gss_name_t principal, CredHandle *cred )
+{
+ cred->dwLower = (DWORD_PTR)handle;
+ cred->dwUpper = (DWORD_PTR)principal;
+}
+
+static SECURITY_STATUS status_gss_to_sspi( 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_INVALID_TOKEN;
+ case GSS_S_DEFECTIVE_CREDENTIAL: return SEC_E_NO_CREDENTIALS;
+ 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%08x to SECURITY_STATUS\n", status );
+ return SEC_E_INTERNAL_ERROR;
+ }
+}
+
+static void expirytime_gss_to_sspi( OM_uint32 expirytime, TimeStamp *timestamp )
+{
+ SYSTEMTIME time;
+ FILETIME filetime;
+ ULARGE_INTEGER tmp;
+
+ GetLocalTime( &time );
+ SystemTimeToFileTime( &time, &filetime );
+ tmp.QuadPart = ((ULONGLONG)filetime.dwLowDateTime | (ULONGLONG)filetime.dwHighDateTime << 32) + expirytime;
+ timestamp->LowPart = tmp.QuadPart;
+ timestamp->HighPart = tmp.QuadPart >> 32;
+}
+
+static SECURITY_STATUS name_sspi_to_gss( const SEC_WCHAR *name_str, gss_name_t *name )
+{
+ OM_uint32 ret, minor_status;
+ gss_OID type = GSS_C_NO_OID; /* FIXME: detect the appropriate value for this ourselves? */
+ gss_buffer_desc buf;
+
+ buf.length = WideCharToMultiByte( CP_UNIXCP, 0, name_str, -1, NULL, 0, NULL, NULL );
+ if (!(buf.value = HeapAlloc( GetProcessHeap(), 0, buf.length ))) return SEC_E_INSUFFICIENT_MEMORY;
+ WideCharToMultiByte( CP_UNIXCP, 0, name_str, -1, buf.value, buf.length, NULL, NULL );
+ buf.length--;
+
+ ret = gss_import_name( &minor_status, &buf, type, name );
+ TRACE( "gss_import_name returned %08x minor status %08x\n", ret, minor_status );
+
+ HeapFree( GetProcessHeap(), 0, buf.value );
+ return status_gss_to_sspi( ret );
+}
+#endif
+
/***********************************************************************
* QueryCredentialsAttributesA
*/
@@ -55,23 +126,135 @@ static SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesW(CredHandle
/***********************************************************************
* 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)
+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;
+#ifdef HAVE_GSSAPI
+ OM_uint32 ret, minor_status, expiry_time;
+ gss_name_t principal = GSS_C_NO_NAME;
+ gss_cred_usage_t cred_usage;
+ gss_cred_id_t cred_handle;
+
+ 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)
+ {
+ 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:
+ return SEC_E_UNKNOWN_CREDENTIALS;
+ }
+
+ if (pszPrincipal && ((ret = name_sspi_to_gss( pszPrincipal, &principal )) != SEC_E_OK)) return ret;
+
+ ret = gss_acquire_cred( &minor_status, principal, GSS_C_INDEFINITE, GSS_C_NULL_OID_SET, cred_usage,
+ &cred_handle, NULL, &expiry_time );
+ TRACE( "gss_acquire_cred returned %08x minor status %08x\n", ret, minor_status );
+ if (ret == GSS_S_COMPLETE || ret == GSS_S_CONTINUE_NEEDED)
+ {
+ credhandle_gss_to_sspi( cred_handle, principal, phCredential );
+ expirytime_gss_to_sspi( expiry_time, ptsExpiry );
+ }
+ else if (principal != GSS_C_NO_NAME) gss_release_name( &minor_status, &principal );
+
+ return status_gss_to_sspi( ret );
+#else
+ 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 );
+ FIXME( "Wine was built without Kerberos support.\n" );
+ return SEC_E_UNSUPPORTED_FUNCTION;
+#endif
}
/***********************************************************************
* 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)
+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;
+ SECURITY_STATUS ret = SEC_E_INSUFFICIENT_MEMORY;
+ int len_user = 0, len_domain = 0, len_passwd = 0;
+ SEC_WCHAR *principal = NULL, *package = NULL, *user = NULL, *domain = NULL, *passwd = NULL;
+ SEC_WINNT_AUTH_IDENTITY_W *authdata = NULL;
+ SEC_WINNT_AUTH_IDENTITY_A *id = 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 (pszPrincipal)
+ {
+ int len = MultiByteToWideChar( CP_ACP, 0, pszPrincipal, -1, NULL, 0 );
+ if (!(principal = HeapAlloc( GetProcessHeap(), 0, len * sizeof(SEC_WCHAR) ))) goto done;
+ MultiByteToWideChar( CP_ACP, 0, pszPrincipal, -1, principal, len );
+ }
+ if (pszPackage)
+ {
+ int len = MultiByteToWideChar( CP_ACP, 0, pszPackage, -1, NULL, 0 );
+ if (!(package = HeapAlloc( GetProcessHeap(), 0, len * sizeof(SEC_WCHAR) ))) goto done;
+ MultiByteToWideChar( CP_ACP, 0, pszPackage, -1, package, len );
+ }
+ if (pAuthData)
+ {
+ id = (PSEC_WINNT_AUTH_IDENTITY_A)pAuthData;
+ if (id->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
+ {
+ if (!(authdata = HeapAlloc( GetProcessHeap(), 0, sizeof(SEC_WINNT_AUTH_IDENTITY_W) ))) goto done;
+ if (id->UserLength)
+ {
+ len_user = MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, NULL, 0 );
+ if (!(user = HeapAlloc( GetProcessHeap(), 0, len_user * sizeof(SEC_WCHAR) ))) goto done;
+ MultiByteToWideChar( CP_ACP, 0, (char *)id->User, id->UserLength, user, len_user );
+ }
+ if (id->DomainLength)
+ {
+ len_domain = MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, NULL, 0 );
+ if (!(domain = HeapAlloc( GetProcessHeap(), 0, len_domain * sizeof(SEC_WCHAR) ))) goto done;
+ MultiByteToWideChar( CP_ACP, 0, (char *)id->Domain, id->DomainLength, domain, len_domain );
+ }
+ if (id->PasswordLength)
+ {
+ len_passwd = MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, NULL, 0 );
+ if (!(passwd = HeapAlloc( GetProcessHeap(), 0, len_passwd * sizeof(SEC_WCHAR) ))) goto done;
+ MultiByteToWideChar( CP_ACP, 0, (char *)id->Password, id->PasswordLength, passwd, len_passwd );
+ }
+ authdata->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
+ authdata->User = user;
+ authdata->UserLength = len_user;
+ authdata->Domain = domain;
+ authdata->DomainLength = len_domain;
+ authdata->Password = passwd;
+ authdata->PasswordLength = len_passwd;
+ }
+ else authdata = (PSEC_WINNT_AUTH_IDENTITY_W)id;
+ }
+
+ ret = kerberos_AcquireCredentialsHandleW( principal, package, fCredentialUse, pLogonID, authdata, pGetKeyFn,
+ pGetKeyArgument, phCredential, ptsExpiry );
+
+done:
+ if (authdata != (SEC_WINNT_AUTH_IDENTITY_W *)id) HeapFree( GetProcessHeap(), 0, authdata );
+ HeapFree( GetProcessHeap(), 0, package );
+ HeapFree( GetProcessHeap(), 0, principal );
+ HeapFree( GetProcessHeap(), 0, user );
+ HeapFree( GetProcessHeap(), 0, domain );
+ HeapFree( GetProcessHeap(), 0, passwd );
+ return ret;
}
/***********************************************************************
--
2.11.0
More information about the wine-patches
mailing list