add LOCAL_PEERCRED and experimental doors support

git-svn-id: svn://svn.h5l.se/heimdal/trunk/heimdal@15249 ec53bebd-3082-4978-b11e-865c3cabbd6b
This commit is contained in:
Love Hörnquist Åstrand
2005-05-29 12:53:32 +00:00
parent a68cecf9a9
commit 4c4b29144e

View File

@@ -1,5 +1,5 @@
/*
* Copyright (c) 1997-2004 Kungliga Tekniska H<>gskolan
* Copyright (c) 1997-2005 Kungliga Tekniska H<>gskolan
* (Royal Institute of Technology, Stockholm, Sweden).
* All rights reserved.
*
@@ -85,15 +85,14 @@ update_client_creds(int s, kcm_client *peer)
/* Solaris 10 */
{
ucred_t *peercred;
if (getpeerucred(fd, &peercred) != 0) {
krb5_warn(kcm_context, errno, "failed to determine peer identity");
return 1;
peer->uid = ucred_geteuid(peercred);
peer->gid = ucred_getegid(peercred);
peer->pid = 0;
ucred_free(peercred);
return 0;
}
peer->uid = ucred_geteuid(peercred);
peer->gid = ucred_getegid(peercred);
peer->pid = 0;
ucred_free(peercred);
return 0;
}
#endif
#ifdef GETPEEREID
@@ -102,14 +101,12 @@ update_client_creds(int s, kcm_client *peer)
uid_t uid;
gid_t gid;
if (getpeereid(s, &uid, &gid) != 0) {
krb5_warn(kcm_context, errno, "failed to determine peer identity");
return 1;
if (getpeereid(s, &uid, &gid) == 0) {
peer->uid = uid;
peer->gid = gid;
peer->pid = 0;
return 0;
}
peer->uid = uid;
peer->gid = gid;
peer->pid = 0;
return 0;
}
#endif
#ifdef SO_PEERCRED
@@ -118,15 +115,28 @@ update_client_creds(int s, kcm_client *peer)
struct ucred pc;
socklen_t pclen = sizeof(pc);
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&pc,
&pclen) != 0) {
krb5_warn(kcm_context, errno, "failed to determine peer identity");
return 1;
if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, (void *)&pc, &pclen) == 0) {
peer->uid = pc.uid;
peer->gid = pc.gid;
peer->pid = pc.pid;
return 0;
}
}
#endif
#ifdef LOCAL_PEERCRED
{
struct xucred peercred;
socklen_t peercredlen = sizeof(peercred);
if (getsockopt(s, LOCAL_PEERCRED, 1,
(void *)&peercred, &peercredlen) == 0
&& peercred.cr_version == XUCRED_VERSION)
{
peer->uid = peercred.cr_uid;
peer->gid = peercred.cr_gid;
peer->pid = 0;
return 0;
}
peer->uid = pc.uid;
peer->gid = pc.gid;
peer->pid = pc.pid;
return 0;
}
#endif
#if defined(SOCKCREDSIZE) && defined(SCM_CREDS)
@@ -145,7 +155,7 @@ update_client_creds(int s, kcm_client *peer)
crmsg = malloc(crmsgsize);
if (crmsg == NULL)
return 1;
goto failed_scm_creds;
memset(crmsg, 0, crmsgsize);
@@ -154,18 +164,18 @@ update_client_creds(int s, kcm_client *peer)
if (recvmsg(s, &msg, 0) < 0) {
free(crmsg);
return 1;
goto failed_scm_creds;
}
if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) {
free(crmsg);
return 1;
goto failed_scm_creds;
}
cmp = CMSG_FIRSTHDR(&msg);
if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDS) {
free(crmsg);
return 1;
goto failed_scm_creds;
}
sc = (struct sockcred *)(void *)CMSG_DATA(cmp);
@@ -175,9 +185,15 @@ update_client_creds(int s, kcm_client *peer)
peer->pid = 0;
free(crmsg);
return 0;
} else {
/* we already got the cred, just return it */
return 0;
}
failed_scm_creds:
#endif
return 0;
krb5_warn(kcm_context, errno, "failed to determine peer identity");
return 1;
}
@@ -287,7 +303,8 @@ process_request(unsigned char *buf,
krb5_data request;
if (len < 4) {
kcm_log(1, "malformed request from process %d (too short)", client->pid);
kcm_log(1, "malformed request from process %d (too short)",
client->pid);
return -1;
}
@@ -515,15 +532,94 @@ handle_stream(struct descr *d, int index, int min_free)
}
}
#ifdef HAVE_DOORS
void
kcm_door_server(void *cookie, char *argp, size_t arg_size,
door_desc_t *dp, uint_t n_desc)
{
kcm_client peercred;
krb5_error_code ret;
krb5_data reply;
size_t length;
char *p;
reply.length = 0;
p = NULL;
length = 0;
if (door_cred(&info) != 0) {
kcm_log(0, "door_cred failed with %s", strerror(errno));
goto out;
}
peercred.uid = info.dc_euid;
peercred.gid = info.dc_egid;
peercred.pid = info.dc_pid;
ret = process_request(buf, len, &reply, &peercred);
if (reply.length != 0) {
p = alloca(reply.length); /* XXX don't use alloca */
if (p) {
memcpy(p, reply.data, reply.length);
length = reply.length;
}
krb5_data_free(&reply);
}
out:
return door_return(p, length, NULL, 0);
}
static char *door_path;
static void
kcm_setup_door(void)
{
int fd, ret;
char *path;
fd = door_create(kcm_door_server, NULL, 0);
if (fd < 0)
krb5_err(kcm_context, 1, errno, "Failed to create door");
if (door_path != NULL)
path = door_path;
else
path = _PATH_KCM_DOOR;
unlink(path);
ret = open(path, O_RDWR | O_CREAT, 0666);
if (ret < 0)
krb5_err(kcm_context, 1, errno, "Failed to create/open door");
close(ret);
ret = fattach(fd, path);
if (ret < 0)
krb5_err(kcm_context, 1, errno, "Failed to attach door");
}
#endif /* HAVE_DOORS */
void
kcm_loop(void)
{
struct descr *d;
int ndescr;
#ifdef HAVE_DOORS
kcm_setup_door();
#endif
ndescr = init_sockets(&d);
if (ndescr <= 0)
krb5_errx(kcm_context, 1, "No sockets!");
if (ndescr <= 0) {
krb5_warnx(kcm_context, "No sockets!");
#ifndef HAVE_DOORS
exit(1);
#endif
}
while (exit_flag == 0){
struct timeval tmout;
fd_set fds;