1
0
mirror of https://github.com/samba-team/samba.git synced 2025-07-29 15:42:04 +03:00

r21135: Instead of having hooks to update keytabs as an explicit thing, update

them as a hook on ldb modify, via a module.

This should allow the secrets.ldb to be edited by the admin, and to
have things update in the on-disk keytab just as an in-memory keytab
would.

This isn't really a dsdb plugin, but I don't have any other good ideas
about where to put it.

Andrew Bartlett
(This used to be commit 6ce557a1af)
This commit is contained in:
Andrew Bartlett
2007-02-04 07:17:03 +00:00
committed by Gerald (Jerry) Carter
parent 627595b7a3
commit 744dddd75b
8 changed files with 242 additions and 115 deletions

View File

@ -349,8 +349,12 @@ BOOL cli_credentials_set_nt_hash(struct cli_credentials *cred,
{ {
if (obtained >= cred->password_obtained) { if (obtained >= cred->password_obtained) {
cli_credentials_set_password(cred, NULL, obtained); cli_credentials_set_password(cred, NULL, obtained);
cred->nt_hash = talloc(cred, struct samr_Password); if (nt_hash) {
*cred->nt_hash = *nt_hash; cred->nt_hash = talloc(cred, struct samr_Password);
*cred->nt_hash = *nt_hash;
} else {
cred->nt_hash = NULL;
}
return True; return True;
} }

View File

@ -169,12 +169,12 @@ BOOL cli_credentials_parse_file(struct cli_credentials *cred, const char *file,
* @retval NTSTATUS error detailing any failure * @retval NTSTATUS error detailing any failure
*/ */
NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred, NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
struct ldb_context *ldb,
const char *base, const char *base,
const char *filter) const char *filter)
{ {
TALLOC_CTX *mem_ctx; TALLOC_CTX *mem_ctx;
struct ldb_context *ldb;
int ldb_ret; int ldb_ret;
struct ldb_message **msgs; struct ldb_message **msgs;
const char *attrs[] = { const char *attrs[] = {
@ -209,13 +209,15 @@ NTSTATUS cli_credentials_set_secrets(struct cli_credentials *cred,
mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password"); mem_ctx = talloc_named(cred, 0, "cli_credentials fetch machine password");
/* Local secrets are stored in secrets.ldb */
ldb = secrets_db_connect(mem_ctx);
if (!ldb) { if (!ldb) {
/* set anonymous as the fallback, if the machine account won't work */ /* Local secrets are stored in secrets.ldb */
cli_credentials_set_anonymous(cred); ldb = secrets_db_connect(mem_ctx);
DEBUG(1, ("Could not open secrets.ldb\n")); if (!ldb) {
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; /* set anonymous as the fallback, if the machine account won't work */
cli_credentials_set_anonymous(cred);
DEBUG(1, ("Could not open secrets.ldb\n"));
return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
}
} }
/* search for the secret record */ /* search for the secret record */
@ -327,7 +329,7 @@ NTSTATUS cli_credentials_set_machine_account(struct cli_credentials *cred)
cred->machine_account_pending = False; cred->machine_account_pending = False;
filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER, filter = talloc_asprintf(cred, SECRETS_PRIMARY_DOMAIN_FILTER,
cli_credentials_get_domain(cred)); cli_credentials_get_domain(cred));
return cli_credentials_set_secrets(cred, SECRETS_PRIMARY_DOMAIN_DN, return cli_credentials_set_secrets(cred, NULL, SECRETS_PRIMARY_DOMAIN_DN,
filter); filter);
} }
@ -347,7 +349,7 @@ NTSTATUS cli_credentials_set_krbtgt(struct cli_credentials *cred)
filter = talloc_asprintf(cred, SECRETS_KRBTGT_SEARCH, filter = talloc_asprintf(cred, SECRETS_KRBTGT_SEARCH,
cli_credentials_get_realm(cred), cli_credentials_get_realm(cred),
cli_credentials_get_domain(cred)); cli_credentials_get_domain(cred));
return cli_credentials_set_secrets(cred, SECRETS_PRINCIPALS_DN, return cli_credentials_set_secrets(cred, NULL, SECRETS_PRINCIPALS_DN,
filter); filter);
} }
@ -369,7 +371,7 @@ NTSTATUS cli_credentials_set_stored_principal(struct cli_credentials *cred,
cli_credentials_get_realm(cred), cli_credentials_get_realm(cred),
cli_credentials_get_domain(cred), cli_credentials_get_domain(cred),
serviceprincipal); serviceprincipal);
return cli_credentials_set_secrets(cred, SECRETS_PRINCIPALS_DN, return cli_credentials_set_secrets(cred, NULL, SECRETS_PRINCIPALS_DN,
filter); filter);
} }
@ -388,66 +390,3 @@ void cli_credentials_set_machine_account_pending(struct cli_credentials *cred)
} }
NTSTATUS cli_credentials_update_all_keytabs(TALLOC_CTX *parent_ctx)
{
TALLOC_CTX *mem_ctx;
int ldb_ret;
struct ldb_context *ldb;
struct ldb_message **msgs;
const char *attrs[] = { NULL };
struct cli_credentials *creds;
const char *filter;
NTSTATUS status;
int i, ret;
mem_ctx = talloc_new(parent_ctx);
if (!mem_ctx) {
return NT_STATUS_NO_MEMORY;
}
/* Local secrets are stored in secrets.ldb */
ldb = secrets_db_connect(mem_ctx);
if (!ldb) {
DEBUG(1, ("Could not open secrets.ldb\n"));
talloc_free(mem_ctx);
return NT_STATUS_ACCESS_DENIED;
}
/* search for the secret record, but only of things we can
* actually update */
ldb_ret = gendb_search(ldb,
mem_ctx, NULL,
&msgs, attrs,
"(&(objectClass=kerberosSecret)(|(secret=*)(ntPwdHash=*)))");
if (ldb_ret == -1) {
DEBUG(1, ("Error looking for kerberos type secrets to push into a keytab:: %s", ldb_errstring(ldb)));
talloc_free(mem_ctx);
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
for (i=0; i < ldb_ret; i++) {
/* Make a credentials structure from it */
creds = cli_credentials_init(mem_ctx);
if (!creds) {
DEBUG(1, ("cli_credentials_init failed!"));
talloc_free(mem_ctx);
return NT_STATUS_NO_MEMORY;
}
cli_credentials_set_conf(creds);
filter = talloc_asprintf(mem_ctx, "dn=%s", ldb_dn_get_linearized(msgs[i]->dn));
status = cli_credentials_set_secrets(creds, NULL, filter);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to read secrets for keytab update for %s\n",
filter));
continue;
}
ret = cli_credentials_update_keytab(creds);
if (ret != 0) {
DEBUG(1, ("Failed to update keytab for %s\n",
filter));
continue;
}
}
return NT_STATUS_OK;
}

