mirror of
https://salsa.debian.org/freeipa-team/freeipa.git
synced 2025-02-25 18:55:28 -06:00
Periodically refresh global ipa-kdb configuration
Before this patch, ipa-kdb would load global configuration on startup and never update it. This means that if global configuration is changed, the KDC never receives the new configuration until it is restarted. This patch enables caching of the global configuration with a timeout of 60 seconds. https://fedorahosted.org/freeipa/ticket/4153 Reviewed-By: Alexander Bokovoy <abokovoy@redhat.com>
This commit is contained in:
committed by
Martin Kosek
parent
49e83256b4
commit
8b2f4443dc
@@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#include "ipa_kdb.h"
|
#include "ipa_kdb.h"
|
||||||
|
|
||||||
|
#define IPADB_GLOBAL_CONFIG_CACHE_TIME 60
|
||||||
|
|
||||||
struct ipadb_context *ipadb_get_context(krb5_context kcontext)
|
struct ipadb_context *ipadb_get_context(krb5_context kcontext)
|
||||||
{
|
{
|
||||||
void *db_ctx;
|
void *db_ctx;
|
||||||
@@ -41,6 +43,7 @@ struct ipadb_context *ipadb_get_context(krb5_context kcontext)
|
|||||||
static void ipadb_context_free(krb5_context kcontext,
|
static void ipadb_context_free(krb5_context kcontext,
|
||||||
struct ipadb_context **ctx)
|
struct ipadb_context **ctx)
|
||||||
{
|
{
|
||||||
|
struct ipadb_global_config *cfg;
|
||||||
size_t c;
|
size_t c;
|
||||||
|
|
||||||
if (*ctx != NULL) {
|
if (*ctx != NULL) {
|
||||||
@@ -56,10 +59,11 @@ static void ipadb_context_free(krb5_context kcontext,
|
|||||||
ipadb_mspac_struct_free(&(*ctx)->mspac);
|
ipadb_mspac_struct_free(&(*ctx)->mspac);
|
||||||
krb5_free_default_realm(kcontext, (*ctx)->realm);
|
krb5_free_default_realm(kcontext, (*ctx)->realm);
|
||||||
|
|
||||||
for (c = 0; (*ctx)->authz_data && (*ctx)->authz_data[c]; c++) {
|
cfg = &(*ctx)->config;
|
||||||
free((*ctx)->authz_data[c]);
|
for (c = 0; cfg->authz_data && cfg->authz_data[c]; c++) {
|
||||||
|
free(cfg->authz_data[c]);
|
||||||
}
|
}
|
||||||
free((*ctx)->authz_data);
|
free(cfg->authz_data);
|
||||||
|
|
||||||
free(*ctx);
|
free(*ctx);
|
||||||
*ctx = NULL;
|
*ctx = NULL;
|
||||||
@@ -209,7 +213,7 @@ void ipadb_parse_user_auth(LDAP *lcontext, LDAPMessage *le,
|
|||||||
ldap_value_free_len(vals);
|
ldap_value_free_len(vals);
|
||||||
}
|
}
|
||||||
|
|
||||||
int ipadb_get_global_configs(struct ipadb_context *ipactx)
|
static int ipadb_load_global_config(struct ipadb_context *ipactx)
|
||||||
{
|
{
|
||||||
char *attrs[] = { "ipaConfigString", IPA_KRB_AUTHZ_DATA_ATTR,
|
char *attrs[] = { "ipaConfigString", IPA_KRB_AUTHZ_DATA_ATTR,
|
||||||
IPA_USER_AUTH_TYPE, NULL };
|
IPA_USER_AUTH_TYPE, NULL };
|
||||||
@@ -217,7 +221,6 @@ int ipadb_get_global_configs(struct ipadb_context *ipactx)
|
|||||||
LDAPMessage *res = NULL;
|
LDAPMessage *res = NULL;
|
||||||
LDAPMessage *first;
|
LDAPMessage *first;
|
||||||
char *base = NULL;
|
char *base = NULL;
|
||||||
int i;
|
|
||||||
int ret;
|
int ret;
|
||||||
char **authz_data_list;
|
char **authz_data_list;
|
||||||
|
|
||||||
@@ -241,45 +244,44 @@ int ipadb_get_global_configs(struct ipadb_context *ipactx)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Check for permitted authentication types. */
|
/* Check for permitted authentication types. */
|
||||||
ipadb_parse_user_auth(ipactx->lcontext, res, &ipactx->user_auth);
|
ipadb_parse_user_auth(ipactx->lcontext, res, &ipactx->config.user_auth);
|
||||||
|
|
||||||
vals = ldap_get_values_len(ipactx->lcontext, first,
|
/* Load config strings. */
|
||||||
"ipaConfigString");
|
vals = ldap_get_values_len(ipactx->lcontext, first, "ipaConfigString");
|
||||||
if (!vals || !vals[0]) {
|
if (vals) {
|
||||||
/* no config, set nothing */
|
ipactx->config.disable_last_success = false;
|
||||||
ret = 0;
|
ipactx->config.disable_lockout = false;
|
||||||
goto done;
|
for (int i = 0; vals[i]; i++) {
|
||||||
}
|
|
||||||
|
|
||||||
for (i = 0; vals[i]; i++) {
|
|
||||||
if (strncasecmp("KDC:Disable Last Success",
|
if (strncasecmp("KDC:Disable Last Success",
|
||||||
vals[i]->bv_val, vals[i]->bv_len) == 0) {
|
vals[i]->bv_val, vals[i]->bv_len) == 0) {
|
||||||
ipactx->disable_last_success = true;
|
ipactx->config.disable_last_success = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (strncasecmp("KDC:Disable Lockout",
|
if (strncasecmp("KDC:Disable Lockout",
|
||||||
vals[i]->bv_val, vals[i]->bv_len) == 0) {
|
vals[i]->bv_val, vals[i]->bv_len) == 0) {
|
||||||
ipactx->disable_lockout = true;
|
ipactx->config.disable_lockout = true;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Load authz data. */
|
||||||
ret = ipadb_ldap_attr_to_strlist(ipactx->lcontext, first,
|
ret = ipadb_ldap_attr_to_strlist(ipactx->lcontext, first,
|
||||||
IPA_KRB_AUTHZ_DATA_ATTR, &authz_data_list);
|
IPA_KRB_AUTHZ_DATA_ATTR, &authz_data_list);
|
||||||
if (ret != 0 && ret != ENOENT) {
|
|
||||||
goto done;
|
|
||||||
}
|
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
if (ipactx->authz_data != NULL) {
|
if (ipactx->config.authz_data != NULL) {
|
||||||
for (i = 0; ipactx->authz_data[i]; i++) {
|
for (int i = 0; ipactx->config.authz_data[i]; i++)
|
||||||
free(ipactx->authz_data[i]);
|
free(ipactx->config.authz_data[i]);
|
||||||
}
|
free(ipactx->config.authz_data);
|
||||||
free(ipactx->authz_data);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ipactx->authz_data = authz_data_list;
|
ipactx->config.authz_data = authz_data_list;
|
||||||
}
|
} else if (ret != ENOENT)
|
||||||
|
goto done;
|
||||||
|
|
||||||
|
/* Success! */
|
||||||
|
ipactx->config.last_update = time(NULL);
|
||||||
ret = 0;
|
ret = 0;
|
||||||
|
|
||||||
done:
|
done:
|
||||||
@@ -289,6 +291,18 @@ done:
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const struct ipadb_global_config *
|
||||||
|
ipadb_get_global_config(struct ipadb_context *ipactx)
|
||||||
|
{
|
||||||
|
time_t now = 0;
|
||||||
|
|
||||||
|
if (time(&now) != (time_t)-1
|
||||||
|
&& now - ipactx->config.last_update > IPADB_GLOBAL_CONFIG_CACHE_TIME)
|
||||||
|
ipadb_load_global_config(ipactx);
|
||||||
|
|
||||||
|
return &ipactx->config;
|
||||||
|
}
|
||||||
|
|
||||||
int ipadb_get_connection(struct ipadb_context *ipactx)
|
int ipadb_get_connection(struct ipadb_context *ipactx)
|
||||||
{
|
{
|
||||||
struct berval **vals = NULL;
|
struct berval **vals = NULL;
|
||||||
@@ -390,7 +404,7 @@ int ipadb_get_connection(struct ipadb_context *ipactx)
|
|||||||
ipactx->n_supp_encs = n_kst;
|
ipactx->n_supp_encs = n_kst;
|
||||||
|
|
||||||
/* get additional options */
|
/* get additional options */
|
||||||
ret = ipadb_get_global_configs(ipactx);
|
ret = ipadb_load_global_config(ipactx);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -87,6 +87,14 @@ enum ipadb_user_auth {
|
|||||||
IPADB_USER_AUTH_OTP = 1 << 3,
|
IPADB_USER_AUTH_OTP = 1 << 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
struct ipadb_global_config {
|
||||||
|
time_t last_update;
|
||||||
|
bool disable_last_success;
|
||||||
|
bool disable_lockout;
|
||||||
|
char **authz_data;
|
||||||
|
enum ipadb_user_auth user_auth;
|
||||||
|
};
|
||||||
|
|
||||||
struct ipadb_context {
|
struct ipadb_context {
|
||||||
char *uri;
|
char *uri;
|
||||||
char *base;
|
char *base;
|
||||||
@@ -99,10 +107,9 @@ struct ipadb_context {
|
|||||||
krb5_key_salt_tuple *supp_encs;
|
krb5_key_salt_tuple *supp_encs;
|
||||||
int n_supp_encs;
|
int n_supp_encs;
|
||||||
struct ipadb_mspac *mspac;
|
struct ipadb_mspac *mspac;
|
||||||
bool disable_last_success;
|
|
||||||
bool disable_lockout;
|
/* Don't access this directly, use ipadb_get_global_config(). */
|
||||||
char **authz_data;
|
struct ipadb_global_config config;
|
||||||
enum ipadb_user_auth user_auth;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#define IPA_E_DATA_MAGIC 0x0eda7a
|
#define IPA_E_DATA_MAGIC 0x0eda7a
|
||||||
@@ -277,3 +284,5 @@ void ipadb_audit_as_req(krb5_context kcontext,
|
|||||||
/* AUTH METHODS */
|
/* AUTH METHODS */
|
||||||
void ipadb_parse_user_auth(LDAP *lcontext, LDAPMessage *le,
|
void ipadb_parse_user_auth(LDAP *lcontext, LDAPMessage *le,
|
||||||
enum ipadb_user_auth *user_auth);
|
enum ipadb_user_auth *user_auth);
|
||||||
|
const struct ipadb_global_config *
|
||||||
|
ipadb_get_global_config(struct ipadb_context *ipactx);
|
||||||
|
|||||||
@@ -30,6 +30,7 @@ void ipadb_audit_as_req(krb5_context kcontext,
|
|||||||
krb5_timestamp authtime,
|
krb5_timestamp authtime,
|
||||||
krb5_error_code error_code)
|
krb5_error_code error_code)
|
||||||
{
|
{
|
||||||
|
const struct ipadb_global_config *gcfg;
|
||||||
struct ipadb_context *ipactx;
|
struct ipadb_context *ipactx;
|
||||||
struct ipadb_e_data *ied;
|
struct ipadb_e_data *ied;
|
||||||
krb5_error_code kerr;
|
krb5_error_code kerr;
|
||||||
@@ -63,6 +64,10 @@ void ipadb_audit_as_req(krb5_context kcontext,
|
|||||||
|
|
||||||
client->mask = 0;
|
client->mask = 0;
|
||||||
|
|
||||||
|
gcfg = ipadb_get_global_config(ipactx);
|
||||||
|
if (gcfg == NULL)
|
||||||
|
return;
|
||||||
|
|
||||||
switch (error_code) {
|
switch (error_code) {
|
||||||
case 0:
|
case 0:
|
||||||
/* Check if preauth flag is specified (default), otherwise we have
|
/* Check if preauth flag is specified (default), otherwise we have
|
||||||
@@ -72,7 +77,7 @@ void ipadb_audit_as_req(krb5_context kcontext,
|
|||||||
client->fail_auth_count = 0;
|
client->fail_auth_count = 0;
|
||||||
client->mask |= KMASK_FAIL_AUTH_COUNT;
|
client->mask |= KMASK_FAIL_AUTH_COUNT;
|
||||||
}
|
}
|
||||||
if (ipactx->disable_last_success) {
|
if (gcfg->disable_last_success) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
client->last_success = authtime;
|
client->last_success = authtime;
|
||||||
@@ -83,7 +88,7 @@ void ipadb_audit_as_req(krb5_context kcontext,
|
|||||||
case KRB5KDC_ERR_PREAUTH_FAILED:
|
case KRB5KDC_ERR_PREAUTH_FAILED:
|
||||||
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
|
case KRB5KRB_AP_ERR_BAD_INTEGRITY:
|
||||||
|
|
||||||
if (ipactx->disable_lockout) {
|
if (gcfg->disable_lockout) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1878,6 +1878,9 @@ void get_authz_data_types(krb5_context context, krb5_db_entry *entry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (ied == NULL || ied->authz_data == NULL) {
|
if (ied == NULL || ied->authz_data == NULL) {
|
||||||
|
const struct ipadb_global_config *gcfg = NULL;
|
||||||
|
char **tmp = NULL;
|
||||||
|
|
||||||
if (context == NULL) {
|
if (context == NULL) {
|
||||||
krb5_klog_syslog(LOG_ERR, "Missing Kerberos context, no " \
|
krb5_klog_syslog(LOG_ERR, "Missing Kerberos context, no " \
|
||||||
"authorization data will be added.");
|
"authorization data will be added.");
|
||||||
@@ -1885,14 +1888,17 @@ void get_authz_data_types(krb5_context context, krb5_db_entry *entry,
|
|||||||
}
|
}
|
||||||
|
|
||||||
ipactx = ipadb_get_context(context);
|
ipactx = ipadb_get_context(context);
|
||||||
if (ipactx == NULL || ipactx->authz_data == NULL) {
|
gcfg = ipadb_get_global_config(ipactx);
|
||||||
|
if (gcfg != NULL)
|
||||||
|
tmp = gcfg->authz_data;
|
||||||
|
if (ipactx == NULL || tmp == NULL) {
|
||||||
krb5_klog_syslog(LOG_ERR, "No default authorization data types " \
|
krb5_klog_syslog(LOG_ERR, "No default authorization data types " \
|
||||||
"available, no authorization data will " \
|
"available, no authorization data will " \
|
||||||
"be added.");
|
"be added.");
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
authz_data_list = ipactx->authz_data;
|
authz_data_list = tmp;
|
||||||
} else {
|
} else {
|
||||||
authz_data_list = ied->authz_data;
|
authz_data_list = ied->authz_data;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -320,18 +320,25 @@ static void ipadb_validate_password(struct ipadb_context *ipactx,
|
|||||||
static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
|
static enum ipadb_user_auth ipadb_get_user_auth(struct ipadb_context *ipactx,
|
||||||
LDAPMessage *lentry)
|
LDAPMessage *lentry)
|
||||||
{
|
{
|
||||||
|
enum ipadb_user_auth gua = IPADB_USER_AUTH_NONE;
|
||||||
enum ipadb_user_auth ua = IPADB_USER_AUTH_NONE;
|
enum ipadb_user_auth ua = IPADB_USER_AUTH_NONE;
|
||||||
|
const struct ipadb_global_config *gcfg = NULL;
|
||||||
|
|
||||||
/* Get the user's user_auth settings. */
|
/* Get the user's user_auth settings. */
|
||||||
ipadb_parse_user_auth(ipactx->lcontext, lentry, &ua);
|
ipadb_parse_user_auth(ipactx->lcontext, lentry, &ua);
|
||||||
|
|
||||||
|
/* Get the global user_auth settings. */
|
||||||
|
gcfg = ipadb_get_global_config(ipactx);
|
||||||
|
if (gcfg != NULL)
|
||||||
|
gua = gcfg->user_auth;
|
||||||
|
|
||||||
/* If the disabled flag is set, ignore everything else. */
|
/* If the disabled flag is set, ignore everything else. */
|
||||||
if ((ua | ipactx->user_auth) & IPADB_USER_AUTH_DISABLED)
|
if ((ua | gua) & IPADB_USER_AUTH_DISABLED)
|
||||||
return IPADB_USER_AUTH_DISABLED;
|
return IPADB_USER_AUTH_DISABLED;
|
||||||
|
|
||||||
/* Determine which user_auth policy is active: user or global. */
|
/* Determine which user_auth policy is active: user or global. */
|
||||||
if (ua == IPADB_USER_AUTH_NONE)
|
if (ua == IPADB_USER_AUTH_NONE)
|
||||||
ua = ipactx->user_auth;
|
ua = gua;
|
||||||
|
|
||||||
/* Perform flag validation. */
|
/* Perform flag validation. */
|
||||||
ipadb_validate_otp(ipactx, lentry, &ua);
|
ipadb_validate_otp(ipactx, lentry, &ua);
|
||||||
|
|||||||
Reference in New Issue
Block a user