s4:resolve_oids LDB module - not really a change but a nicer method to call "talloc_r...
[Samba/nascimento.git] / source4 / dsdb / samdb / ldb_modules / linked_attributes.c
blob56ed447771e1e3a58f5daf755b6d10869e535178
1 /*
2 ldb database library
4 Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007
5 Copyright (C) Simo Sorce <idra@samba.org> 2008
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 3 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program. If not, see <http://www.gnu.org/licenses/>.
22 * Name: ldb
24 * Component: ldb linked_attributes module
26 * Description: Module to ensure linked attribute pairs remain in sync
28 * Author: Andrew Bartlett
31 #include "includes.h"
32 #include "ldb_module.h"
33 #include "dlinklist.h"
34 #include "dsdb/samdb/samdb.h"
35 #include "librpc/gen_ndr/ndr_misc.h"
36 #include "dsdb/samdb/ldb_modules/util.h"
39 static int linked_attributes_fix_links(struct ldb_module *module,
40 struct ldb_dn *old_dn, struct ldb_dn *new_dn,
41 struct ldb_message_element *el, struct dsdb_schema *schema,
42 const struct dsdb_attribute *schema_attr)
44 unsigned int i;
45 TALLOC_CTX *tmp_ctx = talloc_new(module);
46 struct ldb_context *ldb = ldb_module_get_ctx(module);
47 const struct dsdb_attribute *target;
48 const char *attrs[2];
50 target = dsdb_attribute_by_linkID(schema, schema_attr->linkID ^ 1);
51 if (target == NULL) {
52 /* there is no counterpart link to change */
53 return LDB_SUCCESS;
56 attrs[0] = target->lDAPDisplayName;
57 attrs[1] = NULL;
59 for (i=0; i<el->num_values; i++) {
60 struct dsdb_dn *dsdb_dn;
61 unsigned int j;
62 int ret;
63 struct ldb_result *res;
64 struct ldb_message *msg;
65 struct ldb_message_element *el2;
67 dsdb_dn = dsdb_dn_parse(tmp_ctx, ldb, &el->values[i], schema_attr->syntax->ldap_oid);
68 if (dsdb_dn == NULL) {
69 talloc_free(tmp_ctx);
70 return LDB_ERR_INVALID_DN_SYNTAX;
73 ret = dsdb_module_search_dn(module, tmp_ctx, &res, dsdb_dn->dn,
74 attrs,
75 DSDB_SEARCH_SHOW_DELETED |
76 DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT |
77 DSDB_SEARCH_REVEAL_INTERNALS);
78 if (ret != LDB_SUCCESS) {
79 ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - remote not found - %s",
80 el->name, target->lDAPDisplayName,
81 ldb_dn_get_linearized(old_dn),
82 ldb_dn_get_linearized(dsdb_dn->dn),
83 ldb_errstring(ldb));
84 talloc_free(tmp_ctx);
85 return ret;
87 msg = res->msgs[0];
89 if (msg->num_elements != 1 ||
90 ldb_attr_cmp(msg->elements[0].name, target->lDAPDisplayName) != 0) {
91 ldb_set_errstring(ldb, "Bad msg elements in linked_attributes_fix_links");
92 talloc_free(tmp_ctx);
93 return LDB_ERR_OPERATIONS_ERROR;
95 el2 = &msg->elements[0];
97 el2->flags = LDB_FLAG_MOD_REPLACE;
99 /* find our DN in the values */
100 for (j=0; j<el2->num_values; j++) {
101 struct dsdb_dn *dsdb_dn2;
102 dsdb_dn2 = dsdb_dn_parse(msg, ldb, &el2->values[j], target->syntax->ldap_oid);
103 if (dsdb_dn2 == NULL) {
104 talloc_free(tmp_ctx);
105 return LDB_ERR_INVALID_DN_SYNTAX;
107 if (ldb_dn_compare(old_dn, dsdb_dn2->dn) != 0) {
108 continue;
110 ret = ldb_dn_update_components(dsdb_dn2->dn, new_dn);
111 if (ret != LDB_SUCCESS) {
112 talloc_free(tmp_ctx);
113 return ret;
116 el2->values[j] = data_blob_string_const(
117 dsdb_dn_get_extended_linearized(el2->values, dsdb_dn2, 1));
120 ret = dsdb_check_single_valued_link(target, el2);
121 if (ret != LDB_SUCCESS) {
122 talloc_free(tmp_ctx);
123 return ret;
126 ret = dsdb_module_modify(module, msg, DSDB_MODIFY_RELAX);
127 if (ret != LDB_SUCCESS) {
128 ldb_asprintf_errstring(ldb, "Linked attribute %s->%s between %s and %s - update failed - %s",
129 el->name, target->lDAPDisplayName,
130 ldb_dn_get_linearized(old_dn),
131 ldb_dn_get_linearized(dsdb_dn->dn),
132 ldb_errstring(ldb));
133 talloc_free(tmp_ctx);
134 return ret;
138 talloc_free(tmp_ctx);
139 return LDB_SUCCESS;
143 /* rename */
144 static int linked_attributes_rename(struct ldb_module *module, struct ldb_request *req)
146 struct ldb_result *res;
147 struct ldb_message *msg;
148 unsigned int i;
149 int ret;
150 struct ldb_context *ldb = ldb_module_get_ctx(module);
151 struct dsdb_schema *schema;
153 - load the current msg
154 - find any linked attributes
155 - if its a link then find the target object
156 - modify the target linked attributes with the new DN
158 ret = dsdb_module_search_dn(module, req, &res, req->op.rename.olddn,
159 NULL, DSDB_SEARCH_SHOW_DELETED);
160 if (ret != LDB_SUCCESS) {
161 return ret;
164 schema = dsdb_get_schema(ldb, res);
165 if (!schema) {
166 ldb_oom(ldb);
167 return LDB_ERR_OPERATIONS_ERROR;
170 msg = res->msgs[0];
172 for (i=0; i<msg->num_elements; i++) {
173 struct ldb_message_element *el = &msg->elements[i];
174 const struct dsdb_attribute *schema_attr
175 = dsdb_attribute_by_lDAPDisplayName(schema, el->name);
176 if (!schema_attr || schema_attr->linkID == 0) {
177 continue;
179 ret = linked_attributes_fix_links(module, msg->dn, req->op.rename.newdn, el,
180 schema, schema_attr);
181 if (ret != LDB_SUCCESS) {
182 talloc_free(res);
183 return ret;
187 talloc_free(res);
189 return ldb_next_request(module, req);
193 _PUBLIC_ const struct ldb_module_ops ldb_linked_attributes_module_ops = {
194 .name = "linked_attributes",
195 .rename = linked_attributes_rename,