summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--daemons/ipa-kdb/ipa_kdb.c26
-rw-r--r--daemons/ipa-kdb/ipa_kdb.h21
-rw-r--r--daemons/ipa-kdb/ipa_kdb_mkey.c148
-rw-r--r--daemons/ipa-kdb/ipa_kdb_passwords.c2
-rw-r--r--daemons/ipa-kdb/ipa_kdb_principals.c13
-rw-r--r--ipaserver/install/krbinstance.py7
6 files changed, 161 insertions, 56 deletions
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index fbcb03bee..7fc575b8f 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -43,7 +43,7 @@ struct ipadb_context *ipadb_get_context(krb5_context kcontext)
static void ipadb_context_free(krb5_context kcontext,
struct ipadb_context **ctx)
{
- struct ipadb_global_config *cfg;
+ struct ipadb_global_config *cfg;
size_t c;
if (*ctx != NULL) {
@@ -69,6 +69,7 @@ static void ipadb_context_free(krb5_context kcontext,
free(*ctx);
*ctx = NULL;
}
+ krb5_db_set_context(kcontext, NULL);
}
#define LDAPI_URI_PREFIX "ldapi://"
@@ -515,8 +516,13 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext,
/* only check for unsupported 'temporary' value for now */
for (i = 0; db_args != NULL && db_args[i] != NULL; i++) {
- if (strncmp(db_args[i], IPA_SETUP, sizeof(IPA_SETUP)) == 0) {
- ipactx->override_restrictions = true;
+ if (strncmp(db_args[i], IPA_OVERRIDE, sizeof(IPA_OVERRIDE)) == 0) {
+ ipactx->special_flags |= IPA_SPECIAL_OVERRIDE_RESTRICTION;
+ }
+
+ if (strncmp(db_args[i], IPA_SETUP_CREATE,
+ sizeof(IPA_SETUP_CREATE)) == 0) {
+ ipactx->special_flags |= IPA_SPECIAL_CREATE_STEP;
}
if (strncmp(db_args[i], "temporary", 9) == 0) {
@@ -578,6 +584,12 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext,
goto fail;
}
+ kerr = ipadb_check_master_key(ipactx);
+ if (kerr != 0) {
+ ret = ENOENT;
+ goto fail;
+ }
+
return 0;
fail:
@@ -600,7 +612,9 @@ static krb5_error_code ipadb_create(krb5_context kcontext,
char *conf_section,
char **db_args)
{
- return ipadb_init_module(kcontext, conf_section, db_args, 0);
+ char *setup_args[] = { IPA_OVERRIDE, IPA_SETUP_CREATE, NULL };
+
+ return ipadb_init_module(kcontext, conf_section, setup_args, 0);
}
static krb5_error_code ipadb_get_age(krb5_context kcontext,
@@ -650,9 +664,9 @@ kdb_vftabl kdb_function_table = {
ipadb_free_pwd_policy, /* free_policy */
ipadb_alloc, /* alloc */
ipadb_free, /* free */
- ipadb_fetch_master_key, /* fetch_master_key */
+ NULL, /* fetch_master_key */
NULL, /* fetch_master_key_list */
- ipadb_store_master_key_list, /* store_master_key_list */
+ NULL, /* store_master_key_list */
NULL, /* dbe_search_enctype */
ipadb_change_pwd, /* change_pwd */
NULL, /* promote_db */
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index 1fdb409df..a9d66ad2f 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -72,11 +72,15 @@
#define KMASK_TL_DATA 0x040000
#define KMASK_LOAD 0x200000
-#define IPA_SETUP "ipa-setup-override-restrictions"
+#define IPA_OVERRIDE "ipa-setup-override-restrictions"
+#define IPA_SETUP_CREATE "ipa-setup-create-step"
#define IPA_KRB_AUTHZ_DATA_ATTR "ipaKrbAuthzData"
#define IPA_USER_AUTH_TYPE "ipaUserAuthType"
+#define IPA_SPECIAL_OVERRIDE_RESTRICTION 0x01
+#define IPA_SPECIAL_CREATE_STEP 0x02
+
struct ipadb_mspac;
enum ipadb_user_auth {
@@ -104,7 +108,7 @@ struct ipadb_context {
char *kdc_hostname;
LDAP *lcontext;
krb5_context kcontext;
- bool override_restrictions;
+ uint32_t special_flags;
krb5_key_salt_tuple *supp_encs;
int n_supp_encs;
krb5_key_salt_tuple *def_encs;
@@ -226,18 +230,7 @@ krb5_error_code ipadb_check_policy_as(krb5_context kcontext,
krb5_pa_data ***e_data);
/* MASTER KEY FUNCTIONS */
-krb5_error_code ipadb_fetch_master_key(krb5_context kcontext,
- krb5_principal mname,
- krb5_keyblock *key,
- krb5_kvno *kvno,
- char *db_args);
-krb5_error_code ipadb_store_master_key_list(krb5_context kcontext,
- char *db_arg,
- krb5_principal mname,
- krb5_keylist_node *keylist,
- char *master_pwd);
-
-krb5_error_code ipadb_create_master_key(krb5_context kcontext);
+krb5_error_code ipadb_check_master_key(struct ipadb_context *ipactx);
/* PASSWORD FUNCTIONS */
krb5_error_code ipadb_change_pwd(krb5_context context,
diff --git a/daemons/ipa-kdb/ipa_kdb_mkey.c b/daemons/ipa-kdb/ipa_kdb_mkey.c
index 3d2f9753a..1d208e3cc 100644
--- a/daemons/ipa-kdb/ipa_kdb_mkey.c
+++ b/daemons/ipa-kdb/ipa_kdb_mkey.c
@@ -27,13 +27,10 @@ static char *krbmkey_attrs[] = {
NULL
};
-krb5_error_code ipadb_fetch_master_key(krb5_context kcontext,
- krb5_principal mname,
- krb5_keyblock *key,
- krb5_kvno *kvno,
- char *db_args)
+static krb5_error_code ipadb_fetch_master_key(struct ipadb_context *ipactx,
+ krb5_keyblock *key,
+ krb5_kvno *kvno)
{
- struct ipadb_context *ipactx;
LDAPMessage *res = NULL;
LDAPMessage *first;
struct berval **vals = NULL;
@@ -44,11 +41,6 @@ krb5_error_code ipadb_fetch_master_key(krb5_context kcontext,
int ret;
int i;
- ipactx = ipadb_get_context(kcontext);
- if (!ipactx) {
- return KRB5_KDB_DBNOTINITED;
- }
-
if (!ipactx->lcontext) {
ret = ipadb_get_connection(ipactx);
if (ret != 0) {
@@ -131,15 +123,10 @@ done:
return kerr;
}
-krb5_error_code ipadb_store_master_key_list(krb5_context kcontext,
- char *db_arg,
- krb5_principal mname,
- krb5_keylist_node *keylist,
- char *master_pwd)
+static krb5_error_code ipadb_store_master_key(struct ipadb_context *ipactx,
+ krb5_keylist_node *cur_key)
{
- struct ipadb_context *ipactx;
BerElement *be = NULL;
- krb5_keyblock k = { 0, 0, 0, NULL };
struct berval mkey;
ber_int_t tvno;
ber_int_t ttype;
@@ -147,16 +134,6 @@ krb5_error_code ipadb_store_master_key_list(krb5_context kcontext,
krb5_error_code kerr;
int ret;
- ipactx = ipadb_get_context(kcontext);
- if (!ipactx) {
- return KRB5_KDB_DBNOTINITED;
- }
-
- /* we support storing only one key for now */
- if (!keylist || keylist->next) {
- return EINVAL;
- }
-
if (!ipactx->lcontext) {
ret = ipadb_get_connection(ipactx);
if (ret != 0) {
@@ -172,10 +149,10 @@ krb5_error_code ipadb_store_master_key_list(krb5_context kcontext,
}
- tvno = keylist->kvno;
- ttype = keylist->keyblock.enctype;
- mkey.bv_len = keylist->keyblock.length;
- mkey.bv_val = (void *)keylist->keyblock.contents;
+ tvno = cur_key->kvno;
+ ttype = cur_key->keyblock.enctype;
+ mkey.bv_len = cur_key->keyblock.length;
+ mkey.bv_val = (void *)cur_key->keyblock.contents;
ret = ber_printf(be, "{i{iO}}", tvno, ttype, &mkey);
if (ret == -1) {
@@ -219,7 +196,112 @@ done:
if (be) {
ber_free(be, 1);
}
- krb5_free_keyblock_contents(kcontext, &k);
ldap_mods_free(mods, 1);
return kerr;
}
+
+static krb5_error_code ipadb_update_krbMKey(struct ipadb_context *ipactx,
+ krb5_keylist_node *master_key,
+ bool update)
+{
+ krb5_error_code kerr;
+ LDAPMessage *res = NULL;
+
+ if (update) {
+ /* check if we need to update the master key in LDAP for
+ * older replicas, if the attr is found, keep it updated */
+ kerr = ipadb_simple_search(ipactx, ipactx->realm_base,
+ LDAP_SCOPE_BASE, "(krbMKey=*)",
+ krbmkey_attrs, &res);
+ switch (kerr) {
+ case 0:
+ ldap_msgfree(res);
+ break;
+ case KRB5_KDB_NOENTRY:
+ return 0;
+ default:
+ return kerr;
+ }
+ }
+
+ /* FIXME: on domain level X we may want to not add the key */
+ kerr = ipadb_store_master_key(ipactx, master_key);
+ if (kerr) {
+ com_err("IPA KDB driver", kerr,
+ "while storing master key (version %d)",
+ (int)master_key->kvno);
+ }
+ return kerr;
+}
+
+krb5_error_code ipadb_check_db_exists(struct ipadb_context *ipactx)
+{
+ if (ipactx->special_flags & IPA_SPECIAL_CREATE_STEP) return EEXIST;
+ return 0;
+}
+
+/* See if we have a keytab, if not try to fetch the key from ldap, and
+ * stash it for the future (upgrade path) */
+krb5_error_code ipadb_check_master_key(struct ipadb_context *ipactx)
+{
+ krb5_error_code kerr;
+ char *cmname = NULL;
+ krb5_principal mname = NULL;
+ krb5_keyblock mkey = { 0 };
+ krb5_keylist_node *keylist;
+ krb5_kvno mkvno;
+
+ kerr = asprintf(&cmname, KRB5_KDB_M_NAME"@%s", ipactx->realm);
+ if (kerr < 0) return ENOMEM;
+
+ kerr = krb5_parse_name(ipactx->kcontext, cmname, &mname);
+ if (kerr) goto done;
+
+ kerr = krb5_db_fetch_mkey(ipactx->kcontext, mname, ENCTYPE_UNKNOWN,
+ 0, 0, NULL, &mkvno, NULL, &mkey);
+ if (kerr == 0) kerr = ipadb_check_db_exists(ipactx);
+ if (kerr && (kerr != KRB5_KDB_CANTREAD_STORED)) goto done;
+
+ if (kerr == KRB5_KDB_CANTREAD_STORED) {
+ /* check if we have a key in LDAP, and stash it in the keytab */
+ kerr = ipadb_fetch_master_key(ipactx, &mkey, &mkvno);
+ if (kerr == 0) kerr = ipadb_check_db_exists(ipactx);
+ if (kerr) {
+ /* if we are setting up then lack of mkey is normal */
+ if (ipactx->special_flags & IPA_SPECIAL_CREATE_STEP) kerr = 0;
+ goto done;
+ }
+
+ kerr = krb5_db_store_master_key(ipactx->kcontext, NULL,
+ mname, mkvno, &mkey, NULL);
+ } else {
+ /* if override is set do extra checks on ldap keytab so that it
+ * is uploaded during initial setup if needed */
+ if (ipactx->special_flags & IPA_SPECIAL_OVERRIDE_RESTRICTION) {
+ krb5_keylist_node curkey = { mkey, mkvno, NULL };
+ kerr = ipadb_update_krbMKey(ipactx, &curkey, false);
+ if (kerr) goto done;
+ }
+
+ /* check if we have the latest kvno as current key. If not stash
+ * the new keys in the keytab */
+ kerr = krb5_db_fetch_mkey_list(ipactx->kcontext, mname, &mkey);
+ if (kerr) goto done;
+
+ keylist = krb5_db_mkey_list_alias(ipactx->kcontext);
+
+ if (keylist->kvno > mkvno) {
+ kerr = krb5_db_store_master_key_list(ipactx->kcontext, NULL,
+ mname, NULL);
+
+ /* we do not consider it fatal if this fails on update */
+ (void)ipadb_update_krbMKey(ipactx, keylist, true);
+ }
+ }
+
+done:
+ krb5_free_keyblock_contents(ipactx->kcontext, &mkey);
+ krb5_free_principal(ipactx->kcontext, mname);
+ free(cmname);
+ return kerr;
+}
diff --git a/daemons/ipa-kdb/ipa_kdb_passwords.c b/daemons/ipa-kdb/ipa_kdb_passwords.c
index ad57181d5..5932eefbd 100644
--- a/daemons/ipa-kdb/ipa_kdb_passwords.c
+++ b/daemons/ipa-kdb/ipa_kdb_passwords.c
@@ -124,7 +124,7 @@ krb5_error_code ipadb_change_pwd(krb5_context context,
}
if (!db_entry->e_data) {
- if (!ipactx->override_restrictions) {
+ if (!(ipactx->special_flags & IPA_SPECIAL_OVERRIDE_RESTRICTION)) {
return EINVAL;
} else {
/* kadmin is creating a new principal */
diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c
index e32be856a..b3c6b5032 100644
--- a/daemons/ipa-kdb/ipa_kdb_principals.c
+++ b/daemons/ipa-kdb/ipa_kdb_principals.c
@@ -1855,7 +1855,16 @@ static krb5_error_code ipadb_entry_to_mods(krb5_context kcontext,
}
/* KADM5_TL_DATA */
+ /* apparently, at least some versions of kdb5_util fails to set this
+ * flag when t sets master key rotation infomation in TL_DATA.
+ * So for now check if KADM5_KEY_DATA has been set, and just overwrite
+ * TL_DATA if any is present */
+#if KADM5_ACTUALLY_SETS_KADM5_TL_DATA_ON_MASTER_KEY_ROTATION
if (entry->mask & KMASK_TL_DATA) {
+#else
+ if (entry->n_tl_data &&
+ entry->mask & KMASK_KEY_DATA) {
+#endif
kerr = ipadb_get_tl_data(entry,
KRB5_TL_LAST_ADMIN_UNLOCK,
sizeof(time32le),
@@ -2015,7 +2024,7 @@ static krb5_error_code ipadb_add_principal(krb5_context kcontext,
goto done;
}
- if (!ipactx->override_restrictions) {
+ if (!(ipactx->special_flags & IPA_SPECIAL_OVERRIDE_RESTRICTION)) {
return KRB5_KDB_CONSTRAINT_VIOLATION;
}
@@ -2233,7 +2242,7 @@ krb5_error_code ipadb_delete_principal(krb5_context kcontext,
return KRB5_KDB_DBNOTINITED;
}
- if (!ipactx->override_restrictions) {
+ if (!(ipactx->special_flags & IPA_SPECIAL_OVERRIDE_RESTRICTION)) {
return KRB5_KDB_CONSTRAINT_VIOLATION;
}
diff --git a/ipaserver/install/krbinstance.py b/ipaserver/install/krbinstance.py
index 4f1995f7b..214945301 100644
--- a/ipaserver/install/krbinstance.py
+++ b/ipaserver/install/krbinstance.py
@@ -273,6 +273,13 @@ class KrbInstance(service.Service):
os.chmod(path, chmod)
def __init_ipa_kdb(self):
+ # Save away old stash file if any
+ old_stash = os.path.join(paths.VAR_KERBEROS_KRB5KDC_DIR,
+ '.k5.' + self.realm)
+ if os.path.exists(old_stash):
+ self.fstore.backup_file(old_stash);
+ os.unlink(old_stash);
+
# kdb5_util may take a very long time when entropy is low
installutils.check_entropy()