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..9d0c2fce2c4a56 100644 --- a/src/native/libs/System.Net.Security.Native/pal_gssapi.c +++ b/src/native/libs/System.Net.Security.Native/pal_gssapi.c @@ -58,7 +58,21 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = STRING_LENGTH(gss_ntlm_o #if defined(GSS_SHIM) -#define FOR_ALL_GSS_FUNCTIONS \ +#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) + +#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_REQUIRED_GSS_FUNCTIONS \ PER_FUNCTION_BLOCK(gss_accept_sec_context) \ PER_FUNCTION_BLOCK(gss_acquire_cred) \ PER_FUNCTION_BLOCK(gss_acquire_cred_with_password) \ @@ -78,14 +92,11 @@ 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 + PER_FUNCTION_BLOCK(GSS_C_NT_HOSTBASED_SERVICE) \ -#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 +#define FOR_ALL_GSS_FUNCTIONS \ + FOR_ALL_REQUIRED_GSS_FUNCTIONS \ + 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 +129,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 @@ -138,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 @@ -183,10 +203,20 @@ 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; - 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) + { + // preserve the original majorStatus/minorStatus from gss_acquire_cred + majorStatus = GSS_S_COMPLETE; + } + else + { + *minorStatus = tempMinorStatus; + } } #endif @@ -606,10 +636,20 @@ 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 && GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE) { 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) + { + // preserve the original majorStatus/minorStatus from gss_acquire_cred_with_password + majorStatus = GSS_S_COMPLETE; + } + else + { + *minorStatus = tempMinorStatus; + } } #endif 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)