initial commit for kerberos support
authordodo040 <dorian.ducournau@gmail.com>
Thu, 11 May 2017 16:51:45 +0000 (18:51 +0200)
committerArmin Novak <armin.novak@thincast.com>
Mon, 13 Nov 2017 15:20:55 +0000 (16:20 +0100)
27 files changed:
CMakeLists.txt
ci/cmake-preloads/config-debian-squeeze.txt
ci/cmake-preloads/config-linux-all.txt
ci/cmake-preloads/config-ubuntu-1204.txt
cmake/FindGSSAPI.cmake [new file with mode: 0644]
cmake/FindKRB5.cmake [deleted file]
config.h.in
libfreerdp/core/CMakeLists.txt
libfreerdp/core/gateway/ntlm.c
libfreerdp/core/nla.c
libfreerdp/core/nla.h
libfreerdp/core/transport.c
winpr/include/winpr/sspi.h
winpr/libwinpr/sspi/CMakeLists.txt
winpr/libwinpr/sspi/Kerberos/kerberos.c [new file with mode: 0644]
winpr/libwinpr/sspi/Kerberos/kerberos.h [new file with mode: 0644]
winpr/libwinpr/sspi/NTLM/ntlm.c
winpr/libwinpr/sspi/Negotiate/negotiate.c
winpr/libwinpr/sspi/Negotiate/negotiate.h
winpr/libwinpr/sspi/sspi.h
winpr/libwinpr/sspi/sspi_gss.c [new file with mode: 0644]
winpr/libwinpr/sspi/sspi_gss.h [new file with mode: 0644]
winpr/libwinpr/sspi/sspi_winpr.c
winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c
winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c
winpr/libwinpr/sspi/test/TestNTLM.c
winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c

index ed064a1..444d6a8 100644 (file)
@@ -674,14 +674,14 @@ set(OPENH264_FEATURE_TYPE "OPTIONAL")
 set(OPENH264_FEATURE_PURPOSE "codec")
 set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library")
 
-set(KRB5_FEATURE_TYPE "OPTIONAL")
-set(KRB5_FEATURE_PURPOSE "auth")
-set(KRB5_FEATURE_DESCRIPTION "add kerberos support")
-
 set(GSM_FEATURE_TYPE "OPTIONAL")
 set(GSM_FEATURE_PURPOSE "codec")
 set(GSM_FEATURE_DESCRIPTION "GSM audio codec library")
 
+set(GSSAPI_FEATURE_TYPE "OPTIONAL")
+set(GSSAPI_FEATURE_PURPOSE "auth")
+set(GSSAPI_FEATURE_DESCRIPTION "add kerberos support")
+
 if(WIN32)
        set(X11_FEATURE_TYPE "DISABLED")
        set(WAYLAND_FEATURE_TYPE "DISABLED")
@@ -775,7 +775,22 @@ find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DE
 find_feature(x264 ${X264_FEATURE_TYPE} ${X264_FEATURE_PURPOSE} ${X264_FEATURE_DESCRIPTION})
 find_feature(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION})
 find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION})
-find_feature(KRB5 ${KRB5_FEATURE_TYPE} ${KRB5_FEATURE_PURPOSE} ${KRB5_FEATURE_DESCRIPTION})
+
+find_feature(GSSAPI ${GSSAPI_FEATURE_TYPE} ${GSSAPI_FEATURE_PURPOSE} ${GSSAPI_FEATURE_DESCRIPTION})
+
+if ( (WITH_GSSAPI) AND (NOT GSS_FOUND))
+       message(WARNING "-DWITH_GSSAPI=ON is set, but not GSSAPI implementation was found, disabling")
+else()
+       if(GSS_FLAVOUR STREQUAL "MIT") 
+               message(STATUS "MIT Kerberos suppport")
+               add_definitions("-DWITH_GSSAPI -DWITH_GSSAPI_MIT")
+       elseif(GSS_FLAVOUR STREQUAL "HEIMDAL")
+               message(STATUS "Heimdal Kerberos support")
+               add_definitions("-DWITH_GSSAPI -DWITH_GSSAPI_HEIMDAL")
+       else()
+               message(STATUS "Kerberos version not detected")
+       endif()
+endif()
 
 if(TARGET_ARCH MATCHES "x86|x64")
        if (NOT APPLE)
index 483a52a..1129f9a 100644 (file)
@@ -2,7 +2,7 @@ message("PRELOADING cache")
 set (WITH_MANPAGES OFF CACHE BOOL "man pages")
 set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
 set (WITH_CUPS OFF CACHE BOOL "CUPS printing")
-set (WITH_KRB5 ON CACHE BOOL "Kerberos support")
+set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
 set (WITH_ALSA OFF CACHE BOOL "alsa audio")
 set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support")
 set (WITH_XV OFF CACHE BOOL "xvideo support")
index dd3221b..8db0bcd 100644 (file)
@@ -7,7 +7,7 @@ set (WITH_PULSE ON CACHE BOOL "pulse")
 set (WITH_CHANNELS ON CACHE BOOL "channels")
 set (BUILTIN_CHANNELS ON CACHE BOOL "static channels")
 set (WITH_CUPS ON CACHE BOOL "cups")
-set (WITH_KRB5 ON CACHE BOOL "Kerberos support")
+set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
 set (WITH_PCSC ON CACHE BOOL "PCSC")
 set (WITH_JPEG ON CACHE BOOL "jepg")
 set (WITH_GSTREAMER_0_10 ON CACHE BOOL "gstreamer")
index 483a52a..1129f9a 100644 (file)
@@ -2,7 +2,7 @@ message("PRELOADING cache")
 set (WITH_MANPAGES OFF CACHE BOOL "man pages")
 set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type")
 set (WITH_CUPS OFF CACHE BOOL "CUPS printing")
-set (WITH_KRB5 ON CACHE BOOL "Kerberos support")
+set (WITH_GSSAPI ON CACHE BOOL "Kerberos support")
 set (WITH_ALSA OFF CACHE BOOL "alsa audio")
 set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support")
 set (WITH_XV OFF CACHE BOOL "xvideo support")
diff --git a/cmake/FindGSSAPI.cmake b/cmake/FindGSSAPI.cmake
new file mode 100644 (file)
index 0000000..9cc87e9
--- /dev/null
@@ -0,0 +1,288 @@
+# - Try to find the GSS Kerberos library
+# Once done this will define
+#
+#  GSS_ROOT_DIR - Set this variable to the root installation of GSS
+#
+# Read-Only variables:
+#  GSS_FOUND - system has the Heimdal library
+#  GSS_FLAVOUR - "MIT" or "Heimdal" if anything found.
+#  GSS_INCLUDE_DIR - the Heimdal include directory
+#  GSS_LIBRARIES - The libraries needed to use GSS
+#  GSS_LINK_DIRECTORIES - Directories to add to linker search path
+#  GSS_LINKER_FLAGS - Additional linker flags
+#  GSS_COMPILER_FLAGS - Additional compiler flags
+#  GSS_VERSION - This is set to version advertised by pkg-config or read from manifest.
+#                In case the library is found but no version info availabe it'll be set to "unknown"
+
+set(_MIT_MODNAME mit-krb5-gssapi)
+set(_HEIMDAL_MODNAME heimdal-gssapi)
+
+include(CheckIncludeFile)
+include(CheckIncludeFiles)
+include(CheckTypeSize)
+
+set(_GSS_ROOT_HINTS
+    "${GSS_ROOT_DIR}"
+    "$ENV{GSS_ROOT_DIR}"
+)
+
+# try to find library using system pkg-config if user didn't specify root dir
+if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}")
+    if(UNIX)
+        find_package(PkgConfig QUIET)
+        pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME})
+        list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}")
+    elseif(WIN32)
+        list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]")
+    endif()
+endif()
+
+if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approach.
+    find_file(_GSS_CONFIGURE_SCRIPT
+        NAMES
+            "krb5-config"
+        HINTS
+            ${_GSS_ROOT_HINTS}
+        PATH_SUFFIXES
+            bin
+        NO_CMAKE_PATH
+        NO_CMAKE_ENVIRONMENT_PATH
+    )
+
+    # if not found in user-supplied directories, maybe system knows better
+    find_file(_GSS_CONFIGURE_SCRIPT
+        NAMES
+            "krb5-config"
+        PATH_SUFFIXES
+            bin
+    )
+
+    if(_GSS_CONFIGURE_SCRIPT)
+        execute_process(
+            COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi"
+            OUTPUT_VARIABLE _GSS_CFLAGS
+            RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+        )
+        if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
+            # should also work in an odd case when multiple directories are given
+            string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS)
+            string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}")
+            string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}")
+
+            foreach(_flag ${_GSS_CFLAGS})
+                if(_flag MATCHES "^-I.*")
+                    string(REGEX REPLACE "^-I" "" _val "${_flag}")
+                    list(APPEND _GSS_INCLUDE_DIR "${_val}")
+                else()
+                    list(APPEND _GSS_COMPILER_FLAGS "${_flag}")
+                endif()
+            endforeach()
+        endif()
+
+        execute_process(
+            COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi"
+            OUTPUT_VARIABLE _GSS_LIB_FLAGS
+            RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+        )
+        if(NOT _GSS_CONFIGURE_FAILED) # 0 means success
+            # this script gives us libraries and link directories. Blah. We have to deal with it.
+            # string(STRIP "krb5support ${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
+                       string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS)
+            string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+            string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}")
+
+            foreach(_flag ${_GSS_LIB_FLAGS})
+                if(_flag MATCHES "^-l.*")
+                    string(REGEX REPLACE "^-l" "" _val "${_flag}")
+                    list(APPEND _GSS_LIBRARIES "${_val}")
+                elseif(_flag MATCHES "^-L.*")
+                    string(REGEX REPLACE "^-L" "" _val "${_flag}")
+                    list(APPEND _GSS_LINK_DIRECTORIES "${_val}")
+                else()
+                    list(APPEND _GSS_LINKER_FLAGS "${_flag}")
+                endif()
+            endforeach()
+        endif()
+
+
+        execute_process(
+            COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version"
+            OUTPUT_VARIABLE _GSS_VERSION
+            RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+        )
+
+        # older versions may not have the "--version" parameter. In this case we just don't care.
+        if(_GSS_CONFIGURE_FAILED)
+            set(_GSS_VERSION 0)
+        endif()
+
+
+        execute_process(
+            COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor"
+            OUTPUT_VARIABLE _GSS_VENDOR
+            RESULT_VARIABLE _GSS_CONFIGURE_FAILED
+        )
+
+        # older versions may not have the "--vendor" parameter. In this case we just don't care.
+        if(_GSS_CONFIGURE_FAILED)
+            set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter
+        else()
+            if(_GSS_VENDOR MATCHES ".*H|heimdal.*")
+                set(GSS_FLAVOUR "Heimdal")
+            else()
+                set(GSS_FLAVOUR "MIT")
+            endif()
+        endif()
+
+    else() # either there is no config script or we are on platform that doesn't provide one (Windows?)
+
+        find_path(_GSS_INCLUDE_DIR
+            NAMES
+                "gssapi/gssapi.h"
+            HINTS
+                ${_GSS_ROOT_HINTS}
+            PATH_SUFFIXES
+                include
+                inc
+        )
+
+        if(_GSS_INCLUDE_DIR) #jay, we've found something
+            set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}")
+            check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS)
+
+            if(_GSS_HAVE_MIT_HEADERS)
+                set(GSS_FLAVOUR "MIT")
+            else()
+                # prevent compiling the header - just check if we can include it
+                set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__")
+                check_include_file( "roken.h" _GSS_HAVE_ROKEN_H)
+
+                check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H)
+                if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H)
+                    set(GSS_FLAVOUR "Heimdal")
+                endif()
+                set(CMAKE_REQUIRED_DEFINITIONS "")
+            endif()
+        else()
+            # I'm not convinced if this is the right way but this is what autotools do at the moment
+            find_path(_GSS_INCLUDE_DIR
+                NAMES
+                    "gssapi.h"
+                HINTS
+                    ${_GSS_ROOT_HINTS}
+                PATH_SUFFIXES
+                    include
+                    inc
+            )
+
+            if(_GSS_INCLUDE_DIR)
+                set(GSS_FLAVOUR "Heimdal")
+            endif()
+        endif()
+
+        # if we have headers, check if we can link libraries
+        if(GSS_FLAVOUR)
+            set(_GSS_LIBDIR_SUFFIXES "")
+            set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS})
+            get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH)
+            list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT})
+
+            if(WIN32)
+                if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+                    list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64")
+                    if(GSS_FLAVOUR STREQUAL "MIT")
+                        set(_GSS_LIBNAME "gssapi64")
+                    else()
+                        set(_GSS_LIBNAME "libgssapi")
+                    endif()
+                else()
+                    list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386")
+                    if(GSS_FLAVOUR STREQUAL "MIT")
+                        set(_GSS_LIBNAME "gssapi32")
+                    else()
+                        set(_GSS_LIBNAME "libgssapi")
+                    endif()
+                endif()
+            else()
+                list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS
+                if(GSS_FLAVOUR STREQUAL "MIT")
+                    set(_GSS_LIBNAME "gssapi_krb5")
+                else()
+                    set(_GSS_LIBNAME "gssapi")
+                endif()
+            endif()
+
+            find_library(_GSS_LIBRARIES
+                NAMES
+                    ${_GSS_LIBNAME}
+                HINTS
+                    ${_GSS_LIBDIR_HINTS}
+                PATH_SUFFIXES
+                    ${_GSS_LIBDIR_SUFFIXES}
+            )
+
+        endif()
+
+    endif()
+else()
+    if(_GSS_PKG_${_MIT_MODNAME}_VERSION)
+        set(GSS_FLAVOUR "MIT")
+        set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION)
+    else()
+        set(GSS_FLAVOUR "Heimdal")
+        set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION)
+    endif()
+endif()
+
+set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR})
+set(GSS_LIBRARIES ${_GSS_LIBRARIES})
+set(GSS_LINK_DIRECTORIES ${_GSS_LINK_DIRECTORIES})
+set(GSS_LINKER_FLAGS ${_GSS_LINKER_FLAGS})
+set(GSS_COMPILER_FLAGS ${_GSS_COMPILER_FLAGS})
+set(GSS_VERSION ${_GSS_VERSION})
+
+if(GSS_FLAVOUR)
+
+    if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal")
+        if(CMAKE_SIZEOF_VOID_P EQUAL 8)
+            set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest")
+        else()
+            set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest")
+        endif()
+
+        if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}")
+            file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str
+                 REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$")
+
+            string(REGEX MATCH "[0-9]\\.[^\"]+"
+                   GSS_VERSION "${heimdal_version_str}")
+        endif()
+
+        if(NOT GSS_VERSION)
+            set(GSS_VERSION "Heimdal Unknown")
+        endif()
+    elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT")
+        get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE)
+        if(WIN32 AND _MIT_VERSION)
+            set(GSS_VERSION "${_MIT_VERSION}")
+        else()
+            set(GSS_VERSION "MIT Unknown")
+        endif()
+    endif()
+endif()
+
+
+include(FindPackageHandleStandardArgs)
+
+set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR)
+
+find_package_handle_standard_args(GSS
+    REQUIRED_VARS
+        ${_GSS_REQUIRED_VARS}
+    VERSION_VAR
+        GSS_VERSION
+    FAIL_MESSAGE
+        "Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR"
+)
+
+mark_as_advanced(GSS_INCLUDE_DIR GSS_LIBRARIES)
diff --git a/cmake/FindKRB5.cmake b/cmake/FindKRB5.cmake
deleted file mode 100644 (file)
index 477f50e..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-# - Try to find krb5
-# Once done this will define
-#  KRB5_FOUND - pcsc was found
-#  KRB5_INCLUDE_DIRS - pcsc include directories
-#  KRB5_LIBRARIES - libraries needed for linking
-
-include(FindPkgConfig)
-
-if(PKG_CONFIG_FOUND)
-       pkg_check_modules(PC_KRB5 QUIET libkrb5)
-endif()
-
-find_path(KRB5_INCLUDE_DIR krb5.h
-       HINTS ${PC_KRB5_INCLUDEDIR} ${PC_KRB5_INCLUDE_DIRS}
-       PATH_SUFFIXES KRB5)
-
-find_library(KRB5_LIBRARY NAMES krb5 
-       HINTS ${PC_KRB5_LIBDIR} ${PC_KRB5_LIBRARY_DIRS})
-
-include(FindPackageHandleStandardArgs)
-find_package_handle_standard_args(KRB5 DEFAULT_MSG KRB5_LIBRARY KRB5_INCLUDE_DIR)
-
-set(KRB5_LIBRARIES ${KRB5_LIBRARY})
-set(KRB5_INCLUDE_DIRS ${KRB5_INCLUDE_DIR})
-
-mark_as_advanced(KRB5_INCLUDE_DIR KRB5_LIBRARY)
-
-
index a61d7b3..f1a2a06 100644 (file)
@@ -61,7 +61,6 @@
 /* Plugins */
 #cmakedefine BUILTIN_CHANNELS
 #cmakedefine WITH_RDPDR
-#cmakedefine WITH_KRB5
 
 /* Debug */
 #cmakedefine WITH_DEBUG_CERTIFICATE
index e73946e..4c69828 100644 (file)
@@ -21,7 +21,6 @@ set(MODULE_PREFIX "FREERDP_CORE")
 freerdp_definition_add(-DEXT_PATH="${FREERDP_EXTENSION_PATH}")
 
 freerdp_include_directory_add(${OPENSSL_INCLUDE_DIR})
-freerdp_include_directory_add(${KRB5_INCLUDE_DIRS})
 
 set(${MODULE_PREFIX}_GATEWAY_DIR "gateway")
 
@@ -141,10 +140,6 @@ endif()
 
 freerdp_library_add(${OPENSSL_LIBRARIES})
 
-if (WITH_KRB5)
-       freerdp_library_add(${KRB5_LIBRARIES})
-endif(WITH_KRB5)
-
 if(BUILD_TESTING)
        add_subdirectory(test)
 endif()
index 18dfc10..e52a0d2 100644 (file)
@@ -49,7 +49,7 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
 
        sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password);
 
-       status = ntlm->table->QuerySecurityPackageInfo(NTLMSP_NAME, &ntlm->pPackageInfo);
+       status = ntlm->table->QuerySecurityPackageInfo(NTLMSSP_NAME, &ntlm->pPackageInfo);
 
        if (status != SEC_E_OK)
        {
@@ -60,7 +60,7 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char*
 
        ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken;
 
-       status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME,
+       status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSSP_NAME,
                                                       SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL,
                                                       &ntlm->credentials, &ntlm->expiration);
 
index 47958ea..e945c74 100644 (file)
@@ -1,11 +1,12 @@
 /**
- * WinPR: Windows Portable Runtime
+ * FreeRDP: A Remote Desktop Protocol Implementation
  * Network Level Authentication (NLA)
  *
  * Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  * Copyright 2015 Thincast Technologies GmbH
  * Copyright 2015 DI (FH) Martin Haimberger <martin.haimberger@thincast.com>
  * Copyright 2016 Martin Fleisz <martin.fleisz@thincast.com>
+ * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -94,7 +95,7 @@
  *
  */
 
-#define NLA_PKG_NAME   NEGOSSP_NAME
+#define NLA_PKG_NAME   NEGO_SSP_NAME
 
 #define TERMSRV_SPN_PREFIX     "TERMSRV/"
 
@@ -116,6 +117,7 @@ void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity)
 {
        if (identity)
        {
+               /* Password authentication */
                if (identity->User)
                {
                        memset(identity->User, 0, identity->UserLength * 2);
@@ -139,7 +141,7 @@ void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity)
 }
 
 /**
- * Initialize NTLMSSP authentication module (client).
+ * Initialize NTLM/Kerberos SSP authentication module (client).
  * @param credssp
  */
 
@@ -159,7 +161,7 @@ static int nla_client_init(rdpNla* nla)
                settings->DisableCredentialsDelegation = TRUE;
 
        if ((!settings->Password) || (!settings->Username)
-           || (!strlen(settings->Username)))
+           || (!strlen(settings->Password)) || (!strlen(settings->Username)))
        {
                PromptPassword = TRUE;
        }
@@ -220,8 +222,11 @@ static int nla_client_init(rdpNla* nla)
                nla->identity = NULL;
        }
        else
-               sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain,
-                                    settings->Password);
+       {
+               if (sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain,
+                                        settings->Password) < 0)
+                       return -1;
+       }
 
 #ifndef _WIN32
        {
@@ -262,7 +267,7 @@ static int nla_client_init(rdpNla* nla)
 
        if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength))
        {
-               WLog_ERR(TAG, "Failed to allocate sspic secBuffer");
+               WLog_ERR(TAG, "Failed to allocate sspi secBuffer");
                return -1;
        }
 
