Ejemplo n.º 1
0
/*
 * Get other side's uid for UNIX socket.
 *
 * Standardise on getpeereid() from BSDs.
 */
int getpeereid(int fd, uid_t *uid_p, gid_t *gid_p)
{
#ifdef SO_PEERCRED
	struct ucred cred;
	socklen_t len = sizeof(cred);
	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) >= 0) {
		*uid_p = cred.uid;
		*gid_p = cred.gid;
		return 0;
	}
#else /* !SO_PEERCRED */
#ifdef HAVE_GETPEERUCRED
	ucred_t *cred = NULL;
	if (getpeerucred(fd, &cred) >= 0) {
		*uid_p = ucred_geteuid(cred);
		*gid_p = ucred_getegid(cred);
		ucred_free(cred);
		if ((int)*uid_p == -1 || (int)*gid_p == -1)
			return -1;
		return 0;
	}
#else
	errno = ENOSYS;
#endif /* HAVE_GETPEERUCRED */
#endif /* !SO_PEERCRED */
	return -1;
}
Ejemplo n.º 2
0
int
auth_recv (m_msg_t m, uid_t *uid, gid_t *gid)
{
    ucred_t *ucred = NULL;
    uid_t    uid_tmp;
    gid_t    gid_tmp;
    int      rc = -1;

    if (getpeerucred (m->sd, &ucred) < 0) {
        log_msg (LOG_ERR, "Failed to get peer ucred: %s", strerror (errno));
    }
    else if ((uid_tmp = ucred_geteuid (ucred)) < 0) {
        log_msg (LOG_ERR, "Failed to get peer UID: %s", strerror (errno));
    }
    else if ((gid_tmp = ucred_getegid (ucred)) < 0) {
        log_msg (LOG_ERR, "Failed to get peer GID: %s", strerror (errno));
    }
    else {
        *uid = uid_tmp;
        *gid = gid_tmp;
        rc = 0;
    }

    if (ucred) {
        ucred_free (ucred);
    }
    return (rc);
}
Ejemplo n.º 3
0
int getpeereid(int sock, uid_t *euid, gid_t *egid)
{
    int rc = -1;

#ifdef HAVE_GETPEERUCRED
    ucred_t *cred;

    rc = getpeerucred(sock, &cred);
    if (rc == 0) {
	if (euid) *euid = ucred_geteuid(cred);
	if (egid) *egid = ucred_getegid(cred);
	ucred_free(cred);
    }
#elif 0 // defined(SO_PEERCRED)
    struct ucred cred;
    socklen_t len = sizeof(struct ucred);

    rc = getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &cred, &len);
    if (rc == 0) {
	if (euid) *euid = cred.uid;
	if (egid) *egid = cred.gid;
    }
#else
//#warning "Need getpeereid(), getpeerucred(), or getsockopt(SO_PEERCRED) support"
    if (euid) *euid = 65534; /* nobody */
    if (egid) *egid = 65534; /* nogroup */
#endif
    return rc;
}
Ejemplo n.º 4
0
/*
 * Set local connection credentials into given hash structure
 */
int
__pmServerSetLocalCreds(int fd, __pmHashCtl *attrs)
{
#if defined(HAVE_STRUCT_UCRED)		/* Linux */
    struct ucred ucred;
    __pmSockLen length = sizeof(ucred);

    if (__pmGetSockOpt(fd, SOL_SOCKET, SO_PEERCRED, &ucred, &length) < 0)
	return -oserror();
    return SetCredentialAttrs(attrs, ucred.pid, ucred.uid, ucred.gid);

#elif defined(HAVE_GETPEEREID)		/* MacOSX */
    uid_t uid;
    gid_t gid;

    if (getpeereid(__pmFD(fd), &uid, &gid) < 0)
	return -oserror();
    return SetCredentialAttrs(attrs, 0, uid, gid);

#elif defined(HAVE_GETPEERUCRED)	/* Solaris */
    unsigned int uid, gid, pid;
    ucred_t *ucred = NULL;

    if (getpeerucred(__pmFD(fd), &ucred) < 0)
	return -oserror();
    pid = ucred_getpid(ucred);
    uid = ucred_geteuid(ucred);
    gid = ucred_getegid(ucred);
    ucred_free(ucred);
    return SetCredentialAttrs(attrs, pid, uid, gid);

#else
    return -EOPNOTSUPP;
#endif
}
Ejemplo n.º 5
0
/**
 * pfl_socket_getpeercred - Retrieve credentials of process on other end
 *	of a UNIX domain socket.
 * @s: socket file descriptor.
 * @uid: value-result user ID.
 * @gid: value-result group ID.
 */
int
pfl_socket_getpeercred(int s, uid_t *uid, gid_t *gid)
{
#ifdef HAVE_GETPEEREID
	if (getpeereid(s, uid, gid) == -1)
		return (errno);
#elif defined(HAVE_GETPEERUCRED)
	ucred_t *ucr;

	if (getpeerucred(s, &ucr) == -1)
		return (errno);
	*uid = ucred_geteuid(ucr);
	*gid = ucred_getegid(ucr);
	ucred_free(ucr);
#else
	struct ucred ucr;
	socklen_t len;

	len = sizeof(ucr);
	if (getsockopt(s, SOL_SOCKET, SO_PEERCRED, &ucr, &len))
		return (errno);
	*uid = ucr.uid;
	*gid = ucr.gid;
#endif
	return (0);
}
Ejemplo n.º 6
0
// Calls from the door function to check that the client credentials
// match this process. Returns 0 if credentials okay, otherwise -1.
static int check_credentials() {
  ucred_t *cred_info = NULL;
  int ret = -1; // deny by default

  // get client credentials
  if (door_ucred(&cred_info) == -1) {
    return -1; // unable to get them, deny
  }

  // get our euid/eguid (probably could cache these)
  uid_t euid = geteuid();
  gid_t egid = getegid();

  // get euid/egid from ucred_free
  uid_t ucred_euid = ucred_geteuid(cred_info);
  gid_t ucred_egid = ucred_getegid(cred_info);

  // check that the effective uid/gid matches
  if (ucred_euid == euid && ucred_egid == egid) {
    ret =  0;  // allow
  }

  ucred_free(cred_info);
  return ret;
}
Ejemplo n.º 7
0
/*
 * call-seq:
 *   basicsocket.getpeereid => [euid, egid]
 *
 * Returns the user and group on the peer of the UNIX socket.
 * The result is a two element array which contains the effective uid and the effective gid.
 *
 *   Socket.unix_server_loop("/tmp/sock") {|s|
 *     begin
 *       euid, egid = s.getpeereid
 *
 *       # Check the connected client is myself or not.
 *       next if euid != Process.uid
 *
 *       # do something about my resource.
 *
 *     ensure
 *       s.close
 *     end
 *   }
 *
 */
