getsocketpeer.c 4.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159
  1. /** BEGIN COPYRIGHT BLOCK
  2. * This Program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; version 2 of the License.
  3. *
  4. * This Program is distributed in the hope that it will be useful, but WITHOUT
  5. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.
  6. *
  7. * You should have received a copy of the GNU General Public License along with
  8. * this Program; if not, write to the Free Software Foundation, Inc., 59 Temple
  9. * Place, Suite 330, Boston, MA 02111-1307 USA.
  10. *
  11. * In addition, as a special exception, Red Hat, Inc. gives You the additional
  12. * right to link the code of this Program with code not covered under the GNU
  13. * General Public License ("Non-GPL Code") and to distribute linked combinations * including the two, subject to the limitations in this paragraph. Non-GPL Code * permitted under this exception must only link to the code of this Program
  14. * through those well defined interfaces identified in the file named EXCEPTION
  15. * found in the source code files (the "Approved Interfaces"). The files of
  16. * Non-GPL Code may instantiate templates or use macros or inline functions from * the Approved Interfaces without causing the resulting work to be covered by
  17. * the GNU General Public License. Only Red Hat, Inc. may make changes or
  18. * additions to the list of Approved Interfaces. You must obey the GNU General
  19. * Public License in all respects for all of the Program code and other code used
  20. * in conjunction with the Program except the Non-GPL Code covered by this
  21. * exception. If you modify this file, you may extend this exception to your
  22. * version of the file, but you are not obligated to do so. If you do not wish to
  23. * provide this exception without modification, you must delete this exception
  24. * statement from your version and license this file solely under the GPL without
  25. * exception.
  26. *
  27. *
  28. * Copyright (C) 2007 Red Hat, Inc.
  29. * All rights reserved.
  30. * END COPYRIGHT BLOCK **/
  31. #ifdef HAVE_CONFIG_H
  32. # include <config.h>
  33. #endif
  34. #if defined(ENABLE_LDAPI)
  35. #if defined(HAVE_GETPEERUCRED)
  36. #include <ucred.h>
  37. #endif
  38. #include <sys/types.h>
  39. #include <unistd.h>
  40. #include <sys/socket.h>
  41. /* nspr secrets - we need to do an end run around nspr
  42. in order to do things it does not support
  43. */
  44. #include <private/pprio.h>
  45. int slapd_get_socket_peer(PRFileDesc *nspr_fd, uid_t *uid, gid_t *gid)
  46. {
  47. int ret = -1;
  48. int fd = PR_FileDesc2NativeHandle(nspr_fd); /* naughty private func */
  49. #if defined(SO_PEERCRED) /* linux */
  50. struct ucred creds;
  51. socklen_t len = sizeof(creds);
  52. if(0 == getsockopt(fd, SOL_SOCKET, SO_PEERCRED, (void*)&creds, &len ))
  53. {
  54. if(sizeof(creds) == len)
  55. {
  56. if(uid)
  57. *uid = creds.uid;
  58. if(gid)
  59. *gid = creds.gid;
  60. ret = 0;
  61. }
  62. }
  63. #elif defined(HAVE_GETPEERUCRED) /* solaris10 */
  64. ucred_t *creds = 0;
  65. if(0 == getpeerucred(fd, &creds))
  66. {
  67. if(uid)
  68. {
  69. *uid = ucred_getruid(creds);
  70. if(-1 != uid)
  71. ret = 0;
  72. }
  73. if(gid)
  74. {
  75. *gid = ucred_getrgid(creds);
  76. if(-1 == *gid)
  77. ret = -1;
  78. else
  79. ret = 0;
  80. }
  81. ucred_free(creds);
  82. }
  83. #elif defined(HAVE_GETPEEREID) /* osx / some BSDs */
  84. if(0 == getpeereid(fd, &uid, &gid))
  85. ret = 0;
  86. #else /* hpux / Solaris9 / some BSDs - file descriptor cooperative auth */
  87. #include <string.h>
  88. #include <sys/types.h>
  89. #include <sys/stat.h>
  90. #include <errno.h>
  91. struct msghdr msg;
  92. struct iovec iov;
  93. char dummy[8];
  94. int pass_sd[2];
  95. int rc = 0;
  96. unsigned int retrycnt = 0xffffffff; /* safety net */
  97. int myerrno = 0;
  98. memset((void *)&msg, 0, sizeof(msg));
  99. iov.iov_base = dummy;
  100. iov.iov_len = sizeof(dummy);
  101. msg.msg_iov = &iov;
  102. msg.msg_iovlen = 1;
  103. msg.msg_accrights = (caddr_t)&pass_sd;
  104. msg.msg_accrightslen = sizeof(pass_sd); /* Initialize it with 8 bytes.
  105. If recvmsg is successful,
  106. 4 is supposed to be returned. */
  107. /*
  108. Since PR_SockOpt_Nonblocking is set to the socket,
  109. recvmsg returns immediately if no data is waiting to be received.
  110. If recvmsg returns an error and EGAIN (== EWOULDBLOCK) is set to errno,
  111. we should retry some time.
  112. */
  113. while ((rc = recvmsg(fd, &msg, MSG_PEEK)) < 0 && (EAGAIN == (myerrno = errno)) && retrycnt-- >= 0)
  114. ;
  115. if (rc >= 0 && msg.msg_accrightslen == sizeof(int))
  116. {
  117. struct stat st;
  118. ret = fstat(pass_sd[0], &st);
  119. if(0 == ret && S_ISFIFO(st.st_mode) &&
  120. 0 == (st.st_mode & (S_IRWXG|S_IRWXO)))
  121. {
  122. if(uid)
  123. *uid = st.st_uid;
  124. if(gid)
  125. *gid = st.st_gid;
  126. } else {
  127. ret = -1;
  128. }
  129. }
  130. #endif
  131. return ret;
  132. }
  133. #endif /* ENABLE_LDAPI */