@@ -282,6 +287,17 @@ static int nla_client_init(rdpNla* nla)
        nla->ServicePrincipalName = spn;
 #endif
        nla->table = InitSecurityInterfaceEx(0);
+#ifdef WITH_GSSAPI /* KERBEROS SSP */
+       nla->status = nla->table->QuerySecurityPackageInfo(KERBEROS_SSP_NAME, &nla->pPackageInfo);
+
+       if (nla->status != SEC_E_OK)
+       {
+               WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08"PRIX32"]",
+                        GetSecurityStatusString(nla->status), nla->status);
+               return -1;
+       }
+
+#else /* NTLM SSP */
        nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo);
 
        if (nla->status != SEC_E_OK)
@@ -291,7 +307,11 @@ static int nla_client_init(rdpNla* nla)
                return -1;
        }
 
+#endif
        nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
+       nla->packageName = nla->pPackageInfo->Name;
+       WLog_DBG(TAG, "%s %"PRIu32" : packageName=%s ; cbMaxToken=%d", __FUNCTION__, __LINE__,
+                nla->packageName, nla->cbMaxToken);
        nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME,
                      SECPKG_CRED_OUTBOUND, NULL, nla->identity, NULL, NULL, &nla->credentials,
                      &nla->expiration);
@@ -345,6 +365,32 @@ int nla_client_begin(rdpNla* nla)
        WLog_VRB(TAG, " InitializeSecurityContext status %s [0x%08"PRIX32"]",
                 GetSecurityStatusString(nla->status), nla->status);
 
+       /* Handle kerberos context initialization failure.
+        * After kerberos failed initialize NTLM context */
+       if (nla->status == SEC_E_NO_CREDENTIALS)
+       {
+               nla->status = nla->table->InitializeSecurityContext(&nla->credentials,
+                             NULL, nla->ServicePrincipalName, nla->fContextReq, 0,
+                             SECURITY_NATIVE_DREP, NULL, 0, &nla->context,
+                             &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration);
+               WLog_VRB(TAG, " InitializeSecurityContext status %s [0x%08"PRIX32"]",
+                        GetSecurityStatusString(nla->status), nla->status);
+
+               if (nla->status)
+               {
+                       SECURITY_STATUS status = nla->table->QuerySecurityPackageInfo(NTLM_SSP_NAME, &nla->pPackageInfo);
+
+                       if (status != SEC_E_OK)
+                       {
+                               WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08"PRIX32"]",
+                                        GetSecurityStatusString(nla->status), status);
+                               return -1;
+                       }
+
+                       nla->cbMaxToken = nla->pPackageInfo->cbMaxToken;
+                       nla->packageName = nla->pPackageInfo->Name;
+               }
+       }
        if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
        {
                if (nla->table->CompleteAuthToken)
@@ -719,28 +765,32 @@ static int nla_server_authenticate(rdpNla* nla)
 
                if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
                {
-                       freerdp_peer *peer = nla->instance->context->peer;
+                       freerdp_peerpeer = nla->instance->context->peer;
 
                        if (peer->ComputeNtlmHash)
                        {
                                SECURITY_STATUS status;
+                               status = nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB,
+                                        peer->ComputeNtlmHash, 0);
 
-                               status = nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB, peer->ComputeNtlmHash, 0);
                                if (status != SEC_E_OK)
                                {
-                                       WLog_ERR(TAG, "SetContextAttributesA(hash cb) status %s [0x%08"PRIX32"]", GetSecurityStatusString(status), status);
+                                       WLog_ERR(TAG, "SetContextAttributesA(hash cb) status %s [0x%08"PRIX32"]",
+                                                GetSecurityStatusString(status), status);
                                }
 
-                               status = nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB_DATA, peer, 0);
+                               status = nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_HASH_CB_DATA, peer,
+                                        0);
                                if (status != SEC_E_OK)
                                {
-                                       WLog_ERR(TAG, "SetContextAttributesA(hash cb data) status %s [0x%08"PRIX32"]", GetSecurityStatusString(status), status);
+                                       WLog_ERR(TAG, "SetContextAttributesA(hash cb data) status %s [0x%08"PRIX32"]",
+                                                GetSecurityStatusString(status), status);
                                }
                        }
                        else if (nla->SamFile)
                        {
                                nla->table->SetContextAttributes(&nla->context, SECPKG_ATTR_AUTH_NTLM_SAM_FILE, nla->SamFile,
-                                               strlen(nla->SamFile) + 1);
+                                                                strlen(nla->SamFile) + 1);
                        }
 
                        if (nla->table->CompleteAuthToken)
@@ -781,7 +831,7 @@ static int nla_server_authenticate(rdpNla* nla)
 
                        nla->havePubKeyAuth = TRUE;
                        nla->status = nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES,
-                                      &nla->ContextSizes);
+                                     &nla->ContextSizes);
 
                        if (nla->status != SEC_E_OK)
                        {
@@ -815,21 +865,21 @@ static int nla_server_authenticate(rdpNla* nla)
                         */
                        switch (GetLastError())
                        {
-                               case ERROR_PASSWORD_MUST_CHANGE:
-                                       nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
-                                       break;
+                           case ERROR_PASSWORD_MUST_CHANGE:
+                                   nla->errorCode = STATUS_PASSWORD_MUST_CHANGE;
+                                   break;
 
-                               case ERROR_PASSWORD_EXPIRED:
-                                       nla->errorCode = STATUS_PASSWORD_EXPIRED;
-                                       break;
+                           case ERROR_PASSWORD_EXPIRED:
+                                   nla->errorCode = STATUS_PASSWORD_EXPIRED;
+                                   break;
 
-                               case ERROR_ACCOUNT_DISABLED:
-                                       nla->errorCode = STATUS_ACCOUNT_DISABLED;
-                                       break;
+                           case ERROR_ACCOUNT_DISABLED:
+                                   nla->errorCode = STATUS_ACCOUNT_DISABLED;
+                                   break;
 
-                               default:
-                                       nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError());
-                                       break;
+                           default:
+                                   nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError());
+                                   break;
                        }
 
                        WLog_ERR(TAG, "AcceptSecurityContext status %s [0x%08"PRIX32"]",
@@ -962,18 +1012,29 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
        int public_key_length;
        public_key_length = nla->PublicKey.cbBuffer;
 
-       if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, nla->ContextSizes.cbSecurityTrailer + public_key_length))
+       if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, public_key_length + nla->ContextSizes.cbSecurityTrailer))
                return SEC_E_INSUFFICIENT_MEMORY;
 
-       Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
-       Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
-       Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
-       Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */
-       Buffers[1].cbBuffer = public_key_length;
-       Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer;
-       CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer);
+       if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0)
+       {
+               Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */
+               Buffers[0].cbBuffer = public_key_length;
+               Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
+               CopyMemory(Buffers[0].pvBuffer, nla->PublicKey.pvBuffer, Buffers[0].cbBuffer);
+       }
+       else if ((strcmp(nla->packageName, NEGO_SSP_NAME) != 0) ||
+                (strcmp(nla->packageName, NTLM_SSP_NAME) != 0))
+       {
+               Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
+               Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
+               Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer;
+               Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */
+               Buffers[1].cbBuffer = public_key_length;
+               Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer;
+               CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer);
+       }
 
-       if (nla->server)
+       if ((strcmp(nla->packageName, KERBEROS_SSP_NAME) != 0) && nla->server)
        {
                /* server echos the public key +1 */
                ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer);
@@ -991,14 +1052,6 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla)
                return status;
        }
 
-       if (Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer)
-       {
-               /* EncryptMessage may not use all the signature space, so we need to shrink the excess */
-               MoveMemory(((BYTE*)nla->pubKeyAuth.pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer,
-                          Buffers[1].cbBuffer);
-               nla->pubKeyAuth.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer;
-       }
-
        return status;
 }
 
@@ -1022,23 +1075,43 @@ SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
                return SEC_E_INVALID_TOKEN;
        }
 
+       if ((nla->PublicKey.cbBuffer + nla->ContextSizes.cbSecurityTrailer) != nla->pubKeyAuth.cbBuffer)
+       {
+               WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %"PRIu32"", (int) nla->pubKeyAuth.cbBuffer);
+               return SEC_E_INVALID_TOKEN;
+       }
+
        length = nla->pubKeyAuth.cbBuffer;
        buffer = (BYTE*) malloc(length);
 
        if (!buffer)
                return SEC_E_INSUFFICIENT_MEMORY;
 
-       CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
-       public_key_length = nla->PublicKey.cbBuffer;
-       Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
-       Buffers[0].cbBuffer = signature_length;
-       Buffers[0].pvBuffer = buffer;
-       Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */
-       Buffers[1].cbBuffer = length - signature_length;
-       Buffers[1].pvBuffer = buffer + signature_length;
-       Message.cBuffers = 2;
-       Message.ulVersion = SECBUFFER_VERSION;
-       Message.pBuffers = (PSecBuffer) &Buffers;
+       if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0)
+       {
+               CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
+               Buffers[0].BufferType = SECBUFFER_DATA; /* Wrapped and encrypted TLS Public Key */
+               Buffers[0].cbBuffer = length;
+               Buffers[0].pvBuffer = buffer;
+               Message.cBuffers = 1;
+               Message.ulVersion = SECBUFFER_VERSION;
+               Message.pBuffers = (PSecBuffer) &Buffers;
+       }
+       else if ((strcmp(nla->packageName, NEGO_SSP_NAME) == 0) ||
+                (strcmp(nla->packageName,  NTLM_SSP_NAME) == 0))
+       {
+               CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length);
+               public_key_length = nla->PublicKey.cbBuffer;
+               Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
+               Buffers[0].cbBuffer = signature_length;
+               Buffers[0].pvBuffer = buffer;
+               Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */
+               Buffers[1].cbBuffer = length - signature_length;
+               Buffers[1].pvBuffer = buffer + signature_length;
+               Message.cBuffers = 2;
+               Message.ulVersion = SECBUFFER_VERSION;
+               Message.pBuffers = (PSecBuffer) &Buffers;
+       }
        status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
 
        if (status != SEC_E_OK)
@@ -1049,8 +1122,17 @@ SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla)
                return status;
        }
 
-       public_key1 = (BYTE*) nla->PublicKey.pvBuffer;
-       public_key2 = (BYTE*) Buffers[1].pvBuffer;
+       if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0)
+       {
+               public_key1 = public_key2 = (BYTE*) nla->pubKeyAuth.pvBuffer ;
+               public_key_length = length;
+       }
+       else if ((strcmp(nla->packageName, NEGO_SSP_NAME) == 0) ||
+                (strcmp(nla->packageName, NTLM_SSP_NAME) == 0))
+       {
+               public_key1 = (BYTE*) nla->PublicKey.pvBuffer;
+               public_key2 = (BYTE*) Buffers[1].pvBuffer;
+       }
 
        if (!nla->server)
        {
@@ -1087,6 +1169,15 @@ int nla_sizeof_ts_password_creds(rdpNla* nla)
        return length;
 }
 
+static int nla_sizeof_ts_credentials(rdpNla* nla)
+{
+       int size = 0;
+       size += ber_sizeof_integer(1);
+       size += ber_sizeof_contextual_tag(ber_sizeof_integer(1));
+       size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla)));
+       return size;
+}
+
 BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s)
 {
        int length;
@@ -1207,15 +1298,6 @@ static int nla_write_ts_password_creds(rdpNla* nla, wStream* s)
        return size;
 }
 
-static int nla_sizeof_ts_credentials(rdpNla* nla)
-{
-       int size = 0;
-       size += ber_sizeof_integer(1);
-       size += ber_sizeof_contextual_tag(ber_sizeof_integer(1));
-       size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla)));
-       return size;
-}
-
 static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
 {
        wStream* s;
@@ -1234,9 +1316,9 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials)
        ret = ber_read_sequence_tag(s, &length) &&
              /* [0] credType (INTEGER) */
              ber_read_contextual_tag(s, 0, &length, TRUE) &&
-             ber_read_integer(s, NULL) &&
-             /* [1] credentials (OCTET STRING) */
-             ber_read_contextual_tag(s, 1, &length, TRUE) &&
+             ber_read_integer(s, NULL);
+       /* [1] credentials (OCTET STRING) */
+       ret += ber_read_contextual_tag(s, 1, &length, TRUE) &&
              ber_read_octet_string_tag(s, &ts_password_creds_length) &&
              nla_read_ts_password_creds(nla, s);
        Stream_Free(s, FALSE);
@@ -1276,6 +1358,7 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
 
        if (nla->identity)
        {
+               /* TSPasswordCreds */
                DomainLength = nla->identity->DomainLength;
                UserLength = nla->identity->UserLength;
                PasswordLength = nla->identity->PasswordLength;
@@ -1283,6 +1366,7 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
 
        if (nla->settings->DisableCredentialsDelegation && nla->identity)
        {
+               /* TSPasswordCreds */
                nla->identity->DomainLength = 0;
                nla->identity->UserLength = 0;
                nla->identity->PasswordLength = 0;
@@ -1309,6 +1393,7 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla)
 
        if (nla->settings->DisableCredentialsDelegation)
        {
+               /* TSPasswordCreds */
                nla->identity->DomainLength = DomainLength;
                nla->identity->UserLength = UserLength;
                nla->identity->PasswordLength = PasswordLength;
@@ -1328,20 +1413,34 @@ static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla)
                return SEC_E_INSUFFICIENT_MEMORY;
 
        if (!sspi_SecBufferAlloc(&nla->authInfo,
-                                nla->ContextSizes.cbSecurityTrailer + nla->tsCredentials.cbBuffer))
+                                nla->tsCredentials.cbBuffer + nla->ContextSizes.cbSecurityTrailer))
                return SEC_E_INSUFFICIENT_MEMORY;
 
-       Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
-       Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
-       Buffers[0].pvBuffer = nla->authInfo.pvBuffer;
-       ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer);
-       Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
-       Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer;
-       Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer];
-       CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer);
-       Message.cBuffers = 2;
-       Message.ulVersion = SECBUFFER_VERSION;
-       Message.pBuffers = (PSecBuffer) &Buffers;
+       if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0)
+       {
+               Buffers[0].BufferType = SECBUFFER_DATA; /* TSCredentials */
+               Buffers[0].cbBuffer = nla->tsCredentials.cbBuffer;
+               Buffers[0].pvBuffer = nla->authInfo.pvBuffer;
+               CopyMemory(Buffers[0].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[0].cbBuffer);
+               Message.cBuffers = 1;
+               Message.ulVersion = SECBUFFER_VERSION;
+               Message.pBuffers = (PSecBuffer) &Buffers;
+       }
+       else if ((strcmp(nla->packageName, NEGO_SSP_NAME) == 0) ||
+                (strcmp(nla->packageName, NTLM_SSP_NAME) == 0))
+       {
+               Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
+               Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
+               Buffers[0].pvBuffer = nla->authInfo.pvBuffer;
+               MoveMemory(Buffers[0].pvBuffer, nla->authInfo.pvBuffer, Buffers[0].cbBuffer);
+               Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
+               Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer;
+               Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer];
+               CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer);
+               Message.cBuffers = 2;
+               Message.ulVersion = SECBUFFER_VERSION;
+               Message.pBuffers = (PSecBuffer) &Buffers;
+       }
        status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++);
 
        if (status != SEC_E_OK)
@@ -1351,14 +1450,6 @@ static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla)
                return status;
        }
 
-       if (Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer)
-       {
-               /* EncryptMessage may not use all the signature space, so we need to shrink the excess */
-               MoveMemory(((BYTE*)nla->authInfo.pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer,
-                          Buffers[1].cbBuffer);
-               nla->authInfo.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer;
-       }
-
        return SEC_E_OK;
 }
 
@@ -1370,8 +1461,6 @@ static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla)
        SecBuffer Buffers[2];
        SecBufferDesc Message;
        SECURITY_STATUS status;
-       Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
-       Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
 
        if (nla->authInfo.cbBuffer < 1)
        {
@@ -1385,14 +1474,30 @@ static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla)
        if (!buffer)
                return SEC_E_INSUFFICIENT_MEMORY;
 
-       CopyMemory(buffer, nla->authInfo.pvBuffer, length);
-       Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
-       Buffers[0].pvBuffer = buffer;
-       Buffers[1].cbBuffer = length - nla->ContextSizes.cbSecurityTrailer;
-       Buffers[1].pvBuffer = &buffer[nla->ContextSizes.cbSecurityTrailer];
-       Message.cBuffers = 2;
-       Message.ulVersion = SECBUFFER_VERSION;
-       Message.pBuffers = (PSecBuffer) &Buffers;
+       if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0)
+       {
+               CopyMemory(buffer, nla->authInfo.pvBuffer, length);
+               Buffers[0].BufferType = SECBUFFER_DATA; /* Wrapped and encrypted TSCredentials */
+               Buffers[0].cbBuffer = length;
+               Buffers[0].pvBuffer = buffer;
+               Message.cBuffers = 1;
+               Message.ulVersion = SECBUFFER_VERSION;
+               Message.pBuffers = (PSecBuffer) &Buffers;
+       }
+       else if ((strcmp(nla->packageName,  NEGO_SSP_NAME) == 0) ||
+                (strcmp(nla->packageName, NTLM_SSP_NAME) == 0))
+       {
+               CopyMemory(buffer, nla->authInfo.pvBuffer, length);
+               Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */
+               Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer;
+               Buffers[0].pvBuffer = buffer;
+               Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */
+               Buffers[1].cbBuffer = length - nla->ContextSizes.cbSecurityTrailer;
+               Buffers[1].pvBuffer = &buffer[ Buffers[0].cbBuffer ];
+               Message.cBuffers = 2;
+               Message.ulVersion = SECBUFFER_VERSION;
+               Message.pBuffers = (PSecBuffer) &Buffers;
+       }
        status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP);
 
        if (status != SEC_E_OK)
index 5039fb4..2f72b64 100644 (file)
@@ -1,6 +1,6 @@
 /**
  * FreeRDP: A Remote Desktop Protocol Implementation
- * Credential Security Support Provider (CredSSP)
+ * Network Level Authentication (NLA)
  *
  * Copyright 2010-2012 Marc-Andre Moreau <marcandre.moreau@gmail.com>
  *
@@ -60,6 +60,7 @@ struct rdp_nla
        rdpSettings* settings;
        rdpTransport* transport;
        UINT32 cbMaxToken;
+       SEC_CHAR* packageName;
        UINT32 version;
        UINT32 errorCode;
        ULONG fContextReq;
index fb99952..4fdceb9 100644 (file)
@@ -59,7 +59,7 @@
 
 static void* transport_client_thread(void* arg);
 
-#ifdef WITH_KRB5
+#ifdef WITH_GSSAPI
 
 #include <krb5.h>
 #include <winpr/library.h>
@@ -150,7 +150,7 @@ out:
        krb5_free_context(context);
        return ret;
 }
-#endif /* WITH_KRB5 */
+#endif /* WITH_GSSAPI */
 
 static void transport_ssl_cb(SSL* ssl, int where, int ret)
 {
@@ -174,7 +174,7 @@ static void transport_ssl_cb(SSL* ssl, int where, int ret)
                                        if (transport->NlaMode)
                                        {
                                                UINT32 kret = 0;
-#ifdef WITH_KRB5
+#ifdef WITH_GSSAPI
 
                                                if ((strlen(transport->settings->Domain) != 0) &&
                                                    (strncmp(transport->settings->Domain, ".", 1) != 0))
@@ -184,7 +184,7 @@ static void transport_ssl_cb(SSL* ssl, int where, int ret)
                                                                                            transport->settings->Password);
                                                }
                                                else
-#endif /* WITH_KRB5 */
+#endif /* WITH_GSSAPI */
                                                        kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
 
                                                if (!freerdp_get_last_error(transport->context))
index 53a033a..df2d502 100644 (file)
@@ -92,8 +92,9 @@ typedef SecPkgInfoW* PSecPkgInfoW;
 #define PSecPkgInfo PSecPkgInfoA
 #endif
 
-#define NTLMSP_NAME    _T("NTLM")
-#define NEGOSSP_NAME   _T("Negotiate")
+#define NTLMSSP_NAME           _T("NTLM")
+#define KERBEROS_SSP_NAME      _T("Kerberos")
+#define NEGOSSP_NAME           _T("Negotiate")
 
 #endif
 