static VALUE
bsock_getpeereid(VALUE self)
{
UNRUBBY_SOCKET_HACK;
#if defined(HAVE_GETPEEREID)
    rb_io_t *fptr;
    uid_t euid;
    gid_t egid;
    GetOpenFile(self, fptr);
    if (getpeereid(fptr->fd, &euid, &egid) == -1)
	rb_sys_fail("getpeereid");
    return rb_assoc_new(UIDT2NUM(euid), GIDT2NUM(egid));
#elif defined(SO_PEERCRED) /* GNU/Linux */
    rb_io_t *fptr;
    struct ucred cred;
    socklen_t len = sizeof(cred);
    GetOpenFile(self, fptr);
    if (getsockopt(fptr->fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == -1)
	rb_sys_fail("getsockopt(SO_PEERCRED)");
    return rb_assoc_new(UIDT2NUM(cred.uid), GIDT2NUM(cred.gid));
#elif defined(HAVE_GETPEERUCRED) /* Solaris */
    rb_io_t *fptr;
    ucred_t *uc = NULL;
    VALUE ret;
    GetOpenFile(self, fptr);
    if (getpeerucred(fptr->fd, &uc) == -1)
	rb_sys_fail("getpeerucred");
    ret = rb_assoc_new(UIDT2NUM(ucred_geteuid(uc)), GIDT2NUM(ucred_getegid(uc)));
    ucred_free(uc);
    return ret;
#endif
}
Ejemplo n.º 8
0
Archivo: cred.c Proyecto: gpg/payproc
/* Retrieve the credentials from the peer using the connect file
   descriptor FD.  Returns 0 on success or -1 on error.  */
int
credentials_from_socket (int fd, pid_t *r_pid, uid_t *r_uid, gid_t *r_gid)
{
  int rc = -1;

#ifdef HAVE_SO_PEERCRED
  {
    struct ucred cr;
    socklen_t cl = sizeof cr;

    if (!getsockopt (fd, SOL_SOCKET, SO_PEERCRED, &cr, &cl))
      {
         *r_pid = cr.pid;
         *r_uid = cr.uid;
         *r_gid = cr.gid;
         rc = 0;
      }
  }
#elif defined (HAVE_GETPEERUCRED)
  {
    ucred_t *ucred = NULL;

    if (getpeerucred (fd, &ucred) != -1)
      {
	*r_pid = ucred_getpid (ucred);
        *r_uid = ucred_geteuid (ucred);
        *r_gid = ucred_getegid (ucred);
        rc = 0;
	ucred_free (ucred);
      }
  }
#elif defined (HAVE_LOCAL_PEEREID)
  {
    struct unpcbid unp;
    socklen_t unpl = sizeof unp;

    if (getsockopt (fd, 0, LOCAL_PEEREID, &unp, &unpl) != -1)
      {
	*r_pid = unp.unp_pid;
	*r_uid = unp.unp_euid;
	*r_gid = unp.unp_egid;
	rc = 0;
      }
  }
#elif defined(HAVE_GETPEEREID)
  {
    if (getpeereid (fd, r_uid, r_gid) != -1)
      {
	r_pid = (pid_t)(-1);
	rc = 0;
      }
  }
#endif

  return rc;
}
Ejemplo n.º 9
0
int main (void)
{
  ucred_t *cred ;
  uid_t uid ;
  gid_t gid ;
  int s = 0 ;
  getpeerucred(s, &cred) ;
  uid = ucred_geteuid(cred) ;
  gid = ucred_getegid(cred) ;
  ucred_free(cred) ;
  return 0 ;
}
Ejemplo n.º 10
0
Archivo: auth.c Proyecto: Feechka/UOBP
static int
checkPeerGroup (PeerCredentials *credentials, const MethodDescriptor_group *group) {
  if (group->id == ucred_getegid(*credentials)) return 1;

  {
    const gid_t *groups;
    int count = ucred_getgroups(*credentials, &groups);
    while (count > 0)
      if (group->id == groups[--count])
        return 1;
  }

  return 0;
}
Ejemplo n.º 11
0
int
getpeereid(int s, uid_t *euid, gid_t *egid)
{
	ucred_t *cred = alloca(ucred_size());
	int ret;

	ret = getpeerucred(s, &cred);
	if (ret != 0)
		return ret;

	*euid = ucred_geteuid(cred);
	if (*euid < 0)
		return -1;
	*egid = ucred_getegid(cred);
	if (*egid < 0)
		return -1;

	return 0;
}
Ejemplo n.º 12
0
/*
 * check_auth() checks if a given cred has
 * the authorization to create/remove targets/initiators/tpgt
 * cred is from the door call.
 */
Boolean_t
check_auth_addremove(ucred_t *cred)
{
	targ_scf_t *h = NULL;
	Boolean_t ret = False;
	int exit_code = 1;
	uid_t uid;
	gid_t gid;
	pid_t pid;
	const priv_set_t	*eset;

	pid = fork();

	switch (pid) {
	case 0:
		/* Child process to check authorization */
		uid = ucred_geteuid(cred);
		if (seteuid(uid) != 0) {
			syslog(LOG_ERR, "not priviliged\n");
			exit(-1);
		}

		gid = ucred_getegid(cred);
		if (setegid(gid) != 0) {
			syslog(LOG_ERR, "not priviliged\n");
			exit(-1);
		}

		eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
		setppriv(PRIV_ON, PRIV_EFFECTIVE, eset);

		h = mgmt_handle_init();

		if (h == NULL) {
			exit(1);
		}
		if (mgmt_transaction_start(h, "dummy", "dummy") == True) {
			scf_pg_delete(h->t_pg);
			mgmt_transaction_end(h);
			exit_code = 0;
		} else {
			exit_code = 1;
		}
		mgmt_handle_fini(h);
		exit(exit_code);
		break;
	case -1:
		/* Fail to fork */
		exit(SMF_EXIT_ERR_CONFIG);
	default:
		wait(&exit_code);
		exit_code = exit_code >> 8;
		if (exit_code == 0)
			ret = True;
		else
			ret = False;
		break;
	}

	return (ret);
}
Ejemplo n.º 13
0
value netsys_get_peer_credentials(value fd) {
    CAMLparam1(fd);
    CAMLlocal1(result);

#if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(HAVE_GETPEERUCRED)
    uid_t uid;
    gid_t gid;
#else
    int uid;
    int gid;
#endif

#if defined(HAVE_GETPEEREID)
    /* BSD, AIX, Cygwin */
    /* http://cr.yp.to/docs/secureipc.html */
    if (getpeereid(Int_val(fd), &uid, &gid) != 0) {
	uerror("getpeereid", Nothing);
    }

#elif defined(SO_PEERCRED)
    /* Linux */
    {
	socklen_t len;
	struct ucred credentials;

	len = sizeof(struct ucred);
	if (getsockopt(Int_val(fd),
		       SOL_SOCKET,
		       SO_PEERCRED,
		       &credentials,
		       &len) == -1) {
	    uerror("getsockopt",Nothing);
	};
	uid = credentials.uid;       /* Effective user ID */
	gid = credentials.gid;       /* Effective group ID */
    }
#elif defined(HAVE_GETPEERUCRED)
    /* Solaris */
    { 
	ucred_t    *ucred;
	ucred = NULL;			/* must be initialized to NULL */
	if (getpeerucred(Int_val(fd), &ucred) == -1) {
	    uerror("getpeerucred",Nothing);
	};
	if ((uid = ucred_geteuid(ucred)) == -1) {
	    uerror("ucred_geteuid",Nothing);
	    ucred_free(ucred);
	};
	if ((gid = ucred_getegid(ucred)) == -1) {
	    uerror("ucred_getegid",Nothing);
	    ucred_free(ucred);
	};
	ucred_free(ucred);
    }
#else
    invalid_argument("get_peer_credentials");
#endif

    /* Allocate a pair, and put the result into it: */
    result = alloc_tuple(2);
    Store_field(result, 0, Val_int(uid));
    Store_field(result, 1, Val_int(gid));

    CAMLreturn(result);
}
Ejemplo n.º 14
0
/**
 * Create a connection handle by accepting on a listen socket.  This
 * function may block if the listen socket has no connection ready.
 *
 * @param access function to use to check if access is allowed
 * @param access_cls closure for access
 * @param lsock listen socket
 * @return the connection handle, NULL on error
 */
struct GNUNET_CONNECTION_Handle *
GNUNET_CONNECTION_create_from_accept (GNUNET_CONNECTION_AccessCheck access,
                                      void *access_cls,
                                      struct GNUNET_NETWORK_Handle *lsock)
{
  struct GNUNET_CONNECTION_Handle *connection;
  char addr[128];
  socklen_t addrlen;
  struct GNUNET_NETWORK_Handle *sock;
  int aret;
  struct sockaddr_in *v4;
  struct sockaddr_in6 *v6;
  struct sockaddr *sa;
  void *uaddr;
  struct GNUNET_CONNECTION_Credentials *gcp;
  struct GNUNET_CONNECTION_Credentials gc;
#ifdef SO_PEERCRED
  struct ucred uc;
  socklen_t olen;
#endif

  addrlen = sizeof (addr);
  sock =
      GNUNET_NETWORK_socket_accept (lsock, (struct sockaddr *) &addr, &addrlen);
  if (NULL == sock)
  {
    LOG_STRERROR (GNUNET_ERROR_TYPE_WARNING, "accept");
    return NULL;
  }
  if ((addrlen > sizeof (addr)) || (addrlen < sizeof (sa_family_t)))
  {
    GNUNET_break (0);
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
    return NULL;
  }

  sa = (struct sockaddr *) addr;
  v6 = (struct sockaddr_in6 *) addr;
  if ((AF_INET6 == sa->sa_family) && (IN6_IS_ADDR_V4MAPPED (&v6->sin6_addr)))
  {
    /* convert to V4 address */
    v4 = GNUNET_malloc (sizeof (struct sockaddr_in));
    memset (v4, 0, sizeof (struct sockaddr_in));
    v4->sin_family = AF_INET;
#if HAVE_SOCKADDR_IN_SIN_LEN
    v4->sin_len = (u_char) sizeof (struct sockaddr_in);
#endif
    memcpy (&v4->sin_addr,
            &((char *) &v6->sin6_addr)[sizeof (struct in6_addr) -
                                       sizeof (struct in_addr)],
            sizeof (struct in_addr));
    v4->sin_port = v6->sin6_port;
    uaddr = v4;
    addrlen = sizeof (struct sockaddr_in);
  }
  else
  {
    uaddr = GNUNET_malloc (addrlen);
    memcpy (uaddr, addr, addrlen);
  }
  gcp = NULL;
  gc.uid = 0;
  gc.gid = 0;
  if (AF_UNIX == sa->sa_family)
  {
#if HAVE_GETPEEREID
    /* most BSDs */
    if (0 == getpeereid (GNUNET_NETWORK_get_fd (sock), &gc.uid, &gc.gid))
      gcp = &gc;
#else
#ifdef SO_PEERCRED
    /* largely traditional GNU/Linux */
    olen = sizeof (uc);
    if ((0 ==
         getsockopt (GNUNET_NETWORK_get_fd (sock), SOL_SOCKET, SO_PEERCRED, &uc,
                     &olen)) && (olen == sizeof (uc)))
    {
      gc.uid = uc.uid;
      gc.gid = uc.gid;
      gcp = &gc;
    }
#else
#if HAVE_GETPEERUCRED
    /* this is for Solaris 10 */
    ucred_t *uc;

    uc = NULL;
    if (0 == getpeerucred (GNUNET_NETWORK_get_fd (sock), &uc))
    {
      gc.uid = ucred_geteuid (uc);
      gc.gid = ucred_getegid (uc);
      gcp = &gc;
    }
    ucred_free (uc);
#endif
#endif
#endif
  }

  if ((NULL != access) &&
      (GNUNET_YES != (aret = access (access_cls, gcp, uaddr, addrlen))))
  {
    if (GNUNET_NO == aret)
      LOG (GNUNET_ERROR_TYPE_INFO, _("Access denied to `%s'\n"),
           GNUNET_a2s (uaddr, addrlen));
    GNUNET_break (GNUNET_OK ==
                  GNUNET_NETWORK_socket_shutdown (sock, SHUT_RDWR));
    GNUNET_break (GNUNET_OK == GNUNET_NETWORK_socket_close (sock));
    GNUNET_free (uaddr);
    return NULL;
  }
  connection = GNUNET_malloc (sizeof (struct GNUNET_CONNECTION_Handle));
  connection->write_buffer_size = GNUNET_SERVER_MIN_BUFFER_SIZE;
  connection->write_buffer = GNUNET_malloc (connection->write_buffer_size);
  connection->addr = uaddr;
  connection->addrlen = addrlen;
  connection->sock = sock;
  LOG (GNUNET_ERROR_TYPE_INFO, 
       _("Accepting connection from `%s': %p\n"),
       GNUNET_a2s (uaddr, addrlen), connection);
  return connection;
}
Ejemplo n.º 15
0
static int32_t
qb_ipcs_uc_recv_and_auth(int32_t sock, void *msg, size_t len,
			 struct ipc_auth_ugp *ugp)
{
	int32_t res = 0;
	struct msghdr msg_recv;
	struct iovec iov_recv;

#ifdef SO_PASSCRED
	char cmsg_cred[CMSG_SPACE(sizeof(struct ucred))];
	int off = 0;
	int on = 1;
#endif
	msg_recv.msg_iov = &iov_recv;
	msg_recv.msg_iovlen = 1;
	msg_recv.msg_name = 0;
	msg_recv.msg_namelen = 0;
#ifdef SO_PASSCRED
	msg_recv.msg_control = (void *)cmsg_cred;
	msg_recv.msg_controllen = sizeof(cmsg_cred);
#endif
#ifdef QB_SOLARIS
	msg_recv.msg_accrights = 0;
	msg_recv.msg_accrightslen = 0;
#else
	msg_recv.msg_flags = 0;
#endif /* QB_SOLARIS */

	iov_recv.iov_base = msg;
	iov_recv.iov_len = len;
#ifdef SO_PASSCRED
	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &on, sizeof(on));
#endif

	res = qb_ipc_us_recv_msghdr(sock, &msg_recv, msg, len);
	if (res < 0) {
		goto cleanup_and_return;
	}
	if (res != len) {
		res = -EIO;
		goto cleanup_and_return;
	}

	/*
	 * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
	 * retrieval mechanisms for various Platforms
	 */
#ifdef HAVE_GETPEERUCRED
	/*
	 * Solaris and some BSD systems
	 */
	{
		ucred_t *uc = NULL;

		if (getpeerucred(sock, &uc) == 0) {
			res = 0;
			ugp->uid = ucred_geteuid(uc);
			ugp->gid = ucred_getegid(uc);
			ugp->pid = ucred_getpid(uc);
			ucred_free(uc);
		} else {
			res = -errno;
		}
	}
#elif HAVE_GETPEEREID
	/*
	 * Usually MacOSX systems
	 */
	{
		/*
		 * TODO get the peer's pid.
		 * c->pid = ?;
		 */
		if (getpeereid(sock, &ugp->uid, &ugp->gid) == 0) {
			res = 0;
		} else {
			res = -errno;
		}
	}

#elif SO_PASSCRED
	/*
	 * Usually Linux systems
	 */
	{
		struct ucred cred;
		struct cmsghdr *cmsg;

		res = -EINVAL;
		for (cmsg = CMSG_FIRSTHDR(&msg_recv); cmsg != NULL;
		     cmsg = CMSG_NXTHDR(&msg_recv, cmsg)) {
			if (cmsg->cmsg_type != SCM_CREDENTIALS)
				continue;

			memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
			res = 0;
			ugp->pid = cred.pid;
			ugp->uid = cred.uid;
			ugp->gid = cred.gid;
			break;
		}
	}
#else /* no credentials */
	ugp->pid = 0;
	ugp->uid = 0;
	ugp->gid = 0;
	res = -ENOTSUP;
#endif /* no credentials */

cleanup_and_return:

#ifdef SO_PASSCRED
	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &off, sizeof(off));
