From b81f168f0e26241907035eb942204c7fbfd01a77 Mon Sep 17 00:00:00 2001 From: dodo040 Date: Thu, 11 May 2017 18:51:45 +0200 Subject: [PATCH] initial commit for kerberos support --- CMakeLists.txt | 25 +- ci/cmake-preloads/config-debian-squeeze.txt | 2 +- ci/cmake-preloads/config-linux-all.txt | 2 +- ci/cmake-preloads/config-ubuntu-1204.txt | 2 +- cmake/FindGSSAPI.cmake | 288 ++++++ cmake/FindKRB5.cmake | 28 - config.h.in | 1 - libfreerdp/core/CMakeLists.txt | 5 - libfreerdp/core/gateway/ntlm.c | 4 +- libfreerdp/core/nla.c | 301 ++++-- libfreerdp/core/nla.h | 3 +- libfreerdp/core/transport.c | 8 +- winpr/include/winpr/sspi.h | 8 +- winpr/libwinpr/sspi/CMakeLists.txt | 17 +- winpr/libwinpr/sspi/Kerberos/kerberos.c | 734 +++++++++++++++ winpr/libwinpr/sspi/Kerberos/kerberos.h | 83 ++ winpr/libwinpr/sspi/NTLM/ntlm.c | 7 +- winpr/libwinpr/sspi/Negotiate/negotiate.c | 237 +++-- winpr/libwinpr/sspi/Negotiate/negotiate.h | 1 + winpr/libwinpr/sspi/sspi.h | 1 + winpr/libwinpr/sspi/sspi_gss.c | 666 +++++++++++++ winpr/libwinpr/sspi/sspi_gss.h | 883 ++++++++++++++++++ winpr/libwinpr/sspi/sspi_winpr.c | 291 +++--- .../sspi/test/TestAcquireCredentialsHandle.c | 2 +- .../sspi/test/TestInitializeSecurityContext.c | 4 +- winpr/libwinpr/sspi/test/TestNTLM.c | 3 +- .../sspi/test/TestQuerySecurityPackageInfo.c | 2 +- 27 files changed, 3208 insertions(+), 400 deletions(-) create mode 100644 cmake/FindGSSAPI.cmake delete mode 100644 cmake/FindKRB5.cmake create mode 100644 winpr/libwinpr/sspi/Kerberos/kerberos.c create mode 100644 winpr/libwinpr/sspi/Kerberos/kerberos.h create mode 100644 winpr/libwinpr/sspi/sspi_gss.c create mode 100644 winpr/libwinpr/sspi/sspi_gss.h diff --git a/CMakeLists.txt b/CMakeLists.txt index ed064a1b4..444d6a8b6 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -674,14 +674,14 @@ set(OPENH264_FEATURE_TYPE "OPTIONAL") set(OPENH264_FEATURE_PURPOSE "codec") set(OPENH264_FEATURE_DESCRIPTION "use OpenH264 library") -set(KRB5_FEATURE_TYPE "OPTIONAL") -set(KRB5_FEATURE_PURPOSE "auth") -set(KRB5_FEATURE_DESCRIPTION "add kerberos support") - set(GSM_FEATURE_TYPE "OPTIONAL") set(GSM_FEATURE_PURPOSE "codec") set(GSM_FEATURE_DESCRIPTION "GSM audio codec library") +set(GSSAPI_FEATURE_TYPE "OPTIONAL") +set(GSSAPI_FEATURE_PURPOSE "auth") +set(GSSAPI_FEATURE_DESCRIPTION "add kerberos support") + if(WIN32) set(X11_FEATURE_TYPE "DISABLED") set(WAYLAND_FEATURE_TYPE "DISABLED") @@ -775,7 +775,22 @@ find_feature(JPEG ${JPEG_FEATURE_TYPE} ${JPEG_FEATURE_PURPOSE} ${JPEG_FEATURE_DE find_feature(x264 ${X264_FEATURE_TYPE} ${X264_FEATURE_PURPOSE} ${X264_FEATURE_DESCRIPTION}) find_feature(OpenH264 ${OPENH264_FEATURE_TYPE} ${OPENH264_FEATURE_PURPOSE} ${OPENH264_FEATURE_DESCRIPTION}) find_feature(GSM ${GSM_FEATURE_TYPE} ${GSM_FEATURE_PURPOSE} ${GSM_FEATURE_DESCRIPTION}) -find_feature(KRB5 ${KRB5_FEATURE_TYPE} ${KRB5_FEATURE_PURPOSE} ${KRB5_FEATURE_DESCRIPTION}) + +find_feature(GSSAPI ${GSSAPI_FEATURE_TYPE} ${GSSAPI_FEATURE_PURPOSE} ${GSSAPI_FEATURE_DESCRIPTION}) + +if ( (WITH_GSSAPI) AND (NOT GSS_FOUND)) + message(WARNING "-DWITH_GSSAPI=ON is set, but not GSSAPI implementation was found, disabling") +else() + if(GSS_FLAVOUR STREQUAL "MIT") + message(STATUS "MIT Kerberos suppport") + add_definitions("-DWITH_GSSAPI -DWITH_GSSAPI_MIT") + elseif(GSS_FLAVOUR STREQUAL "HEIMDAL") + message(STATUS "Heimdal Kerberos support") + add_definitions("-DWITH_GSSAPI -DWITH_GSSAPI_HEIMDAL") + else() + message(STATUS "Kerberos version not detected") + endif() +endif() if(TARGET_ARCH MATCHES "x86|x64") if (NOT APPLE) diff --git a/ci/cmake-preloads/config-debian-squeeze.txt b/ci/cmake-preloads/config-debian-squeeze.txt index 483a52a4f..1129f9af3 100644 --- a/ci/cmake-preloads/config-debian-squeeze.txt +++ b/ci/cmake-preloads/config-debian-squeeze.txt @@ -2,7 +2,7 @@ message("PRELOADING cache") set (WITH_MANPAGES OFF CACHE BOOL "man pages") set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") set (WITH_CUPS OFF CACHE BOOL "CUPS printing") -set (WITH_KRB5 ON CACHE BOOL "Kerberos support") +set (WITH_GSSAPI ON CACHE BOOL "Kerberos support") set (WITH_ALSA OFF CACHE BOOL "alsa audio") set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support") set (WITH_XV OFF CACHE BOOL "xvideo support") diff --git a/ci/cmake-preloads/config-linux-all.txt b/ci/cmake-preloads/config-linux-all.txt index dd3221b5b..8db0bcd1c 100644 --- a/ci/cmake-preloads/config-linux-all.txt +++ b/ci/cmake-preloads/config-linux-all.txt @@ -7,7 +7,7 @@ set (WITH_PULSE ON CACHE BOOL "pulse") set (WITH_CHANNELS ON CACHE BOOL "channels") set (BUILTIN_CHANNELS ON CACHE BOOL "static channels") set (WITH_CUPS ON CACHE BOOL "cups") -set (WITH_KRB5 ON CACHE BOOL "Kerberos support") +set (WITH_GSSAPI ON CACHE BOOL "Kerberos support") set (WITH_PCSC ON CACHE BOOL "PCSC") set (WITH_JPEG ON CACHE BOOL "jepg") set (WITH_GSTREAMER_0_10 ON CACHE BOOL "gstreamer") diff --git a/ci/cmake-preloads/config-ubuntu-1204.txt b/ci/cmake-preloads/config-ubuntu-1204.txt index 483a52a4f..1129f9af3 100644 --- a/ci/cmake-preloads/config-ubuntu-1204.txt +++ b/ci/cmake-preloads/config-ubuntu-1204.txt @@ -2,7 +2,7 @@ message("PRELOADING cache") set (WITH_MANPAGES OFF CACHE BOOL "man pages") set (CMAKE_BUILD_TYPE "Debug" CACHE STRING "build type") set (WITH_CUPS OFF CACHE BOOL "CUPS printing") -set (WITH_KRB5 ON CACHE BOOL "Kerberos support") +set (WITH_GSSAPI ON CACHE BOOL "Kerberos support") set (WITH_ALSA OFF CACHE BOOL "alsa audio") set (WITH_FFMPEG OFF CACHE BOOL "ffmepg support") set (WITH_XV OFF CACHE BOOL "xvideo support") diff --git a/cmake/FindGSSAPI.cmake b/cmake/FindGSSAPI.cmake new file mode 100644 index 000000000..9cc87e968 --- /dev/null +++ b/cmake/FindGSSAPI.cmake @@ -0,0 +1,288 @@ +# - Try to find the GSS Kerberos library +# Once done this will define +# +# GSS_ROOT_DIR - Set this variable to the root installation of GSS +# +# Read-Only variables: +# GSS_FOUND - system has the Heimdal library +# GSS_FLAVOUR - "MIT" or "Heimdal" if anything found. +# GSS_INCLUDE_DIR - the Heimdal include directory +# GSS_LIBRARIES - The libraries needed to use GSS +# GSS_LINK_DIRECTORIES - Directories to add to linker search path +# GSS_LINKER_FLAGS - Additional linker flags +# GSS_COMPILER_FLAGS - Additional compiler flags +# GSS_VERSION - This is set to version advertised by pkg-config or read from manifest. +# In case the library is found but no version info availabe it'll be set to "unknown" + +set(_MIT_MODNAME mit-krb5-gssapi) +set(_HEIMDAL_MODNAME heimdal-gssapi) + +include(CheckIncludeFile) +include(CheckIncludeFiles) +include(CheckTypeSize) + +set(_GSS_ROOT_HINTS + "${GSS_ROOT_DIR}" + "$ENV{GSS_ROOT_DIR}" +) + +# try to find library using system pkg-config if user didn't specify root dir +if(NOT GSS_ROOT_DIR AND NOT "$ENV{GSS_ROOT_DIR}") + if(UNIX) + find_package(PkgConfig QUIET) + pkg_search_module(_GSS_PKG ${_MIT_MODNAME} ${_HEIMDAL_MODNAME}) + list(APPEND _GSS_ROOT_HINTS "${_GSS_PKG_PREFIX}") + elseif(WIN32) + list(APPEND _GSS_ROOT_HINTS "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos;InstallDir]") + endif() +endif() + +if(NOT _GSS_FOUND) #not found by pkg-config. Let's take more traditional approach. + find_file(_GSS_CONFIGURE_SCRIPT + NAMES + "krb5-config" + HINTS + ${_GSS_ROOT_HINTS} + PATH_SUFFIXES + bin + NO_CMAKE_PATH + NO_CMAKE_ENVIRONMENT_PATH + ) + + # if not found in user-supplied directories, maybe system knows better + find_file(_GSS_CONFIGURE_SCRIPT + NAMES + "krb5-config" + PATH_SUFFIXES + bin + ) + + if(_GSS_CONFIGURE_SCRIPT) + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--cflags" "gssapi" + OUTPUT_VARIABLE _GSS_CFLAGS + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + if(NOT _GSS_CONFIGURE_FAILED) # 0 means success + # should also work in an odd case when multiple directories are given + string(STRIP "${_GSS_CFLAGS}" _GSS_CFLAGS) + string(REGEX REPLACE " +-I" ";" _GSS_CFLAGS "${_GSS_CFLAGS}") + string(REGEX REPLACE " +-([^I][^ \\t;]*)" ";-\\1" _GSS_CFLAGS "${_GSS_CFLAGS}") + + foreach(_flag ${_GSS_CFLAGS}) + if(_flag MATCHES "^-I.*") + string(REGEX REPLACE "^-I" "" _val "${_flag}") + list(APPEND _GSS_INCLUDE_DIR "${_val}") + else() + list(APPEND _GSS_COMPILER_FLAGS "${_flag}") + endif() + endforeach() + endif() + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--libs" "gssapi" + OUTPUT_VARIABLE _GSS_LIB_FLAGS + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + if(NOT _GSS_CONFIGURE_FAILED) # 0 means success + # this script gives us libraries and link directories. Blah. We have to deal with it. + # string(STRIP "krb5support ${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS) + string(STRIP "${_GSS_LIB_FLAGS}" _GSS_LIB_FLAGS) + string(REGEX REPLACE " +-(L|l)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}") + string(REGEX REPLACE " +-([^Ll][^ \\t;]*)" ";-\\1" _GSS_LIB_FLAGS "${_GSS_LIB_FLAGS}") + + foreach(_flag ${_GSS_LIB_FLAGS}) + if(_flag MATCHES "^-l.*") + string(REGEX REPLACE "^-l" "" _val "${_flag}") + list(APPEND _GSS_LIBRARIES "${_val}") + elseif(_flag MATCHES "^-L.*") + string(REGEX REPLACE "^-L" "" _val "${_flag}") + list(APPEND _GSS_LINK_DIRECTORIES "${_val}") + else() + list(APPEND _GSS_LINKER_FLAGS "${_flag}") + endif() + endforeach() + endif() + + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--version" + OUTPUT_VARIABLE _GSS_VERSION + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + + # older versions may not have the "--version" parameter. In this case we just don't care. + if(_GSS_CONFIGURE_FAILED) + set(_GSS_VERSION 0) + endif() + + + execute_process( + COMMAND ${_GSS_CONFIGURE_SCRIPT} "--vendor" + OUTPUT_VARIABLE _GSS_VENDOR + RESULT_VARIABLE _GSS_CONFIGURE_FAILED + ) + + # older versions may not have the "--vendor" parameter. In this case we just don't care. + if(_GSS_CONFIGURE_FAILED) + set(GSS_FLAVOUR "Heimdal") # most probably, shouldn't really matter + else() + if(_GSS_VENDOR MATCHES ".*H|heimdal.*") + set(GSS_FLAVOUR "Heimdal") + else() + set(GSS_FLAVOUR "MIT") + endif() + endif() + + else() # either there is no config script or we are on platform that doesn't provide one (Windows?) + + find_path(_GSS_INCLUDE_DIR + NAMES + "gssapi/gssapi.h" + HINTS + ${_GSS_ROOT_HINTS} + PATH_SUFFIXES + include + inc + ) + + if(_GSS_INCLUDE_DIR) #jay, we've found something + set(CMAKE_REQUIRED_INCLUDES "${_GSS_INCLUDE_DIR}") + check_include_files( "gssapi/gssapi_generic.h;gssapi/gssapi_krb5.h" _GSS_HAVE_MIT_HEADERS) + + if(_GSS_HAVE_MIT_HEADERS) + set(GSS_FLAVOUR "MIT") + else() + # prevent compiling the header - just check if we can include it + set(CMAKE_REQUIRED_DEFINITIONS "${CMAKE_REQUIRED_DEFINITIONS} -D__ROKEN_H__") + check_include_file( "roken.h" _GSS_HAVE_ROKEN_H) + + check_include_file( "heimdal/roken.h" _GSS_HAVE_HEIMDAL_ROKEN_H) + if(_GSS_HAVE_ROKEN_H OR _GSS_HAVE_HEIMDAL_ROKEN_H) + set(GSS_FLAVOUR "Heimdal") + endif() + set(CMAKE_REQUIRED_DEFINITIONS "") + endif() + else() + # I'm not convinced if this is the right way but this is what autotools do at the moment + find_path(_GSS_INCLUDE_DIR + NAMES + "gssapi.h" + HINTS + ${_GSS_ROOT_HINTS} + PATH_SUFFIXES + include + inc + ) + + if(_GSS_INCLUDE_DIR) + set(GSS_FLAVOUR "Heimdal") + endif() + endif() + + # if we have headers, check if we can link libraries + if(GSS_FLAVOUR) + set(_GSS_LIBDIR_SUFFIXES "") + set(_GSS_LIBDIR_HINTS ${_GSS_ROOT_HINTS}) + get_filename_component(_GSS_CALCULATED_POTENTIAL_ROOT "${_GSS_INCLUDE_DIR}" PATH) + list(APPEND _GSS_LIBDIR_HINTS ${_GSS_CALCULATED_POTENTIAL_ROOT}) + + if(WIN32) + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + list(APPEND _GSS_LIBDIR_SUFFIXES "lib/AMD64") + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi64") + else() + set(_GSS_LIBNAME "libgssapi") + endif() + else() + list(APPEND _GSS_LIBDIR_SUFFIXES "lib/i386") + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi32") + else() + set(_GSS_LIBNAME "libgssapi") + endif() + endif() + else() + list(APPEND _GSS_LIBDIR_SUFFIXES "lib;lib64") # those suffixes are not checked for HINTS + if(GSS_FLAVOUR STREQUAL "MIT") + set(_GSS_LIBNAME "gssapi_krb5") + else() + set(_GSS_LIBNAME "gssapi") + endif() + endif() + + find_library(_GSS_LIBRARIES + NAMES + ${_GSS_LIBNAME} + HINTS + ${_GSS_LIBDIR_HINTS} + PATH_SUFFIXES + ${_GSS_LIBDIR_SUFFIXES} + ) + + endif() + + endif() +else() + if(_GSS_PKG_${_MIT_MODNAME}_VERSION) + set(GSS_FLAVOUR "MIT") + set(_GSS_VERSION _GSS_PKG_${_MIT_MODNAME}_VERSION) + else() + set(GSS_FLAVOUR "Heimdal") + set(_GSS_VERSION _GSS_PKG_${_MIT_HEIMDAL}_VERSION) + endif() +endif() + +set(GSS_INCLUDE_DIR ${_GSS_INCLUDE_DIR}) +set(GSS_LIBRARIES ${_GSS_LIBRARIES}) +set(GSS_LINK_DIRECTORIES ${_GSS_LINK_DIRECTORIES}) +set(GSS_LINKER_FLAGS ${_GSS_LINKER_FLAGS}) +set(GSS_COMPILER_FLAGS ${_GSS_COMPILER_FLAGS}) +set(GSS_VERSION ${_GSS_VERSION}) + +if(GSS_FLAVOUR) + + if(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "Heimdal") + if(CMAKE_SIZEOF_VOID_P EQUAL 8) + set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.amd64.manifest") + else() + set(HEIMDAL_MANIFEST_FILE "Heimdal.Application.x86.manifest") + endif() + + if(EXISTS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}") + file(STRINGS "${GSS_INCLUDE_DIR}/${HEIMDAL_MANIFEST_FILE}" heimdal_version_str + REGEX "^.*version=\"[0-9]\\.[^\"]+\".*$") + + string(REGEX MATCH "[0-9]\\.[^\"]+" + GSS_VERSION "${heimdal_version_str}") + endif() + + if(NOT GSS_VERSION) + set(GSS_VERSION "Heimdal Unknown") + endif() + elseif(NOT GSS_VERSION AND GSS_FLAVOUR STREQUAL "MIT") + get_filename_component(_MIT_VERSION "[HKEY_LOCAL_MACHINE\\SOFTWARE\\MIT\\Kerberos\\SDK\\CurrentVersion;VersionString]" NAME CACHE) + if(WIN32 AND _MIT_VERSION) + set(GSS_VERSION "${_MIT_VERSION}") + else() + set(GSS_VERSION "MIT Unknown") + endif() + endif() +endif() + + +include(FindPackageHandleStandardArgs) + +set(_GSS_REQUIRED_VARS GSS_LIBRARIES GSS_FLAVOUR) + +find_package_handle_standard_args(GSS + REQUIRED_VARS + ${_GSS_REQUIRED_VARS} + VERSION_VAR + GSS_VERSION + FAIL_MESSAGE + "Could NOT find GSS, try to set the path to GSS root folder in the system variable GSS_ROOT_DIR" +) + +mark_as_advanced(GSS_INCLUDE_DIR GSS_LIBRARIES) diff --git a/cmake/FindKRB5.cmake b/cmake/FindKRB5.cmake deleted file mode 100644 index 477f50e2f..000000000 --- a/cmake/FindKRB5.cmake +++ /dev/null @@ -1,28 +0,0 @@ -# - Try to find krb5 -# Once done this will define -# KRB5_FOUND - pcsc was found -# KRB5_INCLUDE_DIRS - pcsc include directories -# KRB5_LIBRARIES - libraries needed for linking - -include(FindPkgConfig) - -if(PKG_CONFIG_FOUND) - pkg_check_modules(PC_KRB5 QUIET libkrb5) -endif() - -find_path(KRB5_INCLUDE_DIR krb5.h - HINTS ${PC_KRB5_INCLUDEDIR} ${PC_KRB5_INCLUDE_DIRS} - PATH_SUFFIXES KRB5) - -find_library(KRB5_LIBRARY NAMES krb5 - HINTS ${PC_KRB5_LIBDIR} ${PC_KRB5_LIBRARY_DIRS}) - -include(FindPackageHandleStandardArgs) -find_package_handle_standard_args(KRB5 DEFAULT_MSG KRB5_LIBRARY KRB5_INCLUDE_DIR) - -set(KRB5_LIBRARIES ${KRB5_LIBRARY}) -set(KRB5_INCLUDE_DIRS ${KRB5_INCLUDE_DIR}) - -mark_as_advanced(KRB5_INCLUDE_DIR KRB5_LIBRARY) - - diff --git a/config.h.in b/config.h.in index a61d7b35f..f1a2a0693 100644 --- a/config.h.in +++ b/config.h.in @@ -61,7 +61,6 @@ /* Plugins */ #cmakedefine BUILTIN_CHANNELS #cmakedefine WITH_RDPDR -#cmakedefine WITH_KRB5 /* Debug */ #cmakedefine WITH_DEBUG_CERTIFICATE diff --git a/libfreerdp/core/CMakeLists.txt b/libfreerdp/core/CMakeLists.txt index e73946ea5..4c69828d7 100644 --- a/libfreerdp/core/CMakeLists.txt +++ b/libfreerdp/core/CMakeLists.txt @@ -21,7 +21,6 @@ set(MODULE_PREFIX "FREERDP_CORE") freerdp_definition_add(-DEXT_PATH="${FREERDP_EXTENSION_PATH}") freerdp_include_directory_add(${OPENSSL_INCLUDE_DIR}) -freerdp_include_directory_add(${KRB5_INCLUDE_DIRS}) set(${MODULE_PREFIX}_GATEWAY_DIR "gateway") @@ -141,10 +140,6 @@ endif() freerdp_library_add(${OPENSSL_LIBRARIES}) -if (WITH_KRB5) - freerdp_library_add(${KRB5_LIBRARIES}) -endif(WITH_KRB5) - if(BUILD_TESTING) add_subdirectory(test) endif() diff --git a/libfreerdp/core/gateway/ntlm.c b/libfreerdp/core/gateway/ntlm.c index 18dfc108e..e52a0d208 100644 --- a/libfreerdp/core/gateway/ntlm.c +++ b/libfreerdp/core/gateway/ntlm.c @@ -49,7 +49,7 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* sspi_SetAuthIdentity(&(ntlm->identity), user, domain, password); - status = ntlm->table->QuerySecurityPackageInfo(NTLMSP_NAME, &ntlm->pPackageInfo); + status = ntlm->table->QuerySecurityPackageInfo(NTLMSSP_NAME, &ntlm->pPackageInfo); if (status != SEC_E_OK) { @@ -60,7 +60,7 @@ BOOL ntlm_client_init(rdpNtlm* ntlm, BOOL http, char* user, char* domain, char* ntlm->cbMaxToken = ntlm->pPackageInfo->cbMaxToken; - status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, + status = ntlm->table->AcquireCredentialsHandle(NULL, NTLMSSP_NAME, SECPKG_CRED_OUTBOUND, NULL, &ntlm->identity, NULL, NULL, &ntlm->credentials, &ntlm->expiration); diff --git a/libfreerdp/core/nla.c b/libfreerdp/core/nla.c index 47958ead0..e945c74de 100644 --- a/libfreerdp/core/nla.c +++ b/libfreerdp/core/nla.c @@ -1,11 +1,12 @@ /** - * WinPR: Windows Portable Runtime + * FreeRDP: A Remote Desktop Protocol Implementation * Network Level Authentication (NLA) * * Copyright 2010-2012 Marc-Andre Moreau * Copyright 2015 Thincast Technologies GmbH * Copyright 2015 DI (FH) Martin Haimberger * Copyright 2016 Martin Fleisz + * Copyright 2017 Dorian Ducournau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -94,7 +95,7 @@ * */ -#define NLA_PKG_NAME NEGOSSP_NAME +#define NLA_PKG_NAME NEGO_SSP_NAME #define TERMSRV_SPN_PREFIX "TERMSRV/" @@ -116,6 +117,7 @@ void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity) { if (identity) { + /* Password authentication */ if (identity->User) { memset(identity->User, 0, identity->UserLength * 2); @@ -139,7 +141,7 @@ void nla_identity_free(SEC_WINNT_AUTH_IDENTITY* identity) } /** - * Initialize NTLMSSP authentication module (client). + * Initialize NTLM/Kerberos SSP authentication module (client). * @param credssp */ @@ -159,7 +161,7 @@ static int nla_client_init(rdpNla* nla) settings->DisableCredentialsDelegation = TRUE; if ((!settings->Password) || (!settings->Username) - || (!strlen(settings->Username))) + || (!strlen(settings->Password)) || (!strlen(settings->Username))) { PromptPassword = TRUE; } @@ -220,8 +222,11 @@ static int nla_client_init(rdpNla* nla) nla->identity = NULL; } else - sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain, - settings->Password); + { + if (sspi_SetAuthIdentity(nla->identity, settings->Username, settings->Domain, + settings->Password) < 0) + return -1; + } #ifndef _WIN32 { @@ -262,7 +267,7 @@ static int nla_client_init(rdpNla* nla) if (!sspi_SecBufferAlloc(&nla->PublicKey, tls->PublicKeyLength)) { - WLog_ERR(TAG, "Failed to allocate sspic secBuffer"); + WLog_ERR(TAG, "Failed to allocate sspi secBuffer"); return -1; } @@ -282,6 +287,17 @@ static int nla_client_init(rdpNla* nla) nla->ServicePrincipalName = spn; #endif nla->table = InitSecurityInterfaceEx(0); +#ifdef WITH_GSSAPI /* KERBEROS SSP */ + nla->status = nla->table->QuerySecurityPackageInfo(KERBEROS_SSP_NAME, &nla->pPackageInfo); + + if (nla->status != SEC_E_OK) + { + WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08"PRIX32"]", + GetSecurityStatusString(nla->status), nla->status); + return -1; + } + +#else /* NTLM SSP */ nla->status = nla->table->QuerySecurityPackageInfo(NLA_PKG_NAME, &nla->pPackageInfo); if (nla->status != SEC_E_OK) @@ -291,7 +307,11 @@ static int nla_client_init(rdpNla* nla) return -1; } +#endif nla->cbMaxToken = nla->pPackageInfo->cbMaxToken; + nla->packageName = nla->pPackageInfo->Name; + WLog_DBG(TAG, "%s %"PRIu32" : packageName=%s ; cbMaxToken=%d", __FUNCTION__, __LINE__, + nla->packageName, nla->cbMaxToken); nla->status = nla->table->AcquireCredentialsHandle(NULL, NLA_PKG_NAME, SECPKG_CRED_OUTBOUND, NULL, nla->identity, NULL, NULL, &nla->credentials, &nla->expiration); @@ -345,6 +365,32 @@ int nla_client_begin(rdpNla* nla) WLog_VRB(TAG, " InitializeSecurityContext status %s [0x%08"PRIX32"]", GetSecurityStatusString(nla->status), nla->status); + /* Handle kerberos context initialization failure. + * After kerberos failed initialize NTLM context */ + if (nla->status == SEC_E_NO_CREDENTIALS) + { + nla->status = nla->table->InitializeSecurityContext(&nla->credentials, + NULL, nla->ServicePrincipalName, nla->fContextReq, 0, + SECURITY_NATIVE_DREP, NULL, 0, &nla->context, + &nla->outputBufferDesc, &nla->pfContextAttr, &nla->expiration); + WLog_VRB(TAG, " InitializeSecurityContext status %s [0x%08"PRIX32"]", + GetSecurityStatusString(nla->status), nla->status); + + if (nla->status) + { + SECURITY_STATUS status = nla->table->QuerySecurityPackageInfo(NTLM_SSP_NAME, &nla->pPackageInfo); + + if (status != SEC_E_OK) + { + WLog_ERR(TAG, "QuerySecurityPackageInfo status %s [0x%08"PRIX32"]", + GetSecurityStatusString(nla->status), status); + return -1; + } + + nla->cbMaxToken = nla->pPackageInfo->cbMaxToken; + nla->packageName = nla->pPackageInfo->Name; + } + } if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED)) { if (nla->table->CompleteAuthToken) @@ -719,28 +765,32 @@ static int nla_server_authenticate(rdpNla* nla) if ((nla->status == SEC_I_COMPLETE_AND_CONTINUE) || (nla->status == SEC_I_COMPLETE_NEEDED)) { - freerdp_peer *peer = nla->instance->context->peer; + freerdp_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) @@ -781,7 +831,7 @@ static int nla_server_authenticate(rdpNla* nla) nla->havePubKeyAuth = TRUE; nla->status = nla->table->QueryContextAttributes(&nla->context, SECPKG_ATTR_SIZES, - &nla->ContextSizes); + &nla->ContextSizes); if (nla->status != SEC_E_OK) { @@ -815,21 +865,21 @@ static int nla_server_authenticate(rdpNla* nla) */ switch (GetLastError()) { - case ERROR_PASSWORD_MUST_CHANGE: - nla->errorCode = STATUS_PASSWORD_MUST_CHANGE; - break; + case ERROR_PASSWORD_MUST_CHANGE: + nla->errorCode = STATUS_PASSWORD_MUST_CHANGE; + break; - case ERROR_PASSWORD_EXPIRED: - nla->errorCode = STATUS_PASSWORD_EXPIRED; - break; + case ERROR_PASSWORD_EXPIRED: + nla->errorCode = STATUS_PASSWORD_EXPIRED; + break; - case ERROR_ACCOUNT_DISABLED: - nla->errorCode = STATUS_ACCOUNT_DISABLED; - break; + case ERROR_ACCOUNT_DISABLED: + nla->errorCode = STATUS_ACCOUNT_DISABLED; + break; - default: - nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError()); - break; + default: + nla->errorCode = NTSTATUS_FROM_WIN32(GetLastError()); + break; } WLog_ERR(TAG, "AcceptSecurityContext status %s [0x%08"PRIX32"]", @@ -962,18 +1012,29 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla) int public_key_length; public_key_length = nla->PublicKey.cbBuffer; - if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, nla->ContextSizes.cbSecurityTrailer + public_key_length)) + if (!sspi_SecBufferAlloc(&nla->pubKeyAuth, public_key_length + nla->ContextSizes.cbSecurityTrailer)) return SEC_E_INSUFFICIENT_MEMORY; - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; - Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; - Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */ - Buffers[1].cbBuffer = public_key_length; - Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer; - CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer); + if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0) + { + Buffers[0].BufferType = SECBUFFER_DATA; /* TLS Public Key */ + Buffers[0].cbBuffer = public_key_length; + Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; + CopyMemory(Buffers[0].pvBuffer, nla->PublicKey.pvBuffer, Buffers[0].cbBuffer); + } + else if ((strcmp(nla->packageName, NEGO_SSP_NAME) != 0) || + (strcmp(nla->packageName, NTLM_SSP_NAME) != 0)) + { + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; + Buffers[0].pvBuffer = nla->pubKeyAuth.pvBuffer; + Buffers[1].BufferType = SECBUFFER_DATA; /* TLS Public Key */ + Buffers[1].cbBuffer = public_key_length; + Buffers[1].pvBuffer = ((BYTE*) nla->pubKeyAuth.pvBuffer) + nla->ContextSizes.cbSecurityTrailer; + CopyMemory(Buffers[1].pvBuffer, nla->PublicKey.pvBuffer, Buffers[1].cbBuffer); + } - if (nla->server) + if ((strcmp(nla->packageName, KERBEROS_SSP_NAME) != 0) && nla->server) { /* server echos the public key +1 */ ap_integer_increment_le((BYTE*) Buffers[1].pvBuffer, Buffers[1].cbBuffer); @@ -991,14 +1052,6 @@ SECURITY_STATUS nla_encrypt_public_key_echo(rdpNla* nla) return status; } - if (Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer) - { - /* EncryptMessage may not use all the signature space, so we need to shrink the excess */ - MoveMemory(((BYTE*)nla->pubKeyAuth.pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer, - Buffers[1].cbBuffer); - nla->pubKeyAuth.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer; - } - return status; } @@ -1022,23 +1075,43 @@ SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla) return SEC_E_INVALID_TOKEN; } + if ((nla->PublicKey.cbBuffer + nla->ContextSizes.cbSecurityTrailer) != nla->pubKeyAuth.cbBuffer) + { + WLog_ERR(TAG, "unexpected pubKeyAuth buffer size: %"PRIu32"", (int) nla->pubKeyAuth.cbBuffer); + return SEC_E_INVALID_TOKEN; + } + length = nla->pubKeyAuth.cbBuffer; buffer = (BYTE*) malloc(length); if (!buffer) return SEC_E_INSUFFICIENT_MEMORY; - CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length); - public_key_length = nla->PublicKey.cbBuffer; - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[0].cbBuffer = signature_length; - Buffers[0].pvBuffer = buffer; - Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */ - Buffers[1].cbBuffer = length - signature_length; - Buffers[1].pvBuffer = buffer + signature_length; - Message.cBuffers = 2; - Message.ulVersion = SECBUFFER_VERSION; - Message.pBuffers = (PSecBuffer) &Buffers; + if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0) + { + CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length); + Buffers[0].BufferType = SECBUFFER_DATA; /* Wrapped and encrypted TLS Public Key */ + Buffers[0].cbBuffer = length; + Buffers[0].pvBuffer = buffer; + Message.cBuffers = 1; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } + else if ((strcmp(nla->packageName, NEGO_SSP_NAME) == 0) || + (strcmp(nla->packageName, NTLM_SSP_NAME) == 0)) + { + CopyMemory(buffer, nla->pubKeyAuth.pvBuffer, length); + public_key_length = nla->PublicKey.cbBuffer; + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = signature_length; + Buffers[0].pvBuffer = buffer; + Buffers[1].BufferType = SECBUFFER_DATA; /* Encrypted TLS Public Key */ + Buffers[1].cbBuffer = length - signature_length; + Buffers[1].pvBuffer = buffer + signature_length; + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP); if (status != SEC_E_OK) @@ -1049,8 +1122,17 @@ SECURITY_STATUS nla_decrypt_public_key_echo(rdpNla* nla) return status; } - public_key1 = (BYTE*) nla->PublicKey.pvBuffer; - public_key2 = (BYTE*) Buffers[1].pvBuffer; + if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0) + { + public_key1 = public_key2 = (BYTE*) nla->pubKeyAuth.pvBuffer ; + public_key_length = length; + } + else if ((strcmp(nla->packageName, NEGO_SSP_NAME) == 0) || + (strcmp(nla->packageName, NTLM_SSP_NAME) == 0)) + { + public_key1 = (BYTE*) nla->PublicKey.pvBuffer; + public_key2 = (BYTE*) Buffers[1].pvBuffer; + } if (!nla->server) { @@ -1087,6 +1169,15 @@ int nla_sizeof_ts_password_creds(rdpNla* nla) return length; } +static int nla_sizeof_ts_credentials(rdpNla* nla) +{ + int size = 0; + size += ber_sizeof_integer(1); + size += ber_sizeof_contextual_tag(ber_sizeof_integer(1)); + size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla))); + return size; +} + BOOL nla_read_ts_password_creds(rdpNla* nla, wStream* s) { int length; @@ -1207,15 +1298,6 @@ static int nla_write_ts_password_creds(rdpNla* nla, wStream* s) return size; } -static int nla_sizeof_ts_credentials(rdpNla* nla) -{ - int size = 0; - size += ber_sizeof_integer(1); - size += ber_sizeof_contextual_tag(ber_sizeof_integer(1)); - size += ber_sizeof_sequence_octet_string(ber_sizeof_sequence(nla_sizeof_ts_password_creds(nla))); - return size; -} - static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials) { wStream* s; @@ -1234,9 +1316,9 @@ static BOOL nla_read_ts_credentials(rdpNla* nla, PSecBuffer ts_credentials) ret = ber_read_sequence_tag(s, &length) && /* [0] credType (INTEGER) */ ber_read_contextual_tag(s, 0, &length, TRUE) && - ber_read_integer(s, NULL) && - /* [1] credentials (OCTET STRING) */ - ber_read_contextual_tag(s, 1, &length, TRUE) && + ber_read_integer(s, NULL); + /* [1] credentials (OCTET STRING) */ + ret += ber_read_contextual_tag(s, 1, &length, TRUE) && ber_read_octet_string_tag(s, &ts_password_creds_length) && nla_read_ts_password_creds(nla, s); Stream_Free(s, FALSE); @@ -1276,6 +1358,7 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla) if (nla->identity) { + /* TSPasswordCreds */ DomainLength = nla->identity->DomainLength; UserLength = nla->identity->UserLength; PasswordLength = nla->identity->PasswordLength; @@ -1283,6 +1366,7 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla) if (nla->settings->DisableCredentialsDelegation && nla->identity) { + /* TSPasswordCreds */ nla->identity->DomainLength = 0; nla->identity->UserLength = 0; nla->identity->PasswordLength = 0; @@ -1309,6 +1393,7 @@ static BOOL nla_encode_ts_credentials(rdpNla* nla) if (nla->settings->DisableCredentialsDelegation) { + /* TSPasswordCreds */ nla->identity->DomainLength = DomainLength; nla->identity->UserLength = UserLength; nla->identity->PasswordLength = PasswordLength; @@ -1328,20 +1413,34 @@ static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla) return SEC_E_INSUFFICIENT_MEMORY; if (!sspi_SecBufferAlloc(&nla->authInfo, - nla->ContextSizes.cbSecurityTrailer + nla->tsCredentials.cbBuffer)) + nla->tsCredentials.cbBuffer + nla->ContextSizes.cbSecurityTrailer)) return SEC_E_INSUFFICIENT_MEMORY; - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; - Buffers[0].pvBuffer = nla->authInfo.pvBuffer; - ZeroMemory(Buffers[0].pvBuffer, Buffers[0].cbBuffer); - Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ - Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer; - Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer]; - CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer); - Message.cBuffers = 2; - Message.ulVersion = SECBUFFER_VERSION; - Message.pBuffers = (PSecBuffer) &Buffers; + if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0) + { + Buffers[0].BufferType = SECBUFFER_DATA; /* TSCredentials */ + Buffers[0].cbBuffer = nla->tsCredentials.cbBuffer; + Buffers[0].pvBuffer = nla->authInfo.pvBuffer; + CopyMemory(Buffers[0].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[0].cbBuffer); + Message.cBuffers = 1; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } + else if ((strcmp(nla->packageName, NEGO_SSP_NAME) == 0) || + (strcmp(nla->packageName, NTLM_SSP_NAME) == 0)) + { + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; + Buffers[0].pvBuffer = nla->authInfo.pvBuffer; + MoveMemory(Buffers[0].pvBuffer, nla->authInfo.pvBuffer, Buffers[0].cbBuffer); + Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ + Buffers[1].cbBuffer = nla->tsCredentials.cbBuffer; + Buffers[1].pvBuffer = &((BYTE*) nla->authInfo.pvBuffer)[Buffers[0].cbBuffer]; + CopyMemory(Buffers[1].pvBuffer, nla->tsCredentials.pvBuffer, Buffers[1].cbBuffer); + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } status = nla->table->EncryptMessage(&nla->context, 0, &Message, nla->sendSeqNum++); if (status != SEC_E_OK) @@ -1351,14 +1450,6 @@ static SECURITY_STATUS nla_encrypt_ts_credentials(rdpNla* nla) return status; } - if (Buffers[0].cbBuffer < nla->ContextSizes.cbSecurityTrailer) - { - /* EncryptMessage may not use all the signature space, so we need to shrink the excess */ - MoveMemory(((BYTE*)nla->authInfo.pvBuffer) + Buffers[0].cbBuffer, Buffers[1].pvBuffer, - Buffers[1].cbBuffer); - nla->authInfo.cbBuffer = Buffers[0].cbBuffer + Buffers[1].cbBuffer; - } - return SEC_E_OK; } @@ -1370,8 +1461,6 @@ static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla) SecBuffer Buffers[2]; SecBufferDesc Message; SECURITY_STATUS status; - Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ - Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ if (nla->authInfo.cbBuffer < 1) { @@ -1385,14 +1474,30 @@ static SECURITY_STATUS nla_decrypt_ts_credentials(rdpNla* nla) if (!buffer) return SEC_E_INSUFFICIENT_MEMORY; - CopyMemory(buffer, nla->authInfo.pvBuffer, length); - Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; - Buffers[0].pvBuffer = buffer; - Buffers[1].cbBuffer = length - nla->ContextSizes.cbSecurityTrailer; - Buffers[1].pvBuffer = &buffer[nla->ContextSizes.cbSecurityTrailer]; - Message.cBuffers = 2; - Message.ulVersion = SECBUFFER_VERSION; - Message.pBuffers = (PSecBuffer) &Buffers; + if (strcmp(nla->packageName, KERBEROS_SSP_NAME) == 0) + { + CopyMemory(buffer, nla->authInfo.pvBuffer, length); + Buffers[0].BufferType = SECBUFFER_DATA; /* Wrapped and encrypted TSCredentials */ + Buffers[0].cbBuffer = length; + Buffers[0].pvBuffer = buffer; + Message.cBuffers = 1; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } + else if ((strcmp(nla->packageName, NEGO_SSP_NAME) == 0) || + (strcmp(nla->packageName, NTLM_SSP_NAME) == 0)) + { + CopyMemory(buffer, nla->authInfo.pvBuffer, length); + Buffers[0].BufferType = SECBUFFER_TOKEN; /* Signature */ + Buffers[0].cbBuffer = nla->ContextSizes.cbSecurityTrailer; + Buffers[0].pvBuffer = buffer; + Buffers[1].BufferType = SECBUFFER_DATA; /* TSCredentials */ + Buffers[1].cbBuffer = length - nla->ContextSizes.cbSecurityTrailer; + Buffers[1].pvBuffer = &buffer[ Buffers[0].cbBuffer ]; + Message.cBuffers = 2; + Message.ulVersion = SECBUFFER_VERSION; + Message.pBuffers = (PSecBuffer) &Buffers; + } status = nla->table->DecryptMessage(&nla->context, &Message, nla->recvSeqNum++, &pfQOP); if (status != SEC_E_OK) diff --git a/libfreerdp/core/nla.h b/libfreerdp/core/nla.h index 5039fb43c..2f72b6497 100644 --- a/libfreerdp/core/nla.h +++ b/libfreerdp/core/nla.h @@ -1,6 +1,6 @@ /** * FreeRDP: A Remote Desktop Protocol Implementation - * Credential Security Support Provider (CredSSP) + * Network Level Authentication (NLA) * * Copyright 2010-2012 Marc-Andre Moreau * @@ -60,6 +60,7 @@ struct rdp_nla rdpSettings* settings; rdpTransport* transport; UINT32 cbMaxToken; + SEC_CHAR* packageName; UINT32 version; UINT32 errorCode; ULONG fContextReq; diff --git a/libfreerdp/core/transport.c b/libfreerdp/core/transport.c index fb999522c..4fdceb988 100644 --- a/libfreerdp/core/transport.c +++ b/libfreerdp/core/transport.c @@ -59,7 +59,7 @@ static void* transport_client_thread(void* arg); -#ifdef WITH_KRB5 +#ifdef WITH_GSSAPI #include #include @@ -150,7 +150,7 @@ out: krb5_free_context(context); return ret; } -#endif /* WITH_KRB5 */ +#endif /* WITH_GSSAPI */ static void transport_ssl_cb(SSL* ssl, int where, int ret) { @@ -174,7 +174,7 @@ static void transport_ssl_cb(SSL* ssl, int where, int ret) if (transport->NlaMode) { UINT32 kret = 0; -#ifdef WITH_KRB5 +#ifdef WITH_GSSAPI if ((strlen(transport->settings->Domain) != 0) && (strncmp(transport->settings->Domain, ".", 1) != 0)) @@ -184,7 +184,7 @@ static void transport_ssl_cb(SSL* ssl, int where, int ret) transport->settings->Password); } else -#endif /* WITH_KRB5 */ +#endif /* WITH_GSSAPI */ kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED; if (!freerdp_get_last_error(transport->context)) diff --git a/winpr/include/winpr/sspi.h b/winpr/include/winpr/sspi.h index 53a033aff..df2d50267 100644 --- a/winpr/include/winpr/sspi.h +++ b/winpr/include/winpr/sspi.h @@ -92,8 +92,9 @@ typedef SecPkgInfoW* PSecPkgInfoW; #define PSecPkgInfo PSecPkgInfoA #endif -#define NTLMSP_NAME _T("NTLM") -#define NEGOSSP_NAME _T("Negotiate") +#define NTLMSSP_NAME _T("NTLM") +#define KERBEROS_SSP_NAME _T("Kerberos") +#define NEGOSSP_NAME _T("Negotiate") #endif @@ -589,6 +590,7 @@ typedef SecPkgCredentials_NamesW* PSecPkgCredentials_NamesW; typedef struct _SEC_WINNT_AUTH_IDENTITY_W { + /* TSPasswordCreds */ UINT16* User; UINT32 UserLength; UINT16* Domain; @@ -600,6 +602,7 @@ typedef struct _SEC_WINNT_AUTH_IDENTITY_W typedef struct _SEC_WINNT_AUTH_IDENTITY_A { + /* TSPasswordCreds */ BYTE* User; UINT32 UserLength; BYTE* Domain; @@ -611,6 +614,7 @@ typedef struct _SEC_WINNT_AUTH_IDENTITY_A struct _SEC_WINNT_AUTH_IDENTITY { + /* TSPasswordCreds */ UINT16* User; UINT32 UserLength; UINT16* Domain; diff --git a/winpr/libwinpr/sspi/CMakeLists.txt b/winpr/libwinpr/sspi/CMakeLists.txt index efcad4725..0949ae3f3 100644 --- a/winpr/libwinpr/sspi/CMakeLists.txt +++ b/winpr/libwinpr/sspi/CMakeLists.txt @@ -27,6 +27,10 @@ set(${MODULE_PREFIX}_NTLM_SRCS NTLM/ntlm.c NTLM/ntlm.h) +set(${MODULE_PREFIX}_KERBEROS_SRCS + Kerberos/kerberos.c + Kerberos/kerberos.h) + set(${MODULE_PREFIX}_NEGOTIATE_SRCS Negotiate/negotiate.c Negotiate/negotiate.h) @@ -38,17 +42,20 @@ set(${MODULE_PREFIX}_SCHANNEL_SRCS Schannel/schannel.h) set(${MODULE_PREFIX}_CREDSSP_SRCS - CredSSP/credssp.c) + CredSSP/credssp.c + CredSSP/credssp.h) set(${MODULE_PREFIX}_SRCS - ${${MODULE_PREFIX}_CREDSSP_SRCS} sspi_winpr.c sspi_winpr.h sspi_export.c + sspi_gss.c + sspi_gss.h sspi.c sspi.h) -winpr_module_add(${${MODULE_PREFIX}_NTLM_SRCS} +winpr_module_add(${${MODULE_PREFIX}_CREDSSP_SRCS} + ${${MODULE_PREFIX}_NTLM_SRCS} ${${MODULE_PREFIX}_KERBEROS_SRCS} ${${MODULE_PREFIX}_NEGOTIATE_SRCS} ${${MODULE_PREFIX}_SCHANNEL_SRCS} @@ -64,6 +71,10 @@ if(MBEDTLS_FOUND) winpr_library_add(${MBEDTLS_LIBRARIES}) endif() +if(GSS_FOUND) + winpr_library_add(${GSS_LIBRARIES}) +endif() + if(WIN32) winpr_library_add(ws2_32) endif() diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.c b/winpr/libwinpr/sspi/Kerberos/kerberos.c new file mode 100644 index 000000000..194af7ff0 --- /dev/null +++ b/winpr/libwinpr/sspi/Kerberos/kerberos.c @@ -0,0 +1,734 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Kerberos Auth Protocol + * + * Copyright 2015 ANSSI, Author Thomas Calderon + * Copyright 2017 Dorian Ducournau + * + * 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 +#include +#include +#include +#include + +#include +#include +#include +#include +#include + +#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 @FQDN, let's construct it */ + gss_name = _strdup(ServicePrincipalName); + + if (!gss_name) + return -1; + + p = strchr(gss_name, '/'); + + if (p) + *p = '@'; + + name_buffer.value = gss_name; + name_buffer.length = strlen(gss_name) + 1; + major_status = sspi_gss_import_name(&minor_status, &name_buffer, + SSPI_GSS_C_NT_HOSTBASED_SERVICE, &(context->target_name)); + free(gss_name); + + if (SSPI_GSS_ERROR(major_status)) + { + WLog_ERR(TAG, "error: gss_import_name failed"); + return -1; + } + + return 1; +} + +#ifdef WITH_GSSAPI +krb5_error_code KRB5_CALLCONV +acquire_cred(krb5_context ctx, krb5_principal client, const char* password) +{ + krb5_error_code ret; + krb5_creds creds; + krb5_deltat starttime = 0; + krb5_get_init_creds_opt* options = NULL; + krb5_ccache ccache; + krb5_init_creds_context init_ctx = NULL; + + /* Get default ccache */ + if ((ret = krb5_cc_default(ctx, &ccache))) + { + WLog_ERR(TAG, "error while getting default ccache"); + goto cleanup; + } + + if ((ret = krb5_cc_initialize(ctx, ccache, client))) + { + WLog_ERR(TAG, "error: could not initialize ccache"); + goto cleanup; + } + + memset(&creds, 0, sizeof(creds)); + + if ((ret = krb5_get_init_creds_opt_alloc(ctx, &options))) + { + WLog_ERR(TAG, "error while allocating options"); + goto cleanup; + } + + /* Set default options */ + krb5_get_init_creds_opt_set_forwardable(options, 0); + krb5_get_init_creds_opt_set_proxiable(options, 0); +#ifdef WITH_GSSAPI_MIT + + /* for MIT we specify ccache output using an option */ + if ((ret = krb5_get_init_creds_opt_set_out_ccache(ctx, options, ccache))) + { + WLog_ERR(TAG, "error while setting ccache output"); + goto cleanup; + } + +#endif + + if ((ret = krb5_init_creds_init(ctx, client, NULL, NULL, starttime, options, &init_ctx))) + { + WLog_ERR(TAG, "error krb5_init_creds_init failed"); + goto cleanup; + } + + if ((ret = krb5_init_creds_set_password(ctx, init_ctx, password))) + { + WLog_ERR(TAG, "error krb5_init_creds_set_password failed"); + goto cleanup; + } + + /* Get credentials */ + if ((ret = krb5_init_creds_get(ctx, init_ctx))) + { + WLog_ERR(TAG, "error while getting credentials"); + goto cleanup; + } + + /* Retrieve credentials */ + if ((ret = krb5_init_creds_get_creds(ctx, init_ctx, &creds))) + { + WLog_ERR(TAG, "error while retrieving credentials"); + goto cleanup; + } + +#ifdef WITH_GSSAPI_HEIMDAL + + /* For Heimdal, we use this function to store credentials */ + if ((ret = krb5_init_creds_store(ctx, init_ctx, ccache))) + { + WLog_ERR(TAG, "error while storing credentials"); + goto cleanup; + } + +#endif +cleanup: + krb5_free_cred_contents(ctx, &creds); + + if (options) + krb5_get_init_creds_opt_free(ctx, options); + + if (init_ctx) + krb5_init_creds_free(ctx, init_ctx); + + if (ccache) + krb5_cc_close(ctx, ccache); + + return ret; +} + +int init_creds(LPCWSTR username, size_t username_len, LPCWSTR password, size_t password_len) +{ + krb5_error_code ret = 0; + krb5_context ctx = NULL; + krb5_principal principal = NULL; + char* krb_name = NULL; + char* lusername = NULL; + char* lrealm = NULL; + char* lpassword = NULL; + size_t krb_name_len = 0; + size_t lrealm_len = 0; + size_t lusername_len = 0; + int status = 0; + status = ConvertFromUnicode(CP_UTF8, 0, username, + username_len, &lusername, 0, NULL, NULL); + + if (status <= 0) + { + WLog_ERR(TAG, "Failed to convert username"); + goto cleanup; + } + + status = ConvertFromUnicode(CP_UTF8, 0, password, + password_len, &lpassword, 0, NULL, NULL); + + if (status <= 0) + { + WLog_ERR(TAG, "Failed to convert password"); + goto cleanup; + } + + /* Could call krb5_init_secure_context, but it disallows user overrides */ + ret = krb5_init_context(&ctx); + + if (ret) + { + WLog_ERR(TAG, "error: while initializing Kerberos 5 library"); + goto cleanup; + } + + ret = krb5_get_default_realm(ctx, &lrealm); + + if (ret) + { + WLog_WARN(TAG, "could not get Kerberos default realm"); + goto cleanup; + } + + lrealm_len = strlen(lrealm); + lusername_len = strlen(lusername); + krb_name_len = lusername_len + lrealm_len + 1; // +1 for '@' + krb_name = calloc(krb_name_len + 1, sizeof(char)); + + if (!krb_name) + { + WLog_ERR(TAG, "could not allocate memory for string rep of principal\n"); + ret = -1; + goto cleanup; + } + + /* Set buffer */ + _snprintf(krb_name, krb_name_len + 1, "%s@%s", lusername, lrealm); +#ifdef WITH_DEBUG_NLA + WLog_DBG(TAG, "copied string is %s\n", krb_name); +#endif + ret = krb5_parse_name(ctx, krb_name, &principal); + + if (ret) + { + WLog_ERR(TAG, "could not convert %s to principal", krb_name); + goto cleanup; + } + + ret = acquire_cred(ctx, principal, lpassword); + + if (ret) + { + WLog_ERR(TAG, "Kerberos credentials not found and could not be acquired"); + goto cleanup; + } + +cleanup: + free(lusername); + free(lpassword); + + if (krb_name) + free(krb_name); + + if (lrealm) + krb5_free_default_realm(ctx, lrealm); + + if (principal) + krb5_free_principal(ctx, principal); + + if (ctx) + krb5_free_context(ctx); + + return ret; +} +#endif + +SECURITY_STATUS SEC_ENTRY kerberos_InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, + ULONG TargetDataRep, PSecBufferDesc pInput, ULONG Reserved2, + PCtxtHandle phNewContext, PSecBufferDesc pOutput, + ULONG* pfContextAttr, PTimeStamp ptsExpiry) +{ + KRB_CONTEXT* context; + SSPI_CREDENTIALS* credentials; + PSecBuffer input_buffer = NULL; + PSecBuffer output_buffer = NULL; + sspi_gss_buffer_desc input_tok; + sspi_gss_buffer_desc output_tok; + sspi_gss_OID actual_mech; + sspi_gss_OID desired_mech; + UINT32 actual_services; + input_tok.length = 0; + output_tok.length = 0; + desired_mech = SSPI_GSS_C_SPNEGO_KRB5; + context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + { + context = kerberos_ContextNew(); + + if (!context) + return SEC_E_INSUFFICIENT_MEMORY; + + credentials = (SSPI_CREDENTIALS*) sspi_SecureHandleGetLowerPointer(phCredential); + context->credentials = credentials; + + if (kerberos_SetContextServicePrincipalNameA(context, pszTargetName) < 0) + return SEC_E_INTERNAL_ERROR; + + sspi_SecureHandleSetLowerPointer(phNewContext, context); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) KRB_PACKAGE_NAME); + } + + if (!pInput) + { +#if defined(WITH_GSSAPI) + context->major_status = sspi_gss_init_sec_context(&(context->minor_status), + context->cred, &(context->gss_ctx), context->target_name, + desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG, + SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS, + &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time)); + + if (SSPI_GSS_ERROR(context->major_status)) + { + /* GSSAPI failed because we do not have credentials */ + if (context->major_status & SSPI_GSS_S_NO_CRED) + { + /* Then let's try to acquire credentials using login and password, + * and only those two, means not with a smartcard. + * If we use smartcard-logon, the credentials have already + * been acquired by pkinit process. If not, returned error previously. + */ + if (init_creds(context->credentials->identity.User, + context->credentials->identity.UserLength, + context->credentials->identity.Password, + context->credentials->identity.PasswordLength)) + return SEC_E_NO_CREDENTIALS; + else + WLog_INFO(TAG, "Authenticated to Kerberos v5 via login/password"); + + /* retry GSSAPI call */ + context->major_status = sspi_gss_init_sec_context(&(context->minor_status), + context->cred, &(context->gss_ctx), context->target_name, + desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG, + SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS, + &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time)); + + if (SSPI_GSS_ERROR(context->major_status)) + { + /* We can't use Kerberos */ + return SEC_E_INTERNAL_ERROR; + } + } + } + +#endif + + if (context->major_status & SSPI_GSS_S_CONTINUE_NEEDED) + { + if (output_tok.length != 0) + { + if (!pOutput) + return SEC_E_INVALID_TOKEN; + + if (pOutput->cBuffers < 1) + return SEC_E_INVALID_TOKEN; + + output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN); + + if (!output_buffer) + return SEC_E_INVALID_TOKEN; + + if (output_buffer->cbBuffer < 1) + return SEC_E_INVALID_TOKEN; + + CopyMemory(output_buffer->pvBuffer, output_tok.value, output_tok.length); + output_buffer->cbBuffer = output_tok.length; + sspi_gss_release_buffer(&(context->minor_status), &output_tok); + return SEC_I_CONTINUE_NEEDED; + } + } + } + else + { + input_buffer = sspi_FindSecBuffer(pInput, SECBUFFER_TOKEN); + + if (!input_buffer) + return SEC_E_INVALID_TOKEN; + + if (input_buffer->cbBuffer < 1) + return SEC_E_INVALID_TOKEN; + + input_tok.value = input_buffer->pvBuffer; + input_tok.length = input_buffer->cbBuffer; + context->major_status = sspi_gss_init_sec_context(&(context->minor_status), + context->cred, &(context->gss_ctx), context->target_name, + desired_mech, SSPI_GSS_C_MUTUAL_FLAG | SSPI_GSS_C_DELEG_FLAG, + SSPI_GSS_C_INDEFINITE, SSPI_GSS_C_NO_CHANNEL_BINDINGS, + &input_tok, &actual_mech, &output_tok, &actual_services, &(context->actual_time)); + + if (SSPI_GSS_ERROR(context->major_status)) + return SEC_E_INTERNAL_ERROR; + + if (output_tok.length == 0) + { + /* Free output_buffer to detect second call in NLA */ + output_buffer = sspi_FindSecBuffer(pOutput, SECBUFFER_TOKEN); + sspi_SecBufferFree(output_buffer); + return SEC_E_OK; + } + else + { + return SEC_E_INTERNAL_ERROR; + } + } + + return SEC_E_INTERNAL_ERROR; +} + +SECURITY_STATUS SEC_ENTRY kerberos_DeleteSecurityContext(PCtxtHandle phContext) +{ + KRB_CONTEXT* context; + context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + return SEC_E_INVALID_HANDLE; + + kerberos_ContextFree(context); + return SEC_E_OK; +} + +SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer) +{ + return SEC_E_OK; +} + +SECURITY_STATUS SEC_ENTRY kerberos_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer) +{ + if (!phContext) + return SEC_E_INVALID_HANDLE; + + if (!pBuffer) + return SEC_E_INSUFFICIENT_MEMORY; + + if (ulAttribute == SECPKG_ATTR_SIZES) + { + SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer; + /* The MaxTokenSize by default is 12,000 bytes. This has been the default value + * since Windows 2000 SP2 and still remains in Windows 7 and Windows 2008 R2. + * For Windows Server 2012, the default value of the MaxTokenSize registry + * entry is 48,000 bytes.*/ + ContextSizes->cbMaxToken = KERBEROS_SecPkgInfoA.cbMaxToken; + ContextSizes->cbMaxSignature = 0; /* means verify not supported */ + ContextSizes->cbBlockSize = 0; /* padding not used */ + ContextSizes->cbSecurityTrailer = 60; /* gss_wrap adds additional 60 bytes for encrypt message */ + return SEC_E_OK; + } + + return SEC_E_UNSUPPORTED_FUNCTION; +} + +SECURITY_STATUS SEC_ENTRY kerberos_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) +{ + int index; + int conf_state; + UINT32 major_status; + UINT32 minor_status; + KRB_CONTEXT* context; + sspi_gss_buffer_desc input; + sspi_gss_buffer_desc output; + PSecBuffer data_buffer = NULL; + context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + return SEC_E_INVALID_HANDLE; + + for (index = 0; index < (int) pMessage->cBuffers; index++) + { + if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA) + data_buffer = &pMessage->pBuffers[index]; + } + + if (!data_buffer) + return SEC_E_INVALID_TOKEN; + + input.value = data_buffer->pvBuffer; + input.length = data_buffer->cbBuffer; + major_status = sspi_gss_wrap(&minor_status, context->gss_ctx, TRUE, + SSPI_GSS_C_QOP_DEFAULT, &input, &conf_state, &output); + + if (SSPI_GSS_ERROR(major_status)) + return SEC_E_INTERNAL_ERROR; + + if (conf_state == 0) + { + WLog_ERR(TAG, "error: gss_wrap confidentiality was not applied"); + sspi_gss_release_buffer(&minor_status, &output); + return SEC_E_INTERNAL_ERROR; + } + + CopyMemory(data_buffer->pvBuffer, output.value, output.length); + sspi_gss_release_buffer(&minor_status, &output); + return SEC_E_OK; +} + +SECURITY_STATUS SEC_ENTRY kerberos_DecryptMessage(PCtxtHandle phContext, + PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +{ + int index; + int conf_state; + UINT32 major_status; + UINT32 minor_status; + KRB_CONTEXT* context; + sspi_gss_buffer_desc input_data; + sspi_gss_buffer_desc output; + PSecBuffer data_buffer_to_unwrap = NULL; + context = (KRB_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); + + if (!context) + return SEC_E_INVALID_HANDLE; + + for (index = 0; index < (int) pMessage->cBuffers; index++) + { + if (pMessage->pBuffers[index].BufferType == SECBUFFER_DATA) + data_buffer_to_unwrap = &pMessage->pBuffers[index]; + } + + if (!data_buffer_to_unwrap) + return SEC_E_INVALID_TOKEN; + + /* unwrap encrypted TLS key AND its signature */ + input_data.value = data_buffer_to_unwrap->pvBuffer; + input_data.length = data_buffer_to_unwrap->cbBuffer; + major_status = sspi_gss_unwrap(&minor_status, context->gss_ctx, &input_data, &output, &conf_state, + NULL); + + if (SSPI_GSS_ERROR(major_status)) + return SEC_E_INTERNAL_ERROR; + + if (conf_state == 0) + { + WLog_ERR(TAG, "error: gss_unwrap confidentiality was not applied"); + sspi_gss_release_buffer(&minor_status, &output); + return SEC_E_INTERNAL_ERROR; + } + + CopyMemory(data_buffer_to_unwrap->pvBuffer, output.value, output.length); + sspi_gss_release_buffer(&minor_status, &output); + return SEC_E_OK; +} + +SECURITY_STATUS SEC_ENTRY kerberos_MakeSignature(PCtxtHandle phContext, + ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +{ + return SEC_E_OK; +} + +SECURITY_STATUS SEC_ENTRY kerberos_VerifySignature(PCtxtHandle phContext, + PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +{ + return SEC_E_OK; +} + + +const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA = +{ + 1, /* dwVersion */ + NULL, /* EnumerateSecurityPackages */ + kerberos_QueryCredentialsAttributesA, /* QueryCredentialsAttributes */ + kerberos_AcquireCredentialsHandleA, /* AcquireCredentialsHandle */ + kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + kerberos_InitializeSecurityContextA, /* InitializeSecurityContext */ + NULL, /* AcceptSecurityContext */ + NULL, /* CompleteAuthToken */ + kerberos_DeleteSecurityContext, /* DeleteSecurityContext */ + NULL, /* ApplyControlToken */ + kerberos_QueryContextAttributesA, /* QueryContextAttributes */ + NULL, /* ImpersonateSecurityContext */ + NULL, /* RevertSecurityContext */ + kerberos_MakeSignature, /* MakeSignature */ + kerberos_VerifySignature, /* VerifySignature */ + NULL, /* FreeContextBuffer */ + NULL, /* QuerySecurityPackageInfo */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContext */ + NULL, /* AddCredentials */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + kerberos_EncryptMessage, /* EncryptMessage */ + kerberos_DecryptMessage, /* DecryptMessage */ + NULL, /* SetContextAttributes */ +}; + +const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW = +{ + 1, /* dwVersion */ + NULL, /* EnumerateSecurityPackages */ + kerberos_QueryCredentialsAttributesW, /* QueryCredentialsAttributes */ + kerberos_AcquireCredentialsHandleW, /* AcquireCredentialsHandle */ + kerberos_FreeCredentialsHandle, /* FreeCredentialsHandle */ + NULL, /* Reserved2 */ + kerberos_InitializeSecurityContextW, /* InitializeSecurityContext */ + NULL, /* AcceptSecurityContext */ + NULL, /* CompleteAuthToken */ + kerberos_DeleteSecurityContext, /* DeleteSecurityContext */ + NULL, /* ApplyControlToken */ + kerberos_QueryContextAttributesW, /* QueryContextAttributes */ + NULL, /* ImpersonateSecurityContext */ + NULL, /* RevertSecurityContext */ + kerberos_MakeSignature, /* MakeSignature */ + kerberos_VerifySignature, /* VerifySignature */ + NULL, /* FreeContextBuffer */ + NULL, /* QuerySecurityPackageInfo */ + NULL, /* Reserved3 */ + NULL, /* Reserved4 */ + NULL, /* ExportSecurityContext */ + NULL, /* ImportSecurityContext */ + NULL, /* AddCredentials */ + NULL, /* Reserved8 */ + NULL, /* QuerySecurityContextToken */ + kerberos_EncryptMessage, /* EncryptMessage */ + kerberos_DecryptMessage, /* DecryptMessage */ + NULL, /* SetContextAttributes */ +}; diff --git a/winpr/libwinpr/sspi/Kerberos/kerberos.h b/winpr/libwinpr/sspi/Kerberos/kerberos.h new file mode 100644 index 000000000..a974aff4b --- /dev/null +++ b/winpr/libwinpr/sspi/Kerberos/kerberos.h @@ -0,0 +1,83 @@ +/** + * FreeRDP: A Remote Desktop Protocol Client + * Kerberos Auth Protocol + * + * Copyright 2015 ANSSI, Author Thomas Calderon + * Copyright 2017 Dorian Ducournau + * + * 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 +#include + +#include "../sspi.h" +#include "../../log.h" + +#ifdef WITH_GSSAPI +#include +#include +#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 */ diff --git a/winpr/libwinpr/sspi/NTLM/ntlm.c b/winpr/libwinpr/sspi/NTLM/ntlm.c index 5266bc764..0dadbcfa1 100644 --- a/winpr/libwinpr/sspi/NTLM/ntlm.c +++ b/winpr/libwinpr/sspi/NTLM/ntlm.c @@ -747,9 +747,10 @@ SECURITY_STATUS SEC_ENTRY ntlm_QueryContextAttributesW(PCtxtHandle phContext, UL { SecPkgContext_Sizes* ContextSizes = (SecPkgContext_Sizes*) pBuffer; ContextSizes->cbMaxToken = 2010; - ContextSizes->cbMaxSignature = 16; - ContextSizes->cbBlockSize = 0; - ContextSizes->cbSecurityTrailer = 16; + ContextSizes->cbMaxSignature = 16; /* the size of expected signature is 16 bytes */ + ContextSizes->cbBlockSize = 0; /* no padding */ + ContextSizes->cbSecurityTrailer = 16; /* no security trailer appended in NTLM + contrary to Kerberos */ return SEC_E_OK; } else if (ulAttribute == SECPKG_ATTR_AUTH_IDENTITY) diff --git a/winpr/libwinpr/sspi/Negotiate/negotiate.c b/winpr/libwinpr/sspi/Negotiate/negotiate.c index 4829b8886..315e3c764 100644 --- a/winpr/libwinpr/sspi/Negotiate/negotiate.c +++ b/winpr/libwinpr/sspi/Negotiate/negotiate.c @@ -3,6 +3,7 @@ * Negotiate Security Package * * Copyright 2011-2014 Marc-Andre Moreau + * Copyright 2017 Dorian Ducournau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -33,12 +34,37 @@ extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA; extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW; -char* NEGOTIATE_PACKAGE_NAME = "Negotiate"; +extern const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA; +extern const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW; + +#ifdef WITH_GSSAPI +static BOOL ErrorInitContextKerberos = FALSE; +#else +static BOOL ErrorInitContextKerberos = TRUE; +#endif + +void negotiate_SetSubPackage(NEGOTIATE_CONTEXT* context, const char* name) +{ + if (strcmp(name, KERBEROS_SSP_NAME) == 0) + { + context->sspiA = (SecurityFunctionTableA*) &KERBEROS_SecurityFunctionTableA; + context->sspiW = (SecurityFunctionTableW*) &KERBEROS_SecurityFunctionTableW; + context->kerberos = TRUE; + } + else + { + context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA; + context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW; + context->kerberos = FALSE; + } + + sspi_SecureHandleSetLowerPointer(&(context->SubContext), NULL); + sspi_SecureHandleSetUpperPointer(&(context->SubContext), NULL); +} NEGOTIATE_CONTEXT* negotiate_ContextNew() { NEGOTIATE_CONTEXT* context; - context = (NEGOTIATE_CONTEXT*) calloc(1, sizeof(NEGOTIATE_CONTEXT)); if (!context) @@ -46,12 +72,8 @@ NEGOTIATE_CONTEXT* negotiate_ContextNew() context->NegotiateFlags = 0; context->state = NEGOTIATE_STATE_INITIAL; - SecInvalidateHandle(&(context->SubContext)); - - context->sspiA = (SecurityFunctionTableA*) &NTLM_SecurityFunctionTableA; - context->sspiW = (SecurityFunctionTableW*) &NTLM_SecurityFunctionTableW; - + negotiate_SetSubPackage(context, KERBEROS_SSP_NAME); return context; } @@ -60,14 +82,14 @@ void negotiate_ContextFree(NEGOTIATE_CONTEXT* context) free(context); } -SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -78,24 +100,54 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextW(PCredHandle phCre return SEC_E_INTERNAL_ERROR; sspi_SecureHandleSetLowerPointer(phNewContext, context); - sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOSSP_NAME); } - status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext), - pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), - pOutput, pfContextAttr, ptsExpiry); + /* if Kerberos has previously failed or WITH_GSSAPI is not defined, we use NTLM directly */ + if (ErrorInitContextKerberos == FALSE) + { + if (!pInput) + { + negotiate_SetSubPackage(context, KERBEROS_SSP_NAME); + } + + status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext), + pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), + pOutput, pfContextAttr, ptsExpiry); + + if (status == SEC_E_NO_CREDENTIALS) + { + WLog_WARN(TAG, "No Kerberos credentials. Retry with NTLM"); + ErrorInitContextKerberos = TRUE; + context->sspiA->DeleteSecurityContext(&(context->SubContext)); + negotiate_ContextFree(context); + return status; + } + } + else + { + if (!pInput) + { + context->sspiA->DeleteSecurityContext(&(context->SubContext)); + negotiate_SetSubPackage(context, NTLMSSP_NAME); + } + + status = context->sspiW->InitializeSecurityContextW(phCredential, &(context->SubContext), + pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), + pOutput, pfContextAttr, ptsExpiry); + } return status; } -SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -106,23 +158,53 @@ SECURITY_STATUS SEC_ENTRY negotiate_InitializeSecurityContextA(PCredHandle phCre return SEC_E_INTERNAL_ERROR; sspi_SecureHandleSetLowerPointer(phNewContext, context); - sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOSSP_NAME); } - status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext), - pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), - pOutput, pfContextAttr, ptsExpiry); + /* if Kerberos has previously failed or WITH_GSSAPI is not defined, we use NTLM directly */ + if (ErrorInitContextKerberos == FALSE) + { + if (!pInput) + { + negotiate_SetSubPackage(context, KERBEROS_SSP_NAME); + } + + status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext), + pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), + pOutput, pfContextAttr, ptsExpiry); + + if (status == SEC_E_NO_CREDENTIALS) + { + WLog_WARN(TAG, "No Kerberos credentials. Retry with NTLM"); + ErrorInitContextKerberos = TRUE; + context->sspiA->DeleteSecurityContext(&(context->SubContext)); + negotiate_ContextFree(context); + return status; + } + } + else + { + if (!pInput) + { + context->sspiA->DeleteSecurityContext(&(context->SubContext)); + negotiate_SetSubPackage(context, NTLMSSP_NAME); + } + + status = context->sspiA->InitializeSecurityContextA(phCredential, &(context->SubContext), + pszTargetName, fContextReq, Reserved1, TargetDataRep, pInput, Reserved2, &(context->SubContext), + pOutput, pfContextAttr, ptsExpiry); + } return status; } -SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, - PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) +SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredential, + PCtxtHandle phContext, + PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) { SECURITY_STATUS status; NEGOTIATE_CONTEXT* context; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -133,18 +215,20 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcceptSecurityContext(PCredHandle phCredenti return SEC_E_INTERNAL_ERROR; sspi_SecureHandleSetLowerPointer(phNewContext, context); - sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOTIATE_PACKAGE_NAME); + sspi_SecureHandleSetUpperPointer(phNewContext, (void*) NEGOSSP_NAME); } + negotiate_SetSubPackage(context, NTLMSSP_NAME); /* server-side Kerberos not yet implemented */ status = context->sspiA->AcceptSecurityContext(phCredential, &(context->SubContext), - pInput, fContextReq, TargetDataRep, &(context->SubContext), - pOutput, pfContextAttr, ptsTimeStamp); + pInput, fContextReq, TargetDataRep, &(context->SubContext), + pOutput, pfContextAttr, ptsTimeStamp); if (status != SEC_E_OK) { WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } + return status; } @@ -152,7 +236,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_CompleteAuthToken(PCtxtHandle phContext, PSe { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -168,7 +251,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!context) @@ -178,7 +260,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_DeleteSecurityContext(PCtxtHandle phContext) status = context->sspiW->DeleteSecurityContext(&(context->SubContext)); negotiate_ContextFree(context); - return status; } @@ -186,7 +267,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_ImpersonateSecurityContext(PCtxtHandle phCon { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -202,7 +282,6 @@ SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -214,11 +293,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_RevertSecurityContext(PCtxtHandle phContext) return status; } -SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -233,11 +312,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesW(PCtxtHandle phContex return status; } -SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContext, + ULONG ulAttribute, void* pBuffer) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -252,11 +331,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_QueryContextAttributesA(PCtxtHandle phContex return status; } -SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) +SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -266,16 +345,17 @@ SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesW(PCtxtHandle phContext, return SEC_E_INSUFFICIENT_MEMORY; if (context->sspiW->SetContextAttributesW) - status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer, cbBuffer); + status = context->sspiW->SetContextAttributesW(&(context->SubContext), ulAttribute, pBuffer, + cbBuffer); return status; } -SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) +SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_OK; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (!phContext) @@ -285,21 +365,23 @@ SECURITY_STATUS SEC_ENTRY negotiate_SetContextAttributesA(PCtxtHandle phContext, return SEC_E_INSUFFICIENT_MEMORY; if (context->sspiA->SetContextAttributesA) - status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer, cbBuffer); + status = context->sspiA->SetContextAttributesA(&(context->SubContext), ulAttribute, pBuffer, + cbBuffer); return status; } -SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, + SEC_WCHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && - (fCredentialUse != SECPKG_CRED_INBOUND) && - (fCredentialUse != SECPKG_CRED_BOTH)) + (fCredentialUse != SECPKG_CRED_INBOUND) && + (fCredentialUse != SECPKG_CRED_BOTH)) { return SEC_E_INVALID_PARAMETER; } @@ -312,28 +394,27 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleW(SEC_WCHAR* pszPrin credentials->fCredentialUse = fCredentialUse; credentials->pGetKeyFn = pGetKeyFn; credentials->pvGetKeyArgument = pvGetKeyArgument; - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; if (identity) sspi_CopyAuthIdentity(&(credentials->identity), identity); sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); - + sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOSSP_NAME); return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, + SEC_CHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SSPI_CREDENTIALS* credentials; SEC_WINNT_AUTH_IDENTITY* identity; if ((fCredentialUse != SECPKG_CRED_OUTBOUND) && - (fCredentialUse != SECPKG_CRED_INBOUND) && - (fCredentialUse != SECPKG_CRED_BOTH)) + (fCredentialUse != SECPKG_CRED_INBOUND) && + (fCredentialUse != SECPKG_CRED_BOTH)) { return SEC_E_INVALID_PARAMETER; } @@ -346,24 +427,24 @@ SECURITY_STATUS SEC_ENTRY negotiate_AcquireCredentialsHandleA(SEC_CHAR* pszPrinc credentials->fCredentialUse = fCredentialUse; credentials->pGetKeyFn = pGetKeyFn; credentials->pvGetKeyArgument = pvGetKeyArgument; - identity = (SEC_WINNT_AUTH_IDENTITY*) pAuthData; if (identity) sspi_CopyAuthIdentity(&(credentials->identity), identity); sspi_SecureHandleSetLowerPointer(phCredential, (void*) credentials); - sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOTIATE_PACKAGE_NAME); - + sspi_SecureHandleSetUpperPointer(phCredential, (void*) NEGOSSP_NAME); return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { return SEC_E_UNSUPPORTED_FUNCTION; } -SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY negotiate_QueryCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { return SEC_E_UNSUPPORTED_FUNCTION; } @@ -385,11 +466,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_FreeCredentialsHandle(PCredHandle phCredenti return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (context->sspiW->EncryptMessage) @@ -398,11 +479,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_EncryptMessage(PCtxtHandle phContext, ULONG return status; } -SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, + ULONG MessageSeqNo, ULONG* pfQOP) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (context->sspiW->DecryptMessage) @@ -411,11 +492,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_DecryptMessage(PCtxtHandle phContext, PSecBu return status; } -SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (context->sspiW->MakeSignature) @@ -424,11 +505,11 @@ SECURITY_STATUS SEC_ENTRY negotiate_MakeSignature(PCtxtHandle phContext, ULONG f return status; } -SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, ULONG* pfQOP) +SECURITY_STATUS SEC_ENTRY negotiate_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, + ULONG MessageSeqNo, ULONG* pfQOP) { NEGOTIATE_CONTEXT* context; SECURITY_STATUS status = SEC_E_UNSUPPORTED_FUNCTION; - context = (NEGOTIATE_CONTEXT*) sspi_SecureHandleGetLowerPointer(phContext); if (context->sspiW->VerifySignature) @@ -511,13 +592,13 @@ const SecPkgInfoA NEGOTIATE_SecPkgInfoA = "Microsoft Package Negotiator" /* Comment */ }; -WCHAR NEGOTIATE_SecPkgInfoW_Name[] = { 'N','e','g','o','t','i','a','t','e','\0' }; +WCHAR NEGOTIATE_SecPkgInfoW_Name[] = { 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', '\0' }; WCHAR NEGOTIATE_SecPkgInfoW_Comment[] = { - 'M','i','c','r','o','s','o','f','t',' ', - 'P','a','c','k','a','g','e',' ', - 'N','e','g','o','t','i','a','t','o','r','\0' + 'M', 'i', 'c', 'r', 'o', 's', 'o', 'f', 't', ' ', + 'P', 'a', 'c', 'k', 'a', 'g', 'e', ' ', + 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'o', 'r', '\0' }; const SecPkgInfoW NEGOTIATE_SecPkgInfoW = diff --git a/winpr/libwinpr/sspi/Negotiate/negotiate.h b/winpr/libwinpr/sspi/Negotiate/negotiate.h index fe6375e30..ac50e96fa 100644 --- a/winpr/libwinpr/sspi/Negotiate/negotiate.h +++ b/winpr/libwinpr/sspi/Negotiate/negotiate.h @@ -44,6 +44,7 @@ struct _NEGOTIATE_CONTEXT CtxtHandle SubContext; + BOOL kerberos; SecurityFunctionTableA* sspiA; SecurityFunctionTableW* sspiW; }; diff --git a/winpr/libwinpr/sspi/sspi.h b/winpr/libwinpr/sspi/sspi.h index 430efd1d2..2a73ad110 100644 --- a/winpr/libwinpr/sspi/sspi.h +++ b/winpr/libwinpr/sspi/sspi.h @@ -85,6 +85,7 @@ enum SecurityFunctionTableIndex BOOL IsSecurityStatusError(SECURITY_STATUS status); +#include "sspi_gss.h" #include "sspi_winpr.h" #endif /* WINPR_SSPI_PRIVATE_H */ diff --git a/winpr/libwinpr/sspi/sspi_gss.c b/winpr/libwinpr/sspi/sspi_gss.c new file mode 100644 index 000000000..d2a5ec24f --- /dev/null +++ b/winpr/libwinpr/sspi/sspi_gss.c @@ -0,0 +1,666 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Generic Security Service Application Program Interface (GSSAPI) + * + * Copyright 2015 ANSSI, Author Thomas Calderon + * Copyright 2015 Marc-Andre Moreau + * + * 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 +#include + +#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_FUNCTION_TABLE g_GssApiLink = +{ + (fn_sspi_gss_acquire_cred) gss_acquire_cred, /* gss_acquire_cred */ + (fn_sspi_gss_release_cred) gss_release_cred, /* gss_release_cred */ + (fn_sspi_gss_init_sec_context) gss_init_sec_context, /* gss_init_sec_context */ + (fn_sspi_gss_accept_sec_context) gss_accept_sec_context, /* gss_accept_sec_context */ + (fn_sspi_gss_process_context_token) gss_process_context_token, /* gss_process_context_token */ + (fn_sspi_gss_delete_sec_context) gss_delete_sec_context, /* gss_delete_sec_context */ + (fn_sspi_gss_context_time) gss_context_time, /* gss_context_time */ + (fn_sspi_gss_get_mic) gss_get_mic, /* gss_get_mic */ + (fn_sspi_gss_verify_mic) gss_verify_mic, /* gss_verify_mic */ + (fn_sspi_gss_wrap) gss_wrap, /* gss_wrap */ + (fn_sspi_gss_unwrap) gss_unwrap, /* gss_unwrap */ + (fn_sspi_gss_display_status) gss_display_status, /* gss_display_status */ + (fn_sspi_gss_indicate_mechs) gss_indicate_mechs, /* gss_indicate_mechs */ + (fn_sspi_gss_compare_name) gss_compare_name, /* gss_compare_name */ + (fn_sspi_gss_display_name) gss_display_name, /* gss_display_name */ + (fn_sspi_gss_import_name) gss_import_name, /* gss_import_name */ + (fn_sspi_gss_release_name) gss_release_name, /* gss_release_name */ + (fn_sspi_gss_release_buffer) gss_release_buffer, /* gss_release_buffer */ + (fn_sspi_gss_release_oid_set) gss_release_oid_set, /* gss_release_oid_set */ + (fn_sspi_gss_inquire_cred) gss_inquire_cred, /* gss_inquire_cred */ + (fn_sspi_gss_inquire_context) gss_inquire_context, /* gss_inquire_context */ + (fn_sspi_gss_wrap_size_limit) gss_wrap_size_limit, /* gss_wrap_size_limit */ +#if 0 + (fn_sspi_gss_import_name_object) gss_import_name_object, /* gss_import_name_object */ + (fn_sspi_gss_export_name_object) gss_export_name_object, /* gss_export_name_object */ +#else + (fn_sspi_gss_import_name_object) NULL, /* gss_import_name_object */ + (fn_sspi_gss_export_name_object) NULL, /* gss_export_name_object */ +#endif + (fn_sspi_gss_add_cred) gss_add_cred, /* gss_add_cred */ + (fn_sspi_gss_inquire_cred_by_mech) gss_inquire_cred_by_mech, /* gss_inquire_cred_by_mech */ + (fn_sspi_gss_export_sec_context) gss_export_sec_context, /* gss_export_sec_context */ + (fn_sspi_gss_import_sec_context) gss_import_sec_context, /* gss_import_sec_context */ + (fn_sspi_gss_release_oid) gss_release_oid, /* gss_release_oid */ + (fn_sspi_gss_create_empty_oid_set) gss_create_empty_oid_set, /* gss_create_empty_oid_set */ + (fn_sspi_gss_add_oid_set_member) gss_add_oid_set_member, /* gss_add_oid_set_member */ + (fn_sspi_gss_test_oid_set_member) gss_test_oid_set_member, /* gss_test_oid_set_member */ +#ifdef WITH_GSSAPI_MIT + (fn_sspi_gss_str_to_oid) gss_str_to_oid, /* gss_str_to_oid */ +#else + (fn_sspi_gss_str_to_oid) NULL, /* gss_str_to_oid */ +#endif + (fn_sspi_gss_oid_to_str) gss_oid_to_str, /* gss_oid_to_str */ + (fn_sspi_gss_inquire_names_for_mech) gss_inquire_names_for_mech, /* gss_inquire_names_for_mech */ + (fn_sspi_gss_inquire_mechs_for_name) gss_inquire_mechs_for_name, /* gss_inquire_mechs_for_name */ + (fn_sspi_gss_sign) gss_sign, /* gss_sign */ + (fn_sspi_gss_verify) gss_verify, /* gss_verify */ + (fn_sspi_gss_seal) gss_seal, /* gss_seal */ + (fn_sspi_gss_unseal) gss_unseal, /* gss_unseal */ + (fn_sspi_gss_export_name) gss_export_name, /* gss_export_name */ + (fn_sspi_gss_duplicate_name) gss_duplicate_name, /* gss_duplicate_name */ + (fn_sspi_gss_canonicalize_name) gss_canonicalize_name, /* gss_canonicalize_name */ + (fn_sspi_gss_pseudo_random) gss_pseudo_random, /* gss_pseudo_random */ + (fn_sspi_gss_store_cred) gss_store_cred, /* gss_store_cred */ +#ifdef WITH_GSSAPI_MIT + (fn_sspi_gss_set_neg_mechs) gss_set_neg_mechs, /* gss_set_neg_mechs */ +#else + (fn_sspi_gss_set_neg_mechs) NULL, /* gss_set_neg_mechs */ +#endif +}; + +#endif + +GSSAPI_FUNCTION_TABLE g_GssApi = +{ + NULL, /* gss_acquire_cred */ + NULL, /* gss_release_cred */ + NULL, /* gss_init_sec_context */ + NULL, /* gss_accept_sec_context */ + NULL, /* gss_process_context_token */ + NULL, /* gss_delete_sec_context */ + NULL, /* gss_context_time */ + NULL, /* gss_get_mic */ + NULL, /* gss_verify_mic */ + NULL, /* gss_wrap */ + NULL, /* gss_unwrap */ + NULL, /* gss_display_status */ + NULL, /* gss_indicate_mechs */ + NULL, /* gss_compare_name */ + NULL, /* gss_display_name */ + NULL, /* gss_import_name */ + NULL, /* gss_release_name */ + NULL, /* gss_release_buffer */ + NULL, /* gss_release_oid_set */ + NULL, /* gss_inquire_cred */ + NULL, /* gss_inquire_context */ + NULL, /* gss_wrap_size_limit */ + NULL, /* gss_import_name_object */ + NULL, /* gss_export_name_object */ + NULL, /* gss_add_cred */ + NULL, /* gss_inquire_cred_by_mech */ + NULL, /* gss_export_sec_context */ + NULL, /* gss_import_sec_context */ + NULL, /* gss_release_oid */ + NULL, /* gss_create_empty_oid_set */ + NULL, /* gss_add_oid_set_member */ + NULL, /* gss_test_oid_set_member */ + NULL, /* gss_str_to_oid */ + NULL, /* gss_oid_to_str */ + NULL, /* gss_inquire_names_for_mech */ + NULL, /* gss_inquire_mechs_for_name */ + NULL, /* gss_sign */ + NULL, /* gss_verify */ + NULL, /* gss_seal */ + NULL, /* gss_unseal */ + NULL, /* gss_export_name */ + NULL, /* gss_duplicate_name */ + NULL, /* gss_canonicalize_name */ + NULL, /* gss_pseudo_random */ + NULL, /* gss_store_cred */ + NULL, /* gss_set_neg_mechs */ +}; + +int sspi_GssApiInit() +{ + if (g_Initialized) + return 1; + + g_Initialized = TRUE; +#ifdef WITH_GSSAPI + CopyMemory(&g_GssApi, &g_GssApiLink, sizeof(GSSAPI_FUNCTION_TABLE)); + return 1; +#else + return -1; +#endif +} diff --git a/winpr/libwinpr/sspi/sspi_gss.h b/winpr/libwinpr/sspi/sspi_gss.h new file mode 100644 index 000000000..4ad9988a3 --- /dev/null +++ b/winpr/libwinpr/sspi/sspi_gss.h @@ -0,0 +1,883 @@ +/** + * FreeRDP: A Remote Desktop Protocol Implementation + * Generic Security Service Application Program Interface (GSSAPI) + * + * Copyright 2015 ANSSI, Author Thomas Calderon + * Copyright 2015 Marc-Andre Moreau + * + * 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 +#include + +/** + * 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 */ diff --git a/winpr/libwinpr/sspi/sspi_winpr.c b/winpr/libwinpr/sspi/sspi_winpr.c index 3d731e3f5..cff5178a9 100644 --- a/winpr/libwinpr/sspi/sspi_winpr.c +++ b/winpr/libwinpr/sspi/sspi_winpr.c @@ -3,6 +3,7 @@ * Security Support Provider Interface (SSPI) * * Copyright 2012-2014 Marc-Andre Moreau + * Copyright 2017 Dorian Ducournau * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -42,6 +43,11 @@ extern const SecPkgInfoW NTLM_SecPkgInfoW; extern const SecurityFunctionTableA NTLM_SecurityFunctionTableA; extern const SecurityFunctionTableW NTLM_SecurityFunctionTableW; +extern const SecPkgInfoA KERBEROS_SecPkgInfoA; +extern const SecPkgInfoW KERBEROS_SecPkgInfoW; +extern const SecurityFunctionTableA KERBEROS_SecurityFunctionTableA; +extern const SecurityFunctionTableW KERBEROS_SecurityFunctionTableW; + extern const SecPkgInfoA NEGOTIATE_SecPkgInfoA; extern const SecPkgInfoW NEGOTIATE_SecPkgInfoW; extern const SecurityFunctionTableA NEGOTIATE_SecurityFunctionTableA; @@ -60,6 +66,7 @@ extern const SecurityFunctionTableW SCHANNEL_SecurityFunctionTableW; const SecPkgInfoA* SecPkgInfoA_LIST[] = { &NTLM_SecPkgInfoA, + &KERBEROS_SecPkgInfoA, &NEGOTIATE_SecPkgInfoA, &CREDSSP_SecPkgInfoA, &SCHANNEL_SecPkgInfoA @@ -68,6 +75,7 @@ const SecPkgInfoA* SecPkgInfoA_LIST[] = const SecPkgInfoW* SecPkgInfoW_LIST[] = { &NTLM_SecPkgInfoW, + &KERBEROS_SecPkgInfoW, &NEGOTIATE_SecPkgInfoW, &CREDSSP_SecPkgInfoW, &SCHANNEL_SecPkgInfoW @@ -93,19 +101,22 @@ typedef struct _SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME; const SecurityFunctionTableA_NAME SecurityFunctionTableA_NAME_LIST[] = { { "NTLM", &NTLM_SecurityFunctionTableA }, + { "Kerberos", &KERBEROS_SecurityFunctionTableA }, { "Negotiate", &NEGOTIATE_SecurityFunctionTableA }, { "CREDSSP", &CREDSSP_SecurityFunctionTableA }, { "Schannel", &SCHANNEL_SecurityFunctionTableA } }; -WCHAR NTLM_NAME_W[] = { 'N','T','L','M','\0' }; -WCHAR NEGOTIATE_NAME_W[] = { 'N','e','g','o','t','i','a','t','e','\0' }; -WCHAR CREDSSP_NAME_W[] = { 'C','r','e','d','S','S','P','\0' }; -WCHAR SCHANNEL_NAME_W[] = { 'S','c','h','a','n','n','e','l','\0' }; +WCHAR NTLM_NAME_W[] = { 'N', 'T', 'L', 'M', '\0' }; +WCHAR KERBEROS_NAME_W[] = { 'K', 'e', 'r', 'b', 'e', 'r', 'o', 's', '\0' }; +WCHAR NEGOTIATE_NAME_W[] = { 'N', 'e', 'g', 'o', 't', 'i', 'a', 't', 'e', '\0' }; +WCHAR CREDSSP_NAME_W[] = { 'C', 'r', 'e', 'd', 'S', 'S', 'P', '\0' }; +WCHAR SCHANNEL_NAME_W[] = { 'S', 'c', 'h', 'a', 'n', 'n', 'e', 'l', '\0' }; const SecurityFunctionTableW_NAME SecurityFunctionTableW_NAME_LIST[] = { { NTLM_NAME_W, &NTLM_SecurityFunctionTableW }, + { KERBEROS_NAME_W, &KERBEROS_SecurityFunctionTableW }, { NEGOTIATE_NAME_W, &NEGOTIATE_SecurityFunctionTableW }, { CREDSSP_NAME_W, &CREDSSP_SecurityFunctionTableW }, { SCHANNEL_NAME_W, &SCHANNEL_SecurityFunctionTableW } @@ -134,13 +145,10 @@ CONTEXT_BUFFER_ALLOC_TABLE ContextBufferAllocTable; int sspi_ContextBufferAllocTableNew() { size_t size; - ContextBufferAllocTable.entries = NULL; ContextBufferAllocTable.cEntries = 0; ContextBufferAllocTable.cMaxEntries = 4; - size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries; - ContextBufferAllocTable.entries = (CONTEXT_BUFFER_ALLOC_ENTRY*) calloc(1, size); if (!ContextBufferAllocTable.entries) @@ -155,7 +163,6 @@ int sspi_ContextBufferAllocTableGrow() CONTEXT_BUFFER_ALLOC_ENTRY* entries; ContextBufferAllocTable.cEntries = 0; ContextBufferAllocTable.cMaxEntries *= 2; - size = sizeof(CONTEXT_BUFFER_ALLOC_ENTRY) * ContextBufferAllocTable.cMaxEntries; if (!size) @@ -170,9 +177,8 @@ int sspi_ContextBufferAllocTableGrow() } ContextBufferAllocTable.entries = entries; - - ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], size / 2); - + ZeroMemory((void*) &ContextBufferAllocTable.entries[ContextBufferAllocTable.cMaxEntries / 2], + size / 2); return 1; } @@ -197,10 +203,8 @@ void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size) return NULL; ContextBufferAllocTable.cEntries++; - ContextBufferAllocTable.entries[index].contextBuffer = contextBuffer; ContextBufferAllocTable.entries[index].allocatorIndex = allocatorIndex; - return ContextBufferAllocTable.entries[index].contextBuffer; } } @@ -211,24 +215,21 @@ void* sspi_ContextBufferAlloc(UINT32 allocatorIndex, size_t size) return NULL; /* the next call to sspi_ContextBufferAlloc() should now succeed */ - return sspi_ContextBufferAlloc(allocatorIndex, size); } SSPI_CREDENTIALS* sspi_CredentialsNew() { SSPI_CREDENTIALS* credentials; - credentials = (SSPI_CREDENTIALS*) calloc(1, sizeof(SSPI_CREDENTIALS)); - return credentials; } void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials) { - size_t userLength; - size_t domainLength; - size_t passwordLength; + size_t userLength = 0; + size_t domainLength = 0; + size_t passwordLength = 0; if (!credentials) return; @@ -247,11 +248,9 @@ void sspi_CredentialsFree(SSPI_CREDENTIALS* credentials) memset(credentials->identity.User, 0, userLength); memset(credentials->identity.Domain, 0, domainLength); memset(credentials->identity.Password, 0, passwordLength); - free(credentials->identity.User); free(credentials->identity.Domain); free(credentials->identity.Password); - free(credentials); } @@ -261,6 +260,7 @@ void* sspi_SecBufferAlloc(PSecBuffer SecBuffer, ULONG size) return NULL; SecBuffer->pvBuffer = calloc(1, size); + if (!SecBuffer->pvBuffer) return NULL; @@ -288,7 +288,6 @@ SecHandle* sspi_SecureHandleAlloc() return NULL; SecInvalidateHandle(handle); - return handle; } @@ -300,7 +299,6 @@ void* sspi_SecureHandleGetLowerPointer(SecHandle* handle) return NULL; pointer = (void*) ~((size_t) handle->dwLower); - return pointer; } @@ -318,7 +316,7 @@ void sspi_SecureHandleSetLowerPointer(SecHandle* handle, void* pointer) if (!handle) return; - handle->dwLower = (ULONG_PTR) (~((size_t) pointer)); + handle->dwLower = (ULONG_PTR)(~((size_t) pointer)); } void* sspi_SecureHandleGetUpperPointer(SecHandle* handle) @@ -329,7 +327,6 @@ void* sspi_SecureHandleGetUpperPointer(SecHandle* handle) return NULL; pointer = (void*) ~((size_t) handle->dwUpper); - return pointer; } @@ -338,7 +335,7 @@ void sspi_SecureHandleSetUpperPointer(SecHandle* handle, void* pointer) if (!handle) return; - handle->dwUpper = (ULONG_PTR) (~((size_t) pointer)); + handle->dwUpper = (ULONG_PTR)(~((size_t) pointer)); } void sspi_SecureHandleFree(SecHandle* handle) @@ -346,55 +343,51 @@ void sspi_SecureHandleFree(SecHandle* handle) free(handle); } -int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, const char* password) +int sspi_SetAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, const char* user, const char* domain, + const char* password) { int status; - identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - free(identity->User); - identity->User = (UINT16*) NULL; identity->UserLength = 0; if (user) { - status = ConvertToUnicode(CP_UTF8, 0, user, -1, (LPWSTR*) &(identity->User), 0); + status = ConvertToUnicode(CP_UTF8, 0, user, -1, (LPWSTR*) & (identity->User), 0); if (status <= 0) return -1; - identity->UserLength = (ULONG) (status - 1); + identity->UserLength = (ULONG)(status - 1); } free(identity->Domain); - identity->Domain = (UINT16*) NULL; identity->DomainLength = 0; if (domain) { - status = ConvertToUnicode(CP_UTF8, 0, domain, -1, (LPWSTR*) &(identity->Domain), 0); + status = ConvertToUnicode(CP_UTF8, 0, domain, -1, (LPWSTR*) & (identity->Domain), 0); if (status <= 0) return -1; - identity->DomainLength = (ULONG) (status - 1); + identity->DomainLength = (ULONG)(status - 1); } free(identity->Password); - identity->Password = NULL; identity->PasswordLength = 0; if (password) { - status = ConvertToUnicode(CP_UTF8, 0, password, -1, (LPWSTR*) &(identity->Password), 0); + status = ConvertToUnicode(CP_UTF8, 0, password, -1, (LPWSTR*) & (identity->Password), 0); if (status <= 0) return -1; - identity->PasswordLength = (ULONG) (status - 1); + identity->PasswordLength = (ULONG)(status - 1); } return 1; @@ -407,20 +400,18 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN if (srcIdentity->Flags == SEC_WINNT_AUTH_IDENTITY_ANSI) { status = sspi_SetAuthIdentity(identity, (char*) srcIdentity->User, - (char*) srcIdentity->Domain, (char*) srcIdentity->Password); + (char*) srcIdentity->Domain, (char*) srcIdentity->Password); if (status <= 0) return -1; identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - return 1; } identity->Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - + /* login/password authentication */ identity->User = identity->Domain = identity->Password = NULL; - identity->UserLength = srcIdentity->UserLength; if (identity->UserLength > 0) @@ -463,8 +454,7 @@ int sspi_CopyAuthIdentity(SEC_WINNT_AUTH_IDENTITY* identity, SEC_WINNT_AUTH_IDEN identity->Password[identity->PasswordLength] = 0; } - identity->PasswordLength = srcIdentity->PasswordLength; - + /* End of login/password authentication */ return 1; } @@ -492,7 +482,6 @@ void sspi_GlobalInit() if (!sspi_initialized) { winpr_InitializeSSL(WINPR_SSL_INIT_DEFAULT); - sspi_ContextBufferAllocTableNew(); sspi_initialized = TRUE; } @@ -512,7 +501,6 @@ SecurityFunctionTableA* sspi_GetSecurityFunctionTableAByNameA(const SEC_CHAR* Na { int index; UINT32 cPackages; - cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -535,7 +523,6 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameW(const SEC_WCHAR* N { int index; UINT32 cPackages; - cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -554,7 +541,6 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Na int status; SEC_WCHAR* NameW = NULL; SecurityFunctionTableW* table; - status = ConvertToUnicode(CP_UTF8, 0, Name, -1, &NameW, 0); if (status <= 0) @@ -562,7 +548,6 @@ SecurityFunctionTableW* sspi_GetSecurityFunctionTableWByNameA(const SEC_CHAR* Na table = sspi_GetSecurityFunctionTableWByNameW(NameW); free(NameW); - return table; } @@ -580,21 +565,19 @@ void sspi_ContextBufferFree(void* contextBuffer) { contextBuffer = ContextBufferAllocTable.entries[index].contextBuffer; allocatorIndex = ContextBufferAllocTable.entries[index].allocatorIndex; - ContextBufferAllocTable.cEntries--; - ContextBufferAllocTable.entries[index].allocatorIndex = 0; ContextBufferAllocTable.entries[index].contextBuffer = NULL; switch (allocatorIndex) { - case EnumerateSecurityPackagesIndex: - FreeContextBuffer_EnumerateSecurityPackages(contextBuffer); - break; + case EnumerateSecurityPackagesIndex: + FreeContextBuffer_EnumerateSecurityPackages(contextBuffer); + break; - case QuerySecurityPackageInfoIndex: - FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer); - break; + case QuerySecurityPackageInfoIndex: + FreeContextBuffer_QuerySecurityPackageInfo(contextBuffer); + break; } } } @@ -606,16 +589,15 @@ void sspi_ContextBufferFree(void* contextBuffer) /* Package Management */ -SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, PSecPkgInfoW* ppPackageInfo) +SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, + PSecPkgInfoW* ppPackageInfo) { int index; size_t size; UINT32 cPackages; SecPkgInfoW* pPackageInfo; - cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST)); size = sizeof(SecPkgInfoW) * cPackages; - pPackageInfo = (SecPkgInfoW*) sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size); if (!pPackageInfo) @@ -633,20 +615,18 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesW(ULONG* pcPackages, PS *(pcPackages) = cPackages; *(ppPackageInfo) = pPackageInfo; - return SEC_E_OK; } -SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PSecPkgInfoA* ppPackageInfo) +SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, + PSecPkgInfoA* ppPackageInfo) { int index; size_t size; UINT32 cPackages; SecPkgInfoA* pPackageInfo; - cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST)); size = sizeof(SecPkgInfoA) * cPackages; - pPackageInfo = (SecPkgInfoA*) sspi_ContextBufferAlloc(EnumerateSecurityPackagesIndex, size); if (!pPackageInfo) @@ -660,6 +640,7 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PS pPackageInfo[index].cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken; pPackageInfo[index].Name = _strdup(SecPkgInfoA_LIST[index]->Name); pPackageInfo[index].Comment = _strdup(SecPkgInfoA_LIST[index]->Comment); + if (!pPackageInfo[index].Name || !pPackageInfo[index].Comment) { sspi_ContextBufferFree(pPackageInfo); @@ -669,7 +650,6 @@ SECURITY_STATUS SEC_ENTRY winpr_EnumerateSecurityPackagesA(ULONG* pcPackages, PS *(pcPackages) = cPackages; *(ppPackageInfo) = pPackageInfo; - return SEC_E_OK; } @@ -678,7 +658,6 @@ void FreeContextBuffer_EnumerateSecurityPackages(void* contextBuffer) int index; UINT32 cPackages; SecPkgInfoA* pPackageInfo = (SecPkgInfoA*) contextBuffer; - cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -700,13 +679,13 @@ SecurityFunctionTableA* SEC_ENTRY winpr_InitSecurityInterfaceA(void) return &winpr_SecurityFunctionTableA; } -SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, PSecPkgInfoW* ppPackageInfo) +SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageName, + PSecPkgInfoW* ppPackageInfo) { int index; size_t size; UINT32 cPackages; SecPkgInfoW* pPackageInfo; - cPackages = sizeof(SecPkgInfoW_LIST) / sizeof(*(SecPkgInfoW_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -725,25 +704,22 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoW(SEC_WCHAR* pszPackageN pPackageInfo->cbMaxToken = SecPkgInfoW_LIST[index]->cbMaxToken; pPackageInfo->Name = _wcsdup(SecPkgInfoW_LIST[index]->Name); pPackageInfo->Comment = _wcsdup(SecPkgInfoW_LIST[index]->Comment); - *(ppPackageInfo) = pPackageInfo; - return SEC_E_OK; } } *(ppPackageInfo) = NULL; - return SEC_E_SECPKG_NOT_FOUND; } -SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName, PSecPkgInfoA* ppPackageInfo) +SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageName, + PSecPkgInfoA* ppPackageInfo) { int index; size_t size; UINT32 cPackages; SecPkgInfoA* pPackageInfo; - cPackages = sizeof(SecPkgInfoA_LIST) / sizeof(*(SecPkgInfoA_LIST)); for (index = 0; index < (int) cPackages; index++) @@ -762,6 +738,7 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageNa pPackageInfo->cbMaxToken = SecPkgInfoA_LIST[index]->cbMaxToken; pPackageInfo->Name = _strdup(SecPkgInfoA_LIST[index]->Name); pPackageInfo->Comment = _strdup(SecPkgInfoA_LIST[index]->Comment); + if (!pPackageInfo->Name || !pPackageInfo->Comment) { sspi_ContextBufferFree(pPackageInfo); @@ -769,13 +746,11 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityPackageInfoA(SEC_CHAR* pszPackageNa } *(ppPackageInfo) = pPackageInfo; - return SEC_E_OK; } } *(ppPackageInfo) = NULL; - return SEC_E_SECPKG_NOT_FOUND; } @@ -793,9 +768,10 @@ void FreeContextBuffer_QuerySecurityPackageInfo(void* contextBuffer) /* Credential Management */ -SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, SEC_WCHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipal, + SEC_WCHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS status; SecurityFunctionTableW* table = sspi_GetSecurityFunctionTableWByNameW(pszPackage); @@ -807,20 +783,21 @@ SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleW(SEC_WCHAR* pszPrincipa return SEC_E_UNSUPPORTED_FUNCTION; status = table->AcquireCredentialsHandleW(pszPrincipal, pszPackage, fCredentialUse, - pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); + pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "AcquireCredentialsHandleW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, SEC_CHAR* pszPackage, - ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, - void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal, + SEC_CHAR* pszPackage, + ULONG fCredentialUse, void* pvLogonID, void* pAuthData, SEC_GET_KEY_FN pGetKeyFn, + void* pvGetKeyArgument, PCredHandle phCredential, PTimeStamp ptsExpiry) { SECURITY_STATUS status; SecurityFunctionTableA* table = sspi_GetSecurityFunctionTableAByNameA(pszPackage); @@ -832,23 +809,23 @@ SECURITY_STATUS SEC_ENTRY winpr_AcquireCredentialsHandleA(SEC_CHAR* pszPrincipal return SEC_E_UNSUPPORTED_FUNCTION; status = table->AcquireCredentialsHandleA(pszPrincipal, pszPackage, fCredentialUse, - pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); + pvLogonID, pAuthData, pGetKeyFn, pvGetKeyArgument, phCredential, ptsExpiry); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "AcquireCredentialsHandleA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags, PSecBuffer pPackedContext, HANDLE* pToken) +SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULONG fFlags, + PSecBuffer pPackedContext, HANDLE* pToken) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -867,7 +844,7 @@ SECURITY_STATUS SEC_ENTRY winpr_ExportSecurityContext(PCtxtHandle phContext, ULO if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ExportSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -878,7 +855,6 @@ SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential) char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -897,18 +873,18 @@ SECURITY_STATUS SEC_ENTRY winpr_FreeCredentialsHandle(PCredHandle phCredential) if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "FreeCredentialsHandle status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext) +SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, + PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -927,18 +903,18 @@ SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextW(SEC_WCHAR* pszPackage, PS if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ImportSecurityContextW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext) +SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, + PSecBuffer pPackedContext, HANDLE pToken, PCtxtHandle phContext) { char* Name = NULL; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -957,18 +933,18 @@ SECURITY_STATUS SEC_ENTRY winpr_ImportSecurityContextA(SEC_CHAR* pszPackage, PSe if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ImportSecurityContextA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { SEC_WCHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_WCHAR*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -987,18 +963,18 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesW(PCredHandle phCreden if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QueryCredentialsAttributesW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCredential, + ULONG ulAttribute, void* pBuffer) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -1017,7 +993,7 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCreden if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QueryCredentialsAttributesA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1025,14 +1001,14 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryCredentialsAttributesA(PCredHandle phCreden /* Context Management */ -SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential, PCtxtHandle phContext, - PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) +SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential, + PCtxtHandle phContext, + PSecBufferDesc pInput, ULONG fContextReq, ULONG TargetDataRep, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsTimeStamp) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -1047,12 +1023,12 @@ SECURITY_STATUS SEC_ENTRY winpr_AcceptSecurityContext(PCredHandle phCredential, return SEC_E_UNSUPPORTED_FUNCTION; status = table->AcceptSecurityContext(phCredential, phContext, pInput, fContextReq, - TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp); + TargetDataRep, phNewContext, pOutput, pfContextAttr, ptsTimeStamp); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "AcceptSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1063,7 +1039,6 @@ SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext, PSecBuf char* Name = NULL; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1082,7 +1057,7 @@ SECURITY_STATUS SEC_ENTRY winpr_ApplyControlToken(PCtxtHandle phContext, PSecBuf if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ApplyControlToken status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1093,7 +1068,6 @@ SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext, PSecBuf char* Name = NULL; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1112,7 +1086,7 @@ SECURITY_STATUS SEC_ENTRY winpr_CompleteAuthToken(PCtxtHandle phContext, PSecBuf if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "CompleteAuthToken status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1123,7 +1097,6 @@ SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext) char* Name = NULL; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1142,7 +1115,7 @@ SECURITY_STATUS SEC_ENTRY winpr_DeleteSecurityContext(PCtxtHandle phContext) if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "DeleteSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1154,7 +1127,6 @@ SECURITY_STATUS SEC_ENTRY winpr_FreeContextBuffer(void* pvContextBuffer) return SEC_E_INVALID_HANDLE; sspi_ContextBufferFree(pvContextBuffer); - return SEC_E_OK; } @@ -1163,7 +1135,6 @@ SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1182,21 +1153,21 @@ SECURITY_STATUS SEC_ENTRY winpr_ImpersonateSecurityContext(PCtxtHandle phContext if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "ImpersonateSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredential, PCtxtHandle phContext, - SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_WCHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -1211,27 +1182,27 @@ SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextW(PCredHandle phCredent return SEC_E_UNSUPPORTED_FUNCTION; status = table->InitializeSecurityContextW(phCredential, phContext, - pszTargetName, fContextReq, Reserved1, TargetDataRep, - pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); + pszTargetName, fContextReq, Reserved1, TargetDataRep, + pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "InitializeSecurityContextW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredential, PCtxtHandle phContext, - SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, - PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, - PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) +SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredential, + PCtxtHandle phContext, + SEC_CHAR* pszTargetName, ULONG fContextReq, ULONG Reserved1, ULONG TargetDataRep, + PSecBufferDesc pInput, ULONG Reserved2, PCtxtHandle phNewContext, + PSecBufferDesc pOutput, PULONG pfContextAttr, PTimeStamp ptsExpiry) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phCredential); if (!Name) @@ -1246,24 +1217,24 @@ SECURITY_STATUS SEC_ENTRY winpr_InitializeSecurityContextA(PCredHandle phCredent return SEC_E_UNSUPPORTED_FUNCTION; status = table->InitializeSecurityContextA(phCredential, phContext, - pszTargetName, fContextReq, Reserved1, TargetDataRep, - pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); + pszTargetName, fContextReq, Reserved1, TargetDataRep, + pInput, Reserved2, phNewContext, pOutput, pfContextAttr, ptsExpiry); if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "InitializeSecurityContextA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1282,18 +1253,18 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesW(PCtxtHandle phContext, U if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QueryContextAttributesW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer) +SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1312,7 +1283,7 @@ SECURITY_STATUS SEC_ENTRY winpr_QueryContextAttributesA(PCtxtHandle phContext, U if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QueryContextAttributesA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1323,7 +1294,6 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext, SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1342,18 +1312,18 @@ SECURITY_STATUS SEC_ENTRY winpr_QuerySecurityContextToken(PCtxtHandle phContext, if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "QuerySecurityContextToken status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) +SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer) { SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1372,18 +1342,18 @@ SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesW(PCtxtHandle phContext, ULO if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "SetContextAttributesW status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, void* pBuffer, ULONG cbBuffer) +SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULONG ulAttribute, + void* pBuffer, ULONG cbBuffer) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1402,7 +1372,7 @@ SECURITY_STATUS SEC_ENTRY winpr_SetContextAttributesA(PCtxtHandle phContext, ULO if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "SetContextAttributesA status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1413,7 +1383,6 @@ SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext) SEC_CHAR* Name; SECURITY_STATUS status; SecurityFunctionTableW* table; - Name = (SEC_CHAR*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1432,7 +1401,7 @@ SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext) if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "RevertSecurityContext status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; @@ -1440,12 +1409,12 @@ SECURITY_STATUS SEC_ENTRY winpr_RevertSecurityContext(PCtxtHandle phContext) /* Message Support */ -SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) +SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBufferDesc pMessage, + ULONG MessageSeqNo, PULONG pfQOP) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1464,18 +1433,18 @@ SECURITY_STATUS SEC_ENTRY winpr_DecryptMessage(PCtxtHandle phContext, PSecBuffer if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "DecryptMessage status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1494,18 +1463,18 @@ SECURITY_STATUS SEC_ENTRY winpr_EncryptMessage(PCtxtHandle phContext, ULONG fQOP if (status != SEC_E_OK) { WLog_ERR(TAG, "EncryptMessage status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP, PSecBufferDesc pMessage, ULONG MessageSeqNo) +SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP, + PSecBufferDesc pMessage, ULONG MessageSeqNo) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1524,18 +1493,18 @@ SECURITY_STATUS SEC_ENTRY winpr_MakeSignature(PCtxtHandle phContext, ULONG fQOP, if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "MakeSignature status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; } -SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, ULONG MessageSeqNo, PULONG pfQOP) +SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBufferDesc pMessage, + ULONG MessageSeqNo, PULONG pfQOP) { char* Name; SECURITY_STATUS status; SecurityFunctionTableA* table; - Name = (char*) sspi_SecureHandleGetUpperPointer(phContext); if (!Name) @@ -1554,7 +1523,7 @@ SECURITY_STATUS SEC_ENTRY winpr_VerifySignature(PCtxtHandle phContext, PSecBuffe if (IsSecurityStatusError(status)) { WLog_WARN(TAG, "VerifySignature status %s [0x%08"PRIX32"]", - GetSecurityStatusString(status), status); + GetSecurityStatusString(status), status); } return status; diff --git a/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c b/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c index 66ebacac7..7c4eda7e7 100644 --- a/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c +++ b/winpr/libwinpr/sspi/test/TestAcquireCredentialsHandle.c @@ -37,7 +37,7 @@ int TestAcquireCredentialsHandle(int argc, char* argv[]) identity.PasswordLength = strlen(test_Password); identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; - status = table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, + status = table->AcquireCredentialsHandle(NULL, NTLMSSP_NAME, SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) diff --git a/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c b/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c index e5e930843..ac91a25cb 100644 --- a/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c +++ b/winpr/libwinpr/sspi/test/TestInitializeSecurityContext.c @@ -29,7 +29,7 @@ int TestInitializeSecurityContext(int argc, char* argv[]) table = InitSecurityInterface(); - status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo); + status = QuerySecurityPackageInfo(NTLMSSP_NAME, &pPackageInfo); if (status != SEC_E_OK) { @@ -56,7 +56,7 @@ int TestInitializeSecurityContext(int argc, char* argv[]) identity.PasswordLength = strlen(test_Password); identity.Flags = SEC_WINNT_AUTH_IDENTITY_ANSI; - status = table->AcquireCredentialsHandle(NULL, NTLMSP_NAME, + status = table->AcquireCredentialsHandle(NULL, NTLMSSP_NAME, SECPKG_CRED_OUTBOUND, NULL, &identity, NULL, NULL, &credentials, &expiration); if (status != SEC_E_OK) diff --git a/winpr/libwinpr/sspi/test/TestNTLM.c b/winpr/libwinpr/sspi/test/TestNTLM.c index eb424e65a..ffac39d23 100644 --- a/winpr/libwinpr/sspi/test/TestNTLM.c +++ b/winpr/libwinpr/sspi/test/TestNTLM.c @@ -72,8 +72,7 @@ static const BYTE TEST_NTLM_HASH[16] = static const BYTE TEST_NTLM_V2_HASH[16] = { 0x4c, 0x7f, 0x70, 0x6f, 0x7d, 0xde, 0x05, 0xa9, 0xd1, 0xa0, 0xf4, 0xe7, 0xff, 0xe3, 0xbf, 0xb8 }; -//#define NTLM_PACKAGE_NAME NEGOSSP_NAME -#define NTLM_PACKAGE_NAME NTLMSP_NAME +#define NTLM_PACKAGE_NAME NTLMSSP_NAME struct _TEST_NTLM_CLIENT { diff --git a/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c b/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c index a85797f48..c86e19967 100644 --- a/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c +++ b/winpr/libwinpr/sspi/test/TestQuerySecurityPackageInfo.c @@ -11,7 +11,7 @@ int TestQuerySecurityPackageInfo(int argc, char* argv[]) sspi_GlobalInit(); - status = QuerySecurityPackageInfo(NTLMSP_NAME, &pPackageInfo); + status = QuerySecurityPackageInfo(NTLMSSP_NAME, &pPackageInfo); if (status != SEC_E_OK) {