From: Greg Hudson Date: Mon, 10 May 2010 22:42:04 +0000 (+0000) Subject: Add lockout-related performance tuning variables X-Git-Tag: krb5-1.9-beta1~242 X-Git-Url: http://git.tremily.us/?a=commitdiff_plain;h=6eacb6d5f29da306ea605a5efb00c0d01c3182b1;p=krb5.git Add lockout-related performance tuning variables The account lockout feature of krb5 1.8 came at a cost in database accesses for principals requiring preauth, even if lockout is not used. Add dbmodules variables disable_last_success and disable_lockout for the DB2 and LDAP back ends, allowing the admin to recover the lost performance at the cost of new functionality. (Unrelated documentation fix: document database_name as a DB2-specific dbmodules variable instead of the realm variable it used to be.) ticket: 6719 git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24003 dc483132-0cff-0310-8789-dd5450dbe970 --- diff --git a/doc/admin.texinfo b/doc/admin.texinfo index 1ec468518..7d2e79718 100644 --- a/doc/admin.texinfo +++ b/doc/admin.texinfo @@ -1051,6 +1051,23 @@ For each section, the following tags may be specified in the subsection: @itemx db_library This tag indicates the name of the loadable database library. The value should be @samp{db2} for DB2 database and @samp{kldap} for LDAP database. +@itemx database_name +This DB2-specific tag indicates the location of the database. The +default is @* @code{@value{DefaultDatabaseName}}. + +@itemx disable_last_success +If set to @code{true}, suppresses KDC updates to the ``Last successful +authentication'' field of principal entries requiring preauthentication. +Setting this flag may improve performance. (Principal entries which do +not require preauthentication never update the ``Last successful +authentication'' field.) + +@itemx disable_lockout +If set to @code{true}, suppresses KDC updates to the ``Last failed +authentication'' and ``Failed password attempts'' fields of principal +entries requiring preauthentication. Setting this flag may improve +performance, but also disables account lockout. + @itemx ldap_kerberos_container_dn This LDAP specific tag indicates the DN of the container object where the realm objects will be located. @@ -1481,10 +1498,6 @@ database. The default is @code{@value{DefaultAclFile}}. daemons @code{kadmind4} and @code{v5passwdd} use to authenticate to the database. The default is @code{@value{DefaultAdminKeytab}}. -@itemx database_name -(String.) Location of the Kerberos database for this realm. The -default is @* @code{@value{DefaultDatabaseName}}. - @itemx default_principal_expiration (Absolute time string.) Specifies the default expiration date of principals created in this realm. The default value for this tag is diff --git a/src/include/k5-int.h b/src/include/k5-int.h index 9a23a7e68..fc39acdc7 100644 --- a/src/include/k5-int.h +++ b/src/include/k5-int.h @@ -203,6 +203,8 @@ typedef INT64_TYPE krb5_int64; #define KRB5_CONF_DEFAULT_PRINCIPAL_EXPIRATION "default_principal_expiration" #define KRB5_CONF_DEFAULT_PRINCIPAL_FLAGS "default_principal_flags" #define KRB5_CONF_DICT_FILE "dict_file" +#define KRB5_CONF_DISABLE_LAST_SUCCESS "disable_last_success" +#define KRB5_CONF_DISABLE_LOCKOUT "disable_lockout" #define KRB5_CONF_DNS_LOOKUP_KDC "dns_lookup_kdc" #define KRB5_CONF_DNS_LOOKUP_REALM "dns_lookup_realm" #define KRB5_CONF_DNS_FALLBACK "dns_fallback" diff --git a/src/plugins/kdb/db2/kdb_db2.c b/src/plugins/kdb/db2/kdb_db2.c index 713ed7aac..9c73c12db 100644 --- a/src/plugins/kdb/db2/kdb_db2.c +++ b/src/plugins/kdb/db2/kdb_db2.c @@ -204,6 +204,7 @@ configure_context(krb5_context context, char *conf_section, char **db_args) krb5_db2_context *db_ctx; char **t_ptr, *opt = NULL, *val = NULL, *pval = NULL; profile_t profile = KRB5_DB_GET_PROFILE(context); + int bval; status = k5db2_init_context(context); if (status != 0) @@ -252,6 +253,18 @@ configure_context(krb5_context context, char *conf_section, char **db_args) db_ctx->db_name = strdup(pval); } + status = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section, + KRB5_CONF_DISABLE_LAST_SUCCESS, FALSE, &bval); + if (status != 0) + goto cleanup; + db_ctx->disable_last_success = bval; + + status = profile_get_boolean(profile, KDB_MODULE_SECTION, conf_section, + KRB5_CONF_DISABLE_LOCKOUT, FALSE, &bval); + if (status != 0) + goto cleanup; + db_ctx->disable_lockout = bval; + cleanup: free(opt); free(val); diff --git a/src/plugins/kdb/db2/kdb_db2.h b/src/plugins/kdb/db2/kdb_db2.h index 45958ee02..7b4fcf405 100644 --- a/src/plugins/kdb/db2/kdb_db2.h +++ b/src/plugins/kdb/db2/kdb_db2.h @@ -46,7 +46,9 @@ typedef struct _krb5_db2_context { krb5_keyblock *db_master_key; /* Master key of database */ krb5_keylist_node *db_master_key_list; /* Master key list of database */ osa_adb_policy_t policy_db; - krb5_boolean tempdb; + krb5_boolean tempdb; + krb5_boolean disable_last_success; + krb5_boolean disable_lockout; } krb5_db2_context; #define KRB5_DB2_MAX_RETRY 5 diff --git a/src/plugins/kdb/db2/lockout.c b/src/plugins/kdb/db2/lockout.c index 498c0dea6..ec22dce73 100644 --- a/src/plugins/kdb/db2/lockout.c +++ b/src/plugins/kdb/db2/lockout.c @@ -33,6 +33,7 @@ #include #include #include +#include "kdb5.h" #include "kdb_db2.h" /* @@ -120,6 +121,10 @@ krb5_db2_lockout_check_policy(krb5_context context, krb5_kvno max_fail = 0; krb5_deltat failcnt_interval = 0; krb5_deltat lockout_duration = 0; + krb5_db2_context *db_ctx = context->dal_handle->db_context; + + if (db_ctx->disable_lockout) + return 0; code = lookup_lockout_policy(context, entry, &max_fail, &failcnt_interval, @@ -144,6 +149,8 @@ krb5_db2_lockout_audit(krb5_context context, krb5_deltat failcnt_interval = 0; krb5_deltat lockout_duration = 0; int nentries = 1; + krb5_db2_context *db_ctx = context->dal_handle->db_context; + krb5_boolean need_update = FALSE; switch (status) { case 0: @@ -158,38 +165,43 @@ krb5_db2_lockout_audit(krb5_context context, return 0; } - code = lookup_lockout_policy(context, entry, &max_fail, - &failcnt_interval, - &lockout_duration); - if (code != 0) - return code; - - assert (!locked_check_p(context, stamp, max_fail, lockout_duration, entry)); + if (!db_ctx->disable_lockout) { + code = lookup_lockout_policy(context, entry, &max_fail, + &failcnt_interval, &lockout_duration); + if (code != 0) + return code; + } + /* Only mark the authentication as successful if the entry + * required preauthentication, otherwise we have no idea. */ if (status == 0 && (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)) { - /* - * Only mark the authentication as successful if the entry - * required preauthentication, otherwise we have no idea. - */ - entry->fail_auth_count = 0; - entry->last_success = stamp; - } else if (status == KRB5KDC_ERR_PREAUTH_FAILED || - status == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + if (!db_ctx->disable_lockout && entry->fail_auth_count != 0) { + entry->fail_auth_count = 0; + need_update = TRUE; + } + if (!db_ctx->disable_last_success) { + entry->last_success = stamp; + need_update = TRUE; + } + } else if (!db_ctx->disable_lockout && + (status == KRB5KDC_ERR_PREAUTH_FAILED || + status == KRB5KRB_AP_ERR_BAD_INTEGRITY)) { if (failcnt_interval != 0 && stamp > entry->last_failed + failcnt_interval) { - /* Reset fail_auth_count after failcnt_interval */ + /* Reset fail_auth_count after failcnt_interval. */ entry->fail_auth_count = 0; } entry->last_failed = stamp; entry->fail_auth_count++; - } else - return 0; /* nothing to do */ + need_update = TRUE; + } - code = krb5_db2_db_put_principal(context, entry, - &nentries, NULL); - if (code != 0) - return code; + if (need_update) { + code = krb5_db2_db_put_principal(context, entry, &nentries, NULL); + if (code != 0) + return code; + } return 0; } diff --git a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h index 2130f8bc0..95909f6be 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h +++ b/src/plugins/kdb/ldap/libkdb_ldap/kdb_ldap.h @@ -223,6 +223,8 @@ typedef struct _krb5_ldap_context { k5_mutex_t hndl_lock; krb5_ldap_krbcontainer_params *krbcontainer; krb5_ldap_realm_params *lrparams; + krb5_boolean disable_last_success; + krb5_boolean disable_lockout; krb5_context kcontext; /* to set the error code and message */ } krb5_ldap_context; diff --git a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c index 65ae88734..c3cb185d0 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/ldap_misc.c @@ -105,6 +105,37 @@ prof_get_integer_def(krb5_context ctx, const char *conf_section, return 0; } +/* Get integer or string values from the config section, falling back + to the default section, then to hard-coded values. */ +static errcode_t +prof_get_boolean_def(krb5_context ctx, const char *conf_section, + const char *name, krb5_boolean dfl, krb5_boolean *out) +{ + errcode_t err; + int out_temp = 0; + + err = profile_get_boolean(ctx->profile, KDB_MODULE_SECTION, conf_section, + name, -1, &out_temp); + if (err) { + krb5_set_error_message(ctx, err, "Error reading '%s' attribute: %s", + name, error_message(err)); + return err; + } + if (out_temp != -1) { + *out = out_temp; + return 0; + } + err = profile_get_boolean(ctx->profile, KDB_MODULE_DEF_SECTION, name, 0, + dfl, &out_temp); + if (err) { + krb5_set_error_message(ctx, err, "Error reading '%s' attribute: %s", + name, error_message(err)); + return err; + } + *out = out_temp; + return 0; +} + /* We don't have non-null defaults in any of our calls, so don't bother with the extra argument. */ static errcode_t @@ -309,6 +340,16 @@ krb5_ldap_read_server_params(krb5_context context, char *conf_section, } } + if ((st = prof_get_boolean_def(context, conf_section, + KRB5_CONF_DISABLE_LAST_SUCCESS, FALSE, + &ldap_context->disable_last_success))) + goto cleanup; + + if ((st = prof_get_boolean_def(context, conf_section, + KRB5_CONF_DISABLE_LOCKOUT, FALSE, + &ldap_context->disable_lockout))) + goto cleanup; + cleanup: return(st); } diff --git a/src/plugins/kdb/ldap/libkdb_ldap/lockout.c b/src/plugins/kdb/ldap/libkdb_ldap/lockout.c index 020c77a94..323963e8d 100644 --- a/src/plugins/kdb/ldap/libkdb_ldap/lockout.c +++ b/src/plugins/kdb/ldap/libkdb_ldap/lockout.c @@ -113,10 +113,16 @@ krb5_ldap_lockout_check_policy(krb5_context context, krb5_timestamp stamp) { krb5_error_code code; + kdb5_dal_handle *dal_handle; + krb5_ldap_context *ldap_context; krb5_kvno max_fail = 0; krb5_deltat failcnt_interval = 0; krb5_deltat lockout_duration = 0; + SETUP_CONTEXT(); + if (ldap_context->disable_lockout) + return 0; + code = lookup_lockout_policy(context, entry, &max_fail, &failcnt_interval, &lockout_duration); @@ -136,11 +142,15 @@ krb5_ldap_lockout_audit(krb5_context context, krb5_error_code status) { krb5_error_code code; + kdb5_dal_handle *dal_handle; + krb5_ldap_context *ldap_context; krb5_kvno max_fail = 0; krb5_deltat failcnt_interval = 0; krb5_deltat lockout_duration = 0; int nentries = 1; + SETUP_CONTEXT(); + switch (status) { case 0: case KRB5KDC_ERR_PREAUTH_FAILED: @@ -150,26 +160,32 @@ krb5_ldap_lockout_audit(krb5_context context, return 0; } - code = lookup_lockout_policy(context, entry, &max_fail, - &failcnt_interval, - &lockout_duration); - if (code != 0) - return code; + if (!ldap_context->disable_lockout) { + code = lookup_lockout_policy(context, entry, &max_fail, + &failcnt_interval, + &lockout_duration); + if (code != 0) + return code; + } entry->mask = 0; assert (!locked_check_p(context, stamp, max_fail, lockout_duration, entry)); + /* Only mark the authentication as successful if the entry + * required preauthentication, otherwise we have no idea. */ if (status == 0 && (entry->attributes & KRB5_KDB_REQUIRES_PRE_AUTH)) { - /* - * Only mark the authentication as successful if the entry - * required preauthentication, otherwise we have no idea. - */ - entry->fail_auth_count = 0; - entry->last_success = stamp; - entry->mask |= KADM5_FAIL_AUTH_COUNT | KADM5_LAST_SUCCESS; - } else if (status == KRB5KDC_ERR_PREAUTH_FAILED || - status == KRB5KRB_AP_ERR_BAD_INTEGRITY) { + if (!ldap_context->disable_lockout && entry->fail_auth_count != 0) { + entry->fail_auth_count = 0; + entry->mask |= KADM5_FAIL_AUTH_COUNT; + } + if (!ldap_context->disable_last_success) { + entry->last_success = stamp; + entry->mask |= KADM5_LAST_SUCCESS; + } + } else if (!ldap_context->disable_lockout && + (status == KRB5KDC_ERR_PREAUTH_FAILED || + status == KRB5KRB_AP_ERR_BAD_INTEGRITY)) { if (failcnt_interval != 0 && stamp > entry->last_failed + failcnt_interval) { /* Reset fail_auth_count after failcnt_interval */ @@ -182,8 +198,7 @@ krb5_ldap_lockout_audit(krb5_context context, } if (entry->mask) { - code = krb5_ldap_put_principal(context, entry, - &nentries, NULL); + code = krb5_ldap_put_principal(context, entry, &nentries, NULL); if (code != 0) return code; }