#endif

	return res;
}
Ejemplo n.º 16
0
int lutil_getpeereid( int s, uid_t *euid, gid_t *egid
#ifdef LDAP_PF_LOCAL_SENDMSG
	, struct berval *peerbv
#endif
	)
{
#ifdef LDAP_PF_LOCAL
#if defined( HAVE_GETPEERUCRED )
	ucred_t *uc = NULL;
	if( getpeerucred( s, &uc ) == 0 )  {
		*euid = ucred_geteuid( uc );
		*egid = ucred_getegid( uc );
		ucred_free( uc );
		return 0;
	}

#elif defined( SO_PEERCRED )
	struct ucred peercred;
	ber_socklen_t peercredlen = sizeof peercred;

	if(( getsockopt( s, SOL_SOCKET, SO_PEERCRED,
		(void *)&peercred, &peercredlen ) == 0 )
		&& ( peercredlen == sizeof peercred ))
	{
		*euid = peercred.uid;
		*egid = peercred.gid;
		return 0;
	}

#elif defined( LOCAL_PEERCRED )
	struct xucred peercred;
	ber_socklen_t peercredlen = sizeof peercred;

	if(( getsockopt( s, LOCAL_PEERCRED, 1,
		(void *)&peercred, &peercredlen ) == 0 )
		&& ( peercred.cr_version == XUCRED_VERSION ))
	{
		*euid = peercred.cr_uid;
		*egid = peercred.cr_gid;
		return 0;
	}
#elif defined( LDAP_PF_LOCAL_SENDMSG ) && defined( MSG_WAITALL )
	int err, fd;
	struct iovec iov;
	struct msghdr msg = {0};
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
# ifndef CMSG_SPACE
# define CMSG_SPACE(len)	(_CMSG_ALIGN(sizeof(struct cmsghdr)) + _CMSG_ALIGN(len))
# endif
# ifndef CMSG_LEN
# define CMSG_LEN(len)		(_CMSG_ALIGN(sizeof(struct cmsghdr)) + (len))
# endif
	struct {
		struct cmsghdr cm;
		int fd;
	} control_st;
	struct cmsghdr *cmsg;
# endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL */
	struct stat st;
	struct sockaddr_un lname, rname;
	ber_socklen_t llen, rlen;

	rlen = sizeof(rname);
	llen = sizeof(lname);
	memset( &lname, 0, sizeof( lname ));
	getsockname(s, (struct sockaddr *)&lname, &llen);

	iov.iov_base = peerbv->bv_val;
	iov.iov_len = peerbv->bv_len;
	msg.msg_iov = &iov;
	msg.msg_iovlen = 1;
	peerbv->bv_len = 0;

# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
	msg.msg_control = &control_st;
	msg.msg_controllen = sizeof( struct cmsghdr ) + sizeof( int );	/* no padding! */

	cmsg = CMSG_FIRSTHDR( &msg );
# else
	msg.msg_accrights = (char *)&fd;
	msg.msg_accrightslen = sizeof(fd);
# endif

	/*
	 * AIX returns a bogus file descriptor if recvmsg() is
	 * called with MSG_PEEK (is this a bug?). Hence we need
	 * to receive the Abandon PDU.
	 */
	err = recvmsg( s, &msg, MSG_WAITALL );
	if( err >= 0 &&
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
	    cmsg->cmsg_len == CMSG_LEN( sizeof(int) ) &&
	    cmsg->cmsg_level == SOL_SOCKET &&
	    cmsg->cmsg_type == SCM_RIGHTS
# else
		msg.msg_accrightslen == sizeof(int)
# endif /* HAVE_STRUCT_MSGHDR_MSG_CONTROL*/
	) {
		int mode = S_IFIFO|S_ISUID|S_IRWXU;

		/* We must receive a valid descriptor, it must be a pipe,
		 * it must only be accessible by its owner, and it must
		 * have the name of our socket written on it.
		 */
		peerbv->bv_len = err;
# ifdef HAVE_STRUCT_MSGHDR_MSG_CONTROL
		fd = (*(int *)CMSG_DATA( cmsg ));
# endif
		err = fstat( fd, &st );
		if ( err == 0 )
			rlen = read(fd, &rname, rlen);
		close(fd);
		if( err == 0 && st.st_mode == mode &&
			llen == rlen && !memcmp(&lname, &rname, llen))
		{
			*euid = st.st_uid;
			*egid = st.st_gid;
			return 0;
		}
	}
#elif defined(SOCKCREDSIZE)
	struct msghdr msg;
	ber_socklen_t crmsgsize;
	void *crmsg;
	struct cmsghdr *cmp;
	struct sockcred *sc;

	memset(&msg, 0, sizeof msg);
	crmsgsize = CMSG_SPACE(SOCKCREDSIZE(NGROUPS));
	if (crmsgsize == 0) goto sc_err;
	crmsg = malloc(crmsgsize);
	if (crmsg == NULL) goto sc_err;
	memset(crmsg, 0, crmsgsize);
	
	msg.msg_control = crmsg;
	msg.msg_controllen = crmsgsize;
	
	if (recvmsg(s, &msg, 0) < 0) {
		free(crmsg);
		goto sc_err;
	}	

	if (msg.msg_controllen == 0 || (msg.msg_flags & MSG_CTRUNC) != 0) {
		free(crmsg);
		goto sc_err;
	}	
	
	cmp = CMSG_FIRSTHDR(&msg);
	if (cmp->cmsg_level != SOL_SOCKET || cmp->cmsg_type != SCM_CREDS) {
		printf("nocreds\n");
		goto sc_err;
	}	
	
	sc = (struct sockcred *)(void *)CMSG_DATA(cmp);
	
	*euid = sc->sc_euid;
	*egid = sc->sc_egid;

	free(crmsg);
	return 0;

sc_err:	
#endif
#endif /* LDAP_PF_LOCAL */

	return -1;
}
Ejemplo n.º 17
0
/*
 * Get uid, gid and pid of unix socket peer.
 *
 * Pid may not be availalbe on some OSes.
 * It's set to 0 then.
 */
