summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source4/lib/ldb/common/ldb_modules.c1
-rw-r--r--source4/nbt_server/config.mk10
-rw-r--r--source4/nbt_server/wins/wins_ldb.c137
-rw-r--r--source4/nbt_server/wins/winsdb.c83
-rw-r--r--source4/nbt_server/wins/winsdb.h13
-rw-r--r--source4/nbt_server/wins/winsserver.c2
-rw-r--r--source4/wrepl_server/wrepl_server.c2
7 files changed, 242 insertions, 6 deletions
diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c
index e336a58901..f49ccf5413 100644
--- a/source4/lib/ldb/common/ldb_modules.c
+++ b/source4/lib/ldb/common/ldb_modules.c
@@ -132,6 +132,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[])
{ "extended_dn", extended_dn_module_init },
{ "password_hash", password_hash_module_init },
{ "kludge_acl", kludge_acl_module_init },
+ { "wins_ldb", wins_ldb_module_init },
#endif
{ NULL, NULL }
};
diff --git a/source4/nbt_server/config.mk b/source4/nbt_server/config.mk
index 330eef6e81..4d5f90e9fb 100644
--- a/source4/nbt_server/config.mk
+++ b/source4/nbt_server/config.mk
@@ -13,6 +13,16 @@ REQUIRED_SUBSYSTEMS = \
#######################
#######################
+# Start MODULE libldb_wins_ldb
+[MODULE::libldb_wins_ldb]
+SUBSYSTEM = LIBLDB
+OUTPUT_TYPE = MERGEDOBJ
+OBJ_FILES = \
+ wins/wins_ldb.o
+# End MODULE libldb_wins_ldb
+#######################
+
+#######################
# Start SUBSYSTEM NBTD_WINS
[SUBSYSTEM::NBTD_WINS]
OBJ_FILES = \
diff --git a/source4/nbt_server/wins/wins_ldb.c b/source4/nbt_server/wins/wins_ldb.c
new file mode 100644
index 0000000000..7bf1fa9916
--- /dev/null
+++ b/source4/nbt_server/wins/wins_ldb.c
@@ -0,0 +1,137 @@
+/*
+ ldb database module
+
+ Copyright (C) Stefan Metzmacher 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
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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.
+*/
+
+/*
+ * Name: ldb
+ *
+ * Component: ldb winsdb module
+ *
+ * Description: verify winsdb records before they're written to disk
+ *
+ * Author: Stefan Metzmacher
+ */
+
+#include "includes.h"
+#include "nbt_server/nbt_server.h"
+#include "nbt_server/wins/winsdb.h"
+#include "lib/ldb/include/ldb.h"
+#include "lib/ldb/include/ldb_errors.h"
+#include "lib/ldb/include/ldb_private.h"
+
+/* add_record: do things with the sambaPassword attribute */
+static int wins_ldb_verify(struct ldb_module *module, struct ldb_request *req, const struct ldb_message *msg)
+{
+ struct winsdb_handle *h = talloc_get_type(ldb_get_opaque(module->ldb, "winsdb_handle"),
+ struct winsdb_handle);
+ char *error = NULL;
+
+ if (!h) {
+ error = talloc_strdup(module, "WINS_LDB: INTERNAL ERROR: no winsdb_handle present!");
+ ldb_debug(module->ldb, LDB_DEBUG_FATAL, "%s", error);
+ ldb_set_errstring(module, error);
+ return LDB_ERR_OTHER;
+ }
+
+ switch (h->caller) {
+ case WINSDB_HANDLE_CALLER_NBTD:
+ case WINSDB_HANDLE_CALLER_WREPL:
+ /* we trust our nbt and wrepl code ... */
+ return ldb_next_request(module, req);
+
+ case WINSDB_HANDLE_CALLER_ADMIN:
+ error = talloc_strdup(module, "WINS_LDB: TODO verify add/modify for WINSDB_HANDLE_CALLER_ADMIN");
+ ldb_debug(module->ldb, LDB_DEBUG_WARNING, "%s\n", error);
+ return ldb_next_request(module, req);
+ }
+
+ return LDB_ERR_OTHER;
+}
+
+static int wins_ldb_request(struct ldb_module *module, struct ldb_request *req)
+{
+ const struct ldb_message *msg = req->op.mod.message;
+
+ switch (req->operation) {
+ case LDB_REQ_ADD:
+ msg = req->op.add.message;
+ break;
+
+ case LDB_REQ_MODIFY:
+ msg = req->op.mod.message;
+ break;
+
+ default:
+ goto call_next;
+ }
+
+ if (ldb_dn_is_special(msg->dn)) goto call_next;
+
+ return wins_ldb_verify(module, req, msg);
+
+call_next:
+ return ldb_next_request(module, req);
+}
+
+static const struct ldb_module_ops wins_ldb_ops = {
+ .name = "wins_ldb",
+ .request = wins_ldb_request
+};
+
+
+/* the init function */
+struct ldb_module *wins_ldb_module_init(struct ldb_context *ldb, const char *options[])
+{
+ struct ldb_module *ctx;
+ struct winsdb_handle *h;
+ const char *owner;
+ int ret;
+
+ ctx = talloc(ldb, struct ldb_module);
+ if (!ctx) return NULL;
+
+ ctx->private_data = NULL;
+ ctx->ldb = ldb;
+ ctx->prev = ctx->next = NULL;
+ ctx->ops = &wins_ldb_ops;
+
+ owner = lp_parm_string(-1, "winsdb", "local_owner");
+ if (!owner) {
+ owner = iface_n_ip(0);
+ if (!owner) {
+ owner = "0.0.0.0";
+ }
+ }
+
+ h = talloc(ctx, struct winsdb_handle);
+ if (!h) goto failed;
+ h->ldb = ldb;
+ h->caller = WINSDB_HANDLE_CALLER_ADMIN;
+ h->local_owner = talloc_strdup(h, owner);
+ if (!h->local_owner) goto failed;
+
+ ret = ldb_set_opaque(ldb, "winsdb_handle", h);
+ if (ret != LDB_SUCCESS) goto failed;
+
+ return ctx;
+
+failed:
+ talloc_free(ctx);
+ return NULL;
+}
diff --git a/source4/nbt_server/wins/winsdb.c b/source4/nbt_server/wins/winsdb.c
index d2a47e8f7c..3e73d89fdd 100644
--- a/source4/nbt_server/wins/winsdb.c
+++ b/source4/nbt_server/wins/winsdb.c
@@ -27,7 +27,6 @@
#include "lib/ldb/include/ldb.h"
#include "lib/ldb/include/ldb_errors.h"
#include "system/time.h"
-#include "auth/auth.h"
uint64_t winsdb_get_maxVersion(struct winsdb_handle *h)
{
@@ -771,11 +770,78 @@ failed:
return NBT_RCODE_SVR;
}
-struct winsdb_handle *winsdb_connect(TALLOC_CTX *mem_ctx)
+static BOOL winsdb_check_or_add_module_list(struct winsdb_handle *h)
+{
+ int trans;
+ int ret;
+ struct ldb_dn *dn;
+ struct ldb_result *res = NULL;
+ struct ldb_message *msg = NULL;
+ TALLOC_CTX *tmp_ctx = talloc_new(h);
+ unsigned int flags = 0;
+
+ trans = ldb_transaction_start(h->ldb);
+ if (trans != LDB_SUCCESS) goto failed;
+
+ /* check if we have a special @MODULES record already */
+ dn = ldb_dn_explode(tmp_ctx, "@MODULES");
+ if (!dn) goto failed;
+
+ /* find the record in the WINS database */
+ ret = ldb_search(h->ldb, dn, LDB_SCOPE_BASE, NULL, NULL, &res);
+ if (ret != LDB_SUCCESS) goto failed;
+ talloc_steal(tmp_ctx, res);
+
+ if (res->count > 0) goto skip;
+
+ /* if there's no record, add one */
+ msg = ldb_msg_new(tmp_ctx);
+ if (!msg) goto failed;
+ msg->dn = dn;
+
+ ret = ldb_msg_add_string(msg, "@LIST", "wins_ldb");
+ if (ret != 0) goto failed;
+
+ ret = ldb_add(h->ldb, msg);
+ if (ret != 0) goto failed;
+
+ trans = ldb_transaction_commit(h->ldb);
+ if (trans != LDB_SUCCESS) goto failed;
+
+ /* close and reopen the database, with the modules */
+ trans = LDB_ERR_OTHER;
+ talloc_free(h->ldb);
+ h->ldb = NULL;
+
+ if (lp_parm_bool(-1,"winsdb", "nosync", False)) {
+ flags |= LDB_FLG_NOSYNC;
+ }
+
+ h->ldb = ldb_wrap_connect(h, lock_path(h, lp_wins_url()),
+ NULL, NULL, flags, NULL);
+ if (!h->ldb) goto failed;
+
+ talloc_free(tmp_ctx);
+ return True;
+
+skip:
+ if (trans == LDB_SUCCESS) ldb_transaction_cancel(h->ldb);
+ talloc_free(tmp_ctx);
+ return True;
+
+failed:
+ if (trans == LDB_SUCCESS) ldb_transaction_cancel(h->ldb);
+ talloc_free(tmp_ctx);
+ return False;
+}
+
+struct winsdb_handle *winsdb_connect(TALLOC_CTX *mem_ctx, enum winsdb_handle_caller caller)
{
struct winsdb_handle *h = NULL;
const char *owner;
unsigned int flags = 0;
+ BOOL ret;
+ int ldb_err;
h = talloc(mem_ctx, struct winsdb_handle);
if (!h) return NULL;
@@ -785,8 +851,10 @@ struct winsdb_handle *winsdb_connect(TALLOC_CTX *mem_ctx)
}
h->ldb = ldb_wrap_connect(h, lock_path(h, lp_wins_url()),
- system_session(h), NULL, flags, NULL);
- if (!h->ldb) goto failed;
+ NULL, NULL, flags, NULL);
+ if (!h->ldb) goto failed;
+
+ h->caller = caller;
owner = lp_parm_string(-1, "winsdb", "local_owner");
if (!owner) {
@@ -796,6 +864,13 @@ struct winsdb_handle *winsdb_connect(TALLOC_CTX *mem_ctx)
h->local_owner = talloc_strdup(h, owner);
if (!h->local_owner) goto failed;
+ /* make sure the module list is available and used */
+ ret = winsdb_check_or_add_module_list(h);
+ if (!ret) goto failed;
+
+ ldb_err = ldb_set_opaque(h->ldb, "winsdb_handle", h);
+ if (ldb_err != LDB_SUCCESS) goto failed;
+
return h;
failed:
talloc_free(h);
diff --git a/source4/nbt_server/wins/winsdb.h b/source4/nbt_server/wins/winsdb.h
index 6310966d87..47e11b4694 100644
--- a/source4/nbt_server/wins/winsdb.h
+++ b/source4/nbt_server/wins/winsdb.h
@@ -47,10 +47,23 @@ struct winsdb_record {
const char *registered_by;
};
+enum winsdb_handle_caller {
+ WINSDB_HANDLE_CALLER_ADMIN = 0,
+ WINSDB_HANDLE_CALLER_NBTD = 1,
+ WINSDB_HANDLE_CALLER_WREPL = 2
+};
+
struct winsdb_handle {
/* wins server database handle */
struct ldb_context *ldb;
+ /*
+ * the type of the caller, as we pass this to the
+ * 'wins_ldb' ldb module can decide if it needs to verify the
+ * the records before they're written to disk
+ */
+ enum winsdb_handle_caller caller;
+
/* local owner address */
const char *local_owner;
};
diff --git a/source4/nbt_server/wins/winsserver.c b/source4/nbt_server/wins/winsserver.c
index b5c008121b..7d3ab8294b 100644
--- a/source4/nbt_server/wins/winsserver.c
+++ b/source4/nbt_server/wins/winsserver.c
@@ -829,7 +829,7 @@ NTSTATUS nbtd_winsserver_init(struct nbtd_server *nbtsrv)
tmp = lp_parm_int(-1,"wreplsrv","tombstone_timeout", 1*24*60*60);
nbtsrv->winssrv->config.tombstone_timeout = tmp;
- nbtsrv->winssrv->wins_db = winsdb_connect(nbtsrv->winssrv);
+ nbtsrv->winssrv->wins_db = winsdb_connect(nbtsrv->winssrv, WINSDB_HANDLE_CALLER_NBTD);
if (!nbtsrv->winssrv->wins_db) {
return NT_STATUS_INTERNAL_DB_ERROR;
}
diff --git a/source4/wrepl_server/wrepl_server.c b/source4/wrepl_server/wrepl_server.c
index 60d6f3f36b..299f0648e6 100644
--- a/source4/wrepl_server/wrepl_server.c
+++ b/source4/wrepl_server/wrepl_server.c
@@ -69,7 +69,7 @@ failed:
*/
static NTSTATUS wreplsrv_open_winsdb(struct wreplsrv_service *service)
{
- service->wins_db = winsdb_connect(service);
+ service->wins_db = winsdb_connect(service, WINSDB_HANDLE_CALLER_WREPL);
if (!service->wins_db) {
return NT_STATUS_INTERNAL_DB_ERROR;
}