#include "kcm_locl.h"
#include <pwd.h>
krb5_error_code
kcm_ccache_resolve_client(krb5_context context,
kcm_client *client,
kcm_operation opcode,
const char *name,
kcm_ccache *ccache)
{
krb5_error_code ret;
ret = kcm_ccache_resolve_by_name(context, name, ccache);
if (ret) {
kcm_log(1, "Failed to resolve cache %s", name);
return ret;
}
ret = kcm_access(context, client, opcode, *ccache);
if (ret) {
ret = KRB5_FCC_NOFILE;
kcm_release_ccache(context, *ccache);
}
return ret;
}
krb5_error_code
kcm_ccache_destroy_client(krb5_context context,
kcm_client *client,
const char *name)
{
krb5_error_code ret;
kcm_ccache ccache;
ret = kcm_ccache_resolve_by_name(context, name, &ccache);
if (ret) {
kcm_log(1, "Failed to resolve cache %s", name);
return ret;
}
ret = kcm_access(context, client, KCM_OP_DESTROY, ccache);
kcm_release_ccache(context, ccache);
if (ret)
return ret;
return kcm_ccache_destroy(context, name);
}
krb5_error_code
kcm_ccache_new_client(krb5_context context,
kcm_client *client,
const char *name,
kcm_ccache *ccache_p)
{
krb5_error_code ret;
kcm_ccache ccache;
ret = kcm_ccache_resolve_by_name(context, name, &ccache);
if (ret == 0) {
if ((ccache->uid != client->uid) && !CLIENT_IS_ROOT(client))
return KRB5_FCC_PERM;
} else if (ret != KRB5_FCC_NOFILE && !(CLIENT_IS_ROOT(client) && ret == KRB5_FCC_PERM)) {
return ret;
}
if (ret == KRB5_FCC_NOFILE) {
ret = kcm_ccache_new(context, name, &ccache);
if (ret) {
kcm_log(1, "Failed to initialize cache %s", name);
return ret;
}
ccache->uid = client->uid;
ccache->session = client->session;
kcm_session_add(client->session);
} else {
ret = kcm_zero_ccache_data(context, ccache);
if (ret) {
kcm_log(1, "Failed to empty cache %s", name);
kcm_release_ccache(context, ccache);
return ret;
}
heim_ipc_event_cancel(ccache->renew_event);
heim_ipc_event_cancel(ccache->expire_event);
}
ret = kcm_access(context, client, KCM_OP_INITIALIZE, ccache);
if (ret) {
kcm_release_ccache(context, ccache);
kcm_ccache_destroy(context, name);
return ret;
}
if (CLIENT_IS_ROOT(client)) {
unsigned long uid;
int matches = sscanf(name,"%ld:",&uid);
if (matches == 0)
matches = sscanf(name,"%ld",&uid);
if (matches == 1) {
kcm_chown(context, client, ccache, (uid_t)uid);
}
}
*ccache_p = ccache;
return 0;
}
const char *
kcm_client_get_execpath(kcm_client *client)
{
if (client->execpath[0] == '\0') {
int ret = proc_pidpath(client->pid, client->execpath, sizeof(client->execpath));
if (ret != -1)
client->execpath[sizeof(client->execpath) - 1] = '\0';
else {
client->execpath[0] = 0x01;
client->execpath[1] = 0x0;
}
}
if (client->execpath[0] != '/')
return NULL;
return client->execpath;
}