summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimo Sorce <ssorce@redhat.com>2011-06-10 14:25:03 -0400
committerSimo Sorce <ssorce@redhat.com>2011-08-26 08:24:49 -0400
commit0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe (patch)
tree1b66f96cfc6ae1d6c0f0cb1cd85994cedef8a380
parente9e426354f28ca01586b1b5ef7130b19b392232b (diff)
downloadfreeipa-0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe.tar.gz
freeipa-0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe.tar.xz
freeipa-0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe.zip
ipa-kdb: Get/Store Master Key directly from LDAP
-rw-r--r--daemons/ipa-kdb/Makefile.am1
-rw-r--r--daemons/ipa-kdb/ipa_kdb.c21
-rw-r--r--daemons/ipa-kdb/ipa_kdb.h17
-rw-r--r--daemons/ipa-kdb/ipa_kdb_mkey.c225
-rw-r--r--daemons/ipa-kdb/ipa_kdb_principals.c12
5 files changed, 264 insertions, 12 deletions
diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am
index a632bb01c..37bfca403 100644
--- a/daemons/ipa-kdb/Makefile.am
+++ b/daemons/ipa-kdb/Makefile.am
@@ -28,6 +28,7 @@ plugin_LTLIBRARIES = \
ipadb_la_SOURCES = \
ipa_kdb.c \
ipa_kdb_common.c \
+ ipa_kdb_mkey.c \
ipa_kdb_principals.c \
$(KRB5_UTIL_SRCS) \
$(NULL)
diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c
index 0f63bc83c..394cdb7b6 100644
--- a/daemons/ipa-kdb/ipa_kdb.c
+++ b/daemons/ipa-kdb/ipa_kdb.c
@@ -307,21 +307,26 @@ static krb5_error_code ipadb_init_module(krb5_context kcontext,
ipactx = ipadb_get_context(kcontext);
ipadb_context_free(kcontext, &ipactx);
+ ipactx = calloc(1, sizeof(struct ipadb_context));
+ if (!ipactx) {
+ return ENOMEM;
+ }
+
/* 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], "temporary", 9) == 0) {
krb5_set_error_message(kcontext, EINVAL,
"Plugin requires -update argument!");
- return EINVAL;
+ ret = EINVAL;
+ goto fail;
}
}
- ipactx = calloc(1, sizeof(struct ipadb_context));
- if (!ipactx) {
- return ENOMEM;
- }
-
ipactx->kcontext = kcontext;
kerr = krb5_get_default_realm(kcontext, &ipactx->realm);
@@ -469,9 +474,9 @@ kdb_vftabl kdb_function_table = {
ipadb_free_policy, /* free_policy */
ipadb_alloc, /* alloc */
ipadb_free, /* free */
- NULL, /* fetch_master_key */
+ ipadb_fetch_master_key, /* fetch_master_key */
NULL, /* fetch_master_key_list */
- NULL, /* store_master_key_list */
+ ipadb_store_master_key_list, /* store_master_key_list */
NULL, /* dbe_search_enctype */
NULL, /* change_pwd */
NULL, /* promote_db */
diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h
index 26c6a3df6..b76cfdc9d 100644
--- a/daemons/ipa-kdb/ipa_kdb.h
+++ b/daemons/ipa-kdb/ipa_kdb.h
@@ -70,6 +70,8 @@
* In krb5 1.10 this should be superceeded by a better mechanism */
#define KDB_TL_USER_INFO 0x7ffe
+#define IPA_SETUP "ipa-setup-override-restrictions"
+
struct ipadb_context {
char *uri;
char *base;
@@ -77,6 +79,7 @@ struct ipadb_context {
char *realm_base;
LDAP *lcontext;
krb5_context kcontext;
+ bool override_restrictions;
krb5_key_salt_tuple *supp_encs;
int n_supp_encs;
};
@@ -129,3 +132,17 @@ krb5_error_code ipadb_iterate(krb5_context kcontext,
char *match_entry,
int (*func)(krb5_pointer, krb5_db_entry *),
krb5_pointer func_arg);
+
+/* 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);
diff --git a/daemons/ipa-kdb/ipa_kdb_mkey.c b/daemons/ipa-kdb/ipa_kdb_mkey.c
new file mode 100644
index 000000000..3d2f9753a
--- /dev/null
+++ b/daemons/ipa-kdb/ipa_kdb_mkey.c
@@ -0,0 +1,225 @@
+/*
+ * MIT Kerberos KDC database backend for FreeIPA
+ *
+ * Authors: Simo Sorce <ssorce@redhat.com>
+ *
+ * Copyright (C) 2011 Simo Sorce, Red Hat
+ * see file 'COPYING' for use and warranty information
+ *
+ * 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 3 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, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "ipa_kdb.h"
+
+static char *krbmkey_attrs[] = {
+ "krbMKey",
+ NULL
+};
+
+krb5_error_code ipadb_fetch_master_key(krb5_context kcontext,
+ krb5_principal mname,
+ krb5_keyblock *key,
+ krb5_kvno *kvno,
+ char *db_args)
+{
+ struct ipadb_context *ipactx;
+ LDAPMessage *res = NULL;
+ LDAPMessage *first;
+ struct berval **vals = NULL;
+ BerElement *be = NULL;
+ krb5_error_code kerr;
+ krb5_keyblock k;
+ int mkvno;
+ 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) {
+ kerr = KRB5_KDB_SERVER_INTERNAL_ERR;
+ goto done;
+ }
+ }
+
+ be = ber_alloc_t(LBER_USE_DER);
+ if (!be) {
+ kerr = ENOMEM;
+ goto done;
+ }
+
+ kerr = ipadb_simple_search(ipactx, ipactx->realm_base, LDAP_SCOPE_BASE,
+ "(krbMKey=*)", krbmkey_attrs, &res);
+ if (kerr) {
+ goto done;
+ }
+
+ first = ldap_first_entry(ipactx->lcontext, res);
+ if (!first) {
+ kerr = KRB5_KDB_NOENTRY;
+ goto done;
+ }
+
+ mkvno = 0;
+ k.contents = NULL;
+ vals = ldap_get_values_len(ipactx->lcontext, first, "krbmkey");
+ for (i = 0; vals[i]; i++) {
+ struct berval *mkey;
+ ber_tag_t tag;
+ ber_int_t tvno;
+ ber_int_t ttype;
+
+ ber_init2(be, vals[i], LBER_USE_DER);
+
+ tag = ber_scanf(be, "{i{iO}}", &tvno, &ttype, &mkey);
+ if (tag == LBER_ERROR) {
+ kerr = KRB5_KDB_SERVER_INTERNAL_ERR;
+ goto done;
+ }
+
+ if (tvno > mkvno) {
+ mkvno = tvno;
+ k.enctype = ttype;
+ k.length = mkey->bv_len;
+ if (k.contents) {
+ free(k.contents);
+ }
+ k.contents = malloc(k.length);
+ if (!k.contents) {
+ kerr = ENOMEM;
+ goto done;
+ }
+ memcpy(k.contents, mkey->bv_val, k.length);
+ }
+ ber_bvfree(mkey);
+ }
+
+ if (mkvno == 0) {
+ kerr = KRB5_KDB_NOENTRY;
+ goto done;
+ }
+
+ *kvno = mkvno;
+ key->magic = KV5M_KEYBLOCK;
+ key->enctype = k.enctype;
+ key->length = k.length;
+ key->contents = k.contents;
+
+ kerr = 0;
+
+done:
+ if (be) {
+ ber_free(be, 0);
+ }
+ ldap_value_free_len(vals);
+ ldap_msgfree(res);
+ 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)
+{
+ 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;
+ LDAPMod **mods = NULL;
+ 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) {
+ kerr = KRB5_KDB_SERVER_INTERNAL_ERR;
+ goto done;
+ }
+ }
+
+ be = ber_alloc_t(LBER_USE_DER);
+ if (!be) {
+ kerr = ENOMEM;
+ goto done;
+ }
+
+
+ tvno = keylist->kvno;
+ ttype = keylist->keyblock.enctype;
+ mkey.bv_len = keylist->keyblock.length;
+ mkey.bv_val = (void *)keylist->keyblock.contents;
+
+ ret = ber_printf(be, "{i{iO}}", tvno, ttype, &mkey);
+ if (ret == -1) {
+ kerr = KRB5_KDB_INTERNAL_ERROR;
+ goto done;
+ }
+
+ mods = calloc(2, sizeof(LDAPMod *));
+ if (!mods) {
+ kerr = ENOMEM;
+ goto done;
+ }
+ mods[0] = calloc(1, sizeof(LDAPMod));
+ if (!mods[0]) {
+ kerr = ENOMEM;
+ goto done;
+ }
+ mods[0]->mod_op = LDAP_MOD_ADD | LDAP_MOD_BVALUES;
+ mods[0]->mod_type = strdup("krbMKey");
+ if (!mods[0]->mod_type) {
+ kerr = ENOMEM;
+ goto done;
+ }
+ mods[0]->mod_bvalues = calloc(2, sizeof(struct berval *));
+ if (!mods[0]->mod_bvalues) {
+ kerr = ENOMEM;
+ goto done;
+ }
+
+ ret = ber_flatten(be, &mods[0]->mod_bvalues[0]);
+ if (ret == -1) {
+ kerr = KRB5_KDB_INTERNAL_ERROR;
+ goto done;
+ }
+
+ kerr = ipadb_simple_modify(ipactx, ipactx->realm_base, mods);
+
+ kerr = 0;
+
+done:
+ if (be) {
+ ber_free(be, 1);
+ }
+ krb5_free_keyblock_contents(kcontext, &k);
+ ldap_mods_free(mods, 1);
+ return kerr;
+}
diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c
index bd84f5b3b..97b240650 100644
--- a/daemons/ipa-kdb/ipa_kdb_principals.c
+++ b/daemons/ipa-kdb/ipa_kdb_principals.c
@@ -572,7 +572,6 @@ static krb5_error_code ipadb_fetch_principals(struct ipadb_context *ipactx,
krb5_error_code kerr;
char *src_filter = NULL;
char *esc_search_expr = NULL;
- LDAPMessage *res = NULL;
int ret;
if (!ipactx->lcontext) {
@@ -603,9 +602,6 @@ static krb5_error_code ipadb_fetch_principals(struct ipadb_context *ipactx,
result);
done:
- if (kerr) {
- ldap_msgfree(res);
- }
free(src_filter);
free(esc_search_expr);
return kerr;
@@ -1517,6 +1513,10 @@ static krb5_error_code ipadb_add_principal(krb5_context kcontext,
goto done;
}
+ if (!ipactx->override_restrictions) {
+ return KRB5_KDB_CONSTRAINT_VIOLATION;
+ }
+
kerr = krb5_unparse_name(kcontext, entry->princ, &principal);
if (kerr != 0) {
goto done;
@@ -1711,6 +1711,10 @@ krb5_error_code ipadb_delete_principal(krb5_context kcontext,
return KRB5_KDB_DBNOTINITED;
}
+ if (!ipactx->override_restrictions) {
+ return KRB5_KDB_CONSTRAINT_VIOLATION;
+ }
+
kerr = krb5_unparse_name(kcontext, search_for, &principal);
if (kerr != 0) {
goto done;