forked from unpbook/unpv13e
-
Notifications
You must be signed in to change notification settings - Fork 0
/
tfcred01.c
84 lines (68 loc) · 2.16 KB
/
tfcred01.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
#include "unp.h"
#include <sys/param.h>
#include <sys/ucred.h>
ssize_t recv_cred(int, void *, size_t, struct fcred *);
main()
{
int fd[2], on, n;
char buf[100];
struct fcred cred;
if (socketpair(AF_LOCAL, SOCK_STREAM, 0, fd) < 0)
err_sys("socketpair error");
/* must set the socket option on the *receiving* socket */
on = 1;
Setsockopt(fd[1], 0, LOCAL_CREDS, &on, sizeof(on));
Write(fd[0], "hello, world\n", 13);
if ( (n = recv_cred(fd[1], buf, sizeof(buf), &cred)) < 0)
err_sys("recv_cred error");
else if (n == 0)
err_quit("recv_cred, unexpected EOF");
buf[n] = 0; /* null terminate */
printf("data: %s", buf);
if (cred.fc_ngroups == 0)
printf("(no credentials returned)\n");
else {
printf("real user ID = %d\n", cred.fc_ruid);
printf("real group ID = %d\n", cred.fc_rgid);
printf("login name = %-*s\n", MAXLOGNAME, cred.fc_login);
printf("effective user ID = %d\n", cred.fc_uid);
printf("effective group ID = %d\n", cred.fc_gid);
printf("%d supplementary groups:", cred.fc_ngroups - 1);
for (n = 1; n < cred.fc_ngroups; n++) /* [0] is the egid */
printf(" %d", cred.fc_groups[n]);
printf("\n");
}
exit(0);
}
#define CONTROL_LEN (sizeof(struct cmsghdr) + sizeof(struct fcred))
ssize_t
recv_cred(int fd, void *ptr, size_t nbytes, struct fcred *fcredptr)
{
struct msghdr msg;
struct iovec iov[1];
char control[CONTROL_LEN + 20];
int n;
msg.msg_name = NULL;
msg.msg_namelen = 0;
iov[0].iov_base = ptr;
iov[0].iov_len = nbytes;
msg.msg_iov = iov;
msg.msg_iovlen = 1;
msg.msg_control = control;
msg.msg_controllen = sizeof(control);
msg.msg_flags = 0;
if ( (n = recvmsg(fd, &msg, 0)) < 0)
return(n);
fcredptr->fc_ngroups = 0; /* indicates no credentials returned */
if (fcredptr && msg.msg_controllen > 0) {
struct cmsghdr *cmptr = (struct cmsghdr *) control;
if (cmptr->cmsg_len != sizeof(struct cmsghdr) + sizeof(struct fcred))
err_quit("control length = %d", cmptr->cmsg_len);
if (cmptr->cmsg_level != SOL_SOCKET)
err_quit("control level != SOL_SOCKET");
if (cmptr->cmsg_type != SCM_CREDS)
err_quit("control type != SCM_CREDS");
memcpy(fcredptr, CMSG_DATA(cmptr), sizeof(struct fcred));
}
return(n);
}