diff options
Diffstat (limited to 'source4/dsdb/samdb/ldb_modules')
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/config.mk | 16 | ||||
-rw-r--r-- | source4/dsdb/samdb/ldb_modules/update_keytab.c | 189 |
2 files changed, 203 insertions, 2 deletions
diff --git a/source4/dsdb/samdb/ldb_modules/config.mk b/source4/dsdb/samdb/ldb_modules/config.mk index 929d0bcead..b50e275ebf 100644 --- a/source4/dsdb/samdb/ldb_modules/config.mk +++ b/source4/dsdb/samdb/ldb_modules/config.mk @@ -133,8 +133,7 @@ OBJ_FILES = \ SUBSYSTEM = ldb INIT_FUNCTION = password_hash_module_init OBJ_FILES = password_hash.o -PUBLIC_DEPENDENCIES = HEIMDAL_KRB5 -PRIVATE_DEPENDENCIES = HEIMDAL_HDB_KEYS LIBTALLOC +PRIVATE_DEPENDENCIES = HEIMDAL_HDB_KEYS LIBTALLOC HEIMDAL_KRB5 # # End MODULE ldb_password_hash ################################################ @@ -212,3 +211,16 @@ OBJ_FILES = \ # End MODULE ldb_schema ################################################ +################################################ +# Start MODULE ldb_update_kt +[MODULE::ldb_update_kt] +SUBSYSTEM = ldb +PRIVATE_DEPENDENCIES = LIBTALLOC CREDENTIALS_KRB5 +#Also depends on credentials, but that would loop +INIT_FUNCTION = ldb_update_kt_init +OBJ_FILES = \ + update_keytab.o +# +# End MODULE ldb_update_kt +################################################ + diff --git a/source4/dsdb/samdb/ldb_modules/update_keytab.c b/source4/dsdb/samdb/ldb_modules/update_keytab.c new file mode 100644 index 0000000000..411f8c98ef --- /dev/null +++ b/source4/dsdb/samdb/ldb_modules/update_keytab.c @@ -0,0 +1,189 @@ +/* + ldb database library + + Copyright (C) Andrew Bartlett <abartlet@samba.org> 2007 + + 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 update_keytabs module + * + * Description: Update keytabs whenever their matching secret record changes + * + * Author: Andrew Bartlett + */ + +#include "includes.h" +#include "ldb/include/includes.h" +#include "auth/credentials/credentials.h" +#include "auth/credentials/credentials_krb5.h" +#include "system/kerberos.h" + +struct dn_list { + struct cli_credentials *creds; + struct dn_list *prev, *next; +}; + +struct update_kt_private { + struct dn_list *changed_dns; +}; + +static int add_modified(struct ldb_module *module, struct ldb_dn *dn, BOOL delete) { + struct update_kt_private *data = talloc_get_type(module->private_data, struct update_kt_private); + struct dn_list *item = talloc(data->changed_dns? (void *)data->changed_dns: (void *)data, struct dn_list); + char *filter; + NTSTATUS status; + if (!item) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + item->creds = cli_credentials_init(item); + if (!item->creds) { + DEBUG(1, ("cli_credentials_init failed!")); + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + cli_credentials_set_conf(item->creds); + filter = talloc_asprintf(item, "(&(&(objectClass=kerberosSecret)(&(privateKeytab=*)(|(secret=*)(ntPwdHash=*))))(dn=%s))", + ldb_dn_get_linearized(dn)); + status = cli_credentials_set_secrets(item->creds, module->ldb, NULL, filter); + talloc_free(filter); + if (NT_STATUS_IS_OK(status)) { + if (delete) { + /* Ensure we don't helpfully keep an old keytab entry */ + cli_credentials_set_kvno(item->creds, cli_credentials_get_kvno(item->creds)+2); + /* Wipe passwords */ + cli_credentials_set_nt_hash(item->creds, NULL, + CRED_SPECIFIED); + } + DLIST_ADD_END(data->changed_dns, item, struct dn_list *); + } + return LDB_SUCCESS; +} + +/* add */ +static int update_kt_add(struct ldb_module *module, struct ldb_request *req) +{ + int ret; + ret = ldb_next_request(module, req); + if (ret != LDB_SUCCESS) { + return ret; + } + return add_modified(module, req->op.add.message->dn, False); +} + +/* modify */ +static int update_kt_modify(struct ldb_module *module, struct ldb_request *req) +{ + int ret; + ret = ldb_next_request(module, req); + if (ret != LDB_SUCCESS) { + return ret; + } + return add_modified(module, req->op.mod.message->dn, False); +} + +/* delete */ +static int update_kt_delete(struct ldb_module *module, struct ldb_request *req) +{ + int ret; + /* Before we delete it, record the details */ + ret = add_modified(module, req->op.del.dn, True); + if (ret != LDB_SUCCESS) { + return ret; + } + return ldb_next_request(module, req); +} + +/* rename */ +static int update_kt_rename(struct ldb_module *module, struct ldb_request *req) +{ + int ret; + ret = ldb_next_request(module, req); + if (ret != LDB_SUCCESS) { + return ret; + } + return add_modified(module, req->op.rename.newdn, False); +} + +/* end a transaction */ +static int update_kt_end_trans(struct ldb_module *module) +{ + struct update_kt_private *data = talloc_get_type(module->private_data, struct update_kt_private); + + struct dn_list *p; + for (p=data->changed_dns; p; p = p->next) { + int kret; + kret = cli_credentials_update_keytab(p->creds); + if (kret != 0) { + talloc_free(data->changed_dns); + data->changed_dns = NULL; + ldb_asprintf_errstring(module->ldb, "Failed to update keytab: %s", error_message(kret)); + return LDB_ERR_OPERATIONS_ERROR; + } + } + + talloc_free(data->changed_dns); + data->changed_dns = NULL; + return ldb_next_end_trans(module); +} + +/* end a transaction */ +static int update_kt_del_trans(struct ldb_module *module) +{ + struct update_kt_private *data = talloc_get_type(module->private_data, struct update_kt_private); + + talloc_free(data->changed_dns); + data->changed_dns = NULL; + + return ldb_next_end_trans(module); +} + +static int update_kt_init(struct ldb_module *module) +{ + struct update_kt_private *data; + + data = talloc(module, struct update_kt_private); + if (data == NULL) { + ldb_oom(module->ldb); + return LDB_ERR_OPERATIONS_ERROR; + } + + module->private_data = data; + data->changed_dns = NULL; + + return ldb_next_init(module); +} + +static const struct ldb_module_ops update_kt_ops = { + .name = "update_keytab", + .init_context = update_kt_init, + .add = update_kt_add, + .modify = update_kt_modify, + .rename = update_kt_rename, + .del = update_kt_delete, + .end_transaction = update_kt_end_trans, + .del_transaction = update_kt_del_trans, +}; + +int ldb_update_kt_init(void) +{ + return ldb_register_module(&update_kt_ops); +} |