selftests-drs: make our generated class subclass of classschema
[Samba/gebeck_regimport.git] / lib / ldb-samba / ldb_wrap.c
blob028bd6f58d285b03b382d50a02d098bf28707b68
1 /*
2 Unix SMB/CIFS implementation.
4 LDB wrap functions
6 Copyright (C) Andrew Tridgell 2004-2009
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.
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.
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/>.
23 the stupidity of the unix fcntl locking design forces us to never
24 allow a database file to be opened twice in the same process. These
25 wrappers provide convenient access to a tdb or ldb, taking advantage
26 of talloc destructors to ensure that only a single open is done
29 #include "includes.h"
30 #include "lib/events/events.h"
31 #include <ldb.h>
32 #include <ldb_errors.h>
33 #include "lib/ldb-samba/ldif_handlers.h"
34 #include "ldb_wrap.h"
35 #include "dsdb/samdb/samdb.h"
36 #include "param/param.h"
37 #include "../lib/util/dlinklist.h"
38 #include <tdb.h>
41 this is used to catch debug messages from ldb
43 static void ldb_wrap_debug(void *context, enum ldb_debug_level level,
44 const char *fmt, va_list ap) PRINTF_ATTRIBUTE(3,0);
46 static void ldb_wrap_debug(void *context, enum ldb_debug_level level,
47 const char *fmt, va_list ap)
49 int samba_level = -1;
50 switch (level) {
51 case LDB_DEBUG_FATAL:
52 samba_level = 0;
53 break;
54 case LDB_DEBUG_ERROR:
55 samba_level = 1;
56 break;
57 case LDB_DEBUG_WARNING:
58 samba_level = 2;
59 break;
60 case LDB_DEBUG_TRACE:
61 samba_level = 5;
62 break;
65 if (CHECK_DEBUGLVL(samba_level)) {
66 char *s = NULL;
67 vasprintf(&s, fmt, ap);
68 if (!s) return;
69 DEBUG(samba_level, ("ldb: %s\n", s));
70 free(s);
76 connecting to a ldb can be a relatively expensive operation because
77 of the schema and partition loads. We keep a list of open ldb
78 contexts here, and try to re-use when possible.
80 This means callers of ldb_wrap_connect() must use talloc_unlink() or
81 the free of a parent to destroy the context
83 static struct ldb_wrap {
84 struct ldb_wrap *next, *prev;
85 struct ldb_wrap_context {
86 /* the context is what we use to tell if two ldb
87 * connections are exactly equivalent
89 const char *url;
90 struct tevent_context *ev;
91 struct loadparm_context *lp_ctx;
92 struct auth_session_info *session_info;
93 struct cli_credentials *credentials;
94 unsigned int flags;
95 } context;
96 struct ldb_context *ldb;
97 } *ldb_wrap_list;
100 free a ldb_wrap structure
102 static int ldb_wrap_destructor(struct ldb_wrap *w)
104 DLIST_REMOVE(ldb_wrap_list, w);
105 return 0;
109 * The casefolder for s4's LDB databases - Unicode-safe
111 char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n)
113 return strupper_talloc_n(mem_ctx, s, n);
117 struct ldb_context *samba_ldb_init(TALLOC_CTX *mem_ctx,
118 struct tevent_context *ev,
119 struct loadparm_context *lp_ctx,
120 struct auth_session_info *session_info,
121 struct cli_credentials *credentials)
123 struct ldb_context *ldb;
124 int ret;
126 ldb = ldb_init(mem_ctx, ev);
127 if (ldb == NULL) {
128 return NULL;
131 ldb_set_modules_dir(ldb, modules_path(ldb, "ldb"));
133 ldb_set_debug(ldb, ldb_wrap_debug, NULL);
135 ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
137 if (session_info) {
138 if (ldb_set_opaque(ldb, "sessionInfo", session_info)) {
139 talloc_free(ldb);
140 return NULL;
144 if (credentials) {
145 if (ldb_set_opaque(ldb, "credentials", credentials)) {
146 talloc_free(ldb);
147 return NULL;
151 if (ldb_set_opaque(ldb, "loadparm", lp_ctx)) {
152 talloc_free(ldb);
153 return NULL;
156 /* This must be done before we load the schema, as these
157 * handlers for objectSid and objectGUID etc must take
158 * precedence over the 'binary attribute' declaration in the
159 * schema */
160 ret = ldb_register_samba_handlers(ldb);
161 if (ret != LDB_SUCCESS) {
162 talloc_free(ldb);
163 return NULL;
166 /* we usually want Samba databases to be private. If we later
167 find we need one public, we will need to add a parameter to
168 ldb_wrap_connect() */
169 ldb_set_create_perms(ldb, 0600);
171 return ldb;
174 struct ldb_context *ldb_wrap_find(const char *url,
175 struct tevent_context *ev,
176 struct loadparm_context *lp_ctx,
177 struct auth_session_info *session_info,
178 struct cli_credentials *credentials,
179 unsigned int flags)
181 struct ldb_wrap *w;
182 /* see if we can re-use an existing ldb */
183 for (w=ldb_wrap_list; w; w=w->next) {
184 if (w->context.ev == ev &&
185 w->context.lp_ctx == lp_ctx &&
186 w->context.session_info == session_info &&
187 w->context.credentials == credentials &&
188 w->context.flags == flags &&
189 (w->context.url == url || strcmp(w->context.url, url) == 0))
190 return w->ldb;
193 return NULL;
196 int samba_ldb_connect(struct ldb_context *ldb, struct loadparm_context *lp_ctx,
197 const char *url, unsigned int flags)
199 int ret;
200 char *real_url = NULL;
202 /* allow admins to force non-sync ldb for all databases */
203 if (lpcfg_parm_bool(lp_ctx, NULL, "ldb", "nosync", false)) {
204 flags |= LDB_FLG_NOSYNC;
207 if (DEBUGLVL(10)) {
208 flags |= LDB_FLG_ENABLE_TRACING;
211 real_url = lpcfg_private_path(ldb, lp_ctx, url);
212 if (real_url == NULL) {
213 return LDB_ERR_OPERATIONS_ERROR;
216 ret = ldb_connect(ldb, real_url, flags, NULL);
218 if (ret != LDB_SUCCESS) {
219 return ret;
222 /* setup for leak detection */
223 ldb_set_opaque(ldb, "wrap_url", real_url);
225 return LDB_SUCCESS;
228 bool ldb_wrap_add(const char *url, struct tevent_context *ev,
229 struct loadparm_context *lp_ctx,
230 struct auth_session_info *session_info,
231 struct cli_credentials *credentials,
232 unsigned int flags,
233 struct ldb_context *ldb)
235 struct ldb_wrap *w;
236 struct ldb_wrap_context c;
238 /* add to the list of open ldb contexts */
239 w = talloc(ldb, struct ldb_wrap);
240 if (w == NULL) {
241 return false;
244 c.url = url;
245 c.ev = ev;
246 c.lp_ctx = lp_ctx;
247 c.session_info = session_info;
248 c.credentials = credentials;
249 c.flags = flags;
251 w->context = c;
252 w->context.url = talloc_strdup(w, url);
253 if (w->context.url == NULL) {
254 return false;
257 if (session_info) {
258 /* take a reference to the session_info, as it is
259 * possible for the ldb to live longer than the
260 * session_info. This happens when a DRS DsBind call
261 * reuses a handle, but the original connection is
262 * shutdown. The token for the new connection is still
263 * valid, so we need the session_info to remain valid for
264 * ldb modules to use
266 if (talloc_reference(w, session_info) == NULL) {
267 return false;
271 w->ldb = ldb;
273 DLIST_ADD(ldb_wrap_list, w);
275 talloc_set_destructor(w, ldb_wrap_destructor);
277 return true;
282 wrapped connection to a ldb database
283 to close just talloc_free() the returned ldb_context
285 TODO: We need an error_string parameter
287 struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
288 struct tevent_context *ev,
289 struct loadparm_context *lp_ctx,
290 const char *url,
291 struct auth_session_info *session_info,
292 struct cli_credentials *credentials,
293 unsigned int flags)
295 struct ldb_context *ldb;
296 int ret;
298 ldb = ldb_wrap_find(url, ev, lp_ctx, session_info, credentials, flags);
299 if (ldb != NULL)
300 return talloc_reference(mem_ctx, ldb);
302 ldb = samba_ldb_init(mem_ctx, ev, lp_ctx, session_info, credentials);
304 if (ldb == NULL)
305 return NULL;
307 ret = samba_ldb_connect(ldb, lp_ctx, url, flags);
308 if (ret != LDB_SUCCESS) {
309 talloc_free(ldb);
310 return NULL;
313 if (!ldb_wrap_add(url, ev, lp_ctx, session_info, credentials, flags, ldb)) {
314 talloc_free(ldb);
315 return NULL;
318 DEBUG(3,("ldb_wrap open of %s\n", url));
320 return ldb;
324 when we fork() we need to make sure that any open ldb contexts have
325 any open transactions cancelled (ntdb databases doesn't need reopening,
326 as we don't use clear_if_first).
328 void ldb_wrap_fork_hook(void)
330 struct ldb_wrap *w;
332 for (w=ldb_wrap_list; w; w=w->next) {
333 if (ldb_transaction_cancel_noerr(w->ldb) != LDB_SUCCESS) {
334 smb_panic("Failed to cancel child transactions\n");
338 if (tdb_reopen_all(1) != 0) {
339 smb_panic("tdb_reopen_all failed\n");
343 char *ldb_relative_path(struct ldb_context *ldb,
344 TALLOC_CTX *mem_ctx,
345 const char *name)
347 const char *base_url =
348 (const char *)ldb_get_opaque(ldb, "ldb_url");
349 char *path, *p, *full_name;
350 if (name == NULL) {
351 return NULL;
353 if (strncmp("tdb://", base_url, 6) == 0) {
354 base_url = base_url+6;
356 path = talloc_strdup(mem_ctx, base_url);
357 if (path == NULL) {
358 return NULL;
360 if ( (p = strrchr(path, '/')) != NULL) {
361 p[0] = '\0';
362 full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name);
363 } else {
364 full_name = talloc_asprintf(mem_ctx, "./%s", name);
366 talloc_free(path);
367 return full_name;