2 Unix SMB/CIFS implementation.
4 LDB based services configuration
6 Copyright (C) Simo Sorce 2006
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 2 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, write to the Free Software
20 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
24 #include "ldb/include/ldb.h"
25 #include "ldb/include/ldb_errors.h"
26 #include "auth/auth.h"
28 #include "param/share.h"
30 static NTSTATUS
sldb_init(TALLOC_CTX
*mem_ctx
, const struct share_ops
*ops
, struct share_context
**ctx
)
32 struct ldb_context
*sdb
;
34 *ctx
= talloc(mem_ctx
, struct share_context
);
36 DEBUG(0, ("ERROR: Out of memory!\n"));
37 return NT_STATUS_NO_MEMORY
;
40 sdb
= ldb_wrap_connect( *ctx
,
41 private_path(*ctx
, "share.ldb"),
47 return NT_STATUS_UNSUCCESSFUL
;
51 (*ctx
)->priv_data
= (void *)sdb
;
56 static const char *sldb_string_option(struct share_config
*scfg
, const char *opt_name
, const char *defval
)
58 struct ldb_message
*msg
;
59 struct ldb_message_element
*el
;
61 if (scfg
== NULL
) return defval
;
63 msg
= talloc_get_type(scfg
->opaque
, struct ldb_message
);
65 if (strchr(opt_name
, ':')) {
68 name
= talloc_strdup(scfg
, opt_name
);
72 p
= strchr(name
, ':');
75 el
= ldb_msg_find_element(msg
, name
);
77 el
= ldb_msg_find_element(msg
, opt_name
);
84 return (const char *)(el
->values
[0].data
);
87 static int sldb_int_option(struct share_config
*scfg
, const char *opt_name
, int defval
)
92 val
= sldb_string_option(scfg
, opt_name
, NULL
);
93 if (val
== NULL
) return defval
;
96 ret
= (int)strtol(val
, NULL
, 10);
102 static BOOL
sldb_bool_option(struct share_config
*scfg
, const char *opt_name
, BOOL defval
)
106 val
= sldb_string_option(scfg
, opt_name
, NULL
);
107 if (val
== NULL
) return defval
;
109 if (strcasecmp(val
, "true") == 0) return True
;
114 static const char **sldb_string_list_option(TALLOC_CTX
*mem_ctx
, struct share_config
*scfg
, const char *opt_name
)
116 struct ldb_message
*msg
;
117 struct ldb_message_element
*el
;
121 if (scfg
== NULL
) return NULL
;
123 msg
= talloc_get_type(scfg
->opaque
, struct ldb_message
);
125 if (strchr(opt_name
, ':')) {
128 name
= talloc_strdup(scfg
, opt_name
);
132 p
= strchr(name
, ':');
135 el
= ldb_msg_find_element(msg
, name
);
137 el
= ldb_msg_find_element(msg
, opt_name
);
144 list
= talloc_array(mem_ctx
, const char *, el
->num_values
+ 1);
145 if (!list
) return NULL
;
147 for (i
= 0; i
< el
->num_values
; i
++) {
148 list
[i
] = (const char *)(el
->values
[i
].data
);
155 static NTSTATUS
sldb_list_all(TALLOC_CTX
*mem_ctx
,
156 struct share_context
*ctx
,
162 struct ldb_context
*ldb
;
163 struct ldb_result
*res
;
166 tmp_ctx
= talloc_new(mem_ctx
);
168 DEBUG(0,("ERROR: Out of memory!\n"));
169 return NT_STATUS_NO_MEMORY
;
172 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
174 ret
= ldb_search(ldb
, ldb_dn_new(tmp_ctx
, ldb
, "CN=SHARES"), LDB_SCOPE_SUBTREE
, "(name=*)", NULL
, &res
);
175 talloc_steal(tmp_ctx
, res
);
176 if (ret
!= LDB_SUCCESS
) {
177 talloc_free(tmp_ctx
);
178 return NT_STATUS_BAD_NETWORK_NAME
;
181 n
= talloc_array(mem_ctx
, const char *, res
->count
);
183 DEBUG(0,("ERROR: Out of memory!\n"));
184 talloc_free(tmp_ctx
);
185 return NT_STATUS_NO_MEMORY
;
188 for (i
= 0, j
= 0; i
< res
->count
; i
++) {
189 n
[j
] = talloc_strdup(n
, ldb_msg_find_attr_as_string(res
->msgs
[i
], "name", NULL
));
191 DEBUG(0,("WARNING: Malformed share object in share database\n!"));
199 talloc_free(tmp_ctx
);
204 static NTSTATUS
sldb_get_config(TALLOC_CTX
*mem_ctx
,
205 struct share_context
*ctx
,
207 struct share_config
**scfg
)
210 struct share_config
*s
;
211 struct ldb_context
*ldb
;
212 struct ldb_result
*res
;
215 tmp_ctx
= talloc_new(mem_ctx
);
217 DEBUG(0,("ERROR: Out of memory!\n"));
218 return NT_STATUS_NO_MEMORY
;
221 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
223 ret
= ldb_search_exp_fmt(ldb
, tmp_ctx
, &res
,
224 ldb_dn_new(tmp_ctx
, ldb
, "CN=SHARES"), LDB_SCOPE_SUBTREE
, NULL
,
226 if (ret
!= LDB_SUCCESS
|| res
->count
!= 1) {
227 talloc_free(tmp_ctx
);
228 return NT_STATUS_BAD_NETWORK_NAME
;
231 s
= talloc(tmp_ctx
, struct share_config
);
233 DEBUG(0,("ERROR: Out of memory!\n"));
234 talloc_free(tmp_ctx
);
235 return NT_STATUS_NO_MEMORY
;
238 s
->name
= talloc_strdup(s
, ldb_msg_find_attr_as_string(res
->msgs
[0], "name", NULL
));
240 DEBUG(0,("ERROR: Invalid share object!\n"));
241 talloc_free(tmp_ctx
);
242 return NT_STATUS_UNSUCCESSFUL
;
245 s
->opaque
= talloc_steal(s
, res
->msgs
[0]);
247 DEBUG(0,("ERROR: Invalid share object!\n"));
248 talloc_free(tmp_ctx
);
249 return NT_STATUS_UNSUCCESSFUL
;
254 *scfg
= talloc_steal(mem_ctx
, s
);
256 talloc_free(tmp_ctx
);
260 #define SHARE_ADD_STRING(name, value) do { \
261 err = ldb_msg_add_string(msg, name, value); \
262 if (err != LDB_SUCCESS) { \
263 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
264 ret = NT_STATUS_UNSUCCESSFUL; \
268 #define SHARE_ADD_INT(name, value) do { \
269 err = ldb_msg_add_fmt(msg, name, "%d", value); \
270 if (err != LDB_SUCCESS) { \
271 DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \
272 ret = NT_STATUS_UNSUCCESSFUL; \
276 #define SHARE_ADD_BLOB(name, value) do { \
277 err = ldb_msg_add_value(msg, name, value, NULL); \
278 if (err != LDB_SUCCESS) { \
279 DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \
280 ret = NT_STATUS_UNSUCCESSFUL; \
284 NTSTATUS
sldb_create(struct share_context
*ctx
, const char *name
, struct share_info
*info
, int count
)
286 struct ldb_context
*ldb
;
287 struct ldb_message
*msg
;
292 for (i
= 0, j
= 0; i
< count
|| j
!= 0x03; i
++) {
293 if (strcasecmp(info
[i
].name
, SHARE_TYPE
) == 0) j
|= 0x02;
294 if (strcasecmp(info
[i
].name
, SHARE_PATH
) == 0) j
|= 0x01;
295 if (strcasecmp(info
[i
].name
, SHARE_NAME
) == 0) {
296 if (strcasecmp(name
, (char *)info
[i
].value
) != 0) {
297 return NT_STATUS_INVALID_PARAMETER
;
301 if (!name
|| j
!= 0x03) {
302 return NT_STATUS_INVALID_PARAMETER
;
305 tmp_ctx
= talloc_new(NULL
);
307 DEBUG(0,("ERROR: Out of memory!\n"));
308 return NT_STATUS_NO_MEMORY
;
311 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
313 msg
= ldb_msg_new(tmp_ctx
);
315 DEBUG(0,("ERROR: Out of memory!\n"));
316 ret
= NT_STATUS_NO_MEMORY
;
320 /* TODO: escape info->name */
321 msg
->dn
= ldb_dn_new_fmt(tmp_ctx
, ldb
, "CN=%s,CN=SHARES", name
);
323 DEBUG(0,("ERROR: Out of memory!\n"));
324 ret
= NT_STATUS_NO_MEMORY
;
328 SHARE_ADD_STRING("objectClass", "top");
329 SHARE_ADD_STRING("objectClass", "share");
330 SHARE_ADD_STRING("cn", name
);
331 SHARE_ADD_STRING(SHARE_NAME
, name
);
333 for (i
= 0; i
< count
; i
++) {
334 if (strcasecmp(info
[i
].name
, SHARE_NAME
) == 0) continue;
336 switch (info
[i
].type
) {
337 case SHARE_INFO_STRING
:
338 SHARE_ADD_STRING(info
[i
].name
, (char *)info
[i
].value
);
341 SHARE_ADD_INT(info
[i
].name
, *((int *)info
[i
].value
));
343 case SHARE_INFO_BLOB
:
344 SHARE_ADD_BLOB(info
[i
].name
, (DATA_BLOB
*)info
[i
].value
);
347 DEBUG(2,("ERROR: Invalid share info type for %s\n", info
[i
].name
));
348 ret
= NT_STATUS_INVALID_PARAMETER
;
353 /* TODO: Security Descriptor */
355 SHARE_ADD_STRING(SHARE_AVAILABLE
, "True");
356 SHARE_ADD_STRING(SHARE_BROWSEABLE
, "True");
357 SHARE_ADD_STRING(SHARE_READONLY
, "False");
358 SHARE_ADD_STRING(SHARE_NTVFS_HANDLER
, "unixuid");
359 SHARE_ADD_STRING(SHARE_NTVFS_HANDLER
, "posix");
361 err
= ldb_add(ldb
, msg
);
362 if (err
!= LDB_SUCCESS
) {
363 DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
364 " err=%d [%s]\n", name
, err
, ldb_errstring(ldb
)));
365 if (err
== LDB_ERR_NO_SUCH_OBJECT
) {
366 ret
= NT_STATUS_BAD_NETWORK_NAME
;
368 ret
= NT_STATUS_UNSUCCESSFUL
;
375 talloc_free(tmp_ctx
);
379 #define SHARE_MOD_STRING(name, value) do { \
380 err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
381 if (err != LDB_SUCCESS) { \
382 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
383 ret = NT_STATUS_UNSUCCESSFUL; \
386 err = ldb_msg_add_string(msg, name, value); \
387 if (err != LDB_SUCCESS) { \
388 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
389 ret = NT_STATUS_UNSUCCESSFUL; \
393 #define SHARE_MOD_INT(name, value) do { \
394 err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
395 if (err != LDB_SUCCESS) { \
396 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
397 ret = NT_STATUS_UNSUCCESSFUL; \
400 err = ldb_msg_add_fmt(msg, name, "%d", value); \
401 if (err != LDB_SUCCESS) { \
402 DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \
403 ret = NT_STATUS_UNSUCCESSFUL; \
407 #define SHARE_MOD_BLOB(name, value) do { \
408 err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
409 if (err != LDB_SUCCESS) { \
410 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
411 ret = NT_STATUS_UNSUCCESSFUL; \
414 err = ldb_msg_add_value(msg, name, value, NULL); \
415 if (err != LDB_SUCCESS) { \
416 DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \
417 ret = NT_STATUS_UNSUCCESSFUL; \
421 NTSTATUS
sldb_set(struct share_context
*ctx
, const char *name
, struct share_info
*info
, int count
)
423 struct ldb_context
*ldb
;
424 struct ldb_message
*msg
;
427 bool do_rename
= False
;
432 return NT_STATUS_INVALID_PARAMETER
;
435 tmp_ctx
= talloc_new(NULL
);
437 DEBUG(0,("ERROR: Out of memory!\n"));
438 return NT_STATUS_NO_MEMORY
;
441 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
443 msg
= ldb_msg_new(tmp_ctx
);
445 DEBUG(0,("ERROR: Out of memory!\n"));
446 ret
= NT_STATUS_NO_MEMORY
;
450 /* TODO: escape name */
451 msg
->dn
= ldb_dn_new_fmt(tmp_ctx
, ldb
, "CN=%s,CN=SHARES", name
);
453 DEBUG(0,("ERROR: Out of memory!\n"));
454 ret
= NT_STATUS_NO_MEMORY
;
458 for (i
= 0; i
< count
; i
++) {
459 if (strcasecmp(info
[i
].name
, SHARE_NAME
) == 0) {
460 if (strcasecmp(name
, (char *)info
[i
].value
) != 0) {
462 newname
= (char *)info
[i
].value
;
463 SHARE_MOD_STRING("cn", (char *)info
[i
].value
);
467 switch (info
[i
].type
) {
468 case SHARE_INFO_STRING
:
469 SHARE_MOD_STRING(info
[i
].name
, (char *)info
[i
].value
);
472 SHARE_MOD_INT(info
[i
].name
, *((int *)info
[i
].value
));
474 case SHARE_INFO_BLOB
:
475 SHARE_MOD_BLOB(info
[i
].name
, (DATA_BLOB
*)info
[i
].value
);
478 DEBUG(2,("ERROR: Invalid share info type for %s\n", info
[i
].name
));
479 ret
= NT_STATUS_INVALID_PARAMETER
;
485 struct ldb_dn
*olddn
, *newdn
;
489 /* TODO: escape newname */
490 newdn
= ldb_dn_new_fmt(tmp_ctx
, ldb
, "CN=%s,CN=SHARES", newname
);
492 DEBUG(0,("ERROR: Out of memory!\n"));
493 ret
= NT_STATUS_NO_MEMORY
;
497 err
= ldb_rename(ldb
, olddn
, newdn
);
498 if (err
!= LDB_SUCCESS
) {
499 DEBUG(2,("ERROR: unable to rename share %s (to %s)\n"
500 " err=%d [%s]\n", name
, newname
, err
, ldb_errstring(ldb
)));
501 if (err
== LDB_ERR_NO_SUCH_OBJECT
) {
502 ret
= NT_STATUS_BAD_NETWORK_NAME
;
504 ret
= NT_STATUS_UNSUCCESSFUL
;
512 err
= ldb_modify(ldb
, msg
);
513 if (err
!= LDB_SUCCESS
) {
514 DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
515 " err=%d [%s]\n", name
, err
, ldb_errstring(ldb
)));
516 if (err
== LDB_ERR_NO_SUCH_OBJECT
) {
517 ret
= NT_STATUS_BAD_NETWORK_NAME
;
519 ret
= NT_STATUS_UNSUCCESSFUL
;
526 talloc_free(tmp_ctx
);
530 NTSTATUS
sldb_remove(struct share_context
*ctx
, const char *name
)
532 struct ldb_context
*ldb
;
538 tmp_ctx
= talloc_new(NULL
);
540 DEBUG(0,("ERROR: Out of memory!\n"));
541 return NT_STATUS_NO_MEMORY
;
544 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
546 dn
= ldb_dn_new_fmt(tmp_ctx
, ldb
, "CN=%s,CN=SHARES", name
);
548 DEBUG(0,("ERROR: Out of memory!\n"));
549 ret
= NT_STATUS_NO_MEMORY
;
553 err
= ldb_delete(ldb
, dn
);
554 if (err
!= LDB_SUCCESS
) {
555 DEBUG(2,("ERROR: unable to remove share %s from share.ldb\n"
556 " err=%d [%s]\n", name
, err
, ldb_errstring(ldb
)));
557 ret
= NT_STATUS_UNSUCCESSFUL
;
563 talloc_free(tmp_ctx
);
567 NTSTATUS
share_ldb_init(void)
569 static struct share_ops ops
= {
572 .string_option
= sldb_string_option
,
573 .int_option
= sldb_int_option
,
574 .bool_option
= sldb_bool_option
,
575 .string_list_option
= sldb_string_list_option
,
576 .list_all
= sldb_list_all
,
577 .get_config
= sldb_get_config
,
578 .create
= sldb_create
,
580 .remove
= sldb_remove
583 return share_register(&ops
);