#include "ldap_main.h"
#include "kdb_ldap.h"
#include "ldap_principal.h"
#include "princ_xdr.h"
#include "ldap_err.h"
struct timeval timelimit = {300, 0};
char *principal_attributes[] = { "krbprincipalname",
"objectclass",
"krbprincipalkey",
"krbmaxrenewableage",
"krbmaxticketlife",
"krbticketflags",
"krbprincipalexpiration",
"krbticketpolicyreference",
"krbUpEnabled",
"krbpwdpolicyreference",
"krbpasswordexpiration",
"krbLastFailedAuth",
"krbLoginFailedCount",
"krbLastSuccessfulAuth",
#ifdef HAVE_EDIRECTORY
"loginexpirationtime",
"logindisabled",
#endif
"loginexpirationtime",
"logindisabled",
"modifytimestamp",
"krbLastPwdChange",
"krbExtraData",
"krbObjectReferences",
NULL };
static char *attributes_set[] = { "krbmaxticketlife",
"krbmaxrenewableage",
"krbticketflags",
"krbprincipalexpiration",
"krbticketpolicyreference",
"krbUpEnabled",
"krbpwdpolicyreference",
"krbpasswordexpiration",
"krbprincipalkey",
"krblastpwdchange",
"krbextradata",
"krbLastSuccessfulAuth",
"krbLastFailedAuth",
"krbLoginFailedCount",
NULL };
void
krb5_dbe_free_contents(context, entry)
krb5_context context;
krb5_db_entry *entry;
{
krb5_tl_data *tl_data_next=NULL;
krb5_tl_data *tl_data=NULL;
int i, j;
if (entry->e_data)
free(entry->e_data);
if (entry->princ)
krb5_free_principal(context, entry->princ);
for (tl_data = entry->tl_data; tl_data; tl_data = tl_data_next) {
tl_data_next = tl_data->tl_data_next;
if (tl_data->tl_data_contents)
free(tl_data->tl_data_contents);
free(tl_data);
}
if (entry->key_data) {
for (i = 0; i < entry->n_key_data; i++) {
for (j = 0; j < entry->key_data[i].key_data_ver; j++) {
if (entry->key_data[i].key_data_length[j]) {
if (entry->key_data[i].key_data_contents[j]) {
memset(entry->key_data[i].key_data_contents[j],
0,
(unsigned) entry->key_data[i].key_data_length[j]);
free (entry->key_data[i].key_data_contents[j]);
}
}
entry->key_data[i].key_data_contents[j] = NULL;
entry->key_data[i].key_data_length[j] = 0;
entry->key_data[i].key_data_type[j] = 0;
}
}
free(entry->key_data);
}
memset(entry, 0, sizeof(*entry));
return;
}
krb5_error_code
krb5_ldap_free_principal(kcontext , entries, nentries)
krb5_context kcontext;
krb5_db_entry *entries;
int nentries;
{
register int i;
for (i = 0; i < nentries; i++)
krb5_dbe_free_contents(kcontext, &entries[i]);
return 0;
}
krb5_error_code
krb5_ldap_iterate(context, match_expr, func, func_arg)
krb5_context context;
char *match_expr;
krb5_error_code (*func) (krb5_pointer, krb5_db_entry *);
krb5_pointer func_arg;
{
krb5_db_entry entry;
krb5_principal principal;
char **subtree=NULL, *princ_name=NULL, *realm=NULL, **values=NULL, *filter=NULL;
unsigned int filterlen=0, tree=0, ntree=1, i=0;
krb5_error_code st=0, tempst=0;
LDAP *ld=NULL;
LDAPMessage *result=NULL, *ent=NULL;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
char *default_match_expr = "*";
krb5_clear_error_message(context);
memset(&entry, 0, sizeof(krb5_db_entry));
SETUP_CONTEXT();
realm = ldap_context->lrparams->realm_name;
if (realm == NULL) {
realm = context->default_realm;
if (realm == NULL) {
st = EINVAL;
krb5_set_error_message(context, st, "Default realm not set");
goto cleanup;
}
}
if (match_expr == NULL)
match_expr = default_match_expr;
filterlen = strlen(FILTER) + strlen(match_expr) + 2 + 1;
filter = malloc (filterlen);
CHECK_NULL(filter);
memset(filter, 0, filterlen);
sprintf(filter, FILTER"%s))", match_expr);
if ((st = krb5_get_subtree_info(ldap_context, &subtree, &ntree)) != 0)
goto cleanup;
GET_HANDLE();
for (tree=0; tree < ntree; ++tree) {
LDAP_SEARCH(subtree[tree], ldap_context->lrparams->search_scope, filter, principal_attributes);
for (ent=ldap_first_entry(ld, result); ent != NULL; ent=ldap_next_entry(ld, ent)) {
if ((values=ldap_get_values(ld, ent, "krbprincipalname")) != NULL) {
for (i=0; values[i] != NULL; ++i) {
if (values[i])
if (krb5_ldap_parse_principal_name(values[i], &princ_name) != 0)
continue;
if (krb5_parse_name(context, princ_name, &principal) != 0)
continue;
if (is_principal_in_realm(ldap_context, principal) == 0) {
if ((st = populate_krb5_db_entry(context, ldap_context, ld, ent, principal,
&entry)) != 0)
goto cleanup;
(*func)(func_arg, &entry);
krb5_dbe_free_contents(context, &entry);
(void) krb5_free_principal(context, principal);
if (princ_name)
free(princ_name);
break;
}
(void) krb5_free_principal(context, principal);
if (princ_name)
free(princ_name);
}
ldap_value_free(values);
}
}
ldap_msgfree(result);
}
cleanup:
if (filter)
free (filter);
for (;ntree; --ntree)
if (subtree[ntree-1])
free (subtree[ntree-1]);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
krb5_error_code
krb5_ldap_delete_principal(context, searchfor, nentries)
krb5_context context;
krb5_const_principal searchfor;
int *nentries;
{
char *user=NULL, *DN=NULL, *strval[10] = {NULL};
LDAPMod **mods=NULL;
LDAP *ld=NULL;
int j=0, ptype=0, pcount=0, attrsetmask=0;
krb5_error_code st=0;
krb5_boolean singleentry=FALSE;
KEY *secretkey=NULL;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
krb5_db_entry entries;
krb5_boolean more=0;
krb5_clear_error_message(context);
SETUP_CONTEXT();
if ((st=krb5_ldap_get_principal(context, searchfor, &entries, nentries, &more)) != 0 || *nentries == 0)
goto cleanup;
if (((st=krb5_get_princ_type(context, &entries, &(ptype))) != 0) ||
((st=krb5_get_attributes_mask(context, &entries, &(attrsetmask))) != 0) ||
((st=krb5_get_princ_count(context, &entries, &(pcount))) != 0) ||
((st=krb5_get_userdn(context, &entries, &(DN))) != 0))
goto cleanup;
if (DN == NULL) {
st = EINVAL;
krb5_set_error_message(context, st, "DN information missing");
goto cleanup;
}
GET_HANDLE();
if (ptype == KDB_STANDALONE_PRINCIPAL_OBJECT) {
st = ldap_delete_ext_s(ld, DN, NULL, NULL);
if (st != LDAP_SUCCESS) {
st = set_ldap_error (context, st, OP_DEL);
goto cleanup;
}
} else {
if (((st=krb5_unparse_name(context, searchfor, &user)) != 0)
|| ((st=krb5_ldap_unparse_principal_name(user)) != 0))
goto cleanup;
memset(strval, 0, sizeof(strval));
strval[0] = user;
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbprincipalname", LDAP_MOD_DELETE,
strval)) != 0)
goto cleanup;
singleentry = (pcount == 1) ? TRUE: FALSE;
if (singleentry == FALSE) {
if (secretkey != NULL) {
if ((st=krb5_add_ber_mem_ldap_mod(&mods, "krbprincipalkey", LDAP_MOD_DELETE | LDAP_MOD_BVALUES,
secretkey->keys)) != 0)
goto cleanup;
}
} else {
while (attrsetmask) {
if (attrsetmask & 1) {
if ((st=krb5_add_str_mem_ldap_mod(&mods, attributes_set[j], LDAP_MOD_DELETE,
NULL)) != 0)
goto cleanup;
}
attrsetmask >>= 1;
++j;
}
{
char *attrvalues[] = {"krbticketpolicyaux", "krbprincipalaux", NULL};
int p, q, r=0, amask=0;
if ((st=checkattributevalue(ld, DN, "objectclass", attrvalues, &amask)) != 0)
goto cleanup;
memset(strval, 0, sizeof(strval));
for (p=1, q=0; p<=4; p<<=1, ++q)
if (p & amask)
strval[r++] = attrvalues[q];
strval[r] = NULL;
if (r > 0) {
if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_DELETE,
strval)) != 0)
goto cleanup;
}
}
}
st=ldap_modify_ext_s(ld, DN, mods, NULL, NULL);
if (st != LDAP_SUCCESS) {
st = set_ldap_error(context, st, OP_MOD);
goto cleanup;
}
}
cleanup:
if (user)
free (user);
if (DN)
free (DN);
if (secretkey != NULL) {
int i=0;
while (i < secretkey->nkey) {
free (secretkey->keys[i]->bv_val);
free (secretkey->keys[i]);
++i;
}
free (secretkey->keys);
free (secretkey);
}
if (st == 0)
krb5_ldap_free_principal(context, &entries, *nentries);
ldap_mods_free(mods, 1);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
krb5_error_code
krb5_ldap_unparse_principal_name(char *user_name)
{
char *tmp_princ_name=NULL, *princ_name=NULL, *tmp=NULL;
int l=0;
krb5_error_code st=0;
if (strstr(user_name, "\\@")) {
tmp_princ_name = strdup(user_name);
if (!tmp_princ_name) {
st = ENOMEM;
goto cleanup;
}
tmp = tmp_princ_name;
princ_name = (char *) malloc (strlen(user_name));
if (!princ_name) {
st = ENOMEM;
goto cleanup;
}
memset(princ_name, 0, strlen(user_name));
l = 0;
while (*tmp_princ_name) {
if ((*tmp_princ_name == '\\') && (*(tmp_princ_name+1) == '@')) {
tmp_princ_name += 1;
} else {
*(princ_name + l) = *tmp_princ_name++;
l++;
}
}
memset(user_name, 0, strlen(user_name));
sprintf(user_name, "%s", princ_name);
}
cleanup:
if (tmp) {
free(tmp);
tmp = NULL;
}
if (princ_name) {
free(princ_name);
princ_name = NULL;
}
return st;
}
krb5_error_code
krb5_ldap_parse_principal_name(i_princ_name, o_princ_name)
char *i_princ_name;
char **o_princ_name;
{
char *tmp_princ_name = NULL, *princ_name = NULL, *at_rlm_name = NULL;
int l = 0, m = 0, tmp_princ_name_len = 0, princ_name_len = 0, at_count = 0;
krb5_error_code st = 0;
at_rlm_name = strrchr(i_princ_name, '@');
if (!at_rlm_name) {
*o_princ_name = strdup(i_princ_name);
if (!o_princ_name) {
st = ENOMEM;
goto cleanup;
}
} else {
tmp_princ_name_len = at_rlm_name - i_princ_name;
tmp_princ_name = (char *) malloc ((unsigned) tmp_princ_name_len + 1);
if (!tmp_princ_name) {
st = ENOMEM;
goto cleanup;
}
memset(tmp_princ_name, 0, (unsigned) tmp_princ_name_len + 1);
memcpy(tmp_princ_name, i_princ_name, (unsigned) tmp_princ_name_len);
l = 0;
while (tmp_princ_name[l]) {
if (tmp_princ_name[l++] == '@')
at_count++;
}
princ_name_len = strlen(i_princ_name) + at_count + 1;
princ_name = (char *) malloc ((unsigned) princ_name_len);
if (!princ_name) {
st = ENOMEM;
goto cleanup;
}
memset(princ_name, 0, (unsigned) princ_name_len);
l = 0;
m = 0;
while (tmp_princ_name[l]) {
if (tmp_princ_name[l] == '@') {
princ_name[m++]='\\';
}
princ_name[m++]=tmp_princ_name[l++];
}
strcat(princ_name, at_rlm_name);
*o_princ_name = princ_name;
}
cleanup:
if (tmp_princ_name) {
free(tmp_princ_name);
tmp_princ_name = NULL;
}
return st;
}