/src/netbsd/src/external/bsd/openldap/dist/libraries/liblutil/getpeereid.c

https://bitbucket.org/killerpenguinassassins/open_distrib_devel · C · 222 lines · 165 code · 32 blank · 25 comment · 37 complexity · 2c755e1e9d93a5aea660067ec05d2789 MD5 · raw file

  1. /* $NetBSD: getpeereid.c,v 1.1.1.4 2010/12/12 15:22:08 adam Exp $ */
  2. /* getpeereid.c */
  3. /* OpenLDAP: pkg/ldap/libraries/liblutil/getpeereid.c,v 1.24.2.7 2010/04/13 20:23:05 kurt Exp */
  4. /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
  5. *
  6. * Copyright 2000-2010 The OpenLDAP Foundation.
  7. * All rights reserved.
  8. *
  9. * Redistribution and use in source and binary forms, with or without
  10. * modification, are permitted only as authorized by the OpenLDAP
  11. * Public License.
  12. *
  13. * A copy of this license is available in the file LICENSE in the
  14. * top-level directory of the distribution or, alternatively, at
  15. * <http://www.OpenLDAP.org/license.html>.
  16. */
  17. #ifndef _GNU_SOURCE
  18. #define _GNU_SOURCE 1 /* Needed for glibc struct ucred */
  19. #endif
  20. #include "portable.h"
  21. #ifndef HAVE_GETPEEREID
  22. #include <sys/types.h>
  23. #include <ac/unistd.h>
  24. #include <ac/socket.h>
  25. #include <ac/errno.h>
  26. #ifdef HAVE_GETPEERUCRED
  27. #include <ucred.h>
  28. #endif
  29. #ifdef LDAP_PF_LOCAL_SENDMSG
  30. #include <lber.h>
  31. #ifdef HAVE_SYS_UIO_H
  32. #include <sys/uio.h>
  33. #endif
  34. #include <sys/stat.h>
  35. #endif
  36. #ifdef HAVE_SYS_UCRED_H
  37. #ifdef HAVE_GRP_H
  38. #include <grp.h> /* for NGROUPS on Tru64 5.1 */
  39. #endif
  40. #include <sys/ucred.h>
  41. #endif
  42. #include <stdlib.h>
  43. int lutil_getpeereid( int s, uid_t *euid, gid_t *egid
  44. #ifdef LDAP_PF_LOCAL_SENDMSG
  45. , struct berval *peerbv
  46. #endif
  47. )
  48. {
  49. #ifdef LDAP_PF_LOCAL
  50. #if defined( HAVE_GETPEERUCRED )
  51. ucred_t *uc = NULL;
  52. if( getpeerucred( s, &uc ) == 0 ) {
  53. *euid = ucred_geteuid( uc );
  54. *egid = ucred_getegid( uc );
  55. ucred_free( uc );
  56. return 0;
  57. }
  58. #elif defined( SO_PEERCRED )
  59. struct ucred peercred;
  60. ber_socklen_t peercredlen = sizeof peercred;
  61. if(( getsockopt( s, SOL_SOCKET, SO_PEERCRED,
  62. (void *)&peercred, &peercredlen ) == 0 )
  63. && ( peercredlen == sizeof peercred ))
  64. {
  65. *euid = peercred.uid;
  66. *egid = peercred.gid;
  67. return 0;
  68. }
  69. #elif defined( LOCAL_PEERCRED )
  70. struct xucred peercred;
  71. ber_socklen_t peercredlen = sizeof peercred;
  72. if(( getsockopt( s, LOCAL_PEERCRED, 1,
  73. (void *)&peercred, &peercredlen ) == 0 )
  74. && ( peercred.cr_version == XUCRED_VERSION ))
  75. {
  76. *euid = peercred.cr_uid;
  77. *egid = peercred.cr_gid;
  78. return 0;
  79. }
  80. #elif defined( LDAP_PF_LOCAL_SENDMSG ) && defined( MSG_WAITALL )
  81. int err, fd;
  82. struct iovec iov;
  83. struct msghdr msg = {0};
  84. # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
  85. # ifndef CMSG_SPACE
  86. # define CMSG_SPACE(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
  87. # endif
  88. # ifndef CMSG_LEN
  89. # define CMSG_LEN(len) (_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
  90. # endif
  91. struct {
  92. struct cmsghdr cm;
  93. int fd;
  94. } control_st;
  95. struct cmsghdr *cmsg;
  96. # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
  97. struct stat st;
  98. struct sockaddr_un lname, rname;
  99. ber_socklen_t llen, rlen;
  100. rlen = sizeof(rname);
  101. llen = sizeof(lname);
  102. memset( &lname, 0, sizeof( lname ));
  103. getsockname(s, (struct sockaddr *)&lname, &llen);
  104. iov.iov_base = peerbv->bv_val;
  105. iov.iov_len = peerbv->bv_len;
  106. msg.msg_iov = &iov;
  107. msg.msg_iovlen = 1;
  108. peerbv->bv_len = 0;
  109. # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
  110. msg.msg_control = &control_st;
  111. msg.msg_controllen = sizeof( struct cmsghdr ) + sizeof( int ); /* no padding! */
  112. cmsg = CMSG_FIRSTHDR( &msg );
  113. # else
  114. msg.msg_accrights = (char *)&fd;
  115. msg.msg_accrightslen = sizeof(fd);
  116. # endif
  117. /*
  118. * AIX returns a bogus file descriptor if recvmsg() is
  119. * called with MSG_PEEK (is this a bug?). Hence we need
  120. * to receive the Abandon PDU.
  121. */
  122. err = recvmsg( s, &msg, MSG_WAITALL );
  123. if( err >= 0 &&
  124. # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
  125. cmsg->cmsg_len == CMSG_LEN( sizeof(int) ) &&
  126. cmsg->cmsg_level == SOL_SOCKET &&
  127. cmsg->cmsg_type == SCM_RIGHTS
  128. # else
  129. msg.msg_accrightslen == sizeof(int)
  130. # endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL*/
  131. ) {
  132. int mode = S_IFIFO|S_ISUID|S_IRWXU;
  133. /* We must receive a valid descriptor, it must be a pipe,
  134. * it must only be accessible by its owner, and it must
  135. * have the name of our socket written on it.
  136. */
  137. peerbv->bv_len = err;
  138. # ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
  139. fd = (*(int *)CMSG_DATA( cmsg ));
  140. # endif
  141. err = fstat( fd, &st );
  142. if ( err == 0 )
  143. rlen = read(fd, &rname, rlen);
  144. close(fd);
  145. if( err == 0 && st.st_mode == mode &&
  146. llen == rlen && !memcmp(&lname, &rname, llen))
  147. {
  148. *euid = st.st_uid;
  149. *egid = st.st_gid;
  150. return 0;
  151. }
  152. }
  153. #elif defined(SOCKCREDSIZE)
  154. struct msghdr msg;
  155. ber_socklen_t crmsgsize;
  156. void *crmsg;
  157. struct cmsghdr *cmp;
  158. struct sockcred *sc;
  159. memset(&msg, 0, sizeof msg);
  160. crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS));
  161. if (crmsgsize == 0) goto sc_err;
  162. crmsg = malloc(crmsgsize);
  163. if (crmsg == NULL) goto sc_err;
  164. memset(crmsg, 0, crmsgsize);
  165. msg.msg_control = crmsg;
  166. msg.msg_controllen = crmsgsize;
  167. if (recvmsg(s, &msg, 0) < 0) {
  168. free(crmsg);
  169. goto sc_err;
  170. }
  171. if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) {
  172. free(crmsg);
  173. goto sc_err;
  174. }
  175. cmp = CMSG_FIRSTHDR(&msg);
  176. if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDS) {
  177. printf("nocreds\n");
  178. goto sc_err;
  179. }
  180. sc = (struct sockcred *)(void *)CMSG_DATA(cmp);
  181. *euid = sc->sc_euid;
  182. *egid = sc->sc_egid;
  183. free(crmsg);
  184. return 0;
  185. sc_err:
  186. #endif
  187. #endif /* LDAP_PF_LOCAL */
  188. return -1;
  189. }
  190. #endif /* HAVE_GETPEEREID */