2 Unix SMB/CIFS implementation.
4 LDB based shares 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 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/>.
24 #include <ldb_errors.h>
25 #include "auth/auth.h"
27 #include "param/share.h"
28 #include "param/param.h"
30 NTSTATUS
share_ldb_init(void);
32 static NTSTATUS
sldb_init(TALLOC_CTX
*mem_ctx
, const struct share_ops
*ops
,
33 struct tevent_context
*ev_ctx
,
34 struct loadparm_context
*lp_ctx
,
35 struct share_context
**ctx
)
37 struct ldb_context
*sdb
;
39 *ctx
= talloc(mem_ctx
, struct share_context
);
41 DEBUG(0, ("ERROR: Out of memory!\n"));
42 return NT_STATUS_NO_MEMORY
;
45 sdb
= ldb_wrap_connect(*ctx
, ev_ctx
, lp_ctx
,
46 lpcfg_private_path(*ctx
, lp_ctx
, "share.ldb"),
47 system_session(lp_ctx
),
52 return NT_STATUS_UNSUCCESSFUL
;
56 (*ctx
)->priv_data
= (void *)sdb
;
61 static const char *sldb_string_option(struct share_config
*scfg
, const char *opt_name
, const char *defval
)
63 struct ldb_message
*msg
;
64 struct ldb_message_element
*el
;
66 if (scfg
== NULL
) return defval
;
68 msg
= talloc_get_type(scfg
->opaque
, struct ldb_message
);
70 if (strchr(opt_name
, ':')) {
73 name
= talloc_strdup(scfg
, opt_name
);
77 p
= strchr(name
, ':');
80 el
= ldb_msg_find_element(msg
, name
);
82 el
= ldb_msg_find_element(msg
, opt_name
);
89 return (const char *)(el
->values
[0].data
);
92 static int sldb_int_option(struct share_config
*scfg
, const char *opt_name
, int defval
)
97 val
= sldb_string_option(scfg
, opt_name
, NULL
);
98 if (val
== NULL
) return defval
;
101 ret
= (int)strtol(val
, NULL
, 10);
102 if (errno
) return -1;
107 static bool sldb_bool_option(struct share_config
*scfg
, const char *opt_name
, bool defval
)
111 val
= sldb_string_option(scfg
, opt_name
, NULL
);
112 if (val
== NULL
) return defval
;
114 if (strcasecmp(val
, "true") == 0) return true;
119 static const char **sldb_string_list_option(TALLOC_CTX
*mem_ctx
, struct share_config
*scfg
, const char *opt_name
)
121 struct ldb_message
*msg
;
122 struct ldb_message_element
*el
;
126 if (scfg
== NULL
) return NULL
;
128 msg
= talloc_get_type(scfg
->opaque
, struct ldb_message
);
130 if (strchr(opt_name
, ':')) {
133 name
= talloc_strdup(scfg
, opt_name
);
137 p
= strchr(name
, ':');
140 el
= ldb_msg_find_element(msg
, name
);
142 el
= ldb_msg_find_element(msg
, opt_name
);
149 list
= talloc_array(mem_ctx
, const char *, el
->num_values
+ 1);
150 if (!list
) return NULL
;
152 for (i
= 0; i
< el
->num_values
; i
++) {
153 list
[i
] = (const char *)(el
->values
[i
].data
);
160 static NTSTATUS
sldb_list_all(TALLOC_CTX
*mem_ctx
,
161 struct share_context
*ctx
,
167 struct ldb_context
*ldb
;
168 struct ldb_result
*res
;
171 tmp_ctx
= talloc_new(mem_ctx
);
173 DEBUG(0,("ERROR: Out of memory!\n"));
174 return NT_STATUS_NO_MEMORY
;
177 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
179 ret
= ldb_search(ldb
, tmp_ctx
, &res
, ldb_dn_new(tmp_ctx
, ldb
, "CN=SHARES"),
180 LDB_SCOPE_SUBTREE
, NULL
, "(name=*)");
181 if (ret
!= LDB_SUCCESS
) {
182 talloc_free(tmp_ctx
);
183 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
186 n
= talloc_array(mem_ctx
, const char *, res
->count
);
188 DEBUG(0,("ERROR: Out of memory!\n"));
189 talloc_free(tmp_ctx
);
190 return NT_STATUS_NO_MEMORY
;
193 for (i
= 0, j
= 0; i
< res
->count
; i
++) {
194 n
[j
] = talloc_strdup(n
, ldb_msg_find_attr_as_string(res
->msgs
[i
], "name", NULL
));
196 DEBUG(0,("WARNING: Malformed share object in share database\n!"));
204 talloc_free(tmp_ctx
);
209 static NTSTATUS
sldb_get_config(TALLOC_CTX
*mem_ctx
,
210 struct share_context
*ctx
,
212 struct share_config
**scfg
)
215 struct share_config
*s
;
216 struct ldb_context
*ldb
;
217 struct ldb_result
*res
;
220 tmp_ctx
= talloc_new(mem_ctx
);
222 DEBUG(0,("ERROR: Out of memory!\n"));
223 return NT_STATUS_NO_MEMORY
;
226 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
228 ret
= ldb_search(ldb
, tmp_ctx
, &res
,
229 ldb_dn_new(tmp_ctx
, ldb
, "CN=SHARES"), LDB_SCOPE_SUBTREE
, NULL
,
231 if (ret
!= LDB_SUCCESS
|| res
->count
> 1) {
232 talloc_free(tmp_ctx
);
233 return NT_STATUS_INTERNAL_DB_CORRUPTION
;
234 } else if (res
->count
!= 1) {
235 talloc_free(tmp_ctx
);
236 return NT_STATUS_OBJECT_NAME_NOT_FOUND
;
239 s
= talloc(tmp_ctx
, struct share_config
);
241 DEBUG(0,("ERROR: Out of memory!\n"));
242 talloc_free(tmp_ctx
);
243 return NT_STATUS_NO_MEMORY
;
246 s
->name
= talloc_strdup(s
, ldb_msg_find_attr_as_string(res
->msgs
[0], "name", NULL
));
248 DEBUG(0,("ERROR: Invalid share object!\n"));
249 talloc_free(tmp_ctx
);
250 return NT_STATUS_UNSUCCESSFUL
;
253 s
->opaque
= talloc_steal(s
, res
->msgs
[0]);
255 DEBUG(0,("ERROR: Invalid share object!\n"));
256 talloc_free(tmp_ctx
);
257 return NT_STATUS_UNSUCCESSFUL
;
262 *scfg
= talloc_steal(mem_ctx
, s
);
264 talloc_free(tmp_ctx
);
268 #define SHARE_ADD_STRING(name, value) do { \
269 err = ldb_msg_add_string(msg, name, value); \
270 if (err != LDB_SUCCESS) { \
271 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
272 ret = NT_STATUS_UNSUCCESSFUL; \
276 #define SHARE_ADD_INT(name, value) do { \
277 err = ldb_msg_add_fmt(msg, name, "%d", value); \
278 if (err != LDB_SUCCESS) { \
279 DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \
280 ret = NT_STATUS_UNSUCCESSFUL; \
284 #define SHARE_ADD_BLOB(name, value) do { \
285 err = ldb_msg_add_value(msg, name, value, NULL); \
286 if (err != LDB_SUCCESS) { \
287 DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \
288 ret = NT_STATUS_UNSUCCESSFUL; \
292 static NTSTATUS
sldb_create(struct share_context
*ctx
, const char *name
, struct share_info
*info
, int count
)
294 struct ldb_context
*ldb
;
295 struct ldb_message
*msg
;
300 for (i
= 0, j
= 0; i
< count
&& j
!= 0x03; i
++) {
301 if (strcasecmp(info
[i
].name
, SHARE_TYPE
) == 0) j
|= 0x02;
302 if (strcasecmp(info
[i
].name
, SHARE_PATH
) == 0) j
|= 0x01;
303 if (strcasecmp(info
[i
].name
, SHARE_NAME
) == 0) {
304 if (strcasecmp(name
, (char *)info
[i
].value
) != 0) {
305 return NT_STATUS_INVALID_PARAMETER
;
309 if (!name
|| j
!= 0x03) {
310 return NT_STATUS_INVALID_PARAMETER
;
313 tmp_ctx
= talloc_new(NULL
);
315 DEBUG(0,("ERROR: Out of memory!\n"));
316 return NT_STATUS_NO_MEMORY
;
319 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
321 msg
= ldb_msg_new(tmp_ctx
);
323 DEBUG(0,("ERROR: Out of memory!\n"));
324 ret
= NT_STATUS_NO_MEMORY
;
328 /* TODO: escape info->name */
329 msg
->dn
= ldb_dn_new_fmt(tmp_ctx
, ldb
, "CN=%s,CN=SHARES", name
);
331 DEBUG(0,("ERROR: Out of memory!\n"));
332 ret
= NT_STATUS_NO_MEMORY
;
336 SHARE_ADD_STRING("objectClass", "top");
337 SHARE_ADD_STRING("objectClass", "share");
338 SHARE_ADD_STRING("cn", name
);
339 SHARE_ADD_STRING(SHARE_NAME
, name
);
341 for (i
= 0; i
< count
; i
++) {
342 if (strcasecmp(info
[i
].name
, SHARE_NAME
) == 0) continue;
344 switch (info
[i
].type
) {
345 case SHARE_INFO_STRING
:
346 SHARE_ADD_STRING(info
[i
].name
, (char *)info
[i
].value
);
349 SHARE_ADD_INT(info
[i
].name
, *((int *)info
[i
].value
));
351 case SHARE_INFO_BLOB
:
352 SHARE_ADD_BLOB(info
[i
].name
, (DATA_BLOB
*)info
[i
].value
);
355 DEBUG(2,("ERROR: Invalid share info type for %s\n", info
[i
].name
));
356 ret
= NT_STATUS_INVALID_PARAMETER
;
361 /* TODO: Security Descriptor */
363 SHARE_ADD_STRING(SHARE_AVAILABLE
, "true");
364 SHARE_ADD_STRING(SHARE_BROWSEABLE
, "true");
365 SHARE_ADD_STRING(SHARE_READONLY
, "false");
366 SHARE_ADD_STRING(SHARE_NTVFS_HANDLER
, "unixuid");
367 SHARE_ADD_STRING(SHARE_NTVFS_HANDLER
, "posix");
369 err
= ldb_add(ldb
, msg
);
370 if (err
!= LDB_SUCCESS
) {
371 DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
372 " err=%d [%s]\n", name
, err
, ldb_errstring(ldb
)));
373 if (err
== LDB_ERR_NO_SUCH_OBJECT
) {
374 ret
= NT_STATUS_OBJECT_NAME_NOT_FOUND
;
375 } else if (err
== LDB_ERR_ENTRY_ALREADY_EXISTS
) {
376 ret
= NT_STATUS_OBJECT_NAME_COLLISION
;
378 ret
= NT_STATUS_UNSUCCESSFUL
;
385 talloc_free(tmp_ctx
);
389 #define SHARE_MOD_STRING(name, value) do { \
390 err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
391 if (err != LDB_SUCCESS) { \
392 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
393 ret = NT_STATUS_UNSUCCESSFUL; \
396 err = ldb_msg_add_string(msg, name, value); \
397 if (err != LDB_SUCCESS) { \
398 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
399 ret = NT_STATUS_UNSUCCESSFUL; \
403 #define SHARE_MOD_INT(name, value) do { \
404 err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
405 if (err != LDB_SUCCESS) { \
406 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
407 ret = NT_STATUS_UNSUCCESSFUL; \
410 err = ldb_msg_add_fmt(msg, name, "%d", value); \
411 if (err != LDB_SUCCESS) { \
412 DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \
413 ret = NT_STATUS_UNSUCCESSFUL; \
417 #define SHARE_MOD_BLOB(name, value) do { \
418 err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
419 if (err != LDB_SUCCESS) { \
420 DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
421 ret = NT_STATUS_UNSUCCESSFUL; \
424 err = ldb_msg_add_value(msg, name, value, NULL); \
425 if (err != LDB_SUCCESS) { \
426 DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \
427 ret = NT_STATUS_UNSUCCESSFUL; \
431 static NTSTATUS
sldb_set(struct share_context
*ctx
, const char *name
, struct share_info
*info
, int count
)
433 struct ldb_context
*ldb
;
434 struct ldb_message
*msg
;
437 bool do_rename
= false;
442 return NT_STATUS_INVALID_PARAMETER
;
445 tmp_ctx
= talloc_new(NULL
);
447 DEBUG(0,("ERROR: Out of memory!\n"));
448 return NT_STATUS_NO_MEMORY
;
451 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
453 msg
= ldb_msg_new(tmp_ctx
);
455 DEBUG(0,("ERROR: Out of memory!\n"));
456 ret
= NT_STATUS_NO_MEMORY
;
460 /* TODO: escape name */
461 msg
->dn
= ldb_dn_new_fmt(tmp_ctx
, ldb
, "CN=%s,CN=SHARES", name
);
463 DEBUG(0,("ERROR: Out of memory!\n"));
464 ret
= NT_STATUS_NO_MEMORY
;
468 for (i
= 0; i
< count
; i
++) {
469 if (strcasecmp(info
[i
].name
, SHARE_NAME
) == 0) {
470 if (strcasecmp(name
, (char *)info
[i
].value
) != 0) {
472 newname
= (char *)info
[i
].value
;
473 SHARE_MOD_STRING("cn", (char *)info
[i
].value
);
477 switch (info
[i
].type
) {
478 case SHARE_INFO_STRING
:
479 SHARE_MOD_STRING(info
[i
].name
, (char *)info
[i
].value
);
482 SHARE_MOD_INT(info
[i
].name
, *((int *)info
[i
].value
));
484 case SHARE_INFO_BLOB
:
485 SHARE_MOD_BLOB(info
[i
].name
, (DATA_BLOB
*)info
[i
].value
);
488 DEBUG(2,("ERROR: Invalid share info type for %s\n", info
[i
].name
));
489 ret
= NT_STATUS_INVALID_PARAMETER
;
495 struct ldb_dn
*olddn
, *newdn
;
499 /* TODO: escape newname */
500 newdn
= ldb_dn_new_fmt(tmp_ctx
, ldb
, "CN=%s,CN=SHARES", newname
);
502 DEBUG(0,("ERROR: Out of memory!\n"));
503 ret
= NT_STATUS_NO_MEMORY
;
507 err
= ldb_rename(ldb
, olddn
, newdn
);
508 if (err
!= LDB_SUCCESS
) {
509 DEBUG(2,("ERROR: unable to rename share %s (to %s)\n"
510 " err=%d [%s]\n", name
, newname
, err
, ldb_errstring(ldb
)));
511 if (err
== LDB_ERR_NO_SUCH_OBJECT
) {
512 ret
= NT_STATUS_OBJECT_NAME_COLLISION
;
514 ret
= NT_STATUS_UNSUCCESSFUL
;
522 err
= ldb_modify(ldb
, msg
);
523 if (err
!= LDB_SUCCESS
) {
524 DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
525 " err=%d [%s]\n", name
, err
, ldb_errstring(ldb
)));
526 if (err
== LDB_ERR_NO_SUCH_OBJECT
) {
527 ret
= NT_STATUS_OBJECT_NAME_COLLISION
;
529 ret
= NT_STATUS_UNSUCCESSFUL
;
536 talloc_free(tmp_ctx
);
540 static NTSTATUS
sldb_remove(struct share_context
*ctx
, const char *name
)
542 struct ldb_context
*ldb
;
548 tmp_ctx
= talloc_new(NULL
);
550 DEBUG(0,("ERROR: Out of memory!\n"));
551 return NT_STATUS_NO_MEMORY
;
554 ldb
= talloc_get_type(ctx
->priv_data
, struct ldb_context
);
556 dn
= ldb_dn_new_fmt(tmp_ctx
, ldb
, "CN=%s,CN=SHARES", name
);
558 DEBUG(0,("ERROR: Out of memory!\n"));
559 ret
= NT_STATUS_NO_MEMORY
;
563 err
= ldb_delete(ldb
, dn
);
564 if (err
!= LDB_SUCCESS
) {
565 DEBUG(2,("ERROR: unable to remove share %s from share.ldb\n"
566 " err=%d [%s]\n", name
, err
, ldb_errstring(ldb
)));
567 ret
= NT_STATUS_UNSUCCESSFUL
;
573 talloc_free(tmp_ctx
);
577 static const struct share_ops ops
= {
580 .string_option
= sldb_string_option
,
581 .int_option
= sldb_int_option
,
582 .bool_option
= sldb_bool_option
,
583 .string_list_option
= sldb_string_list_option
,
584 .list_all
= sldb_list_all
,
585 .get_config
= sldb_get_config
,
586 .create
= sldb_create
,
588 .remove
= sldb_remove
591 NTSTATUS
share_ldb_init(void)
593 return share_register(&ops
);