From: Dmitry Timoshkov dmitry@baikal.ru
RFC4752 mentions these flags as required on the client side: https://www.rfc-editor.org/rfc/rfc4752#page-3
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=55304 Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- libs/ldap/libldap/sasl_w.c | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-)
diff --git a/libs/ldap/libldap/sasl_w.c b/libs/ldap/libldap/sasl_w.c index 48028352ef4..1d514d0f047 100644 --- a/libs/ldap/libldap/sasl_w.c +++ b/libs/ldap/libldap/sasl_w.c @@ -1,5 +1,6 @@ /* * Copyright 2022 Hans Leidekker for CodeWeavers + * Copyright 2023 Dmitry Timoshkov * * SSPI based replacement for Cyrus SASL * @@ -18,6 +19,10 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include "portable.h" +#include "ldap-int.h" +#include "ldap_log.h" + #include <assert.h> #include <stdio.h> #include <stdlib.h> @@ -36,6 +41,7 @@ struct connection sasl_interact_t prompts[4]; unsigned int max_token; unsigned int trailer_size; + unsigned int qop; sasl_ssf_t ssf; char *buf; unsigned buf_size; @@ -147,6 +153,8 @@ int sasl_client_new( const char *service, const char *server, const char *localp SecPkgInfoA *info; int len;
+ ldap_log_printf( NULL, LDAP_DEBUG_TRACE, "sasl_client_new: service %s, server %s\n", service, server ); + if (!check_callback( prompt, SASL_CB_AUTHNAME ) || !check_callback( prompt, SASL_CB_GETREALM ) || !check_callback( prompt, SASL_CB_PASS )) return SASL_BADPARAM;
@@ -261,10 +269,13 @@ int sasl_client_start( sasl_conn_t *handle, const char *mechlist, sasl_interact_ { 0, SECBUFFER_ALERT, NULL } }; SecBufferDesc out_buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(out_bufs), out_bufs }; - ULONG attrs, flags = ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY; + /* FIXME: flags probably should depend on LDAP_OPT_SSPI_FLAGS */ + ULONG attrs, flags = ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_MUTUAL_AUTH | ISC_REQ_SEQUENCE_DETECT; SECURITY_STATUS status; int ret;
+ ldap_log_printf( NULL, LDAP_DEBUG_TRACE, "sasl_client_start\n" ); + if (!*prompts) { *prompts = conn->prompts; @@ -311,9 +322,12 @@ int sasl_client_step( sasl_conn_t *handle, const char *serverin, unsigned int se }; SecBufferDesc in_buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(in_bufs), in_bufs }; SecBufferDesc out_buf_desc = { SECBUFFER_VERSION, ARRAYSIZE(out_bufs), out_bufs }; - ULONG attrs, flags = ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY; + /* FIXME: flags probably should depend on LDAP_OPT_SSPI_FLAGS */ + ULONG attrs, flags = ISC_REQ_INTEGRITY | ISC_REQ_CONFIDENTIALITY | ISC_REQ_MUTUAL_AUTH | ISC_REQ_SEQUENCE_DETECT; SECURITY_STATUS status;
+ ldap_log_printf( NULL, LDAP_DEBUG_TRACE, "sasl_client_step: target %s\n", conn->target ); + status = InitializeSecurityContextA( NULL, &conn->ctxt_handle, conn->target, flags, 0, 0, &in_buf_desc, 0, &conn->ctxt_handle, &out_buf_desc, &attrs, NULL ); if (status == SEC_E_OK || status == SEC_I_CONTINUE_NEEDED) @@ -323,8 +337,13 @@ int sasl_client_step( sasl_conn_t *handle, const char *serverin, unsigned int se if (status == SEC_I_CONTINUE_NEEDED) return SASL_CONTINUE; else { + if (((flags & ISC_REQ_INTEGRITY) && !(attrs & ISC_RET_INTEGRITY)) || + ((flags & ISC_REQ_CONFIDENTIALITY) && !(attrs & ISC_RET_CONFIDENTIALITY))) + return SASL_BADSERV; /* refuse to continue if the server doesn't support requested security levels */ + conn->ssf = get_key_size( &conn->ctxt_handle ); conn->trailer_size = get_trailer_size( &conn->ctxt_handle ); + conn->qop = attrs; return SASL_OK; } }