int getpeercreds(int fd, uid_t *uid_p, gid_t *gid_p, pid_t *pid_p)
{
	/* What a mess */

#if defined(SO_PEERCRED)
	/* linux and others */
#if defined(HAVE_SYS_UCRED_H)
	struct sockpeercred cred;	/* openbsd */
#else
	struct ucred cred;		/* linux */
#endif
	socklen_t len = sizeof(cred);
	if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &cred, &len) == 0) {
		*uid_p = cred.uid;
		*gid_p = cred.gid;
		*pid_p = cred.pid;
		return 0;
	}
	return -1;
#elif defined(HAVE_GETPEERUCRED)
	/* solaris */
	ucred_t *cred = NULL;
	if (getpeerucred(fd, &cred) == 0) {
		*uid_p = ucred_geteuid(cred);
		*gid_p = ucred_getegid(cred);
		*pid_p = ucred_getpid(cred);
		ucred_free(cred);
		if ((int)*uid_p == -1 || (int)*gid_p == -1)
			return -1;
		return 0;
	}
	return -1;
#elif defined(LOCAL_PEEREID)
	/* netbsd */
	struct unpcbid cred;
	socklen_t len = sizeof(cred);
	if (getsockopt(fd, 0, LOCAL_PEEREID, &cred, &len) != 0)
		return -1;
	*uid_p = cred.unp_euid;
	*gid_p = cred.unp_egid;
	*pid_p = cred.unp_pid;
	return 0;
