mirror of https://github.com/FreeRDP/FreeRDP
Updated KRB5 detection, added error case handler
* Linking against KRB5 library now, no dynamic usage. * Added proper CMake detection script for KRB5 detection * Added some additional error conditions.
This commit is contained in:
parent
56c0219907
commit
50cd702a15
|
@ -656,6 +656,10 @@ 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")
|
||||
|
@ -753,6 +757,7 @@ 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})
|
||||
|
||||
if(TARGET_ARCH MATCHES "x86|x64")
|
||||
if (NOT APPLE)
|
||||
|
|
|
@ -0,0 +1,28 @@
|
|||
# - 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)
|
||||
|
||||
|
|
@ -53,7 +53,7 @@
|
|||
/* Plugins */
|
||||
#cmakedefine BUILTIN_CHANNELS
|
||||
#cmakedefine WITH_RDPDR
|
||||
#cmakedefine WITH_KRB5_SUPPORT
|
||||
#cmakedefine WITH_KRB5
|
||||
|
||||
/* Debug */
|
||||
#cmakedefine WITH_DEBUG_CERTIFICATE
|
||||
|
|
|
@ -21,6 +21,7 @@ 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")
|
||||
|
||||
|
@ -140,6 +141,10 @@ endif()
|
|||
|
||||
freerdp_library_add(${OPENSSL_LIBRARIES})
|
||||
|
||||
if (WITH_KRB5)
|
||||
freerdp_library_add(${KRB5_LIBRARIES})
|
||||
endif(WITH_KRB5)
|
||||
|
||||
if(BUILD_TESTING)
|
||||
add_subdirectory(test)
|
||||
endif()
|
||||
|
|
|
@ -59,35 +59,11 @@
|
|||
|
||||
static void* transport_client_thread(void* arg);
|
||||
|
||||
#ifdef WITH_KRB5_SUPPORT
|
||||
#ifdef WITH_KRB5
|
||||
|
||||
#include <krb5.h>
|
||||
#include <winpr/library.h>
|
||||
|
||||
static HMODULE g_KRB5Module = NULL;
|
||||
|
||||
struct _KRB5FunctionTable
|
||||
{
|
||||
krb5_error_code(* pKrb5_init_context)(krb5_context* m_context);
|
||||
krb5_error_code(*pKrb5_parse_name_flags)(krb5_context m_context, const char* m_address, int m_flags,
|
||||
krb5_principal* m_principal);
|
||||
krb5_error_code(*pKrb5_cc_cache_match)(krb5_context m_context, krb5_principal m_client,
|
||||
krb5_ccache* m_id);
|
||||
krb5_error_code(*pKrb5_cc_default)(krb5_context m_context, krb5_ccache* m_id);
|
||||
krb5_error_code(*pKrb5_init_creds_init)(krb5_context m_context, krb5_principal m_client,
|
||||
krb5_prompter_fct m_prompter, void* m_prompter_data, krb5_deltat m_start_time,
|
||||
krb5_get_init_creds_opt* m_options, krb5_init_creds_context* m_ctx);
|
||||
krb5_error_code(*pKrb5_init_creds_set_password)(krb5_context m_context,
|
||||
krb5_init_creds_context m_ctx, const char* m_password);
|
||||
krb5_error_code(*pKrb5_init_creds_get)(krb5_context m_context, krb5_init_creds_context m_ctx);
|
||||
void (*pKrb5_init_creds_free)(krb5_context m_context, krb5_init_creds_context m_ctx);
|
||||
void (*pKrb5_free_context)(krb5_context m_context);
|
||||
};
|
||||
typedef struct _KRB5FunctionTable KRB5FunctionTable;
|
||||
|
||||
static KRB5FunctionTable g_KRB5 = { 0 };
|
||||
|
||||
UINT32 transport_krb5_check_account(char* username, char* domain, char* passwd)
|
||||
static UINT32 transport_krb5_check_account(char* username, char* domain, char* passwd)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_context context;
|
||||
|
@ -95,112 +71,79 @@ UINT32 transport_krb5_check_account(char* username, char* domain, char* passwd)
|
|||
char address[256];
|
||||
krb5_ccache ccache;
|
||||
krb5_init_creds_context ctx = NULL;
|
||||
memset(address, 0, sizeof(address));
|
||||
strcpy(address, username);
|
||||
strcat(address, "@");
|
||||
strcat(address, domain);
|
||||
g_KRB5Module = LoadLibrary("libkrb5.so.26");
|
||||
|
||||
if (!g_KRB5Module)
|
||||
{
|
||||
g_KRB5Module = LoadLibrary("libkrb5.so");
|
||||
}
|
||||
|
||||
if (!g_KRB5Module)
|
||||
{
|
||||
WLog_ERR(TAG, "Failed to load krb5 module\n");
|
||||
}
|
||||
|
||||
g_KRB5.pKrb5_init_context = (void*) GetProcAddress(g_KRB5Module, "krb5_init_context");
|
||||
g_KRB5.pKrb5_parse_name_flags = (void*) GetProcAddress(g_KRB5Module, "krb5_parse_name_flags");
|
||||
g_KRB5.pKrb5_cc_cache_match = (void*) GetProcAddress(g_KRB5Module, "krb5_cc_cache_match");
|
||||
g_KRB5.pKrb5_cc_default = (void*) GetProcAddress(g_KRB5Module, "krb5_cc_default");
|
||||
g_KRB5.pKrb5_init_creds_init = (void*) GetProcAddress(g_KRB5Module, "krb5_init_creds_init");
|
||||
g_KRB5.pKrb5_init_creds_set_password = (void*) GetProcAddress(g_KRB5Module,
|
||||
"krb5_init_creds_set_password");
|
||||
g_KRB5.pKrb5_init_creds_get = (void*) GetProcAddress(g_KRB5Module, "krb5_init_creds_get");
|
||||
g_KRB5.pKrb5_init_creds_free = (void*) GetProcAddress(g_KRB5Module, "krb5_init_creds_free");
|
||||
g_KRB5.pKrb5_free_context = (void*) GetProcAddress(g_KRB5Module, "krb5_free_context");
|
||||
_snprintf(address, sizeof(address), "%s@%s", username, domain);
|
||||
|
||||
/* Create a krb5 library context */
|
||||
if ((ret = g_KRB5.pKrb5_init_context(&context)) != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "krb5_init_context failed with error %d\n", (int)ret);
|
||||
}
|
||||
|
||||
if ((ret = g_KRB5.pKrb5_parse_name_flags(context, address, 0, &principal)) != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "krb5_parse_name_flags failed with error %d\n", (int)ret);
|
||||
}
|
||||
|
||||
if ((ret = krb5_init_context(&context)) != 0)
|
||||
WLog_ERR(TAG, "krb5_init_context failed with error %d", (int)ret);
|
||||
else if ((ret = krb5_parse_name_flags(context, address, 0, &principal)) != 0)
|
||||
WLog_ERR(TAG, "krb5_parse_name_flags failed with error %d", (int)ret);
|
||||
/* Find a credential cache with a specified client principal */
|
||||
if ((ret = g_KRB5.pKrb5_cc_cache_match(context, principal, &ccache)) != 0)
|
||||
else if ((ret = krb5_cc_cache_match(context, principal, &ccache)) != 0)
|
||||
{
|
||||
if ((ret = g_KRB5.pKrb5_cc_default(context, &ccache)) != 0)
|
||||
{
|
||||
WLog_ERR(TAG, "krb5 failed to resolve credentials cache with error %d\n", (int)ret);
|
||||
}
|
||||
if ((ret = krb5_cc_default(context, &ccache)) != 0)
|
||||
WLog_ERR(TAG, "krb5 failed to resolve credentials cache with error %d", (int)ret);
|
||||
}
|
||||
|
||||
if (ret != KRB5KDC_ERR_NONE)
|
||||
goto out;
|
||||
/* Create a context for acquiring initial credentials */
|
||||
if ((ret = g_KRB5.pKrb5_init_creds_init(context, principal, NULL, NULL, 0, NULL, &ctx)) != 0)
|
||||
else if ((ret = krb5_init_creds_init(context, principal, NULL, NULL, 0, NULL, &ctx)) != 0)
|
||||
{
|
||||
WLog_WARN(TAG, "krb5_init_creds_init returned error %d\n", (int)ret);
|
||||
WLog_WARN(TAG, "krb5_init_creds_init returned error %d", (int)ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Set a password for acquiring initial credentials */
|
||||
if ((ret = g_KRB5.pKrb5_init_creds_set_password(context, ctx, passwd)) != 0)
|
||||
else if ((ret = krb5_init_creds_set_password(context, ctx, passwd)) != 0)
|
||||
{
|
||||
WLog_WARN(TAG, "krb5_init_creds_set_password returned error %d\n", ret);
|
||||
WLog_WARN(TAG, "krb5_init_creds_set_password returned error %d", ret);
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Acquire credentials using an initial credential context */
|
||||
ret = g_KRB5.pKrb5_init_creds_get(context, ctx);
|
||||
ret = krb5_init_creds_get(context, ctx);
|
||||
out:
|
||||
|
||||
switch (ret)
|
||||
{
|
||||
case 0:
|
||||
case KRB5KDC_ERR_NONE:
|
||||
break;
|
||||
|
||||
case KRB5_KDC_UNREACH:
|
||||
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
|
||||
case KRB5KRB_AP_ERR_MODIFIED:
|
||||
case KRB5KDC_ERR_PREAUTH_FAILED:
|
||||
case KRB5_GET_IN_TKT_LOOP:
|
||||
WLog_WARN(TAG, "krb5_init_creds_get: Password incorrect");
|
||||
|
||||
if (ctx)
|
||||
g_KRB5.pKrb5_init_creds_free(context, ctx);
|
||||
|
||||
return FREERDP_ERROR_AUTHENTICATION_FAILED;
|
||||
ret = FREERDP_ERROR_AUTHENTICATION_FAILED;
|
||||
break;
|
||||
|
||||
case KRB5KDC_ERR_KEY_EXP:
|
||||
WLog_WARN(TAG, "krb5_init_creds_get: Password has expired");
|
||||
ret = FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
|
||||
break;
|
||||
|
||||
if (ctx)
|
||||
g_KRB5.pKrb5_init_creds_free(context, ctx);
|
||||
case KRB5KDC_ERR_CLIENT_REVOKED:
|
||||
ret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
|
||||
break;
|
||||
|
||||
return FREERDP_ERROR_CONNECT_PASSWORD_EXPIRED;
|
||||
case KRB5KDC_ERR_POLICY:
|
||||
ret = FREERDP_ERROR_INSUFFICIENT_PRIVILEGES;
|
||||
break;
|
||||
|
||||
default:
|
||||
WLog_WARN(TAG, "krb5_init_creds_get");
|
||||
|
||||
if (ctx)
|
||||
g_KRB5.pKrb5_init_creds_free(context, ctx);
|
||||
|
||||
return FREERDP_ERROR_CONNECT_TRANSPORT_FAILED;
|
||||
ret = FREERDP_ERROR_CONNECT_TRANSPORT_FAILED;
|
||||
break;
|
||||
}
|
||||
|
||||
out:
|
||||
|
||||
if (ctx)
|
||||
g_KRB5.pKrb5_init_creds_free(context, ctx);
|
||||
krb5_init_creds_free(context, ctx);
|
||||
|
||||
g_KRB5.pKrb5_free_context(context);
|
||||
return 0;
|
||||
krb5_free_context(context);
|
||||
return ret;
|
||||
}
|
||||
#endif /* WITH_KRB5_SUPPORT */
|
||||
#endif /* WITH_KRB5 */
|
||||
|
||||
static void transport_ssl_cb(SSL* ssl, int where, int ret)
|
||||
{
|
||||
|
@ -224,7 +167,7 @@ static void transport_ssl_cb(SSL* ssl, int where, int ret)
|
|||
if (transport->NlaMode)
|
||||
{
|
||||
UINT32 kret = 0;
|
||||
#ifdef WITH_KRB5_SUPPORT
|
||||
#ifdef WITH_KRB5
|
||||
|
||||
if ((strlen(transport->settings->Domain) != 0) &&
|
||||
(strncmp(transport->settings->Domain, ".", 1) != 0))
|
||||
|
@ -233,7 +176,7 @@ static void transport_ssl_cb(SSL* ssl, int where, int ret)
|
|||
transport->settings->Password);
|
||||
}
|
||||
else
|
||||
#endif /* WITH_KRB5_SUPPORT */
|
||||
#endif /* WITH_KRB5 */
|
||||
kret = FREERDP_ERROR_CONNECT_PASSWORD_CERTAINLY_EXPIRED;
|
||||
|
||||
if (!freerdp_get_last_error(transport->context))
|
||||
|
|
Loading…
Reference in New Issue