diff options
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r-- | source4/lib/ldb/common/ldb.c | 50 | ||||
-rw-r--r-- | source4/lib/ldb/common/ldb_modules.c | 4 | ||||
-rw-r--r-- | source4/lib/ldb/include/ldb.h | 37 | ||||
-rw-r--r-- | source4/lib/ldb/ldb.i | 20 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_search.c | 24 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.c | 144 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_tdb/ldb_tdb.h | 2 | ||||
-rw-r--r-- | source4/lib/ldb/ldb_wrap.c | 20 | ||||
-rw-r--r-- | source4/lib/ldb/modules/asq.c | 4 | ||||
-rwxr-xr-x | source4/lib/ldb/tests/python/ldap.py | 8 |
10 files changed, 178 insertions, 135 deletions
diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c index 75c8109042..c013565da0 100644 --- a/source4/lib/ldb/common/ldb.c +++ b/source4/lib/ldb/common/ldb.c @@ -527,10 +527,6 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req) FIRST_OP(ldb, extended); ret = module->ops->extended(module, req); break; - case LDB_SEQUENCE_NUMBER: - FIRST_OP(ldb, sequence_number); - ret = module->ops->sequence_number(module, req); - break; default: FIRST_OP(ldb, request); ret = module->ops->request(module, req); @@ -1172,35 +1168,47 @@ int ldb_rename(struct ldb_context *ldb, int ldb_sequence_number(struct ldb_context *ldb, enum ldb_sequence_type type, uint64_t *seq_num) { - struct ldb_request *req; + struct ldb_seqnum_request *seq; + struct ldb_seqnum_result *seqr; + struct ldb_result *res; + TALLOC_CTX *tmp_ctx; int ret; - req = talloc_zero(ldb, struct ldb_request); - if (req == NULL) { + *seq_num = 0; + + tmp_ctx = talloc_zero(ldb, struct ldb_request); + if (tmp_ctx == NULL) { ldb_set_errstring(ldb, "Out of Memory"); return LDB_ERR_OPERATIONS_ERROR; } + seq = talloc_zero(tmp_ctx, struct ldb_seqnum_request); + if (seq == NULL) { + ldb_set_errstring(ldb, "Out of Memory"); + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + seq->type = type; - req->operation = LDB_SEQUENCE_NUMBER; - req->controls = NULL; - req->context = NULL; - req->callback = ldb_op_default_callback; - ldb_set_timeout(ldb, req, 0); /* use default timeout */ - - req->op.seq_num.type = type; - /* do request and autostart a transaction */ - ret = ldb_request(ldb, req); + ret = ldb_extended(ldb, LDB_EXTENDED_SEQUENCE_NUMBER, seq, &res); + if (ret != LDB_SUCCESS) { + goto done; + } + talloc_steal(tmp_ctx, res); - if (ret == LDB_SUCCESS) { - *seq_num = req->op.seq_num.seq_num; + if (strcmp(LDB_EXTENDED_SEQUENCE_NUMBER, res->extended->oid) != 0) { + ldb_set_errstring(ldb, "Invalid OID in reply"); + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; } + seqr = talloc_get_type(res->extended->data, + struct ldb_seqnum_result); + *seq_num = seqr->seq_num; - talloc_free(req); +done: + talloc_free(tmp_ctx); return ret; } - - /* return extended error information */ diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 5cc8de29b4..2b453bb0c3 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -517,10 +517,6 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request) FIND_OP(module, extended); ret = module->ops->extended(module, request); break; - case LDB_SEQUENCE_NUMBER: - FIND_OP(module, sequence_number); - ret = module->ops->sequence_number(module, request); - break; default: FIND_OP(module, request); ret = module->ops->request(module, request); diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h index b1ce3ef70b..9bc5c183d8 100644 --- a/source4/lib/ldb/include/ldb.h +++ b/source4/lib/ldb/include/ldb.h @@ -652,7 +652,6 @@ enum ldb_request_type { LDB_DELETE, LDB_RENAME, LDB_EXTENDED, - LDB_SEQUENCE_NUMBER, LDB_REQ_REGISTER_CONTROL, LDB_REQ_REGISTER_PARTITION }; @@ -679,21 +678,38 @@ struct ldb_extended { void *data; /* NULL or a valid talloc pointer! talloc_get_type() will be used on it */ }; +#define LDB_EXTENDED_SEQUENCE_NUMBER "1.3.6.1.4.1.7165.4.4.3" + +enum ldb_sequence_type { + LDB_SEQ_HIGHEST_SEQ, + LDB_SEQ_HIGHEST_TIMESTAMP, + LDB_SEQ_NEXT +}; + +struct ldb_seqnum_request { + enum ldb_sequence_type type; +}; + +struct ldb_seqnum_result { + uint64_t seq_num; + uint32_t flags; +}; + struct ldb_result { unsigned int count; struct ldb_message **msgs; - char **refs; struct ldb_extended *extended; struct ldb_control **controls; + char **refs; }; struct ldb_reply { + int error; enum ldb_reply_type type; struct ldb_message *message; struct ldb_extended *response; - char *referral; struct ldb_control **controls; - int error; + char *referral; }; struct ldb_request; @@ -732,18 +748,6 @@ struct ldb_register_partition { struct ldb_dn *dn; }; -enum ldb_sequence_type { - LDB_SEQ_HIGHEST_SEQ, - LDB_SEQ_HIGHEST_TIMESTAMP, - LDB_SEQ_NEXT -}; - -struct ldb_sequence_number { - enum ldb_sequence_type type; - uint64_t seq_num; - uint32_t flags; -}; - typedef int (*ldb_request_callback_t)(struct ldb_request *, struct ldb_reply *); struct ldb_request { @@ -757,7 +761,6 @@ struct ldb_request { struct ldb_delete del; struct ldb_rename rename; struct ldb_extended extended; - struct ldb_sequence_number seq_num; struct ldb_register_control reg_control; struct ldb_register_partition reg_partition; } op; diff --git a/source4/lib/ldb/ldb.i b/source4/lib/ldb/ldb.i index 024ba1959a..6013462225 100644 --- a/source4/lib/ldb/ldb.i +++ b/source4/lib/ldb/ldb.i @@ -1219,25 +1219,6 @@ int py_module_del_transaction(struct ldb_module *mod) return LDB_SUCCESS; } -int py_module_sequence_number(struct ldb_module *mod, struct ldb_request *req) -{ - PyObject *py_ldb = mod->private_data; - PyObject *py_result; - int ret; - - py_result = PyObject_CallMethod(py_ldb, "sequence_number", "ili", req->op.seq_num.type, req->op.seq_num.seq_num, req->op.seq_num.flags); - - if (py_result == NULL) { - return LDB_ERR_OPERATIONS_ERROR; - } - - ret = PyInt_AsLong(py_result); - - Py_DECREF(py_result); - - return ret; -} - static int py_module_destructor(void *_mod) { struct ldb_module *mod = _mod; @@ -1292,7 +1273,6 @@ int py_module_init (struct ldb_module *mod) $1->start_transaction = py_module_start_transaction; $1->end_transaction = py_module_end_transaction; $1->del_transaction = py_module_del_transaction; - $1->sequence_number = py_module_sequence_number; } %feature("docstring") ldb_register_module "S.register_module(module) -> None\n" diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c index a220b4a628..1c76411db2 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_search.c +++ b/source4/lib/ldb/ldb_tdb/ldb_search.c @@ -277,30 +277,6 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes } /* - lock the database for read - use by ltdb_search -*/ -static int ltdb_lock_read(struct ldb_module *module) -{ - struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data; - if (ltdb->in_transaction == 0) { - return tdb_lockall_read(ltdb->tdb); - } - return 0; -} - -/* - unlock the database after a ltdb_lock_read() -*/ -static int ltdb_unlock_read(struct ldb_module *module) -{ - struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data; - if (ltdb->in_transaction == 0) { - return tdb_unlockall_read(ltdb->tdb); - } - return 0; -} - -/* add a set of attributes from a record to a set of results return 0 on success, -1 on failure */ diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c index 0087f6c44d..2282f61d47 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c @@ -79,6 +79,30 @@ static int ltdb_err_map(enum TDB_ERROR tdb_code) return LDB_ERR_OTHER; } +/* + lock the database for read - use by ltdb_search and ltdb_sequence_number +*/ +int ltdb_lock_read(struct ldb_module *module) +{ + struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data; + if (ltdb->in_transaction == 0) { + return tdb_lockall_read(ltdb->tdb); + } + return 0; +} + +/* + unlock the database after a ltdb_lock_read() +*/ +int ltdb_unlock_read(struct ldb_module *module) +{ + struct ltdb_private *ltdb = (struct ltdb_private *)module->private_data; + if (ltdb->in_transaction == 0) { + return tdb_unlockall_read(ltdb->tdb); + } + return 0; +} + /* form a TDB_DATA for a record key @@ -860,61 +884,88 @@ static int ltdb_del_trans(struct ldb_module *module) /* return sequenceNumber from @BASEINFO */ -static int ltdb_sequence_number(struct ldb_module *module, - struct ldb_request *req) +static int ltdb_sequence_number(struct ltdb_context *ctx, + struct ldb_extended **ext) { + struct ldb_module *module = ctx->module; + struct ldb_request *req = ctx->req; TALLOC_CTX *tmp_ctx; + struct ldb_seqnum_request *seq; + struct ldb_seqnum_result *res; struct ldb_message *msg = NULL; struct ldb_dn *dn; const char *date; - int tret; + int ret; + seq = talloc_get_type(req->op.extended.data, + struct ldb_seqnum_request); + if (seq == NULL) { + return LDB_ERR_OPERATIONS_ERROR; + } + + req->handle->state = LDB_ASYNC_PENDING; + + if (ltdb_lock_read(module) != 0) { + return LDB_ERR_OPERATIONS_ERROR; + } + + res = talloc_zero(req, struct ldb_seqnum_result); + if (res == NULL) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } tmp_ctx = talloc_new(req); if (tmp_ctx == NULL) { - talloc_free(tmp_ctx); - return LDB_ERR_OPERATIONS_ERROR; + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; } dn = ldb_dn_new(tmp_ctx, module->ldb, LTDB_BASEINFO); msg = talloc(tmp_ctx, struct ldb_message); if (msg == NULL) { - talloc_free(tmp_ctx); - return LDB_ERR_OPERATIONS_ERROR; + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; } - req->op.seq_num.flags = 0; - - tret = ltdb_search_dn1(module, dn, msg); - if (tret != LDB_SUCCESS) { - talloc_free(tmp_ctx); - /* zero is as good as anything when we don't know */ - req->op.seq_num.seq_num = 0; - return tret; + ret = ltdb_search_dn1(module, dn, msg); + if (ret != LDB_SUCCESS) { + goto done; } - switch (req->op.seq_num.type) { + switch (seq->type) { case LDB_SEQ_HIGHEST_SEQ: - req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0); + res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0); break; case LDB_SEQ_NEXT: - req->op.seq_num.seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0); - req->op.seq_num.seq_num++; + res->seq_num = ldb_msg_find_attr_as_uint64(msg, LTDB_SEQUENCE_NUMBER, 0); + res->seq_num++; break; case LDB_SEQ_HIGHEST_TIMESTAMP: date = ldb_msg_find_attr_as_string(msg, LTDB_MOD_TIMESTAMP, NULL); if (date) { - req->op.seq_num.seq_num = ldb_string_to_time(date); + res->seq_num = ldb_string_to_time(date); } else { - req->op.seq_num.seq_num = 0; + res->seq_num = 0; /* zero is as good as anything when we don't know */ } break; } - talloc_free(tmp_ctx); + *ext = talloc_zero(req, struct ldb_extended); + if (*ext == NULL) { + ret = LDB_ERR_OPERATIONS_ERROR; + goto done; + } + (*ext)->oid = LDB_EXTENDED_SEQUENCE_NUMBER; + (*ext)->data = talloc_steal(*ext, res); - return LDB_SUCCESS; + ret = LDB_SUCCESS; + +done: + talloc_free(tmp_ctx); + ltdb_unlock_read(module); + return ret; } void ltdb_request_done(struct ldb_request *req, int error) @@ -949,6 +1000,47 @@ static void ltdb_timeout(struct event_context *ev, ltdb_request_done(ctx->req, LDB_ERR_TIME_LIMIT_EXCEEDED); } +static void ltdb_request_extended_done(struct ldb_request *req, + struct ldb_extended *ext, + int error) +{ + struct ldb_reply *ares; + + /* if we already returned an error just return */ + if (req->handle->status != LDB_SUCCESS) { + return; + } + + ares = talloc_zero(req, struct ldb_reply); + if (!ares) { + ldb_oom(req->handle->ldb); + req->callback(req, NULL); + return; + } + ares->type = LDB_REPLY_DONE; + ares->response = ext; + ares->error = error; + + req->callback(req, ares); +} + +static void ltdb_handle_extended(struct ltdb_context *ctx) +{ + struct ldb_extended *ext = NULL; + int ret; + + if (strcmp(ctx->req->op.extended.oid, + LDB_EXTENDED_SEQUENCE_NUMBER) == 0) { + /* get sequence number */ + ret = ltdb_sequence_number(ctx, &ext); + } else { + /* not recognized */ + ret = LDB_ERR_UNSUPPORTED_CRITICAL_EXTENSION; + } + + ltdb_request_extended_done(ctx->req, ext, ret); +} + static void ltdb_callback(struct event_context *ev, struct timed_event *te, struct timeval t, @@ -975,6 +1067,9 @@ static void ltdb_callback(struct event_context *ev, case LDB_RENAME: ret = ltdb_rename(ctx); break; + case LDB_EXTENDED: + ltdb_handle_extended(ctx); + return; default: /* no other op supported */ ret = LDB_ERR_UNWILLING_TO_PERFORM; @@ -1037,11 +1132,10 @@ static const struct ldb_module_ops ltdb_ops = { .modify = ltdb_handle_request, .del = ltdb_handle_request, .rename = ltdb_handle_request, -/* .request = ltdb_handle_request, */ + .extended = ltdb_handle_request, .start_transaction = ltdb_start_trans, .end_transaction = ltdb_end_trans, .del_transaction = ltdb_del_trans, - .sequence_number = ltdb_sequence_number }; /* diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h index 223181ca0b..61e90bccc6 100644 --- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h +++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h @@ -112,6 +112,8 @@ int ltdb_filter_attrs(struct ldb_message *msg, const char * const *attrs); int ltdb_search(struct ltdb_context *ctx); /* The following definitions come from lib/ldb/ldb_tdb/ldb_tdb.c */ +int ltdb_lock_read(struct ldb_module *module); +int ltdb_unlock_read(struct ldb_module *module); struct TDB_DATA ltdb_key(struct ldb_module *module, struct ldb_dn *dn); int ltdb_store(struct ldb_module *module, const struct ldb_message *msg, int flgs); int ltdb_delete_noindex(struct ldb_module *module, struct ldb_dn *dn); diff --git a/source4/lib/ldb/ldb_wrap.c b/source4/lib/ldb/ldb_wrap.c index cc8099f27f..bc9266a306 100644 --- a/source4/lib/ldb/ldb_wrap.c +++ b/source4/lib/ldb/ldb_wrap.c @@ -3505,25 +3505,6 @@ int py_module_del_transaction(struct ldb_module *mod) return LDB_SUCCESS; } -int py_module_sequence_number(struct ldb_module *mod, struct ldb_request *req) -{ - PyObject *py_ldb = mod->private_data; - PyObject *py_result; - int ret; - - py_result = PyObject_CallMethod(py_ldb, "sequence_number", "ili", req->op.seq_num.type, req->op.seq_num.seq_num, req->op.seq_num.flags); - - if (py_result == NULL) { - return LDB_ERR_OPERATIONS_ERROR; - } - - ret = PyInt_AsLong(py_result); - - Py_DECREF(py_result); - - return ret; -} - static int py_module_destructor(void *_mod) { struct ldb_module *mod = _mod; @@ -6648,7 +6629,6 @@ SWIGINTERN PyObject *_wrap_register_module(PyObject *SWIGUNUSEDPARM(self), PyObj arg1->start_transaction = py_module_start_transaction; arg1->end_transaction = py_module_end_transaction; arg1->del_transaction = py_module_del_transaction; - arg1->sequence_number = py_module_sequence_number; result = ldb_register_module((struct ldb_module_ops const *)arg1); if (result != 0) { PyErr_SetObject(PyExc_LdbError, Py_BuildValue((char *)"(i,s)", result, ldb_strerror(result))); diff --git a/source4/lib/ldb/modules/asq.c b/source4/lib/ldb/modules/asq.c index 17896a006a..835715e7dc 100644 --- a/source4/lib/ldb/modules/asq.c +++ b/source4/lib/ldb/modules/asq.c @@ -222,10 +222,10 @@ static int asq_build_first_request(struct asq_context *ac, struct ldb_request ** base_attrs[1] = NULL; - ret = ldb_build_search_req_ex(base_req, ac->module->ldb, ac, + ret = ldb_build_search_req(base_req, ac->module->ldb, ac, ac->req->op.search.base, LDB_SCOPE_BASE, - ac->req->op.search.tree, + NULL, (const char * const *)base_attrs, NULL, ac, asq_base_callback, diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py index e2cc658521..71fd98876e 100755 --- a/source4/lib/ldb/tests/python/ldap.py +++ b/source4/lib/ldb/tests/python/ldap.py @@ -756,7 +756,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """ ldb.delete(res[0].dn) - attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "memberOf"] + attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "memberOf", "allowedAttributes", "allowedAttributesEffective"] print "Testing ldb.search for (&(cn=ldaptestUSer2)(objectClass=user))" res = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs) self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))") @@ -768,9 +768,11 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """ self.assertTrue("objectGUID" in res[0]) self.assertTrue("whenCreated" in res[0]) self.assertTrue("nTSecurityDescriptor" in res[0]) + self.assertTrue("allowedAttributes" in res[0]) + self.assertTrue("allowedAttributesEffective" in res[0]) self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper()) - attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member"] + attrs = ["cn", "name", "objectClass", "objectGUID", "whenCreated", "nTSecurityDescriptor", "member", "allowedAttributes", "allowedAttributesEffective"] print "Testing ldb.search for (&(cn=ldaptestgroup2)(objectClass=group))" res = ldb.search(self.base_dn, expression="(&(cn=ldaptestgroup2)(objectClass=group))", scope=SCOPE_SUBTREE, attrs=attrs) self.assertEquals(len(res), 1, "Could not find (&(cn=ldaptestgroup2)(objectClass=group))") @@ -782,6 +784,8 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """ self.assertTrue("objectGuid" not in res[0]) self.assertTrue("whenCreated" in res[0]) self.assertTrue("nTSecurityDescriptor" in res[0]) + self.assertTrue("allowedAttributes" in res[0]) + self.assertTrue("allowedAttributesEffective" in res[0]) memberUP = [] for m in res[0]["member"]: memberUP.append(m.upper()) |