#elif defined(HAVE_GETPEEREID)
	/* generic bsd; no pid */
	*pid_p = 0;
	return getpeereid(fd, uid_p, gid_p) == 0 ? 0 : -1;
#elif defined(LOCAL_PEERCRED)
	/* freebsd, osx, dfly; no pid */
	struct xucred cred;
	socklen_t len = sizeof(cred);
	if (getsockopt(fd, 0, LOCAL_PEERCRED, &cred, &len) != 0)
		return -1;
	if (cred.cr_version != XUCRED_VERSION) {
		errno = EINVAL;
		return -1;
	}
	*uid_p = cred.cr_uid;
	*gid_p = cred.cr_gid;
	*pid_p = 0;
	return 0;
#else
	/* no implementation */
	errno = ENOSYS;
	return -1;
#endif
}
Ejemplo n.º 18
0
static int32_t
qb_ipc_auth_creds(struct ipc_auth_data *data)
{
	int32_t res = 0;

	/*
	 * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
	 * retrieval mechanisms for various Platforms
	 */
#ifdef HAVE_GETPEERUCRED
	/*
	 * Solaris and some BSD systems
	 */
	{
		ucred_t *uc = NULL;

		if (getpeerucred(data->sock, &uc) == 0) {
			res = 0;
			data->ugp.uid = ucred_geteuid(uc);
			data->ugp.gid = ucred_getegid(uc);
			data->ugp.pid = ucred_getpid(uc);
			ucred_free(uc);
		} else {
			res = -errno;
		}
	}
#elif defined(HAVE_GETPEEREID)
	/*
	* Usually MacOSX systems
	*/
	{
		/*
		* TODO get the peer's pid.
		* c->pid = ?;
		*/
		if (getpeereid(data->sock, &data->ugp.uid, &data->ugp.gid) == 0) {
			res = 0;
		} else {
			res = -errno;
		}
	}

#elif defined(SO_PASSCRED)
	/*
	* Usually Linux systems
	*/
	{
		struct ucred cred;
		struct cmsghdr *cmsg;

		res = -EINVAL;
		for (cmsg = CMSG_FIRSTHDR(&data->msg_recv); cmsg != NULL;
			cmsg = CMSG_NXTHDR(&data->msg_recv, cmsg)) {
			if (cmsg->cmsg_type != SCM_CREDENTIALS)
				continue;

			memcpy(&cred, CMSG_DATA(cmsg), sizeof(struct ucred));
			res = 0;
			data->ugp.pid = cred.pid;
			data->ugp.uid = cred.uid;
			data->ugp.gid = cred.gid;
			break;
		}
	}
#else /* no credentials */
	data->ugp.pid = 0;
	data->ugp.uid = 0;
	data->ugp.gid = 0;
	res = -ENOTSUP;
#endif /* no credentials */

	return res;
}
Ejemplo n.º 19
0
static int
lx_getsockopt(ulong_t *args)
{
	int sockfd = (int)args[0];
	int level = (int)args[1];
	int optname = (int)args[2];
	void *optval = (void *)args[3];
	int *optlenp = (int *)args[4];
	int r;

	lx_debug("\tgetsockopt(%d, %d, %d, 0x%p, 0x%p)", sockfd, level, optname,
	    optval, optlenp);

	/*
	 * According to the Linux man page, a NULL optval should indicate
	 * (as in Solaris) that no return value is expected.  Instead, it
	 * actually triggers an EFAULT error.
	 */
	if (optval == NULL)
		return (-EFAULT);

	/*
	 * Do a table lookup of the Solaris equivalent of the given option
	 */
	if (level < IPPROTO_IP || level >= IPPROTO_TAB_SIZE)
		return (-EOPNOTSUPP);

	if (ltos_proto_opts[level].maxentries == 0 ||
	    optname <= 0 || optname >= (ltos_proto_opts[level].maxentries))
		return (-ENOPROTOOPT);

	if (((level == LX_SOL_SOCKET) && (optname == LX_SO_PASSCRED)) ||
	    ((level == IPPROTO_TCP) && (optname == LX_TCP_CORK))) {
		/*
		 * Linux sets LX_SO_PASSCRED when it wants to send credentials
		 * over a socket. Since we do not support it, it is never set
		 * and we return 0.
		 *
		 * We don't support TCP_CORK but some apps rely on it.  So,
		 * rather than return an error we just return 0.  This
		 * isn't exactly a lie, since this option really isn't set,
		 * but it's not the whole truth either.  Fortunately, we
		 * aren't under oath.
		 */
		r = 0;
		if (uucopy(&r, optval, sizeof (int)) != 0)
			return (-errno);
		r = sizeof (int);
		if (uucopy(&r, optlenp, sizeof (int)) != 0)
			return (-errno);
		return (0);
	}
	if ((level == LX_SOL_SOCKET) && (optname == LX_SO_PEERCRED)) {
		struct lx_ucred	lx_ucred;
		ucred_t		*ucp;

		/*
		 * We don't support SO_PEERCRED, but we do have equivalent
		 * functionality in getpeerucred() so invoke that here.
		 */

		/* Verify there's going to be enough room for the results. */
		if (uucopy(optlenp, &r, sizeof (int)) != 0)
			return (-errno);
		if (r < sizeof (struct lx_ucred))
			return (-EOVERFLOW);

		/*
		 * We allocate a ucred_t ourselves rather than allow
		 * getpeerucred() to do it for us because getpeerucred()
		 * uses malloc(3C) and we'd rather use SAFE_ALLOCA().
		 */
		if ((ucp = (ucred_t *)SAFE_ALLOCA(ucred_size())) == NULL)
			return (-ENOMEM);

		/* Get the credential for the remote end of this socket. */
		if (getpeerucred(sockfd, &ucp) != 0)
			return (-errno);
		if (((lx_ucred.lxu_pid = ucred_getpid(ucp)) == -1) ||
		    ((lx_ucred.lxu_uid = ucred_geteuid(ucp)) == (uid_t)-1) ||
		    ((lx_ucred.lxu_gid = ucred_getegid(ucp)) == (gid_t)-1)) {
			return (-errno);
		}

		/* Copy out the results. */
		if ((uucopy(&lx_ucred, optval, sizeof (lx_ucred))) != 0)
			return (-errno);
		r = sizeof (lx_ucred);
		if ((uucopy(&r, optlenp, sizeof (int))) != 0)
			return (-errno);
		return (0);
	}

	optname = ltos_proto_opts[level].proto[optname];

	if (optname == OPTNOTSUP)
		return (-ENOPROTOOPT);

	if (level == LX_SOL_SOCKET)
		level = SOL_SOCKET;

	r = getsockopt(sockfd, level, optname, optval, optlenp);

	return ((r < 0) ? -errno : r);
}
Ejemplo n.º 20
0
static int
lx_getsockopt(ulong_t *args)
{
	int sockfd = (int)args[0];
	int level = (int)args[1];
	int optname = (int)args[2];
	void *optval = (void *)args[3];
	int *optlenp = (int *)args[4];
	int r;
	int orig_optname;
	lx_proto_opts_t *proto_opts;

	lx_debug("\tgetsockopt(%d, %d, %d, 0x%p, 0x%p)", sockfd, level, optname,
	    optval, optlenp);

	/*
	 * According to the Linux man page, a NULL optval should indicate
	 * (as in Solaris) that no return value is expected.  Instead, it
	 * actually triggers an EFAULT error.
	 */
	if (optval == NULL)
		return (-EFAULT);

	if (level > LX_IPPROTO_RAW || level == LX_IPPROTO_UDP)
		return (-EOPNOTSUPP);

	if ((proto_opts = get_proto_opt_tbl(level)) == NULL)
		return (-ENOPROTOOPT);

	if (optname <= 0 || optname >= (proto_opts->maxentries)) {
		lx_unsupported("Unsupported sockopt %d, proto %d", optname,
		    level);
		return (-ENOPROTOOPT);
	}

	if ((level == LX_IPPROTO_TCP) && (optname == LX_TCP_CORK)) {
		/*
		 * We don't support TCP_CORK but some apps rely on it.  So,
		 * rather than return an error we just return 0.  This
		 * isn't exactly a lie, since this option really isn't set,
		 * but it's not the whole truth either.  Fortunately, we
		 * aren't under oath.
		 */
		r = 0;
		if (uucopy(&r, optval, sizeof (int)) != 0)
			return (-errno);
		r = sizeof (int);
		if (uucopy(&r, optlenp, sizeof (int)) != 0)
			return (-errno);
		return (0);
	}
	if ((level == LX_SOL_SOCKET) && (optname == LX_SO_PEERCRED)) {
		struct lx_ucred	lx_ucred;
		ucred_t		*ucp;

		/*
		 * We don't support SO_PEERCRED, but we do have equivalent
		 * functionality in getpeerucred() so invoke that here.
		 */

		/* Verify there's going to be enough room for the results. */
		if (uucopy(optlenp, &r, sizeof (int)) != 0)
			return (-errno);
		if (r < sizeof (struct lx_ucred))
			return (-EOVERFLOW);

		/*
		 * We allocate a ucred_t ourselves rather than allow
		 * getpeerucred() to do it for us because getpeerucred()
		 * uses malloc(3C) and we'd rather use SAFE_ALLOCA().
		 */
		if ((ucp = (ucred_t *)SAFE_ALLOCA(ucred_size())) == NULL)
			return (-ENOMEM);

		/* Get the credential for the remote end of this socket. */
		if (getpeerucred(sockfd, &ucp) != 0)
			return (-errno);
		if (((lx_ucred.lxu_pid = ucred_getpid(ucp)) == -1) ||
		    ((lx_ucred.lxu_uid = ucred_geteuid(ucp)) == (uid_t)-1) ||
		    ((lx_ucred.lxu_gid = ucred_getegid(ucp)) == (gid_t)-1)) {
			return (-errno);
		}

		/* Copy out the results. */
		if ((uucopy(&lx_ucred, optval, sizeof (lx_ucred))) != 0)
			return (-errno);
		r = sizeof (lx_ucred);
		if ((uucopy(&r, optlenp, sizeof (int))) != 0)
			return (-errno);
		return (0);
	}

	orig_optname = optname;

	optname = proto_opts->proto[optname];
	if (optname == OPTNOTSUP) {
		lx_unsupported("unsupported sockopt %d, proto %d",
		    orig_optname, level);
		return (-ENOPROTOOPT);
	}

	if (level == LX_SOL_SOCKET)
		level = SOL_SOCKET;

	r = getsockopt(sockfd, level, optname, optval, optlenp);

	if (r == 0 && level == SOL_SOCKET && optname == SO_TYPE) {
		/* translate our type back to Linux */
		*(int *)optval = stol_socktype[(*(int *)optval)];
	}

	return ((r < 0) ? -errno : r);
}
Ejemplo n.º 21
0
void
_nscd_proc_alt_get(
	void		*buf,
	int		*door)
{
	int		errnum;
	uid_t		set2uid;
	gid_t		set2gid;
	nss_pheader_t	*phdr = (nss_pheader_t *)buf;
	char		*me = "_nscd_proc_alt_get";
	ucred_t		*uc = NULL;
	child_t		*ch;

	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
	(me, "getting an alternate door ...\n");

	/* make sure there is a door to talk to the forker */
	if (forking_door == -1) {
		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_ERROR)
		(me, "no door to talk to the forker\n");

		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
		    NSCD_SELF_CRED_NO_FORKER);
	}

	/* get door client's credential information */
	if (door_ucred(&uc) != 0) {
		errnum = errno;
		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
		(me, "door_ucred failed: %s\n", strerror(errnum));

		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, errnum,
		    NSCD_DOOR_UCRED_ERROR);
	}

	/* get door client's effective uid and effective gid */
	set2uid = ucred_geteuid(uc);
	set2gid = ucred_getegid(uc);
	ucred_free(uc);
	uc = NULL;

	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
	(me, "child uid = %d, gid = %d\n", set2uid, set2gid);

	/* is a slot available ? if not, no one to serve */
	if (child == NULL || (ch = get_cslot(set2uid, 0)) == NULL) {

		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
		(me, "no child slot available (child array = %p, slot = %d)\n",
		    child, ch->child_slot);

		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
		    NSCD_SELF_CRED_NO_CHILD_SLOT);
	}

	/* create the per user nscd if necessary */
	if (ch->child_state != CHILD_STATE_PIDKNOWN) {

		nss_pheader_t	phdr1;
		NSCD_CLEAR_STATUS(&phdr1);

		(void) mutex_lock(ch->mutex);
		if (ch->child_state == CHILD_STATE_UIDKNOWN) {

			/* ask forker to fork a new child */
			selfcred_fork(&phdr1, forking_door, ch->child_slot,
			    set2uid, set2gid);
			if (NSCD_STATUS_IS_NOT_OK(&phdr1)) {
				(void) mutex_unlock(ch->mutex);
				NSCD_COPY_STATUS(phdr, &phdr1);
				return;
			}
			ch->child_state = CHILD_STATE_FORKSENT;
		}

		_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
		(me, "waiting for door (slot = %d, uid = %d, gid = %d)\n",
		    ch->child_slot, set2uid, set2gid);

		/* wait for the per user nscd to become available */
		while (ch->child_state == CHILD_STATE_FORKSENT) {
			timestruc_t to;
			int err;
			int ttl = 5;

			to.tv_sec = ttl;
			to.tv_nsec = 0;
			_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
				(me, "cond_reltimedwait %d seconds\n", ttl);
			err = cond_reltimedwait(ch->cond, ch->mutex, &to);
			if (err == ETIME) {
				ch->child_state = CHILD_STATE_UIDKNOWN;
				_NSCD_LOG(NSCD_LOG_SELF_CRED,
				    NSCD_LOG_LEVEL_DEBUG)
				(me, "door wait timedout (slot = %d)\n",
				    ch->child_slot);
				break;
			}
		}
		(void) mutex_unlock(ch->mutex);
	}

	if (ch->child_state != CHILD_STATE_PIDKNOWN) {

		NSCD_RETURN_N2N_STATUS(phdr, NSS_NSCD_PRIV, 0,
		    NSCD_SELF_CRED_INVALID_SLOT_STATE);
	}

	*door = ch->child_door;

	_NSCD_LOG(NSCD_LOG_SELF_CRED, NSCD_LOG_LEVEL_DEBUG)
	(me, "returning door %d for slot %d, uid %d, gid = %d\n",
	    *door, ch->child_slot, set2uid, set2gid);

	NSCD_RETURN_STATUS(phdr, NSS_ALTRETRY, 0);
}
Ejemplo n.º 22
0
/*
 * check_auth_modify() checks if a given cred has
 * the authorization to add/change/remove configuration values.
 * cred is from the door call.
 */
