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")
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)
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")
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")
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")
--- /dev/null
+# - 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)
+++ /dev/null
-# - 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)
-
-
/* Plugins */
#cmakedefine BUILTIN_CHANNELS
#cmakedefine WITH_RDPDR
-#cmakedefine WITH_KRB5
/* Debug */
#cmakedefine WITH_DEBUG_CERTIFICATE
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")
freerdp_library_add(${OPENSSL_LIBRARIES})
-if (WITH_KRB5)
- freerdp_library_add(${KRB5_LIBRARIES})
-endif(WITH_KRB5)
-
if(BUILD_TESTING)
add_subdirectory(test)
endif()
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)
{
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);
/**
- * 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.
*
*/
-#define NLA_PKG_NAME NEGOSSP_NAME
+#define NLA_PKG_NAME NEGO_SSP_NAME
#define TERMSRV_SPN_PREFIX "TERMSRV/"
{
if (identity)
{
+ /* Password authentication */
if (identity->User)
{
memset(identity->User, 0, identity->UserLength * 2);
}
/**
- * Initialize NTLMSSP authentication module (client).
+ * Initialize NTLM/Kerberos SSP authentication module (client).
* @param credssp
*/
settings->DisableCredentialsDelegation = TRUE;
if ((!settings->Password) || (!settings->Username)
- || (!strlen(settings->Username)))
+ || (!strlen(settings->Password)) || (!strlen(settings->Username)))
{
PromptPassword = TRUE;
}
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
{
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;
}
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)
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);
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)
if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED))
{
- freerdp_peer *peer = nla->instance->context->peer;
+ freerdp_peer* peer = 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)
nla->havePubKeyAuth = TRUE;
nla->status = nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES,
- &nla->ContextSizes);
+ &nla->ContextSizes);
if (nla->status != SEC_E_OK)
{
*/
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"]",
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);
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;
}
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)
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)
{
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;
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;
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);
if (nla->identity)
{
+ /* TSPasswordCreds */
DomainLength = nla->identity->DomainLength;
UserLength = nla->identity->UserLength;
PasswordLength = nla->identity->PasswordLength;
if (nla->settings->DisableCredentialsDelegation && nla->identity)
{
+ /* TSPasswordCreds */
nla->identity->DomainLength = 0;
nla->identity->UserLength = 0;
nla->identity->PasswordLength = 0;
if (nla->settings->DisableCredentialsDelegation)
{
+ /* TSPasswordCreds */
nla->identity->DomainLength = DomainLength;
nla->identity->UserLength = UserLength;
nla->identity->PasswordLength = PasswordLength;
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)
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;
}
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)
{
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)
/**
* 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>
*
rdpSettings* settings;
rdpTransport* transport;
UINT32 cbMaxToken;
+ SEC_CHAR* packageName;
UINT32 version;
UINT32 errorCode;
ULONG fContextReq;
static void* transport_client_thread(void* arg);
-#ifdef WITH_KRB5
+#ifdef WITH_GSSAPI
#include <krb5.h>
#include <winpr/library.h>
krb5_free_context(context);
return ret;
}
-#endif /* WITH_KRB5 */
+#endif /* WITH_GSSAPI */
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))
transport->settings->Password);
}
else
-#endif /* WITH_KRB5 */
+#endif /* WITH_GSSAPI */
kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
if (!freerdp_get_last_error(transport->context))
#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
typedef struct _SEC_WINNT_AUTH_IDENTITY_W
{
+ /* TSPasswordCreds */
UINT16* User;
UINT32 UserLength;
UINT16* Domain;
typedef struct _SEC_WINNT_AUTH_IDENTITY_A
{
+ /* TSPasswordCreds */
BYTE* User;
UINT32 UserLength;
BYTE* Domain;
struct _SEC_WINNT_AUTH_IDENTITY
{
+ /* TSPasswordCreds */
UINT16* User;
UINT32 UserLength;
UINT16* Domain;
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)
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}
winpr_library_add(${MBEDTLS_LIBRARIES})
endif()
+if(GSS_FOUND)
+ winpr_library_add(${GSS_LIBRARIES})
+endif()
+
if(WIN32)
winpr_library_add(ws2_32)
endif()
--- /dev/null
+/**
+ * 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 */
+};
--- /dev/null
+/**
+ * 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 */
{
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)
* 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)
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;
}
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)
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)
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)
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;
}
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
-
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
-
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!context)
status = context->sspiW->DeleteSecurityContext(&(context->SubContext));
negotiate_ContextFree(context);
-
return status;
}
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
-
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!phContext)
{
NEGOTIATE_CONTEXT* context;
SECURITY_STATUS status = SEC_E_OK;
-
context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext);
if (!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)
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)
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)
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)
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;
}
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;
}
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;
}
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)
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)
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)
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)
"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 =
CtxtHandle SubContext;
+ BOOL kerberos;
SecurityFunctionTableA* sspiA;
SecurityFunctionTableW* sspiW;
};
BOOL IsSecurityStatusError(SECURITY_STATUS status);
+#include "sspi_gss.h"
#include "sspi_winpr.h"
#endif /* WINPR_SSPI_PRIVATE_H */
--- /dev/null
+/**
+ * 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
+}
--- /dev/null
+/**
+ * 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 */
* 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.
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;
const SecPkgInfoA* SecPkgInfoA_LIST[] =
{
&NTLM_SecPkgInfoA,
+ &KERBEROS_SecPkgInfoA,
&NEGOTIATE_SecPkgInfoA,
&CREDSSP_SecPkgInfoA,
&SCHANNEL_SecPkgInfoA
const SecPkgInfoW* SecPkgInfoW_LIST[] =
{
&NTLM_SecPkgInfoW,
+ &KERBEROS_SecPkgInfoW,
&NEGOTIATE_SecPkgInfoW,
&CREDSSP_SecPkgInfoW,
&SCHANNEL_SecPkgInfoW
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 }
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)
CONTEXT_BUFFER_ALLOC_ENTRY* entries;
ContextBufferAllocTable.cEntries = 0;
ContextBufferAllocTable.cMaxEntries *= 2;
-
size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries;
if (!size)
}
ContextBufferAllocTable.entries = entries;
-
- ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], size / 2);
-
+ ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2],
+ size / 2);
return 1;
}
return NULL;
ContextBufferAllocTable.cEntries++;
-
ContextBufferAllocTable.entries[index].contextBuffer = contextBuffer;
ContextBufferAllocTable.entries[index].allocatorIndex = allocatorIndex;
-
return ContextBufferAllocTable.entries[index].contextBuffer;
}
}
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;
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);
}
return NULL;
SecBuffer->pvBuffer = calloc(1, size);
+
if (!SecBuffer->pvBuffer)
return NULL;
return NULL;
SecInvalidateHandle(handle);
-
return handle;
}
return NULL;
pointer = (void*) ~((size_t) handle->dwLower);
-
return pointer;
}
if (!handle)
return;
- handle->dwLower = (ULONG_PTR) (~((size_t) pointer));
+ handle->dwLower = (ULONG_PTR)(~((size_t) pointer));
}
void* sspi_SecureHandleGetUpperPointer(SecHandle* handle)
return NULL;
pointer = (void*) ~((size_t) handle->dwUpper);
-
return pointer;
}
if (!handle)
return;
- handle->dwUpper = (ULONG_PTR) (~((size_t) pointer));
+ handle->dwUpper = (ULONG_PTR)(~((size_t) pointer));
}
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;
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)
identity->Password[identity->PasswordLength] = 0;
}
- identity->PasswordLength = srcIdentity->PasswordLength;
-
+ /* End of login/password authentication */
return 1;
}
if (!sspi_initialized)
{
winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT);
-
sspi_ContextBufferAllocTableNew();
sspi_initialized = TRUE;
}
{
int index;
UINT32 cPackages;
-
cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
for (index = 0; index < (int) cPackages; index++)
{
int index;
UINT32 cPackages;
-
cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST));
for (index = 0; index < (int) cPackages; index++)
int status;
SEC_WCHAR* NameW = NULL;
SecurityFunctionTableW* table;
-
status = ConvertToUnicode(CP_UTF8, 0, Name, -1, &NameW, 0);
if (status <= 0)
table = sspi_GetSecurityFunctionTableWByNameW(NameW);
free(NameW);
-
return table;
}
{
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;
}
}
}
/* 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)
*(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)
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);
*(pcPackages) = cPackages;
*(ppPackageInfo) = pPackageInfo;
-
return SEC_E_OK;
}
int index;
UINT32 cPackages;
SecPkgInfoA* pPackageInfo = (SecPkgInfoA*) contextBuffer;
-
cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST));
for (index = 0; index < (int) cPackages; index++)
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++)
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++)
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);
}
*(ppPackageInfo) = pPackageInfo;
-
return SEC_E_OK;
}
}
*(ppPackageInfo) = NULL;
-
return SEC_E_SECPKG_NOT_FOUND;
}
/* 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);
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);
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)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "ExportSecurityContext status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
char* Name;
SECURITY_STATUS status;
SecurityFunctionTableA* table;
-
Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential);
if (!Name)
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)
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)
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)
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)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "QueryCredentialsAttributesA status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
/* 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)
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;
char* Name = NULL;
SECURITY_STATUS status;
SecurityFunctionTableA* table;
-
Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "ApplyControlToken status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
char* Name = NULL;
SECURITY_STATUS status;
SecurityFunctionTableA* table;
-
Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
char* Name = NULL;
SECURITY_STATUS status;
SecurityFunctionTableA* table;
-
Name = (char*) sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
return SEC_E_INVALID_HANDLE;
sspi_ContextBufferFree(pvContextBuffer);
-
return SEC_E_OK;
}
SEC_CHAR* Name;
SECURITY_STATUS status;
SecurityFunctionTableW* table;
-
Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
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)
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)
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)
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)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "QueryContextAttributesA status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
SEC_CHAR* Name;
SECURITY_STATUS status;
SecurityFunctionTableW* table;
-
Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
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)
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)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "SetContextAttributesA status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
SEC_CHAR* Name;
SECURITY_STATUS status;
SecurityFunctionTableW* table;
-
Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext);
if (!Name)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "RevertSecurityContext status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
/* 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)
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)
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)
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)
if (IsSecurityStatusError(status))
{
WLog_WARN(TAG, "VerifySignature status %s [0x%08"PRIX32"]",
- GetSecurityStatusString(status), status);
+ GetSecurityStatusString(status), status);
}
return status;
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)
table = InitSecurityInterface();
- status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo);
+ status = QuerySecurityPackageInfo(NTLMSSP_NAME, &pPackageInfo);
if (status != SEC_E_OK)
{
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)
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
{
sspi_GlobalInit();
- status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo);
+ status = QuerySecurityPackageInfo(NTLMSSP_NAME, &pPackageInfo);
if (status != SEC_E_OK)
{