4 Copyright (C) Andrew Bartlett 2005
5 Copyright (C) Simo Sorce 2006-2008
7 ** NOTE! The following LGPL license applies to the ldb
8 ** library. This does NOT imply that all of Samba is released
11 This library is free software; you can redistribute it and/or
12 modify it under the terms of the GNU Lesser General Public
13 License as published by the Free Software Foundation; either
14 version 3 of the License, or (at your option) any later version.
16 This library is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 Lesser General Public License for more details.
21 You should have received a copy of the GNU Lesser General Public
22 License along with this library; if not, see <http://www.gnu.org/licenses/>.
28 * Component: ldb rdn name module
30 * Description: keep a consistent name attribute on objects manpulations
32 * Author: Andrew Bartlett
35 * - made the module async
39 #include "ldb_includes.h"
40 #include "ldb_module.h"
42 struct rename_context
{
44 struct ldb_module
*module
;
45 struct ldb_request
*req
;
47 struct ldb_reply
*ares
;
50 static struct ldb_message_element
*rdn_name_find_attribute(const struct ldb_message
*msg
, const char *name
)
54 for (i
= 0; i
< msg
->num_elements
; i
++) {
55 if (ldb_attr_cmp(name
, msg
->elements
[i
].name
) == 0) {
56 return &msg
->elements
[i
];
63 static int rdn_name_add_callback(struct ldb_request
*req
,
64 struct ldb_reply
*ares
)
66 struct rename_context
*ac
;
68 ac
= talloc_get_type(req
->context
, struct rename_context
);
71 return ldb_module_done(ac
->req
, NULL
, NULL
,
72 LDB_ERR_OPERATIONS_ERROR
);
74 if (ares
->error
!= LDB_SUCCESS
) {
75 return ldb_module_done(ac
->req
, ares
->controls
,
76 ares
->response
, ares
->error
);
79 if (ares
->type
!= LDB_REPLY_DONE
) {
80 return ldb_module_done(ac
->req
, NULL
, NULL
,
81 LDB_ERR_OPERATIONS_ERROR
);
84 return ldb_module_done(ac
->req
, ares
->controls
,
85 ares
->response
, LDB_SUCCESS
);
88 static int rdn_name_add(struct ldb_module
*module
, struct ldb_request
*req
)
90 struct ldb_context
*ldb
;
91 struct ldb_request
*down_req
;
92 struct rename_context
*ac
;
93 struct ldb_message
*msg
;
94 struct ldb_message_element
*attribute
;
95 const struct ldb_schema_attribute
*a
;
97 struct ldb_val rdn_val
;
100 ldb
= ldb_module_get_ctx(module
);
101 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "rdn_name_add_record");
103 /* do not manipulate our control entries */
104 if (ldb_dn_is_special(req
->op
.add
.message
->dn
)) {
105 return ldb_next_request(module
, req
);
108 ac
= talloc_zero(req
, struct rename_context
);
110 return LDB_ERR_OPERATIONS_ERROR
;
116 msg
= ldb_msg_copy_shallow(req
, req
->op
.add
.message
);
118 return LDB_ERR_OPERATIONS_ERROR
;
121 rdn_name
= ldb_dn_get_rdn_name(msg
->dn
);
122 if (rdn_name
== NULL
) {
124 return LDB_ERR_OPERATIONS_ERROR
;
127 rdn_val
= ldb_val_dup(msg
, ldb_dn_get_rdn_val(msg
->dn
));
129 /* Perhaps someone above us tried to set this? */
130 if ((attribute
= rdn_name_find_attribute(msg
, "name")) != NULL
) {
131 attribute
->num_values
= 0;
134 if (ldb_msg_add_value(msg
, "name", &rdn_val
, NULL
) != 0) {
136 return LDB_ERR_OPERATIONS_ERROR
;
139 attribute
= rdn_name_find_attribute(msg
, rdn_name
);
142 if (ldb_msg_add_value(msg
, rdn_name
, &rdn_val
, NULL
) != 0) {
144 return LDB_ERR_OPERATIONS_ERROR
;
147 a
= ldb_schema_attribute_by_name(ldb
, rdn_name
);
149 for (i
= 0; i
< attribute
->num_values
; i
++) {
150 ret
= a
->syntax
->comparison_fn(ldb
, msg
,
151 &rdn_val
, &attribute
->values
[i
]);
153 /* overwrite so it matches in case */
154 attribute
->values
[i
] = rdn_val
;
158 if (i
== attribute
->num_values
) {
159 ldb_debug_set(ldb
, LDB_DEBUG_FATAL
,
160 "RDN mismatch on %s: %s (%s)",
161 ldb_dn_get_linearized(msg
->dn
), rdn_name
, rdn_val
.data
);
163 /* Match AD's error here */
164 return LDB_ERR_INVALID_DN_SYNTAX
;
168 ret
= ldb_build_add_req(&down_req
, ldb
, req
,
171 ac
, rdn_name_add_callback
,
173 if (ret
!= LDB_SUCCESS
) {
177 talloc_steal(down_req
, msg
);
179 /* go on with the call chain */
180 return ldb_next_request(module
, down_req
);
183 static int rdn_modify_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
185 struct rename_context
*ac
;
187 ac
= talloc_get_type(req
->context
, struct rename_context
);
190 return ldb_module_done(ac
->req
, NULL
, NULL
,
191 LDB_ERR_OPERATIONS_ERROR
);
193 if (ares
->error
!= LDB_SUCCESS
) {
194 return ldb_module_done(ac
->req
, ares
->controls
,
195 ares
->response
, ares
->error
);
198 /* the only supported reply right now is a LDB_REPLY_DONE */
199 if (ares
->type
!= LDB_REPLY_DONE
) {
200 return ldb_module_done(ac
->req
, NULL
, NULL
,
201 LDB_ERR_OPERATIONS_ERROR
);
204 /* send saved controls eventually */
205 return ldb_module_done(ac
->req
, ac
->ares
->controls
,
206 ac
->ares
->response
, LDB_SUCCESS
);
209 static int rdn_rename_callback(struct ldb_request
*req
, struct ldb_reply
*ares
)
211 struct ldb_context
*ldb
;
212 struct rename_context
*ac
;
213 struct ldb_request
*mod_req
;
214 const char *rdn_name
;
215 struct ldb_val rdn_val
;
216 struct ldb_message
*msg
;
219 ac
= talloc_get_type(req
->context
, struct rename_context
);
220 ldb
= ldb_module_get_ctx(ac
->module
);
225 if (ares
->error
!= LDB_SUCCESS
) {
226 return ldb_module_done(ac
->req
, ares
->controls
,
227 ares
->response
, ares
->error
);
230 /* the only supported reply right now is a LDB_REPLY_DONE */
231 if (ares
->type
!= LDB_REPLY_DONE
) {
235 /* save reply for caller */
236 ac
->ares
= talloc_steal(ac
, ares
);
238 msg
= ldb_msg_new(ac
);
242 msg
->dn
= ldb_dn_copy(msg
, ac
->req
->op
.rename
.newdn
);
243 if (msg
->dn
== NULL
) {
246 rdn_name
= ldb_dn_get_rdn_name(ac
->req
->op
.rename
.newdn
);
247 if (rdn_name
== NULL
) {
251 rdn_val
= ldb_val_dup(msg
, ldb_dn_get_rdn_val(ac
->req
->op
.rename
.newdn
));
253 if (ldb_msg_add_empty(msg
, rdn_name
, LDB_FLAG_MOD_REPLACE
, NULL
) != 0) {
256 if (ldb_msg_add_value(msg
, rdn_name
, &rdn_val
, NULL
) != 0) {
259 if (ldb_msg_add_empty(msg
, "name", LDB_FLAG_MOD_REPLACE
, NULL
) != 0) {
262 if (ldb_msg_add_value(msg
, "name", &rdn_val
, NULL
) != 0) {
266 ret
= ldb_build_mod_req(&mod_req
, ldb
,
268 ac
, rdn_modify_callback
,
270 if (ret
!= LDB_SUCCESS
) {
271 return ldb_module_done(ac
->req
, NULL
, NULL
, ret
);
273 talloc_steal(mod_req
, msg
);
275 /* do the mod call */
276 return ldb_request(ldb
, mod_req
);
279 return ldb_module_done(ac
->req
, NULL
, NULL
,
280 LDB_ERR_OPERATIONS_ERROR
);
283 static int rdn_name_rename(struct ldb_module
*module
, struct ldb_request
*req
)
285 struct ldb_context
*ldb
;
286 struct rename_context
*ac
;
287 struct ldb_request
*down_req
;
290 ldb
= ldb_module_get_ctx(module
);
291 ldb_debug(ldb
, LDB_DEBUG_TRACE
, "rdn_name_rename");
293 /* do not manipulate our control entries */
294 if (ldb_dn_is_special(req
->op
.rename
.newdn
)) {
295 return ldb_next_request(module
, req
);
298 ac
= talloc_zero(req
, struct rename_context
);
300 return LDB_ERR_OPERATIONS_ERROR
;
306 ret
= ldb_build_rename_req(&down_req
,
309 req
->op
.rename
.olddn
,
310 req
->op
.rename
.newdn
,
316 if (ret
!= LDB_SUCCESS
) {
317 return LDB_ERR_OPERATIONS_ERROR
;
320 /* rename first, modify "name" if rename is ok */
321 return ldb_next_request(module
, down_req
);
324 const struct ldb_module_ops ldb_rdn_name_module_ops
= {
327 .rename
= rdn_name_rename
,