Boolean_t
check_auth_modify(ucred_t *cred)
{
	targ_scf_t *h = NULL;
	Boolean_t ret = False;
	int exit_code = -1;
	uid_t uid;
	gid_t gid;
	pid_t pid;
	tgt_node_t *n = NULL;
	scf_transaction_entry_t *ent = NULL;
	const priv_set_t	*eset;

	pid = fork();

	switch (pid) {
	case 0:
		/* Child process to check authorization */
		uid = ucred_geteuid(cred);
		if (seteuid(uid) != 0) {
			syslog(LOG_ERR, "not priviliged\n");
			exit(-1);
		}

		gid = ucred_getegid(cred);
		if (setegid(gid) != 0) {
			syslog(LOG_ERR, "not priviliged\n");
			exit(-1);
		}

		eset = ucred_getprivset(cred, PRIV_EFFECTIVE);
		setppriv(PRIV_ON, PRIV_EFFECTIVE, eset);

		h = mgmt_handle_init();

		if (h == NULL) {
			exit(-1);
		}
		if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
			n = tgt_node_alloc("dummy", String, "dummy");
			new_property(h, n);
			tgt_node_free(n);
			if (mgmt_transaction_end(h) == True) {
				exit_code = 0;
			} else {
				exit_code = -1;
			}
		} else {
			exit_code = -1;
		}
		if (exit_code != 0) {
			mgmt_handle_fini(h);
			exit(exit_code);
		}
		if (mgmt_transaction_start(h, "iscsitgt", "basic") == True) {
			ent = scf_entry_create(h->t_handle);
			if (ent) {
				scf_transaction_property_delete(h->t_trans,
				    ent, "dummy");
			}
		}
		mgmt_transaction_end(h);

		mgmt_handle_fini(h);
		exit(exit_code);
		break;
	case -1:
		/* Fail to fork */
		exit(SMF_EXIT_ERR_CONFIG);
	default:
		wait(&exit_code);
		exit_code = exit_code >> 8;
		if (exit_code == 0)
			ret = True;
		else
			ret = False;
		break;
	}

	return (ret);
}
Ejemplo n.º 23
0
static cs_error_t
req_setup_recv (
	struct conn_info *conn_info)
{
	int res;
	struct msghdr msg_recv;
	struct iovec iov_recv;
	cs_error_t auth_res = CS_ERR_LIBRARY;

#ifdef COROSYNC_LINUX
	struct cmsghdr *cmsg;
	char cmsg_cred[CMSG_SPACE (sizeof (struct ucred))];
	int off = 0;
	int on = 1;
	struct ucred *cred;
#endif
	msg_recv.msg_flags = 0;
	msg_recv.msg_iov = &iov_recv;
	msg_recv.msg_iovlen = 1;
	msg_recv.msg_name = 0;
	msg_recv.msg_namelen = 0;
#ifdef COROSYNC_LINUX
	msg_recv.msg_control = (void *)cmsg_cred;
	msg_recv.msg_controllen = sizeof (cmsg_cred);
#endif
#ifdef COROSYNC_SOLARIS
	msg_recv.msg_accrights = 0;
	msg_recv.msg_accrightslen = 0;
#endif /* COROSYNC_SOLARIS */

