docs-xml: fix pid directory example
[Samba/bb.git] / lib / ldb-samba / ldb_wrap.c
blob83a06743bef9ebce865cefbe36cb33a234fec409
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 char *s = NULL;
51 switch (level) {
52 case LDB_DEBUG_FATAL:
53 samba_level = 0;
54 break;
55 case LDB_DEBUG_ERROR:
56 samba_level = 1;
57 break;
58 case LDB_DEBUG_WARNING:
59 samba_level = 2;
60 break;
61 case LDB_DEBUG_TRACE:
62 samba_level = 5;
63 break;
66 vasprintf(&s, fmt, ap);
67 if (!s) return;
68 DEBUG(samba_level, ("ldb: %s\n", s));
69 free(s);
74 connecting to a ldb can be a relatively expensive operation because
75 of the schema and partition loads. We keep a list of open ldb
76 contexts here, and try to re-use when possible.
78 This means callers of ldb_wrap_connect() must use talloc_unlink() or
79 the free of a parent to destroy the context
81 static struct ldb_wrap {
82 struct ldb_wrap *next, *prev;
83 struct ldb_wrap_context {
84 /* the context is what we use to tell if two ldb
85 * connections are exactly equivalent
87 const char *url;
88 struct tevent_context *ev;
89 struct loadparm_context *lp_ctx;
90 struct auth_session_info *session_info;
91 struct cli_credentials *credentials;
92 unsigned int flags;
93 } context;
94 struct ldb_context *ldb;
95 } *ldb_wrap_list;
98 free a ldb_wrap structure
100 static int ldb_wrap_destructor(struct ldb_wrap *w)
102 DLIST_REMOVE(ldb_wrap_list, w);
103 return 0;
107 * The casefolder for s4's LDB databases - Unicode-safe
109 char *wrap_casefold(void *context, void *mem_ctx, const char *s, size_t n)
111 return strupper_talloc_n(mem_ctx, s, n);
115 struct ldb_context *samba_ldb_init(TALLOC_CTX *mem_ctx,
116 struct tevent_context *ev,
117 struct loadparm_context *lp_ctx,
118 struct auth_session_info *session_info,
119 struct cli_credentials *credentials)
121 struct ldb_context *ldb;
122 int ret;
124 ldb = ldb_init(mem_ctx, ev);
125 if (ldb == NULL) {
126 return NULL;
129 ldb_set_modules_dir(ldb, modules_path(ldb, "ldb"));
131 ldb_set_debug(ldb, ldb_wrap_debug, NULL);
133 ldb_set_utf8_fns(ldb, NULL, wrap_casefold);
135 if (session_info) {
136 if (ldb_set_opaque(ldb, "sessionInfo", session_info)) {
137 talloc_free(ldb);
138 return NULL;
142 if (credentials) {
143 if (ldb_set_opaque(ldb, "credentials", credentials)) {
144 talloc_free(ldb);
145 return NULL;
149 if (ldb_set_opaque(ldb, "loadparm", lp_ctx)) {
150 talloc_free(ldb);
151 return NULL;
154 /* This must be done before we load the schema, as these
155 * handlers for objectSid and objectGUID etc must take
156 * precedence over the 'binary attribute' declaration in the
157 * schema */
158 ret = ldb_register_samba_handlers(ldb);
159 if (ret != LDB_SUCCESS) {
160 talloc_free(ldb);
161 return NULL;
164 /* we usually want Samba databases to be private. If we later
165 find we need one public, we will need to add a parameter to
166 ldb_wrap_connect() */
167 ldb_set_create_perms(ldb, 0600);
169 return ldb;
172 struct ldb_context *ldb_wrap_find(const char *url,
173 struct tevent_context *ev,
174 struct loadparm_context *lp_ctx,
175 struct auth_session_info *session_info,
176 struct cli_credentials *credentials,
177 unsigned int flags)
179 struct ldb_wrap *w;
180 /* see if we can re-use an existing ldb */
181 for (w=ldb_wrap_list; w; w=w->next) {
182 if (w->context.ev == ev &&
183 w->context.lp_ctx == lp_ctx &&
184 w->context.session_info == session_info &&
185 w->context.credentials == credentials &&
186 w->context.flags == flags &&
187 (w->context.url == url || strcmp(w->context.url, url) == 0))
188 return w->ldb;
191 return NULL;
194 int samba_ldb_connect(struct ldb_context *ldb, struct loadparm_context *lp_ctx,
195 const char *url, unsigned int flags)
197 int ret;
198 char *real_url = NULL;
200 /* allow admins to force non-sync ldb for all databases */
201 if (lpcfg_parm_bool(lp_ctx, NULL, "ldb", "nosync", false)) {
202 flags |= LDB_FLG_NOSYNC;
205 if (DEBUGLVL(10)) {
206 flags |= LDB_FLG_ENABLE_TRACING;
209 real_url = lpcfg_private_path(ldb, lp_ctx, url);
210 if (real_url == NULL) {
211 return LDB_ERR_OPERATIONS_ERROR;
214 ret = ldb_connect(ldb, real_url, flags, NULL);
216 if (ret != LDB_SUCCESS) {
217 return ret;
220 /* setup for leak detection */
221 ldb_set_opaque(ldb, "wrap_url", real_url);
223 return LDB_SUCCESS;
226 bool ldb_wrap_add(const char *url, struct tevent_context *ev,
227 struct loadparm_context *lp_ctx,
228 struct auth_session_info *session_info,
229 struct cli_credentials *credentials,
230 unsigned int flags,
231 struct ldb_context *ldb)
233 struct ldb_wrap *w;
234 struct ldb_wrap_context c;
236 /* add to the list of open ldb contexts */
237 w = talloc(ldb, struct ldb_wrap);
238 if (w == NULL) {
239 return false;
242 c.url = url;
243 c.ev = ev;
244 c.lp_ctx = lp_ctx;
245 c.session_info = session_info;
246 c.credentials = credentials;
247 c.flags = flags;
249 w->context = c;
250 w->context.url = talloc_strdup(w, url);
251 if (w->context.url == NULL) {
252 return false;
255 if (session_info) {
256 /* take a reference to the session_info, as it is
257 * possible for the ldb to live longer than the
258 * session_info. This happens when a DRS DsBind call
259 * reuses a handle, but the original connection is
260 * shutdown. The token for the new connection is still
261 * valid, so we need the session_info to remain valid for
262 * ldb modules to use
264 if (talloc_reference(w, session_info) == NULL) {
265 return false;
269 w->ldb = ldb;
271 DLIST_ADD(ldb_wrap_list, w);
273 talloc_set_destructor(w, ldb_wrap_destructor);
275 return true;
280 wrapped connection to a ldb database
281 to close just talloc_free() the returned ldb_context
283 TODO: We need an error_string parameter
285 struct ldb_context *ldb_wrap_connect(TALLOC_CTX *mem_ctx,
286 struct tevent_context *ev,
287 struct loadparm_context *lp_ctx,
288 const char *url,
289 struct auth_session_info *session_info,
290 struct cli_credentials *credentials,
291 unsigned int flags)
293 struct ldb_context *ldb;
294 int ret;
296 ldb = ldb_wrap_find(url, ev, lp_ctx, session_info, credentials, flags);
297 if (ldb != NULL)
298 return talloc_reference(mem_ctx, ldb);
300 ldb = samba_ldb_init(mem_ctx, ev, lp_ctx, session_info, credentials);
302 if (ldb == NULL)
303 return NULL;
305 ret = samba_ldb_connect(ldb, lp_ctx, url, flags);
306 if (ret != LDB_SUCCESS) {
307 talloc_free(ldb);
308 return NULL;
311 if (!ldb_wrap_add(url, ev, lp_ctx, session_info, credentials, flags, ldb)) {
312 talloc_free(ldb);
313 return NULL;
316 DEBUG(3,("ldb_wrap open of %s\n", url));
318 return ldb;
322 when we fork() we need to make sure that any open ldb contexts have
323 any open transactions cancelled (ntdb databases doesn't need reopening,
324 as we don't use clear_if_first).
326 void ldb_wrap_fork_hook(void)
328 struct ldb_wrap *w;
330 for (w=ldb_wrap_list; w; w=w->next) {
331 if (ldb_transaction_cancel_noerr(w->ldb) != LDB_SUCCESS) {
332 smb_panic("Failed to cancel child transactions\n");
336 if (tdb_reopen_all(1) != 0) {
337 smb_panic("tdb_reopen_all failed\n");
341 char *ldb_relative_path(struct ldb_context *ldb,
342 TALLOC_CTX *mem_ctx,
343 const char *name)
345 const char *base_url =
346 (const char *)ldb_get_opaque(ldb, "ldb_url");
347 char *path, *p, *full_name;
348 if (name == NULL) {
349 return NULL;
351 if (strncmp("tdb://", base_url, 6) == 0) {
352 base_url = base_url+6;
354 path = talloc_strdup(mem_ctx, base_url);
355 if (path == NULL) {
356 return NULL;
358 if ( (p = strrchr(path, '/')) != NULL) {
359 p[0] = '\0';
360 full_name = talloc_asprintf(mem_ctx, "%s/%s", path, name);
361 } else {
362 full_name = talloc_asprintf(mem_ctx, "./%s", name);
364 talloc_free(path);
365 return full_name;