summaryrefslogtreecommitdiff
path: root/source4
diff options
context:
space:
mode:
Diffstat (limited to 'source4')
-rw-r--r--source4/dsdb/common/util.c93
-rw-r--r--source4/dsdb/pydsdb.c27
-rw-r--r--source4/dsdb/repl/drepl_fsmo.c62
-rw-r--r--source4/dsdb/repl/replicated_objects.c27
-rw-r--r--source4/dsdb/samdb/cracknames.c102
-rw-r--r--source4/dsdb/samdb/ldb_modules/rootdse.c37
-rw-r--r--source4/dsdb/schema/schema_info_attr.c75
-rw-r--r--source4/dsdb/schema/schema_init.c15
-rw-r--r--source4/dsdb/schema/schema_prefixmap.c13
-rw-r--r--source4/lib/registry/pyregistry.c47
-rw-r--r--source4/lib/registry/regf.c40
-rw-r--r--source4/lib/registry/regf.idl4
-rw-r--r--source4/libcli/finddcs_cldap.c13
-rw-r--r--source4/libnet/libnet_lookup.c5
-rw-r--r--source4/librpc/idl/winbind.idl5
-rw-r--r--source4/librpc/rpc/pyrpc.h12
-rw-r--r--source4/librpc/rpc/pyrpc_util.c53
-rwxr-xr-xsource4/librpc/wscript_build12
-rw-r--r--source4/rpc_server/drsuapi/dcesrv_drsuapi.c55
-rwxr-xr-xsource4/scripting/bin/samba_dnsupdate87
-rwxr-xr-xsource4/scripting/devel/getncchanges1
-rwxr-xr-xsource4/scripting/devel/ldapcmp14
-rwxr-xr-xsource4/scripting/devel/rodcdns43
-rw-r--r--source4/scripting/python/samba/join.py2
-rw-r--r--source4/scripting/python/samba/samdb.py8
-rw-r--r--source4/torture/basic/base.c4
-rw-r--r--source4/torture/basic/delaywrite.c132
-rw-r--r--source4/torture/basic/delete.c2
-rw-r--r--source4/torture/basic/disconnect.c2
-rw-r--r--source4/torture/config.mk2
-rw-r--r--source4/torture/drs/python/fsmo.py4
-rw-r--r--source4/torture/drs/unit/prefixmap_tests.c9
-rw-r--r--source4/torture/drs/unit/schemainfo_tests.c81
-rw-r--r--source4/torture/gentest.c2
-rw-r--r--source4/torture/libnetapi/config.mk3
-rw-r--r--source4/torture/libnetapi/libnetapi.c1
-rw-r--r--source4/torture/libnetapi/libnetapi_server.c76
-rw-r--r--source4/torture/libnetapi/wscript_build2
-rw-r--r--source4/torture/nbench/nbio.c4
-rw-r--r--source4/torture/nbt/winsreplication.c4
-rw-r--r--source4/torture/ndr/ndr.c1
-rw-r--r--source4/torture/ndr/ntlmssp.c119
-rw-r--r--source4/torture/ndr/winreg.c4
-rw-r--r--source4/torture/raw/notify.c8
-rw-r--r--source4/torture/rpc/handles.c6
-rw-r--r--source4/torture/rpc/lsa.c2
-rw-r--r--source4/torture/rpc/netlogon.c10
-rw-r--r--source4/torture/rpc/svcctl.c63
-rw-r--r--source4/torture/smb2/lease.c2
-rw-r--r--source4/torture/smb2/notify.c8
-rw-r--r--source4/torture/util_smb.c4
-rw-r--r--source4/torture/wscript_build2
-rw-r--r--source4/winbind/wb_irpc.c50
-rw-r--r--source4/winbind/wb_server.h1
-rw-r--r--source4/winbind/wb_update_rodc_dns.c167
-rw-r--r--source4/winbind/wscript_build2
56 files changed, 1356 insertions, 273 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index 0e371082be..a5d7caeefe 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -43,6 +43,7 @@
#include "dsdb/common/util.h"
#include "lib/socket/socket.h"
#include "dsdb/samdb/ldb_modules/util.h"
+#include "librpc/gen_ndr/irpc.h"
/*
search the sam for the specified attributes in a specific domain, filter on
@@ -3982,3 +3983,95 @@ bool dsdb_attr_in_rodc_fas(const struct dsdb_attribute *sa)
/* other attributes are denied */
return false;
}
+
+/* return fsmo role dn and role owner dn for a particular role*/
+WERROR dsdb_get_fsmo_role_info(TALLOC_CTX *tmp_ctx,
+ struct ldb_context *ldb,
+ uint32_t role,
+ struct ldb_dn **fsmo_role_dn,
+ struct ldb_dn **role_owner_dn)
+{
+ int ret;
+ switch (role) {
+ case DREPL_NAMING_MASTER:
+ *fsmo_role_dn = samdb_partitions_dn(ldb, tmp_ctx);
+ ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ case DREPL_INFRASTRUCTURE_MASTER:
+ *fsmo_role_dn = samdb_infrastructure_dn(ldb, tmp_ctx);
+ ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ case DREPL_RID_MASTER:
+ ret = samdb_rid_manager_dn(ldb, tmp_ctx, fsmo_role_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ case DREPL_SCHEMA_MASTER:
+ *fsmo_role_dn = ldb_get_schema_basedn(ldb);
+ ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ case DREPL_PDC_MASTER:
+ *fsmo_role_dn = ldb_get_default_basedn(ldb);
+ ret = samdb_reference_dn(ldb, tmp_ctx, *fsmo_role_dn, "fSMORoleOwner", role_owner_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s",
+ ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ break;
+ default:
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+ return WERR_OK;
+}
+
+const char *samdb_dn_to_dnshostname(struct ldb_context *ldb,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_dn *server_dn)
+{
+ int ldb_ret;
+ struct ldb_result *res = NULL;
+ const char * const attrs[] = { "dNSHostName", NULL};
+
+ ldb_ret = ldb_search(ldb, mem_ctx, &res,
+ server_dn,
+ LDB_SCOPE_BASE,
+ attrs, NULL);
+ if (ldb_ret != LDB_SUCCESS) {
+ DEBUG(4, ("Failed to find dNSHostName for dn %s, ldb error: %s",
+ ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
+ return NULL;
+ }
+
+ return samdb_result_string(res->msgs[0], "dNSHostName", NULL);
+}
diff --git a/source4/dsdb/pydsdb.c b/source4/dsdb/pydsdb.c
index 5ba69d7388..7f2e71550c 100644
--- a/source4/dsdb/pydsdb.c
+++ b/source4/dsdb/pydsdb.c
@@ -534,6 +534,30 @@ static PyObject *py_dsdb_get_partitions_dn(PyObject *self, PyObject *args)
}
+/*
+ call into samdb_rodc()
+ */
+static PyObject *py_dsdb_am_rodc(PyObject *self, PyObject *args)
+{
+ PyObject *py_ldb;
+ struct ldb_context *ldb;
+ int ret;
+ bool am_rodc;
+
+ if (!PyArg_ParseTuple(args, "O", &py_ldb))
+ return NULL;
+
+ PyErr_LDB_OR_RAISE(py_ldb, ldb);
+
+ ret = samdb_rodc(ldb, &am_rodc);
+ if (samdb_rodc(ldb, &am_rodc) != LDB_SUCCESS) {
+ PyErr_SetString(PyExc_RuntimeError, ldb_errstring(ldb));
+ return NULL;
+ }
+
+ return PyBool_FromLong(am_rodc);
+}
+
static PyMethodDef py_dsdb_methods[] = {
{ "_samdb_server_site_name", (PyCFunction)py_samdb_server_site_name,
@@ -573,6 +597,9 @@ static PyMethodDef py_dsdb_methods[] = {
{ "_dsdb_set_am_rodc",
(PyCFunction)py_dsdb_set_am_rodc, METH_VARARGS,
NULL },
+ { "_am_rodc",
+ (PyCFunction)py_dsdb_am_rodc, METH_VARARGS,
+ NULL },
{ "_dsdb_set_schema_from_ldif", (PyCFunction)py_dsdb_set_schema_from_ldif, METH_VARARGS,
NULL },
{ "_dsdb_set_schema_from_ldb", (PyCFunction)py_dsdb_set_schema_from_ldb, METH_VARARGS,
diff --git a/source4/dsdb/repl/drepl_fsmo.c b/source4/dsdb/repl/drepl_fsmo.c
index 375e37b517..ad655f77b9 100644
--- a/source4/dsdb/repl/drepl_fsmo.c
+++ b/source4/dsdb/repl/drepl_fsmo.c
@@ -6,6 +6,7 @@
Copyright (C) Nadezhda Ivanova 2010
Copyright (C) Andrew Tridgell 2010
Copyright (C) Andrew Bartlett 2010
+ Copyright (C) Anatoliy Atanasov 2010
based on drepl_ridalloc.c
@@ -62,76 +63,31 @@ WERROR dreplsrv_fsmo_role_check(struct dreplsrv_service *service,
{
struct ldb_dn *role_owner_dn, *fsmo_role_dn, *ntds_dn;
TALLOC_CTX *tmp_ctx = talloc_new(service);
- struct ldb_context *ldb = service->samdb;
- int ret;
uint64_t fsmo_info = 0;
enum drsuapi_DsExtendedOperation extended_op = DRSUAPI_EXOP_NONE;
WERROR werr;
- ntds_dn = samdb_ntds_settings_dn(ldb);
+ ntds_dn = samdb_ntds_settings_dn(service->samdb);
if (!ntds_dn) {
return WERR_DS_DRA_INTERNAL_ERROR;
}
+ werr = dsdb_get_fsmo_role_info(tmp_ctx, service->samdb, role,
+ &fsmo_role_dn, &role_owner_dn);
+ if (!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+
switch (role) {
case DREPL_NAMING_MASTER:
- fsmo_role_dn = samdb_partitions_dn(ldb, tmp_ctx),
- ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn);
- if (ret != LDB_SUCCESS) {
- DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Naming Master object - %s",
- ldb_errstring(ldb)));
- talloc_free(tmp_ctx);
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
- break;
case DREPL_INFRASTRUCTURE_MASTER:
- fsmo_role_dn = samdb_infrastructure_dn(ldb, tmp_ctx);
- ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn);
- if (ret != LDB_SUCCESS) {
- DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
- ldb_errstring(ldb)));
- talloc_free(tmp_ctx);
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
+ case DREPL_SCHEMA_MASTER:
extended_op = DRSUAPI_EXOP_FSMO_REQ_ROLE;
break;
case DREPL_RID_MASTER:
- ret = samdb_rid_manager_dn(ldb, tmp_ctx, &fsmo_role_dn);
- if (ret != LDB_SUCCESS) {
- DEBUG(0, (__location__ ": Failed to find RID Manager object - %s", ldb_errstring(ldb)));
- talloc_free(tmp_ctx);
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
-
- ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn);
- if (ret != LDB_SUCCESS) {
- DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in RID Manager object - %s",
- ldb_errstring(ldb)));
- talloc_free(tmp_ctx);
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
extended_op = DRSUAPI_EXOP_FSMO_RID_REQ_ROLE;
break;
- case DREPL_SCHEMA_MASTER:
- fsmo_role_dn = ldb_get_schema_basedn(ldb);
- ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn);
- if (ret != LDB_SUCCESS) {
- DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Schema Master object - %s",
- ldb_errstring(ldb)));
- talloc_free(tmp_ctx);
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
- extended_op = DRSUAPI_EXOP_FSMO_REQ_ROLE;
- break;
case DREPL_PDC_MASTER:
- fsmo_role_dn = ldb_get_default_basedn(ldb);
- ret = samdb_reference_dn(ldb, tmp_ctx, fsmo_role_dn, "fSMORoleOwner", &role_owner_dn);
- if (ret != LDB_SUCCESS) {
- DEBUG(0,(__location__ ": Failed to find fSMORoleOwner in Pd Master object - %s",
- ldb_errstring(ldb)));
- talloc_free(tmp_ctx);
- return WERR_DS_DRA_INTERNAL_ERROR;
- }
extended_op = DRSUAPI_EXOP_FSMO_REQ_PDC;
break;
default:
diff --git a/source4/dsdb/repl/replicated_objects.c b/source4/dsdb/repl/replicated_objects.c
index 838dc84655..0beb53c2f3 100644
--- a/source4/dsdb/repl/replicated_objects.c
+++ b/source4/dsdb/repl/replicated_objects.c
@@ -197,7 +197,7 @@ WERROR dsdb_convert_object_ex(struct ldb_context *ldb,
}
WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb,
- const char *partition_dn,
+ const char *partition_dn_str,
const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr,
uint32_t object_count,
const struct drsuapi_DsReplicaObjectListItemEx *first_object,
@@ -210,6 +210,7 @@ WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb,
struct dsdb_extended_replicated_objects **objects)
{
WERROR status;
+ struct ldb_dn *partition_dn;
const struct dsdb_schema *schema;
struct dsdb_extended_replicated_objects *out;
const struct drsuapi_DsReplicaObjectListItemEx *cur;
@@ -226,14 +227,24 @@ WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb,
return WERR_DS_SCHEMA_NOT_LOADED;
}
- status = dsdb_schema_pfm_contains_drsuapi_pfm(schema->prefixmap, mapping_ctr);
- if (!W_ERROR_IS_OK(status)) {
- talloc_free(out);
- return status;
+ partition_dn = ldb_dn_new(out, ldb, partition_dn_str);
+ W_ERROR_HAVE_NO_MEMORY_AND_FREE(partition_dn, out);
+
+ if (ldb_dn_compare(partition_dn, ldb_get_schema_basedn(ldb)) != 0) {
+ /*
+ * check for schema changes in case
+ * we are not replicating Schema NC
+ */
+ status = dsdb_schema_info_cmp(schema, mapping_ctr);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(1,("Remote schema has changed while replicating %s\n",
+ partition_dn_str));
+ talloc_free(out);
+ return status;
+ }
}
- out->partition_dn = ldb_dn_new(out, ldb, partition_dn);
- W_ERROR_HAVE_NO_MEMORY(out->partition_dn);
+ out->partition_dn = partition_dn;
out->source_dsa = source_dsa;
out->uptodateness_vector= uptodateness_vector;
@@ -242,7 +253,7 @@ WERROR dsdb_extended_replicated_objects_convert(struct ldb_context *ldb,
out->objects = talloc_array(out,
struct dsdb_extended_replicated_object,
out->num_objects);
- W_ERROR_HAVE_NO_MEMORY(out->objects);
+ W_ERROR_HAVE_NO_MEMORY_AND_FREE(out->objects, out);
/* pass the linked attributes down to the repl_meta_data
module */
diff --git a/source4/dsdb/samdb/cracknames.c b/source4/dsdb/samdb/cracknames.c
index 63fe34552d..e642984171 100644
--- a/source4/dsdb/samdb/cracknames.c
+++ b/source4/dsdb/samdb/cracknames.c
@@ -39,12 +39,14 @@
static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
struct smb_krb5_context *smb_krb5_context,
- uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
+ enum drsuapi_DsNameFormat format_desired,
struct ldb_dn *name_dn, const char *name,
const char *domain_filter, const char *result_filter,
struct drsuapi_DsNameInfo1 *info1);
static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
- uint32_t format_offered, uint32_t format_desired,
+ enum drsuapi_DsNameFormat format_offered,
+ enum drsuapi_DsNameFormat format_desired,
struct ldb_dn *name_dn, const char *name,
struct drsuapi_DsNameInfo1 *info1);
@@ -177,7 +179,8 @@ static enum drsuapi_DsNameStatus LDB_lookup_spn_alias(krb5_context context, stru
static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
struct smb_krb5_context *smb_krb5_context,
- uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
+ enum drsuapi_DsNameFormat format_desired,
const char *name, struct drsuapi_DsNameInfo1 *info1)
{
WERROR wret;
@@ -262,7 +265,8 @@ static WERROR DsCrackNameSPNAlias(struct ldb_context *sam_ctx, TALLOC_CTX *mem_c
static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
struct smb_krb5_context *smb_krb5_context,
- uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
+ enum drsuapi_DsNameFormat format_desired,
const char *name, struct drsuapi_DsNameInfo1 *info1)
{
int ldb_ret;
@@ -348,7 +352,8 @@ static WERROR DsCrackNameUPN(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
/* Crack a single 'name', from format_offered into format_desired, returning the result in info1 */
WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
- uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
+ enum drsuapi_DsNameFormat format_desired,
const char *name, struct drsuapi_DsNameInfo1 *info1)
{
krb5_error_code ret;
@@ -678,7 +683,8 @@ WERROR DsCrackNameOneName(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
* database */
static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
- uint32_t format_offered, uint32_t format_desired,
+ enum drsuapi_DsNameFormat format_offered,
+ enum drsuapi_DsNameFormat format_desired,
struct ldb_dn *name_dn, const char *name,
struct drsuapi_DsNameInfo1 *info1)
{
@@ -717,7 +723,8 @@ static WERROR DsCrackNameOneSyntactical(TALLOC_CTX *mem_ctx,
static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
struct smb_krb5_context *smb_krb5_context,
- uint32_t format_flags, uint32_t format_offered, uint32_t format_desired,
+ uint32_t format_flags, enum drsuapi_DsNameFormat format_offered,
+ enum drsuapi_DsNameFormat format_desired,
struct ldb_dn *name_dn, const char *name,
const char *domain_filter, const char *result_filter,
struct drsuapi_DsNameInfo1 *info1)
@@ -872,6 +879,8 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
return DsCrackNameUPN(sam_ctx, mem_ctx, smb_krb5_context,
format_flags, format_offered, format_desired,
name, info1);
+ default:
+ break;
}
info1->status = DRSUAPI_DS_NAME_STATUS_NOT_FOUND;
return WERR_OK;
@@ -894,6 +903,8 @@ static WERROR DsCrackNameOneFilter(struct ldb_context *sam_ctx, TALLOC_CTX *mem_
case DRSUAPI_DS_NAME_FORMAT_CANONICAL_EX:
canonical_name = ldb_dn_canonical_ex_string(mem_ctx, result_res[i]->dn);
break;
+ default:
+ break;
}
if (strcasecmp_m(canonical_name, name) == 0) {
result = result_res[i];
@@ -1208,7 +1219,7 @@ NTSTATUS crack_service_principal_name(struct ldb_context *sam_ctx,
NTSTATUS crack_name_to_nt4_name(TALLOC_CTX *mem_ctx,
struct tevent_context *ev_ctx,
struct loadparm_context *lp_ctx,
- uint32_t format_offered,
+ enum drsuapi_DsNameFormat format_offered,
const char *name,
const char **nt4_domain, const char **nt4_account)
{
@@ -1275,7 +1286,7 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx,
const char **nt4_domain,
const char **nt4_account)
{
- uint32_t format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN;
+ enum drsuapi_DsNameFormat format_offered = DRSUAPI_DS_NAME_FORMAT_UNKNOWN;
/* Handle anonymous bind */
if (!name || !*name) {
@@ -1298,3 +1309,76 @@ NTSTATUS crack_auto_name_to_nt4_name(TALLOC_CTX *mem_ctx,
return crack_name_to_nt4_name(mem_ctx, ev_ctx, lp_ctx, format_offered, name, nt4_domain, nt4_account);
}
+
+
+WERROR dcesrv_drsuapi_ListRoles(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
+ const struct drsuapi_DsNameRequest1 *req1,
+ struct drsuapi_DsNameCtr1 **ctr1)
+{
+ struct drsuapi_DsNameInfo1 *names;
+ uint32_t i;
+ uint32_t count = 5;/*number of fsmo role owners we are going to return*/
+
+ *ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
+ W_ERROR_HAVE_NO_MEMORY(*ctr1);
+ names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
+ W_ERROR_HAVE_NO_MEMORY(names);
+
+ for (i = 0; i < count; i++) {
+ WERROR werr;
+ struct ldb_dn *role_owner_dn, *fsmo_role_dn, *server_dn;
+ werr = dsdb_get_fsmo_role_info(mem_ctx, sam_ctx, i,
+ &fsmo_role_dn, &role_owner_dn);
+ if(!W_ERROR_IS_OK(werr)) {
+ return werr;
+ }
+ server_dn = ldb_dn_copy(mem_ctx, role_owner_dn);
+ ldb_dn_remove_child_components(server_dn, 1);
+ names[i].status = DRSUAPI_DS_NAME_STATUS_OK;
+ names[i].dns_domain_name = samdb_dn_to_dnshostname(sam_ctx, mem_ctx,
+ server_dn);
+ if(!names[i].dns_domain_name) {
+ DEBUG(4, ("list_roles: Failed to find dNSHostName for server %s",
+ ldb_dn_get_linearized(server_dn)));
+ }
+ names[i].result_name = talloc_strdup(mem_ctx, ldb_dn_get_linearized(role_owner_dn));
+ }
+
+ (*ctr1)->count = count;
+ (*ctr1)->array = names;
+
+ return WERR_OK;
+}
+
+WERROR dcesrv_drsuapi_CrackNamesByNameFormat(struct ldb_context *sam_ctx, TALLOC_CTX *mem_ctx,
+ const struct drsuapi_DsNameRequest1 *req1,
+ struct drsuapi_DsNameCtr1 **ctr1)
+{
+ struct drsuapi_DsNameInfo1 *names;
+ uint32_t i, count;
+ WERROR status;
+
+ *ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
+ W_ERROR_HAVE_NO_MEMORY(*ctr1);
+
+ count = req1->count;
+ names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
+ W_ERROR_HAVE_NO_MEMORY(names);
+
+ for (i=0; i < count; i++) {
+ status = DsCrackNameOneName(sam_ctx, mem_ctx,
+ req1->format_flags,
+ req1->format_offered,
+ req1->format_desired,
+ req1->names[i].str,
+ &names[i]);
+ if (!W_ERROR_IS_OK(status)) {
+ return status;
+ }
+ }
+
+ (*ctr1)->count = count;
+ (*ctr1)->array = names;
+
+ return WERR_OK;
+}
diff --git a/source4/dsdb/samdb/ldb_modules/rootdse.c b/source4/dsdb/samdb/ldb_modules/rootdse.c
index 2e7c97af38..b84621f9ee 100644
--- a/source4/dsdb/samdb/ldb_modules/rootdse.c
+++ b/source4/dsdb/samdb/ldb_modules/rootdse.c
@@ -492,6 +492,35 @@ static int rootdse_callback(struct ldb_request *req, struct ldb_reply *ares)
return LDB_SUCCESS;
}
+/*
+ mark our registered controls as non-critical in the request
+
+ This is needed as clients may mark controls as critical even if they
+ are not needed at all in a request. For example, the centrify client
+ sets the SD_FLAGS control as critical on ldap modify requests which
+ are setting the dNSHostName attribute on the machine account. That
+ request doesn't need SD_FLAGS at all, but centrify adds it on all
+ ldap requests.
+ */
+static void rootdse_mark_noncritical(struct ldb_module *module, struct ldb_control **controls)
+{
+ int i, j;
+ struct private_data *priv = talloc_get_type(ldb_module_get_private(module), struct private_data);
+
+ if (!controls) return;
+
+ for (i=0; controls[i]; i++) {
+ if (controls[i]->critical == 0) {
+ continue;
+ }
+ for (j=0; j<priv->num_controls; j++) {
+ if (strcasecmp(priv->controls[j], controls[i]->oid) == 0) {
+ controls[i]->critical = 0;
+ }
+ }
+ }
+}
+
static int rootdse_search(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb;
@@ -499,6 +528,8 @@ static int rootdse_search(struct ldb_module *module, struct ldb_request *req)
struct ldb_request *down_req;
int ret;
+ rootdse_mark_noncritical(module, req->controls);
+
ldb = ldb_module_get_ctx(module);
/* see if its for the rootDSE - only a base search on the "" DN qualifies */
@@ -963,6 +994,8 @@ static int rootdse_add(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
+ rootdse_mark_noncritical(module, req->controls);
+
/*
If dn is not "" we should let it pass through
*/
@@ -1013,6 +1046,8 @@ static int rootdse_modify(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
+ rootdse_mark_noncritical(module, req->controls);
+
/*
If dn is not "" we should let it pass through
*/
@@ -1054,6 +1089,8 @@ static int rootdse_delete(struct ldb_module *module, struct ldb_request *req)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
+ rootdse_mark_noncritical(module, req->controls);
+
/*
If dn is not "" we should let it pass through
*/
diff --git a/source4/dsdb/schema/schema_info_attr.c b/source4/dsdb/schema/schema_info_attr.c
index a9c5e932a1..0b5d50b529 100644
--- a/source4/dsdb/schema/schema_info_attr.c
+++ b/source4/dsdb/schema/schema_info_attr.c
@@ -70,6 +70,28 @@ WERROR dsdb_schema_info_blob_new(TALLOC_CTX *mem_ctx, DATA_BLOB *_schema_info_bl
/**
+ * Verify the 'blob' is a valid schemaInfo blob
+ */
+bool dsdb_schema_info_blob_is_valid(const DATA_BLOB *blob)
+{
+ if (!blob || !blob->data) {
+ return false;
+ }
+
+ /* schemaInfo blob must be 21 bytes long */
+ if (blob->length != 21) {
+ return false;
+ }
+
+ /* schemaInfo blob should start with 0xFF */
+ if (blob->data[0] != 0xFF) {
+ return false;
+ }
+
+ return true;
+}
+
+/**
* Parse schemaInfo structure from a data_blob
* (DATA_BLOB or ldb_val).
* Suitable for parsing blobs that comes from
@@ -83,16 +105,8 @@ WERROR dsdb_schema_info_from_blob(const DATA_BLOB *blob,
struct dsdb_schema_info *schema_info;
struct schemaInfoBlob schema_info_blob;
- if (!blob || !blob->data) {
- return WERR_INVALID_PARAMETER;
- }
-
- if (blob->length != 21) {
- return WERR_INVALID_PARAMETER;
- }
-
- /* schemaInfo blob should start with 0xFF */
- if (blob->data[0] != 0xFF) {
+ /* verify schemaInfo blob is valid */
+ if (!dsdb_schema_info_blob_is_valid(blob)) {
return WERR_INVALID_PARAMETER;
}
@@ -150,6 +164,47 @@ WERROR dsdb_blob_from_schema_info(const struct dsdb_schema_info *schema_info,
return WERR_OK;
}
+/**
+ * Compares schemaInfo signatures in dsdb_schema and prefixMap.
+ * NOTE: At present function compares schemaInfo values
+ * as string without taking into account schemVersion field
+ *
+ * @return WERR_OK if schemaInfos are equal
+ * WERR_DS_DRA_SCHEMA_MISMATCH if schemaInfos are different
+ */
+WERROR dsdb_schema_info_cmp(const struct dsdb_schema *schema,
+ const struct drsuapi_DsReplicaOIDMapping_Ctr *ctr)
+{
+ bool bres;
+ DATA_BLOB blob;
+ char *schema_info_str;
+ struct drsuapi_DsReplicaOIDMapping *mapping;
+
+ /* we should have at least schemaInfo element */
+ if (ctr->num_mappings < 1) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ /* verify schemaInfo element is valid */
+ mapping = &ctr->mappings[ctr->num_mappings - 1];
+ if (mapping->id_prefix != 0) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ blob = data_blob_const(mapping->oid.binary_oid, mapping->oid.length);
+ if (!dsdb_schema_info_blob_is_valid(&blob)) {
+ return WERR_INVALID_PARAMETER;
+ }
+
+ schema_info_str = hex_encode_talloc(NULL, blob.data, blob.length);
+ W_ERROR_HAVE_NO_MEMORY(schema_info_str);
+
+ bres = strequal(schema->schema_info, schema_info_str);
+ talloc_free(schema_info_str);
+
+ return bres ? WERR_OK : WERR_DS_DRA_SCHEMA_MISMATCH;
+}
+
/**
* Reads schema_info structure from schemaInfo
diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index a95e7ec2af..ba12f523e8 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -113,20 +113,17 @@ WERROR dsdb_load_oid_mappings_ldb(struct dsdb_schema *schema,
WERROR werr;
const char *schema_info;
struct dsdb_schema_prefixmap *pfm;
- struct dsdb_schema_info *schi;
TALLOC_CTX *mem_ctx;
+ /* verify schemaInfo blob is valid one */
+ if (!dsdb_schema_info_blob_is_valid(schemaInfo)) {
+ DEBUG(0,(__location__": dsdb_schema_info_blob_is_valid() failed.\n"));
+ return WERR_INVALID_PARAMETER;
+ }
+
mem_ctx = talloc_new(schema);
W_ERROR_HAVE_NO_MEMORY(mem_ctx);
- /* parse schemaInfo blob to verify it is valid */
- werr = dsdb_schema_info_from_blob(schemaInfo, mem_ctx, &schi);
- if (!W_ERROR_IS_OK(werr)) {
- DEBUG(0, (__location__ " dsdb_schema_info_from_blob failed: %s\n", win_errstr(werr)));
- talloc_free(mem_ctx);
- return werr;
- }
-
/* fetch prefixMap */
werr = _dsdb_prefixmap_from_ldb_val(prefixMap,
mem_ctx, &pfm);
diff --git a/source4/dsdb/schema/schema_prefixmap.c b/source4/dsdb/schema/schema_prefixmap.c
index 50f74b7161..79894fe272 100644
--- a/source4/dsdb/schema/schema_prefixmap.c
+++ b/source4/dsdb/schema/schema_prefixmap.c
@@ -188,6 +188,7 @@ static WERROR _dsdb_pfm_make_binary_oid(const char *full_oid, TALLOC_CTX *mem_ct
/* encode oid in BER format */
if (!ber_write_OID_String(mem_ctx, _bin_oid, full_oid)) {
+ DEBUG(0,("ber_write_OID_String() failed for %s\n", full_oid));
return WERR_INTERNAL_ERROR;
}
@@ -341,7 +342,9 @@ WERROR dsdb_schema_pfm_oid_from_attid(struct dsdb_schema_prefixmap *pfm, uint32_
}
if (!pfm_entry) {
- return WERR_INTERNAL_ERROR;
+ DEBUG(1,("Failed to find prefixMap entry for ATTID = 0x%08X (%d)\n",
+ attid, attid));
+ return WERR_DS_NO_ATTRIBUTE_OR_VALUE;
}
/* copy oid prefix making enough room */
@@ -363,6 +366,8 @@ WERROR dsdb_schema_pfm_oid_from_attid(struct dsdb_schema_prefixmap *pfm, uint32_
}
if (!ber_read_OID_String(mem_ctx, bin_oid, _oid)) {
+ DEBUG(0,("ber_read_OID_String() failed for %s\n",
+ hex_encode_talloc(bin_oid.data, bin_oid.data, bin_oid.length)));
werr = WERR_INTERNAL_ERROR;
}
@@ -394,7 +399,6 @@ static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_
if (have_schema_info) {
DATA_BLOB blob;
- struct dsdb_schema_info *schi = NULL;
if (ctr->num_mappings < 2) {
return WERR_INVALID_PARAMETER;
@@ -406,10 +410,9 @@ static WERROR _dsdb_drsuapi_pfm_verify(const struct drsuapi_DsReplicaOIDMapping_
return WERR_INVALID_PARAMETER;
}
- /* parse schemaInfo blob to verify it is valid */
+ /* verify schemaInfo blob is valid one */
blob = data_blob_const(mapping->oid.binary_oid, mapping->oid.length);
- if (!W_ERROR_IS_OK(dsdb_schema_info_from_blob(&blob, talloc_autofree_context(), &schi))) {
- talloc_free(schi);
+ if (!dsdb_schema_info_blob_is_valid(&blob)) {
return WERR_INVALID_PARAMETER;
}
diff --git a/source4/lib/registry/pyregistry.c b/source4/lib/registry/pyregistry.c
index 7f4f8333c6..1373ed87ca 100644
--- a/source4/lib/registry/pyregistry.c
+++ b/source4/lib/registry/pyregistry.c
@@ -2,6 +2,7 @@
Unix SMB/CIFS implementation.
Samba utility functions
Copyright (C) Jelmer Vernooij <jelmer@samba.org> 2008
+ Copyright (C) Wilco Baan Hofman <wilco@baanhofman.nl> 2010
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
@@ -238,16 +239,53 @@ static PyMethodDef hive_key_methods[] = {
{ NULL }
};
-static PyObject *hive_open(PyTypeObject *type, PyObject *args, PyObject *kwargs)
-{
- /* reg_open_hive */
+static PyObject *hive_new(PyTypeObject *type, PyObject *args, PyObject *kwargs) {
Py_RETURN_NONE;
}
+static PyObject *py_open_hive(PyTypeObject *type, PyObject *args, PyObject *kwargs)
+{
+ const char *kwnames[] = { "location", "lp_ctx", "session_info", "credentials", NULL };
+ WERROR result;
+ struct loadparm_context *lp_ctx;
+ PyObject *py_lp_ctx, *py_session_info, *py_credentials;
+ struct auth_session_info *session_info;
+ struct cli_credentials *credentials;
+ char *location;
+ struct hive_key *hive_key;
+
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|OOO",
+ discard_const_p(char *, kwnames),
+ &location,
+ &py_lp_ctx, &py_session_info,
+ &py_credentials))
+ return NULL;
+
+ lp_ctx = lpcfg_from_py_object(NULL, py_lp_ctx); /* FIXME: leaky */
+ if (lp_ctx == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Expected loadparm context");
+ return NULL;
+ }
+
+ credentials = cli_credentials_from_py_object(py_credentials);
+ if (credentials == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Expected credentials");
+ return NULL;
+ }
+ session_info = NULL;
+
+ result = reg_open_hive(NULL, location, session_info, credentials,
+ tevent_context_init(NULL),
+ lp_ctx, &hive_key);
+ PyErr_WERROR_IS_ERR_RAISE(result);
+
+ return py_talloc_steal(&PyHiveKey, hive_key);
+}
+
PyTypeObject PyHiveKey = {
.tp_name = "HiveKey",
.tp_methods = hive_key_methods,
- .tp_new = hive_open,
+ .tp_new = hive_new,
.tp_basicsize = sizeof(py_talloc_Object),
.tp_dealloc = py_talloc_dealloc,
.tp_flags = Py_TPFLAGS_DEFAULT,
@@ -396,6 +434,7 @@ static PyMethodDef py_registry_methods[] = {
{ "open_directory", py_open_directory, METH_VARARGS, "open_dir(location) -> key" },
{ "create_directory", py_create_directory, METH_VARARGS, "create_dir(location) -> key" },
{ "open_ldb", (PyCFunction)py_open_ldb_file, METH_VARARGS|METH_KEYWORDS, "open_ldb(location, session_info=None, credentials=None, loadparm_context=None) -> key" },
+ { "open_hive", (PyCFunction)py_open_hive, METH_VARARGS|METH_KEYWORDS, "open_hive(location, session_info=None, credentials=None, loadparm_context=None) -> key" },
{ "str_regtype", py_str_regtype, METH_VARARGS, "str_regtype(int) -> str" },
{ "get_predef_name", py_get_predef_name, METH_VARARGS, "get_predef_name(hkey) -> str" },
{ NULL }
diff --git a/source4/lib/registry/regf.c b/source4/lib/registry/regf.c
index cfbaaddf54..b62109ed57 100644
--- a/source4/lib/registry/regf.c
+++ b/source4/lib/registry/regf.c
@@ -110,7 +110,7 @@ static DATA_BLOB hbin_get(const struct regf_data *data, uint32_t offset)
hbin = hbin_by_offset(data, offset, &rel_offset);
if (hbin == NULL) {
- DEBUG(1, ("Can't find HBIN containing 0x%04x\n", offset));
+ DEBUG(1, ("Can't find HBIN at 0x%04x\n", offset));
return ret;
}
@@ -216,6 +216,8 @@ static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size,
if (data->hbins[i] == NULL) {
DEBUG(4, ("No space available in other HBINs for block of size %d, allocating new HBIN\n",
size));
+
+ /* Add extra hbin block */
data->hbins = talloc_realloc(data, data->hbins,
struct hbin_block *, i+2);
hbin = talloc(data->hbins, struct hbin_block);
@@ -224,17 +226,22 @@ static DATA_BLOB hbin_alloc(struct regf_data *data, uint32_t size,
data->hbins[i] = hbin;
data->hbins[i+1] = NULL;
+ /* Set hbin data */
hbin->HBIN_ID = talloc_strdup(hbin, "hbin");
hbin->offset_from_first = (i == 0?0:data->hbins[i-1]->offset_from_first+data->hbins[i-1]->offset_to_next);
hbin->offset_to_next = 0x1000;
hbin->unknown[0] = 0;
- hbin->unknown[0] = 0;
+ hbin->unknown[1] = 0;
unix_to_nt_time(&hbin->last_change, time(NULL));
hbin->block_size = hbin->offset_to_next;
hbin->data = talloc_zero_array(hbin, uint8_t, hbin->block_size - 0x20);
+ /* Update the regf header */
+ data->header->last_block += hbin->offset_to_next;
- rel_offset = 0x0;
+ /* Set the next block to it's proper size and set the
+ * rel_offset for this block */
SIVAL(hbin->data, size, hbin->block_size - size - 0x20);
+ rel_offset = 0x0;
}
/* Set size and mark as used */
@@ -314,7 +321,7 @@ static void hbin_free (struct regf_data *data, uint32_t offset)
size = -size;
/* If the next block is free, merge into big free block */
- if (rel_offset + size < hbin->offset_to_next) {
+ if (rel_offset + size < hbin->offset_to_next - 0x20) {
next_size = IVALS(hbin->data, rel_offset+size);
if (next_size > 0) {
size += next_size;
@@ -489,7 +496,7 @@ static struct regf_key_data *regf_get_key(TALLOC_CTX *ctx,
if (!hbin_get_tdr(regf, offset, nk,
(tdr_pull_fn_t)tdr_pull_nk_block, nk)) {
- DEBUG(0, ("Unable to find HBIN data for offset %d\n", offset));
+ DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n", offset));
return NULL;
}
@@ -519,7 +526,8 @@ static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
tmp = hbin_get(regf, private_data->nk->values_offset);
if (!tmp.data) {
- DEBUG(0, ("Unable to find value list\n"));
+ DEBUG(0, ("Unable to find value list at 0x%x\n",
+ private_data->nk->values_offset));
return WERR_GENERAL_FAILURE;
}
@@ -534,7 +542,7 @@ static WERROR regf_get_value(TALLOC_CTX *ctx, struct hive_key *key,
if (!hbin_get_tdr(regf, vk_offset, vk,
(tdr_pull_fn_t)tdr_pull_vk_block, vk)) {
- DEBUG(0, ("Unable to get VK block at %d\n", vk_offset));
+ DEBUG(0, ("Unable to get VK block at 0x%x\n", vk_offset));
talloc_free(vk);
return WERR_GENERAL_FAILURE;
}
@@ -606,9 +614,15 @@ static WERROR regf_get_subkey_by_index(TALLOC_CTX *ctx,
if (idx >= nk->num_subkeys)
return WERR_NO_MORE_ITEMS;
+ /* Make sure that we don't crash if the key is empty */
+ if (nk->subkeys_offset == -1) {
+ return WERR_NO_MORE_ITEMS;
+ }
+
data = hbin_get(private_data->hive, nk->subkeys_offset);
if (!data.data) {
- DEBUG(0, ("Unable to find subkey list\n"));
+ DEBUG(0, ("Unable to find subkey list at 0x%x\n",
+ nk->subkeys_offset));
return WERR_GENERAL_FAILURE;
}
@@ -845,6 +859,11 @@ static WERROR regf_get_subkey_by_name(TALLOC_CTX *ctx,
struct nk_block *nk = private_data->nk;
uint32_t key_off = 0;
+ /* Make sure that we don't crash if the key is empty */
+ if (nk->subkeys_offset == -1) {
+ return WERR_BADFILE;
+ }
+
data = hbin_get(private_data->hive, nk->subkeys_offset);
if (!data.data) {
DEBUG(0, ("Unable to find subkey list\n"));
@@ -1739,7 +1758,7 @@ static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
if (!hbin_get_tdr(regf, regf->header->data_offset, root,
(tdr_pull_fn_t)tdr_pull_nk_block, root)) {
- DEBUG(0, ("Unable to find HBIN data for offset %d\n",
+ DEBUG(0, ("Unable to find HBIN data for offset 0x%x\n",
regf->header->data_offset));
return WERR_GENERAL_FAILURE;
}
@@ -1764,6 +1783,7 @@ static WERROR regf_add_key(TALLOC_CTX *ctx, const struct hive_key *parent,
*ret = (struct hive_key *)regf_get_key(ctx, regf, offset);
+ DEBUG(9, ("Storing key %s\n", name));
return regf_save_hbin(private_data->hive);
}
@@ -1789,7 +1809,7 @@ static WERROR regf_set_value(struct hive_key *key, const char *name,
if (!hbin_get_tdr(regf, tmp_vk_offset, private_data,
(tdr_pull_fn_t)tdr_pull_vk_block,
&vk)) {
- DEBUG(0, ("Unable to get VK block at %d\n",
+ DEBUG(0, ("Unable to get VK block at 0x%x\n",
tmp_vk_offset));
return WERR_GENERAL_FAILURE;
}
diff --git a/source4/lib/registry/regf.idl b/source4/lib/registry/regf.idl
index fd58ad2d61..064aaf09ce 100644
--- a/source4/lib/registry/regf.idl
+++ b/source4/lib/registry/regf.idl
@@ -74,8 +74,8 @@ interface regf
};
[noprint] enum reg_key_type {
- REG_ROOT_KEY = 0x20,
- REG_SUB_KEY = 0x2C,
+ REG_ROOT_KEY = 0x2C,
+ REG_SUB_KEY = 0x20,
REG_SYM_LINK = 0x10
};
diff --git a/source4/libcli/finddcs_cldap.c b/source4/libcli/finddcs_cldap.c
index 33e31a9cf7..b7a8324c0f 100644
--- a/source4/libcli/finddcs_cldap.c
+++ b/source4/libcli/finddcs_cldap.c
@@ -36,6 +36,7 @@ struct finddcs_cldap_state {
struct tevent_req *req;
const char *domain_name;
struct dom_sid *domain_sid;
+ const char *srv_name;
const char **srv_addresses;
uint32_t minimum_dc_flags;
uint32_t srv_address_index;
@@ -112,18 +113,17 @@ static bool finddcs_cldap_srv_lookup(struct finddcs_cldap_state *state,
struct resolve_context *resolve_ctx,
struct tevent_context *event_ctx)
{
- const char *srv_name;
struct composite_context *creq;
struct nbt_name name;
if (io->in.site_name) {
- srv_name = talloc_asprintf(state, "_ldap._tcp.%s._sites.%s",
+ state->srv_name = talloc_asprintf(state, "_ldap._tcp.%s._sites.%s",
io->in.site_name, io->in.domain_name);
} else {
- srv_name = talloc_asprintf(state, "_ldap._tcp.%s", io->in.domain_name);
+ state->srv_name = talloc_asprintf(state, "_ldap._tcp.%s", io->in.domain_name);
}
- make_nbt_name(&name, srv_name, 0);
+ make_nbt_name(&name, state->srv_name, 0);
creq = resolve_name_ex_send(resolve_ctx, state,
RESOLVE_NAME_FLAG_FORCE_DNS | RESOLVE_NAME_FLAG_DNS_SRV,
@@ -167,6 +167,7 @@ static void finddcs_cldap_next_server(struct finddcs_cldap_state *state)
if (state->srv_addresses[state->srv_address_index] == NULL) {
tevent_req_nterror(state->req, NT_STATUS_OBJECT_NAME_NOT_FOUND);
+ DEBUG(2,("finddcs: No matching CLDAP server found\n"));
return;
}
@@ -247,9 +248,12 @@ static void finddcs_cldap_name_resolved(struct composite_context *ctx)
status = resolve_name_recv(ctx, state, &address);
if (tevent_req_nterror(state->req, status)) {
+ DEBUG(2,("finddcs: No matching NBT <1c> server found\n"));
return;
}
+ DEBUG(4,("finddcs: Found NBT <1c> server at %s\n", address));
+
state->srv_addresses = talloc_array(state, const char *, 2);
if (tevent_req_nomem(state->srv_addresses, state->req)) {
return;
@@ -279,6 +283,7 @@ static void finddcs_cldap_srv_resolved(struct composite_context *ctx)
status = resolve_name_multiple_recv(ctx, state, &state->srv_addresses);
if (tevent_req_nterror(state->req, status)) {
+ DEBUG(2,("finddcs: Failed to find SRV record for %s\n", state->srv_name));
return;
}
diff --git a/source4/libnet/libnet_lookup.c b/source4/libnet/libnet_lookup.c
index 3677c2a31e..6b8ab6edd4 100644
--- a/source4/libnet/libnet_lookup.c
+++ b/source4/libnet/libnet_lookup.c
@@ -195,10 +195,7 @@ struct tevent_req *libnet_LookupDCs_send(struct libnet_context *ctx,
struct finddcs finddcs_io;
ZERO_STRUCT(finddcs_io);
- finddcs_io.in.domain_name = lpcfg_realm(ctx->lp_ctx);
- if (strcmp(finddcs_io.in.domain_name, "") == 0) {
- finddcs_io.in.domain_name = lpcfg_workgroup(ctx->lp_ctx);
- }
+ finddcs_io.in.domain_name = io->in.domain_name;
finddcs_io.in.minimum_dc_flags = NBT_SERVER_LDAP | NBT_SERVER_DS | NBT_SERVER_WRITABLE;
diff --git a/source4/librpc/idl/winbind.idl b/source4/librpc/idl/winbind.idl
index 849b8166a7..f9bccb87c5 100644
--- a/source4/librpc/idl/winbind.idl
+++ b/source4/librpc/idl/winbind.idl
@@ -47,4 +47,9 @@ interface winbind
[in,out] [size_is(count)] id_map ids[]
);
+ NTSTATUS winbind_DsrUpdateReadOnlyServerDnsRecords(
+ [in,unique] [string,charset(UTF16)] uint16 *site_name,
+ [in] uint32 dns_ttl,
+ [in,out,ref] NL_DNS_NAME_INFO_ARRAY *dns_names
+ );
}
diff --git a/source4/librpc/rpc/pyrpc.h b/source4/librpc/rpc/pyrpc.h
index fb5f35fcf1..c3bc83877c 100644
--- a/source4/librpc/rpc/pyrpc.h
+++ b/source4/librpc/rpc/pyrpc.h
@@ -24,7 +24,7 @@
#define PY_CHECK_TYPE(type, var, fail) \
if (!PyObject_TypeCheck(var, type)) {\
- PyErr_Format(PyExc_TypeError, "Expected type %s for %s", (type)->tp_name, #var); \
+ PyErr_Format(PyExc_TypeError, __location__ ": Expected type '%s' for '%s' of type '%s'", (type)->tp_name, #var, Py_TYPE(var)->tp_name); \
fail; \
}
@@ -42,4 +42,14 @@ typedef struct {
struct dcerpc_binding_handle *binding_handle;
} dcerpc_InterfaceObject;
+
+/*
+ these prototypes should be generated by the python pidl backend, but
+ aren't yet. They are needed when one module that has python access
+ is accessed by another module
+ */
+union netr_LogonLevel *py_export_netr_LogonLevel(TALLOC_CTX *mem_ctx, int level, PyObject *in);
+union netr_Validation;
+PyObject *py_import_netr_Validation(TALLOC_CTX *mem_ctx, int level, union netr_Validation *in);
+
#endif /* _PYRPC_H_ */
diff --git a/source4/librpc/rpc/pyrpc_util.c b/source4/librpc/rpc/pyrpc_util.c
index f3911eeb9a..ba42c08154 100644
--- a/source4/librpc/rpc/pyrpc_util.c
+++ b/source4/librpc/rpc/pyrpc_util.c
@@ -28,6 +28,8 @@
#include "param/pyparam.h"
#include "auth/credentials/pycredentials.h"
#include "lib/events/events.h"
+#include "lib/messaging/messaging.h"
+#include "lib/messaging/irpc.h"
#ifndef Py_TYPE /* Py_TYPE is only available on Python > 2.6 */
#define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
@@ -65,7 +67,31 @@ bool py_check_dcerpc_type(PyObject *obj, const char *module, const char *typenam
return ret;
}
-PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, PyObject *kwargs, const struct ndr_interface_table *table)
+/*
+ connect to a IRPC pipe from python
+ */
+static NTSTATUS pyrpc_irpc_connect(TALLOC_CTX *mem_ctx, const char *irpc_server,
+ const struct ndr_interface_table *table,
+ struct tevent_context *event_ctx,
+ struct loadparm_context *lp_ctx,
+ struct dcerpc_binding_handle **binding_handle)
+{
+ struct messaging_context *msg;
+
+ msg = messaging_client_init(mem_ctx, lpcfg_messaging_path(mem_ctx, lp_ctx), event_ctx);
+ NT_STATUS_HAVE_NO_MEMORY(msg);
+
+ *binding_handle = irpc_binding_handle_by_name(mem_ctx, msg, irpc_server, table);
+ if (*binding_handle == NULL) {
+ talloc_free(msg);
+ return NT_STATUS_INVALID_PIPE_STATE;
+ }
+
+ return NT_STATUS_OK;
+}
+
+PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, PyObject *kwargs,
+ const struct ndr_interface_table *table)
{
dcerpc_InterfaceObject *ret;
const char *binding_string;
@@ -103,18 +129,17 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
talloc_free(mem_ctx);
return NULL;
}
- credentials = cli_credentials_from_py_object(py_credentials);
- if (credentials == NULL) {
- PyErr_SetString(PyExc_TypeError, "Expected credentials");
- talloc_free(mem_ctx);
- return NULL;
- }
+
ret = PyObject_New(dcerpc_InterfaceObject, type);
ret->mem_ctx = mem_ctx;
event_ctx = s4_event_context_init(ret->mem_ctx);
- if (py_basis != Py_None) {
+ if (strncmp(binding_string, "irpc:", 5) == 0) {
+ ret->pipe = NULL;
+ status = pyrpc_irpc_connect(ret->mem_ctx, binding_string+5, table,
+ event_ctx, lp_ctx, &ret->binding_handle);
+ } else if (py_basis != Py_None) {
struct dcerpc_pipe *base_pipe;
PyObject *py_base;
PyTypeObject *ClientConnection_Type;
@@ -144,6 +169,12 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
ret->pipe = talloc_steal(ret->mem_ctx, ret->pipe);
} else {
+ credentials = cli_credentials_from_py_object(py_credentials);
+ if (credentials == NULL) {
+ PyErr_SetString(PyExc_TypeError, "Expected credentials");
+ talloc_free(mem_ctx);
+ return NULL;
+ }
status = dcerpc_pipe_connect(event_ctx, &ret->pipe, binding_string,
table, credentials, event_ctx, lp_ctx);
}
@@ -153,8 +184,10 @@ PyObject *py_dcerpc_interface_init_helper(PyTypeObject *type, PyObject *args, Py
return NULL;
}
- ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;
- ret->binding_handle = ret->pipe->binding_handle;
+ if (ret->pipe) {
+ ret->pipe->conn->flags |= DCERPC_NDR_REF_ALLOC;
+ ret->binding_handle = ret->pipe->binding_handle;
+ }
return (PyObject *)ret;
}
diff --git a/source4/librpc/wscript_build b/source4/librpc/wscript_build
index 06bd8a7794..65e8260ab4 100755
--- a/source4/librpc/wscript_build
+++ b/source4/librpc/wscript_build
@@ -764,6 +764,18 @@ bld.SAMBA_PYTHON('python_irpc',
realname='samba/dcerpc/irpc.so'
)
+bld.SAMBA_PYTHON('python_winbind',
+ source='gen_ndr/py_winbind.c',
+ deps='RPC_NDR_WINBIND PYTALLOC pyrpc_util python_netlogon',
+ realname='samba/dcerpc/winbind.so'
+ )
+
+bld.SAMBA_PYTHON('python_idmap',
+ source='../../librpc/gen_ndr/py_idmap.c',
+ deps='NDR_IDMAP PYTALLOC pyrpc_util',
+ realname='samba/dcerpc/idmap.so'
+ )
+
bld.SAMBA_PYTHON('python_drsuapi',
source='../../librpc/gen_ndr/py_drsuapi.c',
diff --git a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
index 16c19cdd3e..2299714c2d 100644
--- a/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
+++ b/source4/rpc_server/drsuapi/dcesrv_drsuapi.c
@@ -406,14 +406,12 @@ static WERROR dcesrv_drsuapi_DsGetNT4ChangeLog(struct dcesrv_call_state *dce_cal
DRSUAPI_UNSUPPORTED(drsuapi_DsGetNT4ChangeLog);
}
-
/*
drsuapi_DsCrackNames
*/
static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TALLOC_CTX *mem_ctx,
struct drsuapi_DsCrackNames *r)
{
- WERROR status;
struct drsuapi_bind_state *b_state;
struct dcesrv_handle *h;
@@ -427,37 +425,36 @@ static WERROR dcesrv_drsuapi_DsCrackNames(struct dcesrv_call_state *dce_call, TA
switch (r->in.level) {
case 1: {
- struct drsuapi_DsNameCtr1 *ctr1;
- struct drsuapi_DsNameInfo1 *names;
- uint32_t i, count;
-
- ctr1 = talloc(mem_ctx, struct drsuapi_DsNameCtr1);
- W_ERROR_HAVE_NO_MEMORY(ctr1);
-
- count = r->in.req->req1.count;
- names = talloc_array(mem_ctx, struct drsuapi_DsNameInfo1, count);
- W_ERROR_HAVE_NO_MEMORY(names);
-
- for (i=0; i < count; i++) {
- status = DsCrackNameOneName(b_state->sam_ctx, mem_ctx,
- r->in.req->req1.format_flags,
- r->in.req->req1.format_offered,
- r->in.req->req1.format_desired,
- r->in.req->req1.names[i].str,
- &names[i]);
- if (!W_ERROR_IS_OK(status)) {
- return status;
- }
+ switch(r->in.req->req1.format_offered){
+ case DRSUAPI_DS_NAME_FORMAT_UPN_AND_ALTSECID:
+ case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN_EX:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_GLOBAL_CATALOG_SERVERS:
+ case DRSUAPI_DS_NAME_FORMAT_UPN_FOR_LOGON:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_WITH_DCS_IN_SITE:
+ case DRSUAPI_DS_NAME_FORMAT_STRING_SID_NAME:
+ case DRSUAPI_DS_NAME_FORMAT_ALT_SECURITY_IDENTITIES_NAME:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_NCS:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS:
+ case DRSUAPI_DS_NAME_FORMAT_MAP_SCHEMA_GUID:
+ case DRSUAPI_DS_NAME_FORMAT_NT4_ACCOUNT_NAME_SANS_DOMAIN:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_INFO_FOR_SERVER:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_FOR_DOMAIN_IN_SITE:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_DOMAINS_IN_SITE:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_SERVERS_IN_SITE:
+ case DRSUAPI_DS_NAME_FORMAT_LIST_SITES:
+ DEBUG(0, ("DsCrackNames: Unsupported operation requested: %X",
+ r->in.req->req1.format_offered));
+ return WERR_OK;
+ case DRSUAPI_DS_NAME_FORMAT_LIST_ROLES:
+ return dcesrv_drsuapi_ListRoles(b_state->sam_ctx, mem_ctx,
+ &r->in.req->req1, &r->out.ctr->ctr1);
+ default:/* format_offered is in the enum drsuapi_DsNameFormat*/
+ return dcesrv_drsuapi_CrackNamesByNameFormat(b_state->sam_ctx, mem_ctx,
+ &r->in.req->req1, &r->out.ctr->ctr1);
}
-
- ctr1->count = count;
- ctr1->array = names;
- r->out.ctr->ctr1 = ctr1;
-
return WERR_OK;
}
}
-
return WERR_UNKNOWN_LEVEL;
}
diff --git a/source4/scripting/bin/samba_dnsupdate b/source4/scripting/bin/samba_dnsupdate
index b295224ddc..d3abcb1052 100755
--- a/source4/scripting/bin/samba_dnsupdate
+++ b/source4/scripting/bin/samba_dnsupdate
@@ -36,17 +36,20 @@ from samba import getopt as options
from ldb import SCOPE_BASE
from samba.auth import system_session
from samba.samdb import SamDB
+from samba.dcerpc import netlogon, winbind
samba.ensure_external_module("dns", "dnspython")
import dns.resolver as resolver
default_ttl = 900
+am_rodc = False
parser = optparse.OptionParser("samba_dnsupdate")
sambaopts = options.SambaOptions(parser)
parser.add_option_group(sambaopts)
parser.add_option_group(options.VersionOptions(parser))
parser.add_option("--verbose", action="store_true")
+parser.add_option("--all-names", action="store_true")
parser.add_option("--all-interfaces", action="store_true")
parser.add_option("--use-file", type="string", help="Use a file, rather than real DNS calls")
@@ -75,7 +78,8 @@ if len(IPs) == 0:
print "No IP interfaces - skipping DNS updates"
sys.exit(0)
-
+if opts.verbose:
+ print "IPs: %s" % IPs
########################################################
# get credentials if we haven't got them already
@@ -189,19 +193,22 @@ def check_dns_name(d):
###########################################
# get the list of substitution vars
def get_subst_vars():
- global lp
+ global lp, am_rodc
vars = {}
samdb = SamDB(url=lp.get("sam database"), session_info=system_session(),
lp=lp)
vars['DNSDOMAIN'] = lp.get('realm').lower()
+ vars['DNSFOREST'] = lp.get('realm').lower()
vars['HOSTNAME'] = lp.get('netbios name').lower() + "." + vars['DNSDOMAIN']
vars['NTDSGUID'] = samdb.get_ntds_GUID()
vars['SITE'] = samdb.server_site_name()
res = samdb.search(base=None, scope=SCOPE_BASE, attrs=["objectGUID"])
guid = samdb.schema_format_value("objectGUID", res[0]['objectGUID'][0])
vars['DOMAINGUID'] = guid
+ am_rodc = samdb.am_rodc()
+
return vars
@@ -241,6 +248,75 @@ def call_nsupdate(d):
os.unlink(tmpfile)
+
+def rodc_dns_update(d, t):
+ '''a single DNS update via the RODC netlogon call'''
+ global sub_vars
+
+ if opts.verbose:
+ print "Calling netlogon RODC update for %s" % d
+
+ typemap = {
+ netlogon.NlDnsLdapAtSite : netlogon.NlDnsInfoTypeNone,
+ netlogon.NlDnsGcAtSite : netlogon.NlDnsDomainNameAlias,
+ netlogon.NlDnsDsaCname : netlogon.NlDnsDomainNameAlias,
+ netlogon.NlDnsKdcAtSite : netlogon.NlDnsInfoTypeNone,
+ netlogon.NlDnsDcAtSite : netlogon.NlDnsInfoTypeNone,
+ netlogon.NlDnsRfc1510KdcAtSite : netlogon.NlDnsInfoTypeNone,
+ netlogon.NlDnsGenericGcAtSite : netlogon.NlDnsDomainNameAlias
+ }
+
+ w = winbind.winbind("irpc:winbind_server", lp)
+ dns_names = netlogon.NL_DNS_NAME_INFO_ARRAY()
+ dns_names.count = 1
+ name = netlogon.NL_DNS_NAME_INFO()
+ name.type = t
+ name.dns_domain_info_type = typemap[t]
+ name.priority = 0
+ name.weight = 0
+ if d.port is not None:
+ name.port = int(d.port)
+ name.dns_register = True
+ dns_names.names = [ name ]
+ site_name = sub_vars['SITE'].decode('utf-8')
+
+ try:
+ ret_names = w.DsrUpdateReadOnlyServerDnsRecords(site_name, default_ttl, dns_names)
+ if ret_names.names[0].status != 0:
+ print("Failed to set DNS entry: %s (status %u)" % (d, ret_names.names[0].status))
+ except RuntimeError, reason:
+ print("Error setting DNS entry of type %u: %s: %s" % (t, d, reason))
+
+
+def call_rodc_update(d):
+ '''RODCs need to use the netlogon API for nsupdate'''
+ global lp, sub_vars
+
+ # we expect failure for 3268 if we aren't a GC
+ if d.port is not None and int(d.port) == 3268:
+ return
+
+ # map the DNS request to a netlogon update type
+ map = {
+ netlogon.NlDnsLdapAtSite : '_ldap._tcp.${SITE}._sites.${DNSDOMAIN}',
+ netlogon.NlDnsGcAtSite : '_ldap._tcp.${SITE}._sites.gc._msdcs.${DNSDOMAIN}',
+ netlogon.NlDnsDsaCname : '${NTDSGUID}._msdcs.${DNSFOREST}',
+ netlogon.NlDnsKdcAtSite : '_kerberos._tcp.${SITE}._sites.dc._msdcs.${DNSDOMAIN}',
+ netlogon.NlDnsDcAtSite : '_ldap._tcp.${SITE}._sites.dc._msdcs.${DNSDOMAIN}',
+ netlogon.NlDnsRfc1510KdcAtSite : '_kerberos._tcp.${SITE}._sites.${DNSDOMAIN}',
+ netlogon.NlDnsGenericGcAtSite : '_gc._tcp.${SITE}._sites.${DNSFOREST}'
+ }
+
+ for t in map:
+ subname = samba.substitute_var(map[t], sub_vars)
+ if subname.lower() == d.name.lower():
+ # found a match - do the update
+ rodc_dns_update(d, t)
+ return
+ if opts.verbose:
+ print("Unable to map to netlogon DNS update: %s" % d)
+
+
# get the list of DNS entries we should have
dns_update_list = lp.private_path('dns_update_list')
@@ -273,7 +349,7 @@ for d in dns_list:
# now check if the entries already exist on the DNS server
for d in dns_list:
- if not check_dns_name(d):
+ if opts.all_names or not check_dns_name(d):
update_list.append(d)
if len(update_list) == 0:
@@ -286,7 +362,10 @@ get_credentials(lp)
# ask nsupdate to add entries as needed
for d in update_list:
- call_nsupdate(d)
+ if am_rodc:
+ call_rodc_update(d)
+ else:
+ call_nsupdate(d)
# delete the ccache if we created it
if ccachename is not None:
diff --git a/source4/scripting/devel/getncchanges b/source4/scripting/devel/getncchanges
index 7656c22ea4..99f14eafe9 100755
--- a/source4/scripting/devel/getncchanges
+++ b/source4/scripting/devel/getncchanges
@@ -54,6 +54,7 @@ def do_DsBind(drs):
if __name__ == "__main__":
parser = OptionParser("getncchanges [options] server")
sambaopts = options.SambaOptions(parser)
+ parser.add_option_group(sambaopts)
credopts = options.CredentialsOptionsDouble(parser)
parser.add_option_group(credopts)
diff --git a/source4/scripting/devel/ldapcmp b/source4/scripting/devel/ldapcmp
index 76b4e8eec6..edf37d36d0 100755
--- a/source4/scripting/devel/ldapcmp
+++ b/source4/scripting/devel/ldapcmp
@@ -518,13 +518,10 @@ class LDAPBundel(object):
if __name__ == "__main__":
parser = OptionParser("ldapcmp [options] domain|configuration|schema")
sambaopts = options.SambaOptions(parser)
+ parser.add_option_group(sambaopts)
credopts = options.CredentialsOptionsDouble(parser)
parser.add_option_group(credopts)
- lp = sambaopts.get_loadparm()
- creds = credopts.get_credentials(lp)
- creds2 = credopts.get_credentials2(lp)
-
parser.add_option("", "--host", dest="host",
help="IP of the first LDAP server",)
parser.add_option("", "--host2", dest="host2",
@@ -537,6 +534,15 @@ if __name__ == "__main__":
help="Print all DN pairs that have been compared",)
(opts, args) = parser.parse_args()
+ lp = sambaopts.get_loadparm()
+ creds = credopts.get_credentials(lp)
+ creds2 = credopts.get_credentials2(lp)
+ if creds2.is_anonymous():
+ creds2 = creds
+
+ if creds.is_anonymous():
+ parser.error("You must supply at least one username/password pair")
+
if not (len(args) == 1 and args[0].upper() in ["DOMAIN", "CONFIGURATION", "SCHEMA"]):
parser.error("Incorrect arguments")
diff --git a/source4/scripting/devel/rodcdns b/source4/scripting/devel/rodcdns
new file mode 100755
index 0000000000..bd24342ab8
--- /dev/null
+++ b/source4/scripting/devel/rodcdns
@@ -0,0 +1,43 @@
+#!/usr/bin/env python
+
+# script to call a netlogon RODC DNS update
+
+import sys
+from optparse import OptionParser
+
+sys.path.insert(0, "bin/python")
+
+import samba
+import samba.getopt as options
+from samba.dcerpc import netlogon, winbind
+
+########### main code ###########
+if __name__ == "__main__":
+ parser = OptionParser("rodcdns [options]")
+ sambaopts = options.SambaOptions(parser)
+
+ parser.add_option("", "--weight", dest="weight", help="record weight", default=0, type='int')
+ parser.add_option("", "--priority", dest="priority", help="record priority", default=100, type='int')
+ parser.add_option("", "--port", dest="port", help="port number", default=389, type='int')
+ parser.add_option("", "--type", dest="type", help="record type", default=netlogon.NlDnsLdapAtSite, type='int')
+ parser.add_option("", "--site", dest="site", help="site name", default="Default-First-Site-Name")
+
+ (opts, args) = parser.parse_args()
+
+ lp = sambaopts.get_loadparm()
+
+ w = winbind.winbind("irpc:winbind_server", lp)
+
+ dns_names = netlogon.NL_DNS_NAME_INFO_ARRAY()
+ dns_names.count = 1
+ name = netlogon.NL_DNS_NAME_INFO()
+ name.type = opts.type
+ name.priority = opts.priority
+ name.weight = opts.weight
+ name.port = opts.port
+ name.dns_register = True
+ dns_names.names = [ name ]
+ site_name = opts.site.decode('utf-8')
+
+ ret_names = w.DsrUpdateReadOnlyServerDnsRecords(site_name, 600, dns_names)
+ print("Status: %u" % ret_names.names[0].status)
diff --git a/source4/scripting/python/samba/join.py b/source4/scripting/python/samba/join.py
index 2cb1e3da0b..679dc5bf99 100644
--- a/source4/scripting/python/samba/join.py
+++ b/source4/scripting/python/samba/join.py
@@ -69,6 +69,8 @@ def join_rodc(server=None, creds=None, lp=None, site=None, netbios_name=None,
def find_dc(ctx, domain):
'''find a writeable DC for the given domain'''
ctx.cldap_ret = ctx.net.finddc(domain, nbt.NBT_SERVER_LDAP | nbt.NBT_SERVER_DS | nbt.NBT_SERVER_WRITABLE)
+ if ctx.cldap_ret.client_site is not None and ctx.cldap_ret.client_site != "":
+ ctx.site = ctx.cldap_ret.client_site
return ctx.cldap_ret.pdc_dns_name;
diff --git a/source4/scripting/python/samba/samdb.py b/source4/scripting/python/samba/samdb.py
index e2ac37a240..bbc52a9ebd 100644
--- a/source4/scripting/python/samba/samdb.py
+++ b/source4/scripting/python/samba/samdb.py
@@ -40,7 +40,7 @@ class SamDB(samba.Ldb):
def __init__(self, url=None, lp=None, modules_dir=None, session_info=None,
credentials=None, flags=0, options=None, global_schema=True,
- auto_connect=True, am_rodc=False):
+ auto_connect=True, am_rodc=None):
self.lp = lp
if not auto_connect:
url = None
@@ -54,7 +54,8 @@ class SamDB(samba.Ldb):
if global_schema:
dsdb._dsdb_set_global_schema(self)
- dsdb._dsdb_set_am_rodc(self, am_rodc)
+ if am_rodc is not None:
+ dsdb._dsdb_set_am_rodc(self, am_rodc)
def connect(self, url=None, flags=0, options=None):
if self.lp is not None:
@@ -63,6 +64,9 @@ class SamDB(samba.Ldb):
super(SamDB, self).connect(url=url, flags=flags,
options=options)
+ def am_rodc(self):
+ return dsdb._am_rodc(self)
+
def domain_dn(self):
# find the DNs for the domain
res = self.search(base="",
diff --git a/source4/torture/basic/base.c b/source4/torture/basic/base.c
index c9148d1915..7b96e1c093 100644
--- a/source4/torture/basic/base.c
+++ b/source4/torture/basic/base.c
@@ -680,13 +680,13 @@ static bool run_deferopen(struct torture_context *tctx, struct smbcli_state *cli
torture_comment(tctx, "pid %u open %d\n", (unsigned)getpid(), i);
- msleep(10 * msec);
+ smb_msleep(10 * msec);
i++;
if (NT_STATUS_IS_ERR(smbcli_close(cli->tree, fnum))) {
torture_comment(tctx,"Failed to close %s, error=%s\n", fname, smbcli_errstr(cli->tree));
return false;
}
- msleep(2 * msec);
+ smb_msleep(2 * msec);
}
if (NT_STATUS_IS_ERR(smbcli_unlink(cli->tree, fname))) {
diff --git a/source4/torture/basic/delaywrite.c b/source4/torture/basic/delaywrite.c
index 0c43c29cad..f82b32fe8d 100644
--- a/source4/torture/basic/delaywrite.c
+++ b/source4/torture/basic/delaywrite.c
@@ -111,7 +111,7 @@ static bool test_delayed_write_update(struct torture_context *tctx, struct smbcl
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
@@ -162,7 +162,7 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
/* 3 second delay to ensure we get past any 2 second time
granularity (older systems may have that) */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
finfo1.all_info.in.file.fnum = fnum1;
@@ -180,7 +180,7 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
/* 3 second delay to ensure we get past any 2 second time
granularity (older systems may have that) */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
/* Do a zero length SMBwrite call to truncate. */
written = smbcli_smbwrite(cli->tree, fnum1, "x", 1024, 0);
@@ -231,7 +231,7 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
@@ -241,7 +241,7 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
}
fflush(stdout);
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
@@ -282,7 +282,7 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
@@ -292,7 +292,7 @@ static bool test_delayed_write_update1(struct torture_context *tctx, struct smbc
}
fflush(stdout);
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* the close should trigger an write time update */
smbcli_close(cli->tree, fnum1);
@@ -353,7 +353,7 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
/* 3 second delay to ensure we get past any 2 second time
granularity (older systems may have that) */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
finfo1.all_info.in.file.fnum = fnum1;
@@ -418,7 +418,7 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
@@ -428,7 +428,7 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
}
fflush(stdout);
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
@@ -467,7 +467,7 @@ static bool test_delayed_write_update1a(struct torture_context *tctx, struct smb
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
@@ -535,7 +535,7 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
/* 3 second delay to ensure we get past any 2 second time
granularity (older systems may have that) */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
finfo1.all_info.in.file.fnum = fnum1;
@@ -596,7 +596,7 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
@@ -606,7 +606,7 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
}
fflush(stdout);
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
@@ -644,7 +644,7 @@ static bool test_delayed_write_update1b(struct torture_context *tctx, struct smb
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
@@ -710,7 +710,7 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
/* 3 second delay to ensure we get past any 2 second time
granularity (older systems may have that) */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
finfo1.all_info.level = RAW_FILEINFO_ALL_INFO;
finfo1.all_info.in.file.fnum = fnum1;
@@ -776,7 +776,7 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo1.all_info.out.write_time == finfo2.all_info.out.write_time) {
@@ -786,7 +786,7 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
}
fflush(stdout);
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* Do a non-zero length SMBwrite and make sure it doesn't update the write time. */
written = smbcli_smbwrite(cli->tree, fnum1, "x", 0, 1);
@@ -822,7 +822,7 @@ static bool test_delayed_write_update1c(struct torture_context *tctx, struct smb
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo2.all_info.out.write_time != finfo3.all_info.out.write_time) {
@@ -900,7 +900,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
/* 3 second delay to ensure we get past any 2 second time
granularity (older systems may have that) */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
{
/* Try using setfileinfo instead of write to update write time. */
@@ -1007,7 +1007,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
@@ -1015,7 +1015,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
}
fflush(stdout);
- msleep(2 * msec);
+ smb_msleep(2 * msec);
fnum2 = smbcli_open(cli->tree, fname, O_RDWR, DENY_NONE);
if (fnum2 == -1) {
@@ -1099,7 +1099,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
break;
}
fflush(stdout);
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
@@ -1131,7 +1131,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
torture_comment(tctx, "Second open initial write time %s\n",
nt_time_string(tctx, finfo1.basic_info.out.write_time));
- msleep(10 * msec);
+ smb_msleep(10 * msec);
torture_comment(tctx, "Doing a 10 byte write to extend the file to see if this changes the last write time.\n");
written = smbcli_write(cli->tree, fnum1, 0, "0123456789", 31, 10);
@@ -1187,7 +1187,7 @@ static bool test_delayed_write_update2(struct torture_context *tctx, struct smbc
break;
}
fflush(stdout);
- msleep(1*msec);
+ smb_msleep(1*msec);
}
if (finfo1.basic_info.out.write_time == finfo2.basic_info.out.write_time) {
@@ -1258,7 +1258,7 @@ static bool test_finfo_after_write(struct torture_context *tctx, struct smbcli_s
goto done;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
written = smbcli_write(cli->tree, fnum1, 0, "x", 0, 1);
@@ -1573,7 +1573,7 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
diff, sec);
break;
}
- msleep(0.5 * msec);
+ smb_msleep(0.5 * msec);
}
GET_INFO_BOTH(finfo1,pinfo1);
@@ -1602,7 +1602,7 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo2,pinfo2);
@@ -1612,7 +1612,7 @@ static bool test_delayed_write_update3(struct torture_context *tctx,
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
GET_INFO_BOTH(finfo3,pinfo3);
COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
@@ -1699,7 +1699,7 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
* sleep some time, to demonstrate the handling of write times
* doesn't depend on the time since the open
*/
- msleep(5 * msec);
+ smb_msleep(5 * msec);
/* get the initial times */
GET_INFO_BOTH(finfo1,pinfo1);
@@ -1739,20 +1739,20 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
diff, sec);
break;
}
- msleep(0.5 * msec);
+ smb_msleep(0.5 * msec);
}
GET_INFO_BOTH(finfo1,pinfo1);
COMPARE_WRITE_TIME_GREATER(pinfo1, pinfo0);
- msleep(3 * msec);
+ smb_msleep(3 * msec);
/*
* demonstrate that a truncate write always
* updates the write time immediately
*/
for (i=0; i < 3; i++) {
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* do a write */
torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
written = smbcli_smbwrite(cli->tree, fnum1, "x", 10240, 0);
@@ -1767,7 +1767,7 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
finfo1 = finfo2;
}
- msleep(3 * msec);
+ smb_msleep(3 * msec);
/* sure any further write doesn't update the write time */
start = timeval_current();
@@ -1792,7 +1792,7 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo2,pinfo2);
@@ -1802,7 +1802,7 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
}
/* sleep */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
/* get the initial times */
GET_INFO_BOTH(finfo1,pinfo1);
@@ -1813,7 +1813,7 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
* updates the write time immediately
*/
for (i=0; i < 3; i++) {
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* do a write */
torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
@@ -1829,7 +1829,7 @@ static bool test_delayed_write_update3a(struct torture_context *tctx,
}
/* sleep */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
GET_INFO_BOTH(finfo3,pinfo3);
COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
@@ -1914,7 +1914,7 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
* sleep some time, to demonstrate the handling of write times
* doesn't depend on the time since the open
*/
- msleep(5 * msec);
+ smb_msleep(5 * msec);
/* get the initial times */
GET_INFO_BOTH(finfo1,pinfo1);
@@ -1954,7 +1954,7 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
diff, sec);
break;
}
- msleep(0.5 * msec);
+ smb_msleep(0.5 * msec);
}
GET_INFO_BOTH(finfo1,pinfo1);
@@ -1983,7 +1983,7 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo2,pinfo2);
@@ -1993,7 +1993,7 @@ static bool test_delayed_write_update3b(struct torture_context *tctx,
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
GET_INFO_BOTH(finfo3,pinfo3);
COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
@@ -2082,7 +2082,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
* sleep some time, to demonstrate the handling of write times
* doesn't depend on the time since the open
*/
- msleep(5 * msec);
+ smb_msleep(5 * msec);
/* get the initial times */
GET_INFO_BOTH(finfo1,pinfo1);
@@ -2093,7 +2093,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
* updates the write time immediately
*/
for (i=0; i < 3; i++) {
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* do a write */
torture_comment(tctx, "Do a truncate SMBwrite [%d] on the file handle\n", i);
written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
@@ -2130,7 +2130,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo2,pinfo2);
@@ -2140,7 +2140,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
/* get the initial times */
GET_INFO_BOTH(finfo1,pinfo1);
@@ -2151,7 +2151,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
* updates the write time immediately
*/
for (i=0; i < 3; i++) {
- msleep(2 * msec);
+ smb_msleep(2 * msec);
/* do a write */
torture_comment(tctx, "Do a truncate write [%d] on the file handle\n", i);
written = smbcli_smbwrite(cli->tree, fnum1, "x", 512, 0);
@@ -2167,7 +2167,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
GET_INFO_BOTH(finfo2,pinfo2);
COMPARE_WRITE_TIME_EQUAL(finfo2, finfo1);
@@ -2195,7 +2195,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo2,pinfo2);
@@ -2205,7 +2205,7 @@ static bool test_delayed_write_update3c(struct torture_context *tctx,
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
GET_INFO_BOTH(finfo3,pinfo3);
COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
@@ -2289,7 +2289,7 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
GET_INFO_BOTH(finfo0,pinfo0);
/* sleep a bit */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
/* do a write */
torture_comment(tctx, "Do a write on the file handle\n");
@@ -2329,7 +2329,7 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
diff, sec);
break;
}
- msleep(0.5 * msec);
+ smb_msleep(0.5 * msec);
}
GET_INFO_BOTH(finfo1,pinfo1);
@@ -2358,7 +2358,7 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo2,pinfo2);
@@ -2368,7 +2368,7 @@ static bool test_delayed_write_update4(struct torture_context *tctx,
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
GET_INFO_BOTH(finfo3,pinfo3);
COMPARE_WRITE_TIME_EQUAL(finfo3, finfo2);
@@ -2489,7 +2489,7 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo3,pinfo3);
@@ -2521,7 +2521,7 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo4,pinfo4);
@@ -2531,7 +2531,7 @@ static bool test_delayed_write_update5(struct torture_context *tctx,
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
GET_INFO_BOTH(finfo5,pinfo5);
COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
@@ -2651,7 +2651,7 @@ static bool test_delayed_write_update5b(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo3,pinfo3);
@@ -2683,7 +2683,7 @@ static bool test_delayed_write_update5b(struct torture_context *tctx,
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo4,pinfo4);
@@ -2693,7 +2693,7 @@ static bool test_delayed_write_update5b(struct torture_context *tctx,
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
GET_INFO_BOTH(finfo5,pinfo5);
COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
@@ -2830,7 +2830,7 @@ again:
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo3,pinfo3);
@@ -2862,7 +2862,7 @@ again:
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
GET_INFO_BOTH(finfo4,pinfo4);
@@ -2872,7 +2872,7 @@ again:
}
/* sleep */
- msleep(5 * msec);
+ smb_msleep(5 * msec);
GET_INFO_BOTH(finfo5,pinfo5);
COMPARE_WRITE_TIME_EQUAL(finfo5, finfo4);
@@ -2898,7 +2898,7 @@ again:
COMPARE_WRITE_TIME_EQUAL(finfo5, pinfo6);
/* See if we have lost the sticky write time on handle2 */
- msleep(3 * msec);
+ smb_msleep(3 * msec);
torture_comment(tctx, "Have we lost the sticky write time ?\n");
/* Make sure any further normal write doesn't update the write time */
@@ -2925,7 +2925,7 @@ again:
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
/* What about a truncate write ? */
@@ -2952,7 +2952,7 @@ again:
ret = false;
break;
}
- msleep(1 * msec);
+ smb_msleep(1 * msec);
}
diff --git a/source4/torture/basic/delete.c b/source4/torture/basic/delete.c
index 22d92193b9..2b26b1e64a 100644
--- a/source4/torture/basic/delete.c
+++ b/source4/torture/basic/delete.c
@@ -1422,7 +1422,7 @@ static bool deltest21(struct torture_context *tctx)
/* On slow build farm machines it might happen that they are not fast
* enogh to delete the file for this test */
- msleep(200);
+ smb_msleep(200);
/* File should not be there. */
fnum1 = smbcli_nt_create_full(cli1->tree, fname, 0,
diff --git a/source4/torture/basic/disconnect.c b/source4/torture/basic/disconnect.c
index 7f071178f4..2cfa72048e 100644
--- a/source4/torture/basic/disconnect.c
+++ b/source4/torture/basic/disconnect.c
@@ -162,7 +162,7 @@ bool torture_disconnect(struct torture_context *torture)
* new process comes in. Try to get rid of the random
* failures in the build farm.
*/
- msleep(200);
+ smb_msleep(200);
}
}
diff --git a/source4/torture/config.mk b/source4/torture/config.mk
index 9ee2edfdd0..4e5c852df7 100644
--- a/source4/torture/config.mk
+++ b/source4/torture/config.mk
@@ -95,7 +95,7 @@ mkinclude libsmbclient/config.mk
[SUBSYSTEM::TORTURE_NDR]
PRIVATE_DEPENDENCIES = torture SERVICE_SMB
-TORTURE_NDR_OBJ_FILES = $(addprefix $(torturesrcdir)/ndr/, ndr.o winreg.o atsvc.o lsa.o epmap.o dfs.o netlogon.o drsuapi.o spoolss.o samr.o dfsblob.o drsblobs.o nbt.o)
+TORTURE_NDR_OBJ_FILES = $(addprefix $(torturesrcdir)/ndr/, ndr.o winreg.o atsvc.o lsa.o epmap.o dfs.o netlogon.o drsuapi.o spoolss.o samr.o dfsblob.o drsblobs.o nbt.o ntlmssp.o)
$(eval $(call proto_header_template,$(torturesrcdir)/ndr/proto.h,$(TORTURE_NDR_OBJ_FILES:.o=.c)))
diff --git a/source4/torture/drs/python/fsmo.py b/source4/torture/drs/python/fsmo.py
index c64a0b2987..9b13275e18 100644
--- a/source4/torture/drs/python/fsmo.py
+++ b/source4/torture/drs/python/fsmo.py
@@ -148,6 +148,10 @@ class DrsFsmoTestCase(samba.tests.TestCase):
self._role_transfer(role="rid", role_dn=self.rid_dn)
pass
+ def test_NamingMasterTransfer(self):
+ self._role_transfer(role="naming", role_dn=self.naming_dn)
+ pass
+
########################################################################################
def get_env_var(var_name):
diff --git a/source4/torture/drs/unit/prefixmap_tests.c b/source4/torture/drs/unit/prefixmap_tests.c
index a4521eb675..a954399771 100644
--- a/source4/torture/drs/unit/prefixmap_tests.c
+++ b/source4/torture/drs/unit/prefixmap_tests.c
@@ -394,8 +394,13 @@ static bool torture_drs_unit_pfm_oid_from_attid_check_attid(struct torture_conte
const char *oid;
/* Test with valid prefixMap attid */
- werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x00000000, tctx, &oid);
- torture_assert_werr_ok(tctx, werr, "Testing prefixMap type attid = 0x0000000");
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x00010001, tctx, &oid);
+ torture_assert_werr_ok(tctx, werr, "Testing prefixMap type attid = 0x00010001");
+
+ /* Test with valid attid but invalid index */
+ werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x01110001, tctx, &oid);
+ torture_assert_werr_equal(tctx, werr, WERR_DS_NO_ATTRIBUTE_OR_VALUE,
+ "Testing invalid-index attid = 0x01110001");
/* Test with attid in msDS-IntId range */
werr = dsdb_schema_pfm_oid_from_attid(priv->pfm_full, 0x80000000, tctx, &oid);
diff --git a/source4/torture/drs/unit/schemainfo_tests.c b/source4/torture/drs/unit/schemainfo_tests.c
index 3958eb365b..e419ab0c49 100644
--- a/source4/torture/drs/unit/schemainfo_tests.c
+++ b/source4/torture/drs/unit/schemainfo_tests.c
@@ -297,6 +297,82 @@ static bool test_dsdb_blob_from_schema_info(struct torture_context *tctx,
return true;
}
+static bool test_dsdb_schema_info_cmp(struct torture_context *tctx,
+ struct drsut_schemainfo_data *priv)
+{
+ DATA_BLOB blob;
+ struct drsuapi_DsReplicaOIDMapping_Ctr *ctr;
+
+ ctr = talloc_zero(priv, struct drsuapi_DsReplicaOIDMapping_Ctr);
+ torture_assert(tctx, ctr, "Not enough memory!");
+
+ /* not enough elements */
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* an empty element for schemaInfo */
+ ctr->num_mappings = 1;
+ ctr->mappings = talloc_zero_array(ctr, struct drsuapi_DsReplicaOIDMapping, 1);
+ torture_assert(tctx, ctr->mappings, "Not enough memory!");
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with invalid schemaInfo - length != 21 */
+ blob = strhex_to_data_blob(ctr, "FF00000001FD821C07C7455143A3DB51F75A630A7F00");
+ torture_assert(tctx, blob.data, "Not enough memory!");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with invalid schemaInfo - marker != 0xFF */
+ blob = strhex_to_data_blob(ctr, "AA00000001FD821C07C7455143A3DB51F75A630A7F");
+ torture_assert(tctx, blob.data, "Not enough memory!");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo, but not correct one */
+ blob = strhex_to_data_blob(ctr, "FF0000000000000000000000000000000000000000");
+ torture_assert(tctx, blob.data, "Not enough memory!");
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_DS_DRA_SCHEMA_MISMATCH,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with correct schemaInfo, but invalid ATTID */
+ blob = strhex_to_data_blob(ctr, priv->schema->schema_info);
+ torture_assert(tctx, blob.data, "Not enough memory!");
+ ctr->mappings[0].id_prefix = 1;
+ ctr->mappings[0].oid.length = blob.length;
+ ctr->mappings[0].oid.binary_oid = blob.data;
+ torture_assert_werr_equal(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ WERR_INVALID_PARAMETER,
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ /* test with valid schemaInfo */
+ blob = strhex_to_data_blob(ctr, priv->schema->schema_info);
+ ctr->mappings[0].id_prefix = 0;
+ torture_assert_werr_ok(tctx,
+ dsdb_schema_info_cmp(priv->schema, ctr),
+ "dsdb_schema_info_cmp(): unexpected result");
+
+ talloc_free(ctr);
+ return true;
+}
+
/*
* Tests dsdb_module_schema_info_blob_read()
* and dsdb_module_schema_info_blob_write()
@@ -515,6 +591,9 @@ static bool torture_drs_unit_schemainfo_setup(struct torture_context *tctx,
/* create schema mockup object */
priv->schema = dsdb_new_schema(priv);
+ /* set schema_info in dsdb_schema for testing */
+ priv->schema->schema_info = talloc_strdup(priv->schema, SCHEMA_INFO_DEFAULT_STR);
+
/* pre-cache invocationId for samdb_ntds_invocation_id()
* to work with our mock ldb */
ldb_err = ldb_set_opaque(priv->ldb, "cache.invocation_id",
@@ -575,6 +654,8 @@ struct torture_tcase * torture_drs_unit_schemainfo(struct torture_suite *suite)
(pfn_run)test_dsdb_schema_info_from_blob);
torture_tcase_add_simple_test(tc, "dsdb_blob_from_schema_info",
(pfn_run)test_dsdb_blob_from_schema_info);
+ torture_tcase_add_simple_test(tc, "dsdb_schema_info_cmp",
+ (pfn_run)test_dsdb_schema_info_cmp);
torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_blob read|write",
(pfn_run)test_dsdb_module_schema_info_blob_rw);
torture_tcase_add_simple_test(tc, "dsdb_module_schema_info_update",
diff --git a/source4/torture/gentest.c b/source4/torture/gentest.c
index 4fc05df3f4..6f69460dc8 100644
--- a/source4/torture/gentest.c
+++ b/source4/torture/gentest.c
@@ -1211,7 +1211,7 @@ static void check_pending(void)
{
int i, j;
- msleep(20);
+ smb_msleep(20);
for (j=0;j<NINSTANCES;j++) {
for (i=0;i<NSERVERS;i++) {
diff --git a/source4/torture/libnetapi/config.mk b/source4/torture/libnetapi/config.mk
index 2ac506e1b2..0cd485e44a 100644
--- a/source4/torture/libnetapi/config.mk
+++ b/source4/torture/libnetapi/config.mk
@@ -12,6 +12,7 @@ PRIVATE_DEPENDENCIES = \
TORTURE_LIBNETAPI_OBJ_FILES = $(addprefix $(torturesrcdir)/libnetapi/, libnetapi.o \
libnetapi_user.o \
- libnetapi_group.o)
+ libnetapi_group.o
+ libnetapi_server.o)
$(eval $(call proto_header_template,$(torturesrcdir)/libnetapi/proto.h,$(TORTURE_LIBNETAPI_OBJ_FILES:.o=.c)))
diff --git a/source4/torture/libnetapi/libnetapi.c b/source4/torture/libnetapi/libnetapi.c
index c3a27eba0c..6854bf8444 100644
--- a/source4/torture/libnetapi/libnetapi.c
+++ b/source4/torture/libnetapi/libnetapi.c
@@ -68,6 +68,7 @@ NTSTATUS torture_libnetapi_init(void)
suite = torture_suite_create(talloc_autofree_context(), "NETAPI");
+ torture_suite_add_simple_test(suite, "SERVER", torture_libnetapi_server);
torture_suite_add_simple_test(suite, "GROUP", torture_libnetapi_group);
torture_suite_add_simple_test(suite, "USER", torture_libnetapi_user);
torture_suite_add_simple_test(suite, "INITIALIZE", torture_libnetapi_initialize);
diff --git a/source4/torture/libnetapi/libnetapi_server.c b/source4/torture/libnetapi/libnetapi_server.c
new file mode 100644
index 0000000000..1888009402
--- /dev/null
+++ b/source4/torture/libnetapi/libnetapi_server.c
@@ -0,0 +1,76 @@
+/*
+ Unix SMB/CIFS implementation.
+ SMB torture tester
+ Copyright (C) Guenther Deschner 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "torture/smbtorture.h"
+#include <netapi.h>
+#include "torture/libnetapi/proto.h"
+
+#define NETAPI_STATUS(tctx, x,y,fn) \
+ torture_warning(tctx, "FAILURE: line %d: %s failed with status: %s (%d)\n", \
+ __LINE__, fn, libnetapi_get_error_string(x,y), y);
+
+bool torture_libnetapi_server(struct torture_context *tctx)
+{
+ NET_API_STATUS status = 0;
+ uint8_t *buffer = NULL;
+ int i;
+
+ const char *hostname = torture_setting_string(tctx, "host", NULL);
+ struct libnetapi_ctx *ctx;
+
+ torture_assert(tctx, torture_libnetapi_init_context(tctx, &ctx),
+ "failed to initialize libnetapi");
+
+ torture_comment(tctx, "NetServer tests\n");
+
+ torture_comment(tctx, "Testing NetRemoteTOD\n");
+
+ status = NetRemoteTOD(hostname, &buffer);
+ if (status) {
+ NETAPI_STATUS(tctx, ctx, status, "NetRemoteTOD");
+ goto out;
+ }
+ NetApiBufferFree(buffer);
+
+ torture_comment(tctx, "Testing NetRemoteTOD 10 times\n");
+
+ for (i=0; i<10; i++) {
+ status = NetRemoteTOD(hostname, &buffer);
+ if (status) {
+ NETAPI_STATUS(tctx, ctx, status, "NetRemoteTOD");
+ goto out;
+ }
+ NetApiBufferFree(buffer);
+ }
+
+ status = 0;
+
+ torture_comment(tctx, "NetServer tests succeeded\n");
+ out:
+ if (status != 0) {
+ torture_comment(tctx, "NetServer testsuite failed with: %s\n",
+ libnetapi_get_error_string(ctx, status));
+ libnetapi_free(ctx);
+ return false;
+ }
+
+ libnetapi_free(ctx);
+ return true;
+}
diff --git a/source4/torture/libnetapi/wscript_build b/source4/torture/libnetapi/wscript_build
index ddcc602f88..a087c96662 100644
--- a/source4/torture/libnetapi/wscript_build
+++ b/source4/torture/libnetapi/wscript_build
@@ -1,7 +1,7 @@
#!/usr/bin/env python
bld.SAMBA_MODULE('TORTURE_LIBNETAPI',
- source='libnetapi.c libnetapi_user.c libnetapi_group.c',
+ source='libnetapi.c libnetapi_user.c libnetapi_group.c libnetapi_server.c',
autoproto='proto.h',
subsystem='smbtorture',
init_function='torture_libnetapi_init',
diff --git a/source4/torture/nbench/nbio.c b/source4/torture/nbench/nbio.c
index fa8155e2c3..ca186d007b 100644
--- a/source4/torture/nbench/nbio.c
+++ b/source4/torture/nbench/nbio.c
@@ -192,7 +192,7 @@ void nbio_target_rate(double rate)
tdelay = (children[nbio_id].bytes - last_bytes)/(1.0e6*rate) - timeval_elapsed(&last_time);
if (tdelay > 0) {
- msleep(tdelay*1000);
+ smb_msleep(tdelay*1000);
} else {
children[nbio_id].max_latency = MAX(children[nbio_id].max_latency, -tdelay);
}
@@ -210,7 +210,7 @@ void nbio_time_delay(double targett)
{
double elapsed = timeval_elapsed(&children[nbio_id].starttime);
if (targett > elapsed) {
- msleep(1000*(targett - elapsed));
+ smb_msleep(1000*(targett - elapsed));
} else if (elapsed - targett > children[nbio_id].max_latency) {
children[nbio_id].max_latency = MAX(elapsed - targett, children[nbio_id].max_latency);
}
diff --git a/source4/torture/nbt/winsreplication.c b/source4/torture/nbt/winsreplication.c
index a0d4c23ae7..caa2d33ede 100644
--- a/source4/torture/nbt/winsreplication.c
+++ b/source4/torture/nbt/winsreplication.c
@@ -9599,7 +9599,7 @@ static void test_conflict_owned_active_vs_replica_handler_query(struct nbt_name_
while (nbtsock->send_queue) {
event_loop_once(nbtsock->event_ctx);
}
- msleep(1000);
+ smb_msleep(1000);
rec->defend.timeout = 0;
rec->defend.ret = true;
@@ -9656,7 +9656,7 @@ static void test_conflict_owned_active_vs_replica_handler_release(
while (nbtsock->send_queue) {
event_loop_once(nbtsock->event_ctx);
}
- msleep(1000);
+ smb_msleep(1000);
rec->defend.timeout = 0;
rec->defend.ret = true;
diff --git a/source4/torture/ndr/ndr.c b/source4/torture/ndr/ndr.c
index e13cb94bbd..8c2e7f8e45 100644
--- a/source4/torture/ndr/ndr.c
+++ b/source4/torture/ndr/ndr.c
@@ -353,6 +353,7 @@ struct torture_suite *torture_local_ndr(TALLOC_CTX *mem_ctx)
torture_suite_add_suite(suite, ndr_samr_suite(suite));
torture_suite_add_suite(suite, ndr_drsblobs_suite(suite));
torture_suite_add_suite(suite, ndr_nbt_suite(suite));
+ torture_suite_add_suite(suite, ndr_ntlmssp_suite(suite));
torture_suite_add_simple_test(suite, "string terminator",
test_check_string_terminator);
diff --git a/source4/torture/ndr/ntlmssp.c b/source4/torture/ndr/ntlmssp.c
new file mode 100644
index 0000000000..b139fdf232
--- /dev/null
+++ b/source4/torture/ndr/ntlmssp.c
@@ -0,0 +1,119 @@
+/*
+ Unix SMB/CIFS implementation.
+ test suite for ntlmssp ndr operations
+
+ Copyright (C) Guenther Deschner 2010
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "torture/ndr/ndr.h"
+#include "librpc/gen_ndr/ndr_ntlmssp.h"
+
+static const uint8_t ntlmssp_NEGOTIATE_MESSAGE_data[] = {
+ 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x01, 0x00, 0x00, 0x00,
+ 0x97, 0x82, 0x08, 0xe2, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x01, 0xb0, 0x1d,
+ 0x00, 0x00, 0x00, 0x0f
+};
+
+static bool ntlmssp_NEGOTIATE_MESSAGE_check(struct torture_context *tctx,
+ struct NEGOTIATE_MESSAGE *r)
+{
+ return true;
+}
+
+static const uint8_t ntlmssp_CHALLENGE_MESSAGE_data[] = {
+ 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x02, 0x00, 0x00, 0x00,
+ 0x0a, 0x00, 0x0a, 0x00, 0x38, 0x00, 0x00, 0x00, 0x95, 0x82, 0x89, 0xe2,
+ 0xed, 0xc8, 0x2b, 0x7d, 0x2e, 0xd7, 0xd0, 0xd9, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x78, 0x00, 0x78, 0x00, 0x42, 0x00, 0x00, 0x00,
+ 0x06, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0f, 0x53, 0x00, 0x41, 0x00,
+ 0x4d, 0x00, 0x42, 0x00, 0x41, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x53, 0x00,
+ 0x41, 0x00, 0x4d, 0x00, 0x42, 0x00, 0x41, 0x00, 0x01, 0x00, 0x10, 0x00,
+ 0x4d, 0x00, 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x45, 0x00,
+ 0x4e, 0x00, 0x41, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x62, 0x00, 0x65, 0x00,
+ 0x72, 0x00, 0x2e, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x68, 0x00,
+ 0x61, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00,
+ 0x03, 0x00, 0x2e, 0x00, 0x6d, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00,
+ 0x6c, 0x00, 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x2e, 0x00, 0x62, 0x00,
+ 0x65, 0x00, 0x72, 0x00, 0x2e, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00,
+ 0x68, 0x00, 0x61, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00,
+ 0x6d, 0x00, 0x00, 0x00, 0x00, 0x00
+};
+
+static bool ntlmssp_CHALLENGE_MESSAGE_check(struct torture_context *tctx,
+ struct CHALLENGE_MESSAGE *r)
+{
+ return true;
+}
+
+static const uint8_t ntlmssp_AUTHENTICATE_MESSAGE_data[] = {
+ 0x4e, 0x54, 0x4c, 0x4d, 0x53, 0x53, 0x50, 0x00, 0x03, 0x00, 0x00, 0x00,
+ 0x18, 0x00, 0x18, 0x00, 0x8c, 0x00, 0x00, 0x00, 0x0e, 0x01, 0x0e, 0x01,
+ 0xa4, 0x00, 0x00, 0x00, 0x0e, 0x00, 0x0e, 0x00, 0x58, 0x00, 0x00, 0x00,
+ 0x1a, 0x00, 0x1a, 0x00, 0x66, 0x00, 0x00, 0x00, 0x0c, 0x00, 0x0c, 0x00,
+ 0x80, 0x00, 0x00, 0x00, 0x10, 0x00, 0x10, 0x00, 0xb2, 0x01, 0x00, 0x00,
+ 0x15, 0x82, 0x88, 0xe2, 0x06, 0x01, 0xb0, 0x1d, 0x00, 0x00, 0x00, 0x0f,
+ 0x50, 0xe2, 0xb2, 0xa7, 0xf5, 0x83, 0x3e, 0xda, 0x71, 0xa7, 0xe8, 0x6e,
+ 0x95, 0x1e, 0x3a, 0x57, 0x57, 0x00, 0x32, 0x00, 0x4b, 0x00, 0x38, 0x00,
+ 0x44, 0x00, 0x4f, 0x00, 0x4d, 0x00, 0x41, 0x00, 0x64, 0x00, 0x6d, 0x00,
+ 0x69, 0x00, 0x6e, 0x00, 0x69, 0x00, 0x73, 0x00, 0x74, 0x00, 0x72, 0x00,
+ 0x61, 0x00, 0x74, 0x00, 0x6f, 0x00, 0x72, 0x00, 0x57, 0x00, 0x32, 0x00,
+ 0x4b, 0x00, 0x38, 0x00, 0x52, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x38, 0xcf, 0xfb, 0x39,
+ 0x5a, 0xb3, 0x4c, 0x58, 0x86, 0x35, 0xa3, 0xe7, 0x1e, 0x00, 0x98, 0x43,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x96, 0x79, 0x02, 0x77,
+ 0x1e, 0x54, 0xcb, 0x01, 0x3c, 0x21, 0x0a, 0xe9, 0xde, 0x61, 0xc0, 0x7e,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x0a, 0x00, 0x53, 0x00, 0x41, 0x00,
+ 0x4d, 0x00, 0x42, 0x00, 0x41, 0x00, 0x01, 0x00, 0x10, 0x00, 0x4d, 0x00,
+ 0x54, 0x00, 0x48, 0x00, 0x45, 0x00, 0x4c, 0x00, 0x45, 0x00, 0x4e, 0x00,
+ 0x41, 0x00, 0x04, 0x00, 0x1c, 0x00, 0x62, 0x00, 0x65, 0x00, 0x72, 0x00,
+ 0x2e, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x68, 0x00, 0x61, 0x00,
+ 0x74, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00, 0x03, 0x00,
+ 0x2e, 0x00, 0x6d, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x2e, 0x00, 0x62, 0x00, 0x65, 0x00,
+ 0x72, 0x00, 0x2e, 0x00, 0x72, 0x00, 0x65, 0x00, 0x64, 0x00, 0x68, 0x00,
+ 0x61, 0x00, 0x74, 0x00, 0x2e, 0x00, 0x63, 0x00, 0x6f, 0x00, 0x6d, 0x00,
+ 0x08, 0x00, 0x30, 0x00, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x30, 0x00, 0x00, 0x0a, 0xfd, 0x3b, 0x2c,
+ 0xad, 0x43, 0x46, 0x8b, 0x49, 0x01, 0x6c, 0xa5, 0xf3, 0xbc, 0xd2, 0x13,
+ 0xbb, 0x70, 0xe2, 0x65, 0x96, 0xba, 0x0d, 0x8d, 0x5d, 0x31, 0xe6, 0x47,
+ 0x94, 0x61, 0xed, 0x28, 0x0a, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x09, 0x00, 0x1a, 0x00, 0x63, 0x00, 0x69, 0x00, 0x66, 0x00, 0x73, 0x00,
+ 0x2f, 0x00, 0x6d, 0x00, 0x74, 0x00, 0x68, 0x00, 0x65, 0x00, 0x6c, 0x00,
+ 0x65, 0x00, 0x6e, 0x00, 0x61, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0xa4, 0x23, 0xd4, 0x5c, 0x16, 0x52, 0x8d, 0x56, 0x34, 0x2d,
+ 0x1c, 0xff, 0x86, 0x17, 0xc9, 0x4f
+};
+
+static bool ntlmssp_AUTHENTICATE_MESSAGE_check(struct torture_context *tctx,
+ struct AUTHENTICATE_MESSAGE *r)
+{
+ return true;
+}
+
+struct torture_suite *ndr_ntlmssp_suite(TALLOC_CTX *ctx)
+{
+ struct torture_suite *suite = torture_suite_create(ctx, "ntlmssp");
+
+ torture_suite_add_ndr_pull_fn_test(suite, NEGOTIATE_MESSAGE, ntlmssp_NEGOTIATE_MESSAGE_data, NDR_IN, ntlmssp_NEGOTIATE_MESSAGE_check);
+ /* torture_suite_add_ndr_pull_fn_test(suite, CHALLENGE_MESSAGE, ntlmssp_CHALLENGE_MESSAGE_data, NDR_IN, ntlmssp_CHALLENGE_MESSAGE_check);
+ torture_suite_add_ndr_pull_fn_test(suite, AUTHENTICATE_MESSAGE, ntlmssp_AUTHENTICATE_MESSAGE_data, NDR_IN, ntlmssp_AUTHENTICATE_MESSAGE_check); */
+
+ return suite;
+}
diff --git a/source4/torture/ndr/winreg.c b/source4/torture/ndr/winreg.c
index ca3a71ed7d..b6da7bccd2 100644
--- a/source4/torture/ndr/winreg.c
+++ b/source4/torture/ndr/winreg.c
@@ -247,7 +247,7 @@ static bool querymultiplevalues_in_check(struct torture_context *tctx,
torture_assert_int_equal(tctx, r->in.values_in[0].ve_valuename->length, 18, "name len");
torture_assert_int_equal(tctx, r->in.values_in[0].ve_valuename->size, 18, "name size");
torture_assert_int_equal(tctx, r->in.values_in[0].ve_valuelen, 0, "length");
- torture_assert(tctx, (r->in.values_in[0].ve_valueptr == NULL), "ve_valueptr");
+ torture_assert_int_equal(tctx, r->in.values_in[0].ve_valueptr, 0, "ve_valueptr");
torture_assert_int_equal(tctx, r->in.values_in[0].ve_type, 0, "type");
torture_assert_int_equal(tctx, *r->in.buffer_size, 32, "buffer size");
@@ -303,7 +303,7 @@ static bool querymultiplevalues2_in_check(struct torture_context *tctx,
torture_assert_int_equal(tctx, r->in.values_in[0].ve_valuename->length, 10, "name len");
torture_assert_int_equal(tctx, r->in.values_in[0].ve_valuename->size, 10, "name size");
torture_assert_int_equal(tctx, r->in.values_in[0].ve_valuelen, 0, "length");
- torture_assert(tctx, (r->in.values_in[0].ve_valueptr == NULL), "ve_valueptr");
+ torture_assert_int_equal(tctx, r->in.values_in[0].ve_valueptr, 0, "ve_valueptr");
torture_assert_int_equal(tctx, r->in.values_in[0].ve_type, 0, "type");
torture_assert_int_equal(tctx, *r->in.offered, 0, "buffer size");
diff --git a/source4/torture/raw/notify.c b/source4/torture/raw/notify.c
index 6fc005929c..7ccdbd7c76 100644
--- a/source4/torture/raw/notify.c
+++ b/source4/torture/raw/notify.c
@@ -144,7 +144,7 @@ static bool test_notify_dir(struct smbcli_state *cli, struct smbcli_state *cli2,
smbcli_rmdir(cli2->tree, BASEDIR "\\subdir-name");
smbcli_mkdir(cli2->tree, BASEDIR "\\subdir-name");
smbcli_rmdir(cli2->tree, BASEDIR "\\subdir-name");
- msleep(200);
+ smb_msleep(200);
req = smb_raw_changenotify_send(cli->tree, &notify);
status = smb_raw_changenotify_recv(req, mem_ctx, &notify);
CHECK_STATUS(status, NT_STATUS_OK);
@@ -365,7 +365,7 @@ static bool test_notify_recursive(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
notify.nttrans.in.completion_filter = 0;
notify.nttrans.in.recursive = true;
- msleep(200);
+ smb_msleep(200);
req1 = smb_raw_changenotify_send(cli->tree, &notify);
smbcli_rmdir(cli->tree, BASEDIR "\\subdir-name\\subname1-r");
@@ -602,7 +602,7 @@ static bool test_notify_mask(struct smbcli_state *cli, struct torture_context *t
notify.nttrans.in.completion_filter = (1<<i); \
req = smb_raw_changenotify_send(cli->tree, &notify); \
op \
- msleep(200); smb_raw_ntcancel(req); \
+ smb_msleep(200); smb_raw_ntcancel(req); \
status = smb_raw_changenotify_recv(req, tctx, &notify); \
cleanup \
smbcli_close(cli->tree, fnum); \
@@ -1420,7 +1420,7 @@ static bool test_notify_basedir(struct smbcli_state *cli, TALLOC_CTX *mem_ctx)
/* set attribute on a file to assure we receive a notification */
smbcli_setatr(cli->tree, BASEDIR "\\tname1", FILE_ATTRIBUTE_HIDDEN, 0);
- msleep(200);
+ smb_msleep(200);
/* check how many responses were given, expect only 1 for the file */
status = smb_raw_changenotify_recv(req1, mem_ctx, &notify);
diff --git a/source4/torture/rpc/handles.c b/source4/torture/rpc/handles.c
index f47789ae60..13357ac947 100644
--- a/source4/torture/rpc/handles.c
+++ b/source4/torture/rpc/handles.c
@@ -287,7 +287,7 @@ static bool test_handles_lsa_shared(struct torture_context *torture)
/* close first connection */
torture_comment(torture, "disconnect p1\n");
talloc_free(p1);
- msleep(5);
+ smb_msleep(5);
/*
* and it's still available on p2,p3
@@ -327,7 +327,7 @@ static bool test_handles_lsa_shared(struct torture_context *torture)
talloc_free(p2);
talloc_free(p3);
talloc_free(p4);
- msleep(10);
+ smb_msleep(10);
/*
* now open p5
@@ -455,7 +455,7 @@ static bool test_handles_mixed_shared(struct torture_context *torture)
talloc_free(p1);
talloc_free(p2);
- msleep(10);
+ smb_msleep(10);
torture_comment(torture, "connect samr pipe3 - should fail\n");
status = torture_rpc_connection_transport(torture, &p3, &ndr_table_samr,
diff --git a/source4/torture/rpc/lsa.c b/source4/torture/rpc/lsa.c
index 9283fc3e31..a1ad9fde1d 100644
--- a/source4/torture/rpc/lsa.c
+++ b/source4/torture/rpc/lsa.c
@@ -1435,7 +1435,7 @@ static bool test_CreateSecret(struct dcerpc_pipe *p,
r5.in.new_val->size = enc_key.length;
- msleep(200);
+ smb_msleep(200);
torture_comment(tctx, "Testing SetSecret (existing value should move to old)\n");
torture_assert_ntstatus_ok(tctx, dcerpc_lsa_SetSecret_r(b, tctx, &r5),
diff --git a/source4/torture/rpc/netlogon.c b/source4/torture/rpc/netlogon.c
index b83b050fb2..c2eb872462 100644
--- a/source4/torture/rpc/netlogon.c
+++ b/source4/torture/rpc/netlogon.c
@@ -2911,7 +2911,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
torture_assert_ntstatus_ok(tctx, r.out.result, "LogonGetDomainInfo failed");
torture_assert(tctx, netlogon_creds_client_check(creds, &a.cred), "Credential chaining failed");
- msleep(250);
+ smb_msleep(250);
if (sam_ctx) {
/* AD workstation infos entry check */
@@ -3000,7 +3000,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
torture_assert(tctx, netlogon_creds_client_check(creds, &a.cred), "Credential chaining failed");
- msleep(250);
+ smb_msleep(250);
if (sam_ctx) {
/* AD workstation infos entry check */
@@ -3076,7 +3076,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
torture_assert_ntstatus_ok(tctx, r.out.result, "LogonGetDomainInfo failed");
torture_assert(tctx, netlogon_creds_client_check(creds, &a.cred), "Credential chaining failed");
- msleep(250);
+ smb_msleep(250);
if (sam_ctx) {
/* AD workstation infos entry check */
@@ -3147,7 +3147,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
torture_assert_ntstatus_ok(tctx, r.out.result, "LogonGetDomainInfo failed");
torture_assert(tctx, netlogon_creds_client_check(creds, &a.cred), "Credential chaining failed");
- msleep(250);
+ smb_msleep(250);
/* Now the in/out DNS hostnames should be the same */
torture_assert_str_equal(tctx,
@@ -3181,7 +3181,7 @@ static bool test_GetDomainInfo(struct torture_context *tctx,
torture_assert_ntstatus_ok(tctx, r.out.result, "LogonGetDomainInfo failed");
torture_assert(tctx, netlogon_creds_client_check(creds, &a.cred), "Credential chaining failed");
- msleep(250);
+ smb_msleep(250);
/* Checks "workstation flags" */
torture_assert(tctx,
diff --git a/source4/torture/rpc/svcctl.c b/source4/torture/rpc/svcctl.c
index 8f9ec1aed8..5ad678fe0e 100644
--- a/source4/torture/rpc/svcctl.c
+++ b/source4/torture/rpc/svcctl.c
@@ -1,6 +1,6 @@
/*
Unix SMB/CIFS implementation.
- test suite for srvsvc rpc operations
+ test suite for svcctl rpc operations
Copyright (C) Jelmer Vernooij 2004
Copyright (C) Guenther Deschner 2008,2009
@@ -324,6 +324,65 @@ static bool test_QueryServiceObjectSecurity(struct torture_context *tctx,
return true;
}
+static bool test_SetServiceObjectSecurity(struct torture_context *tctx,
+ struct dcerpc_pipe *p)
+{
+ struct svcctl_QueryServiceObjectSecurity q;
+ struct svcctl_SetServiceObjectSecurity r;
+ struct policy_handle h, s;
+ struct dcerpc_binding_handle *b = p->binding_handle;
+
+ uint8_t *buffer;
+ uint32_t needed;
+
+ if (!test_OpenSCManager(b, tctx, &h))
+ return false;
+
+ if (!test_OpenService(b, tctx, &h, TORTURE_DEFAULT_SERVICE, &s))
+ return false;
+
+ q.in.handle = &s;
+ q.in.security_flags = SECINFO_DACL;
+ q.in.offered = 0;
+ q.out.buffer = NULL;
+ q.out.needed = &needed;
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
+ "QueryServiceObjectSecurity failed!");
+
+ if (W_ERROR_EQUAL(q.out.result, WERR_INSUFFICIENT_BUFFER)) {
+ q.in.offered = needed;
+ buffer = talloc_array(tctx, uint8_t, needed);
+ q.out.buffer = buffer;
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_svcctl_QueryServiceObjectSecurity_r(b, tctx, &q),
+ "QueryServiceObjectSecurity failed!");
+ }
+
+ torture_assert_werr_ok(tctx, q.out.result,
+ "QueryServiceObjectSecurity failed!");
+
+ r.in.handle = &s;
+ r.in.security_flags = SECINFO_DACL;
+ r.in.buffer = q.out.buffer;
+ r.in.offered = *q.out.needed;
+
+ torture_assert_ntstatus_ok(tctx,
+ dcerpc_svcctl_SetServiceObjectSecurity_r(b, tctx, &r),
+ "SetServiceObjectSecurity failed!");
+ torture_assert_werr_ok(tctx, r.out.result,
+ "SetServiceObjectSecurity failed!");
+
+ if (!test_CloseServiceHandle(b, tctx, &s))
+ return false;
+
+ if (!test_CloseServiceHandle(b, tctx, &h))
+ return false;
+
+ return true;
+}
+
static bool test_StartServiceW(struct torture_context *tctx,
struct dcerpc_pipe *p)
{
@@ -570,6 +629,8 @@ struct torture_suite *torture_rpc_svcctl(TALLOC_CTX *mem_ctx)
test_QueryServiceConfig2W);
torture_rpc_tcase_add_test(tcase, "QueryServiceObjectSecurity",
test_QueryServiceObjectSecurity);
+ torture_rpc_tcase_add_test(tcase, "SetServiceObjectSecurity",
+ test_SetServiceObjectSecurity);
torture_rpc_tcase_add_test(tcase, "StartServiceW",
test_StartServiceW);
torture_rpc_tcase_add_test(tcase, "ControlService",
diff --git a/source4/torture/smb2/lease.c b/source4/torture/smb2/lease.c
index 63285d40e0..eda3b97eea 100644
--- a/source4/torture/smb2/lease.c
+++ b/source4/torture/smb2/lease.c
@@ -803,7 +803,7 @@ static bool test_lease_multibreak(struct torture_context *tctx,
break_info.held_oplock_level = io.out.oplock_level;
/* Sleep, use a write to clear the recv queue. */
- msleep(250);
+ smb_msleep(250);
ZERO_STRUCT(w);
w.in.file.handle = h3;
w.in.offset = 0;
diff --git a/source4/torture/smb2/notify.c b/source4/torture/smb2/notify.c
index 313ef6848f..0115cd0478 100644
--- a/source4/torture/smb2/notify.c
+++ b/source4/torture/smb2/notify.c
@@ -308,7 +308,7 @@ static bool torture_smb2_notify_dir(struct torture_context *torture,
smb2_util_rmdir(tree2, fname);
smb2_util_mkdir(tree2, fname);
smb2_util_rmdir(tree2, fname);
- msleep(200);
+ smb_msleep(200);
req = smb2_notify_send(tree1, &(notify.smb2));
status = smb2_notify_recv(req, torture, &(notify.smb2));
CHECK_STATUS(status, NT_STATUS_OK);
@@ -603,7 +603,7 @@ static bool torture_smb2_notify_recursive(struct torture_context *torture,
notify.smb2.in.completion_filter = 0;
notify.smb2.in.recursive = true;
- msleep(200);
+ smb_msleep(200);
req1 = smb2_notify_send(tree1, &(notify.smb2));
status = smb2_util_rmdir(tree2, BASEDIR "\\subdir-name\\subname1-r");
@@ -898,7 +898,7 @@ static bool torture_smb2_notify_mask(struct torture_context *torture,
/* send the change notify request */ \
req = smb2_notify_send(tree1, &(notify.smb2)); \
op \
- msleep(200); smb2_cancel(req); \
+ smb_msleep(200); smb2_cancel(req); \
status = smb2_notify_recv(req, torture, &(notify.smb2)); \
cleanup \
smb2_util_close(tree1, h1); \
@@ -1775,7 +1775,7 @@ static bool torture_smb2_notify_basedir(struct torture_context *torture,
/* set attribute on a file to assure we receive a notification */
smb2_util_setatr(tree2, BASEDIR "\\tname1", FILE_ATTRIBUTE_HIDDEN);
- msleep(200);
+ smb_msleep(200);
/* check how many responses were given, expect only 1 for the file */
status = smb2_notify_recv(req1, torture, &(notify.smb2));
diff --git a/source4/torture/util_smb.c b/source4/torture/util_smb.c
index 8d5accd2dc..df2716f316 100644
--- a/source4/torture/util_smb.c
+++ b/source4/torture/util_smb.c
@@ -699,7 +699,7 @@ double torture_create_procs(struct torture_context *tctx,
printf("pid %d failed to start\n", (int)getpid());
_exit(1);
}
- msleep(100);
+ smb_msleep(100);
}
child_status[i] = getpid();
@@ -723,7 +723,7 @@ double torture_create_procs(struct torture_context *tctx,
if (child_status[i]) synccount++;
}
if (synccount == torture_nprocs) break;
- msleep(100);
+ smb_msleep(100);
} while (timeval_elapsed(&tv) < start_time_limit);
if (synccount != torture_nprocs) {
diff --git a/source4/torture/wscript_build b/source4/torture/wscript_build
index 715bec502f..b576a5c95e 100644
--- a/source4/torture/wscript_build
+++ b/source4/torture/wscript_build
@@ -33,7 +33,7 @@ bld.RECURSE('libnetapi')
bld.RECURSE('libsmbclient')
bld.SAMBA_SUBSYSTEM('TORTURE_NDR',
- source='ndr/ndr.c ndr/winreg.c ndr/atsvc.c ndr/lsa.c ndr/epmap.c ndr/dfs.c ndr/netlogon.c ndr/drsuapi.c ndr/spoolss.c ndr/samr.c ndr/dfsblob.c ndr/drsblobs.c ndr/nbt.c',
+ source='ndr/ndr.c ndr/winreg.c ndr/atsvc.c ndr/lsa.c ndr/epmap.c ndr/dfs.c ndr/netlogon.c ndr/drsuapi.c ndr/spoolss.c ndr/samr.c ndr/dfsblob.c ndr/drsblobs.c ndr/nbt.c ndr/ntlmssp.c',
autoproto='ndr/proto.h',
deps='torture SERVICE_SMB'
)
diff --git a/source4/winbind/wb_irpc.c b/source4/winbind/wb_irpc.c
index bfb31e66a7..1eed89fd41 100644
--- a/source4/winbind/wb_irpc.c
+++ b/source4/winbind/wb_irpc.c
@@ -71,6 +71,52 @@ static void wb_irpc_SamLogon_callback(struct composite_context *ctx)
irpc_send_reply(s->msg, status);
}
+struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state {
+ struct irpc_message *msg;
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req;
+};
+
+static void wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback(struct composite_context *ctx);
+
+static NTSTATUS wb_irpc_DsrUpdateReadOnlyServerDnsRecords(struct irpc_message *msg,
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
+{
+ struct wbsrv_service *service = talloc_get_type(msg->private_data,
+ struct wbsrv_service);
+ struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state *s;
+ struct composite_context *ctx;
+
+ DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords called\n"));
+
+ s = talloc(msg, struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state);
+ NT_STATUS_HAVE_NO_MEMORY(s);
+
+ s->msg = msg;
+ s->req = req;
+
+ ctx = wb_update_rodc_dns_send(msg, service, req);
+ NT_STATUS_HAVE_NO_MEMORY(ctx);
+
+ ctx->async.fn = wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback;
+ ctx->async.private_data = s;
+
+ msg->defer_reply = true;
+ return NT_STATUS_OK;
+}
+
+static void wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback(struct composite_context *ctx)
+{
+ struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state *s = talloc_get_type(ctx->async.private_data,
+ struct wb_irpc_DsrUpdateReadOnlyServerDnsRecords_state);
+ NTSTATUS status;
+
+ DEBUG(5, ("wb_irpc_DsrUpdateReadOnlyServerDnsRecords_callback called\n"));
+
+ status = wb_update_rodc_dns_recv(ctx, s, s->req);
+
+ irpc_send_reply(s->msg, status);
+}
+
struct wb_irpc_get_idmap_state {
struct irpc_message *msg;
struct winbind_get_idmap *req;
@@ -149,6 +195,10 @@ NTSTATUS wbsrv_init_irpc(struct wbsrv_service *service)
wb_irpc_SamLogon, service);
NT_STATUS_NOT_OK_RETURN(status);
+ status = IRPC_REGISTER(service->task->msg_ctx, winbind, WINBIND_DSRUPDATEREADONLYSERVERDNSRECORDS,
+ wb_irpc_DsrUpdateReadOnlyServerDnsRecords, service);
+ NT_STATUS_NOT_OK_RETURN(status);
+
status = IRPC_REGISTER(service->task->msg_ctx, winbind, WINBIND_GET_IDMAP,
wb_irpc_get_idmap, service);
NT_STATUS_NOT_OK_RETURN(status);
diff --git a/source4/winbind/wb_server.h b/source4/winbind/wb_server.h
index ddb77d05f6..f20bc0aa51 100644
--- a/source4/winbind/wb_server.h
+++ b/source4/winbind/wb_server.h
@@ -176,6 +176,7 @@ struct wbsrv_samba3_call {
struct netr_LMSessionKey;
struct netr_UserSessionKey;
struct winbind_SamLogon;
+struct winbind_DsrUpdateReadOnlyServerDnsRecords;
#include "winbind/wb_async_helpers.h"
#include "winbind/wb_proto.h"
diff --git a/source4/winbind/wb_update_rodc_dns.c b/source4/winbind/wb_update_rodc_dns.c
new file mode 100644
index 0000000000..5ad2d0cbb0
--- /dev/null
+++ b/source4/winbind/wb_update_rodc_dns.c
@@ -0,0 +1,167 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Do a netr_DsrUpdateReadOnlyServerDnsRecords to a remote DC
+
+ Copyright (C) Andrew Bartlett 2010
+ Copyright (C) Andrew Tridgell 2010
+
+ based heavily on wb_sam_logon.c which is copyright:
+
+ Copyright (C) Volker Lendecke 2005
+ Copyright (C) Andrew Bartlett 2005
+ Copyright (C) Stefan Metzmacher 2006
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ GNU General Public License for more details.
+
+ You should have received a copy of the GNU General Public License
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "libcli/composite/composite.h"
+#include "winbind/wb_server.h"
+#include "smbd/service_task.h"
+#include "auth/credentials/credentials.h"
+#include "libcli/auth/libcli_auth.h"
+#include "librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/winbind.h"
+
+struct wb_update_rodc_dns_state {
+ struct composite_context *ctx;
+
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req;
+
+ struct netlogon_creds_CredentialState *creds_state;
+ struct netr_Authenticator auth1, auth2;
+
+ TALLOC_CTX *r_mem_ctx;
+ struct netr_DsrUpdateReadOnlyServerDnsRecords r;
+};
+
+static void wb_update_rodc_dns_recv_domain(struct composite_context *ctx);
+static void wb_update_rodc_dns_recv_response(struct tevent_req *subreq);
+
+/*
+ Find the connection to the DC (or find an existing connection)
+*/
+struct composite_context *wb_update_rodc_dns_send(TALLOC_CTX *mem_ctx,
+ struct wbsrv_service *service,
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
+{
+ struct composite_context *c, *creq;
+ struct wb_update_rodc_dns_state *s;
+
+ c = composite_create(mem_ctx, service->task->event_ctx);
+ if (!c) return NULL;
+
+ s = talloc_zero(c, struct wb_update_rodc_dns_state);
+ if (composite_nomem(s, c)) return c;
+ s->ctx = c;
+ s->req = req;
+
+ c->private_data = s;
+
+ creq = wb_sid2domain_send(s, service, service->primary_sid);
+ composite_continue(c, creq, wb_update_rodc_dns_recv_domain, s);
+ return c;
+}
+
+/*
+ Having finished making the connection to the DC
+ Send of a DsrUpdateReadOnlyServerDnsRecords request to authenticate a user.
+*/
+static void wb_update_rodc_dns_recv_domain(struct composite_context *creq)
+{
+ struct wb_update_rodc_dns_state *s = talloc_get_type(creq->async.private_data,
+ struct wb_update_rodc_dns_state);
+ struct wbsrv_domain *domain;
+ struct tevent_req *subreq;
+
+ s->ctx->status = wb_sid2domain_recv(creq, &domain);
+ if (!composite_is_ok(s->ctx)) return;
+
+ s->creds_state = cli_credentials_get_netlogon_creds(domain->libnet_ctx->cred);
+ netlogon_creds_client_authenticator(s->creds_state, &s->auth1);
+
+ s->r.in.server_name = talloc_asprintf(s, "\\\\%s",
+ dcerpc_server_name(domain->netlogon_pipe));
+ if (composite_nomem(s->r.in.server_name, s->ctx)) return;
+
+ s->r.in.computer_name = cli_credentials_get_workstation(domain->libnet_ctx->cred);
+ s->r.in.credential = &s->auth1;
+ s->r.out.return_authenticator = &s->auth2;
+ s->r.in.site_name = s->req->in.site_name;
+ s->r.in.dns_ttl = s->req->in.dns_ttl;
+ s->r.in.dns_names = s->req->in.dns_names;
+ s->r.out.dns_names = s->req->in.dns_names;
+
+ /*
+ * use a new talloc context for the DsrUpdateReadOnlyServerDnsRecords call
+ * because then we can just to a talloc_steal on this context
+ * in the final _recv() function to give the caller all the content of
+ * the s->r.out.dns_names
+ */
+ s->r_mem_ctx = talloc_new(s);
+ if (composite_nomem(s->r_mem_ctx, s->ctx)) return;
+
+ subreq = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_r_send(s,
+ s->ctx->event_ctx,
+ domain->netlogon_pipe->binding_handle,
+ &s->r);
+ if (composite_nomem(subreq, s->ctx)) return;
+ tevent_req_set_callback(subreq, wb_update_rodc_dns_recv_response, s);
+}
+
+/*
+ NTLM Authentication
+
+ Check the DsrUpdateReadOnlyServerDnsRecords reply and decrypt the session keys
+*/
+static void wb_update_rodc_dns_recv_response(struct tevent_req *subreq)
+{
+ struct wb_update_rodc_dns_state *s = tevent_req_callback_data(subreq,
+ struct wb_update_rodc_dns_state);
+
+ s->ctx->status = dcerpc_netr_DsrUpdateReadOnlyServerDnsRecords_r_recv(subreq, s->r_mem_ctx);
+ TALLOC_FREE(subreq);
+ if (!composite_is_ok(s->ctx)) return;
+
+ s->ctx->status = s->r.out.result;
+ if (!composite_is_ok(s->ctx)) return;
+
+ if ((s->r.out.return_authenticator == NULL) ||
+ (!netlogon_creds_client_check(s->creds_state,
+ &s->r.out.return_authenticator->cred))) {
+ DEBUG(0, ("Credentials check failed!\n"));
+ composite_error(s->ctx, NT_STATUS_ACCESS_DENIED);
+ return;
+ }
+
+ composite_done(s->ctx);
+}
+
+NTSTATUS wb_update_rodc_dns_recv(struct composite_context *c,
+ TALLOC_CTX *mem_ctx,
+ struct winbind_DsrUpdateReadOnlyServerDnsRecords *req)
+{
+ struct wb_update_rodc_dns_state *s = talloc_get_type(c->private_data,
+ struct wb_update_rodc_dns_state);
+ NTSTATUS status = composite_wait(c);
+
+ if (NT_STATUS_IS_OK(status)) {
+ talloc_steal(mem_ctx, s->r_mem_ctx);
+ req->out.dns_names = s->r.out.dns_names;
+ }
+
+ talloc_free(s);
+ return status;
+}
diff --git a/source4/winbind/wscript_build b/source4/winbind/wscript_build
index c9682f3eec..2c8a6f8317 100644
--- a/source4/winbind/wscript_build
+++ b/source4/winbind/wscript_build
@@ -2,7 +2,7 @@
bld.SAMBA_MODULE('WINBIND',
- source='wb_server.c wb_irpc.c wb_samba3_protocol.c wb_samba3_cmd.c wb_init_domain.c wb_dom_info.c wb_dom_info_trusted.c wb_sid2domain.c wb_name2domain.c wb_sids2xids.c wb_xids2sids.c wb_gid2sid.c wb_sid2uid.c wb_sid2gid.c wb_uid2sid.c wb_connect_lsa.c wb_connect_sam.c wb_cmd_lookupname.c wb_cmd_lookupsid.c wb_cmd_getdcname.c wb_cmd_getgrnam.c wb_cmd_getgrgid.c wb_cmd_getpwnam.c wb_cmd_getpwuid.c wb_cmd_userdomgroups.c wb_cmd_usersids.c wb_cmd_list_groups.c wb_cmd_list_trustdom.c wb_cmd_list_users.c wb_cmd_setpwent.c wb_cmd_getpwent.c wb_cmd_getgrent.c wb_cmd_setgrent.c wb_cmd_getgroups.c wb_pam_auth.c wb_sam_logon.c',
+ source='wb_server.c wb_irpc.c wb_samba3_protocol.c wb_samba3_cmd.c wb_init_domain.c wb_dom_info.c wb_dom_info_trusted.c wb_sid2domain.c wb_name2domain.c wb_sids2xids.c wb_xids2sids.c wb_gid2sid.c wb_sid2uid.c wb_sid2gid.c wb_uid2sid.c wb_connect_lsa.c wb_connect_sam.c wb_cmd_lookupname.c wb_cmd_lookupsid.c wb_cmd_getdcname.c wb_cmd_getgrnam.c wb_cmd_getgrgid.c wb_cmd_getpwnam.c wb_cmd_getpwuid.c wb_cmd_userdomgroups.c wb_cmd_usersids.c wb_cmd_list_groups.c wb_cmd_list_trustdom.c wb_cmd_list_users.c wb_cmd_setpwent.c wb_cmd_getpwent.c wb_cmd_getgrent.c wb_cmd_setgrent.c wb_cmd_getgroups.c wb_pam_auth.c wb_sam_logon.c wb_update_rodc_dns.c',
autoproto='wb_proto.h',
subsystem='service',
init_function='server_service_winbind_init',