From 023ec28aaefeff99ab1d3d8c06a90e40581bb972 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 8 Jun 2022 18:03:14 +0000 Subject: [PATCH 1/5] Fix build detection of GSS_KRB5_CRED_NO_CI_FLAGS_X --- .../System.Net.Security.Native/pal_gssapi.c | 23 ++++++++++++------- src/native/libs/configure.cmake | 13 +++++++++++ 2 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/native/libs/System.Net.Security.Native/pal_gssapi.c b/src/native/libs/System.Net.Security.Native/pal_gssapi.c index 6206fa0fa0ce42..efb8d92237e74c 100644 --- a/src/native/libs/System.Net.Security.Native/pal_gssapi.c +++ b/src/native/libs/System.Net.Security.Native/pal_gssapi.c @@ -58,6 +58,18 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = STRING_LENGTH(gss_ntlm_o #if defined(GSS_SHIM) +#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X + +#define FOR_ALL_OPTIONAL_GSS_FUNCTIONS \ + PER_FUNCTION_BLOCK(gss_set_cred_option) \ + PER_FUNCTION_BLOCK(GSS_KRB5_CRED_NO_CI_FLAGS_X) + +#else + +#define FOR_ALL_OPTIONAL_GSS_FUNCTIONS + +#endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X + #define FOR_ALL_GSS_FUNCTIONS \ PER_FUNCTION_BLOCK(gss_accept_sec_context) \ PER_FUNCTION_BLOCK(gss_acquire_cred) \ @@ -78,14 +90,8 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = STRING_LENGTH(gss_ntlm_o PER_FUNCTION_BLOCK(gss_unwrap) \ PER_FUNCTION_BLOCK(gss_wrap) \ PER_FUNCTION_BLOCK(GSS_C_NT_USER_NAME) \ - PER_FUNCTION_BLOCK(GSS_C_NT_HOSTBASED_SERVICE) - -#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X - -#define FOR_ALL_GSS_FUNCTIONS FOR_ALL_GSS_FUNCTIONS \ - PER_FUNCTION_BLOCK(gss_set_cred_option) - -#endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X + PER_FUNCTION_BLOCK(GSS_C_NT_HOSTBASED_SERVICE) \ + FOR_ALL_OPTIONAL_GSS_FUNCTIONS // define indirection pointers for all functions, like // static TYPEOF(gss_accept_sec_context)* gss_accept_sec_context_ptr; @@ -118,6 +124,7 @@ static void* volatile s_gssLib = NULL; #if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X #define gss_set_cred_option(...) gss_set_cred_option_ptr(__VA_ARGS__) +#define GSS_KRB5_CRED_NO_CI_FLAGS_X (*GSS_KRB5_CRED_NO_CI_FLAGS_X_ptr) #endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X diff --git a/src/native/libs/configure.cmake b/src/native/libs/configure.cmake index 8567842366bc5a..4559017946f488 100644 --- a/src/native/libs/configure.cmake +++ b/src/native/libs/configure.cmake @@ -1030,6 +1030,17 @@ check_include_files( GSS/GSS.h HAVE_GSSFW_HEADERS) +if (HAVE_GSSFW_HEADERS) + find_library(LIBGSS NAMES GSS) +elseif (HAVE_HEIMDAL_HEADERS) + find_library(LIBGSS NAMES gssapi) +else () + find_library(LIBGSS NAMES gssapi_krb5) +endif () + +set (PREVIOUS_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES}) +set (CMAKE_REQUIRED_LIBRARIES ${LIBGSS}) + if (HAVE_GSSFW_HEADERS) check_symbol_exists( GSS_SPNEGO_MECHANISM @@ -1054,6 +1065,8 @@ else () HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X) endif () +set (CMAKE_REQUIRED_LIBRARIES ${PREVIOUS_CMAKE_REQUIRED_LIBRARIES}) + check_symbol_exists(getauxval sys/auxv.h HAVE_GETAUXVAL) check_include_files(crt_externs.h HAVE_CRT_EXTERNS_H) From 3490f24ab7a8d609f6327f41f844e0a93370cadb Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 8 Jun 2022 18:11:32 +0000 Subject: [PATCH 2/5] Don't use GSS_KRB5_CRED_NO_CI_FLAGS_X on NTLM --- src/native/libs/System.Net.Security.Native/pal_gssapi.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/native/libs/System.Net.Security.Native/pal_gssapi.c b/src/native/libs/System.Net.Security.Native/pal_gssapi.c index efb8d92237e74c..7a52249c84cfe0 100644 --- a/src/native/libs/System.Net.Security.Native/pal_gssapi.c +++ b/src/native/libs/System.Net.Security.Native/pal_gssapi.c @@ -613,7 +613,7 @@ static uint32_t AcquireCredWithPassword(uint32_t* minorStatus, // call gss_set_cred_option with GSS_KRB5_CRED_NO_CI_FLAGS_X to support Kerberos Sign Only option from *nix client against a windows server #if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X - if (majorStatus == GSS_S_COMPLETE) + if (!isNtlm && majorStatus == GSS_S_COMPLETE) { GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER; majorStatus = gss_set_cred_option(minorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer); From 2f3e77ccdb53c8c85b5b729b115f4d917bbe2dc3 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Wed, 8 Jun 2022 23:50:36 +0200 Subject: [PATCH 3/5] Handle GSS_S_UNAVAILABLE error from gss_set_cred_option (NTLM wrapped in Negotiate) --- .../System.Net.Security.Native/pal_gssapi.c | 22 +++++++++++++++++-- 1 file changed, 20 insertions(+), 2 deletions(-) diff --git a/src/native/libs/System.Net.Security.Native/pal_gssapi.c b/src/native/libs/System.Net.Security.Native/pal_gssapi.c index 7a52249c84cfe0..7dd5ca0fb80855 100644 --- a/src/native/libs/System.Net.Security.Native/pal_gssapi.c +++ b/src/native/libs/System.Net.Security.Native/pal_gssapi.c @@ -193,7 +193,16 @@ static uint32_t AcquireCredSpNego(uint32_t* minorStatus, if (majorStatus == GSS_S_COMPLETE) { GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER; - majorStatus = gss_set_cred_option(minorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer); + uint32_t tempMinorStatus; + majorStatus = gss_set_cred_option(&tempMinorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer); + if (majorStatus == GSS_S_UNAVAILABLE) + { + majorStatus = GSS_S_COMPLETE; + } + else + { + *minorStatus = tempMinorStatus; + } } #endif @@ -616,7 +625,16 @@ static uint32_t AcquireCredWithPassword(uint32_t* minorStatus, if (!isNtlm && majorStatus == GSS_S_COMPLETE) { GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER; - majorStatus = gss_set_cred_option(minorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer); + uint32_t tempMinorStatus; + majorStatus = gss_set_cred_option(&tempMinorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer); + if (majorStatus == GSS_S_UNAVAILABLE) + { + majorStatus = GSS_S_COMPLETE; + } + else + { + *minorStatus = tempMinorStatus; + } } #endif From 65b5ef73b0c6f6861f896d7360ecc3bee2b8ec1f Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 9 Jun 2022 06:16:50 +0000 Subject: [PATCH 4/5] Make the GSSAPI shim work with krb5 1.13 --- .../System.Net.Security.Native/pal_gssapi.c | 25 ++++++++++++++----- 1 file changed, 19 insertions(+), 6 deletions(-) diff --git a/src/native/libs/System.Net.Security.Native/pal_gssapi.c b/src/native/libs/System.Net.Security.Native/pal_gssapi.c index 7dd5ca0fb80855..78df8dbb0961f7 100644 --- a/src/native/libs/System.Net.Security.Native/pal_gssapi.c +++ b/src/native/libs/System.Net.Security.Native/pal_gssapi.c @@ -64,13 +64,15 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = STRING_LENGTH(gss_ntlm_o PER_FUNCTION_BLOCK(gss_set_cred_option) \ PER_FUNCTION_BLOCK(GSS_KRB5_CRED_NO_CI_FLAGS_X) +#define GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE (gss_set_cred_option_ptr != NULL && GSS_KRB5_CRED_NO_CI_FLAGS_X_ptr != NULL) + #else #define FOR_ALL_OPTIONAL_GSS_FUNCTIONS #endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X -#define FOR_ALL_GSS_FUNCTIONS \ +#define FOR_ALL_REQUIRED_GSS_FUNCTIONS \ PER_FUNCTION_BLOCK(gss_accept_sec_context) \ PER_FUNCTION_BLOCK(gss_acquire_cred) \ PER_FUNCTION_BLOCK(gss_acquire_cred_with_password) \ @@ -91,6 +93,9 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = STRING_LENGTH(gss_ntlm_o PER_FUNCTION_BLOCK(gss_wrap) \ PER_FUNCTION_BLOCK(GSS_C_NT_USER_NAME) \ PER_FUNCTION_BLOCK(GSS_C_NT_HOSTBASED_SERVICE) \ + +#define FOR_ALL_GSS_FUNCTIONS \ + FOR_ALL_REQUIRED_GSS_FUNCTIONS \ FOR_ALL_OPTIONAL_GSS_FUNCTIONS // define indirection pointers for all functions, like @@ -145,19 +150,27 @@ static int32_t ensure_gss_shim_initialized() dlclose(lib); } - // initialize indirection pointers for all functions, like: + // initialize indirection pointers for all required functions, like: // gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context"); // if (gss_accept_sec_context_ptr == NULL) { fprintf(stderr, "Cannot get symbol %s from %s \nError: %s\n", "gss_accept_sec_context", gss_lib_name, dlerror()); return -1; } #define PER_FUNCTION_BLOCK(fn) \ fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \ if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", gss_lib_name, dlerror()); return -1; } - - FOR_ALL_GSS_FUNCTIONS +FOR_ALL_REQUIRED_GSS_FUNCTIONS +#undef PER_FUNCTION_BLOCK + // for optional functions skip the error check +#define PER_FUNCTION_BLOCK(fn) \ + fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); +FOR_ALL_OPTIONAL_GSS_FUNCTIONS #undef PER_FUNCTION_BLOCK return 0; } +#else // GSS_SHIM + +#define GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE 1 + #endif // GSS_SHIM // transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer @@ -190,7 +203,7 @@ static uint32_t AcquireCredSpNego(uint32_t* minorStatus, // call gss_set_cred_option with GSS_KRB5_CRED_NO_CI_FLAGS_X to support Kerberos Sign Only option from *nix client against a windows server #if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X - if (majorStatus == GSS_S_COMPLETE) + if (majorStatus == GSS_S_COMPLETE && GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE) { GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER; uint32_t tempMinorStatus; @@ -622,7 +635,7 @@ static uint32_t AcquireCredWithPassword(uint32_t* minorStatus, // call gss_set_cred_option with GSS_KRB5_CRED_NO_CI_FLAGS_X to support Kerberos Sign Only option from *nix client against a windows server #if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X - if (!isNtlm && majorStatus == GSS_S_COMPLETE) + if (!isNtlm && majorStatus == GSS_S_COMPLETE && GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE) { GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER; uint32_t tempMinorStatus; From 2f7906ac8737612cf4798c1aab9fa4b785b92741 Mon Sep 17 00:00:00 2001 From: Filip Navara Date: Thu, 9 Jun 2022 09:02:04 +0000 Subject: [PATCH 5/5] Preserve the gss_acquire_cred minor status --- src/native/libs/System.Net.Security.Native/pal_gssapi.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/native/libs/System.Net.Security.Native/pal_gssapi.c b/src/native/libs/System.Net.Security.Native/pal_gssapi.c index 78df8dbb0961f7..9d0c2fce2c4a56 100644 --- a/src/native/libs/System.Net.Security.Native/pal_gssapi.c +++ b/src/native/libs/System.Net.Security.Native/pal_gssapi.c @@ -208,8 +208,9 @@ static uint32_t AcquireCredSpNego(uint32_t* minorStatus, GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER; uint32_t tempMinorStatus; majorStatus = gss_set_cred_option(&tempMinorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer); - if (majorStatus == GSS_S_UNAVAILABLE) + if (majorStatus == GSS_S_UNAVAILABLE || majorStatus == GSS_S_COMPLETE) { + // preserve the original majorStatus/minorStatus from gss_acquire_cred majorStatus = GSS_S_COMPLETE; } else @@ -640,8 +641,9 @@ static uint32_t AcquireCredWithPassword(uint32_t* minorStatus, GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER; uint32_t tempMinorStatus; majorStatus = gss_set_cred_option(&tempMinorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer); - if (majorStatus == GSS_S_UNAVAILABLE) + if (majorStatus == GSS_S_UNAVAILABLE || majorStatus == GSS_S_COMPLETE) { + // preserve the original majorStatus/minorStatus from gss_acquire_cred_with_password majorStatus = GSS_S_COMPLETE; } else