@@ -589,6 +590,7 @@ typedef SecPkgCredentials_NamesW* PSecPkgCredentials_NamesW;
 
 typedef struct _SEC_WINNT_AUTH_IDENTITY_W
 {
+       /* TSPasswordCreds */
        UINT16* User;
        UINT32 UserLength;
        UINT16* Domain;
@@ -600,6 +602,7 @@ typedef struct _SEC_WINNT_AUTH_IDENTITY_W
 
 typedef struct _SEC_WINNT_AUTH_IDENTITY_A
 {
+       /* TSPasswordCreds */
        BYTE* User;
        UINT32 UserLength;
        BYTE* Domain;
@@ -611,6 +614,7 @@ typedef struct _SEC_WINNT_AUTH_IDENTITY_A
 
 struct _SEC_WINNT_AUTH_IDENTITY
 {
+       /* TSPasswordCreds */
        UINT16* User;
        UINT32 UserLength;
        UINT16* Domain;
index efcad47..0949ae3 100644 (file)
@@ -27,6 +27,10 @@ set(${MODULE_PREFIX}_NTLM_SRCS
        NTLM/ntlm.c
        NTLM/ntlm.h)
 
+set(${MODULE_PREFIX}_KERBEROS_SRCS
+       Kerberos/kerberos.c
+       Kerberos/kerberos.h)
+
 set(${MODULE_PREFIX}_NEGOTIATE_SRCS
        Negotiate/negotiate.c
        Negotiate/negotiate.h)
@@ -38,17 +42,20 @@ set(${MODULE_PREFIX}_SCHANNEL_SRCS
        Schannel/schannel.h)
 
 set(${MODULE_PREFIX}_CREDSSP_SRCS
-       CredSSP/credssp.c)
+       CredSSP/credssp.c
+       CredSSP/credssp.h)
 
 set(${MODULE_PREFIX}_SRCS
-       ${${MODULE_PREFIX}_CREDSSP_SRCS}
        sspi_winpr.c
        sspi_winpr.h
        sspi_export.c
+       sspi_gss.c
+       sspi_gss.h
        sspi.c
        sspi.h)
 
-winpr_module_add(${${MODULE_PREFIX}_NTLM_SRCS}
+winpr_module_add(${${MODULE_PREFIX}_CREDSSP_SRCS}
+       ${${MODULE_PREFIX}_NTLM_SRCS}
        ${${MODULE_PREFIX}_KERBEROS_SRCS}
        ${${MODULE_PREFIX}_NEGOTIATE_SRCS}
        ${${MODULE_PREFIX}_SCHANNEL_SRCS}
@@ -64,6 +71,10 @@ if(MBEDTLS_FOUND)
        winpr_library_add(${MBEDTLS_LIBRARIES})
 endif()
 
+if(GSS_FOUND)
+       winpr_library_add(${GSS_LIBRARIES})
+endif()
+
 if(WIN32)
        winpr_library_add(ws2_32)
 endif()
diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.c b/winpr/libwinpr/sspi/Kerberos/kerberos.c
new file mode 100644 (file)
index 0000000..194af7f
--- /dev/null
@@ -0,0 +1,734 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Kerberos Auth Protocol
+ *
+ * Copyright 2015 ANSSI, Author Thomas Calderon
+ * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <errno.h>
+#include <fcntl.h>
+
+#include <winpr/crt.h>
+#include <winpr/sspi.h>
+#include <winpr/print.h>
+#include <winpr/sysinfo.h>
+#include <winpr/registry.h>
+
+#include "kerberos.h"
+
+#include "../sspi.h"
+#include "../../log.h"
+#define TAG WINPR_TAG("sspi.Kerberos")
+
+char* KRB_PACKAGE_NAME = "Kerberos";
+
+static sspi_gss_OID_desc g_SSPI_GSS_C_SPNEGO_KRB5 = { 9, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x02" };
+sspi_gss_OID SSPI_GSS_C_SPNEGO_KRB5 = &g_SSPI_GSS_C_SPNEGO_KRB5;
+
+KRB_CONTEXT* kerberos_ContextNew()
+{
+       KRB_CONTEXT* context;
+       context = (KRB_CONTEXT*) calloc(1, sizeof(KRB_CONTEXT));
+
+       if (!context)
+               return NULL;
+
+       context->minor_status = 0;
+       context->major_status = 0;
+       context->gss_ctx = SSPI_GSS_C_NO_CONTEXT;
+       context->cred = SSPI_GSS_C_NO_CREDENTIAL;
+       return context;
+}
+
+void kerberos_ContextFree(KRB_CONTEXT* context)
+{
+       UINT32 minor_status;
+
+       if (!context)
+               return;
+
+       if (context->target_name)
+       {
+               sspi_gss_release_name(&minor_status, &context->target_name);
+               context->target_name = NULL;
+       }
+
+       if (context->gss_ctx)
+       {
+               sspi_gss_delete_sec_context(&minor_status, &context->gss_ctx, SSPI_GSS_C_NO_BUFFER);
+               context->gss_ctx = SSPI_GSS_C_NO_CONTEXT;
+       }
+
+       free(context);
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal,
+        SEC_WCHAR* pszPackage,
+        ULONG fCredentialUse, void* pvLogonID, void* pAuthData,
+        SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument,
+        PCredHandle phCredential, PTimeStamp ptsExpiry)
+{
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal,
+        SEC_CHAR* pszPackage,
+        ULONG fCredentialUse, void* pvLogonID, void* pAuthData,
+        SEC_GET_KEY_FN pGetKeyFn, void* pvGetKeyArgument,
+        PCredHandle phCredential, PTimeStamp ptsExpiry)
+{
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_FreeCredentialsHandle(PCredHandle phCredential)
+{
+       SSPI_CREDENTIALS* credentials;
+
+       if (!phCredential)
+               return SEC_E_INVALID_HANDLE;
+
+       credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
+
+       if (!credentials)
+               return SEC_E_INVALID_HANDLE;
+
+       sspi_CredentialsFree(credentials);
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesW(PCredHandle phCredential,
+        ULONG ulAttribute, void* pBuffer)
+{
+       if (ulAttribute == SECPKG_CRED_ATTR_NAMES)
+       {
+               return SEC_E_OK;
+       }
+
+       return SEC_E_UNSUPPORTED_FUNCTION;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_QueryCredentialsAttributesA(PCredHandle phCredential,
+        ULONG ulAttribute, void* pBuffer)
+{
+       return kerberos_QueryCredentialsAttributesW(phCredential, ulAttribute, pBuffer);
+}
+
+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)
+{
+       return SEC_E_UNSUPPORTED_FUNCTION;
+}
+
+int kerberos_SetContextServicePrincipalNameA(KRB_CONTEXT* context, SEC_CHAR* ServicePrincipalName)
+{
+       char* p;
+       UINT32 major_status;
+       UINT32 minor_status;
+       char* gss_name = NULL;
+       sspi_gss_buffer_desc name_buffer;
+
+       if (!ServicePrincipalName)
+       {
+               context->target_name = NULL;
+               return 1;
+       }
+
+       /* GSSAPI expects a SPN of type <service>@FQDN, let's construct it */
+       gss_name = _strdup(ServicePrincipalName);
+
+       if (!gss_name)
+               return -1;
+
+       p = strchr(gss_name, '/');
+
+       if (p)
+               *p = '@';
+
+       name_buffer.value = gss_name;
+       name_buffer.length = strlen(gss_name) + 1;
+       major_status = sspi_gss_import_name(&minor_status, &name_buffer,
+                                           SSPI_GSS_C_NT_HOSTBASED_SERVICE, &(context->target_name));
+       free(gss_name);
+
+       if (SSPI_GSS_ERROR(major_status))
+       {
+               WLog_ERR(TAG, "error: gss_import_name failed");
+               return -1;
+       }
+
+       return 1;
+}
+
+#ifdef WITH_GSSAPI
+krb5_error_code KRB5_CALLCONV
+acquire_cred(krb5_context ctx, krb5_principal client, const char* password)
+{
+       krb5_error_code ret;
+       krb5_creds creds;
+       krb5_deltat starttime = 0;
+       krb5_get_init_creds_opt* options = NULL;
+       krb5_ccache ccache;
+       krb5_init_creds_context init_ctx = NULL;
+
+       /* Get default ccache */
+       if ((ret = krb5_cc_default(ctx, &ccache)))
+       {
+               WLog_ERR(TAG, "error while getting default ccache");
+               goto cleanup;
+       }
+
+       if ((ret = krb5_cc_initialize(ctx, ccache, client)))
+       {
+               WLog_ERR(TAG, "error: could not initialize ccache");
+               goto cleanup;
+       }
+
+       memset(&creds, 0, sizeof(creds));
+
+       if ((ret = krb5_get_init_creds_opt_alloc(ctx, &options)))
+       {
+               WLog_ERR(TAG, "error while allocating options");
+               goto cleanup;
+       }
+
+       /* Set default options */
+       krb5_get_init_creds_opt_set_forwardable(options, 0);
+       krb5_get_init_creds_opt_set_proxiable(options, 0);
+#ifdef WITH_GSSAPI_MIT
+
+       /* for MIT we specify ccache output using an option */
+       if ((ret = krb5_get_init_creds_opt_set_out_ccache(ctx, options, ccache)))
+       {
+               WLog_ERR(TAG, "error while setting ccache output");
+               goto cleanup;
+       }
+
+#endif
+
+       if ((ret = krb5_init_creds_init(ctx, client, NULL, NULL, starttime, options, &init_ctx)))
+       {
+               WLog_ERR(TAG, "error krb5_init_creds_init failed");
+               goto cleanup;
+       }
+
+       if ((ret = krb5_init_creds_set_password(ctx, init_ctx, password)))
+       {
+               WLog_ERR(TAG, "error krb5_init_creds_set_password failed");
+               goto cleanup;
+       }
+
+       /* Get credentials */
+       if ((ret = krb5_init_creds_get(ctx, init_ctx)))
+       {
+               WLog_ERR(TAG, "error while getting credentials");
+               goto cleanup;
+       }
+
+       /* Retrieve credentials */
+       if ((ret = krb5_init_creds_get_creds(ctx, init_ctx, &creds)))
+       {
+               WLog_ERR(TAG, "error while retrieving credentials");
+               goto cleanup;
+       }
+
+#ifdef WITH_GSSAPI_HEIMDAL
+
+       /* For Heimdal, we use this function to store credentials */
+       if ((ret = krb5_init_creds_store(ctx, init_ctx, ccache)))
+       {
+               WLog_ERR(TAG, "error while storing credentials");
+               goto cleanup;
+       }
+
+#endif
+cleanup:
+       krb5_free_cred_contents(ctx, &creds);
+
+       if (options)
+               krb5_get_init_creds_opt_free(ctx, options);
+
+       if (init_ctx)
+               krb5_init_creds_free(ctx, init_ctx);
+
+       if (ccache)
+               krb5_cc_close(ctx, ccache);
+
+       return ret;
+}
+
+int init_creds(LPCWSTR username, size_t username_len, LPCWSTR password, size_t password_len)
+{
+       krb5_error_code ret = 0;
+       krb5_context ctx = NULL;
+       krb5_principal principal = NULL;
+       char* krb_name = NULL;
+       char* lusername = NULL;
+       char* lrealm = NULL;
+       char* lpassword = NULL;
+       size_t krb_name_len = 0;
+       size_t lrealm_len = 0;
+       size_t lusername_len = 0;
+       int status = 0;
+       status = ConvertFromUnicode(CP_UTF8, 0, username,
+                                   username_len, &lusername, 0, NULL, NULL);
+
+       if (status <= 0)
+       {
+               WLog_ERR(TAG, "Failed to convert username");
+               goto cleanup;
+       }
+
+       status = ConvertFromUnicode(CP_UTF8, 0, password,
+                                   password_len, &lpassword, 0, NULL, NULL);
+
+       if (status <= 0)
+       {
+               WLog_ERR(TAG, "Failed to convert password");
+               goto cleanup;
+       }
+
+       /* Could call krb5_init_secure_context, but it disallows user overrides */
+       ret = krb5_init_context(&ctx);
+
+       if (ret)
+       {
+               WLog_ERR(TAG, "error: while initializing Kerberos 5 library");
+               goto cleanup;
+       }
+
+       ret = krb5_get_default_realm(ctx, &lrealm);
+
+       if (ret)
+       {
+               WLog_WARN(TAG, "could not get Kerberos default realm");
+               goto cleanup;
+       }
+
+       lrealm_len = strlen(lrealm);
+       lusername_len = strlen(lusername);
+       krb_name_len = lusername_len + lrealm_len + 1; // +1 for '@'
+       krb_name = calloc(krb_name_len + 1, sizeof(char));
+
+       if (!krb_name)
+       {
+               WLog_ERR(TAG, "could not allocate memory for string rep of principal\n");
+               ret = -1;
+               goto cleanup;
+       }
+
+       /* Set buffer */
+       _snprintf(krb_name, krb_name_len + 1, "%s@%s", lusername, lrealm);
+#ifdef WITH_DEBUG_NLA
+       WLog_DBG(TAG, "copied string is %s\n", krb_name);
+#endif
+       ret = krb5_parse_name(ctx, krb_name, &principal);
+
+       if (ret)
+       {
+               WLog_ERR(TAG, "could not convert %s to principal", krb_name);
+               goto cleanup;
+       }
+
+       ret = acquire_cred(ctx, principal, lpassword);
+
+       if (ret)
+       {
+               WLog_ERR(TAG, "Kerberos credentials not found and could not be acquired");
+               goto cleanup;
+       }
+
+cleanup:
+       free(lusername);
+       free(lpassword);
+
+       if (krb_name)
+               free(krb_name);
+
+       if (lrealm)
+               krb5_free_default_realm(ctx, lrealm);
+
+       if (principal)
+               krb5_free_principal(ctx, principal);
+
+       if (ctx)
+               krb5_free_context(ctx);
+
+       return ret;
+}
+#endif
+
+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)
+{
+       KRB_CONTEXT* context;
+       SSPI_CREDENTIALS* credentials;
+       PSecBuffer input_buffer = NULL;
+       PSecBuffer output_buffer = NULL;
+       sspi_gss_buffer_desc input_tok;
+       sspi_gss_buffer_desc output_tok;
+       sspi_gss_OID actual_mech;
+       sspi_gss_OID desired_mech;
+       UINT32 actual_services;
+       input_tok.length = 0;
+       output_tok.length = 0;
+       desired_mech = SSPI_GSS_C_SPNEGO_KRB5;
+       context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
+
+       if (!context)
+       {
+               context = kerberos_ContextNew();
+
+               if (!context)
+                       return SEC_E_INSUFFICIENT_MEMORY;
+
+               credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential);
+               context->credentials = credentials;
+
+               if (kerberos_SetContextServicePrincipalNameA(context, pszTargetName) < 0)
+                       return SEC_E_INTERNAL_ERROR;
+
+               sspi_SecureHandleSetLowerPointer(phNewContext, context);
+               sspi_SecureHandleSetUpperPointer(phNewContext, (void*) KRB_PACKAGE_NAME);
+       }
+
+       if (!pInput)
+       {
+#if defined(WITH_GSSAPI)
+               context->major_status = sspi_gss_init_sec_context(&(context->minor_status),
+                                       context->cred, &(context->gss_ctx), context->target_name,
+                                       desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG,
+                                       SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS,
+                                       &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time));
+
+               if (SSPI_GSS_ERROR(context->major_status))
+               {
+                       /* GSSAPI failed because we do not have credentials */
+                       if (context->major_status & SSPI_GSS_S_NO_CRED)
+                       {
+                               /* Then let's try to acquire credentials using login and password,
+                                * and only those two, means not with a smartcard.
+                                * If we use smartcard-logon, the credentials have already
+                                * been acquired by pkinit process. If not, returned error previously.
+                                */
+                               if (init_creds(context->credentials->identity.User,
+                                              context->credentials->identity.UserLength,
+                                              context->credentials->identity.Password,
+                                              context->credentials->identity.PasswordLength))
+                                       return SEC_E_NO_CREDENTIALS;
+                               else
+                                       WLog_INFO(TAG, "Authenticated to Kerberos v5 via login/password");
+
+                               /* retry GSSAPI call */
+                               context->major_status = sspi_gss_init_sec_context(&(context->minor_status),
+                                                       context->cred, &(context->gss_ctx), context->target_name,
+                                                       desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG,
+                                                       SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS,
+                                                       &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time));
+
+                               if (SSPI_GSS_ERROR(context->major_status))
+                               {
+                                       /* We can't use Kerberos */
+                                       return SEC_E_INTERNAL_ERROR;
+                               }
+                       }
+               }
+
+#endif
+
+               if (context->major_status & SSPI_GSS_S_CONTINUE_NEEDED)
+               {
+                       if (output_tok.length != 0)
+                       {
+                               if (!pOutput)
+                                       return SEC_E_INVALID_TOKEN;
+
+                               if (pOutput->cBuffers < 1)
+                                       return SEC_E_INVALID_TOKEN;
+
+                               output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
+
+                               if (!output_buffer)
+                                       return SEC_E_INVALID_TOKEN;
+
+                               if (output_buffer->cbBuffer < 1)
+                                       return SEC_E_INVALID_TOKEN;
+
+                               CopyMemory(output_buffer->pvBuffer, output_tok.value, output_tok.length);
+                               output_buffer->cbBuffer = output_tok.length;
+                               sspi_gss_release_buffer(&(context->minor_status), &output_tok);
+                               return SEC_I_CONTINUE_NEEDED;
+                       }
+               }
+       }
+       else
+       {
+               input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN);
+
+               if (!input_buffer)
+                       return SEC_E_INVALID_TOKEN;
+
+               if (input_buffer->cbBuffer < 1)
+                       return SEC_E_INVALID_TOKEN;
+
+               input_tok.value = input_buffer->pvBuffer;
+               input_tok.length = input_buffer->cbBuffer;
+               context->major_status = sspi_gss_init_sec_context(&(context->minor_status),
+                                       context->cred, &(context->gss_ctx), context->target_name,
+                                       desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG,
+                                       SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS,
+                                       &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time));
+
+               if (SSPI_GSS_ERROR(context->major_status))
+                       return SEC_E_INTERNAL_ERROR;
+
+               if (output_tok.length == 0)
+               {
+                       /* Free output_buffer to detect second call in NLA */
+                       output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN);
+                       sspi_SecBufferFree(output_buffer);
+                       return SEC_E_OK;
+               }
+               else
+               {
+                       return SEC_E_INTERNAL_ERROR;
+               }
+       }
+
+       return SEC_E_INTERNAL_ERROR;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_DeleteSecurityContext(PCtxtHandle phContext)
+{
+       KRB_CONTEXT* context;
+       context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
+
+       if (!context)
+               return SEC_E_INVALID_HANDLE;
+
+       kerberos_ContextFree(context);
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
+        void* pBuffer)
+{
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
+        void* pBuffer)
+{
+       if (!phContext)
+               return SEC_E_INVALID_HANDLE;
+
+       if (!pBuffer)
+               return SEC_E_INSUFFICIENT_MEMORY;
+
+       if (ulAttribute == SECPKG_ATTR_SIZES)
+       {
+               SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer;
+               /* The MaxTokenSize by default is 12,000 bytes. This has been the default value
+                * since Windows 2000 SP2 and still remains in Windows 7 and Windows 2008 R2.
+                *  For Windows Server 2012, the default value of the MaxTokenSize registry
+                *  entry is 48,000 bytes.*/
+               ContextSizes->cbMaxToken = KERBEROS_SecPkgInfoA.cbMaxToken;
+               ContextSizes->cbMaxSignature = 0; /* means verify not supported */
+               ContextSizes->cbBlockSize = 0; /* padding not used */
+               ContextSizes->cbSecurityTrailer = 60; /* gss_wrap adds additional 60 bytes for encrypt message */
+               return SEC_E_OK;
+       }
+
+       return SEC_E_UNSUPPORTED_FUNCTION;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
+        PSecBufferDesc pMessage, ULONG MessageSeqNo)
+{
+       int index;
+       int conf_state;
+       UINT32 major_status;
+       UINT32 minor_status;
+       KRB_CONTEXT* context;
+       sspi_gss_buffer_desc input;
+       sspi_gss_buffer_desc output;
+       PSecBuffer data_buffer = NULL;
+       context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
+
+       if (!context)
+               return SEC_E_INVALID_HANDLE;
+
+       for (index = 0; index < (int) pMessage->cBuffers; index++)
+       {
+               if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA)
+                       data_buffer = &pMessage->pBuffers[index];
+       }
+
+       if (!data_buffer)
+               return SEC_E_INVALID_TOKEN;
+
+       input.value = data_buffer->pvBuffer;
+       input.length = data_buffer->cbBuffer;
+       major_status = sspi_gss_wrap(&minor_status, context->gss_ctx, TRUE,
+                                    SSPI_GSS_C_QOP_DEFAULT, &input, &conf_state, &output);
+
+       if (SSPI_GSS_ERROR(major_status))
+               return SEC_E_INTERNAL_ERROR;
+
+       if (conf_state == 0)
+       {
+               WLog_ERR(TAG, "error: gss_wrap confidentiality was not applied");
+               sspi_gss_release_buffer(&minor_status, &output);
+               return SEC_E_INTERNAL_ERROR;
+       }
+
+       CopyMemory(data_buffer->pvBuffer, output.value, output.length);
+       sspi_gss_release_buffer(&minor_status, &output);
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_DecryptMessage(PCtxtHandle phContext,
+        PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
+{
+       int index;
+       int conf_state;
+       UINT32 major_status;
+       UINT32 minor_status;
+       KRB_CONTEXT* context;
+       sspi_gss_buffer_desc input_data;
+       sspi_gss_buffer_desc output;
+       PSecBuffer data_buffer_to_unwrap = NULL;
+       context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
+
+       if (!context)
+               return SEC_E_INVALID_HANDLE;
+
+       for (index = 0; index < (int) pMessage->cBuffers; index++)
+       {
+               if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA)
+                       data_buffer_to_unwrap = &pMessage->pBuffers[index];
+       }
+
+       if (!data_buffer_to_unwrap)
+               return SEC_E_INVALID_TOKEN;
+
+       /* unwrap encrypted TLS key AND its signature */
+       input_data.value = data_buffer_to_unwrap->pvBuffer;
+       input_data.length = data_buffer_to_unwrap->cbBuffer;
+       major_status = sspi_gss_unwrap(&minor_status, context->gss_ctx, &input_data, &output, &conf_state,
+                                      NULL);
+
+       if (SSPI_GSS_ERROR(major_status))
+               return SEC_E_INTERNAL_ERROR;
+
+       if (conf_state == 0)
+       {
+               WLog_ERR(TAG, "error: gss_unwrap confidentiality was not applied");
+               sspi_gss_release_buffer(&minor_status, &output);
+               return SEC_E_INTERNAL_ERROR;
+       }
+
+       CopyMemory(data_buffer_to_unwrap->pvBuffer, output.value, output.length);
+       sspi_gss_release_buffer(&minor_status, &output);
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_MakeSignature(PCtxtHandle phContext,
+        ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
+{
+       return SEC_E_OK;
+}
+
+SECURITY_STATUS SEC_ENTRY kerberos_VerifySignature(PCtxtHandle phContext,
+        PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
+{
+       return SEC_E_OK;
+}
+
+
+const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA =
+{
+       1,                      /* dwVersion */
+       NULL,                   /* EnumerateSecurityPackages */
+       kerberos_QueryCredentialsAttributesA,   /* QueryCredentialsAttributes */
+       kerberos_AcquireCredentialsHandleA,     /* AcquireCredentialsHandle */
+       kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */
+       NULL,                   /* Reserved2 */
+       kerberos_InitializeSecurityContextA,    /* InitializeSecurityContext */
+       NULL,                   /* AcceptSecurityContext */
+       NULL,                   /* CompleteAuthToken */
+       kerberos_DeleteSecurityContext,                 /* DeleteSecurityContext */
+       NULL,                   /* ApplyControlToken */
+       kerberos_QueryContextAttributesA,       /* QueryContextAttributes */
+       NULL,                   /* ImpersonateSecurityContext */
+       NULL,                   /* RevertSecurityContext */
+       kerberos_MakeSignature, /* MakeSignature */
+       kerberos_VerifySignature,       /* VerifySignature */
+       NULL,                   /* FreeContextBuffer */
+       NULL,                   /* QuerySecurityPackageInfo */
+       NULL,                   /* Reserved3 */
+       NULL,                   /* Reserved4 */
+       NULL,                   /* ExportSecurityContext */
+       NULL,                   /* ImportSecurityContext */
+       NULL,                   /* AddCredentials */
+       NULL,                   /* Reserved8 */
+       NULL,                   /* QuerySecurityContextToken */
+       kerberos_EncryptMessage,        /* EncryptMessage */
+       kerberos_DecryptMessage,        /* DecryptMessage */
+       NULL,                   /* SetContextAttributes */
+};
+
+const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW =
+{
+       1,                      /* dwVersion */
+       NULL,                   /* EnumerateSecurityPackages */
+       kerberos_QueryCredentialsAttributesW,   /* QueryCredentialsAttributes */
+       kerberos_AcquireCredentialsHandleW,     /* AcquireCredentialsHandle */
+       kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */
+       NULL,                   /* Reserved2 */
+       kerberos_InitializeSecurityContextW,    /* InitializeSecurityContext */
+       NULL,                   /* AcceptSecurityContext */
+       NULL,                   /* CompleteAuthToken */
+       kerberos_DeleteSecurityContext,                 /* DeleteSecurityContext */
+       NULL,                   /* ApplyControlToken */
+       kerberos_QueryContextAttributesW,       /* QueryContextAttributes */
+       NULL,                   /* ImpersonateSecurityContext */
+       NULL,                   /* RevertSecurityContext */
+       kerberos_MakeSignature, /* MakeSignature */
+       kerberos_VerifySignature,       /* VerifySignature */
+       NULL,                   /* FreeContextBuffer */
+       NULL,                   /* QuerySecurityPackageInfo */
+       NULL,                   /* Reserved3 */
+       NULL,                   /* Reserved4 */
+       NULL,                   /* ExportSecurityContext */
+       NULL,                   /* ImportSecurityContext */
+       NULL,                   /* AddCredentials */
+       NULL,                   /* Reserved8 */
+       NULL,                   /* QuerySecurityContextToken */
+       kerberos_EncryptMessage,        /* EncryptMessage */
+       kerberos_DecryptMessage,        /* DecryptMessage */
+       NULL,                   /* SetContextAttributes */
+};
diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.h b/winpr/libwinpr/sspi/Kerberos/kerberos.h
new file mode 100644 (file)
index 0000000..a974aff
--- /dev/null
@@ -0,0 +1,83 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Client
+ * Kerberos Auth Protocol
+ *
+ * Copyright 2015 ANSSI, Author Thomas Calderon
+ * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FREERDP_SSPI_KERBEROS_PRIVATE_H
+#define FREERDP_SSPI_KERBEROS_PRIVATE_H
+
+#include <winpr/sspi.h>
+#include <winpr/windows.h>
+
+#include "../sspi.h"
+#include "../../log.h"
+
+#ifdef WITH_GSSAPI
+#include <krb5.h>
+#include <gssapi.h>
+#endif
+
+struct _KRB_CONTEXT
+{
+       CtxtHandle context;
+       SSPI_CREDENTIALS* credentials;
+       SEC_WINNT_AUTH_IDENTITY identity;
+
+       /* GSSAPI */
+       UINT32 major_status;
+       UINT32 minor_status;
+       UINT32 actual_time;
+       sspi_gss_cred_id_t cred;
+       sspi_gss_ctx_id_t gss_ctx;
+       sspi_gss_name_t target_name;
+};
+typedef struct _KRB_CONTEXT KRB_CONTEXT;
+
+const SecPkgInfoA KERBEROS_SecPkgInfoA =
+{
+       0x000F3BBF,             /* fCapabilities */
+       1,                      /* wVersion */
+       0x0010,                 /* wRPCID */
+       0x0000BB80,             /* cbMaxToken : 48k bytes maximum for Windows Server 2012 */
+       "Kerberos",             /* Name */
+       "Kerberos Security Package" /* Comment */
+};
+
+WCHAR KERBEROS_SecPkgInfoW_Name[] = { 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', '\0' };
+
+WCHAR KERBEROS_SecPkgInfoW_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'
+};
+
+const SecPkgInfoW KERBEROS_SecPkgInfoW =
+{
+       0x000F3BBF,             /* fCapabilities */
+       1,                      /* wVersion */
+       0x0010,                 /* wRPCID */
+       0x0000BB80,             /* cbMaxToken : 48k bytes maximum for Windows Server 2012 */
+       KERBEROS_SecPkgInfoW_Name,      /* Name */
+       KERBEROS_SecPkgInfoW_Comment    /* Comment */
+};
+
+
+void krb_ContextFree(KRB_CONTEXT* context);
+
+#endif /* FREERDP_SSPI_KERBEROS_PRIVATE_H */
index 5266bc7..0dadbcf 100644 (file)
@@ -747,9 +747,10 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL
        {
                SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer;
                ContextSizes->cbMaxToken = 2010;
-               ContextSizes->cbMaxSignature = 16;
-               ContextSizes->cbBlockSize = 0;
-               ContextSizes->cbSecurityTrailer = 16;
+               ContextSizes->cbMaxSignature = 16; /* the size of expected signature is 16 bytes */
+               ContextSizes->cbBlockSize = 0; /* no padding */
+               ContextSizes->cbSecurityTrailer = 16; /* no security trailer appended in NTLM
+                                                                       contrary to Kerberos */
                return SEC_E_OK;
        }
        else if (ulAttribute == SECPKG_ATTR_AUTH_IDENTITY)
index 4829b88..315e3c7 100644 (file)
@@ -3,6 +3,7 @@
  * Negotiate Security Package
  *
  * Copyright 2011-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
 extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
 extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;
 
-char* NEGOTIATE_PACKAGE_NAME = "Negotiate";
+extern const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA;
+extern const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW;
+
+#ifdef WITH_GSSAPI
+static BOOL ErrorInitContextKerberos = FALSE;
+#else
+static BOOL ErrorInitContextKerberos = TRUE;
+#endif
+
+void negotiate_SetSubPackage(NEGOTIATE_CONTEXT* context, const char* name)
+{
+       if (strcmp(name, KERBEROS_SSP_NAME) == 0)
+       {
+               context->sspiA = (SecurityFunctionTableA*) &KERBEROS_SecurityFunctionTableA;
+               context->sspiW = (SecurityFunctionTableW*) &KERBEROS_SecurityFunctionTableW;
+               context->kerberos = TRUE;
+       }
+       else
+       {
+               context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA;
+               context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW;
+               context->kerberos = FALSE;
+       }
+
+       sspi_SecureHandleSetLowerPointer(&(context->SubContext), NULL);
+       sspi_SecureHandleSetUpperPointer(&(context->SubContext), NULL);
+}
 
 NEGOTIATE_CONTEXT* negotiate_ContextNew()
 {
        NEGOTIATE_CONTEXT* context;
-
        context = (NEGOTIATE_CONTEXT*) calloc(1, sizeof(NEGOTIATE_CONTEXT));
 
        if (!context)
@@ -46,12 +72,8 @@ NEGOTIATE_CONTEXT* negotiate_ContextNew()
 
        context->NegotiateFlags = 0;
        context->state = NEGOTIATE_STATE_INITIAL;
-
        SecInvalidateHandle(&(context->SubContext));
-
-       context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA;
-       context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW;
-
+       negotiate_SetSubPackage(context, KERBEROS_SSP_NAME);
        return context;
 }
 
@@ -60,14 +82,14 @@ void negotiate_ContextFree(NEGOTIATE_CONTEXT* context)
        free(context);
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
-                                                              SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
-                                                              PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
-                                                              PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
+SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential,
+        PCtxtHandle phContext,
+        SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
+        PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
+        PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
 {
        SECURITY_STATUS status;
        NEGOTIATE_CONTEXT* context;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!context)
@@ -78,24 +100,54 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCre
                        return SEC_E_INTERNAL_ERROR;
 
                sspi_SecureHandleSetLowerPointer(phNewContext, context);
-               sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
+               sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOSSP_NAME);
        }
 
-       status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext),
-                                                           pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
-                                                           pOutput, pfContextAttr, ptsExpiry);
+       /* if Kerberos has previously failed or WITH_GSSAPI is not defined, we use NTLM directly */
+       if (ErrorInitContextKerberos == FALSE)
+       {
+               if (!pInput)
+               {
+                       negotiate_SetSubPackage(context, KERBEROS_SSP_NAME);
+               }
+
+               status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext),
+                        pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
+                        pOutput, pfContextAttr, ptsExpiry);
+
+               if (status == SEC_E_NO_CREDENTIALS)
+               {
+                       WLog_WARN(TAG, "No Kerberos credentials. Retry with NTLM");
+                       ErrorInitContextKerberos = TRUE;
+                       context->sspiA->DeleteSecurityContext(&(context->SubContext));
+                       negotiate_ContextFree(context);
+                       return status;
+               }
+       }
+       else
+       {
+               if (!pInput)
+               {
+                       context->sspiA->DeleteSecurityContext(&(context->SubContext));
+                       negotiate_SetSubPackage(context, NTLMSSP_NAME);
+               }
+
+               status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext),
+                        pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
+                        pOutput, pfContextAttr, ptsExpiry);
+       }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
-                                                              SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
-                                                              PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
-                                                              PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
+SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential,
+        PCtxtHandle phContext,
+        SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
+        PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
+        PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
 {
        SECURITY_STATUS status;
        NEGOTIATE_CONTEXT* context;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!context)
