diff options
author | Simo Sorce <ssorce@redhat.com> | 2011-06-10 14:25:03 -0400 |
---|---|---|
committer | Simo Sorce <ssorce@redhat.com> | 2011-08-26 08:24:49 -0400 |
commit | 0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe (patch) | |
tree | 1b66f96cfc6ae1d6c0f0cb1cd85994cedef8a380 /daemons/ipa-kdb/ipa_kdb_mkey.c | |
parent | e9e426354f28ca01586b1b5ef7130b19b392232b (diff) | |
download | freeipa-0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe.tar.gz freeipa-0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe.tar.xz freeipa-0a4f7960b9cb2cc43c014a9ba5f96ddfbf5713fe.zip |
ipa-kdb: Get/Store Master Key directly from LDAP
Diffstat (limited to 'daemons/ipa-kdb/ipa_kdb_mkey.c')
-rw-r--r-- | daemons/ipa-kdb/ipa_kdb_mkey.c | 225 |
1 files changed, 225 insertions, 0 deletions
diff --git a/daemons/ipa-kdb/ipa_kdb_mkey.c b/daemons/ipa-kdb/ipa_kdb_mkey.c new file mode 100644 index 00000000..3d2f9753 --- /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; +} |