diff options
author | Greg Hudson <ghudson@mit.edu> | 2009-10-25 16:55:12 +0000 |
---|---|---|
committer | Greg Hudson <ghudson@mit.edu> | 2009-10-25 16:55:12 +0000 |
commit | 8d31a9d396f5bea88def4db395ad12dca2ac2e9f (patch) | |
tree | 244f8f5b525432a2a2a280403f38d7b2fbdc0dfd /src/plugins/kdb/db2/kdb_db2.c | |
parent | b82e46df9b6cbf663512985a99c6d79f2b0cb796 (diff) | |
download | krb5-8d31a9d396f5bea88def4db395ad12dca2ac2e9f.zip krb5-8d31a9d396f5bea88def4db395ad12dca2ac2e9f.tar.gz krb5-8d31a9d396f5bea88def4db395ad12dca2ac2e9f.tar.bz2 |
Account lockout
Merge Luke's users/lhoward/lockout2 branch to trunk. Implements
account lockout policies for preauth-using principals using existing
principal metadata fields and new policy fields. The kadmin API
version is bumped from 2 to 3 to compatibly extend the policy_ent_rec
structure.
ticket: 6577
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@23038 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/plugins/kdb/db2/kdb_db2.c')
-rw-r--r-- | src/plugins/kdb/db2/kdb_db2.c | 241 |
1 files changed, 206 insertions, 35 deletions
diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c index a947f2b..b987039 100644 --- a/src/plugins/kdb/db2/kdb_db2.c +++ b/src/plugins/kdb/db2/kdb_db2.c @@ -1,7 +1,7 @@ /* * lib/kdb/kdb_db2.c * - * Copyright 1997,2006,2007,2008 by the Massachusetts Institute of Technology. + * Copyright 1997,2006,2007-2009 by the Massachusetts Institute of Technology. * All Rights Reserved. * * Export of this software from the United States of America may @@ -68,8 +68,6 @@ #define KDB_DB2_DATABASE_NAME "database_name" -#include "kdb_db2.h" - static char *gen_dbsuffix(char *, char *); static krb5_error_code krb5_db2_db_start_update(krb5_context); @@ -774,7 +772,7 @@ destroy_file_suffix(char *dbname, char *suffix) char *filename; struct stat statb; int nb, fd; - unsigned int j; + int j; off_t pos; char buf[BUFSIZ]; char zbuf[BUFSIZ]; @@ -1315,6 +1313,9 @@ krb5_db2_open(krb5_context kcontext, else if (!opt && !strcmp(val, "temporary") ) { tempdb = 1; } + else if (!opt && !strcmp(val, "merge_nra")) { + ; + } /* ignore hash argument. Might have been passed from create */ else if (!opt || strcmp(opt, "hash")) { krb5_set_error_message(kcontext, EINVAL, @@ -1394,8 +1395,9 @@ krb5_db2_create(krb5_context kcontext, char *conf_section, char **db_args) } else if (!opt && !strcmp(val, "temporary")) { tempdb = 1; - } - else if (opt && !strcmp(opt, "hash")) { + } else if (!opt && !strcmp(val, "merge_nra")) { + ; + } else if (opt && !strcmp(opt, "hash")) { flags = KRB5_KDB_CREATE_HASH; } else { krb5_set_error_message(kcontext, EINVAL, @@ -1563,7 +1565,7 @@ krb5_db2_db_set_option(krb5_context kcontext, int option, void *value) krb5_db2_context *db_ctx; kdb5_dal_handle *dal_handle; - if (!k5db2_inited(kcontext)) + if (!k5db2_inited(kcontext)) return KRB5_KDB_DBNOTINITED; dal_handle = kcontext->dal_handle; @@ -1679,6 +1681,8 @@ krb5_db2_promote_db(krb5_context kcontext, char *conf_section, char **db_args) krb5_error_code status = 0; char *db_name = NULL; char *temp_db_name = NULL; + char **db_argp; + int merge_nra = 0; krb5_clear_error_message (kcontext); @@ -1699,7 +1703,14 @@ krb5_db2_promote_db(krb5_context kcontext, char *conf_section, char **db_args) goto clean_n_exit; } - status = krb5_db2_db_rename (kcontext, temp_db_name, db_name); + for (db_argp = db_args; *db_argp; db_argp++) { + if (!strcmp(*db_argp, "merge_nra")) { + merge_nra++; + break; + } + } + + status = krb5_db2_db_rename (kcontext, temp_db_name, db_name, merge_nra); if (status) goto clean_n_exit; @@ -1711,6 +1722,154 @@ clean_n_exit: return status; } +/* + * Merge non-replicated attributes from src into dst, setting + * changed to non-zero if dst was changed. + * + * Non-replicated attributes are: last_success, last_failed, + * fail_auth_count, and any negative TL data values. + */ +static krb5_error_code +krb5_db2_merge_principal(krb5_context kcontext, + krb5_db_entry *src, + krb5_db_entry *dst, + int *changed) +{ + *changed = 0; + + if (dst->last_success != src->last_success) { + dst->last_success = src->last_success; + (*changed)++; + } + + if (dst->last_failed != src->last_failed) { + dst->last_failed = src->last_failed; + (*changed)++; + } + + if (dst->fail_auth_count != src->fail_auth_count) { + dst->fail_auth_count = src->fail_auth_count; + (*changed)++; + } + + return 0; +} + +struct nra_context { + krb5_context kcontext; + krb5_db2_context *db_context; +}; + +/* + * Iteration callback merges non-replicated attributes from + * old database. + */ +static krb5_error_code +krb5_db2_merge_nra_iterator(krb5_pointer ptr, krb5_db_entry *entry) +{ + struct nra_context *nra = (struct nra_context *)ptr; + kdb5_dal_handle *dal_handle = nra->kcontext->dal_handle; + krb5_error_code retval; + int n_entries = 0, changed; + krb5_db_entry s_entry; + krb5_boolean more; + krb5_db2_context *dst_db; + + memset(&s_entry, 0, sizeof(s_entry)); + + dst_db = dal_handle->db_context; + dal_handle->db_context = nra->db_context; + + /* look up the new principal in the old DB */ + retval = krb5_db2_db_get_principal(nra->kcontext, + entry->princ, + &s_entry, + &n_entries, + &more); + if (retval != 0 || n_entries == 0) { + /* principal may be newly created, so ignore */ + dal_handle->db_context = dst_db; + return 0; + } + + /* merge non-replicated attributes from the old entry in */ + krb5_db2_merge_principal(nra->kcontext, &s_entry, entry, &changed); + + dal_handle->db_context = dst_db; + + /* if necessary, commit the modified new entry to the new DB */ + if (changed) { + retval = krb5_db2_db_put_principal(nra->kcontext, + entry, + &n_entries, + NULL); + } else { + retval = 0; + } + + return retval; +} + +/* + * Merge non-replicated attributes (that is, lockout-related + * attributes and negative TL data types) from the old database + * into the new one. + * + * Note: src_db is locked on success. + */ +static krb5_error_code +krb5_db2_begin_nra_merge(krb5_context kcontext, + krb5_db2_context *src_db, + krb5_db2_context *dst_db) +{ + krb5_error_code retval; + kdb5_dal_handle *dal_handle = kcontext->dal_handle; + struct nra_context nra; + + nra.kcontext = kcontext; + nra.db_context = dst_db; + + assert(dal_handle->db_context == dst_db); + dal_handle->db_context = src_db; + + retval = krb5_db2_db_lock(kcontext, KRB5_LOCKMODE_EXCLUSIVE); + if (retval) { + dal_handle->db_context = dst_db; + return retval; + } + + retval = krb5_db2_db_iterate_ext(kcontext, + krb5_db2_merge_nra_iterator, + &nra, + 0, + 0); + if (retval != 0) + (void) krb5_db2_db_unlock(kcontext); + + dal_handle->db_context = dst_db; + + return retval; +} + +/* + * Finish merge of non-replicated attributes by unlocking + * src_db. + */ +static krb5_error_code +krb5_db2_end_nra_merge(krb5_context kcontext, + krb5_db2_context *src_db, + krb5_db2_context *dst_db) +{ + krb5_error_code retval; + kdb5_dal_handle *dal_handle = kcontext->dal_handle; + + dal_handle->db_context = src_db; + retval = krb5_db2_db_unlock(kcontext); + dal_handle->db_context = dst_db; + + return retval; +} + /* Retrieved from pre-DAL code base. */ /* * "Atomically" rename the database in a way that locks out read @@ -1723,12 +1882,12 @@ clean_n_exit: * have to go through the same stuff that we went through up in db_destroy. */ krb5_error_code -krb5_db2_db_rename(context, from, to) +krb5_db2_db_rename(context, from, to, merge_nra) krb5_context context; char *from; char *to; + int merge_nra; { - DB *db; char *fromok; krb5_error_code retval; krb5_db2_context *s_context, *db_ctx; @@ -1745,13 +1904,10 @@ krb5_db2_db_rename(context, from, to) * files must exist because krb5_db2_db_lock, called below, * will fail otherwise. */ - db = k5db2_dbopen(db_ctx, to, O_RDWR|O_CREAT, 0600, 0); - if (db == NULL) { - retval = errno; + retval = krb5_db2_db_create(context, to, 0); + if (retval != 0 && retval != EEXIST) goto errout; - } - else - (*db->close)(db); + /* * Set the database to the target, so that other processes sharing * the target will stop their activity, and notice the new database. @@ -1764,25 +1920,6 @@ krb5_db2_db_rename(context, from, to) if (retval) goto errout; - { - /* Ugly brute force hack. - - Should be going through nice friendly helper routines for - this, but it's a mess of jumbled so-called interfaces right - now. */ - char policy[2048], new_policy[2048]; - assert (strlen(db_ctx->db_name) < 2000); - snprintf(policy, sizeof(policy), "%s.kadm5", db_ctx->db_name); - snprintf(new_policy, sizeof(new_policy), - "%s~.kadm5", db_ctx->db_name); - if (0 != rename(new_policy, policy)) { - retval = errno; - goto errout; - } - strlcat(new_policy, ".lock",sizeof(new_policy)); - (void) unlink(new_policy); - } - db_ctx->db_lf_name = gen_dbsuffix(db_ctx->db_name, KDB2_LOCK_EXT); if (db_ctx->db_lf_name == NULL) { retval = ENOMEM; @@ -1813,6 +1950,11 @@ krb5_db2_db_rename(context, from, to) if ((retval = krb5_db2_db_start_update(context))) goto errfromok; + if (merge_nra) { + if ((retval = krb5_db2_begin_nra_merge(context, s_context, db_ctx))) + goto errfromok; + } + if (rename(from, to)) { retval = errno; goto errfromok; @@ -1821,7 +1963,35 @@ krb5_db2_db_rename(context, from, to) retval = errno; goto errfromok; } + + if (merge_nra) { + krb5_db2_end_nra_merge(context, s_context, db_ctx); + } + retval = krb5_db2_db_end_update(context); + if (retval) + goto errfromok; + + { + /* XXX moved so that NRA merge works */ + /* Ugly brute force hack. + + Should be going through nice friendly helper routines for + this, but it's a mess of jumbled so-called interfaces right + now. */ + char policy[2048], new_policy[2048]; + assert (strlen(db_ctx->db_name) < 2000); + snprintf(policy, sizeof(policy), "%s.kadm5", db_ctx->db_name); + snprintf(new_policy, sizeof(new_policy), + "%s~.kadm5", db_ctx->db_name); + if (0 != rename(new_policy, policy)) { + retval = errno; + goto errfromok; + } + strlcat(new_policy, ".lock",sizeof(new_policy)); + (void) unlink(new_policy); + } + errfromok: free_dbsuffix(fromok); errout: @@ -1839,3 +2009,4 @@ errout: return retval; } + |