tfcred01.c 2.2 KB

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