@@ -106,23 +158,53 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCre
                        return SEC_E_INTERNAL_ERROR;
 
                sspi_SecureHandleSetLowerPointer(phNewContext, context);
-               sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
+               sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOSSP_NAME);
        }
 
-       status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext),
-                                                           pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
-                                                           pOutput, pfContextAttr, ptsExpiry);
+       /* if Kerberos has previously failed or WITH_GSSAPI is not defined, we use NTLM directly */
+       if (ErrorInitContextKerberos == FALSE)
+       {
+               if (!pInput)
+               {
+                       negotiate_SetSubPackage(context, KERBEROS_SSP_NAME);
+               }
+
+               status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext),
+                        pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
+                        pOutput, pfContextAttr, ptsExpiry);
+
+               if (status == SEC_E_NO_CREDENTIALS)
+               {
+                       WLog_WARN(TAG, "No Kerberos credentials. Retry with NTLM");
+                       ErrorInitContextKerberos = TRUE;
+                       context->sspiA->DeleteSecurityContext(&(context->SubContext));
+                       negotiate_ContextFree(context);
+                       return status;
+               }
+       }
+       else
+       {
+               if (!pInput)
+               {
+                       context->sspiA->DeleteSecurityContext(&(context->SubContext));
+                       negotiate_SetSubPackage(context, NTLMSSP_NAME);
+               }
+
+               status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext),
+                        pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext),
+                        pOutput, pfContextAttr, ptsExpiry);
+       }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext,
-                                                         PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
-                                                         PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
+SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredential,
+        PCtxtHandle phContext,
+        PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
+        PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
 {
        SECURITY_STATUS status;
        NEGOTIATE_CONTEXT* context;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!context)
@@ -133,18 +215,20 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredenti
                        return SEC_E_INTERNAL_ERROR;
 
                sspi_SecureHandleSetLowerPointer(phNewContext, context);
-               sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME);
+               sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOSSP_NAME);
        }
 
+       negotiate_SetSubPackage(context, NTLMSSP_NAME); /* server-side Kerberos not yet implemented */
        status = context->sspiA->AcceptSecurityContext(phCredential, &(context->SubContext),
-                                                      pInput, fContextReq, TargetDataRep, &(context->SubContext),
-                                                      pOutput, pfContextAttr, ptsTimeStamp);
+                pInput, fContextReq, TargetDataRep, &(context->SubContext),
+                pOutput, pfContextAttr, ptsTimeStamp);
 
        if (status != SEC_E_OK)
        {
                WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
+
        return status;
 }
 
@@ -152,7 +236,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_CompleteAuthToken(PCtxtHandle phContext, PSe
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_OK;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!context)
@@ -168,7 +251,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_OK;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!context)
@@ -178,7 +260,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext)
                status = context->sspiW->DeleteSecurityContext(&(context->SubContext));
 
        negotiate_ContextFree(context);
-
        return status;
 }
 
@@ -186,7 +267,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_ImpersonateSecurityContext(PCtxtHandle phCon
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_OK;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!phContext)
@@ -202,7 +282,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_OK;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!phContext)
@@ -214,11 +293,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext)
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
+SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext,
+        ULONG ulAttribute, void* pBuffer)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_OK;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!phContext)
@@ -233,11 +312,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContex
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
+SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext,
+        ULONG ulAttribute, void* pBuffer)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_OK;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!phContext)
@@ -252,11 +331,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContex
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
+SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
+        void* pBuffer, ULONG cbBuffer)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_OK;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!phContext)
@@ -266,16 +345,17 @@ SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext,
                return SEC_E_INSUFFICIENT_MEMORY;
 
        if (context->sspiW->SetContextAttributesW)
-               status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer, cbBuffer);
+               status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer,
+                        cbBuffer);
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
+SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
+        void* pBuffer, ULONG cbBuffer)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_OK;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (!phContext)
@@ -285,21 +365,23 @@ SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext,
                return SEC_E_INSUFFICIENT_MEMORY;
 
        if (context->sspiA->SetContextAttributesA)
-               status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer, cbBuffer);
+               status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer,
+                        cbBuffer);
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage,
-                                                             ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
-                                                             void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
+SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal,
+        SEC_WCHAR* pszPackage,
+        ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
+        void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
 {
        SSPI_CREDENTIALS* credentials;
        SEC_WINNT_AUTH_IDENTITY* identity;
 
        if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
-                       (fCredentialUse != SECPKG_CRED_INBOUND) &&
-                       (fCredentialUse != SECPKG_CRED_BOTH))
+           (fCredentialUse != SECPKG_CRED_INBOUND) &&
+           (fCredentialUse != SECPKG_CRED_BOTH))
        {
                return SEC_E_INVALID_PARAMETER;
        }
@@ -312,28 +394,27 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrin
        credentials->fCredentialUse = fCredentialUse;
        credentials->pGetKeyFn = pGetKeyFn;
        credentials->pvGetKeyArgument = pvGetKeyArgument;
-
        identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
 
        if (identity)
                sspi_CopyAuthIdentity(&(credentials->identity), identity);
 
        sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
-       sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME);
-
+       sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOSSP_NAME);
        return SEC_E_OK;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
-                                                             ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
-                                                             void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
+SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal,
+        SEC_CHAR* pszPackage,
+        ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
+        void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
 {
        SSPI_CREDENTIALS* credentials;
        SEC_WINNT_AUTH_IDENTITY* identity;
 
        if ((fCredentialUse != SECPKG_CRED_OUTBOUND) &&
-                       (fCredentialUse != SECPKG_CRED_INBOUND) &&
-                       (fCredentialUse != SECPKG_CRED_BOTH))
+           (fCredentialUse != SECPKG_CRED_INBOUND) &&
+           (fCredentialUse != SECPKG_CRED_BOTH))
        {
                return SEC_E_INVALID_PARAMETER;
        }
@@ -346,24 +427,24 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrinc
        credentials->fCredentialUse = fCredentialUse;
        credentials->pGetKeyFn = pGetKeyFn;
        credentials->pvGetKeyArgument = pvGetKeyArgument;
-
        identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData;
 
        if (identity)
                sspi_CopyAuthIdentity(&(credentials->identity), identity);
 
        sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials);
-       sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME);
-
+       sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOSSP_NAME);
        return SEC_E_OK;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
+SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential,
+        ULONG ulAttribute, void* pBuffer)
 {
        return SEC_E_UNSUPPORTED_FUNCTION;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
+SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential,
+        ULONG ulAttribute, void* pBuffer)
 {
        return SEC_E_UNSUPPORTED_FUNCTION;
 }
@@ -385,11 +466,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredenti
        return SEC_E_OK;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
+SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
+        PSecBufferDesc pMessage, ULONG MessageSeqNo)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (context->sspiW->EncryptMessage)
@@ -398,11 +479,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
+SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage,
+        ULONG MessageSeqNo, ULONG* pfQOP)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (context->sspiW->DecryptMessage)
@@ -411,11 +492,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBu
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
+SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
+        PSecBufferDesc pMessage, ULONG MessageSeqNo)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (context->sspiW->MakeSignature)
@@ -424,11 +505,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG f
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP)
+SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage,
+        ULONG MessageSeqNo, ULONG* pfQOP)
 {
        NEGOTIATE_CONTEXT* context;
        SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION;
-
        context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
 
        if (context->sspiW->VerifySignature)
@@ -511,13 +592,13 @@ const SecPkgInfoA NEGOTIATE_SecPkgInfoA =
        "Microsoft Package Negotiator" /* Comment */
 };
 
