Skip to content

Commit 84f7cad

Browse files
authored
Fix usage of GSS_KRB5_CRED_NO_CI_FLAGS_X (#70447)
* Fix build detection of GSS_KRB5_CRED_NO_CI_FLAGS_X * Don't use GSS_KRB5_CRED_NO_CI_FLAGS_X on NTLM * Handle GSS_S_UNAVAILABLE error from gss_set_cred_option (NTLM wrapped in Negotiate) * Make the GSSAPI shim work with krb5 1.13 * Preserve the gss_acquire_cred minor status
1 parent 3bb45af commit 84f7cad

2 files changed

Lines changed: 68 additions & 15 deletions

File tree

src/native/libs/System.Net.Security.Native/pal_gssapi.c

Lines changed: 55 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,21 @@ static gss_OID_desc gss_mech_ntlm_OID_desc = {.length = STRING_LENGTH(gss_ntlm_o
5858

5959
#if defined(GSS_SHIM)
6060

61-
#define FOR_ALL_GSS_FUNCTIONS \
61+
#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
62+
63+
#define FOR_ALL_OPTIONAL_GSS_FUNCTIONS \
64+
PER_FUNCTION_BLOCK(gss_set_cred_option) \
65+
PER_FUNCTION_BLOCK(GSS_KRB5_CRED_NO_CI_FLAGS_X)
66+
67+
#define GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE (gss_set_cred_option_ptr != NULL && GSS_KRB5_CRED_NO_CI_FLAGS_X_ptr != NULL)
68+
69+
#else
70+
71+
#define FOR_ALL_OPTIONAL_GSS_FUNCTIONS
72+
73+
#endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
74+
75+
#define FOR_ALL_REQUIRED_GSS_FUNCTIONS \
6276
PER_FUNCTION_BLOCK(gss_accept_sec_context) \
6377
PER_FUNCTION_BLOCK(gss_acquire_cred) \
6478
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
7892
PER_FUNCTION_BLOCK(gss_unwrap) \
7993
PER_FUNCTION_BLOCK(gss_wrap) \
8094
PER_FUNCTION_BLOCK(GSS_C_NT_USER_NAME) \
81-
PER_FUNCTION_BLOCK(GSS_C_NT_HOSTBASED_SERVICE)
82-
83-
#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
95+
PER_FUNCTION_BLOCK(GSS_C_NT_HOSTBASED_SERVICE) \
8496

85-
#define FOR_ALL_GSS_FUNCTIONS FOR_ALL_GSS_FUNCTIONS \
86-
PER_FUNCTION_BLOCK(gss_set_cred_option)
87-
88-
#endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
97+
#define FOR_ALL_GSS_FUNCTIONS \
98+
FOR_ALL_REQUIRED_GSS_FUNCTIONS \
99+
FOR_ALL_OPTIONAL_GSS_FUNCTIONS
89100

90101
// define indirection pointers for all functions, like
91102
// static TYPEOF(gss_accept_sec_context)* gss_accept_sec_context_ptr;
@@ -118,6 +129,7 @@ static void* volatile s_gssLib = NULL;
118129

119130
#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
120131
#define gss_set_cred_option(...) gss_set_cred_option_ptr(__VA_ARGS__)
132+
#define GSS_KRB5_CRED_NO_CI_FLAGS_X (*GSS_KRB5_CRED_NO_CI_FLAGS_X_ptr)
121133
#endif //HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
122134

123135

@@ -138,19 +150,27 @@ static int32_t ensure_gss_shim_initialized()
138150
dlclose(lib);
139151
}
140152

141-
// initialize indirection pointers for all functions, like:
153+
// initialize indirection pointers for all required functions, like:
142154
// gss_accept_sec_context_ptr = (TYPEOF(gss_accept_sec_context)*)dlsym(s_gssLib, "gss_accept_sec_context");
143155
// 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; }
144156
#define PER_FUNCTION_BLOCK(fn) \
145157
fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn); \
146158
if (fn##_ptr == NULL) { fprintf(stderr, "Cannot get symbol " #fn " from %s \nError: %s\n", gss_lib_name, dlerror()); return -1; }
147-
148-
FOR_ALL_GSS_FUNCTIONS
159+
FOR_ALL_REQUIRED_GSS_FUNCTIONS
160+
#undef PER_FUNCTION_BLOCK
161+
// for optional functions skip the error check
162+
#define PER_FUNCTION_BLOCK(fn) \
163+
fn##_ptr = (TYPEOF(fn)*)dlsym(s_gssLib, #fn);
164+
FOR_ALL_OPTIONAL_GSS_FUNCTIONS
149165
#undef PER_FUNCTION_BLOCK
150166

151167
return 0;
152168
}
153169

170+
#else // GSS_SHIM
171+
172+
#define GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE 1
173+
154174
#endif // GSS_SHIM
155175

156176
// transfers ownership of the underlying data from gssBuffer to PAL_GssBuffer
@@ -183,10 +203,20 @@ static uint32_t AcquireCredSpNego(uint32_t* minorStatus,
183203

184204
// 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
185205
#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
186-
if (majorStatus == GSS_S_COMPLETE)
206+
if (majorStatus == GSS_S_COMPLETE && GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE)
187207
{
188208
GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER;
189-
majorStatus = gss_set_cred_option(minorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer);
209+
uint32_t tempMinorStatus;
210+
majorStatus = gss_set_cred_option(&tempMinorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer);
211+
if (majorStatus == GSS_S_UNAVAILABLE || majorStatus == GSS_S_COMPLETE)
212+
{
213+
// preserve the original majorStatus/minorStatus from gss_acquire_cred
214+
majorStatus = GSS_S_COMPLETE;
215+
}
216+
else
217+
{
218+
*minorStatus = tempMinorStatus;
219+
}
190220
}
191221
#endif
192222

@@ -606,10 +636,20 @@ static uint32_t AcquireCredWithPassword(uint32_t* minorStatus,
606636

607637
// 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
608638
#if HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X
609-
if (majorStatus == GSS_S_COMPLETE)
639+
if (!isNtlm && majorStatus == GSS_S_COMPLETE && GSS_KRB5_CRED_NO_CI_FLAGS_X_AVAILABLE)
610640
{
611641
GssBuffer emptyBuffer = GSS_C_EMPTY_BUFFER;
612-
majorStatus = gss_set_cred_option(minorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer);
642+
uint32_t tempMinorStatus;
643+
majorStatus = gss_set_cred_option(&tempMinorStatus, outputCredHandle, GSS_KRB5_CRED_NO_CI_FLAGS_X, &emptyBuffer);
644+
if (majorStatus == GSS_S_UNAVAILABLE || majorStatus == GSS_S_COMPLETE)
645+
{
646+
// preserve the original majorStatus/minorStatus from gss_acquire_cred_with_password
647+
majorStatus = GSS_S_COMPLETE;
648+
}
649+
else
650+
{
651+
*minorStatus = tempMinorStatus;
652+
}
613653
}
614654
#endif
615655

src/native/libs/configure.cmake

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1030,6 +1030,17 @@ check_include_files(
10301030
GSS/GSS.h
10311031
HAVE_GSSFW_HEADERS)
10321032

1033+
if (HAVE_GSSFW_HEADERS)
1034+
find_library(LIBGSS NAMES GSS)
1035+
elseif (HAVE_HEIMDAL_HEADERS)
1036+
find_library(LIBGSS NAMES gssapi)
1037+
else ()
1038+
find_library(LIBGSS NAMES gssapi_krb5)
1039+
endif ()
1040+
1041+
set (PREVIOUS_CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES})
1042+
set (CMAKE_REQUIRED_LIBRARIES ${LIBGSS})
1043+
10331044
if (HAVE_GSSFW_HEADERS)
10341045
check_symbol_exists(
10351046
GSS_SPNEGO_MECHANISM
@@ -1054,6 +1065,8 @@ else ()
10541065
HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X)
10551066
endif ()
10561067

1068+
set (CMAKE_REQUIRED_LIBRARIES ${PREVIOUS_CMAKE_REQUIRED_LIBRARIES})
1069+
10571070
check_symbol_exists(getauxval sys/auxv.h HAVE_GETAUXVAL)
10581071
check_include_files(crt_externs.h HAVE_CRT_EXTERNS_H)
10591072

0 commit comments

Comments
 (0)