From abd424889bef7e7f5652691e0cd5d07154898444 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Wed, 25 May 2011 18:32:14 -0400 Subject: ipa-kdb: functions to get principal --- daemons/ipa-kdb/Makefile.am | 1 + daemons/ipa-kdb/ipa_kdb.c | 35 -- daemons/ipa-kdb/ipa_kdb.h | 20 + daemons/ipa-kdb/ipa_kdb_principals.c | 863 +++++++++++++++++++++++++++++++++++ 4 files changed, 884 insertions(+), 35 deletions(-) create mode 100644 daemons/ipa-kdb/ipa_kdb_principals.c (limited to 'daemons') diff --git a/daemons/ipa-kdb/Makefile.am b/daemons/ipa-kdb/Makefile.am index 0d35ea973..2b97a93d3 100644 --- a/daemons/ipa-kdb/Makefile.am +++ b/daemons/ipa-kdb/Makefile.am @@ -24,6 +24,7 @@ plugin_LTLIBRARIES = \ ipadb_la_SOURCES = \ ipa_kdb.c \ ipa_kdb_common.c \ + ipa_kdb_principals.c \ $(NULL) ipadb_la_LDFLAGS = \ diff --git a/daemons/ipa-kdb/ipa_kdb.c b/daemons/ipa-kdb/ipa_kdb.c index 4e8fb3ae9..0f63bc83c 100644 --- a/daemons/ipa-kdb/ipa_kdb.c +++ b/daemons/ipa-kdb/ipa_kdb.c @@ -395,41 +395,6 @@ static krb5_error_code ipadb_get_age(krb5_context kcontext, return 0; } -static krb5_error_code ipadb_get_principal(krb5_context kcontext, - krb5_const_principal search_for, - unsigned int flags, - krb5_db_entry **entry) -{ - return KRB5_PLUGIN_OP_NOTSUPP; -} - -void ipadb_free_principal(krb5_context kcontext, krb5_db_entry *entry) -{ - return; -} - -static krb5_error_code ipadb_put_principal(krb5_context kcontext, - krb5_db_entry *entry, - char **db_args) -{ - return KRB5_PLUGIN_OP_NOTSUPP; -} - -static krb5_error_code ipadb_delete_principal(krb5_context kcontext, - krb5_const_principal search_for) -{ - return KRB5_PLUGIN_OP_NOTSUPP; -} - -static krb5_error_code ipadb_iterate(krb5_context kcontext, - char *match_entry, - int (*func)(krb5_pointer, - krb5_db_entry *), - krb5_pointer func_arg) -{ - return KRB5_PLUGIN_OP_NOTSUPP; -} - static krb5_error_code ipadb_create_policy(krb5_context kcontext, osa_policy_ent_t policy) { diff --git a/daemons/ipa-kdb/ipa_kdb.h b/daemons/ipa-kdb/ipa_kdb.h index 760508d6d..7e20f98ab 100644 --- a/daemons/ipa-kdb/ipa_kdb.h +++ b/daemons/ipa-kdb/ipa_kdb.h @@ -28,6 +28,11 @@ #include #include #include +#include +#include +#include +#include +#include struct ipadb_context { char *uri; @@ -73,3 +78,18 @@ int ipadb_ldap_attr_to_time_t(LDAP *lcontext, LDAPMessage *le, int ipadb_ldap_attr_has_value(LDAP *lcontext, LDAPMessage *le, char *attrname, char *value); +/* PRINCIPALS FUNCTIONS */ +krb5_error_code ipadb_get_principal(krb5_context kcontext, + krb5_const_principal search_for, + unsigned int flags, + krb5_db_entry **entry); +void ipadb_free_principal(krb5_context kcontext, krb5_db_entry *entry); +krb5_error_code ipadb_put_principal(krb5_context kcontext, + krb5_db_entry *entry, + char **db_args); +krb5_error_code ipadb_delete_principal(krb5_context kcontext, + krb5_const_principal search_for); +krb5_error_code ipadb_iterate(krb5_context kcontext, + char *match_entry, + int (*func)(krb5_pointer, krb5_db_entry *), + krb5_pointer func_arg); diff --git a/daemons/ipa-kdb/ipa_kdb_principals.c b/daemons/ipa-kdb/ipa_kdb_principals.c new file mode 100644 index 000000000..f42360da5 --- /dev/null +++ b/daemons/ipa-kdb/ipa_kdb_principals.c @@ -0,0 +1,863 @@ +/* + * 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" + +#define PRINC_SEARCH_FILTER "(&(|(objectclass=krbprincipalaux)" \ + "(objectclass=krbprincipal))" \ + "(krbprincipalname=%s))" + +static char *std_principal_attrs[] = { + "krbPrincipalName", + "krbCanonicalName", + "krbUPEnabled", + "krbPrincipalKey", + "krbTicketPolicyReference", + "krbPrincipalExpiration", + "krbPasswordExpiration", + "krbPwdPolicyReference", + "krbPrincipalType", + "krbPwdHistory", + "krbLastPwdChange", + "krbPrincipalAliases", + "krbLastSuccessfulAuth", + "krbLastFailedAuth", + "krbLoginFailedCount", + "krbExtraData", + "krbLastAdminUnlock", + "krbObjectReferences", + "krbTicketFlags", + "krbMaxTicketLife", + "krbMaxRenewableAge", + + "nsaccountlock", + + NULL +}; + +static char *std_tktpolicy_attrs[] = { + "krbmaxticketlife", + "krbmaxrenewableage", + "krbticketflags", + + NULL +}; + +#define TKTFLAGS_BIT 0x01 +#define MAXTKTLIFE_BIT 0x02 +#define MAXRENEWABLEAGE_BIT 0x04 + +static int ipadb_ldap_attr_to_tl_data(LDAP *lcontext, LDAPMessage *le, + char *attrname, + krb5_tl_data **result, int *num) +{ + struct berval **vals; + krb5_tl_data *prev, *next; + krb5_int16 be_type; + int i; + int ret = ENOENT; + + *result = NULL; + prev = NULL; + vals = ldap_get_values_len(lcontext, le, attrname); + if (vals) { + for (i = 0; vals[i]; i++) { + next = calloc(1, sizeof(krb5_tl_data)); + if (!next) { + ret = ENOMEM; + goto done; + } + + /* fill tl_data struct with the data */ + memcpy(&be_type, vals[i]->bv_val, 2); + next->tl_data_type = ntohs(be_type); + next->tl_data_length = vals[i]->bv_len - 2; + next->tl_data_contents = malloc(next->tl_data_length); + if (!next->tl_data_contents) { + ret = ENOMEM; + goto done; + } + memcpy(next->tl_data_contents, + vals[i]->bv_val + 2, + next->tl_data_length); + + if (prev) { + prev->tl_data_next = next; + } else { + *result = next; + } + prev = next; + } + *num = i; + ret = 0; + + ldap_value_free_len(vals); + } + +done: + if (ret) { + if (*result) { + prev = *result; + while (prev) { + next = prev->tl_data_next; + free(prev); + prev = next; + } + } + *result = NULL; + *num = 0; + } + return ret; +} + +static krb5_error_code ipadb_set_tl_data(krb5_db_entry *entry, + krb5_int16 type, + krb5_ui_2 length, + krb5_octet *data) +{ + krb5_error_code kerr; + krb5_tl_data *new_td = NULL; + krb5_tl_data *td; + + for (td = entry->tl_data; td; td = td->tl_data_next) { + if (td->tl_data_type == type) { + break; + } + } + if (!td) { + /* an existing entry was not found, make new */ + new_td = malloc(sizeof(krb5_tl_data)); + if (!new_td) { + kerr = ENOMEM; + goto done; + } + td = new_td; + td->tl_data_next = entry->tl_data; + td->tl_data_type = type; + entry->tl_data = td; + entry->n_tl_data++; + } + td->tl_data_length = length; + td->tl_data_contents = malloc(td->tl_data_length); + if (!td->tl_data_contents) { + kerr = ENOMEM; + goto done; + } + memcpy(td->tl_data_contents, data, td->tl_data_length); + + new_td = NULL; + kerr = 0; + +done: + free(new_td); + return kerr; +} + +static int ipadb_ldap_attr_to_key_data(LDAP *lcontext, LDAPMessage *le, + char *attrname, + krb5_key_data **result, int *num, + krb5_kvno *res_mkvno) +{ + struct berval **vals; + krb5_key_data *keys = NULL; + BerElement *be = NULL; + void *tmp; + int i = 0; + int ret = ENOENT; + + vals = ldap_get_values_len(lcontext, le, attrname); + if (vals) { + ber_tag_t tag; + ber_int_t major_vno; + ber_int_t minor_vno; + ber_int_t kvno; + ber_int_t mkvno; + ber_int_t type; + ber_tag_t seqtag; + ber_len_t seqlen; + ber_len_t setlen; + ber_tag_t retag; + ber_tag_t opttag; + struct berval tval; + + be = ber_alloc_t(LBER_USE_DER); + if (!be) { + return ENOMEM; + } + + /* reinit the ber element with the new val */ + ber_init2(be, vals[0], LBER_USE_DER); + + /* fill key_data struct with the data */ + retag = ber_scanf(be, "{t[i]t[i]t[i]t[i]t[{", + &tag, &major_vno, + &tag, &minor_vno, + &tag, &kvno, + &tag, &mkvno, + &seqtag); + if (retag == LBER_ERROR || + major_vno != 1 || + minor_vno != 1 || + seqtag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 4)) { + ret = EINVAL; + goto done; + } + + retag = ber_skip_tag(be, &seqlen); + + /* sequence of keys */ + for (i = 0; retag == LBER_SEQUENCE; i++) { + + tmp = realloc(keys, (i + 1) * sizeof(krb5_key_data)); + if (!tmp) { + ret = ENOMEM; + goto done; + } + keys = tmp; + + memset(&keys[i], 0, sizeof(krb5_key_data)); + + keys[i].key_data_kvno = kvno; + + /* do we have a salt type ? (optional) */ + retag = ber_scanf(be, "t", &opttag); + if (retag == LBER_ERROR) { + ret = EINVAL; + goto done; + } + if (opttag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) { + keys[i].key_data_ver = 2; + + retag = ber_scanf(be, "[l{tl[i]", + &seqlen, &tag, &setlen, &type); + if (tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 0)) { + ret = EINVAL; + goto done; + } + keys[i].key_data_type[1] = type; + + /* do we have salt data ? (optional) */ + if (seqlen > setlen + 2) { + retag = ber_scanf(be, "t[o]", &tag, &tval); + if (retag == LBER_ERROR || + tag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) { + ret = EINVAL; + goto done; + } + keys[i].key_data_length[1] = tval.bv_len; + keys[i].key_data_contents[1] = (krb5_octet *)tval.bv_val; + } + + retag = ber_scanf(be, "}]t", &opttag); + if (retag == LBER_ERROR) { + ret = EINVAL; + goto done; + } + + } else { + keys[i].key_data_ver = 1; + } + + if (opttag != (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 1)) { + ret = EINVAL; + goto done; + } + + /* get the key */ + retag = ber_scanf(be, "[{t[i]t[o]}]", &tag, &type, &tag, &tval); + if (retag == LBER_ERROR) { + ret = EINVAL; + goto done; + } + keys[i].key_data_type[0] = type; + keys[i].key_data_length[0] = tval.bv_len; + keys[i].key_data_contents[0] = (krb5_octet *)tval.bv_val; + + /* check for sk2params */ + retag = ber_peek_tag(be, &setlen); + if (retag == (LBER_CONSTRUCTED | LBER_CLASS_CONTEXT | 2)) { + /* not supported yet, skip */ + retag = ber_scanf(be, "t[x]}"); + } else { + retag = ber_scanf(be, "}"); + } + if (retag == LBER_ERROR) { + ret = EINVAL; + goto done; + } + + retag = ber_skip_tag(be, &seqlen); + } + *result = keys; + *num = i; + *res_mkvno = mkvno; + ret = 0; + } + +done: + ber_free(be, 0); /* internal buffer is 'vals[0]' */ + ldap_value_free_len(vals); + if (ret) { + for (i -= 1; keys && i >= 0; i--) { + free(keys[i].key_data_contents[0]); + free(keys[i].key_data_contents[1]); + } + *result = NULL; + *num = 0; + } + return ret; +} + +static krb5_error_code ipadb_parse_ldap_entry(krb5_context kcontext, + char *principal, + LDAPMessage *lentry, + krb5_db_entry **kentry, + uint32_t *polmask) +{ + LDAP *lcontext; + krb5_db_entry *entry; + krb5_error_code kerr; + krb5_tl_data *res_tl_data; + krb5_key_data *res_key_data; + krb5_kvno mkvno; + char *restring; + time_t restime; + bool resbool; + int result; + int ret; + + *polmask = 0; + entry = calloc(1, sizeof(krb5_db_entry)); + if (!entry) { + return ENOMEM; + } + + /* proceed to fill in attributes in the order they are defined in + * krb5_db_entry in kdb.h */ + lcontext = (ipadb_get_context(kcontext))->lcontext; + + entry->magic = KRB5_KDB_MAGIC_NUMBER; + entry->len = KRB5_KDB_V1_BASE_LENGTH; + + /* ignore mask for now */ + + ret = ipadb_ldap_attr_to_int(lcontext, lentry, + "krbTicketFlags", &result); + if (ret == 0) { + entry->attributes = result; + } else { + *polmask |= TKTFLAGS_BIT; + } + + ret = ipadb_ldap_attr_to_int(lcontext, lentry, + "krbMaxTicketLife", &result); + if (ret == 0) { + entry->max_life = result; + } else { + *polmask |= MAXTKTLIFE_BIT; + } + + ret = ipadb_ldap_attr_to_int(lcontext, lentry, + "krbMaxRenewableAge", &result); + if (ret == 0) { + entry->max_renewable_life = result; + } else { + *polmask |= MAXRENEWABLEAGE_BIT; + } + + ret = ipadb_ldap_attr_to_time_t(lcontext, lentry, + "krbPrincipalexpiration", &restime); + switch (ret) { + case 0: + entry->expiration = restime; + case ENOENT: + break; + default: + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + + ret = ipadb_ldap_attr_to_time_t(lcontext, lentry, + "krbPasswordExpiration", &restime); + switch (ret) { + case 0: + entry->pw_expiration = restime; + case ENOENT: + break; + default: + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + + ret = ipadb_ldap_attr_to_time_t(lcontext, lentry, + "krbLastSuccessfulAuth", &restime); + switch (ret) { + case 0: + entry->last_success = restime; + case ENOENT: + break; + default: + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + + ret = ipadb_ldap_attr_to_time_t(lcontext, lentry, + "krbLastFailedAuth", &restime); + switch (ret) { + case 0: + entry->last_failed = restime; + case ENOENT: + break; + default: + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + + ret = ipadb_ldap_attr_to_int(lcontext, lentry, + "krbLoginFailedCount", &result); + if (ret == 0) { + entry->fail_auth_count = result; + } + + /* TODO: e_length, e_data */ + + if (principal) { + kerr = krb5_parse_name(kcontext, principal, &entry->princ); + if (kerr != 0) { + goto done; + } + } else { + /* see if canonical name is available */ + ret = ipadb_ldap_attr_to_str(lcontext, lentry, + "krbCanonicalName", &restring); + switch (ret) { + case ENOENT: + /* if not pick the first principal name in the entry */ + ret = ipadb_ldap_attr_to_str(lcontext, lentry, + "krbPrincipalName", &restring); + if (ret != 0) { + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + case 0: + break; + default: + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + kerr = krb5_parse_name(kcontext, restring, &entry->princ); + free(restring); + if (kerr != 0) { + goto done; + } + } + + ret = ipadb_ldap_attr_to_tl_data(lcontext, lentry, + "krbExtraData", &res_tl_data, &result); + switch (ret) { + case 0: + entry->tl_data = res_tl_data; + entry->n_tl_data = result; + case ENOENT: + break; + default: + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + + ret = ipadb_ldap_attr_to_key_data(lcontext, lentry, + "krbPrincipalKey", + &res_key_data, &result, &mkvno); + switch (ret) { + case 0: + entry->key_data = res_key_data; + entry->n_key_data = result; + if (mkvno) { + krb5_int16 kvno16le = htole16((krb5_int16)mkvno); + + kerr = ipadb_set_tl_data(entry, KRB5_TL_MKVNO, + sizeof(kvno16le), + (krb5_octet *)&kvno16le); + if (kerr) { + goto done; + } + } + case ENOENT: + break; + default: + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + + ret = ipadb_ldap_attr_to_bool(lcontext, lentry, + "nsAccountLock", &resbool); + if ((ret == 0 && resbool == true) || (ret != 0 && ret != ENOENT)) { + entry->attributes |= KRB5_KDB_DISALLOW_ALL_TIX; + } + + ret = ipadb_ldap_attr_to_time_t(lcontext, lentry, + "krbLastPwdChange", &restime); + if (ret == 0) { + krb5_int32 time32le = htole32((krb5_int32)restime); + + kerr = ipadb_set_tl_data(entry, + KRB5_TL_LAST_PWD_CHANGE, + sizeof(time32le), + (krb5_octet *)&time32le); + if (kerr) { + goto done; + } + } + + ret = ipadb_ldap_attr_to_time_t(lcontext, lentry, + "krbLastAdminUnlock", &restime); + if (ret == 0) { + krb5_int32 time32le = htole32((krb5_int32)restime); + + kerr = ipadb_set_tl_data(entry, + KRB5_TL_LAST_ADMIN_UNLOCK, + sizeof(time32le), + (krb5_octet *)&time32le); + if (kerr) { + goto done; + } + } + + /* FIXME: fetch and se policy via krbpwdpolicyreference or fallback */ + + kerr = 0; + +done: + if (kerr) { + ipadb_free_principal(kcontext, entry); + entry = NULL; + } + *kentry = entry; + return kerr; +} + +static krb5_error_code ipadb_fetch_principals(struct ipadb_context *ipactx, + char *search_expr, + LDAPMessage **result) +{ + krb5_error_code kerr; + char *src_filter = NULL; + char *esc_search_expr = NULL; + LDAPMessage *res = NULL; + int ret; + + if (!ipactx->lcontext) { + ret = ipadb_get_connection(ipactx); + if (ret != 0) { + kerr = KRB5_KDB_SERVER_INTERNAL_ERR; + goto done; + } + } + + /* escape filter but do not touch '*' as this function accepts + * wildcards in names */ + esc_search_expr = ipadb_filter_escape(search_expr, false); + if (!esc_search_expr) { + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + + ret = asprintf(&src_filter, PRINC_SEARCH_FILTER, esc_search_expr); + if (ret == -1) { + kerr = KRB5_KDB_INTERNAL_ERROR; + goto done; + } + + kerr = ipadb_simple_search(ipactx, + ipactx->base, LDAP_SCOPE_SUBTREE, + src_filter, std_principal_attrs, + result); + +done: + if (kerr) { + ldap_msgfree(res); + } + free(src_filter); + free(esc_search_expr); + return kerr; +} + +static krb5_error_code ipadb_find_principal(krb5_context kcontext, + unsigned int flags, + LDAPMessage *res, + char **principal, + LDAPMessage **entry) +{ + struct ipadb_context *ipactx; + bool found = false; + LDAPMessage *le = NULL; + struct berval **vals; + int i; + + ipactx = ipadb_get_context(kcontext); + if (!ipactx) { + return KRB5_KDB_DBNOTINITED; + } + + while (!found) { + + if (!le) { + le = ldap_first_entry(ipactx->lcontext, res); + } else { + le = ldap_next_entry(ipactx->lcontext, le); + } + if (!le) { + break; + } + + vals = ldap_get_values_len(ipactx->lcontext, le, "krbprincipalname"); + if (vals == NULL) { + continue; + } + + /* we need to check for a strict match as a '*' in the name may have + * caused the ldap server to return multiple entries */ + for (i = 0; vals[i]; i++) { + /* FIXME: use case insensitive compare and tree as alias ?? */ + if (strcmp(vals[i]->bv_val, (*principal)) == 0) { + found = true; + } + } + + ldap_value_free_len(vals); + + if (!found) { + continue; + } + + /* we need to check if this is the canonical name */ + vals = ldap_get_values_len(ipactx->lcontext, le, "krbcanonicalname"); + if (vals == NULL) { + continue; + } + + /* FIXME: use case insensitive compare and treat as alias ?? */ + if (strcmp(vals[0]->bv_val, (*principal)) != 0 && + !(flags & KRB5_KDB_FLAG_ALIAS_OK)) { + /* search does not allow aliases */ + found = false; + ldap_value_free_len(vals); + continue; + } + + free(*principal); + *principal = strdup(vals[0]->bv_val); + if (!(*principal)) { + return KRB5_KDB_INTERNAL_ERROR; + } + + ldap_value_free_len(vals); + } + + if (!found || !le) { + return KRB5_KDB_NOENTRY; + } + + *entry = le; + return 0; +} + +static krb5_error_code ipadb_fetch_tktpolicy(krb5_context kcontext, + LDAPMessage *lentry, + krb5_db_entry *entry, + uint32_t polmask) +{ + struct ipadb_context *ipactx; + krb5_error_code kerr; + char *policy_dn = NULL; + LDAPMessage *res = NULL; + LDAPMessage *first; + int result; + int ret; + + ipactx = ipadb_get_context(kcontext); + if (!ipactx) { + return KRB5_KDB_DBNOTINITED; + } + + ret = ipadb_ldap_attr_to_str(ipactx->lcontext, lentry, + "krbticketpolicyreference", &policy_dn); + switch (ret) { + case 0: + break; + case ENOENT: + ret = asprintf(&policy_dn, "cn=%s,cn=kerberos,%s", + ipactx->realm, ipactx->base); + if (ret == -1) { + kerr = ENOMEM; + goto done; + } + break; + default: + kerr = ret; + goto done; + } + + kerr = ipadb_simple_search(ipactx, + policy_dn, LDAP_SCOPE_BASE, + "(objectclass=krbticketpolicyaux)", + std_tktpolicy_attrs, + &res); + if (kerr == 0) { + first = ldap_first_entry(ipactx->lcontext, res); + if (!first) { + kerr = KRB5_KDB_NOENTRY; + } else { + if (polmask & MAXTKTLIFE_BIT) { + ret = ipadb_ldap_attr_to_int(ipactx->lcontext, first, + "krbmaxticketlife", &result); + if (ret == 0) { + entry->max_life = result; + } else { + entry->max_life = 86400; + } + } + if (polmask & MAXRENEWABLEAGE_BIT) { + ret = ipadb_ldap_attr_to_int(ipactx->lcontext, first, + "krbmaxrenewableage", &result); + if (ret == 0) { + entry->max_renewable_life = result; + } else { + entry->max_renewable_life = 604800; + } + } + if (polmask & TKTFLAGS_BIT) { + ret = ipadb_ldap_attr_to_int(ipactx->lcontext, first, + "krbticketflags", &result); + if (ret == 0) { + entry->attributes |= result; + } else { + entry->attributes |= KRB5_KDB_REQUIRES_PRE_AUTH; + } + } + } + } + + if (kerr == KRB5_KDB_NOENTRY) { + /* No policy at all ?? + * set hardcoded default policy for now */ + if (polmask & MAXTKTLIFE_BIT) { + entry->max_life = 86400; + } + if (polmask & MAXRENEWABLEAGE_BIT) { + entry->max_renewable_life = 604800; + } + if (polmask & TKTFLAGS_BIT) { + entry->attributes |= KRB5_KDB_REQUIRES_PRE_AUTH; + } + + kerr = 0; + } + +done: + ldap_msgfree(res); + free(policy_dn); + return kerr; +} + +/* TODO: handle case where main object and krbprincipal data are not + * the same object but linked objects ? + * (by way of krbprincipalaux being in a separate object from krbprincipal). + * Currently we only support objcts with both objectclasses present at the + * same time. */ + +krb5_error_code ipadb_get_principal(krb5_context kcontext, + krb5_const_principal search_for, + unsigned int flags, + krb5_db_entry **entry) +{ + struct ipadb_context *ipactx; + krb5_error_code kerr; + char *principal = NULL; + LDAPMessage *res = NULL; + LDAPMessage *lentry; + uint32_t pol; + + ipactx = ipadb_get_context(kcontext); + if (!ipactx) { + return KRB5_KDB_DBNOTINITED; + } + + kerr = krb5_unparse_name(kcontext, search_for, &principal); + if (kerr != 0) { + goto done; + } + + kerr = ipadb_fetch_principals(ipactx, principal, &res); + if (kerr != 0) { + goto done; + } + + kerr = ipadb_find_principal(kcontext, flags, res, &principal, &lentry); + if (kerr != 0) { + goto done; + } + + kerr = ipadb_parse_ldap_entry(kcontext, principal, lentry, entry, &pol); + if (kerr != 0) { + goto done; + } + + if (pol) { + kerr = ipadb_fetch_tktpolicy(kcontext, lentry, *entry, pol); + if (kerr != 0) { + goto done; + } + } + +done: + ldap_msgfree(res); + krb5_free_unparsed_name(kcontext, principal); + return kerr; +} + +void ipadb_free_principal(krb5_context kcontext, krb5_db_entry *entry) +{ + return; +} + +krb5_error_code ipadb_put_principal(krb5_context kcontext, + krb5_db_entry *entry, + char **db_args) +{ + return KRB5_PLUGIN_OP_NOTSUPP; +} + +krb5_error_code ipadb_delete_principal(krb5_context kcontext, + krb5_const_principal search_for) +{ + return KRB5_PLUGIN_OP_NOTSUPP; +} + +krb5_error_code ipadb_iterate(krb5_context kcontext, + char *match_entry, + int (*func)(krb5_pointer, krb5_db_entry *), + krb5_pointer func_arg) +{ + return KRB5_PLUGIN_OP_NOTSUPP; +} + -- cgit