summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/common/flags.h1
-rw-r--r--source4/dsdb/repl/drepl_out_helpers.c11
-rw-r--r--source4/dsdb/repl/drepl_service.c2
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c49
-rw-r--r--source4/dsdb/samdb/ldb_modules/password_hash.c450
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c47
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_fsmo.c64
-rw-r--r--source4/dsdb/samdb/samdb.h2
-rw-r--r--source4/dsdb/schema/schema_init.c293
-rw-r--r--source4/kdc/hdb-ldb.c139
-rw-r--r--source4/lib/ldb/ldb_map/ldb_map.c5
-rwxr-xr-xsource4/lib/ldb/tests/python/ldap.py4
-rw-r--r--source4/libnet/libnet_become_dc.c49
-rw-r--r--source4/libnet/libnet_samsync_ldb.c2
-rw-r--r--source4/libnet/libnet_unbecome_dc.c13
-rw-r--r--source4/librpc/idl/drsblobs.idl64
-rw-r--r--source4/librpc/idl/drsuapi.idl22
-rw-r--r--source4/librpc/idl/netlogon.idl2
-rw-r--r--source4/librpc/idl/samr.idl18
-rw-r--r--source4/librpc/rpc/dcerpc_util.c14
-rw-r--r--source4/pidl/lib/Parse/Pidl/Expr.pm72
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm1
-rw-r--r--source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm2
-rw-r--r--source4/rpc_server/dcerpc_server.c24
-rw-r--r--source4/rpc_server/drsuapi/dcesrv_drsuapi.c15
-rw-r--r--source4/rpc_server/lsa/dcesrv_lsa.c6
-rw-r--r--source4/rpc_server/samr/dcesrv_samr.c66
-rw-r--r--source4/scripting/python/samba/provision.py31
-rw-r--r--source4/setup/named.conf63
-rw-r--r--source4/setup/named.txt46
-rw-r--r--source4/setup/provision.zone7
-rw-r--r--source4/setup/schema_samba4.ldif6
-rw-r--r--source4/setup/slapd.conf4
-rw-r--r--source4/torture/rpc/dssync.c28
-rw-r--r--source4/torture/rpc/lsa.c40
-rw-r--r--source4/torture/rpc/samr.c40
-rw-r--r--source4/torture/rpc/samsync.c8
-rw-r--r--source4/winbind/wb_cmd_list_trustdom.c3
38 files changed, 1326 insertions, 387 deletions
diff --git a/source4/dsdb/common/flags.h b/source4/dsdb/common/flags.h
index 36111418e2..e8802fdf9c 100644
--- a/source4/dsdb/common/flags.h
+++ b/source4/dsdb/common/flags.h
@@ -122,3 +122,4 @@
#define DS_BEHAVIOR_WIN2000 0
#define DS_BEHAVIOR_WIN2003_INTERIM 1
#define DS_BEHAVIOR_WIN2003 2
+#define DS_BEHAVIOR_WIN2008 3
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index 281e5691e2..345e3db1ab 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -142,10 +142,19 @@ static void dreplsrv_out_drsuapi_bind_recv(struct rpc_request *req)
info24 = &st->bind_r.out.bind_info->info.info24;
st->drsuapi->remote_info28.supported_extensions = info24->supported_extensions;
st->drsuapi->remote_info28.site_guid = info24->site_guid;
- st->drsuapi->remote_info28.u1 = info24->u1;
+ st->drsuapi->remote_info28.pid = info24->pid;
st->drsuapi->remote_info28.repl_epoch = 0;
break;
}
+ case 48: {
+ struct drsuapi_DsBindInfo48 *info48;
+ info48 = &st->bind_r.out.bind_info->info.info48;
+ st->drsuapi->remote_info28.supported_extensions = info48->supported_extensions;
+ st->drsuapi->remote_info28.site_guid = info48->site_guid;
+ st->drsuapi->remote_info28.pid = info48->pid;
+ st->drsuapi->remote_info28.repl_epoch = info48->repl_epoch;
+ break;
+ }
case 28:
st->drsuapi->remote_info28 = st->bind_r.out.bind_info->info.info28;
break;
diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c
index e485c50a47..3611258ca5 100644
--- a/source4/dsdb/repl/drepl_service.c
+++ b/source4/dsdb/repl/drepl_service.c
@@ -104,7 +104,7 @@ static WERROR dreplsrv_connect_samdb(struct dreplsrv_service *service, struct lo
/* TODO: fill in site_guid */
bind_info28->site_guid = GUID_zero();
/* TODO: find out how this is really triggered! */
- bind_info28->u1 = 0;
+ bind_info28->pid = 0;
bind_info28->repl_epoch = 0;
return WERR_OK;
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 22826e4f33..9285d6d0d8 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -699,6 +699,50 @@ static int partition_extended_replicated_objects(struct ldb_module *module, stru
return partition_replicate(module, req, ext->partition_dn);
}
+static int partition_extended_schema_update_now(struct ldb_module *module, struct ldb_request *req)
+{
+ struct dsdb_control_current_partition *partition;
+ struct partition_private_data *data;
+ struct ldb_dn *schema_dn;
+ struct partition_context *ac;
+ struct ldb_module *backend;
+ int ret;
+
+ schema_dn = talloc_get_type(req->op.extended.data, struct ldb_dn);
+ if (!schema_dn) {
+ ldb_debug(module->ldb, LDB_DEBUG_FATAL, "partition_extended: invalid extended data\n");
+ return LDB_ERR_PROTOCOL_ERROR;
+ }
+
+ data = talloc_get_type(module->private_data, struct partition_private_data);
+ if (!data) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ partition = find_partition( data, schema_dn );
+ if (!partition) {
+ return ldb_next_request(module, req);
+ }
+
+ ac = partition_init_handle(req, module);
+ if (!ac) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ backend = make_module_for_next_request(req, module->ldb, partition->module);
+ if (!backend) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = ldb_request_add_control(req, DSDB_CONTROL_CURRENT_PARTITION_OID, false, partition);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ return ldb_next_request(backend, req);
+}
+
+
/* extended */
static int partition_extended(struct ldb_module *module, struct ldb_request *req)
{
@@ -708,6 +752,11 @@ static int partition_extended(struct ldb_module *module, struct ldb_request *req
return partition_extended_replicated_objects(module, req);
}
+ /* forward schemaUpdateNow operation to schema_fsmo module*/
+ if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) == 0) {
+ return partition_extended_schema_update_now( module, req );
+ }
+
/*
* as the extended operation has no dn
* we need to send it to all partitions
diff --git a/source4/dsdb/samdb/ldb_modules/password_hash.c b/source4/dsdb/samdb/ldb_modules/password_hash.c
index 3e442b6341..413ec12479 100644
--- a/source4/dsdb/samdb/ldb_modules/password_hash.c
+++ b/source4/dsdb/samdb/ldb_modules/password_hash.c
@@ -140,6 +140,11 @@ struct setup_password_fields_io {
struct samr_Password *nt_history;
uint32_t lm_history_len;
struct samr_Password *lm_history;
+ const char *salt;
+ DATA_BLOB aes_256;
+ DATA_BLOB aes_128;
+ DATA_BLOB des_md5;
+ DATA_BLOB des_crc;
struct ldb_val supplemental;
NTTIME last_set;
uint32_t kvno;
@@ -216,21 +221,12 @@ static int setup_lm_fields(struct setup_password_fields_io *io)
return LDB_SUCCESS;
}
-static int setup_primary_kerberos(struct setup_password_fields_io *io,
- const struct supplementalCredentialsBlob *old_scb,
- struct package_PrimaryKerberosBlob *pkb)
+static int setup_kerberos_keys(struct setup_password_fields_io *io)
{
krb5_error_code krb5_ret;
Principal *salt_principal;
krb5_salt salt;
krb5_keyblock key;
- uint32_t k=0;
- struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
- struct supplementalCredentialsPackage *old_scp = NULL;
- struct package_PrimaryKerberosBlob _old_pkb;
- struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
- uint32_t i;
- enum ndr_err_code ndr_err;
/* Many, many thanks to lukeh@padl.com for this
* algorithm, described in his Nov 10 2004 mail to
@@ -290,7 +286,7 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io,
}
if (krb5_ret) {
ldb_asprintf_errstring(io->ac->module->ldb,
- "setup_primary_kerberos: "
+ "setup_kerberos_keys: "
"generation of a salting principal failed: %s",
smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
return LDB_ERR_OPERATIONS_ERROR;
@@ -304,81 +300,72 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io,
krb5_free_principal(io->smb_krb5_context->krb5_context, salt_principal);
if (krb5_ret) {
ldb_asprintf_errstring(io->ac->module->ldb,
- "setup_primary_kerberos: "
+ "setup_kerberos_keys: "
"generation of krb5_salt failed: %s",
smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
return LDB_ERR_OPERATIONS_ERROR;
}
/* create a talloc copy */
- pkb3->salt.string = talloc_strndup(io->ac,
- salt.saltvalue.data,
- salt.saltvalue.length);
+ io->g.salt = talloc_strndup(io->ac,
+ salt.saltvalue.data,
+ salt.saltvalue.length);
krb5_free_salt(io->smb_krb5_context->krb5_context, salt);
- if (!pkb3->salt.string) {
+ if (!io->g.salt) {
ldb_oom(io->ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- salt.saltvalue.data = discard_const(pkb3->salt.string);
- salt.saltvalue.length = strlen(pkb3->salt.string);
+ salt.saltvalue.data = discard_const(io->g.salt);
+ salt.saltvalue.length = strlen(io->g.salt);
/*
- * prepare generation of keys
- *
- * ENCTYPE_AES256_CTS_HMAC_SHA1_96 (disabled by default)
- * ENCTYPE_DES_CBC_MD5
- * ENCTYPE_DES_CBC_CRC
- *
- * NOTE: update num_keys when you add another enctype!
+ * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
+ * the salt and the cleartext password
*/
- pkb3->num_keys = 3;
- pkb3->keys = talloc_array(io->ac, struct package_PrimaryKerberosKey, pkb3->num_keys);
- if (!pkb3->keys) {
- ldb_oom(io->ac->module->ldb);
+ krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context,
+ ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+ io->n.cleartext,
+ salt,
+ &key);
+ if (krb5_ret) {
+ ldb_asprintf_errstring(io->ac->module->ldb,
+ "setup_kerberos_keys: "
+ "generation of a aes256-cts-hmac-sha1-96 key failed: %s",
+ smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
return LDB_ERR_OPERATIONS_ERROR;
}
- pkb3->unknown3 = talloc_zero_array(io->ac, uint64_t, pkb3->num_keys);
- if (!pkb3->unknown3) {
+ io->g.aes_256 = data_blob_talloc(io->ac,
+ key.keyvalue.data,
+ key.keyvalue.length);
+ krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
+ if (!io->g.aes_256.data) {
ldb_oom(io->ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- if (lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"), NULL, "password_hash", "create_aes_key", false)) {
- /*
- * TODO:
- *
- * w2k and w2k3 doesn't support AES, so we'll not include
- * the AES key here yet.
- *
- * Also we don't have an example supplementalCredentials blob
- * from Windows Longhorn Server with AES support
- *
- */
/*
- * create ENCTYPE_AES256_CTS_HMAC_SHA1_96 key out of
+ * create ENCTYPE_AES128_CTS_HMAC_SHA1_96 key out of
* the salt and the cleartext password
*/
krb5_ret = krb5_string_to_key_salt(io->smb_krb5_context->krb5_context,
- ENCTYPE_AES256_CTS_HMAC_SHA1_96,
+ ENCTYPE_AES128_CTS_HMAC_SHA1_96,
io->n.cleartext,
salt,
&key);
- pkb3->keys[k].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
- pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB);
- if (!pkb3->keys[k].value) {
- krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
- ldb_oom(io->ac->module->ldb);
+ if (krb5_ret) {
+ ldb_asprintf_errstring(io->ac->module->ldb,
+ "setup_kerberos_keys: "
+ "generation of a aes128-cts-hmac-sha1-96 key failed: %s",
+ smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
return LDB_ERR_OPERATIONS_ERROR;
}
- *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value,
- key.keyvalue.data,
- key.keyvalue.length);
+ io->g.aes_128 = data_blob_talloc(io->ac,
+ key.keyvalue.data,
+ key.keyvalue.length);
krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
- if (!pkb3->keys[k].value->data) {
+ if (!io->g.aes_128.data) {
ldb_oom(io->ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- k++;
-}
/*
* create ENCTYPE_DES_CBC_MD5 key out of
@@ -389,22 +376,21 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io,
io->n.cleartext,
salt,
&key);
- pkb3->keys[k].keytype = ENCTYPE_DES_CBC_MD5;
- pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB);
- if (!pkb3->keys[k].value) {
- krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
- ldb_oom(io->ac->module->ldb);
+ if (krb5_ret) {
+ ldb_asprintf_errstring(io->ac->module->ldb,
+ "setup_kerberos_keys: "
+ "generation of a des-cbc-md5 key failed: %s",
+ smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
return LDB_ERR_OPERATIONS_ERROR;
}
- *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value,
- key.keyvalue.data,
- key.keyvalue.length);
+ io->g.des_md5 = data_blob_talloc(io->ac,
+ key.keyvalue.data,
+ key.keyvalue.length);
krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
- if (!pkb3->keys[k].value->data) {
+ if (!io->g.des_md5.data) {
ldb_oom(io->ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- k++;
/*
* create ENCTYPE_DES_CBC_CRC key out of
@@ -415,30 +401,60 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io,
io->n.cleartext,
salt,
&key);
- pkb3->keys[k].keytype = ENCTYPE_DES_CBC_CRC;
- pkb3->keys[k].value = talloc(pkb3->keys, DATA_BLOB);
- if (!pkb3->keys[k].value) {
- krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
- ldb_oom(io->ac->module->ldb);
+ if (krb5_ret) {
+ ldb_asprintf_errstring(io->ac->module->ldb,
+ "setup_kerberos_keys: "
+ "generation of a des-cbc-crc key failed: %s",
+ smb_get_krb5_error_message(io->smb_krb5_context->krb5_context, krb5_ret, io->ac));
return LDB_ERR_OPERATIONS_ERROR;
}
- *pkb3->keys[k].value = data_blob_talloc(pkb3->keys[k].value,
- key.keyvalue.data,
- key.keyvalue.length);
+ io->g.des_crc = data_blob_talloc(io->ac,
+ key.keyvalue.data,
+ key.keyvalue.length);
krb5_free_keyblock_contents(io->smb_krb5_context->krb5_context, &key);
- if (!pkb3->keys[k].value->data) {
+ if (!io->g.des_crc.data) {
ldb_oom(io->ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
- k++;
- /* fix up key number */
- pkb3->num_keys = k;
+ return LDB_SUCCESS;
+}
+
+static int setup_primary_kerberos(struct setup_password_fields_io *io,
+ const struct supplementalCredentialsBlob *old_scb,
+ struct package_PrimaryKerberosBlob *pkb)
+{
+ struct package_PrimaryKerberosCtr3 *pkb3 = &pkb->ctr.ctr3;
+ struct supplementalCredentialsPackage *old_scp = NULL;
+ struct package_PrimaryKerberosBlob _old_pkb;
+ struct package_PrimaryKerberosCtr3 *old_pkb3 = NULL;
+ uint32_t i;
+ enum ndr_err_code ndr_err;
+
+ /*
+ * prepare generation of keys
+ *
+ * ENCTYPE_DES_CBC_MD5
+ * ENCTYPE_DES_CBC_CRC
+ */
+ pkb3->salt.string = io->g.salt;
+ pkb3->num_keys = 2;
+ pkb3->keys = talloc_array(io->ac,
+ struct package_PrimaryKerberosKey,
+ pkb3->num_keys);
+ if (!pkb3->keys) {
+ ldb_oom(io->ac->module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ pkb3->keys[0].keytype = ENCTYPE_DES_CBC_MD5;
+ pkb3->keys[0].value = &io->g.des_md5;
+ pkb3->keys[1].keytype = ENCTYPE_DES_CBC_CRC;
+ pkb3->keys[1].value = &io->g.des_crc;
/* initialize the old keys to zero */
pkb3->num_old_keys = 0;
pkb3->old_keys = NULL;
- pkb3->unknown3_old = NULL;
/* if there're no old keys, then we're done */
if (!old_scb) {
@@ -446,10 +462,6 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io,
}
for (i=0; i < old_scb->sub.num_packages; i++) {
- if (old_scb->sub.packages[i].unknown1 != 0x00000001) {
- continue;
- }
-
if (strcmp("Primary:Kerberos", old_scb->sub.packages[i].name) != 0) {
continue;
}
@@ -503,7 +515,117 @@ static int setup_primary_kerberos(struct setup_password_fields_io *io,
/* fill in the old keys */
pkb3->num_old_keys = old_pkb3->num_keys;
pkb3->old_keys = old_pkb3->keys;
- pkb3->unknown3_old = old_pkb3->unknown3;
+
+ return LDB_SUCCESS;
+}
+
+static int setup_primary_kerberos_newer(struct setup_password_fields_io *io,
+ const struct supplementalCredentialsBlob *old_scb,
+ struct package_PrimaryKerberosNewerBlob *pkb)
+{
+ struct package_PrimaryKerberosNewerCtr4 *pkb4 = &pkb->ctr.ctr4;
+ struct supplementalCredentialsPackage *old_scp = NULL;
+ struct package_PrimaryKerberosNewerBlob _old_pkb;
+ struct package_PrimaryKerberosNewerCtr4 *old_pkb4 = NULL;
+ uint32_t i;
+ enum ndr_err_code ndr_err;
+
+ /*
+ * prepare generation of keys
+ *
+ * ENCTYPE_AES256_CTS_HMAC_SHA1_96
+ * ENCTYPE_AES128_CTS_HMAC_SHA1_96
+ * ENCTYPE_DES_CBC_MD5
+ * ENCTYPE_DES_CBC_CRC
+ */
+ pkb4->salt.string = io->g.salt;
+ pkb4->num_keys = 4;
+ pkb4->keys = talloc_array(io->ac,
+ struct package_PrimaryKerberosNewerKey,
+ pkb4->num_keys);
+ if (!pkb4->keys) {
+ ldb_oom(io->ac->module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ pkb4->keys[0].keytype = ENCTYPE_AES256_CTS_HMAC_SHA1_96;
+ pkb4->keys[0].value = &io->g.aes_256;
+ pkb4->keys[1].keytype = ENCTYPE_AES128_CTS_HMAC_SHA1_96;
+ pkb4->keys[1].value = &io->g.aes_128;
+ pkb4->keys[2].keytype = ENCTYPE_DES_CBC_MD5;
+ pkb4->keys[2].value = &io->g.des_md5;
+ pkb4->keys[3].keytype = ENCTYPE_DES_CBC_CRC;
+ pkb4->keys[3].value = &io->g.des_crc;
+
+ /* initialize the old keys to zero */
+ pkb4->num_old_keys1 = 0;
+ pkb4->old_keys1 = NULL;
+ pkb4->num_old_keys2 = 0;
+ pkb4->old_keys2 = NULL;
+
+ /* if there're no old keys, then we're done */
+ if (!old_scb) {
+ return LDB_SUCCESS;
+ }
+
+ for (i=0; i < old_scb->sub.num_packages; i++) {
+ if (strcmp("Primary:Kerberos-Newer-Keys", old_scb->sub.packages[i].name) != 0) {
+ continue;
+ }
+
+ if (!old_scb->sub.packages[i].data || !old_scb->sub.packages[i].data[0]) {
+ continue;
+ }
+
+ old_scp = &old_scb->sub.packages[i];
+ break;
+ }
+ /* Primary:Kerberos element of supplementalCredentials */
+ if (old_scp) {
+ DATA_BLOB blob;
+
+ blob = strhex_to_data_blob(old_scp->data);
+ if (!blob.data) {
+ ldb_oom(io->ac->module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ talloc_steal(io->ac, blob.data);
+
+ /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
+ ndr_err = ndr_pull_struct_blob(&blob, io->ac,
+ lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),
+ &_old_pkb,
+ (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosNewerBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+ ldb_asprintf_errstring(io->ac->module->ldb,
+ "setup_primary_kerberos_newer: "
+ "failed to pull old package_PrimaryKerberosNewerBlob: %s",
+ nt_errstr(status));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (_old_pkb.version != 4) {
+ ldb_asprintf_errstring(io->ac->module->ldb,
+ "setup_primary_kerberos: "
+ "package_PrimaryKerberosNewerBlob version[%u] expected[4]",
+ _old_pkb.version);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ old_pkb4 = &_old_pkb.ctr.ctr4;
+ }
+
+ /* if we didn't found the old keys we're done */
+ if (!old_pkb4) {
+ return LDB_SUCCESS;
+ }
+
+ /* fill in the old keys */
+ pkb4->num_old_keys1 = old_pkb4->num_keys;
+ pkb4->old_keys1 = old_pkb4->keys;
+ pkb4->num_old_keys2 = old_pkb4->num_old_keys1;
+ pkb4->old_keys2 = old_pkb4->old_keys1;
return LDB_SUCCESS;
}
@@ -845,30 +967,48 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
struct supplementalCredentialsBlob scb;
struct supplementalCredentialsBlob _old_scb;
struct supplementalCredentialsBlob *old_scb = NULL;
- /* Packages + (Kerberos, WDigest and maybe CLEARTEXT) */
- uint32_t num_packages = 1 + 2;
- struct supplementalCredentialsPackage packages[1+3];
- struct supplementalCredentialsPackage *pp = &packages[0];
- struct supplementalCredentialsPackage *pk = &packages[1];
- struct supplementalCredentialsPackage *pd = &packages[2];
- struct supplementalCredentialsPackage *pc = NULL;
+ /* Packages + (Kerberos-Newer-Keys, Kerberos, WDigest and CLEARTEXT) */
+ uint32_t num_names = 0;
+ const char *names[1+4];
+ uint32_t num_packages = 0;
+ struct supplementalCredentialsPackage packages[1+4];
+ /* Packages */
+ struct supplementalCredentialsPackage *pp = NULL;
struct package_PackagesBlob pb;
DATA_BLOB pb_blob;
char *pb_hexstr;
+ /* Primary:Kerberos-Newer-Keys */
+ const char **nkn = NULL;
+ struct supplementalCredentialsPackage *pkn = NULL;
+ struct package_PrimaryKerberosNewerBlob pknb;
+ DATA_BLOB pknb_blob;
+ char *pknb_hexstr;
+ /* Primary:Kerberos */
+ const char **nk = NULL;
+ struct supplementalCredentialsPackage *pk = NULL;
struct package_PrimaryKerberosBlob pkb;
DATA_BLOB pkb_blob;
char *pkb_hexstr;
+ /* Primary:WDigest */
+ const char **nd = NULL;
+ struct supplementalCredentialsPackage *pd = NULL;
struct package_PrimaryWDigestBlob pdb;
DATA_BLOB pdb_blob;
char *pdb_hexstr;
+ /* Primary:CLEARTEXT */
+ const char **nc = NULL;
+ struct supplementalCredentialsPackage *pc = NULL;
struct package_PrimaryCLEARTEXTBlob pcb;
DATA_BLOB pcb_blob;
char *pcb_hexstr;
int ret;
enum ndr_err_code ndr_err;
uint8_t zero16[16];
+ bool do_newer_keys = false;
+ bool do_cleartext = false;
ZERO_STRUCT(zero16);
+ ZERO_STRUCT(names);
if (!io->n.cleartext) {
/*
@@ -880,7 +1020,9 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
/* if there's an old supplementaCredentials blob then parse it */
if (io->o.supplemental) {
- ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac, lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")), &_old_scb,
+ ndr_err = ndr_pull_struct_blob_all(io->o.supplemental, io->ac,
+ lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),
+ &_old_scb,
(ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
@@ -891,22 +1033,101 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
return LDB_ERR_OPERATIONS_ERROR;
}
- old_scb = &_old_scb;
+ if (_old_scb.sub.signature == SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
+ old_scb = &_old_scb;
+ } else {
+ ldb_debug(io->ac->module->ldb, LDB_DEBUG_ERROR,
+ "setup_supplemental_field: "
+ "supplementalCredentialsBlob signature[0x%04X] expected[0x%04X]",
+ _old_scb.sub.signature, SUPPLEMENTAL_CREDENTIALS_SIGNATURE);
+ }
}
+ /* TODO: do the correct check for this, it maybe depends on the functional level? */
+ do_newer_keys = lp_parm_bool(ldb_get_opaque(io->ac->module->ldb, "loadparm"),
+ NULL, "password_hash", "create_aes_key", false);
+
if (io->domain->store_cleartext &&
(io->u.user_account_control & UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED)) {
- pc = &packages[3];
- num_packages++;
+ do_cleartext = true;
+ }
+
+ /*
+ * The ordering is this
+ *
+ * Primary:Kerberos-Newer-Keys (optional)
+ * Primary:Kerberos
+ * Primary:WDigest
+ * Primary:CLEARTEXT (optional)
+ *
+ * And the 'Packages' package is insert before the last
+ * other package.
+ */
+ if (do_newer_keys) {
+ /* Primary:Kerberos-Newer-Keys */
+ nkn = &names[num_names++];
+ pkn = &packages[num_packages++];
+ }
+
+ /* Primary:Kerberos */
+ nk = &names[num_names++];
+ pk = &packages[num_packages++];
+
+ if (!do_cleartext) {
+ /* Packages */
+ pp = &packages[num_packages++];
+ }
+
+ /* Primary:WDigest */
+ nd = &names[num_names++];
+ pd = &packages[num_packages++];
+
+ if (do_cleartext) {
+ /* Packages */
+ pp = &packages[num_packages++];
+
+ /* Primary:CLEARTEXT */
+ nc = &names[num_names++];
+ pc = &packages[num_packages++];
}
- /* Kerberos, WDigest, CLEARTEXT and termination(counted by the Packages element) */
- pb.names = talloc_zero_array(io->ac, const char *, num_packages);
+ if (pkn) {
+ /*
+ * setup 'Primary:Kerberos-Newer-Keys' element
+ */
+ *nkn = "Kerberos-Newer-Keys";
+
+ ret = setup_primary_kerberos_newer(io, old_scb, &pknb);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ndr_err = ndr_push_struct_blob(&pknb_blob, io->ac,
+ lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),
+ &pknb,
+ (ndr_push_flags_fn_t)ndr_push_package_PrimaryKerberosNewerBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
+ ldb_asprintf_errstring(io->ac->module->ldb,
+ "setup_supplemental_field: "
+ "failed to push package_PrimaryKerberosNeverBlob: %s",
+ nt_errstr(status));
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ pknb_hexstr = data_blob_hex_string(io->ac, &pknb_blob);
+ if (!pknb_hexstr) {
+ ldb_oom(io->ac->module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ pkn->name = "Primary:Kerberos-Newer-Keys";
+ pkn->reserved = 1;
+ pkn->data = pknb_hexstr;
+ }
/*
* setup 'Primary:Kerberos' element
*/
- pb.names[0] = "Kerberos";
+ *nk = "Kerberos";
ret = setup_primary_kerberos(io, old_scb, &pkb);
if (ret != LDB_SUCCESS) {
@@ -925,29 +1146,19 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
nt_errstr(status));
return LDB_ERR_OPERATIONS_ERROR;
}
- /*
- * TODO:
- *
- * This is ugly, but we want to generate the same blob as
- * w2k and w2k3...we should handle this in the idl
- */
- if (!data_blob_append(io->ac, &pkb_blob, zero16, sizeof(zero16))) {
- ldb_oom(io->ac->module->ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
pkb_hexstr = data_blob_hex_string(io->ac, &pkb_blob);
if (!pkb_hexstr) {
ldb_oom(io->ac->module->ldb);
return LDB_ERR_OPERATIONS_ERROR;
}
pk->name = "Primary:Kerberos";
- pk->unknown1 = 1;
+ pk->reserved = 1;
pk->data = pkb_hexstr;
/*
* setup 'Primary:WDigest' element
*/
- pb.names[1] = "WDigest";
+ *nd = "WDigest";
ret = setup_primary_wdigest(io, old_scb, &pdb);
if (ret != LDB_SUCCESS) {
@@ -972,14 +1183,14 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
return LDB_ERR_OPERATIONS_ERROR;
}
pd->name = "Primary:WDigest";
- pd->unknown1 = 1;
+ pd->reserved = 1;
pd->data = pdb_hexstr;
/*
* setup 'Primary:CLEARTEXT' element
*/
if (pc) {
- pb.names[2] = "CLEARTEXT";
+ *nc = "CLEARTEXT";
pcb.cleartext = io->n.cleartext;
@@ -1001,13 +1212,14 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
return LDB_ERR_OPERATIONS_ERROR;
}
pc->name = "Primary:CLEARTEXT";
- pc->unknown1 = 1;
+ pc->reserved = 1;
pc->data = pcb_hexstr;
}
/*
* setup 'Packages' element
*/
+ pb.names = names;
ndr_err = ndr_push_struct_blob(&pb_blob, io->ac,
lp_iconv_convenience(ldb_get_opaque(io->ac->module->ldb, "loadparm")),
&pb,
@@ -1026,12 +1238,13 @@ static int setup_supplemental_field(struct setup_password_fields_io *io)
return LDB_ERR_OPERATIONS_ERROR;
}
pp->name = "Packages";
- pp->unknown1 = 2;
+ pp->reserved = 2;
pp->data = pb_hexstr;
/*
* setup 'supplementalCredentials' value
*/
+ ZERO_STRUCT(scb);
scb.sub.num_packages = num_packages;
scb.sub.packages = packages;
@@ -1083,7 +1296,7 @@ static int setup_password_fields(struct setup_password_fields_io *io)
return LDB_ERR_UNWILLING_TO_PERFORM;
}
- if (io->n.cleartext && !io->n.nt_hash) {
+ if (io->n.cleartext) {
struct samr_Password *hash;
hash = talloc(io->ac, struct samr_Password);
@@ -1104,7 +1317,7 @@ static int setup_password_fields(struct setup_password_fields_io *io)
}
}
- if (io->n.cleartext && !io->n.lm_hash) {
+ if (io->n.cleartext) {
struct samr_Password *hash;
hash = talloc(io->ac, struct samr_Password);
@@ -1122,6 +1335,13 @@ static int setup_password_fields(struct setup_password_fields_io *io)
}
}
+ if (io->n.cleartext) {
+ ret = setup_kerberos_keys(io);
+ if (ret != 0) {
+ return ret;
+ }
+ }
+
ret = setup_nt_fields(io);
if (ret != 0) {
return ret;
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index 75f99a139d..97491a2ae3 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -391,9 +391,50 @@ static int rootdse_init(struct ldb_module *module)
return ldb_next_init(module);
}
+static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_result *ext_res;
+ int ret;
+ struct ldb_dn *schema_dn;
+ struct ldb_message_element *schemaUpdateNowAttr;
+
+ /*
+ If dn is not "" we should let it pass through
+ */
+ if (!ldb_dn_is_null(req->op.mod.message->dn)) {
+ return ldb_next_request(module, req);
+ }
+
+ /*
+ dn is empty so check for schemaUpdateNow attribute
+ "The type of modification and values specified in the LDAP modify operation do not matter." MSDN
+ */
+ schemaUpdateNowAttr = ldb_msg_find_element(req->op.mod.message, "schemaUpdateNow");
+ if (!schemaUpdateNowAttr) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ schema_dn = samdb_schema_dn(module->ldb);
+ if (!schema_dn) {
+ ldb_reset_err_string(module->ldb);
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+ "rootdse_modify: no schema dn present: (skip ldb_extended call)\n");
+ return ldb_next_request(module, req);
+ }
+
+ ret = ldb_extended(module->ldb, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID, schema_dn, &ext_res);
+ if (ret != LDB_SUCCESS) {
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ talloc_free(ext_res);
+ return ret;
+}
+
_PUBLIC_ const struct ldb_module_ops ldb_rootdse_module_ops = {
.name = "rootdse",
- .init_context = rootdse_init,
- .search = rootdse_search,
- .request = rootdse_request
+ .init_context = rootdse_init,
+ .search = rootdse_search,
+ .request = rootdse_request,
+ .modify = rootdse_modify
};
diff --git a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
index a397228723..2acc5c0af4 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_fsmo.c
@@ -148,8 +148,70 @@ static int schema_fsmo_add(struct ldb_module *module, struct ldb_request *req)
return ldb_next_request(module, req);
}
+static int schema_fsmo_extended(struct ldb_module *module, struct ldb_request *req)
+{
+ WERROR status;
+ struct ldb_dn *schema_dn;
+ struct dsdb_schema *schema;
+ char *error_string = NULL;
+ int ret;
+ TALLOC_CTX *mem_ctx;
+
+ if (strcmp(req->op.extended.oid, DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID) != 0) {
+ return ldb_next_request(module, req);
+ }
+
+ schema_dn = samdb_schema_dn(module->ldb);
+ if (!schema_dn) {
+ ldb_reset_err_string(module->ldb);
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+ "schema_fsmo_extended: no schema dn present: (skip schema loading)\n");
+ return ldb_next_request(module, req);
+ }
+
+ mem_ctx = talloc_new(module);
+ if (!mem_ctx) {
+ ldb_oom(module->ldb);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = dsdb_schema_from_schema_dn(mem_ctx, module->ldb,
+ lp_iconv_convenience(ldb_get_opaque(module->ldb, "loadparm")),
+ schema_dn, &schema, &error_string);
+
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ ldb_reset_err_string(module->ldb);
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING,
+ "schema_fsmo_extended: no schema head present: (skip schema loading)\n");
+ talloc_free(mem_ctx);
+ return ldb_next_request(module, req);
+ }
+
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(module->ldb,
+ "schema_fsmo_extended: dsdb_schema load failed: %s",
+ error_string);
+ talloc_free(mem_ctx);
+ return ldb_next_request(module, req);
+ }
+
+ /* Replace the old schema*/
+ ret = dsdb_set_schema(module->ldb, schema);
+ if (ret != LDB_SUCCESS) {
+ ldb_debug_set(module->ldb, LDB_DEBUG_FATAL,
+ "schema_fsmo_extended: dsdb_set_schema() failed: %d:%s",
+ ret, ldb_strerror(ret));
+ talloc_free(mem_ctx);
+ return ret;
+ }
+
+ talloc_free(mem_ctx);
+ return LDB_SUCCESS;
+}
+
_PUBLIC_ const struct ldb_module_ops ldb_schema_fsmo_module_ops = {
.name = "schema_fsmo",
.init_context = schema_fsmo_init,
- .add = schema_fsmo_add
+ .add = schema_fsmo_add,
+ .extended = schema_fsmo_extended
};
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index 75aa819ccd..b8a3e16d46 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -90,4 +90,6 @@ struct dsdb_pdc_fsmo {
struct ldb_dn *master_dn;
};
+#define DSDB_EXTENDED_SCHEMA_UPDATE_NOW_OID "1.3.6.1.4.1.7165.4.4.2"
+
#endif /* __SAMDB_H__ */
diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index 71d952b944..2ec5ad34b1 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -268,18 +268,145 @@ WERROR dsdb_verify_oid_mappings_drsuapi(const struct dsdb_schema *schema, const
WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32_t *out)
{
+ return dsdb_find_prefix_for_oid(schema->num_prefixes, schema->prefixes, in, out);
+}
+
+
+WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out)
+{
uint32_t i;
for (i=0; i < schema->num_prefixes; i++) {
+ const char *val;
+ if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
+ continue;
+ }
+
+ val = talloc_asprintf(mem_ctx, "%s%u",
+ schema->prefixes[i].oid,
+ in & 0xFFFF);
+ W_ERROR_HAVE_NO_MEMORY(val);
+
+ *out = val;
+ return WERR_OK;
+ }
+
+ return WERR_DS_NO_MSDS_INTID;
+}
+
+/*
+ * this function is called from within a ldb transaction from the schema_fsmo module
+ */
+WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
+{
+ WERROR status;
+ uint32_t num_prefixes;
+ struct dsdb_schema_oid_prefix *prefixes;
+ struct ldb_val ndr_blob;
+ TALLOC_CTX *mem_ctx;
+ uint32_t out;
+
+ mem_ctx = talloc_new(ldb);
+ W_ERROR_HAVE_NO_MEMORY(mem_ctx);
+
+ /* Read prefixes from disk*/
+ status = dsdb_read_prefixes_from_ldb( mem_ctx, ldb, &num_prefixes, &prefixes );
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("dsdb_create_prefix_mapping: dsdb_read_prefixes_from_ldb failed\n"));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ /* Check if there is a prefix for the oid in the prefixes array*/
+ status = dsdb_find_prefix_for_oid( num_prefixes, prefixes, full_oid, &out );
+ if (W_ERROR_IS_OK(status)) {
+ /* prefix found*/
+ talloc_free(mem_ctx);
+ return status;
+ }
+ /* Update prefix map in ldb*/
+ /* Update the prefixes */
+ status = dsdb_prefix_map_update(mem_ctx, &num_prefixes, &prefixes, full_oid);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("dsdb_create_prefix_mapping: dsdb_prefix_map_update failed\n"));
+ talloc_free(mem_ctx);
+ return status;
+ }
+ /* Convert prefixes in ndr blob*/
+ status = dsdb_write_prefixes_to_ndr( mem_ctx, ldb, num_prefixes, prefixes, &ndr_blob );
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ndr failed\n"));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ /* Update prefixMap in ldb*/
+ status = dsdb_write_prefixes_to_ldb( mem_ctx, ldb, &ndr_blob );
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("dsdb_create_prefix_mapping: dsdb_write_prefixes_to_ldb failed\n"));
+ talloc_free(mem_ctx);
+ return status;
+ }
+
+ talloc_free(mem_ctx);
+ return status;
+}
+
+WERROR dsdb_prefix_map_update(TALLOC_CTX *mem_ctx, uint32_t *num_prefixes, struct dsdb_schema_oid_prefix **prefixes, const char *oid)
+{
+ uint32_t new_num_prefixes, index_new_prefix, new_entry_id;
+ const char* lastDotOffset;
+ size_t size;
+
+ new_num_prefixes = *num_prefixes + 1;
+ index_new_prefix = *num_prefixes;
+ new_entry_id = (*num_prefixes)<<16;
+
+ /* Extract the prefix from the oid*/
+ lastDotOffset = strrchr(oid, '.');
+ if (lastDotOffset == NULL) {
+ DEBUG(0,("dsdb_prefix_map_update: failed to find the last dot\n"));
+ return WERR_NOT_FOUND;
+ }
+
+ /* Calculate the size of the remainig string that should be the prefix of it */
+ size = strlen(oid) - strlen(lastDotOffset);
+ if (size <= 0) {
+ DEBUG(0,("dsdb_prefix_map_update: size of the remaining string invalid\n"));
+ return WERR_FOOBAR;
+ }
+ /* Add one because we need to copy the dot */
+ size += 1;
+
+ /* Create a spot in the prefixMap for one more prefix*/
+ (*prefixes) = talloc_realloc(mem_ctx, *prefixes, struct dsdb_schema_oid_prefix, new_num_prefixes);
+ W_ERROR_HAVE_NO_MEMORY(*prefixes);
+
+ /* Add the new prefix entry*/
+ (*prefixes)[index_new_prefix].id = new_entry_id;
+ (*prefixes)[index_new_prefix].oid = talloc_strndup(mem_ctx, oid, size);
+ (*prefixes)[index_new_prefix].oid_len = strlen((*prefixes)[index_new_prefix].oid);
+
+ /* Increase num_prefixes because new prefix has been added */
+ ++(*num_prefixes);
+
+ return WERR_OK;
+}
+
+WERROR dsdb_find_prefix_for_oid(uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, const char *in, uint32_t *out)
+{
+ uint32_t i;
+
+ for (i=0; i < num_prefixes; i++) {
const char *val_str;
char *end_str;
unsigned val;
- if (strncmp(schema->prefixes[i].oid, in, schema->prefixes[i].oid_len) != 0) {
+ if (strncmp(prefixes[i].oid, in, prefixes[i].oid_len) != 0) {
continue;
}
- val_str = in + schema->prefixes[i].oid_len;
+ val_str = in + prefixes[i].oid_len;
end_str = NULL;
errno = 0;
@@ -305,58 +432,152 @@ WERROR dsdb_map_oid2int(const struct dsdb_schema *schema, const char *in, uint32
return WERR_INVALID_PARAM;
}
- *out = schema->prefixes[i].id | val;
+ *out = prefixes[i].id | val;
return WERR_OK;
}
return WERR_DS_NO_MSDS_INTID;
}
-WERROR dsdb_map_int2oid(const struct dsdb_schema *schema, uint32_t in, TALLOC_CTX *mem_ctx, const char **out)
+WERROR dsdb_write_prefixes_to_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, struct ldb_val *ndr_blob)
{
+ struct ldb_message msg;
+ struct ldb_dn *schema_dn;
+ struct ldb_message_element el;
+ int ret;
+
+ schema_dn = samdb_schema_dn(ldb);
+ if (!schema_dn) {
+ DEBUG(0,("dsdb_write_prefixes_to_ldb: no schema dn present\n"));
+ return WERR_FOOBAR;
+ }
+
+ el.num_values = 1;
+ el.values = ndr_blob;
+ el.flags = LDB_FLAG_MOD_REPLACE;
+ el.name = talloc_strdup(mem_ctx, "prefixMap");
+
+ msg.dn = ldb_dn_copy(mem_ctx, schema_dn);
+ msg.num_elements = 1;
+ msg.elements = &el;
+
+ ret = ldb_modify( ldb, &msg );
+ if (ret != 0) {
+ DEBUG(0,("dsdb_write_prefixes_to_ldb: ldb_modify failed\n"));
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
+}
+
+WERROR dsdb_read_prefixes_from_ldb(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t* num_prefixes, struct dsdb_schema_oid_prefix **prefixes)
+{
+ struct prefixMapBlob *blob;
+ enum ndr_err_code ndr_err;
uint32_t i;
+ const struct ldb_val *prefix_val;
+ struct ldb_dn *schema_dn;
+ struct ldb_result *schema_res;
+ int ret;
+ static const char *schema_attrs[] = {
+ "prefixMap",
+ NULL
+ };
- for (i=0; i < schema->num_prefixes; i++) {
- const char *val;
- if (schema->prefixes[i].id != (in & 0xFFFF0000)) {
- continue;
- }
+ schema_dn = samdb_schema_dn(ldb);
+ if (!schema_dn) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: no schema dn present\n"));
+ return WERR_FOOBAR;
+ }
- val = talloc_asprintf(mem_ctx, "%s%u",
- schema->prefixes[i].oid,
- in & 0xFFFF);
- W_ERROR_HAVE_NO_MEMORY(val);
+ ret = ldb_search(ldb, schema_dn, LDB_SCOPE_BASE,NULL, schema_attrs,&schema_res);
+ if (ret == LDB_ERR_NO_SUCH_OBJECT) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefix map present\n"));
+ return WERR_FOOBAR;
+ } else if (ret != LDB_SUCCESS) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: failed to search the schema head\n"));
+ return WERR_FOOBAR;
+ }
- *out = val;
- return WERR_OK;
+ prefix_val = ldb_msg_find_ldb_val(schema_res->msgs[0], "prefixMap");
+ if (!prefix_val) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: no prefixMap attribute found\n"));
+ return WERR_FOOBAR;
}
- return WERR_DS_NO_MSDS_INTID;
+ blob = talloc(mem_ctx, struct prefixMapBlob);
+ W_ERROR_HAVE_NO_MEMORY(blob);
+
+ ndr_err = ndr_pull_struct_blob(prefix_val, blob,
+ lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ blob,
+ (ndr_pull_flags_fn_t)ndr_pull_prefixMapBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: ndr_pull_struct_blob failed\n"));
+ talloc_free(blob);
+ return WERR_FOOBAR;
+ }
+
+ if (blob->version != PREFIX_MAP_VERSION_DSDB) {
+ DEBUG(0,("dsdb_read_prefixes_from_ldb: blob->version incorect\n"));
+ talloc_free(blob);
+ return WERR_FOOBAR;
+ }
+
+ *num_prefixes = blob->ctr.dsdb.num_mappings;
+ *prefixes = talloc_array(mem_ctx, struct dsdb_schema_oid_prefix, *num_prefixes);
+ if(!(*prefixes)) {
+ talloc_free(blob);
+ return WERR_NOMEM;
+ }
+ for (i=0; i < blob->ctr.dsdb.num_mappings; i++) {
+ (*prefixes)[i].id = blob->ctr.dsdb.mappings[i].id_prefix<<16;
+ (*prefixes)[i].oid = talloc_strdup(mem_ctx, blob->ctr.dsdb.mappings[i].oid.oid);
+ (*prefixes)[i].oid = talloc_asprintf_append((*prefixes)[i].oid, ".");
+ (*prefixes)[i].oid_len = strlen(blob->ctr.dsdb.mappings[i].oid.oid);
+ }
+
+ talloc_free(blob);
+ return WERR_OK;
}
-/*
- * this function is called from within a ldb transaction from the schema_fsmo module
- */
-WERROR dsdb_create_prefix_mapping(struct ldb_context *ldb, struct dsdb_schema *schema, const char *full_oid)
+
+WERROR dsdb_write_prefixes_to_ndr(TALLOC_CTX *mem_ctx, struct ldb_context *ldb, uint32_t num_prefixes, const struct dsdb_schema_oid_prefix *prefixes, struct ldb_val *out)
{
- /*
- * TODO:
- * - (maybe) read the old prefixMap attribute and parse it
- *
- * - recheck the prefix doesn't exist (because the ldb
- * has maybe a more uptodate value than schem->prefixes
- *
- * - calculate a new mapping for the oid prefix of full_oid
- * - store the new prefixMap attribute
- *
- * - (maybe) update schema->prefixes
- * or
- * - better find a way to indicate a schema reload,
- * so that other processes also notice the schema change
- */
- return WERR_NOT_SUPPORTED;
+ struct prefixMapBlob *blob;
+ enum ndr_err_code ndr_err;
+ uint32_t i;
+
+ blob = talloc_zero(mem_ctx, struct prefixMapBlob);
+ W_ERROR_HAVE_NO_MEMORY(blob);
+
+ blob->version = PREFIX_MAP_VERSION_DSDB;
+ blob->ctr.dsdb.num_mappings = num_prefixes;
+ blob->ctr.dsdb.mappings = talloc_realloc(blob,
+ blob->ctr.dsdb.mappings,
+ struct drsuapi_DsReplicaOIDMapping,
+ blob->ctr.dsdb.num_mappings);
+ if (!blob->ctr.dsdb.mappings) {
+ return WERR_NOMEM;
+ }
+
+ for (i=0; i < num_prefixes; i++) {
+ blob->ctr.dsdb.mappings[i].id_prefix = prefixes[i].id>>16;
+ blob->ctr.dsdb.mappings[i].oid.oid = talloc_strdup(blob->ctr.dsdb.mappings, prefixes[i].oid);
+ }
+
+ ndr_err = ndr_push_struct_blob(out, ldb,
+ lp_iconv_convenience(ldb_get_opaque(ldb, "loadparm")),
+ blob,
+ (ndr_push_flags_fn_t)ndr_push_prefixMapBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return WERR_FOOBAR;
+ }
+
+ return WERR_OK;
}
+
#define GET_STRING_LDB(msg, attr, mem_ctx, p, elem, strict) do { \
(p)->elem = samdb_result_string(msg, attr, NULL);\
if (strict && (p)->elem == NULL) { \
diff --git a/source4/kdc/hdb-ldb.c b/source4/kdc/hdb-ldb.c
index 70e578ee0d..9960085b1a 100644
--- a/source4/kdc/hdb-ldb.c
+++ b/source4/kdc/hdb-ldb.c
@@ -190,9 +190,12 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context,
struct samr_Password *hash;
const struct ldb_val *sc_val;
struct supplementalCredentialsBlob scb;
- struct supplementalCredentialsPackage *scp = NULL;
+ struct supplementalCredentialsPackage *scpk = NULL;
+ struct supplementalCredentialsPackage *scpkn = NULL;
struct package_PrimaryKerberosBlob _pkb;
struct package_PrimaryKerberosCtr3 *pkb3 = NULL;
+ struct package_PrimaryKerberosNewerBlob _pknb;
+ struct package_PrimaryKerberosNewerCtr4 *pkb4 = NULL;
uint32_t i;
uint32_t allocated_keys = 0;
@@ -221,35 +224,75 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context,
goto out;
}
+ if (scb.sub.signature != SUPPLEMENTAL_CREDENTIALS_SIGNATURE) {
+ NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb);
+ ret = EINVAL;
+ goto out;
+ }
+
for (i=0; i < scb.sub.num_packages; i++) {
- if (scb.sub.packages[i].unknown1 != 0x00000001) {
- continue;
+ if (strcmp("Primary:Kerberos-Newer-Keys", scb.sub.packages[i].name) == 0) {
+ scpkn = &scb.sub.packages[i];
+ if (!scpkn->data || !scpkn->data[0]) {
+ scpkn = NULL;
+ continue;
+ }
+ break;
+ } else if (strcmp("Primary:Kerberos", scb.sub.packages[i].name) == 0) {
+ scpk = &scb.sub.packages[i];
+ if (!scpk->data || !scpk->data[0]) {
+ scpk = NULL;
+ }
+ /*
+ * we don't break here in hope to find
+ * a Kerberos-Newer-Keys package
+ */
}
+ }
+ }
+ /* Primary:Kerberos-Newer-Keys element of supplementalCredentials */
+ if (scpkn) {
+ DATA_BLOB blob;
- if (strcmp("Primary:Kerberos", scb.sub.packages[i].name) != 0) {
- continue;
- }
+ blob = strhex_to_data_blob(scpkn->data);
+ if (!blob.data) {
+ ret = ENOMEM;
+ goto out;
+ }
+ talloc_steal(mem_ctx, blob.data);
- if (!scb.sub.packages[i].data || !scb.sub.packages[i].data[0]) {
- continue;
- }
+ /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
+ ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, iconv_convenience, &_pknb,
+ (ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosNewerBlob);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ krb5_set_error_string(context, "LDB_message2entry_keys: could not parse package_PrimaryKerberosNewerBlob");
+ krb5_warnx(context, "LDB_message2entry_keys: could not parse package_PrimaryKerberosNewerBlob");
+ ret = EINVAL;
+ goto out;
+ }
- scp = &scb.sub.packages[i];
- break;
+ if (_pknb.version != 4) {
+ krb5_set_error_string(context, "LDB_message2entry_keys: could not parse PrimaryKerberosNewer not version 4");
+ krb5_warnx(context, "LDB_message2entry_keys: could not parse PrimaryKerberosNewer not version 4");
+ ret = EINVAL;
+ goto out;
}
- }
- /* Primary:Kerberos element of supplementalCredentials */
- if (scp) {
+
+ pkb4 = &_pknb.ctr.ctr4;
+
+ allocated_keys += pkb4->num_keys;
+ } else if (scpk) {
+ /* Fallback to Primary:Kerberos element of supplementalCredentials */
DATA_BLOB blob;
- blob = strhex_to_data_blob(scp->data);
+ blob = strhex_to_data_blob(scpk->data);
if (!blob.data) {
ret = ENOMEM;
goto out;
}
talloc_steal(mem_ctx, blob.data);
- /* TODO: use ndr_pull_struct_blob_all(), when the ndr layer handles it correct with relative pointers */
+ /* we cannot use ndr_pull_struct_blob_all() here, as w2k and w2k3 add padding bytes */
ndr_err = ndr_pull_struct_blob(&blob, mem_ctx, iconv_convenience, &_pkb,
(ndr_pull_flags_fn_t)ndr_pull_package_PrimaryKerberosBlob);
if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
@@ -304,7 +347,68 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context,
entry_ex->entry.keys.len++;
}
- if (pkb3) {
+ if (pkb4) {
+ for (i=0; i < pkb4->num_keys; i++) {
+ bool use = true;
+ Key key;
+
+ if (!pkb4->keys[i].value) continue;
+
+ if (userAccountControl & UF_USE_DES_KEY_ONLY) {
+ switch (pkb4->keys[i].keytype) {
+ case ENCTYPE_DES_CBC_CRC:
+ case ENCTYPE_DES_CBC_MD5:
+ break;
+ default:
+ use = false;
+ break;
+ }
+ }
+
+ if (!use) continue;
+
+ key.mkvno = 0;
+ key.salt = NULL;
+
+ if (pkb4->salt.string) {
+ DATA_BLOB salt;
+
+ salt = data_blob_string_const(pkb4->salt.string);
+
+ key.salt = calloc(1, sizeof(*key.salt));
+ if (key.salt == NULL) {
+ ret = ENOMEM;
+ goto out;
+ }
+
+ key.salt->type = hdb_pw_salt;
+
+ ret = krb5_data_copy(&key.salt->salt, salt.data, salt.length);
+ if (ret) {
+ free(key.salt);
+ key.salt = NULL;
+ goto out;
+ }
+ }
+
+ ret = krb5_keyblock_init(context,
+ pkb4->keys[i].keytype,
+ pkb4->keys[i].value->data,
+ pkb4->keys[i].value->length,
+ &key.key);
+ if (ret) {
+ if (key.salt) {
+ free_Salt(key.salt);
+ free(key.salt);
+ key.salt = NULL;
+ }
+ goto out;
+ }
+
+ entry_ex->entry.keys.val[entry_ex->entry.keys.len] = key;
+ entry_ex->entry.keys.len++;
+ }
+ } else if (pkb3) {
for (i=0; i < pkb3->num_keys; i++) {
bool use = true;
Key key;
@@ -325,6 +429,7 @@ static krb5_error_code LDB_message2entry_keys(krb5_context context,
if (!use) continue;
key.mkvno = 0;
+ key.salt = NULL;
if (pkb3->salt.string) {
DATA_BLOB salt;
diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c
index 9c189feb11..b3f639dc67 100644
--- a/source4/lib/ldb/ldb_map/ldb_map.c
+++ b/source4/lib/ldb/ldb_map/ldb_map.c
@@ -810,6 +810,7 @@ static struct ldb_val map_objectclass_convert_remote(struct ldb_module *module,
/* Generate a local message with a mapped objectClass. */
static struct ldb_message_element *map_objectclass_generate_local(struct ldb_module *module, void *mem_ctx, const char *local_attr, const struct ldb_message *remote)
{
+ const struct ldb_map_context *data = map_get_context(module);
struct ldb_message_element *el, *oc;
struct ldb_val val;
int i;
@@ -844,10 +845,10 @@ static struct ldb_message_element *map_objectclass_generate_local(struct ldb_mod
el->values[i] = map_objectclass_convert_remote(module, el->values, &oc->values[i]);
}
- val.data = (uint8_t *)talloc_strdup(el->values, "extensibleObject");
+ val.data = (uint8_t *)talloc_strdup(el->values, data->add_objectclass);
val.length = strlen((char *)val.data);
- /* Remove last value if it was "extensibleObject" */
+ /* Remove last value if it was the string in data->add_objectclass (eg samba4top, extensibleObject) */
if (ldb_val_equal_exact(&val, &el->values[i-1])) {
el->num_values--;
el->values = talloc_realloc(el, el->values, struct ldb_val, el->num_values);
diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py
index 0dc514aeaf..042469602c 100755
--- a/source4/lib/ldb/tests/python/ldap.py
+++ b/source4/lib/ldb/tests/python/ldap.py
@@ -579,7 +579,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
self.assertEquals(str(res[0].dn), ("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
- time.sleep(2)
+ time.sleep(4)
print "Testing ldb.search for (&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group)) to check subtree renames and linked attributes"
res = ldb.search(self.base_dn, expression="(&(member=CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn + ")(objectclass=group))", scope=SCOPE_SUBTREE)
@@ -835,7 +835,7 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
ldb.delete(("CN=ldaptestuser2,CN=Users," + self.base_dn))
- time.sleep(2)
+ time.sleep(4)
attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"]
print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group)) to check linked delete"
diff --git a/source4/libnet/libnet_become_dc.c b/source4/libnet/libnet_become_dc.c
index 3fece1a9ba..1ce067c321 100644
--- a/source4/libnet/libnet_become_dc.c
+++ b/source4/libnet/libnet_become_dc.c
@@ -1516,13 +1516,30 @@ static void becomeDC_drsuapi_connect_send(struct libnet_BecomeDC_state *s,
drsuapi->s = s;
if (!drsuapi->binding) {
- if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc", "print", false)) {
- binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,print,seal]", s->source_dsa.dns_name);
- if (composite_nomem(binding_str, c)) return;
- } else {
- binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[krb5,seal]", s->source_dsa.dns_name);
- if (composite_nomem(binding_str, c)) return;
+ char *krb5_str = "";
+ char *print_str = "";
+ /*
+ * Note: Replication only works with Windows 2000 when 'krb5' is
+ * passed as auth_type here. If NTLMSSP is used, Windows
+ * 2000 returns garbage in the DsGetNCChanges() response
+ * if encrypted password attributes would be in the response.
+ * That means the replication of the schema and configuration
+ * partition works fine, but it fails for the domain partition.
+ */
+ if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc",
+ "force krb5", true))
+ {
+ krb5_str = "krb5,";
+ }
+ if (lp_parm_bool(s->libnet->lp_ctx, NULL, "become_dc",
+ "print", false))
+ {
+ print_str = "print,";
}
+ binding_str = talloc_asprintf(s, "ncacn_ip_tcp:%s[%s%sseal]",
+ s->source_dsa.dns_name,
+ krb5_str, print_str);
+ if (composite_nomem(binding_str, c)) return;
c->status = dcerpc_parse_binding(s, binding_str, &drsuapi->binding);
talloc_free(binding_str);
if (!composite_is_ok(c)) return;
@@ -1602,12 +1619,7 @@ static void becomeDC_drsuapi_bind_send(struct libnet_BecomeDC_state *s,
bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
#endif
bind_info28->site_guid = s->dest_dsa.site_guid;
- if (s->domain.behavior_version == 2) {
- /* TODO: find out how this is really triggered! */
- bind_info28->u1 = 528;
- } else {
- bind_info28->u1 = 516;
- }
+ bind_info28->pid = 0;
bind_info28->repl_epoch = 0;
drsuapi->bind_info_ctr.length = 28;
@@ -1636,10 +1648,19 @@ static WERROR becomeDC_drsuapi_bind_recv(struct libnet_BecomeDC_state *s,
info24 = &drsuapi->bind_r.out.bind_info->info.info24;
drsuapi->remote_info28.supported_extensions = info24->supported_extensions;
drsuapi->remote_info28.site_guid = info24->site_guid;
- drsuapi->remote_info28.u1 = info24->u1;
+ drsuapi->remote_info28.pid = info24->pid;
drsuapi->remote_info28.repl_epoch = 0;
break;
}
+ case 48: {
+ struct drsuapi_DsBindInfo48 *info48;
+ info48 = &drsuapi->bind_r.out.bind_info->info.info48;
+ drsuapi->remote_info28.supported_extensions = info48->supported_extensions;
+ drsuapi->remote_info28.site_guid = info48->site_guid;
+ drsuapi->remote_info28.pid = info48->pid;
+ drsuapi->remote_info28.repl_epoch = info48->repl_epoch;
+ break;
+ }
case 28:
drsuapi->remote_info28 = drsuapi->bind_r.out.bind_info->info.info28;
break;
@@ -2083,7 +2104,7 @@ static void becomeDC_drsuapi1_add_entry_send(struct libnet_BecomeDC_state *s)
vd[0] = data_blob_talloc(vd, NULL, 4);
if (composite_nomem(vd[0].data, c)) return;
- SIVAL(vd[0].data, 0, DS_BEHAVIOR_WIN2003);
+ SIVAL(vd[0].data, 0, DS_BEHAVIOR_WIN2008);
vs[0].blob = &vd[0];
diff --git a/source4/libnet/libnet_samsync_ldb.c b/source4/libnet/libnet_samsync_ldb.c
index b223a74a31..c72aef7d70 100644
--- a/source4/libnet/libnet_samsync_ldb.c
+++ b/source4/libnet/libnet_samsync_ldb.c
@@ -198,7 +198,7 @@ static NTSTATUS samsync_ldb_handle_domain(TALLOC_CTX *mem_ctx,
}
samdb_msg_add_string(state->sam_ldb, mem_ctx,
- msg, "oEMInformation", domain->comment.string);
+ msg, "oEMInformation", domain->oem_information.string);
samdb_msg_add_int64(state->sam_ldb, mem_ctx,
msg, "forceLogoff", domain->force_logoff_time);
diff --git a/source4/libnet/libnet_unbecome_dc.c b/source4/libnet/libnet_unbecome_dc.c
index cff919018a..6a42fa2370 100644
--- a/source4/libnet/libnet_unbecome_dc.c
+++ b/source4/libnet/libnet_unbecome_dc.c
@@ -574,7 +574,7 @@ static void unbecomeDC_drsuapi_bind_send(struct libnet_UnbecomeDC_state *s)
bind_info28 = &s->drsuapi.local_info28;
bind_info28->supported_extensions = 0;
bind_info28->site_guid = GUID_zero();
- bind_info28->u1 = 508;
+ bind_info28->pid = 0;
bind_info28->repl_epoch = 0;
s->drsuapi.bind_info_ctr.length = 28;
@@ -612,10 +612,19 @@ static void unbecomeDC_drsuapi_bind_recv(struct rpc_request *req)
info24 = &s->drsuapi.bind_r.out.bind_info->info.info24;
s->drsuapi.remote_info28.supported_extensions = info24->supported_extensions;
s->drsuapi.remote_info28.site_guid = info24->site_guid;
- s->drsuapi.remote_info28.u1 = info24->u1;
+ s->drsuapi.remote_info28.pid = info24->pid;
s->drsuapi.remote_info28.repl_epoch = 0;
break;
}
+ case 48: {
+ struct drsuapi_DsBindInfo48 *info48;
+ info48 = &s->drsuapi.bind_r.out.bind_info->info.info48;
+ s->drsuapi.remote_info28.supported_extensions = info48->supported_extensions;
+ s->drsuapi.remote_info28.site_guid = info48->site_guid;
+ s->drsuapi.remote_info28.pid = info48->pid;
+ s->drsuapi.remote_info28.repl_epoch = info48->repl_epoch;
+ break;
+ }
case 28:
s->drsuapi.remote_info28 = s->drsuapi.bind_r.out.bind_info->info.info28;
break;
diff --git a/source4/librpc/idl/drsblobs.idl b/source4/librpc/idl/drsblobs.idl
index f8cbdac8c5..c876ae7fed 100644
--- a/source4/librpc/idl/drsblobs.idl
+++ b/source4/librpc/idl/drsblobs.idl
@@ -205,7 +205,7 @@ interface drsblobs {
typedef struct {
[value(2*strlen_m(name))] uint16 name_len;
[value(strlen(data))] uint16 data_len;
- uint16 unknown1; /* 2 for name = 'Packages', 1 for name = 'Primary:*' */
+ uint16 reserved; /* 2 for 'Packages', 1 for 'Primary:*', but should be ignored */
[charset(UTF16)] uint8 name[name_len];
/*
* the data field contains data as HEX strings
@@ -215,6 +215,9 @@ interface drsblobs {
* as non termiated UTF16 strings with
* a UTF16 NULL byte as separator
*
+ * 'Primary:Kerberos-Newer-Keys':
+ * ...
+ *
* 'Primary:Kerberos':
* ...
*
@@ -228,11 +231,16 @@ interface drsblobs {
[charset(DOS)] uint8 data[data_len];
} supplementalCredentialsPackage;
- /* this are 0x30 (48) whitespaces (0x20) followed by 'P' (0x50) */
- const string SUPPLEMENTAL_CREDENTIALS_PREFIX = " P";
+ /* this are 0x30 (48) whitespaces (0x20) */
+ const string SUPPLEMENTAL_CREDENTIALS_PREFIX = " ";
+
+ typedef [flag(NDR_PAHEX)] enum {
+ SUPPLEMENTAL_CREDENTIALS_SIGNATURE = 0x0050
+ } supplementalCredentialsSignature;
typedef [gensize] struct {
- [value(SUPPLEMENTAL_CREDENTIALS_PREFIX),charset(UTF16)] uint16 prefix[0x31];
+ [value(SUPPLEMENTAL_CREDENTIALS_PREFIX),charset(UTF16)] uint16 prefix[0x30];
+ [value(SUPPLEMENTAL_CREDENTIALS_SIGNATURE)] supplementalCredentialsSignature signature;
uint16 num_packages;
supplementalCredentialsPackage packages[num_packages];
} supplementalCredentialsSubBlob;
@@ -264,23 +272,25 @@ interface drsblobs {
} package_PrimaryKerberosString;
typedef struct {
+ [value(0)] uint16 reserved1;
+ [value(0)] uint16 reserved2;
+ [value(0)] uint32 reserved3;
uint32 keytype;
[value((value?value->length:0))] uint32 value_len;
[relative,subcontext(0),subcontext_size(value_len),flag(NDR_REMAINING)] DATA_BLOB *value;
- [value(0)] uint32 unknown1;
- [value(0)] uint32 unknown2;
} package_PrimaryKerberosKey;
typedef struct {
uint16 num_keys;
uint16 num_old_keys;
package_PrimaryKerberosString salt;
- [value(0)] uint32 unknown1;
- [value(0)] uint32 unknown2;
package_PrimaryKerberosKey keys[num_keys];
package_PrimaryKerberosKey old_keys[num_old_keys];
- udlong unknown3[num_keys];
- udlong unknown3_old[num_old_keys];
+ [value(0)] uint32 padding1;
+ [value(0)] uint32 padding2;
+ [value(0)] uint32 padding3;
+ [value(0)] uint32 padding4;
+ [value(0)] uint32 padding5;
} package_PrimaryKerberosCtr3;
typedef [nodiscriminant] union {
@@ -296,6 +306,40 @@ interface drsblobs {
[in] package_PrimaryKerberosBlob blob
);
+ typedef struct {
+ [value(0)] uint32 unknown1;
+ [value(0)] uint32 unknown2;
+ [value(0x00001000)] uint32 unknown3; /* could the the iterator for the AES key creation */
+ uint32 keytype;
+ [value((value?value->length:0))] uint32 value_len;
+ [relative,subcontext(0),subcontext_size(value_len),flag(NDR_REMAINING)] DATA_BLOB *value;
+ } package_PrimaryKerberosNewerKey;
+
+ typedef struct {
+ uint16 num_keys;
+ [value(0)] uint16 unknown1;
+ uint16 num_old_keys1;
+ uint16 num_old_keys2;
+ package_PrimaryKerberosString salt;
+ [value(0x00001000)] uint32 unknown2; /* could the the iterator for the AES key creation */
+ package_PrimaryKerberosNewerKey keys[num_keys];
+ package_PrimaryKerberosNewerKey old_keys1[num_old_keys1];
+ package_PrimaryKerberosNewerKey old_keys2[num_old_keys2];
+ } package_PrimaryKerberosNewerCtr4;
+
+ typedef [nodiscriminant] union {
+ [case(4)] package_PrimaryKerberosNewerCtr4 ctr4;
+ } package_PrimaryKerberosNewerCtr;
+
+ typedef [public] struct {
+ [value(4)] uint32 version;
+ [switch_is(version)] package_PrimaryKerberosNewerCtr ctr;
+ } package_PrimaryKerberosNewerBlob;
+
+ void decode_PrimaryKerberosNewer(
+ [in] package_PrimaryKerberosNewerBlob blob
+ );
+
typedef [public] struct {
[flag(STR_NOTERM|NDR_REMAINING)] string cleartext;
} package_PrimaryCLEARTEXTBlob;
diff --git a/source4/librpc/idl/drsuapi.idl b/source4/librpc/idl/drsuapi.idl
index b9cff5d11d..c19da4fa19 100644
--- a/source4/librpc/idl/drsuapi.idl
+++ b/source4/librpc/idl/drsuapi.idl
@@ -58,21 +58,36 @@ interface drsuapi
DRSUAPI_SUPPORTED_EXTENSION_80000000 = 0x80000000
} drsuapi_SupportedExtensions;
+ typedef [bitmap32bit] bitmap {
+ DRSUAPI_SUPPORTED_EXTENSION_ADAM = 0x00000001,
+ DRSUAPI_SUPPORTED_EXTENSION_LH_BETA2 = 0x00000002
+ } drsuapi_SupportedExtensionsExt;
+
/* this is used by w2k */
typedef struct {
drsuapi_SupportedExtensions supported_extensions;
GUID site_guid;
- uint32 u1;
+ uint32 pid;
} drsuapi_DsBindInfo24;
/* this is used by w2k3 */
typedef struct {
drsuapi_SupportedExtensions supported_extensions;
GUID site_guid;
- uint32 u1;
+ uint32 pid;
uint32 repl_epoch;
} drsuapi_DsBindInfo28;
+ /* this is used by w2k8 */
+ typedef struct {
+ drsuapi_SupportedExtensions supported_extensions;
+ GUID site_guid;
+ uint32 pid;
+ uint32 repl_epoch;
+ drsuapi_SupportedExtensionsExt supported_extensions_ext;
+ GUID config_dn_guid;
+ } drsuapi_DsBindInfo48;
+
typedef struct {
[flag(NDR_REMAINING)] DATA_BLOB info;
} drsuapi_DsBindInfoFallBack;
@@ -80,6 +95,7 @@ interface drsuapi
typedef [nodiscriminant] union {
[case(24)][subcontext(4)] drsuapi_DsBindInfo24 info24;
[case(28)][subcontext(4)] drsuapi_DsBindInfo28 info28;
+ [case(48)][subcontext(4)] drsuapi_DsBindInfo48 info48;
[default][subcontext(4)] drsuapi_DsBindInfoFallBack FallBack;
} drsuapi_DsBindInfo;
@@ -1409,7 +1425,7 @@ interface drsuapi
GUID bind_guid;
NTTIME_1sec bind_time;
[flag(NDR_BIG_ENDIAN)] ipv4address client_ip_address;
- uint32 u5; /* this is the same value the client used as u1 in the DsBindInfoX struct */
+ uint32 u5; /* this is the same value the client used as pid in the DsBindInfoX struct */
} drsuapi_DsReplicaConnection04;
typedef struct {
diff --git a/source4/librpc/idl/netlogon.idl b/source4/librpc/idl/netlogon.idl
index 6da496a486..d8f7d2f7e6 100644
--- a/source4/librpc/idl/netlogon.idl
+++ b/source4/librpc/idl/netlogon.idl
@@ -403,7 +403,7 @@ interface netlogon
typedef struct {
lsa_String domain_name;
- lsa_String comment;
+ lsa_String oem_information; /* comment */
dlong force_logoff_time;
uint16 min_password_length;
uint16 password_history_length;
diff --git a/source4/librpc/idl/samr.idl b/source4/librpc/idl/samr.idl
index 3a11ab752c..b6cce38196 100644
--- a/source4/librpc/idl/samr.idl
+++ b/source4/librpc/idl/samr.idl
@@ -208,7 +208,7 @@ import "misc.idl", "lsa.idl", "security.idl";
typedef struct {
NTTIME force_logoff_time;
- lsa_String comment;
+ lsa_String oem_information; /* comment */
lsa_String domain_name;
lsa_String primary; /* PDC name if this is a BDC */
udlong sequence_num;
@@ -218,15 +218,15 @@ import "misc.idl", "lsa.idl", "security.idl";
uint32 num_users;
uint32 num_groups;
uint32 num_aliases;
- } samr_DomInfo2;
+ } samr_DomGeneralInformation;
typedef struct {
NTTIME force_logoff_time;
} samr_DomInfo3;
typedef struct {
- lsa_String comment;
- } samr_DomInfo4;
+ lsa_String oem_information; /* comment */
+ } samr_DomOEMInformation;
typedef struct {
lsa_String domain_name;
@@ -250,11 +250,11 @@ import "misc.idl", "lsa.idl", "security.idl";
} samr_DomInfo9;
typedef struct {
- samr_DomInfo2 info2;
+ samr_DomGeneralInformation general;
hyper lockout_duration;
hyper lockout_window;
uint16 lockout_threshold;
- } samr_DomInfo11;
+ } samr_DomGeneralInformation2;
typedef struct {
hyper lockout_duration;
@@ -271,15 +271,15 @@ import "misc.idl", "lsa.idl", "security.idl";
typedef [switch_type(uint16)] union {
[case(1)] samr_DomInfo1 info1;
- [case(2)] samr_DomInfo2 info2;
+ [case(2)] samr_DomGeneralInformation general;
[case(3)] samr_DomInfo3 info3;
- [case(4)] samr_DomInfo4 info4;
+ [case(4)] samr_DomOEMInformation oem;
[case(5)] samr_DomInfo5 info5;
[case(6)] samr_DomInfo6 info6;
[case(7)] samr_DomInfo7 info7;
[case(8)] samr_DomInfo8 info8;
[case(9)] samr_DomInfo9 info9;
- [case(11)] samr_DomInfo11 info11;
+ [case(11)] samr_DomGeneralInformation2 general2;
[case(12)] samr_DomInfo12 info12;
[case(13)] samr_DomInfo13 info13;
} samr_DomainInfo;
diff --git a/source4/librpc/rpc/dcerpc_util.c b/source4/librpc/rpc/dcerpc_util.c
index 71c6d5f2cc..32646e85b0 100644
--- a/source4/librpc/rpc/dcerpc_util.c
+++ b/source4/librpc/rpc/dcerpc_util.c
@@ -647,11 +647,21 @@ NTSTATUS dcerpc_generic_session_key(struct dcerpc_connection *c,
/*
fetch the user session key - may be default (above) or the SMB session key
+
+ The key is always truncated to 16 bytes
*/
_PUBLIC_ NTSTATUS dcerpc_fetch_session_key(struct dcerpc_pipe *p,
- DATA_BLOB *session_key)
+ DATA_BLOB *session_key)
{
- return p->conn->security_state.session_key(p->conn, session_key);
+ NTSTATUS status;
+ status = p->conn->security_state.session_key(p->conn, session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ session_key->length = MIN(session_key->length, 16);
+
+ return NT_STATUS_OK;
}
diff --git a/source4/pidl/lib/Parse/Pidl/Expr.pm b/source4/pidl/lib/Parse/Pidl/Expr.pm
index 4e02be0575..5524374fae 100644
--- a/source4/pidl/lib/Parse/Pidl/Expr.pm
+++ b/source4/pidl/lib/Parse/Pidl/Expr.pm
@@ -1127,7 +1127,7 @@ sub new {
[#Rule 2
'exp', 1,
sub
-#line 22 "pidl/expr.yp"
+#line 22 "./pidl/expr.yp"
{ "\"$_[1]\"" }
],
[#Rule 3
@@ -1139,199 +1139,199 @@ sub
[#Rule 5
'exp', 2,
sub
-#line 25 "pidl/expr.yp"
+#line 25 "./pidl/expr.yp"
{ "~$_[2]" }
],
[#Rule 6
'exp', 3,
sub
-#line 26 "pidl/expr.yp"
+#line 26 "./pidl/expr.yp"
{ "$_[1] + $_[3]" }
],
[#Rule 7
'exp', 3,
sub
-#line 27 "pidl/expr.yp"
+#line 27 "./pidl/expr.yp"
{ "$_[1] - $_[3]" }
],
[#Rule 8
'exp', 3,
sub
-#line 28 "pidl/expr.yp"
+#line 28 "./pidl/expr.yp"
{ "$_[1] * $_[3]" }
],
[#Rule 9
'exp', 3,
sub
-#line 29 "pidl/expr.yp"
+#line 29 "./pidl/expr.yp"
{ "$_[1] % $_[3]" }
],
[#Rule 10
'exp', 3,
sub
-#line 30 "pidl/expr.yp"
+#line 30 "./pidl/expr.yp"
{ "$_[1] < $_[3]" }
],
[#Rule 11
'exp', 3,
sub
-#line 31 "pidl/expr.yp"
+#line 31 "./pidl/expr.yp"
{ "$_[1] > $_[3]" }
],
[#Rule 12
'exp', 3,
sub
-#line 32 "pidl/expr.yp"
+#line 32 "./pidl/expr.yp"
{ "$_[1] | $_[3]" }
],
[#Rule 13
'exp', 3,
sub
-#line 33 "pidl/expr.yp"
+#line 33 "./pidl/expr.yp"
{ "$_[1] == $_[3]" }
],
[#Rule 14
'exp', 3,
sub
-#line 34 "pidl/expr.yp"
+#line 34 "./pidl/expr.yp"
{ "$_[1] <= $_[3]" }
],
[#Rule 15
'exp', 3,
sub
-#line 35 "pidl/expr.yp"
+#line 35 "./pidl/expr.yp"
{ "$_[1] => $_[3]" }
],
[#Rule 16
'exp', 3,
sub
-#line 36 "pidl/expr.yp"
+#line 36 "./pidl/expr.yp"
{ "$_[1] << $_[3]" }
],
[#Rule 17
'exp', 3,
sub
-#line 37 "pidl/expr.yp"
+#line 37 "./pidl/expr.yp"
{ "$_[1] >> $_[3]" }
],
[#Rule 18
'exp', 3,
sub
-#line 38 "pidl/expr.yp"
+#line 38 "./pidl/expr.yp"
{ "$_[1] != $_[3]" }
],
[#Rule 19
'exp', 3,
sub
-#line 39 "pidl/expr.yp"
+#line 39 "./pidl/expr.yp"
{ "$_[1] || $_[3]" }
],
[#Rule 20
'exp', 3,
sub
-#line 40 "pidl/expr.yp"
+#line 40 "./pidl/expr.yp"
{ "$_[1] && $_[3]" }
],
[#Rule 21
'exp', 3,
sub
-#line 41 "pidl/expr.yp"
+#line 41 "./pidl/expr.yp"
{ "$_[1] & $_[3]" }
],
[#Rule 22
'exp', 5,
sub
-#line 42 "pidl/expr.yp"
+#line 42 "./pidl/expr.yp"
{ "$_[1]?$_[3]:$_[5]" }
],
[#Rule 23
'exp', 2,
sub
-#line 43 "pidl/expr.yp"
+#line 43 "./pidl/expr.yp"
{ "~$_[1]" }
],
[#Rule 24
'exp', 2,
sub
-#line 44 "pidl/expr.yp"
+#line 44 "./pidl/expr.yp"
{ "not $_[1]" }
],
[#Rule 25
'exp', 3,
sub
-#line 45 "pidl/expr.yp"
+#line 45 "./pidl/expr.yp"
{ "$_[1] / $_[3]" }
],
[#Rule 26
'exp', 2,
sub
-#line 46 "pidl/expr.yp"
+#line 46 "./pidl/expr.yp"
{ "-$_[2]" }
],
[#Rule 27
'exp', 2,
sub
-#line 47 "pidl/expr.yp"
+#line 47 "./pidl/expr.yp"
{ "&$_[2]" }
],
[#Rule 28
'exp', 3,
sub
-#line 48 "pidl/expr.yp"
+#line 48 "./pidl/expr.yp"
{ "$_[1]^$_[3]" }
],
[#Rule 29
'exp', 3,
sub
-#line 49 "pidl/expr.yp"
+#line 49 "./pidl/expr.yp"
{ "($_[2])" }
],
[#Rule 30
'possible_pointer', 1,
sub
-#line 53 "pidl/expr.yp"
+#line 53 "./pidl/expr.yp"
{ $_[0]->_Lookup($_[1]) }
],
[#Rule 31
'possible_pointer', 2,
sub
-#line 54 "pidl/expr.yp"
+#line 54 "./pidl/expr.yp"
{ $_[0]->_Dereference($_[2]); "*$_[2]" }
],
[#Rule 32
'var', 1,
sub
-#line 57 "pidl/expr.yp"
+#line 57 "./pidl/expr.yp"
{ $_[0]->_Use($_[1]) }
],
[#Rule 33
'var', 3,
sub
-#line 58 "pidl/expr.yp"
+#line 58 "./pidl/expr.yp"
{ $_[0]->_Use("$_[1].$_[3]") }
],
[#Rule 34
'var', 3,
sub
-#line 59 "pidl/expr.yp"
+#line 59 "./pidl/expr.yp"
{ "($_[2])" }
],
[#Rule 35
'var', 3,
sub
-#line 60 "pidl/expr.yp"
+#line 60 "./pidl/expr.yp"
{ $_[0]->_Use("*$_[1]"); $_[1]."->".$_[3] }
],
[#Rule 36
'func', 4,
sub
-#line 64 "pidl/expr.yp"
+#line 64 "./pidl/expr.yp"
{ "$_[1]($_[3])" }
],
[#Rule 37
'opt_args', 0,
sub
-#line 65 "pidl/expr.yp"
+#line 65 "./pidl/expr.yp"
{ "" }
],
[#Rule 38
@@ -1349,7 +1349,7 @@ sub
[#Rule 42
'args', 3,
sub
-#line 68 "pidl/expr.yp"
+#line 68 "./pidl/expr.yp"
{ "$_[1], $_[3]" }
]
],
@@ -1357,7 +1357,7 @@ sub
bless($self,$class);
}
-#line 71 "pidl/expr.yp"
+#line 71 "./pidl/expr.yp"
package Parse::Pidl::Expr;
diff --git a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm
index 87ed29b54e..d2ab407eb0 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba3/ClientNDR.pm
@@ -153,7 +153,6 @@ sub ParseFunction($$$)
$self->pidl("");
$self->pidl("status = cli_do_rpc_ndr(cli,");
$self->pidl("\t\t\tmem_ctx,");
- $self->pidl("\t\t\tPI_$uif,");
$self->pidl("\t\t\t&ndr_table_$if,");
$self->pidl("\t\t\t$ufn,");
$self->pidl("\t\t\t&r);");
diff --git a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
index 0d1806a0fa..a0de1f127a 100644
--- a/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
+++ b/source4/pidl/lib/Parse/Pidl/Samba4/NDR/Parser.pm
@@ -770,7 +770,7 @@ sub ParseElementPrint($$$$)
} else {
my $counter = "cntr_$e->{NAME}_$l->{LEVEL_INDEX}";
- $self->pidl("ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", $length);");
+ $self->pidl("ndr->print(ndr, \"\%s: ARRAY(\%d)\", \"$e->{NAME}\", (int)$length);");
$self->pidl("ndr->depth++;");
$self->pidl("for ($counter=0;$counter<$length;$counter++) {");
$self->indent;
diff --git a/source4/rpc_server/dcerpc_server.c b/source4/rpc_server/dcerpc_server.c
index d8dafd61f6..ac36825acd 100644
--- a/source4/rpc_server/dcerpc_server.c
+++ b/source4/rpc_server/dcerpc_server.c
@@ -270,11 +270,20 @@ NTSTATUS dcesrv_generic_session_key(struct dcesrv_connection *p,
/*
fetch the user session key - may be default (above) or the SMB session key
+
+ The key is always truncated to 16 bytes
*/
_PUBLIC_ NTSTATUS dcesrv_fetch_session_key(struct dcesrv_connection *p,
DATA_BLOB *session_key)
{
- return p->auth_state.session_key(p, session_key);
+ NTSTATUS status = p->auth_state.session_key(p, session_key);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ session_key->length = MIN(session_key->length, 16);
+
+ return NT_STATUS_OK;
}
@@ -534,7 +543,18 @@ static NTSTATUS dcesrv_bind(struct dcesrv_call_state *call)
uint32_t context_id;
const struct dcesrv_interface *iface;
- if (call->pkt.u.bind.assoc_group_id != 0) {
+ /*
+ * Association groups allow policy handles to be shared across
+ * multiple client connections. We don't implement this yet.
+ *
+ * So we just allow 0 if the client wants to create a new
+ * association group.
+ *
+ * And we allow the 0x12345678 value, we give away as
+ * assoc_group_id back to the clients
+ */
+ if (call->pkt.u.bind.assoc_group_id != 0 &&
+ call->pkt.u.bind.assoc_group_id != 0x12345678) {
return dcesrv_bind_nak(call, 0);
}
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index e0a222e767..bbb78cb778 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -45,7 +45,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
struct ldb_result *ntds_res;
struct ldb_dn *ntds_dn;
static const char *ntds_attrs[] = { "ms-DS-ReplicationEpoch", NULL };
- uint32_t u1;
+ uint32_t pid;
uint32_t repl_epoch;
int ret;
@@ -98,9 +98,12 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
repl_epoch = samdb_result_uint(ntds_res->msgs[0], "ms-DS-ReplicationEpoch", 0);
/*
- * TODO: find out what this is...
+ * The "process identifier" of the client.
+ * According to the WSPP docs, sectin 5.35, this is
+ * for informational and debugging purposes only.
+ * The assignment is implementation specific.
*/
- u1 = 0;
+ pid = 0;
/*
* store the clients bind_guid
@@ -119,7 +122,7 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
info24 = &r->in.bind_info->info.info24;
b_state->remote_info28.supported_extensions = info24->supported_extensions;
b_state->remote_info28.site_guid = info24->site_guid;
- b_state->remote_info28.u1 = info24->u1;
+ b_state->remote_info28.pid = info24->pid;
b_state->remote_info28.repl_epoch = 0;
break;
}
@@ -171,8 +174,8 @@ static WERROR dcesrv_drsuapi_DsBind(struct dcesrv_call_state *dce_call, TALLOC_C
b_state->local_info28.supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
#endif
b_state->local_info28.site_guid = site_guid;
- b_state->local_info28.u1 = u1;
- b_state->local_info28.repl_epoch = repl_epoch;
+ b_state->local_info28.pid = pid;
+ b_state->local_info28.repl_epoch = repl_epoch;
/*
* allocate the return bind_info
diff --git a/source4/rpc_server/lsa/dcesrv_lsa.c b/source4/rpc_server/lsa/dcesrv_lsa.c
index eb60f426d8..f02e2325a0 100644
--- a/source4/rpc_server/lsa/dcesrv_lsa.c
+++ b/source4/rpc_server/lsa/dcesrv_lsa.c
@@ -1130,9 +1130,6 @@ static NTSTATUS dcesrv_lsa_EnumTrustDom(struct dcesrv_call_state *dce_call, TALL
if (count == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- if (count == 0 || r->in.max_size == 0) {
- return NT_STATUS_OK;
- }
/* convert to lsa_TrustInformation format */
entries = talloc_array(mem_ctx, struct lsa_DomainInfo, count);
@@ -1218,9 +1215,6 @@ static NTSTATUS dcesrv_lsa_EnumTrustedDomainsEx(struct dcesrv_call_state *dce_ca
if (count == -1) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- if (count == 0 || r->in.max_size == 0) {
- return NT_STATUS_OK;
- }
/* convert to lsa_DomainInformation format */
entries = talloc_array(mem_ctx, struct lsa_TrustDomainInfoInfoEx, count);
diff --git a/source4/rpc_server/samr/dcesrv_samr.c b/source4/rpc_server/samr/dcesrv_samr.c
index 8ee77a6a30..e54d518f76 100644
--- a/source4/rpc_server/samr/dcesrv_samr.c
+++ b/source4/rpc_server/samr/dcesrv_samr.c
@@ -521,10 +521,10 @@ static NTSTATUS dcesrv_samr_info_DomInfo1(struct samr_domain_state *state,
/*
return DomInfo2
*/
-static NTSTATUS dcesrv_samr_info_DomInfo2(struct samr_domain_state *state,
- TALLOC_CTX *mem_ctx,
- struct ldb_message **dom_msgs,
- struct samr_DomInfo2 *info)
+static NTSTATUS dcesrv_samr_info_DomGeneralInformation(struct samr_domain_state *state,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message **dom_msgs,
+ struct samr_DomGeneralInformation *info)
{
/* This pulls the NetBIOS name from the
cn=NTDS Settings,cn=<NETBIOS name of PDC>,....
@@ -538,7 +538,7 @@ static NTSTATUS dcesrv_samr_info_DomInfo2(struct samr_domain_state *state,
info->force_logoff_time = ldb_msg_find_attr_as_uint64(dom_msgs[0], "forceLogoff",
0x8000000000000000LL);
- info->comment.string = samdb_result_string(dom_msgs[0], "comment", NULL);
+ info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL);
info->domain_name.string = state->domain_name;
info->sequence_num = ldb_msg_find_attr_as_uint64(dom_msgs[0], "modifiedCount",
@@ -592,12 +592,12 @@ static NTSTATUS dcesrv_samr_info_DomInfo3(struct samr_domain_state *state,
/*
return DomInfo4
*/
-static NTSTATUS dcesrv_samr_info_DomInfo4(struct samr_domain_state *state,
+static NTSTATUS dcesrv_samr_info_DomOEMInformation(struct samr_domain_state *state,
TALLOC_CTX *mem_ctx,
struct ldb_message **dom_msgs,
- struct samr_DomInfo4 *info)
+ struct samr_DomOEMInformation *info)
{
- info->comment.string = samdb_result_string(dom_msgs[0], "comment", NULL);
+ info->oem_information.string = samdb_result_string(dom_msgs[0], "oEMInformation", NULL);
return NT_STATUS_OK;
}
@@ -700,13 +700,13 @@ static NTSTATUS dcesrv_samr_info_DomInfo9(struct samr_domain_state *state,
/*
return DomInfo11
*/
-static NTSTATUS dcesrv_samr_info_DomInfo11(struct samr_domain_state *state,
+static NTSTATUS dcesrv_samr_info_DomGeneralInformation2(struct samr_domain_state *state,
TALLOC_CTX *mem_ctx,
struct ldb_message **dom_msgs,
- struct samr_DomInfo11 *info)
+ struct samr_DomGeneralInformation2 *info)
{
NTSTATUS status;
- status = dcesrv_samr_info_DomInfo2(state, mem_ctx, dom_msgs, &info->info2);
+ status = dcesrv_samr_info_DomGeneralInformation(state, mem_ctx, dom_msgs, &info->general);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
@@ -792,7 +792,7 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call,
case 2:
{
static const char * const attrs2[] = {"forceLogoff",
- "comment",
+ "oEMInformation",
"modifiedCount",
"fSMORoleOwner",
NULL};
@@ -808,7 +808,7 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call,
}
case 4:
{
- static const char * const attrs2[] = {"comment",
+ static const char * const attrs2[] = {"oEMInformation",
NULL};
attrs = attrs2;
break;
@@ -843,7 +843,7 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call,
break;
case 11:
{
- static const char * const attrs2[] = { "comment", "forceLogoff",
+ static const char * const attrs2[] = { "oEMInformation", "forceLogoff",
"modifiedCount",
"lockoutDuration",
"lockOutObservationWindow",
@@ -886,42 +886,42 @@ static NTSTATUS dcesrv_samr_QueryDomainInfo(struct dcesrv_call_state *dce_call,
switch (r->in.level) {
case 1:
return dcesrv_samr_info_DomInfo1(d_state, mem_ctx, dom_msgs,
- &r->out.info->info1);
+ &r->out.info->info1);
case 2:
- return dcesrv_samr_info_DomInfo2(d_state, mem_ctx, dom_msgs,
- &r->out.info->info2);
+ return dcesrv_samr_info_DomGeneralInformation(d_state, mem_ctx, dom_msgs,
+ &r->out.info->general);
case 3:
return dcesrv_samr_info_DomInfo3(d_state, mem_ctx, dom_msgs,
- &r->out.info->info3);
+ &r->out.info->info3);
case 4:
- return dcesrv_samr_info_DomInfo4(d_state, mem_ctx, dom_msgs,
- &r->out.info->info4);
+ return dcesrv_samr_info_DomOEMInformation(d_state, mem_ctx, dom_msgs,
+ &r->out.info->oem);
case 5:
return dcesrv_samr_info_DomInfo5(d_state, mem_ctx, dom_msgs,
- &r->out.info->info5);
+ &r->out.info->info5);
case 6:
return dcesrv_samr_info_DomInfo6(d_state, mem_ctx, dom_msgs,
- &r->out.info->info6);
+ &r->out.info->info6);
case 7:
return dcesrv_samr_info_DomInfo7(d_state, mem_ctx, dom_msgs,
- &r->out.info->info7);
+ &r->out.info->info7);
case 8:
return dcesrv_samr_info_DomInfo8(d_state, mem_ctx, dom_msgs,
- &r->out.info->info8);
+ &r->out.info->info8);
case 9:
return dcesrv_samr_info_DomInfo9(d_state, mem_ctx, dom_msgs,
- &r->out.info->info9);
+ &r->out.info->info9);
case 11:
- return dcesrv_samr_info_DomInfo11(d_state, mem_ctx, dom_msgs,
- &r->out.info->info11);
+ return dcesrv_samr_info_DomGeneralInformation2(d_state, mem_ctx, dom_msgs,
+ &r->out.info->general2);
case 12:
return dcesrv_samr_info_DomInfo12(d_state, mem_ctx, dom_msgs,
- &r->out.info->info12);
+ &r->out.info->info12);
case 13:
return dcesrv_samr_info_DomInfo13(d_state, mem_ctx, dom_msgs,
- &r->out.info->info13);
+ &r->out.info->info13);
}
-
+
return NT_STATUS_INVALID_INFO_CLASS;
}
@@ -962,10 +962,10 @@ static NTSTATUS dcesrv_samr_SetDomainInfo(struct dcesrv_call_state *dce_call, TA
SET_INT64 (msg, info1.min_password_age, "minPwdAge");
break;
case 3:
- SET_UINT64 (msg, info3.force_logoff_time, "forceLogoff");
+ SET_UINT64 (msg, info3.force_logoff_time, "forceLogoff");
break;
case 4:
- SET_STRING(msg, info4.comment, "comment");
+ SET_STRING(msg, oem.oem_information, "oEMInformation");
break;
case 6:
@@ -2997,7 +2997,7 @@ static NTSTATUS dcesrv_samr_QueryUserInfo(struct dcesrv_call_state *dce_call, TA
case 1:
{
static const char * const attrs2[] = {"sAMAccountName", "displayName",
- "primaryGroupID", "description",
+ "primaryroupID", "description",
"comment", NULL};
attrs = attrs2;
break;
diff --git a/source4/scripting/python/samba/provision.py b/source4/scripting/python/samba/provision.py
index 6eb47c8595..4b310381ef 100644
--- a/source4/scripting/python/samba/provision.py
+++ b/source4/scripting/python/samba/provision.py
@@ -244,6 +244,7 @@ def provision_paths_from_lp(lp, dnsdomain):
paths.templates = os.path.join(paths.private_dir, "templates.ldb")
paths.dns = os.path.join(paths.private_dir, dnsdomain + ".zone")
paths.namedconf = os.path.join(paths.private_dir, "named.conf")
+ paths.namedtxt = os.path.join(paths.private_dir, "named.txt")
paths.krb5conf = os.path.join(paths.private_dir, "krb5.conf")
paths.winsdb = os.path.join(paths.private_dir, "wins.ldb")
paths.s4_ldapi_path = os.path.join(paths.private_dir, "ldapi")
@@ -1043,6 +1044,7 @@ def provision(setup_dir, message, session_info,
policy_path = os.path.join(paths.sysvol, names.dnsdomain, "Policies",
"{" + policyguid + "}")
os.makedirs(policy_path, 0755)
+ open(os.path.join(policy_path, "GPT.INI"), 'w').write("")
os.makedirs(os.path.join(policy_path, "Machine"), 0755)
os.makedirs(os.path.join(policy_path, "User"), 0755)
if not os.path.isdir(paths.netlogon):
@@ -1081,12 +1083,15 @@ def provision(setup_dir, message, session_info,
hostip6=hostip6, hostname=names.hostname,
dnspass=dnspass, realm=names.realm,
domainguid=domainguid, hostguid=hostguid)
- message("Please install the zone located in %s into your DNS server" % paths.dns)
create_named_conf(paths.namedconf, setup_path, realm=names.realm,
+ dnsdomain=names.dnsdomain, private_dir=paths.private_dir)
+
+ create_named_txt(paths.namedtxt, setup_path, realm=names.realm,
dnsdomain=names.dnsdomain, private_dir=paths.private_dir,
keytab_name=paths.dns_keytab)
- message("See %s for example configuration statements for secure GSS-TSIG updates" % paths.namedconf)
+ message("See %s for an example configuration include file for BIND" % paths.namedconf)
+ message("and %s for further documentation required for secure DNS updates" % paths.namedtxt)
create_krb5_conf(paths.krb5conf, setup_path, dnsdomain=names.dnsdomain,
hostname=names.hostname, realm=names.realm)
@@ -1376,7 +1381,7 @@ def create_zone_file(path, setup_path, dnsdomain, domaindn,
def create_named_conf(path, setup_path, realm, dnsdomain,
- private_dir, keytab_name):
+ private_dir):
"""Write out a file containing zone statements suitable for inclusion in a
named.conf file (including GSS-TSIG configuration).
@@ -1392,8 +1397,28 @@ def create_named_conf(path, setup_path, realm, dnsdomain,
"DNSDOMAIN": dnsdomain,
"REALM": realm,
"REALM_WC": "*." + ".".join(realm.split(".")[1:]),
+ "PRIVATE_DIR": private_dir
+ })
+
+def create_named_txt(path, setup_path, realm, dnsdomain,
+ private_dir, keytab_name):
+ """Write out a file containing zone statements suitable for inclusion in a
+ named.conf file (including GSS-TSIG configuration).
+
+ :param path: Path of the new named.conf file.
+ :param setup_path: Setup path function.
+ :param realm: Realm name
+ :param dnsdomain: DNS Domain name
+ :param private_dir: Path to private directory
+ :param keytab_name: File name of DNS keytab file
+ """
+
+ setup_file(setup_path("named.txt"), path, {
+ "DNSDOMAIN": dnsdomain,
+ "REALM": realm,
"DNS_KEYTAB": keytab_name,
"DNS_KEYTAB_ABS": os.path.join(private_dir, keytab_name),
+ "PRIVATE_DIR": private_dir
})
def create_krb5_conf(path, setup_path, dnsdomain, hostname, realm):
diff --git a/source4/setup/named.conf b/source4/setup/named.conf
index 4f98bbd914..0b087069c7 100644
--- a/source4/setup/named.conf
+++ b/source4/setup/named.conf
@@ -1,12 +1,15 @@
+# This file should be included in your main BIND configuration file
#
-# Insert these snippets into your named.conf or bind.conf to configure
-# the BIND nameserver.
-#
+# For example with
+# include "${PRIVATE_DIR}/named.conf";
-# You should always include the actual forward zone configuration:
zone "${DNSDOMAIN}." IN {
type master;
- file "${DNSDOMAIN}.zone";
+ file "${PRIVATE_DIR}/${DNSDOMAIN}.zone";
+ /*
+ * Attention: Not all BIND versions support "ms-self". The instead use
+ * of allow-update { any; }; is another, but less secure possibility.
+ */
update-policy {
/*
* A rather long description here, as the "ms-self" option does
@@ -44,6 +47,8 @@ zone "${DNSDOMAIN}." IN {
# The reverse zone configuration is optional. The following example assumes a
# subnet of 192.168.123.0/24:
+
+/*
zone "123.168.192.in-addr.arpa" in {
type master;
file "123.168.192.in-addr.arpa.zone";
@@ -51,54 +56,12 @@ zone "123.168.192.in-addr.arpa" in {
grant ${REALM_WC} wildcard *.123.168.192.in-addr.arpa. PTR;
};
};
+*/
+
# Note that the reverse zone file is not created during the provision process.
-# The most recent BIND version (9.5.0a5 or later) supports secure GSS-TSIG
+# The most recent BIND versions (9.5.0a5 or later) support secure GSS-TSIG
# updates. If you are running an earlier version of BIND, or if you do not wish
# to use secure GSS-TSIG updates, you may remove the update-policy sections in
# both examples above.
-# If you are running a capable version of BIND and you wish to support secure
-# GSS-TSIG updates, you must make the following configuration changes:
-
-# - Insert the following lines into the options {} section of your named.conf
-# file:
-tkey-gssapi-credential "DNS/${DNSDOMAIN}";
-tkey-domain "${REALM}";
-
-# - Modify BIND init scripts to pass the location of the generated keytab file.
-# Fedora 8 & later provide a variable named KEYTAB_FILE in /etc/sysconfig/named
-# for this purpose:
-KEYTAB_FILE="${DNS_KEYTAB_ABS}"
-# Note that the Fedora scripts translate KEYTAB_FILE behind the scenes into a
-# variable named KRB5_KTNAME, which is ultimately passed to the BIND daemon. If
-# your distribution does not provide a variable like KEYTAB_FILE to pass a
-# keytab file to the BIND daemon, a workaround is to place the following line in
-# BIND's sysconfig file or in the init script for BIND:
-export KRB5_KTNAME="${DNS_KEYTAB_ABS}"
-
-# - Set appropriate ownership and permissions on the ${DNS_KEYTAB} file. Note
-# that most distributions have BIND configured to run under a non-root user
-# account. For example, Fedora 9 runs BIND as the user "named" once the daemon
-# relinquishes its rights. Therefore, the file ${DNS_KEYTAB} must be readable
-# by the user that BIND run as. If BIND is running as a non-root user, the
-# "${DNS_KEYTAB}" file must have its permissions altered to allow the daemon to
-# read it. Under Fedora 9, execute the following commands:
-chgrp named ${DNS_KEYTAB_ABS}
-chmod g+r ${DNS_KEYTAB_ABS}
-
-# - Ensure the BIND zone file(s) that will be dynamically updated are in a
-# directory where the BIND daemon can write. When BIND performs dynamic
-# updates, it not only needs to update the zone file itself but it must also
-# create a journal (.jnl) file to track the dynamic updates as they occur.
-# Under Fedora 9, the /var/named directory can not be written to by the "named"
-# user. However, the directory /var/named/dynamic directory does provide write
-# access. Therefore the zone files were placed under the /var/named/dynamic
-# directory. The file directives in both example zone statements at the
-# beginning of this file were changed by prepending the directory "dynamic/".
-
-# - If SELinux is enabled, ensure that all files have the appropriate SELinux
-# file contexts. The ${DNS_KEYTAB} file must be accessible by the BIND daemon
-# and should have a SELinux type of named_conf_t. This can be set with the
-# following command:
-chcon -t named_conf_t ${DNS_KEYTAB_ABS}
diff --git a/source4/setup/named.txt b/source4/setup/named.txt
new file mode 100644
index 0000000000..c1e6b3a9ee
--- /dev/null
+++ b/source4/setup/named.txt
@@ -0,0 +1,46 @@
+# Additional informations for DNS setup using BIND
+
+# If you are running a capable version of BIND and you wish to support secure
+# GSS-TSIG updates, you must make the following configuration changes:
+
+# - Insert the following lines into the options {} section of your named.conf
+# file:
+tkey-gssapi-credential "DNS/${DNSDOMAIN}";
+tkey-domain "${REALM}";
+
+# - Modify BIND init scripts to pass the location of the generated keytab file.
+# Fedora 8 & later provide a variable named KEYTAB_FILE in /etc/sysconfig/named
+# for this purpose:
+KEYTAB_FILE="${DNS_KEYTAB_ABS}"
+# Note that the Fedora scripts translate KEYTAB_FILE behind the scenes into a
+# variable named KRB5_KTNAME, which is ultimately passed to the BIND daemon. If
+# your distribution does not provide a variable like KEYTAB_FILE to pass a
+# keytab file to the BIND daemon, a workaround is to place the following line in
+# BIND's sysconfig file or in the init script for BIND:
+export KRB5_KTNAME="${DNS_KEYTAB_ABS}"
+
+# - Set appropriate ownership and permissions on the ${DNS_KEYTAB} file. Note
+# that most distributions have BIND configured to run under a non-root user
+# account. For example, Fedora 9 runs BIND as the user "named" once the daemon
+# relinquishes its rights. Therefore, the file ${DNS_KEYTAB} must be readable
+# by the user that BIND run as. If BIND is running as a non-root user, the
+# "${DNS_KEYTAB}" file must have its permissions altered to allow the daemon to
+# read it. Under Fedora 9, execute the following commands:
+chgrp named ${DNS_KEYTAB_ABS}
+chmod g+r ${DNS_KEYTAB_ABS}
+
+# - Ensure the BIND zone file(s) that will be dynamically updated are in a
+# directory where the BIND daemon can write. When BIND performs dynamic
+# updates, it not only needs to update the zone file itself but it must also
+# create a journal (.jnl) file to track the dynamic updates as they occur.
+# Under Fedora 9, the /var/named directory can not be written to by the "named"
+# user. However, the directory /var/named/dynamic directory does provide write
+# access. Therefore the zone files were placed under the /var/named/dynamic
+# directory. The file directives in both example zone statements at the
+# beginning of this file were changed by prepending the directory "dynamic/".
+
+# - If SELinux is enabled, ensure that all files have the appropriate SELinux
+# file contexts. The ${DNS_KEYTAB} file must be accessible by the BIND daemon
+# and should have a SELinux type of named_conf_t. This can be set with the
+# following command:
+chcon -t named_conf_t ${DNS_KEYTAB_ABS}
diff --git a/source4/setup/provision.zone b/source4/setup/provision.zone
index 28c1c29762..17ae3bb47a 100644
--- a/source4/setup/provision.zone
+++ b/source4/setup/provision.zone
@@ -14,10 +14,12 @@ ${HOSTIP6_BASE_LINE}
;
${HOSTIP6_HOST_LINE}
${HOSTNAME} IN A ${HOSTIP}
-${HOSTGUID}._msdcs IN CNAME ${HOSTNAME}
+gc._msdcs IN CNAME ${HOSTNAME}
+${HOSTGUID}._msdcs IN CNAME ${HOSTNAME}
;
; global catalog servers
_gc._tcp IN SRV 0 100 3268 ${HOSTNAME}
+_gc._tcp.${DEFAULTSITE}._sites IN SRV 0 100 3268 ${HOSTNAME}
_ldap._tcp.gc._msdcs IN SRV 0 100 389 ${HOSTNAME}
_ldap._tcp.${DEFAULTSITE}._sites.gc._msdcs IN SRV 0 100 389 ${HOSTNAME}
;
@@ -25,12 +27,15 @@ _ldap._tcp.${DEFAULTSITE}._sites.gc._msdcs IN SRV 0 100 389 ${HOSTNAME}
_ldap._tcp IN SRV 0 100 389 ${HOSTNAME}
_ldap._tcp.dc._msdcs IN SRV 0 100 389 ${HOSTNAME}
_ldap._tcp.pdc._msdcs IN SRV 0 100 389 ${HOSTNAME}
+_ldap._tcp.${DOMAINGUID} IN SRV 0 100 389 ${HOSTNAME}
_ldap._tcp.${DOMAINGUID}.domains._msdcs IN SRV 0 100 389 ${HOSTNAME}
+_ldap._tcp.${DEFAULTSITE}._sites IN SRV 0 100 389 ${HOSTNAME}
_ldap._tcp.${DEFAULTSITE}._sites.dc._msdcs IN SRV 0 100 389 ${HOSTNAME}
;
; krb5 servers
_kerberos._tcp IN SRV 0 100 88 ${HOSTNAME}
_kerberos._tcp.dc._msdcs IN SRV 0 100 88 ${HOSTNAME}
+_kerberos._tcp.${DEFAULTSITE}._sites IN SRV 0 100 88 ${HOSTNAME}
_kerberos._tcp.${DEFAULTSITE}._sites.dc._msdcs IN SRV 0 100 88 ${HOSTNAME}
_kerberos._udp IN SRV 0 100 88 ${HOSTNAME}
; MIT kpasswd likes to lookup this name on password change
diff --git a/source4/setup/schema_samba4.ldif b/source4/setup/schema_samba4.ldif
index 21d17c5caa..3e129e4f6b 100644
--- a/source4/setup/schema_samba4.ldif
+++ b/source4/setup/schema_samba4.ldif
@@ -3,9 +3,15 @@
#
## Samba4 OID allocation from Samba3's examples/LDAP/samba.schema
## 1.3.6.1.4.1.7165.4.1.x - attributetypes
+
## 1.3.6.1.4.1.7165.4.2.x - objectclasses
+
## 1.3.6.1.4.1.7165.4.3.x - LDB/LDAP Controls
+### see dsdb/samdb/samdb.h
+
## 1.3.6.1.4.1.7165.4.4.x - LDB/LDAP Extended Operations
+### see dsdb/samdb/samdb.h
+
## 1.3.6.1.4.1.7165.4.255.x - mapped OIDs due to conflicts between AD and standards-track
#
#
diff --git a/source4/setup/slapd.conf b/source4/setup/slapd.conf
index 495847f7fe..4dcfd2aba7 100644
--- a/source4/setup/slapd.conf
+++ b/source4/setup/slapd.conf
@@ -32,6 +32,7 @@ access to dn.subtree="cn=samba"
access to dn.subtree="${DOMAINDN}"
by dn=cn=samba-admin,cn=samba manage
+ by dn=cn=manager manage
by * none
password-hash {CLEARTEXT}
@@ -40,6 +41,8 @@ include ${LDAPDIR}/modules.conf
defaultsearchbase ${DOMAINDN}
+rootdn cn=Manager
+
${REFINT_CONFIG}
${MEMBEROF_CONFIG}
@@ -47,6 +50,7 @@ ${MEMBEROF_CONFIG}
database ldif
suffix cn=Samba
directory ${LDAPDIR}/db/samba
+rootdn cn=Manager,cn=Samba
database hdb
diff --git a/source4/torture/rpc/dssync.c b/source4/torture/rpc/dssync.c
index 053f78e99b..2930a9b1f9 100644
--- a/source4/torture/rpc/dssync.c
+++ b/source4/torture/rpc/dssync.c
@@ -23,6 +23,7 @@
#include "includes.h"
#include "lib/cmdline/popt_common.h"
#include "librpc/gen_ndr/ndr_drsuapi_c.h"
+#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "libcli/cldap/cldap.h"
#include "libcli/ldap/ldap_client.h"
#include "torture/torture.h"
@@ -104,7 +105,7 @@ static struct DsSyncTest *test_create_context(struct torture_context *tctx)
our_bind_info28->supported_extensions = 0xFFFFFFFF;
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_ADDENTRYREPLY_V3;
our_bind_info28->site_guid = GUID_zero();
- our_bind_info28->u1 = 0;
+ our_bind_info28->pid = 0;
our_bind_info28->repl_epoch = 1;
our_bind_info_ctr = &ctx->admin.drsuapi.our_bind_info_ctr;
@@ -153,7 +154,7 @@ static struct DsSyncTest *test_create_context(struct torture_context *tctx)
our_bind_info28->supported_extensions |= DRSUAPI_SUPPORTED_EXTENSION_XPRESS_COMPRESS;
}
our_bind_info28->site_guid = GUID_zero();
- our_bind_info28->u1 = 508;
+ our_bind_info28->pid = 0;
our_bind_info28->repl_epoch = 0;
our_bind_info_ctr = &ctx->new_dc.drsuapi.our_bind_info_ctr;
@@ -210,13 +211,25 @@ static bool _test_DsBind(struct torture_context *tctx,
info24 = &b->req.out.bind_info->info.info24;
b->peer_bind_info28.supported_extensions= info24->supported_extensions;
b->peer_bind_info28.site_guid = info24->site_guid;
- b->peer_bind_info28.u1 = info24->u1;
+ b->peer_bind_info28.pid = info24->pid;
b->peer_bind_info28.repl_epoch = 0;
break;
}
+ case 48: {
+ struct drsuapi_DsBindInfo48 *info48;
+ info48 = &b->req.out.bind_info->info.info48;
+ b->peer_bind_info28.supported_extensions= info48->supported_extensions;
+ b->peer_bind_info28.site_guid = info48->site_guid;
+ b->peer_bind_info28.pid = info48->pid;
+ b->peer_bind_info28.repl_epoch = info48->repl_epoch;
+ break;
+ }
case 28:
b->peer_bind_info28 = b->req.out.bind_info->info.info28;
break;
+ default:
+ printf("DsBind - warning: unknown BindInfo length: %u\n",
+ b->req.out.bind_info->length);
}
}
@@ -514,6 +527,8 @@ static void test_analyse_objects(struct torture_context *tctx,
DEBUGADD(0,("ATTR: %s enc.length=%lu plain.length=%lu\n",
name, (long)enc_data->length, (long)plain_data.length));
if (plain_data.length) {
+ enum ndr_err_code ndr_err;
+ struct supplementalCredentialsBlob scb;
dump_data(0, plain_data.data, plain_data.length);
if (save_values_dir) {
char *fname;
@@ -529,6 +544,13 @@ static void test_analyse_objects(struct torture_context *tctx,
}
talloc_free(fname);
}
+
+ ndr_err = ndr_pull_struct_blob_all(&plain_data, tctx,
+ lp_iconv_convenience(tctx->lp_ctx), &scb,
+ (ndr_pull_flags_fn_t)ndr_pull_supplementalCredentialsBlob);
+ if (NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ NDR_PRINT_DEBUG(supplementalCredentialsBlob, &scb);
+ }
} else {
dump_data(0, enc_data->data, enc_data->length);
}
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index a4e702f759..e6102f0a82 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -1822,6 +1822,19 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
printf("\nTesting EnumTrustDom\n");
+ r.in.handle = handle;
+ r.in.resume_handle = &resume_handle;
+ r.in.max_size = 0;
+ r.out.domains = &domains;
+ r.out.resume_handle = &resume_handle;
+
+ enum_status = dcerpc_lsa_EnumTrustDom(p, mem_ctx, &r);
+
+ if (!(NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES) || NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES))) {
+ printf("EnumTrustDom of zero size failed - %s\n", nt_errstr(enum_status));
+ return false;
+ }
+
do {
r.in.handle = handle;
r.in.resume_handle = &resume_handle;
@@ -1848,12 +1861,30 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
return false;
}
+ if (domains.count == 0) {
+ printf("EnumTrustDom failed - should have returned 'NT_STATUS_NO_MORE_ENTRIES' for 0 trusted domains\n");
+ return false;
+ }
+
ret &= test_query_each_TrustDom(p, mem_ctx, handle, &domains);
} while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)));
printf("\nTesting EnumTrustedDomainsEx\n");
+ r_ex.in.handle = handle;
+ r_ex.in.resume_handle = &resume_handle;
+ r_ex.in.max_size = LSA_ENUM_TRUST_DOMAIN_EX_MULTIPLIER * 3;
+ r_ex.out.domains = &domains_ex;
+ r_ex.out.resume_handle = &resume_handle;
+
+ enum_status = dcerpc_lsa_EnumTrustedDomainsEx(p, mem_ctx, &r_ex);
+
+ if (!(NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES) || NT_STATUS_EQUAL(enum_status, NT_STATUS_NO_MORE_ENTRIES))) {
+ printf("EnumTrustedDomainEx of zero size failed - %s\n", nt_errstr(enum_status));
+ return false;
+ }
+
resume_handle = 0;
do {
r_ex.in.handle = handle;
@@ -1884,6 +1915,11 @@ static bool test_EnumTrustDom(struct dcerpc_pipe *p,
return false;
}
+ if (domains_ex.count == 0) {
+ printf("EnumTrustDomainEx failed - should have returned 'NT_STATUS_NO_MORE_ENTRIES' for 0 trusted domains\n");
+ return false;
+ }
+
ret &= test_query_each_TrustDomEx(p, mem_ctx, handle, &domains_ex);
} while ((NT_STATUS_EQUAL(enum_status, STATUS_MORE_ENTRIES)));
@@ -1906,6 +1942,10 @@ static bool test_CreateTrustedDomain(struct dcerpc_pipe *p,
printf("Testing CreateTrustedDomain for 12 domains\n");
+ if (!test_EnumTrustDom(p, mem_ctx, handle)) {
+ ret = false;
+ }
+
for (i=0; i< 12; i++) {
char *trust_name = talloc_asprintf(mem_ctx, "torturedom%02d", i);
char *trust_sid = talloc_asprintf(mem_ctx, "S-1-5-21-97398-379795-100%02d", i);
diff --git a/source4/torture/rpc/samr.c b/source4/torture/rpc/samr.c
index 55c75ba270..6afda6e9b5 100644
--- a/source4/torture/rpc/samr.c
+++ b/source4/torture/rpc/samr.c
@@ -3595,17 +3595,17 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
switch (r.in.level) {
case 1:
case 4:
- if (dom_info.out.info->info2.num_users < r.in.start_idx) {
+ if (dom_info.out.info->general.num_users < r.in.start_idx) {
printf("QueryDomainInfo indicates that QueryDisplayInfo returned more users (%d/%d) than the domain %s is said to contain!\n",
- r.in.start_idx, dom_info.out.info->info2.num_groups,
- dom_info.out.info->info2.domain_name.string);
+ r.in.start_idx, dom_info.out.info->general.num_groups,
+ dom_info.out.info->general.domain_name.string);
ret = false;
}
if (!seen_testuser) {
struct policy_handle user_handle;
if (NT_STATUS_IS_OK(test_OpenUser_byname(p, mem_ctx, handle, TEST_ACCOUNT_NAME, &user_handle))) {
printf("Didn't find test user " TEST_ACCOUNT_NAME " in enumeration of %s\n",
- dom_info.out.info->info2.domain_name.string);
+ dom_info.out.info->general.domain_name.string);
ret = false;
test_samr_handle_Close(p, mem_ctx, &user_handle);
}
@@ -3613,10 +3613,10 @@ static bool test_QueryDisplayInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
break;
case 3:
case 5:
- if (dom_info.out.info->info2.num_groups != r.in.start_idx) {
+ if (dom_info.out.info->general.num_groups != r.in.start_idx) {
printf("QueryDomainInfo indicates that QueryDisplayInfo didn't return all (%d/%d) the groups in %s\n",
- r.in.start_idx, dom_info.out.info->info2.num_groups,
- dom_info.out.info->info2.domain_name.string);
+ r.in.start_idx, dom_info.out.info->general.num_groups,
+ dom_info.out.info->general.domain_name.string);
ret = false;
}
@@ -3745,7 +3745,7 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
s.in.level = 4;
s.in.info = talloc(mem_ctx, union samr_DomainInfo);
- s.in.info->info4.comment.string = domain_comment;
+ s.in.info->oem.oem_information.string = domain_comment;
status = dcerpc_samr_SetDomainInfo(p, mem_ctx, &s);
if (!NT_STATUS_IS_OK(status)) {
printf("SetDomainInfo level %u (set comment) failed - %s\n",
@@ -3769,26 +3769,26 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
switch (levels[i]) {
case 2:
- if (strcmp(r.out.info->info2.comment.string, domain_comment) != 0) {
- printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
- levels[i], r.out.info->info2.comment.string, domain_comment);
+ if (strcmp(r.out.info->general.oem_information.string, domain_comment) != 0) {
+ printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
+ levels[i], r.out.info->general.oem_information.string, domain_comment);
ret = false;
}
- if (!r.out.info->info2.primary.string) {
+ if (!r.out.info->general.primary.string) {
printf("QueryDomainInfo level %u returned no PDC name\n",
levels[i]);
ret = false;
- } else if (r.out.info->info2.role == SAMR_ROLE_DOMAIN_PDC) {
- if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), r.out.info->info2.primary.string) != 0) {
+ } else if (r.out.info->general.role == SAMR_ROLE_DOMAIN_PDC) {
+ if (dcerpc_server_name(p) && strcasecmp_m(dcerpc_server_name(p), r.out.info->general.primary.string) != 0) {
printf("QueryDomainInfo level %u returned different PDC name (%s) compared to server name (%s), despite claiming to be the PDC\n",
- levels[i], r.out.info->info2.primary.string, dcerpc_server_name(p));
+ levels[i], r.out.info->general.primary.string, dcerpc_server_name(p));
}
}
break;
case 4:
- if (strcmp(r.out.info->info4.comment.string, domain_comment) != 0) {
- printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
- levels[i], r.out.info->info4.comment.string, domain_comment);
+ if (strcmp(r.out.info->oem.oem_information.string, domain_comment) != 0) {
+ printf("QueryDomainInfo level %u returned different oem_information (comment) (%s, expected %s)\n",
+ levels[i], r.out.info->oem.oem_information.string, domain_comment);
ret = false;
}
break;
@@ -3800,9 +3800,9 @@ static bool test_QueryDomainInfo(struct dcerpc_pipe *p, TALLOC_CTX *mem_ctx,
}
break;
case 11:
- if (strcmp(r.out.info->info11.info2.comment.string, domain_comment) != 0) {
+ if (strcmp(r.out.info->general2.general.oem_information.string, domain_comment) != 0) {
printf("QueryDomainInfo level %u returned different comment (%s, expected %s)\n",
- levels[i], r.out.info->info11.info2.comment.string, domain_comment);
+ levels[i], r.out.info->general2.general.oem_information.string, domain_comment);
ret = false;
}
break;
diff --git a/source4/torture/rpc/samsync.c b/source4/torture/rpc/samsync.c
index 7114756460..1e76de1dd2 100644
--- a/source4/torture/rpc/samsync.c
+++ b/source4/torture/rpc/samsync.c
@@ -346,9 +346,9 @@ static bool samsync_handle_domain(TALLOC_CTX *mem_ctx, struct samsync_state *sam
TEST_STRING_EQUAL(q[5].out.info->info5.domain_name, domain->domain_name);
- TEST_STRING_EQUAL(q[2].out.info->info2.comment, domain->comment);
- TEST_STRING_EQUAL(q[4].out.info->info4.comment, domain->comment);
- TEST_TIME_EQUAL(q[2].out.info->info2.force_logoff_time, domain->force_logoff_time);
+ TEST_STRING_EQUAL(q[2].out.info->general.oem_information, domain->oem_information);
+ TEST_STRING_EQUAL(q[4].out.info->oem.oem_information, domain->oem_information);
+ TEST_TIME_EQUAL(q[2].out.info->general.force_logoff_time, domain->force_logoff_time);
TEST_TIME_EQUAL(q[3].out.info->info3.force_logoff_time, domain->force_logoff_time);
TEST_TIME_EQUAL(q[1].out.info->info1.min_password_length, domain->min_password_length);
@@ -1487,7 +1487,7 @@ bool torture_rpc_samsync(struct torture_context *torture)
s.in.level = 4;
s.in.info = talloc(mem_ctx, union samr_DomainInfo);
- s.in.info->info4.comment.string
+ s.in.info->oem.oem_information.string
= talloc_asprintf(mem_ctx,
"Tortured by Samba4: %s",
timestring(mem_ctx, time(NULL)));
diff --git a/source4/winbind/wb_cmd_list_trustdom.c b/source4/winbind/wb_cmd_list_trustdom.c
index 8d0c1bd947..fe98ce2f6a 100644
--- a/source4/winbind/wb_cmd_list_trustdom.c
+++ b/source4/winbind/wb_cmd_list_trustdom.c
@@ -159,7 +159,8 @@ static void cmd_list_trustdoms_recv_doms(struct rpc_request *req)
state->r.out.domains->domains[i].sid);
}
- if (NT_STATUS_IS_OK(state->ctx->status)) {
+ if (NT_STATUS_IS_OK(state->ctx->status) || NT_STATUS_EQUAL(state->ctx->status, NT_STATUS_NO_MORE_ENTRIES)) {
+ state->ctx->status = NT_STATUS_OK;
composite_done(state->ctx);
return;
}