-WCHAR NEGOTIATE_SecPkgInfoW_Name[] = { 'N','e','g','o','t','i','a','t','e','\0' };
+WCHAR NEGOTIATE_SecPkgInfoW_Name[] = { 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', '\0' };
 
 WCHAR NEGOTIATE_SecPkgInfoW_Comment[] =
 {
-       'M','i','c','r','o','s','o','f','t',' ',
-       'P','a','c','k','a','g','e',' ',
-       'N','e','g','o','t','i','a','t','o','r','\0'
+       'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', ' ',
+       'P', 'a', 'c', 'k', 'a', 'g', 'e', ' ',
+       'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'o', 'r', '\0'
 };
 
 const SecPkgInfoW NEGOTIATE_SecPkgInfoW =
index fe6375e..ac50e96 100644 (file)
@@ -44,6 +44,7 @@ struct _NEGOTIATE_CONTEXT
 
        CtxtHandle SubContext;
 
+       BOOL kerberos;
        SecurityFunctionTableA* sspiA;
        SecurityFunctionTableW* sspiW;
 };
index 430efd1..2a73ad1 100644 (file)
@@ -85,6 +85,7 @@ enum SecurityFunctionTableIndex
 
 BOOL IsSecurityStatusError(SECURITY_STATUS status);
 
+#include "sspi_gss.h"
 #include "sspi_winpr.h"
 
 #endif /* WINPR_SSPI_PRIVATE_H */
