s4-dsdb: added dsdb_module_dn_by_guid()
[kai/samba-autobuild/.git] / source4 / dsdb / samdb / ldb_modules / util.c
1 /* 
2    Unix SMB/CIFS implementation.
3    Samba utility functions
4
5    Copyright (C) Andrew Tridgell 2009
6    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2009
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 #include "includes.h"
23 #include "ldb.h"
24 #include "ldb_module.h"
25 #include "dsdb/samdb/ldb_modules/util.h"
26 #include "dsdb/samdb/samdb.h"
27
28 int dsdb_module_search_handle_flags(struct ldb_module *module, struct ldb_request *req, int dsdb_flags) 
29 {
30         int ret;
31         if (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) {
32                 struct ldb_search_options_control *options;
33                 /* Using the phantom root control allows us to search all partitions */
34                 options = talloc(req, struct ldb_search_options_control);
35                 if (options == NULL) {
36                         ldb_module_oom(module);
37                         return LDB_ERR_OPERATIONS_ERROR;
38                 }
39                 options->search_options = LDB_SEARCH_OPTION_PHANTOM_ROOT;
40                 
41                 ret = ldb_request_add_control(req,
42                                               LDB_CONTROL_SEARCH_OPTIONS_OID,
43                                               true, options);
44                 if (ret != LDB_SUCCESS) {
45                         return ret;
46                 }
47         }
48
49         if (dsdb_flags & DSDB_SEARCH_SHOW_DELETED) {
50                 ret = ldb_request_add_control(req, LDB_CONTROL_SHOW_DELETED_OID, true, NULL);
51                 if (ret != LDB_SUCCESS) {
52                         return ret;
53                 }
54         }
55
56         if (dsdb_flags & DSDB_SEARCH_SHOW_DN_IN_STORAGE_FORMAT) {
57                 ret = ldb_request_add_control(req, DSDB_CONTROL_DN_STORAGE_FORMAT_OID, true, NULL);
58                 if (ret != LDB_SUCCESS) {
59                         return ret;
60                 }
61         }
62
63         if (dsdb_flags & DSDB_SEARCH_SHOW_EXTENDED_DN) {
64                 struct ldb_extended_dn_control *extended_ctrl = talloc(req, struct ldb_extended_dn_control);
65                 if (!extended_ctrl) {
66                         ldb_module_oom(module);
67                         return LDB_ERR_OPERATIONS_ERROR;
68                 }
69                 extended_ctrl->type = 1;
70                 
71                 ret = ldb_request_add_control(req, LDB_CONTROL_EXTENDED_DN_OID, true, extended_ctrl);
72                 if (ret != LDB_SUCCESS) {
73                         return ret;
74                 }
75         }
76
77         if (dsdb_flags & DSDB_SEARCH_REVEAL_INTERNALS) {
78                 ret = ldb_request_add_control(req, LDB_CONTROL_REVEAL_INTERNALS, false, NULL);
79                 if (ret != LDB_SUCCESS) {
80                         return ret;
81                 }
82         }
83
84         return LDB_SUCCESS;
85 }
86
87 /*
88   search for attrs on one DN, in the modules below
89  */
90 int dsdb_module_search_dn(struct ldb_module *module,
91                           TALLOC_CTX *mem_ctx,
92                           struct ldb_result **_res,
93                           struct ldb_dn *basedn,
94                           const char * const *attrs,
95                           int dsdb_flags)
96 {
97         int ret;
98         struct ldb_request *req;
99         TALLOC_CTX *tmp_ctx;
100         struct ldb_result *res;
101
102         tmp_ctx = talloc_new(mem_ctx);
103
104         res = talloc_zero(tmp_ctx, struct ldb_result);
105         if (!res) {
106                 return LDB_ERR_OPERATIONS_ERROR;
107         }
108
109         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
110                                    basedn,
111                                    LDB_SCOPE_BASE,
112                                    NULL,
113                                    attrs,
114                                    NULL,
115                                    res,
116                                    ldb_search_default_callback,
117                                    NULL);
118         if (ret != LDB_SUCCESS) {
119                 talloc_free(tmp_ctx);
120                 return ret;
121         }
122
123         ret = dsdb_module_search_handle_flags(module, req, dsdb_flags);
124         if (ret != LDB_SUCCESS) {
125                 talloc_free(tmp_ctx);
126                 return ret;
127         }
128
129         ret = ldb_next_request(module, req);
130         if (ret == LDB_SUCCESS) {
131                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
132         }
133
134         if (ret != LDB_SUCCESS) {
135                 talloc_free(tmp_ctx);
136                 return ret;
137         }
138
139         if (res->count != 1) {
140                 /* we may be reading a DB that does not have the 'check base on search' option... */
141                 ret = LDB_ERR_NO_SUCH_OBJECT;
142                 ldb_asprintf_errstring(ldb_module_get_ctx(module), 
143                                        "dsdb_module_search_dn: did not find base dn %s (%d results)", 
144                                        ldb_dn_get_linearized(basedn), res->count);
145         } else {
146                 *_res = talloc_steal(mem_ctx, res);
147         }
148         talloc_free(tmp_ctx);
149         return ret;
150 }
151
152 /*
153   search for attrs in the modules below
154  */
155 int dsdb_module_search(struct ldb_module *module,
156                        TALLOC_CTX *mem_ctx,
157                        struct ldb_result **_res,
158                        struct ldb_dn *basedn, enum ldb_scope scope, 
159                        const char * const *attrs,
160                        int dsdb_flags, 
161                        const char *expression)
162 {
163         int ret;
164         struct ldb_request *req;
165         TALLOC_CTX *tmp_ctx;
166         struct ldb_result *res;
167
168         tmp_ctx = talloc_new(mem_ctx);
169
170         res = talloc_zero(tmp_ctx, struct ldb_result);
171         if (!res) {
172                 return LDB_ERR_OPERATIONS_ERROR;
173         }
174
175         ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
176                                    basedn,
177                                    scope,
178                                    expression,
179                                    attrs,
180                                    NULL,
181                                    res,
182                                    ldb_search_default_callback,
183                                    NULL);
184         if (ret != LDB_SUCCESS) {
185                 talloc_free(tmp_ctx);
186                 return ret;
187         }
188
189         ret = dsdb_module_search_handle_flags(module, req, dsdb_flags);
190         if (ret != LDB_SUCCESS) {
191                 talloc_free(tmp_ctx);
192                 return ret;
193         }
194
195         ret = ldb_next_request(module, req);
196         if (ret == LDB_SUCCESS) {
197                 ret = ldb_wait(req->handle, LDB_WAIT_ALL);
198         }
199
200         talloc_free(req);
201         if (ret == LDB_SUCCESS) {
202                 *_res = talloc_steal(mem_ctx, res);
203         }
204         talloc_free(tmp_ctx);
205         return ret;
206 }
207
208 /*
209   find a DN given a GUID. This searches across all partitions
210  */
211 int dsdb_module_dn_by_guid(struct ldb_module *module, TALLOC_CTX *mem_ctx,
212                            const struct GUID *guid, struct ldb_dn **dn)
213 {
214         struct ldb_result *res;
215         const char *attrs[] = { NULL };
216         char *expression;
217         TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
218         int ret;
219
220         expression = talloc_asprintf(tmp_ctx, "objectGUID=%s", GUID_string(tmp_ctx, guid));
221         if (!expression) {
222                 ldb_module_oom(module);
223                 return LDB_ERR_OPERATIONS_ERROR;
224         }
225
226         ret = dsdb_module_search(module, tmp_ctx, &res, NULL, LDB_SCOPE_SUBTREE,
227                                  attrs, DSDB_SEARCH_SHOW_DELETED | DSDB_SEARCH_SEARCH_ALL_PARTITIONS,
228                                  expression);
229         if (ret != LDB_SUCCESS) {
230                 talloc_free(tmp_ctx);
231                 return ret;
232         }
233         if (ret->count == 0) {
234                 talloc_free(tmp_ctx);
235                 return LDB_ERR_NO_SUCH_OBJECT;
236         }
237         if (res->count != 1) {
238                 ldb_asprintf_errstring(ldb_module_get_ctx(module), "More than one object found matching %s\n",
239                                        expression);
240                 talloc_free(tmp_ctx);
241                 return LDB_ERR_OPERATIONS_ERROR;
242         }
243
244         *dn = talloc_steal(mem_ctx, res->msgs[0].dn);
245
246         talloc_free(tmp_ctx);
247         return LDB_SUCCESS;
248 }