summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/dsdb/samdb/ldb_modules/extended_dn_out.c131
1 files changed, 77 insertions, 54 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
index 3126dd2d79..7d1826ea6e 100644
--- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
+++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c
@@ -46,8 +46,58 @@ struct extended_dn_out_private {
bool dereference;
bool normalise;
struct dsdb_openldap_dereference_control *dereference_control;
+ const char **attrs;
};
+/* Do the lazy init of the derererence control */
+
+static int extended_dn_out_dereference_setup_control(struct ldb_context *ldb, struct extended_dn_out_private *p)
+{
+ const struct dsdb_schema *schema;
+ struct dsdb_openldap_dereference_control *dereference_control;
+ struct dsdb_attribute *cur;
+
+ unsigned int i = 0;
+ if (p->dereference_control) {
+ return LDB_SUCCESS;
+ }
+
+ schema = dsdb_get_schema(ldb, p);
+ if (!schema) {
+ /* No schema on this DB (yet) */
+ return LDB_SUCCESS;
+ }
+
+ p->dereference_control = dereference_control
+ = talloc_zero(p, struct dsdb_openldap_dereference_control);
+
+ if (!p->dereference_control) {
+ return ldb_oom(ldb);
+ }
+
+ for (cur = schema->attributes; cur; cur = cur->next) {
+ if (dsdb_dn_oid_to_format(cur->syntax->ldap_oid) != DSDB_NORMAL_DN) {
+ continue;
+ }
+ dereference_control->dereference
+ = talloc_realloc(p, dereference_control->dereference,
+ struct dsdb_openldap_dereference *, i + 2);
+ if (!dereference_control) {
+ return ldb_oom(ldb);
+ }
+ dereference_control->dereference[i] = talloc(dereference_control->dereference,
+ struct dsdb_openldap_dereference);
+ if (!dereference_control->dereference[i]) {
+ return ldb_oom(ldb);
+ }
+ dereference_control->dereference[i]->source_attribute = cur->lDAPDisplayName;
+ dereference_control->dereference[i]->dereference_attribute = p->attrs;
+ i++;
+ dereference_control->dereference[i] = NULL;
+ }
+ return LDB_SUCCESS;
+}
+
static char **copy_attrs(void *mem_ctx, const char * const * attrs)
{
char **nattrs;
@@ -661,13 +711,29 @@ static int extended_dn_out_search(struct ldb_module *module, struct ldb_request
/* Add in dereference control, if we were asked to, we are
* using the 'dereference' mode (such as with an OpenLDAP
* backend) and have the control prepared */
- if (control && p && p->dereference && p->dereference_control) {
- ret = ldb_request_add_control(down_req,
- DSDB_OPENLDAP_DEREFERENCE_CONTROL,
- critical, p->dereference_control);
+ if (control && p && p->dereference) {
+ ret = extended_dn_out_dereference_setup_control(ldb, p);
if (ret != LDB_SUCCESS) {
return ret;
}
+
+ /* We should always have this, but before the schema
+ * is with us, things get tricky */
+ if (p->dereference_control) {
+
+ /* This control must *not* be critical,
+ * because if this particular request did not
+ * return any dereferencable attributes in the
+ * end, then OpenLDAP will reply with
+ * unavailableCriticalExtension, rather than
+ * just an empty return control */
+ ret = ldb_request_add_control(down_req,
+ DSDB_OPENLDAP_DEREFERENCE_CONTROL,
+ false, p->dereference_control);
+ if (ret != LDB_SUCCESS) {
+ return ret;
+ }
+ }
}
/* perform the search */
@@ -731,24 +797,19 @@ static int extended_dn_out_ldb_init(struct ldb_module *module)
static int extended_dn_out_dereference_init(struct ldb_module *module, const char *attrs[])
{
int ret;
- unsigned int i = 0;
struct extended_dn_out_private *p = talloc_zero(module, struct extended_dn_out_private);
struct dsdb_extended_dn_store_format *dn_format;
- struct dsdb_openldap_dereference_control *dereference_control;
- struct dsdb_attribute *cur;
- struct ldb_context *ldb = ldb_module_get_ctx(module);
- const struct dsdb_schema *schema;
ldb_module_set_private(module, p);
if (!p) {
- return ldb_oom(ldb);
+ return ldb_module_oom(module);
}
dn_format = talloc(p, struct dsdb_extended_dn_store_format);
if (!dn_format) {
talloc_free(p);
- return ldb_oom(ldb_module_get_ctx(module));
+ return ldb_module_oom(module);
}
dn_format->store_extended_dn_in_ldb = false;
@@ -761,57 +822,19 @@ static int extended_dn_out_dereference_init(struct ldb_module *module, const cha
p->dereference = true;
+ p->attrs = attrs;
/* At the moment, servers that need dereference also need the
* DN and attribute names to be normalised */
p->normalise = true;
ret = ldb_mod_register_control(module, LDB_CONTROL_EXTENDED_DN_OID);
if (ret != LDB_SUCCESS) {
- ldb_debug(ldb, LDB_DEBUG_ERROR,
- "extended_dn_out: Unable to register control with rootdse!\n");
- return ldb_operr(ldb);
- }
-
- ret = ldb_next_init(module);
-
- if (ret != LDB_SUCCESS) {
- return ret;
- }
-
- schema = dsdb_get_schema(ldb, p);
- if (!schema) {
- /* No schema on this DB (yet) */
- return LDB_SUCCESS;
+ ldb_debug(ldb_module_get_ctx(module), LDB_DEBUG_ERROR,
+ "extended_dn_out: Unable to register control with rootdse!\n");
+ return ldb_operr(ldb_module_get_ctx(module));
}
- p->dereference_control = dereference_control
- = talloc_zero(p, struct dsdb_openldap_dereference_control);
-
- if (!p->dereference_control) {
- return ldb_oom(ldb);
- }
-
- for (cur = schema->attributes; cur; cur = cur->next) {
- if (dsdb_dn_oid_to_format(cur->syntax->ldap_oid) == DSDB_INVALID_DN) {
- continue;
- }
- dereference_control->dereference
- = talloc_realloc(p, dereference_control->dereference,
- struct dsdb_openldap_dereference *, i + 2);
- if (!dereference_control) {
- return ldb_oom(ldb);
- }
- dereference_control->dereference[i] = talloc(dereference_control->dereference,
- struct dsdb_openldap_dereference);
- if (!dereference_control->dereference[i]) {
- return ldb_oom(ldb);
- }
- dereference_control->dereference[i]->source_attribute = cur->lDAPDisplayName;
- dereference_control->dereference[i]->dereference_attribute = attrs;
- i++;
- dereference_control->dereference[i] = NULL;
- }
- return LDB_SUCCESS;
+ return ldb_next_init(module);
}
static int extended_dn_out_openldap_init(struct ldb_module *module)