diff options
Diffstat (limited to 'source4')
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, ¬ify); status = smb_raw_changenotify_recv(req, mem_ctx, ¬ify); 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, ¬ify); 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, ¬ify); \ op \ - msleep(200); smb_raw_ntcancel(req); \ + smb_msleep(200); smb_raw_ntcancel(req); \ status = smb_raw_changenotify_recv(req, tctx, ¬ify); \ 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, ¬ify); 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', |