[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