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:
parent
ba58edd0bc
commit
271b5af92e
@ -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)) {
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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()
|
||||
|
@ -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}
|
||||
|
@ -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}
|
||||
|
@ -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
|
||||
|
@ -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}
|
||||
|
Loading…
x
Reference in New Issue
Block a user