The branch, master has been updated via 73d6bb7 s4-gensec Don't give more to sasl_encode() than it will permit via 15a3077 s4-gensec Don't upgrade all DIGEST-MD5 connections to seal via f9c7365 s4-provisionbackend Allow a fixed URI to be specified for LDAP backend via 4d9b12a s4-provision Remove serverdn parameter from Schema() from 640fbf8 s4-dsdb: register the DCPROMO_OID control with the rootdse
http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit 73d6bb74476561ef0140d21810541825c44b44a4 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Oct 19 17:12:35 2010 +1100 s4-gensec Don't give more to sasl_encode() than it will permit We need to ask the library how much data to pass in at any time. Andrew Bartlett Autobuild-User: Andrew Bartlett <abart...@samba.org> Autobuild-Date: Tue Oct 19 08:37:45 UTC 2010 on sn-devel-104 commit 15a3077885227cc5e81e331979713c27192a01ef Author: Andrew Bartlett <abart...@samba.org> Date: Tue Oct 19 15:12:20 2010 +1100 s4-gensec Don't upgrade all DIGEST-MD5 connections to seal The issue here is that when props.max_ssf = UINT_MAX was always set, as was the maxbufsize, and the connection would always be upgraded, regardless of the callers wishes. Andrew Bartlett commit f9c7365e535727b1d6d6ef55ed8c196368c625b9 Author: Andrew Bartlett <abart...@samba.org> Date: Tue Oct 19 10:38:10 2010 +1100 s4-provisionbackend Allow a fixed URI to be specified for LDAP backend This is added to make the 'existing' LDAP backend class more useful, and to allow debuging of our OpenLDAP backend class with wireshark, by forcing the traffic over loopback TCP, which is much easier to sniff. Andrew Bartlett commit 4d9b12ae8f9fc7c097b94e6c02df3cb1c38a52ce Author: Andrew Bartlett <abart...@samba.org> Date: Tue Oct 19 09:12:57 2010 +1100 s4-provision Remove serverdn parameter from Schema() We don't need to know the server DN here any more, and it makes no sense for many callers. Andrew Bartlett ----------------------------------------------------------------------- Summary of changes: source4/auth/gensec/cyrus_sasl.c | 46 ++++++++---- source4/scripting/bin/upgradeprovision | 3 +- source4/scripting/python/samba/provision.py | 81 ++++++++++---------- source4/scripting/python/samba/provisionbackend.py | 41 +++++----- source4/scripting/python/samba/schema.py | 10 +-- source4/setup/provision | 12 +++ 6 files changed, 110 insertions(+), 83 deletions(-) Changeset truncated at 500 lines: diff --git a/source4/auth/gensec/cyrus_sasl.c b/source4/auth/gensec/cyrus_sasl.c index c4f9544..e05a3b8 100644 --- a/source4/auth/gensec/cyrus_sasl.c +++ b/source4/auth/gensec/cyrus_sasl.c @@ -29,6 +29,7 @@ struct gensec_sasl_state { sasl_conn_t *conn; int step; + bool wrap; }; static NTSTATUS sasl_nt_status(int sasl_ret) @@ -125,7 +126,7 @@ static NTSTATUS gensec_sasl_client_start(struct gensec_security *gensec_security sasl_callback_t *callbacks; - gensec_sasl_state = talloc(gensec_security, struct gensec_sasl_state); + gensec_sasl_state = talloc_zero(gensec_security, struct gensec_sasl_state); if (!gensec_sasl_state) { return NT_STATUS_NO_MEMORY; } @@ -173,26 +174,27 @@ static NTSTATUS gensec_sasl_client_start(struct gensec_security *gensec_security local_addr, remote_addr, callbacks, 0, &gensec_sasl_state->conn); - if (sasl_ret == SASL_OK || sasl_ret == SASL_CONTINUE) { + if (sasl_ret == SASL_OK) { sasl_security_properties_t props; talloc_set_destructor(gensec_sasl_state, gensec_sasl_dispose); - + ZERO_STRUCT(props); if (gensec_security->want_features & GENSEC_FEATURE_SIGN) { props.min_ssf = 1; + props.max_ssf = 1; + props.maxbufsize = 65536; + gensec_sasl_state->wrap = true; } if (gensec_security->want_features & GENSEC_FEATURE_SEAL) { props.min_ssf = 40; - } - - props.max_ssf = UINT_MAX; - props.maxbufsize = 65536; - sasl_ret = sasl_setprop(gensec_sasl_state->conn, SASL_SEC_PROPS, &props); - if (sasl_ret != SASL_OK) { - return sasl_nt_status(sasl_ret); + props.max_ssf = UINT_MAX; + props.maxbufsize = 65536; + gensec_sasl_state->wrap = true; } - } else { + sasl_ret = sasl_setprop(gensec_sasl_state->conn, SASL_SEC_PROPS, &props); + } + if (sasl_ret != SASL_OK) { DEBUG(1, ("GENSEC SASL: client_new failed: %s\n", sasl_errdetail(gensec_sasl_state->conn))); } return sasl_nt_status(sasl_ret); @@ -261,10 +263,17 @@ static NTSTATUS gensec_sasl_wrap_packets(struct gensec_security *gensec_security struct gensec_sasl_state); const char *out_data; unsigned int out_len; + unsigned len_permitted; + int sasl_ret = sasl_getprop(gensec_sasl_state->conn, SASL_SSF, + (const void**)&len_permitted); + if (sasl_ret != SASL_OK) { + return sasl_nt_status(sasl_ret); + } + len_permitted = MIN(len_permitted, in->length); - int sasl_ret = sasl_encode(gensec_sasl_state->conn, - (char*)in->data, in->length, &out_data, - &out_len); + sasl_ret = sasl_encode(gensec_sasl_state->conn, + (char*)in->data, len_permitted, &out_data, + &out_len); if (sasl_ret == SASL_OK) { *out = data_blob_talloc(out_mem_ctx, out_data, out_len); *len_processed = in->length; @@ -281,7 +290,14 @@ static bool gensec_sasl_have_feature(struct gensec_security *gensec_security, struct gensec_sasl_state *gensec_sasl_state = talloc_get_type(gensec_security->private_data, struct gensec_sasl_state); sasl_ssf_t ssf; - int sasl_ret = sasl_getprop(gensec_sasl_state->conn, SASL_SSF, + int sasl_ret; + + /* If we did not elect to wrap, then we have neither sign nor seal, no matter what the SSF claims */ + if (!gensec_sasl_state->wrap) { + return false; + } + + sasl_ret = sasl_getprop(gensec_sasl_state->conn, SASL_SSF, (const void**)&ssf); if (sasl_ret != SASL_OK) { return false; diff --git a/source4/scripting/bin/upgradeprovision b/source4/scripting/bin/upgradeprovision index 37c66b6..c4dcfbf 100755 --- a/source4/scripting/bin/upgradeprovision +++ b/source4/scripting/bin/upgradeprovision @@ -1671,8 +1671,7 @@ if __name__ == '__main__': new_ldbs.startTransactions() # 12) - schema = Schema(setup_path, names.domainsid, schemadn=str(names.schemadn), - serverdn=str(names.serverdn)) + schema = Schema(setup_path, names.domainsid, schemadn=str(names.schemadn)) # We create a closure that will be invoked just before schema reload def schemareloadclosure(): basesam = Ldb(paths.samdb, session_info=session, credentials=creds, lp=lp, diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py index 99e2e13..80c9bfd 100644 --- a/source4/scripting/python/samba/provision.py +++ b/source4/scripting/python/samba/provision.py @@ -644,7 +644,7 @@ def setup_samdb_partitions(samdb_path, setup_path, logger, lp, session_info, ldap_backend_line = "# No LDAP backend" if provision_backend.type is not "ldb": - ldap_backend_line = "ldapBackend: %s" % provision_backend.ldapi_uri + ldap_backend_line = "ldapBackend: %s" % provision_backend.ldap_uri samdb.transaction_start() try: @@ -1055,7 +1055,7 @@ def setup_samdb(path, setup_path, session_info, provision_backend, lp, names, names=names, serverrole=serverrole, schema=schema) if schema is None: - schema = Schema(setup_path, domainsid, schemadn=names.schemadn, serverdn=names.serverdn) + schema = Schema(setup_path, domainsid, schemadn=names.schemadn) # Load the database, but don's load the global schema and don't connect quite yet samdb = SamDB(session_info=session_info, url=None, auto_connect=False, @@ -1338,7 +1338,7 @@ def provision(setup_dir, logger, session_info, dnspass=None, root=None, nobody=None, users=None, wheel=None, backup=None, aci=None, serverrole=None, dom_for_fun_level=None, - ldap_backend_extra_port=None, backend_type=None, + ldap_backend_extra_port=None, ldap_backend_forced_uri=None, backend_type=None, sitename=None, ol_mmr_urls=None, ol_olc=None, setup_ds_path=None, slapd_path=None, nosync=False, @@ -1465,52 +1465,53 @@ def provision(setup_dir, logger, session_info, ldapi_url = "ldapi://%s" % urllib.quote(paths.s4_ldapi_path, safe="") - schema = Schema(setup_path, domainsid, invocationid=invocationid, schemadn=names.schemadn, - serverdn=names.serverdn) + schema = Schema(setup_path, domainsid, invocationid=invocationid, schemadn=names.schemadn) if backend_type == "ldb": provision_backend = LDBBackend(backend_type, - paths=paths, setup_path=setup_path, - lp=lp, credentials=credentials, - names=names, - logger=logger) + paths=paths, setup_path=setup_path, + lp=lp, credentials=credentials, + names=names, + logger=logger) elif backend_type == "existing": provision_backend = ExistingBackend(backend_type, - paths=paths, setup_path=setup_path, - lp=lp, credentials=credentials, - names=names, - logger=logger, - ldapi_url=ldapi_url) + paths=paths, setup_path=setup_path, + lp=lp, credentials=credentials, + names=names, + logger=logger, + ldap_backend_forced_uri=ldap_backend_forced_uri) elif backend_type == "fedora-ds": provision_backend = FDSBackend(backend_type, - paths=paths, setup_path=setup_path, - lp=lp, credentials=credentials, - names=names, - logger=logger, - domainsid=domainsid, - schema=schema, - hostname=hostname, - ldapadminpass=ldapadminpass, - slapd_path=slapd_path, - ldap_backend_extra_port=ldap_backend_extra_port, - ldap_dryrun_mode=ldap_dryrun_mode, - root=root, - setup_ds_path=setup_ds_path) + paths=paths, setup_path=setup_path, + lp=lp, credentials=credentials, + names=names, + logger=logger, + domainsid=domainsid, + schema=schema, + hostname=hostname, + ldapadminpass=ldapadminpass, + slapd_path=slapd_path, + ldap_backend_extra_port=ldap_backend_extra_port, + ldap_dryrun_mode=ldap_dryrun_mode, + root=root, + setup_ds_path=setup_ds_path, + ldap_backend_forced_uri=ldap_backend_forced_uri) elif backend_type == "openldap": provision_backend = OpenLDAPBackend(backend_type, - paths=paths, setup_path=setup_path, - lp=lp, credentials=credentials, - names=names, - logger=logger, - domainsid=domainsid, - schema=schema, - hostname=hostname, - ldapadminpass=ldapadminpass, - slapd_path=slapd_path, - ldap_backend_extra_port=ldap_backend_extra_port, - ldap_dryrun_mode=ldap_dryrun_mode, - ol_mmr_urls=ol_mmr_urls, - nosync=nosync) + paths=paths, setup_path=setup_path, + lp=lp, credentials=credentials, + names=names, + logger=logger, + domainsid=domainsid, + schema=schema, + hostname=hostname, + ldapadminpass=ldapadminpass, + slapd_path=slapd_path, + ldap_backend_extra_port=ldap_backend_extra_port, + ldap_dryrun_mode=ldap_dryrun_mode, + ol_mmr_urls=ol_mmr_urls, + nosync=nosync, + ldap_backend_forced_uri=ldap_backend_forced_uri) else: raise ValueError("Unknown LDAP backend type selected") diff --git a/source4/scripting/python/samba/provisionbackend.py b/source4/scripting/python/samba/provisionbackend.py index 7a36bdc..2556351 100644 --- a/source4/scripting/python/samba/provisionbackend.py +++ b/source4/scripting/python/samba/provisionbackend.py @@ -112,9 +112,8 @@ class ExistingBackend(ProvisionBackend): super(ExistingBackend, self).__init__(backend_type=backend_type, paths=paths, setup_path=setup_path, lp=lp, - credentials=credentials, names=names, logger=logger) - - self.ldapi_uri = ldapi_uri + credentials=credentials, names=names, logger=logger, + ldap_backend_forced_uri=ldap_backend_forced_uri) def init(self): # Check to see that this 'existing' LDAP backend in fact exists @@ -134,9 +133,10 @@ class ExistingBackend(ProvisionBackend): class LDAPBackend(ProvisionBackend): def __init__(self, backend_type, paths=None, setup_path=None, lp=None, - credentials=None, names=None, logger=None, domainsid=None, - schema=None, hostname=None, ldapadminpass=None, slapd_path=None, - ldap_backend_extra_port=None, ldap_dryrun_mode=False): + credentials=None, names=None, logger=None, domainsid=None, + schema=None, hostname=None, ldapadminpass=None, slapd_path=None, + ldap_backend_extra_port=None, + ldap_backend_forced_uri=None, ldap_dryrun_mode=False): super(LDAPBackend, self).__init__(backend_type=backend_type, paths=paths, setup_path=setup_path, lp=lp, @@ -157,7 +157,10 @@ class LDAPBackend(ProvisionBackend): self.ldap_backend_extra_port = ldap_backend_extra_port self.ldap_dryrun_mode = ldap_dryrun_mode - self.ldapi_uri = "ldapi://%s" % urllib.quote(os.path.join(self.ldapdir, "ldapi"), safe="") + if ldap_backend_forced_uri is not None: + self.ldap_uri = ldap_backend_forced_uri + else: + self.ldap_uri = "ldapi://%s" % urllib.quote(os.path.join(self.ldapdir, "ldapi"), safe="") if not os.path.exists(self.ldapdir): os.mkdir(self.ldapdir) @@ -165,10 +168,10 @@ class LDAPBackend(ProvisionBackend): def init(self): from samba.provision import ProvisioningError # we will shortly start slapd with ldapi for final provisioning. first - # check with ldapsearch -> rootDSE via self.ldapi_uri if another + # check with ldapsearch -> rootDSE via self.ldap_uri if another # instance of slapd is already running try: - ldapi_db = Ldb(self.ldapi_uri) + ldapi_db = Ldb(self.ldap_uri) ldapi_db.search(base="", scope=SCOPE_BASE, expression="(objectClass=OpenLDAProotDSE)") try: @@ -180,7 +183,7 @@ class LDAPBackend(ProvisionBackend): p = f.read() f.close() self.logger.info("Check for slapd Process with PID: " + str(p) + " and terminate it manually.") - raise SlapdAlreadyRunning(self.ldapi_uri) + raise SlapdAlreadyRunning(self.ldap_uri) except LdbError: # XXX: We should never be catching all Ldb errors pass @@ -243,7 +246,7 @@ class LDAPBackend(ProvisionBackend): while self.slapd.poll() is None: # Wait until the socket appears try: - ldapi_db = Ldb(self.ldapi_uri, lp=self.lp, credentials=self.credentials) + ldapi_db = Ldb(self.ldap_uri, lp=self.lp, credentials=self.credentials) ldapi_db.search(base="", scope=SCOPE_BASE, expression="(objectClass=OpenLDAProotDSE)") # If we have got here, then we must have a valid connection to the LDAP server! @@ -282,13 +285,14 @@ class OpenLDAPBackend(LDAPBackend): credentials=None, names=None, logger=None, domainsid=None, schema=None, hostname=None, ldapadminpass=None, slapd_path=None, ldap_backend_extra_port=None, ldap_dryrun_mode=False, - ol_mmr_urls=None, nosync=False): + ol_mmr_urls=None, nosync=False, ldap_backend_forced_uri=None): super(OpenLDAPBackend, self).__init__( backend_type=backend_type, paths=paths, setup_path=setup_path, lp=lp, credentials=credentials, names=names, logger=logger, domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, + ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.ol_mmr_urls = ol_mmr_urls @@ -303,7 +307,7 @@ class OpenLDAPBackend(LDAPBackend): self.olcseedldif = os.path.join(self.ldapdir, "olc_seed.ldif") self.schema = Schema(self.setup_path, self.domainsid, - schemadn=self.names.schemadn, serverdn=self.names.serverdn, + schemadn=self.names.schemadn, files=[setup_path("schema_samba4.ldif")]) def setup_db_config(self, dbdir): @@ -496,7 +500,6 @@ class OpenLDAPBackend(LDAPBackend): f.close() # now we generate the needed strings to start slapd automatically, - # first ldapi_uri... if self.ldap_backend_extra_port is not None: # When we use MMR, we can't use 0.0.0.0 as it uses the name # specified there as part of it's clue as to it's own name, @@ -515,12 +518,12 @@ class OpenLDAPBackend(LDAPBackend): "-h"] # copy this command so we have two version, one with -d0 and only - # ldapi, and one with all the listen commands + # ldapi (or the forced ldap_uri), and one with all the listen commands self.slapd_command = list(self.slapd_provision_command) - self.slapd_provision_command.extend([self.ldapi_uri, "-d0"]) + self.slapd_provision_command.extend([self.ldap_uri, "-d0"]) - uris = self.ldapi_uri + uris = self.ldap_uri if server_port_string is not "": uris = uris + " " + server_port_string @@ -569,6 +572,7 @@ class FDSBackend(LDAPBackend): domainsid=domainsid, schema=schema, hostname=hostname, ldapadminpass=ldapadminpass, slapd_path=slapd_path, ldap_backend_extra_port=ldap_backend_extra_port, + ldap_backend_forced_uri=ldap_backend_forced_uri, ldap_dryrun_mode=ldap_dryrun_mode) self.root = root @@ -603,7 +607,6 @@ class FDSBackend(LDAPBackend): self.setup_path, self.domainsid, schemadn=self.names.schemadn, - serverdn=self.names.serverdn, files=[setup_path("schema_samba4.ldif"), self.samba3_ldif], additional_prefixmap=["1000:1.3.6.1.4.1.7165.2.1", "1001:1.3.6.1.4.1.7165.2.2"]) @@ -738,7 +741,7 @@ class FDSBackend(LDAPBackend): raise ProvisioningError("ldif2db failed") def post_setup(self): - ldapi_db = Ldb(self.ldapi_uri, credentials=self.credentials) + ldapi_db = Ldb(self.ldap_uri, credentials=self.credentials) # configure in-directory access control on Fedora DS via the aci # attribute (over a direct ldapi:// socket) diff --git a/source4/scripting/python/samba/schema.py b/source4/scripting/python/samba/schema.py index a9e1122..848d4ec 100644 --- a/source4/scripting/python/samba/schema.py +++ b/source4/scripting/python/samba/schema.py @@ -54,13 +54,12 @@ def get_schema_descriptor(domain_sid): class Schema(object): def __init__(self, setup_path, domain_sid, invocationid=None, schemadn=None, - serverdn=None, files=None, override_prefixmap=None, additional_prefixmap=None): + files=None, override_prefixmap=None, additional_prefixmap=None): """Load schema for the SamDB from the AD schema files and samba4_schema.ldif :param samdb: Load a schema into a SamDB. :param setup_path: Setup path function. :param schemadn: DN of the schema - :param serverdn: DN of the server Returns the schema data loaded, to avoid double-parsing when then needing to add it to the db """ @@ -68,8 +67,6 @@ class Schema(object): self.schemadn = schemadn # We need to have the am_rodc=False just to keep some warnings quiet - this isn't a real SAM, so it's meaningless. self.ldb = SamDB(global_schema=False, am_rodc=False) - if serverdn is not None: - self.ldb.set_ntds_settings_dn("CN=NTDS Settings,%s" % serverdn) if invocationid is not None: self.ldb.set_invocation_id(invocationid) @@ -87,7 +84,7 @@ class Schema(object): self.schema_dn_modify = read_and_sub_file( setup_path("provision_schema_basedn_modify.ldif"), - {"SCHEMADN": schemadn, "SERVERDN": serverdn}) + {"SCHEMADN": schemadn}) descr = b64encode(get_schema_descriptor(domain_sid)) self.schema_dn_add = read_and_sub_file( @@ -174,7 +171,6 @@ def get_dnsyntax_attributes(schemadn,schemaldb): def ldb_with_schema(setup_dir=None, schemadn="cn=schema,cn=configuration,dc=example,dc=com", - serverdn="cn=server,cn=servers,cn=default-first-site-name,cn=sites,cn=cn=configuration,dc=example,dc=com", domainsid=None, override_prefixmap=None): """Load schema for the SamDB from the AD schema files and samba4_schema.ldif @@ -195,4 +191,4 @@ def ldb_with_schema(setup_dir=None, domainsid = security.random_sid() else: domainsid = security.dom_sid(domainsid) - return Schema(setup_path, domainsid, schemadn=schemadn, serverdn=serverdn, override_prefixmap=override_prefixmap) + return Schema(setup_path, domainsid, schemadn=schemadn, override_prefixmap=override_prefixmap) diff --git a/source4/setup/provision b/source4/setup/provision index 21d94cb..c809c4a 100755 --- a/source4/setup/provision +++ b/source4/setup/provision @@ -93,6 +93,8 @@ parser.add_option("--blank", action="store_true", help="do not add users or groups, just the structure") parser.add_option("--ldap-backend-extra-port", type="int", metavar="LDAP-BACKEND-EXTRA-PORT", help="Additional TCP port for LDAP backend server (to use for replication)") +parser.add_option("--ldap-backend-forced-uri", type="string", metavar="LDAP-BACKEND-FORCED-URI", + help="Force the LDAP backend connection to be to a particular URI. Use this ONLY for 'existing' backends, or when debugging the interaction with the LDAP backend and you need to intercept the LDAP traffic") parser.add_option("--ldap-backend-type", type="choice", metavar="LDAP-BACKEND-TYPE", help="LDAP backend type (fedora-ds or openldap)", choices=["fedora-ds", "openldap"]) @@ -230,6 +232,15 @@ elif opts.use_xattrs == "auto": file.close() +if opts.ldap_backend_type == "existing": + if opts.ldap_backend_forced_uri is not None: + logger.warn("You have specified to use an existing LDAP server as the backend, please make sure an LDAP server is running at %s" % opts.ldap_backend_forced_uri) + else: + logger.info("You have specified to use an existing LDAP server as the backend, please make sure an LDAP server is running at the default location") +else: + if opts.ldap_backend_forced_uri is not None: + logger.warn("You have specified to use an fixed URI %s for connecting to your LDAP server backend. This is NOT RECOMMENDED, as our default communiation over ldapi:// is more secure and much less prone to unexpected failure or interaction" % opts.ldap_backend_forced_uri) + session = system_session() try: provision(setup_dir, logger, @@ -245,6 +256,7 @@ try: wheel=opts.wheel, users=opts.users, serverrole=server_role, dom_for_fun_level=dom_for_fun_level, ldap_backend_extra_port=opts.ldap_backend_extra_port, + ldap_backend_forced_uri=opts.ldap_backend_forced_uri, backend_type=opts.ldap_backend_type, ldapadminpass=opts.ldapadminpass, ol_mmr_urls=opts.ol_mmr_urls, slapd_path=opts.slapd_path, setup_ds_path=opts.setup_ds_path, -- Samba Shared Repository