View File

@ -133,8 +133,7 @@ OBJ_FILES = \
SUBSYSTEM = ldb SUBSYSTEM = ldb
INIT_FUNCTION = password_hash_module_init INIT_FUNCTION = password_hash_module_init
OBJ_FILES = password_hash.o OBJ_FILES = password_hash.o
PUBLIC_DEPENDENCIES = HEIMDAL_KRB5 PRIVATE_DEPENDENCIES = HEIMDAL_HDB_KEYS LIBTALLOC HEIMDAL_KRB5
PRIVATE_DEPENDENCIES = HEIMDAL_HDB_KEYS LIBTALLOC
# #
# End MODULE ldb_password_hash # End MODULE ldb_password_hash
################################################ ################################################
@ -212,3 +211,16 @@ OBJ_FILES = \
# End MODULE ldb_schema # 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
################################################

View File

@ -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);
}

View File

@ -266,23 +266,11 @@ int ejs_credentials_cmdline(int eid, int argc, struct MprVar **argv)
return ejs_credentials_obj(obj, cmdline_credentials); return ejs_credentials_obj(obj, cmdline_credentials);
} }
static int ejs_credentials_update_all_keytabs(MprVarHandle eid, int argc, struct MprVar **argv)
{
if (!NT_STATUS_IS_OK(cli_credentials_update_all_keytabs(mprMemCtx()))) {
mpr_Return(eid, mprCreateBoolVar(False));
} else {
mpr_Return(eid, mprCreateBoolVar(True));
}
return 0;
}
/* /*
setup C functions that be called from ejs setup C functions that be called from ejs
*/ */
void smb_setup_ejs_credentials(void) void smb_setup_ejs_credentials(void)
{ {
ejsDefineCFunction(-1, "credentials_init", ejs_credentials_init, NULL, MPR_VAR_SCRIPT_HANDLE); ejsDefineCFunction(-1, "credentials_init", ejs_credentials_init, NULL, MPR_VAR_SCRIPT_HANDLE);
ejsDefineCFunction(-1, "credentials_update_all_keytabs", ejs_credentials_update_all_keytabs, NULL, MPR_VAR_SCRIPT_HANDLE);
} }

