This can happen when credentials are cached.
From: Hans Leidekker hans@codeweavers.com
--- dlls/secur32/lsa.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/secur32/lsa.c b/dlls/secur32/lsa.c index 3cbd49e6b0e..27d5e52cff7 100644 --- a/dlls/secur32/lsa.c +++ b/dlls/secur32/lsa.c @@ -663,6 +663,7 @@ static SECURITY_STATUS WINAPI lsa_QueryContextAttributesA(CtxtHandle *context, U switch (attribute) { case SECPKG_ATTR_SIZES: + case SECPKG_ATTR_SESSION_KEY: return lsa_QueryContextAttributesW( context, attribute, buffer );
case SECPKG_ATTR_NEGOTIATION_INFO: @@ -699,7 +700,6 @@ static SECURITY_STATUS WINAPI lsa_QueryContextAttributesA(CtxtHandle *context, U X(SECPKG_ATTR_NATIVE_NAMES); X(SECPKG_ATTR_PACKAGE_INFO); X(SECPKG_ATTR_PASSWORD_EXPIRY); - X(SECPKG_ATTR_SESSION_KEY); X(SECPKG_ATTR_STREAM_SIZES); X(SECPKG_ATTR_TARGET_INFORMATION); #undef X
From: Hans Leidekker hans@codeweavers.com
--- dlls/msv1_0/main.c | 14 +++++++++++++- dlls/secur32/tests/ntlm.c | 10 ++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-)
diff --git a/dlls/msv1_0/main.c b/dlls/msv1_0/main.c index a877d974486..53d8f1b6415 100644 --- a/dlls/msv1_0/main.c +++ b/dlls/msv1_0/main.c @@ -1138,7 +1138,6 @@ static NTSTATUS NTAPI ntlm_SpQueryContextAttributes( LSA_SEC_HANDLE handle, ULON X(SECPKG_ATTR_NATIVE_NAMES); X(SECPKG_ATTR_PACKAGE_INFO); X(SECPKG_ATTR_PASSWORD_EXPIRY); - X(SECPKG_ATTR_SESSION_KEY); X(SECPKG_ATTR_STREAM_SIZES); X(SECPKG_ATTR_TARGET_INFORMATION); case SECPKG_ATTR_FLAGS: @@ -1167,6 +1166,19 @@ static NTSTATUS NTAPI ntlm_SpQueryContextAttributes( LSA_SEC_HANDLE handle, ULON info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE; return SEC_E_OK; } + case SECPKG_ATTR_SESSION_KEY: + { + struct ntlm_ctx *ctx = (struct ntlm_ctx *)handle; + SecPkgContext_SessionKey *key = (SecPkgContext_SessionKey *)buf; + unsigned char *session_key; + + if (!(session_key = RtlAllocateHeap( GetProcessHeap(), 0, sizeof(ctx->session_key) ))) + return SEC_E_INSUFFICIENT_MEMORY; + memcpy( session_key, ctx->session_key, sizeof(ctx->session_key) ); + key->SessionKey = session_key; + key->SessionKeyLength = sizeof(ctx->session_key); + return SEC_E_OK; + } case SECPKG_ATTR_KEY_INFO: { struct ntlm_ctx *ctx = (struct ntlm_ctx *)handle; diff --git a/dlls/secur32/tests/ntlm.c b/dlls/secur32/tests/ntlm.c index 4accf4b2d79..42d9b580d71 100644 --- a/dlls/secur32/tests/ntlm.c +++ b/dlls/secur32/tests/ntlm.c @@ -824,6 +824,7 @@ static void testAuth(ULONG data_rep, BOOL fake) SecPkgContext_StreamSizes stream_sizes; SecPkgContext_NegotiationInfoA info; SecPkgContext_KeyInfoA key; + SecPkgContext_SessionKey session_key; SecPkgInfoA *pi;
if(pQuerySecurityPackageInfoA( sec_pkg_name, &pkg_info)!= SEC_E_OK) @@ -927,6 +928,15 @@ static void testAuth(ULONG data_rep, BOOL fake) } ok( key.KeySize == 128, "got %lu\n", key.KeySize ); ok( key.EncryptAlgorithm == CALG_RC4, "got %#lx\n", key.EncryptAlgorithm ); + FreeContextBuffer( key.sSignatureAlgorithmName ); + FreeContextBuffer( key.sEncryptAlgorithmName ); + + memset( &session_key, 0, sizeof(session_key) ); + sec_status = QueryContextAttributesA( &client.ctxt, SECPKG_ATTR_SESSION_KEY, &session_key ); + ok( sec_status == SEC_E_OK, "pQueryContextAttributesA returned %08lx\n", sec_status ); + ok( session_key.SessionKeyLength, "got 0 key length\n" ); + ok( session_key.SessionKey != NULL, "got NULL session key\n" ); + FreeContextBuffer( session_key.SessionKey );
memset(&info, 0, sizeof(info)); sec_status = QueryContextAttributesA(&client.ctxt, SECPKG_ATTR_NEGOTIATION_INFO, &info);
From: Hans Leidekker hans@codeweavers.com
--- dlls/kerberos/krb5_ap.c | 20 ++++++++++-- dlls/kerberos/unixlib.c | 72 ++++++++++++++++++++++++++++++++--------- 2 files changed, 75 insertions(+), 17 deletions(-)
diff --git a/dlls/kerberos/krb5_ap.c b/dlls/kerberos/krb5_ap.c index 2f46b7f246f..0cd44b9ca96 100644 --- a/dlls/kerberos/krb5_ap.c +++ b/dlls/kerberos/krb5_ap.c @@ -633,9 +633,26 @@ static NTSTATUS NTAPI kerberos_SpQueryContextAttributes( LSA_SEC_HANDLE context, X(SECPKG_ATTR_NATIVE_NAMES); X(SECPKG_ATTR_PACKAGE_INFO); X(SECPKG_ATTR_PASSWORD_EXPIRY); - X(SECPKG_ATTR_SESSION_KEY); X(SECPKG_ATTR_STREAM_SIZES); X(SECPKG_ATTR_TARGET_INFORMATION); +#undef X + case SECPKG_ATTR_SESSION_KEY: + { + SecPkgContext_SessionKey key = { 128 }; + struct query_context_attributes_params params = { context_handle->handle, attribute, &key }; + NTSTATUS status; + + if (!(key.SessionKey = RtlAllocateHeap( GetProcessHeap(), 0, key.SessionKeyLength ))) return STATUS_NO_MEMORY; + + if ((status = KRB5_CALL( query_context_attributes, ¶ms ))) + { + RtlFreeHeap( GetProcessHeap(), 0, key.SessionKey ); + return status; + } + + *(SecPkgContext_SessionKey *)buffer = key; + return SEC_E_OK; + } case SECPKG_ATTR_SIZES: { struct query_context_attributes_params params = { context_handle->handle, attribute, buffer }; @@ -648,7 +665,6 @@ static NTSTATUS NTAPI kerberos_SpQueryContextAttributes( LSA_SEC_HANDLE context, info->NegotiationState = SECPKG_NEGOTIATION_COMPLETE; return SEC_E_OK; } -#undef X default: FIXME( "unknown attribute %lu\n", attribute ); break; diff --git a/dlls/kerberos/unixlib.c b/dlls/kerberos/unixlib.c index 121809e231b..c81c8a220ea 100644 --- a/dlls/kerberos/unixlib.c +++ b/dlls/kerberos/unixlib.c @@ -403,7 +403,9 @@ MAKE_FUNCPTR( gss_get_mic ); MAKE_FUNCPTR( gss_import_name ); MAKE_FUNCPTR( gss_init_sec_context ); MAKE_FUNCPTR( gss_inquire_context ); +MAKE_FUNCPTR( gss_inquire_sec_context_by_oid ); MAKE_FUNCPTR( gss_release_buffer ); +MAKE_FUNCPTR( gss_release_buffer_set ); MAKE_FUNCPTR( gss_release_cred ); MAKE_FUNCPTR( gss_release_iov_buffer ); MAKE_FUNCPTR( gss_release_name ); @@ -429,21 +431,23 @@ static BOOL load_gssapi_krb5(void) goto fail; \ }
- LOAD_FUNCPTR( gss_accept_sec_context) - LOAD_FUNCPTR( gss_acquire_cred) - LOAD_FUNCPTR( gss_delete_sec_context) - LOAD_FUNCPTR( gss_display_status) - LOAD_FUNCPTR( gss_get_mic) - LOAD_FUNCPTR( gss_import_name) - LOAD_FUNCPTR( gss_init_sec_context) - LOAD_FUNCPTR( gss_inquire_context) - LOAD_FUNCPTR( gss_release_buffer) - LOAD_FUNCPTR( gss_release_cred) - LOAD_FUNCPTR( gss_release_iov_buffer) - LOAD_FUNCPTR( gss_release_name) - LOAD_FUNCPTR( gss_unwrap) - LOAD_FUNCPTR( gss_unwrap_iov) - LOAD_FUNCPTR( gss_verify_mic) + LOAD_FUNCPTR( gss_accept_sec_context ) + LOAD_FUNCPTR( gss_acquire_cred ) + LOAD_FUNCPTR( gss_delete_sec_context ) + LOAD_FUNCPTR( gss_display_status ) + LOAD_FUNCPTR( gss_get_mic ) + LOAD_FUNCPTR( gss_import_name ) + LOAD_FUNCPTR( gss_init_sec_context ) + LOAD_FUNCPTR( gss_inquire_context ) + LOAD_FUNCPTR( gss_inquire_sec_context_by_oid ) + LOAD_FUNCPTR( gss_release_buffer ) + LOAD_FUNCPTR( gss_release_buffer_set ) + LOAD_FUNCPTR( gss_release_cred ) + LOAD_FUNCPTR( gss_release_iov_buffer ) + LOAD_FUNCPTR( gss_release_name ) + LOAD_FUNCPTR( gss_unwrap ) + LOAD_FUNCPTR( gss_unwrap_iov ) + LOAD_FUNCPTR( gss_verify_mic ) LOAD_FUNCPTR( gss_wrap ) LOAD_FUNCPTR( gss_wrap_iov ) #undef LOAD_FUNCPTR @@ -804,11 +808,49 @@ static NTSTATUS make_signature( void *args ) #define KERBEROS_MAX_SIGNATURE_DCE 28 #define KERBEROS_SECURITY_TRAILER_DCE 76
+static NTSTATUS get_session_key( gss_ctx_id_t ctx, SecPkgContext_SessionKey *key ) +{ + gss_OID_desc GSS_C_INQ_SSPI_SESSION_KEY = + { 11, (void *)"\x2a\x86\x48\x86\xf7\x12\x01\x02\x02\x05\x05" }; /* 1.2.840.113554.1.2.2.5.5 */ + OM_uint32 ret, minor_status; + gss_buffer_set_t buffer_set = GSS_C_NO_BUFFER_SET; + + ret = pgss_inquire_sec_context_by_oid( &minor_status, ctx, &GSS_C_INQ_SSPI_SESSION_KEY, &buffer_set ); + if (GSS_ERROR( ret )) trace_gss_status( ret, minor_status ); + if (ret != GSS_S_COMPLETE) return STATUS_INTERNAL_ERROR; + + if (buffer_set == GSS_C_NO_BUFFER_SET || buffer_set->count != 2) + { + pgss_release_buffer_set( &minor_status, &buffer_set ); + return STATUS_INTERNAL_ERROR; + } + + if (key->SessionKeyLength < buffer_set->elements[0].length ) + { + key->SessionKeyLength = buffer_set->elements[0].length; + pgss_release_buffer_set( &minor_status, &buffer_set ); + return STATUS_BUFFER_TOO_SMALL; + } + + memcpy( key->SessionKey, buffer_set->elements[0].value, buffer_set->elements[0].length ); + key->SessionKeyLength = buffer_set->elements[0].length; + + pgss_release_buffer_set( &minor_status, &buffer_set ); + return STATUS_SUCCESS; +} + static NTSTATUS query_context_attributes( void *args ) { struct query_context_attributes_params *params = args; switch (params->attr) { + case SECPKG_ATTR_SESSION_KEY: + { + SecPkgContext_SessionKey *key = (SecPkgContext_SessionKey *)params->buf; + gss_ctx_id_t ctx = ctxhandle_sspi_to_gss( params->context ); + + return get_session_key( ctx, key ); + } case SECPKG_ATTR_SIZES: { SecPkgContext_Sizes *sizes = (SecPkgContext_Sizes *)params->buf;
From: Hans Leidekker hans@codeweavers.com
--- libs/ldap/libldap/sasl_w.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/libs/ldap/libldap/sasl_w.c b/libs/ldap/libldap/sasl_w.c index f257e4db9e3..0e45558461a 100644 --- a/libs/ldap/libldap/sasl_w.c +++ b/libs/ldap/libldap/sasl_w.c @@ -220,6 +220,14 @@ static int fill_auth_identity( const sasl_interact_t *prompts, SEC_WINNT_AUTH_ID return SASL_OK; }
+static ULONG get_key_size( CtxtHandle *ctx ) +{ + SecPkgContext_SessionKey key; + if (QueryContextAttributesA( ctx, SECPKG_ATTR_SESSION_KEY, &key )) return 0; + FreeContextBuffer( key.SessionKey ); + return key.SessionKeyLength * 8; +} + int sasl_client_start( sasl_conn_t *handle, const char *mechlist, sasl_interact_t **prompts, const char **clientout, unsigned int *clientoutlen, const char **mech ) { @@ -287,14 +295,9 @@ int sasl_client_step( sasl_conn_t *handle, const char *serverin, unsigned int se if (status == SEC_I_CONTINUE_NEEDED) return SASL_CONTINUE; else { - SecPkgContext_KeyInfoA key; SecPkgContext_Sizes sizes;
- status = QueryContextAttributesA( &conn->ctxt_handle, SECPKG_ATTR_KEY_INFO, &key ); - if (status != SEC_E_OK) return SASL_FAIL; - FreeContextBuffer( key.sSignatureAlgorithmName ); - FreeContextBuffer( key.sEncryptAlgorithmName ); - conn->ssf = key.KeySize; + conn->ssf = get_key_size( &conn->ctxt_handle );
status = QueryContextAttributesA( &conn->ctxt_handle, SECPKG_ATTR_SIZES, &sizes ); if (status != SEC_E_OK) return SASL_FAIL;
From: Hans Leidekker hans@codeweavers.com
This can happen when credentials are cached. --- libs/ldap/libldap/sasl_w.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-)
diff --git a/libs/ldap/libldap/sasl_w.c b/libs/ldap/libldap/sasl_w.c index 0e45558461a..4f0b809ab63 100644 --- a/libs/ldap/libldap/sasl_w.c +++ b/libs/ldap/libldap/sasl_w.c @@ -261,7 +261,12 @@ int sasl_client_start( sasl_conn_t *handle, const char *mechlist, sasl_interact_ *clientout = out_bufs[0].pvBuffer; *clientoutlen = out_bufs[0].cbBuffer; *mech = "GSS-SPNEGO"; - return (status == SEC_I_CONTINUE_NEEDED) ? SASL_CONTINUE : SASL_OK; + if (status == SEC_I_CONTINUE_NEEDED) return SASL_CONTINUE; + else + { + conn->ssf = get_key_size( &conn->ctxt_handle ); + return SASL_OK; + } }
return SASL_FAIL;
From: Hans Leidekker hans@codeweavers.com
--- libs/ldap/libldap/sasl_w.c | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-)
diff --git a/libs/ldap/libldap/sasl_w.c b/libs/ldap/libldap/sasl_w.c index 4f0b809ab63..83e78adb2a5 100644 --- a/libs/ldap/libldap/sasl_w.c +++ b/libs/ldap/libldap/sasl_w.c @@ -228,6 +228,13 @@ static ULONG get_key_size( CtxtHandle *ctx ) return key.SessionKeyLength * 8; }
+static ULONG get_trailer_size( CtxtHandle *ctx ) +{ + SecPkgContext_Sizes sizes; + if (QueryContextAttributesA( ctx, SECPKG_ATTR_SIZES, &sizes )) return 0; + return sizes.cbSecurityTrailer; +} + int sasl_client_start( sasl_conn_t *handle, const char *mechlist, sasl_interact_t **prompts, const char **clientout, unsigned int *clientoutlen, const char **mech ) { @@ -265,6 +272,7 @@ int sasl_client_start( sasl_conn_t *handle, const char *mechlist, sasl_interact_ else { conn->ssf = get_key_size( &conn->ctxt_handle ); + conn->trailer_size = get_trailer_size( &conn->ctxt_handle ); return SASL_OK; } } @@ -300,13 +308,8 @@ int sasl_client_step( sasl_conn_t *handle, const char *serverin, unsigned int se if (status == SEC_I_CONTINUE_NEEDED) return SASL_CONTINUE; else { - SecPkgContext_Sizes sizes; - conn->ssf = get_key_size( &conn->ctxt_handle ); - - status = QueryContextAttributesA( &conn->ctxt_handle, SECPKG_ATTR_SIZES, &sizes ); - if (status != SEC_E_OK) return SASL_FAIL; - conn->trailer_size = sizes.cbSecurityTrailer; + conn->trailer_size = get_trailer_size( &conn->ctxt_handle ); return SASL_OK; } }