	iov_recv.iov_base = &conn_info->setup_msg[conn_info->setup_bytes_read];
	iov_recv.iov_len = sizeof (mar_req_setup_t) - conn_info->setup_bytes_read;
#ifdef COROSYNC_LINUX
	setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED, &on, sizeof (on));
#endif

retry_recv:
	res = recvmsg (conn_info->fd, &msg_recv, MSG_NOSIGNAL);
	if (res == -1 && errno == EINTR) {
		api->stats_increment_value (conn_info->stats_handle, "recv_retry_count");
		goto retry_recv;
	} else
	if (res == -1 && errno != EAGAIN) {
		return (CS_ERR_LIBRARY);
	} else
	if (res == 0) {
#if defined(COROSYNC_SOLARIS) || defined(COROSYNC_BSD) || defined(COROSYNC_DARWIN)
		/* On many OS poll never return POLLHUP or POLLERR.
		 * EOF is detected when recvmsg return 0.
		 */
		ipc_disconnect (conn_info);
		return (CS_ERR_LIBRARY);
#else
		return (CS_ERR_SECURITY);
#endif
	}
	conn_info->setup_bytes_read += res;

/*
 * currently support getpeerucred, getpeereid, and SO_PASSCRED credential
 * retrieval mechanisms for various Platforms
 */