diff --git a/winpr/libwinpr/sspi/sspi_gss.c b/winpr/libwinpr/sspi/sspi_gss.c
new file mode 100644 (file)
index 0000000..d2a5ec2
--- /dev/null
@@ -0,0 +1,666 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Generic Security Service Application Program Interface (GSSAPI)
+ *
+ * Copyright 2015 ANSSI, Author Thomas Calderon
+ * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifdef HAVE_CONFIG_H
+#include "config.h"
+#endif
+
+#include <winpr/crt.h>
+#include <winpr/library.h>
+
+#include "sspi_gss.h"
+
+#include "../../log.h"
+#define TAG WINPR_TAG("sspi.gss")
+
+int sspi_GssApiInit();
+
+GSSAPI_FUNCTION_TABLE g_GssApi;
+static BOOL g_Initialized = FALSE;
+
+#define GSSAPI_STUB_CALL(_name, ...) \
+       if (!g_Initialized) \
+               sspi_GssApiInit(); \
+       if (!g_GssApi.gss_ ## _name) \
+               return 0; \
+       return g_GssApi.gss_ ## _name ( __VA_ARGS__ )
+
+/**
+ * SSPI GSSAPI OIDs
+ */
+
+static sspi_gss_OID_desc g_SSPI_GSS_C_NT_USER_NAME =           { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x01" };
+static sspi_gss_OID_desc g_SSPI_GSS_C_NT_MACHINE_UID_NAME =    { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x02" };
+static sspi_gss_OID_desc g_SSPI_GSS_C_NT_STRING_UID_NAME =     { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x03" };
+static sspi_gss_OID_desc g_SSPI_GSS_C_NT_HOSTBASED_SERVICE_X = { 6, (void*) "\x2b\x06\x01\x05\x06\x02" };
+static sspi_gss_OID_desc g_SSPI_GSS_C_NT_HOSTBASED_SERVICE =   { 10, (void*) "\x2a\x86\x48\x86\xf7\x12\x01\x02\x01\x04" };
+static sspi_gss_OID_desc g_SSPI_GSS_C_NT_ANONYMOUS =           { 6, (void*) "\x2b\x06\01\x05\x06\x03" };
+static sspi_gss_OID_desc g_SSPI_GSS_C_NT_EXPORT_NAME =         { 6, (void*) "\x2b\x06\x01\x05\x06\x04" };
+
+sspi_gss_OID SSPI_GSS_C_NT_USER_NAME = &g_SSPI_GSS_C_NT_USER_NAME;
+sspi_gss_OID SSPI_GSS_C_NT_MACHINE_UID_NAME = &g_SSPI_GSS_C_NT_MACHINE_UID_NAME;
+sspi_gss_OID SSPI_GSS_C_NT_STRING_UID_NAME = &g_SSPI_GSS_C_NT_STRING_UID_NAME;
+sspi_gss_OID SSPI_GSS_C_NT_HOSTBASED_SERVICE_X = &g_SSPI_GSS_C_NT_HOSTBASED_SERVICE_X;
+sspi_gss_OID SSPI_GSS_C_NT_HOSTBASED_SERVICE = &g_SSPI_GSS_C_NT_HOSTBASED_SERVICE;
+sspi_gss_OID SSPI_GSS_C_NT_ANONYMOUS = &g_SSPI_GSS_C_NT_ANONYMOUS;
+sspi_gss_OID SSPI_GSS_C_NT_EXPORT_NAME = &g_SSPI_GSS_C_NT_EXPORT_NAME;
+
+/**
+ * SSPI GSSAPI Wrapper Stubs
+ */
+
+UINT32 SSPI_GSSAPI sspi_gss_acquire_cred(
+    UINT32* minor_status,
+    sspi_gss_name_t desired_name,
+    UINT32 time_req,
+    sspi_gss_OID_set desired_mechs,
+    sspi_gss_cred_usage_t cred_usage,
+    sspi_gss_cred_id_t* output_cred_handle,
+    sspi_gss_OID_set* actual_mechs,
+    UINT32* time_rec)
+{
+       GSSAPI_STUB_CALL(acquire_cred, minor_status, desired_name, time_req,
+                        desired_mechs, cred_usage, output_cred_handle, actual_mechs, time_rec);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_release_cred(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t* cred_handle)
+{
+       GSSAPI_STUB_CALL(release_cred, minor_status, cred_handle);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_init_sec_context(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t claimant_cred_handle,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_name_t target_name,
+    sspi_gss_OID mech_type,
+    UINT32 req_flags,
+    UINT32 time_req,
+    sspi_gss_channel_bindings_t input_chan_bindings,
+    sspi_gss_buffer_t input_token,
+    sspi_gss_OID* actual_mech_type,
+    sspi_gss_buffer_t output_token,
+    UINT32* ret_flags,
+    UINT32* time_rec)
+{
+       GSSAPI_STUB_CALL(init_sec_context, minor_status, claimant_cred_handle, context_handle,
+                        target_name, mech_type, req_flags, time_req, input_chan_bindings,
+                        input_token, actual_mech_type, output_token, ret_flags, time_rec);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_accept_sec_context(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_cred_id_t acceptor_cred_handle,
+    sspi_gss_buffer_t input_token_buffer,
+    sspi_gss_channel_bindings_t input_chan_bindings,
+    sspi_gss_name_t* src_name,
+    sspi_gss_OID* mech_type,
+    sspi_gss_buffer_t output_token,
+    UINT32* ret_flags,
+    UINT32* time_rec,
+    sspi_gss_cred_id_t* delegated_cred_handle)
+{
+       GSSAPI_STUB_CALL(accept_sec_context, minor_status, context_handle, acceptor_cred_handle,
+                        input_token_buffer, input_chan_bindings, src_name, mech_type, output_token,
+                        ret_flags, time_rec, delegated_cred_handle);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_process_context_token(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t token_buffer)
+{
+       GSSAPI_STUB_CALL(process_context_token, minor_status, context_handle, token_buffer);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_delete_sec_context(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_buffer_t output_token)
+{
+       GSSAPI_STUB_CALL(delete_sec_context, minor_status, context_handle, output_token);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_context_time(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    UINT32* time_rec)
+{
+       GSSAPI_STUB_CALL(context_time, minor_status, context_handle, time_rec);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_get_mic(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_qop_t qop_req,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token)
+{
+       GSSAPI_STUB_CALL(get_mic, minor_status, context_handle, qop_req, message_buffer, message_token);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_verify_mic(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token,
+    sspi_gss_qop_t* qop_state)
+{
+       GSSAPI_STUB_CALL(verify_mic, minor_status, context_handle, message_buffer, message_token,
+                        qop_state);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_wrap(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    sspi_gss_qop_t qop_req,
+    sspi_gss_buffer_t input_message_buffer,
+    int* conf_state,
+    sspi_gss_buffer_t output_message_buffer)
+{
+       GSSAPI_STUB_CALL(wrap, minor_status, context_handle, conf_req_flag,
+                        qop_req, input_message_buffer, conf_state, output_message_buffer);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_unwrap(
+    UINT32* minor_status,
+    const sspi_gss_ctx_id_t context_handle,
+    const sspi_gss_buffer_t input_message_buffer,
+    sspi_gss_buffer_t output_message_buffer,
+    int* conf_state,
+    sspi_gss_qop_t* qop_state)
+{
+       GSSAPI_STUB_CALL(unwrap, minor_status, context_handle, input_message_buffer,
+                        output_message_buffer, conf_state, qop_state);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_display_status(
+    UINT32* minor_status,
+    UINT32 status_value,
+    int status_type,
+    sspi_gss_OID mech_type,
+    UINT32* message_context,
+    sspi_gss_buffer_t status_string)
+{
+       GSSAPI_STUB_CALL(display_status, minor_status, status_value, status_type,
+                        mech_type, message_context, status_string);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_indicate_mechs(
+    UINT32* minor_status,
+    sspi_gss_OID_set* mech_set)
+{
+       GSSAPI_STUB_CALL(indicate_mechs, minor_status, mech_set);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_compare_name(
+    UINT32* minor_status,
+    sspi_gss_name_t name1,
+    sspi_gss_name_t name2,
+    int* name_equal)
+{
+       GSSAPI_STUB_CALL(compare_name, minor_status, name1, name2, name_equal);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_display_name(
+    UINT32* minor_status,
+    sspi_gss_name_t input_name,
+    sspi_gss_buffer_t output_name_buffer,
+    sspi_gss_OID* output_name_type)
+{
+       GSSAPI_STUB_CALL(display_name, minor_status, input_name, output_name_buffer, output_name_type);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_import_name(
+    UINT32* minor_status,
+    sspi_gss_buffer_t input_name_buffer,
+    sspi_gss_OID input_name_type,
+    sspi_gss_name_t* output_name)
+{
+       GSSAPI_STUB_CALL(import_name, minor_status, input_name_buffer, input_name_type, output_name);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_release_name(
+    UINT32* minor_status,
+    sspi_gss_name_t* input_name)
+{
+       GSSAPI_STUB_CALL(release_name, minor_status, input_name);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_release_buffer(
+    UINT32* minor_status,
+    sspi_gss_buffer_t buffer)
+{
+       GSSAPI_STUB_CALL(release_buffer, minor_status, buffer);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_release_oid_set(
+    UINT32* minor_status,
+    sspi_gss_OID_set* set)
+{
+       GSSAPI_STUB_CALL(release_oid_set, minor_status, set);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_cred(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    sspi_gss_name_t* name,
+    UINT32* lifetime,
+    sspi_gss_cred_usage_t* cred_usage,
+    sspi_gss_OID_set* mechanisms)
+{
+       GSSAPI_STUB_CALL(inquire_cred, minor_status, cred_handle, name, lifetime, cred_usage, mechanisms);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_context(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_name_t* src_name,
+    sspi_gss_name_t* targ_name,
+    UINT32* lifetime_rec,
+    sspi_gss_OID* mech_type,
+    UINT32* ctx_flags,
+    int* locally_initiated,
+    int* open)
+{
+       GSSAPI_STUB_CALL(inquire_context, minor_status, context_handle, src_name, targ_name,
+                        lifetime_rec, mech_type, ctx_flags, locally_initiated, open);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_wrap_size_limit(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    sspi_gss_qop_t qop_req,
+    UINT32 req_output_size,
+    UINT32* max_input_size)
+{
+       GSSAPI_STUB_CALL(wrap_size_limit, minor_status, context_handle,
+                        conf_req_flag, qop_req, req_output_size, max_input_size);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_import_name_object(
+    UINT32* minor_status,
+    void* input_name,
+    sspi_gss_OID input_name_type,
+    sspi_gss_name_t* output_name)
+{
+       GSSAPI_STUB_CALL(import_name_object, minor_status, input_name, input_name_type, output_name);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_export_name_object(
+    UINT32* minor_status,
+    sspi_gss_name_t input_name,
+    sspi_gss_OID desired_name_type,
+    void** output_name)
+{
+       GSSAPI_STUB_CALL(export_name_object, minor_status, input_name, desired_name_type, output_name);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_add_cred(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t input_cred_handle,
+    sspi_gss_name_t desired_name,
+    sspi_gss_OID desired_mech,
+    sspi_gss_cred_usage_t cred_usage,
+    UINT32 initiator_time_req,
+    UINT32 acceptor_time_req,
+    sspi_gss_cred_id_t* output_cred_handle,
+    sspi_gss_OID_set* actual_mechs,
+    UINT32* initiator_time_rec,
+    UINT32* acceptor_time_rec)
+{
+       GSSAPI_STUB_CALL(add_cred, minor_status, input_cred_handle, desired_name, desired_mech, cred_usage,
+                        initiator_time_req, acceptor_time_req, output_cred_handle, actual_mechs, initiator_time_rec,
+                        acceptor_time_rec);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_cred_by_mech(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    sspi_gss_OID mech_type,
+    sspi_gss_name_t* name,
+    UINT32* initiator_lifetime,
+    UINT32* acceptor_lifetime,
+    sspi_gss_cred_usage_t* cred_usage)
+{
+       GSSAPI_STUB_CALL(inquire_cred_by_mech, minor_status, cred_handle, mech_type, name,
+                        initiator_lifetime, acceptor_lifetime, cred_usage);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_export_sec_context(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_buffer_t interprocess_token)
+{
+       GSSAPI_STUB_CALL(export_sec_context, minor_status, context_handle, interprocess_token);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_import_sec_context(
+    UINT32* minor_status,
+    sspi_gss_buffer_t interprocess_token,
+    sspi_gss_ctx_id_t* context_handle)
+{
+       GSSAPI_STUB_CALL(import_sec_context, minor_status, interprocess_token, context_handle);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_release_oid(
+    UINT32* minor_status,
+    sspi_gss_OID* oid)
+{
+       GSSAPI_STUB_CALL(release_oid, minor_status, oid);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_create_empty_oid_set(
+    UINT32* minor_status,
+    sspi_gss_OID_set* oid_set)
+{
+       GSSAPI_STUB_CALL(create_empty_oid_set, minor_status, oid_set);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_add_oid_set_member(
+    UINT32* minor_status,
+    sspi_gss_OID member_oid,
+    sspi_gss_OID_set* oid_set)
+{
+       GSSAPI_STUB_CALL(add_oid_set_member, minor_status, member_oid, oid_set);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_test_oid_set_member(
+    UINT32* minor_status,
+    sspi_gss_OID member,
+    sspi_gss_OID_set set,
+    int* present)
+{
+       GSSAPI_STUB_CALL(test_oid_set_member, minor_status, member, set, present);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_str_to_oid(
+    UINT32* minor_status,
+    sspi_gss_buffer_t oid_str,
+    sspi_gss_OID* oid)
+{
+       GSSAPI_STUB_CALL(str_to_oid, minor_status, oid_str, oid);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_oid_to_str(
+    UINT32* minor_status,
+    sspi_gss_OID oid,
+    sspi_gss_buffer_t oid_str)
+{
+       GSSAPI_STUB_CALL(oid_to_str, minor_status, oid, oid_str);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_names_for_mech(
+    UINT32* minor_status,
+    sspi_gss_OID mechanism,
+    sspi_gss_OID_set* name_types)
+{
+       GSSAPI_STUB_CALL(inquire_names_for_mech, minor_status, mechanism, name_types);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_mechs_for_name(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_OID_set* mech_types)
+{
+       GSSAPI_STUB_CALL(inquire_mechs_for_name, minor_status, input_name, mech_types);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_sign(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int qop_req,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token)
+{
+       GSSAPI_STUB_CALL(sign, minor_status, context_handle, qop_req, message_buffer, message_token);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_verify(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t token_buffer,
+    int* qop_state)
+{
+       GSSAPI_STUB_CALL(verify, minor_status, context_handle, message_buffer, token_buffer, qop_state);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_seal(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    int qop_req,
+    sspi_gss_buffer_t input_message_buffer,
+    int* conf_state,
+    sspi_gss_buffer_t output_message_buffer)
+{
+       GSSAPI_STUB_CALL(seal, minor_status, context_handle, conf_req_flag, qop_req,
+                        input_message_buffer, conf_state, output_message_buffer);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_unseal(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t input_message_buffer,
+    sspi_gss_buffer_t output_message_buffer,
+    int* conf_state,
+    int* qop_state)
+{
+       GSSAPI_STUB_CALL(unseal, minor_status, context_handle, input_message_buffer, output_message_buffer,
+                        conf_state, qop_state);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_export_name(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_buffer_t exported_name)
+{
+       GSSAPI_STUB_CALL(export_name, minor_status, input_name, exported_name);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_duplicate_name(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_name_t* dest_name)
+{
+       GSSAPI_STUB_CALL(duplicate_name, minor_status, input_name, dest_name);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_canonicalize_name(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    const sspi_gss_OID mech_type,
+    sspi_gss_name_t* output_name)
+{
+       GSSAPI_STUB_CALL(canonicalize_name, minor_status, input_name, mech_type, output_name);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_pseudo_random(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context,
+    int prf_key,
+    const sspi_gss_buffer_t prf_in,
+    ssize_t desired_output_len,
+    sspi_gss_buffer_t prf_out)
+{
+       GSSAPI_STUB_CALL(pseudo_random, minor_status, context, prf_key, prf_in, desired_output_len,
+                        prf_out);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_store_cred(
+    UINT32* minor_status,
+    const sspi_gss_cred_id_t input_cred_handle,
+    sspi_gss_cred_usage_t input_usage,
+    const sspi_gss_OID desired_mech,
+    UINT32 overwrite_cred,
+    UINT32 default_cred,
+    sspi_gss_OID_set* elements_stored,
+    sspi_gss_cred_usage_t* cred_usage_stored)
+{
+       GSSAPI_STUB_CALL(store_cred, minor_status, input_cred_handle, input_usage, desired_mech,
+                        overwrite_cred, default_cred, elements_stored, cred_usage_stored);
+}
+
+UINT32 SSPI_GSSAPI sspi_gss_set_neg_mechs(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    const sspi_gss_OID_set mech_set)
+{
+       GSSAPI_STUB_CALL(set_neg_mechs, minor_status, cred_handle, mech_set);
+}
+
+#ifdef WITH_GSSAPI
+
+#include <gssapi/gssapi.h>
+
+GSSAPI_FUNCTION_TABLE g_GssApiLink =
+{
+       (fn_sspi_gss_acquire_cred) gss_acquire_cred, /* gss_acquire_cred */
+       (fn_sspi_gss_release_cred) gss_release_cred, /* gss_release_cred */
+       (fn_sspi_gss_init_sec_context) gss_init_sec_context, /* gss_init_sec_context */
+       (fn_sspi_gss_accept_sec_context) gss_accept_sec_context, /* gss_accept_sec_context */
+       (fn_sspi_gss_process_context_token) gss_process_context_token, /* gss_process_context_token */
+       (fn_sspi_gss_delete_sec_context) gss_delete_sec_context, /* gss_delete_sec_context */
+       (fn_sspi_gss_context_time) gss_context_time, /* gss_context_time */
+       (fn_sspi_gss_get_mic) gss_get_mic, /* gss_get_mic */
+       (fn_sspi_gss_verify_mic) gss_verify_mic, /* gss_verify_mic */
+       (fn_sspi_gss_wrap) gss_wrap, /* gss_wrap */
+       (fn_sspi_gss_unwrap) gss_unwrap, /* gss_unwrap */
+       (fn_sspi_gss_display_status) gss_display_status, /* gss_display_status */
+       (fn_sspi_gss_indicate_mechs) gss_indicate_mechs, /* gss_indicate_mechs */
+       (fn_sspi_gss_compare_name) gss_compare_name, /* gss_compare_name */
+       (fn_sspi_gss_display_name) gss_display_name, /* gss_display_name */
+       (fn_sspi_gss_import_name) gss_import_name, /* gss_import_name */
+       (fn_sspi_gss_release_name) gss_release_name, /* gss_release_name */
+       (fn_sspi_gss_release_buffer) gss_release_buffer, /* gss_release_buffer */
+       (fn_sspi_gss_release_oid_set) gss_release_oid_set, /* gss_release_oid_set */
+       (fn_sspi_gss_inquire_cred) gss_inquire_cred, /* gss_inquire_cred */
+       (fn_sspi_gss_inquire_context) gss_inquire_context, /* gss_inquire_context */
+       (fn_sspi_gss_wrap_size_limit) gss_wrap_size_limit, /* gss_wrap_size_limit */
+#if 0
+       (fn_sspi_gss_import_name_object) gss_import_name_object, /* gss_import_name_object */
+       (fn_sspi_gss_export_name_object) gss_export_name_object, /* gss_export_name_object */
+#else
+       (fn_sspi_gss_import_name_object) NULL, /* gss_import_name_object */
+       (fn_sspi_gss_export_name_object) NULL, /* gss_export_name_object */
+#endif
+       (fn_sspi_gss_add_cred) gss_add_cred, /* gss_add_cred */
+       (fn_sspi_gss_inquire_cred_by_mech) gss_inquire_cred_by_mech, /* gss_inquire_cred_by_mech */
+       (fn_sspi_gss_export_sec_context) gss_export_sec_context, /* gss_export_sec_context */
+       (fn_sspi_gss_import_sec_context) gss_import_sec_context, /* gss_import_sec_context */
+       (fn_sspi_gss_release_oid) gss_release_oid, /* gss_release_oid */
+       (fn_sspi_gss_create_empty_oid_set) gss_create_empty_oid_set, /* gss_create_empty_oid_set */
+       (fn_sspi_gss_add_oid_set_member) gss_add_oid_set_member, /* gss_add_oid_set_member */
+       (fn_sspi_gss_test_oid_set_member) gss_test_oid_set_member, /* gss_test_oid_set_member */
+#ifdef WITH_GSSAPI_MIT
+       (fn_sspi_gss_str_to_oid) gss_str_to_oid, /* gss_str_to_oid */
+#else
+       (fn_sspi_gss_str_to_oid) NULL, /* gss_str_to_oid */
+#endif
+       (fn_sspi_gss_oid_to_str) gss_oid_to_str, /* gss_oid_to_str */
+       (fn_sspi_gss_inquire_names_for_mech) gss_inquire_names_for_mech, /* gss_inquire_names_for_mech */
+       (fn_sspi_gss_inquire_mechs_for_name) gss_inquire_mechs_for_name, /* gss_inquire_mechs_for_name */
+       (fn_sspi_gss_sign) gss_sign, /* gss_sign */
+       (fn_sspi_gss_verify) gss_verify, /* gss_verify */
+       (fn_sspi_gss_seal) gss_seal, /* gss_seal */
+       (fn_sspi_gss_unseal) gss_unseal, /* gss_unseal */
+       (fn_sspi_gss_export_name) gss_export_name, /* gss_export_name */
+       (fn_sspi_gss_duplicate_name) gss_duplicate_name, /* gss_duplicate_name */
+       (fn_sspi_gss_canonicalize_name) gss_canonicalize_name, /* gss_canonicalize_name */
+       (fn_sspi_gss_pseudo_random) gss_pseudo_random, /* gss_pseudo_random */
+       (fn_sspi_gss_store_cred) gss_store_cred, /* gss_store_cred */
+#ifdef WITH_GSSAPI_MIT
+       (fn_sspi_gss_set_neg_mechs) gss_set_neg_mechs, /* gss_set_neg_mechs */
+#else
+       (fn_sspi_gss_set_neg_mechs) NULL, /* gss_set_neg_mechs */
+#endif
+};
+
+#endif
+
+GSSAPI_FUNCTION_TABLE g_GssApi =
+{
+       NULL, /* gss_acquire_cred */
+       NULL, /* gss_release_cred */
+       NULL, /* gss_init_sec_context */
+       NULL, /* gss_accept_sec_context */
+       NULL, /* gss_process_context_token */
+       NULL, /* gss_delete_sec_context */
+       NULL, /* gss_context_time */
+       NULL, /* gss_get_mic */
+       NULL, /* gss_verify_mic */
+       NULL, /* gss_wrap */
+       NULL, /* gss_unwrap */
+       NULL, /* gss_display_status */
+       NULL, /* gss_indicate_mechs */
+       NULL, /* gss_compare_name */
+       NULL, /* gss_display_name */
+       NULL, /* gss_import_name */
+       NULL, /* gss_release_name */
+       NULL, /* gss_release_buffer */
+       NULL, /* gss_release_oid_set */
+       NULL, /* gss_inquire_cred */
+       NULL, /* gss_inquire_context */
+       NULL, /* gss_wrap_size_limit */
+       NULL, /* gss_import_name_object */
+       NULL, /* gss_export_name_object */
+       NULL, /* gss_add_cred */
+       NULL, /* gss_inquire_cred_by_mech */
+       NULL, /* gss_export_sec_context */
+       NULL, /* gss_import_sec_context */
+       NULL, /* gss_release_oid */
+       NULL, /* gss_create_empty_oid_set */
+       NULL, /* gss_add_oid_set_member */
+       NULL, /* gss_test_oid_set_member */
+       NULL, /* gss_str_to_oid */
+       NULL, /* gss_oid_to_str */
+       NULL, /* gss_inquire_names_for_mech */
+       NULL, /* gss_inquire_mechs_for_name */
+       NULL, /* gss_sign */
+       NULL, /* gss_verify */
+       NULL, /* gss_seal */
+       NULL, /* gss_unseal */
+       NULL, /* gss_export_name */
+       NULL, /* gss_duplicate_name */
+       NULL, /* gss_canonicalize_name */
+       NULL, /* gss_pseudo_random */
+       NULL, /* gss_store_cred */
+       NULL, /* gss_set_neg_mechs */
+};
+
+int sspi_GssApiInit()
+{
+       if (g_Initialized)
+               return 1;
+
+       g_Initialized = TRUE;
+#ifdef WITH_GSSAPI
+       CopyMemory(&g_GssApi, &g_GssApiLink, sizeof(GSSAPI_FUNCTION_TABLE));
+       return 1;
+#else
+       return -1;
+#endif
+}
diff --git a/winpr/libwinpr/sspi/sspi_gss.h b/winpr/libwinpr/sspi/sspi_gss.h
new file mode 100644 (file)
index 0000000..4ad9988
--- /dev/null
@@ -0,0 +1,883 @@
+/**
+ * FreeRDP: A Remote Desktop Protocol Implementation
+ * Generic Security Service Application Program Interface (GSSAPI)
+ *
+ * Copyright 2015 ANSSI, Author Thomas Calderon
+ * Copyright 2015 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef FREERDP_SSPI_GSS_PRIVATE_H
+#define FREERDP_SSPI_GSS_PRIVATE_H
+
+#include <winpr/crt.h>
+#include <winpr/sspi.h>
+
+/**
+ * The following are ABI-compatible, non-conflicting GSSAPI definitions
+ *
+ * http://tools.ietf.org/html/rfc2743
+ * http://tools.ietf.org/html/rfc2744
+ */
+
+#define SSPI_GSSAPI
+#define SSPI_GSSOID
+
+struct sspi_gss_name_struct;
+typedef struct sspi_gss_name_struct* sspi_gss_name_t;
+
+struct sspi_gss_cred_id_struct;
+typedef struct sspi_gss_cred_id_struct* sspi_gss_cred_id_t;
+
+struct sspi_gss_ctx_id_struct;
+typedef struct sspi_gss_ctx_id_struct* sspi_gss_ctx_id_t;
+
+typedef struct sspi_gss_OID_desc_struct
+{
+       UINT32 length;
+       void* elements;
+} sspi_gss_OID_desc, *sspi_gss_OID;
+
+typedef struct sspi_gss_OID_set_desc_struct
+{
+       size_t count;
+       sspi_gss_OID elements;
+} sspi_gss_OID_set_desc, *sspi_gss_OID_set;
+
+typedef struct sspi_gss_buffer_desc_struct
+{
+       size_t length;
+       void* value;
+} sspi_gss_buffer_desc, *sspi_gss_buffer_t;
+
+typedef struct sspi_gss_channel_bindings_struct
+{
+       UINT32 initiator_addrtype;
+       sspi_gss_buffer_desc initiator_address;
+       UINT32 acceptor_addrtype;
+       sspi_gss_buffer_desc acceptor_address;
+       sspi_gss_buffer_desc application_data;
+}* sspi_gss_channel_bindings_t;
+
+typedef UINT32 sspi_gss_qop_t;
+typedef int sspi_gss_cred_usage_t;
+
+#define SSPI_GSS_C_DELEG_FLAG                  1
+#define SSPI_GSS_C_MUTUAL_FLAG                 2
+#define SSPI_GSS_C_REPLAY_FLAG                 4
+#define SSPI_GSS_C_SEQUENCE_FLAG               8
+#define SSPI_GSS_C_CONF_FLAG                   16
+#define SSPI_GSS_C_INTEG_FLAG                  32
+#define SSPI_GSS_C_ANON_FLAG                   64
+#define SSPI_GSS_C_PROT_READY_FLAG             128
+#define SSPI_GSS_C_TRANS_FLAG                  256
+#define SSPI_GSS_C_DELEG_POLICY_FLAG           32768
+
+#define SSPI_GSS_C_BOTH                                0
+#define SSPI_GSS_C_INITIATE                    1
+#define SSPI_GSS_C_ACCEPT                      2
+
+#define SSPI_GSS_C_GSS_CODE                    1
+#define SSPI_GSS_C_MECH_CODE                   2
+
+#define SSPI_GSS_C_AF_UNSPEC                   0
+#define SSPI_GSS_C_AF_LOCAL                    1
+#define SSPI_GSS_C_AF_INET                     2
+#define SSPI_GSS_C_AF_IMPLINK                  3
+#define SSPI_GSS_C_AF_PUP                      4
+#define SSPI_GSS_C_AF_CHAOS                    5
+#define SSPI_GSS_C_AF_NS                       6
+#define SSPI_GSS_C_AF_NBS                      7
+#define SSPI_GSS_C_AF_ECMA                     8
+#define SSPI_GSS_C_AF_DATAKIT                  9
+#define SSPI_GSS_C_AF_CCITT                    10
+#define SSPI_GSS_C_AF_SNA                      11
+#define SSPI_GSS_C_AF_DECnet                   12
+#define SSPI_GSS_C_AF_DLI                      13
+#define SSPI_GSS_C_AF_LAT                      14
+#define SSPI_GSS_C_AF_HYLINK                   15
+#define SSPI_GSS_C_AF_APPLETALK                        16
+#define SSPI_GSS_C_AF_BSC                      17
+#define SSPI_GSS_C_AF_DSS                      18
+#define SSPI_GSS_C_AF_OSI                      19
+#define SSPI_GSS_C_AF_NETBIOS                  20
+#define SSPI_GSS_C_AF_X25                      21
+#define SSPI_GSS_C_AF_NULLADDR                 255
+
+#define SSPI_GSS_C_NO_NAME                     ((sspi_gss_name_t) 0)
+#define SSPI_GSS_C_NO_BUFFER                   ((sspi_gss_buffer_t) 0)
+#define SSPI_GSS_C_NO_OID                      ((sspi_gss_OID) 0)
+#define SSPI_GSS_C_NO_OID_SET                  ((sspi_gss_OID_set) 0)
+#define SSPI_GSS_C_NO_CONTEXT                  ((sspi_gss_ctx_id_t) 0)
+#define SSPI_GSS_C_NO_CREDENTIAL               ((sspi_gss_cred_id_t) 0)
+#define SSPI_GSS_C_NO_CHANNEL_BINDINGS         ((sspi_gss_channel_bindings_t) 0)
+#define SSPI_GSS_C_EMPTY_BUFFER                        {0, NULL}
+
+#define SSPI_GSS_C_NULL_OID                    SSPI_GSS_C_NO_OID
+#define SSPI_GSS_C_NULL_OID_SET                        SSPI_GSS_C_NO_OID_SET
+
+#define SSPI_GSS_C_QOP_DEFAULT                 0
+
+#define SSPI_GSS_C_INDEFINITE                  ((UINT32) 0xFFFFFFFF)
+
+#define SSPI_GSS_S_COMPLETE                    0
+
+#define SSPI_GSS_C_CALLING_ERROR_OFFSET                24
+#define SSPI_GSS_C_ROUTINE_ERROR_OFFSET                16
+#define SSPI_GSS_C_SUPPLEMENTARY_OFFSET                0
+#define SSPI_GSS_C_CALLING_ERROR_MASK          ((UINT32) 0377)
+#define SSPI_GSS_C_ROUTINE_ERROR_MASK          ((UINT32) 0377)
+#define SSPI_GSS_C_SUPPLEMENTARY_MASK          ((UINT32) 0177777)
+
+#define SSPI_GSS_CALLING_ERROR(_x) \
+       ((_x) & (SSPI_GSS_C_CALLING_ERROR_MASK << SSPI_GSS_C_CALLING_ERROR_OFFSET))
+#define SSPI_GSS_ROUTINE_ERROR(_x) \
+       ((_x) & (SSPI_GSS_C_ROUTINE_ERROR_MASK << SSPI_GSS_C_ROUTINE_ERROR_OFFSET))
+#define SSPI_GSS_SUPPLEMENTARY_INFO(_x) \
+       ((_x) & (SSPI_GSS_C_SUPPLEMENTARY_MASK << SSPI_GSS_C_SUPPLEMENTARY_OFFSET))
+#define SSPI_GSS_ERROR(_x) \
+       ((_x) & ((SSPI_GSS_C_CALLING_ERROR_MASK << SSPI_GSS_C_CALLING_ERROR_OFFSET) | \
+                (SSPI_GSS_C_ROUTINE_ERROR_MASK << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)))
+
+#define SSPI_GSS_S_CALL_INACCESSIBLE_READ      (((UINT32) 1) << SSPI_GSS_C_CALLING_ERROR_OFFSET)
+#define SSPI_GSS_S_CALL_INACCESSIBLE_WRITE     (((UINT32) 2) << SSPI_GSS_C_CALLING_ERROR_OFFSET)
+#define SSPI_GSS_S_CALL_BAD_STRUCTURE          (((UINT32) 3) << SSPI_GSS_C_CALLING_ERROR_OFFSET)
+
+#define SSPI_GSS_S_BAD_MECH                    (((UINT32) 1) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_BAD_NAME                    (((UINT32) 2) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_BAD_NAMETYPE                        (((UINT32) 3) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_BAD_BINDINGS                        (((UINT32) 4) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_BAD_STATUS                  (((UINT32) 5) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_BAD_SIG                     (((UINT32) 6) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_NO_CRED                     (((UINT32) 7) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_NO_CONTEXT                  (((UINT32) 8) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_DEFECTIVE_TOKEN             (((UINT32) 9) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_DEFECTIVE_CREDENTIAL                (((UINT32) 10) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_CREDENTIALS_EXPIRED         (((UINT32) 11) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_CONTEXT_EXPIRED             (((UINT32) 12) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_FAILURE                     (((UINT32) 13) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_BAD_QOP                     (((UINT32) 14) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_UNAUTHORIZED                        (((UINT32) 15) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_UNAVAILABLE                 (((UINT32) 16) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_DUPLICATE_ELEMENT           (((UINT32) 17) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_NAME_NOT_MN                 (((UINT32) 18) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+#define SSPI_GSS_S_BAD_MECH_ATTR               (((UINT32) 19) << SSPI_GSS_C_ROUTINE_ERROR_OFFSET)
+
+#define SSPI_GSS_S_CONTINUE_NEEDED             (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 0))
+#define SSPI_GSS_S_DUPLICATE_TOKEN             (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 1))
+#define SSPI_GSS_S_OLD_TOKEN                   (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 2))
+#define SSPI_GSS_S_UNSEQ_TOKEN                 (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 3))
+#define SSPI_GSS_S_GAP_TOKEN                   (1 << (SSPI_GSS_C_SUPPLEMENTARY_OFFSET + 4))
+
+#define SSPI_GSS_C_PRF_KEY_FULL                        0
+#define SSPI_GSS_C_PRF_KEY_PARTIAL             1
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_USER_NAME;
+SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_MACHINE_UID_NAME;
+SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_STRING_UID_NAME;
+SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_HOSTBASED_SERVICE_X;
+SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_HOSTBASED_SERVICE;
+SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_ANONYMOUS;
+SSPI_GSSOID extern sspi_gss_OID SSPI_GSS_C_NT_EXPORT_NAME;
+
+UINT32 SSPI_GSSAPI sspi_gss_acquire_cred(
+    UINT32* minor_status,
+    sspi_gss_name_t desired_name,
+    UINT32 time_req,
+    sspi_gss_OID_set desired_mechs,
+    sspi_gss_cred_usage_t cred_usage,
+    sspi_gss_cred_id_t* output_cred_handle,
+    sspi_gss_OID_set* actual_mechs,
+    UINT32* time_rec);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_acquire_cred)(
+    UINT32* minor_status,
+    sspi_gss_name_t desired_name,
+    UINT32 time_req,
+    sspi_gss_OID_set desired_mechs,
+    sspi_gss_cred_usage_t cred_usage,
+    sspi_gss_cred_id_t* output_cred_handle,
+    sspi_gss_OID_set* actual_mechs,
+    UINT32* time_rec);
+
+UINT32 SSPI_GSSAPI sspi_gss_release_cred(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t* cred_handle);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_cred)(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t* cred_handle);
+
+UINT32 SSPI_GSSAPI sspi_gss_init_sec_context(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t claimant_cred_handle,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_name_t target_name,
+    sspi_gss_OID mech_type,
+    UINT32 req_flags,
+    UINT32 time_req,
+    sspi_gss_channel_bindings_t input_chan_bindings,
+    sspi_gss_buffer_t input_token,
+    sspi_gss_OID* actual_mech_type,
+    sspi_gss_buffer_t output_token,
+    UINT32* ret_flags,
+    UINT32* time_rec);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_init_sec_context)(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t claimant_cred_handle,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_name_t target_name,
+    sspi_gss_OID mech_type,
+    UINT32 req_flags,
+    UINT32 time_req,
+    sspi_gss_channel_bindings_t input_chan_bindings,
+    sspi_gss_buffer_t input_token,
+    sspi_gss_OID* actual_mech_type,
+    sspi_gss_buffer_t output_token,
+    UINT32* ret_flags,
+    UINT32* time_rec);
+
+UINT32 SSPI_GSSAPI sspi_gss_accept_sec_context(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_cred_id_t acceptor_cred_handle,
+    sspi_gss_buffer_t input_token_buffer,
+    sspi_gss_channel_bindings_t input_chan_bindings,
+    sspi_gss_name_t* src_name,
+    sspi_gss_OID* mech_type,
+    sspi_gss_buffer_t output_token,
+    UINT32* ret_flags,
+    UINT32* time_rec,
+    sspi_gss_cred_id_t* delegated_cred_handle);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_accept_sec_context)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_cred_id_t acceptor_cred_handle,
+    sspi_gss_buffer_t input_token_buffer,
+    sspi_gss_channel_bindings_t input_chan_bindings,
+    sspi_gss_name_t* src_name,
+    sspi_gss_OID* mech_type,
+    sspi_gss_buffer_t output_token,
+    UINT32* ret_flags,
+    UINT32* time_rec,
+    sspi_gss_cred_id_t* delegated_cred_handle);
+
+UINT32 SSPI_GSSAPI sspi_gss_process_context_token(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t token_buffer);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_process_context_token)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t token_buffer);
+
+UINT32 SSPI_GSSAPI sspi_gss_delete_sec_context(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_buffer_t output_token);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_delete_sec_context)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_buffer_t output_token);
+
+UINT32 SSPI_GSSAPI sspi_gss_context_time(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    UINT32* time_rec);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_context_time)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    UINT32* time_rec);
+
+UINT32 SSPI_GSSAPI sspi_gss_get_mic(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_qop_t qop_req,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_get_mic)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_qop_t qop_req,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token);
+
+UINT32 SSPI_GSSAPI sspi_gss_verify_mic(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token,
+    sspi_gss_qop_t* qop_state);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_verify_mic)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token,
+    sspi_gss_qop_t* qop_state);
+
+UINT32 SSPI_GSSAPI sspi_gss_wrap(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    sspi_gss_qop_t qop_req,
+    sspi_gss_buffer_t input_message_buffer,
+    int* conf_state,
+    sspi_gss_buffer_t output_message_buffer);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_wrap)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    sspi_gss_qop_t qop_req,
+    sspi_gss_buffer_t input_message_buffer,
+    int* conf_state,
+    sspi_gss_buffer_t output_message_buffer);
+
+UINT32 SSPI_GSSAPI sspi_gss_unwrap(
+    UINT32* minor_status,
+    const sspi_gss_ctx_id_t context_handle,
+    const sspi_gss_buffer_t input_message_buffer,
+    sspi_gss_buffer_t output_message_buffer,
+    int* conf_state,
+    sspi_gss_qop_t* qop_state);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_unwrap)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t input_message_buffer,
+    sspi_gss_buffer_t output_message_buffer,
+    int* conf_state,
+    sspi_gss_qop_t* qop_state);
+
+UINT32 SSPI_GSSAPI sspi_gss_display_status(
+    UINT32* minor_status,
+    UINT32 status_value,
+    int status_type,
+    sspi_gss_OID mech_type,
+    UINT32* message_context,
+    sspi_gss_buffer_t status_string);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_display_status)(
+    UINT32* minor_status,
+    UINT32 status_value,
+    int status_type,
+    sspi_gss_OID mech_type,
+    UINT32* message_context,
+    sspi_gss_buffer_t status_string);
+
+UINT32 SSPI_GSSAPI sspi_gss_indicate_mechs(
+    UINT32* minor_status,
+    sspi_gss_OID_set* mech_set);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_indicate_mechs)(
+    UINT32* minor_status,
+    sspi_gss_OID_set* mech_set);
+
+UINT32 SSPI_GSSAPI sspi_gss_compare_name(
+    UINT32* minor_status,
+    sspi_gss_name_t name1,
+    sspi_gss_name_t name2,
+    int* name_equal);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_compare_name)(
+    UINT32* minor_status,
+    sspi_gss_name_t name1,
+    sspi_gss_name_t name2,
+    int* name_equal);
+
+UINT32 SSPI_GSSAPI sspi_gss_display_name(
+    UINT32* minor_status,
+    sspi_gss_name_t input_name,
+    sspi_gss_buffer_t output_name_buffer,
+    sspi_gss_OID* output_name_type);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_display_name)(
+    UINT32* minor_status,
+    sspi_gss_name_t input_name,
+    sspi_gss_buffer_t output_name_buffer,
+    sspi_gss_OID* output_name_type);
+
+UINT32 SSPI_GSSAPI sspi_gss_import_name(
+    UINT32* minor_status,
+    sspi_gss_buffer_t input_name_buffer,
+    sspi_gss_OID input_name_type,
+    sspi_gss_name_t* output_name);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_import_name)(
+    UINT32* minor_status,
+    sspi_gss_buffer_t input_name_buffer,
+    sspi_gss_OID input_name_type,
+    sspi_gss_name_t* output_name);
+
+UINT32 SSPI_GSSAPI sspi_gss_release_name(
+    UINT32* minor_status,
+    sspi_gss_name_t* input_name);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_name)(
+    UINT32* minor_status,
+    sspi_gss_name_t* input_name);
+
+UINT32 SSPI_GSSAPI sspi_gss_release_buffer(
+    UINT32* minor_status,
+    sspi_gss_buffer_t buffer);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_buffer)(
+    UINT32* minor_status,
+    sspi_gss_buffer_t buffer);
+
+UINT32 SSPI_GSSAPI sspi_gss_release_oid_set(
+    UINT32* minor_status,
+    sspi_gss_OID_set* set);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_oid_set)(
+    UINT32* minor_status,
+    sspi_gss_OID_set* set);
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_cred(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    sspi_gss_name_t* name,
+    UINT32* lifetime,
+    sspi_gss_cred_usage_t* cred_usage,
+    sspi_gss_OID_set* mechanisms);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_cred)(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    sspi_gss_name_t* name,
+    UINT32* lifetime,
+    sspi_gss_cred_usage_t* cred_usage,
+    sspi_gss_OID_set* mechanisms);
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_context(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_name_t* src_name,
+    sspi_gss_name_t* targ_name,
+    UINT32* lifetime_rec,
+    sspi_gss_OID* mech_type,
+    UINT32* ctx_flags,
+    int* locally_initiated,
+    int* open);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_context)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_name_t* src_name,
+    sspi_gss_name_t* targ_name,
+    UINT32* lifetime_rec,
+    sspi_gss_OID* mech_type,
+    UINT32* ctx_flags,
+    int* locally_initiated,
+    int* open);
+
+UINT32 SSPI_GSSAPI sspi_gss_wrap_size_limit(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    sspi_gss_qop_t qop_req,
+    UINT32 req_output_size,
+    UINT32* max_input_size);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_wrap_size_limit)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    sspi_gss_qop_t qop_req,
+    UINT32 req_output_size,
+    UINT32* max_input_size);
+
+UINT32 SSPI_GSSAPI sspi_gss_import_name_object(
+    UINT32* minor_status,
+    void* input_name,
+    sspi_gss_OID input_name_type,
+    sspi_gss_name_t* output_name);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_import_name_object)(
+    UINT32* minor_status,
+    void* input_name,
+    sspi_gss_OID input_name_type,
+    sspi_gss_name_t* output_name);
+
+UINT32 SSPI_GSSAPI sspi_gss_export_name_object(
+    UINT32* minor_status,
+    sspi_gss_name_t input_name,
+    sspi_gss_OID desired_name_type,
+    void** output_name);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_export_name_object)(
+    UINT32* minor_status,
+    sspi_gss_name_t input_name,
+    sspi_gss_OID desired_name_type,
+    void** output_name);
+
+UINT32 SSPI_GSSAPI sspi_gss_add_cred(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t input_cred_handle,
+    sspi_gss_name_t desired_name,
+    sspi_gss_OID desired_mech,
+    sspi_gss_cred_usage_t cred_usage,
+    UINT32 initiator_time_req,
+    UINT32 acceptor_time_req,
+    sspi_gss_cred_id_t* output_cred_handle,
+    sspi_gss_OID_set* actual_mechs,
+    UINT32* initiator_time_rec,
+    UINT32* acceptor_time_rec);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_add_cred)(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t input_cred_handle,
+    sspi_gss_name_t desired_name,
+    sspi_gss_OID desired_mech,
+    sspi_gss_cred_usage_t cred_usage,
+    UINT32 initiator_time_req,
+    UINT32 acceptor_time_req,
+    sspi_gss_cred_id_t* output_cred_handle,
+    sspi_gss_OID_set* actual_mechs,
+    UINT32* initiator_time_rec,
+    UINT32* acceptor_time_rec);
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_cred_by_mech(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    sspi_gss_OID mech_type,
+    sspi_gss_name_t* name,
+    UINT32* initiator_lifetime,
+    UINT32* acceptor_lifetime,
+    sspi_gss_cred_usage_t* cred_usage);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_cred_by_mech)(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    sspi_gss_OID mech_type,
+    sspi_gss_name_t* name,
+    UINT32* initiator_lifetime,
+    UINT32* acceptor_lifetime,
+    sspi_gss_cred_usage_t* cred_usage);
+
+UINT32 SSPI_GSSAPI sspi_gss_export_sec_context(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_buffer_t interprocess_token);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_export_sec_context)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t* context_handle,
+    sspi_gss_buffer_t interprocess_token);
+
+UINT32 SSPI_GSSAPI sspi_gss_import_sec_context(
+    UINT32* minor_status,
+    sspi_gss_buffer_t interprocess_token,
+    sspi_gss_ctx_id_t* context_handle);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_import_sec_context)(
+    UINT32* minor_status,
+    sspi_gss_buffer_t interprocess_token,
+    sspi_gss_ctx_id_t* context_handle);
+
+UINT32 SSPI_GSSAPI sspi_gss_release_oid(
+    UINT32* minor_status,
+    sspi_gss_OID* oid);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_release_oid)(
+    UINT32* minor_status,
+    sspi_gss_OID* oid);
+
+UINT32 SSPI_GSSAPI sspi_gss_create_empty_oid_set(
+    UINT32* minor_status,
+    sspi_gss_OID_set* oid_set);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_create_empty_oid_set)(
+    UINT32* minor_status,
+    sspi_gss_OID_set* oid_set);
+
+UINT32 SSPI_GSSAPI sspi_gss_add_oid_set_member(
+    UINT32* minor_status,
+    sspi_gss_OID member_oid,
+    sspi_gss_OID_set* oid_set);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_add_oid_set_member)(
+    UINT32* minor_status,
+    sspi_gss_OID member_oid,
+    sspi_gss_OID_set* oid_set);
+
+UINT32 SSPI_GSSAPI sspi_gss_test_oid_set_member(
+    UINT32* minor_status,
+    sspi_gss_OID member,
+    sspi_gss_OID_set set,
+    int* present);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_test_oid_set_member)(
+    UINT32* minor_status,
+    sspi_gss_OID member,
+    sspi_gss_OID_set set,
+    int* present);
+
+UINT32 SSPI_GSSAPI sspi_gss_str_to_oid(
+    UINT32* minor_status,
+    sspi_gss_buffer_t oid_str,
+    sspi_gss_OID* oid);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_str_to_oid)(
+    UINT32* minor_status,
+    sspi_gss_buffer_t oid_str,
+    sspi_gss_OID* oid);
+
+UINT32 SSPI_GSSAPI sspi_gss_oid_to_str(
+    UINT32* minor_status,
+    sspi_gss_OID oid,
+    sspi_gss_buffer_t oid_str);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_oid_to_str)(
+    UINT32* minor_status,
+    sspi_gss_OID oid,
+    sspi_gss_buffer_t oid_str);
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_names_for_mech(
+    UINT32* minor_status,
+    sspi_gss_OID mechanism,
+    sspi_gss_OID_set* name_types);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_names_for_mech)(
+    UINT32* minor_status,
+    sspi_gss_OID mechanism,
+    sspi_gss_OID_set* name_types);
+
+UINT32 SSPI_GSSAPI sspi_gss_inquire_mechs_for_name(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_OID_set* mech_types);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_inquire_mechs_for_name)(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_OID_set* mech_types);
+
+UINT32 SSPI_GSSAPI sspi_gss_sign(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int qop_req,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_sign)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int qop_req,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t message_token);
+
+UINT32 SSPI_GSSAPI sspi_gss_verify(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t token_buffer,
+    int* qop_state);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_verify)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t message_buffer,
+    sspi_gss_buffer_t token_buffer,
+    int* qop_state);
+
+UINT32 SSPI_GSSAPI sspi_gss_seal(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    int qop_req,
+    sspi_gss_buffer_t input_message_buffer,
+    int* conf_state,
+    sspi_gss_buffer_t output_message_buffer);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_seal)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    int conf_req_flag,
+    int qop_req,
+    sspi_gss_buffer_t input_message_buffer,
+    int* conf_state,
+    sspi_gss_buffer_t output_message_buffer);
+
+UINT32 SSPI_GSSAPI sspi_gss_unseal(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t input_message_buffer,
+    sspi_gss_buffer_t output_message_buffer,
+    int* conf_state,
+    int* qop_state);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_unseal)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context_handle,
+    sspi_gss_buffer_t input_message_buffer,
+    sspi_gss_buffer_t output_message_buffer,
+    int* conf_state,
+    int* qop_state);
+
+UINT32 SSPI_GSSAPI sspi_gss_export_name(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_buffer_t exported_name);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_export_name)(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_buffer_t exported_name);
+
+UINT32 SSPI_GSSAPI sspi_gss_duplicate_name(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_name_t* dest_name);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_duplicate_name)(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    sspi_gss_name_t* dest_name);
+
+UINT32 SSPI_GSSAPI sspi_gss_canonicalize_name(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    const sspi_gss_OID mech_type,
+    sspi_gss_name_t* output_name);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_canonicalize_name)(
+    UINT32* minor_status,
+    const sspi_gss_name_t input_name,
+    const sspi_gss_OID mech_type,
+    sspi_gss_name_t* output_name);
+
+UINT32 SSPI_GSSAPI sspi_gss_pseudo_random(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context,
+    int prf_key,
+    const sspi_gss_buffer_t prf_in,
+    ssize_t desired_output_len,
+    sspi_gss_buffer_t prf_out);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_pseudo_random)(
+    UINT32* minor_status,
+    sspi_gss_ctx_id_t context,
+    int prf_key,
+    const sspi_gss_buffer_t prf_in,
+    ssize_t desired_output_len,
+    sspi_gss_buffer_t prf_out);
+
+UINT32 SSPI_GSSAPI sspi_gss_store_cred(
+    UINT32* minor_status,
+    const sspi_gss_cred_id_t input_cred_handle,
+    sspi_gss_cred_usage_t input_usage,
+    const sspi_gss_OID desired_mech,
+    UINT32 overwrite_cred,
+    UINT32 default_cred,
+    sspi_gss_OID_set* elements_stored,
+    sspi_gss_cred_usage_t* cred_usage_stored);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_store_cred)(
+    UINT32* minor_status,
+    const sspi_gss_cred_id_t input_cred_handle,
+    sspi_gss_cred_usage_t input_usage,
+    const sspi_gss_OID desired_mech,
+    UINT32 overwrite_cred,
+    UINT32 default_cred,
+    sspi_gss_OID_set* elements_stored,
+    sspi_gss_cred_usage_t* cred_usage_stored);
+
+UINT32 SSPI_GSSAPI sspi_gss_set_neg_mechs(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    const sspi_gss_OID_set mech_set);
+
+typedef UINT32(SSPI_GSSAPI* fn_sspi_gss_set_neg_mechs)(
+    UINT32* minor_status,
+    sspi_gss_cred_id_t cred_handle,
+    const sspi_gss_OID_set mech_set);
+
+#ifdef __cplusplus
+}
+#endif
+
+struct _GSSAPI_FUNCTION_TABLE
+{
+       fn_sspi_gss_acquire_cred gss_acquire_cred;
+       fn_sspi_gss_release_cred gss_release_cred;
+       fn_sspi_gss_init_sec_context gss_init_sec_context;
+       fn_sspi_gss_accept_sec_context gss_accept_sec_context;
+       fn_sspi_gss_process_context_token gss_process_context_token;
+       fn_sspi_gss_delete_sec_context gss_delete_sec_context;
+       fn_sspi_gss_context_time gss_context_time;
+       fn_sspi_gss_get_mic gss_get_mic;
+       fn_sspi_gss_verify_mic gss_verify_mic;
+       fn_sspi_gss_wrap gss_wrap;
+       fn_sspi_gss_unwrap gss_unwrap;
+       fn_sspi_gss_display_status gss_display_status;
+       fn_sspi_gss_indicate_mechs gss_indicate_mechs;
+       fn_sspi_gss_compare_name gss_compare_name;
+       fn_sspi_gss_display_name gss_display_name;
+       fn_sspi_gss_import_name gss_import_name;
+       fn_sspi_gss_release_name gss_release_name;
+       fn_sspi_gss_release_buffer gss_release_buffer;
+       fn_sspi_gss_release_oid_set gss_release_oid_set;
+       fn_sspi_gss_inquire_cred gss_inquire_cred;
+       fn_sspi_gss_inquire_context gss_inquire_context;
+       fn_sspi_gss_wrap_size_limit gss_wrap_size_limit;
+       fn_sspi_gss_import_name_object gss_import_name_object;
+       fn_sspi_gss_export_name_object gss_export_name_object;
+       fn_sspi_gss_add_cred gss_add_cred;
+       fn_sspi_gss_inquire_cred_by_mech gss_inquire_cred_by_mech;
+       fn_sspi_gss_export_sec_context gss_export_sec_context;
+       fn_sspi_gss_import_sec_context gss_import_sec_context;
+       fn_sspi_gss_release_oid gss_release_oid;
+       fn_sspi_gss_create_empty_oid_set gss_create_empty_oid_set;
+       fn_sspi_gss_add_oid_set_member gss_add_oid_set_member;
+       fn_sspi_gss_test_oid_set_member gss_test_oid_set_member;
+       fn_sspi_gss_str_to_oid gss_str_to_oid;
+       fn_sspi_gss_oid_to_str gss_oid_to_str;
+       fn_sspi_gss_inquire_names_for_mech gss_inquire_names_for_mech;
+       fn_sspi_gss_inquire_mechs_for_name gss_inquire_mechs_for_name;
+       fn_sspi_gss_sign gss_sign;
+       fn_sspi_gss_verify gss_verify;
+       fn_sspi_gss_seal gss_seal;
+       fn_sspi_gss_unseal gss_unseal;
+       fn_sspi_gss_export_name gss_export_name;
+       fn_sspi_gss_duplicate_name gss_duplicate_name;
+       fn_sspi_gss_canonicalize_name gss_canonicalize_name;
+       fn_sspi_gss_pseudo_random gss_pseudo_random;
+       fn_sspi_gss_store_cred gss_store_cred;
+       fn_sspi_gss_set_neg_mechs gss_set_neg_mechs;
+};
+typedef struct _GSSAPI_FUNCTION_TABLE GSSAPI_FUNCTION_TABLE;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /* FREERDP_SSPI_GSS_PRIVATE_H */
index 3d731e3..cff5178 100644 (file)
@@ -3,6 +3,7 @@
  * Security Support Provider Interface (SSPI)
  *
  * Copyright 2012-2014 Marc-Andre Moreau <marcandre.moreau@gmail.com>
