diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/extended_dn_out.c | 45 |
1 files changed, 44 insertions, 1 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c index 55dd6939e3..987a3b3cfb 100644 --- a/source4/dsdb/samdb/ldb_modules/extended_dn_out.c +++ b/source4/dsdb/samdb/ldb_modules/extended_dn_out.c @@ -322,6 +322,8 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares, struct ldb_message *msg = ares->message; struct extended_dn_out_private *p; struct ldb_context *ldb; + bool have_reveal_control, checked_reveal_control=false; + ac = talloc_get_type(req->context, struct extended_search_context); p = talloc_get_type(ldb_module_get_private(ac->module), struct extended_dn_out_private); ldb = ldb_module_get_ctx(ac->module); @@ -433,7 +435,7 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares, struct dsdb_dn *dsdb_dn = NULL; struct ldb_val *plain_dn = &msg->elements[i].values[j]; dsdb_dn = dsdb_dn_parse(msg, ldb, plain_dn, attribute->syntax->ldap_oid); - + if (!dsdb_dn || !ldb_dn_validate(dsdb_dn->dn)) { ldb_asprintf_errstring(ldb, "could not parse %.*s in %s on %s as a %s DN", @@ -445,6 +447,38 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares, } dn = dsdb_dn->dn; + if (!checked_reveal_control) { + have_reveal_control = + ldb_request_get_control(req, LDB_CONTROL_REVEAL_INTERNALS) != NULL; + checked_reveal_control = true; + } + + /* this is a fast method for detecting deleted + linked attributes. It relies on the + linearization of extended DNs sorting by name, + and "DELETED" being the first name */ + if (plain_dn->length >= 12 && + strncmp((const char *)plain_dn->data, "<DELETED=1>;", 12) == 0) { + if (!have_reveal_control) { + /* it's a deleted linked + * attribute, and we don't + * have the reveal control */ + memmove(&msg->elements[i].values[j], + &msg->elements[i].values[j+1], + (msg->elements[i].num_values-(j+1))*sizeof(struct ldb_val)); + msg->elements[i].num_values--; + j--; + continue; + } + } + + /* don't let users see the internal extended + GUID components */ + if (!have_reveal_control) { + const char *accept[] = { "GUID", "SID", "WKGUID", NULL }; + ldb_dn_extended_filter(dn, accept); + } + if (p->normalise) { ret = fix_dn(dn); if (ret != LDB_SUCCESS) { @@ -488,6 +522,15 @@ static int extended_callback(struct ldb_request *req, struct ldb_reply *ares, msg->elements[i].values[j] = data_blob_string_const(dn_str); talloc_free(dsdb_dn); } + if (msg->elements[i].num_values == 0) { + /* we've deleted all of the values from this + * element - remove the element */ + memmove(&msg->elements[i], + &msg->elements[i+1], + (msg->num_elements-(i+1))*sizeof(struct ldb_message_element)); + msg->num_elements--; + i--; + } } return ldb_module_send_entry(ac->req, msg, ares->controls); } |