View File

@ -488,16 +488,14 @@ function provision_become_dc(subobj, message, paths, session_info)
assert(ok); assert(ok);
message("Setting up " + paths.secrets + "\n"); message("Setting up " + paths.secrets + "\n");
setup_ldb("secrets.ldif", info, paths.secrets); setup_ldb("secrets_init.ldif", info, paths.secrets);
setup_ldb("secrets.ldif", info, paths.secrets, false);
tmp = lp.get("secrets database"); tmp = lp.get("secrets database");
ok = lp.set("secrets database", paths.secrets); ok = lp.set("secrets database", paths.secrets);
assert(ok); assert(ok);
message("Setting up keytabs\n");
var keytab_ok = credentials_update_all_keytabs();
assert(keytab_ok);
ok = lp.set("secrets database", tmp); ok = lp.set("secrets database", tmp);
assert(ok); assert(ok);
@ -547,12 +545,9 @@ function provision(subobj, message, blank, paths, session_info, credentials, lda
setup_ldb("share.ldif", info, paths.shareconf); setup_ldb("share.ldif", info, paths.shareconf);
} }
message("Setting up secrets.ldb\n"); message("Setting up " + paths.secrets + "\n");
setup_ldb("secrets.ldif", info, paths.secrets); setup_ldb("secrets_init.ldif", info, paths.secrets);
setup_ldb("secrets.ldif", info, paths.secrets, false);
message("Setting up keytabs\n");
var keytab_ok = credentials_update_all_keytabs();
assert(keytab_ok);
message("Setting up hklm.ldb\n"); message("Setting up hklm.ldb\n");
setup_ldb("hklm.ldif", info, paths.hklm); setup_ldb("hklm.ldif", info, paths.hklm);

View File

@ -1,18 +1,3 @@
dn: @INDEXLIST
@IDXATTR: cn
@IDXATTR: flatname
@IDXATTR: realm
dn: @ATTRIBUTES
realm: CASE_INSENSITIVE
flatname: CASE_INSENSITIVE
sAMAccountName: CASE_INSENSITIVE
#Add modules to the list to activate them by default
#beware often order is important
dn: @MODULES
@LIST: operational
dn: CN=LSA Secrets dn: CN=LSA Secrets
objectClass: top objectClass: top
objectClass: container objectClass: container

View File

@ -0,0 +1,15 @@
dn: @INDEXLIST
@IDXATTR: cn
@IDXATTR: flatname
@IDXATTR: realm
dn: @ATTRIBUTES
realm: CASE_INSENSITIVE
flatname: CASE_INSENSITIVE
sAMAccountName: CASE_INSENSITIVE
#Add modules to the list to activate them by default
#beware often order is important
dn: @MODULES
@LIST: update_keytab,operational,objectguid