From 6c17e3d2800723bafebd1986ab59a9422c881f0b Mon Sep 17 00:00:00 2001 From: Stefan Metzmacher Date: Tue, 23 Jan 2024 14:20:24 +0100 Subject: [PATCH] s4:ldap_server: add support for tls channel bindings ldap server require strong auth = allow_sasl_over_tls is now an alias for 'allow_sasl_without_tls_channel_bindings' and should be avoided and changed to 'yes' or 'allow_sasl_without_tls_channel_bindings'. BUG: https://bugzilla.samba.org/show_bug.cgi?id=15621 Signed-off-by: Stefan Metzmacher Reviewed-by: Andrew Bartlett --- .../ldap/ldapserverrequirestrongauth.xml | 40 +++++++++--- lib/param/loadparm.h | 1 + lib/param/param_table.c | 2 + python/samba/netcmd/testparm.py | 10 +++ selftest/target/Samba4.pm | 2 +- source3/utils/testparm.c | 12 ++++ source4/ldap_server/ldap_bind.c | 62 ++++++++++++++++--- source4/ldap_server/ldap_server.c | 11 ++++ 8 files changed, 123 insertions(+), 17 deletions(-) diff --git a/docs-xml/smbdotconf/ldap/ldapserverrequirestrongauth.xml b/docs-xml/smbdotconf/ldap/ldapserverrequirestrongauth.xml index 02bdd811491..18f8903dcaa 100644 --- a/docs-xml/smbdotconf/ldap/ldapserverrequirestrongauth.xml +++ b/docs-xml/smbdotconf/ldap/ldapserverrequirestrongauth.xml @@ -7,20 +7,44 @@ The defines whether the ldap server requires ldap traffic to be signed or signed and encrypted (sealed). - Possible values are no, allow_sasl_over_tls + Possible values are no, + allow_sasl_without_tls_channel_bindings and yes. - A value of no allows simple and sasl binds over - all transports. + Windows has LdapEnforceChannelBinding under + HKLM\SYSTEM\CurrentControlSet\Services\NTDS\Parameters\. + - A value of allow_sasl_over_tls allows simple and sasl binds - (without sign or seal) over TLS encrypted connections. Unencrypted connections only - allow sasl binds with sign or seal. + A value of no allows simple and sasl binds over + all transports. This matches LdapEnforceChannelBinding=0. + + A value of allow_sasl_without_tls_channel_bindings + allows simple and sasl binds (without sign or seal) over TLS encrypted connections. + Missing tls channel bindings are ignored, so only use this if a value of + yes is not possible. + Unencrypted connections only allow sasl binds with sign or seal. + This matches LdapEnforceChannelBinding=1. + + + Before support for tls channel bindings existed in Samba, + a value of allow_sasl_over_tls was possible in order + to allow sasl binds without tls channel bindings. This now misleading + as a value of yes will now allow sasl binds + with tls channel bindings. Configurations should be changed to + yes instead or + allow_sasl_without_tls_channel_bindings + if really required. Currently allow_sasl_over_tls + is just an alias of allow_sasl_without_tls_channel_bindings, + but it will be removed in future versions. + A value of yes allows only simple binds - over TLS encrypted connections. Unencrypted connections only - allow sasl binds with sign or seal. + and sasl binds with correct tls channel bindings + over TLS encrypted connections. sasl binds without tls channel bindings + are not allowed. Unencrypted connections only + allow sasl binds with sign or seal. This matches LdapEnforceChannelBinding=2. + yes diff --git a/lib/param/loadparm.h b/lib/param/loadparm.h index 0bf4c173652..7e9e5d2da3f 100644 --- a/lib/param/loadparm.h +++ b/lib/param/loadparm.h @@ -206,6 +206,7 @@ enum printing_types {PRINT_BSD,PRINT_SYSV,PRINT_AIX,PRINT_HPUX, enum ldap_server_require_strong_auth { LDAP_SERVER_REQUIRE_STRONG_AUTH_NO, LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS, + LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_WITHOUT_TLS_CB, LDAP_SERVER_REQUIRE_STRONG_AUTH_YES, }; diff --git a/lib/param/param_table.c b/lib/param/param_table.c index ce591560ba8..8db4c381e41 100644 --- a/lib/param/param_table.c +++ b/lib/param/param_table.c @@ -318,6 +318,8 @@ static const struct enum_list enum_ldap_server_require_strong_auth_vals[] = { { LDAP_SERVER_REQUIRE_STRONG_AUTH_NO, "0" }, { LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS, "allow_sasl_over_tls" }, + { LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_WITHOUT_TLS_CB, + "allow_sasl_without_tls_channel_bindings" }, { LDAP_SERVER_REQUIRE_STRONG_AUTH_YES, "Yes" }, { LDAP_SERVER_REQUIRE_STRONG_AUTH_YES, "True" }, { LDAP_SERVER_REQUIRE_STRONG_AUTH_YES, "1" }, diff --git a/python/samba/netcmd/testparm.py b/python/samba/netcmd/testparm.py index 41dbb4bd623..a419ddf1260 100644 --- a/python/samba/netcmd/testparm.py +++ b/python/samba/netcmd/testparm.py @@ -183,6 +183,16 @@ class cmd_testparm(Command): "When acting as Active Directory domain controller, " + entry + " should be in vfs objects.") + strong_auth = lp.get("ldap server require strong auth") + if strong_auth == "allow_sasl_over_tls": + logger.warning( + "WARNING: You have not configured " + "'ldap server require strong auth = " + "allow_sasl_over_tls'.\n" + "Please change to 'yes' (preferred) or " + "'allow_sasl_without_tls_channel_bindings' " + "(if really needed).") + return valid def allow_access(self, deny_list, allow_list, cname, caddr): diff --git a/selftest/target/Samba4.pm b/selftest/target/Samba4.pm index 48a78b2c8d2..f52d6740c6e 100755 --- a/selftest/target/Samba4.pm +++ b/selftest/target/Samba4.pm @@ -1625,7 +1625,7 @@ sub provision_ad_dc_ntvfs($$$) print "PROVISIONING AD DC (NTVFS)...\n"; my $extra_conf_options = "netbios aliases = localDC1-a server services = +winbind -winbindd - ldap server require strong auth = allow_sasl_over_tls + ldap server require strong auth = allow_sasl_without_tls_channel_bindings raw NTLMv2 auth = yes lsa over netlogon = yes rpc server port = 1027 diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index fd90e8d734a..34bce413f82 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -615,6 +615,18 @@ static int do_global_checks(void) ret = 1; } + if (lp_ldap_server_require_strong_auth() == + LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS) + { + fprintf(stderr, + "WARNING: You have not configured " + "'ldap server require strong auth = " + "allow_sasl_over_tls'.\n" + "Please change to 'yes' (preferred) or " + "'allow_sasl_without_tls_channel_bindings' " + "(if really needed)\n\n"); + } + if (lp_server_schannel() != true) { /* can be 'auto' */ fprintf(stderr, "WARNING: You have not configured " diff --git a/source4/ldap_server/ldap_bind.c b/source4/ldap_server/ldap_bind.c index d592d472c06..65e252edb70 100644 --- a/source4/ldap_server/ldap_bind.c +++ b/source4/ldap_server/ldap_bind.c @@ -27,6 +27,7 @@ #include "dsdb/samdb/samdb.h" #include "auth/gensec/gensec.h" #include "auth/gensec/gensec_tstream.h" +#include "lib/tls/tls.h" #include "param/param.h" #include "../lib/util/tevent_ntstatus.h" #include "lib/util/time_basic.h" @@ -359,6 +360,49 @@ static NTSTATUS ldapsrv_setup_gensec(struct ldapsrv_connection *conn, gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAP_STYLE); if (conn->sockets.active == conn->sockets.tls) { + uint32_t initiator_addrtype = 0; + const DATA_BLOB *initiator_address = NULL; + uint32_t acceptor_addrtype = 0; + const DATA_BLOB *acceptor_address = NULL; + const DATA_BLOB *application_data = + tstream_tls_channel_bindings(conn->sockets.tls); + + status = gensec_set_channel_bindings(gensec_security, + initiator_addrtype, + initiator_address, + acceptor_addrtype, + acceptor_address, + application_data); + if (!NT_STATUS_IS_OK(status)) { + return status; + } + + /* + * By default channel bindings are required, + * so we only set GENSEC_FEATURE_CB_OPTIONAL + * for the legacy option: + * + * ldap server require strong auth = no + * or + * ldap server require strong auth = + * allow_sasl_without_tls_channel_bindings + * + * And this as an alias to cope with existing smb.conf + * files: + * + * ldap server require strong auth = allow_sasl_over_tls + */ + switch (conn->require_strong_auth) { + case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO: + case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS: + case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_WITHOUT_TLS_CB: + gensec_want_feature(gensec_security, + GENSEC_FEATURE_CB_OPTIONAL); + break; + default: + break; + } + gensec_want_feature(gensec_security, GENSEC_FEATURE_LDAPS_TRANSPORT); } @@ -496,6 +540,14 @@ static void ldapsrv_BindSASL_done(struct tevent_req *subreq) goto do_reply; } + if (NT_STATUS_EQUAL(status, NT_STATUS_BAD_BINDINGS)) { + result = LDAP_INVALID_CREDENTIALS; + errstr = ldapsrv_bind_error_msg(reply, + HRES_SEC_E_BAD_BINDINGS, + 0x0C090711, + status); + goto do_reply; + } if (!NT_STATUS_IS_OK(status)) { status = nt_status_squash(status); result = LDAP_INVALID_CREDENTIALS; @@ -539,17 +591,11 @@ static void ldapsrv_BindSASL_done(struct tevent_req *subreq) case LDAP_SERVER_REQUIRE_STRONG_AUTH_NO: break; case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS: + case LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_WITHOUT_TLS_CB: + case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES: if (call->conn->sockets.active == call->conn->sockets.tls) { break; } - status = NT_STATUS_NETWORK_ACCESS_DENIED; - result = LDAP_STRONG_AUTH_REQUIRED; - errstr = talloc_asprintf(reply, - "SASL:[%s]: not allowed if TLS is used.", - req->creds.SASL.mechanism); - goto do_reply; - - case LDAP_SERVER_REQUIRE_STRONG_AUTH_YES: status = NT_STATUS_NETWORK_ACCESS_DENIED; result = LDAP_STRONG_AUTH_REQUIRED; errstr = talloc_asprintf(reply, diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 497d0dbc9a1..90316fd6b68 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -378,6 +378,17 @@ static void ldapsrv_accept(struct stream_connection *c, conn->require_strong_auth = lpcfg_ldap_server_require_strong_auth(conn->lp_ctx); } + if (conn->require_strong_auth == + LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS) + { + D_ERR("WARNING: You have not configured " + "'ldap server require strong auth = " + "allow_sasl_over_tls'.\n" + "Please change to 'yes' (preferred and default) or " + "'allow_sasl_without_tls_channel_bindings' " + "(if really needed)\n\n"); + } + ret = ldapsrv_backend_Init(conn, &errstring); if (ret != LDB_SUCCESS) { char *reason = talloc_asprintf(conn,