#ifdef HAVE_GETPEERUCRED
/*
 * Solaris and some BSD systems
 */
	{
		ucred_t *uc = NULL;
		uid_t euid = -1;
		gid_t egid = -1;

		if (getpeerucred (conn_info->fd, &uc) == 0) {
			euid = ucred_geteuid (uc);
			egid = ucred_getegid (uc);
			conn_info->client_pid = ucred_getpid (uc);
			if (api->security_valid (euid, egid)) {
				auth_res = CS_OK;
			} else {
				auth_res = hdb_error_to_cs(errno);
			}
			ucred_free(uc);
		}
	}
#elif HAVE_GETPEEREID
/*
 * Usually MacOSX systems
 */

	{
		uid_t euid;
		gid_t egid;

		/*
		 * TODO get the peer's pid.
		 * conn_info->client_pid = ?;
		 */
		euid = -1;
		egid = -1;
		if (getpeereid (conn_info->fd, &euid, &egid) == 0) {
			if (api->security_valid (euid, egid)) {
				auth_res = CS_OK;
			} else {
				auth_res = hdb_error_to_cs(errno);
			}
		}
	}

#elif SO_PASSCRED
/*
 * Usually Linux systems
 */
	cmsg = CMSG_FIRSTHDR (&msg_recv);
	assert (cmsg);
	cred = (struct ucred *)CMSG_DATA (cmsg);
	if (cred) {
		conn_info->client_pid = cred->pid;
		if (api->security_valid (cred->uid, cred->gid)) {
			auth_res = CS_OK;
		} else {
			auth_res = hdb_error_to_cs(errno);
		}
	}

#else /* no credentials */
	auth_res = CS_OK;
	log_printf (LOGSYS_LEVEL_ERROR, "Platform does not support IPC authentication.  Using no authentication\n");
#endif /* no credentials */

	if (auth_res != CS_OK) {
		ipc_disconnect (conn_info);
		if (auth_res == CS_ERR_NO_RESOURCES) {
			log_printf (LOGSYS_LEVEL_ERROR,
				"Not enough file desciptors for IPC connection.\n");
		} else {
			log_printf (LOGSYS_LEVEL_ERROR, "Invalid IPC credentials.\n");
		}
		return auth_res;
	}

	if (conn_info->setup_bytes_read == sizeof (mar_req_setup_t)) {
#ifdef COROSYNC_LINUX
		setsockopt(conn_info->fd, SOL_SOCKET, SO_PASSCRED,
			&off, sizeof (off));
#endif
		return (CS_OK);
	}
	return (CS_ERR_LIBRARY);
}