/*
ldb database library
Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007
Copyright (C) Simo Sorce <idra@samba.org> 2008
Copyright (C) Matthieu Patou <mat@matws.net> 2011
Copyright (C) Andrew Tridgell 2009
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Name: ldb
*
* Component: ldb linked_attributes module
*
* Description: Module to ensure linked attribute pairs (i.e. forward-links
* and backlinks) remain in sync.
*
* Backlinks are 'plain' links (without extra metadata). When the link target
* object is modified (e.g. renamed), we use the backlinks to keep the link
* source object updated. Note there are some cases where we can't do this:
* - one-way links, which don't have a corresponding backlink
* - two-way deactivated links, i.e. when a user is removed from a group,
* the forward 'member' link still exists (but is inactive), however, the
* 'memberOf' backlink is deleted.
* In these cases, we can end up with a dangling forward link which is
* incorrect (i.e. the target has been renamed or deleted). We have dbcheck
* rules to detect and fix this, and cope otherwise by filtering at runtime
* (i.e. in the extended_dn module).
*
* See also repl_meta_data.c, which handles updating links for deleted
* objects, as well as link changes received from another DC.
*
* Author: Andrew Bartlett
*/
#include "includes.h"
#include "ldb_module.h"
#include "util/dlinklist.h"
#include "dsdb/samdb/samdb.h"
#include "librpc/gen_ndr/ndr_misc.h"
#include "dsdb/samdb/ldb_modules/util.h"
#undef strcasecmp
struct la_private_transaction {
struct la_context *la_list;
};
struct la_private {
struct la_private_transaction *transaction;
bool sorted_links;
};
struct la_op_store {
struct la_op_store *next;
struct la_op_store *prev;
enum la_op {LA_OP_ADD, LA_OP_DEL} op;
struct GUID guid;
char *name;
};
struct replace_context {
struct la_context *ac;
unsigned int num_elements;
struct ldb_message_element *el;
};
struct la_context {
struct la_context *next, *prev;
const struct dsdb_schema *schema;
struct ldb_module *module;
struct ldb_request *req;
struct ldb_dn *mod_dn;
struct replace_context *rc;
struct la_op_store *ops;
struct ldb_extended *op_response;
struct ldb_control **op_controls;
/*
* For futur use
* will tell which GC to use for resolving links
*/
char *gc_dns_name;
};
static int handle_verify_name_control(TALLOC_CTX *ctx, struct ldb_context *ldb,
struct ldb_control *control, struct la_context *ac)
{
/*
* If we are a GC let's remove the control,
* if there is a specified GC check that is us.
*/
struct ldb_verify_name_control *lvnc = talloc_get_type_abort(control->data, struct ldb_verify_name_control);
if (samdb_is_gc(ldb)) {
/* Because we can't easily talloc a struct ldb_dn*/
struct ldb_dn **dn = talloc_array(ctx, struct ldb_dn *, 1);
int ret = samdb_server_reference_dn(ldb, ctx, dn);
const char *dns;
if (ret != LDB_SUCCESS) {
return ldb_operr(ldb);
}
dns = samdb_dn_to_dnshostname(ldb, ctx, *dn);
if (!dns) {
return ldb_operr(ldb);
}
if (!lvnc->gc || strcasecmp(dns, lvnc->gc) == 0) {
if (!ldb_save_controls(control, ctx, NULL)) {
return ldb_operr(ldb);
}
} else {
control->critical = true;
}
talloc_free(dn);
} else {
/* For the moment we don't
|