+ * Copyright 2017 Dorian Ducournau <dorian.ducournau@gmail.com>
  *
  * Licensed under the Apache License, Version 2.0 (the "License");
  * you may not use this file except in compliance with the License.
@@ -42,6 +43,11 @@ extern const SecPkgInfoW NTLM_SecPkgInfoW;
 extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA;
 extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW;
 
+extern const SecPkgInfoA KERBEROS_SecPkgInfoA;
+extern const SecPkgInfoW KERBEROS_SecPkgInfoW;
+extern const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA;
+extern const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW;
+
 extern const SecPkgInfoA NEGOTIATE_SecPkgInfoA;
 extern const SecPkgInfoW NEGOTIATE_SecPkgInfoW;
 extern const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA;
@@ -60,6 +66,7 @@ extern const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW;
 const SecPkgInfoA* SecPkgInfoA_LIST[] =
 {
        &NTLM_SecPkgInfoA,
+       &KERBEROS_SecPkgInfoA,
        &NEGOTIATE_SecPkgInfoA,
        &CREDSSP_SecPkgInfoA,
        &SCHANNEL_SecPkgInfoA
@@ -68,6 +75,7 @@ const SecPkgInfoA* SecPkgInfoA_LIST[] =
 const SecPkgInfoW* SecPkgInfoW_LIST[] =
 {
        &NTLM_SecPkgInfoW,
+       &KERBEROS_SecPkgInfoW,
        &NEGOTIATE_SecPkgInfoW,
        &CREDSSP_SecPkgInfoW,
        &SCHANNEL_SecPkgInfoW
@@ -93,19 +101,22 @@ typedef struct _SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME;
 const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] =
 {
        { "NTLM", &NTLM_SecurityFunctionTableA },
+       { "Kerberos", &KERBEROS_SecurityFunctionTableA },
        { "Negotiate", &NEGOTIATE_SecurityFunctionTableA },
        { "CREDSSP", &CREDSSP_SecurityFunctionTableA },
        { "Schannel", &SCHANNEL_SecurityFunctionTableA }
 };
 
-WCHAR NTLM_NAME_W[] = { 'N','T','L','M','\0' };
-WCHAR NEGOTIATE_NAME_W[] = { 'N','e','g','o','t','i','a','t','e','\0' };
-WCHAR CREDSSP_NAME_W[] = { 'C','r','e','d','S','S','P','\0' };
-WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l','\0' };
+WCHAR NTLM_NAME_W[] = { 'N', 'T', 'L', 'M', '\0' };
+WCHAR KERBEROS_NAME_W[] = { 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', '\0' };
+WCHAR NEGOTIATE_NAME_W[] = { 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', '\0' };
+WCHAR CREDSSP_NAME_W[] = { 'C', 'r', 'e', 'd', 'S', 'S', 'P', '\0' };
+WCHAR SCHANNEL_NAME_W[] = { 'S', 'c', 'h', 'a', 'n', 'n', 'e', 'l', '\0' };
 
 const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] =
 {
        { NTLM_NAME_W, &NTLM_SecurityFunctionTableW },
+       { KERBEROS_NAME_W, &KERBEROS_SecurityFunctionTableW },
        { NEGOTIATE_NAME_W, &NEGOTIATE_SecurityFunctionTableW },
        { CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW },
        { SCHANNEL_NAME_W, &SCHANNEL_SecurityFunctionTableW }
@@ -134,13 +145,10 @@ CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable;
 int sspi_ContextBufferAllocTableNew()
 {
        size_t size;
-
        ContextBufferAllocTable.entries = NULL;
        ContextBufferAllocTable.cEntries = 0;
        ContextBufferAllocTable.cMaxEntries = 4;
-
        size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
-
        ContextBufferAllocTable.entries = (CONTEXT_BUFFER_ALLOC_ENTRY*) calloc(1, size);
 
        if (!ContextBufferAllocTable.entries)
@@ -155,7 +163,6 @@ int sspi_ContextBufferAllocTableGrow()
        CONTEXT_BUFFER_ALLOC_ENTRY* entries;
        ContextBufferAllocTable.cEntries = 0;
        ContextBufferAllocTable.cMaxEntries *= 2;
-
        size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
 
        if (!size)
@@ -170,9 +177,8 @@ int sspi_ContextBufferAllocTableGrow()
        }
 
        ContextBufferAllocTable.entries = entries;
-
-       ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], size / 2);
-
+       ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2],
+                  size / 2);
        return 1;
 }
 
@@ -197,10 +203,8 @@ void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
                                return NULL;
 
                        ContextBufferAllocTable.cEntries++;
