summaryrefslogtreecommitdiff
path: root/source4/dsdb
diff options
context:
space:
mode:
authorNadezhda Ivanova <nadezhda.ivanova@postpath.com>2010-01-13 12:02:31 +0200
committerNadezhda Ivanova <nadezhda.ivanova@postpath.com>2010-01-13 12:02:31 +0200
commit9b3871ed293f76e770e572cd6b59f59670f1f6f8 (patch)
tree2b79286e3a6f7af9e26466393a0b26075a238be8 /source4/dsdb
parent309473f938d18b9993c2c4f120eeff7b4641985a (diff)
parentca847952054f5bbde1d40ad4260589b6fcc9721d (diff)
downloadsamba-9b3871ed293f76e770e572cd6b59f59670f1f6f8.tar.gz
samba-9b3871ed293f76e770e572cd6b59f59670f1f6f8.tar.bz2
samba-9b3871ed293f76e770e572cd6b59f59670f1f6f8.zip
Merge branch 'master' of git://git.samba.org/samba
Diffstat (limited to 'source4/dsdb')
-rw-r--r--source4/dsdb/common/util.c134
-rw-r--r--source4/dsdb/config.mk3
-rw-r--r--source4/dsdb/repl/drepl_out_helpers.c337
-rw-r--r--source4/dsdb/repl/drepl_out_pull.c63
-rw-r--r--source4/dsdb/repl/drepl_partitions.c80
-rw-r--r--source4/dsdb/repl/drepl_periodic.c2
-rw-r--r--source4/dsdb/repl/drepl_ridalloc.c282
-rw-r--r--source4/dsdb/repl/drepl_service.c1
-rw-r--r--source4/dsdb/repl/drepl_service.h11
-rw-r--r--source4/dsdb/samdb/ldb_modules/acl.c38
-rw-r--r--source4/dsdb/samdb/ldb_modules/config.mk23
-rw-r--r--source4/dsdb/samdb/ldb_modules/instancetype.c3
-rw-r--r--source4/dsdb/samdb/ldb_modules/lazy_commit.c13
-rw-r--r--source4/dsdb/samdb/ldb_modules/partition.c12
-rw-r--r--source4/dsdb/samdb/ldb_modules/pdc_fsmo.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/repl_meta_data.c12
-rw-r--r--source4/dsdb/samdb/ldb_modules/ridalloc.c646
-rw-r--r--source4/dsdb/samdb/ldb_modules/samba3sid.c197
-rw-r--r--source4/dsdb/samdb/ldb_modules/samba_dsdb.c77
-rw-r--r--source4/dsdb/samdb/ldb_modules/samldb.c684
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_data.c5
-rw-r--r--source4/dsdb/samdb/ldb_modules/schema_load.c8
-rw-r--r--source4/dsdb/samdb/ldb_modules/show_deleted.c4
-rw-r--r--source4/dsdb/samdb/ldb_modules/tests/samba3sam.py17
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.c192
-rw-r--r--source4/dsdb/samdb/ldb_modules/util.h5
-rw-r--r--source4/dsdb/samdb/samdb.h8
-rw-r--r--source4/dsdb/schema/schema.h1
-rw-r--r--source4/dsdb/schema/schema_init.c64
-rw-r--r--source4/dsdb/schema/schema_query.c30
-rw-r--r--source4/dsdb/schema/schema_syntax.c180
31 files changed, 2132 insertions, 1004 deletions
diff --git a/source4/dsdb/common/util.c b/source4/dsdb/common/util.c
index b8ba26a4ec..6147940e3b 100644
--- a/source4/dsdb/common/util.c
+++ b/source4/dsdb/common/util.c
@@ -1196,11 +1196,18 @@ const struct dom_sid *samdb_domain_sid(struct ldb_context *ldb)
return domain_sid;
failed:
- DEBUG(1,("Failed to find domain_sid for open ldb\n"));
talloc_free(tmp_ctx);
return NULL;
}
+/*
+ get domain sid from cache
+*/
+const struct dom_sid *samdb_domain_sid_cache_only(struct ldb_context *ldb)
+{
+ return (struct dom_sid *)ldb_get_opaque(ldb, "cache.domain_sid");
+}
+
bool samdb_set_domain_sid(struct ldb_context *ldb, const struct dom_sid *dom_sid_in)
{
TALLOC_CTX *tmp_ctx;
@@ -1521,6 +1528,86 @@ struct ldb_dn *samdb_server_site_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx
return server_site_dn;
}
+/*
+ find a 'reference' DN that points at another object
+ (eg. serverReference, rIDManagerReference etc)
+ */
+int samdb_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
+ const char *attribute, struct ldb_dn **dn)
+{
+ const char *attrs[2];
+ struct ldb_result *res;
+ int ret;
+
+ attrs[0] = attribute;
+ attrs[1] = NULL;
+
+ ret = ldb_search(ldb, mem_ctx, &res, base, LDB_SCOPE_BASE, attrs, NULL);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ if (res->count != 1) {
+ talloc_free(res);
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+
+ *dn = ldb_msg_find_attr_as_dn(ldb, mem_ctx, res->msgs[0], attribute);
+ if (!*dn) {
+ talloc_free(res);
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ }
+
+ talloc_free(res);
+ return LDB_SUCCESS;
+}
+
+/*
+ find our machine account via the serverReference attribute in the
+ server DN
+ */
+int samdb_server_reference_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
+{
+ struct ldb_dn *server_dn;
+ int ret;
+
+ server_dn = samdb_server_dn(ldb, mem_ctx);
+ if (server_dn == NULL) {
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+
+ ret = samdb_reference_dn(ldb, mem_ctx, server_dn, "serverReference", dn);
+ talloc_free(server_dn);
+
+ return ret;
+}
+
+/*
+ find the RID Manager$ DN via the rIDManagerReference attribute in the
+ base DN
+ */
+int samdb_rid_manager_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
+{
+ return samdb_reference_dn(ldb, mem_ctx, samdb_base_dn(ldb), "rIDManagerReference", dn);
+}
+
+/*
+ find the RID Set DN via the rIDSetReferences attribute in our
+ machine account DN
+ */
+int samdb_rid_set_dn(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
+{
+ struct ldb_dn *server_ref_dn;
+ int ret;
+
+ ret = samdb_server_reference_dn(ldb, mem_ctx, &server_ref_dn);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ ret = samdb_reference_dn(ldb, mem_ctx, server_ref_dn, "rIDSetReferences", dn);
+ talloc_free(server_ref_dn);
+ return ret;
+}
+
const char *samdb_server_site_name(struct ldb_context *ldb, TALLOC_CTX *mem_ctx)
{
const struct ldb_val *val = ldb_dn_get_rdn_val(samdb_server_site_dn(ldb, mem_ctx));
@@ -2353,16 +2440,20 @@ int dsdb_search_dn_with_deleted(struct ldb_context *ldb,
/*
- use a DN to find a GUID
+ use a DN to find a GUID with a given attribute name
*/
-int dsdb_find_guid_by_dn(struct ldb_context *ldb,
- struct ldb_dn *dn, struct GUID *guid)
+int dsdb_find_guid_attr_by_dn(struct ldb_context *ldb,
+ struct ldb_dn *dn, const char *attribute,
+ struct GUID *guid)
{
int ret;
struct ldb_result *res;
- const char *attrs[] = { "objectGUID", NULL };
+ const char *attrs[2];
TALLOC_CTX *tmp_ctx = talloc_new(ldb);
+ attrs[0] = attribute;
+ attrs[1] = NULL;
+
ret = dsdb_search_dn_with_deleted(ldb, tmp_ctx, &res, dn, attrs);
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
@@ -2372,11 +2463,20 @@ int dsdb_find_guid_by_dn(struct ldb_context *ldb,
talloc_free(tmp_ctx);
return LDB_ERR_NO_SUCH_OBJECT;
}
- *guid = samdb_result_guid(res->msgs[0], "objectGUID");
+ *guid = samdb_result_guid(res->msgs[0], attribute);
talloc_free(tmp_ctx);
return LDB_SUCCESS;
}
+/*
+ use a DN to find a GUID
+ */
+int dsdb_find_guid_by_dn(struct ldb_context *ldb,
+ struct ldb_dn *dn, struct GUID *guid)
+{
+ return dsdb_find_guid_attr_by_dn(ldb, dn, "objectGUID", guid);
+}
+
/*
@@ -2717,6 +2817,12 @@ int drsuapi_DsReplicaCursor2_compare(const struct drsuapi_DsReplicaCursor2 *c1,
return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
}
+int drsuapi_DsReplicaCursor_compare(const struct drsuapi_DsReplicaCursor *c1,
+ const struct drsuapi_DsReplicaCursor *c2)
+{
+ return GUID_compare(&c1->source_dsa_invocation_id, &c2->source_dsa_invocation_id);
+}
+
/*
see if we are a RODC
@@ -3099,3 +3205,19 @@ int dsdb_tombstone_lifetime(struct ldb_context *ldb, uint32_t *lifetime)
talloc_free(dn);
return LDB_SUCCESS;
}
+
+/*
+ compare a ldb_val to a string case insensitively
+ */
+int samdb_ldb_val_case_cmp(const char *s, struct ldb_val *v)
+{
+ size_t len = strlen(s);
+ int ret;
+ if (len > v->length) return 1;
+ ret = strncasecmp(s, (const char *)v->data, v->length);
+ if (ret != 0) return ret;
+ if (v->length > len && v->data[len] != 0) {
+ return -1;
+ }
+ return 0;
+}
diff --git a/source4/dsdb/config.mk b/source4/dsdb/config.mk
index 35a0c84903..3226c08ec0 100644
--- a/source4/dsdb/config.mk
+++ b/source4/dsdb/config.mk
@@ -64,7 +64,8 @@ DREPL_SRV_OBJ_FILES = $(addprefix $(dsdbsrcdir)/repl/, \
drepl_partitions.o \
drepl_out_pull.o \
drepl_out_helpers.o \
- drepl_notify.o)
+ drepl_notify.o \
+ drepl_ridalloc.o)
$(eval $(call proto_header_template,$(dsdbsrcdir)/repl/drepl_service_proto.h,$(DREPL_SRV_OBJ_FILES:.o=.c)))
diff --git a/source4/dsdb/repl/drepl_out_helpers.c b/source4/dsdb/repl/drepl_out_helpers.c
index 722db4f8ee..a4f5d1faec 100644
--- a/source4/dsdb/repl/drepl_out_helpers.c
+++ b/source4/dsdb/repl/drepl_out_helpers.c
@@ -202,81 +202,90 @@ NTSTATUS dreplsrv_out_drsuapi_recv(struct tevent_req *req)
}
struct dreplsrv_op_pull_source_state {
- struct composite_context *creq;
-
struct dreplsrv_out_operation *op;
-
- struct dreplsrv_drsuapi_connection *drsuapi;
-
- bool have_all;
-
- uint32_t ctr_level;
- struct drsuapi_DsGetNCChangesCtr1 *ctr1;
- struct drsuapi_DsGetNCChangesCtr6 *ctr6;
};
static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq);
-struct composite_context *dreplsrv_op_pull_source_send(struct dreplsrv_out_operation *op)
+struct tevent_req *dreplsrv_op_pull_source_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ struct dreplsrv_out_operation *op)
{
- struct composite_context *c;
- struct dreplsrv_op_pull_source_state *st;
+ struct tevent_req *req;
+ struct dreplsrv_op_pull_source_state *state;
struct tevent_req *subreq;
- c = composite_create(op, op->service->task->event_ctx);
- if (c == NULL) return NULL;
-
- st = talloc_zero(c, struct dreplsrv_op_pull_source_state);
- if (composite_nomem(st, c)) return c;
+ req = tevent_req_create(mem_ctx, &state,
+ struct dreplsrv_op_pull_source_state);
+ if (req == NULL) {
+ return NULL;
+ }
- st->creq = c;
- st->op = op;
+ state->op = op;
- subreq = dreplsrv_out_drsuapi_send(st,
- op->service->task->event_ctx,
- op->source_dsa->conn);
- if (composite_nomem(subreq, c)) return c;
- tevent_req_set_callback(subreq, dreplsrv_op_pull_source_connect_done, st);
+ subreq = dreplsrv_out_drsuapi_send(state, ev, op->source_dsa->conn);
+ if (tevent_req_nomem(subreq, req)) {
+ return tevent_req_post(req, ev);
+ }
+ tevent_req_set_callback(subreq, dreplsrv_op_pull_source_connect_done, req);
- return c;
+ return req;
}
-static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st);
+static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req);
static void dreplsrv_op_pull_source_connect_done(struct tevent_req *subreq)
{
- struct dreplsrv_op_pull_source_state *st = tevent_req_callback_data(subreq,
- struct dreplsrv_op_pull_source_state);
- struct composite_context *c = st->creq;
+ struct tevent_req *req = tevent_req_callback_data(subreq,
+ struct tevent_req);
+ NTSTATUS status;
- c->status = dreplsrv_out_drsuapi_recv(subreq);
+ status = dreplsrv_out_drsuapi_recv(subreq);
TALLOC_FREE(subreq);
- if (!composite_is_ok(c)) return;
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
- dreplsrv_op_pull_source_get_changes_send(st);
+ dreplsrv_op_pull_source_get_changes_trigger(req);
}
-static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req);
+static void dreplsrv_op_pull_source_get_changes_done(struct rpc_request *rreq);
-static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_source_state *st)
+static void dreplsrv_op_pull_source_get_changes_trigger(struct tevent_req *req)
{
- struct composite_context *c = st->creq;
- struct repsFromTo1 *rf1 = st->op->source_dsa->repsFrom1;
- struct dreplsrv_service *service = st->op->service;
- struct dreplsrv_partition *partition = st->op->source_dsa->partition;
- struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
- struct rpc_request *req;
+ struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
+ struct dreplsrv_op_pull_source_state);
+ struct repsFromTo1 *rf1 = state->op->source_dsa->repsFrom1;
+ struct dreplsrv_service *service = state->op->service;
+ struct dreplsrv_partition *partition = state->op->source_dsa->partition;
+ struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
+ struct rpc_request *rreq;
struct drsuapi_DsGetNCChanges *r;
+ struct drsuapi_DsReplicaCursorCtrEx *uptodateness_vector;
- r = talloc(st, struct drsuapi_DsGetNCChanges);
- if (composite_nomem(r, c)) return;
+ r = talloc(state, struct drsuapi_DsGetNCChanges);
+ if (tevent_req_nomem(r, req)) {
+ return;
+ }
r->out.level_out = talloc(r, int32_t);
- if (composite_nomem(r->out.level_out, c)) return;
+ if (tevent_req_nomem(r->out.level_out, req)) {
+ return;
+ }
r->in.req = talloc(r, union drsuapi_DsGetNCChangesRequest);
- if (composite_nomem(r->in.req, c)) return;
+ if (tevent_req_nomem(r->in.req, req)) {
+ return;
+ }
r->out.ctr = talloc(r, union drsuapi_DsGetNCChangesCtr);
- if (composite_nomem(r->out.ctr, c)) return;
+ if (tevent_req_nomem(r->out.ctr, req)) {
+ return;
+ }
+
+ if (partition->uptodatevector_ex.count == 0) {
+ uptodateness_vector = NULL;
+ } else {
+ uptodateness_vector = &partition->uptodatevector_ex;
+ }
r->in.bind_handle = &drsuapi->bind_handle;
if (drsuapi->remote_info28.supported_extensions & DRSUAPI_SUPPORTED_EXTENSION_GETCHGREQ_V8) {
@@ -285,12 +294,12 @@ static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_sou
r->in.req->req8.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
r->in.req->req8.naming_context = &partition->nc;
r->in.req->req8.highwatermark = rf1->highwatermark;
- r->in.req->req8.uptodateness_vector = NULL;/*&partition->uptodatevector_ex;*/
+ r->in.req->req8.uptodateness_vector = uptodateness_vector;
r->in.req->req8.replica_flags = rf1->replica_flags;
r->in.req->req8.max_object_count = 133;
r->in.req->req8.max_ndr_size = 1336811;
- r->in.req->req8.extended_op = DRSUAPI_EXOP_NONE;
- r->in.req->req8.fsmo_info = 0;
+ r->in.req->req8.extended_op = state->op->extended_op;
+ r->in.req->req8.fsmo_info = state->op->fsmo_info;
r->in.req->req8.partial_attribute_set = NULL;
r->in.req->req8.partial_attribute_set_ex= NULL;
r->in.req->req8.mapping_ctr.num_mappings= 0;
@@ -301,40 +310,50 @@ static void dreplsrv_op_pull_source_get_changes_send(struct dreplsrv_op_pull_sou
r->in.req->req5.source_dsa_invocation_id= rf1->source_dsa_invocation_id;
r->in.req->req5.naming_context = &partition->nc;
r->in.req->req5.highwatermark = rf1->highwatermark;
- r->in.req->req5.uptodateness_vector = NULL;/*&partition->uptodatevector_ex;*/
+ r->in.req->req5.uptodateness_vector = uptodateness_vector;
r->in.req->req5.replica_flags = rf1->replica_flags;
r->in.req->req5.max_object_count = 133;
r->in.req->req5.max_ndr_size = 1336770;
- r->in.req->req5.extended_op = DRSUAPI_EXOP_NONE;
- r->in.req->req5.fsmo_info = 0;
+ r->in.req->req5.extended_op = state->op->extended_op;
+ r->in.req->req5.fsmo_info = state->op->fsmo_info;
}
- req = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi->pipe, r, r);
- composite_continue_rpc(c, req, dreplsrv_op_pull_source_get_changes_recv, st);
+#if 0
+ NDR_PRINT_IN_DEBUG(drsuapi_DsGetNCChanges, r);
+#endif
+
+ rreq = dcerpc_drsuapi_DsGetNCChanges_send(drsuapi->pipe, r, r);
+ if (tevent_req_nomem(rreq, req)) {
+ return;
+ }
+ composite_continue_rpc(NULL, rreq, dreplsrv_op_pull_source_get_changes_done, req);
}
-static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st,
- struct drsuapi_DsGetNCChanges *r,
- uint32_t ctr_level,
- struct drsuapi_DsGetNCChangesCtr1 *ctr1,
- struct drsuapi_DsGetNCChangesCtr6 *ctr6);
+static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req,
+ struct drsuapi_DsGetNCChanges *r,
+ uint32_t ctr_level,
+ struct drsuapi_DsGetNCChangesCtr1 *ctr1,
+ struct drsuapi_DsGetNCChangesCtr6 *ctr6);
-static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req)
+static void dreplsrv_op_pull_source_get_changes_done(struct rpc_request *rreq)
{
- struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data,
- struct dreplsrv_op_pull_source_state);
- struct composite_context *c = st->creq;
- struct drsuapi_DsGetNCChanges *r = talloc_get_type(req->ndr.struct_ptr,
+ struct tevent_req *req = talloc_get_type(rreq->async.private_data,
+ struct tevent_req);
+ NTSTATUS status;
+ struct drsuapi_DsGetNCChanges *r = talloc_get_type(rreq->ndr.struct_ptr,
struct drsuapi_DsGetNCChanges);
uint32_t ctr_level = 0;
struct drsuapi_DsGetNCChangesCtr1 *ctr1 = NULL;
struct drsuapi_DsGetNCChangesCtr6 *ctr6 = NULL;
- c->status = dcerpc_ndr_request_recv(req);
- if (!composite_is_ok(c)) return;
+ status = dcerpc_ndr_request_recv(rreq);
+ if (tevent_req_nterror(req, status)) {
+ return;
+ }
if (!W_ERROR_IS_OK(r->out.result)) {
- composite_error(c, werror_to_ntstatus(r->out.result));
+ status = werror_to_ntstatus(r->out.result);
+ tevent_req_nterror(req, status);
return;
}
@@ -361,38 +380,42 @@ static void dreplsrv_op_pull_source_get_changes_recv(struct rpc_request *req)
ctr_level = 6;
ctr6 = &r->out.ctr->ctr7.ctr.xpress6.ts->ctr6;
} else {
- composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
+ status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+ tevent_req_nterror(req, status);
return;
}
if (!ctr1 && !ctr6) {
- composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
+ status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+ tevent_req_nterror(req, status);
return;
}
if (ctr_level == 6) {
if (!W_ERROR_IS_OK(ctr6->drs_error)) {
- composite_error(c, werror_to_ntstatus(ctr6->drs_error));
+ status = werror_to_ntstatus(ctr6->drs_error);
+ tevent_req_nterror(req, status);
return;
}
}
- dreplsrv_op_pull_source_apply_changes_send(st, r, ctr_level, ctr1, ctr6);
+ dreplsrv_op_pull_source_apply_changes_trigger(req, r, ctr_level, ctr1, ctr6);
}
-static void dreplsrv_update_refs_send(struct dreplsrv_op_pull_source_state *st);
+static void dreplsrv_update_refs_trigger(struct tevent_req *req);
-static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_source_state *st,
- struct drsuapi_DsGetNCChanges *r,
- uint32_t ctr_level,
- struct drsuapi_DsGetNCChangesCtr1 *ctr1,
- struct drsuapi_DsGetNCChangesCtr6 *ctr6)
+static void dreplsrv_op_pull_source_apply_changes_trigger(struct tevent_req *req,
+ struct drsuapi_DsGetNCChanges *r,
+ uint32_t ctr_level,
+ struct drsuapi_DsGetNCChangesCtr1 *ctr1,
+ struct drsuapi_DsGetNCChangesCtr6 *ctr6)
{
- struct composite_context *c = st->creq;
- struct repsFromTo1 rf1 = *st->op->source_dsa->repsFrom1;
- struct dreplsrv_service *service = st->op->service;
- struct dreplsrv_partition *partition = st->op->source_dsa->partition;
- struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
+ struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
+ struct dreplsrv_op_pull_source_state);
+ struct repsFromTo1 rf1 = *state->op->source_dsa->repsFrom1;
+ struct dreplsrv_service *service = state->op->service;
+ struct dreplsrv_partition *partition = state->op->source_dsa->partition;
+ struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
const struct drsuapi_DsReplicaOIDMapping_Ctr *mapping_ctr;
uint32_t object_count;
struct drsuapi_DsReplicaObjectListItemEx *first_object;
@@ -402,6 +425,7 @@ static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_s
struct dsdb_extended_replicated_objects *objects;
bool more_data = false;
WERROR status;
+ NTSTATUS nt_status;
switch (ctr_level) {
case 1:
@@ -425,7 +449,8 @@ static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_s
more_data = ctr6->more_data;
break;
default:
- composite_error(c, werror_to_ntstatus(WERR_BAD_NET_RESP));
+ nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+ tevent_req_nterror(req, nt_status);
return;
}
@@ -439,32 +464,39 @@ static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_s
&rf1,
uptodateness_vector,
&drsuapi->gensec_skey,
- st, &objects);
+ state, &objects);
if (!W_ERROR_IS_OK(status)) {
- DEBUG(0,("Failed to convert objects: %s\n", win_errstr(status)));
- composite_error(c, werror_to_ntstatus(status));
+ nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+ DEBUG(0,("Failed to convert objects: %s/%s\n",
+ win_errstr(status), nt_errstr(nt_status)));
+ tevent_req_nterror(req, nt_status);
return;
}
status = dsdb_extended_replicated_objects_commit(service->samdb,
objects,
- &st->op->source_dsa->notify_uSN);
+ &state->op->source_dsa->notify_uSN);
talloc_free(objects);
if (!W_ERROR_IS_OK(status)) {
- DEBUG(0,("Failed to commit objects: %s\n", win_errstr(status)));
- composite_error(c, werror_to_ntstatus(status));
+ nt_status = werror_to_ntstatus(WERR_BAD_NET_RESP);
+ DEBUG(0,("Failed to commit objects: %s/%s\n",
+ win_errstr(status), nt_errstr(nt_status)));
+ tevent_req_nterror(req, nt_status);
return;
}
/* if it applied fine, we need to update the highwatermark */
- *st->op->source_dsa->repsFrom1 = rf1;
+ *state->op->source_dsa->repsFrom1 = rf1;
/*
* TODO: update our uptodatevector!
*/
+ /* we don't need this maybe very large structure anymore */
+ TALLOC_FREE(r);
+
if (more_data) {
- dreplsrv_op_pull_source_get_changes_send(st);
+ dreplsrv_op_pull_source_get_changes_trigger(req);
return;
}
@@ -473,43 +505,89 @@ static void dreplsrv_op_pull_source_apply_changes_send(struct dreplsrv_op_pull_s
we join the domain, but they quickly expire. We do it here
so we can use the already established DRSUAPI pipe
*/
- dreplsrv_update_refs_send(st);
+ dreplsrv_update_refs_trigger(req);
}
-WERROR dreplsrv_op_pull_source_recv(struct composite_context *c)
+static void dreplsrv_update_refs_done(struct rpc_request *rreq);
+
+/*
+ send a UpdateRefs request to refresh our repsTo record on the server
+ */
+static void dreplsrv_update_refs_trigger(struct tevent_req *req)
{
- NTSTATUS status;
+ struct dreplsrv_op_pull_source_state *state = tevent_req_data(req,
+ struct dreplsrv_op_pull_source_state);
+ struct dreplsrv_service *service = state->op->service;
+ struct dreplsrv_partition *partition = state->op->source_dsa->partition;
+ struct dreplsrv_drsuapi_connection *drsuapi = state->op->source_dsa->conn->drsuapi;
+ struct rpc_request *rreq;
+ struct drsuapi_DsReplicaUpdateRefs *r;
+ char *ntds_guid_str;
+ char *ntds_dns_name;
+
+ r = talloc(state, struct drsuapi_DsReplicaUpdateRefs);
+ if (tevent_req_nomem(r, req)) {
+ return;
+ }
- status = composite_wait(c);
+ ntds_guid_str = GUID_string(r, &service->ntds_guid);
+ if (tevent_req_nomem(ntds_guid_str, req)) {
+ return;
+ }
- talloc_free(c);
- return ntstatus_to_werror(status);
+ ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
+ ntds_guid_str,
+ lp_dnsdomain(service->task->lp_ctx));
+ if (tevent_req_nomem(ntds_dns_name, req)) {
+ return;
+ }
+
+ r->in.bind_handle = &drsuapi->bind_handle;
+ r->in.level = 1;
+ r->in.req.req1.naming_context = &partition->nc;
+ r->in.req.req1.dest_dsa_dns_name = ntds_dns_name;
+ r->in.req.req1.dest_dsa_guid = service->ntds_guid;
+ r->in.req.req1.options =
+ DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE |
+ DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE;
+ if (!samdb_rodc(service->task->lp_ctx)) {
+ r->in.req.req1.options |= DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE;
+ }
+
+ rreq = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r);
+ if (tevent_req_nomem(rreq, req)) {
+ return;
+ }
+ composite_continue_rpc(NULL, rreq, dreplsrv_update_refs_done, req);
}
/*
receive a UpdateRefs reply
*/
-static void dreplsrv_update_refs_recv(struct rpc_request *req)
+static void dreplsrv_update_refs_done(struct rpc_request *rreq)
{
- struct dreplsrv_op_pull_source_state *st = talloc_get_type(req->async.private_data,
- struct dreplsrv_op_pull_source_state);
- struct composite_context *c = st->creq;
- struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(req->ndr.struct_ptr,
+ struct tevent_req *req = talloc_get_type(rreq->async.private_data,
+ struct tevent_req);
+ struct drsuapi_DsReplicaUpdateRefs *r = talloc_get_type(rreq->ndr.struct_ptr,
struct drsuapi_DsReplicaUpdateRefs);
+ NTSTATUS status;
- c->status = dcerpc_ndr_request_recv(req);
- if (!composite_is_ok(c)) {
+ status = dcerpc_ndr_request_recv(rreq);
+ if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("UpdateRefs failed with %s\n",
- nt_errstr(c->status)));
+ nt_errstr(status)));
+ tevent_req_nterror(req, status);
return;
}
if (!W_ERROR_IS_OK(r->out.result)) {
- DEBUG(0,("UpdateRefs failed with %s for %s %s\n",
+ status = werror_to_ntstatus(r->out.result);
+ DEBUG(0,("UpdateRefs failed with %s/%s for %s %s\n",
win_errstr(r->out.result),
+ nt_errstr(status),
r->in.req.req1.dest_dsa_dns_name,
r->in.req.req1.naming_context->dn));
- composite_error(c, werror_to_ntstatus(r->out.result));
+ tevent_req_nterror(req, status);
return;
}
@@ -517,46 +595,19 @@ static void dreplsrv_update_refs_recv(struct rpc_request *req)
r->in.req.req1.dest_dsa_dns_name,
r->in.req.req1.naming_context->dn));
- composite_done(c);
+ tevent_req_done(req);
}
-/*
- send a UpdateRefs request to refresh our repsTo record on the server
- */
-static void dreplsrv_update_refs_send(struct dreplsrv_op_pull_source_state *st)
+WERROR dreplsrv_op_pull_source_recv(struct tevent_req *req)
{
- struct composite_context *c = st->creq;
- struct dreplsrv_service *service = st->op->service;
- struct dreplsrv_partition *partition = st->op->source_dsa->partition;
- struct dreplsrv_drsuapi_connection *drsuapi = st->op->source_dsa->conn->drsuapi;
- struct rpc_request *req;
- struct drsuapi_DsReplicaUpdateRefs *r;
- char *ntds_guid_str;
- char *ntds_dns_name;
-
- r = talloc(st, struct drsuapi_DsReplicaUpdateRefs);
- if (composite_nomem(r, c)) return;
-
- ntds_guid_str = GUID_string(r, &service->ntds_guid);
- if (composite_nomem(ntds_guid_str, c)) return;
-
- ntds_dns_name = talloc_asprintf(r, "%s._msdcs.%s",
- ntds_guid_str,
- lp_dnsdomain(service->task->lp_ctx));
- if (composite_nomem(ntds_dns_name, c)) return;
+ NTSTATUS status;
- r->in.bind_handle = &drsuapi->bind_handle;
- r->in.level = 1;
- r->in.req.req1.naming_context = &partition->nc;
- r->in.req.req1.dest_dsa_dns_name = ntds_dns_name;
- r->in.req.req1.dest_dsa_guid = service->ntds_guid;
- r->in.req.req1.options =
- DRSUAPI_DS_REPLICA_UPDATE_ADD_REFERENCE |
- DRSUAPI_DS_REPLICA_UPDATE_DELETE_REFERENCE;
- if (!samdb_rodc(service->task->lp_ctx)) {
- r->in.req.req1.options |= DRSUAPI_DS_REPLICA_UPDATE_WRITEABLE;
+ if (tevent_req_is_nterror(req, &status)) {
+ tevent_req_received(req);
+ return ntstatus_to_werror(status);
}
- req = dcerpc_drsuapi_DsReplicaUpdateRefs_send(drsuapi->pipe, r, r);
- composite_continue_rpc(c, req, dreplsrv_update_refs_recv, st);
+ tevent_req_received(req);
+ return WERR_OK;
}
+
diff --git a/source4/dsdb/repl/drepl_out_pull.c b/source4/dsdb/repl/drepl_out_pull.c
index 2793eec8b4..101214609a 100644
--- a/source4/dsdb/repl/drepl_out_pull.c
+++ b/source4/dsdb/repl/drepl_out_pull.c
@@ -33,21 +33,25 @@
#include "librpc/gen_ndr/ndr_drsblobs.h"
#include "libcli/composite/composite.h"
-static WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s,
- struct dreplsrv_partition *p,
- struct dreplsrv_partition_source_dsa *source,
- TALLOC_CTX *mem_ctx)
+WERROR dreplsrv_schedule_partition_pull_source(struct dreplsrv_service *s,
+ struct dreplsrv_partition_source_dsa *source,
+ enum drsuapi_DsExtendedOperation extended_op,
+ uint64_t fsmo_info,
+ dreplsrv_fsmo_callback_t callback)
{
struct dreplsrv_out_operation *op;
- op = talloc_zero(mem_ctx, struct dreplsrv_out_operation);
+ op = talloc_zero(s, struct dreplsrv_out_operation);
W_ERROR_HAVE_NO_MEMORY(op);
op->service = s;
op->source_dsa = source;
+ op->extended_op = extended_op;
+ op->fsmo_info = fsmo_info;
+ op->callback = callback;
DLIST_ADD_END(s->ops.pending, op, struct dreplsrv_out_operation *);
- talloc_steal(s, op);
+
return WERR_OK;
}
@@ -59,7 +63,7 @@ static WERROR dreplsrv_schedule_partition_pull(struct dreplsrv_service *s,
struct dreplsrv_partition_source_dsa *cur;
for (cur = p->sources; cur; cur = cur->next) {
- status = dreplsrv_schedule_partition_pull_source(s, p, cur, mem_ctx);
+ status = dreplsrv_schedule_partition_pull_source(s, cur, DRSUAPI_EXOP_NONE, 0, NULL);
W_ERROR_NOT_OK_RETURN(status);
}
@@ -95,8 +99,10 @@ WERROR dreplsrv_schedule_partition_pull_by_guid(struct dreplsrv_service *s, TALL
return WERR_NOT_FOUND;
}
-static void dreplsrv_pending_op_callback(struct dreplsrv_out_operation *op)
+static void dreplsrv_pending_op_callback(struct tevent_req *subreq)
{
+ struct dreplsrv_out_operation *op = tevent_req_callback_data(subreq,
+ struct dreplsrv_out_operation);
struct repsFromTo1 *rf = op->source_dsa->repsFrom1;
struct dreplsrv_service *s = op->service;
time_t t;
@@ -105,7 +111,8 @@ static void dreplsrv_pending_op_callback(struct dreplsrv_out_operation *op)
t = time(NULL);
unix_to_nt_time(&now, t);
- rf->result_last_attempt = dreplsrv_op_pull_source_recv(op->creq);
+ rf->result_last_attempt = dreplsrv_op_pull_source_recv(subreq);
+ TALLOC_FREE(subreq);
if (W_ERROR_IS_OK(rf->result_last_attempt)) {
rf->consecutive_sync_failures = 0;
rf->last_success = now;
@@ -116,30 +123,28 @@ static void dreplsrv_pending_op_callback(struct dreplsrv_out_operation *op)
rf->consecutive_sync_failures++;
- DEBUG(1,("dreplsrv_op_pull_source(%s/%s) failures[%u]\n",
- win_errstr(rf->result_last_attempt),
- nt_errstr(werror_to_ntstatus(rf->result_last_attempt)),
- rf->consecutive_sync_failures));
+ DEBUG(1,("dreplsrv_op_pull_source(%s/%s) for %s failures[%u]\n",
+ win_errstr(rf->result_last_attempt),
+ win_errstr(rf->result_last_attempt),
+ ldb_dn_get_linearized(op->source_dsa->partition->dn),
+ rf->consecutive_sync_failures));
done:
+ if (op->callback) {
+ op->callback(s, rf->result_last_attempt);
+ }
talloc_free(op);
s->ops.current = NULL;
dreplsrv_run_pending_ops(s);
dreplsrv_notify_run_ops(s);
}
-static void dreplsrv_pending_op_callback_creq(struct composite_context *creq)
-{
- struct dreplsrv_out_operation *op = talloc_get_type(creq->async.private_data,
- struct dreplsrv_out_operation);
- dreplsrv_pending_op_callback(op);
-}
-
void dreplsrv_run_pending_ops(struct dreplsrv_service *s)
{
struct dreplsrv_out_operation *op;
time_t t;
NTTIME now;
+ struct tevent_req *subreq;
if (s->ops.current || s->ops.n_current) {
/* if there's still one running, we're done */
@@ -160,12 +165,18 @@ void dreplsrv_run_pending_ops(struct dreplsrv_service *s)
op->source_dsa->repsFrom1->last_attempt = now;
- op->creq = dreplsrv_op_pull_source_send(op);
- if (!op->creq) {
- dreplsrv_pending_op_callback(op);
+ subreq = dreplsrv_op_pull_source_send(op, s->task->event_ctx, op);
+ if (!subreq) {
+ struct repsFromTo1 *rf = op->source_dsa->repsFrom1;
+
+ rf->result_last_attempt = WERR_NOMEM;
+ rf->consecutive_sync_failures++;
+
+ DEBUG(1,("dreplsrv_op_pull_source(%s/%s) failures[%u]\n",
+ win_errstr(rf->result_last_attempt),
+ nt_errstr(werror_to_ntstatus(rf->result_last_attempt)),
+ rf->consecutive_sync_failures));
return;
}
-
- op->creq->async.fn = dreplsrv_pending_op_callback_creq;
- op->creq->async.private_data = op;
+ tevent_req_set_callback(subreq, dreplsrv_pending_op_callback, op);
}
diff --git a/source4/dsdb/repl/drepl_partitions.c b/source4/dsdb/repl/drepl_partitions.c
index 5b8227e7de..9a24fe541a 100644
--- a/source4/dsdb/repl/drepl_partitions.c
+++ b/source4/dsdb/repl/drepl_partitions.c
@@ -88,9 +88,9 @@ WERROR dreplsrv_load_partitions(struct dreplsrv_service *s)
return WERR_OK;
}
-static WERROR dreplsrv_out_connection_attach(struct dreplsrv_service *s,
- const struct repsFromTo1 *rft,
- struct dreplsrv_out_connection **_conn)
+WERROR dreplsrv_out_connection_attach(struct dreplsrv_service *s,
+ const struct repsFromTo1 *rft,
+ struct dreplsrv_out_connection **_conn)
{
struct dreplsrv_out_connection *cur, *conn = NULL;
const char *hostname;
@@ -188,6 +188,65 @@ static WERROR dreplsrv_partition_add_source_dsa(struct dreplsrv_service *s,
return WERR_OK;
}
+/*
+ convert from one udv format to the other
+ */
+static WERROR udv_convert(TALLOC_CTX *mem_ctx,
+ const struct replUpToDateVectorCtr2 *udv,
+ struct drsuapi_DsReplicaCursorCtrEx *udv_ex)
+{
+ int i;
+
+ udv_ex->version = 2;
+ udv_ex->reserved1 = 0;
+ udv_ex->reserved2 = 0;
+ udv_ex->count = udv->count;
+ udv_ex->cursors = talloc_array(mem_ctx, struct drsuapi_DsReplicaCursor, udv->count);
+ W_ERROR_HAVE_NO_MEMORY(udv_ex->cursors);
+
+ for (i=0; i<udv->count; i++) {
+ udv_ex->cursors[i].source_dsa_invocation_id = udv->cursors[i].source_dsa_invocation_id;
+ udv_ex->cursors[i].highest_usn = udv->cursors[i].highest_usn;
+ }
+
+ return WERR_OK;
+}
+
+/*
+ add our local UDV element for the partition
+ */
+static WERROR add_local_udv(struct dreplsrv_service *s,
+ struct dreplsrv_partition *p,
+ const struct GUID *our_invocation_id,
+ struct drsuapi_DsReplicaCursorCtrEx *udv)
+{
+ int ret;
+ uint64_t highest_usn;
+ int i;
+
+ ret = dsdb_load_partition_usn(s->samdb, p->dn, &highest_usn);
+ if (ret != LDB_SUCCESS) {
+ /* nothing to add */
+ return WERR_OK;
+ }
+
+ for (i=0; i<udv->count; i++) {
+ if (GUID_equal(our_invocation_id, &udv->cursors[i].source_dsa_invocation_id)) {
+ udv->cursors[i].highest_usn = highest_usn;
+ return WERR_OK;
+ }
+ }
+
+ udv->cursors = talloc_realloc(p, udv->cursors, struct drsuapi_DsReplicaCursor, udv->count+1);
+ W_ERROR_HAVE_NO_MEMORY(udv->cursors);
+
+ udv->cursors[udv->count].source_dsa_invocation_id = *our_invocation_id;
+ udv->cursors[udv->count].highest_usn = highest_usn;
+ udv->count++;
+
+ return WERR_OK;
+}
+
static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s,
struct dreplsrv_partition *p)
{
@@ -232,6 +291,11 @@ static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s,
talloc_free(nc_sid);
}
+ talloc_free(p->uptodatevector.cursors);
+ talloc_free(p->uptodatevector_ex.cursors);
+ ZERO_STRUCT(p->uptodatevector);
+ ZERO_STRUCT(p->uptodatevector_ex);
+
ouv_value = ldb_msg_find_ldb_val(r->msgs[0], "replUpToDateVector");
if (ouv_value) {
enum ndr_err_code ndr_err;
@@ -251,14 +315,14 @@ static WERROR dreplsrv_refresh_partition(struct dreplsrv_service *s,
p->uptodatevector.count = ouv.ctr.ctr2.count;
p->uptodatevector.reserved = ouv.ctr.ctr2.reserved;
- talloc_free(p->uptodatevector.cursors);
p->uptodatevector.cursors = talloc_steal(p, ouv.ctr.ctr2.cursors);
- }
- /*
- * TODO: add our own uptodatevector cursor
- */
+ status = udv_convert(p, &p->uptodatevector, &p->uptodatevector_ex);
+ W_ERROR_NOT_OK_RETURN(status);
+ }
+ status = add_local_udv(s, p, samdb_ntds_invocation_id(s->samdb), &p->uptodatevector_ex);
+ W_ERROR_NOT_OK_RETURN(status);
orf_el = ldb_msg_find_element(r->msgs[0], "repsFrom");
if (orf_el) {
diff --git a/source4/dsdb/repl/drepl_periodic.c b/source4/dsdb/repl/drepl_periodic.c
index 61d5598207..d2fbe45586 100644
--- a/source4/dsdb/repl/drepl_periodic.c
+++ b/source4/dsdb/repl/drepl_periodic.c
@@ -109,6 +109,8 @@ static void dreplsrv_periodic_run(struct dreplsrv_service *service)
/* the KCC might have changed repsFrom */
dreplsrv_refresh_partitions(service);
+ dreplsrv_ridalloc_check_rid_pool(service);
+
dreplsrv_run_pending_ops(service);
dreplsrv_notify_run_ops(service);
}
diff --git a/source4/dsdb/repl/drepl_ridalloc.c b/source4/dsdb/repl/drepl_ridalloc.c
new file mode 100644
index 0000000000..43fc5a2c51
--- /dev/null
+++ b/source4/dsdb/repl/drepl_ridalloc.c
@@ -0,0 +1,282 @@
+/*
+ Unix SMB/CIFS mplementation.
+
+ DSDB replication service - RID allocation code
+
+ Copyright (C) Andrew Tridgell 2010
+ Copyright (C) Andrew Bartlett 2010
+
+ based on drepl_notify.c
+
+ 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 "dsdb/samdb/samdb.h"
+#include "smbd/service.h"
+#include "dsdb/repl/drepl_service.h"
+#include "param/param.h"
+
+
+/*
+ create the RID manager source dsa structure
+ */
+static WERROR drepl_create_rid_manager_source_dsa(struct dreplsrv_service *service,
+ struct ldb_dn *rid_manager_dn, struct ldb_dn *fsmo_role_dn)
+{
+ struct dreplsrv_partition_source_dsa *sdsa;
+ struct ldb_context *ldb = service->samdb;
+ int ret;
+ WERROR werr;
+
+ sdsa = talloc_zero(service, struct dreplsrv_partition_source_dsa);
+ W_ERROR_HAVE_NO_MEMORY(sdsa);
+
+ sdsa->partition = talloc_zero(sdsa, struct dreplsrv_partition);
+ if (!sdsa->partition) {
+ talloc_free(sdsa);
+ return WERR_NOMEM;
+ }
+
+ sdsa->partition->dn = samdb_base_dn(ldb);
+ sdsa->partition->nc.dn = ldb_dn_alloc_linearized(sdsa->partition, rid_manager_dn);
+ ret = dsdb_find_guid_by_dn(ldb, rid_manager_dn, &sdsa->partition->nc.guid);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find GUID for %s\n",
+ ldb_dn_get_linearized(rid_manager_dn)));
+ talloc_free(sdsa);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ sdsa->repsFrom1 = &sdsa->_repsFromBlob.ctr.ctr1;
+ ret = dsdb_find_guid_attr_by_dn(ldb, fsmo_role_dn, "objectGUID", &sdsa->repsFrom1->source_dsa_obj_guid);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find objectGUID for %s\n",
+ ldb_dn_get_linearized(fsmo_role_dn)));
+ talloc_free(sdsa);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ sdsa->repsFrom1->other_info = talloc_zero(sdsa, struct repsFromTo1OtherInfo);
+ if (!sdsa->repsFrom1->other_info) {
+ talloc_free(sdsa);
+ return WERR_NOMEM;
+ }
+
+ sdsa->repsFrom1->other_info->dns_name =
+ talloc_asprintf(sdsa->repsFrom1->other_info, "%s._msdcs.%s",
+ GUID_string(sdsa->repsFrom1->other_info, &sdsa->repsFrom1->source_dsa_obj_guid),
+ lp_dnsdomain(service->task->lp_ctx));
+ if (!sdsa->repsFrom1->other_info->dns_name) {
+ talloc_free(sdsa);
+ return WERR_NOMEM;
+ }
+
+
+ werr = dreplsrv_out_connection_attach(service, sdsa->repsFrom1, &sdsa->conn);
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0,(__location__ ": Failed to attach to RID manager connection\n"));
+ talloc_free(sdsa);
+ return werr;
+ }
+
+ service->ridalloc.rid_manager_source_dsa = sdsa;
+ return WERR_OK;
+}
+
+/*
+ called when a rid allocation request has completed
+ */
+static void drepl_new_rid_pool_callback(struct dreplsrv_service *service, WERROR werr)
+{
+ if (!W_ERROR_IS_OK(werr)) {
+ DEBUG(0,(__location__ ": RID Manager failed RID allocation - %s\n",
+ win_errstr(werr)));
+ } else {
+ DEBUG(3,(__location__ ": RID Manager completed RID allocation OK\n"));
+ }
+
+ /* don't keep the connection open to the RID Manager */
+ talloc_free(service->ridalloc.rid_manager_source_dsa);
+ service->ridalloc.rid_manager_source_dsa = NULL;
+
+ service->ridalloc.in_progress = false;
+}
+
+/*
+ schedule a getncchanges request to the RID Manager to ask for a new
+ set of RIDs using DRSUAPI_EXOP_FSMO_RID_ALLOC
+ */
+static WERROR drepl_request_new_rid_pool(struct dreplsrv_service *service,
+ struct ldb_dn *rid_manager_dn, struct ldb_dn *fsmo_role_dn,
+ uint64_t alloc_pool)
+{
+ WERROR werr;
+
+ if (service->ridalloc.rid_manager_source_dsa == NULL) {
+ /* we need to establish a connection to the RID
+ Manager */
+ werr = drepl_create_rid_manager_source_dsa(service, rid_manager_dn, fsmo_role_dn);
+ W_ERROR_NOT_OK_RETURN(werr);
+ }
+
+ service->ridalloc.in_progress = true;
+
+ werr = dreplsrv_schedule_partition_pull_source(service, service->ridalloc.rid_manager_source_dsa,
+ DRSUAPI_EXOP_FSMO_RID_ALLOC, alloc_pool,
+ drepl_new_rid_pool_callback);
+ return werr;
+}
+
+
+/*
+ see if we are on the last pool we have
+ */
+static int drepl_ridalloc_pool_exhausted(struct ldb_context *ldb, bool *exhausted, uint64_t *alloc_pool)
+{
+ struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
+ TALLOC_CTX *tmp_ctx = talloc_new(ldb);
+ uint64_t prev_alloc_pool;
+ const char *attrs[] = { "rIDPreviousAllocationPool", "rIDAllocationPool", NULL };
+ int ret;
+ struct ldb_result *res;
+
+ server_dn = ldb_dn_get_parent(tmp_ctx, samdb_ntds_settings_dn(ldb));
+ if (!server_dn) {
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = samdb_reference_dn(ldb, tmp_ctx, server_dn, "serverReference", &machine_dn);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find serverReference in %s - %s",
+ ldb_dn_get_linearized(server_dn), ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = samdb_reference_dn(ldb, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
+ if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+ *exhausted = true;
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+ }
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to find rIDSetReferences in %s - %s",
+ ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = ldb_search(ldb, tmp_ctx, &res, rid_set_dn, LDB_SCOPE_BASE, attrs, NULL);
+ if (ret != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Failed to load RID Set attrs from %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb)));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ *alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
+ prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
+
+ if (*alloc_pool != prev_alloc_pool) {
+ *exhausted = false;
+ } else {
+ *exhausted = true;
+ }
+
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+
+/*
+ see if we are low on RIDs in the RID Set rIDAllocationPool. If we
+ are, then schedule a replication call with DRSUAPI_EXOP_FSMO_RID_ALLOC
+ to the RID Manager
+ */
+WERROR dreplsrv_ridalloc_check_rid_pool(struct dreplsrv_service *service)
+{
+ struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
+ TALLOC_CTX *tmp_ctx = talloc_new(service);
+ struct ldb_context *ldb = service->samdb;
+ bool exhausted;
+ WERROR werr;
+ int ret;
+ uint64_t alloc_pool;
+
+ if (service->ridalloc.in_progress) {
+ talloc_free(tmp_ctx);
+ return WERR_OK;
+ }
+
+ /*
+ steps:
+ - find who the RID Manager is
+ - if we are the RID Manager then nothing to do
+ - find our RID Set object
+ - load rIDAllocationPool and rIDPreviousAllocationPool
+ - if rIDAllocationPool != rIDPreviousAllocationPool then
+ nothing to do
+ - schedule a getncchanges with DRSUAPI_EXOP_FSMO_RID_ALLOC
+ to the RID Manager
+ */
+
+ /* work out who is the RID Manager */
+ ret = samdb_rid_manager_dn(ldb, tmp_ctx, &rid_manager_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;
+ }
+
+ /* find the DN of the RID Manager */
+ ret = samdb_reference_dn(ldb, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_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;
+ }
+
+ if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) == 0) {
+ /* we are the RID Manager - no need to do a
+ DRSUAPI_EXOP_FSMO_RID_ALLOC */
+ talloc_free(tmp_ctx);
+ return WERR_OK;
+ }
+
+ ret = drepl_ridalloc_pool_exhausted(ldb, &exhausted, &alloc_pool);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return WERR_DS_DRA_INTERNAL_ERROR;
+ }
+
+ DEBUG(2,(__location__ ": Requesting more RIDs from RID Manager\n"));
+
+ werr = drepl_request_new_rid_pool(service, rid_manager_dn, fsmo_role_dn, alloc_pool);
+ talloc_free(tmp_ctx);
+ return werr;
+}
+
+/* called by the samldb ldb module to tell us to ask for a new RID
+ pool */
+void dreplsrv_allocate_rid(struct messaging_context *msg, void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id, DATA_BLOB *data)
+{
+ struct dreplsrv_service *service = talloc_get_type(private_data, struct dreplsrv_service);
+ dreplsrv_ridalloc_check_rid_pool(service);
+}
diff --git a/source4/dsdb/repl/drepl_service.c b/source4/dsdb/repl/drepl_service.c
index a05ccc8d70..44164ff68f 100644
--- a/source4/dsdb/repl/drepl_service.c
+++ b/source4/dsdb/repl/drepl_service.c
@@ -206,6 +206,7 @@ static void dreplsrv_task_init(struct task_server *task)
irpc_add_name(task->msg_ctx, "dreplsrv");
IRPC_REGISTER(task->msg_ctx, drsuapi, DRSUAPI_DSREPLICASYNC, drepl_replica_sync, service);
+ messaging_register(task->msg_ctx, service, MSG_DREPL_ALLOCATE_RID, dreplsrv_allocate_rid);
}
/*
diff --git a/source4/dsdb/repl/drepl_service.h b/source4/dsdb/repl/drepl_service.h
index 0f9684fa78..0a0d721d5c 100644
--- a/source4/dsdb/repl/drepl_service.h
+++ b/source4/dsdb/repl/drepl_service.h
@@ -100,6 +100,8 @@ struct dreplsrv_partition {
struct dreplsrv_partition_source_dsa *sources;
};
+typedef void (*dreplsrv_fsmo_callback_t)(struct dreplsrv_service *, WERROR );
+
struct dreplsrv_out_operation {
struct dreplsrv_out_operation *prev, *next;
@@ -107,7 +109,9 @@ struct dreplsrv_out_operation {
struct dreplsrv_partition_source_dsa *source_dsa;
- struct composite_context *creq;
+ enum drsuapi_DsExtendedOperation extended_op;
+ uint64_t fsmo_info;
+ dreplsrv_fsmo_callback_t callback;
};
struct dreplsrv_notify_operation {
@@ -204,6 +208,11 @@ struct dreplsrv_service {
/* an active notify operation */
struct dreplsrv_notify_operation *n_current;
} ops;
+
+ struct {
+ bool in_progress;
+ struct dreplsrv_partition_source_dsa *rid_manager_source_dsa;
+ } ridalloc;
};
#include "dsdb/repl/drepl_out_helpers.h"
diff --git a/source4/dsdb/samdb/ldb_modules/acl.c b/source4/dsdb/samdb/ldb_modules/acl.c
index a3298362f3..a779821107 100644
--- a/source4/dsdb/samdb/ldb_modules/acl.c
+++ b/source4/dsdb/samdb/ldb_modules/acl.c
@@ -35,10 +35,10 @@
#include "ldb_module.h"
#include "auth/auth.h"
#include "libcli/security/security.h"
-#include "librpc/gen_ndr/ndr_security.h"
#include "dsdb/samdb/samdb.h"
#include "librpc/gen_ndr/ndr_security.h"
#include "param/param.h"
+#include "dsdb/samdb/ldb_modules/util.h"
struct extended_access_check_attribute {
const char *oa_name;
@@ -53,7 +53,7 @@ struct acl_private {
struct acl_context {
struct ldb_module *module;
struct ldb_request *req;
- enum security_user_level user_type;
+ bool am_system;
bool allowedAttributes;
bool allowedAttributesEffective;
bool allowedChildClasses;
@@ -70,14 +70,6 @@ bool is_root_base_dn(struct ldb_context *ldb, struct ldb_dn *dn_to_check)
return (result==0);
}
-static enum security_user_level what_is_user(struct ldb_module *module)
-{
- struct ldb_context *ldb = ldb_module_get_ctx(module);
- struct auth_session_info *session_info
- = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
- return security_session_user_level(session_info);
-}
-
static struct security_token *acl_user_token(struct ldb_module *module)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
@@ -309,7 +301,7 @@ static int acl_check_access_on_attribute(struct ldb_module *module,
struct security_descriptor *sd,
struct dom_sid *rp_sid,
uint32_t access,
- struct dsdb_attribute *attr)
+ const struct dsdb_attribute *attr)
{
int ret;
NTSTATUS status;
@@ -370,7 +362,7 @@ static int acl_check_access_on_class(struct ldb_module *module,
uint32_t access_granted;
struct object_tree *root = NULL;
struct object_tree *new_node = NULL;
- struct GUID *guid;
+ const struct GUID *guid;
const struct dsdb_schema *schema = dsdb_get_schema(ldb);
TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
struct security_token *token = acl_user_token(module);
@@ -450,7 +442,7 @@ static int acl_allowedAttributes(struct ldb_module *module,
struct ldb_control *as_system = ldb_request_get_control(ac->req,
LDB_CONTROL_AS_SYSTEM_OID);
ldb_msg_remove_attr(msg, "allowedAttributesEffective");
- if (ac->user_type == SECURITY_SYSTEM || as_system) {
+ if (ac->am_system || as_system) {
for (i=0; attr_list && attr_list[i]; i++) {
ldb_msg_add_string(msg, "allowedAttributesEffective", attr_list[i]);
}
@@ -468,7 +460,7 @@ static int acl_allowedAttributes(struct ldb_module *module,
return ret;
}
for (i=0; attr_list && attr_list[i]; i++) {
- struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema,
+ const struct dsdb_attribute *attr = dsdb_attribute_by_lDAPDisplayName(schema,
attr_list[i]);
if (!attr) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -566,7 +558,7 @@ static int acl_childClassesEffective(struct ldb_module *module,
struct dom_sid *sid = NULL;
int i, j, ret;
- if (ac->user_type == SECURITY_SYSTEM || as_system) {
+ if (ac->am_system || as_system) {
return acl_childClasses(module, sd_msg, msg, "allowedChildClassesEffective");
}
@@ -650,7 +642,7 @@ static int acl_sDRightsEffective(struct ldb_module *module,
if (ret != LDB_SUCCESS) {
return ret;
}
- if (ac->user_type == SECURITY_SYSTEM || as_system) {
+ if (ac->am_system || as_system) {
flags = SECINFO_OWNER | SECINFO_GROUP | SECINFO_SACL | SECINFO_DACL;
}
else {
@@ -707,7 +699,7 @@ static int acl_add(struct ldb_module *module, struct ldb_request *req)
struct object_tree *new_node = NULL;
struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
- if (what_is_user(module) == SECURITY_SYSTEM || as_system) {
+ if (dsdb_module_am_system(module) || as_system) {
return ldb_next_request(module, req);
}
@@ -773,7 +765,7 @@ static int acl_modify(struct ldb_module *module, struct ldb_request *req)
{
DEBUG(10, ("ldb:acl_modify: %s\n", req->op.mod.message->elements[0].name));
}
- if (what_is_user(module) == SECURITY_SYSTEM || as_system) {
+ if (dsdb_module_am_system(module) || as_system) {
return ldb_next_request(module, req);
}
if (ldb_dn_is_special(req->op.mod.message->dn)) {
@@ -901,7 +893,7 @@ static int acl_delete(struct ldb_module *module, struct ldb_request *req)
struct ldb_control *as_system = ldb_request_get_control(req, LDB_CONTROL_AS_SYSTEM_OID);
DEBUG(10, ("ldb:acl_delete: %s\n", ldb_dn_get_linearized(req->op.del.dn)));
- if (what_is_user(module) == SECURITY_SYSTEM || as_system) {
+ if (dsdb_module_am_system(module) || as_system) {
return ldb_next_request(module, req);
}
@@ -955,7 +947,7 @@ static int acl_rename(struct ldb_module *module, struct ldb_request *req)
};
DEBUG(10, ("ldb:acl_rename: %s\n", ldb_dn_get_linearized(req->op.rename.olddn)));
- if (what_is_user(module) == SECURITY_SYSTEM || as_system) {
+ if (dsdb_module_am_system(module) || as_system) {
return ldb_next_request(module, req);
}
if (ldb_dn_is_special(req->op.rename.olddn)) {
@@ -1135,7 +1127,7 @@ static int acl_search_callback(struct ldb_request *req, struct ldb_reply *ares)
}
}
if (data && data->password_attrs) {
- if (ac->user_type != SECURITY_SYSTEM) {
+ if (!ac->am_system) {
for (i = 0; data->password_attrs[i]; i++) {
ldb_msg_remove_attr(ares->message, data->password_attrs[i]);
}
@@ -1173,7 +1165,7 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req)
ac->module = module;
ac->req = req;
- ac->user_type = what_is_user(module);
+ ac->am_system = dsdb_module_am_system(module);
ac->allowedAttributes = ldb_attr_in_list(req->op.search.attrs, "allowedAttributes");
ac->allowedAttributesEffective = ldb_attr_in_list(req->op.search.attrs, "allowedAttributesEffective");
ac->allowedChildClasses = ldb_attr_in_list(req->op.search.attrs, "allowedChildClasses");
@@ -1183,7 +1175,7 @@ static int acl_search(struct ldb_module *module, struct ldb_request *req)
/* replace any attributes in the parse tree that are private,
so we don't allow a search for 'userPassword=penguin',
just as we would not allow that attribute to be returned */
- if (ac->user_type != SECURITY_SYSTEM) {
+ if (ac->am_system) {
/* FIXME: We should copy the tree and keep the original unmodified. */
/* remove password attributes */
if (data && data->password_attrs) {
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk
index 6128dc9d65..f9f1714358 100644
--- a/source4/dsdb/samdb/ldb_modules/config.mk
+++ b/source4/dsdb/samdb/ldb_modules/config.mk
@@ -1,9 +1,11 @@
################################################
# Start SUBSYSTEM DSDB_MODULE_HELPERS
[SUBSYSTEM::DSDB_MODULE_HELPERS]
-PRIVATE_DEPENDENCIES = LIBLDB LIBNDR SAMDB_SCHEMA
+PRIVATE_DEPENDENCIES = LIBLDB LIBNDR SAMDB_SCHEMA MESSAGING
-DSDB_MODULE_HELPERS_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/util.o
+DSDB_MODULE_HELPERS_OBJ_FILES = \
+ $(dsdbsrcdir)/samdb/ldb_modules/util.o \
+ $(dsdbsrcdir)/samdb/ldb_modules/ridalloc.o
$(eval $(call proto_header_template,$(dsdbsrcdir)/samdb/ldb_modules/util_proto.h,$(DSDB_MODULE_HELPERS_OBJ_FILES:.o=.c)))
@@ -135,13 +137,26 @@ SUBSYSTEM = LIBLDB
INIT_FUNCTION = LDB_MODULE(samba3sam)
PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBLDB SMBPASSWD \
NSS_WRAPPER LIBSECURITY NDR_SECURITY
-# End MODULE ldb_samldb
+# End MODULE ldb_samba3sam
################################################
ldb_samba3sam_OBJ_FILES = \
$(dsdbsrcdir)/samdb/ldb_modules/samba3sam.o
################################################
+# Start MODULE ldb_samba3sid
+[MODULE::ldb_samba3sid]
+SUBSYSTEM = LIBLDB
+INIT_FUNCTION = LDB_MODULE(samba3sid)
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS LIBLDB SMBPASSWD \
+ NSS_WRAPPER LIBSECURITY NDR_SECURITY
+# End MODULE ldb_samba3sid
+################################################
+
+ldb_samba3sid_OBJ_FILES = \
+ $(dsdbsrcdir)/samdb/ldb_modules/samba3sid.o
+
+################################################
# Start MODULE ldb_simple_ldap_map
[MODULE::ldb_simple_ldap_map]
SUBSYSTEM = LIBLDB
@@ -337,7 +352,7 @@ ldb_subtree_delete_OBJ_FILES = $(dsdbsrcdir)/samdb/ldb_modules/subtree_delete.o
[MODULE::ldb_linked_attributes]
INIT_FUNCTION = LDB_MODULE(linked_attributes)
CFLAGS = -Ilib/ldb/include
-PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SAMDB
+PRIVATE_DEPENDENCIES = LIBTALLOC LIBEVENTS SAMDB DSDB_MODULE_HELPERS
SUBSYSTEM = LIBLDB
# End MODULE ldb_linked_attributes
################################################
diff --git a/source4/dsdb/samdb/ldb_modules/instancetype.c b/source4/dsdb/samdb/ldb_modules/instancetype.c
index b17f40e82a..0a297d587a 100644
--- a/source4/dsdb/samdb/ldb_modules/instancetype.c
+++ b/source4/dsdb/samdb/ldb_modules/instancetype.c
@@ -36,6 +36,7 @@
#include "librpc/gen_ndr/ndr_misc.h"
#include "dsdb/samdb/samdb.h"
#include "../libds/common/flags.h"
+#include "dsdb/samdb/ldb_modules/util.h"
struct it_context {
struct ldb_module *module;
@@ -143,7 +144,7 @@ static int instancetype_add(struct ldb_module *module, struct ldb_request *req)
ret = ldb_build_add_req(&down_req, ldb, req,
msg,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
if (ret != LDB_SUCCESS) {
return ret;
diff --git a/source4/dsdb/samdb/ldb_modules/lazy_commit.c b/source4/dsdb/samdb/ldb_modules/lazy_commit.c
index 0502b2efa1..b4eaf50d51 100644
--- a/source4/dsdb/samdb/ldb_modules/lazy_commit.c
+++ b/source4/dsdb/samdb/ldb_modules/lazy_commit.c
@@ -28,6 +28,7 @@
*/
#include "ldb_module.h"
+#include "dsdb/samdb/ldb_modules/util.h"
static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
{
@@ -47,28 +48,28 @@ static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
req->op.search.tree,
req->op.search.attrs,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_ADD:
ret = ldb_build_add_req(&new_req, ldb_module_get_ctx(module), req,
req->op.add.message,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_MODIFY:
ret = ldb_build_mod_req(&new_req, ldb_module_get_ctx(module), req,
req->op.mod.message,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_DELETE:
ret = ldb_build_del_req(&new_req, ldb_module_get_ctx(module), req,
req->op.del.dn,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_RENAME:
@@ -76,7 +77,7 @@ static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
req->op.rename.olddn,
req->op.rename.newdn,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
case LDB_EXTENDED:
@@ -85,7 +86,7 @@ static int unlazy_op(struct ldb_module *module, struct ldb_request *req)
req->op.extended.oid,
req->op.extended.data,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
break;
default:
diff --git a/source4/dsdb/samdb/ldb_modules/partition.c b/source4/dsdb/samdb/ldb_modules/partition.c
index 01ae0a10a7..59e7fab393 100644
--- a/source4/dsdb/samdb/ldb_modules/partition.c
+++ b/source4/dsdb/samdb/ldb_modules/partition.c
@@ -39,7 +39,6 @@ struct part_request {
struct partition_context {
struct ldb_module *module;
struct ldb_request *req;
- bool got_success;
struct part_request *part_req;
int num_requests;
@@ -160,7 +159,7 @@ static int partition_req_callback(struct ldb_request *req,
}
}
- if (ares->error != LDB_SUCCESS && !ac->got_success) {
+ if (ares->error != LDB_SUCCESS) {
return ldb_module_done(ac->req, ares->controls,
ares->response, ares->error);
}
@@ -182,9 +181,6 @@ static int partition_req_callback(struct ldb_request *req,
return ldb_module_send_entry(ac->req, ares->message, ares->controls);
case LDB_REPLY_DONE:
- if (ares->error == LDB_SUCCESS) {
- ac->got_success = true;
- }
if (ac->req->operation == LDB_EXTENDED) {
/* FIXME: check for ares->response, replmd does not fill it ! */
if (ares->response) {
@@ -205,7 +201,7 @@ static int partition_req_callback(struct ldb_request *req,
/* this was the last one, call callback */
return ldb_module_done(ac->req, ares->controls,
ares->response,
- ac->got_success?LDB_SUCCESS:ares->error);
+ ares->error);
}
/* not the last, now call the next one */
@@ -528,9 +524,7 @@ static int partition_search(struct ldb_module *module, struct ldb_request *req)
*/
if (ldb_dn_compare(data->partitions[i]->ctrl->dn, req->op.search.base) == 0) {
match = true;
- if (req->op.search.scope == LDB_SCOPE_BASE) {
- stop = true;
- }
+ stop = true;
}
if (!match &&
(ldb_dn_compare_base(req->op.search.base, data->partitions[i]->ctrl->dn) == 0 &&
diff --git a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
index 796ecaf7bc..00d9a30fd3 100644
--- a/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
+++ b/source4/dsdb/samdb/ldb_modules/pdc_fsmo.c
@@ -75,8 +75,8 @@ static int pdc_fsmo_init(struct ldb_module *module)
return ldb_next_init(module);
} else if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "pdc_fsmo_init: failed to search the domain object: %d:%s",
- ret, ldb_strerror(ret));
+ "pdc_fsmo_init: failed to search the domain object: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
talloc_free(mem_ctx);
return ret;
}
diff --git a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
index 890eb91d6d..b4caac4c8d 100644
--- a/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
+++ b/source4/dsdb/samdb/ldb_modules/repl_meta_data.c
@@ -672,7 +672,7 @@ static int replmd_add(struct ldb_module *module, struct ldb_request *req)
/* check if there's a show relax control (used by provision to say 'I know what I'm doing') */
control = ldb_request_get_control(req, LDB_CONTROL_RELAX_OID);
if (control) {
- allow_add_guid = 1;
+ allow_add_guid = true;
}
/* do not manipulate our control entries */
@@ -2667,10 +2667,12 @@ static int replmd_replicated_apply_merge(struct replmd_replicated_request *ar)
break;
}
- DEBUG(1,("Discarding older DRS attribute update to %s on %s from %s\n",
- msg->elements[i-removed_attrs].name,
- ldb_dn_get_linearized(msg->dn),
- GUID_string(ar, &rmd->ctr.ctr1.array[i].originating_invocation_id)));
+ if (rmd->ctr.ctr1.array[i].attid != DRSUAPI_ATTRIBUTE_instanceType) {
+ DEBUG(1,("Discarding older DRS attribute update to %s on %s from %s\n",
+ msg->elements[i-removed_attrs].name,
+ ldb_dn_get_linearized(msg->dn),
+ GUID_string(ar, &rmd->ctr.ctr1.array[i].originating_invocation_id)));
+ }
/* we don't want to apply this change so remove the attribute */
ldb_msg_remove_element(msg, &msg->elements[i-removed_attrs]);
diff --git a/source4/dsdb/samdb/ldb_modules/ridalloc.c b/source4/dsdb/samdb/ldb_modules/ridalloc.c
new file mode 100644
index 0000000000..a64062fcdc
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/ridalloc.c
@@ -0,0 +1,646 @@
+/*
+ RID allocation helper functions
+
+ Copyright (C) Andrew Bartlett 2010
+ Copyright (C) Andrew Tridgell 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/>.
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: RID allocation logic
+ *
+ * Description: manage RID Set and RID Manager objects
+ *
+ */
+
+#include "includes.h"
+#include "ldb_module.h"
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+#include "lib/messaging/irpc.h"
+#include "param/param.h"
+#include "librpc/gen_ndr/ndr_misc.h"
+
+/*
+ Note: the RID allocation attributes in AD are very badly named. Here
+ is what we think they really do:
+
+ in RID Set object:
+ - rIDPreviousAllocationPool: the pool which a DC is currently
+ pulling RIDs from. Managed by client DC
+
+ - rIDAllocationPool: the pool that the DC will switch to next,
+ when rIDPreviousAllocationPool is exhausted. Managed by RID Manager.
+
+ - rIDNextRID: the last RID allocated by this DC. Managed by client DC
+
+ in RID Manager object:
+ - rIDAvailablePool: the pool where the RID Manager gets new rID
+ pools from when it gets a EXOP_RID_ALLOC getncchanges call (or
+ locally when the DC is the RID Manager)
+ */
+
+
+/*
+ make a IRPC call to the drepl task to ask it to get the RID
+ Manager to give us another RID pool.
+
+ This function just sends the message to the drepl task then
+ returns immediately. It should be called well before we
+ completely run out of RIDs
+ */
+static void ridalloc_poke_rid_manager(struct ldb_module *module)
+{
+ struct messaging_context *msg;
+ struct server_id *server;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct loadparm_context *lp_ctx = ldb_get_opaque(ldb, "loadparm");
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+
+ msg = messaging_client_init(tmp_ctx, lp_messaging_path(tmp_ctx, lp_ctx),
+ lp_iconv_convenience(lp_ctx),
+ ldb_get_event_context(ldb));
+ if (!msg) {
+ DEBUG(3,(__location__ ": Failed to create messaging context\n"));
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ server = irpc_servers_byname(msg, msg, "dreplsrv");
+ if (!server) {
+ /* this means the drepl service is not running */
+ talloc_free(tmp_ctx);
+ return;
+ }
+
+ messaging_send(msg, server[0], MSG_DREPL_ALLOCATE_RID, NULL);
+
+ /* we don't care if the message got through */
+ talloc_free(tmp_ctx);
+}
+
+
+/*
+ allocate a new range of RIDs in the RID Manager object
+ */
+static int ridalloc_rid_manager_allocate(struct ldb_module *module, struct ldb_dn *rid_manager_dn, uint64_t *new_pool)
+{
+ int ret;
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+ const char *attrs[] = { "rIDAvailablePool", NULL };
+ uint64_t rid_pool, new_rid_pool, dc_pool;
+ uint32_t rid_pool_lo, rid_pool_hi;
+ struct ldb_result *res;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ const unsigned alloc_size = 500;
+
+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_manager_dn, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find rIDAvailablePool in %s - %s",
+ ldb_dn_get_linearized(rid_manager_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ rid_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAvailablePool", 0);
+ rid_pool_lo = rid_pool & 0xFFFFFFFF;
+ rid_pool_hi = rid_pool >> 32;
+ if (rid_pool_lo >= rid_pool_hi) {
+ ldb_asprintf_errstring(ldb, "Out of RIDs in RID Manager - rIDAvailablePool is %u-%u",
+ rid_pool_lo, rid_pool_hi);
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* lower part of new pool is the low part of the rIDAvailablePool */
+ dc_pool = rid_pool_lo;
+
+ /* allocate 500 RIDs to this DC */
+ rid_pool_lo = MIN(rid_pool_hi, rid_pool_lo + alloc_size);
+
+ /* work out upper part of new pool */
+ dc_pool |= (((uint64_t)rid_pool_lo-1)<<32);
+
+ /* and new rIDAvailablePool value */
+ new_rid_pool = rid_pool_lo | (((uint64_t)rid_pool_hi)<<32);
+
+ ret = dsdb_module_constrainted_update_integer(module, rid_manager_dn, "rIDAvailablePool",
+ rid_pool, new_rid_pool);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to update rIDAvailablePool - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ (*new_pool) = dc_pool;
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+/*
+ create a RID Set object for the specified DC
+ */
+static int ridalloc_create_rid_set_ntds(struct ldb_module *module, TALLOC_CTX *mem_ctx,
+ struct ldb_dn *rid_manager_dn,
+ struct ldb_dn *ntds_dn, struct ldb_dn **dn)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
+ int ret;
+ uint64_t dc_pool;
+ struct ldb_message *msg;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+
+ /*
+ steps:
+
+ find the machine object for the DC
+ construct the RID Set DN
+ load rIDAvailablePool to find next available set
+ modify RID Manager object to update rIDAvailablePool
+ add the RID Set object
+ link to the RID Set object in machine object
+ */
+
+ server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
+ if (!server_dn) {
+ ldb_module_oom(module);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
+ ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ rid_set_dn = ldb_dn_copy(tmp_ctx, machine_dn);
+ if (rid_set_dn == NULL) {
+ ldb_module_oom(module);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ if (! ldb_dn_add_child_fmt(rid_set_dn, "CN=RID Set")) {
+ ldb_module_oom(module);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* grab a pool from the RID Manager object */
+ ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, &dc_pool);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* create the RID Set object */
+ msg = ldb_msg_new(tmp_ctx);
+ msg->dn = rid_set_dn;
+
+ ret = ldb_msg_add_string(msg, "objectClass", "rIDSet");
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ ret = ldb_msg_add_fmt(msg, "rIDAllocationPool", "%llu", (unsigned long long)dc_pool);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* w2k8-r2 sets these to zero when first created */
+ ret = ldb_msg_add_fmt(msg, "rIDPreviousAllocationPool", "0");
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ ret = ldb_msg_add_fmt(msg, "rIDUsedPool", "0");
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ ret = ldb_msg_add_fmt(msg, "rIDNextRID", "0");
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* we need this to go all the way to the top of the module
+ * stack, as we need all the extra attributes added (including
+ * complex ones like ntsecuritydescriptor) */
+ ret = dsdb_module_add(module, msg, DSDB_FLAG_TOP_MODULE | DSDB_MODIFY_RELAX);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to add RID Set %s - %s",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* add the rIDSetReferences link */
+ msg = ldb_msg_new(tmp_ctx);
+ msg->dn = machine_dn;
+
+ ret = ldb_msg_add_string(msg, "rIDSetReferences", ldb_dn_get_linearized(rid_set_dn));
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ msg->elements[0].flags = LDB_FLAG_MOD_ADD;
+
+ ret = dsdb_module_modify(module, msg, 0);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to add rIDSetReferences to %s - %s",
+ ldb_dn_get_linearized(msg->dn),
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ (*dn) = talloc_steal(mem_ctx, rid_set_dn);
+
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+
+/*
+ create a RID Set object for this DC
+ */
+static int ridalloc_create_own_rid_set(struct ldb_module *module, TALLOC_CTX *mem_ctx,
+ struct ldb_dn **dn)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+
+ /* work out who is the RID Manager */
+ ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* find the DN of the RID Manager */
+ ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
+ ridalloc_poke_rid_manager(module);
+ ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
+ talloc_free(tmp_ctx);
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ ret = ridalloc_create_rid_set_ntds(module, mem_ctx, rid_manager_dn, fsmo_role_dn, dn);
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+/*
+ refresh a RID Set object for the specified DC
+ also returns the first RID for the new pool
+ */
+static int ridalloc_refresh_rid_set_ntds(struct ldb_module *module,
+ struct ldb_dn *rid_manager_dn,
+ struct ldb_dn *ntds_dn, uint64_t *new_pool)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+ struct ldb_dn *server_dn, *machine_dn, *rid_set_dn;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ int ret;
+
+ /* grab a pool from the RID Manager object */
+ ret = ridalloc_rid_manager_allocate(module, rid_manager_dn, new_pool);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
+ if (!server_dn) {
+ ldb_module_oom(module);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find serverReference in %s - %s",
+ ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
+ ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_module_set_integer(module, rid_set_dn, "rIDAllocationPool", *new_pool);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to modify RID Set object %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+
+/*
+ get a new RID pool for ourselves
+ also returns the first rid for the new pool
+ */
+static int ridalloc_refresh_own_pool(struct ldb_module *module, uint64_t *new_pool)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+ struct ldb_dn *rid_manager_dn, *fsmo_role_dn;
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+
+ /* work out who is the RID Manager */
+ ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find RID Manager object - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* find the DN of the RID Manager */
+ ret = dsdb_module_reference_dn(module, tmp_ctx, rid_manager_dn, "fSMORoleOwner", &fsmo_role_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find fSMORoleOwner in RID Manager object - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (ldb_dn_compare(samdb_ntds_settings_dn(ldb), fsmo_role_dn) != 0) {
+ ridalloc_poke_rid_manager(module);
+ ldb_asprintf_errstring(ldb, "Remote RID Set allocation needs refresh");
+ talloc_free(tmp_ctx);
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ ret = ridalloc_refresh_rid_set_ntds(module, rid_manager_dn, fsmo_role_dn, new_pool);
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
+/* allocate a RID using our RID Set
+ If we run out of RIDs then allocate a new pool
+ either locally or by contacting the RID Manager
+*/
+int ridalloc_allocate_rid(struct ldb_module *module, uint32_t *rid)
+{
+ struct ldb_context *ldb;
+ static const char * const attrs[] = { "rIDAllocationPool", "rIDPreviousAllocationPool",
+ "rIDNextRID" , "rIDUsedPool", NULL };
+ int ret;
+ struct ldb_dn *rid_set_dn;
+ struct ldb_result *res;
+ uint64_t alloc_pool, prev_alloc_pool;
+ uint32_t prev_alloc_pool_lo, prev_alloc_pool_hi;
+ uint32_t rid_used_pool;
+ int prev_rid;
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+
+ (*rid) = 0;
+ ldb = ldb_module_get_ctx(module);
+
+ ret = samdb_rid_set_dn(ldb, tmp_ctx, &rid_set_dn);
+ if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+ ret = ridalloc_create_own_rid_set(module, tmp_ctx, &rid_set_dn);
+ }
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": No RID Set DN - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
+ ldb_dn_get_linearized(rid_set_dn));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ prev_alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDPreviousAllocationPool", 0);
+ alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
+ prev_rid = ldb_msg_find_attr_as_int(res->msgs[0], "rIDNextRID", 0);
+ rid_used_pool = ldb_msg_find_attr_as_int(res->msgs[0], "rIDUsedPool", 0);
+ if (alloc_pool == 0) {
+ ldb_asprintf_errstring(ldb, __location__ ": Bad RID Set %s",
+ ldb_dn_get_linearized(rid_set_dn));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
+ prev_alloc_pool_hi = prev_alloc_pool >> 32;
+ if (prev_rid >= prev_alloc_pool_hi) {
+ if (prev_alloc_pool == 0) {
+ ret = dsdb_module_set_integer(module, rid_set_dn, "rIDPreviousAllocationPool", alloc_pool);
+ } else {
+ ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
+ prev_alloc_pool, alloc_pool);
+ }
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ prev_alloc_pool = alloc_pool;
+ prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
+ prev_alloc_pool_hi = prev_alloc_pool >> 32;
+
+ /* update the rIDUsedPool attribute */
+ ret = dsdb_module_set_integer(module, rid_set_dn, "rIDUsedPool", rid_used_pool+1);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDUsedPool on %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ (*rid) = prev_alloc_pool_lo;
+ }
+
+ /* see if we are still out of RIDs, and if so then ask
+ the RID Manager to give us more */
+ if (prev_rid >= prev_alloc_pool_hi) {
+ uint64_t new_pool;
+ ret = ridalloc_refresh_own_pool(module, &new_pool);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDPreviousAllocationPool",
+ prev_alloc_pool, new_pool);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to update rIDPreviousAllocationPool on %s - %s",
+ ldb_dn_get_linearized(rid_set_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ prev_alloc_pool = new_pool;
+ prev_alloc_pool_lo = prev_alloc_pool & 0xFFFFFFFF;
+ prev_alloc_pool_hi = prev_alloc_pool >> 32;
+ (*rid) = prev_alloc_pool_lo;
+ } else {
+ /* despite the name, rIDNextRID is the value of the last user
+ * added by this DC, not the next available RID */
+ if (*rid == 0) {
+ (*rid) = prev_rid + 1;
+ }
+ }
+
+ if (*rid < prev_alloc_pool_lo || *rid > prev_alloc_pool_hi) {
+ ldb_asprintf_errstring(ldb, __location__ ": Bad rid chosen %u from range %u-%u",
+ (unsigned)*rid, (unsigned)prev_alloc_pool_lo,
+ (unsigned)prev_alloc_pool_hi);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* now modify the RID Set to use up this RID using a
+ * constrained delete/add if possible */
+ if (prev_rid == 0) {
+ ret = dsdb_module_set_integer(module, rid_set_dn, "rIDNextRID", *rid);
+ } else {
+ ret = dsdb_module_constrainted_update_integer(module, rid_set_dn, "rIDNextRID", prev_rid, *rid);
+ }
+
+ /* if we are half-exhausted then ask the repl task to start
+ * getting another one */
+ if (*rid > (prev_alloc_pool_hi + prev_alloc_pool_lo)/2) {
+ ridalloc_poke_rid_manager(module);
+ }
+
+ talloc_free(tmp_ctx);
+
+ return ret;
+}
+
+
+/*
+ called by DSDB_EXTENDED_ALLOCATE_RID_POOL extended operation in samldb
+ */
+int ridalloc_allocate_rid_pool_fsmo(struct ldb_module *module, struct dsdb_fsmo_extended_op *exop)
+{
+ struct ldb_dn *ntds_dn, *server_dn, *machine_dn, *rid_set_dn;
+ struct ldb_dn *rid_manager_dn;
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ uint64_t new_pool;
+
+ ret = dsdb_module_dn_by_guid(module, tmp_ctx, &exop->destination_dsa_guid, &ntds_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Unable to find NTDS object for guid %s - %s\n",
+ GUID_string(tmp_ctx, &exop->destination_dsa_guid), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ server_dn = ldb_dn_get_parent(tmp_ctx, ntds_dn);
+ if (!server_dn) {
+ ldb_module_oom(module);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = dsdb_module_reference_dn(module, tmp_ctx, server_dn, "serverReference", &machine_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to find serverReference in %s - %s",
+ ldb_dn_get_linearized(server_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+
+ ret = dsdb_module_rid_manager_dn(module, tmp_ctx, &rid_manager_dn);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": Failed to find RID Manager object - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_module_reference_dn(module, tmp_ctx, machine_dn, "rIDSetReferences", &rid_set_dn);
+ if (ret == LDB_ERR_NO_SUCH_ATTRIBUTE) {
+ ret = ridalloc_create_rid_set_ntds(module, tmp_ctx, rid_manager_dn, ntds_dn, &rid_set_dn);
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, "Failed to find rIDSetReferences in %s - %s",
+ ldb_dn_get_linearized(machine_dn), ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ if (exop->fsmo_info != 0) {
+ const char *attrs[] = { "rIDAllocationPool", NULL };
+ struct ldb_result *res;
+ uint64_t alloc_pool;
+
+ ret = dsdb_module_search_dn(module, tmp_ctx, &res, rid_set_dn, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb, __location__ ": No RID Set %s",
+ ldb_dn_get_linearized(rid_set_dn));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ alloc_pool = ldb_msg_find_attr_as_uint64(res->msgs[0], "rIDAllocationPool", 0);
+ if (alloc_pool != exop->fsmo_info) {
+ /* it has already been updated */
+ DEBUG(2,(__location__ ": rIDAllocationPool fsmo_info mismatch - already changed (0x%llx 0x%llx)\n",
+ (unsigned long long)exop->fsmo_info,
+ (unsigned long long)alloc_pool));
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+ }
+ }
+
+ ret = ridalloc_refresh_rid_set_ntds(module, rid_manager_dn, ntds_dn, &new_pool);
+ talloc_free(tmp_ctx);
+ return ret;
+}
diff --git a/source4/dsdb/samdb/ldb_modules/samba3sid.c b/source4/dsdb/samdb/ldb_modules/samba3sid.c
new file mode 100644
index 0000000000..76848eb258
--- /dev/null
+++ b/source4/dsdb/samdb/ldb_modules/samba3sid.c
@@ -0,0 +1,197 @@
+/*
+ samba3sid module
+
+ Copyright (C) Andrew Bartlett 2010
+ Copyright (C) Andrew Tridgell 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/>.
+*/
+
+/*
+ add objectSID to users and groups using samba3 nextRid method
+ */
+
+#include "includes.h"
+#include "libcli/ldap/ldap_ndr.h"
+#include "ldb_module.h"
+#include "dsdb/samdb/samdb.h"
+#include "dsdb/samdb/ldb_modules/util.h"
+#include "libcli/security/security.h"
+#include "librpc/gen_ndr/ndr_security.h"
+#include "../lib/util/util_ldb.h"
+#include "ldb_wrap.h"
+#include "param/param.h"
+
+/*
+ RID algorithm from pdb_ldap.c in source3/passdb/
+ (loosely based on Volkers code)
+ */
+static int samba3sid_next_sid(struct ldb_module *module,
+ TALLOC_CTX *mem_ctx, char **sid)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ struct ldb_result *res;
+ const char *attrs[] = { "sambaNextRid", "sambaNextUserRid",
+ "sambaNextGroupRid", "sambaSID", NULL };
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ int sambaNextRid, sambaNextGroupRid, sambaNextUserRid;
+ struct ldb_message *msg;
+ int rid;
+ const char *sambaSID;
+
+ ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
+ attrs, DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
+ "(&(objectClass=sambaDomain)(sambaDomainName=%s))",
+ lp_sam_name(ldb_get_opaque(ldb, "loadparm")));
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": Failed to find domain object - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+ if (res->count != 1) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": Expected exactly 1 domain object - got %u",
+ res->count);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ msg = res->msgs[0];
+
+ sambaNextRid = ldb_msg_find_attr_as_uint(msg, "sambaNextRid", -1);
+ sambaNextUserRid = ldb_msg_find_attr_as_uint(msg, "sambaNextUserRid", -1);
+ sambaNextGroupRid = ldb_msg_find_attr_as_uint(msg, "sambaNextGroupRid", -1);
+ sambaSID = ldb_msg_find_attr_as_string(msg, "sambaSID", NULL);
+
+ if (sambaSID == NULL) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": No sambaSID in %s",
+ ldb_dn_get_linearized(msg->dn));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* choose the highest of the 3 - see pdb_ldap.c for an
+ * explanation */
+ rid = sambaNextRid;
+ if (sambaNextUserRid > rid) {
+ rid = sambaNextUserRid;
+ }
+ if (sambaNextGroupRid > rid) {
+ rid = sambaNextGroupRid;
+ }
+ if (rid == -1) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": No sambaNextRid in %s",
+ ldb_dn_get_linearized(msg->dn));
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* sambaNextRid is actually the previous RID .... */
+ rid += 1;
+
+ (*sid) = talloc_asprintf(tmp_ctx, "%s-%d", sambaSID, rid);
+ if (!*sid) {
+ ldb_module_oom(module);
+ talloc_free(tmp_ctx);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = dsdb_module_constrainted_update_integer(module, msg->dn,
+ "sambaNextRid",
+ sambaNextRid, rid);
+ if (ret != LDB_SUCCESS) {
+ ldb_asprintf_errstring(ldb,
+ __location__
+ ": Failed to update sambaNextRid - %s",
+ ldb_errstring(ldb));
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ talloc_steal(mem_ctx, *sid);
+ talloc_free(tmp_ctx);
+ return LDB_SUCCESS;
+}
+
+
+
+/* add */
+static int samba3sid_add(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb;
+ int ret;
+ const struct ldb_message *msg = req->op.add.message;
+ struct ldb_message *new_msg;
+ char *sid;
+ struct ldb_request *new_req;
+
+ ldb = ldb_module_get_ctx(module);
+
+ /* do not manipulate our control entries */
+ if (ldb_dn_is_special(req->op.add.message->dn)) {
+ return ldb_next_request(module, req);
+ }
+
+ if (!samdb_find_attribute(ldb, msg, "objectclass", "posixAccount") &&
+ !samdb_find_attribute(ldb, msg, "objectclass", "posixGroup")) {
+ /* its not a user or a group */
+ return ldb_next_request(module, req);
+ }
+
+ if (ldb_msg_find_element(msg, "sambaSID")) {
+ /* a SID was supplied */
+ return ldb_next_request(module, req);
+ }
+
+ new_msg = ldb_msg_copy_shallow(req, req->op.add.message);
+ if (!new_msg) {
+ ldb_module_oom(module);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ ret = samba3sid_next_sid(module, new_msg, &sid);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ret = ldb_msg_add_steal_string(new_msg, "sambaSID", sid);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ ret = ldb_build_add_req(&new_req, ldb, req,
+ new_msg,
+ req->controls,
+ req, dsdb_next_callback,
+ req);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ return ldb_next_request(module, new_req);
+}
+
+_PUBLIC_ const struct ldb_module_ops ldb_samba3sid_module_ops = {
+ .name = "samba3sid",
+ .add = samba3sid_add,
+};
+
diff --git a/source4/dsdb/samdb/ldb_modules/samba_dsdb.c b/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
index a461a94806..44526128f1 100644
--- a/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
+++ b/source4/dsdb/samdb/ldb_modules/samba_dsdb.c
@@ -138,53 +138,6 @@ static int prepare_modules_line(struct ldb_context *ldb,
-/*
- initialise the invocationID for a standalone server
- */
-static int initialise_invocation_id(struct ldb_module *module, struct GUID *guid)
-{
- struct ldb_message *msg;
- struct ldb_context *ldb = ldb_module_get_ctx(module);
- int ret;
-
- *guid = GUID_random();
-
- msg = ldb_msg_new(module);
- if (msg == NULL) {
- ldb_module_oom(module);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- msg->dn = ldb_dn_new(msg, ldb, "@SAMBA_DSDB");
- if (!msg->dn) {
- ldb_module_oom(module);
- talloc_free(msg);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- ret = dsdb_msg_add_guid(msg, guid, "invocationID");
- if (ret != LDB_SUCCESS) {
- ldb_module_oom(module);
- talloc_free(msg);
- return ret;
- }
- msg->elements[0].flags = LDB_FLAG_MOD_ADD;
-
- ret = ldb_modify(ldb, msg);
- if (ret != LDB_SUCCESS) {
- ldb_asprintf_errstring(ldb, "Failed to setup standalone invocationID - %s",
- ldb_errstring(ldb));
- talloc_free(msg);
- return ret;
- }
-
- DEBUG(1,("Initialised standalone invocationID to %s\n",
- GUID_string(msg, guid)));
-
- talloc_free(msg);
-
- return LDB_SUCCESS;
-}
-
-
static int samba_dsdb_init(struct ldb_module *module)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
@@ -258,7 +211,7 @@ static int samba_dsdb_init(struct ldb_module *module)
static const char *openldap_backend_modules[] = {
"entryuuid", "paged_searches", NULL };
- static const char *samba_dsdb_attrs[] = { "backendType", "serverRole", "invocationID", NULL };
+ static const char *samba_dsdb_attrs[] = { "backendType", "serverRole", NULL };
const char *backendType, *serverRole;
if (!tmp_ctx) {
@@ -293,34 +246,6 @@ static int samba_dsdb_init(struct ldb_module *module)
return ret;
}
- if (strcmp(serverRole, "standalone") == 0 ||
- strcmp(serverRole, "member server") == 0) {
- struct GUID *guid;
-
- guid = talloc(module, struct GUID);
- if (!guid) {
- ldb_module_oom(module);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- *guid = samdb_result_guid(res->msgs[0], "invocationID");
- if (GUID_all_zero(guid)) {
- ret = initialise_invocation_id(module, guid);
- if (ret != LDB_SUCCESS) {
- talloc_free(tmp_ctx);
- return ret;
- }
- }
-
- /* cache the domain_sid in the ldb. See the matching
- * code in samdb_ntds_invocation_id() */
- ret = ldb_set_opaque(ldb, "cache.invocation_id", guid);
- if (ret != LDB_SUCCESS) {
- talloc_free(tmp_ctx);
- return ret;
- }
- }
-
backend_modules = NULL;
if (strcasecmp(backendType, "ldb") == 0) {
extended_dn_module = extended_dn_module_ldb;
diff --git a/source4/dsdb/samdb/ldb_modules/samldb.c b/source4/dsdb/samdb/ldb_modules/samldb.c
index 17a99c74c7..ccf76aaef2 100644
--- a/source4/dsdb/samdb/ldb_modules/samldb.c
+++ b/source4/dsdb/samdb/ldb_modules/samldb.c
@@ -59,12 +59,6 @@ struct samldb_ctx {
/* the resulting message */
struct ldb_message *msg;
- /* used to find parent domain */
- struct ldb_dn *check_dn;
- struct ldb_dn *domain_dn;
- struct dom_sid *domain_sid;
- uint32_t next_rid;
-
/* holds the entry SID */
struct dom_sid *sid;
@@ -175,139 +169,6 @@ static int samldb_next_step(struct samldb_ctx *ac)
}
}
-/*
- * samldb_get_parent_domain (async)
- */
-
-static int samldb_get_parent_domain(struct samldb_ctx *ac);
-
-static int samldb_get_parent_domain_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- const char *nextRid;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
-
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- /* save entry */
- if ((ac->domain_dn != NULL) || (ac->domain_sid != NULL)) {
- /* one too many! */
- ldb_set_errstring(ldb,
- "Invalid number of results while searching "
- "for domain object!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- nextRid = ldb_msg_find_attr_as_string(ares->message,
- "nextRid", NULL);
- if (nextRid == NULL) {
- ldb_asprintf_errstring(ldb,
- "While looking for domain above %s attribute nextRid not found in %s!",
- ldb_dn_get_linearized(
- ac->req->op.add.message->dn),
- ldb_dn_get_linearized(ares->message->dn));
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- ac->next_rid = strtol(nextRid, NULL, 0);
-
- ac->domain_sid = samdb_result_dom_sid(ac, ares->message,
- "objectSid");
- if (ac->domain_sid == NULL) {
- ldb_set_errstring(ldb,
- "Unable to get the parent domain SID!");
- ret = LDB_ERR_CONSTRAINT_VIOLATION;
- break;
- }
- ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
-
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_REFERRAL:
- /* ignore */
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_DONE:
- talloc_free(ares);
- if ((ac->domain_dn == NULL) || (ac->domain_sid == NULL)) {
- /* not found -> retry */
- ret = samldb_get_parent_domain(ac);
- } else {
- /* found, go on */
- ret = samldb_next_step(ac);
- }
- break;
- }
-
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
- }
-
- return LDB_SUCCESS;
-}
-
-/* Find a domain object in the parents of a particular DN. */
-static int samldb_get_parent_domain(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- static const char * const attrs[] = { "objectSid", "nextRid", NULL };
- struct ldb_request *req;
- struct ldb_dn *dn;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
-
- if (ac->check_dn == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- dn = ldb_dn_get_parent(ac, ac->check_dn);
- if (dn == NULL) {
- ldb_set_errstring(ldb,
- "Unable to find parent domain object!");
- return LDB_ERR_CONSTRAINT_VIOLATION;
- }
-
- ac->check_dn = dn;
-
- ret = ldb_build_search_req(&req, ldb, ac,
- dn, LDB_SCOPE_BASE,
- "(|(objectClass=domain)"
- "(objectClass=builtinDomain))",
- attrs,
- NULL,
- ac, samldb_get_parent_domain_callback,
- ac->req);
-
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- return ldb_next_request(ac->module, req);
-}
-
-
static int samldb_generate_samAccountName(struct ldb_message *msg)
{
char *name;
@@ -395,7 +256,7 @@ static int samldb_check_samAccountName(struct samldb_ctx *ac)
}
ret = ldb_build_search_req(&req, ldb, ac,
- ac->domain_dn, LDB_SCOPE_SUBTREE,
+ samdb_base_dn(ldb), LDB_SCOPE_SUBTREE,
filter, NULL,
NULL,
ac, samldb_check_samAccountName_callback,
@@ -464,134 +325,45 @@ static int samldb_check_samAccountType(struct samldb_ctx *ac)
return samldb_next_step(ac);
}
-
-/*
- * samldb_get_sid_domain (async)
- */
-
-static int samldb_get_sid_domain_callback(struct ldb_request *req,
- struct ldb_reply *ares)
+static bool samldb_msg_add_sid(struct ldb_message *msg,
+ const char *name,
+ const struct dom_sid *sid)
{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- const char *nextRid;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
-
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- /* save entry */
- if (ac->next_rid != 0) {
- /* one too many! */
- ldb_set_errstring(ldb,
- "Invalid number of results while searching "
- "for domain object!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- nextRid = ldb_msg_find_attr_as_string(ares->message,
- "nextRid", NULL);
- if (nextRid == NULL) {
- ldb_asprintf_errstring(ldb,
- "Attribute nextRid not found in %s!",
- ldb_dn_get_linearized(ares->message->dn));
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- ac->next_rid = strtol(nextRid, NULL, 0);
-
- ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
-
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_REFERRAL:
- /* ignore */
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_DONE:
- talloc_free(ares);
- if (ac->next_rid == 0) {
- ldb_asprintf_errstring(ldb,
- "Unable to get nextRid from domain entry!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- /* found, go on */
- ret = samldb_next_step(ac);
- break;
- }
+ struct ldb_val v;
+ enum ndr_err_code ndr_err;
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
+ ndr_err = ndr_push_struct_blob(&v, msg, NULL, sid,
+ (ndr_push_flags_fn_t)ndr_push_dom_sid);
+ if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+ return false;
}
-
- return LDB_SUCCESS;
+ return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
}
-/* Find a domain object in the parents of a particular DN. */
-static int samldb_get_sid_domain(struct samldb_ctx *ac)
+
+/* allocate a SID using our RID Set */
+static int samldb_allocate_sid(struct samldb_ctx *ac)
{
- struct ldb_context *ldb;
- static const char * const attrs[] = { "nextRid", NULL };
- struct ldb_request *req;
- char *filter;
+ uint32_t rid;
int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (ac->sid == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
+ ret = ridalloc_allocate_rid(ac->module, &rid);
+ if (ret != LDB_SUCCESS) {
+ return ret;
}
- ac->domain_sid = dom_sid_dup(ac, ac->sid);
- if (!ac->domain_sid) {
+ ac->sid = dom_sid_add_rid(ac, samdb_domain_sid(ldb), rid);
+ if (ac->sid == NULL) {
+ ldb_module_oom(ac->module);
return LDB_ERR_OPERATIONS_ERROR;
}
- /* get the domain component part of the provided SID */
- ac->domain_sid->num_auths--;
- filter = talloc_asprintf(ac,
- "(&(objectSid=%s)"
- "(|(objectClass=domain)"
- "(objectClass=builtinDomain)))",
- ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
- if (filter == NULL) {
+ if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
return LDB_ERR_OPERATIONS_ERROR;
}
- ret = ldb_build_search_req(&req, ldb, ac,
- ldb_get_default_basedn(ldb),
- LDB_SCOPE_SUBTREE,
- filter, attrs,
- NULL,
- ac, samldb_get_sid_domain_callback,
- ac->req);
-
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- ac->next_rid = 0;
- return ldb_next_request(ac->module, req);
+ return samldb_next_step(ac);
}
/*
@@ -722,161 +494,6 @@ static int samldb_check_primaryGroupID_2(struct samldb_ctx *ac)
}
-static bool samldb_msg_add_sid(struct ldb_message *msg,
- const char *name,
- const struct dom_sid *sid)
-{
- struct ldb_val v;
- enum ndr_err_code ndr_err;
-
- ndr_err = ndr_push_struct_blob(&v, msg, NULL, sid,
- (ndr_push_flags_fn_t)ndr_push_dom_sid);
- if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
- return false;
- }
- return (ldb_msg_add_value(msg, name, &v, NULL) == 0);
-}
-
-static int samldb_new_sid(struct samldb_ctx *ac)
-{
-
- if (ac->domain_sid == NULL || ac->next_rid == 0) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac->sid = dom_sid_add_rid(ac, ac->domain_sid, ac->next_rid + 1);
- if (ac->sid == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- if ( ! samldb_msg_add_sid(ac->msg, "objectSid", ac->sid)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- return samldb_next_step(ac);
-}
-
-/*
- * samldb_notice_sid_callback (async)
- */
-
-static int samldb_notice_sid_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
- if (ares->type != LDB_REPLY_DONE) {
- ldb_set_errstring(ldb,
- "Invalid reply type!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
-
- ret = samldb_next_step(ac);
-
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
- }
-
- return LDB_SUCCESS;
-}
-
-/* If we are adding new users/groups, we need to update the nextRid
- * attribute to be 'above' the new/incoming RID. Attempt to do it
- * atomically. */
-static int samldb_notice_sid(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- uint32_t old_id, new_id;
- struct ldb_request *req;
- struct ldb_message *msg;
- struct ldb_message_element *els;
- struct ldb_val *vals;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
- old_id = ac->next_rid;
- new_id = ac->sid->sub_auths[ac->sid->num_auths - 1];
-
- if (old_id >= new_id) {
- /* no need to update the domain nextRid attribute */
- return samldb_next_step(ac);
- }
-
- /* we do a delete and add as a single operation. That prevents
- a race, in case we are not actually on a transaction db */
- msg = ldb_msg_new(ac);
- if (msg == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- els = talloc_array(msg, struct ldb_message_element, 2);
- if (els == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- vals = talloc_array(msg, struct ldb_val, 2);
- if (vals == NULL) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- msg->dn = ac->domain_dn;
- msg->num_elements = 2;
- msg->elements = els;
-
- els[0].num_values = 1;
- els[0].values = &vals[0];
- els[0].flags = LDB_FLAG_MOD_DELETE;
- els[0].name = talloc_strdup(msg, "nextRid");
- if (!els[0].name) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- els[1].num_values = 1;
- els[1].values = &vals[1];
- els[1].flags = LDB_FLAG_MOD_ADD;
- els[1].name = els[0].name;
-
- vals[0].data = (uint8_t *)talloc_asprintf(vals, "%u", old_id);
- if (!vals[0].data) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- vals[0].length = strlen((char *)vals[0].data);
-
- vals[1].data = (uint8_t *)talloc_asprintf(vals, "%u", new_id);
- if (!vals[1].data) {
- ldb_oom(ldb);
- return LDB_ERR_OPERATIONS_ERROR;
- }
- vals[1].length = strlen((char *)vals[1].data);
-
- ret = ldb_build_mod_req(&req, ldb, ac,
- msg, NULL,
- ac, samldb_notice_sid_callback,
- ac->req);
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- return ldb_next_request(ac->module, req);
-}
-
/*
* samldb_set_defaultObjectCategory_callback (async)
*/
@@ -1142,11 +759,6 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
ldb = ldb_module_get_ctx(ac->module);
- /* search for a parent domain objet */
- ac->check_dn = ac->req->op.add.message->dn;
- ret = samldb_add_step(ac, samldb_get_parent_domain);
- if (ret != LDB_SUCCESS) return ret;
-
/* Add informations for the different account types */
ac->type = type;
if (strcmp(ac->type, "user") == 0) {
@@ -1174,9 +786,11 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
ret = samdb_find_or_add_attribute(ldb, ac->msg,
"pwdLastSet", "0");
if (ret != LDB_SUCCESS) return ret;
- ret = samdb_find_or_add_attribute(ldb, ac->msg,
- "primaryGroupID", "513");
- if (ret != LDB_SUCCESS) return ret;
+ if (!ldb_msg_find_element(ac->msg, "primaryGroupID")) {
+ ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
+ "primaryGroupID", DOMAIN_RID_USERS);
+ if (ret != LDB_SUCCESS) return ret;
+ }
ret = samdb_find_or_add_attribute(ldb, ac->msg,
"accountExpires", "9223372036854775807");
if (ret != LDB_SUCCESS) return ret;
@@ -1287,20 +901,21 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
lp_ctx = talloc_get_type(ldb_get_opaque(ldb, "loadparm"),
struct loadparm_context);
- sid_generator = lp_sid_generator(lp_ctx);
- if (sid_generator == SID_GENERATOR_INTERNAL) {
- /* check if we have a valid SID */
- ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
- if ( ! ac->sid) {
- ret = samldb_add_step(ac, samldb_new_sid);
- if (ret != LDB_SUCCESS) return ret;
- } else {
- ret = samldb_add_step(ac, samldb_get_sid_domain);
+ /* don't allow objectSID to be specified without the RELAX control */
+ ac->sid = samdb_result_dom_sid(ac, ac->msg, "objectSid");
+ if (ac->sid && !ldb_request_get_control(ac->req, LDB_CONTROL_RELAX_OID) &&
+ !dsdb_module_am_system(ac->module)) {
+ ldb_asprintf_errstring(ldb, "No SID may be specified in user/group creation for %s",
+ ldb_dn_get_linearized(ac->msg->dn));
+ return LDB_ERR_UNWILLING_TO_PERFORM;
+ }
+
+ if ( ! ac->sid) {
+ sid_generator = lp_sid_generator(lp_ctx);
+ if (sid_generator == SID_GENERATOR_INTERNAL) {
+ ret = samldb_add_step(ac, samldb_allocate_sid);
if (ret != LDB_SUCCESS) return ret;
}
-
- ret = samldb_add_step(ac, samldb_notice_sid);
- if (ret != LDB_SUCCESS) return ret;
}
/* finally proceed with adding the entry */
@@ -1310,144 +925,6 @@ static int samldb_fill_object(struct samldb_ctx *ac, const char *type)
return samldb_first_step(ac);
}
-/*
- * samldb_foreign_notice_sid (async)
- */
-
-static int samldb_foreign_notice_sid_callback(struct ldb_request *req,
- struct ldb_reply *ares)
-{
- struct ldb_context *ldb;
- struct samldb_ctx *ac;
- const char *nextRid;
- const char *name;
- int ret;
-
- ac = talloc_get_type(req->context, struct samldb_ctx);
- ldb = ldb_module_get_ctx(ac->module);
-
- if (!ares) {
- ret = LDB_ERR_OPERATIONS_ERROR;
- goto done;
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
-
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- /* save entry */
- if (ac->next_rid != 0) {
- /* one too many! */
- ldb_set_errstring(ldb,
- "Invalid number of results while searching "
- "for domain object!");
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- nextRid = ldb_msg_find_attr_as_string(ares->message,
- "nextRid", NULL);
- if (nextRid == NULL) {
- ldb_asprintf_errstring(ldb,
- "While looking for foreign SID %s attribute nextRid not found in %s",
- dom_sid_string(ares, ac->sid),
- ldb_dn_get_linearized(ares->message->dn));
- ret = LDB_ERR_OPERATIONS_ERROR;
- break;
- }
-
- ac->next_rid = strtol(nextRid, NULL, 0);
-
- ac->domain_dn = ldb_dn_copy(ac, ares->message->dn);
-
- name = samdb_result_string(ares->message, "name", NULL);
- ldb_debug(ldb, LDB_DEBUG_TRACE,
- "NOTE (strange but valid): Adding foreign SID "
- "record with SID %s, but this domain (%s) is "
- "not foreign in the database\n",
- dom_sid_string(ares, ac->sid), name);
-
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_REFERRAL:
- /* ignore */
- talloc_free(ares);
- ret = LDB_SUCCESS;
- break;
-
- case LDB_REPLY_DONE:
- talloc_free(ares);
-
- /* if this is a fake foreign SID, notice the SID */
- if (ac->domain_dn) {
- ret = samldb_notice_sid(ac);
- break;
- }
-
- /* found, go on */
- ret = samldb_next_step(ac);
- break;
- }
-
-done:
- if (ret != LDB_SUCCESS) {
- return ldb_module_done(ac->req, NULL, NULL, ret);
- }
-
- return LDB_SUCCESS;
-}
-
-/* Find a domain object in the parents of a particular DN. */
-static int samldb_foreign_notice_sid(struct samldb_ctx *ac)
-{
- struct ldb_context *ldb;
- static const char * const attrs[3] = { "nextRid", "name", NULL };
- struct ldb_request *req;
- NTSTATUS status;
- char *filter;
- int ret;
-
- ldb = ldb_module_get_ctx(ac->module);
-
- if (ac->sid == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- status = dom_sid_split_rid(ac, ac->sid, &ac->domain_sid, NULL);
- if (!NT_STATUS_IS_OK(status)) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
-
- filter = talloc_asprintf(ac,
- "(&(objectSid=%s)"
- "(|(objectClass=domain)"
- "(objectClass=builtinDomain)))",
- ldap_encode_ndr_dom_sid(ac, ac->domain_sid));
- if (filter == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ret = ldb_build_search_req(&req, ldb, ac,
- ldb_get_default_basedn(ldb),
- LDB_SCOPE_SUBTREE,
- filter, attrs,
- NULL,
- ac, samldb_foreign_notice_sid_callback,
- ac->req);
-
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- return ldb_next_request(ac->module, req);
-}
-
-
static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
{
struct ldb_context *ldb;
@@ -1455,8 +932,6 @@ static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
ldb = ldb_module_get_ctx(ac->module);
- ac->next_rid = 0;
-
ac->sid = samdb_result_dom_sid(ac->msg, ac->msg, "objectSid");
if (ac->sid == NULL) {
ac->sid = dom_sid_parse_talloc(ac->msg,
@@ -1474,10 +949,6 @@ static int samldb_fill_foreignSecurityPrincipal_object(struct samldb_ctx *ac)
}
}
- /* check if we need to notice this SID */
- ret = samldb_add_step(ac, samldb_foreign_notice_sid);
- if (ret != LDB_SUCCESS) return ret;
-
/* finally proceed with adding the entry */
ret = samldb_add_step(ac, samldb_add_entry);
if (ret != LDB_SUCCESS) return ret;
@@ -2313,6 +1784,20 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
el2->flags = LDB_FLAG_MOD_REPLACE;
}
+ el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
+ if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
+ struct samldb_ctx *ac;
+
+ ac = samldb_ctx_init(module, req);
+ if (ac == NULL)
+ return LDB_ERR_OPERATIONS_ERROR;
+
+ req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
+ req->op.mod.message);
+
+ return samldb_prim_group_change(ac);
+ }
+
el = ldb_msg_find_element(req->op.mod.message, "userAccountControl");
if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
uint32_t user_account_control;
@@ -2340,21 +1825,18 @@ static int samldb_modify(struct ldb_module *module, struct ldb_request *req)
}
el2 = ldb_msg_find_element(msg, "isCriticalSystemObject");
el2->flags = LDB_FLAG_MOD_REPLACE;
- }
- }
-
- el = ldb_msg_find_element(req->op.mod.message, "primaryGroupID");
- if (el && el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE) && el->num_values == 1) {
- struct samldb_ctx *ac;
- ac = samldb_ctx_init(module, req);
- if (ac == NULL)
- return LDB_ERR_OPERATIONS_ERROR;
-
- req->op.mod.message = ac->msg = ldb_msg_copy_shallow(req,
- req->op.mod.message);
-
- return samldb_prim_group_change(ac);
+ /* DCs have primaryGroupID of DOMAIN_RID_DCS */
+ if (!ldb_msg_find_element(msg, "primaryGroupID")) {
+ ret = samdb_msg_add_uint(ldb, msg, msg,
+ "primaryGroupID", DOMAIN_RID_DCS);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ el2 = ldb_msg_find_element(msg, "primaryGroupID");
+ el2->flags = LDB_FLAG_MOD_REPLACE;
+ }
+ }
}
el = ldb_msg_find_element(req->op.mod.message, "member");
@@ -2392,17 +1874,41 @@ static int samldb_delete(struct ldb_module *module, struct ldb_request *req)
return samldb_prim_group_users_check(ac);
}
+static int samldb_extended_allocate_rid_pool(struct ldb_module *module, struct ldb_request *req)
+{
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct dsdb_fsmo_extended_op *exop;
+ int ret;
+
+ exop = talloc_get_type(req->op.extended.data, struct dsdb_fsmo_extended_op);
+ if (!exop) {
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "samldb_extended_allocate_rid_pool: invalid extended data\n");
+ return LDB_ERR_PROTOCOL_ERROR;
+ }
+
+ ret = ridalloc_allocate_rid_pool_fsmo(module, exop);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
+}
-static int samldb_init(struct ldb_module *module)
+static int samldb_extended(struct ldb_module *module, struct ldb_request *req)
{
- return ldb_next_init(module);
+ if (strcmp(req->op.extended.oid, DSDB_EXTENDED_ALLOCATE_RID_POOL) == 0) {
+ return samldb_extended_allocate_rid_pool(module, req);
+ }
+
+ return ldb_next_request(module, req);
}
+
_PUBLIC_ const struct ldb_module_ops ldb_samldb_module_ops = {
.name = "samldb",
- .init_context = samldb_init,
.add = samldb_add,
.modify = samldb_modify,
- .del = samldb_delete
+ .del = samldb_delete,
+ .extended = samldb_extended
};
diff --git a/source4/dsdb/samdb/ldb_modules/schema_data.c b/source4/dsdb/samdb/ldb_modules/schema_data.c
index 2e99113953..8125a46cbb 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_data.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_data.c
@@ -290,6 +290,11 @@ static int schema_data_add(struct ldb_module *module, struct ldb_request *req)
}
}
+ /* bypass further processing if CONTROL_RELAX is set */
+ if (ldb_request_get_control(req, LDB_CONTROL_RELAX_OID)) {
+ return ldb_next_request(module, req);
+ }
+
/* generate and add msDS-IntId attr value */
if (attributeID
&& (dsdb_functional_level(ldb) >= DS_DOMAIN_FUNCTION_2003)
diff --git a/source4/dsdb/samdb/ldb_modules/schema_load.c b/source4/dsdb/samdb/ldb_modules/schema_load.c
index c72911fe89..6c11df21ce 100644
--- a/source4/dsdb/samdb/ldb_modules/schema_load.c
+++ b/source4/dsdb/samdb/ldb_modules/schema_load.c
@@ -181,8 +181,8 @@ static int schema_load_init(struct ldb_module *module)
ret = dsdb_set_schema(ldb, schema);
if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "schema_load_init: dsdb_set_schema() failed: %d:%s",
- ret, ldb_strerror(ret));
+ "schema_load_init: dsdb_set_schema() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
talloc_free(mem_ctx);
return ret;
}
@@ -240,8 +240,8 @@ static int schema_load_extended(struct ldb_module *module, struct ldb_request *r
ret = dsdb_set_schema(ldb, schema);
if (ret != LDB_SUCCESS) {
ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "schema_load_extended: dsdb_set_schema() failed: %d:%s",
- ret, ldb_strerror(ret));
+ "schema_load_extended: dsdb_set_schema() failed: %d:%s: %s",
+ ret, ldb_strerror(ret), ldb_errstring(ldb));
talloc_free(mem_ctx);
return ret;
}
diff --git a/source4/dsdb/samdb/ldb_modules/show_deleted.c b/source4/dsdb/samdb/ldb_modules/show_deleted.c
index 666d28053c..93463ae95f 100644
--- a/source4/dsdb/samdb/ldb_modules/show_deleted.c
+++ b/source4/dsdb/samdb/ldb_modules/show_deleted.c
@@ -32,7 +32,7 @@
#include "includes.h"
#include "ldb/include/ldb_module.h"
#include "dsdb/samdb/samdb.h"
-
+#include "dsdb/samdb/ldb_modules/util.h"
static int show_deleted_search(struct ldb_module *module, struct ldb_request *req)
{
@@ -83,7 +83,7 @@ static int show_deleted_search(struct ldb_module *module, struct ldb_request *re
new_tree,
req->op.search.attrs,
req->controls,
- req->context, req->callback,
+ req, dsdb_next_callback,
req);
if (ret != LDB_SUCCESS) {
return ret;
diff --git a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
index 2478043eb4..cc1a86ed4a 100644
--- a/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
+++ b/source4/dsdb/samdb/ldb_modules/tests/samba3sam.py
@@ -29,6 +29,8 @@ from samba import Ldb, substitute_var
from samba.tests import LdbTestCase, TestCaseInTempDir, cmdline_loadparm
import samba.dcerpc.security
import samba.ndr
+from samba.auth import system_session
+from samba import param
datadir = os.path.join(os.path.dirname(__file__),
"../../../../../testdata/samba3")
@@ -49,7 +51,7 @@ class MapBaseTestCase(TestCaseInTempDir):
"@TO": "sambaDomainName=TESTS," + s3.basedn})
ldb.add({"dn": "@MODULES",
- "@LIST": "rootdse,paged_results,server_sort,asq,samldb,password_hash,operational,objectguid,rdn_name,samba3sam,partition"})
+ "@LIST": "rootdse,paged_results,server_sort,asq,samldb,password_hash,operational,objectguid,rdn_name,samba3sam,samba3sid,partition"})
ldb.add({"dn": "@PARTITION",
"partition": ["%s" % (s4.basedn_casefold),
@@ -58,6 +60,9 @@ class MapBaseTestCase(TestCaseInTempDir):
"modules": "*:"})
def setUp(self):
+ cmdline_loadparm.set("sid generator", "backend")
+ cmdline_loadparm.set("workgroup", "TESTS")
+ cmdline_loadparm.set("netbios name", "TESTS")
super(MapBaseTestCase, self).setUp()
def make_dn(basedn, rdn):
@@ -75,7 +80,7 @@ class MapBaseTestCase(TestCaseInTempDir):
"""Simple helper class that contains data for a specific SAM
connection."""
def __init__(self, basedn, dn):
- self.db = Ldb(lp=cmdline_loadparm)
+ self.db = Ldb(lp=cmdline_loadparm, session_info=system_session())
self.basedn = basedn
self.basedn_casefold = ldb.Dn(self.db, basedn).get_casefold()
self.substvars = {"BASEDN": self.basedn}
@@ -124,13 +129,13 @@ class Samba3SamTestCase(MapBaseTestCase):
def setUp(self):
super(Samba3SamTestCase, self).setUp()
- ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
+ ldb = Ldb(self.ldburl, lp=cmdline_loadparm, session_info=system_session())
self.samba3.setup_data("samba3.ldif")
ldif = read_datafile("provision_samba3sam.ldif")
ldb.add_ldif(self.samba4.subst(ldif))
self.setup_modules(ldb, self.samba3, self.samba4)
del ldb
- self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
+ self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm, session_info=system_session())
def test_search_non_mapped(self):
"""Looking up by non-mapped attribute"""
@@ -291,12 +296,12 @@ class MapTestCase(MapBaseTestCase):
def setUp(self):
super(MapTestCase, self).setUp()
- ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
+ ldb = Ldb(self.ldburl, lp=cmdline_loadparm, session_info=system_session())
ldif = read_datafile("provision_samba3sam.ldif")
ldb.add_ldif(self.samba4.subst(ldif))
self.setup_modules(ldb, self.samba3, self.samba4)
del ldb
- self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm)
+ self.ldb = Ldb(self.ldburl, lp=cmdline_loadparm, session_info=system_session())
def test_map_search(self):
"""Running search tests on mapped data."""
diff --git a/source4/dsdb/samdb/ldb_modules/util.c b/source4/dsdb/samdb/ldb_modules/util.c
index 32b79a6701..46252cb279 100644
--- a/source4/dsdb/samdb/ldb_modules/util.c
+++ b/source4/dsdb/samdb/ldb_modules/util.c
@@ -26,6 +26,7 @@
#include "dsdb/samdb/ldb_modules/util.h"
#include "dsdb/samdb/samdb.h"
#include "util.h"
+#include "libcli/security/security.h"
/*
add a set of controls to a ldb_request structure based on a set of
@@ -214,6 +215,8 @@ int dsdb_module_search(struct ldb_module *module,
if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
const struct ldb_module_ops *ops = ldb_module_get_ops(module);
ret = ops->search(module, req);
+ } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
+ ret = ldb_request(ldb_module_get_ctx(module), req);
} else {
ret = ldb_next_request(module, req);
}
@@ -332,6 +335,8 @@ int dsdb_module_modify(struct ldb_module *module,
if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
const struct ldb_module_ops *ops = ldb_module_get_ops(module);
ret = ops->modify(module, mod_req);
+ } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
+ ret = ldb_request(ldb_module_get_ctx(module), mod_req);
} else {
ret = ldb_next_request(module, mod_req);
}
@@ -380,6 +385,8 @@ int dsdb_module_rename(struct ldb_module *module,
if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
const struct ldb_module_ops *ops = ldb_module_get_ops(module);
ret = ops->rename(module, req);
+ } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
+ ret = ldb_request(ldb_module_get_ctx(module), req);
} else {
ret = ldb_next_request(module, req);
}
@@ -391,6 +398,54 @@ int dsdb_module_rename(struct ldb_module *module,
return ret;
}
+/*
+ a ldb_add request operating on modules below the
+ current module
+ */
+int dsdb_module_add(struct ldb_module *module,
+ const struct ldb_message *message,
+ uint32_t dsdb_flags)
+{
+ struct ldb_request *req;
+ int ret;
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ TALLOC_CTX *tmp_ctx = talloc_new(module);
+
+ ret = ldb_build_add_req(&req, ldb, tmp_ctx,
+ message,
+ NULL,
+ NULL,
+ ldb_op_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ ret = dsdb_request_add_controls(module, req, dsdb_flags);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(tmp_ctx);
+ return ret;
+ }
+
+ /* Run the new request */
+ if (dsdb_flags & DSDB_FLAG_OWN_MODULE) {
+ const struct ldb_module_ops *ops = ldb_module_get_ops(module);
+ ret = ops->add(module, req);
+ } else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
+ ret = ldb_request(ldb_module_get_ctx(module), req);
+ } else {
+ ret = ldb_next_request(module, req);
+ }
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+
const struct dsdb_class * get_last_structural_class(const struct dsdb_schema *schema,const struct ldb_message_element *element)
{
const struct dsdb_class *last_class = NULL;
@@ -446,3 +501,140 @@ int dsdb_check_single_valued_link(const struct dsdb_attribute *attr,
return LDB_SUCCESS;
}
+
+
+/*
+ find a 'reference' DN that points at another object
+ (eg. serverReference, rIDManagerReference etc)
+ */
+int dsdb_module_reference_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn *base,
+ const char *attribute, struct ldb_dn **dn)
+{
+ const char *attrs[2];
+ struct ldb_result *res;
+ int ret;
+
+ attrs[0] = attribute;
+ attrs[1] = NULL;
+
+ ret = dsdb_module_search_dn(module, mem_ctx, &res, base, attrs, 0);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ *dn = ldb_msg_find_attr_as_dn(ldb_module_get_ctx(module),
+ mem_ctx, res->msgs[0], attribute);
+ if (!*dn) {
+ talloc_free(res);
+ return LDB_ERR_NO_SUCH_ATTRIBUTE;
+ }
+
+ talloc_free(res);
+ return LDB_SUCCESS;
+}
+
+/*
+ find the RID Manager$ DN via the rIDManagerReference attribute in the
+ base DN
+ */
+int dsdb_module_rid_manager_dn(struct ldb_module *module, TALLOC_CTX *mem_ctx, struct ldb_dn **dn)
+{
+ return dsdb_module_reference_dn(module, mem_ctx,
+ samdb_base_dn(ldb_module_get_ctx(module)),
+ "rIDManagerReference", dn);
+}
+
+
+/*
+ update an integer attribute safely via a constrained delete/add
+ */
+int dsdb_module_constrainted_update_integer(struct ldb_module *module, struct ldb_dn *dn,
+ const char *attr, uint64_t old_val, uint64_t new_val)
+{
+ struct ldb_message *msg;
+ struct ldb_message_element *el;
+ struct ldb_val v1, v2;
+ int ret;
+ char *vstring;
+
+ msg = ldb_msg_new(module);
+ msg->dn = dn;
+
+ ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_DELETE, &el);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(msg);
+ return ret;
+ }
+ el->num_values = 1;
+ el->values = &v1;
+ vstring = talloc_asprintf(msg, "%llu", (unsigned long long)old_val);
+ if (!vstring) {
+ ldb_module_oom(module);
+ talloc_free(msg);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ v1 = data_blob_string_const(vstring);
+
+ ret = ldb_msg_add_empty(msg, attr, LDB_FLAG_MOD_ADD, &el);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(msg);
+ return ret;
+ }
+ el->num_values = 1;
+ el->values = &v2;
+ vstring = talloc_asprintf(msg, "%llu", (unsigned long long)new_val);
+ if (!vstring) {
+ ldb_module_oom(module);
+ talloc_free(msg);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ v2 = data_blob_string_const(vstring);
+
+ ret = dsdb_module_modify(module, msg, 0);
+ talloc_free(msg);
+ return ret;
+}
+
+/*
+ used to chain to the callers callback
+ */
+int dsdb_next_callback(struct ldb_request *req, struct ldb_reply *ares)
+{
+ struct ldb_request *up_req = talloc_get_type(req->context, struct ldb_request);
+
+ talloc_steal(up_req, req);
+ return up_req->callback(up_req, ares);
+}
+
+
+/*
+ set an integer attribute
+ */
+int dsdb_module_set_integer(struct ldb_module *module, struct ldb_dn *dn,
+ const char *attr, uint64_t new_val)
+{
+ struct ldb_message *msg;
+ int ret;
+
+ msg = ldb_msg_new(module);
+ msg->dn = dn;
+
+ ret = ldb_msg_add_fmt(msg, attr, "%llu", (unsigned long long)new_val);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(msg);
+ return ret;
+ }
+ msg->elements[0].flags = LDB_FLAG_MOD_REPLACE;
+
+ ret = dsdb_module_modify(module, msg, 0);
+ talloc_free(msg);
+ return ret;
+}
+
+bool dsdb_module_am_system(struct ldb_module *module)
+{
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ struct auth_session_info *session_info
+ = (struct auth_session_info *)ldb_get_opaque(ldb, "sessionInfo");
+ return security_session_user_level(session_info) == SECURITY_SYSTEM;
+}
diff --git a/source4/dsdb/samdb/ldb_modules/util.h b/source4/dsdb/samdb/ldb_modules/util.h
index add39e110a..53ed9bd48e 100644
--- a/source4/dsdb/samdb/ldb_modules/util.h
+++ b/source4/dsdb/samdb/ldb_modules/util.h
@@ -19,9 +19,11 @@
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
-struct dsdb_schema; /* predeclare schema struct */
+/* predeclare some structures used by utility functions */
+struct dsdb_schema;
struct GUID;
struct dsdb_attribute;
+struct dsdb_fsmo_extended_op;
#include "dsdb/samdb/ldb_modules/util_proto.h"
@@ -32,3 +34,4 @@ struct dsdb_attribute;
#define DSDB_SEARCH_SHOW_EXTENDED_DN 0x0010
#define DSDB_MODIFY_RELAX 0x0020
#define DSDB_FLAG_OWN_MODULE 0x0040
+#define DSDB_FLAG_TOP_MODULE 0x0080
diff --git a/source4/dsdb/samdb/samdb.h b/source4/dsdb/samdb/samdb.h
index a05aa00f7a..6df30b2904 100644
--- a/source4/dsdb/samdb/samdb.h
+++ b/source4/dsdb/samdb/samdb.h
@@ -142,4 +142,12 @@ struct dsdb_extended_dn_store_format {
#define DSDB_OPAQUE_PARTITION_MODULE_MSG_OPAQUE_NAME "DSDB_OPAQUE_PARTITION_MODULE_MSG"
+/* this takes a struct dsdb_fsmo_extended_op */
+#define DSDB_EXTENDED_ALLOCATE_RID_POOL "1.3.6.1.4.1.7165.4.4.5"
+
+struct dsdb_fsmo_extended_op {
+ uint64_t fsmo_info;
+ struct GUID destination_dsa_guid;
+};
+
#endif /* __SAMDB_H__ */
diff --git a/source4/dsdb/schema/schema.h b/source4/dsdb/schema/schema.h
index 186f5d5ddb..1a40c45b21 100644
--- a/source4/dsdb/schema/schema.h
+++ b/source4/dsdb/schema/schema.h
@@ -62,6 +62,7 @@ struct dsdb_attribute {
uint32_t attributeID_id;
struct GUID schemaIDGUID;
uint32_t mAPIID;
+ uint32_t msDS_IntId;
struct GUID attributeSecurityGUID;
struct GUID objectGUID;
diff --git a/source4/dsdb/schema/schema_init.c b/source4/dsdb/schema/schema_init.c
index ccdf97cf2d..77b4e2a473 100644
--- a/source4/dsdb/schema/schema_init.c
+++ b/source4/dsdb/schema/schema_init.c
@@ -558,21 +558,19 @@ WERROR dsdb_attribute_from_ldb(struct ldb_context *ldb,
/* set an invalid value */
attr->attributeID_id = 0xFFFFFFFF;
} else {
- /* check if msDS-IntId element is set */
- attr->attributeID_id = samdb_result_uint(msg, "msDS-IntId", 0xFFFFFFFF);
- if (attr->attributeID_id == 0xFFFFFFFF) {
- /* msDS-IntId is not set, make */
- status = dsdb_schema_pfm_make_attid(schema->prefixmap,
- attr->attributeID_oid,
- &attr->attributeID_id);
- if (!W_ERROR_IS_OK(status)) {
- DEBUG(0,("%s: '%s': unable to map attributeID %s: %s\n",
- __location__, attr->lDAPDisplayName, attr->attributeID_oid,
- win_errstr(status)));
- return status;
- }
+ status = dsdb_schema_pfm_make_attid(schema->prefixmap,
+ attr->attributeID_oid,
+ &attr->attributeID_id);
+ if (!W_ERROR_IS_OK(status)) {
+ DEBUG(0,("%s: '%s': unable to map attributeID %s: %s\n",
+ __location__, attr->lDAPDisplayName, attr->attributeID_oid,
+ win_errstr(status)));
+ return status;
}
}
+ /* fetch msDS-IntId to be used in resolving ATTRTYP values */
+ GET_UINT32_LDB(msg, "msDS-IntId", attr, msDS_IntId);
+
GET_GUID_LDB(msg, "schemaIDGUID", attr, schemaIDGUID);
GET_UINT32_LDB(msg, "mAPIID", attr, mAPIID);
@@ -621,10 +619,14 @@ WERROR dsdb_attribute_from_ldb(struct ldb_context *ldb,
attr->syntax = dsdb_syntax_for_attribute(attr);
if (!attr->syntax) {
+ DEBUG(0,(__location__ ": Unknown schema syntax for %s\n",
+ attr->lDAPDisplayName));
return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
}
if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Unknown schema syntax for %s\n",
+ attr->lDAPDisplayName));
return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
}
@@ -833,6 +835,7 @@ static const struct {
{ "mayContain", "1.2.840.113556.1.2.25" },
{ "defaultSecurityDescriptor", "1.2.840.113556.1.4.224" },
{ "defaultHidingValue", "1.2.840.113556.1.4.518" },
+ { "msDS-IntId", "1.2.840.113556.1.4.1716" },
};
static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb_schema *schema,
@@ -945,7 +948,7 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb
} \
} while (0)
-#define GET_UINT32_DS(s, r, attr, p, elem) do { \
+#define GET_UINT32_DS(s, r, attr, p, elem, def_val) do { \
struct drsuapi_DsReplicaAttribute *_a; \
_a = dsdb_find_object_attr_name(s, r, attr, NULL); \
if (_a && _a->value_ctr.num_values >= 1 \
@@ -953,7 +956,7 @@ static struct drsuapi_DsReplicaAttribute *dsdb_find_object_attr_name(struct dsdb
&& _a->value_ctr.values[0].blob->length == 4) { \
(p)->elem = IVAL(_a->value_ctr.values[0].blob->data,0);\
} else { \
- (p)->elem = 0; \
+ (p)->elem = def_val; \
} \
} while (0)
@@ -1011,7 +1014,7 @@ WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb,
GET_STRING_DS(schema, r, "name", mem_ctx, attr, cn, true);
GET_STRING_DS(schema, r, "lDAPDisplayName", mem_ctx, attr, lDAPDisplayName, true);
- GET_UINT32_DS(schema, r, "attributeID", attr, attributeID_id);
+ GET_UINT32_DS(schema, r, "attributeID", attr, attributeID_id, 0xFFFFFFFF);
status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attr->attributeID_id,
mem_ctx, &attr->attributeID_oid);
if (!W_ERROR_IS_OK(status)) {
@@ -1020,19 +1023,22 @@ WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb,
win_errstr(status)));
return status;
}
+ /* fetch msDS-IntId to be used in resolving ATTRTYP values */
+ GET_UINT32_DS(schema, r, "msDS-IntId", attr, msDS_IntId, 0);
+
GET_GUID_DS(schema, r, "schemaIDGUID", mem_ctx, attr, schemaIDGUID);
- GET_UINT32_DS(schema, r, "mAPIID", attr, mAPIID);
+ GET_UINT32_DS(schema, r, "mAPIID", attr, mAPIID, 0);
GET_GUID_DS(schema, r, "attributeSecurityGUID", mem_ctx, attr, attributeSecurityGUID);
attr->objectGUID = r->identifier->guid;
- GET_UINT32_DS(schema, r, "searchFlags", attr, searchFlags);
- GET_UINT32_DS(schema, r, "systemFlags", attr, systemFlags);
+ GET_UINT32_DS(schema, r, "searchFlags", attr, searchFlags, 0);
+ GET_UINT32_DS(schema, r, "systemFlags", attr, systemFlags, 0);
GET_BOOL_DS(schema, r, "isMemberOfPartialAttributeSet", attr, isMemberOfPartialAttributeSet, false);
- GET_UINT32_DS(schema, r, "linkID", attr, linkID);
+ GET_UINT32_DS(schema, r, "linkID", attr, linkID, 0);
- GET_UINT32_DS(schema, r, "attributeSyntax", attr, attributeSyntax_id);
+ GET_UINT32_DS(schema, r, "attributeSyntax", attr, attributeSyntax_id, 0xFFFFFFFF);
status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, attr->attributeSyntax_id,
mem_ctx, &attr->attributeSyntax_oid);
if (!W_ERROR_IS_OK(status)) {
@@ -1041,7 +1047,7 @@ WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb,
win_errstr(status)));
return status;
}
- GET_UINT32_DS(schema, r, "oMSyntax", attr, oMSyntax);
+ GET_UINT32_DS(schema, r, "oMSyntax", attr, oMSyntax, 0);
GET_BLOB_DS(schema, r, "oMObjectClass", mem_ctx, attr, oMObjectClass);
GET_BOOL_DS(schema, r, "isSingleValued", attr, isSingleValued, true);
@@ -1049,7 +1055,7 @@ WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb,
GET_UINT32_PTR_DS(schema, r, "rangeUpper", attr, rangeUpper);
GET_BOOL_DS(schema, r, "extendedCharsAllowed", attr, extendedCharsAllowed, false);
- GET_UINT32_DS(schema, r, "schemaFlagsEx", attr, schemaFlagsEx);
+ GET_UINT32_DS(schema, r, "schemaFlagsEx", attr, schemaFlagsEx, 0);
GET_BLOB_DS(schema, r, "msDs-Schema-Extensions", mem_ctx, attr, msDs_Schema_Extensions);
GET_BOOL_DS(schema, r, "showInAdvancedViewOnly", attr, showInAdvancedViewOnly, false);
@@ -1062,10 +1068,14 @@ WERROR dsdb_attribute_from_drsuapi(struct ldb_context *ldb,
attr->syntax = dsdb_syntax_for_attribute(attr);
if (!attr->syntax) {
+ DEBUG(0,(__location__ ": Unknown schema syntax for %s\n",
+ attr->lDAPDisplayName));
return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
}
if (dsdb_schema_setup_ldb_schema_attribute(ldb, attr) != LDB_SUCCESS) {
+ DEBUG(0,(__location__ ": Unknown schema syntax for %s\n",
+ attr->lDAPDisplayName));
return WERR_DS_ATT_SCHEMA_REQ_SYNTAX;
}
@@ -1084,7 +1094,7 @@ WERROR dsdb_class_from_drsuapi(struct ldb_context *ldb,
GET_STRING_DS(schema, r, "name", mem_ctx, obj, cn, true);
GET_STRING_DS(schema, r, "lDAPDisplayName", mem_ctx, obj, lDAPDisplayName, true);
- GET_UINT32_DS(schema, r, "governsID", obj, governsID_id);
+ GET_UINT32_DS(schema, r, "governsID", obj, governsID_id, 0xFFFFFFFF);
status = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, obj->governsID_id,
mem_ctx, &obj->governsID_oid);
if (!W_ERROR_IS_OK(status)) {
@@ -1097,7 +1107,7 @@ WERROR dsdb_class_from_drsuapi(struct ldb_context *ldb,
obj->objectGUID = r->identifier->guid;
- GET_UINT32_DS(schema, r, "objectClassCategory", obj, objectClassCategory);
+ GET_UINT32_DS(schema, r, "objectClassCategory", obj, objectClassCategory, 0);
GET_STRING_DS(schema, r, "rDNAttID", mem_ctx, obj, rDNAttID, false);
attr = dsdb_find_object_attr_name(schema, r, "defaultObjectCategory", NULL);
@@ -1114,7 +1124,7 @@ WERROR dsdb_class_from_drsuapi(struct ldb_context *ldb,
}
obj->defaultObjectCategory = (char *)blob.data;
- GET_UINT32_DS(schema, r, "subClassOf", obj, subClassOf_id);
+ GET_UINT32_DS(schema, r, "subClassOf", obj, subClassOf_id, 0);
GET_UINT32_LIST_DS(schema, r, "systemAuxiliaryClass", mem_ctx, obj, systemAuxiliaryClass_ids);
GET_UINT32_LIST_DS(schema, r, "auxiliaryClass", mem_ctx, obj, auxiliaryClass_ids);
@@ -1129,7 +1139,7 @@ WERROR dsdb_class_from_drsuapi(struct ldb_context *ldb,
GET_STRING_DS(schema, r, "defaultSecurityDescriptor", mem_ctx, obj, defaultSecurityDescriptor, false);
- GET_UINT32_DS(schema, r, "schemaFlagsEx", obj, schemaFlagsEx);
+ GET_UINT32_DS(schema, r, "schemaFlagsEx", obj, schemaFlagsEx, 0);
GET_BLOB_DS(schema, r, "msDs-Schema-Extensions", mem_ctx, obj, msDs_Schema_Extensions);
GET_BOOL_DS(schema, r, "showInAdvancedViewOnly", obj, showInAdvancedViewOnly, false);
diff --git a/source4/dsdb/schema/schema_query.c b/source4/dsdb/schema/schema_query.c
index df17787f38..4e11e50c17 100644
--- a/source4/dsdb/schema/schema_query.c
+++ b/source4/dsdb/schema/schema_query.c
@@ -39,7 +39,14 @@ static int strcasecmp_with_ldb_val(const struct ldb_val *target, const char *str
{
int ret = strncasecmp((const char *)target->data, str, target->length);
if (ret == 0) {
- return (target->length - strlen(str));
+ size_t len = strlen(str);
+ if (target->length > len) {
+ if (target->data[len] == 0) {
+ return 0;
+ }
+ return 1;
+ }
+ return (target->length - len);
}
return ret;
}
@@ -55,6 +62,15 @@ const struct dsdb_attribute *dsdb_attribute_by_attributeID_id(const struct dsdb_
*/
if (id == 0xFFFFFFFF) return NULL;
+ /* check for msDS-IntId type attribute */
+ if (dsdb_pfm_get_attid_type(id) == dsdb_attid_type_intid) {
+ for (c = schema->attributes; c; c = c->next) {
+ if (c->msDS_IntId == id) {
+ return c;
+ }
+ }
+ }
+
BINARY_ARRAY_SEARCH_P(schema->attributes_by_attributeID_id,
schema->num_attributes, attributeID_id, id, uint32_cmp, c);
return c;
@@ -84,6 +100,18 @@ const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName(const struct dsdb
return c;
}
+const struct dsdb_attribute *dsdb_attribute_by_lDAPDisplayName_ldb_val(const struct dsdb_schema *schema,
+ const struct ldb_val *name)
+{
+ struct dsdb_attribute *a;
+
+ if (!name) return NULL;
+
+ BINARY_ARRAY_SEARCH_P(schema->attributes_by_lDAPDisplayName,
+ schema->num_attributes, lDAPDisplayName, name, strcasecmp_with_ldb_val, a);
+ return a;
+}
+
const struct dsdb_attribute *dsdb_attribute_by_linkID(const struct dsdb_schema *schema,
int linkID)
{
diff --git a/source4/dsdb/schema/schema_syntax.c b/source4/dsdb/schema/schema_syntax.c
index de52b9c628..48c2031024 100644
--- a/source4/dsdb/schema/schema_syntax.c
+++ b/source4/dsdb/schema/schema_syntax.c
@@ -576,6 +576,57 @@ static WERROR dsdb_syntax_DATA_BLOB_ldb_to_drsuapi(struct ldb_context *ldb,
return WERR_OK;
}
+static WERROR _dsdb_syntax_auto_OID_drsuapi_to_ldb(struct ldb_context *ldb,
+ const struct dsdb_schema *schema,
+ const struct dsdb_attribute *attr,
+ const struct drsuapi_DsReplicaAttribute *in,
+ TALLOC_CTX *mem_ctx,
+ struct ldb_message_element *out)
+{
+ uint32_t i;
+
+ out->flags = 0;
+ out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
+ W_ERROR_HAVE_NO_MEMORY(out->name);
+
+ out->num_values = in->value_ctr.num_values;
+ out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
+ W_ERROR_HAVE_NO_MEMORY(out->values);
+
+ for (i=0; i < out->num_values; i++) {
+ uint32_t v;
+ const struct dsdb_class *c;
+ const struct dsdb_attribute *a;
+ const char *str = NULL;
+
+ if (in->value_ctr.values[i].blob == NULL) {
+ return WERR_FOOBAR;
+ }
+
+ if (in->value_ctr.values[i].blob->length != 4) {
+ return WERR_FOOBAR;
+ }
+
+ v = IVAL(in->value_ctr.values[i].blob->data, 0);
+
+ if ((c = dsdb_class_by_governsID_id(schema, v))) {
+ str = talloc_strdup(out->values, c->lDAPDisplayName);
+ } else if ((a = dsdb_attribute_by_attributeID_id(schema, v))) {
+ str = talloc_strdup(out->values, a->lDAPDisplayName);
+ } else {
+ WERROR werr;
+ werr = dsdb_schema_pfm_oid_from_attid(schema->prefixmap, v, out->values, &str);
+ W_ERROR_NOT_OK_RETURN(werr);
+ }
+ W_ERROR_HAVE_NO_MEMORY(str);
+
+ /* the values need to be reversed */
+ out->values[out->num_values - (i + 1)] = data_blob_string_const(str);
+ }
+
+ return WERR_OK;
+}
+
static WERROR _dsdb_syntax_OID_obj_drsuapi_to_ldb(struct ldb_context *ldb,
const struct dsdb_schema *schema,
const struct dsdb_attribute *attr,
@@ -711,6 +762,60 @@ static WERROR _dsdb_syntax_OID_oid_drsuapi_to_ldb(struct ldb_context *ldb,
return WERR_OK;
}
+static WERROR _dsdb_syntax_auto_OID_ldb_to_drsuapi(struct ldb_context *ldb,
+ const struct dsdb_schema *schema,
+ const struct dsdb_attribute *attr,
+ const struct ldb_message_element *in,
+ TALLOC_CTX *mem_ctx,
+ struct drsuapi_DsReplicaAttribute *out)
+{
+ uint32_t i;
+ DATA_BLOB *blobs;
+
+ out->attid= attr->attributeID_id;
+ out->value_ctr.num_values= in->num_values;
+ out->value_ctr.values= talloc_array(mem_ctx,
+ struct drsuapi_DsAttributeValue,
+ in->num_values);
+ W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
+
+ blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
+ W_ERROR_HAVE_NO_MEMORY(blobs);
+
+ for (i=0; i < in->num_values; i++) {
+ const struct dsdb_class *obj_class;
+ const struct dsdb_attribute *obj_attr;
+ struct ldb_val *v;
+
+ out->value_ctr.values[i].blob= &blobs[i];
+
+ blobs[i] = data_blob_talloc(blobs, NULL, 4);
+ W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
+
+ /* in DRS windows puts the classes in the opposite
+ order to the order used in ldap */
+ v = &in->values[(in->num_values-1)-i];
+
+ if ((obj_class = dsdb_class_by_lDAPDisplayName_ldb_val(schema, v))) {
+ SIVAL(blobs[i].data, 0, obj_class->governsID_id);
+ } else if ((obj_attr = dsdb_attribute_by_lDAPDisplayName_ldb_val(schema, v))) {
+ SIVAL(blobs[i].data, 0, obj_attr->attributeID_id);
+ } else {
+ uint32_t attid;
+ WERROR werr;
+ werr = dsdb_schema_pfm_make_attid(schema->prefixmap,
+ (const char *)v->data,
+ &attid);
+ W_ERROR_NOT_OK_RETURN(werr);
+ SIVAL(blobs[i].data, 0, attid);
+ }
+
+ }
+
+
+ return WERR_OK;
+}
+
static WERROR _dsdb_syntax_OID_obj_ldb_to_drsuapi(struct ldb_context *ldb,
const struct dsdb_schema *schema,
const struct dsdb_attribute *attr,
@@ -839,18 +944,19 @@ static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb,
TALLOC_CTX *mem_ctx,
struct ldb_message_element *out)
{
- uint32_t i;
-
switch (attr->attributeID_id) {
case DRSUAPI_ATTRIBUTE_objectClass:
case DRSUAPI_ATTRIBUTE_subClassOf:
case DRSUAPI_ATTRIBUTE_auxiliaryClass:
+ case DRSUAPI_ATTRIBUTE_systemAuxiliaryClass:
case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
case DRSUAPI_ATTRIBUTE_possSuperiors:
return _dsdb_syntax_OID_obj_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
case DRSUAPI_ATTRIBUTE_systemMustContain:
case DRSUAPI_ATTRIBUTE_systemMayContain:
case DRSUAPI_ATTRIBUTE_mustContain:
+ case DRSUAPI_ATTRIBUTE_rDNAttId:
+ case DRSUAPI_ATTRIBUTE_transportAddressAttribute:
case DRSUAPI_ATTRIBUTE_mayContain:
return _dsdb_syntax_OID_attr_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
case DRSUAPI_ATTRIBUTE_governsID:
@@ -859,41 +965,9 @@ static WERROR dsdb_syntax_OID_drsuapi_to_ldb(struct ldb_context *ldb,
return _dsdb_syntax_OID_oid_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
}
- out->flags = 0;
- out->name = talloc_strdup(mem_ctx, attr->lDAPDisplayName);
- W_ERROR_HAVE_NO_MEMORY(out->name);
-
- out->num_values = in->value_ctr.num_values;
- out->values = talloc_array(mem_ctx, struct ldb_val, out->num_values);
- W_ERROR_HAVE_NO_MEMORY(out->values);
-
- for (i=0; i < out->num_values; i++) {
- uint32_t v;
- const char *name;
- char *str;
-
- if (in->value_ctr.values[i].blob == NULL) {
- return WERR_FOOBAR;
- }
-
- if (in->value_ctr.values[i].blob->length != 4) {
- return WERR_FOOBAR;
- }
-
- v = IVAL(in->value_ctr.values[i].blob->data, 0);
-
- name = dsdb_lDAPDisplayName_by_id(schema, v);
- if (!name) {
- return WERR_FOOBAR;
- }
-
- str = talloc_strdup(out->values, name);
- W_ERROR_HAVE_NO_MEMORY(str);
-
- out->values[i] = data_blob_string_const(str);
- }
-
- return WERR_OK;
+ DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
+ attr->lDAPDisplayName));
+ return _dsdb_syntax_auto_OID_drsuapi_to_ldb(ldb, schema, attr, in, mem_ctx, out);
}
static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb,
@@ -903,9 +977,6 @@ static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb,
TALLOC_CTX *mem_ctx,
struct drsuapi_DsReplicaAttribute *out)
{
- uint32_t i;
- DATA_BLOB *blobs;
-
if (attr->attributeID_id == 0xFFFFFFFF) {
return WERR_FOOBAR;
}
@@ -914,12 +985,15 @@ static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb,
case DRSUAPI_ATTRIBUTE_objectClass:
case DRSUAPI_ATTRIBUTE_subClassOf:
case DRSUAPI_ATTRIBUTE_auxiliaryClass:
+ case DRSUAPI_ATTRIBUTE_systemAuxiliaryClass:
case DRSUAPI_ATTRIBUTE_systemPossSuperiors:
case DRSUAPI_ATTRIBUTE_possSuperiors:
return _dsdb_syntax_OID_obj_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
case DRSUAPI_ATTRIBUTE_systemMustContain:
case DRSUAPI_ATTRIBUTE_systemMayContain:
case DRSUAPI_ATTRIBUTE_mustContain:
+ case DRSUAPI_ATTRIBUTE_rDNAttId:
+ case DRSUAPI_ATTRIBUTE_transportAddressAttribute:
case DRSUAPI_ATTRIBUTE_mayContain:
return _dsdb_syntax_OID_attr_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
case DRSUAPI_ATTRIBUTE_governsID:
@@ -928,30 +1002,10 @@ static WERROR dsdb_syntax_OID_ldb_to_drsuapi(struct ldb_context *ldb,
return _dsdb_syntax_OID_oid_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
}
- out->attid = attr->attributeID_id;
- out->value_ctr.num_values = in->num_values;
- out->value_ctr.values = talloc_array(mem_ctx,
- struct drsuapi_DsAttributeValue,
- in->num_values);
- W_ERROR_HAVE_NO_MEMORY(out->value_ctr.values);
-
- blobs = talloc_array(mem_ctx, DATA_BLOB, in->num_values);
- W_ERROR_HAVE_NO_MEMORY(blobs);
+ DEBUG(0,(__location__ ": Unknown handling for attributeID_id for %s\n",
+ attr->lDAPDisplayName));
- for (i=0; i < in->num_values; i++) {
- uint32_t v;
-
- out->value_ctr.values[i].blob = &blobs[i];
-
- blobs[i] = data_blob_talloc(blobs, NULL, 4);
- W_ERROR_HAVE_NO_MEMORY(blobs[i].data);
-
- v = strtol((const char *)in->values[i].data, NULL, 10);
-
- SIVAL(blobs[i].data, 0, v);
- }
-
- return WERR_OK;
+ return _dsdb_syntax_auto_OID_ldb_to_drsuapi(ldb, schema, attr, in, mem_ctx, out);
}
static WERROR dsdb_syntax_UNICODE_drsuapi_to_ldb(struct ldb_context *ldb,