From 0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 10 Jun 2011 14:25:03 -0400 Subject: ipa-kdb: Get/Store Master Key directly from LDAP --- daemons/ipa-kdb/Makefile.am | 1 + daemons/ipa-kdb/ipa_kdb.c | 21 ++-- daemons/ipa-kdb/ipa_kdb.h | 17 +++ daemons/ipa-kdb/ipa_kdb_mkey.c | 225 +++++++++++++++++++++++++++++++++++ daemons/ipa-kdb/ipa_kdb_principals.c | 12 +- 5 files changed, 264 insertions(+), 12 deletions(-) create mode 100644 daemons/ipa-kdb/ipa_kdb_mkey.c (limited to 'daemons') 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 + * + * 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 . + */ + +#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; -- cgit