#include "ldap_main.h"
#include "kdb_ldap.h"
#include "ldap_services.h"
#include "ldap_err.h"
#if defined(HAVE_EDIRECTORY)
static char *realmcontclass[] = {"krbRealmContainer", NULL};
krb5_error_code
krb5_ldap_create_service(context, service, mask)
krb5_context context;
krb5_ldap_service_params *service;
int mask;
{
int i=0, j=0;
krb5_error_code st=0;
LDAP *ld=NULL;
char **rdns=NULL, *realmattr=NULL, *strval[3]={NULL};
LDAPMod **mods=NULL;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
char errbuf[1024];
if (service == NULL || service->servicedn == NULL) {
st = EINVAL;
krb5_set_error_message (context, st, "Service DN NULL");
goto cleanup;
}
SETUP_CONTEXT();
GET_HANDLE();
memset(strval, 0, sizeof(strval));
strval[0] = "krbService";
if (service->servicetype == LDAP_KDC_SERVICE) {
strval[1] = "krbKdcService";
realmattr = "krbKdcServers";
} else if (service->servicetype == LDAP_ADMIN_SERVICE) {
strval[1] = "krbAdmService";
realmattr = "krbAdmServers";
} else if (service->servicetype == LDAP_PASSWD_SERVICE) {
strval[1] = "krbPwdService";
realmattr = "krbPwdServers";
} else {
strval[1] = "krbKdcService";
realmattr = "krbKdcServers";
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "objectclass", LDAP_MOD_ADD, strval)) != 0)
goto cleanup;
rdns = ldap_explode_dn(service->servicedn, 1);
if (rdns == NULL) {
st = LDAP_INVALID_DN_SYNTAX;
goto cleanup;
}
memset(strval, 0, sizeof(strval));
strval[0] = rdns[0];
if ((st=krb5_add_str_mem_ldap_mod(&mods, "cn", LDAP_MOD_ADD, strval)) != 0)
goto cleanup;
if (mask & LDAP_SERVICE_SERVICEFLAG) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbserviceflags", LDAP_MOD_ADD,
service->krbserviceflags)) != 0)
goto cleanup;
}
if (mask & LDAP_SERVICE_HOSTSERVER) {
if (service->krbhostservers != NULL) {
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbhostserver", LDAP_MOD_ADD,
service->krbhostservers)) != 0)
goto cleanup;
} else {
st = EINVAL;
krb5_set_error_message (context, st, "'krbhostserver' argument invalid");
goto cleanup;
}
}
if (mask & LDAP_SERVICE_REALMREFERENCE) {
if (service->krbrealmreferences != NULL) {
unsigned int realmmask=0;
for (j=0; service->krbrealmreferences[j] != NULL; ++j) {
st = checkattributevalue(ld, service->krbrealmreferences[j], "ObjectClass",
realmcontclass, &realmmask);
CHECK_CLASS_VALIDITY(st, realmmask, "realm object value: ");
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbrealmreferences", LDAP_MOD_ADD,
service->krbrealmreferences)) != 0)
goto cleanup;
} else {
st = EINVAL;
krb5_set_error_message (context, st, "Server has no 'krbrealmreferences'");
goto cleanup;
}
}
if ((st=ldap_add_ext_s(ld, service->servicedn, mods, NULL, NULL)) != LDAP_SUCCESS) {
st = set_ldap_error (context, st, OP_ADD);
goto cleanup;
}
if (mask & LDAP_SERVICE_REALMREFERENCE) {
for (i=0; service->krbrealmreferences[i]; ++i) {
if ((st=updateAttribute(ld, service->krbrealmreferences[i], realmattr,
service->servicedn)) != 0) {
sprintf (errbuf, "Error adding 'krbRealmReferences' to %s: ",
service->krbrealmreferences[i]);
prepend_err_str (context, errbuf, st, st);
ldap_delete_ext_s(ld, service->servicedn, NULL, NULL);
goto cleanup;
}
}
}
cleanup:
if (rdns)
ldap_value_free (rdns);
ldap_mods_free(mods, 1);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
krb5_error_code
krb5_ldap_modify_service(context, service, mask)
krb5_context context;
krb5_ldap_service_params *service;
int mask;
{
int i=0, j=0, count=0;
krb5_error_code st=0;
LDAP *ld=NULL;
char **values=NULL, *attr[] = { "krbRealmReferences", NULL};
char *realmattr=NULL;
char **oldrealmrefs=NULL, **newrealmrefs=NULL;
LDAPMod **mods=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;
if (service == NULL || service->servicedn == NULL) {
st = EINVAL;
krb5_set_error_message (context, st, "Service DN is NULL");
goto cleanup;
}
SETUP_CONTEXT();
GET_HANDLE();
if (mask & LDAP_SERVICE_SERVICEFLAG) {
if ((st=krb5_add_int_mem_ldap_mod(&mods, "krbserviceflags", LDAP_MOD_REPLACE,
service->krbserviceflags)) != 0)
goto cleanup;
}
if (mask & LDAP_SERVICE_HOSTSERVER) {
if (service->krbhostservers != NULL) {
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbhostserver", LDAP_MOD_REPLACE,
service->krbhostservers)) != 0)
goto cleanup;
} else {
st = EINVAL;
krb5_set_error_message (context, st, "'krbhostserver' value invalid");
goto cleanup;
}
}
if (mask & LDAP_SERVICE_REALMREFERENCE) {
if (service->krbrealmreferences != NULL) {
unsigned int realmmask=0;
for (j=0; service->krbrealmreferences[j]; ++j) {
st = checkattributevalue(ld, service->krbrealmreferences[j], "ObjectClass",
realmcontclass, &realmmask);
CHECK_CLASS_VALIDITY(st, realmmask, "realm object value: ");
}
if ((st=krb5_add_str_mem_ldap_mod(&mods, "krbrealmreferences", LDAP_MOD_REPLACE,
service->krbrealmreferences)) != 0)
goto cleanup;
if (service->servicetype == LDAP_KDC_SERVICE)
realmattr = "krbKdcServers";
else if (service->servicetype == LDAP_ADMIN_SERVICE)
realmattr = "krbAdmservers";
else if (service->servicetype == LDAP_PASSWD_SERVICE)
realmattr = "krbPwdServers";
else
realmattr = "krbKdcServers";
if ((st = ldap_search_ext_s (ld,
service->servicedn,
LDAP_SCOPE_BASE,
0,
attr,
0,
NULL,
NULL,
NULL,
0,
&result)) != LDAP_SUCCESS) {
st = set_ldap_error (context, st, OP_SEARCH);
goto cleanup;
}
ent = ldap_first_entry(ld, result);
if (ent) {
if ((values=ldap_get_values(ld, ent, "krbRealmReferences")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &oldrealmrefs, count)) != 0)
goto cleanup;
ldap_value_free(values);
}
}
ldap_msgfree(result);
} else {
st = EINVAL;
krb5_set_error_message (context, st, "'krbRealmReferences' value invalid");
goto cleanup;
}
}
if ((st=ldap_modify_ext_s(ld, service->servicedn, mods, NULL, NULL)) != LDAP_SUCCESS) {
st = set_ldap_error (context, st, OP_MOD);
goto cleanup;
}
if (mask & LDAP_SERVICE_REALMREFERENCE) {
for (i=0; service->krbrealmreferences[i]; ++i)
;
if ((st=copy_arrays(service->krbrealmreferences, &newrealmrefs, i)) != 0)
goto cleanup;
if (disjoint_members(oldrealmrefs, newrealmrefs) != 0)
goto cleanup;
if (oldrealmrefs) {
for (i=0; oldrealmrefs[i]; ++i)
if ((st=deleteAttribute(ld, oldrealmrefs[i], realmattr, service->servicedn)) != 0) {
prepend_err_str (context, "Error deleting realm attribute:", st, st);
goto cleanup;
}
}
for (i=0; newrealmrefs[i]; ++i)
if ((st=updateAttribute(ld, newrealmrefs[i], realmattr, service->servicedn)) != 0) {
prepend_err_str (context, "Error updating realm attribute: ", st, st);
goto cleanup;
}
}
cleanup:
if (oldrealmrefs) {
for (i=0; oldrealmrefs[i]; ++i)
free (oldrealmrefs[i]);
free (oldrealmrefs);
}
if (newrealmrefs) {
for (i=0; newrealmrefs[i]; ++i)
free (newrealmrefs[i]);
free (newrealmrefs);
}
ldap_mods_free(mods, 1);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
krb5_error_code
krb5_ldap_delete_service(context, service, servicedn)
krb5_context context;
krb5_ldap_service_params *service;
char *servicedn;
{
krb5_error_code st = 0;
LDAP *ld=NULL;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_context *ldap_context=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
SETUP_CONTEXT();
GET_HANDLE();
st = ldap_delete_ext_s(ld, servicedn, NULL, NULL);
if (st != 0) {
st = set_ldap_error (context, st, OP_DEL);
}
#ifndef HAVE_EDIRECTORY
{
int i=0;
char *attr=NULL;
if (service) {
if (service->krbrealmreferences) {
if (service->servicetype == LDAP_KDC_SERVICE)
attr = "krbkdcservers";
else if (service->servicetype == LDAP_ADMIN_SERVICE)
attr = "krbadmservers";
else if (service->servicetype == LDAP_PASSWD_SERVICE)
attr = "krbpwdservers";
for (i=0; service->krbrealmreferences[i]; ++i) {
deleteAttribute(ld, service->krbrealmreferences[i], attr, servicedn);
}
}
}
}
#endif
cleanup:
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
krb5_error_code
krb5_ldap_list_services(context, containerdn, services)
krb5_context context;
char *containerdn;
char ***services;
{
return (krb5_ldap_list(context, services, "krbService", containerdn));
}
krb5_error_code
krb5_ldap_read_service(context, servicedn, service, omask)
krb5_context context;
char *servicedn;
krb5_ldap_service_params **service;
int *omask;
{
char **values=NULL;
int i=0, count=0, objectmask=0;
krb5_error_code st=0, tempst=0;
LDAPMessage *result=NULL,*ent=NULL;
char *attributes[] = {"krbHostServer", "krbServiceflags",
"krbRealmReferences", "objectclass", NULL};
char *attrvalues[] = {"krbService", NULL};
krb5_ldap_service_params *lservice=NULL;
krb5_ldap_context *ldap_context=NULL;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
LDAP *ld = NULL;
if (servicedn == NULL) {
st = EINVAL;
krb5_set_error_message (context, st, "Service DN NULL");
goto cleanup;
}
SETUP_CONTEXT();
GET_HANDLE();
*omask = 0;
st = checkattributevalue(ld, servicedn, "objectClass", attrvalues, &objectmask);
CHECK_CLASS_VALIDITY(st, objectmask, "service object value: ");
lservice =(krb5_ldap_service_params *) calloc(1, sizeof(krb5_ldap_service_params));
if (lservice == NULL) {
st = ENOMEM;
goto cleanup;
}
lservice->tl_data = calloc (1, sizeof(*lservice->tl_data));
if (lservice->tl_data == NULL) {
st = ENOMEM;
goto cleanup;
}
lservice->tl_data->tl_data_type = KDB_TL_USER_INFO;
LDAP_SEARCH(servicedn, LDAP_SCOPE_BASE, "(objectclass=krbService)", attributes);
lservice->servicedn = strdup(servicedn);
CHECK_NULL(lservice->servicedn);
ent=ldap_first_entry(ld, result);
if (ent != NULL) {
if ((values=ldap_get_values(ld, ent, "krbServiceFlags")) != NULL) {
lservice->krbserviceflags = atoi(values[0]);
*omask |= LDAP_SERVICE_SERVICEFLAG;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbHostServer")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &(lservice->krbhostservers), count)) != 0)
goto cleanup;
*omask |= LDAP_SERVICE_HOSTSERVER;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "krbRealmReferences")) != NULL) {
count = ldap_count_values(values);
if ((st=copy_arrays(values, &(lservice->krbrealmreferences), count)) != 0)
goto cleanup;
*omask |= LDAP_SERVICE_REALMREFERENCE;
ldap_value_free(values);
}
if ((values=ldap_get_values(ld, ent, "objectClass")) != NULL) {
for (i=0; values[i]; ++i) {
if (strcasecmp(values[i], "krbKdcService") == 0) {
lservice->servicetype = LDAP_KDC_SERVICE;
break;
}
if (strcasecmp(values[i], "krbAdmService") == 0) {
lservice->servicetype = LDAP_ADMIN_SERVICE;
break;
}
if (strcasecmp(values[i], "krbPwdService") == 0) {
lservice->servicetype = LDAP_PASSWD_SERVICE;
break;
}
}
ldap_value_free(values);
}
}
ldap_msgfree(result);
cleanup:
if (st != 0) {
krb5_ldap_free_service(context, lservice);
*service = NULL;
} else {
store_tl_data(lservice->tl_data, KDB_TL_MASK, omask);
*service = lservice;
}
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
krb5_error_code
krb5_ldap_free_service(context, service)
krb5_context context;
krb5_ldap_service_params *service;
{
int i=0;
if (service == NULL)
return 0;
if (service->servicedn)
free (service->servicedn);
if (service->krbrealmreferences) {
for (i=0; service->krbrealmreferences[i]; ++i)
free (service->krbrealmreferences[i]);
free (service->krbrealmreferences);
}
if (service->krbhostservers) {
for (i=0; service->krbhostservers[i]; ++i)
free (service->krbhostservers[i]);
free (service->krbhostservers);
}
if (service->tl_data) {
if (service->tl_data->tl_data_contents)
free (service->tl_data->tl_data_contents);
free (service->tl_data);
}
free (service);
return 0;
}
krb5_error_code
krb5_ldap_set_service_passwd(context, service, passwd)
krb5_context context;
char *service;
char *passwd;
{
krb5_error_code st=0;
LDAPMod **mods=NULL;
char *password[2] = {NULL};
LDAP *ld=NULL;
krb5_ldap_context *ldap_context=NULL;
kdb5_dal_handle *dal_handle=NULL;
krb5_ldap_server_handle *ldap_server_handle=NULL;
password[0] = passwd;
SETUP_CONTEXT();
GET_HANDLE();
if ((st=krb5_add_str_mem_ldap_mod(&mods, "userPassword", LDAP_MOD_REPLACE, password)) != 0)
goto cleanup;
st = ldap_modify_ext_s(ld, service, mods, NULL, NULL);
if (st) {
st = set_ldap_error (context, st, OP_MOD);
}
cleanup:
ldap_mods_free(mods, 1);
krb5_ldap_put_handle_to_pool(ldap_context, ldap_server_handle);
return st;
}
#endif