summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2009-07-14 08:15:50 +1000
committerAndrew Bartlett <abartlet@samba.org>2009-07-16 09:23:35 +1000
commit271b5af92e9aada36adc648a6dd43a13c5aed340 (patch)
treea82d7670ea64704670b09feffd83f6db23a1c433
parentba58edd0bc2d77c6ed1b6a76f33787da9031db5b (diff)
downloadsamba-271b5af92e9aada36adc648a6dd43a13c5aed340.tar.gz
samba-271b5af92e9aada36adc648a6dd43a13c5aed340.tar.bz2
samba-271b5af92e9aada36adc648a6dd43a13c5aed340.zip
s4:dsdb Handle dc/domain/forest functional levels properly
Rather than have the functional levels scattered in 4 different, unconnected locations, the provision script now sets it, and the rootdse module maintains it's copy only as a cached view onto the original values. We also use the functional level to determine if we should store AES Kerberos keys. Andrew Bartlett
-rw-r--r--source4/dsdb/samdb/ldb_modules/password_hash.c7
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c140
-rw-r--r--source4/scripting/python/pyglue.c6
-rw-r--r--source4/scripting/python/samba/__init__.py5
-rw-r--r--source4/scripting/python/samba/provision.py24
-rw-r--r--source4/setup/provision_basedn_modify.ldif4
-rw-r--r--source4/setup/provision_configuration.ldif2
-rw-r--r--source4/setup/provision_rootdse_add.ldif3
-rw-r--r--source4/setup/provision_self_join.ldif4
9 files changed, 174 insertions, 21 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index a28ca1d568..ef641ac18b 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -1026,6 +1026,7 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
uint8_t zero16[16];
bool do_newer_keys = false;
bool do_cleartext = false;
+ int *domainFunctionality;
ZERO_STRUCT(zero16);
ZERO_STRUCT(names);
@@ -1064,10 +1065,10 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
_old_scb.sub.signature, SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
}
}
+ /* Per MS-SAMR 3.1.1.8.11.6 we create AES keys if our domain functionality level is 2008 or higher */
+ domainFunctionality = talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int);
- /* TODO: do the correct check for this, it maybe depends on the functional level? */
- do_newer_keys = lp_parm_bool(ldb_get_opaque(ldb, "loadparm"),
- NULL, "password_hash", "create_aes_key", false);
+ do_newer_keys = *domainFunctionality && (*domainFunctionality >= DS_BEHAVIOR_WIN2008);
if (io->domain->store_cleartext &&
(io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index 7080fb632f..59ea51dbce 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -59,6 +59,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data);
char **server_sasl;
const struct dsdb_schema *schema;
+ int *val;
ldb = ldb_module_get_ctx(module);
schema = dsdb_get_schema(ldb);
@@ -77,7 +78,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
}
}
- if (do_attribute(attrs, "supportedControl")) {
+ if (priv && do_attribute(attrs, "supportedControl")) {
int i;
for (i = 0; i < priv->num_controls; i++) {
char *control = talloc_strdup(msg, priv->controls[i]);
@@ -91,7 +92,7 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
}
}
- if (do_attribute(attrs, "namingContexts")) {
+ if (priv && do_attribute(attrs, "namingContexts")) {
int i;
for (i = 0; i < priv->num_partitions; i++) {
struct ldb_dn *dn = priv->partitions[i];
@@ -201,13 +202,37 @@ static int rootdse_add_dynamic(struct ldb_module *module, struct ldb_message *ms
}
}
- if (schema && do_attribute_explicit(attrs, "vendorVersion")) {
+ if (do_attribute_explicit(attrs, "vendorVersion")) {
if (ldb_msg_add_fmt(msg, "vendorVersion",
"%s", SAMBA_VERSION_STRING) != 0) {
goto failed;
}
}
+ if (priv && do_attribute(attrs, "domainFunctionality")
+ && (val = talloc_get_type(ldb_get_opaque(ldb, "domainFunctionality"), int))) {
+ if (ldb_msg_add_fmt(msg, "domainFunctionality",
+ "%d", *val) != 0) {
+ goto failed;
+ }
+ }
+
+ if (priv && do_attribute(attrs, "forestFunctionality")
+ && (val = talloc_get_type(ldb_get_opaque(ldb, "forestFunctionality"), int))) {
+ if (ldb_msg_add_fmt(msg, "forestFunctionality",
+ "%d", *val) != 0) {
+ goto failed;
+ }
+ }
+
+ if (priv && do_attribute(attrs, "domainControllerFunctionality")
+ && (val = talloc_get_type(ldb_get_opaque(ldb, "domainControllerFunctionality"), int))) {
+ if (ldb_msg_add_fmt(msg, "domainControllerFunctionality",
+ "%d", *val) != 0) {
+ goto failed;
+ }
+ }
+
/* TODO: lots more dynamic attributes should be added here */
return LDB_SUCCESS;
@@ -394,12 +419,17 @@ static int rootdse_request(struct ldb_module *module, struct ldb_request *req)
static int rootdse_init(struct ldb_module *module)
{
+ int ret;
struct ldb_context *ldb;
+ struct ldb_result *res;
struct private_data *data;
+ const char *attrs[] = { "msDS-Behavior-Version", NULL };
+ const char *ds_attrs[] = { "dsServiceName", NULL };
+ TALLOC_CTX *mem_ctx;
ldb = ldb_module_get_ctx(module);
- data = talloc(module, struct private_data);
+ data = talloc_zero(module, struct private_data);
if (data == NULL) {
return -1;
}
@@ -412,7 +442,107 @@ static int rootdse_init(struct ldb_module *module)
ldb_set_default_dns(ldb);
- return ldb_next_init(module);
+ ret = ldb_next_init(module);
+
+ if (ret) {
+ return ret;
+ }
+
+ mem_ctx = talloc_new(data);
+ if (!mem_ctx) {
+ ldb_oom(ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* Now that the partitions are set up, do a search for:
+ - domainControllerFunctionality
+ - domainFunctionality
+ - forestFunctionality
+
+ Then stuff these values into an opaque
+ */
+ ret = ldb_search(ldb, mem_ctx, &res,
+ ldb_get_default_basedn(ldb),
+ LDB_SCOPE_BASE, attrs, NULL);
+ if (ret == LDB_SUCCESS && res->count == 1) {
+ int domain_behaviour_version
+ = ldb_msg_find_attr_as_int(res->msgs[0],
+ "msDS-Behavior-Version", -1);
+ if (domain_behaviour_version != -1) {
+ int *val = talloc(ldb, int);
+ if (!val) {
+ ldb_oom(ldb);
+ talloc_free(mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ *val = domain_behaviour_version;
+ ret = ldb_set_opaque(ldb, "domainFunctionality", val);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+ }
+ }
+
+ ret = ldb_search(ldb, mem_ctx, &res,
+ samdb_partitions_dn(ldb, mem_ctx),
+ LDB_SCOPE_BASE, attrs, NULL);
+ if (ret == LDB_SUCCESS && res->count == 1) {
+ int forest_behaviour_version
+ = ldb_msg_find_attr_as_int(res->msgs[0],
+ "msDS-Behavior-Version", -1);
+ if (forest_behaviour_version != -1) {
+ int *val = talloc(ldb, int);
+ if (!val) {
+ ldb_oom(ldb);
+ talloc_free(mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ *val = forest_behaviour_version;
+ ret = ldb_set_opaque(ldb, "forestFunctionality", val);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+ }
+ }
+
+ ret = ldb_search(ldb, mem_ctx, &res,
+ ldb_dn_new(mem_ctx, ldb, ""),
+ LDB_SCOPE_BASE, ds_attrs, NULL);
+ if (ret == LDB_SUCCESS && res->count == 1) {
+ struct ldb_dn *ds_dn
+ = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0],
+ "dsServiceName");
+ if (ds_dn) {
+ ret = ldb_search(ldb, mem_ctx, &res, ds_dn,
+ LDB_SCOPE_BASE, attrs, NULL);
+ if (ret == LDB_SUCCESS && res->count == 1) {
+ int domain_controller_behaviour_version
+ = ldb_msg_find_attr_as_int(res->msgs[0],
+ "msDS-Behavior-Version", -1);
+ if (domain_controller_behaviour_version != -1) {
+ int *val = talloc(ldb, int);
+ if (!val) {
+ ldb_oom(ldb);
+ talloc_free(mem_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ *val = domain_controller_behaviour_version;
+ ret = ldb_set_opaque(ldb,
+ "domainControllerFunctionality", val);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(mem_ctx);
+ return ret;
+ }
+ }
+ }
+ }
+ }
+
+ talloc_free(mem_ctx);
+
+ return LDB_SUCCESS;
}
static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
diff --git a/source4/scripting/python/pyglue.c b/source4/scripting/python/pyglue.c
index abd018f6fc..c6b731ce8b 100644
--- a/source4/scripting/python/pyglue.c
+++ b/source4/scripting/python/pyglue.c
@@ -362,5 +362,11 @@ void initglue(void)
return;
PyModule_AddObject(m, "version", PyString_FromString(SAMBA_VERSION_STRING));
+
+ PyModule_AddObject(m, "DS_BEHAVIOR_WIN2000", PyInt_FromLong(DS_BEHAVIOR_WIN2000));
+ PyModule_AddObject(m, "DS_BEHAVIOR_WIN2003_INTERIM", PyInt_FromLong(DS_BEHAVIOR_WIN2003_INTERIM));
+ PyModule_AddObject(m, "DS_BEHAVIOR_WIN2003", PyInt_FromLong(DS_BEHAVIOR_WIN2003));
+ PyModule_AddObject(m, "DS_BEHAVIOR_WIN2008", PyInt_FromLong(DS_BEHAVIOR_WIN2008));
+
}
diff --git a/source4/scripting/python/samba/__init__.py b/source4/scripting/python/samba/__init__.py
index 60a7919136..e3ebc4a637 100644
--- a/source4/scripting/python/samba/__init__.py
+++ b/source4/scripting/python/samba/__init__.py
@@ -242,3 +242,8 @@ def valid_netbios_name(name):
return True
version = glue.version
+
+DS_BEHAVIOR_WIN2000 = glue.DS_BEHAVIOR_WIN2000
+DS_BEHAVIOR_WIN2003_INTERIM = glue.DS_BEHAVIOR_WIN2003_INTERIM
+DS_BEHAVIOR_WIN2003 = glue.DS_BEHAVIOR_WIN2003
+DS_BEHAVIOR_WIN2008 = glue.DS_BEHAVIOR_WIN2008
diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py
index 189c93a1fc..8f57105224 100644
--- a/source4/scripting/python/samba/provision.py
+++ b/source4/scripting/python/samba/provision.py
@@ -37,7 +37,8 @@ import param
import registry
import samba
from auth import system_session
-from samba import Ldb, substitute_var, valid_netbios_name, check_all_substituted
+from samba import version, Ldb, substitute_var, valid_netbios_name, check_all_substituted, \
+ DS_BEHAVIOR_WIN2000, DS_BEHAVIOR_WIN2003_INTERIM, DS_BEHAVIOR_WIN2003, DS_BEHAVIOR_WIN2008
from samba.samdb import SamDB
from samba.idmap import IDmapDB
from samba.dcerpc import security
@@ -729,7 +730,7 @@ def setup_samdb_rootdse(samdb, setup_path, names):
def setup_self_join(samdb, names,
machinepass, dnspass,
domainsid, invocationid, setup_path,
- policyguid):
+ policyguid, domainControllerFunctionality):
"""Join a host to its own domain."""
assert isinstance(invocationid, str)
setup_add_ldif(samdb, setup_path("provision_self_join.ldif"), {
@@ -745,7 +746,9 @@ def setup_self_join(samdb, names,
"DNSPASS_B64": b64encode(dnspass),
"REALM": names.realm,
"DOMAIN": names.domain,
- "DNSDOMAIN": names.dnsdomain})
+ "DNSDOMAIN": names.dnsdomain,
+ "SAMBA_VERSION_STRING": version,
+ "DOMAIN_CONTROLLER_FUNCTIONALITY": str(domainControllerFunctionality)})
setup_add_ldif(samdb, setup_path("provision_group_policy.ldif"), {
"POLICYGUID": policyguid,
"DNSDOMAIN": names.dnsdomain,
@@ -765,6 +768,10 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
:note: This will wipe the main SAM database file!
"""
+ domainFunctionality = DS_BEHAVIOR_WIN2008
+ forestFunctionality = DS_BEHAVIOR_WIN2008
+ domainControllerFunctionality = DS_BEHAVIOR_WIN2008
+
erase = (fill != FILL_DRS)
# Also wipes the database
@@ -780,6 +787,11 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
return samdb
message("Pre-loading the Samba 4 and AD schema")
+
+ samdb.set_opaque_integer("domainFunctionality", domainFunctionality)
+ samdb.set_opaque_integer("forestFunctionality", forestFunctionality)
+ samdb.set_opaque_integer("domainControllerFunctionality", domainControllerFunctionality)
+
samdb.set_domain_sid(str(domainsid))
if serverrole == "domain controller":
samdb.set_invocation_id(invocationid)
@@ -818,6 +830,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
"POLICYGUID": policyguid,
"DOMAINDN": names.domaindn,
"DOMAINGUID_MOD": domainguid_mod,
+ "DOMAIN_FUNCTIONALITY": str(domainFunctionality)
})
message("Adding configuration container (permitted to fail)")
@@ -864,7 +877,8 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
"DOMAIN": names.domain,
"SCHEMADN": names.schemadn,
"DOMAINDN": names.domaindn,
- "SERVERDN": names.serverdn
+ "SERVERDN": names.serverdn,
+ "FOREST_FUNCTIONALALITY": str(forestFunctionality)
})
message("Setting up display specifiers")
@@ -908,7 +922,7 @@ def setup_samdb(path, setup_path, session_info, credentials, lp,
dnspass=dnspass,
machinepass=machinepass,
domainsid=domainsid, policyguid=policyguid,
- setup_path=setup_path)
+ setup_path=setup_path, domainControllerFunctionality=domainControllerFunctionality)
except:
samdb.transaction_cancel()
diff --git a/source4/setup/provision_basedn_modify.ldif b/source4/setup/provision_basedn_modify.ldif
index a7f3ce985c..36e80ec69c 100644
--- a/source4/setup/provision_basedn_modify.ldif
+++ b/source4/setup/provision_basedn_modify.ldif
@@ -47,10 +47,10 @@ replace: serverState
serverState: 1
-
replace: nTMixedDomain
-nTMixedDomain: 1
+nTMixedDomain: 0
-
replace: msDS-Behavior-Version
-msDS-Behavior-Version: 0
+msDS-Behavior-Version: ${DOMAIN_FUNCTIONALITY}
-
replace: ridManagerReference
ridManagerReference: CN=RID Manager$,CN=System,${DOMAINDN}
diff --git a/source4/setup/provision_configuration.ldif b/source4/setup/provision_configuration.ldif
index e84ac8517e..0dad24c705 100644
--- a/source4/setup/provision_configuration.ldif
+++ b/source4/setup/provision_configuration.ldif
@@ -6,7 +6,7 @@ objectClass: top
objectClass: crossRefContainer
cn: Partitions
systemFlags: -2147483648
-msDS-Behavior-Version: 0
+msDS-Behavior-Version: ${FOREST_FUNCTIONALALITY}
fSMORoleOwner: CN=NTDS Settings,${SERVERDN}
dn: CN=Enterprise Configuration,CN=Partitions,${CONFIGDN}
diff --git a/source4/setup/provision_rootdse_add.ldif b/source4/setup/provision_rootdse_add.ldif
index e4e4309a90..f9ee4e5904 100644
--- a/source4/setup/provision_rootdse_add.ldif
+++ b/source4/setup/provision_rootdse_add.ldif
@@ -11,9 +11,6 @@ supportedLDAPVersion: 2
dnsHostName: ${DNSNAME}
ldapServiceName: ${DNSDOMAIN}:${NETBIOSNAME}$@${REALM}
serverName: ${SERVERDN}
-domainFunctionality: 0
-forestFunctionality: 0
-domainControllerFunctionality: 2
isSynchronized: FALSE
vendorName: Samba Team (http://samba.org)
supportedCapabilities: 1.2.840.113556.1.4.800
diff --git a/source4/setup/provision_self_join.ldif b/source4/setup/provision_self_join.ldif
index b7ca872319..b60fea6576 100644
--- a/source4/setup/provision_self_join.ldif
+++ b/source4/setup/provision_self_join.ldif
@@ -13,7 +13,7 @@ primaryGroupID: 516
accountExpires: 9223372036854775807
sAMAccountName: ${NETBIOSNAME}$
operatingSystem: Samba
-operatingSystemVersion: 4.0
+operatingSystemVersion: ${SAMBA_VERSION_STRING}
dNSHostName: ${DNSNAME}
isCriticalSystemObject: TRUE
userPassword:: ${MACHINEPASS_B64}
@@ -57,7 +57,7 @@ options: 1
systemFlags: 33554432
dMDLocation: ${SCHEMADN}
invocationId: ${INVOCATIONID}
-msDS-Behavior-Version: 2
+msDS-Behavior-Version: ${DOMAIN_CONTROLLER_FUNCTIONALITY}
msDS-hasMasterNCs: ${CONFIGDN}
msDS-hasMasterNCs: ${SCHEMADN}
msDS-hasMasterNCs: ${DOMAINDN}