Line data Source code
1 : /*
2 : ldb database library
3 :
4 : Copyright (C) Andrew Bartlett <abartlet@samba.org> 2006-2007
5 : Copyright (C) Stefan Metzmacher <metze@samba.org> 2007
6 : Copyright (C) Matthias Dieter Wallnöfer <mdw@samba.org> 2010-2011
7 :
8 : This program is free software; you can redistribute it and/or modify
9 : it under the terms of the GNU General Public License as published by
10 : the Free Software Foundation; either version 3 of the License, or
11 : (at your option) any later version.
12 :
13 : This program is distributed in the hope that it will be useful,
14 : but WITHOUT ANY WARRANTY; without even the implied warranty of
15 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 : GNU General Public License for more details.
17 :
18 : You should have received a copy of the GNU General Public License
19 : along with this program. If not, see <http://www.gnu.org/licenses/>.
20 : */
21 :
22 : /*
23 : * Name: ldb
24 : *
25 : * Component: ldb subtree rename module
26 : *
27 : * Description: Rename a subtree in LDB
28 : *
29 : * Author: Andrew Bartlett
30 : */
31 :
32 : #include "includes.h"
33 : #include <ldb.h>
34 : #include <ldb_module.h>
35 : #include "libds/common/flags.h"
36 : #include "dsdb/samdb/samdb.h"
37 : #include "dsdb/samdb/ldb_modules/util.h"
38 :
39 : struct subtree_rename_context {
40 : struct ldb_module *module;
41 : struct ldb_request *req;
42 : bool base_renamed;
43 : };
44 :
45 80793 : static struct subtree_rename_context *subren_ctx_init(struct ldb_module *module,
46 : struct ldb_request *req)
47 : {
48 151 : struct subtree_rename_context *ac;
49 :
50 :
51 80944 : ac = talloc_zero(req, struct subtree_rename_context);
52 80793 : if (ac == NULL) {
53 0 : return NULL;
54 : }
55 :
56 80793 : ac->module = module;
57 80793 : ac->req = req;
58 80793 : ac->base_renamed = false;
59 :
60 80793 : return ac;
61 : }
62 :
63 81338 : static int subtree_rename_search_onelevel_callback(struct ldb_request *req,
64 : struct ldb_reply *ares)
65 : {
66 158 : struct subtree_rename_context *ac;
67 158 : int ret;
68 :
69 81338 : ac = talloc_get_type(req->context, struct subtree_rename_context);
70 :
71 81338 : if (!ares) {
72 0 : return ldb_module_done(ac->req, NULL, NULL,
73 : LDB_ERR_OPERATIONS_ERROR);
74 : }
75 81338 : if (ares->error != LDB_SUCCESS) {
76 0 : return ldb_module_done(ac->req, ares->controls,
77 : ares->response, ares->error);
78 : }
79 :
80 81338 : if (ac->base_renamed == false) {
81 80793 : ac->base_renamed = true;
82 :
83 80944 : ret = dsdb_module_rename(ac->module,
84 80642 : ac->req->op.rename.olddn,
85 80793 : ac->req->op.rename.newdn,
86 : DSDB_FLAG_NEXT_MODULE, req);
87 80793 : if (ret != LDB_SUCCESS) {
88 17 : return ldb_module_done(ac->req, NULL, NULL, ret);
89 : }
90 : }
91 :
92 81321 : switch (ares->type) {
93 545 : case LDB_REPLY_ENTRY:
94 : {
95 545 : struct ldb_dn *old_dn = NULL;
96 545 : struct ldb_dn *new_dn = NULL;
97 :
98 545 : old_dn = ares->message->dn;
99 545 : new_dn = ldb_dn_copy(ares, old_dn);
100 545 : if (!new_dn) {
101 0 : return ldb_module_oom(ac->module);
102 : }
103 :
104 545 : if ( ! ldb_dn_remove_base_components(new_dn,
105 545 : ldb_dn_get_comp_num(ac->req->op.rename.olddn))) {
106 0 : return ldb_module_done(ac->req, NULL, NULL,
107 : LDB_ERR_OPERATIONS_ERROR);
108 : }
109 :
110 545 : if ( ! ldb_dn_add_base(new_dn, ac->req->op.rename.newdn)) {
111 0 : return ldb_module_done(ac->req, NULL, NULL,
112 : LDB_ERR_OPERATIONS_ERROR);
113 : }
114 545 : ret = dsdb_module_rename(ac->module, old_dn, new_dn, DSDB_FLAG_OWN_MODULE, req);
115 545 : if (ret != LDB_SUCCESS) {
116 0 : return ldb_module_done(ac->req, NULL, NULL, ret);
117 : }
118 :
119 545 : talloc_free(ares);
120 :
121 545 : return LDB_SUCCESS;
122 : }
123 0 : case LDB_REPLY_REFERRAL:
124 : /* ignore */
125 0 : break;
126 80776 : case LDB_REPLY_DONE:
127 80776 : talloc_free(ares);
128 80776 : return ldb_module_done(ac->req, NULL, NULL, LDB_SUCCESS);
129 0 : default:
130 : {
131 0 : struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
132 :
133 0 : ldb_asprintf_errstring(ldb, "Invalid LDB reply type %d", ares->type);
134 0 : return ldb_module_done(ac->req, NULL, NULL,
135 : LDB_ERR_OPERATIONS_ERROR);
136 : }
137 : }
138 :
139 0 : return LDB_SUCCESS;
140 : }
141 :
142 : /* rename */
143 80793 : static int subtree_rename(struct ldb_module *module, struct ldb_request *req)
144 : {
145 151 : struct ldb_context *ldb;
146 151 : static const char * const no_attrs[] = {NULL};
147 151 : struct ldb_request *search_req;
148 151 : struct subtree_rename_context *ac;
149 151 : int ret;
150 :
151 80793 : if (ldb_dn_is_special(req->op.rename.olddn)) { /* do not manipulate our control entries */
152 0 : return ldb_next_request(module, req);
153 : }
154 :
155 80793 : ldb = ldb_module_get_ctx(module);
156 :
157 : /*
158 : * This gets complex: We need to:
159 : * - Do a search for all entries under this entry
160 : * - Wait for these results to appear
161 : * - Do our own rename (in first callback)
162 : * - In the callback for each result, issue a dsdb_module_rename()
163 : */
164 :
165 80793 : ac = subren_ctx_init(module, req);
166 80793 : if (!ac) {
167 0 : return ldb_oom(ldb);
168 : }
169 :
170 80793 : ret = ldb_build_search_req(&search_req, ldb_module_get_ctx(ac->module), ac,
171 80642 : ac->req->op.rename.olddn,
172 : LDB_SCOPE_ONELEVEL,
173 : "(objectClass=*)",
174 : no_attrs,
175 : NULL,
176 : ac,
177 : subtree_rename_search_onelevel_callback,
178 : req);
179 80793 : LDB_REQ_SET_LOCATION(search_req);
180 80793 : if (ret != LDB_SUCCESS) {
181 0 : return ret;
182 : }
183 :
184 80793 : ret = ldb_request_add_control(search_req, LDB_CONTROL_SHOW_RECYCLED_OID,
185 : true, NULL);
186 80793 : if (ret != LDB_SUCCESS) {
187 0 : return ret;
188 : }
189 :
190 80793 : return ldb_next_request(ac->module, search_req);
191 : }
192 :
193 : static const struct ldb_module_ops ldb_subtree_rename_module_ops = {
194 : .name = "subtree_rename",
195 : .rename = subtree_rename
196 : };
197 :
198 6040 : int ldb_subtree_rename_module_init(const char *version)
199 : {
200 6040 : LDB_MODULE_CHECK_VERSION(version);
201 6040 : return ldb_register_module(&ldb_subtree_rename_module_ops);
202 : }
|