summaryrefslogtreecommitdiff
path: root/source4/lib/ldb
diff options
context:
space:
mode:
authorbubulle <bubulle@alioth.debian.org>2010-09-06 20:54:34 +0000
committerbubulle <bubulle@alioth.debian.org>2010-09-06 20:54:34 +0000
commit53601faba8f69c3454ad07acaceeef9165cb3743 (patch)
treeb31a4174a7f4d2650717c1902a6bc3f922e13117 /source4/lib/ldb
parent1b77db997b6a2ce389356509415a6e5e540bcfe0 (diff)
downloadsamba-53601faba8f69c3454ad07acaceeef9165cb3743.tar.gz
Merge 3.5.4 in upstream branch
git-svn-id: svn://svn.debian.org/svn/pkg-samba/branches/samba/upstream@3574 fc4039ab-9d04-0410-8cac-899223bdd6b0
Diffstat (limited to 'source4/lib/ldb')
-rw-r--r--source4/lib/ldb/Makefile.in5
-rw-r--r--source4/lib/ldb/common/attrib_handlers.c132
-rw-r--r--source4/lib/ldb/common/ldb.c225
-rw-r--r--source4/lib/ldb/common/ldb_attributes.c37
-rw-r--r--source4/lib/ldb/common/ldb_controls.c66
-rw-r--r--source4/lib/ldb/common/ldb_debug.c41
-rw-r--r--source4/lib/ldb/common/ldb_dn.c509
-rw-r--r--source4/lib/ldb/common/ldb_ldif.c93
-rw-r--r--source4/lib/ldb/common/ldb_match.c2
-rw-r--r--source4/lib/ldb/common/ldb_modules.c125
-rw-r--r--source4/lib/ldb/common/ldb_msg.c12
-rw-r--r--source4/lib/ldb/common/ldb_parse.c61
-rwxr-xr-xsource4/lib/ldb/config.guess4
-rw-r--r--source4/lib/ldb/config.mk12
-rwxr-xr-xsource4/lib/ldb/config.sub2
-rw-r--r--source4/lib/ldb/configure.ac2
-rw-r--r--source4/lib/ldb/external/libevents.m42
-rw-r--r--source4/lib/ldb/external/libtalloc.m47
-rw-r--r--source4/lib/ldb/external/libtdb.m42
-rw-r--r--source4/lib/ldb/include/dlinklist.h11
-rw-r--r--source4/lib/ldb/include/ldb.h99
-rw-r--r--source4/lib/ldb/include/ldb_errors.h2
-rw-r--r--source4/lib/ldb/include/ldb_handlers.h29
-rw-r--r--source4/lib/ldb/include/ldb_module.h15
-rw-r--r--source4/lib/ldb/include/ldb_private.h13
-rw-r--r--source4/lib/ldb/ldb.mk12
-rw-r--r--source4/lib/ldb/ldb.pc.in2
-rw-r--r--source4/lib/ldb/ldb_ildap/ldb_ildap.c6
-rw-r--r--source4/lib/ldb/ldb_ldap/ldb_ldap.c6
-rw-r--r--source4/lib/ldb/ldb_map/ldb_map.c16
-rw-r--r--source4/lib/ldb/ldb_map/ldb_map_inbound.c8
-rw-r--r--source4/lib/ldb/ldb_map/ldb_map_outbound.c16
-rw-r--r--source4/lib/ldb/ldb_sqlite3/base160.c2
-rw-r--r--source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c1
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_cache.c13
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_index.c178
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_pack.c6
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_search.c25
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.c125
-rw-r--r--source4/lib/ldb/ldb_tdb/ldb_tdb.h5
-rw-r--r--source4/lib/ldb/modules/asq.c8
-rw-r--r--source4/lib/ldb/modules/operational.c314
-rw-r--r--source4/lib/ldb/modules/paged_results.c4
-rw-r--r--source4/lib/ldb/modules/paged_searches.c115
-rw-r--r--source4/lib/ldb/modules/rdn_name.c24
-rw-r--r--source4/lib/ldb/modules/sort.c15
-rw-r--r--source4/lib/ldb/pyldb.c619
-rw-r--r--source4/lib/ldb/pyldb.h17
-rw-r--r--source4/lib/ldb/python.mk2
-rw-r--r--source4/lib/ldb/rules.mk1
-rwxr-xr-xsource4/lib/ldb/tests/python/api.py203
-rwxr-xr-xsource4/lib/ldb/tests/python/ldap.py606
-rwxr-xr-xsource4/lib/ldb/tests/python/sec_descriptor.py1615
-rw-r--r--source4/lib/ldb/tools/cmdline.c75
-rw-r--r--source4/lib/ldb/tools/cmdline.h4
-rw-r--r--source4/lib/ldb/tools/ldbadd.c18
-rw-r--r--source4/lib/ldb/tools/ldbdel.c7
-rw-r--r--source4/lib/ldb/tools/ldbedit.c10
-rw-r--r--source4/lib/ldb/tools/ldbmodify.c7
-rw-r--r--source4/lib/ldb/tools/ldbrename.c6
-rw-r--r--source4/lib/ldb/tools/ldbsearch.c9
61 files changed, 4363 insertions, 1245 deletions
diff --git a/source4/lib/ldb/Makefile.in b/source4/lib/ldb/Makefile.in
index 663dea9f80..c1f403d550 100644
--- a/source4/lib/ldb/Makefile.in
+++ b/source4/lib/ldb/Makefile.in
@@ -23,6 +23,7 @@ PACKAGE_VERSION = @PACKAGE_VERSION@
PYTHON = @PYTHON@
PYTHON_CONFIG = @PYTHON_CONFIG@
ldbdir = $(srcdir)
+LIB_PATH_VAR = @LIB_PATH_VAR@
LDB_MODULESDIR = @LDB_MODULESDIR@
@@ -146,10 +147,10 @@ realdistclean:: distclean
check:: test @PYTHON_CHECK_TARGET@
check-soloading: sample.$(SHLIBEXT)
- LDB_MODULES_PATH=$(builddir) $(srcdir)/tests/test-soloading.sh
+ $(LIB_PATH_VAR)=lib LDB_MODULES_PATH=$(builddir) $(srcdir)/tests/test-soloading.sh
test:: all check-soloading
- for t in $(TESTS); do echo STARTING $${t}; $(srcdir)/tests/$${t} || exit 1; done
+ for t in $(TESTS); do echo STARTING $${t}; $(LIB_PATH_VAR)=lib $(srcdir)/tests/$${t} || exit 1; done
valgrindtest:: all
for t in $(TESTS); do echo STARTING $${t}; VALGRIND="valgrind -q --db-attach=yes --num-callers=30" $(srcdir)/tests/$${t} || exit 1; done
diff --git a/source4/lib/ldb/common/attrib_handlers.c b/source4/lib/ldb/common/attrib_handlers.c
index 80725ec04f..ba21fcac9b 100644
--- a/source4/lib/ldb/common/attrib_handlers.c
+++ b/source4/lib/ldb/common/attrib_handlers.c
@@ -62,7 +62,7 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
out->data = (uint8_t *)ldb_casefold(ldb, mem_ctx, (const char *)(in->data), in->length);
if (out->data == NULL) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%s]", in->data);
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_handler_fold: unable to casefold string [%.*s]", (int)in->length, (const char *)in->data);
return -1;
}
@@ -105,7 +105,7 @@ int ldb_handler_fold(struct ldb_context *ldb, void *mem_ctx,
canonicalise a ldap Integer
rfc2252 specifies it should be in decimal form
*/
-int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
+static int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out)
{
char *end;
@@ -124,13 +124,45 @@ int ldb_canonicalise_Integer(struct ldb_context *ldb, void *mem_ctx,
/*
compare two Integers
*/
-int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx,
+static int ldb_comparison_Integer(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
return strtoll((char *)v1->data, NULL, 0) - strtoll((char *)v2->data, NULL, 0);
}
/*
+ canonicalise a ldap Boolean
+ rfc2252 specifies it should be either "TRUE" or "FALSE"
+*/
+static int ldb_canonicalise_Boolean(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *in, struct ldb_val *out)
+{
+ if (strncasecmp((char *)in->data, "TRUE", in->length) == 0) {
+ out->data = (uint8_t *)talloc_strdup(mem_ctx, "TRUE");
+ out->length = 4;
+ } else if (strncasecmp((char *)in->data, "FALSE", in->length) == 0) {
+ out->data = (uint8_t *)talloc_strdup(mem_ctx, "FALSE");
+ out->length = 4;
+ } else {
+ return -1;
+ }
+ return 0;
+}
+
+/*
+ compare two Booleans
+*/
+static int ldb_comparison_Boolean(struct ldb_context *ldb, void *mem_ctx,
+ const struct ldb_val *v1, const struct ldb_val *v2)
+{
+ if (v1->length != v2->length) {
+ return v1->length - v2->length;
+ }
+ return strncasecmp((char *)v1->data, (char *)v2->data, v1->length);
+}
+
+
+/*
compare two binary blobs
*/
int ldb_comparison_binary(struct ldb_context *ldb, void *mem_ctx,
@@ -155,13 +187,13 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
{
const char *s1=(const char *)v1->data, *s2=(const char *)v2->data;
size_t n1 = v1->length, n2 = v2->length;
- const char *u1, *u2;
char *b1, *b2;
+ const char *u1, *u2;
int ret;
- while (*s1 == ' ' && n1) { s1++; n1--; };
- while (*s2 == ' ' && n2) { s2++; n2--; };
- /* TODO: make utf8 safe, possibly with helper function from application */
- while (*s1 && *s2 && n1 && n2) {
+ while (n1 && *s1 == ' ') { s1++; n1--; };
+ while (n2 && *s2 == ' ') { s2++; n2--; };
+
+ while (n1 && n2 && *s1 && *s2) {
/* the first 127 (0x7F) chars are ascii and utf8 guarantes they
* never appear in multibyte sequences */
if (((unsigned char)s1[0]) & 0x80) goto utf8str;
@@ -169,43 +201,58 @@ int ldb_comparison_fold(struct ldb_context *ldb, void *mem_ctx,
if (toupper((unsigned char)*s1) != toupper((unsigned char)*s2))
break;
if (*s1 == ' ') {
- while (s1[0] == s1[1] && n1) { s1++; n1--; }
- while (s2[0] == s2[1] && n2) { s2++; n2--; }
+ while (n1 && s1[0] == s1[1]) { s1++; n1--; }
+ while (n2 && s2[0] == s2[1]) { s2++; n2--; }
}
s1++; s2++;
n1--; n2--;
}
- if (! (*s1 && *s2)) {
- /* check for trailing spaces only if one of the pointers
- * has reached the end of the strings otherwise we
- * can mistakenly match.
- * ex. "domain users" <-> "domainUpdates"
- */
- while (*s1 == ' ') { s1++; n1--; }
- while (*s2 == ' ') { s2++; n2--; }
+
+ /* check for trailing spaces only if the other pointers has
+ * reached the end of the strings otherwise we can
+ * mistakenly match. ex. "domain users" <->
+ * "domainUpdates"
+ */
+ if (n1 && *s1 == ' ' && (!n2 || !*s2)) {
+ while (n1 && *s1 == ' ') { s1++; n1--; }
+ }
+ if (n2 && *s2 == ' ' && (!n1 || !*s1)) {
+ while (n2 && *s2 == ' ') { s2++; n2--; }
}
- if (n1 != n2) {
- return n1 - n2;
+ if (n1 == 0 && n2 != 0) {
+ return -(int)toupper(*s2);
}
- return (int)(toupper(*s1)) - (int)(toupper(*s2));
+ if (n2 == 0 && n1 != 0) {
+ return (int)toupper(*s1);
+ }
+ if (n2 == 0 && n2 == 0) {
+ return 0;
+ }
+ return (int)toupper(*s1) - (int)toupper(*s2);
utf8str:
/* no need to recheck from the start, just from the first utf8 char found */
b1 = ldb_casefold(ldb, mem_ctx, s1, n1);
b2 = ldb_casefold(ldb, mem_ctx, s2, n2);
- if (b1 && b2) {
- /* Both strings converted correctly */
-
- u1 = b1;
- u2 = b2;
- } else {
- /* One of the strings was not UTF8, so we have no options but to do a binary compare */
-
- u1 = s1;
- u2 = s2;
+ if (!b1 || !b2) {
+ /* One of the strings was not UTF8, so we have no
+ * options but to do a binary compare */
+ talloc_free(b1);
+ talloc_free(b2);
+ if (memcmp(s1, s2, MIN(n1, n2)) == 0) {
+ if (n1 == n2) return 0;
+ if (n1 > n2) {
+ return (int)toupper(s1[n2]);
+ } else {
+ return -(int)toupper(s2[n1]);
+ }
+ }
}
+ u1 = b1;
+ u2 = b2;
+
while (*u1 & *u2) {
if (*u1 != *u2)
break;
@@ -231,7 +278,7 @@ utf8str:
/*
canonicalise a attribute in DN format
*/
-int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
+static int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out)
{
struct ldb_dn *dn;
@@ -240,7 +287,7 @@ int ldb_canonicalise_dn(struct ldb_context *ldb, void *mem_ctx,
out->length = 0;
out->data = NULL;
- dn = ldb_dn_from_ldb_val(ldb, mem_ctx, in);
+ dn = ldb_dn_from_ldb_val(mem_ctx, ldb, in);
if ( ! ldb_dn_validate(dn)) {
return LDB_ERR_INVALID_DN_SYNTAX;
}
@@ -262,16 +309,16 @@ done:
/*
compare two dns
*/
-int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
+static int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
struct ldb_dn *dn1 = NULL, *dn2 = NULL;
int ret;
- dn1 = ldb_dn_from_ldb_val(ldb, mem_ctx, v1);
+ dn1 = ldb_dn_from_ldb_val(mem_ctx, ldb, v1);
if ( ! ldb_dn_validate(dn1)) return -1;
- dn2 = ldb_dn_from_ldb_val(ldb, mem_ctx, v2);
+ dn2 = ldb_dn_from_ldb_val(mem_ctx, ldb, v2);
if ( ! ldb_dn_validate(dn2)) {
talloc_free(dn1);
return -1;
@@ -287,7 +334,7 @@ int ldb_comparison_dn(struct ldb_context *ldb, void *mem_ctx,
/*
compare two utc time values. 1 second resolution
*/
-int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx,
+static int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2)
{
time_t t1, t2;
@@ -299,7 +346,7 @@ int ldb_comparison_utctime(struct ldb_context *ldb, void *mem_ctx,
/*
canonicalise a utc time
*/
-int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx,
+static int ldb_canonicalise_utctime(struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out)
{
time_t t = ldb_string_to_time((char *)in->data);
@@ -356,7 +403,14 @@ static const struct ldb_schema_syntax ldb_standard_syntaxes[] = {
.ldif_write_fn = ldb_handler_copy,
.canonicalise_fn = ldb_canonicalise_utctime,
.comparison_fn = ldb_comparison_utctime
- }
+ },
+ {
+ .name = LDB_SYNTAX_BOOLEAN,
+ .ldif_read_fn = ldb_handler_copy,
+ .ldif_write_fn = ldb_handler_copy,
+ .canonicalise_fn = ldb_canonicalise_Boolean,
+ .comparison_fn = ldb_comparison_Boolean
+ },
};
diff --git a/source4/lib/ldb/common/ldb.c b/source4/lib/ldb/common/ldb.c
index 86ce2069a5..e9c924583e 100644
--- a/source4/lib/ldb/common/ldb.c
+++ b/source4/lib/ldb/common/ldb.c
@@ -41,8 +41,8 @@ static int ldb_context_destructor(void *ptr)
if (ldb->transaction_active) {
ldb_debug(ldb, LDB_DEBUG_FATAL,
- "A transaction is still active in ldb context [%p]",
- ldb);
+ "A transaction is still active in ldb context [%p] on %s",
+ ldb, (const char *)ldb_get_opaque(ldb, "ldb_url"));
}
return 0;
@@ -240,7 +240,7 @@ int ldb_connect(struct ldb_context *ldb, const char *url,
if (ldb_load_modules(ldb, options) != LDB_SUCCESS) {
ldb_debug(ldb, LDB_DEBUG_FATAL,
- "Unable to load modules for %s: %s\n",
+ "Unable to load modules for %s: %s",
url, ldb_errstring(ldb));
return LDB_ERR_OTHER;
}
@@ -257,6 +257,9 @@ void ldb_set_errstring(struct ldb_context *ldb, const char *err_string)
talloc_free(ldb->err_string);
}
ldb->err_string = talloc_strdup(ldb, err_string);
+ if (ldb->flags & LDB_FLG_ENABLE_TRACING) {
+ ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_set_errstring: %s", ldb->err_string);
+ }
}
void ldb_asprintf_errstring(struct ldb_context *ldb, const char *format, ...)
@@ -282,15 +285,20 @@ void ldb_reset_err_string(struct ldb_context *ldb)
}
}
-#define FIRST_OP(ldb, op) do { \
+#define FIRST_OP_NOERR(ldb, op) do { \
module = ldb->modules; \
while (module && module->ops->op == NULL) module = module->next; \
- if (module == NULL) { \
+} while (0)
+
+#define FIRST_OP(ldb, op) do { \
+ FIRST_OP_NOERR(ldb, op); \
+ if (module == NULL) { \
ldb_asprintf_errstring(ldb, "unable to find module or backend to handle operation: " #op); \
return LDB_ERR_OPERATIONS_ERROR; \
} \
} while (0)
+
/*
start a transaction
*/
@@ -311,6 +319,7 @@ int ldb_transaction_start(struct ldb_context *ldb)
/* start a new transaction */
ldb->transaction_active++;
+ ldb->prepare_commit_done = false;
FIRST_OP(ldb, start_transaction);
@@ -330,6 +339,57 @@ int ldb_transaction_start(struct ldb_context *ldb)
}
/*
+ prepare for transaction commit (first phase of two phase commit)
+*/
+int ldb_transaction_prepare_commit(struct ldb_context *ldb)
+{
+ struct ldb_module *module;
+ int status;
+
+ if (ldb->prepare_commit_done) {
+ return LDB_SUCCESS;
+ }
+
+ /* commit only when all nested transactions are complete */
+ if (ldb->transaction_active > 1) {
+ return LDB_SUCCESS;
+ }
+
+ ldb->prepare_commit_done = true;
+
+ if (ldb->transaction_active < 0) {
+ ldb_debug(ldb, LDB_DEBUG_FATAL,
+ "prepare commit called but no ldb transactions are active!");
+ ldb->transaction_active = 0;
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+
+ /* call prepare transaction if available */
+ FIRST_OP_NOERR(ldb, prepare_commit);
+ if (module == NULL) {
+ return LDB_SUCCESS;
+ }
+
+ status = module->ops->prepare_commit(module);
+ if (status != LDB_SUCCESS) {
+ /* if a module fails the prepare then we need
+ to call the end transaction for everyone */
+ FIRST_OP(ldb, end_transaction);
+ module->ops->end_transaction(module);
+ if (ldb->err_string == NULL) {
+ /* no error string was setup by the backend */
+ ldb_asprintf_errstring(ldb,
+ "ldb transaction prepare commit: %s (%d)",
+ ldb_strerror(status),
+ status);
+ }
+ }
+
+ return status;
+}
+
+
+/*
commit a transaction
*/
int ldb_transaction_commit(struct ldb_context *ldb)
@@ -337,6 +397,11 @@ int ldb_transaction_commit(struct ldb_context *ldb)
struct ldb_module *module;
int status;
+ status = ldb_transaction_prepare_commit(ldb);
+ if (status != LDB_SUCCESS) {
+ return status;
+ }
+
ldb->transaction_active--;
ldb_debug(ldb, LDB_DEBUG_TRACE,
@@ -355,10 +420,9 @@ int ldb_transaction_commit(struct ldb_context *ldb)
return LDB_ERR_OPERATIONS_ERROR;
}
- FIRST_OP(ldb, end_transaction);
-
ldb_reset_err_string(ldb);
+ FIRST_OP(ldb, end_transaction);
status = module->ops->end_transaction(module);
if (status != LDB_SUCCESS) {
if (ldb->err_string == NULL) {
@@ -368,10 +432,14 @@ int ldb_transaction_commit(struct ldb_context *ldb)
ldb_strerror(status),
status);
}
+ /* cancel the transaction */
+ FIRST_OP(ldb, del_transaction);
+ module->ops->del_transaction(module);
}
return status;
}
+
/*
cancel a transaction
*/
@@ -393,7 +461,7 @@ int ldb_transaction_cancel(struct ldb_context *ldb)
if (ldb->transaction_active < 0) {
ldb_debug(ldb, LDB_DEBUG_FATAL,
- "commit called but no ldb transactions are active!");
+ "cancel called but no ldb transactions are active!");
ldb->transaction_active = 0;
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -557,6 +625,99 @@ int ldb_request_get_status(struct ldb_request *req)
return req->handle->status;
}
+
+/*
+ trace a ldb request
+*/
+static void ldb_trace_request(struct ldb_context *ldb, struct ldb_request *req)
+{
+ TALLOC_CTX *tmp_ctx = talloc_new(req);
+ int i;
+
+ switch (req->operation) {
+ case LDB_SEARCH:
+ ldb_debug_add(ldb, "ldb_trace_request: SEARCH\n");
+ ldb_debug_add(ldb, " dn: %s\n",
+ ldb_dn_is_null(req->op.search.base)?"<rootDSE>":
+ ldb_dn_get_linearized(req->op.search.base));
+ ldb_debug_add(ldb, " scope: %s\n",
+ req->op.search.scope==LDB_SCOPE_BASE?"base":
+ req->op.search.scope==LDB_SCOPE_ONELEVEL?"one":
+ req->op.search.scope==LDB_SCOPE_SUBTREE?"sub":"UNKNOWN");
+ ldb_debug_add(ldb, " expr: %s\n",
+ ldb_filter_from_tree(tmp_ctx, req->op.search.tree));
+ if (req->op.search.attrs == NULL) {
+ ldb_debug_add(ldb, " attr: <ALL>\n");
+ } else {
+ for (i=0; req->op.search.attrs[i]; i++) {
+ ldb_debug_add(ldb, " attr: %s\n", req->op.search.attrs[i]);
+ }
+ }
+ break;
+ case LDB_DELETE:
+ ldb_debug_add(ldb, "ldb_trace_request: DELETE\n");
+ ldb_debug_add(ldb, " dn: %s\n",
+ ldb_dn_get_linearized(req->op.del.dn));
+ break;
+ case LDB_RENAME:
+ ldb_debug_add(ldb, "ldb_trace_request: RENAME\n");
+ ldb_debug_add(ldb, " olddn: %s\n",
+ ldb_dn_get_linearized(req->op.rename.olddn));
+ ldb_debug_add(ldb, " newdn: %s\n",
+ ldb_dn_get_linearized(req->op.rename.newdn));
+ break;
+ case LDB_EXTENDED:
+ ldb_debug_add(ldb, "ldb_trace_request: EXTENDED\n");
+ ldb_debug_add(ldb, " oid: %s\n", req->op.extended.oid);
+ ldb_debug_add(ldb, " data: %s\n", req->op.extended.data?"yes":"no");
+ break;
+ case LDB_ADD:
+ ldb_debug_add(ldb, "ldb_trace_request: ADD\n");
+ ldb_debug_add(req->handle->ldb, "%s\n",
+ ldb_ldif_message_string(req->handle->ldb, tmp_ctx,
+ LDB_CHANGETYPE_ADD,
+ req->op.add.message));
+ break;
+ case LDB_MODIFY:
+ ldb_debug_add(ldb, "ldb_trace_request: MODIFY\n");
+ ldb_debug_add(req->handle->ldb, "%s\n",
+ ldb_ldif_message_string(req->handle->ldb, tmp_ctx,
+ LDB_CHANGETYPE_ADD,
+ req->op.mod.message));
+ break;
+ case LDB_REQ_REGISTER_CONTROL:
+ ldb_debug_add(ldb, "ldb_trace_request: REGISTER_CONTROL\n");
+ ldb_debug_add(req->handle->ldb, "%s\n",
+ req->op.reg_control.oid);
+ break;
+ case LDB_REQ_REGISTER_PARTITION:
+ ldb_debug_add(ldb, "ldb_trace_request: REGISTER_PARTITION\n");
+ ldb_debug_add(req->handle->ldb, "%s\n",
+ ldb_dn_get_linearized(req->op.reg_partition.dn));
+ break;
+ default:
+ ldb_debug_add(ldb, "ldb_trace_request: UNKNOWN(%u)\n",
+ req->operation);
+ break;
+ }
+
+ if (req->controls == NULL) {
+ ldb_debug_add(ldb, " control: <NONE>\n");
+ } else {
+ for (i=0; req->controls && req->controls[i]; i++) {
+ ldb_debug_add(ldb, " control: %s crit:%u data:%s\n",
+ req->controls[i]->oid,
+ req->controls[i]->critical,
+ req->controls[i]->data?"yes":"no");
+ }
+ }
+
+ ldb_debug_end(ldb, LDB_DEBUG_TRACE);
+
+ talloc_free(tmp_ctx);
+}
+
+
/*
start an ldb request
NOTE: the request must be a talloc context.
@@ -574,6 +735,10 @@ int ldb_request(struct ldb_context *ldb, struct ldb_request *req)
ldb_reset_err_string(ldb);
+ if (ldb->flags & LDB_FLG_ENABLE_TRACING) {
+ ldb_trace_request(ldb, req);
+ }
+
/* call the first module in the chain */
switch (req->operation) {
case LDB_SEARCH:
@@ -677,10 +842,12 @@ int ldb_search_default_callback(struct ldb_request *req,
/* this is the last message, and means the request is done */
/* we have to signal and eventual ldb_wait() waiting that the
* async request operation was completed */
+ talloc_free(ares);
return ldb_request_done(req, LDB_SUCCESS);
}
talloc_free(ares);
+
return LDB_SUCCESS;
}
@@ -758,6 +925,10 @@ int ldb_build_search_req_ex(struct ldb_request **ret_req,
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (parent) {
+ req->handle->nesting++;
+ }
+
*ret_req = req;
return LDB_SUCCESS;
}
@@ -825,6 +996,10 @@ int ldb_build_add_req(struct ldb_request **ret_req,
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (parent) {
+ req->handle->nesting++;
+ }
+
*ret_req = req;
return LDB_SUCCESS;
@@ -863,6 +1038,10 @@ int ldb_build_mod_req(struct ldb_request **ret_req,
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (parent) {
+ req->handle->nesting++;
+ }
+
*ret_req = req;
return LDB_SUCCESS;
@@ -901,6 +1080,10 @@ int ldb_build_del_req(struct ldb_request **ret_req,
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (parent) {
+ req->handle->nesting++;
+ }
+
*ret_req = req;
return LDB_SUCCESS;
@@ -941,6 +1124,10 @@ int ldb_build_rename_req(struct ldb_request **ret_req,
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (parent) {
+ req->handle->nesting++;
+ }
+
*ret_req = req;
return LDB_SUCCESS;
@@ -1010,6 +1197,10 @@ int ldb_build_extended_req(struct ldb_request **ret_req,
return LDB_ERR_OPERATIONS_ERROR;
}
+ if (parent) {
+ req->handle->nesting++;
+ }
+
*ret_req = req;
return LDB_SUCCESS;
@@ -1430,3 +1621,21 @@ void *ldb_get_opaque(struct ldb_context *ldb, const char *name)
}
return NULL;
}
+
+int ldb_global_init(void)
+{
+ /* Provided for compatibility with some older versions of ldb */
+ return 0;
+}
+
+/* return the ldb flags */
+unsigned int ldb_get_flags(struct ldb_context *ldb)
+{
+ return ldb->flags;
+}
+
+/* set the ldb flags */
+void ldb_set_flags(struct ldb_context *ldb, unsigned flags)
+{
+ ldb->flags = flags;
+}
diff --git a/source4/lib/ldb/common/ldb_attributes.c b/source4/lib/ldb/common/ldb_attributes.c
index 9fa0fb2ccd..79c5dd69de 100644
--- a/source4/lib/ldb/common/ldb_attributes.c
+++ b/source4/lib/ldb/common/ldb_attributes.c
@@ -118,8 +118,9 @@ static const struct ldb_schema_attribute ldb_attribute_default = {
/*
return the attribute handlers for a given attribute
*/
-const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb,
- const char *name)
+static const struct ldb_schema_attribute *ldb_schema_attribute_by_name_internal(
+ struct ldb_context *ldb,
+ const char *name)
{
int i, e, b = 0, r;
const struct ldb_schema_attribute *def = &ldb_attribute_default;
@@ -152,6 +153,25 @@ const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_conte
return def;
}
+/*
+ return the attribute handlers for a given attribute
+*/
+const struct ldb_schema_attribute *ldb_schema_attribute_by_name(struct ldb_context *ldb,
+ const char *name)
+{
+ if (ldb->schema.attribute_handler_override) {
+ const struct ldb_schema_attribute *ret =
+ ldb->schema.attribute_handler_override(ldb,
+ ldb->schema.attribute_handler_override_private,
+ name);
+ if (ret) {
+ return ret;
+ }
+ }
+
+ return ldb_schema_attribute_by_name_internal(ldb, name);
+}
+
/*
add to the list of ldif handlers for this ldb context
@@ -161,7 +181,7 @@ void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name)
const struct ldb_schema_attribute *a;
int i;
- a = ldb_schema_attribute_by_name(ldb, name);
+ a = ldb_schema_attribute_by_name_internal(ldb, name);
if (a == NULL || a->name == NULL) {
return;
}
@@ -273,3 +293,14 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c
return NULL;
}
+/*
+ set an attribute handler override function - used to delegate schema handling
+ to external code
+ */
+void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb,
+ ldb_attribute_handler_override_fn_t override,
+ void *private_data)
+{
+ ldb->schema.attribute_handler_override_private = private_data;
+ ldb->schema.attribute_handler_override = override;
+}
diff --git a/source4/lib/ldb/common/ldb_controls.c b/source4/lib/ldb/common/ldb_controls.c
index 0c587e0905..b38373ec12 100644
--- a/source4/lib/ldb/common/ldb_controls.c
+++ b/source4/lib/ldb/common/ldb_controls.c
@@ -39,7 +39,6 @@ struct ldb_control *ldb_request_get_control(struct ldb_request *req, const char
{
int i;
- /* check if there's a paged request control */
if (req->controls != NULL) {
for (i = 0; req->controls[i]; i++) {
if (strcmp(oid, req->controls[i]->oid) == 0) {
@@ -59,7 +58,6 @@ struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid
{
int i;
- /* check if there's a paged request control */
if (rep->controls != NULL) {
for (i = 0; rep->controls[i]; i++) {
if (strcmp(oid, rep->controls[i]->oid) == 0) {
@@ -75,7 +73,7 @@ struct ldb_control *ldb_reply_get_control(struct ldb_reply *rep, const char *oid
/* saves the current controls list into the "saver" and replace the one in req with a new one excluding
the "exclude" control */
-/* returns False on error */
+/* returns 0 on error */
int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver)
{
struct ldb_control **lcs;
@@ -129,7 +127,13 @@ int ldb_request_add_control(struct ldb_request *req, const char *oid, bool criti
struct ldb_control **ctrls;
struct ldb_control *ctrl;
- for (n=0; req->controls && req->controls[n];) { n++; }
+ for (n=0; req->controls && req->controls[n];) {
+ /* having two controls of the same OID makes no sense */
+ if (strcmp(oid, req->controls[n]->oid) == 0) {
+ return LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS;
+ }
+ n++;
+ }
ctrls = talloc_realloc(req, req->controls,
struct ldb_control *,
@@ -557,6 +561,60 @@ struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, void *me
continue;
}
+ if (strncmp(control_strings[i], "show_deactivated_link:", 22) == 0) {
+ const char *p;
+ int crit, ret;
+
+ p = &(control_strings[i][22]);
+ ret = sscanf(p, "%d", &crit);
+ if ((ret != 1) || (crit < 0) || (crit > 1)) {
+ error_string = talloc_asprintf(mem_ctx, "invalid show_deactivated_link control syntax\n");
+ error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
+ error_string = talloc_asprintf_append(error_string, " note: b = boolean");
+ ldb_set_errstring(ldb, error_string);
+ talloc_free(error_string);
+ return NULL;
+ }
+
+ ctrl[i] = talloc(ctrl, struct ldb_control);
+ if (!ctrl[i]) {
+ ldb_oom(ldb);
+ return NULL;
+ }
+ ctrl[i]->oid = LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID;
+ ctrl[i]->critical = crit;
+ ctrl[i]->data = NULL;
+
+ continue;
+ }
+
+ if (strncmp(control_strings[i], "show_recycled:", 14) == 0) {
+ const char *p;
+ int crit, ret;
+
+ p = &(control_strings[i][14]);
+ ret = sscanf(p, "%d", &crit);
+ if ((ret != 1) || (crit < 0) || (crit > 1)) {
+ error_string = talloc_asprintf(mem_ctx, "invalid show_recycled control syntax\n");
+ error_string = talloc_asprintf_append(error_string, " syntax: crit(b)\n");
+ error_string = talloc_asprintf_append(error_string, " note: b = boolean");
+ ldb_set_errstring(ldb, error_string);
+ talloc_free(error_string);
+ return NULL;
+ }
+
+ ctrl[i] = talloc(ctrl, struct ldb_control);
+ if (!ctrl[i]) {
+ ldb_oom(ldb);
+ return NULL;
+ }
+ ctrl[i]->oid = LDB_CONTROL_SHOW_RECYCLED_OID;
+ ctrl[i]->critical = crit;
+ ctrl[i]->data = NULL;
+
+ continue;
+ }
+
if (strncmp(control_strings[i], "permissive_modify:", 18) == 0) {
const char *p;
int crit, ret;
diff --git a/source4/lib/ldb/common/ldb_debug.c b/source4/lib/ldb/common/ldb_debug.c
index f8009eb8a3..6aa58ccf71 100644
--- a/source4/lib/ldb/common/ldb_debug.c
+++ b/source4/lib/ldb/common/ldb_debug.c
@@ -56,9 +56,19 @@ static void ldb_debug_stderr(void *context, enum ldb_debug_level level,
{
if (level <= LDB_DEBUG_WARNING) {
vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
}
}
+static void ldb_debug_stderr_all(void *context, enum ldb_debug_level level,
+ const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
+static void ldb_debug_stderr_all(void *context, enum ldb_debug_level level,
+ const char *fmt, va_list ap)
+{
+ vfprintf(stderr, fmt, ap);
+ fprintf(stderr, "\n");
+}
+
/*
convenience function to setup debug messages on stderr
messages of level LDB_DEBUG_WARNING and higher are printed
@@ -75,13 +85,42 @@ void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *
{
va_list ap;
if (ldb->debug_ops.debug == NULL) {
- ldb_set_debug_stderr(ldb);
+ if (ldb->flags & LDB_FLG_ENABLE_TRACING) {
+ ldb_set_debug(ldb, ldb_debug_stderr_all, ldb);
+ } else {
+ ldb_set_debug_stderr(ldb);
+ }
}
va_start(ap, fmt);
ldb->debug_ops.debug(ldb->debug_ops.context, level, fmt, ap);
va_end(ap);
}
+/*
+ add to an accumulated log message
+ */
+void ldb_debug_add(struct ldb_context *ldb, const char *fmt, ...)
+{
+ va_list ap;
+ va_start(ap, fmt);
+ if (ldb->partial_debug == NULL) {
+ ldb->partial_debug = talloc_vasprintf(ldb, fmt, ap);
+ } else {
+ ldb->partial_debug = talloc_vasprintf_append(ldb->partial_debug,
+ fmt, ap);
+ }
+ va_end(ap);
+}
+
+/*
+ send the accumulated log message, and free it
+ */
+void ldb_debug_end(struct ldb_context *ldb, enum ldb_debug_level level)
+{
+ ldb_debug(ldb, level, "%s", ldb->partial_debug);
+ talloc_free(ldb->partial_debug);
+ ldb->partial_debug = NULL;
+}
/*
log a message, and set the ldb error string to the same message
diff --git a/source4/lib/ldb/common/ldb_dn.c b/source4/lib/ldb/common/ldb_dn.c
index 402d629501..12a513fc42 100644
--- a/source4/lib/ldb/common/ldb_dn.c
+++ b/source4/lib/ldb/common/ldb_dn.c
@@ -1,4 +1,4 @@
-/*
+/*
ldb database library
Copyright (C) Simo Sorce 2005
@@ -6,7 +6,7 @@
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
** under the LGPL
-
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
@@ -52,7 +52,7 @@ struct ldb_dn_component {
struct ldb_val cf_value;
};
-struct ldb_dn_extended_component {
+struct ldb_dn_ext_component {
char *name;
struct ldb_val value;
@@ -69,37 +69,48 @@ struct ldb_dn {
bool valid_case;
char *linearized;
- char *extended_linearized;
+ char *ext_linearized;
char *casefold;
unsigned int comp_num;
struct ldb_dn_component *components;
- unsigned int extended_comp_num;
- struct ldb_dn_extended_component *extended_components;
+ unsigned int ext_comp_num;
+ struct ldb_dn_ext_component *ext_components;
};
/* strdn may be NULL */
-struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const struct ldb_val *strdn)
+struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx,
+ struct ldb_context *ldb,
+ const struct ldb_val *strdn)
{
struct ldb_dn *dn;
if (! ldb) return NULL;
+ if (strdn && strdn->data
+ && (strlen((const char*)strdn->data) != strdn->length)) {
+ /* The RDN must not contain a character with value 0x0 */
+ return NULL;
+ }
+
dn = talloc_zero(mem_ctx, struct ldb_dn);
LDB_DN_NULL_FAILED(dn);
dn->ldb = ldb;
if (strdn->data && strdn->length) {
- if (strdn->data[0] == '@') {
+ const char *data = (const char *)strdn->data;
+ size_t length = strdn->length;
+
+ if (data[0] == '@') {
dn->special = true;
- }
- dn->extended_linearized = talloc_strndup(dn, (const char *)strdn->data, strdn->length);
- LDB_DN_NULL_FAILED(dn->extended_linearized);
-
- if (strdn->data[0] == '<') {
- const char *p_save, *p = dn->extended_linearized;
+ }
+ dn->ext_linearized = talloc_strndup(dn, data, length);
+ LDB_DN_NULL_FAILED(dn->ext_linearized);
+
+ if (data[0] == '<') {
+ const char *p_save, *p = dn->ext_linearized;
do {
p_save = p;
p = strstr(p, ">;");
@@ -107,16 +118,16 @@ struct ldb_dn *ldb_dn_from_ldb_val(void *mem_ctx, struct ldb_context *ldb, const
p = p + 2;
}
} while (p);
-
- if (p_save == dn->extended_linearized) {
+
+ if (p_save == dn->ext_linearized) {
dn->linearized = talloc_strdup(dn, "");
} else {
dn->linearized = talloc_strdup(dn, p_save);
}
LDB_DN_NULL_FAILED(dn->linearized);
} else {
- dn->linearized = dn->extended_linearized;
- dn->extended_linearized = NULL;
+ dn->linearized = dn->ext_linearized;
+ dn->ext_linearized = NULL;
}
} else {
dn->linearized = talloc_strdup(dn, "");
@@ -131,7 +142,9 @@ failed:
}
/* strdn may be NULL */
-struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *strdn)
+struct ldb_dn *ldb_dn_new(void *mem_ctx,
+ struct ldb_context *ldb,
+ const char *strdn)
{
struct ldb_val blob;
blob.data = strdn;
@@ -139,7 +152,9 @@ struct ldb_dn *ldb_dn_new(void *mem_ctx, struct ldb_context *ldb, const char *st
return ldb_dn_from_ldb_val(mem_ctx, ldb, &blob);
}
-struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char *new_fmt, ...)
+struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx,
+ struct ldb_context *ldb,
+ const char *new_fmt, ...)
{
char *strdn;
va_list ap;
@@ -155,7 +170,7 @@ struct ldb_dn *ldb_dn_new_fmt(void *mem_ctx, struct ldb_context *ldb, const char
talloc_free(strdn);
return dn;
}
-
+
return NULL;
}
@@ -175,7 +190,8 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len)
if (p - src == len) /* found no escapable chars */
break;
- memcpy(d, s, p - s); /* copy the part of the string before the stop */
+ /* copy the part of the string before the stop */
+ memcpy(d, s, p - s);
d += (p - s); /* move to current position */
if (*p) { /* it is a normal escapable character */
@@ -195,7 +211,7 @@ static int ldb_dn_escape_internal(char *dst, const char *src, int len)
/* return the length of the resulting string */
return (l + (d - dst));
-}
+}
char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
{
@@ -221,6 +237,9 @@ char *ldb_dn_escape_value(void *mem_ctx, struct ldb_val value)
/*
explode a DN string into a ldb_dn structure
based on RFC4514 except that we don't support multiple valued RDNs
+
+ TODO: according to MS-ADTS:3.1.1.5.2 Naming Constraints
+ DN must be compliant with RFC2253
*/
static bool ldb_dn_explode(struct ldb_dn *dn)
{
@@ -244,8 +263,8 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
return true;
}
- if (dn->extended_linearized) {
- parse_dn = dn->extended_linearized;
+ if (dn->ext_linearized) {
+ parse_dn = dn->ext_linearized;
} else {
parse_dn = dn->linearized;
}
@@ -254,6 +273,11 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
return false;
}
+ /* The RDN size must be less than 255 characters */
+ if (strlen(parse_dn) > 255) {
+ return false;
+ }
+
/* Empty DNs */
if (parse_dn[0] == '\0') {
return true;
@@ -267,11 +291,11 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
/* make sure we free this if alloced previously before replacing */
talloc_free(dn->components);
- talloc_free(dn->extended_components);
- dn->extended_components = NULL;
+ talloc_free(dn->ext_components);
+ dn->ext_components = NULL;
/* in the common case we have 3 or more components */
- /* make sure all components are zeroed, other functions depend on this */
+ /* make sure all components are zeroed, other functions depend on it */
dn->components = talloc_zero_array(dn, struct ldb_dn_component, 3);
if ( ! dn->components) {
return false;
@@ -313,7 +337,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
continue;
}
}
-
+
if (in_ex_name && *p == '=') {
*d++ = '\0';
p++;
@@ -324,46 +348,46 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
}
if (in_ex_value && *p == '>') {
- const struct ldb_dn_extended_syntax *extended_syntax;
+ const struct ldb_dn_extended_syntax *ext_syntax;
struct ldb_val ex_val = {
- .data = ex_value,
+ .data = (uint8_t *)ex_value,
.length = d - ex_value
};
-
+
*d++ = '\0';
p++;
in_ex_value = false;
/* Process name and ex_value */
- dn->extended_components = talloc_realloc(dn,
- dn->extended_components,
- struct ldb_dn_extended_component,
- dn->extended_comp_num + 1);
- if ( ! dn->extended_components) {
+ dn->ext_components = talloc_realloc(dn,
+ dn->ext_components,
+ struct ldb_dn_ext_component,
+ dn->ext_comp_num + 1);
+ if ( ! dn->ext_components) {
/* ouch ! */
goto failed;
}
- extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name);
- if (!extended_syntax) {
+ ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, ex_name);
+ if (!ext_syntax) {
/* We don't know about this type of extended DN */
goto failed;
}
- dn->extended_components[dn->extended_comp_num].name = talloc_strdup(dn->extended_components, ex_name);
- if (!dn->extended_components[dn->extended_comp_num].name) {
+ dn->ext_components[dn->ext_comp_num].name = talloc_strdup(dn->ext_components, ex_name);
+ if (!dn->ext_components[dn->ext_comp_num].name) {
/* ouch */
goto failed;
}
- ret = extended_syntax->read_fn(dn->ldb, dn->extended_components,
- &ex_val, &dn->extended_components[dn->extended_comp_num].value);
+ ret = ext_syntax->read_fn(dn->ldb, dn->ext_components,
+ &ex_val, &dn->ext_components[dn->ext_comp_num].value);
if (ret != LDB_SUCCESS) {
dn->invalid = true;
goto failed;
}
- dn->extended_comp_num++;
+ dn->ext_comp_num++;
if (*p == '\0') {
/* We have reached the end (extended component only)! */
@@ -402,12 +426,14 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
is_oid = true;
} else
if ( ! isalpha(*p)) {
- /* not a digit nor an alpha, invalid attribute name */
+ /* not a digit nor an alpha,
+ * invalid attribute name */
dn->invalid = true;
goto failed;
}
-
- /* Copy this character across from parse_dn, now we have trimmed out spaces */
+
+ /* Copy this character across from parse_dn,
+ * now we have trimmed out spaces */
*d++ = *p++;
continue;
}
@@ -420,7 +446,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
}
if (trim && (*p != '=')) {
- /* spaces/tabs are not allowed in attribute names */
+ /* spaces/tabs are not allowed */
dn->invalid = true;
goto failed;
}
@@ -432,7 +458,9 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
trim = true;
l = 0;
- /* Terminate this string in d (which is a copy of parse_dn with spaces trimmed) */
+ /* Terminate this string in d
+ * (which is a copy of parse_dn
+ * with spaces trimmed) */
*d++ = '\0';
dn->components[dn->comp_num].name = talloc_strdup(dn->components, dt);
if ( ! dn->components[dn->comp_num].name) {
@@ -453,7 +481,8 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
}
if (is_oid && ( ! (isdigit(*p) || (*p == '.')))) {
- /* not a digit nor a dot, invalid attribute oid */
+ /* not a digit nor a dot,
+ * invalid attribute oid */
dn->invalid = true;
goto failed;
} else
@@ -601,7 +630,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
break;
}
- if (*p == ' ') {
+ if (*p == ' ') {
if ( ! t) t = p;
} else {
if ( t ) t = NULL;
@@ -609,7 +638,7 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
*d++ = *p++;
l++;
-
+
break;
}
@@ -630,9 +659,9 @@ static bool ldb_dn_explode(struct ldb_dn *dn)
}
*d++ = '\0';
- dn->components[dn->comp_num].value.data = (uint8_t *)talloc_strdup(dn->components, dt);
dn->components[dn->comp_num].value.length = l;
-
+ dn->components[dn->comp_num].value.data =
+ (uint8_t *)talloc_strdup(dn->components, dt);
if ( ! dn->components[dn->comp_num].value.data) {
/* ouch */
goto failed;
@@ -676,8 +705,10 @@ const char *ldb_dn_get_linearized(struct ldb_dn *dn)
/* calculate maximum possible length of DN */
for (len = 0, i = 0; i < dn->comp_num; i++) {
- len += strlen(dn->components[i].name); /* name len */
- len += (dn->components[i].value.length * 3); /* max escaped data len */
+ /* name len */
+ len += strlen(dn->components[i].name);
+ /* max escaped data len */
+ len += (dn->components[i].value.length * 3);
len += 2; /* '=' and ',' */
}
dn->linearized = talloc_array(dn, char, len);
@@ -703,7 +734,8 @@ const char *ldb_dn_get_linearized(struct ldb_dn *dn)
*(--d) = '\0';
/* don't waste more memory than necessary */
- dn->linearized = talloc_realloc(dn, dn->linearized, char, (d - dn->linearized + 1));
+ dn->linearized = talloc_realloc(dn, dn->linearized,
+ char, (d - dn->linearized + 1));
return dn->linearized;
}
@@ -721,27 +753,26 @@ char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
if (!ldb_dn_has_extended(dn)) {
return talloc_strdup(mem_ctx, linearized);
}
-
+
if (!ldb_dn_validate(dn)) {
return NULL;
}
- for (i=0; i < dn->extended_comp_num; i++) {
+ for (i = 0; i < dn->ext_comp_num; i++) {
+ const struct ldb_dn_extended_syntax *ext_syntax;
+ const char *name = dn->ext_components[i].name;
+ struct ldb_val ec_val = dn->ext_components[i].value;
struct ldb_val val;
int ret;
- const struct ldb_dn_extended_syntax *extended_syntax;
- const char *name = dn->extended_components[i].name;
-
- extended_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
+
+ ext_syntax = ldb_dn_extended_syntax_by_name(dn->ldb, name);
if (mode == 1) {
- ret = extended_syntax->write_clear_fn(dn->ldb, mem_ctx,
- &dn->extended_components[i].value,
- &val);
+ ret = ext_syntax->write_clear_fn(dn->ldb, mem_ctx,
+ &ec_val, &val);
} else if (mode == 0) {
- ret = extended_syntax->write_hex_fn(dn->ldb, mem_ctx,
- &dn->extended_components[i].value,
- &val);
+ ret = ext_syntax->write_hex_fn(dn->ldb, mem_ctx,
+ &ec_val, &val);
} else {
ret = -1;
}
@@ -751,9 +782,11 @@ char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
}
if (i == 0) {
- p = talloc_asprintf(mem_ctx, "<%s=%s>", dn->extended_components[i].name, val.data);
+ p = talloc_asprintf(mem_ctx, "<%s=%s>",
+ name, val.data);
} else {
- p = talloc_asprintf_append(p, ";<%s=%s>", dn->extended_components[i].name, val.data);
+ p = talloc_asprintf_append(p, ";<%s=%s>",
+ name, val.data);
}
talloc_free(val.data);
@@ -763,7 +796,7 @@ char *ldb_dn_get_extended_linearized(void *mem_ctx, struct ldb_dn *dn, int mode)
}
}
- if (dn->extended_comp_num && *linearized) {
+ if (dn->ext_comp_num && *linearized) {
p = talloc_asprintf_append(p, ";%s", linearized);
}
@@ -782,7 +815,7 @@ char *ldb_dn_alloc_linearized(void *mem_ctx, struct ldb_dn *dn)
}
/*
- casefold a dn. We need to casefold the attribute names, and canonicalize
+ casefold a dn. We need to casefold the attribute names, and canonicalize
attribute values of case insensitive attributes.
*/
@@ -801,12 +834,16 @@ static bool ldb_dn_casefold_internal(struct ldb_dn *dn)
for (i = 0; i < dn->comp_num; i++) {
const struct ldb_schema_attribute *a;
- dn->components[i].cf_name = ldb_attr_casefold(dn->components, dn->components[i].name);
+ dn->components[i].cf_name =
+ ldb_attr_casefold(dn->components,
+ dn->components[i].name);
if (!dn->components[i].cf_name) {
goto failed;
}
- a = ldb_schema_attribute_by_name(dn->ldb, dn->components[i].cf_name);
+ a = ldb_schema_attribute_by_name(dn->ldb,
+ dn->components[i].cf_name);
+
ret = a->syntax->canonicalise_fn(dn->ldb, dn->components,
&(dn->components[i].value),
&(dn->components[i].cf_value));
@@ -834,7 +871,7 @@ const char *ldb_dn_get_casefold(struct ldb_dn *dn)
if (dn->casefold) return dn->casefold;
- if (dn->special) {
+ if (dn->special) {
dn->casefold = talloc_strdup(dn, dn->linearized);
if (!dn->casefold) return NULL;
dn->valid_case = true;
@@ -846,20 +883,16 @@ const char *ldb_dn_get_casefold(struct ldb_dn *dn)
}
if (dn->comp_num == 0) {
- if (dn->linearized && dn->linearized[0] == '\0') {
- /* hmm a NULL dn, should we faild casefolding ? */
- dn->casefold = talloc_strdup(dn, "");
- return dn->casefold;
- }
- /* A DN must be NULL, special, or have components */
- dn->invalid = true;
- return NULL;
+ dn->casefold = talloc_strdup(dn, "");
+ return dn->casefold;
}
/* calculate maximum possible length of DN */
for (len = 0, i = 0; i < dn->comp_num; i++) {
- len += strlen(dn->components[i].cf_name); /* name len */
- len += (dn->components[i].cf_value.length * 3); /* max escaped data len */
+ /* name len */
+ len += strlen(dn->components[i].cf_name);
+ /* max escaped data len */
+ len += (dn->components[i].cf_value.length * 3);
len += 2; /* '=' and ',' */
}
dn->casefold = talloc_array(dn, char, len);
@@ -884,7 +917,8 @@ const char *ldb_dn_get_casefold(struct ldb_dn *dn)
*(--d) = '\0';
/* don't waste more memory than necessary */
- dn->casefold = talloc_realloc(dn, dn->casefold, char, strlen(dn->casefold) + 1);
+ dn->casefold = talloc_realloc(dn, dn->casefold,
+ char, strlen(dn->casefold) + 1);
return dn->casefold;
}
@@ -913,8 +947,13 @@ int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
* we will avoid exploding and casfolding */
int dif;
dif = strlen(dn->linearized) - strlen(base->linearized);
- if (dif < 0) return dif;
- if (strcmp(base->linearized, &dn->linearized[dif]) == 0) return 0;
+ if (dif < 0) {
+ return dif;
+ }
+ if (strcmp(base->linearized,
+ &dn->linearized[dif]) == 0) {
+ return 0;
+ }
}
if ( ! ldb_dn_casefold_internal(base)) {
@@ -949,15 +988,24 @@ int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
n_dn = dn->comp_num - 1;
while (n_base >= 0) {
+ char *b_name = base->components[n_base].cf_name;
+ char *dn_name = dn->components[n_dn].cf_name;
+
+ char *b_vdata = (char *)base->components[n_base].cf_value.data;
+ char *dn_vdata = (char *)dn->components[n_dn].cf_value.data;
+
+ size_t b_vlen = base->components[n_base].cf_value.length;
+ size_t dn_vlen = dn->components[n_dn].cf_value.length;
+
/* compare attr names */
- ret = strcmp(base->components[n_base].cf_name, dn->components[n_dn].cf_name);
+ ret = strcmp(b_name, dn_name);
if (ret != 0) return ret;
- /* compare attr.cf_value. */
- if (base->components[n_base].cf_value.length != dn->components[n_dn].cf_value.length) {
- return base->components[n_base].cf_value.length - dn->components[n_dn].cf_value.length;
+ /* compare attr.cf_value. */
+ if (b_vlen != dn_vlen) {
+ return b_vlen - dn_vlen;
}
- ret = strcmp((char *)base->components[n_base].cf_value.data, (char *)dn->components[n_dn].cf_value.data);
+ ret = strcmp(b_vdata, dn_vdata);
if (ret != 0) return ret;
n_base--;
@@ -967,7 +1015,7 @@ int ldb_dn_compare_base(struct ldb_dn *base, struct ldb_dn *dn)
return 0;
}
-/* compare DNs using casefolding compare functions.
+/* compare DNs using casefolding compare functions.
If they match, then return 0
*/
@@ -976,13 +1024,17 @@ int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
{
int i, ret;
- if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) return -1;
+ if (( ! dn0) || dn0->invalid || ! dn1 || dn1->invalid) {
+ return -1;
+ }
if (( ! dn0->valid_case) || ( ! dn1->valid_case)) {
if (dn0->linearized && dn1->linearized) {
/* try with a normal compare first, if we are lucky
* we will avoid exploding and casfolding */
- if (strcmp(dn0->linearized, dn1->linearized) == 0) return 0;
+ if (strcmp(dn0->linearized, dn1->linearized) == 0) {
+ return 0;
+ }
}
if ( ! ldb_dn_casefold_internal(dn0)) {
@@ -1012,22 +1064,37 @@ int ldb_dn_compare(struct ldb_dn *dn0, struct ldb_dn *dn1)
}
for (i = 0; i < dn0->comp_num; i++) {
+ char *dn0_name = dn0->components[i].cf_name;
+ char *dn1_name = dn1->components[i].cf_name;
+
+ char *dn0_vdata = (char *)dn0->components[i].cf_value.data;
+ char *dn1_vdata = (char *)dn1->components[i].cf_value.data;
+
+ size_t dn0_vlen = dn0->components[i].cf_value.length;
+ size_t dn1_vlen = dn1->components[i].cf_value.length;
+
/* compare attr names */
- ret = strcmp(dn0->components[i].cf_name, dn1->components[i].cf_name);
- if (ret != 0) return ret;
+ ret = strcmp(dn0_name, dn1_name);
+ if (ret != 0) {
+ return ret;
+ }
- /* compare attr.cf_value. */
- if (dn0->components[i].cf_value.length != dn1->components[i].cf_value.length) {
- return dn0->components[i].cf_value.length - dn1->components[i].cf_value.length;
+ /* compare attr.cf_value. */
+ if (dn0_vlen != dn1_vlen) {
+ return dn0_vlen - dn1_vlen;
+ }
+ ret = strcmp(dn0_vdata, dn1_vdata);
+ if (ret != 0) {
+ return ret;
}
- ret = strcmp((char *)dn0->components[i].cf_value.data, (char *)dn1->components[i].cf_value.data);
- if (ret != 0) return ret;
}
return 0;
}
-static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_dn_component *src)
+static struct ldb_dn_component ldb_dn_copy_component(
+ void *mem_ctx,
+ struct ldb_dn_component *src)
{
struct ldb_dn_component dst;
@@ -1071,9 +1138,11 @@ static struct ldb_dn_component ldb_dn_copy_component(void *mem_ctx, struct ldb_d
return dst;
}
-static struct ldb_dn_extended_component ldb_dn_extended_copy_component(void *mem_ctx, struct ldb_dn_extended_component *src)
+static struct ldb_dn_ext_component ldb_dn_ext_copy_component(
+ void *mem_ctx,
+ struct ldb_dn_ext_component *src)
{
- struct ldb_dn_extended_component dst;
+ struct ldb_dn_ext_component dst;
memset(&dst, 0, sizeof(dst));
@@ -1113,14 +1182,19 @@ struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
if (dn->components) {
int i;
- new_dn->components = talloc_zero_array(new_dn, struct ldb_dn_component, dn->comp_num);
+ new_dn->components =
+ talloc_zero_array(new_dn,
+ struct ldb_dn_component,
+ dn->comp_num);
if ( ! new_dn->components) {
talloc_free(new_dn);
return NULL;
}
for (i = 0; i < dn->comp_num; i++) {
- new_dn->components[i] = ldb_dn_copy_component(new_dn->components, &dn->components[i]);
+ new_dn->components[i] =
+ ldb_dn_copy_component(new_dn->components,
+ &dn->components[i]);
if ( ! new_dn->components[i].value.data) {
talloc_free(new_dn);
return NULL;
@@ -1128,18 +1202,24 @@ struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
}
}
- if (dn->extended_components) {
+ if (dn->ext_components) {
int i;
- new_dn->extended_components = talloc_zero_array(new_dn, struct ldb_dn_extended_component, dn->extended_comp_num);
- if ( ! new_dn->extended_components) {
+ new_dn->ext_components =
+ talloc_zero_array(new_dn,
+ struct ldb_dn_ext_component,
+ dn->ext_comp_num);
+ if ( ! new_dn->ext_components) {
talloc_free(new_dn);
return NULL;
}
- for (i = 0; i < dn->extended_comp_num; i++) {
- new_dn->extended_components[i] = ldb_dn_extended_copy_component(new_dn->extended_components, &dn->extended_components[i]);
- if ( ! new_dn->extended_components[i].value.data) {
+ for (i = 0; i < dn->ext_comp_num; i++) {
+ new_dn->ext_components[i] =
+ ldb_dn_ext_copy_component(
+ new_dn->ext_components,
+ &dn->ext_components[i]);
+ if ( ! new_dn->ext_components[i].value.data) {
talloc_free(new_dn);
return NULL;
}
@@ -1162,9 +1242,10 @@ struct ldb_dn *ldb_dn_copy(void *mem_ctx, struct ldb_dn *dn)
}
}
- if (dn->extended_linearized) {
- new_dn->extended_linearized = talloc_strdup(new_dn, dn->extended_linearized);
- if ( ! new_dn->extended_linearized) {
+ if (dn->ext_linearized) {
+ new_dn->ext_linearized = talloc_strdup(new_dn,
+ dn->ext_linearized);
+ if ( ! new_dn->ext_linearized) {
talloc_free(new_dn);
return NULL;
}
@@ -1211,7 +1292,9 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
}
for (i = 0; i < base->comp_num; dn->comp_num++, i++) {
- dn->components[dn->comp_num] = ldb_dn_copy_component(dn->components, &base->components[i]);
+ dn->components[dn->comp_num] =
+ ldb_dn_copy_component(dn->components,
+ &base->components[i]);
if (dn->components[dn->comp_num].value.data == NULL) {
dn->invalid = true;
return false;
@@ -1220,7 +1303,8 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
if (dn->casefold && s) {
if (*dn->casefold) {
- t = talloc_asprintf(dn, "%s,%s", dn->casefold, s);
+ t = talloc_asprintf(dn, "%s,%s",
+ dn->casefold, s);
} else {
t = talloc_strdup(dn, s);
}
@@ -1235,9 +1319,10 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
if ( ! s) {
return false;
}
-
+
if (*dn->linearized) {
- t = talloc_asprintf(dn, "%s,%s", dn->linearized, s);
+ t = talloc_asprintf(dn, "%s,%s",
+ dn->linearized, s);
} else {
t = talloc_strdup(dn, s);
}
@@ -1249,13 +1334,14 @@ bool ldb_dn_add_base(struct ldb_dn *dn, struct ldb_dn *base)
dn->linearized = t;
}
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- if (dn->extended_linearized) {
- LDB_FREE(dn->extended_linearized);
+ /* Wipe the ext_linearized DN,
+ * the GUID and SID are almost certainly no longer valid */
+ if (dn->ext_linearized) {
+ LDB_FREE(dn->ext_linearized);
}
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
+ LDB_FREE(dn->ext_components);
+ dn->ext_comp_num = 0;
return true;
}
@@ -1290,7 +1376,7 @@ bool ldb_dn_add_base_fmt(struct ldb_dn *dn, const char *base_fmt, ...)
talloc_free(base_str);
return ret;
-}
+}
/* modify the given dn by adding children elements.
*
@@ -1335,8 +1421,10 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
dn->components[j] = dn->components[i];
}
- for (i = 0; i < child->comp_num; i++) {
- dn->components[i] = ldb_dn_copy_component(dn->components, &child->components[i]);
+ for (i = 0; i < child->comp_num; i++) {
+ dn->components[i] =
+ ldb_dn_copy_component(dn->components,
+ &child->components[i]);
if (dn->components[i].value.data == NULL) {
dn->invalid = true;
return false;
@@ -1358,7 +1446,7 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
if ( ! s) {
return false;
}
-
+
t = talloc_asprintf(dn, "%s,%s", s, dn->linearized);
if ( ! t) {
dn->invalid = true;
@@ -1368,11 +1456,12 @@ bool ldb_dn_add_child(struct ldb_dn *dn, struct ldb_dn *child)
dn->linearized = t;
}
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
+ /* Wipe the ext_linearized DN,
+ * the GUID and SID are almost certainly no longer valid */
+ LDB_FREE(dn->ext_linearized);
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
+ LDB_FREE(dn->ext_components);
+ dn->ext_comp_num = 0;
return true;
}
@@ -1429,7 +1518,7 @@ bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
LDB_FREE(dn->components[dn->comp_num - i].cf_name);
LDB_FREE(dn->components[dn->comp_num - i].cf_value.data);
}
-
+
dn->comp_num -= num;
if (dn->valid_case) {
@@ -1443,11 +1532,12 @@ bool ldb_dn_remove_base_components(struct ldb_dn *dn, unsigned int num)
LDB_FREE(dn->casefold);
LDB_FREE(dn->linearized);
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
+ /* Wipe the ext_linearized DN,
+ * the GUID and SID are almost certainly no longer valid */
+ LDB_FREE(dn->ext_linearized);
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
+ LDB_FREE(dn->ext_components);
+ dn->ext_comp_num = 0;
return true;
}
@@ -1487,11 +1577,12 @@ bool ldb_dn_remove_child_components(struct ldb_dn *dn, unsigned int num)
LDB_FREE(dn->casefold);
LDB_FREE(dn->linearized);
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
+ /* Wipe the ext_linearized DN,
+ * the GUID and SID are almost certainly no longer valid */
+ LDB_FREE(dn->ext_linearized);
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
+ LDB_FREE(dn->ext_components);
+ dn->ext_comp_num = 0;
return true;
}
@@ -1509,11 +1600,12 @@ struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
return NULL;
}
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
+ /* Wipe the ext_linearized DN,
+ * the GUID and SID are almost certainly no longer valid */
+ LDB_FREE(dn->ext_linearized);
- LDB_FREE(dn->extended_components);
- dn->extended_comp_num = 0;
+ LDB_FREE(dn->ext_components);
+ dn->ext_comp_num = 0;
return new_dn;
}
@@ -1522,7 +1614,8 @@ struct ldb_dn *ldb_dn_get_parent(void *mem_ctx, struct ldb_dn *dn)
ie dc=samba,dc=org -> samba.org/
uid=administrator,ou=users,dc=samba,dc=org = samba.org/users/administrator
- There are two formats, the EX format has the last / replaced with a newline (\n).
+ There are two formats,
+ the EX format has the last '/' replaced with a newline (\n).
*/
static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
@@ -1530,7 +1623,7 @@ static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
TALLOC_CTX *tmpctx;
char *cracked = NULL;
const char *format = (ex_format ? "\n" : "/" );
-
+
if ( ! ldb_dn_validate(dn)) {
return NULL;
}
@@ -1544,10 +1637,12 @@ static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
}
if (cracked) {
cracked = talloc_asprintf(tmpctx, "%s.%s",
- ldb_dn_escape_value(tmpctx, dn->components[i].value),
+ ldb_dn_escape_value(tmpctx,
+ dn->components[i].value),
cracked);
} else {
- cracked = ldb_dn_escape_value(tmpctx, dn->components[i].value);
+ cracked = ldb_dn_escape_value(tmpctx,
+ dn->components[i].value);
}
if (!cracked) {
goto done;
@@ -1563,8 +1658,9 @@ static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
/* Now walk backwards appending remaining components */
for (; i > 0; i--) {
- cracked = talloc_asprintf_append_buffer(cracked, "/%s",
- ldb_dn_escape_value(tmpctx, dn->components[i].value));
+ cracked = talloc_asprintf_append_buffer(cracked, "/%s",
+ ldb_dn_escape_value(tmpctx,
+ dn->components[i].value));
if (!cracked) {
goto done;
}
@@ -1572,7 +1668,8 @@ static char *ldb_dn_canonical(void *mem_ctx, struct ldb_dn *dn, int ex_format) {
/* Last one, possibly a newline for the 'ex' format */
cracked = talloc_asprintf_append_buffer(cracked, "%s%s", format,
- ldb_dn_escape_value(tmpctx, dn->components[i].value));
+ ldb_dn_escape_value(tmpctx,
+ dn->components[i].value));
talloc_steal(mem_ctx, cracked);
done:
@@ -1607,7 +1704,8 @@ const char *ldb_dn_get_component_name(struct ldb_dn *dn, unsigned int num)
return dn->components[num].name;
}
-const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn, unsigned int num)
+const struct ldb_val *ldb_dn_get_component_val(struct ldb_dn *dn,
+ unsigned int num)
{
if ( ! ldb_dn_validate(dn)) {
return NULL;
@@ -1634,7 +1732,8 @@ const struct ldb_val *ldb_dn_get_rdn_val(struct ldb_dn *dn)
return &dn->components[0].value;
}
-int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const struct ldb_val val)
+int ldb_dn_set_component(struct ldb_dn *dn, int num,
+ const char *name, const struct ldb_val val)
{
char *n;
struct ldb_val v;
@@ -1675,60 +1774,68 @@ int ldb_dn_set_component(struct ldb_dn *dn, int num, const char *name, const str
LDB_FREE(dn->casefold);
LDB_FREE(dn->linearized);
- /* Wipe the extended_linearized DN, as the GUID and SID are almost certainly no longer valid */
- LDB_FREE(dn->extended_linearized);
+ /* Wipe the ext_linearized DN,
+ * the GUID and SID are almost certainly no longer valid */
+ LDB_FREE(dn->ext_linearized);
- dn->extended_comp_num = 0;
- LDB_FREE(dn->extended_components);
+ dn->ext_comp_num = 0;
+ LDB_FREE(dn->ext_components);
return LDB_SUCCESS;
}
-const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn, const char *name)
+const struct ldb_val *ldb_dn_get_extended_component(struct ldb_dn *dn,
+ const char *name)
{
int i;
if ( ! ldb_dn_validate(dn)) {
return NULL;
}
- for (i=0; i < dn->extended_comp_num; i++) {
- if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
- return &dn->extended_components[i].value;
+ for (i=0; i < dn->ext_comp_num; i++) {
+ if (ldb_attr_cmp(dn->ext_components[i].name, name) == 0) {
+ return &dn->ext_components[i].value;
}
}
return NULL;
}
-int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const struct ldb_val *val)
+int ldb_dn_set_extended_component(struct ldb_dn *dn,
+ const char *name, const struct ldb_val *val)
{
- struct ldb_dn_extended_component *p;
+ struct ldb_dn_ext_component *p;
int i;
-
+
if ( ! ldb_dn_validate(dn)) {
return LDB_ERR_OTHER;
}
- for (i=0; i < dn->extended_comp_num; i++) {
- if (ldb_attr_cmp(dn->extended_components[i].name, name) == 0) {
+ for (i=0; i < dn->ext_comp_num; i++) {
+ if (ldb_attr_cmp(dn->ext_components[i].name, name) == 0) {
if (val) {
- dn->extended_components[i].value = ldb_val_dup(dn->extended_components, val);
+ dn->ext_components[i].value =
+ ldb_val_dup(dn->ext_components, val);
- dn->extended_components[i].name = talloc_strdup(dn->extended_components, name);
- if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
+ dn->ext_components[i].name =
+ talloc_strdup(dn->ext_components, name);
+ if (!dn->ext_components[i].name ||
+ !dn->ext_components[i].value.data) {
dn->invalid = true;
return LDB_ERR_OPERATIONS_ERROR;
}
-
+
} else {
- if (i != (dn->extended_comp_num - 1)) {
- memmove(&dn->extended_components[i], &dn->extended_components[i+1],
- ((dn->extended_comp_num-1) - i)*sizeof(*dn->extended_components));
+ if (i != (dn->ext_comp_num - 1)) {
+ memmove(&dn->ext_components[i],
+ &dn->ext_components[i+1],
+ ((dn->ext_comp_num-1) - i) *
+ sizeof(*dn->ext_components));
}
- dn->extended_comp_num--;
-
- dn->extended_components = talloc_realloc(dn,
- dn->extended_components,
- struct ldb_dn_extended_component,
- dn->extended_comp_num);
- if (!dn->extended_components) {
+ dn->ext_comp_num--;
+
+ dn->ext_components = talloc_realloc(dn,
+ dn->ext_components,
+ struct ldb_dn_ext_component,
+ dn->ext_comp_num);
+ if (!dn->ext_components) {
dn->invalid = true;
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -1737,33 +1844,33 @@ int ldb_dn_set_extended_component(struct ldb_dn *dn, const char *name, const str
}
}
- p = dn->extended_components
+ p = dn->ext_components
= talloc_realloc(dn,
- dn->extended_components,
- struct ldb_dn_extended_component,
- dn->extended_comp_num + 1);
- if (!dn->extended_components) {
+ dn->ext_components,
+ struct ldb_dn_ext_component,
+ dn->ext_comp_num + 1);
+ if (!dn->ext_components) {
dn->invalid = true;
return LDB_ERR_OPERATIONS_ERROR;
}
-
- p[dn->extended_comp_num].value = ldb_val_dup(dn->extended_components, val);
- p[dn->extended_comp_num].name = talloc_strdup(p, name);
-
- if (!dn->extended_components[i].name || !dn->extended_components[i].value.data) {
+
+ p[dn->ext_comp_num].value = ldb_val_dup(dn->ext_components, val);
+ p[dn->ext_comp_num].name = talloc_strdup(p, name);
+
+ if (!dn->ext_components[i].name || !dn->ext_components[i].value.data) {
dn->invalid = true;
return LDB_ERR_OPERATIONS_ERROR;
}
- dn->extended_components = p;
- dn->extended_comp_num++;
-
+ dn->ext_components = p;
+ dn->ext_comp_num++;
+
return LDB_SUCCESS;
}
void ldb_dn_remove_extended_components(struct ldb_dn *dn)
{
- dn->extended_comp_num = 0;
- LDB_FREE(dn->extended_components);
+ dn->ext_comp_num = 0;
+ LDB_FREE(dn->ext_components);
}
bool ldb_dn_is_valid(struct ldb_dn *dn)
@@ -1781,8 +1888,8 @@ bool ldb_dn_is_special(struct ldb_dn *dn)
bool ldb_dn_has_extended(struct ldb_dn *dn)
{
if ( ! dn || dn->invalid) return false;
- if (dn->extended_linearized && (dn->extended_linearized[0] == '<')) return true;
- return dn->extended_comp_num != 0;
+ if (dn->ext_linearized && (dn->ext_linearized[0] == '<')) return true;
+ return dn->ext_comp_num != 0;
}
bool ldb_dn_check_special(struct ldb_dn *dn, const char *check)
diff --git a/source4/lib/ldb/common/ldb_ldif.c b/source4/lib/ldb/common/ldb_ldif.c
index 400fb352ff..b7ab7300b2 100644
--- a/source4/lib/ldb/common/ldb_ldif.c
+++ b/source4/lib/ldb/common/ldb_ldif.c
@@ -185,11 +185,15 @@ char *ldb_base64_encode(void *mem_ctx, const char *buf, int len)
/*
see if a buffer should be base64 encoded
*/
-int ldb_should_b64_encode(const struct ldb_val *val)
+int ldb_should_b64_encode(struct ldb_context *ldb, const struct ldb_val *val)
{
unsigned int i;
uint8_t *p = val->data;
+ if (ldb->flags & LDB_FLG_SHOW_BINARY) {
+ return 0;
+ }
+
if (val->length == 0) {
return 0;
}
@@ -296,7 +300,7 @@ int ldb_ldif_write(struct ldb_context *ldb,
}
}
if (!ldb_changetypes[i].name) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d\n",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Invalid ldif changetype %d",
ldif->changetype);
talloc_free(mem_ctx);
return -1;
@@ -333,7 +337,7 @@ int ldb_ldif_write(struct ldb_context *ldb,
if (ret != LDB_SUCCESS) {
v = msg->elements[i].values[j];
}
- if (ret != LDB_SUCCESS || ldb_should_b64_encode(&v)) {
+ if (ret != LDB_SUCCESS || ldb_should_b64_encode(ldb, &v)) {
ret = fprintf_fn(private_data, "%s:: ",
msg->elements[i].name);
CHECK_RET;
@@ -346,9 +350,14 @@ int ldb_ldif_write(struct ldb_context *ldb,
} else {
ret = fprintf_fn(private_data, "%s: ", msg->elements[i].name);
CHECK_RET;
- ret = fold_string(fprintf_fn, private_data,
- (char *)v.data, v.length,
- strlen(msg->elements[i].name)+2);
+ if (ldb->flags & LDB_FLG_SHOW_BINARY) {
+ ret = fprintf_fn(private_data, "%*.*s",
+ v.length, v.length, (char *)v.data);
+ } else {
+ ret = fold_string(fprintf_fn, private_data,
+ (char *)v.data, v.length,
+ strlen(msg->elements[i].name)+2);
+ }
CHECK_RET;
ret = fprintf_fn(private_data, "\n");
CHECK_RET;
@@ -561,7 +570,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
/* first line must be a dn */
if (ldb_attr_cmp(attr, "dn") != 0) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'\n",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: First line of ldif must be a dn not '%s'",
attr);
goto failed;
}
@@ -569,7 +578,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
msg->dn = ldb_dn_from_ldb_val(msg, ldb, &value);
if ( ! ldb_dn_validate(msg->dn)) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'\n",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Error: Unable to parse dn '%s'",
(char *)value.data);
goto failed;
}
@@ -588,8 +597,8 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
}
}
if (!ldb_changetypes[i].name) {
- ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Error: Bad ldif changetype '%s'\n",(char *)value.data);
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "Error: Bad ldif changetype '%s'",(char *)value.data);
}
flags = 0;
continue;
@@ -632,13 +641,13 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
if (!el->values) {
goto failed;
}
- ret = a->syntax->ldif_read_fn(ldb, ldif, &value, &el->values[el->num_values]);
+ ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[el->num_values]);
if (ret != 0) {
goto failed;
}
if (value.length == 0) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Error: Attribute value cannot be empty for attribute '%s'\n", el->name);
+ "Error: Attribute value cannot be empty for attribute '%s'", el->name);
goto failed;
}
if (value.data != el->values[el->num_values].data) {
@@ -647,7 +656,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
el->num_values++;
} else {
/* its a new attribute */
- msg->elements = talloc_realloc(ldif, msg->elements,
+ msg->elements = talloc_realloc(msg, msg->elements,
struct ldb_message_element,
msg->num_elements+1);
if (!msg->elements) {
@@ -661,7 +670,7 @@ struct ldb_ldif *ldb_ldif_read(struct ldb_context *ldb,
goto failed;
}
el->num_values = 1;
- ret = a->syntax->ldif_read_fn(ldb, ldif, &value, &el->values[0]);
+ ret = a->syntax->ldif_read_fn(ldb, el->values, &value, &el->values[0]);
if (ret != 0) {
goto failed;
}
@@ -759,3 +768,59 @@ int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif
state.f = f;
return ldb_ldif_write(ldb, fprintf_file, &state, ldif);
}
+
+/*
+ wrapper around ldif_write() for a string
+*/
+struct ldif_write_string_state {
+ char *string;
+};
+
+static int ldif_printf_string(void *private_data, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
+
+static int ldif_printf_string(void *private_data, const char *fmt, ...)
+{
+ struct ldif_write_string_state *state =
+ (struct ldif_write_string_state *)private_data;
+ va_list ap;
+ size_t oldlen = talloc_get_size(state->string);
+ va_start(ap, fmt);
+
+ state->string = talloc_vasprintf_append(state->string, fmt, ap);
+ va_end(ap);
+ if (!state->string) {
+ return -1;
+ }
+
+ return talloc_get_size(state->string) - oldlen;
+}
+
+char *ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ const struct ldb_ldif *ldif)
+{
+ struct ldif_write_string_state state;
+ state.string = talloc_strdup(mem_ctx, "");
+ if (!state.string) {
+ return NULL;
+ }
+ if (ldb_ldif_write(ldb, ldif_printf_string, &state, ldif) == -1) {
+ return NULL;
+ }
+ return state.string;
+}
+
+/*
+ convenient function to turn a ldb_message into a string. Useful for
+ debugging
+ */
+char *ldb_ldif_message_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ enum ldb_changetype changetype,
+ const struct ldb_message *msg)
+{
+ struct ldb_ldif ldif;
+
+ ldif.changetype = changetype;
+ ldif.msg = discard_const_p(struct ldb_message, msg);
+
+ return ldb_ldif_write_string(ldb, mem_ctx, &ldif);
+}
diff --git a/source4/lib/ldb/common/ldb_match.c b/source4/lib/ldb/common/ldb_match.c
index c622701d30..e6ee0de027 100644
--- a/source4/lib/ldb/common/ldb_match.c
+++ b/source4/lib/ldb/common/ldb_match.c
@@ -335,7 +335,7 @@ static int ldb_match_extended(struct ldb_context *ldb,
}
}
if (comp == NULL) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s\n",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb: unknown extended rule_id %s",
tree->u.extended.rule_id);
return -1;
}
diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c
index ae97ef4cce..ea29a09a2a 100644
--- a/source4/lib/ldb/common/ldb_modules.c
+++ b/source4/lib/ldb/common/ldb_modules.c
@@ -1,4 +1,4 @@
-/*
+/*
ldb database library
Copyright (C) Simo Sorce 2004-2008
@@ -6,7 +6,7 @@
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
** under the LGPL
-
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
@@ -84,13 +84,13 @@ const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *m
/* spaces not admitted */
modstr = ldb_modules_strdup_no_spaces(mem_ctx, string);
if ( ! modstr) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_strdup_no_spaces()\n");
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_strdup_no_spaces()");
return NULL;
}
modules = talloc_realloc(mem_ctx, modules, char *, 2);
if ( ! modules ) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()\n");
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()");
talloc_free(modstr);
return NULL;
}
@@ -106,7 +106,7 @@ const char **ldb_modules_list_from_string(struct ldb_context *ldb, TALLOC_CTX *m
i++;
modules = talloc_realloc(mem_ctx, modules, char *, i + 2);
if ( ! modules ) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()\n");
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "Out of Memory in ldb_modules_list_from_string()");
return NULL;
}
@@ -127,7 +127,7 @@ static struct backends_list_entry {
static struct ops_list_entry {
const struct ldb_module_ops *ops;
- struct ops_list_entry *next;
+ struct ops_list_entry *next;
} *registered_modules = NULL;
static const struct ldb_builtins {
@@ -239,7 +239,7 @@ int ldb_connect_backend(struct ldb_context *ldb,
if (fn == NULL) {
ldb_debug(ldb, LDB_DEBUG_FATAL,
- "Unable to find backend for '%s'\n", url);
+ "Unable to find backend for '%s'", url);
return LDB_ERR_OTHER;
}
@@ -247,7 +247,7 @@ int ldb_connect_backend(struct ldb_context *ldb,
if (ret != LDB_SUCCESS) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Failed to connect to '%s'\n", url);
+ "Failed to connect to '%s'", url);
return ret;
}
return ret;
@@ -264,9 +264,9 @@ static const struct ldb_module_ops *ldb_find_module_ops(const char *name)
if (strcmp(builtins[i].module_ops->name, name) == 0)
return builtins[i].module_ops;
}
-
+
for (e = registered_modules; e; e = e->next) {
- if (strcmp(e->ops->name, name) == 0)
+ if (strcmp(e->ops->name, name) == 0)
return e->ops;
}
@@ -301,21 +301,21 @@ static void *ldb_dso_load_symbol(struct ldb_context *ldb, const char *name,
if (ldb->modules_dir == NULL)
return NULL;
- path = talloc_asprintf(ldb, "%s/%s.%s", ldb->modules_dir, name,
+ path = talloc_asprintf(ldb, "%s/%s.%s", ldb->modules_dir, name,
SHLIBEXT);
- ldb_debug(ldb, LDB_DEBUG_TRACE, "trying to load %s from %s\n", name, path);
+ ldb_debug(ldb, LDB_DEBUG_TRACE, "trying to load %s from %s", name, path);
handle = dlopen(path, RTLD_NOW);
if (handle == NULL) {
- ldb_debug(ldb, LDB_DEBUG_WARNING, "unable to load %s from %s: %s\n", name, path, dlerror());
+ ldb_debug(ldb, LDB_DEBUG_WARNING, "unable to load %s from %s: %s", name, path, dlerror());
return NULL;
}
sym = (int (*)(void))dlsym(handle, symbol);
if (sym == NULL) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "no symbol `%s' found in %s: %s\n", symbol, path, dlerror());
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "no symbol `%s' found in %s: %s", symbol, path, dlerror());
return NULL;
}
@@ -328,7 +328,7 @@ int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, str
{
struct ldb_module *module;
int i;
-
+
module = backend;
for (i = 0; module_list[i] != NULL; i++) {
@@ -338,10 +338,10 @@ int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, str
if (strcmp(module_list[i], "") == 0) {
continue;
}
-
+
ops = ldb_find_module_ops(module_list[i]);
if (ops == NULL) {
- char *symbol_name = talloc_asprintf(ldb, "ldb_%s_module_ops",
+ char *symbol_name = talloc_asprintf(ldb, "ldb_%s_module_ops",
module_list[i]);
if (symbol_name == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
@@ -349,31 +349,31 @@ int ldb_load_modules_list(struct ldb_context *ldb, const char **module_list, str
ops = ldb_dso_load_symbol(ldb, module_list[i], symbol_name);
talloc_free(symbol_name);
}
-
+
if (ops == NULL) {
- ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found\n",
+ ldb_debug(ldb, LDB_DEBUG_WARNING, "WARNING: Module [%s] not found",
module_list[i]);
continue;
}
-
+
current = talloc_zero(ldb, struct ldb_module);
if (current == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
talloc_set_name(current, "ldb_module: %s", module_list[i]);
-
+
current->ldb = ldb;
current->ops = ops;
-
+
DLIST_ADD(module, current);
}
*out = module;
return LDB_SUCCESS;
}
-int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module)
+int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module)
{
- while (module && module->ops->init_context == NULL)
+ while (module && module->ops->init_context == NULL)
module = module->next;
/* init is different in that it is not an error if modules
@@ -382,7 +382,7 @@ int ldb_init_module_chain(struct ldb_context *ldb, struct ldb_module *module)
if (module) {
int ret = module->ops->init_context(module);
if (ret != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "module %s initialization failed\n", module->ops->name);
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "module %s initialization failed", module->ops->name);
return ret;
}
}
@@ -412,7 +412,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[])
}
/* if not overloaded by options and the backend is not ldap try to load the modules list from ldb */
- if ((modules == NULL) && (strcmp("ldap", ldb->modules->ops->name) != 0)) {
+ if ((modules == NULL) && (strcmp("ldap", ldb->modules->ops->name) != 0)) {
const char * const attrs[] = { "@LIST" , NULL};
struct ldb_result *res = NULL;
struct ldb_dn *mods_dn;
@@ -424,11 +424,11 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[])
}
ret = ldb_search(ldb, mods_dn, &res, mods_dn, LDB_SCOPE_BASE, attrs, "@LIST=*");
-
+
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db");
} else if (ret != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out\n", ldb_errstring(ldb));
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "ldb error (%s) occurred searching for modules, bailing out", ldb_errstring(ldb));
talloc_free(mem_ctx);
return ret;
} else {
@@ -436,7 +436,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[])
if (res->count == 0) {
ldb_debug(ldb, LDB_DEBUG_TRACE, "no modules required by the db");
} else if (res->count > 1) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found (%d), bailing out\n", res->count);
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "Too many records found (%d), bailing out", res->count);
talloc_free(mem_ctx);
return -1;
} else {
@@ -472,10 +472,14 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[])
which makes writing a module simpler, and makes it more likely to keep working
when ldb is extended
*/
-#define FIND_OP(module, op) do { \
- struct ldb_context *ldb = module->ldb; \
+#define FIND_OP_NOERR(module, op) do { \
module = module->next; \
while (module && module->ops->op == NULL) module = module->next; \
+} while (0)
+
+#define FIND_OP(module, op) do { \
+ struct ldb_context *ldb = module->ldb; \
+ FIND_OP_NOERR(module, op); \
if (module == NULL) { \
ldb_asprintf_errstring(ldb, "Unable to find backend operation for " #op ); \
return LDB_ERR_OPERATIONS_ERROR; \
@@ -536,6 +540,8 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
return LDB_ERR_UNWILLING_TO_PERFORM;
}
+ request->handle->nesting++;
+
switch (request->operation) {
case LDB_SEARCH:
FIND_OP(module, search);
@@ -566,6 +572,9 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
ret = module->ops->request(module, request);
break;
}
+
+ request->handle->nesting--;
+
if (ret == LDB_SUCCESS) {
return ret;
}
@@ -573,6 +582,17 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request)
/* Set a default error string, to place the blame somewhere */
ldb_asprintf_errstring(module->ldb, "error in module %s: %s (%d)", module->ops->name, ldb_strerror(ret), ret);
}
+
+ if (!(request->handle->flags & LDB_HANDLE_FLAG_DONE_CALLED)) {
+ /* It is _extremely_ common that a module returns a
+ * failure without calling ldb_module_done(), but that
+ * guarantees we will end up hanging in
+ * ldb_wait(). This fixes it without having to rewrite
+ * all our modules, and leaves us one less sharp
+ * corner for module developers to cut themselves on
+ */
+ ldb_module_done(request, NULL, NULL, ret);
+ }
return ret;
}
@@ -595,6 +615,17 @@ int ldb_next_end_trans(struct ldb_module *module)
return module->ops->end_transaction(module);
}
+int ldb_next_prepare_commit(struct ldb_module *module)
+{
+ FIND_OP_NOERR(module, prepare_commit);
+ if (module == NULL) {
+ /* we are allowed to have no prepare commit in
+ backends */
+ return LDB_SUCCESS;
+ }
+ return module->ops->prepare_commit(module);
+}
+
int ldb_next_del_trans(struct ldb_module *module)
{
FIND_OP(module, del_transaction);
@@ -614,6 +645,7 @@ struct ldb_handle *ldb_handle_new(TALLOC_CTX *mem_ctx, struct ldb_context *ldb)
h->status = LDB_SUCCESS;
h->state = LDB_ASYNC_INIT;
h->ldb = ldb;
+ h->flags = 0;
return h;
}
@@ -645,6 +677,16 @@ int ldb_module_send_entry(struct ldb_request *req,
ares->controls = talloc_steal(ares, ctrls);
ares->error = LDB_SUCCESS;
+ if ((req->handle->ldb->flags & LDB_FLG_ENABLE_TRACING) &&
+ req->handle->nesting == 0) {
+ char *s;
+ ldb_debug_add(req->handle->ldb, "ldb_trace_response: ENTRY\n");
+ s = ldb_ldif_message_string(req->handle->ldb, msg, LDB_CHANGETYPE_NONE, msg);
+ ldb_debug_add(req->handle->ldb, "%s\n", s);
+ talloc_free(s);
+ ldb_debug_end(req->handle->ldb, LDB_DEBUG_TRACE);
+ }
+
return req->callback(req, ares);
}
@@ -670,6 +712,13 @@ int ldb_module_send_referral(struct ldb_request *req,
ares->referral = talloc_steal(ares, ref);
ares->error = LDB_SUCCESS;
+ if ((req->handle->ldb->flags & LDB_FLG_ENABLE_TRACING) &&
+ req->handle->nesting == 0) {
+ ldb_debug_add(req->handle->ldb, "ldb_trace_response: REFERRAL\n");
+ ldb_debug_add(req->handle->ldb, "ref: %s\n", ref);
+ ldb_debug_end(req->handle->ldb, LDB_DEBUG_TRACE);
+ }
+
return req->callback(req, ares);
}
@@ -700,6 +749,19 @@ int ldb_module_done(struct ldb_request *req,
ares->response = talloc_steal(ares, response);
ares->error = error;
+ req->handle->flags |= LDB_HANDLE_FLAG_DONE_CALLED;
+
+ if ((req->handle->ldb->flags & LDB_FLG_ENABLE_TRACING) &&
+ req->handle->nesting == 0) {
+ ldb_debug_add(req->handle->ldb, "ldb_trace_response: DONE\n");
+ ldb_debug_add(req->handle->ldb, "error: %u\n", error);
+ if (ldb_errstring(req->handle->ldb)) {
+ ldb_debug_add(req->handle->ldb, "msg: %s\n",
+ ldb_errstring(req->handle->ldb));
+ }
+ ldb_debug_end(req->handle->ldb, LDB_DEBUG_TRACE);
+ }
+
req->callback(req, ares);
return error;
}
@@ -756,7 +818,6 @@ int ldb_mod_register_control(struct ldb_module *module, const char *oid)
LDB_BACKEND(tdb), \
LDAP_BACKEND \
SQLITE3_BACKEND \
- LDB_MODULE(operational), \
LDB_MODULE(rdn_name), \
LDB_MODULE(paged_results), \
LDB_MODULE(server_sort), \
diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c
index ad53a3d29d..702978a361 100644
--- a/source4/lib/ldb/common/ldb_msg.c
+++ b/source4/lib/ldb/common/ldb_msg.c
@@ -643,12 +643,12 @@ const char **ldb_attr_list_copy(TALLOC_CTX *mem_ctx, const char * const *attrs)
{
const char **ret;
int i;
- for (i=0;attrs[i];i++) /* noop */ ;
+ for (i=0;attrs && attrs[i];i++) /* noop */ ;
ret = talloc_array(mem_ctx, const char *, i+1);
if (ret == NULL) {
return NULL;
}
- for (i=0;attrs[i];i++) {
+ for (i=0;attrs && attrs[i];i++) {
ret[i] = attrs[i];
}
ret[i] = attrs[i];
@@ -665,7 +665,7 @@ const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *att
const char **ret;
int i;
bool found = false;
- for (i=0;attrs[i];i++) {
+ for (i=0;attrs && attrs[i];i++) {
if (ldb_attr_cmp(attrs[i], new_attr) == 0) {
found = true;
}
@@ -677,7 +677,7 @@ const char **ldb_attr_list_copy_add(TALLOC_CTX *mem_ctx, const char * const *att
if (ret == NULL) {
return NULL;
}
- for (i=0;attrs[i];i++) {
+ for (i=0;attrs && attrs[i];i++) {
ret[i] = attrs[i];
}
ret[i] = new_attr;
@@ -739,6 +739,10 @@ int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *rep
void ldb_msg_remove_element(struct ldb_message *msg, struct ldb_message_element *el)
{
int n = (el - msg->elements);
+ if (n >= msg->num_elements) {
+ /* should we abort() here? */
+ return;
+ }
if (n != msg->num_elements-1) {
memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el));
}
diff --git a/source4/lib/ldb/common/ldb_parse.c b/source4/lib/ldb/common/ldb_parse.c
index 654a635abf..ba16b57da3 100644
--- a/source4/lib/ldb/common/ldb_parse.c
+++ b/source4/lib/ldb/common/ldb_parse.c
@@ -267,7 +267,8 @@ static enum ldb_parse_op ldb_parse_filtertype(void *mem_ctx, char **type, char *
p++;
}
- while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-')) { /* attribute names can only be alphanums */
+ while ((isascii(*p) && isalnum((unsigned char)*p)) || (*p == '-') || (*p == '.')) {
+ /* attribute names can only be alphanums */
p++;
}
@@ -817,3 +818,61 @@ void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree,
break;
}
}
+
+/*
+ shallow copy a tree - copying only the elements array so that the caller
+ can safely add new elements without changing the message
+*/
+struct ldb_parse_tree *ldb_parse_tree_copy_shallow(TALLOC_CTX *mem_ctx,
+ const struct ldb_parse_tree *ot)
+{
+ int i;
+ struct ldb_parse_tree *nt;
+
+ nt = talloc(mem_ctx, struct ldb_parse_tree);
+ if (!nt) {
+ return NULL;
+ }
+
+ *nt = *ot;
+
+ switch (ot->operation) {
+ case LDB_OP_AND:
+ case LDB_OP_OR:
+ nt->u.list.elements = talloc_array(nt, struct ldb_parse_tree *,
+ ot->u.list.num_elements);
+ if (!nt->u.list.elements) {
+ talloc_free(nt);
+ return NULL;
+ }
+
+ for (i=0;i<ot->u.list.num_elements;i++) {
+ nt->u.list.elements[i] =
+ ldb_parse_tree_copy_shallow(nt->u.list.elements,
+ ot->u.list.elements[i]);
+ if (!nt->u.list.elements[i]) {
+ talloc_free(nt);
+ return NULL;
+ }
+ }
+ break;
+ case LDB_OP_NOT:
+ nt->u.isnot.child = ldb_parse_tree_copy_shallow(nt,
+ ot->u.isnot.child);
+ if (!nt->u.isnot.child) {
+ talloc_free(nt);
+ return NULL;
+ }
+ break;
+ case LDB_OP_EQUALITY:
+ case LDB_OP_GREATER:
+ case LDB_OP_LESS:
+ case LDB_OP_APPROX:
+ case LDB_OP_SUBSTRING:
+ case LDB_OP_PRESENT:
+ case LDB_OP_EXTENDED:
+ break;
+ }
+
+ return nt;
+}
diff --git a/source4/lib/ldb/config.guess b/source4/lib/ldb/config.guess
index 4af85584ae..da83314608 100755
--- a/source4/lib/ldb/config.guess
+++ b/source4/lib/ldb/config.guess
@@ -808,7 +808,7 @@ EOF
echo ${UNAME_MACHINE}-pc-pw32
exit ;;
*:Interix*:[3456]*)
- case ${UNAME_MACHINE} in
+ case ${UNAME_MACHINE} in
x86)
echo i586-pc-interix${UNAME_RELEASE}
exit ;;
@@ -984,7 +984,7 @@ EOF
echo x86_64-unknown-linux-gnu
exit ;;
xtensa*:Linux:*:*)
- echo ${UNAME_MACHINE}-unknown-linux-gnu
+ echo ${UNAME_MACHINE}-unknown-linux-gnu
exit ;;
i*86:Linux:*:*)
# The BFD linker knows what the default object file format is, so
diff --git a/source4/lib/ldb/config.mk b/source4/lib/ldb/config.mk
index 6fcf3943d0..4a1f814baa 100644
--- a/source4/lib/ldb/config.mk
+++ b/source4/lib/ldb/config.mk
@@ -47,18 +47,6 @@ SUBSYSTEM = LIBLDB
ldb_paged_searches_OBJ_FILES = $(ldbsrcdir)/modules/paged_searches.o
################################################
-# Start MODULE ldb_operational
-[MODULE::ldb_operational]
-SUBSYSTEM = LIBLDB
-CFLAGS = -I$(ldbsrcdir)/include
-PRIVATE_DEPENDENCIES = LIBTALLOC LIBTEVENT
-INIT_FUNCTION = LDB_MODULE(operational)
-# End MODULE ldb_operational
-################################################
-
-ldb_operational_OBJ_FILES = $(ldbsrcdir)/modules/operational.o
-
-################################################
# Start MODULE ldb_rdn_name
[MODULE::ldb_rdn_name]
SUBSYSTEM = LIBLDB
diff --git a/source4/lib/ldb/config.sub b/source4/lib/ldb/config.sub
index 80a785297e..a39437d015 100755
--- a/source4/lib/ldb/config.sub
+++ b/source4/lib/ldb/config.sub
@@ -1454,7 +1454,7 @@ case $basic_machine in
os=-aout
;;
c4x-* | tic4x-*)
- os=-coff
+ os=-coff
;;
# This must come before the *-dec entry.
pdp10-*)
diff --git a/source4/lib/ldb/configure.ac b/source4/lib/ldb/configure.ac
index d61b31afd4..a0fab6d786 100644
--- a/source4/lib/ldb/configure.ac
+++ b/source4/lib/ldb/configure.ac
@@ -11,7 +11,7 @@ AC_DEFUN([SMB_MODULE_DEFAULT], [echo -n ""])
AC_DEFUN([SMB_LIBRARY_ENABLE], [echo -n ""])
AC_DEFUN([SMB_EXT_LIB], [echo -n ""])
AC_DEFUN([SMB_ENABLE], [echo -n ""])
-AC_INIT(ldb, 0.9.3)
+AC_INIT(ldb, 0.9.7)
AC_CONFIG_SRCDIR([common/ldb.c])
AC_LIBREPLACE_ALL_CHECKS
diff --git a/source4/lib/ldb/external/libevents.m4 b/source4/lib/ldb/external/libevents.m4
index 6a0e36af8b..af046f1430 100644
--- a/source4/lib/ldb/external/libevents.m4
+++ b/source4/lib/ldb/external/libevents.m4
@@ -3,5 +3,5 @@ AC_SUBST(TEVENT_CFLAGS)
AC_SUBST(TEVENT_LIBS)
AC_CHECK_HEADER(tevent.h,
- [AC_CHECK_LIB(tevent, tevent_context_init, [TEVENT_LIBS="-ltevent"]) ],
+ [AC_CHECK_LIB(tevent, tevent_context_init, [TEVENT_LIBS="-ltevent"], , -ltalloc) ],
[PKG_CHECK_MODULES(TEVENT, tevent)])
diff --git a/source4/lib/ldb/external/libtalloc.m4 b/source4/lib/ldb/external/libtalloc.m4
index a4c5b8a9d9..8c63fcc041 100644
--- a/source4/lib/ldb/external/libtalloc.m4
+++ b/source4/lib/ldb/external/libtalloc.m4
@@ -2,6 +2,7 @@ AC_SUBST(TALLOC_OBJ)
AC_SUBST(TALLOC_CFLAGS)
AC_SUBST(TALLOC_LIBS)
-AC_CHECK_HEADER(talloc.h,
- [AC_CHECK_LIB(talloc, talloc_init, [TALLOC_LIBS="-ltalloc"]) ],
- [PKG_CHECK_MODULES(TALLOC, talloc)])
+PKG_CHECK_MODULES(TALLOC, talloc >= 2.0.0,
+ [ ],
+ [ AC_CHECK_HEADER(talloc.h,
+ [ AC_CHECK_LIB(talloc, talloc_init, [TALLOC_LIBS="-ltalloc"])])])
diff --git a/source4/lib/ldb/external/libtdb.m4 b/source4/lib/ldb/external/libtdb.m4
index 8c2cab702f..44971e1fa9 100644
--- a/source4/lib/ldb/external/libtdb.m4
+++ b/source4/lib/ldb/external/libtdb.m4
@@ -4,4 +4,4 @@ AC_SUBST(TDB_LIBS)
AC_CHECK_HEADER(tdb.h,
[AC_CHECK_LIB(tdb, tdb_open, [TDB_LIBS="-ltdb"]) ],
- [PKG_CHECK_MODULES(TDB, tdb >= 1.1.0)])
+ [PKG_CHECK_MODULES(TDB, tdb >= 1.1.6)])
diff --git a/source4/lib/ldb/include/dlinklist.h b/source4/lib/ldb/include/dlinklist.h
index acab9fa043..62f885dd30 100644
--- a/source4/lib/ldb/include/dlinklist.h
+++ b/source4/lib/ldb/include/dlinklist.h
@@ -23,6 +23,7 @@
#ifndef _DLINKLIST_H
#define _DLINKLIST_H
+
/* hook into the front of the list */
#define DLIST_ADD(list, p) \
do { \
@@ -38,7 +39,6 @@ do { \
} while (0)
/* remove an element from a list - element doesn't have to be in list. */
-#ifndef DLIST_REMOVE
#define DLIST_REMOVE(list, p) \
do { \
if ((p) == (list)) { \
@@ -50,7 +50,6 @@ do { \
} \
if ((p) && ((p) != (list))) (p)->next = (p)->prev = NULL; \
} while (0)
-#endif
/* promote an element to the top of the list */
#define DLIST_PROMOTE(list, p) \
@@ -59,7 +58,7 @@ do { \
DLIST_ADD(list, p); \
} while (0)
-/* hook into the end of the list - needs a tmp pointer */
+/* hook into the end of the list - needs the entry type */
#define DLIST_ADD_END(list, p, type) \
do { \
if (!(list)) { \
@@ -88,11 +87,11 @@ do { \
}\
} while (0)
-/* demote an element to the end of the list, needs a tmp pointer */
-#define DLIST_DEMOTE(list, p, tmp) \
+/* demote an element to the end of the list, needs the entry type */
+#define DLIST_DEMOTE(list, p, type) \
do { \
DLIST_REMOVE(list, p); \
- DLIST_ADD_END(list, p, tmp); \
+ DLIST_ADD_END(list, p, type); \
} while (0)
/* concatenate two lists - putting all elements of the 2nd list at the
diff --git a/source4/lib/ldb/include/ldb.h b/source4/lib/ldb/include/ldb.h
index be41151409..a083696073 100644
--- a/source4/lib/ldb/include/ldb.h
+++ b/source4/lib/ldb/include/ldb.h
@@ -94,8 +94,8 @@ struct ldb_dn;
/**
There are a number of flags that are used with ldap_modify() in
- ldb_message_element.flags fields. The LDA_FLAGS_MOD_ADD,
- LDA_FLAGS_MOD_DELETE and LDA_FLAGS_MOD_REPLACE flags are used in
+ ldb_message_element.flags fields. The LDB_FLAGS_MOD_ADD,
+ LDB_FLAGS_MOD_DELETE and LDB_FLAGS_MOD_REPLACE flags are used in
ldap_modify() calls to specify whether attributes are being added,
deleted or modified respectively.
*/
@@ -240,6 +240,17 @@ struct ldb_utf8_fns {
*/
#define LDB_FLG_NOMMAP 8
+/**
+ Flag to tell ldif handlers not to force encoding of binary
+ structures in base64
+*/
+#define LDB_FLG_SHOW_BINARY 16
+
+/**
+ Flags to enable ldb tracing
+*/
+#define LDB_FLG_ENABLE_TRACING 32
+
/*
structures for ldb_parse_tree handling code
*/
@@ -375,6 +386,17 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c
*/
#define LDB_ATTR_FLAG_FIXED (1<<2)
+/*
+ when this is set, attempts to create two records which have the same
+ value for this attribute will return LDB_ERR_ENTRY_ALREADY_EXISTS
+ */
+#define LDB_ATTR_FLAG_UNIQUE_INDEX (1<<3)
+
+/*
+ when this is set, attempts to create two attribute values for this attribute on a single DN will return LDB_ERR_CONSTRAINT_VIOLATION
+ */
+#define LDB_ATTR_FLAG_SINGLE_VALUE (1<<4)
+
/**
LDAP attribute syntax for a DN
@@ -403,6 +425,15 @@ const struct ldb_dn_extended_syntax *ldb_dn_extended_syntax_by_name(struct ldb_c
#define LDB_SYNTAX_INTEGER "1.3.6.1.4.1.1466.115.121.1.27"
/**
+ LDAP attribute syntax for a boolean
+
+ This is the well-known LDAP attribute syntax for a boolean.
+
+ See <a href="http://www.ietf.org/rfc/rfc2252.txt">RFC 2252</a>, Section 4.3.2
+*/
+#define LDB_SYNTAX_BOOLEAN "1.3.6.1.4.1.1466.115.121.1.7"
+
+/**
LDAP attribute syntax for an octet string
This is the well-known LDAP attribute syntax for an octet string.
@@ -471,6 +502,20 @@ typedef int (*ldb_qsort_cmp_fn_t) (void *v1, void *v2, void *opaque);
#define LDB_CONTROL_SHOW_DELETED_OID "1.2.840.113556.1.4.417"
/**
+ OID for getting recycled objects
+
+ \sa <a href="http://msdn.microsoft.com/en-us/library/dd304621(PROT.13).aspx">Microsoft documentation of this OID</a>
+*/
+#define LDB_CONTROL_SHOW_RECYCLED_OID "1.2.840.113556.1.4.2064"
+
+/**
+ OID for getting deactivated linked attributes
+
+ \sa <a href="http://msdn.microsoft.com/en-us/library/dd302781(PROT.13).aspx">Microsoft documentation of this OID</a>
+*/
+#define LDB_CONTROL_SHOW_DEACTIVATED_LINK_OID "1.2.840.113556.1.4.2065"
+
+/**
OID for extended DN
\sa <a href="http://msdn.microsoft.com/library/default.asp?url=/library/en-us/ldap/ldap/ldap_server_extended_dn_oid.asp">Microsoft documentation of this OID</a>
@@ -601,8 +646,8 @@ struct ldb_extended_dn_control {
};
struct ldb_server_sort_control {
- char *attributeName;
- char *orderingRule;
+ const char *attributeName;
+ const char *orderingRule;
int reverse;
};
@@ -1249,6 +1294,11 @@ int ldb_sequence_number(struct ldb_context *ldb, enum ldb_sequence_type type, ui
int ldb_transaction_start(struct ldb_context *ldb);
/**
+ first phase of two phase commit
+ */
+int ldb_transaction_prepare_commit(struct ldb_context *ldb);
+
+/**
commit a transaction
*/
int ldb_transaction_commit(struct ldb_context *ldb);
@@ -1421,6 +1471,32 @@ struct ldb_ldif *ldb_ldif_read_string(struct ldb_context *ldb, const char **s);
int ldb_ldif_write_file(struct ldb_context *ldb, FILE *f, const struct ldb_ldif *msg);
/**
+ Write an LDIF message to a string
+
+ \param ldb the ldb context (from ldb_init())
+ \param mem_ctx the talloc context on which to attach the string)
+ \param msg the message to write out
+
+ \return the string containing the LDIF, or NULL on error
+
+ \sa ldb_ldif_read_string for the reader equivalent to this function.
+*/
+char * ldb_ldif_write_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ const struct ldb_ldif *msg);
+
+
+/*
+ Produce a string form of an ldb message
+
+ convenient function to turn a ldb_message into a string. Useful for
+ debugging
+ */
+char *ldb_ldif_message_string(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
+ enum ldb_changetype changetype,
+ const struct ldb_message *msg);
+
+
+/**
Base64 encode a buffer
\param mem_ctx the memory context that the result is allocated
@@ -1769,6 +1845,12 @@ void ldb_parse_tree_attr_replace(struct ldb_parse_tree *tree,
const char *attr,
const char *replace);
+/*
+ shallow copy a tree - copying only the elements array so that the caller
+ can safely add new elements without changing the message
+*/
+struct ldb_parse_tree *ldb_parse_tree_copy_shallow(TALLOC_CTX *mem_ctx,
+ const struct ldb_parse_tree *ot);
/**
Convert a time structure to a string
@@ -1837,4 +1919,13 @@ void ldb_qsort (void *const pbase, size_t total_elems, size_t size, void *opaque
*/
struct ldb_control **ldb_parse_control_strings(struct ldb_context *ldb, TALLOC_CTX *mem_ctx, const char **control_strings);
+/**
+ return the ldb flags
+*/
+unsigned int ldb_get_flags(struct ldb_context *ldb);
+
+/* set the ldb flags */
+void ldb_set_flags(struct ldb_context *ldb, unsigned flags);
+
+
#endif
diff --git a/source4/lib/ldb/include/ldb_errors.h b/source4/lib/ldb/include/ldb_errors.h
index 9362233fd5..706d82732d 100644
--- a/source4/lib/ldb/include/ldb_errors.h
+++ b/source4/lib/ldb/include/ldb_errors.h
@@ -120,6 +120,7 @@
backend.
*/
#define LDB_ERR_STRONG_AUTH_REQUIRED 8
+
/* 9 RESERVED */
/**
@@ -181,6 +182,7 @@
already exists in the entry.
*/
#define LDB_ERR_ATTRIBUTE_OR_VALUE_EXISTS 20
+
/**
The function used an invalid (incorrect syntax) attribute value.
*/
diff --git a/source4/lib/ldb/include/ldb_handlers.h b/source4/lib/ldb/include/ldb_handlers.h
index e1c14e679b..21fbcc33f8 100644
--- a/source4/lib/ldb/include/ldb_handlers.h
+++ b/source4/lib/ldb/include/ldb_handlers.h
@@ -31,37 +31,12 @@
* Author: Simo Sorce
*/
-
int ldb_handler_copy( struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out);
-
-int ldb_handler_fold( struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out);
-
-int ldb_canonicalise_Integer( struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out);
-
-int ldb_comparison_Integer( struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2);
-
int ldb_comparison_binary( struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2);
-
-int ldb_comparison_fold( struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2);
-
-int ldb_canonicalise_dn( struct ldb_context *ldb, void *mem_ctx,
+int db_handler_fold( struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *in, struct ldb_val *out);
-
-int ldb_comparison_dn( struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2);
-
-int ldb_comparison_objectclass( struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *v1, const struct ldb_val *v2);
-
-int ldb_comparison_utctime( struct ldb_context *ldb, void *mem_ctx,
+int ldb_comparison_fold( struct ldb_context *ldb, void *mem_ctx,
const struct ldb_val *v1, const struct ldb_val *v2);
-int ldb_canonicalise_utctime( struct ldb_context *ldb, void *mem_ctx,
- const struct ldb_val *in, struct ldb_val *out);
-
diff --git a/source4/lib/ldb/include/ldb_module.h b/source4/lib/ldb/include/ldb_module.h
index 4e1019184d..ae8c4d50df 100644
--- a/source4/lib/ldb/include/ldb_module.h
+++ b/source4/lib/ldb/include/ldb_module.h
@@ -52,6 +52,7 @@ struct ldb_module_ops {
int (*request)(struct ldb_module *, struct ldb_request *); /* match any other operation */
int (*extended)(struct ldb_module *, struct ldb_request *); /* extended operations */
int (*start_transaction)(struct ldb_module *);
+ int (*prepare_commit)(struct ldb_module *);
int (*end_transaction)(struct ldb_module *);
int (*del_transaction)(struct ldb_module *);
int (*sequence_number)(struct ldb_module *, struct ldb_request *);
@@ -63,6 +64,8 @@ struct ldb_module_ops {
void ldb_debug(struct ldb_context *ldb, enum ldb_debug_level level, const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
void ldb_debug_set(struct ldb_context *ldb, enum ldb_debug_level level,
const char *fmt, ...) PRINTF_ATTRIBUTE(3, 4);
+void ldb_debug_add(struct ldb_context *ldb, const char *fmt, ...) PRINTF_ATTRIBUTE(2, 3);
+void ldb_debug_end(struct ldb_context *ldb, enum ldb_debug_level level);
#define ldb_oom(ldb) ldb_debug_set(ldb, LDB_DEBUG_FATAL, "ldb out of memory at %s:%d\n", __FILE__, __LINE__)
@@ -88,13 +91,20 @@ int ldb_schema_attribute_add(struct ldb_context *ldb,
const char *syntax);
void ldb_schema_attribute_remove(struct ldb_context *ldb, const char *name);
+/* we allow external code to override the name -> schema_attribute function */
+typedef const struct ldb_schema_attribute *(*ldb_attribute_handler_override_fn_t)(struct ldb_context *, void *, const char *);
+
+void ldb_schema_attribute_set_override_handler(struct ldb_context *ldb,
+ ldb_attribute_handler_override_fn_t override,
+ void *private_data);
+
/* The following definitions come from lib/ldb/common/ldb_controls.c */
struct ldb_control *get_control_from_list(struct ldb_control **controls, const char *oid);
int save_controls(struct ldb_control *exclude, struct ldb_request *req, struct ldb_control ***saver);
int check_critical_controls(struct ldb_control **controls);
/* The following definitions come from lib/ldb/common/ldb_ldif.c */
-int ldb_should_b64_encode(const struct ldb_val *val);
+int ldb_should_b64_encode(struct ldb_context *ldb, const struct ldb_val *val);
/* The following definitions come from lib/ldb/common/ldb_match.c */
int ldb_match_msg(struct ldb_context *ldb,
@@ -119,6 +129,7 @@ int ldb_next_request(struct ldb_module *module, struct ldb_request *request);
int ldb_next_start_trans(struct ldb_module *module);
int ldb_next_end_trans(struct ldb_module *module);
int ldb_next_del_trans(struct ldb_module *module);
+int ldb_next_prepare_commit(struct ldb_module *module);
int ldb_next_init(struct ldb_module *module);
void ldb_set_errstring(struct ldb_context *ldb, const char *err_string);
@@ -158,4 +169,6 @@ int ldb_module_done(struct ldb_request *req,
int ldb_mod_register_control(struct ldb_module *module, const char *oid);
+void ldb_set_default_dns(struct ldb_context *ldb);
+
#endif
diff --git a/source4/lib/ldb/include/ldb_private.h b/source4/lib/ldb/include/ldb_private.h
index 2e8da9941c..0e0a1a206d 100644
--- a/source4/lib/ldb/include/ldb_private.h
+++ b/source4/lib/ldb/include/ldb_private.h
@@ -47,10 +47,14 @@ struct ldb_module_ops;
struct ldb_backend_ops;
+#define LDB_HANDLE_FLAG_DONE_CALLED 1
+
struct ldb_handle {
int status;
enum ldb_state state;
struct ldb_context *ldb;
+ unsigned flags;
+ unsigned nesting;
};
/* basic module structure */
@@ -65,6 +69,9 @@ struct ldb_module {
schema related information needed for matching rules
*/
struct ldb_schema {
+ void *attribute_handler_override_private;
+ ldb_attribute_handler_override_fn_t attribute_handler_override;
+
/* attribute handling table */
unsigned num_attributes;
struct ldb_schema_attribute *attributes;
@@ -108,17 +115,19 @@ struct ldb_context {
char *modules_dir;
struct tevent_context *ev_ctx;
+
+ bool prepare_commit_done;
+
+ char *partial_debug;
};
/* The following definitions come from lib/ldb/common/ldb.c */
int ldb_connect_backend(struct ldb_context *ldb, const char *url, const char *options[],
struct ldb_module **backend_module);
-void ldb_set_default_dns(struct ldb_context *ldb);
extern const struct ldb_module_ops ldb_objectclass_module_ops;
-extern const struct ldb_module_ops ldb_operational_module_ops;
extern const struct ldb_module_ops ldb_paged_results_module_ops;
extern const struct ldb_module_ops ldb_rdn_name_module_ops;
extern const struct ldb_module_ops ldb_schema_module_ops;
diff --git a/source4/lib/ldb/ldb.mk b/source4/lib/ldb/ldb.mk
index ff8c1f3baf..e87db64574 100644
--- a/source4/lib/ldb/ldb.mk
+++ b/source4/lib/ldb/ldb.mk
@@ -20,8 +20,8 @@ COMMON_OBJ=$(COMDIR)/ldb.o $(COMDIR)/ldb_ldif.o \
$(COMDIR)/attrib_handlers.o $(COMDIR)/ldb_controls.o $(COMDIR)/qsort.o
MODDIR=modules
-MODULES_OBJ=$(MODDIR)/operational.o $(MODDIR)/rdn_name.o \
- $(MODDIR)/paged_results.o $(MODDIR)/sort.o $(MODDIR)/asq.o
+MODULES_OBJ=$(MODDIR)/rdn_name.o ${MODDIR}/asq.o \
+ $(MODDIR)/paged_results.o $(MODDIR)/sort.o
NSSDIR=nssldb
NSS_OBJ= $(NSSDIR)/ldb-nss.o $(NSSDIR)/ldb-pwd.o $(NSSDIR)/ldb-grp.o
@@ -66,16 +66,16 @@ build-python:: ldb.$(SHLIBEXT)
pyldb.o: $(ldbdir)/pyldb.c
$(CC) $(PICFLAG) -c $(ldbdir)/pyldb.c $(CFLAGS) `$(PYTHON_CONFIG) --cflags`
-
-ldb.$(SHLIBEXT): pyldb.o
+
+ldb.$(SHLIBEXT): pyldb.o
$(SHLD) $(SHLD_FLAGS) -o ldb.$(SHLIBEXT) pyldb.o $(LIB_FLAGS) `$(PYTHON_CONFIG) --ldflags`
install-python:: build-python
mkdir -p $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='$(prefix)')"`
cp ldb.$(SHLIBEXT) $(DESTDIR)`$(PYTHON) -c "import distutils.sysconfig; print distutils.sysconfig.get_python_lib(1, prefix='$(prefix)')"`
-check-python:: build-python
- LD_LIBRARY_PATH=lib PYTHONPATH=.:$(ldbdir) $(PYTHON) $(ldbdir)/tests/python/api.py
+check-python:: build-python lib/$(SONAME)
+ $(LIB_PATH_VAR)=lib PYTHONPATH=.:$(ldbdir) $(PYTHON) $(ldbdir)/tests/python/api.py
clean::
rm -f ldb.$(SHLIBEXT)
diff --git a/source4/lib/ldb/ldb.pc.in b/source4/lib/ldb/ldb.pc.in
index b7e4c85844..01482f6bfb 100644
--- a/source4/lib/ldb/ldb.pc.in
+++ b/source4/lib/ldb/ldb.pc.in
@@ -2,7 +2,7 @@ prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
-modulesdir=@modulesdir@
+modulesdir=@LDB_MODULESDIR@
Name: ldb
Description: An LDAP-like embedded database
diff --git a/source4/lib/ldb/ldb_ildap/ldb_ildap.c b/source4/lib/ldb/ldb_ildap/ldb_ildap.c
index 4447d0e09a..ffde048223 100644
--- a/source4/lib/ldb/ldb_ildap/ldb_ildap.c
+++ b/source4/lib/ldb/ldb_ildap/ldb_ildap.c
@@ -790,7 +790,7 @@ static int ildb_connect(struct ldb_context *ldb, const char *url,
status = ldap_connect(ildb->ldap, url);
if (!NT_STATUS_IS_OK(status)) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s\n",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to connect to ldap URL '%s' - %s",
url, ldap_errstr(ildb->ldap, module, status));
goto failed;
}
@@ -810,14 +810,14 @@ static int ildb_connect(struct ldb_context *ldb, const char *url,
const char *password = cli_credentials_get_password(creds);
status = ldap_bind_simple(ildb->ldap, bind_dn, password);
if (!NT_STATUS_IS_OK(status)) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s",
ldap_errstr(ildb->ldap, module, status));
goto failed;
}
} else {
status = ldap_bind_sasl(ildb->ldap, creds, lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s\n",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Failed to bind - %s",
ldap_errstr(ildb->ldap, module, status));
goto failed;
}
diff --git a/source4/lib/ldb/ldb_ldap/ldb_ldap.c b/source4/lib/ldb/ldb_ldap/ldb_ldap.c
index 43a01f75a7..52c16101bb 100644
--- a/source4/lib/ldb/ldb_ldap/ldb_ldap.c
+++ b/source4/lib/ldb/ldb_ldap/ldb_ldap.c
@@ -219,7 +219,7 @@ static int lldb_search(struct lldb_context *lldb_ac)
}
if (req->controls != NULL) {
- ldb_debug(ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!\n");
+ ldb_debug(ldb, LDB_DEBUG_WARNING, "Controls are not yet supported by ldb_ldap backend!");
}
ldb_request_set_state(req, LDB_ASYNC_PENDING);
@@ -871,7 +871,7 @@ static int lldb_connect(struct ldb_context *ldb,
ret = ldap_initialize(&lldb->ldap, url);
if (ret != LDAP_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s\n",
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_initialize failed for URL '%s' - %s",
url, ldap_err2string(ret));
goto failed;
}
@@ -880,7 +880,7 @@ static int lldb_connect(struct ldb_context *ldb,
ret = ldap_set_option(lldb->ldap, LDAP_OPT_PROTOCOL_VERSION, &version);
if (ret != LDAP_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s\n",
+ ldb_debug(ldb, LDB_DEBUG_FATAL, "ldap_set_option failed - %s",
ldap_err2string(ret));
goto failed;
}
diff --git a/source4/lib/ldb/ldb_map/ldb_map.c b/source4/lib/ldb/ldb_map/ldb_map.c
index 5b4ea7910a..68e9d3f392 100644
--- a/source4/lib/ldb/ldb_map/ldb_map.c
+++ b/source4/lib/ldb/ldb_map/ldb_map.c
@@ -242,7 +242,7 @@ int ldb_next_remote_request(struct ldb_module *module, struct ldb_request *reque
default:
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
- "Invalid remote request!\n");
+ "Invalid remote request!");
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -503,14 +503,14 @@ struct ldb_dn *ldb_dn_map_local(struct ldb_module *module, void *mem_ctx, struct
case MAP_GENERATE:
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
"MAP_IGNORE/MAP_GENERATE attribute '%s' "
- "used in DN!\n", ldb_dn_get_component_name(dn, i));
+ "used in DN!", ldb_dn_get_component_name(dn, i));
goto failed;
case MAP_CONVERT:
if (map->u.convert.convert_local == NULL) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
"'convert_local' not set for attribute '%s' "
- "used in DN!\n", ldb_dn_get_component_name(dn, i));
+ "used in DN!", ldb_dn_get_component_name(dn, i));
goto failed;
}
/* fall through */
@@ -578,14 +578,14 @@ struct ldb_dn *ldb_dn_map_remote(struct ldb_module *module, void *mem_ctx, struc
case MAP_GENERATE:
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
"MAP_IGNORE/MAP_GENERATE attribute '%s' "
- "used in DN!\n", ldb_dn_get_component_name(dn, i));
+ "used in DN!", ldb_dn_get_component_name(dn, i));
goto failed;
case MAP_CONVERT:
if (map->u.convert.convert_remote == NULL) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
"'convert_remote' not set for attribute '%s' "
- "used in DN!\n", ldb_dn_get_component_name(dn, i));
+ "used in DN!", ldb_dn_get_component_name(dn, i));
goto failed;
}
/* fall through */
@@ -1007,7 +1007,7 @@ static int map_init_dns(struct ldb_module *module, struct ldb_map_context *data,
dn = ldb_dn_new_fmt(data, ldb, "%s=%s", MAP_DN_NAME, name);
if ( ! ldb_dn_validate(dn)) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
- "Failed to construct '%s' DN!\n", MAP_DN_NAME);
+ "Failed to construct '%s' DN!", MAP_DN_NAME);
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -1018,13 +1018,13 @@ static int map_init_dns(struct ldb_module *module, struct ldb_map_context *data,
}
if (res->count == 0) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
- "No results for '%s=%s'!\n", MAP_DN_NAME, name);
+ "No results for '%s=%s'!", MAP_DN_NAME, name);
talloc_free(res);
return LDB_ERR_CONSTRAINT_VIOLATION;
}
if (res->count > 1) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
- "Too many results for '%s=%s'!\n", MAP_DN_NAME, name);
+ "Too many results for '%s=%s'!", MAP_DN_NAME, name);
talloc_free(res);
return LDB_ERR_CONSTRAINT_VIOLATION;
}
diff --git a/source4/lib/ldb/ldb_map/ldb_map_inbound.c b/source4/lib/ldb/ldb_map/ldb_map_inbound.c
index 455740ce59..89037419fb 100644
--- a/source4/lib/ldb/ldb_map/ldb_map_inbound.c
+++ b/source4/lib/ldb/ldb_map/ldb_map_inbound.c
@@ -73,7 +73,7 @@ static int ldb_msg_el_partition(struct ldb_module *module, struct ldb_message *l
/* Unknown attribute: ignore */
if (map == NULL) {
ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
- "Not mapping attribute '%s': no mapping found\n",
+ "Not mapping attribute '%s': no mapping found",
old->name);
goto local;
}
@@ -86,7 +86,7 @@ static int ldb_msg_el_partition(struct ldb_module *module, struct ldb_message *l
if (map->u.convert.convert_local == NULL) {
ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
"Not mapping attribute '%s': "
- "'convert_local' not set\n",
+ "'convert_local' not set",
map->local_name);
goto local;
}
@@ -100,7 +100,7 @@ static int ldb_msg_el_partition(struct ldb_module *module, struct ldb_message *l
if (map->u.generate.generate_remote == NULL) {
ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
"Not mapping attribute '%s': "
- "'generate_remote' not set\n",
+ "'generate_remote' not set",
map->local_name);
goto local;
}
@@ -167,7 +167,7 @@ static int ldb_msg_partition(struct ldb_module *module, struct ldb_message *loca
/* Skip 'IS_MAPPED' */
if (ldb_attr_cmp(msg->elements[i].name, IS_MAPPED) == 0) {
ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
- "Skipping attribute '%s'\n",
+ "Skipping attribute '%s'",
msg->elements[i].name);
continue;
}
diff --git a/source4/lib/ldb/ldb_map/ldb_map_outbound.c b/source4/lib/ldb/ldb_map/ldb_map_outbound.c
index ffcefad6be..6a8e796ca4 100644
--- a/source4/lib/ldb/ldb_map/ldb_map_outbound.c
+++ b/source4/lib/ldb/ldb_map/ldb_map_outbound.c
@@ -304,7 +304,7 @@ static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local
if (map->u.convert.convert_remote == NULL) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
"Skipping attribute '%s': "
- "'convert_remote' not set\n",
+ "'convert_remote' not set",
attr_name);
return LDB_SUCCESS;
}
@@ -323,7 +323,7 @@ static int ldb_msg_el_merge(struct ldb_module *module, struct ldb_message *local
if (map->u.generate.generate_local == NULL) {
ldb_debug(ldb, LDB_DEBUG_ERROR, "ldb_map: "
"Skipping attribute '%s': "
- "'generate_local' not set\n",
+ "'generate_local' not set",
attr_name);
return LDB_SUCCESS;
}
@@ -900,7 +900,7 @@ static int map_subtree_collect_remote(struct ldb_module *module, void *mem_ctx,
if (map->type == MAP_GENERATE) {
ldb_debug(ldb, LDB_DEBUG_WARNING, "ldb_map: "
"Skipping attribute '%s': "
- "'convert_operator' not set\n",
+ "'convert_operator' not set",
tree->u.equality.attr);
*new = NULL;
return 0;
@@ -1062,7 +1062,7 @@ int map_return_entry(struct map_context *ac, struct ldb_reply *ares)
ac->req->op.search.scope)) {
ldb_debug(ldb, LDB_DEBUG_TRACE, "ldb_map: "
"Skipping record '%s': "
- "doesn't match original search\n",
+ "doesn't match original search",
ldb_dn_get_linearized(ares->message->dn));
return LDB_SUCCESS;
}
@@ -1250,17 +1250,19 @@ static int map_remote_search_callback(struct ldb_request *req,
ares->response, LDB_SUCCESS);
}
- talloc_free(ares);
-
/* reset the pointer to the start of the list */
ac->r_current = ac->r_list;
/* no entry just return */
if (ac->r_current == NULL) {
- return ldb_module_done(ac->req, ares->controls,
+ ret = ldb_module_done(ac->req, ares->controls,
ares->response, LDB_SUCCESS);
+ talloc_free(ares);
+ return ret;
}
+ talloc_free(ares);
+
ret = map_search_local(ac);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
diff --git a/source4/lib/ldb/ldb_sqlite3/base160.c b/source4/lib/ldb/ldb_sqlite3/base160.c
index 423e2b6841..7ad39f7c2f 100644
--- a/source4/lib/ldb/ldb_sqlite3/base160.c
+++ b/source4/lib/ldb/ldb_sqlite3/base160.c
@@ -122,7 +122,7 @@ lsqlite3_base160Next(char base160[])
* We need a minimum of four digits, and we will always get a multiple of
* four digits.
*/
- if (len = strlen(pBase160)) >= 4)
+ if ((len = strlen(pBase160)) >= 4)
{
pBase160 += strlen(pBase160) - 1;
diff --git a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
index 8acbac4cc3..d0573d389e 100644
--- a/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
+++ b/source4/lib/ldb/ldb_sqlite3/ldb_sqlite3.c
@@ -485,6 +485,7 @@ query_int(const struct lsqlite3_private * lsqlite3,
/* Format the query */
if ((p = sqlite3_vmprintf(pSql, args)) == NULL) {
+ va_end(args);
return SQLITE_NOMEM;
}
diff --git a/source4/lib/ldb/ldb_tdb/ldb_cache.c b/source4/lib/ldb/ldb_tdb/ldb_cache.c
index 43b965f239..2c399686ea 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_cache.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_cache.c
@@ -32,6 +32,7 @@
*/
#include "ldb_tdb.h"
+#include "ldb_private.h"
#define LTDB_FLAG_CASE_INSENSITIVE (1<<0)
#define LTDB_FLAG_INTEGER (1<<1)
@@ -115,6 +116,12 @@ static int ltdb_attributes_load(struct ldb_module *module)
ldb = ldb_module_get_ctx(module);
+ if (ldb->schema.attribute_handler_override) {
+ /* we skip loading the @ATTRIBUTES record when a module is supplying
+ its own attribute handling */
+ return LDB_SUCCESS;
+ }
+
dn = ldb_dn_new(module, ldb, LTDB_ATTRIBUTES);
if (dn == NULL) goto failed;
@@ -134,7 +141,7 @@ static int ltdb_attributes_load(struct ldb_module *module)
const struct ldb_schema_syntax *s;
if (ltdb_attributes_flags(&msg->elements[i], &flags) != 0) {
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'\n", msg->elements[i].name);
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid @ATTRIBUTES element for '%s'", msg->elements[i].name);
goto failed;
}
switch (flags & ~LTDB_FLAG_HIDDEN) {
@@ -149,7 +156,7 @@ static int ltdb_attributes_load(struct ldb_module *module)
break;
default:
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES\n",
+ "Invalid flag combination 0x%x for '%s' in @ATTRIBUTES",
flags, msg->elements[i].name);
goto failed;
}
@@ -157,7 +164,7 @@ static int ltdb_attributes_load(struct ldb_module *module)
s = ldb_standard_syntax_by_name(ldb, syntax);
if (s == NULL) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES\n",
+ "Invalid attribute syntax '%s' for '%s' in @ATTRIBUTES",
syntax, msg->elements[i].name);
goto failed;
}
diff --git a/source4/lib/ldb/ldb_tdb/ldb_index.c b/source4/lib/ldb/ldb_tdb/ldb_index.c
index c99c2936d8..b959471d16 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_index.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_index.c
@@ -426,7 +426,8 @@ struct dn_list {
caller frees
*/
static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
- const char *attr, const struct ldb_val *value)
+ const char *attr, const struct ldb_val *value,
+ const struct ldb_schema_attribute **ap)
{
struct ldb_dn *ret;
struct ldb_val v;
@@ -440,6 +441,9 @@ static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
}
a = ldb_schema_attribute_by_name(ldb, attr);
+ if (ap) {
+ *ap = a;
+ }
r = a->syntax->canonicalise_fn(ldb, ldb, value, &v);
if (r != LDB_SUCCESS) {
const char *errstr = ldb_errstring(ldb);
@@ -451,7 +455,7 @@ static struct ldb_dn *ltdb_index_key(struct ldb_context *ldb,
talloc_free(attr_folded);
return NULL;
}
- if (ldb_should_b64_encode(&v)) {
+ if (ldb_should_b64_encode(ldb, &v)) {
char *vstr = ldb_base64_encode(ldb, (char *)v.data, v.length);
if (!vstr) return NULL;
ret = ldb_dn_new_fmt(ldb, ldb, "%s:%s::%s", LTDB_INDEX, attr_folded, vstr);
@@ -531,7 +535,7 @@ static int ltdb_index_dn_simple(struct ldb_module *module,
/* the attribute is indexed. Pull the list of DNs that match the
search criterion */
- dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value);
+ dn = ltdb_index_key(ldb, tree->u.equality.attr, &tree->u.equality.value, NULL);
if (!dn) return LDB_ERR_OPERATIONS_ERROR;
msg = talloc(list, struct ldb_message);
@@ -792,6 +796,18 @@ static int ltdb_index_dn_not(struct ldb_module *module,
return LDB_ERR_OPERATIONS_ERROR;
}
+
+static bool ltdb_index_unique(struct ldb_context *ldb,
+ const char *attr)
+{
+ const struct ldb_schema_attribute *a;
+ a = ldb_schema_attribute_by_name(ldb, attr);
+ if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
+ return true;
+ }
+ return false;
+}
+
/*
AND two index results
*/
@@ -802,7 +818,7 @@ static int ltdb_index_dn_and(struct ldb_module *module,
{
struct ldb_context *ldb;
unsigned int i;
- int ret;
+ int ret, pass;
ldb = ldb_module_get_ctx(module);
@@ -810,52 +826,71 @@ static int ltdb_index_dn_and(struct ldb_module *module,
list->dn = NULL;
list->count = 0;
- for (i=0;i<tree->u.list.num_elements;i++) {
- struct dn_list *list2;
- int v;
-
- list2 = talloc(module, struct dn_list);
- if (list2 == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- v = ltdb_index_dn(module, tree->u.list.elements[i], index_list, list2);
-
- if (v == LDB_ERR_NO_SUCH_OBJECT) {
- /* 0 && X == 0 */
- talloc_free(list->dn);
- talloc_free(list2);
- return LDB_ERR_NO_SUCH_OBJECT;
- }
-
- if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
- talloc_free(list2);
- continue;
- }
-
- if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
- ret = LDB_SUCCESS;
- talloc_free(list->dn);
- list->dn = talloc_move(list, &list2->dn);
- list->count = list2->count;
- } else {
- if (list_intersect(ldb, list, list2) == -1) {
- talloc_free(list2);
+ for (pass=0;pass<=1;pass++) {
+ /* in the first pass we only look for unique simple
+ equality tests, in the hope of avoiding having to look
+ at any others */
+ bool only_unique = pass==0?true:false;
+
+ for (i=0;i<tree->u.list.num_elements;i++) {
+ struct dn_list *list2;
+ int v;
+ bool is_unique = false;
+ const struct ldb_parse_tree *subtree = tree->u.list.elements[i];
+
+ if (subtree->operation == LDB_OP_EQUALITY &&
+ ltdb_index_unique(ldb, subtree->u.equality.attr)) {
+ is_unique = true;
+ }
+ if (is_unique != only_unique) continue;
+
+ list2 = talloc(module, struct dn_list);
+ if (list2 == NULL) {
return LDB_ERR_OPERATIONS_ERROR;
}
- }
+
+ v = ltdb_index_dn(module, subtree, index_list, list2);
- talloc_free(list2);
-
- if (list->count == 0) {
- talloc_free(list->dn);
- return LDB_ERR_NO_SUCH_OBJECT;
+ if (v == LDB_ERR_NO_SUCH_OBJECT) {
+ /* 0 && X == 0 */
+ talloc_free(list->dn);
+ talloc_free(list2);
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+
+ if (v != LDB_SUCCESS && v != LDB_ERR_NO_SUCH_OBJECT) {
+ talloc_free(list2);
+ continue;
+ }
+
+ if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
+ ret = LDB_SUCCESS;
+ talloc_free(list->dn);
+ list->dn = talloc_move(list, &list2->dn);
+ list->count = list2->count;
+ } else {
+ if (list_intersect(ldb, list, list2) == -1) {
+ talloc_free(list2);
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
+ }
+
+ talloc_free(list2);
+
+ if (list->count == 0) {
+ talloc_free(list->dn);
+ return LDB_ERR_NO_SUCH_OBJECT;
+ }
+
+ if (list->count == 1) {
+ /* it isn't worth loading the next part of the tree */
+ return ret;
+ }
}
- }
-
+ }
return ret;
}
-
+
/*
AND index results and ONE level special index
*/
@@ -882,7 +917,7 @@ static int ltdb_index_dn_one(struct ldb_module *module,
search criterion */
val.data = (uint8_t *)((uintptr_t)ldb_dn_get_casefold(parent_dn));
val.length = strlen((char *)val.data);
- key = ltdb_index_key(ldb, LTDB_IDXONE, &val);
+ key = ltdb_index_key(ldb, LTDB_IDXONE, &val, NULL);
if (!key) {
talloc_free(list2);
return LDB_ERR_OPERATIONS_ERROR;
@@ -1002,7 +1037,8 @@ static int ltdb_index_dn(struct ldb_module *module,
extracting just the given attributes
*/
static int ltdb_index_filter(const struct dn_list *dn_list,
- struct ltdb_context *ac)
+ struct ltdb_context *ac,
+ uint32_t *match_count)
{
struct ldb_context *ldb;
struct ldb_message *msg;
@@ -1058,6 +1094,8 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
ac->request_terminated = true;
return ret;
}
+
+ (*match_count)++;
}
return LDB_SUCCESS;
@@ -1068,7 +1106,7 @@ static int ltdb_index_filter(const struct dn_list *dn_list,
returns -1 if an indexed search is not possible, in which
case the caller should call ltdb_search_full()
*/
-int ltdb_search_indexed(struct ltdb_context *ac)
+int ltdb_search_indexed(struct ltdb_context *ac, uint32_t *match_count)
{
struct ldb_context *ldb;
void *data = ldb_module_get_private(ac->module);
@@ -1121,21 +1159,17 @@ int ltdb_search_indexed(struct ltdb_context *ac)
if (ac->scope != LDB_SCOPE_BASE && idxattr == 1) {
ret = ltdb_index_dn(ac->module, ac->tree, ltdb->cache->indexlist, dn_list);
-
- if (ret != LDB_SUCCESS && ret != LDB_ERR_NO_SUCH_OBJECT) {
- talloc_free(dn_list);
- return ret;
- }
}
- if (ac->scope == LDB_SCOPE_ONELEVEL && idxone == 1) {
+ if (ret == LDB_ERR_OPERATIONS_ERROR &&
+ ac->scope == LDB_SCOPE_ONELEVEL && idxone == 1) {
ret = ltdb_index_dn_one(ac->module, ac->base, dn_list);
}
if (ret == LDB_SUCCESS) {
/* we've got a candidate list - now filter by the full tree
and extract the needed attributes */
- ret = ltdb_index_filter(dn_list, ac);
+ ret = ltdb_index_filter(dn_list, ac, match_count);
}
talloc_free(dn_list);
@@ -1185,7 +1219,8 @@ static int ltdb_index_add1_new(struct ldb_context *ldb,
static int ltdb_index_add1_add(struct ldb_context *ldb,
struct ldb_message *msg,
int idx,
- const char *dn)
+ const char *dn,
+ const struct ldb_schema_attribute *a)
{
struct ldb_val *v2;
unsigned int i;
@@ -1197,6 +1232,10 @@ static int ltdb_index_add1_add(struct ldb_context *ldb,
}
}
+ if (a->flags & LDB_ATTR_FLAG_UNIQUE_INDEX) {
+ return LDB_ERR_ENTRY_ALREADY_EXISTS;
+ }
+
v2 = talloc_realloc(msg->elements, msg->elements[idx].values,
struct ldb_val,
msg->elements[idx].num_values+1);
@@ -1223,6 +1262,7 @@ static int ltdb_index_add1(struct ldb_module *module, const char *dn,
struct ldb_dn *dn_key;
int ret;
unsigned int i;
+ const struct ldb_schema_attribute *a;
ldb = ldb_module_get_ctx(module);
@@ -1232,7 +1272,7 @@ static int ltdb_index_add1(struct ldb_module *module, const char *dn,
return LDB_ERR_OPERATIONS_ERROR;
}
- dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx]);
+ dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], &a);
if (!dn_key) {
talloc_free(msg);
return LDB_ERR_OPERATIONS_ERROR;
@@ -1260,7 +1300,7 @@ static int ltdb_index_add1(struct ldb_module *module, const char *dn,
if (i == msg->num_elements) {
ret = ltdb_index_add1_new(ldb, msg, dn);
} else {
- ret = ltdb_index_add1_add(ldb, msg, i, dn);
+ ret = ltdb_index_add1_add(ldb, msg, i, dn, a);
}
if (ret == LDB_SUCCESS) {
@@ -1343,7 +1383,7 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn,
return LDB_SUCCESS;
}
- dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx]);
+ dn_key = ltdb_index_key(ldb, el->name, &el->values[v_idx], NULL);
if (!dn_key) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -1370,14 +1410,14 @@ int ltdb_index_del_value(struct ldb_module *module, const char *dn,
i = ldb_msg_find_idx(msg, dn, &j, LTDB_IDX);
if (i == -1) {
struct ldb_ldif ldif;
-
- ldb_debug(ldb, LDB_DEBUG_ERROR,
- "ERROR: dn %s not found in %s\n", dn,
- ldb_dn_get_linearized(dn_key));
+ char *ldif_string;
ldif.changetype = LDB_CHANGETYPE_NONE;
ldif.msg = msg;
- ldb_ldif_write_file(ldb, stdout, &ldif);
- sleep(100);
+ ldif_string = ldb_ldif_write_string(ldb, NULL, &ldif);
+ ldb_debug(ldb, LDB_DEBUG_ERROR,
+ "ERROR: dn %s not found in %s", dn,
+ ldif_string);
+ talloc_free(ldif_string);
/* it ain't there. hmmm */
talloc_free(dn_key);
return LDB_SUCCESS;
@@ -1459,6 +1499,10 @@ int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int
const char *dn;
int ret;
+ if (ldb_dn_is_special(msg->dn)) {
+ return LDB_SUCCESS;
+ }
+
/* We index for ONE Level only if requested */
ret = ldb_msg_find_idx(ltdb->cache->indexlist, NULL, NULL, LTDB_IDXONE);
if (ret != 0) {
@@ -1537,6 +1581,8 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *
ret = ltdb_unpack_data(module, &data, msg);
if (ret != 0) {
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
+ ldb_dn_get_linearized(msg->dn));
talloc_free(msg);
return -1;
}
@@ -1546,7 +1592,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *
key2 = ltdb_key(module, msg->dn);
if (key2.dptr == NULL) {
/* probably a corrupt record ... darn */
- ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s\n",
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid DN in re_index: %s",
ldb_dn_get_linearized(msg->dn));
talloc_free(msg);
return 0;
@@ -1568,7 +1614,7 @@ static int re_index(struct tdb_context *tdb, TDB_DATA key, TDB_DATA data, void *
ret = ltdb_index_add0(module, dn, msg->elements, msg->num_elements);
} else {
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Adding special ONE LEVEL index failed (%s)!\n",
+ "Adding special ONE LEVEL index failed (%s)!",
ldb_dn_get_linearized(msg->dn));
}
diff --git a/source4/lib/ldb/ldb_tdb/ldb_pack.c b/source4/lib/ldb/ldb_tdb/ldb_pack.c
index 1995606f88..e7aeb47e72 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_pack.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_pack.c
@@ -236,6 +236,10 @@ int ltdb_unpack_data(struct ldb_module *module,
errno = EIO;
goto failed;
}
+ if (len == 0) {
+ errno = EIO;
+ goto failed;
+ }
message->elements[i].flags = 0;
message->elements[i].name = talloc_strndup(message->elements, (char *)p, len);
if (message->elements[i].name == NULL) {
@@ -280,7 +284,7 @@ int ltdb_unpack_data(struct ldb_module *module,
if (remaining != 0) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Error: %d bytes unread in ltdb_unpack_data\n", remaining);
+ "Error: %d bytes unread in ltdb_unpack_data", remaining);
}
return 0;
diff --git a/source4/lib/ldb/ldb_tdb/ldb_search.c b/source4/lib/ldb/ldb_tdb/ldb_search.c
index d395c28f28..a6647ccd50 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_search.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_search.c
@@ -265,6 +265,9 @@ int ltdb_search_dn1(struct ldb_module *module, struct ldb_dn *dn, struct ldb_mes
ret = ltdb_unpack_data(module, &tdb_data, msg);
free(tdb_data.dptr);
if (ret == -1) {
+ struct ldb_context *ldb = ldb_module_get_ctx(module);
+ ldb_debug(ldb, LDB_DEBUG_ERROR, "Invalid data for index %s\n",
+ ldb_dn_get_linearized(msg->dn));
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -535,7 +538,9 @@ int ltdb_search(struct ltdb_context *ctx)
ctx->attrs = req->op.search.attrs;
if (ret == LDB_SUCCESS) {
- ret = ltdb_search_indexed(ctx);
+ uint32_t match_count = 0;
+
+ ret = ltdb_search_indexed(ctx, &match_count);
if (ret == LDB_ERR_NO_SUCH_OBJECT) {
/* Not in the index, therefore OK! */
ret = LDB_SUCCESS;
@@ -546,6 +551,24 @@ int ltdb_search(struct ltdb_context *ctx)
* callback error */
if ( ! ctx->request_terminated && ret != LDB_SUCCESS) {
/* Not indexed, so we need to do a full scan */
+#if 0
+ /* useful for debugging when slow performance
+ * is caused by unindexed searches */
+ char *expression = ldb_filter_from_tree(ctx, ctx->tree);
+ printf("FULL SEARCH: %s\n", expression);
+ talloc_free(expression);
+#endif
+ if (match_count != 0) {
+ /* the indexing code gave an error
+ * after having returned at least one
+ * entry. This means the indexes are
+ * corrupt or a database record is
+ * corrupt. We cannot continue with a
+ * full search or we may return
+ * duplicate entries
+ */
+ return LDB_ERR_OPERATIONS_ERROR;
+ }
ret = ltdb_search_full(ctx);
if (ret != LDB_SUCCESS) {
ldb_set_errstring(ldb, "Indexed and full searches both failed!\n");
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.c b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
index 9df62be936..55acb6132d 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.c
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.c
@@ -254,7 +254,7 @@ static int ltdb_add_internal(struct ldb_module *module,
const struct ldb_message *msg)
{
struct ldb_context *ldb = ldb_module_get_ctx(module);
- int ret;
+ int ret, i;
ret = ltdb_check_special_dn(module, msg);
if (ret != LDB_SUCCESS) {
@@ -265,6 +265,24 @@ static int ltdb_add_internal(struct ldb_module *module,
return LDB_ERR_OPERATIONS_ERROR;
}
+ for (i=0;i<msg->num_elements;i++) {
+ struct ldb_message_element *el = &msg->elements[i];
+ const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
+
+ if (el->num_values == 0) {
+ ldb_asprintf_errstring(ldb, "attribute %s on %s specified, but with 0 values (illegal)",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
+ if (el->num_values > 1) {
+ ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ }
+ }
+
ret = ltdb_store(module, msg, TDB_INSERT);
if (ret == LDB_ERR_ENTRY_ALREADY_EXISTS) {
@@ -602,15 +620,28 @@ int ltdb_modify_internal(struct ldb_module *module,
struct ldb_message_element *el2;
struct ldb_val *vals;
const char *dn;
-
+ const struct ldb_schema_attribute *a = ldb_schema_attribute_by_name(ldb, el->name);
switch (msg->elements[i].flags & LDB_FLAG_MOD_MASK) {
case LDB_FLAG_MOD_ADD:
+
/* add this element to the message. fail if it
already exists */
idx = find_element(msg2, el->name);
+ if (el->num_values == 0) {
+ ldb_asprintf_errstring(ldb, "attribute %s on %s speicified, but with 0 values (illigal)",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
if (idx == -1) {
+ if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
+ if (el->num_values > 1) {
+ ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ }
if (msg_add_element(ldb, msg2, el) != 0) {
ret = LDB_ERR_OTHER;
goto failed;
@@ -618,6 +649,13 @@ int ltdb_modify_internal(struct ldb_module *module,
continue;
}
+ /* If this is an add, then if it already
+ * exists in the object, then we violoate the
+ * single-value rule */
+ if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+
el2 = &msg2->elements[idx];
/* An attribute with this name already exists,
@@ -657,6 +695,13 @@ int ltdb_modify_internal(struct ldb_module *module,
break;
case LDB_FLAG_MOD_REPLACE:
+ if (a && a->flags & LDB_ATTR_FLAG_SINGLE_VALUE) {
+ if (el->num_values > 1) {
+ ldb_asprintf_errstring(ldb, "SINGLE-VALUE attribute %s on %s speicified more than once",
+ el->name, ldb_dn_get_linearized(msg->dn));
+ return LDB_ERR_CONSTRAINT_VIOLATION;
+ }
+ }
/* replace all elements of this attribute name with the elements
listed. The attribute not existing is not an error */
msg_delete_attribute(module, ldb, msg2, el->name);
@@ -805,37 +850,18 @@ static int ltdb_rename(struct ltdb_context *ctx)
return LDB_ERR_OPERATIONS_ERROR;
}
- if (ldb_dn_compare(req->op.rename.olddn, req->op.rename.newdn) == 0) {
- /* The rename operation is apparently only changing case -
- the DNs are the same. Delete the old DN before adding
- the new one to avoid a TDB_ERR_EXISTS error.
-
- The only drawback to this is that if the delete
- succeeds but the add fails, we rely on the
- transaction to roll this all back. */
- tret = ltdb_delete_internal(module, req->op.rename.olddn);
- if (tret != LDB_SUCCESS) {
- return tret;
- }
-
- tret = ltdb_add_internal(module, msg);
- if (tret != LDB_SUCCESS) {
- return tret;
- }
- } else {
- /* The rename operation is changing DNs. Try to add the new
- DN first to avoid clobbering another DN not related to
- this rename operation. */
- tret = ltdb_add_internal(module, msg);
- if (tret != LDB_SUCCESS) {
- return tret;
- }
+ /* Always delete first then add, to avoid conflicts with
+ * unique indexes. We rely on the transaction to make this
+ * atomic
+ */
+ tret = ltdb_delete_internal(module, req->op.rename.olddn);
+ if (tret != LDB_SUCCESS) {
+ return tret;
+ }
- tret = ltdb_delete_internal(module, req->op.rename.olddn);
- if (tret != LDB_SUCCESS) {
- ltdb_delete_internal(module, req->op.rename.newdn);
- return LDB_ERR_OPERATIONS_ERROR;
- }
+ tret = ltdb_add_internal(module, msg);
+ if (tret != LDB_SUCCESS) {
+ return tret;
}
return LDB_SUCCESS;
@@ -857,18 +883,46 @@ static int ltdb_start_trans(struct ldb_module *module)
return LDB_SUCCESS;
}
-static int ltdb_end_trans(struct ldb_module *module)
+static int ltdb_prepare_commit(struct ldb_module *module)
{
void *data = ldb_module_get_private(module);
struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
- ltdb->in_transaction--;
+ if (ltdb->in_transaction != 1) {
+ return LDB_SUCCESS;
+ }
if (ltdb_index_transaction_commit(module) != 0) {
tdb_transaction_cancel(ltdb->tdb);
+ ltdb->in_transaction--;
return ltdb_err_map(tdb_error(ltdb->tdb));
}
+ if (tdb_transaction_prepare_commit(ltdb->tdb) != 0) {
+ ltdb->in_transaction--;
+ return ltdb_err_map(tdb_error(ltdb->tdb));
+ }
+
+ ltdb->prepared_commit = true;
+
+ return LDB_SUCCESS;
+}
+
+static int ltdb_end_trans(struct ldb_module *module)
+{
+ void *data = ldb_module_get_private(module);
+ struct ltdb_private *ltdb = talloc_get_type(data, struct ltdb_private);
+
+ if (!ltdb->prepared_commit) {
+ int ret = ltdb_prepare_commit(module);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
+
+ ltdb->in_transaction--;
+ ltdb->prepared_commit = false;
+
if (tdb_transaction_commit(ltdb->tdb) != 0) {
return ltdb_err_map(tdb_error(ltdb->tdb));
}
@@ -1209,6 +1263,7 @@ static const struct ldb_module_ops ltdb_ops = {
.extended = ltdb_handle_request,
.start_transaction = ltdb_start_trans,
.end_transaction = ltdb_end_trans,
+ .prepare_commit = ltdb_prepare_commit,
.del_transaction = ltdb_del_trans,
};
@@ -1266,7 +1321,7 @@ static int ltdb_connect(struct ldb_context *ldb, const char *url,
ldb_get_create_perms(ldb), ldb);
if (!ltdb->tdb) {
ldb_debug(ldb, LDB_DEBUG_ERROR,
- "Unable to open tdb '%s'\n", path);
+ "Unable to open tdb '%s'", path);
talloc_free(ltdb);
return -1;
}
diff --git a/source4/lib/ldb/ldb_tdb/ldb_tdb.h b/source4/lib/ldb/ldb_tdb/ldb_tdb.h
index 5a1c8fee2d..c8c1dad5de 100644
--- a/source4/lib/ldb/ldb_tdb/ldb_tdb.h
+++ b/source4/lib/ldb/ldb_tdb/ldb_tdb.h
@@ -8,8 +8,6 @@ struct ltdb_private {
TDB_CONTEXT *tdb;
unsigned int connect_flags;
- /* a double is used for portability and ease of string
- handling. It has plenty of digits of precision */
unsigned long long sequence_number;
/* the low level tdb seqnum - used to avoid loading BASEINFO when
@@ -30,6 +28,7 @@ struct ltdb_private {
bool check_base;
struct ltdb_idxptr *idxptr;
+ bool prepared_commit;
};
/*
@@ -83,7 +82,7 @@ int ltdb_check_at_attributes_values(const struct ldb_val *value);
struct ldb_parse_tree;
-int ltdb_search_indexed(struct ltdb_context *ctx);
+int ltdb_search_indexed(struct ltdb_context *ctx, uint32_t *);
int ltdb_index_add(struct ldb_module *module, const struct ldb_message *msg);
int ltdb_index_del(struct ldb_module *module, const struct ldb_message *msg);
int ltdb_index_one(struct ldb_module *module, const struct ldb_message *msg, int add);
diff --git a/source4/lib/ldb/modules/asq.c b/source4/lib/ldb/modules/asq.c
index 475b609e41..0819f7f559 100644
--- a/source4/lib/ldb/modules/asq.c
+++ b/source4/lib/ldb/modules/asq.c
@@ -26,8 +26,8 @@
*
* Component: ldb attribute scoped query control module
*
- * Description: this module searches all the the objects pointed
- * by the DNs contained in the references attribute
+ * Description: this module searches all the objects pointed by
+ * the DNs contained in the references attribute
*
* Author: Simo Sorce
*/
@@ -351,7 +351,7 @@ static int asq_search(struct ldb_module *module, struct ldb_request *req)
ldb = ldb_module_get_ctx(module);
- /* check if there's a paged request control */
+ /* check if there's an ASQ control */
control = ldb_request_get_control(req, LDB_CONTROL_ASQ_OID);
if (control == NULL) {
/* not found go on */
@@ -393,7 +393,7 @@ static int asq_init(struct ldb_module *module)
ret = ldb_mod_register_control(module, LDB_CONTROL_ASQ_OID);
if (ret != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_WARNING, "asq: Unable to register control with rootdse!\n");
+ ldb_debug(ldb, LDB_DEBUG_WARNING, "asq: Unable to register control with rootdse!");
}
return ldb_next_init(module);
diff --git a/source4/lib/ldb/modules/operational.c b/source4/lib/ldb/modules/operational.c
deleted file mode 100644
index 43b223b52e..0000000000
--- a/source4/lib/ldb/modules/operational.c
+++ /dev/null
@@ -1,314 +0,0 @@
-/*
- ldb database library
-
- Copyright (C) Andrew Tridgell 2005
- Copyright (C) Simo Sorce 2006-2008
-
- ** NOTE! The following LGPL license applies to the ldb
- ** library. This does NOT imply that all of Samba is released
- ** under the LGPL
-
- This library is free software; you can redistribute it and/or
- modify it under the terms of the GNU Lesser General Public
- License as published by the Free Software Foundation; either
- version 3 of the License, or (at your option) any later version.
-
- This library 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
- Lesser General Public License for more details.
-
- You should have received a copy of the GNU Lesser General Public
- License along with this library; if not, see <http://www.gnu.org/licenses/>.
-*/
-/*
- handle operational attributes
- */
-
-/*
- createTimestamp: HIDDEN, searchable, ldaptime, alias for whenCreated
- modifyTimestamp: HIDDEN, searchable, ldaptime, alias for whenChanged
-
- for the above two, we do the search as normal, and if
- createTimestamp or modifyTimestamp is asked for, then do
- additional searches for whenCreated and whenChanged and fill in
- the resulting values
-
- we also need to replace these with the whenCreated/whenChanged
- equivalent in the search expression trees
-
- whenCreated: not-HIDDEN, CONSTRUCTED, SEARCHABLE
- whenChanged: not-HIDDEN, CONSTRUCTED, SEARCHABLE
-
- on init we need to setup attribute handlers for these so
- comparisons are done correctly. The resolution is 1 second.
-
- on add we need to add both the above, for current time
-
- on modify we need to change whenChanged
-
-
- subschemaSubentry: HIDDEN, not-searchable,
- points at DN CN=Aggregate,$SCHEMADN
-
- for this one we do the search as normal, then add the static
- value if requested. How do we work out the $BASEDN from inside a
- module?
-
-
- structuralObjectClass: HIDDEN, CONSTRUCTED, not-searchable. always same as objectclass?
-
- for this one we do the search as normal, then if requested ask
- for objectclass, change the attribute name, and add it
-
- allowedAttributesEffective: HIDDEN, CONSTRUCTED, not-searchable,
- list of attributes that can be modified - requires schema lookup
-
-
- attributeTypes: in schema only
- objectClasses: in schema only
- matchingRules: in schema only
- matchingRuleUse: in schema only
- creatorsName: not supported by w2k3?
- modifiersName: not supported by w2k3?
-*/
-
-#include "ldb_includes.h"
-#include "ldb_module.h"
-
-#ifndef ARRAY_SIZE
-#define ARRAY_SIZE(a) (sizeof(a)/sizeof(a[0]))
-#endif
-
-/*
- construct a canonical name from a message
-*/
-static int construct_canonical_name(struct ldb_module *module, struct ldb_message *msg)
-{
- char *canonicalName;
- canonicalName = ldb_dn_canonical_string(msg, msg->dn);
- if (canonicalName == NULL) {
- return -1;
- }
- return ldb_msg_add_steal_string(msg, "canonicalName", canonicalName);
-}
-
-/*
- a list of attribute names that should be substituted in the parse
- tree before the search is done
-*/
-static const struct {
- const char *attr;
- const char *replace;
-} parse_tree_sub[] = {
- { "createTimestamp", "whenCreated" },
- { "modifyTimestamp", "whenChanged" }
-};
-
-
-/*
- a list of attribute names that are hidden, but can be searched for
- using another (non-hidden) name to produce the correct result
-*/
-static const struct {
- const char *attr;
- const char *replace;
- int (*constructor)(struct ldb_module *, struct ldb_message *);
-} search_sub[] = {
- { "createTimestamp", "whenCreated", NULL },
- { "modifyTimestamp", "whenChanged", NULL },
- { "structuralObjectClass", "objectClass", NULL },
- { "canonicalName", "distinguishedName", construct_canonical_name }
-};
-
-/*
- post process a search result record. For any search_sub[] attributes that were
- asked for, we need to call the appropriate copy routine to copy the result
- into the message, then remove any attributes that we added to the search but were
- not asked for by the user
-*/
-static int operational_search_post_process(struct ldb_module *module,
- struct ldb_message *msg,
- const char * const *attrs)
-{
- struct ldb_context *ldb;
- int i, a=0;
-
- ldb = ldb_module_get_ctx(module);
-
- for (a=0;attrs && attrs[a];a++) {
- for (i=0;i<ARRAY_SIZE(search_sub);i++) {
- if (ldb_attr_cmp(attrs[a], search_sub[i].attr) != 0) {
- continue;
- }
-
- /* construct the new attribute, using either a supplied
- constructor or a simple copy */
- if (search_sub[i].constructor) {
- if (search_sub[i].constructor(module, msg) != 0) {
- goto failed;
- }
- } else if (ldb_msg_copy_attr(msg,
- search_sub[i].replace,
- search_sub[i].attr) != 0) {
- goto failed;
- }
-
- /* remove the added search attribute, unless it was asked for
- by the user */
- if (search_sub[i].replace == NULL ||
- ldb_attr_in_list(attrs, search_sub[i].replace) ||
- ldb_attr_in_list(attrs, "*")) {
- continue;
- }
-
- ldb_msg_remove_attr(msg, search_sub[i].replace);
- }
- }
-
- return 0;
-
-failed:
- ldb_debug_set(ldb, LDB_DEBUG_WARNING,
- "operational_search_post_process failed for attribute '%s'\n",
- attrs[a]);
- return -1;
-}
-
-
-/*
- hook search operations
-*/
-
-struct operational_context {
- struct ldb_module *module;
- struct ldb_request *req;
-
- const char * const *attrs;
-};
-
-static int operational_callback(struct ldb_request *req, struct ldb_reply *ares)
-{
- struct operational_context *ac;
- int ret;
-
- ac = talloc_get_type(req->context, struct operational_context);
-
- if (!ares) {
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
- if (ares->error != LDB_SUCCESS) {
- return ldb_module_done(ac->req, ares->controls,
- ares->response, ares->error);
- }
-
- switch (ares->type) {
- case LDB_REPLY_ENTRY:
- /* for each record returned post-process to add any derived
- attributes that have been asked for */
- ret = operational_search_post_process(ac->module,
- ares->message,
- ac->attrs);
- if (ret != 0) {
- return ldb_module_done(ac->req, NULL, NULL,
- LDB_ERR_OPERATIONS_ERROR);
- }
- return ldb_module_send_entry(ac->req, ares->message, ares->controls);
-
- case LDB_REPLY_REFERRAL:
- /* ignore referrals */
- break;
-
- case LDB_REPLY_DONE:
-
- return ldb_module_done(ac->req, ares->controls,
- ares->response, LDB_SUCCESS);
- }
-
- talloc_free(ares);
- return LDB_SUCCESS;
-}
-
-static int operational_search(struct ldb_module *module, struct ldb_request *req)
-{
- struct ldb_context *ldb;
- struct operational_context *ac;
- struct ldb_request *down_req;
- const char **search_attrs = NULL;
- int i, a;
- int ret;
-
- ldb = ldb_module_get_ctx(module);
-
- ac = talloc(req, struct operational_context);
- if (ac == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- ac->module = module;
- ac->req = req;
- ac->attrs = req->op.search.attrs;
-
- /* FIXME: We must copy the tree and keep the original
- * unmodified. SSS */
- /* replace any attributes in the parse tree that are
- searchable, but are stored using a different name in the
- backend */
- for (i=0;i<ARRAY_SIZE(parse_tree_sub);i++) {
- ldb_parse_tree_attr_replace(req->op.search.tree,
- parse_tree_sub[i].attr,
- parse_tree_sub[i].replace);
- }
-
- /* in the list of attributes we are looking for, rename any
- attributes to the alias for any hidden attributes that can
- be fetched directly using non-hidden names */
- for (a=0;ac->attrs && ac->attrs[a];a++) {
- for (i=0;i<ARRAY_SIZE(search_sub);i++) {
- if (ldb_attr_cmp(ac->attrs[a], search_sub[i].attr) == 0 &&
- search_sub[i].replace) {
- if (!search_attrs) {
- search_attrs = ldb_attr_list_copy(req, ac->attrs);
- if (search_attrs == NULL) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
- }
- search_attrs[a] = search_sub[i].replace;
- }
- }
- }
-
- ret = ldb_build_search_req_ex(&down_req, ldb, ac,
- req->op.search.base,
- req->op.search.scope,
- req->op.search.tree,
- /* use new set of attrs if any */
- search_attrs == NULL?req->op.search.attrs:search_attrs,
- req->controls,
- ac, operational_callback,
- req);
- if (ret != LDB_SUCCESS) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- /* perform the search */
- return ldb_next_request(module, down_req);
-}
-
-static int operational_init(struct ldb_module *ctx)
-{
- int ret = 0;
-
- if (ret != 0) {
- return ret;
- }
-
- return ldb_next_init(ctx);
-}
-
-const struct ldb_module_ops ldb_operational_module_ops = {
- .name = "operational",
- .search = operational_search,
- .init_context = operational_init
-};
diff --git a/source4/lib/ldb/modules/paged_results.c b/source4/lib/ldb/modules/paged_results.c
index 2a06c5e6c5..b712f84872 100644
--- a/source4/lib/ldb/modules/paged_results.c
+++ b/source4/lib/ldb/modules/paged_results.c
@@ -408,8 +408,8 @@ static int paged_request_init(struct ldb_module *module)
ret = ldb_mod_register_control(module, LDB_CONTROL_PAGED_RESULTS_OID);
if (ret != LDB_SUCCESS) {
ldb_debug(ldb, LDB_DEBUG_WARNING,
- "paged_request:"
- "Unable to register control with rootdse!\n");
+ "paged_results:"
+ "Unable to register control with rootdse!");
}
return ldb_next_init(module);
diff --git a/source4/lib/ldb/modules/paged_searches.c b/source4/lib/ldb/modules/paged_searches.c
index 01e77cb22c..c5430eb9bf 100644
--- a/source4/lib/ldb/modules/paged_searches.c
+++ b/source4/lib/ldb/modules/paged_searches.c
@@ -2,6 +2,7 @@
ldb database library
Copyright (C) Simo Sorce 2005-2008
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -52,23 +53,40 @@ struct ps_context {
char **saved_referrals;
int num_referrals;
+
+ struct ldb_request *down_req;
};
-static int check_ps_continuation(struct ldb_request *req, struct ldb_reply *ares)
+static int check_ps_continuation(struct ps_context *ac, struct ldb_request *req, struct ldb_reply *ares)
{
- struct ps_context *ac;
- struct ldb_paged_control *rep_control, *req_control;
+ struct ldb_context *ldb;
+ struct ldb_control *rep_control, *req_control;
+ struct ldb_paged_control *paged_rep_control = NULL, *paged_req_control = NULL;
+ ldb = ldb_module_get_ctx(ac->module);
- ac = talloc_get_type(req->context, struct ps_context);
+ rep_control = ldb_reply_get_control(ares, LDB_CONTROL_PAGED_RESULTS_OID);
+ if (rep_control) {
+ paged_rep_control = talloc_get_type(rep_control->data, struct ldb_paged_control);
+ }
- /* look up our paged control */
- if (!ares->controls || strcmp(LDB_CONTROL_PAGED_RESULTS_OID, ares->controls[0]->oid) != 0) {
- /* something wrong here */
- return LDB_ERR_OPERATIONS_ERROR;
+ req_control = ldb_request_get_control(req, LDB_CONTROL_PAGED_RESULTS_OID);
+ paged_req_control = talloc_get_type(req_control->data, struct ldb_paged_control);
+
+ if (!rep_control || !paged_rep_control) {
+ if (paged_req_control->cookie) {
+ /* something wrong here - why give us a control back befre, but not one now? */
+ ldb_set_errstring(ldb, "paged_searches: ERROR: We got back a control from a previous page, but this time no control was returned!");
+ return LDB_ERR_OPERATIONS_ERROR;
+ } else {
+ /* No cookie recived yet, valid to just return the full data set */
+
+ /* we are done */
+ ac->pending = false;
+ return LDB_SUCCESS;
+ }
}
- rep_control = talloc_get_type(ares->controls[0]->data, struct ldb_paged_control);
- if (rep_control->cookie_len == 0) {
+ if (paged_rep_control->cookie_len == 0) {
/* we are done */
ac->pending = false;
return LDB_SUCCESS;
@@ -79,21 +97,14 @@ static int check_ps_continuation(struct ldb_request *req, struct ldb_reply *ares
/* if there's a reply control we must find a request
* control matching it */
- if (strcmp(LDB_CONTROL_PAGED_RESULTS_OID, req->controls[0]->oid) != 0) {
- /* something wrong here */
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- req_control = talloc_get_type(req->controls[0]->data, struct ldb_paged_control);
-
- if (req_control->cookie) {
- talloc_free(req_control->cookie);
+ if (paged_req_control->cookie) {
+ talloc_free(paged_req_control->cookie);
}
- req_control->cookie = talloc_memdup(req_control,
- rep_control->cookie,
- rep_control->cookie_len);
- req_control->cookie_len = rep_control->cookie_len;
+ paged_req_control->cookie = talloc_memdup(req_control,
+ paged_rep_control->cookie,
+ paged_rep_control->cookie_len);
+ paged_req_control->cookie_len = paged_rep_control->cookie_len;
ac->pending = true;
return LDB_SUCCESS;
@@ -141,8 +152,6 @@ static int send_referrals(struct ps_context *ac)
return LDB_SUCCESS;
}
-static int ps_next_request(struct ps_context *ac);
-
static int ps_callback(struct ldb_request *req, struct ldb_reply *ares)
{
struct ps_context *ac;
@@ -176,14 +185,15 @@ static int ps_callback(struct ldb_request *req, struct ldb_reply *ares)
case LDB_REPLY_DONE:
- ret = check_ps_continuation(req, ares);
+ ret = check_ps_continuation(ac, req, ares);
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req, NULL, NULL, ret);
}
if (ac->pending) {
- ret = ps_next_request(ac);
+ ret = ldb_next_request(ac->module, ac->down_req);
+
if (ret != LDB_SUCCESS) {
return ldb_module_done(ac->req,
NULL, NULL, ret);
@@ -214,14 +224,16 @@ static int ps_search(struct ldb_module *module, struct ldb_request *req)
struct ldb_context *ldb;
struct private_data *private_data;
struct ps_context *ac;
+ struct ldb_paged_control *control;
+ int ret;
private_data = talloc_get_type(ldb_module_get_private(module), struct private_data);
ldb = ldb_module_get_ctx(module);
- /* check if paging is supported and if there is a any control */
- if (!private_data || !private_data->paged_supported || req->controls) {
+ /* check if paging is supported */
+ if (!private_data || !private_data->paged_supported) {
/* do not touch this request paged controls not
- * supported or explicit controls have been set or we
+ * supported or we
* are just not setup yet */
return ldb_next_request(module, req);
}
@@ -238,30 +250,9 @@ static int ps_search(struct ldb_module *module, struct ldb_request *req)
ac->saved_referrals = NULL;
ac->num_referrals = 0;
- return ps_next_request(ac);
-}
-
-static int ps_next_request(struct ps_context *ac) {
-
- struct ldb_context *ldb;
- struct ldb_paged_control *control;
- struct ldb_control **controls;
- struct ldb_request *new_req;
- int ret;
-
ldb = ldb_module_get_ctx(ac->module);
- controls = talloc_array(ac, struct ldb_control *, 2);
- if (!controls) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- controls[0] = talloc(controls, struct ldb_control);
- if (!controls[0]) {
- return LDB_ERR_OPERATIONS_ERROR;
- }
-
- control = talloc(controls[0], struct ldb_paged_control);
+ control = talloc(ac, struct ldb_paged_control);
if (!control) {
return LDB_ERR_OPERATIONS_ERROR;
}
@@ -270,26 +261,28 @@ static int ps_next_request(struct ps_context *ac) {
control->cookie = NULL;
control->cookie_len = 0;
- controls[0]->oid = LDB_CONTROL_PAGED_RESULTS_OID;
- controls[0]->critical = 1;
- controls[0]->data = control;
- controls[1] = NULL;
-
- ret = ldb_build_search_req_ex(&new_req, ldb, ac,
+ ret = ldb_build_search_req_ex(&ac->down_req, ldb, ac,
ac->req->op.search.base,
ac->req->op.search.scope,
ac->req->op.search.tree,
ac->req->op.search.attrs,
- controls,
+ ac->req->controls,
ac,
ps_callback,
ac->req);
if (ret != LDB_SUCCESS) {
return ret;
}
- talloc_steal(new_req, controls);
- return ldb_next_request(ac->module, new_req);
+ ret = ldb_request_add_control(ac->down_req, LDB_CONTROL_PAGED_RESULTS_OID,
+ true, control);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+
+ talloc_steal(ac->down_req, control);
+
+ return ldb_next_request(ac->module, ac->down_req);
}
static int check_supported_paged(struct ldb_request *req,
diff --git a/source4/lib/ldb/modules/rdn_name.c b/source4/lib/ldb/modules/rdn_name.c
index 880678d89d..8b54f52b5e 100644
--- a/source4/lib/ldb/modules/rdn_name.c
+++ b/source4/lib/ldb/modules/rdn_name.c
@@ -1,8 +1,8 @@
/*
ldb database library
- Copyright (C) Andrew Bartlet 2005
- Copyright (C) Simo Sorce 2006-2008
+ Copyright (C) Andrew Bartlett 2005
+ Copyright (C) Simo Sorce 2006-2008
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
@@ -23,13 +23,13 @@
*/
/*
- * Name: rdb_name
+ * Name: rdn_name
*
* Component: ldb rdn name module
*
* Description: keep a consistent name attribute on objects manpulations
*
- * Author: Andrew Bartlet
+ * Author: Andrew Bartlett
*
* Modifications:
* - made the module async
@@ -98,7 +98,7 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
int i, ret;
ldb = ldb_module_get_ctx(module);
- ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_add_record\n");
+ ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_add_record");
/* do not manipulate our control entries */
if (ldb_dn_is_special(req->op.add.message->dn)) {
@@ -156,9 +156,15 @@ static int rdn_name_add(struct ldb_module *module, struct ldb_request *req)
}
}
if (i == attribute->num_values) {
- ldb_debug_set(ldb, LDB_DEBUG_FATAL,
- "RDN mismatch on %s: %s (%s)",
- ldb_dn_get_linearized(msg->dn), rdn_name, rdn_val.data);
+ char *rdn_errstring = talloc_asprintf(ac, "RDN mismatch on %s: %s (%.*s) should match one of:",
+ ldb_dn_get_linearized(msg->dn), rdn_name,
+ (int)rdn_val.length, (const char *)rdn_val.data);
+ for (i = 0; i < attribute->num_values; i++) {
+ rdn_errstring = talloc_asprintf_append(rdn_errstring, " (%.*s)",
+ (int)attribute->values[i].length,
+ (const char *)attribute->values[i].data);
+ }
+ ldb_debug_set(ldb, LDB_DEBUG_FATAL, "%s", rdn_errstring);
talloc_free(ac);
/* Match AD's error here */
return LDB_ERR_INVALID_DN_SYNTAX;
@@ -288,7 +294,7 @@ static int rdn_name_rename(struct ldb_module *module, struct ldb_request *req)
int ret;
ldb = ldb_module_get_ctx(module);
- ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_rename\n");
+ ldb_debug(ldb, LDB_DEBUG_TRACE, "rdn_name_rename");
/* do not manipulate our control entries */
if (ldb_dn_is_special(req->op.rename.newdn)) {
diff --git a/source4/lib/ldb/modules/sort.c b/source4/lib/ldb/modules/sort.c
index 309101c32b..b4ea017b32 100644
--- a/source4/lib/ldb/modules/sort.c
+++ b/source4/lib/ldb/modules/sort.c
@@ -117,10 +117,13 @@ static int sort_compare(struct ldb_message **msg1, struct ldb_message **msg2, vo
el1 = ldb_msg_find_element(*msg1, ac->attributeName);
el2 = ldb_msg_find_element(*msg2, ac->attributeName);
- if (!el1 || !el2) {
- /* the attribute was not found return and
- * set an error */
- ac->sort_result = LDB_ERR_UNWILLING_TO_PERFORM;
+ if (!el1 && el2) {
+ return 1;
+ }
+ if (el1 && !el2) {
+ return -1;
+ }
+ if (!el1 && !el2) {
return 0;
}
@@ -255,7 +258,7 @@ static int server_sort_search(struct ldb_module *module, struct ldb_request *req
ldb = ldb_module_get_ctx(module);
- /* check if there's a paged request control */
+ /* check if there's a server sort control */
control = ldb_request_get_control(req, LDB_CONTROL_SERVER_SORT_OID);
if (control == NULL) {
/* not found go on */
@@ -336,7 +339,7 @@ static int server_sort_init(struct ldb_module *module)
if (ret != LDB_SUCCESS) {
ldb_debug(ldb, LDB_DEBUG_WARNING,
"server_sort:"
- "Unable to register control with rootdse!\n");
+ "Unable to register control with rootdse!");
}
return ldb_next_init(module);
diff --git a/source4/lib/ldb/pyldb.c b/source4/lib/ldb/pyldb.c
index 81b960979f..1ba5109f2f 100644
--- a/source4/lib/ldb/pyldb.c
+++ b/source4/lib/ldb/pyldb.c
@@ -1,16 +1,17 @@
/*
Unix SMB/CIFS implementation.
- Swig interface to ldb.
+ Python interface to ldb.
Copyright (C) 2005,2006 Tim Potter <tpot@samba.org>
Copyright (C) 2006 Simo Sorce <idra@samba.org>
- Copyright (C) 2007-2008 Jelmer Vernooij <jelmer@samba.org>
+ Copyright (C) 2007-2009 Jelmer Vernooij <jelmer@samba.org>
+ Copyright (C) 2009 Matthias Dieter Wallnöfer
** NOTE! The following LGPL license applies to the ldb
** library. This does NOT imply that all of Samba is released
** under the LGPL
-
+
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
@@ -41,49 +42,50 @@ typedef intargfunc ssizeargfunc;
#define Py_RETURN_NONE return Py_INCREF(Py_None), Py_None
#endif
-/* Picked out of thin air. To do this properly, we should probably have some part of the
- * errors in LDB be allocated to bindings ? */
-#define LDB_ERR_PYTHON_EXCEPTION 142
-
-static PyObject *PyExc_LdbError;
-
-void PyErr_SetLdbError(int ret, struct ldb_context *ldb_ctx)
+static void PyErr_SetLdbError(PyObject *error, int ret, struct ldb_context *ldb_ctx)
{
if (ret == LDB_ERR_PYTHON_EXCEPTION)
return; /* Python exception should already be set, just keep that */
- PyErr_SetObject(PyExc_LdbError, Py_BuildValue(discard_const_p(char, "(i,s)"),
- ret, ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
+
+ PyErr_SetObject(error,
+ Py_BuildValue(discard_const_p(char, "(i,s)"), ret,
+ ldb_ctx == NULL?ldb_strerror(ret):ldb_errstring(ldb_ctx)));
}
+static PyObject *PyExc_LdbError;
+
+PyAPI_DATA(PyTypeObject) PyLdbMessage;
+PyAPI_DATA(PyTypeObject) PyLdbModule;
+PyAPI_DATA(PyTypeObject) PyLdbDn;
+PyAPI_DATA(PyTypeObject) PyLdb;
+PyAPI_DATA(PyTypeObject) PyLdbMessageElement;
+PyAPI_DATA(PyTypeObject) PyLdbTree;
+
static PyObject *PyObject_FromLdbValue(struct ldb_context *ldb_ctx,
struct ldb_message_element *el,
struct ldb_val *val)
{
- const struct ldb_schema_attribute *a;
struct ldb_val new_val;
TALLOC_CTX *mem_ctx = talloc_new(NULL);
PyObject *ret;
-
+
new_val = *val;
-
- if (ldb_ctx != NULL) {
- a = ldb_schema_attribute_by_name(ldb_ctx, el->name);
-
- if (a != NULL) {
- if (a->syntax->ldif_write_fn(ldb_ctx, mem_ctx, val, &new_val) != 0) {
- talloc_free(mem_ctx);
- return NULL;
- }
- }
- }
-
+
ret = PyString_FromStringAndSize((const char *)new_val.data, new_val.length);
-
+
talloc_free(mem_ctx);
-
+
return ret;
}
+/**
+ * Obtain a ldb DN from a Python object.
+ *
+ * @param mem_ctx Memory context
+ * @param object Python object
+ * @param ldb_ctx LDB context
+ * @return Whether or not the conversion succeeded
+ */
bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object,
struct ldb_context *ldb_ctx, struct ldb_dn **dn)
{
@@ -104,6 +106,12 @@ bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object,
return false;
}
+/**
+ * Create a Python object from a ldb_result.
+ *
+ * @param result LDB result to convert
+ * @return Python object with converted result (a list object)
+ */
static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
{
PyObject *ret;
@@ -119,11 +127,20 @@ static PyObject *PyLdbResult_FromResult(struct ldb_result *result)
return ret;
}
-static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx, PyObject *obj)
+/**
+ * Create a LDB Result from a Python object.
+ * If conversion fails, NULL will be returned and a Python exception set.
+ *
+ * @param mem_ctx Memory context in which to allocate the LDB Result
+ * @param obj Python object to convert
+ * @return a ldb_result, or NULL if the conversion failed
+ */
+static struct ldb_result *PyLdbResult_AsResult(TALLOC_CTX *mem_ctx,
+ PyObject *obj)
{
struct ldb_result *res;
int i;
-
+
if (obj == Py_None)
return NULL;
@@ -194,13 +211,35 @@ static PyObject *py_ldb_dn_check_special(PyLdbDnObject *self, PyObject *args)
static int py_ldb_dn_compare(PyLdbDnObject *dn1, PyLdbDnObject *dn2)
{
- return ldb_dn_compare(dn1->dn, dn2->dn);
+ int ret;
+ ret = ldb_dn_compare(dn1->dn, dn2->dn);
+ if (ret < 0) ret = -1;
+ if (ret > 0) ret = 1;
+ return ret;
}
static PyObject *py_ldb_dn_get_parent(PyLdbDnObject *self)
{
struct ldb_dn *dn = PyLdbDn_AsDn((PyObject *)self);
- return PyLdbDn_FromDn(ldb_dn_get_parent(NULL, dn));
+ struct ldb_dn *parent;
+ PyLdbDnObject *py_ret;
+ TALLOC_CTX *mem_ctx = talloc_new(NULL);
+
+ parent = ldb_dn_get_parent(mem_ctx, dn);
+ if (parent == NULL) {
+ talloc_free(mem_ctx);
+ Py_RETURN_NONE;
+ }
+
+ py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
+ if (py_ret == NULL) {
+ PyErr_NoMemory();
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+ py_ret->mem_ctx = mem_ctx;
+ py_ret->dn = parent;
+ return (PyObject *)py_ret;
}
#define dn_ldb_ctx(dn) ((struct ldb_context *)dn)
@@ -281,11 +320,20 @@ static PyObject *py_ldb_dn_concat(PyLdbDnObject *self, PyObject *py_other)
{
struct ldb_dn *dn = PyLdbDn_AsDn((PyObject *)self),
*other;
- struct ldb_dn *ret = ldb_dn_copy(NULL, dn);
+ PyLdbDnObject *py_ret;
+
if (!PyObject_AsDn(NULL, py_other, NULL, &other))
return NULL;
- ldb_dn_add_child(ret, other);
- return PyLdbDn_FromDn(ret);
+
+ py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
+ if (py_ret == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+ py_ret->mem_ctx = talloc_new(NULL);
+ py_ret->dn = ldb_dn_copy(py_ret->mem_ctx, dn);
+ ldb_dn_add_child(py_ret->dn, other);
+ return (PyObject *)py_ret;
}
static PySequenceMethods py_ldb_dn_seq = {
@@ -299,6 +347,7 @@ static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwa
char *str;
PyObject *py_ldb;
struct ldb_context *ldb_ctx;
+ TALLOC_CTX *mem_ctx;
PyLdbDnObject *py_ret;
const char * const kwnames[] = { "ldb", "dn", NULL };
@@ -308,22 +357,28 @@ static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwa
return NULL;
ldb_ctx = PyLdb_AsLdbContext(py_ldb);
-
- ret = ldb_dn_new(ldb_ctx, ldb_ctx, str);
- /* ldb_dn_new() doesn't accept NULL as memory context, so
- we do it this way... */
- talloc_steal(NULL, ret);
+
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ ret = ldb_dn_new(mem_ctx, ldb_ctx, str);
if (ret == NULL || !ldb_dn_validate(ret)) {
+ talloc_free(mem_ctx);
PyErr_SetString(PyExc_ValueError, "unable to parse dn string");
return NULL;
}
py_ret = (PyLdbDnObject *)type->tp_alloc(type, 0);
if (ret == NULL) {
+ talloc_free(mem_ctx);
PyErr_NoMemory();
return NULL;
}
+ py_ret->mem_ctx = mem_ctx;
py_ret->dn = ret;
return (PyObject *)py_ret;
}
@@ -331,6 +386,11 @@ static PyObject *py_ldb_dn_new(PyTypeObject *type, PyObject *args, PyObject *kwa
PyObject *PyLdbDn_FromDn(struct ldb_dn *dn)
{
PyLdbDnObject *py_ret;
+
+ if (dn == NULL) {
+ Py_RETURN_NONE;
+ }
+
py_ret = (PyLdbDnObject *)PyLdbDn.tp_alloc(&PyLdbDn, 0);
if (py_ret == NULL) {
PyErr_NoMemory();
@@ -372,14 +432,14 @@ static void py_ldb_debug(void *context, enum ldb_debug_level level, const char *
static PyObject *py_ldb_set_debug(PyLdbObject *self, PyObject *args)
{
PyObject *cb;
-
+
if (!PyArg_ParseTuple(args, "O", &cb))
return NULL;
Py_INCREF(cb);
/* FIXME: Where do we DECREF cb ? */
- PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_set_debug(self->ldb_ctx, py_ldb_debug, cb), PyLdb_AsLdbContext(self));
-
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_set_debug(self->ldb_ctx, py_ldb_debug, cb), PyLdb_AsLdbContext(self));
+
Py_RETURN_NONE;
}
@@ -407,25 +467,25 @@ static PyObject *py_ldb_set_modules_dir(PyTypeObject *self, PyObject *args)
static PyObject *py_ldb_transaction_start(PyLdbObject *self)
{
- PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_start(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_start(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
Py_RETURN_NONE;
}
static PyObject *py_ldb_transaction_commit(PyLdbObject *self)
{
- PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_commit(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
Py_RETURN_NONE;
}
static PyObject *py_ldb_transaction_cancel(PyLdbObject *self)
{
- PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_transaction_cancel(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_transaction_cancel(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
Py_RETURN_NONE;
}
static PyObject *py_ldb_setup_wellknown_attributes(PyLdbObject *self)
{
- PyErr_LDB_ERROR_IS_ERR_RAISE(ldb_setup_wellknown_attributes(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ldb_setup_wellknown_attributes(PyLdb_AsLdbContext(self)), PyLdb_AsLdbContext(self));
Py_RETURN_NONE;
}
@@ -451,7 +511,6 @@ static PyObject *py_ldb_get_schema_basedn(PyLdbObject *self)
return PyLdbDn_FromDn(dn);
}
-
static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
{
struct ldb_dn *dn = ldb_get_config_basedn(PyLdb_AsLdbContext(self));
@@ -460,7 +519,6 @@ static PyObject *py_ldb_get_config_basedn(PyLdbObject *self)
return PyLdbDn_FromDn(dn);
}
-
static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
{
struct ldb_dn *dn = ldb_get_default_basedn(PyLdb_AsLdbContext(self));
@@ -469,22 +527,24 @@ static PyObject *py_ldb_get_default_basedn(PyLdbObject *self)
return PyLdbDn_FromDn(dn);
}
-static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list)
+static const char **PyList_AsStringList(TALLOC_CTX *mem_ctx, PyObject *list,
+ const char *paramname)
{
const char **ret;
int i;
if (!PyList_Check(list)) {
- PyErr_SetString(PyExc_TypeError, "options is not a list");
+ PyErr_Format(PyExc_TypeError, "%s is not a list", paramname);
return NULL;
}
ret = talloc_array(NULL, const char *, PyList_Size(list)+1);
for (i = 0; i < PyList_Size(list); i++) {
PyObject *item = PyList_GetItem(list, i);
if (!PyString_Check(item)) {
- PyErr_SetString(PyExc_TypeError, "options should be strings");
+ PyErr_Format(PyExc_TypeError, "%s should be strings", paramname);
return NULL;
}
- ret[i] = PyString_AsString(item);
+ ret[i] = talloc_strndup(ret, PyString_AsString(item),
+ PyString_Size(item));
}
ret[i] = NULL;
return ret;
@@ -510,15 +570,15 @@ static int py_ldb_init(PyLdbObject *self, PyObject *args, PyObject *kwargs)
if (py_options == Py_None) {
options = NULL;
} else {
- options = PyList_AsStringList(ldb, py_options);
+ options = PyList_AsStringList(ldb, py_options, "options");
if (options == NULL)
return -1;
}
-
+
if (url != NULL) {
ret = ldb_connect(ldb, url, flags, options);
if (ret != LDB_SUCCESS) {
- PyErr_SetLdbError(ret, ldb);
+ PyErr_SetLdbError(PyExc_LdbError, ret, ldb);
return -1;
}
}
@@ -531,17 +591,19 @@ static PyObject *py_ldb_new(PyTypeObject *type, PyObject *args, PyObject *kwargs
{
PyLdbObject *ret;
struct ldb_context *ldb;
- ldb = ldb_init(NULL, NULL);
- if (ldb == NULL) {
+ ret = (PyLdbObject *)type->tp_alloc(type, 0);
+ if (ret == NULL) {
PyErr_NoMemory();
return NULL;
}
+ ret->mem_ctx = talloc_new(NULL);
+ ldb = ldb_init(ret->mem_ctx, NULL);
- ret = (PyLdbObject *)type->tp_alloc(type, 0);
- if (ret == NULL) {
+ if (ldb == NULL) {
PyErr_NoMemory();
return NULL;
}
+
ret->ldb_ctx = ldb;
return (PyObject *)ret;
}
@@ -555,7 +617,7 @@ static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwa
const char **options;
const char * const kwnames[] = { "url", "flags", "options", NULL };
- if (!PyArg_ParseTupleAndKeywords(args, kwargs, "s|iO",
+ if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|ziO",
discard_const_p(char *, kwnames),
&url, &flags, &py_options))
return NULL;
@@ -563,15 +625,15 @@ static PyObject *py_ldb_connect(PyLdbObject *self, PyObject *args, PyObject *kwa
if (py_options == Py_None) {
options = NULL;
} else {
- options = PyList_AsStringList(NULL, py_options);
+ options = PyList_AsStringList(NULL, py_options, "options");
if (options == NULL)
return NULL;
}
-
+
ret = ldb_connect(PyLdb_AsLdbContext(self), url, flags, options);
talloc_free(options);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
Py_RETURN_NONE;
}
@@ -589,7 +651,7 @@ static PyObject *py_ldb_modify(PyLdbObject *self, PyObject *args)
}
ret = ldb_modify(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg));
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
Py_RETURN_NONE;
}
@@ -601,23 +663,39 @@ static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
Py_ssize_t dict_pos, msg_pos;
struct ldb_message_element *msgel;
struct ldb_message *msg;
+ struct ldb_context *ldb_ctx;
+ struct ldb_request *req;
PyObject *key, *value;
+ PyObject *py_controls = Py_None;
+ TALLOC_CTX *mem_ctx;
+ struct ldb_control **parsed_controls;
- if (!PyArg_ParseTuple(args, "O", &py_msg))
+ if (!PyArg_ParseTuple(args, "O|O", &py_msg, &py_controls ))
return NULL;
+ ldb_ctx = PyLdb_AsLdbContext(self);
+ mem_ctx = talloc_new(NULL);
+ if (py_controls == Py_None) {
+ parsed_controls = NULL;
+ } else {
+ const char **controls = PyList_AsStringList(ldb_ctx, py_controls, "controls");
+ parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);
+ talloc_free(controls);
+ }
if (PyDict_Check(py_msg)) {
PyObject *dn_value = PyDict_GetItemString(py_msg, "dn");
- msg = ldb_msg_new(NULL);
+ msg = ldb_msg_new(mem_ctx);
msg->elements = talloc_zero_array(msg, struct ldb_message_element, PyDict_Size(py_msg));
msg_pos = dict_pos = 0;
if (dn_value) {
- if (!PyObject_AsDn(msg, dn_value, PyLdb_AsLdbContext(self), &msg->dn)) {
+ if (!PyObject_AsDn(msg, dn_value, ldb_ctx, &msg->dn)) {
PyErr_SetString(PyExc_TypeError, "unable to import dn object");
+ talloc_free(mem_ctx);
return NULL;
}
if (msg->dn == NULL) {
PyErr_SetString(PyExc_TypeError, "dn set but not found");
+ talloc_free(mem_ctx);
return NULL;
}
}
@@ -628,6 +706,7 @@ static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
msgel = PyObject_AsMessageElement(msg->elements, value, 0, key_str);
if (msgel == NULL) {
PyErr_SetString(PyExc_TypeError, "unable to import element");
+ talloc_free(mem_ctx);
return NULL;
}
memcpy(&msg->elements[msg_pos], msgel, sizeof(*msgel));
@@ -637,6 +716,7 @@ static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
if (msg->dn == NULL) {
PyErr_SetString(PyExc_TypeError, "no dn set");
+ talloc_free(mem_ctx);
return NULL;
}
@@ -644,14 +724,57 @@ static PyObject *py_ldb_add(PyLdbObject *self, PyObject *args)
} else {
msg = PyLdbMessage_AsMessage(py_msg);
}
-
- ret = ldb_add(PyLdb_AsLdbContext(self), msg);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
+
+ ret = ldb_msg_sanity_check(ldb_ctx, msg);
+ if (ret != LDB_SUCCESS) {
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
+ talloc_free(mem_ctx);
+ return NULL;
+ }
- Py_RETURN_NONE;
-}
+ ret = ldb_build_add_req(&req, ldb_ctx, ldb_ctx,
+ msg,
+ parsed_controls,
+ NULL,
+ ldb_op_default_callback,
+ NULL);
+ if (ret != LDB_SUCCESS) {
+ PyErr_SetString(PyExc_TypeError, "failed to build request");
+ talloc_free(mem_ctx);
+ return NULL;
+ }
+
+ /* do request and autostart a transaction */
+ /* Then let's LDB handle the message error in case of pb as they are meaningful */
+
+ ret = ldb_transaction_start(ldb_ctx);
+ if (ret != LDB_SUCCESS) {
+ talloc_free(req);
+ talloc_free(mem_ctx);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
+ }
+ ret = ldb_request(ldb_ctx, req);
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_wait(req->handle, LDB_WAIT_ALL);
+ }
+
+ if (ret == LDB_SUCCESS) {
+ ret = ldb_transaction_commit(ldb_ctx);
+ } else {
+ ldb_transaction_cancel(ldb_ctx);
+ if (ldb_ctx->err_string == NULL) {
+ /* no error string was setup by the backend */
+ ldb_asprintf_errstring(ldb_ctx, "%s (%d)", ldb_strerror(ret), ret);
+ }
+ }
+ talloc_free(req);
+ talloc_free(mem_ctx);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
+
+ Py_RETURN_NONE;
+}
static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args)
{
@@ -668,7 +791,7 @@ static PyObject *py_ldb_delete(PyLdbObject *self, PyObject *args)
return NULL;
ret = ldb_delete(ldb, dn);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
Py_RETURN_NONE;
}
@@ -679,18 +802,29 @@ static PyObject *py_ldb_rename(PyLdbObject *self, PyObject *args)
struct ldb_dn *dn1, *dn2;
int ret;
struct ldb_context *ldb;
+ TALLOC_CTX *mem_ctx;
if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
return NULL;
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
ldb = PyLdb_AsLdbContext(self);
- if (!PyObject_AsDn(NULL, py_dn1, ldb, &dn1))
+ if (!PyObject_AsDn(mem_ctx, py_dn1, ldb, &dn1)) {
+ talloc_free(mem_ctx);
return NULL;
+ }
- if (!PyObject_AsDn(NULL, py_dn2, ldb, &dn2))
+ if (!PyObject_AsDn(mem_ctx, py_dn2, ldb, &dn2)) {
+ talloc_free(mem_ctx);
return NULL;
+ }
ret = ldb_rename(ldb, dn1, dn2);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb);
+ talloc_free(mem_ctx);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb);
Py_RETURN_NONE;
}
@@ -716,7 +850,7 @@ static PyObject *py_ldb_schema_attribute_add(PyLdbObject *self, PyObject *args)
ret = ldb_schema_attribute_add(PyLdb_AsLdbContext(self), attribute, flags, syntax);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, PyLdb_AsLdbContext(self));
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, PyLdb_AsLdbContext(self));
Py_RETURN_NONE;
}
@@ -727,7 +861,6 @@ static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
Py_RETURN_NONE;
} else {
/* We don't want this attached to the 'ldb' any more */
- talloc_steal(NULL, ldif);
return Py_BuildValue(discard_const_p(char, "(iO)"),
ldif->changetype,
PyLdbMessage_FromMessage(ldif->msg));
@@ -735,22 +868,102 @@ static PyObject *ldb_ldif_to_pyobject(struct ldb_ldif *ldif)
}
+static PyObject *py_ldb_write_ldif(PyLdbMessageObject *self, PyObject *args)
+{
+ int changetype;
+ PyObject *py_msg;
+ struct ldb_ldif ldif;
+ PyObject *ret;
+ char *string;
+ TALLOC_CTX *mem_ctx;
+
+ if (!PyArg_ParseTuple(args, "Oi", &py_msg, &changetype))
+ return NULL;
+
+ if (!PyLdbMessage_Check(py_msg)) {
+ PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for msg");
+ return NULL;
+ }
+
+ ldif.msg = PyLdbMessage_AsMessage(py_msg);
+ ldif.changetype = changetype;
+
+ mem_ctx = talloc_new(NULL);
+
+ string = ldb_ldif_write_string(PyLdb_AsLdbContext(self), mem_ctx, &ldif);
+ if (!string) {
+ PyErr_SetString(PyExc_KeyError, "Failed to generate LDIF");
+ return NULL;
+ }
+
+ ret = PyString_FromString(string);
+
+ talloc_free(mem_ctx);
+
+ return ret;
+}
+
static PyObject *py_ldb_parse_ldif(PyLdbObject *self, PyObject *args)
{
PyObject *list;
struct ldb_ldif *ldif;
const char *s;
+ TALLOC_CTX *mem_ctx;
+
if (!PyArg_ParseTuple(args, "s", &s))
return NULL;
+ mem_ctx = talloc_new(NULL);
+ if (!mem_ctx) {
+ Py_RETURN_NONE;
+ }
+
list = PyList_New(0);
- while ((ldif = ldb_ldif_read_string(self->ldb_ctx, &s)) != NULL) {
- PyList_Append(list, ldb_ldif_to_pyobject(ldif));
+ while (s && *s != '\0') {
+ ldif = ldb_ldif_read_string(self->ldb_ctx, &s);
+ talloc_steal(mem_ctx, ldif);
+ if (ldif) {
+ PyList_Append(list, ldb_ldif_to_pyobject(ldif));
+ } else {
+ PyErr_SetString(PyExc_ValueError, "unable to parse ldif string");
+ talloc_free(mem_ctx);
+ return NULL;
+ }
}
+ talloc_free(mem_ctx); /* The pyobject already has a reference to the things it needs */
return PyObject_GetIter(list);
}
+static PyObject *py_ldb_msg_diff(PyLdbObject *self, PyObject *args)
+{
+ PyObject *py_msg_old;
+ PyObject *py_msg_new;
+ struct ldb_message *diff;
+ PyObject *py_ret;
+
+ if (!PyArg_ParseTuple(args, "OO", &py_msg_old, &py_msg_new))
+ return NULL;
+
+ if (!PyLdbMessage_Check(py_msg_old)) {
+ PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for old message");
+ return NULL;
+ }
+
+ if (!PyLdbMessage_Check(py_msg_new)) {
+ PyErr_SetString(PyExc_TypeError, "Expected Ldb Message for new message");
+ return NULL;
+ }
+
+ diff = ldb_msg_diff(PyLdb_AsLdbContext(self), PyLdbMessage_AsMessage(py_msg_old), PyLdbMessage_AsMessage(py_msg_new));
+ if (diff == NULL)
+ return NULL;
+
+ py_ret = PyLdbMessage_FromMessage(diff);
+
+ return py_ret;
+}
+
static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
{
const struct ldb_schema_attribute *a;
@@ -763,18 +976,18 @@ static PyObject *py_ldb_schema_format_value(PyLdbObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "sO", &element_name, &val))
return NULL;
-
+
mem_ctx = talloc_new(NULL);
-
+
old_val.data = (uint8_t *)PyString_AsString(val);
old_val.length = PyString_Size(val);
-
+
a = ldb_schema_attribute_by_name(PyLdb_AsLdbContext(self), element_name);
if (a == NULL) {
Py_RETURN_NONE;
}
-
+
if (a->syntax->ldif_write_fn(PyLdb_AsLdbContext(self), mem_ctx, &old_val, &new_val) != 0) {
talloc_free(mem_ctx);
Py_RETURN_NONE;
@@ -802,6 +1015,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
struct ldb_context *ldb_ctx;
struct ldb_control **parsed_controls;
struct ldb_dn *base;
+ PyObject *py_ret;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|OizOO",
discard_const_p(char *, kwnames),
@@ -813,7 +1027,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_attrs == Py_None) {
attrs = NULL;
} else {
- attrs = PyList_AsStringList(ldb_ctx, py_attrs);
+ attrs = PyList_AsStringList(NULL, py_attrs, "attrs");
if (attrs == NULL)
return NULL;
}
@@ -821,14 +1035,16 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
if (py_base == Py_None) {
base = ldb_get_default_basedn(ldb_ctx);
} else {
- if (!PyObject_AsDn(ldb_ctx, py_base, ldb_ctx, &base))
+ if (!PyObject_AsDn(ldb_ctx, py_base, ldb_ctx, &base)) {
+ talloc_free(attrs);
return NULL;
+ }
}
if (py_controls == Py_None) {
parsed_controls = NULL;
} else {
- const char **controls = PyList_AsStringList(ldb_ctx, py_controls);
+ const char **controls = PyList_AsStringList(ldb_ctx, py_controls, "controls");
parsed_controls = ldb_parse_control_strings(ldb_ctx, ldb_ctx, controls);
talloc_free(controls);
}
@@ -836,6 +1052,7 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
res = talloc_zero(ldb_ctx, struct ldb_result);
if (res == NULL) {
PyErr_NoMemory();
+ talloc_free(attrs);
return NULL;
}
@@ -849,14 +1066,16 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
ldb_search_default_callback,
NULL);
+ talloc_steal(req, attrs);
+
if (ret != LDB_SUCCESS) {
talloc_free(res);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb_ctx);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
return NULL;
}
ret = ldb_request(ldb_ctx, req);
-
+
if (ret == LDB_SUCCESS) {
ret = ldb_wait(req->handle, LDB_WAIT_ALL);
}
@@ -865,11 +1084,15 @@ static PyObject *py_ldb_search(PyLdbObject *self, PyObject *args, PyObject *kwar
if (ret != LDB_SUCCESS) {
talloc_free(res);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, ldb_ctx);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, ldb_ctx);
return NULL;
}
- return PyLdbResult_FromResult(res);
+ py_ret = PyLdbResult_FromResult(res);
+
+ talloc_free(res);
+
+ return py_ret;
}
static PyObject *py_ldb_get_opaque(PyLdbObject *self, PyObject *args)
@@ -983,6 +1206,12 @@ static PyMethodDef py_ldb_methods[] = {
{ "parse_ldif", (PyCFunction)py_ldb_parse_ldif, METH_VARARGS,
"S.parse_ldif(ldif) -> iter(messages)\n"
"Parse a string formatted using LDIF." },
+ { "write_ldif", (PyCFunction)py_ldb_write_ldif, METH_VARARGS,
+ "S.write_ldif(message, changetype) -> ldif\n"
+ "Print the message as a string formatted using LDIF." },
+ { "msg_diff", (PyCFunction)py_ldb_msg_diff, METH_VARARGS,
+ "S.msg_diff(Message) -> Message\n"
+ "Return an LDB Message of the difference between two Message objects." },
{ "get_opaque", (PyCFunction)py_ldb_get_opaque, METH_VARARGS,
"S.get_opaque(name) -> value\n"
"Get an opaque value set on this LDB connection. \n"
@@ -1035,7 +1264,7 @@ static int py_ldb_contains(PyLdbObject *self, PyObject *obj)
ret = ldb_search(ldb_ctx, ldb_ctx, &result, dn, LDB_SCOPE_BASE, NULL, NULL);
if (ret != LDB_SUCCESS) {
- PyErr_SetLdbError(ret, ldb_ctx);
+ PyErr_SetLdbError(PyExc_LdbError, ret, ldb_ctx);
return -1;
}
@@ -1115,11 +1344,12 @@ static PyObject *py_ldb_module_del_transaction(PyLdbModuleObject *self)
static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, PyObject *kwargs)
{
- PyObject *py_base, *py_tree, *py_attrs;
+ PyObject *py_base, *py_tree, *py_attrs, *py_ret;
int ret, scope;
struct ldb_request *req;
const char * const kwnames[] = { "base", "scope", "tree", "attrs", NULL };
struct ldb_module *mod;
+ const char * const*attrs;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "OiOO",
discard_const_p(char *, kwnames),
@@ -1128,17 +1358,33 @@ static PyObject *py_ldb_module_search(PyLdbModuleObject *self, PyObject *args, P
mod = self->mod;
+ if (py_attrs == Py_None) {
+ attrs = NULL;
+ } else {
+ attrs = PyList_AsStringList(NULL, py_attrs, "attrs");
+ if (attrs == NULL)
+ return NULL;
+ }
+
ret = ldb_build_search_req(&req, mod->ldb, NULL, PyLdbDn_AsDn(py_base),
- scope, NULL /* expr */, py_attrs == Py_None?NULL:PyList_AsStringList(req, py_attrs),
+ scope, NULL /* expr */, attrs,
NULL /* controls */, NULL, NULL, NULL);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
+
+ talloc_steal(req, attrs);
+
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
+
+ req->op.search.res = NULL;
ret = mod->ops->search(mod, req);
- talloc_free(req);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
- return PyLdbResult_FromResult(req->op.search.res);
+ py_ret = PyLdbResult_FromResult(req->op.search.res);
+
+ talloc_free(req);
+
+ return py_ret;
}
@@ -1159,7 +1405,7 @@ static PyObject *py_ldb_module_add(PyLdbModuleObject *self, PyObject *args)
mod = PyLdbModule_AsModule(self);
ret = mod->ops->add(mod, req);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
Py_RETURN_NONE;
}
@@ -1173,15 +1419,15 @@ static PyObject *py_ldb_module_modify(PyLdbModuleObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O", &py_message))
return NULL;
-
+
req = talloc_zero(NULL, struct ldb_request);
req->operation = LDB_MODIFY;
req->op.mod.message = PyLdbMessage_AsMessage(py_message);
-
+
mod = PyLdbModule_AsModule(self);
ret = mod->ops->modify(mod, req);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, mod->ldb);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, mod->ldb);
Py_RETURN_NONE;
}
@@ -1194,14 +1440,14 @@ static PyObject *py_ldb_module_delete(PyLdbModuleObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "O", &py_dn))
return NULL;
-
+
req = talloc_zero(NULL, struct ldb_request);
req->operation = LDB_DELETE;
req->op.del.dn = PyLdbDn_AsDn(py_dn);
-
+
ret = PyLdbModule_AsModule(self)->ops->del(PyLdbModule_AsModule(self), req);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
Py_RETURN_NONE;
}
@@ -1214,16 +1460,16 @@ static PyObject *py_ldb_module_rename(PyLdbModuleObject *self, PyObject *args)
if (!PyArg_ParseTuple(args, "OO", &py_dn1, &py_dn2))
return NULL;
-
+
req = talloc_zero(NULL, struct ldb_request);
req->operation = LDB_RENAME;
req->op.rename.olddn = PyLdbDn_AsDn(py_dn1);
req->op.rename.newdn = PyLdbDn_AsDn(py_dn2);
-
+
ret = PyLdbModule_AsModule(self)->ops->rename(PyLdbModule_AsModule(self), req);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
Py_RETURN_NONE;
}
@@ -1256,6 +1502,21 @@ PyTypeObject PyLdbModule = {
.tp_flags = Py_TPFLAGS_DEFAULT,
};
+
+/**
+ * Create a ldb_message_element from a Python object.
+ *
+ * This will accept any sequence objects that contains strings, or
+ * a string object.
+ *
+ * A reference to set_obj will be borrowed.
+ *
+ * @param mem_ctx Memory context
+ * @param set_obj Python object to convert
+ * @param flags ldb_message_element flags to set
+ * @param attr_name Name of the attribute
+ * @return New ldb_message_element, allocated as child of mem_ctx
+ */
struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
PyObject *set_obj, int flags,
const char *attr_name)
@@ -1263,19 +1524,19 @@ struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
struct ldb_message_element *me;
if (PyLdbMessageElement_Check(set_obj))
- return PyLdbMessageElement_AsMessageElement(set_obj);
+ return talloc_reference(mem_ctx,
+ PyLdbMessageElement_AsMessageElement(set_obj));
me = talloc(mem_ctx, struct ldb_message_element);
- me->name = attr_name;
+ me->name = talloc_strdup(me, attr_name);
me->flags = flags;
if (PyString_Check(set_obj)) {
me->num_values = 1;
me->values = talloc_array(me, struct ldb_val, me->num_values);
me->values[0].length = PyString_Size(set_obj);
- me->values[0].data = (uint8_t *)talloc_strndup(me->values,
- PyString_AsString(set_obj),
- me->values[0].length);
+ me->values[0].data = talloc_memdup(me,
+ (uint8_t *)PyString_AsString(set_obj), me->values[0].length);
} else if (PySequence_Check(set_obj)) {
int i;
me->num_values = PySequence_Size(set_obj);
@@ -1284,7 +1545,8 @@ struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx,
PyObject *obj = PySequence_GetItem(set_obj, i);
me->values[i].length = PyString_Size(obj);
- me->values[i].data = (uint8_t *)PyString_AsString(obj);
+ me->values[i].data = talloc_memdup(me,
+ (uint8_t *)PyString_AsString(obj), me->values[i].length);
}
} else {
talloc_free(me);
@@ -1324,8 +1586,30 @@ static PyObject *py_ldb_msg_element_get(PyLdbMessageElementObject *self, PyObjec
&(PyLdbMessageElement_AsMessageElement(self)->values[i]));
}
+static PyObject *py_ldb_msg_element_flags(PyLdbMessageElementObject *self, PyObject *args)
+{
+ struct ldb_message_element *el;
+
+ el = PyLdbMessageElement_AsMessageElement(self);
+ return PyInt_FromLong(el->flags);
+}
+
+static PyObject *py_ldb_msg_element_set_flags(PyLdbMessageElementObject *self, PyObject *args)
+{
+ int flags;
+ struct ldb_message_element *el;
+ if (!PyArg_ParseTuple(args, "i", &flags))
+ return NULL;
+
+ el = PyLdbMessageElement_AsMessageElement(self);
+ el->flags = flags;
+ Py_RETURN_NONE;
+}
+
static PyMethodDef py_ldb_msg_element_methods[] = {
{ "get", (PyCFunction)py_ldb_msg_element_get, METH_VARARGS, NULL },
+ { "set_flags", (PyCFunction)py_ldb_msg_element_set_flags, METH_VARARGS, NULL },
+ { "flags", (PyCFunction)py_ldb_msg_element_flags, METH_NOARGS, NULL },
{ NULL },
};
@@ -1385,33 +1669,49 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb
char *name = NULL;
const char * const kwnames[] = { "elements", "flags", "name", NULL };
PyLdbMessageElementObject *ret;
+ TALLOC_CTX *mem_ctx;
if (!PyArg_ParseTupleAndKeywords(args, kwargs, "|Ois",
discard_const_p(char *, kwnames),
&py_elements, &flags, &name))
return NULL;
- el = talloc_zero(NULL, struct ldb_message_element);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ el = talloc_zero(mem_ctx, struct ldb_message_element);
if (py_elements != NULL) {
int i;
if (PyString_Check(py_elements)) {
el->num_values = 1;
el->values = talloc_array(el, struct ldb_val, 1);
- el->values[0].data = (uint8_t *)PyString_AsString(py_elements);
el->values[0].length = PyString_Size(py_elements);
+ el->values[0].data = talloc_memdup(el,
+ (uint8_t *)PyString_AsString(py_elements), el->values[0].length);
} else if (PySequence_Check(py_elements)) {
el->num_values = PySequence_Size(py_elements);
el->values = talloc_array(el, struct ldb_val, el->num_values);
for (i = 0; i < el->num_values; i++) {
PyObject *item = PySequence_GetItem(py_elements, i);
- el->values[i].data = (uint8_t *)PyString_AsString(item);
+ if (!PyString_Check(item)) {
+ PyErr_Format(PyExc_TypeError,
+ "Expected string as element %d in list",
+ i);
+ talloc_free(mem_ctx);
+ return NULL;
+ }
el->values[i].length = PyString_Size(item);
+ el->values[i].data = talloc_memdup(el,
+ (uint8_t *)PyString_AsString(item), el->values[i].length);
}
} else {
PyErr_SetString(PyExc_TypeError,
"Expected string or list");
- talloc_free(el);
+ talloc_free(mem_ctx);
return NULL;
}
}
@@ -1422,12 +1722,12 @@ static PyObject *py_ldb_msg_element_new(PyTypeObject *type, PyObject *args, PyOb
ret = (PyLdbMessageElementObject *)PyLdbMessageElement.tp_alloc(&PyLdbMessageElement, 0);
if (ret == NULL) {
PyErr_NoMemory();
- talloc_free(el);
+ talloc_free(mem_ctx);
return NULL;
}
- ret->mem_ctx = talloc_new(NULL);
- ret->el = talloc_reference(ret->mem_ctx, el);
+ ret->mem_ctx = mem_ctx;
+ ret->el = el;
return (PyObject *)ret;
}
@@ -1513,8 +1813,13 @@ static PyObject *py_ldb_msg_keys(PyLdbMessageObject *self)
static PyObject *py_ldb_msg_getitem_helper(PyLdbMessageObject *self, PyObject *py_name)
{
struct ldb_message_element *el;
- char *name = PyString_AsString(py_name);
+ char *name;
struct ldb_message *msg = PyLdbMessage_AsMessage(self);
+ if (!PyString_Check(py_name)) {
+ PyErr_SetNone(PyExc_TypeError);
+ return NULL;
+ }
+ name = PyString_AsString(py_name);
if (!strcmp(name, "dn"))
return PyLdbDn_FromDn(msg->dn);
el = ldb_msg_find_element(msg, name);
@@ -1541,8 +1846,11 @@ static PyObject *py_ldb_msg_get(PyLdbMessageObject *self, PyObject *args)
return NULL;
ret = py_ldb_msg_getitem_helper(self, name);
- if (ret == NULL)
+ if (ret == NULL) {
+ if (PyErr_Occurred())
+ return NULL;
Py_RETURN_NONE;
+ }
return ret;
}
@@ -1582,15 +1890,22 @@ static PyObject *py_ldb_msg_iter(PyLdbMessageObject *self)
static int py_ldb_msg_setitem(PyLdbMessageObject *self, PyObject *name, PyObject *value)
{
- char *attr_name = PyString_AsString(name);
+ char *attr_name;
+
+ if (!PyString_Check(name)) {
+ PyErr_SetNone(PyExc_TypeError);
+ return -1;
+ }
+
+ attr_name = PyString_AsString(name);
if (value == NULL) {
+ /* delitem */
ldb_msg_remove_attr(self->msg, attr_name);
} else {
- struct ldb_message_element *el = PyObject_AsMessageElement(NULL,
+ struct ldb_message_element *el = PyObject_AsMessageElement(self->msg,
value, 0, attr_name);
if (el == NULL)
return -1;
- talloc_steal(self->msg, el);
ldb_msg_remove_attr(PyLdbMessage_AsMessage(self), attr_name);
ldb_msg_add(PyLdbMessage_AsMessage(self), el, el->flags);
}
@@ -1612,6 +1927,7 @@ static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kw
{
const char * const kwnames[] = { "dn", NULL };
struct ldb_message *ret;
+ TALLOC_CTX *mem_ctx;
PyObject *pydn = NULL;
PyLdbMessageObject *py_ret;
@@ -1620,24 +1936,37 @@ static PyObject *py_ldb_msg_new(PyTypeObject *type, PyObject *args, PyObject *kw
&pydn))
return NULL;
- ret = ldb_msg_new(NULL);
+ mem_ctx = talloc_new(NULL);
+ if (mem_ctx == NULL) {
+ PyErr_NoMemory();
+ return NULL;
+ }
+
+ ret = ldb_msg_new(mem_ctx);
if (ret == NULL) {
+ talloc_free(mem_ctx);
PyErr_NoMemory();
return NULL;
}
- if (pydn != NULL)
- if (!PyObject_AsDn(NULL, pydn, NULL, &ret->dn))
+ if (pydn != NULL) {
+ struct ldb_dn *dn;
+ if (!PyObject_AsDn(NULL, pydn, NULL, &dn)) {
+ talloc_free(mem_ctx);
return NULL;
+ }
+ ret->dn = talloc_reference(ret, dn);
+ }
py_ret = (PyLdbMessageObject *)type->tp_alloc(type, 0);
if (py_ret == NULL) {
PyErr_NoMemory();
+ talloc_free(mem_ctx);
return NULL;
}
- py_ret->mem_ctx = talloc_new(NULL);
- py_ret->msg = talloc_reference(py_ret->mem_ctx, ret);
+ py_ret->mem_ctx = mem_ctx;
+ py_ret->msg = ret;
return (PyObject *)py_ret;
}
@@ -1657,12 +1986,19 @@ PyObject *PyLdbMessage_FromMessage(struct ldb_message *msg)
static PyObject *py_ldb_msg_get_dn(PyLdbMessageObject *self, void *closure)
{
- return PyLdbDn_FromDn(PyLdbMessage_AsMessage(self)->dn);
+ struct ldb_message *msg = PyLdbMessage_AsMessage(self);
+ return PyLdbDn_FromDn(msg->dn);
}
static int py_ldb_msg_set_dn(PyLdbMessageObject *self, PyObject *value, void *closure)
{
- PyLdbMessage_AsMessage(self)->dn = PyLdbDn_AsDn(value);
+ struct ldb_message *msg = PyLdbMessage_AsMessage(self);
+ if (!PyLdbDn_Check(value)) {
+ PyErr_SetNone(PyExc_TypeError);
+ return -1;
+ }
+
+ msg->dn = talloc_reference(msg, PyLdbDn_AsDn(value));
return 0;
}
@@ -1709,7 +2045,7 @@ PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *tree)
PyErr_NoMemory();
return NULL;
}
-
+
ret->mem_ctx = talloc_new(NULL);
ret->tree = talloc_reference(ret->mem_ctx, tree);
return (PyObject *)ret;
@@ -2023,7 +2359,7 @@ static PyObject *py_register_module(PyObject *module, PyObject *args)
ret = ldb_register_module(ops);
- PyErr_LDB_ERROR_IS_ERR_RAISE(ret, NULL);
+ PyErr_LDB_ERROR_IS_ERR_RAISE(PyExc_LdbError, ret, NULL);
Py_RETURN_NONE;
}
@@ -2113,6 +2449,10 @@ void initldb(void)
PyModule_AddObject(m, "CHANGETYPE_DELETE", PyInt_FromLong(LDB_CHANGETYPE_DELETE));
PyModule_AddObject(m, "CHANGETYPE_MODIFY", PyInt_FromLong(LDB_CHANGETYPE_MODIFY));
+ PyModule_AddObject(m, "FLAG_MOD_ADD", PyInt_FromLong(LDB_FLAG_MOD_ADD));
+ PyModule_AddObject(m, "FLAG_MOD_REPLACE", PyInt_FromLong(LDB_FLAG_MOD_REPLACE));
+ PyModule_AddObject(m, "FLAG_MOD_DELETE", PyInt_FromLong(LDB_FLAG_MOD_DELETE));
+
PyModule_AddObject(m, "SUCCESS", PyInt_FromLong(LDB_SUCCESS));
PyModule_AddObject(m, "ERR_OPERATIONS_ERROR", PyInt_FromLong(LDB_ERR_OPERATIONS_ERROR));
PyModule_AddObject(m, "ERR_PROTOCOL_ERROR", PyInt_FromLong(LDB_ERR_PROTOCOL_ERROR));
@@ -2151,9 +2491,14 @@ void initldb(void)
PyModule_AddObject(m, "ERR_ENTRY_ALREADY_EXISTS", PyInt_FromLong(LDB_ERR_ENTRY_ALREADY_EXISTS));
PyModule_AddObject(m, "ERR_OBJECT_CLASS_MODS_PROHIBITED", PyInt_FromLong(LDB_ERR_OBJECT_CLASS_MODS_PROHIBITED));
PyModule_AddObject(m, "ERR_AFFECTS_MULTIPLE_DSAS", PyInt_FromLong(LDB_ERR_AFFECTS_MULTIPLE_DSAS));
-
PyModule_AddObject(m, "ERR_OTHER", PyInt_FromLong(LDB_ERR_OTHER));
+ PyModule_AddObject(m, "FLG_RDONLY", PyInt_FromLong(LDB_FLG_RDONLY));
+ PyModule_AddObject(m, "FLG_NOSYNC", PyInt_FromLong(LDB_FLG_NOSYNC));
+ PyModule_AddObject(m, "FLG_RECONNECT", PyInt_FromLong(LDB_FLG_RECONNECT));
+ PyModule_AddObject(m, "FLG_NOMMAP", PyInt_FromLong(LDB_FLG_NOMMAP));
+
+
PyModule_AddObject(m, "__docformat__", PyString_FromString("restructuredText"));
PyExc_LdbError = PyErr_NewException(discard_const_p(char, "_ldb.LdbError"), NULL, NULL);
diff --git a/source4/lib/ldb/pyldb.h b/source4/lib/ldb/pyldb.h
index 731911a387..a0954158bd 100644
--- a/source4/lib/ldb/pyldb.h
+++ b/source4/lib/ldb/pyldb.h
@@ -27,6 +27,7 @@
#define _PYLDB_H_
#include <Python.h>
+#include <talloc.h>
typedef struct {
PyObject_HEAD
@@ -34,7 +35,6 @@ typedef struct {
TALLOC_CTX *mem_ctx;
} PyLdbObject;
-PyAPI_DATA(PyTypeObject) PyLdb;
PyObject *PyLdb_FromLdbContext(struct ldb_context *ldb_ctx);
#define PyLdb_AsLdbContext(pyobj) ((PyLdbObject *)pyobj)->ldb_ctx
#define PyLdb_Check(ob) PyObject_TypeCheck(ob, &PyLdb)
@@ -45,7 +45,6 @@ typedef struct {
TALLOC_CTX *mem_ctx;
} PyLdbDnObject;
-PyAPI_DATA(PyTypeObject) PyLdbDn;
PyObject *PyLdbDn_FromDn(struct ldb_dn *);
bool PyObject_AsDn(TALLOC_CTX *mem_ctx, PyObject *object, struct ldb_context *ldb_ctx, struct ldb_dn **dn);
#define PyLdbDn_AsDn(pyobj) ((PyLdbDnObject *)pyobj)->dn
@@ -56,8 +55,6 @@ typedef struct {
struct ldb_message *msg;
TALLOC_CTX *mem_ctx;
} PyLdbMessageObject;
-PyAPI_DATA(PyTypeObject) PyLdbMessage;
-PyObject *PyLdbMessage_FromMessage(struct ldb_message *message);
#define PyLdbMessage_Check(ob) PyObject_TypeCheck(ob, &PyLdbMessage)
#define PyLdbMessage_AsMessage(pyobj) ((PyLdbMessageObject *)pyobj)->msg
@@ -66,7 +63,7 @@ typedef struct {
struct ldb_module *mod;
TALLOC_CTX *mem_ctx;
} PyLdbModuleObject;
-PyAPI_DATA(PyTypeObject) PyLdbModule;
+PyObject *PyLdbMessage_FromMessage(struct ldb_message *message);
PyObject *PyLdbModule_FromModule(struct ldb_module *mod);
#define PyLdbModule_AsModule(pyobj) ((PyLdbModuleObject *)pyobj)->mod
@@ -75,7 +72,6 @@ typedef struct {
struct ldb_message_element *el;
TALLOC_CTX *mem_ctx;
} PyLdbMessageElementObject;
-PyAPI_DATA(PyTypeObject) PyLdbMessageElement;
struct ldb_message_element *PyObject_AsMessageElement(TALLOC_CTX *mem_ctx, PyObject *obj, int flags, const char *name);
PyObject *PyLdbMessageElement_FromMessageElement(struct ldb_message_element *, TALLOC_CTX *mem_ctx);
#define PyLdbMessageElement_AsMessageElement(pyobj) ((PyLdbMessageElementObject *)pyobj)->el
@@ -86,16 +82,17 @@ typedef struct {
struct ldb_parse_tree *tree;
TALLOC_CTX *mem_ctx;
} PyLdbTreeObject;
-PyAPI_DATA(PyTypeObject) PyLdbTree;
PyObject *PyLdbTree_FromTree(struct ldb_parse_tree *);
#define PyLdbTree_AsTree(pyobj) ((PyLdbTreeObject *)pyobj)->tree
-void PyErr_SetLdbError(int ret, struct ldb_context *ldb_ctx);
-#define PyErr_LDB_ERROR_IS_ERR_RAISE(ret,ldb) \
+#define PyErr_LDB_ERROR_IS_ERR_RAISE(err,ret,ldb) \
if (ret != LDB_SUCCESS) { \
- PyErr_SetLdbError(ret, ldb); \
+ PyErr_SetLdbError(err, ret, ldb); \
return NULL; \
}
+/* Picked out of thin air. To do this properly, we should probably have some part of the
+ * errors in LDB be allocated to bindings ? */
+#define LDB_ERR_PYTHON_EXCEPTION 142
#endif /* _PYLDB_H_ */
diff --git a/source4/lib/ldb/python.mk b/source4/lib/ldb/python.mk
index 6cc6d2e90e..dbc2eb27eb 100644
--- a/source4/lib/ldb/python.mk
+++ b/source4/lib/ldb/python.mk
@@ -2,5 +2,5 @@
LIBRARY_REALNAME = ldb.$(SHLIBEXT)
PUBLIC_DEPENDENCIES = LIBLDB PYTALLOC
-pyldb_OBJ_FILES = $(ldbsrcdir)/pyldb.o
+pyldb_OBJ_FILES = $(ldbsrcdir)/pyldb.o
$(pyldb_OBJ_FILES): CFLAGS+=-I$(ldbsrcdir)/include
diff --git a/source4/lib/ldb/rules.mk b/source4/lib/ldb/rules.mk
index 639271b76d..0598f8039b 100644
--- a/source4/lib/ldb/rules.mk
+++ b/source4/lib/ldb/rules.mk
@@ -19,6 +19,7 @@ ctags:
showflags::
@echo 'ldb will be compiled with flags:'
@echo ' CFLAGS = $(CFLAGS)'
+ @echo ' SHLD_FLAGS = $(SHLD_FLAGS)'
@echo ' LIBS = $(LIBS)'
distclean::
diff --git a/source4/lib/ldb/tests/python/api.py b/source4/lib/ldb/tests/python/api.py
index c372b8fa71..956908d7d6 100755
--- a/source4/lib/ldb/tests/python/api.py
+++ b/source4/lib/ldb/tests/python/api.py
@@ -14,6 +14,7 @@ def filename():
return os.tempnam()
class NoContextTests(unittest.TestCase):
+
def test_valid_attr_name(self):
self.assertTrue(ldb.valid_attr_name("foo"))
self.assertFalse(ldb.valid_attr_name("24foo"))
@@ -28,6 +29,7 @@ class NoContextTests(unittest.TestCase):
class SimpleLdb(unittest.TestCase):
+
def test_connect(self):
ldb.Ldb(filename())
@@ -86,23 +88,23 @@ class SimpleLdb(unittest.TestCase):
def test_search_scope_base(self):
l = ldb.Ldb(filename())
- self.assertEquals(len(l.search(ldb.Dn(l, "dc=foo"),
+ self.assertEquals(len(l.search(ldb.Dn(l, "dc=foo1"),
ldb.SCOPE_ONELEVEL)), 0)
def test_delete(self):
l = ldb.Ldb(filename())
- self.assertRaises(ldb.LdbError, lambda: l.delete(ldb.Dn(l, "dc=foo")))
+ self.assertRaises(ldb.LdbError, lambda: l.delete(ldb.Dn(l, "dc=foo2")))
def test_contains(self):
l = ldb.Ldb(filename())
- self.assertFalse(ldb.Dn(l, "dc=foo") in l)
+ self.assertFalse(ldb.Dn(l, "dc=foo3") in l)
l = ldb.Ldb(filename())
m = ldb.Message()
- m.dn = ldb.Dn(l, "dc=foo")
+ m.dn = ldb.Dn(l, "dc=foo3")
m["b"] = ["a"]
l.add(m)
try:
- self.assertTrue(ldb.Dn(l, "dc=foo") in l)
+ self.assertTrue(ldb.Dn(l, "dc=foo3") in l)
finally:
l.delete(m.dn)
@@ -125,45 +127,53 @@ class SimpleLdb(unittest.TestCase):
def test_add(self):
l = ldb.Ldb(filename())
m = ldb.Message()
- m.dn = ldb.Dn(l, "dc=foo")
+ m.dn = ldb.Dn(l, "dc=foo4")
m["bla"] = "bla"
self.assertEquals(len(l.search()), 1)
l.add(m)
try:
self.assertEquals(len(l.search()), 2)
finally:
- l.delete(ldb.Dn(l, "dc=foo"))
+ l.delete(ldb.Dn(l, "dc=foo4"))
+
+ def test_add_w_unhandled_ctrl(self):
+ l = ldb.Ldb(filename())
+ m = ldb.Message()
+ m.dn = ldb.Dn(l, "dc=foo4")
+ m["bla"] = "bla"
+ self.assertEquals(len(l.search()), 1)
+ self.assertRaises(ldb.LdbError, lambda: l.add(m,["search_options:1:2"]))
def test_add_dict(self):
l = ldb.Ldb(filename())
- m = {"dn": ldb.Dn(l, "dc=foo"),
+ m = {"dn": ldb.Dn(l, "dc=foo5"),
"bla": "bla"}
self.assertEquals(len(l.search()), 1)
l.add(m)
try:
self.assertEquals(len(l.search()), 2)
finally:
- l.delete(ldb.Dn(l, "dc=foo"))
+ l.delete(ldb.Dn(l, "dc=foo5"))
def test_add_dict_string_dn(self):
l = ldb.Ldb(filename())
- m = {"dn": "dc=foo", "bla": "bla"}
+ m = {"dn": "dc=foo6", "bla": "bla"}
self.assertEquals(len(l.search()), 1)
l.add(m)
try:
self.assertEquals(len(l.search()), 2)
finally:
- l.delete(ldb.Dn(l, "dc=foo"))
+ l.delete(ldb.Dn(l, "dc=foo6"))
def test_rename(self):
l = ldb.Ldb(filename())
m = ldb.Message()
- m.dn = ldb.Dn(l, "dc=foo")
+ m.dn = ldb.Dn(l, "dc=foo7")
m["bla"] = "bla"
self.assertEquals(len(l.search()), 1)
l.add(m)
try:
- l.rename(ldb.Dn(l, "dc=foo"), ldb.Dn(l, "dc=bar"))
+ l.rename(ldb.Dn(l, "dc=foo7"), ldb.Dn(l, "dc=bar"))
self.assertEquals(len(l.search()), 2)
finally:
l.delete(ldb.Dn(l, "dc=bar"))
@@ -171,13 +181,13 @@ class SimpleLdb(unittest.TestCase):
def test_rename_string_dns(self):
l = ldb.Ldb(filename())
m = ldb.Message()
- m.dn = ldb.Dn(l, "dc=foo")
+ m.dn = ldb.Dn(l, "dc=foo8")
m["bla"] = "bla"
self.assertEquals(len(l.search()), 1)
l.add(m)
self.assertEquals(len(l.search()), 2)
try:
- l.rename("dc=foo", "dc=bar")
+ l.rename("dc=foo8", "dc=bar")
self.assertEquals(len(l.search()), 2)
finally:
l.delete(ldb.Dn(l, "dc=bar"))
@@ -193,10 +203,13 @@ class SimpleLdb(unittest.TestCase):
try:
m = ldb.Message()
m.dn = ldb.Dn(l, "dc=modifydelete")
- m["bla"] = ldb.MessageElement([], ldb.CHANGETYPE_DELETE, "bla")
+ m["bla"] = ldb.MessageElement([], ldb.FLAG_MOD_DELETE, "bla")
+ self.assertEquals(ldb.FLAG_MOD_DELETE, m["bla"].flags())
l.modify(m)
rm = l.search(m.dn)[0]
self.assertEquals(1, len(rm))
+ rm = l.search(m.dn, attrs=["bla"])[0]
+ self.assertEquals(0, len(rm))
finally:
l.delete(ldb.Dn(l, "dc=modifydelete"))
@@ -209,7 +222,8 @@ class SimpleLdb(unittest.TestCase):
try:
m = ldb.Message()
m.dn = ldb.Dn(l, "dc=add")
- m["bla"] = ldb.MessageElement(["456"], ldb.CHANGETYPE_ADD, "bla")
+ m["bla"] = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla")
+ self.assertEquals(ldb.FLAG_MOD_ADD, m["bla"].flags())
l.modify(m)
rm = l.search(m.dn)[0]
self.assertEquals(2, len(rm))
@@ -217,7 +231,7 @@ class SimpleLdb(unittest.TestCase):
finally:
l.delete(ldb.Dn(l, "dc=add"))
- def test_modify_modify(self):
+ def test_modify_replace(self):
l = ldb.Ldb(filename())
m = ldb.Message()
m.dn = ldb.Dn(l, "dc=modify2")
@@ -226,18 +240,48 @@ class SimpleLdb(unittest.TestCase):
try:
m = ldb.Message()
m.dn = ldb.Dn(l, "dc=modify2")
- m["bla"] = ldb.MessageElement(["456"], ldb.CHANGETYPE_MODIFY, "bla")
+ m["bla"] = ldb.MessageElement(["789"], ldb.FLAG_MOD_REPLACE, "bla")
+ self.assertEquals(ldb.FLAG_MOD_REPLACE, m["bla"].flags())
l.modify(m)
rm = l.search(m.dn)[0]
self.assertEquals(2, len(rm))
- self.assertEquals(["1234"], list(rm["bla"]))
+ self.assertEquals(["789"], list(rm["bla"]))
+ rm = l.search(m.dn, attrs=["bla"])[0]
+ self.assertEquals(1, len(rm))
finally:
l.delete(ldb.Dn(l, "dc=modify2"))
+ def test_modify_flags_change(self):
+ l = ldb.Ldb(filename())
+ m = ldb.Message()
+ m.dn = ldb.Dn(l, "dc=add")
+ m["bla"] = ["1234"]
+ l.add(m)
+ try:
+ m = ldb.Message()
+ m.dn = ldb.Dn(l, "dc=add")
+ m["bla"] = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla")
+ self.assertEquals(ldb.FLAG_MOD_ADD, m["bla"].flags())
+ l.modify(m)
+ rm = l.search(m.dn)[0]
+ self.assertEquals(2, len(rm))
+ self.assertEquals(["1234", "456"], list(rm["bla"]))
+
+ #Now create another modify, but switch the flags before we do it
+ m["bla"] = ldb.MessageElement(["456"], ldb.FLAG_MOD_ADD, "bla")
+ m["bla"].set_flags(ldb.FLAG_MOD_DELETE)
+ l.modify(m)
+ rm = l.search(m.dn, attrs=["bla"])[0]
+ self.assertEquals(1, len(rm))
+ self.assertEquals(["1234"], list(rm["bla"]))
+
+ finally:
+ l.delete(ldb.Dn(l, "dc=add"))
+
def test_transaction_commit(self):
l = ldb.Ldb(filename())
l.transaction_start()
- m = ldb.Message(ldb.Dn(l, "dc=foo"))
+ m = ldb.Message(ldb.Dn(l, "dc=foo9"))
m["foo"] = ["bar"]
l.add(m)
l.transaction_commit()
@@ -246,11 +290,11 @@ class SimpleLdb(unittest.TestCase):
def test_transaction_cancel(self):
l = ldb.Ldb(filename())
l.transaction_start()
- m = ldb.Message(ldb.Dn(l, "dc=foo"))
+ m = ldb.Message(ldb.Dn(l, "dc=foo10"))
m["foo"] = ["bar"]
l.add(m)
l.transaction_cancel()
- self.assertEquals(0, len(l.search(ldb.Dn(l, "dc=foo"))))
+ self.assertEquals(0, len(l.search(ldb.Dn(l, "dc=foo10"))))
def test_set_debug(self):
def my_report_fn(level, text):
@@ -258,45 +302,69 @@ class SimpleLdb(unittest.TestCase):
l = ldb.Ldb(filename())
l.set_debug(my_report_fn)
+ def test_zero_byte_string(self):
+ """Testing we do not get trapped in the \0 byte in a property string."""
+ l = ldb.Ldb(filename())
+ l.add({
+ "dn" : "dc=somedn",
+ "objectclass" : "user",
+ "cN" : "LDAPtestUSER",
+ "givenname" : "ldap",
+ "displayname" : "foo\0bar",
+ })
+ res = l.search(expression="(dn=dc=somedn)")
+ self.assertEquals("foo\0bar", res[0]["displayname"][0])
+
class DnTests(unittest.TestCase):
+
def setUp(self):
self.ldb = ldb.Ldb(filename())
+ def test_set_dn_invalid(self):
+ x = ldb.Message()
+ def assign():
+ x.dn = "astring"
+ self.assertRaises(TypeError, assign)
+
def test_eq(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
- y = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo11,bar=bloe")
+ y = ldb.Dn(self.ldb, "dc=foo11,bar=bloe")
self.assertEquals(x, y)
def test_str(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
- self.assertEquals(x.__str__(), "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo12,bar=bloe")
+ self.assertEquals(x.__str__(), "dc=foo12,bar=bloe")
def test_repr(self):
- x = ldb.Dn(self.ldb, "dc=foo,bla=blie")
- self.assertEquals(x.__repr__(), "Dn('dc=foo,bla=blie')")
+ x = ldb.Dn(self.ldb, "dc=foo13,bla=blie")
+ self.assertEquals(x.__repr__(), "Dn('dc=foo13,bla=blie')")
def test_get_casefold(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
- self.assertEquals(x.get_casefold(), "DC=FOO,BAR=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo14,bar=bloe")
+ self.assertEquals(x.get_casefold(), "DC=FOO14,BAR=bloe")
def test_validate(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo15,bar=bloe")
self.assertTrue(x.validate())
def test_parent(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo16,bar=bloe")
self.assertEquals("bar=bloe", x.parent().__str__())
+ def test_parent_nonexistant(self):
+ x = ldb.Dn(self.ldb, "@BLA")
+ self.assertEquals(None, x.parent())
+
def test_compare(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
- y = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo17,bar=bloe")
+ y = ldb.Dn(self.ldb, "dc=foo17,bar=bloe")
self.assertEquals(x, y)
- z = ldb.Dn(self.ldb, "dc=foo,bar=blie")
+ z = ldb.Dn(self.ldb, "dc=foo17,bar=blie")
self.assertNotEquals(z, y)
def test_is_valid(self):
- x = ldb.Dn(self.ldb, "dc=foo,dc=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo18,dc=bloe")
self.assertTrue(x.is_valid())
x = ldb.Dn(self.ldb, "")
# is_valid()'s return values appears to be a side effect of
@@ -304,45 +372,47 @@ class DnTests(unittest.TestCase):
# self.assertFalse(x.is_valid())
def test_is_special(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo19,bar=bloe")
self.assertFalse(x.is_special())
x = ldb.Dn(self.ldb, "@FOOBAR")
self.assertTrue(x.is_special())
def test_check_special(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo20,bar=bloe")
self.assertFalse(x.check_special("FOOBAR"))
x = ldb.Dn(self.ldb, "@FOOBAR")
self.assertTrue(x.check_special("@FOOBAR"))
def test_len(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo21,bar=bloe")
self.assertEquals(2, len(x))
- x = ldb.Dn(self.ldb, "dc=foo")
+ x = ldb.Dn(self.ldb, "dc=foo21")
self.assertEquals(1, len(x))
def test_add_child(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo22,bar=bloe")
self.assertTrue(x.add_child(ldb.Dn(self.ldb, "bla=bloe")))
- self.assertEquals("bla=bloe,dc=foo,bar=bloe", x.__str__())
+ self.assertEquals("bla=bloe,dc=foo22,bar=bloe", x.__str__())
def test_add_base(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
+ x = ldb.Dn(self.ldb, "dc=foo23,bar=bloe")
base = ldb.Dn(self.ldb, "bla=bloe")
self.assertTrue(x.add_base(base))
- self.assertEquals("dc=foo,bar=bloe,bla=bloe", x.__str__())
+ self.assertEquals("dc=foo23,bar=bloe,bla=bloe", x.__str__())
def test_add(self):
- x = ldb.Dn(self.ldb, "dc=foo")
+ x = ldb.Dn(self.ldb, "dc=foo24")
y = ldb.Dn(self.ldb, "bar=bla")
- self.assertEquals("dc=foo,bar=bla", str(y + x))
+ self.assertEquals("dc=foo24,bar=bla", str(y + x))
def test_parse_ldif(self):
msgs = self.ldb.parse_ldif("dn: foo=bar\n")
msg = msgs.next()
self.assertEquals("foo=bar", str(msg[1].dn))
self.assertTrue(isinstance(msg[1], ldb.Message))
-
+ ldif = self.ldb.write_ldif(msg[1], ldb.CHANGETYPE_NONE)
+ self.assertEquals("dn: foo=bar\n\n", ldif)
+
def test_parse_ldif_more(self):
msgs = self.ldb.parse_ldif("dn: foo=bar\n\n\ndn: bar=bar")
msg = msgs.next()
@@ -351,31 +421,32 @@ class DnTests(unittest.TestCase):
self.assertEquals("bar=bar", str(msg[1].dn))
def test_canonical_string(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
- self.assertEquals("/bloe/foo", x.canonical_str())
+ x = ldb.Dn(self.ldb, "dc=foo25,bar=bloe")
+ self.assertEquals("/bloe/foo25", x.canonical_str())
def test_canonical_ex_string(self):
- x = ldb.Dn(self.ldb, "dc=foo,bar=bloe")
- self.assertEquals("/bloe\nfoo", x.canonical_ex_str())
+ x = ldb.Dn(self.ldb, "dc=foo26,bar=bloe")
+ self.assertEquals("/bloe\nfoo26", x.canonical_ex_str())
class LdbMsgTests(unittest.TestCase):
+
def setUp(self):
self.msg = ldb.Message()
def test_init_dn(self):
- self.msg = ldb.Message(ldb.Dn(ldb.Ldb(), "dc=foo"))
- self.assertEquals("dc=foo", str(self.msg.dn))
+ self.msg = ldb.Message(ldb.Dn(ldb.Ldb(), "dc=foo27"))
+ self.assertEquals("dc=foo27", str(self.msg.dn))
def test_iter_items(self):
self.assertEquals(0, len(self.msg.items()))
- self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "dc=foo")
+ self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "dc=foo28")
self.assertEquals(1, len(self.msg.items()))
def test_repr(self):
- self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "dc=foo")
+ self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "dc=foo29")
self.msg["dc"] = "foo"
- self.assertEquals("Message({'dn': Dn('dc=foo'), 'dc': MessageElement(['foo'])})", repr(self.msg))
+ self.assertEquals("Message({'dn': Dn('dc=foo29'), 'dc': MessageElement(['foo'])})", repr(self.msg))
def test_len(self):
self.assertEquals(0, len(self.msg))
@@ -417,6 +488,10 @@ class LdbMsgTests(unittest.TestCase):
self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "@BASEINFO")
self.assertEquals("@BASEINFO", self.msg.get("dn").__str__())
+ def test_get_invalid(self):
+ self.msg.dn = ldb.Dn(ldb.Ldb("foo.tdb"), "@BASEINFO")
+ self.assertRaises(TypeError, self.msg.get, 42)
+
def test_get_other(self):
self.msg["foo"] = ["bar"]
self.assertEquals("bar", self.msg.get("foo")[0])
@@ -424,8 +499,20 @@ class LdbMsgTests(unittest.TestCase):
def test_get_unknown(self):
self.assertEquals(None, self.msg.get("lalalala"))
+ def test_msg_diff(self):
+ l = ldb.Ldb()
+ msgs = l.parse_ldif("dn: foo=bar\nfoo: bar\nbaz: do\n\ndn: foo=bar\nfoo: bar\nbaz: dont\n")
+ msg1 = msgs.next()[1]
+ msg2 = msgs.next()[1]
+ msgdiff = l.msg_diff(msg1, msg2)
+ self.assertEquals("foo=bar", msgdiff.get("dn").__str__())
+ self.assertRaises(KeyError, lambda: msgdiff["foo"])
+ self.assertEquals(1, len(msgdiff))
+
+
class MessageElementTests(unittest.TestCase):
+
def test_cmp_element(self):
x = ldb.MessageElement(["foo"])
y = ldb.MessageElement(["foo"])
@@ -466,6 +553,7 @@ class MessageElementTests(unittest.TestCase):
class ModuleTests(unittest.TestCase):
+
def test_register_module(self):
class ExampleModule:
name = "example"
@@ -492,6 +580,7 @@ class ModuleTests(unittest.TestCase):
l = ldb.Ldb("usemodule.ldb")
self.assertEquals(["init"], ops)
+
if __name__ == '__main__':
import unittest
unittest.TestProgram()
diff --git a/source4/lib/ldb/tests/python/ldap.py b/source4/lib/ldb/tests/python/ldap.py
index a30273fc66..5b2d380f11 100755
--- a/source4/lib/ldb/tests/python/ldap.py
+++ b/source4/lib/ldb/tests/python/ldap.py
@@ -6,6 +6,8 @@ import getopt
import optparse
import sys
import time
+import random
+import base64
sys.path.append("bin/python")
sys.path.append("../lib/subunit/python")
@@ -17,11 +19,14 @@ from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
from ldb import ERR_NO_SUCH_OBJECT, ERR_ATTRIBUTE_OR_VALUE_EXISTS
from ldb import ERR_ENTRY_ALREADY_EXISTS, ERR_UNWILLING_TO_PERFORM
from ldb import ERR_NOT_ALLOWED_ON_NON_LEAF, ERR_OTHER, ERR_INVALID_DN_SYNTAX
-from samba import Ldb
+from ldb import Message, MessageElement, Dn, FLAG_MOD_REPLACE
+from samba import Ldb, param, dom_sid_to_rid
from subunit import SubunitTestRunner
-from samba import param
import unittest
+from samba.ndr import ndr_pack, ndr_unpack
+from samba.dcerpc import security
+
parser = optparse.OptionParser("ldap [options] <host>")
sambaopts = options.SambaOptions(parser)
parser.add_option_group(sambaopts)
@@ -44,11 +49,11 @@ class BasicTests(unittest.TestCase):
def delete_force(self, ldb, dn):
try:
ldb.delete(dn)
- except LdbError, (num, _):
+ except LdbError, (num, _):
self.assertEquals(num, ERR_NO_SUCH_OBJECT)
def find_basedn(self, ldb):
- res = ldb.search(base="", expression="", scope=SCOPE_BASE,
+ res = ldb.search(base="", expression="", scope=SCOPE_BASE,
attrs=["defaultNamingContext"])
self.assertEquals(len(res), 1)
return res[0]["defaultNamingContext"][0]
@@ -63,12 +68,17 @@ class BasicTests(unittest.TestCase):
self.assertEquals(len(res), 1)
return res[0]["schemaNamingContext"][0]
+ def find_domain_sid(self):
+ res = self.ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
+ return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
+
def setUp(self):
self.ldb = ldb
self.gc_ldb = gc_ldb
self.base_dn = self.find_basedn(ldb)
self.configuration_dn = self.find_configurationdn(ldb)
self.schema_dn = self.find_schemadn(ldb)
+ self.domain_sid = self.find_domain_sid()
print "baseDN: %s\n" % self.base_dn
@@ -78,7 +88,10 @@ class BasicTests(unittest.TestCase):
self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn)
self.delete_force(self.ldb, "cn=ldaptestutf8user2 èùéìòà ,cn=users," + self.base_dn)
-
+ self.delete_force(self.ldb, "cn=parentguidtest,cn=users," + self.base_dn)
+ self.delete_force(self.ldb, "cn=parentguidtest,cn=testotherusers," + self.base_dn)
+ self.delete_force(self.ldb, "cn=testotherusers," + self.base_dn)
+
def test_group_add_invalid_member(self):
"""Testing group add with invalid member"""
try:
@@ -87,21 +100,235 @@ class BasicTests(unittest.TestCase):
"objectclass": "group",
"member": "cn=ldaptestuser,cn=useRs," + self.base_dn})
self.fail()
- except LdbError, (num, _):
+ except LdbError, (num, _):
self.assertEquals(num, ERR_NO_SUCH_OBJECT)
+ def test_parentGUID(self):
+ """Test parentGUID behaviour"""
+ print "Testing parentGUID behaviour\n"
+
+ self.ldb.add({
+ "dn": "cn=parentguidtest,cn=users," + self.base_dn,
+ "objectclass":"user",
+ "samaccountname":"parentguidtest"});
+ res1 = ldb.search(base="cn=parentguidtest,cn=users," + self.base_dn, scope=SCOPE_BASE,
+ attrs=["parentGUID"]);
+ res2 = ldb.search(base="cn=users," + self.base_dn,scope=SCOPE_BASE,
+ attrs=["objectGUID"]);
+ self.assertEquals(res1[0]["parentGUID"], res2[0]["objectGUID"]);
+
+ """Test parentGUID behaviour"""
+ print "Testing parentGUID behaviour on rename\n"
+
+ self.ldb.add({
+ "dn": "cn=testotherusers," + self.base_dn,
+ "objectclass":"container"});
+ res1 = ldb.search(base="cn=testotherusers," + self.base_dn,scope=SCOPE_BASE,
+ attrs=["objectGUID"]);
+ ldb.rename("cn=parentguidtest,cn=users," + self.base_dn,
+ "cn=parentguidtest,cn=testotherusers," + self.base_dn);
+ res2 = ldb.search(base="cn=parentguidtest,cn=testotherusers," + self.base_dn,
+ scope=SCOPE_BASE,
+ attrs=["parentGUID"]);
+ self.assertEquals(res1[0]["objectGUID"], res2[0]["parentGUID"]);
+ ldb.delete("cn=parentguidtest,cn=testotherusers," + self.base_dn)
+ ldb.delete("cn=testotherusers," + self.base_dn)
+
+ def test_groupType(self):
+ """Test groupType behaviour (should appear to be casted to a 32 bit signed integer before comparsion)"""
+ print "Testing groupType behaviour\n"
+
+ res1 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
+ attrs=["groupType"], expression="groupType=2147483653");
+
+ res2 = ldb.search(base=self.base_dn, scope=SCOPE_SUBTREE,
+ attrs=["groupType"], expression="groupType=-2147483643");
+
+ self.assertEquals(len(res1), len(res2))
+
+ self.assertTrue(res1.count > 0)
+
+ self.assertEquals(res1[0]["groupType"][0], "-2147483643")
+
+ def test_primary_group(self):
+ """This tests the primary group behaviour (setting, changing) of a user account"""
+ print "Testing primary group behaviour\n"
+
+ ldb.add({
+ "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+ "objectclass": ["user", "person"]})
+
+ ldb.add({
+ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
+ "objectclass": "group"})
+
+ ldb.add({
+ "dn": "cn=ldaptestgroup2,cn=users," + self.base_dn,
+ "objectclass": "group"})
+
+ res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["objectSID"])
+ self.assertTrue(len(res1) == 1)
+ group_rid_1 = dom_sid_to_rid(ldb.schema_format_value("objectSID",
+ res1[0]["objectSID"][0]))
+
+ res1 = ldb.search("cn=ldaptestgroup2,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["objectSID"])
+ self.assertTrue(len(res1) == 1)
+ group_rid_2 = dom_sid_to_rid(ldb.schema_format_value("objectSID",
+ res1[0]["objectSID"][0]))
+
+ # Try to add invalid primary group
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ m["primaryGroupID"] = MessageElement("0", FLAG_MOD_REPLACE,
+ "primaryGroupID")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+ # Try to make group 1 primary - should be denied since it is not yet
+ # secondary
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ m["primaryGroupID"] = MessageElement(str(group_rid_1),
+ FLAG_MOD_REPLACE, "primaryGroupID")
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+ # Make group 1 secondary
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["member"] = "cn=ldaptestuser,cn=users," + self.base_dn
+ ldb.modify(m)
+
+ # Make group 1 primary
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ m["primaryGroupID"] = MessageElement(str(group_rid_1),
+ FLAG_MOD_REPLACE, "primaryGroupID")
+ ldb.modify(m)
+
+ # Try to delete group 1 - should be denied
+ try:
+ ldb.delete("cn=ldaptestgroup,cn=users," + self.base_dn)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
+
+ # Try to add group 1 also as secondary - should be denied
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ m["member"] = "cn=ldaptestuser,cn=users," + self.base_dn
+ try:
+ ldb.modify(m)
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_ENTRY_ALREADY_EXISTS)
+
+ # Make group 2 secondary
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
+ m["member"] = "cn=ldaptestuser,cn=users," + self.base_dn
+ ldb.modify(m)
+
+ # Swap the groups
+ m = Message()
+ m.dn = Dn(ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ m["primaryGroupID"] = MessageElement(str(group_rid_2),
+ FLAG_MOD_REPLACE, "primaryGroupID")
+ ldb.modify(m)
+
+ # Old primary group should contain a "member" attribute for the user,
+ # the new shouldn't contain anymore one
+ res1 = ldb.search("cn=ldaptestgroup, cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["member"])
+ self.assertTrue(len(res1) == 1)
+ self.assertTrue(len(res1[0]["member"]) == 1)
+ self.assertEquals(res1[0]["member"][0].lower(),
+ ("cn=ldaptestuser,cn=users," + self.base_dn).lower())
+
+ res1 = ldb.search("cn=ldaptestgroup2, cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["member"])
+ self.assertTrue(len(res1) == 1)
+ self.assertFalse("member" in res1[0])
+
+ # Also this should be denied
+ try:
+ ldb.add({
+ "dn": "cn=ldaptestuser1,cn=users," + self.base_dn,
+ "objectclass": ["user", "person"],
+ "primaryGroupID": "0"})
+ self.fail()
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
+
+ self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+ self.delete_force(self.ldb, "cn=ldaptestgroup2,cn=users," + self.base_dn)
+
+ def test_primary_group_token(self):
+ """Test the primary group token behaviour (hidden-generated-readonly attribute on groups)"""
+ print "Testing primary group token behaviour\n"
+
+ ldb.add({
+ "dn": "cn=ldaptestuser,cn=users," + self.base_dn,
+ "objectclass": ["user", "person"]})
+
+ ldb.add({
+ "dn": "cn=ldaptestgroup,cn=users," + self.base_dn,
+ "objectclass": "group"})
+
+ res1 = ldb.search("cn=ldaptestuser, cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["primaryGroupToken"])
+ self.assertTrue(len(res1) == 1)
+ self.assertFalse("primaryGroupToken" in res1[0])
+
+ res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE)
+ self.assertTrue(len(res1) == 1)
+ self.assertFalse("primaryGroupToken" in res1[0])
+
+ res1 = ldb.search("cn=ldaptestgroup,cn=users," + self.base_dn,
+ scope=SCOPE_BASE, attrs=["primaryGroupToken", "objectSID"])
+ self.assertTrue(len(res1) == 1)
+ primary_group_token = int(res1[0]["primaryGroupToken"][0])
+
+ rid = dom_sid_to_rid(ldb.schema_format_value("objectSID", res1[0]["objectSID"][0]))
+ self.assertEquals(primary_group_token, rid)
+
+# Has to wait until we support read-only generated attributes correctly
+# m = Message()
+# m.dn = Dn(ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+# m["primaryGroupToken"] = "100"
+# try:
+# ldb.modify(m)
+# self.fail()
+# except LdbError, (num, msg):
+
+ self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
+ self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
+
def test_all(self):
"""Basic tests"""
+ print "Testing user add"
+
self.delete_force(self.ldb, "cn=ldaptestuser,cn=users," + self.base_dn)
- print "Testing user add"
ldb.add({
- "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
- "objectclass": ["user", "person"],
- "cN": "LDAPtestUSER",
- "givenname": "ldap",
- "sn": "testy"})
+ "dn": "cn=ldaptestuser,cn=uSers," + self.base_dn,
+ "objectclass": ["user", "person"],
+ "cN": "LDAPtestUSER",
+ "givenname": "ldap",
+ "sn": "testy"})
+
+ self.delete_force(self.ldb, "cn=ldaptestgroup,cn=users," + self.base_dn)
ldb.add({
"dn": "cn=ldaptestgroup,cn=uSers," + self.base_dn,
@@ -128,9 +355,9 @@ class BasicTests(unittest.TestCase):
"cn": "LDAPtest2COMPUTER"
})
self.fail()
- except LdbError, (num, _):
+ except LdbError, (num, _):
self.assertEquals(num, ERR_INVALID_DN_SYNTAX)
-
+
self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
try:
ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
@@ -139,9 +366,9 @@ class BasicTests(unittest.TestCase):
"sAMAccountType": "805306368"
})
self.fail()
- except LdbError, (num, _):
+ except LdbError, (num, _):
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
+
self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
try:
ldb.add({"dn": "cn=ldaptestcomputer3,cn=computers," + self.base_dn,
@@ -150,9 +377,9 @@ class BasicTests(unittest.TestCase):
"userAccountControl": "0"
})
self.fail()
- except LdbError, (num, _):
+ except LdbError, (num, _):
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
+
self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
try:
ldb.add({"dn": "cn=ldaptestuser7,cn=users," + self.base_dn,
@@ -161,9 +388,9 @@ class BasicTests(unittest.TestCase):
"userAccountControl": "0"
})
self.fail()
- except LdbError, (num, _):
+ except LdbError, (num, _):
self.assertEquals(num, ERR_UNWILLING_TO_PERFORM)
-
+
self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
ldb.add({"dn": "cn=ldaptestuser7,cn=users," + self.base_dn,
@@ -171,7 +398,7 @@ class BasicTests(unittest.TestCase):
"cn": "LDAPtestuser7",
"userAccountControl": "2"
})
-
+
self.delete_force(self.ldb, "cn=ldaptestuser7,cn=users," + self.base_dn)
self.delete_force(self.ldb, "cn=ldaptestcomputer3,cn=computers," + self.base_dn)
@@ -179,7 +406,7 @@ class BasicTests(unittest.TestCase):
"objectClass": "computer",
"cn": "LDAPtestCOMPUTER3"
})
-
+
print "Testing ldb.search for (&(cn=ldaptestcomputer3)(objectClass=user))";
res = ldb.search(self.base_dn, expression="(&(cn=ldaptestcomputer3)(objectClass=user))");
self.assertEquals(len(res), 1, "Found only %d for (&(cn=ldaptestcomputer3)(objectClass=user))" % len(res))
@@ -239,7 +466,7 @@ dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
changetype: modify
replace: servicePrincipalName
""")
-
+
ldb.modify_ldif("""
dn: cn=ldaptest2computer,cn=computers,""" + self.base_dn + """
changetype: modify
@@ -276,7 +503,7 @@ servicePrincipalName: host/ldaptest2computer28
servicePrincipalName: host/ldaptest2computer29
""")
- res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
+ res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE,
attrs=["servicePrincipalName;range=0-*"])
self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
#print len(res[0]["servicePrincipalName;range=0-*"])
@@ -287,7 +514,7 @@ servicePrincipalName: host/ldaptest2computer29
# print res[0]["servicePrincipalName;range=0-19"].length
self.assertEquals(len(res[0]["servicePrincipalName;range=0-19"]), 20)
-
+
res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=0-30"])
self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
self.assertEquals(len(res[0]["servicePrincipalName;range=0-*"]), 30)
@@ -300,7 +527,7 @@ servicePrincipalName: host/ldaptest2computer29
self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
self.assertEquals(len(res[0]["servicePrincipalName;range=30-*"]), 0)
-
+
res = ldb.search(self.base_dn, expression="(cn=ldaptest2computer))", scope=SCOPE_SUBTREE, attrs=["servicePrincipalName;range=10-40"])
self.assertEquals(len(res), 1, "Could not find (cn=ldaptest2computer)")
self.assertEquals(len(res[0]["servicePrincipalName;range=10-*"]), 20)
@@ -445,7 +672,7 @@ member: cn=ldaptestuser3,cn=users,""" + self.base_dn + """
res_user = ldb.search(self.base_dn, expression="(&(cn=ldaptestUSer2)(objectClass=user))", scope=SCOPE_SUBTREE, attrs=attrs)
self.assertEquals(len(res_user), 1, "Could not find (&(cn=ldaptestUSer2)(objectClass=user))")
- #Check rename works with extended/alternate DN forms
+ #Check rename works with extended/alternate DN forms
ldb.rename("<SID=" + ldb.schema_format_value("objectSID", res_user[0]["objectSID"][0]) + ">" , "cn=ldaptestuser3,cn=users," + self.base_dn)
ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
@@ -512,17 +739,17 @@ member: cn=ldaptestuser3,cn=users,""" + self.base_dn + """
# ensure we cannnot rename it twice
try:
- ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
+ ldb.rename("cn=ldaptestuser3,cn=users," + self.base_dn,
"cn=ldaptestuser2,cn=users," + self.base_dn)
self.fail()
- except LdbError, (num, _):
+ except LdbError, (num, _):
self.assertEquals(num, ERR_NO_SUCH_OBJECT)
# ensure can now use that name
ldb.add({"dn": "cn=ldaptestuser3,cn=users," + self.base_dn,
"objectClass": ["person", "user"],
"cn": "LDAPtestUSER3"})
-
+
# ensure we now cannnot rename
try:
ldb.rename("cn=ldaptestuser2,cn=users," + self.base_dn, "cn=ldaptestuser3,cn=users," + self.base_dn)
@@ -545,11 +772,11 @@ member: cn=ldaptestuser3,cn=users,""" + self.base_dn + """
print "Testing subtree Renames"
- ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
+ ldb.add({"dn": "cn=ldaptestcontainer," + self.base_dn,
"objectClass": "container"})
-
+
self.delete_force(self.ldb, "cn=ldaptestuser4,cn=ldaptestcontainer," + self.base_dn)
- ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
+ ldb.add({"dn": "CN=ldaptestuser4,CN=ldaptestcontainer," + self.base_dn,
"objectClass": ["person", "user"],
"cn": "LDAPtestUSER4"})
@@ -559,7 +786,7 @@ changetype: modify
add: member
member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
""")
-
+
print "Testing ldb.rename of cn=ldaptestcontainer," + self.base_dn + " to cn=ldaptestcontainer2," + self.base_dn
ldb.rename("CN=ldaptestcontainer," + self.base_dn, "CN=ldaptestcontainer2," + self.base_dn)
@@ -569,8 +796,8 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
print "Testing subtree ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
try:
- res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
- expression="(&(cn=ldaptestuser4)(objectClass=user))",
+ res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
+ expression="(&(cn=ldaptestuser4)(objectClass=user))",
scope=SCOPE_SUBTREE)
self.fail(res)
except LdbError, (num, _):
@@ -578,7 +805,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
print "Testing one-level ldb.search for (&(cn=ldaptestuser4)(objectClass=user)) in (just renamed from) cn=ldaptestcontainer," + self.base_dn
try:
- res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
+ res = ldb.search("cn=ldaptestcontainer," + self.base_dn,
expression="(&(cn=ldaptestuser4)(objectClass=user))", scope=SCOPE_ONELEVEL)
self.fail()
except LdbError, (num, _):
@@ -636,7 +863,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
ldb.delete(("CN=ldaptestuser4,CN=ldaptestcontainer2," + self.base_dn))
print "Testing delete of renamed cn=ldaptestcontainer2," + self.base_dn
ldb.delete("cn=ldaptestcontainer2," + self.base_dn)
-
+
self.delete_force(self.ldb, "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn)
ldb.add({"dn": "cn=ldaptestutf8user èùéìòà ,cn=users," + self.base_dn, "objectClass": "user"})
@@ -658,7 +885,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
self.assertEquals(int(res[0]["userAccountControl"][0]), 546)
self.assertEquals(res[0]["memberOf"][0].upper(), ("CN=ldaptestgroup2,CN=Users," + self.base_dn).upper())
self.assertEquals(len(res[0]["memberOf"]), 1)
-
+
print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))"
res2 = ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
self.assertEquals(len(res2), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=cn=person,cn=schema,cn=configuration," + self.base_dn + "))")
@@ -675,14 +902,14 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog"
res3gc = gc_ldb.search(expression="(&(cn=ldaptestuser)(objectCategory=PerSon))")
self.assertEquals(len(res3gc), 1)
-
+
self.assertEquals(res[0].dn, res3gc[0].dn)
print "Testing ldb.search for (&(cn=ldaptestuser)(objectCategory=PerSon)) in with 'phantom root' control"
-
+
res3control = gc_ldb.search(self.base_dn, expression="(&(cn=ldaptestuser)(objectCategory=PerSon))", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:2"])
self.assertEquals(len(res3control), 1, "Could not find (&(cn=ldaptestuser)(objectCategory=PerSon)) in Global Catalog")
-
+
self.assertEquals(res[0].dn, res3control[0].dn)
ldb.delete(res[0].dn)
@@ -747,7 +974,7 @@ member: cn=ldaptestuser4,cn=ldaptestcontainer,""" + self.base_dn + """
self.assertEquals(len(res6), 1, "Could not find (&(cn=*daptestcomputer)(objectCategory=compuTER))")
self.assertEquals(res[0].dn, res6[0].dn)
-
+
ldb.delete("<GUID=" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + ">")
print "Testing ldb.search for (&(cn=ldaptest2computer)(objectClass=user))"
@@ -825,14 +1052,14 @@ replace: member
member: CN=ldaptestuser2,CN=Users,""" + self.base_dn + """
member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
""")
-
+
ldb.modify_ldif("""
dn: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
changetype: modify
replace: member
member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
""")
-
+
ldb.modify_ldif("""
dn: <SID=""" + ldb.schema_format_value("objectSid", res[0]["objectSid"][0]) + """>
changetype: modify
@@ -846,13 +1073,13 @@ add: member
member: <GUID=""" + ldb.schema_format_value("objectGUID", res[0]["objectGUID"][0]) + """>
member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
""")
-
+
ldb.modify_ldif("""
dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
changetype: modify
replace: member
""")
-
+
ldb.modify_ldif("""
dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
changetype: modify
@@ -860,14 +1087,14 @@ add: member
member: <SID=""" + ldb.schema_format_value("objectSid", res_user[0]["objectSid"][0]) + """>
member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
""")
-
+
ldb.modify_ldif("""
dn: cn=ldaptestgroup2,cn=users,""" + self.base_dn + """
changetype: modify
delete: member
member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
""")
-
+
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))")
@@ -923,14 +1150,14 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
if gc_ldb is not None:
print "Testing that we can get at the configuration DN from the main search base on the GC port with the search_options control == 0"
-
+
res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["search_options:1:0"])
self.assertTrue(len(res) > 0)
print "Testing that we do find configuration elements in the global catlog"
res = gc_ldb.search(self.base_dn, expression="objectClass=crossRef", scope=SCOPE_SUBTREE, attrs=["cn"])
self.assertTrue(len(res) > 0)
-
+
print "Testing that we do find configuration elements and user elements at the same time"
res = gc_ldb.search(self.base_dn, expression="(|(objectClass=crossRef)(objectClass=person))", scope=SCOPE_SUBTREE, attrs=["cn"])
self.assertTrue(len(res) > 0)
@@ -947,13 +1174,13 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
res = ldb.search(self.configuration_dn, expression="objectCategory=ntDsDSA", scope=SCOPE_SUBTREE, attrs=["cn"])
self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=ntDsDSA")
self.assertTrue(len(res) != 0)
-
+
res = ldb.search(self.configuration_dn, expression="objectCategory=CN=ntDs-DSA," + self.schema_dn, scope=SCOPE_SUBTREE, attrs=["cn"])
self.assertTrue(len(res) > 0, "Didn't find any records with objectCategory=CN=ntDs-DSA," + self.schema_dn)
self.assertTrue(len(res) != 0)
-
+
print "Testing objectClass attribute order on "+ self.base_dn
- res = ldb.search(expression="objectClass=domain", base=self.base_dn,
+ res = ldb.search(expression="objectClass=domain", base=self.base_dn,
scope=SCOPE_BASE, attrs=["objectClass"])
self.assertEquals(len(res), 1)
@@ -968,15 +1195,15 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
print "Testing ldb.search for objectCategory=person with domain scope control"
res = ldb.search(self.base_dn, expression="objectCategory=person", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
self.assertTrue(len(res) > 0)
-
+
print "Testing ldb.search for objectCategory=user"
res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"])
self.assertTrue(len(res) > 0)
-
+
print "Testing ldb.search for objectCategory=user with domain scope control"
res = ldb.search(self.base_dn, expression="objectCategory=user", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
self.assertTrue(len(res) > 0)
-
+
print "Testing ldb.search for objectCategory=group"
res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"])
self.assertTrue(len(res) > 0)
@@ -985,6 +1212,189 @@ member: CN=ldaptestutf8user èùéìòà,CN=Users,""" + self.base_dn + """
res = ldb.search(self.base_dn, expression="objectCategory=group", scope=SCOPE_SUBTREE, attrs=["cn"], controls=["domain_scope:1"])
self.assertTrue(len(res) > 0)
+ def test_security_descriptor_add(self):
+ """ Testing ldb.add_ldif() for nTSecurityDescriptor """
+ user_name = "testdescriptoruser1"
+ user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
+ #
+ # Test add_ldif() with SDDL security descriptor input
+ #
+ self.delete_force(self.ldb, user_dn)
+ try:
+ sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
+ self.ldb.add_ldif("""
+dn: """ + user_dn + """
+objectclass: user
+sAMAccountName: """ + user_name + """
+nTSecurityDescriptor: """ + sddl)
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ desc = ndr_unpack( security.descriptor, desc )
+ desc_sddl = desc.as_sddl( self.domain_sid )
+ self.assertEqual(desc_sddl, sddl)
+ finally:
+ self.delete_force(self.ldb, user_dn)
+ #
+ # Test add_ldif() with BASE64 security descriptor
+ #
+ try:
+ sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
+ desc = security.descriptor.from_sddl(sddl, self.domain_sid)
+ desc_binary = ndr_pack(desc)
+ desc_base64 = base64.b64encode(desc_binary)
+ self.ldb.add_ldif("""
+dn: """ + user_dn + """
+objectclass: user
+sAMAccountName: """ + user_name + """
+nTSecurityDescriptor:: """ + desc_base64)
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ desc = ndr_unpack(security.descriptor, desc)
+ desc_sddl = desc.as_sddl(self.domain_sid)
+ self.assertEqual(desc_sddl, sddl)
+ finally:
+ self.delete_force(self.ldb, user_dn)
+
+ def test_security_descriptor_add_neg(self):
+ """Test add_ldif() with BASE64 security descriptor input using WRONG domain SID
+ Negative test
+ """
+ user_name = "testdescriptoruser1"
+ user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
+ self.delete_force(self.ldb, user_dn)
+ try:
+ sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
+ desc = security.descriptor.from_sddl(sddl, security.dom_sid('S-1-5-21'))
+ desc_base64 = base64.b64encode( ndr_pack(desc) )
+ self.ldb.add_ldif("""
+dn: """ + user_dn + """
+objectclass: user
+sAMAccountName: """ + user_name + """
+nTSecurityDescriptor:: """ + desc_base64)
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ print res
+ self.assertRaises(KeyError, lambda: res[0]["nTSecurityDescriptor"])
+ finally:
+ self.delete_force(self.ldb, user_dn)
+
+ def test_security_descriptor_modify(self):
+ """ Testing ldb.modify_ldif() for nTSecurityDescriptor """
+ user_name = "testdescriptoruser2"
+ user_dn = "CN=%s,CN=Users,%s" % (user_name, self.base_dn)
+ #
+ # Delete user object and test modify_ldif() with SDDL security descriptor input
+ # Add ACE to the original descriptor test
+ #
+ try:
+ self.delete_force(self.ldb, user_dn)
+ self.ldb.add_ldif("""
+dn: """ + user_dn + """
+objectclass: user
+sAMAccountName: """ + user_name)
+ # Modify descriptor
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ desc = ndr_unpack(security.descriptor, desc)
+ desc_sddl = desc.as_sddl(self.domain_sid)
+ sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
+ mod = """
+dn: """ + user_dn + """
+changetype: modify
+replace: nTSecurityDescriptor
+nTSecurityDescriptor: """ + sddl
+ self.ldb.modify_ldif(mod)
+ # Read modified descriptor
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ desc = ndr_unpack(security.descriptor, desc)
+ desc_sddl = desc.as_sddl(self.domain_sid)
+ self.assertEqual(desc_sddl, sddl)
+ finally:
+ self.delete_force(self.ldb, user_dn)
+ #
+ # Test modify_ldif() with SDDL security descriptor input
+ # New desctiptor test
+ #
+ try:
+ self.ldb.add_ldif("""
+dn: """ + user_dn + """
+objectclass: user
+sAMAccountName: """ + user_name)
+ # Modify descriptor
+ sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
+ mod = """
+dn: """ + user_dn + """
+changetype: modify
+replace: nTSecurityDescriptor
+nTSecurityDescriptor: """ + sddl
+ self.ldb.modify_ldif(mod)
+ # Read modified descriptor
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ desc = ndr_unpack(security.descriptor, desc)
+ desc_sddl = desc.as_sddl(self.domain_sid)
+ self.assertEqual(desc_sddl, sddl)
+ finally:
+ self.delete_force(self.ldb, user_dn)
+ #
+ # Test modify_ldif() with BASE64 security descriptor input
+ # Add ACE to the original descriptor test
+ #
+ try:
+ self.ldb.add_ldif("""
+dn: """ + user_dn + """
+objectclass: user
+sAMAccountName: """ + user_name)
+ # Modify descriptor
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ desc = ndr_unpack(security.descriptor, desc)
+ desc_sddl = desc.as_sddl(self.domain_sid)
+ sddl = desc_sddl[:desc_sddl.find("(")] + "(A;;RPWP;;;AU)" + desc_sddl[desc_sddl.find("("):]
+ desc = security.descriptor.from_sddl(sddl, self.domain_sid)
+ desc_base64 = base64.b64encode(ndr_pack(desc))
+ mod = """
+dn: """ + user_dn + """
+changetype: modify
+replace: nTSecurityDescriptor
+nTSecurityDescriptor:: """ + desc_base64
+ self.ldb.modify_ldif(mod)
+ # Read modified descriptor
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ desc = ndr_unpack(security.descriptor, desc)
+ desc_sddl = desc.as_sddl(self.domain_sid)
+ self.assertEqual(desc_sddl, sddl)
+ finally:
+ self.delete_force(self.ldb, user_dn)
+ #
+ # Test modify_ldif() with BASE64 security descriptor input
+ # New descriptor test
+ #
+ try:
+ self.delete_force(self.ldb, user_dn)
+ self.ldb.add_ldif("""
+dn: """ + user_dn + """
+objectclass: user
+sAMAccountName: """ + user_name)
+ # Modify descriptor
+ sddl = "O:DUG:DUD:PAI(A;;RPWP;;;AU)S:PAI"
+ desc = security.descriptor.from_sddl(sddl, self.domain_sid)
+ desc_base64 = base64.b64encode(ndr_pack(desc))
+ mod = """
+dn: """ + user_dn + """
+changetype: modify
+replace: nTSecurityDescriptor
+nTSecurityDescriptor:: """ + desc_base64
+ self.ldb.modify_ldif(mod)
+ # Read modified descriptor
+ res = self.ldb.search(base=user_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ desc = ndr_unpack(security.descriptor, desc)
+ desc_sddl = desc.as_sddl(self.domain_sid)
+ self.assertEqual(desc_sddl, sddl)
+ finally:
+ self.delete_force(self.ldb, user_dn)
class BaseDnTests(unittest.TestCase):
def setUp(self):
@@ -1008,23 +1418,36 @@ class BaseDnTests(unittest.TestCase):
def test_netlogon_highestcommitted_usn(self):
"""Testing for netlogon and highestCommittedUSN via LDAP"""
- res = self.ldb.search("", scope=SCOPE_BASE,
+ res = self.ldb.search("", scope=SCOPE_BASE,
attrs=["netlogon", "highestCommittedUSN"])
self.assertEquals(len(res), 0)
class SchemaTests(unittest.TestCase):
+ def delete_force(self, ldb, dn):
+ try:
+ ldb.delete(dn)
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_NO_SUCH_OBJECT)
+
def find_schemadn(self, ldb):
res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
self.assertEquals(len(res), 1)
return res[0]["schemaNamingContext"][0]
+ def find_basedn(self, ldb):
+ res = ldb.search(base="", expression="", scope=SCOPE_BASE,
+ attrs=["defaultNamingContext"])
+ self.assertEquals(len(res), 1)
+ return res[0]["defaultNamingContext"][0]
+
def setUp(self):
self.ldb = ldb
self.schema_dn = self.find_schemadn(ldb)
+ self.base_dn = self.find_basedn(ldb)
def test_generated_schema(self):
"""Testing we can read the generated schema via LDAP"""
- res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
+ res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
attrs=["objectClasses", "attributeTypes", "dITContentRules"])
self.assertEquals(len(res), 1)
self.assertTrue("dITContentRules" in res[0])
@@ -1033,18 +1456,77 @@ class SchemaTests(unittest.TestCase):
def test_generated_schema_is_operational(self):
"""Testing we don't get the generated schema via LDAP by default"""
- res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
+ res = self.ldb.search("cn=aggregate,"+self.schema_dn, scope=SCOPE_BASE,
attrs=["*"])
self.assertEquals(len(res), 1)
self.assertFalse("dITContentRules" in res[0])
self.assertFalse("objectClasses" in res[0])
self.assertFalse("attributeTypes" in res[0])
-
+
+ def test_schemaUpdateNow(self):
+ """Testing schemaUpdateNow"""
+ class_name = "test-class" + time.strftime("%s", time.gmtime())
+ class_ldap_display_name = class_name.replace("-", "")
+ object_name = "obj" + time.strftime("%s", time.gmtime())
+
+ ldif = """
+dn: CN=%s,%s""" % (class_name, self.schema_dn) + """
+lDAPDisplayName: """ + class_ldap_display_name + """
+objectClass: top
+objectClass: classSchema
+adminDescription: """ + class_name + """
+adminDisplayName: """ + class_name + """
+cn: """ + class_name + """
+objectCategory: CN=Class-Schema,""" + self.schema_dn + """
+defaultObjectCategory: CN=%s,%s""" % (class_name, self.schema_dn) + """
+distinguishedName: CN=%s,%s""" % (class_name, self.schema_dn) + """
+governsID: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
+instanceType: 4
+name: """ + class_name + """
+objectClassCategory: 1
+subClassOf: organizationalPerson
+systemFlags: 16
+rDNAttID: cn
+systemMustContain: cn
+systemOnly: FALSE
+"""
+ self.ldb.add_ldif(ldif)
+ ldif = """
+dn:
+changetype: modify
+add: schemaUpdateNow
+schemaUpdateNow: 1
+"""
+ self.ldb.modify_ldif(ldif)
+ ldif = """
+dn: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
+objectClass: organizationalPerson
+objectClass: person
+objectClass: """ + class_ldap_display_name + """
+objectClass: top
+cn: """ + object_name + """
+instanceType: 4
+objectCategory: CN=%s,%s"""% (class_name, self.schema_dn) + """
+distinguishedName: CN=%s,CN=Users,%s"""% (object_name, self.base_dn) + """
+name: """ + object_name + """
+"""
+ self.ldb.add_ldif(ldif)
+ # Search for created objectClass
+ res = []
+ res = self.ldb.search("cn=%s,%s" % (class_name, self.schema_dn), scope=SCOPE_BASE, attrs=["*"])
+ self.assertNotEqual(res, [])
+
+ res = []
+ res = self.ldb.search("cn=%s,cn=Users,%s" % (object_name, self.base_dn), scope=SCOPE_BASE, attrs=["*"])
+ self.assertNotEqual(res, [])
+ # Delete the object
+ self.delete_force(self.ldb, "cn=%s,cn=Users,%s" % (object_name, self.base_dn))
+
if not "://" in host:
host = "ldap://%s" % host
ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
-gc_ldb = Ldb("%s:3268" % host, credentials=creds,
+gc_ldb = Ldb("%s:3268" % host, credentials=creds,
session_info=system_session(), lp=lp)
runner = SubunitTestRunner()
diff --git a/source4/lib/ldb/tests/python/sec_descriptor.py b/source4/lib/ldb/tests/python/sec_descriptor.py
new file mode 100755
index 0000000000..155b65f4ab
--- /dev/null
+++ b/source4/lib/ldb/tests/python/sec_descriptor.py
@@ -0,0 +1,1615 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+import getopt
+import optparse
+import sys
+import os
+import base64
+import re
+import random
+
+sys.path.append("bin/python")
+sys.path.append("../lib/subunit/python")
+
+import samba.getopt as options
+
+# Some error messages that are being tested
+from ldb import SCOPE_SUBTREE, SCOPE_ONELEVEL, SCOPE_BASE, LdbError
+from ldb import ERR_NO_SUCH_OBJECT, ERR_INVALID_DN_SYNTAX, ERR_UNWILLING_TO_PERFORM
+from ldb import ERR_INSUFFICIENT_ACCESS_RIGHTS
+
+# For running the test unit
+from samba.ndr import ndr_pack, ndr_unpack
+from samba.dcerpc import security
+
+from samba.auth import system_session
+from samba import Ldb, DS_DOMAIN_FUNCTION_2008
+from subunit import SubunitTestRunner
+import unittest
+
+parser = optparse.OptionParser("sec_descriptor [options] <host>")
+sambaopts = options.SambaOptions(parser)
+parser.add_option_group(sambaopts)
+parser.add_option_group(options.VersionOptions(parser))
+
+# use command line creds if available
+credopts = options.CredentialsOptions(parser)
+parser.add_option_group(credopts)
+opts, args = parser.parse_args()
+
+if len(args) < 1:
+ parser.print_usage()
+ sys.exit(1)
+
+host = args[0]
+
+lp = sambaopts.get_loadparm()
+creds = credopts.get_credentials(lp)
+
+#
+# Tests start here
+#
+
+class DescriptorTests(unittest.TestCase):
+
+ def delete_force(self, ldb, dn):
+ try:
+ ldb.delete(dn)
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_NO_SUCH_OBJECT)
+
+ def find_basedn(self, ldb):
+ res = ldb.search(base="", expression="", scope=SCOPE_BASE,
+ attrs=["defaultNamingContext"])
+ self.assertEquals(len(res), 1)
+ return res[0]["defaultNamingContext"][0]
+
+ def find_configurationdn(self, ldb):
+ res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["configurationNamingContext"])
+ self.assertEquals(len(res), 1)
+ return res[0]["configurationNamingContext"][0]
+
+ def find_schemadn(self, ldb):
+ res = ldb.search(base="", expression="", scope=SCOPE_BASE, attrs=["schemaNamingContext"])
+ self.assertEquals(len(res), 1)
+ return res[0]["schemaNamingContext"][0]
+
+ def find_domain_sid(self, ldb):
+ res = ldb.search(base=self.base_dn, expression="(objectClass=*)", scope=SCOPE_BASE)
+ return ndr_unpack( security.dom_sid,res[0]["objectSid"][0])
+
+ def get_users_domain_dn(self, name):
+ return "CN=%s,CN=Users,%s" % (name, self.base_dn)
+
+ def modify_desc(self, object_dn, desc):
+ assert(isinstance(desc, str) or isinstance(desc, security.descriptor))
+ mod = """
+dn: """ + object_dn + """
+changetype: modify
+replace: nTSecurityDescriptor
+"""
+ if isinstance(desc, str):
+ mod += "nTSecurityDescriptor: %s" % desc
+ elif isinstance(desc, security.descriptor):
+ mod += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
+ self.ldb_admin.modify_ldif(mod)
+
+ def create_domain_ou(self, _ldb, ou_dn, desc=None):
+ ldif = """
+dn: """ + ou_dn + """
+ou: """ + ou_dn.split(",")[0][3:] + """
+objectClass: organizationalUnit
+url: www.example.com
+"""
+ if desc:
+ assert(isinstance(desc, str) or isinstance(desc, security.descriptor))
+ if isinstance(desc, str):
+ ldif += "nTSecurityDescriptor: %s" % desc
+ elif isinstance(desc, security.descriptor):
+ ldif += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
+ _ldb.add_ldif(ldif)
+
+ def create_domain_user(self, _ldb, user_dn, desc=None):
+ ldif = """
+dn: """ + user_dn + """
+sAMAccountName: """ + user_dn.split(",")[0][3:] + """
+objectClass: user
+userPassword: samba123@
+url: www.example.com
+"""
+ if desc:
+ assert(isinstance(desc, str) or isinstance(desc, security.descriptor))
+ if isinstance(desc, str):
+ ldif += "nTSecurityDescriptor: %s" % desc
+ elif isinstance(desc, security.descriptor):
+ ldif += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
+ _ldb.add_ldif(ldif)
+
+ def create_domain_group(self, _ldb, group_dn, desc=None):
+ ldif = """
+dn: """ + group_dn + """
+objectClass: group
+sAMAccountName: """ + group_dn.split(",")[0][3:] + """
+groupType: 4
+url: www.example.com
+"""
+ if desc:
+ assert(isinstance(desc, str) or isinstance(desc, security.descriptor))
+ if isinstance(desc, str):
+ ldif += "nTSecurityDescriptor: %s" % desc
+ elif isinstance(desc, security.descriptor):
+ ldif += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
+ _ldb.add_ldif(ldif)
+
+ def get_unique_schema_class_name(self):
+ while True:
+ class_name = "test-class%s" % random.randint(1,100000)
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ try:
+ self.ldb_admin.search(base=class_dn, attrs=["*"])
+ except LdbError, (num, _):
+ self.assertEquals(num, ERR_NO_SUCH_OBJECT)
+ return class_name
+
+ def create_schema_class(self, _ldb, object_dn, desc=None):
+ ldif = """
+dn: """ + object_dn + """
+objectClass: classSchema
+objectCategory: CN=Class-Schema,""" + self.schema_dn + """
+defaultObjectCategory: """ + object_dn + """
+distinguishedName: """ + object_dn + """
+governsID: 1.2.840.""" + str(random.randint(1,100000)) + """.1.5.9939
+instanceType: 4
+objectClassCategory: 1
+subClassOf: organizationalPerson
+systemFlags: 16
+rDNAttID: cn
+systemMustContain: cn
+systemOnly: FALSE
+"""
+ if desc:
+ assert(isinstance(desc, str) or isinstance(desc, security.descriptor))
+ if isinstance(desc, str):
+ ldif += "nTSecurityDescriptor: %s" % desc
+ elif isinstance(desc, security.descriptor):
+ ldif += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
+ _ldb.add_ldif(ldif)
+
+ def create_configuration_container(self, _ldb, object_dn, desc=None):
+ ldif = """
+dn: """ + object_dn + """
+objectClass: container
+objectCategory: CN=Container,""" + self.schema_dn + """
+showInAdvancedViewOnly: TRUE
+instanceType: 4
+"""
+ if desc:
+ assert(isinstance(desc, str) or isinstance(desc, security.descriptor))
+ if isinstance(desc, str):
+ ldif += "nTSecurityDescriptor: %s" % desc
+ elif isinstance(desc, security.descriptor):
+ ldif += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
+ _ldb.add_ldif(ldif)
+
+ def create_configuration_specifier(self, _ldb, object_dn, desc=None):
+ ldif = """
+dn: """ + object_dn + """
+objectClass: displaySpecifier
+showInAdvancedViewOnly: TRUE
+"""
+ if desc:
+ assert(isinstance(desc, str) or isinstance(desc, security.descriptor))
+ if isinstance(desc, str):
+ ldif += "nTSecurityDescriptor: %s" % desc
+ elif isinstance(desc, security.descriptor):
+ ldif += "nTSecurityDescriptor:: %s" % base64.b64encode(ndr_pack(desc))
+ _ldb.add_ldif(ldif)
+
+ def read_desc(self, object_dn):
+ res = self.ldb_admin.search(base=object_dn, attrs=["nTSecurityDescriptor"])
+ desc = res[0]["nTSecurityDescriptor"][0]
+ return ndr_unpack( security.descriptor, desc )
+
+ def enable_account(self, user_dn):
+ """Enable an account.
+ :param user_dn: Dn of the account to enable.
+ """
+ res = self.ldb_admin.search(user_dn, SCOPE_BASE, None, ["userAccountControl"])
+ assert len(res) == 1
+ userAccountControl = res[0]["userAccountControl"][0]
+ userAccountControl = int(userAccountControl)
+ if (userAccountControl & 0x2):
+ userAccountControl = userAccountControl & ~0x2 # remove disabled bit
+ if (userAccountControl & 0x20):
+ userAccountControl = userAccountControl & ~0x20 # remove 'no password required' bit
+ mod = """
+dn: """ + user_dn + """
+changetype: modify
+replace: userAccountControl
+userAccountControl: %s""" % userAccountControl
+ if self.WIN2003:
+ mod = re.sub("userAccountControl: \d.*", "userAccountControl: 544", mod)
+ self.ldb_admin.modify_ldif(mod)
+
+ def get_ldb_connection(self, target_username, target_password):
+ username_save = creds.get_username(); password_save = creds.get_password()
+ creds.set_username(target_username)
+ creds.set_password(target_password)
+ ldb_target = Ldb(host, credentials=creds, session_info=system_session(), lp=lp)
+ creds.set_username(username_save); creds.set_password(password_save)
+ return ldb_target
+
+ def get_object_sid(self, object_dn):
+ res = self.ldb_admin.search(object_dn)
+ return ndr_unpack( security.dom_sid, res[0]["objectSid"][0] )
+
+ def dacl_add_ace(self, object_dn, ace):
+ desc = self.read_desc( object_dn )
+ desc_sddl = desc.as_sddl( self.domain_sid )
+ if ace in desc_sddl:
+ return
+ if desc_sddl.find("(") >= 0:
+ desc_sddl = desc_sddl[0:desc_sddl.index("(")] + ace + desc_sddl[desc_sddl.index("("):]
+ else:
+ desc_sddl = desc_sddl + ace
+ self.modify_desc(object_dn, desc_sddl)
+
+ def get_desc_sddl(self, object_dn):
+ """ Return object nTSecutiryDescriptor in SDDL format
+ """
+ desc = self.read_desc(object_dn)
+ return desc.as_sddl(self.domain_sid)
+
+ def setUp(self):
+ self.ldb_admin = ldb
+ self.base_dn = self.find_basedn(self.ldb_admin)
+ self.configuration_dn = self.find_configurationdn(self.ldb_admin)
+ self.schema_dn = self.find_schemadn(self.ldb_admin)
+ self.domain_sid = self.find_domain_sid(self.ldb_admin)
+ print "baseDN: %s" % self.base_dn
+ self.SAMBA = False; self.WIN2003 = False
+ res = self.ldb_admin.search(base="", expression="", scope=SCOPE_BASE, attrs=["vendorName"])
+ if "vendorName" in res[0].keys() and "Samba Team" in res[0]["vendorName"][0]:
+ self.SAMBA = True
+ else:
+ self.WIN2003 = True
+ #print "self.SAMBA:", self.SAMBA
+ #print "self.WIN2003:", self.WIN2003
+
+ ################################################################################################
+
+ ## Tests for DOMAIN
+
+ # Default descriptor tests #####################################################################
+
+class OwnerGroupDescriptorTests(DescriptorTests):
+
+ def setUp(self):
+ DescriptorTests.setUp(self)
+ if self.SAMBA:
+ ### Create users
+ # User 1
+ user_dn = self.get_users_domain_dn("testuser1")
+ self.create_domain_user(self.ldb_admin, user_dn)
+ self.enable_account(user_dn)
+ ldif = """
+dn: CN=Enterprise Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn
+ self.ldb_admin.modify_ldif(ldif)
+ # User 2
+ user_dn = self.get_users_domain_dn("testuser2")
+ self.create_domain_user(self.ldb_admin, user_dn)
+ self.enable_account(user_dn)
+ ldif = """
+dn: CN=Domain Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn
+ self.ldb_admin.modify_ldif(ldif)
+ # User 3
+ user_dn = self.get_users_domain_dn("testuser3")
+ self.create_domain_user(self.ldb_admin, user_dn)
+ self.enable_account(user_dn)
+ ldif = """
+dn: CN=Schema Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn
+ self.ldb_admin.modify_ldif(ldif)
+ # User 4
+ user_dn = self.get_users_domain_dn("testuser4")
+ self.create_domain_user(self.ldb_admin, user_dn)
+ self.enable_account(user_dn)
+ # User 5
+ user_dn = self.get_users_domain_dn("testuser5")
+ self.create_domain_user(self.ldb_admin, user_dn)
+ self.enable_account(user_dn)
+ ldif = """
+dn: CN=Enterprise Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn + """
+
+dn: CN=Domain Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn
+ self.ldb_admin.modify_ldif(ldif)
+ # User 6
+ user_dn = self.get_users_domain_dn("testuser6")
+ self.create_domain_user(self.ldb_admin, user_dn)
+ self.enable_account(user_dn)
+ ldif = """
+dn: CN=Enterprise Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn + """
+
+dn: CN=Domain Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn + """
+
+dn: CN=Schema Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn
+ self.ldb_admin.modify_ldif(ldif)
+ # User 7
+ user_dn = self.get_users_domain_dn("testuser7")
+ self.create_domain_user(self.ldb_admin, user_dn)
+ self.enable_account(user_dn)
+ ldif = """
+dn: CN=Domain Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn + """
+
+dn: CN=Schema Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn
+ self.ldb_admin.modify_ldif(ldif)
+ # User 8
+ user_dn = self.get_users_domain_dn("testuser8")
+ self.create_domain_user(self.ldb_admin, user_dn)
+ self.enable_account(user_dn)
+ ldif = """
+dn: CN=Enterprise Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn + """
+
+dn: CN=Schema Admins,CN=Users,""" + self.base_dn + """
+changetype: add
+member: """ + user_dn
+ self.ldb_admin.modify_ldif(ldif)
+ self.results = {
+ # msDS-Behavior-Version < DS_DOMAIN_FUNCTION_2008
+ "ds_behavior_win2003" : {
+ "100" : "O:EAG:DU",
+ "101" : "O:DAG:DU",
+ "102" : "O:%sG:DU",
+ "103" : "O:%sG:DU",
+ "104" : "O:DAG:DU",
+ "105" : "O:DAG:DU",
+ "106" : "O:DAG:DU",
+ "107" : "O:EAG:DU",
+ "108" : "O:DAG:DA",
+ "109" : "O:DAG:DA",
+ "110" : "O:%sG:DA",
+ "111" : "O:%sG:DA",
+ "112" : "O:DAG:DA",
+ "113" : "O:DAG:DA",
+ "114" : "O:DAG:DA",
+ "115" : "O:DAG:DA",
+ "130" : "O:EAG:DU",
+ "131" : "O:DAG:DU",
+ "132" : "O:SAG:DU",
+ "133" : "O:%sG:DU",
+ "134" : "O:EAG:DU",
+ "135" : "O:SAG:DU",
+ "136" : "O:SAG:DU",
+ "137" : "O:SAG:DU",
+ "138" : "O:DAG:DA",
+ "139" : "O:DAG:DA",
+ "140" : "O:%sG:DA",
+ "141" : "O:%sG:DA",
+ "142" : "O:DAG:DA",
+ "143" : "O:DAG:DA",
+ "144" : "O:DAG:DA",
+ "145" : "O:DAG:DA",
+ "160" : "O:EAG:DU",
+ "161" : "O:DAG:DU",
+ "162" : "O:%sG:DU",
+ "163" : "O:%sG:DU",
+ "164" : "O:EAG:DU",
+ "165" : "O:EAG:DU",
+ "166" : "O:DAG:DU",
+ "167" : "O:EAG:DU",
+ "168" : "O:DAG:DA",
+ "169" : "O:DAG:DA",
+ "170" : "O:%sG:DA",
+ "171" : "O:%sG:DA",
+ "172" : "O:DAG:DA",
+ "173" : "O:DAG:DA",
+ "174" : "O:DAG:DA",
+ "175" : "O:DAG:DA",
+ },
+ # msDS-Behavior-Version >= 3
+ "ds_behavior_win2008" : {
+ "100" : "O:EAG:EA",
+ "101" : "O:DAG:DA",
+ "102" : "O:%sG:DU",
+ "103" : "O:%sG:DU",
+ "104" : "O:DAG:DA",
+ "105" : "O:DAG:DA",
+ "106" : "O:DAG:DA",
+ "107" : "O:EAG:EA",
+ "108" : "O:DAG:DA",
+ "109" : "O:DAG:DA",
+ "110" : "O:%sG:DA",
+ "111" : "O:%sG:DA",
+ "112" : "O:DAG:DA",
+ "113" : "O:DAG:DA",
+ "114" : "O:DAG:DA",
+ "115" : "O:DAG:DA",
+ "130" : "",
+ "131" : "",
+ "132" : "",
+ "133" : "%s",
+ "134" : "",
+ "135" : "",
+ "136" : "",
+ "137" : "",
+ "138" : "",
+ "139" : "",
+ "140" : "%s",
+ "141" : "%s",
+ "142" : "",
+ "143" : "",
+ "144" : "",
+ "145" : "",
+ "160" : "O:EAG:EA",
+ "161" : "O:DAG:DA",
+ "162" : "O:%sG:DU",
+ "163" : "O:%sG:DU",
+ "164" : "O:EAG:EA",
+ "165" : "O:EAG:EA",
+ "166" : "O:DAG:DA",
+ "167" : "O:EAG:EA",
+ "168" : "O:DAG:DA",
+ "169" : "O:DAG:DA",
+ "170" : "O:%sG:DA",
+ "171" : "O:%sG:DA",
+ "172" : "O:DAG:DA",
+ "173" : "O:DAG:DA",
+ "174" : "O:DAG:DA",
+ "175" : "O:DAG:DA",
+ },
+ }
+ # Discover 'msDS-Behavior-Version'
+ res = self.ldb_admin.search(base=self.base_dn, expression="distinguishedName=%s" % self.base_dn, \
+ attrs=['msDS-Behavior-Version'])
+ res = int(res[0]['msDS-Behavior-Version'][0])
+ if res < DS_DOMAIN_FUNCTION_2008:
+ self.DS_BEHAVIOR = "ds_behavior_win2003"
+ else:
+ self.DS_BEHAVIOR = "ds_behavior_win2008"
+
+ def tearDown(self):
+ if self.SAMBA:
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("testuser1"))
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("testuser2"))
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("testuser3"))
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("testuser4"))
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("testuser5"))
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("testuser6"))
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("testuser7"))
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("testuser8"))
+ # DOMAIN
+ self.delete_force(self.ldb_admin, self.get_users_domain_dn("test_domain_group1"))
+ self.delete_force(self.ldb_admin, "CN=test_domain_user1,OU=test_domain_ou1," + self.base_dn)
+ self.delete_force(self.ldb_admin, "OU=test_domain_ou2,OU=test_domain_ou1," + self.base_dn)
+ self.delete_force(self.ldb_admin, "OU=test_domain_ou1," + self.base_dn)
+ # SCHEMA
+ # CONFIGURATION
+ self.delete_force(self.ldb_admin, "CN=test-specifier1,CN=test-container1,CN=DisplaySpecifiers," \
+ + self.configuration_dn)
+ self.delete_force(self.ldb_admin, "CN=test-container1,CN=DisplaySpecifiers," + self.configuration_dn)
+
+ def check_user_belongs(self, user_dn, groups=[]):
+ """ Test wether user is member of the expected group(s) """
+ if groups != []:
+ # User is member of at least one additional group
+ res = self.ldb_admin.search(user_dn, attrs=["memberOf"])
+ res = [x.upper() for x in sorted(list(res[0]["memberOf"]))]
+ expected = []
+ for x in groups:
+ expected.append(self.get_users_domain_dn(x))
+ expected = [x.upper() for x in sorted(expected)]
+ self.assertEqual(expected, res)
+ else:
+ # User is not a member of any additional groups but default
+ res = self.ldb_admin.search(user_dn, attrs=["*"])
+ res = [x.upper() for x in res[0].keys()]
+ self.assertFalse( "MEMBEROF" in res)
+
+ def test_100(self):
+ """ Enterprise admin group member creates object (default nTSecurityDescriptor) in DOMAIN
+ """
+ user_name = "testuser1"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection("testuser1", "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ self.create_domain_group(_ldb, group_dn)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["100"], res)
+
+ def test_101(self):
+ """ Dmain admin group member creates object (default nTSecurityDescriptor) in DOMAIN
+ """
+ user_name = "testuser2"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ self.create_domain_group(_ldb, group_dn)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["101"], res)
+
+ def test_102(self):
+ """ Schema admin group member with CC right creates object (default nTSecurityDescriptor) in DOMAIN
+ """
+ user_name = "testuser3"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ object_dn = "OU=test_domain_ou1," + self.base_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_ou(self.ldb_admin, object_dn)
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;%s)" % str(user_sid)
+ self.dacl_add_ace(object_dn, mod)
+ # Create additional object into the first one
+ object_dn = "CN=test_domain_user1," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_user(_ldb, object_dn)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["102"] % str(user_sid), res)
+
+ def test_103(self):
+ """ Regular user with CC right creates object (default nTSecurityDescriptor) in DOMAIN
+ """
+ user_name = "testuser4"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), [])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ object_dn = "OU=test_domain_ou1," + self.base_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_ou(self.ldb_admin, object_dn)
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;%s)" % str(user_sid)
+ self.dacl_add_ace(object_dn, mod)
+ # Create additional object into the first one
+ object_dn = "CN=test_domain_user1," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_user(_ldb, object_dn)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["103"] % str(user_sid), res)
+
+ def test_104(self):
+ """ Enterprise & Domain admin group member creates object (default nTSecurityDescriptor) in DOMAIN
+ """
+ user_name = "testuser5"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ self.create_domain_group(_ldb, group_dn)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["104"], res)
+
+ def test_105(self):
+ """ Enterprise & Domain & Schema admin group member creates object (default nTSecurityDescriptor) in DOMAIN
+ """
+ user_name = "testuser6"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ self.create_domain_group(_ldb, group_dn)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["105"], res)
+
+ def test_106(self):
+ """ Domain & Schema admin group member creates object (default nTSecurityDescriptor) in DOMAIN
+ """
+ user_name = "testuser7"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ self.create_domain_group(_ldb, group_dn)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["106"], res)
+
+ def test_107(self):
+ """ Enterprise & Schema admin group member creates object (default nTSecurityDescriptor) in DOMAIN
+ """
+ user_name = "testuser8"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ self.create_domain_group(_ldb, group_dn)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["107"], res)
+
+ # Control descriptor tests #####################################################################
+
+ def test_108(self):
+ """ Enterprise admin group member creates object (custom descriptor) in DOMAIN
+ """
+ user_name = "testuser1"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_domain_group(_ldb, group_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["108"], res)
+
+ def test_109(self):
+ """ Domain admin group member creates object (custom descriptor) in DOMAIN
+ """
+ user_name = "testuser2"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_domain_group(_ldb, group_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["109"], res)
+
+ def test_110(self):
+ """ Schema admin group member with CC right creates object (custom descriptor) in DOMAIN
+ """
+ user_name = "testuser3"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ object_dn = "OU=test_domain_ou1," + self.base_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_ou(self.ldb_admin, object_dn)
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;%s)" % str(user_sid)
+ self.dacl_add_ace(object_dn, mod)
+ # Create a custom security descriptor
+ # NB! Problematic owner part won't accept DA only <User Sid> !!!
+ desc_sddl = "O:%sG:DAD:(A;;RP;;;DU)" % str(user_sid)
+ # Create additional object into the first one
+ object_dn = "CN=test_domain_user1," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_user(_ldb, object_dn, desc_sddl)
+ desc = self.read_desc(object_dn)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["110"] % str(user_sid), res)
+
+ def test_111(self):
+ """ Regular user with CC right creates object (custom descriptor) in DOMAIN
+ """
+ user_name = "testuser4"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), [])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ object_dn = "OU=test_domain_ou1," + self.base_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_ou(self.ldb_admin, object_dn)
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;%s)" % str(user_sid)
+ self.dacl_add_ace(object_dn, mod)
+ # Create a custom security descriptor
+ # NB! Problematic owner part won't accept DA only <User Sid> !!!
+ desc_sddl = "O:%sG:DAD:(A;;RP;;;DU)" % str(user_sid)
+ # Create additional object into the first one
+ object_dn = "CN=test_domain_user1," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_user(_ldb, object_dn, desc_sddl)
+ desc = self.read_desc(object_dn)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["111"] % str(user_sid), res)
+
+ def test_112(self):
+ """ Domain & Enterprise admin group member creates object (custom descriptor) in DOMAIN
+ """
+ user_name = "testuser5"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_domain_group(_ldb, group_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["112"], res)
+
+ def test_113(self):
+ """ Domain & Enterprise & Schema admin group member creates object (custom descriptor) in DOMAIN
+ """
+ user_name = "testuser6"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_domain_group(_ldb, group_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["113"], res)
+
+ def test_114(self):
+ """ Domain & Schema admin group member creates object (custom descriptor) in DOMAIN
+ """
+ user_name = "testuser7"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_domain_group(_ldb, group_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["114"], res)
+
+ def test_115(self):
+ """ Enterprise & Schema admin group member creates object (custom descriptor) in DOMAIN
+ """
+ user_name = "testuser8"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ group_dn = "CN=test_domain_group1,CN=Users," + self.base_dn
+ self.delete_force(self.ldb_admin, group_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_domain_group(_ldb, group_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(group_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["115"], res)
+
+
+ def test_999(self):
+ user_name = "Administrator"
+ object_dn = "OU=test_domain_ou1," + self.base_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_ou(self.ldb_admin, object_dn)
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(D;CI;WP;;;S-1-3-0)"
+ #mod = ""
+ self.dacl_add_ace(object_dn, mod)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ # Create additional object into the first one
+ object_dn = "OU=test_domain_ou2," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_domain_ou(self.ldb_admin, object_dn)
+ desc_sddl = self.get_desc_sddl(object_dn)
+
+ ## Tests for SCHEMA
+
+ # Defalt descriptor tests ##################################################################
+
+ def test_130(self):
+ user_name = "testuser1"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["130"], res)
+
+ def test_131(self):
+ user_name = "testuser2"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["131"], res)
+
+ def test_132(self):
+ user_name = "testuser3"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["132"], res)
+
+ def test_133(self):
+ user_name = "testuser4"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), [])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ #Change Schema partition descriptor
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["133"] % str(user_sid), res)
+
+ def test_134(self):
+ user_name = "testuser5"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ #Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["134"], res)
+
+ def test_135(self):
+ user_name = "testuser6"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["135"], res)
+
+ def test_136(self):
+ user_name = "testuser7"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["136"], res)
+
+ def test_137(self):
+ user_name = "testuser8"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["137"], res)
+
+ # Custom descriptor tests ##################################################################
+
+ def test_138(self):
+ user_name = "testuser1"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_139(self):
+ user_name = "testuser2"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_140(self):
+ user_name = "testuser3"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create a custom security descriptor
+ # NB! Problematic owner part won't accept DA only <User Sid> !!!
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ desc_sddl = "O:%sG:DAD:(A;;RP;;;DU)" % str(user_sid)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["140"] % str(user_sid), res)
+
+ def test_141(self):
+ user_name = "testuser4"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), [])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create a custom security descriptor
+ # NB! Problematic owner part won't accept DA only <User Sid> !!!
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ desc_sddl = "O:%sG:DAD:(A;;RP;;;DU)" % str(user_sid)
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["141"] % str(user_sid), res)
+
+ def test_142(self):
+ user_name = "testuser5"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_143(self):
+ user_name = "testuser6"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_144(self):
+ user_name = "testuser7"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_145(self):
+ user_name = "testuser8"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Change Schema partition descriptor
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(self.schema_dn, mod)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ # Create example Schema class
+ class_name = self.get_unique_schema_class_name()
+ class_dn = "CN=%s,%s" % (class_name, self.schema_dn)
+ self.create_schema_class(_ldb, class_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(class_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ ## Tests for CONFIGURATION
+
+ # Defalt descriptor tests ##################################################################
+
+ def test_160(self):
+ user_name = "testuser1"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(_ldb, object_dn, )
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["160"], res)
+
+ def test_161(self):
+ user_name = "testuser2"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(_ldb, object_dn, )
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["161"], res)
+
+ def test_162(self):
+ user_name = "testuser3"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ object_dn = "CN=test-container1,CN=DisplaySpecifiers," + self.configuration_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(self.ldb_admin, object_dn, )
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(object_dn, mod)
+ # Create child object with user's credentials
+ object_dn = "CN=test-specifier1," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_specifier(_ldb, object_dn)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["162"] % str(user_sid), res)
+
+ def test_163(self):
+ user_name = "testuser4"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), [])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ object_dn = "CN=test-container1,CN=DisplaySpecifiers," + self.configuration_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(self.ldb_admin, object_dn, )
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(object_dn, mod)
+ # Create child object with user's credentials
+ object_dn = "CN=test-specifier1," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_specifier(_ldb, object_dn)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["163"] % str(user_sid), res)
+
+ def test_164(self):
+ user_name = "testuser5"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(_ldb, object_dn, )
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["164"], res)
+
+ def test_165(self):
+ user_name = "testuser6"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(_ldb, object_dn, )
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["165"], res)
+
+ def test_166(self):
+ user_name = "testuser7"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(_ldb, object_dn, )
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["166"], res)
+
+ def test_167(self):
+ user_name = "testuser8"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(_ldb, object_dn, )
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["167"], res)
+
+ # Custom descriptor tests ##################################################################
+
+ def test_168(self):
+ user_name = "testuser1"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_configuration_container(_ldb, object_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_169(self):
+ user_name = "testuser2"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_configuration_container(_ldb, object_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_170(self):
+ user_name = "testuser3"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ object_dn = "CN=test-container1,CN=DisplaySpecifiers," + self.configuration_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(self.ldb_admin, object_dn, )
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(object_dn, mod)
+ # Create child object with user's credentials
+ object_dn = "CN=test-specifier1," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ # Create a custom security descriptor
+ # NB! Problematic owner part won't accept DA only <User Sid> !!!
+ desc_sddl = "O:%sG:DAD:(A;;RP;;;DU)" % str(user_sid)
+ self.create_configuration_specifier(_ldb, object_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["170"] % str(user_sid), res)
+
+ def test_171(self):
+ user_name = "testuser4"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), [])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ object_dn = "CN=test-container1,CN=DisplaySpecifiers," + self.configuration_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ self.create_configuration_container(self.ldb_admin, object_dn, )
+ user_sid = self.get_object_sid( self.get_users_domain_dn(user_name) )
+ mod = "(A;;CC;;;AU)"
+ self.dacl_add_ace(object_dn, mod)
+ # Create child object with user's credentials
+ object_dn = "CN=test-specifier1," + object_dn
+ self.delete_force(self.ldb_admin, object_dn)
+ # Create a custom security descriptor
+ # NB! Problematic owner part won't accept DA only <User Sid> !!!
+ desc_sddl = "O:%sG:DAD:(A;;RP;;;DU)" % str(user_sid)
+ self.create_configuration_specifier(_ldb, object_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual(self.results[self.DS_BEHAVIOR]["171"] % str(user_sid), res)
+
+ def test_172(self):
+ user_name = "testuser5"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_configuration_container(_ldb, object_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_173(self):
+ user_name = "testuser6"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_configuration_container(_ldb, object_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_174(self):
+ user_name = "testuser7"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Domain Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_configuration_container(_ldb, object_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ def test_175(self):
+ user_name = "testuser8"
+ self.check_user_belongs(self.get_users_domain_dn(user_name), ["Enterprise Admins", "Schema Admins"])
+ # Open Ldb connection with the tested user
+ _ldb = self.get_ldb_connection(user_name, "samba123@")
+ # Create example Configuration container
+ container_name = "test-container1"
+ object_dn = "CN=%s,CN=DisplaySpecifiers,%s" % (container_name, self.configuration_dn)
+ self.delete_force(self.ldb_admin, object_dn)
+ # Create a custom security descriptor
+ desc_sddl = "O:DAG:DAD:(A;;RP;;;DU)"
+ self.create_configuration_container(_ldb, object_dn, desc_sddl)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ res = re.search("(O:.*G:.*?)D:", desc_sddl).group(1)
+ self.assertEqual("O:DAG:DA", res)
+
+ ########################################################################################
+ # Inharitance tests for DACL
+
+class DaclDescriptorTests(DescriptorTests):
+
+ def setUp(self):
+ DescriptorTests.setUp(self)
+
+ def tearDown(self):
+ self.delete_force(self.ldb_admin, "CN=test_inherit_group,OU=test_inherit_ou," + self.base_dn)
+ self.delete_force(self.ldb_admin, "OU=test_inherit_ou," + self.base_dn)
+
+ def create_clean_ou(self, object_dn):
+ """ Base repeating setup for unittests to follow """
+ res = self.ldb_admin.search(base=self.base_dn, scope=SCOPE_SUBTREE, \
+ expression="distinguishedName=%s" % object_dn)
+ # Make sure top testing OU has been deleted before starting the test
+ self.assertEqual(res, [])
+ self.create_domain_ou(self.ldb_admin, object_dn)
+ desc_sddl = self.get_desc_sddl(object_dn)
+ # Make sutre there are inheritable ACEs initially
+ self.assertTrue("CI" in desc_sddl or "OI" in desc_sddl)
+ # Find and remove all inherit ACEs
+ res = re.findall("\(.*?\)", desc_sddl)
+ res = [x for x in res if ("CI" in x) or ("OI" in x)]
+ for x in res:
+ desc_sddl = desc_sddl.replace(x, "")
+ # Add flag 'protected' in both DACL and SACL so no inherit ACEs
+ # can propagate from above
+ desc_sddl = desc_sddl.replace(":AI", ":AIP")
+ # colon at the end breaks ldif parsing, fix it
+ res = re.findall(".*?S:", desc_sddl)
+ if res:
+ desc_sddl = desc_sddl.replace("S:", "")
+ self.modify_desc(object_dn, desc_sddl)
+ # Verify all inheritable ACEs are gone
+ desc_sddl = self.get_desc_sddl(object_dn)
+ self.assertFalse("CI" in desc_sddl)
+ self.assertFalse("OI" in desc_sddl)
+
+ def test_200(self):
+ """ OU with protected flag and child group. See if the group has inherit ACEs.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn)
+ # Make sure created group object contains NO inherit ACEs
+ desc_sddl = self.get_desc_sddl(group_dn)
+ self.assertFalse("ID" in desc_sddl)
+
+ def test_201(self):
+ """ OU with protected flag and no inherit ACEs, child group with custom descriptor.
+ Verify group has custom and default ACEs only.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Create group child object using custom security descriptor
+ sddl = "O:AUG:AUD:AI(D;;WP;;;DU)"
+ self.create_domain_group(self.ldb_admin, group_dn, sddl)
+ # Make sure created group descriptor has NO additional ACEs
+ desc_sddl = self.get_desc_sddl(group_dn)
+ print "group descriptor: " + desc_sddl
+ self.assertEqual(desc_sddl, sddl)
+
+ def test_202(self):
+ """ OU with protected flag and add couple non-inheritable ACEs, child group.
+ See if the group has any of the added ACEs.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Add some custom non-inheritable ACEs
+ mod = "(D;;WP;;;DU)(A;;RP;;;DU)"
+ self.dacl_add_ace(ou_dn, mod)
+ # Verify all inheritable ACEs are gone
+ desc_sddl = self.get_desc_sddl(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn)
+ # Make sure created group object contains NO inherit ACEs
+ # also make sure the added above non-inheritable ACEs are absant too
+ desc_sddl = self.get_desc_sddl(group_dn)
+ self.assertFalse("ID" in desc_sddl)
+ for x in re.findall("\(.*?\)", mod):
+ self.assertFalse(x in desc_sddl)
+
+ def test_203(self):
+ """ OU with protected flag and add 'CI' ACE, child group.
+ See if the group has the added inherited ACE.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Add some custom 'CI' ACE
+ mod = "(D;CI;WP;;;DU)"
+ self.dacl_add_ace(ou_dn, mod)
+ desc_sddl = self.get_desc_sddl(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn, "O:AUG:AUD:AI(A;;CC;;;AU)")
+ # Make sure created group object contains only the above inherited ACE
+ # that we've added manually
+ desc_sddl = self.get_desc_sddl(group_dn)
+ mod = mod.replace(";CI;", ";CIID;")
+ self.assertTrue(mod in desc_sddl)
+
+ def test_204(self):
+ """ OU with protected flag and add 'OI' ACE, child group.
+ See if the group has the added inherited ACE.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Add some custom 'CI' ACE
+ mod = "(D;OI;WP;;;DU)"
+ self.dacl_add_ace(ou_dn, mod)
+ desc_sddl = self.get_desc_sddl(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn, "O:AUG:AUD:AI(A;;CC;;;AU)")
+ # Make sure created group object contains only the above inherited ACE
+ # that we've added manually
+ desc_sddl = self.get_desc_sddl(group_dn)
+ mod = mod.replace(";OI;", ";OIIOID;") # change it how it's gonna look like
+ self.assertTrue(mod in desc_sddl)
+
+ def test_205(self):
+ """ OU with protected flag and add 'OA' for GUID & 'CI' ACE, child group.
+ See if the group has the added inherited ACE.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Add some custom 'OA' for 'name' attribute & 'CI' ACE
+ mod = "(OA;CI;WP;bf967a0e-0de6-11d0-a285-00aa003049e2;;DU)"
+ self.dacl_add_ace(ou_dn, mod)
+ desc_sddl = self.get_desc_sddl(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn, "O:AUG:AUD:AI(A;;CC;;;AU)")
+ # Make sure created group object contains only the above inherited ACE
+ # that we've added manually
+ desc_sddl = self.get_desc_sddl(group_dn)
+ mod = mod.replace(";CI;", ";CIID;") # change it how it's gonna look like
+ self.assertTrue(mod in desc_sddl)
+
+ def test_206(self):
+ """ OU with protected flag and add 'OA' for GUID & 'OI' ACE, child group.
+ See if the group has the added inherited ACE.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Add some custom 'OA' for 'name' attribute & 'OI' ACE
+ mod = "(OA;OI;WP;bf967a0e-0de6-11d0-a285-00aa003049e2;;DU)"
+ self.dacl_add_ace(ou_dn, mod)
+ desc_sddl = self.get_desc_sddl(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn, "O:AUG:AUD:AI(A;;CC;;;AU)")
+ # Make sure created group object contains only the above inherited ACE
+ # that we've added manually
+ desc_sddl = self.get_desc_sddl(group_dn)
+ mod = mod.replace(";OI;", ";OIIOID;") # change it how it's gonna look like
+ self.assertTrue(mod in desc_sddl)
+
+ def test_207(self):
+ """ OU with protected flag and add 'OA' for OU specific GUID & 'CI' ACE, child group.
+ See if the group has the added inherited ACE.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Add some custom 'OA' for 'st' attribute (OU specific) & 'CI' ACE
+ mod = "(OA;CI;WP;bf967a39-0de6-11d0-a285-00aa003049e2;;DU)"
+ self.dacl_add_ace(ou_dn, mod)
+ desc_sddl = self.get_desc_sddl(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn, "O:AUG:AUD:AI(A;;CC;;;AU)")
+ # Make sure created group object contains only the above inherited ACE
+ # that we've added manually
+ desc_sddl = self.get_desc_sddl(group_dn)
+ mod = mod.replace(";CI;", ";CIID;") # change it how it's gonna look like
+ self.assertTrue(mod in desc_sddl)
+
+ def test_208(self):
+ """ OU with protected flag and add 'OA' for OU specific GUID & 'OI' ACE, child group.
+ See if the group has the added inherited ACE.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Add some custom 'OA' for 'st' attribute (OU specific) & 'OI' ACE
+ mod = "(OA;OI;WP;bf967a39-0de6-11d0-a285-00aa003049e2;;DU)"
+ self.dacl_add_ace(ou_dn, mod)
+ desc_sddl = self.get_desc_sddl(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn, "O:AUG:AUD:AI(A;;CC;;;AU)")
+ # Make sure created group object contains only the above inherited ACE
+ # that we've added manually
+ desc_sddl = self.get_desc_sddl(group_dn)
+ mod = mod.replace(";OI;", ";OIIOID;") # change it how it's gonna look like
+ self.assertTrue(mod in desc_sddl)
+
+ def test_209(self):
+ """ OU with protected flag and add 'CI' ACE with 'CO' SID, child group.
+ See if the group has the added inherited ACE.
+ """
+ ou_dn = "OU=test_inherit_ou," + self.base_dn
+ group_dn = "CN=test_inherit_group," + ou_dn
+ # Create inheritable-free OU
+ self.create_clean_ou(ou_dn)
+ # Add some custom 'CI' ACE
+ mod = "(D;CI;WP;;;CO)"
+ self.dacl_add_ace(ou_dn, mod)
+ desc_sddl = self.get_desc_sddl(ou_dn)
+ # Create group child object
+ self.create_domain_group(self.ldb_admin, group_dn, "O:AUG:AUD:AI(A;;CC;;;AU)")
+ # Make sure created group object contains only the above inherited ACE(s)
+ # that we've added manually
+ desc_sddl = self.get_desc_sddl(group_dn)
+ self.assertTrue("(D;ID;WP;;;AU)" in desc_sddl)
+ self.assertTrue("(D;CIIOID;WP;;;CO)" in desc_sddl)
+
+ ########################################################################################
+
+if not "://" in host:
+ host = "ldap://%s" % host
+ldb = Ldb(host, credentials=creds, session_info=system_session(), lp=lp, options=["modules:paged_searches"])
+
+runner = SubunitTestRunner()
+rc = 0
+if not runner.run(unittest.makeSuite(OwnerGroupDescriptorTests)).wasSuccessful():
+ rc = 1
+if not runner.run(unittest.makeSuite(DaclDescriptorTests)).wasSuccessful():
+ rc = 1
+
+sys.exit(rc)
diff --git a/source4/lib/ldb/tools/cmdline.c b/source4/lib/ldb/tools/cmdline.c
index 2701de5a48..73bf2a93a7 100644
--- a/source4/lib/ldb/tools/cmdline.c
+++ b/source4/lib/ldb/tools/cmdline.c
@@ -35,7 +35,45 @@
#include "param/param.h"
#endif
+static struct ldb_cmdline options; /* needs to be static for older compilers */
+
+static struct poptOption popt_options[] = {
+ POPT_AUTOHELP
+ { "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" },
+ { "basedn", 'b', POPT_ARG_STRING, &options.basedn, 0, "base DN", "DN" },
+ { "editor", 'e', POPT_ARG_STRING, &options.editor, 0, "external editor", "PROGRAM" },
+ { "scope", 's', POPT_ARG_STRING, NULL, 's', "search scope", "SCOPE" },
+ { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "increase verbosity", NULL },
+ { "trace", 0, POPT_ARG_NONE, &options.tracing, 0, "enable tracing", NULL },
+ { "interactive", 'i', POPT_ARG_NONE, &options.interactive, 0, "input from stdin", NULL },
+ { "recursive", 'r', POPT_ARG_NONE, &options.recursive, 0, "recursive delete", NULL },
+ { "modules-path", 0, POPT_ARG_STRING, &options.modules_path, 0, "modules path", "PATH" },
+ { "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL },
+ { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL },
+ { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "(|(objectClass=*)(distinguishedName=*))", NULL },
+ { "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL },
+ { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL },
+ { "input", 'I', POPT_ARG_STRING, &options.input, 0, "Input File", "Input" },
+ { "output", 'O', POPT_ARG_STRING, &options.output, 0, "Output File", "Output" },
+ { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" },
+ { "controls", 0, POPT_ARG_STRING, NULL, 'c', "controls", NULL },
+ { "show-binary", 0, POPT_ARG_NONE, &options.show_binary, 0, "display binary LDIF", NULL },
+#if (_SAMBA_BUILD_ >= 4)
+ POPT_COMMON_SAMBA
+ POPT_COMMON_CREDENTIALS
+ POPT_COMMON_CONNECTION
+ POPT_COMMON_VERSION
+#endif
+ { NULL }
+};
+void ldb_cmdline_help(const char *cmdname, FILE *f)
+{
+ poptContext pc;
+ pc = poptGetContext(cmdname, 0, NULL, popt_options,
+ POPT_CONTEXT_KEEP_FIRST);
+ poptPrintHelp(pc, f, 0);
+}
/**
process command line options
@@ -44,7 +82,6 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb,
int argc, const char **argv,
void (*usage)(void))
{
- static struct ldb_cmdline options; /* needs to be static for older compilers */
struct ldb_cmdline *ret=NULL;
poptContext pc;
#if (_SAMBA_BUILD_ >= 4)
@@ -54,34 +91,6 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb,
int opt;
int flags = 0;
- struct poptOption popt_options[] = {
- POPT_AUTOHELP
- { "url", 'H', POPT_ARG_STRING, &options.url, 0, "database URL", "URL" },
- { "basedn", 'b', POPT_ARG_STRING, &options.basedn, 0, "base DN", "DN" },
- { "editor", 'e', POPT_ARG_STRING, &options.editor, 0, "external editor", "PROGRAM" },
- { "scope", 's', POPT_ARG_STRING, NULL, 's', "search scope", "SCOPE" },
- { "verbose", 'v', POPT_ARG_NONE, NULL, 'v', "increase verbosity", NULL },
- { "interactive", 'i', POPT_ARG_NONE, &options.interactive, 0, "input from stdin", NULL },
- { "recursive", 'r', POPT_ARG_NONE, &options.recursive, 0, "recursive delete", NULL },
- { "modules-path", 0, POPT_ARG_STRING, &options.modules_path, 0, "modules path", "PATH" },
- { "num-searches", 0, POPT_ARG_INT, &options.num_searches, 0, "number of test searches", NULL },
- { "num-records", 0, POPT_ARG_INT, &options.num_records, 0, "number of test records", NULL },
- { "all", 'a', POPT_ARG_NONE, &options.all_records, 0, "(|(objectClass=*)(distinguishedName=*))", NULL },
- { "nosync", 0, POPT_ARG_NONE, &options.nosync, 0, "non-synchronous transactions", NULL },
- { "sorted", 'S', POPT_ARG_NONE, &options.sorted, 0, "sort attributes", NULL },
- { "input", 'I', POPT_ARG_STRING, &options.input, 0, "Input File", "Input" },
- { "output", 'O', POPT_ARG_STRING, &options.output, 0, "Output File", "Output" },
- { NULL, 'o', POPT_ARG_STRING, NULL, 'o', "ldb_connect option", "OPTION" },
- { "controls", 0, POPT_ARG_STRING, NULL, 'c', "controls", NULL },
-#if (_SAMBA_BUILD_ >= 4)
- POPT_COMMON_SAMBA
- POPT_COMMON_CREDENTIALS
- POPT_COMMON_CONNECTION
- POPT_COMMON_VERSION
-#endif
- { NULL }
- };
-
#if (_SAMBA_BUILD_ >= 4)
r = ldb_register_samba_handlers(ldb);
if (r != 0) {
@@ -208,6 +217,14 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb,
flags |= LDB_FLG_NOSYNC;
}
+ if (options.show_binary) {
+ flags |= LDB_FLG_SHOW_BINARY;
+ }
+
+ if (options.tracing) {
+ flags |= LDB_FLG_ENABLE_TRACING;
+ }
+
#if (_SAMBA_BUILD_ >= 4)
/* Must be after we have processed command line options */
gensec_init(cmdline_lp_ctx);
diff --git a/source4/lib/ldb/tools/cmdline.h b/source4/lib/ldb/tools/cmdline.h
index 45619ce496..28061a5a7d 100644
--- a/source4/lib/ldb/tools/cmdline.h
+++ b/source4/lib/ldb/tools/cmdline.h
@@ -44,6 +44,8 @@ struct ldb_cmdline {
const char *input;
const char *output;
char **controls;
+ int show_binary;
+ int tracing;
};
struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const char **argv,
@@ -51,3 +53,5 @@ struct ldb_cmdline *ldb_cmdline_process(struct ldb_context *ldb, int argc, const
int handle_controls_reply(struct ldb_control **reply, struct ldb_control **request);
+void ldb_cmdline_help(const char *cmdname, FILE *f);
+
diff --git a/source4/lib/ldb/tools/ldbadd.c b/source4/lib/ldb/tools/ldbadd.c
index be02334797..f022486db8 100644
--- a/source4/lib/ldb/tools/ldbadd.c
+++ b/source4/lib/ldb/tools/ldbadd.c
@@ -38,13 +38,9 @@ static int failures;
static void usage(void)
{
- printf("Usage: ldbadd <options> <ldif...>\n");
- printf("Options:\n");
- printf(" -H ldb_url choose the database (or $LDB_URL)\n");
- printf(" -o options pass options like modules to activate\n");
- printf(" e.g: -o modules:timestamps\n");
- printf("\n");
+ printf("Usage: ldbadd <options> <ldif...>\n");
printf("Adds records to a ldb, reading ldif the specified list of files\n\n");
+ ldb_cmdline_help("ldbadd", stdout);
exit(1);
}
@@ -113,9 +109,13 @@ int main(int argc, const char **argv)
}
}
- if (count != 0 && ldb_transaction_commit(ldb) != 0) {
- printf("Failed to commit transaction: %s\n", ldb_errstring(ldb));
- exit(1);
+ if (count != 0) {
+ if (ldb_transaction_commit(ldb) != 0) {
+ printf("Failed to commit transaction: %s\n", ldb_errstring(ldb));
+ exit(1);
+ }
+ } else {
+ ldb_transaction_cancel(ldb);
}
talloc_free(ldb);
diff --git a/source4/lib/ldb/tools/ldbdel.c b/source4/lib/ldb/tools/ldbdel.c
index 232f51681a..ddf168d574 100644
--- a/source4/lib/ldb/tools/ldbdel.c
+++ b/source4/lib/ldb/tools/ldbdel.c
@@ -61,13 +61,8 @@ static int ldb_delete_recursive(struct ldb_context *ldb, struct ldb_dn *dn)
static void usage(void)
{
printf("Usage: ldbdel <options> <DN...>\n");
- printf("Options:\n");
- printf(" -r recursively delete the given subtree\n");
- printf(" -H ldb_url choose the database (or $LDB_URL)\n");
- printf(" -o options pass options like modules to activate\n");
- printf(" e.g: -o modules:timestamps\n");
- printf("\n");
printf("Deletes records from a ldb\n\n");
+ ldb_cmdline_help("ldbdel", stdout);
exit(1);
}
diff --git a/source4/lib/ldb/tools/ldbedit.c b/source4/lib/ldb/tools/ldbedit.c
index 9d3bd27983..ecadf0f61c 100644
--- a/source4/lib/ldb/tools/ldbedit.c
+++ b/source4/lib/ldb/tools/ldbedit.c
@@ -128,6 +128,7 @@ static int merge_edits(struct ldb_context *ldb,
fprintf(stderr, "failed to add %s - %s\n",
ldb_dn_get_linearized(msgs2[i]->dn),
ldb_errstring(ldb));
+ ldb_transaction_cancel(ldb);
return -1;
}
adds++;
@@ -149,6 +150,7 @@ static int merge_edits(struct ldb_context *ldb,
fprintf(stderr, "failed to delete %s - %s\n",
ldb_dn_get_linearized(msgs1[i]->dn),
ldb_errstring(ldb));
+ ldb_transaction_cancel(ldb);
return -1;
}
deletes++;
@@ -270,13 +272,7 @@ static int do_edit(struct ldb_context *ldb, struct ldb_message **msgs1, int coun
static void usage(void)
{
printf("Usage: ldbedit <options> <expression> <attributes ...>\n");
- printf("Options:\n");
- printf(" -H ldb_url choose the database (or $LDB_URL)\n");
- printf(" -s base|sub|one choose search scope\n");
- printf(" -b basedn choose baseDN\n");
- printf(" -a edit all records (expression 'objectclass=*')\n");
- printf(" -e editor choose editor (or $VISUAL or $EDITOR)\n");
- printf(" -v verbose mode\n");
+ ldb_cmdline_help("ldbedit", stdout);
exit(1);
}
diff --git a/source4/lib/ldb/tools/ldbmodify.c b/source4/lib/ldb/tools/ldbmodify.c
index c3f55c6096..d0bca0479b 100644
--- a/source4/lib/ldb/tools/ldbmodify.c
+++ b/source4/lib/ldb/tools/ldbmodify.c
@@ -39,12 +39,8 @@ static int failures;
static void usage(void)
{
printf("Usage: ldbmodify <options> <ldif...>\n");
- printf("Options:\n");
- printf(" -H ldb_url choose the database (or $LDB_URL)\n");
- printf(" -o options pass options like modules to activate\n");
- printf(" e.g: -o modules:timestamps\n");
- printf("\n");
printf("Modifies a ldb based upon ldif change records\n\n");
+ ldb_cmdline_help("ldbmodify", stdout);
exit(1);
}
@@ -105,6 +101,7 @@ int main(int argc, const char **argv)
exit(1);
}
ret = process_file(ldb, f, &count);
+ fclose(f);
}
}
diff --git a/source4/lib/ldb/tools/ldbrename.c b/source4/lib/ldb/tools/ldbrename.c
index 01ed3d9835..fcae766a20 100644
--- a/source4/lib/ldb/tools/ldbrename.c
+++ b/source4/lib/ldb/tools/ldbrename.c
@@ -39,12 +39,8 @@
static void usage(void)
{
printf("Usage: ldbrename [<options>] <olddn> <newdn>\n");
- printf("Options:\n");
- printf(" -H ldb_url choose the database (or $LDB_URL)\n");
- printf(" -o options pass options like modules to activate\n");
- printf(" e.g: -o modules:timestamps\n");
- printf("\n");
printf("Renames records in a ldb\n\n");
+ ldb_cmdline_help("ldbmodify", stdout);
exit(1);
}
diff --git a/source4/lib/ldb/tools/ldbsearch.c b/source4/lib/ldb/tools/ldbsearch.c
index ba0a2a8927..8f7ee1ce38 100644
--- a/source4/lib/ldb/tools/ldbsearch.c
+++ b/source4/lib/ldb/tools/ldbsearch.c
@@ -38,14 +38,7 @@
static void usage(void)
{
printf("Usage: ldbsearch <options> <expression> <attrs...>\n");
- printf("Options:\n");
- printf(" -H ldb_url choose the database (or $LDB_URL)\n");
- printf(" -s base|sub|one choose search scope\n");
- printf(" -b basedn choose baseDN\n");
- printf(" -i read search expressions from stdin\n");
- printf(" -S sort returned attributes\n");
- printf(" -o options pass options like modules to activate\n");
- printf(" e.g: -o modules:timestamps\n");
+ ldb_cmdline_help("ldbsearch", stdout);
exit(1);
}