1
0
mirror of https://github.com/samba-team/samba.git synced 2025-02-02 09:47:23 +03:00

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
This commit is contained in:
Andrew Bartlett 2009-07-14 08:15:50 +10:00
parent ba58edd0bc
commit 271b5af92e
9 changed files with 174 additions and 21 deletions

View File

@ -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)) {

View File

@ -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)

View File

@ -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));
}

View File

@ -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

View File

@ -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()

View File

@ -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}

View File

@ -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}

View File

@ -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

View File

@ -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}