From 80ddb52a214fae6c0f32f3aba46055464c674f55 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 21 May 2019 13:14:08 +1200 Subject: [PATCH 1/2] ldap tests: test scheme for referrals Ensure that the referrals returned in a search request use the same scheme as the request, i.e. referrals recieved via ldap are prefixed with "ldap://" and those over ldaps are prefixed with "ldaps://" BUG: https://bugzilla.samba.org/show_bug.cgi?id=12478 Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett (cherry picked from commit 6ccf74cf878c295903673e3a1d1ed924a5e87547) --- python/samba/tests/ldap_referrals.py | 91 ++++++++++++++++++++++++++++ selftest/knownfail.d/ldap_referrals | 1 + source4/selftest/tests.py | 9 +++ 3 files changed, 101 insertions(+) create mode 100644 python/samba/tests/ldap_referrals.py create mode 100644 selftest/knownfail.d/ldap_referrals diff --git a/python/samba/tests/ldap_referrals.py b/python/samba/tests/ldap_referrals.py new file mode 100644 index 00000000000..86a39d4e602 --- /dev/null +++ b/python/samba/tests/ldap_referrals.py @@ -0,0 +1,91 @@ +# Test that ldap referral entiries are created and formatted correctly +# +# Copyright (C) Andrew Bartlett 2019 +# +# Based on Unit tests for the notification control +# Copyright (C) Stefan Metzmacher 2016 +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation; either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see . + +from __future__ import print_function +import optparse +import os +import sys + +import samba +from samba.auth import system_session +import samba.getopt as options +from samba import ldb +from samba.samdb import SamDB +import samba.tests +from samba.tests.subunitrun import SubunitOptions + +sys.path.insert(0, "bin/python") +parser = optparse.OptionParser("ldap_referrals.py [options]") +sambaopts = options.SambaOptions(parser) +parser.add_option_group(sambaopts) +parser.add_option_group(options.VersionOptions(parser)) +# use command line creds if available +credopts = options.CredentialsOptions(parser) +parser.add_option_group(credopts) +subunitopts = SubunitOptions(parser) +parser.add_option_group(subunitopts) +opts, args = parser.parse_args() + +lp = sambaopts.get_loadparm() +creds = credopts.get_credentials(lp) + + +class LdapReferralTest(samba.tests.TestCase): + + def setUp(self): + super(LdapReferralTest, self).setUp() + + # The referral entries for an ldap request should have the ldap scheme + # i.e. then should all start with "ldap://" + def test_ldap_search(self): + server = os.environ["SERVER"] + url = "ldap://{0}".format(server) + db = SamDB( + url, credentials=creds, session_info=system_session(lp), lp=lp) + res = db.search( + base=db.domain_dn(), + expression="(objectClass=nonexistent)", + scope=ldb.SCOPE_SUBTREE, + attrs=["objectGUID", "samAccountName"]) + + referals = res.referals + for referal in referals: + self.assertTrue( + referal.startswith("ldap://"), + "{0} does not start with ldap://".format(referal)) + + # The referral entries for an ldaps request should have the ldaps scheme + # i.e. then should all start with "ldaps://" + def test_ldaps_search(self): + server = os.environ["SERVER"] + url = "ldaps://{0}".format(server) + db = SamDB( + url, credentials=creds, session_info=system_session(lp), lp=lp) + res = db.search( + base=db.domain_dn(), + expression="(objectClass=nonexistent)", + scope=ldb.SCOPE_SUBTREE, + attrs=["objectGUID", "samAccountName"]) + + referals = res.referals + for referal in referals: + self.assertTrue( + referal.startswith("ldaps://"), + "{0} does not start with ldaps://".format(referal)) diff --git a/selftest/knownfail.d/ldap_referrals b/selftest/knownfail.d/ldap_referrals new file mode 100644 index 00000000000..403f0d3bd6d --- /dev/null +++ b/selftest/knownfail.d/ldap_referrals @@ -0,0 +1 @@ +^samba.ldap.referrals.samba.tests.ldap_referrals.LdapReferralTest.test_ldaps_search diff --git a/source4/selftest/tests.py b/source4/selftest/tests.py index 5205ff44165..bf8cf6b58eb 100755 --- a/source4/selftest/tests.py +++ b/source4/selftest/tests.py @@ -881,6 +881,15 @@ planoldpythontestsuite("ad_dc_ntvfs", "sort", environ={'SERVER' : '$SERVER', 'DA plantestsuite_loadlist("samba4.ldap.vlv.python(ad_dc_ntvfs)", "ad_dc_ntvfs", [python, os.path.join(samba4srcdir, "dsdb/tests/python/vlv.py"), '$SERVER', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) plantestsuite_loadlist("samba4.ldap.linked_attributes.python(ad_dc_ntvfs)", "ad_dc_ntvfs:local", [python, os.path.join(samba4srcdir, "dsdb/tests/python/linked_attributes.py"), '$PREFIX_ABS/ad_dc_ntvfs/private/sam.ldb', '-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN', '$LOADLIST', '$LISTOPT']) +planoldpythontestsuite( + "ad_dc_ntvfs", + "samba.tests.ldap_referrals", + environ={ + 'SERVER': '$SERVER', + }, + name="samba.ldap.referrals", + extra_args=['-U"$USERNAME%$PASSWORD"', '--workgroup=$DOMAIN']) + # These should be the first tests run against testenvs created by backup/restore for env in ['offlinebackupdc', 'restoredc', 'renamedc', 'labdc']: # check that a restored DC matches the original DC (backupfromdc) -- 2.17.1 From bb9906f4618ea2d9e79398f4d32a3d62436443c0 Mon Sep 17 00:00:00 2001 From: Gary Lockyer Date: Tue, 21 May 2019 13:17:22 +1200 Subject: [PATCH 2/2] ldap server: generate correct referral schemes Ensure that the referrals returned in a search request use the same scheme as the request, i.e. referrals recieved via ldap are prefixed with "ldap://" and those over ldaps are prefixed with "ldaps://" BUG: https://bugzilla.samba.org/show_bug.cgi?id=12478 Signed-off-by: Gary Lockyer Reviewed-by: Andrew Bartlett Autobuild-User(master): Andrew Bartlett Autobuild-Date(master): Fri May 24 05:12:14 UTC 2019 on sn-devel-184 (cherry picked from commit 1958cd8a7fb81ec51b81944ecf4dd0fb5c4208fa) --- lib/ldb/include/ldb_module.h | 5 +++++ selftest/knownfail.d/ldap_referrals | 1 - source4/dsdb/samdb/ldb_modules/partition.c | 16 +++++++++++----- source4/ldap_server/ldap_backend.c | 18 ++++++++++++++++++ source4/ldap_server/ldap_server.c | 1 + source4/ldap_server/ldap_server.h | 6 ++++++ 6 files changed, 41 insertions(+), 6 deletions(-) delete mode 100644 selftest/knownfail.d/ldap_referrals diff --git a/lib/ldb/include/ldb_module.h b/lib/ldb/include/ldb_module.h index 6ba2a49300a..c73fc37f3aa 100644 --- a/lib/ldb/include/ldb_module.h +++ b/lib/ldb/include/ldb_module.h @@ -103,6 +103,11 @@ struct ldb_module; * attributes, not to be printed in trace messages */ #define LDB_SECRET_ATTRIBUTE_LIST_OPAQUE "LDB_SECRET_ATTRIBUTE_LIST" +/* + * The scheme to be used for referral entries, i.e. ldap or ldaps + */ +#define LDAP_REFERRAL_SCHEME_OPAQUE "LDAP_REFERRAL_SCHEME" + /* these function pointers define the operations that a ldb module can intercept */ diff --git a/selftest/knownfail.d/ldap_referrals b/selftest/knownfail.d/ldap_referrals deleted file mode 100644 index 403f0d3bd6d..00000000000 --- a/selftest/knownfail.d/ldap_referrals +++ /dev/null @@ -1 +0,0 @@ -^samba.ldap.referrals.samba.tests.ldap_referrals.LdapReferralTest.test_ldaps_search diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c index 49bdeb04fa5..f66ccab1dd5 100644 --- a/source4/dsdb/samdb/ldb_modules/partition.c +++ b/source4/dsdb/samdb/ldb_modules/partition.c @@ -902,11 +902,17 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req) data->partitions[i]->ctrl->dn) == 0) && (ldb_dn_compare(req->op.search.base, data->partitions[i]->ctrl->dn) != 0)) { - char *ref = talloc_asprintf(ac, - "ldap://%s/%s%s", - lpcfg_dnsdomain(lp_ctx), - ldb_dn_get_linearized(data->partitions[i]->ctrl->dn), - req->op.search.scope == LDB_SCOPE_ONELEVEL ? "??base" : ""); + const char *scheme = ldb_get_opaque( + ldb, LDAP_REFERRAL_SCHEME_OPAQUE); + char *ref = talloc_asprintf( + ac, + "%s://%s/%s%s", + scheme == NULL ? "ldap" : scheme, + lpcfg_dnsdomain(lp_ctx), + ldb_dn_get_linearized( + data->partitions[i]->ctrl->dn), + req->op.search.scope == + LDB_SCOPE_ONELEVEL ? "??base" : ""); if (ref == NULL) { return ldb_oom(ldb); diff --git a/source4/ldap_server/ldap_backend.c b/source4/ldap_server/ldap_backend.c index 39f1aa2a2a6..573472c0f7f 100644 --- a/source4/ldap_server/ldap_backend.c +++ b/source4/ldap_server/ldap_backend.c @@ -647,6 +647,24 @@ static NTSTATUS ldapsrv_SearchRequest(struct ldapsrv_call *call) call->notification.busy = true; } + { + const char *scheme = NULL; + switch (call->conn->referral_scheme) { + case LDAP_REFERRAL_SCHEME_LDAPS: + scheme = "ldaps"; + break; + default: + scheme = "ldap"; + } + ldb_ret = ldb_set_opaque( + samdb, + LDAP_REFERRAL_SCHEME_OPAQUE, + discard_const_p(char *, scheme)); + if (ldb_ret != LDB_SUCCESS) { + goto reply; + } + } + ldb_set_timeout(samdb, lreq, req->timelimit); if (!call->conn->is_privileged) { diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 783823043dc..90d32c6833a 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -436,6 +436,7 @@ static void ldapsrv_accept_tls_done(struct tevent_req *subreq) } conn->sockets.active = conn->sockets.tls; + conn->referral_scheme = LDAP_REFERRAL_SCHEME_LDAPS; ldapsrv_call_read_next(conn); } diff --git a/source4/ldap_server/ldap_server.h b/source4/ldap_server/ldap_server.h index d3e31fb1eec..5b944f5ab9b 100644 --- a/source4/ldap_server/ldap_server.h +++ b/source4/ldap_server/ldap_server.h @@ -24,6 +24,11 @@ #include "system/network.h" #include "lib/param/loadparm.h" +enum ldap_server_referral_scheme { + LDAP_REFERRAL_SCHEME_LDAP, + LDAP_REFERRAL_SCHEME_LDAPS +}; + struct ldapsrv_connection { struct ldapsrv_connection *next, *prev; struct loadparm_context *lp_ctx; @@ -47,6 +52,7 @@ struct ldapsrv_connection { bool is_privileged; enum ldap_server_require_strong_auth require_strong_auth; bool authz_logged; + enum ldap_server_referral_scheme referral_scheme; struct { int initial_timeout; -- 2.17.1