From a8eec313549905724a8186a1a4c14480658e2967 Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Fri, 6 Jan 2006 21:04:32 +0000 Subject: r12746: An initial version of the kludge_acls module. This should be replaced with real ACLs, which tridge is working on. In the meantime, the rules are very simple: - SYSTEM and Administrators can read all. - Users and anonymous cannot read passwords, can read everything else - list of 'password' attributes is hard-coded Most of the difficult work in this was fighting with the C/js interface to add a system_session() all, as it still doesn't get on with me :-) Andrew Bartlett (This used to be commit be9d0cae8989429ef47a713d8f0a82f12966fc78) --- source4/dsdb/samdb/ldb_modules/config.mk | 13 ++ source4/dsdb/samdb/ldb_modules/kludge_acl.c | 210 ++++++++++++++++++++++++++++ source4/lib/ldb/common/ldb_modules.c | 1 + source4/lib/ldb/common/ldb_msg.c | 10 +- source4/scripting/ejs/smbcalls_auth.c | 17 +++ source4/scripting/ejs/smbcalls_ldb.c | 11 +- source4/setup/provision | 4 +- source4/setup/provision_init.ldif | 2 +- 8 files changed, 257 insertions(+), 11 deletions(-) create mode 100644 source4/dsdb/samdb/ldb_modules/kludge_acl.c diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index 7fc0522034..c53c7c1606 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -69,6 +69,19 @@ REQUIRED_SUBSYSTEMS = \ # End MODULE libldb_rootdse ################################################ +################################################ +# Start MODULE libldb_cludge_acl +[MODULE::libldb_kludge_acl] +SUBSYSTEM = LIBLDB +OUTPUT_TYPE = MERGEDOBJ +OBJ_FILES = \ + kludge_acl.o +REQUIRED_SUBSYSTEMS = \ + LIB_SECURITY +# +# End MODULE libldb_rootdse +################################################ + ################################################ # Start MODULE libldb_extended_dn [MODULE::libldb_extended_dn] diff --git a/source4/dsdb/samdb/ldb_modules/kludge_acl.c b/source4/dsdb/samdb/ldb_modules/kludge_acl.c new file mode 100644 index 0000000000..d2fd96267d --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/kludge_acl.c @@ -0,0 +1,210 @@ +/* + ldb database library + + Copyright (C) Andrew Bartlett 2005 + + 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 kludge ACL module + * + * Description: Simple module to enforce a simple form of access + * control, sufficient for securing a default Samba4 + * installation. + * + * Author: Andrew Bartlett + */ + +#include "includes.h" +#include "ldb/include/ldb.h" +#include "ldb/include/ldb_errors.h" +#include "ldb/include/ldb_private.h" +#include "auth/auth.h" + +/* Kludge ACL rules: + * + * - System can read passwords + * - Administrators can write anything + * - Users can read anything that is not a password + * + */ + +const char *password_attribs[] = { + "sambaPassword", + "ntPwdHash", + "sambaNTPwdHistory", + "lmPwdHash", + "sambaLMPwdHistory", + "krb5key" +}; + +enum user_is { + ANONYMOUS, + USER, + ADMINISTRATOR, + SYSTEM +}; + +struct private_data { + + char *some_private_data; +}; + +static enum user_is what_is_user(struct ldb_module *module) +{ + struct auth_session_info *session_info + = ldb_get_opaque(module->ldb, "sessionInfo"); + if (!session_info) { + return ANONYMOUS; + } + + if (is_system_token(session_info->security_token)) { + return SYSTEM; + } + + if (is_administrator_token(session_info->security_token)) { + return SYSTEM; + } + if (is_authenticated_token(session_info->security_token)) { + return USER; + } + if (is_anonymous_token(session_info->security_token)) { + return ANONYMOUS; + } + return ANONYMOUS; +} + +/* search */ +static int kludge_acl_search(struct ldb_module *module, struct ldb_request *req) +{ + enum user_is user_type; + int ret = ldb_next_request(module, req); + struct ldb_message *msg; + int i, j; + + if (ret != LDB_SUCCESS) { + return ret; + } + + user_type = what_is_user(module); + switch (user_type) { + case SYSTEM: + case ADMINISTRATOR: + return ret; + default: + /* For every message, remove password attributes */ + for (i=0; i < req->op.search.res->count; i++) { + msg = req->op.search.res->msgs[i]; + for (j=0; j < ARRAY_SIZE(password_attribs); j++) { + ldb_msg_remove_attr(msg, password_attribs[j]); + } + } + } + return ret; +} + +/* ANY change type */ +static int kludge_acl_change(struct ldb_module *module, struct ldb_request *req){ + enum user_is user_type = what_is_user(module); + switch (user_type) { + case SYSTEM: + case ADMINISTRATOR: + return ldb_next_request(module, req); + default: + ldb_set_errstring(module, + talloc_asprintf(req, "kludge_acl_change: " + "attempted database modify not permitted. User is not SYSTEM or an administrator")); + return LDB_ERR_INSUFFICIENT_ACCESS_RIGHTS; + } +} + +/* start a transaction */ +static int kludge_acl_start_trans(struct ldb_module *module) +{ + return ldb_next_start_trans(module); +} + +/* end a transaction */ +static int kludge_acl_end_trans(struct ldb_module *module) +{ + return ldb_next_end_trans(module); +} + +/* delete a transaction */ +static int kludge_acl_del_trans(struct ldb_module *module) +{ + return ldb_next_del_trans(module); +} + +static int kludge_acl_destructor(void *module_ctx) +{ + struct ldb_module *ctx = talloc_get_type(module_ctx, struct ldb_module); + struct private_data *data = talloc_get_type(ctx->private_data, struct private_data); + /* put your clean-up functions here */ + if (data->some_private_data) talloc_free(data->some_private_data); + return 0; +} + +static int kludge_acl_request(struct ldb_module *module, struct ldb_request *req) +{ + switch (req->operation) { + + case LDB_REQ_SEARCH: + return kludge_acl_search(module, req); + case LDB_REQ_REGISTER: + return ldb_next_request(module, req); + default: + /* anything else must be a change of some kind */ + return kludge_acl_change(module, req); + } +} + +static const struct ldb_module_ops kludge_acl_ops = { + .name = "kludge_acl", + .request = kludge_acl_request, + .start_transaction = kludge_acl_start_trans, + .end_transaction = kludge_acl_end_trans, + .del_transaction = kludge_acl_del_trans, +}; + +struct ldb_module *kludge_acl_module_init(struct ldb_context *ldb, const char *options[]) +{ + struct ldb_module *ctx; + struct private_data *data; + + ctx = talloc(ldb, struct ldb_module); + if (!ctx) + return NULL; + + data = talloc(ctx, struct private_data); + if (data == NULL) { + talloc_free(ctx); + return NULL; + } + + data->some_private_data = NULL; + ctx->private_data = data; + + ctx->ldb = ldb; + ctx->prev = ctx->next = NULL; + ctx->ops = &kludge_acl_ops; + + talloc_set_destructor (ctx, kludge_acl_destructor); + + return ctx; +} diff --git a/source4/lib/ldb/common/ldb_modules.c b/source4/lib/ldb/common/ldb_modules.c index 715112a628..f83f0b06ef 100644 --- a/source4/lib/ldb/common/ldb_modules.c +++ b/source4/lib/ldb/common/ldb_modules.c @@ -141,6 +141,7 @@ int ldb_load_modules(struct ldb_context *ldb, const char *options[]) { "rootdse", rootdse_module_init }, { "extended_dn", extended_dn_module_init }, { "password_hash", password_hash_module_init }, + { "kludge_acl", kludge_acl_module_init }, #endif { NULL, NULL } }; diff --git a/source4/lib/ldb/common/ldb_msg.c b/source4/lib/ldb/common/ldb_msg.c index 269599818c..deb32133c1 100644 --- a/source4/lib/ldb/common/ldb_msg.c +++ b/source4/lib/ldb/common/ldb_msg.c @@ -623,11 +623,13 @@ int ldb_msg_copy_attr(struct ldb_message *msg, const char *attr, const char *rep void ldb_msg_remove_attr(struct ldb_message *msg, const char *attr) { struct ldb_message_element *el = ldb_msg_find_element(msg, attr); - int n = (el - msg->elements); - if (n != msg->num_elements-1) { - memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el)); + if (el) { + int n = (el - msg->elements); + if (n != msg->num_elements-1) { + memmove(el, el+1, ((msg->num_elements-1) - n)*sizeof(*el)); + } + msg->num_elements--; } - msg->num_elements--; } /* diff --git a/source4/scripting/ejs/smbcalls_auth.c b/source4/scripting/ejs/smbcalls_auth.c index 8ef04bec97..3ec376f4fe 100644 --- a/source4/scripting/ejs/smbcalls_auth.c +++ b/source4/scripting/ejs/smbcalls_auth.c @@ -157,10 +157,27 @@ static int ejs_userAuth(MprVarHandle eid, int argc, struct MprVar **argv) return 0; } +/* + initialise credentials ejs object +*/ +static int ejs_system_session(MprVarHandle eid, int argc, struct MprVar **argv) +{ + struct MprVar *obj = mprInitObject(eid, "session_info", argc, argv); + struct auth_session_info *session_info = system_session(mprMemCtx()); + + if (session_info == NULL) { + return -1; + } + + mprSetPtrChild(obj, "session_info", session_info); + return 0; +} + /* setup C functions that be called from ejs */ void smb_setup_ejs_auth(void) { ejsDefineCFunction(-1, "userAuth", ejs_userAuth, NULL, MPR_VAR_SCRIPT_HANDLE); + ejsDefineCFunction(-1, "system_session", ejs_system_session, NULL, MPR_VAR_SCRIPT_HANDLE); } diff --git a/source4/scripting/ejs/smbcalls_ldb.c b/source4/scripting/ejs/smbcalls_ldb.c index 798747b36c..39698947d7 100644 --- a/source4/scripting/ejs/smbcalls_ldb.c +++ b/source4/scripting/ejs/smbcalls_ldb.c @@ -385,9 +385,9 @@ static int ejs_ldbModify(MprVarHandle eid, int argc, struct MprVar **argv) static int ejs_ldbConnect(MprVarHandle eid, int argc, char **argv) { struct ldb_context *ldb; - struct auth_session_info *session_info; + struct auth_session_info *session_info = NULL; struct cli_credentials *creds = NULL; - struct MprVar *credentials; + struct MprVar *credentials, *session; struct MprVar *this = mprGetProperty(ejsGetLocalObject(eid), "this", 0); const char *dbfile; @@ -397,13 +397,16 @@ static int ejs_ldbConnect(MprVarHandle eid, int argc, char **argv) return -1; } - session_info = mprGetThisPtr(eid, "session_info"); - credentials = mprGetProperty(this, "credentials", NULL); if (credentials) { creds = mprGetPtr(credentials, "creds"); } + session = mprGetProperty(this, "session_info", NULL); + if (session) { + session_info = mprGetPtr(session, "session_info"); + } + dbfile = argv[0]; ldb = ldb_wrap_connect(mprMemCtx(), dbfile, diff --git a/source4/setup/provision b/source4/setup/provision index 51e62016a8..6974afeec9 100755 --- a/source4/setup/provision +++ b/source4/setup/provision @@ -114,10 +114,10 @@ if (!provision_validate(subobj, message)) { } var creds = options.get_credentials(); +var system_session = system_session(); message("Provisioning for %s in realm %s\n", subobj.DOMAIN, subobj.REALM); message("Using administrator password: %s\n", subobj.ADMINPASS); -message("Credentials: %s\n", creds); -provision(subobj, message, blank, provision_default_paths(subobj), NULL, creds); +provision(subobj, message, blank, provision_default_paths(subobj), system_session, creds); message("All OK\n"); return 0; diff --git a/source4/setup/provision_init.ldif b/source4/setup/provision_init.ldif index 6d452a17e7..db532f3078 100644 --- a/source4/setup/provision_init.ldif +++ b/source4/setup/provision_init.ldif @@ -69,5 +69,5 @@ isSynchronized: TRUE #Add modules to the list to activate them by default #beware often order is important dn: @MODULES -@LIST: rootdse,paged_results,server_sort,extended_dn,samldb,password_hash,operational,objectguid,rdn_name,objectclass +@LIST: rootdse,kludge_acl,paged_results,server_sort,extended_dn,samldb,password_hash,operational,objectguid,rdn_name,objectclass -- cgit