diff options
-rw-r--r-- | source4/lib/ldb/common/ldb_modules.c | 1 | ||||
-rw-r--r-- | source4/nbt_server/config.mk | 10 | ||||
-rw-r--r-- | source4/nbt_server/wins/wins_ldb.c | 137 | ||||
-rw-r--r-- | source4/nbt_server/wins/winsdb.c | 83 | ||||
-rw-r--r-- | source4/nbt_server/wins/winsdb.h | 13 | ||||
-rw-r--r-- | source4/nbt_server/wins/winsserver.c | 2 | ||||
-rw-r--r-- | source4/wrepl_server/wrepl_server.c | 2 |
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; } |