/*
Unix SMB/CIFS implementation.
- LDB based services configuration
+ LDB based shares configuration
Copyright (C) Simo Sorce 2006
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
-#include "ldb/include/ldb.h"
-#include "ldb/include/ldb_errors.h"
+#include <ldb.h>
+#include <ldb_errors.h>
#include "auth/auth.h"
-#include "db_wrap.h"
+#include "ldb_wrap.h"
#include "param/share.h"
+#include "param/param.h"
-static NTSTATUS sldb_init(TALLOC_CTX *mem_ctx, const struct share_ops *ops, struct share_context **ctx)
+NTSTATUS share_ldb_init(void);
+
+static NTSTATUS sldb_init(TALLOC_CTX *mem_ctx, const struct share_ops *ops,
+ struct tevent_context *ev_ctx,
+ struct loadparm_context *lp_ctx,
+ struct share_context **ctx)
{
struct ldb_context *sdb;
return NT_STATUS_NO_MEMORY;
}
- sdb = ldb_wrap_connect( *ctx,
- private_path(*ctx, "share.ldb"),
- system_session(*ctx),
- NULL, 0, NULL);
+ sdb = ldb_wrap_connect(*ctx, ev_ctx, lp_ctx,
+ lpcfg_private_path(*ctx, lp_ctx, "share.ldb"),
+ system_session(lp_ctx),
+ NULL, 0);
if (!sdb) {
talloc_free(*ctx);
return ret;
}
-static BOOL sldb_bool_option(struct share_config *scfg, const char *opt_name, BOOL defval)
+static bool sldb_bool_option(struct share_config *scfg, const char *opt_name, bool defval)
{
const char *val;
val = sldb_string_option(scfg, opt_name, NULL);
if (val == NULL) return defval;
- if (strcasecmp(val, "true") == 0) return True;
+ if (strcasecmp(val, "true") == 0) return true;
- return False;
+ return false;
}
static const char **sldb_string_list_option(TALLOC_CTX *mem_ctx, struct share_config *scfg, const char *opt_name)
ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
- ret = ldb_search(ldb, ldb_dn_explode(tmp_ctx, "CN=SHARES"), LDB_SCOPE_SUBTREE, "(name=*)", NULL, &res);
+ ret = ldb_search(ldb, tmp_ctx, &res, ldb_dn_new(tmp_ctx, ldb, "CN=SHARES"),
+ LDB_SCOPE_SUBTREE, NULL, "(name=*)");
if (ret != LDB_SUCCESS) {
talloc_free(tmp_ctx);
- return NT_STATUS_UNSUCCESSFUL;
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- talloc_steal(tmp_ctx, res);
n = talloc_array(mem_ctx, const char *, res->count);
if (!n) {
struct ldb_context *ldb;
struct ldb_result *res;
TALLOC_CTX *tmp_ctx;
- char *filter;
tmp_ctx = talloc_new(mem_ctx);
if (!tmp_ctx) {
ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
- filter = talloc_asprintf(tmp_ctx,"(name=%s)", name);
- if (!filter) {
- DEBUG(0,("ERROR: Out of memory!\n"));
+ ret = ldb_search(ldb, tmp_ctx, &res,
+ ldb_dn_new(tmp_ctx, ldb, "CN=SHARES"), LDB_SCOPE_SUBTREE, NULL,
+ "(name=%s)", name);
+ if (ret != LDB_SUCCESS || res->count > 1) {
talloc_free(tmp_ctx);
- return NT_STATUS_NO_MEMORY;
- }
- ret = ldb_search(ldb, ldb_dn_explode(tmp_ctx, "CN=SHARES"), LDB_SCOPE_SUBTREE, filter, NULL, &res);
- if (ret != LDB_SUCCESS || res->count != 1) {
+ return NT_STATUS_INTERNAL_DB_CORRUPTION;
+ } else if (res->count != 1) {
talloc_free(tmp_ctx);
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
}
- talloc_steal(tmp_ctx, res);
s = talloc(tmp_ctx, struct share_config);
if (!s) {
return NT_STATUS_OK;
}
-#define SHARE_ADD_STRING(type, data) do { \
- err = ldb_msg_add_string(msg, type, data); \
+#define SHARE_ADD_STRING(name, value) do { \
+ err = ldb_msg_add_string(msg, name, value); \
+ if (err != LDB_SUCCESS) { \
+ DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
+ ret = NT_STATUS_UNSUCCESSFUL; \
+ goto done; \
+ } } while(0)
+
+#define SHARE_ADD_INT(name, value) do { \
+ err = ldb_msg_add_fmt(msg, name, "%d", value); \
if (err != LDB_SUCCESS) { \
- DEBUG(2,("ERROR: unable to add share %s to ldb msg\n", type)); \
+ DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \
ret = NT_STATUS_UNSUCCESSFUL; \
goto done; \
} } while(0)
-NTSTATUS sldb_create(struct share_context *ctx, struct share_info *info)
+#define SHARE_ADD_BLOB(name, value) do { \
+ err = ldb_msg_add_value(msg, name, value, NULL); \
+ if (err != LDB_SUCCESS) { \
+ DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \
+ ret = NT_STATUS_UNSUCCESSFUL; \
+ goto done; \
+ } } while(0)
+
+static NTSTATUS sldb_create(struct share_context *ctx, const char *name, struct share_info *info, int count)
{
struct ldb_context *ldb;
struct ldb_message *msg;
TALLOC_CTX *tmp_ctx;
NTSTATUS ret;
- char *conns;
- int err;
-
- if (!info->name || !info->type || !info->path) {
+ int err, i, j;
+
+ for (i = 0, j = 0; i < count && j != 0x03; i++) {
+ if (strcasecmp(info[i].name, SHARE_TYPE) == 0) j |= 0x02;
+ if (strcasecmp(info[i].name, SHARE_PATH) == 0) j |= 0x01;
+ if (strcasecmp(info[i].name, SHARE_NAME) == 0) {
+ if (strcasecmp(name, (char *)info[i].value) != 0) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+ }
+ }
+ if (!name || j != 0x03) {
return NT_STATUS_INVALID_PARAMETER;
}
}
/* TODO: escape info->name */
- msg->dn = ldb_dn_string_compose(tmp_ctx, ldb_dn_new(tmp_ctx), "CN=%s,CN=SHARES", info->name);
+ msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
if (!msg->dn) {
DEBUG(0,("ERROR: Out of memory!\n"));
ret = NT_STATUS_NO_MEMORY;
goto done;
}
- SHARE_ADD_STRING("cn", info->name);
SHARE_ADD_STRING("objectClass", "top");
SHARE_ADD_STRING("objectClass", "share");
+ SHARE_ADD_STRING("cn", name);
+ SHARE_ADD_STRING(SHARE_NAME, name);
+
+ for (i = 0; i < count; i++) {
+ if (strcasecmp(info[i].name, SHARE_NAME) == 0) continue;
+
+ switch (info[i].type) {
+ case SHARE_INFO_STRING:
+ SHARE_ADD_STRING(info[i].name, (char *)info[i].value);
+ break;
+ case SHARE_INFO_INT:
+ SHARE_ADD_INT(info[i].name, *((int *)info[i].value));
+ break;
+ case SHARE_INFO_BLOB:
+ SHARE_ADD_BLOB(info[i].name, (DATA_BLOB *)info[i].value);
+ break;
+ default:
+ DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name));
+ ret = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+ }
+
+ /* TODO: Security Descriptor */
+
+ SHARE_ADD_STRING(SHARE_AVAILABLE, "true");
+ SHARE_ADD_STRING(SHARE_BROWSEABLE, "true");
+ SHARE_ADD_STRING(SHARE_READONLY, "false");
+ SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "unixuid");
+ SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "posix");
+
+ err = ldb_add(ldb, msg);
+ if (err != LDB_SUCCESS) {
+ DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
+ " err=%d [%s]\n", name, err, ldb_errstring(ldb)));
+ if (err == LDB_ERR_NO_SUCH_OBJECT) {
+ ret = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+ } else if (err == LDB_ERR_ENTRY_ALREADY_EXISTS) {
+ ret = NT_STATUS_OBJECT_NAME_COLLISION;
+ } else {
+ ret = NT_STATUS_UNSUCCESSFUL;
+ }
+ goto done;
+ }
+
+ ret = NT_STATUS_OK;
+done:
+ talloc_free(tmp_ctx);
+ return ret;
+}
+
+#define SHARE_MOD_STRING(name, value) do { \
+ err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
+ if (err != LDB_SUCCESS) { \
+ DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
+ ret = NT_STATUS_UNSUCCESSFUL; \
+ goto done; \
+ } \
+ err = ldb_msg_add_string(msg, name, value); \
+ if (err != LDB_SUCCESS) { \
+ DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
+ ret = NT_STATUS_UNSUCCESSFUL; \
+ goto done; \
+ } } while(0)
+
+#define SHARE_MOD_INT(name, value) do { \
+ err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
+ if (err != LDB_SUCCESS) { \
+ DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
+ ret = NT_STATUS_UNSUCCESSFUL; \
+ goto done; \
+ } \
+ err = ldb_msg_add_fmt(msg, name, "%d", value); \
+ if (err != LDB_SUCCESS) { \
+ DEBUG(2,("ERROR: unable to add integer share option %s to ldb msg\n", name)); \
+ ret = NT_STATUS_UNSUCCESSFUL; \
+ goto done; \
+ } } while(0)
+
+#define SHARE_MOD_BLOB(name, value) do { \
+ err = ldb_msg_add_empty(msg, name, LDB_FLAG_MOD_REPLACE, NULL); \
+ if (err != LDB_SUCCESS) { \
+ DEBUG(2,("ERROR: unable to add string share option %s to ldb msg\n", name)); \
+ ret = NT_STATUS_UNSUCCESSFUL; \
+ goto done; \
+ } \
+ err = ldb_msg_add_value(msg, name, value, NULL); \
+ if (err != LDB_SUCCESS) { \
+ DEBUG(2,("ERROR: unable to add blob share option %s to ldb msg\n", name)); \
+ ret = NT_STATUS_UNSUCCESSFUL; \
+ goto done; \
+ } } while(0)
- SHARE_ADD_STRING(SHARE_NAME, info->name);
- SHARE_ADD_STRING(SHARE_TYPE, info->type);
- SHARE_ADD_STRING(SHARE_PATH, info->path);
- if (strcmp(info->type, "DISK") == 0) {
- SHARE_ADD_STRING(SHARE_NTVFS_HANDLER, "default");
+static NTSTATUS sldb_set(struct share_context *ctx, const char *name, struct share_info *info, int count)
+{
+ struct ldb_context *ldb;
+ struct ldb_message *msg;
+ TALLOC_CTX *tmp_ctx;
+ NTSTATUS ret;
+ bool do_rename = false;
+ char *newname;
+ int err, i;
+
+ if (!name) {
+ return NT_STATUS_INVALID_PARAMETER;
}
- if (info->comment) {
- SHARE_ADD_STRING(SHARE_COMMENT, info->comment);
+
+ tmp_ctx = talloc_new(NULL);
+ if (!tmp_ctx) {
+ DEBUG(0,("ERROR: Out of memory!\n"));
+ return NT_STATUS_NO_MEMORY;
}
- if (info->password) {
- SHARE_ADD_STRING(SHARE_PASSWORD, info->password);
+ ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
+
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) {
+ DEBUG(0,("ERROR: Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
}
- /* TODO: Security Descriptor */
+ /* TODO: escape name */
+ msg->dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
+ if (!msg->dn) {
+ DEBUG(0,("ERROR: Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
- SHARE_ADD_STRING(SHARE_AVAILABLE, "True");
- SHARE_ADD_STRING(SHARE_BROWSEABLE, "True");
- SHARE_ADD_STRING(SHARE_READONLY, "False");
- conns = talloc_asprintf(tmp_ctx, "%d", info->max_users);
- SHARE_ADD_STRING(SHARE_MAX_CONNECTIONS, conns);
+ for (i = 0; i < count; i++) {
+ if (strcasecmp(info[i].name, SHARE_NAME) == 0) {
+ if (strcasecmp(name, (char *)info[i].value) != 0) {
+ do_rename = true;
+ newname = (char *)info[i].value;
+ SHARE_MOD_STRING("cn", (char *)info[i].value);
+ }
+ }
- err = ldb_add(ldb, msg);
+ switch (info[i].type) {
+ case SHARE_INFO_STRING:
+ SHARE_MOD_STRING(info[i].name, (char *)info[i].value);
+ break;
+ case SHARE_INFO_INT:
+ SHARE_MOD_INT(info[i].name, *((int *)info[i].value));
+ break;
+ case SHARE_INFO_BLOB:
+ SHARE_MOD_BLOB(info[i].name, (DATA_BLOB *)info[i].value);
+ break;
+ default:
+ DEBUG(2,("ERROR: Invalid share info type for %s\n", info[i].name));
+ ret = NT_STATUS_INVALID_PARAMETER;
+ goto done;
+ }
+ }
+
+ if (do_rename) {
+ struct ldb_dn *olddn, *newdn;
+
+ olddn = msg->dn;
+
+ /* TODO: escape newname */
+ newdn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", newname);
+ if (!newdn) {
+ DEBUG(0,("ERROR: Out of memory!\n"));
+ ret = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+
+ err = ldb_rename(ldb, olddn, newdn);
+ if (err != LDB_SUCCESS) {
+ DEBUG(2,("ERROR: unable to rename share %s (to %s)\n"
+ " err=%d [%s]\n", name, newname, err, ldb_errstring(ldb)));
+ if (err == LDB_ERR_NO_SUCH_OBJECT) {
+ ret = NT_STATUS_OBJECT_NAME_COLLISION;
+ } else {
+ ret = NT_STATUS_UNSUCCESSFUL;
+ }
+ goto done;
+ }
+
+ msg->dn = newdn;
+ }
+
+ err = ldb_modify(ldb, msg);
if (err != LDB_SUCCESS) {
DEBUG(2,("ERROR: unable to add share %s to share.ldb\n"
- " err=%d [%s]\n", info->name, err, ldb_errstring(ldb)));
- ret = NT_STATUS_UNSUCCESSFUL;
+ " err=%d [%s]\n", name, err, ldb_errstring(ldb)));
+ if (err == LDB_ERR_NO_SUCH_OBJECT) {
+ ret = NT_STATUS_OBJECT_NAME_COLLISION;
+ } else {
+ ret = NT_STATUS_UNSUCCESSFUL;
+ }
goto done;
}
return ret;
}
-NTSTATUS sldb_remove(struct share_context *ctx, const char *name)
+static NTSTATUS sldb_remove(struct share_context *ctx, const char *name)
{
struct ldb_context *ldb;
struct ldb_dn *dn;
ldb = talloc_get_type(ctx->priv_data, struct ldb_context);
- dn = ldb_dn_string_compose(tmp_ctx, ldb_dn_new(tmp_ctx), "CN=%s,CN=SHARES", name);
+ dn = ldb_dn_new_fmt(tmp_ctx, ldb, "CN=%s,CN=SHARES", name);
if (!dn) {
DEBUG(0,("ERROR: Out of memory!\n"));
ret = NT_STATUS_NO_MEMORY;
return ret;
}
+static const struct share_ops ops = {
+ .name = "ldb",
+ .init = sldb_init,
+ .string_option = sldb_string_option,
+ .int_option = sldb_int_option,
+ .bool_option = sldb_bool_option,
+ .string_list_option = sldb_string_list_option,
+ .list_all = sldb_list_all,
+ .get_config = sldb_get_config,
+ .create = sldb_create,
+ .set = sldb_set,
+ .remove = sldb_remove
+};
+
NTSTATUS share_ldb_init(void)
{
- static struct share_ops ops = {
- .name = "ldb",
- .init = sldb_init,
- .string_option = sldb_string_option,
- .int_option = sldb_int_option,
- .bool_option = sldb_bool_option,
- .string_list_option = sldb_string_list_option,
- .list_all = sldb_list_all,
- .get_config = sldb_get_config,
- .create = sldb_create,
- .remove = sldb_remove
- };
-
return share_register(&ops);
}
-