-
                        ContextBufferAllocTable.entries[index].contextBuffer = contextBuffer;
                        ContextBufferAllocTable.entries[index].allocatorIndex = allocatorIndex;
-
                        return ContextBufferAllocTable.entries[index].contextBuffer;
                }
        }
@@ -211,24 +215,21 @@ void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size)
                return NULL;
 
        /* the next call to sspi_ContextBufferAlloc() should now succeed */
-
        return sspi_ContextBufferAlloc(allocatorIndex, size);
 }
 
 SSPI_CREDENTIALS* sspi_CredentialsNew()
 {
        SSPI_CREDENTIALS* credentials;
-
        credentials = (SSPI_CREDENTIALS*) calloc(1, sizeof(SSPI_CREDENTIALS));
-
        return credentials;
 }
 
 void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
 {
-       size_t userLength;
-       size_t domainLength;
-       size_t passwordLength;
+       size_t userLength = 0;
+       size_t domainLength = 0;
+       size_t passwordLength = 0;
 
        if (!credentials)
                return;
@@ -247,11 +248,9 @@ void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials)
        memset(credentials->identity.User, 0, userLength);
        memset(credentials->identity.Domain, 0, domainLength);
        memset(credentials->identity.Password, 0, passwordLength);
-
        free(credentials->identity.User);
        free(credentials->identity.Domain);
        free(credentials->identity.Password);
-
        free(credentials);
 }
 
@@ -261,6 +260,7 @@ void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size)
                return NULL;
 
        SecBuffer->pvBuffer = calloc(1, size);
+
        if (!SecBuffer->pvBuffer)
                return NULL;
 
@@ -288,7 +288,6 @@ SecHandle* sspi_SecureHandleAlloc()
                return NULL;
 
        SecInvalidateHandle(handle);
-
        return handle;
 }
 
@@ -300,7 +299,6 @@ void* sspi_SecureHandleGetLowerPointer(SecHandle* handle)
                return NULL;
 
        pointer = (void*) ~((size_t) handle->dwLower);
-
        return pointer;
 }
 
@@ -318,7 +316,7 @@ void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer)
        if (!handle)
                return;
 
-       handle->dwLower = (ULONG_PTR) (~((size_t) pointer));
+       handle->dwLower = (ULONG_PTR)(~((size_t) pointer));
 }
 
 void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
@@ -329,7 +327,6 @@ void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
                return NULL;
 
        pointer = (void*) ~((size_t) handle->dwUpper);
-
        return pointer;
 }
 
@@ -338,7 +335,7 @@ void sspi_SecureHandleSetUpperPointer(SecHandle* handle, void* pointer)
        if (!handle)
                return;
 
-       handle->dwUpper = (ULONG_PTR) (~((size_t) pointer));
+       handle->dwUpper = (ULONG_PTR)(~((size_t) pointer));
 }
 
 void sspi_SecureHandleFree(SecHandle* handle)
@@ -346,55 +343,51 @@ void sspi_SecureHandleFree(SecHandle* handle)
        free(handle);
 }
 
-int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, const char* password)
+int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain,
+                         const char* password)
 {
        int status;
-
        identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
-
        free(identity->User);
-
        identity->User = (UINT16*) NULL;
        identity->UserLength = 0;
 
        if (user)
        {
-               status = ConvertToUnicode(CP_UTF8, 0, user, -1, (LPWSTR*) &(identity->User), 0);
+               status = ConvertToUnicode(CP_UTF8, 0, user, -1, (LPWSTR*) & (identity->User), 0);
 
                if (status <= 0)
                        return -1;
 
-               identity->UserLength = (ULONG) (status - 1);
+               identity->UserLength = (ULONG)(status - 1);
        }
 
        free(identity->Domain);
-
        identity->Domain = (UINT16*) NULL;
        identity->DomainLength = 0;
 
        if (domain)
        {
-               status = ConvertToUnicode(CP_UTF8, 0, domain, -1, (LPWSTR*) &(identity->Domain), 0);
+               status = ConvertToUnicode(CP_UTF8, 0, domain, -1, (LPWSTR*) & (identity->Domain), 0);
 
                if (status <= 0)
                        return -1;
 
-               identity->DomainLength = (ULONG) (status - 1);
+               identity->DomainLength = (ULONG)(status - 1);
        }
 
        free(identity->Password);
-
        identity->Password = NULL;
        identity->PasswordLength = 0;
 
        if (password)
        {
-               status = ConvertToUnicode(CP_UTF8, 0, password, -1, (LPWSTR*) &(identity->Password), 0);
+               status = ConvertToUnicode(CP_UTF8, 0, password, -1, (LPWSTR*) & (identity->Password), 0);
 
                if (status <= 0)
                        return -1;
 
-               identity->PasswordLength = (ULONG) (status - 1);
+               identity->PasswordLength = (ULONG)(status - 1);
        }
 
        return 1;
@@ -407,20 +400,18 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN
        if (srcIdentity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI)
        {
                status = sspi_SetAuthIdentity(identity, (char*) srcIdentity->User,
-                                             (char*) srcIdentity->Domain, (char*) srcIdentity->Password);
+                                             (char*) srcIdentity->Domain, (char*) srcIdentity->Password);
 
                if (status <= 0)
                        return -1;
 
                identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
-
                return 1;
        }
 
        identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE;
-
+       /* login/password authentication */
        identity->User = identity->Domain = identity->Password = NULL;
-
        identity->UserLength = srcIdentity->UserLength;
 
        if (identity->UserLength > 0)
@@ -463,8 +454,7 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN
                identity->Password[identity->PasswordLength] = 0;
        }
 
-       identity->PasswordLength = srcIdentity->PasswordLength;
-
+       /* End of login/password authentication */
        return 1;
 }
 
@@ -492,7 +482,6 @@ void sspi_GlobalInit()
        if (!sspi_initialized)
        {
                winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
-
                sspi_ContextBufferAllocTableNew();
                sspi_initialized = TRUE;
        }
@@ -512,7 +501,6 @@ SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Na
 {
        int index;
        UINT32 cPackages;
-
        cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
 
        for (index = 0; index < (int) cPackages; index++)
@@ -535,7 +523,6 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* N
 {
        int index;
        UINT32 cPackages;
-
        cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
 
        for (index = 0; index < (int) cPackages; index++)
@@ -554,7 +541,6 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Na
        int status;
        SEC_WCHAR* NameW = NULL;
        SecurityFunctionTableW* table;
-
        status = ConvertToUnicode(CP_UTF8, 0, Name, -1, &NameW, 0);
 
        if (status <= 0)
@@ -562,7 +548,6 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Na
 
        table = sspi_GetSecurityFunctionTableWByNameW(NameW);
        free(NameW);
-
        return table;
 }
 
@@ -580,21 +565,19 @@ void sspi_ContextBufferFree(void* contextBuffer)
                {
                        contextBuffer = ContextBufferAllocTable.entries[index].contextBuffer;
                        allocatorIndex = ContextBufferAllocTable.entries[index].allocatorIndex;
-
                        ContextBufferAllocTable.cEntries--;
-
                        ContextBufferAllocTable.entries[index].allocatorIndex = 0;
                        ContextBufferAllocTable.entries[index].contextBuffer = NULL;
 
                        switch (allocatorIndex)
                        {
-                       case EnumerateSecurityPackagesIndex:
-                               FreeContextBuffer_EnumerateSecurityPackages(contextBuffer);
-                               break;
+                               case EnumerateSecurityPackagesIndex:
+                                       FreeContextBuffer_EnumerateSecurityPackages(contextBuffer);
+                                       break;
 
-                       case QuerySecurityPackageInfoIndex:
-                               FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer);
-                               break;
+                               case QuerySecurityPackageInfoIndex:
+                                       FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer);
+                                       break;
                        }
                }
        }
@@ -606,16 +589,15 @@ void sspi_ContextBufferFree(void* contextBuffer)
 
 /* Package Management */
 
-SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, PSecPkgInfoW* ppPackageInfo)
+SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages,
+        PSecPkgInfoW* ppPackageInfo)
 {
        int index;
        size_t size;
        UINT32 cPackages;
        SecPkgInfoW* pPackageInfo;
-
        cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
        size = sizeof(SecPkgInfoW) * cPackages;
-
        pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
 
        if (!pPackageInfo)
@@ -633,20 +615,18 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, PS
 
        *(pcPackages) = cPackages;
        *(ppPackageInfo) = pPackageInfo;
-
        return SEC_E_OK;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PSecPkgInfoA* ppPackageInfo)
+SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages,
+        PSecPkgInfoA* ppPackageInfo)
 {
        int index;
        size_t size;
        UINT32 cPackages;
        SecPkgInfoA* pPackageInfo;
-
        cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
        size = sizeof(SecPkgInfoA) * cPackages;
-
        pPackageInfo = (SecPkgInfoA*) sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size);
 
        if (!pPackageInfo)
@@ -660,6 +640,7 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PS
                pPackageInfo[index].cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
                pPackageInfo[index].Name = _strdup(SecPkgInfoA_LIST[index]->Name);
                pPackageInfo[index].Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
+
                if (!pPackageInfo[index].Name || !pPackageInfo[index].Comment)
                {
                        sspi_ContextBufferFree(pPackageInfo);
@@ -669,7 +650,6 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PS
 
        *(pcPackages) = cPackages;
        *(ppPackageInfo) = pPackageInfo;
-
        return SEC_E_OK;
 }
 
@@ -678,7 +658,6 @@ void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer)
        int index;
        UINT32 cPackages;
        SecPkgInfoA* pPackageInfo = (SecPkgInfoA*) contextBuffer;
-
        cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
 
        for (index = 0; index < (int) cPackages; index++)
@@ -700,13 +679,13 @@ SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void)
        return &winpr_SecurityFunctionTableA;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, PSecPkgInfoW* ppPackageInfo)
+SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName,
+        PSecPkgInfoW* ppPackageInfo)
 {
        int index;
        size_t size;
        UINT32 cPackages;
        SecPkgInfoW* pPackageInfo;
-
        cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
 
        for (index = 0; index < (int) cPackages; index++)
@@ -725,25 +704,22 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageN
                        pPackageInfo->cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken;
                        pPackageInfo->Name = _wcsdup(SecPkgInfoW_LIST[index]->Name);
                        pPackageInfo->Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment);
-
                        *(ppPackageInfo) = pPackageInfo;
-
                        return SEC_E_OK;
                }
        }
 
        *(ppPackageInfo) = NULL;
-
        return SEC_E_SECPKG_NOT_FOUND;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName, PSecPkgInfoA* ppPackageInfo)
+SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName,
+        PSecPkgInfoA* ppPackageInfo)
 {
        int index;
        size_t size;
        UINT32 cPackages;
        SecPkgInfoA* pPackageInfo;
-
        cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
 
        for (index = 0; index < (int) cPackages; index++)
@@ -762,6 +738,7 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageNa
                        pPackageInfo->cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken;
                        pPackageInfo->Name = _strdup(SecPkgInfoA_LIST[index]->Name);
                        pPackageInfo->Comment = _strdup(SecPkgInfoA_LIST[index]->Comment);
+
                        if (!pPackageInfo->Name || !pPackageInfo->Comment)
                        {
                                sspi_ContextBufferFree(pPackageInfo);
@@ -769,13 +746,11 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageNa
                        }
 
                        *(ppPackageInfo) = pPackageInfo;
-
                        return SEC_E_OK;
                }
        }
 
        *(ppPackageInfo) = NULL;
-
        return SEC_E_SECPKG_NOT_FOUND;
 }
 
@@ -793,9 +768,10 @@ void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer)
 
 /* Credential Management */
 
-SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage,
-                                                         ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
-                                                         void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
+SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal,
+        SEC_WCHAR* pszPackage,
+        ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
+        void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
 {
        SECURITY_STATUS status;
        SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage);
@@ -807,20 +783,21 @@ SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipa
                return SEC_E_UNSUPPORTED_FUNCTION;
 
        status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse,
-                                                 pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
+                pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
 
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "AcquireCredentialsHandleW status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage,
-                                                         ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
-                                                         void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
+SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal,
+        SEC_CHAR* pszPackage,
+        ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn,
+        void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry)
 {
        SECURITY_STATUS status;
        SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage);
@@ -832,23 +809,23 @@ SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal
                return SEC_E_UNSUPPORTED_FUNCTION;
 
        status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse,
-                                                 pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
+                pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry);
 
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "AcquireCredentialsHandleA status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags, PSecBuffer pPackedContext, HANDLE* pToken)
+SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags,
+        PSecBuffer pPackedContext, HANDLE* pToken)
 {
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -867,7 +844,7 @@ SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULO
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "ExportSecurityContext status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -878,7 +855,6 @@ SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential)
        char* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential);
 
        if (!Name)
@@ -897,18 +873,18 @@ SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential)
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext)
+SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage,
+        PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext)
 {
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -927,18 +903,18 @@ SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, PS
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "ImportSecurityContextW status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext)
+SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage,
+        PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext)
 {
        char* Name = NULL;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -957,18 +933,18 @@ SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, PSe
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "ImportSecurityContextA status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
+SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential,
+        ULONG ulAttribute, void* pBuffer)
 {
        SEC_WCHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_WCHAR*) sspi_SecureHandleGetUpperPointer(phCredential);
 
        if (!Name)
@@ -987,18 +963,18 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCreden
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "QueryCredentialsAttributesW status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer)
+SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential,
+        ULONG ulAttribute, void* pBuffer)
 {
        char* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential);
 
        if (!Name)
@@ -1017,7 +993,7 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCreden
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "QueryCredentialsAttributesA status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -1025,14 +1001,14 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCreden
 
 /* Context Management */
 
-SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext,
-                                                     PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
-                                                     PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
+SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential,
+        PCtxtHandle phContext,
+        PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext,
+        PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp)
 {
        char* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential);
 
        if (!Name)
@@ -1047,12 +1023,12 @@ SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential,
                return SEC_E_UNSUPPORTED_FUNCTION;
 
        status = table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq,
-                                             TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
+                                             TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp);
 
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -1063,7 +1039,6 @@ SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext, PSecBuf
        char* Name = NULL;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1082,7 +1057,7 @@ SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext, PSecBuf
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "ApplyControlToken status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -1093,7 +1068,6 @@ SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext, PSecBuf
        char* Name = NULL;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1112,7 +1086,7 @@ SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext, PSecBuf
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -1123,7 +1097,6 @@ SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext)
        char* Name = NULL;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1142,7 +1115,7 @@ SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext)
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -1154,7 +1127,6 @@ SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer)
                return SEC_E_INVALID_HANDLE;
 
        sspi_ContextBufferFree(pvContextBuffer);
-
        return SEC_E_OK;
 }
 
@@ -1163,7 +1135,6 @@ SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1182,21 +1153,21 @@ SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "ImpersonateSecurityContext status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext,
-                                                          SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
-                                                          PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
-                                                          PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
+SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredential,
+        PCtxtHandle phContext,
+        SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
+        PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
+        PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
 {
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phCredential);
 
        if (!Name)
@@ -1211,27 +1182,27 @@ SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredent
                return SEC_E_UNSUPPORTED_FUNCTION;
 
        status = table->InitializeSecurityContextW(phCredential, phContext,
-                                                  pszTargetName, fContextReq, Reserved1, TargetDataRep,
-                                                  pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
+                pszTargetName, fContextReq, Reserved1, TargetDataRep,
+                pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
 
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "InitializeSecurityContextW status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext,
-                                                          SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
-                                                          PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
-                                                          PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
+SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredential,
+        PCtxtHandle phContext,
+        SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep,
+        PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext,
+        PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry)
 {
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phCredential);
 
        if (!Name)
@@ -1246,24 +1217,24 @@ SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredent
                return SEC_E_UNSUPPORTED_FUNCTION;
 
        status = table->InitializeSecurityContextA(phCredential, phContext,
-                                                  pszTargetName, fContextReq, Reserved1, TargetDataRep,
-                                                  pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
+                pszTargetName, fContextReq, Reserved1, TargetDataRep,
+                pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry);
 
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "InitializeSecurityContextA status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
+SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
+        void* pBuffer)
 {
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1282,18 +1253,18 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, U
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "QueryContextAttributesW status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer)
+SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
+        void* pBuffer)
 {
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1312,7 +1283,7 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, U
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "QueryContextAttributesA status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -1323,7 +1294,6 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext,
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1342,18 +1312,18 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext,
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "QuerySecurityContextToken status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
+SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute,
+        void* pBuffer, ULONG cbBuffer)
 {
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1372,18 +1342,18 @@ SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULO
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "SetContextAttributesW status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer)
+SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute,
+        void* pBuffer, ULONG cbBuffer)
 {
        char* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1402,7 +1372,7 @@ SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULO
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "SetContextAttributesA status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -1413,7 +1383,6 @@ SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
        SEC_CHAR* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableW* table;
-
        Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1432,7 +1401,7 @@ SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "RevertSecurityContext status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
@@ -1440,12 +1409,12 @@ SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext)
 
 /* Message Support */
 
-SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
+SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage,
+        ULONG MessageSeqNo, PULONG pfQOP)
 {
        char* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1464,18 +1433,18 @@ SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBuffer
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "DecryptMessage status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
+SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP,
+        PSecBufferDesc pMessage, ULONG MessageSeqNo)
 {
        char* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1494,18 +1463,18 @@ SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP
        if (status != SEC_E_OK)
        {
                WLog_ERR(TAG, "EncryptMessage status %s [0x%08"PRIX32"]",
-                        GetSecurityStatusString(status), status);
+                        GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo)
+SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
+        PSecBufferDesc pMessage, ULONG MessageSeqNo)
 {
        char* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1524,18 +1493,18 @@ SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP,
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "MakeSignature status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
 }
 
-SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP)
+SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage,
+        ULONG MessageSeqNo, PULONG pfQOP)
 {
        char* Name;
        SECURITY_STATUS status;
        SecurityFunctionTableA* table;
-
        Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
 
        if (!Name)
@@ -1554,7 +1523,7 @@ SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBuffe
        if (IsSecurityStatusError(status))
        {
                WLog_WARN(TAG, "VerifySignature status %s [0x%08"PRIX32"]",
-                         GetSecurityStatusString(status), status);
+                         GetSecurityStatusString(status), status);
        }
 
        return status;
index 66ebaca..7c4eda7 100644 (file)
@@ -37,7 +37,7 @@ int TestAcquireCredentialsHandle(int argc, char* argv[])
        identity.PasswordLength = strlen(test_Password);
        identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
 
-       status = table->AcquireCredentialsHandle(NULL, NTLMSP_NAME,
+       status = table->AcquireCredentialsHandle(NULL, NTLMSSP_NAME,
                        SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration);
 
        if (status != SEC_E_OK)
index e5e9308..ac91a25 100644 (file)
@@ -29,7 +29,7 @@ int TestInitializeSecurityContext(int argc, char* argv[])
 
        table = InitSecurityInterface();
 
-       status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo);
+       status = QuerySecurityPackageInfo(NTLMSSP_NAME, &pPackageInfo);
 
        if (status != SEC_E_OK)
        {
@@ -56,7 +56,7 @@ int TestInitializeSecurityContext(int argc, char* argv[])
        identity.PasswordLength = strlen(test_Password);
        identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI;
 
-       status = table->AcquireCredentialsHandle(NULL, NTLMSP_NAME,
+       status = table->AcquireCredentialsHandle(NULL, NTLMSSP_NAME,
                        SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration);
 
        if (status != SEC_E_OK)
index eb424e6..ffac39d 100644 (file)
@@ -72,8 +72,7 @@ static const BYTE TEST_NTLM_HASH[16] =
 static const BYTE TEST_NTLM_V2_HASH[16] =
 { 0x4c, 0x7f, 0x70, 0x6f, 0x7d, 0xde, 0x05, 0xa9, 0xd1, 0xa0, 0xf4, 0xe7, 0xff, 0xe3, 0xbf, 0xb8 };
 
-//#define NTLM_PACKAGE_NAME    NEGOSSP_NAME
-#define NTLM_PACKAGE_NAME      NTLMSP_NAME
+#define NTLM_PACKAGE_NAME      NTLMSSP_NAME
 
 struct _TEST_NTLM_CLIENT
 {
index a85797f..c86e199 100644 (file)
@@ -11,7 +11,7 @@ int TestQuerySecurityPackageInfo(int argc, char* argv[])
 
        sspi_GlobalInit();
 
-       status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo);
+       status = QuerySecurityPackageInfo(NTLMSSP_NAME, &pPackageInfo);
 
        if (status != SEC_E_OK)
        {