On Wed, 2015-04-08 at 10:12 +0200, Svante Signell wrote:
> Hi,
> 
> I'm trying to write test programs for auth_user/server_authenticate (and
> later for proc_user/server_authenticate) and have problems to get them
> right. The attached programs generate the following output:
> ./auth_recv&
> ./auth_send

New try, now with sendmsg/recvmsg.

Results
Terminal 1:
./auth_recvmsg
auth_recv.c: Socket file descriptor = 3
auth_recv.c: Receiving via datagram socket
auth_recv.c: msgh.msg_controllen = 16
auth_recv.c: recvmsg() returned 4
auth_recv.c: Received data = 125
auth_recv.c: cmhp->cmsg_len[0] = 16
auth_recv.c: Received file descriptor = 4
auth_recv.c: rendezvous valid
<hang>

Terminal 2:
./auth_sendmsg 
auth_send.c: rendezvous port = 125
auth_send.c: Socket file descriptor = 3
auth_send.c: mach_port_insert_right() err = 0
auth_send.c: Sent data = 125
auth_send.c: msgh.msg_controllen = 16
auth_send.c: Sent file descriptor: sfd = 3
auth_send.c: cmhp->cmsg_len = 16
auth_send.c: Sending via datagram socket
auth_send.c: sendmsg() returned 4 bytes
<hang>

Questions:
How to send the rendzevous port: as real data or ancillary data?
Should I use the received FD to do what?? The socket is already there.
Using a named connection, i.e. filling in msgh.msg_name and
msgh.msg_namelen?


/* test of auth_user/server authenticate: send part */

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <error.h>
#include <sys/types.h>
#include <unistd.h>
#include <hurd/hurd_types.h>
#include <hurd/fd.h>
#include <mach.h>
#include <hurd.h>
#include <sys/socket.h>
#include <sys/un.h>

#define SOCK_PATH "auth_socket"

int main (void)
{
  mach_port_t rendezvous  = __mach_reply_port ();
  mach_port_t newport;
  error_t err;
  struct msghdr msgh;
  struct iovec iov;
  int sfd, data;
  struct sockaddr_un addr = { 0 };
  ssize_t ns;
  //char wbuf[30];
  int cspc = CMSG_SPACE(sizeof(int));
  union {
    struct cmsghdr cmh;
    char control[cspc];
  } control_un;
  struct cmsghdr *cmhp = NULL;

  printf ("auth_send.c: rendezvous port = %d\n", (int)rendezvous);

  addr.sun_family = AF_UNIX;
  strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);

  sfd = socket (AF_UNIX, SOCK_DGRAM, 0);

  if (sfd == -1)
    {
      perror ("socket");
      exit(EXIT_FAILURE);
    }

  printf("auth_send.c: Socket file descriptor = %d\n", sfd);

  err = connect (sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
  if (err == -1)
    {
      close(sfd);
      perror ("connect");
      exit(EXIT_FAILURE);
    }

  err = mach_port_insert_right (mach_task_self (), rendezvous,
				rendezvous, MACH_MSG_TYPE_MAKE_SEND);

  printf ("auth_send.c: mach_port_insert_right() err = %d\n", err);
  if (err)
    goto out;

  msgh.msg_iov = &iov;
  msgh.msg_iovlen = 1;
  data = rendezvous;
  iov.iov_base = &data;
  iov.iov_len = sizeof(int);
  printf("auth_send.c: Sent data = %d\n", data);
  msgh.msg_name = NULL;
  msgh.msg_namelen = 0;
  msgh.msg_control = control_un.control;
  msgh.msg_controllen = sizeof(control_un.control);
  printf("auth_send.c: msgh.msg_controllen = %d\n", (int)msgh.msg_controllen);
  
  cmhp = CMSG_FIRSTHDR(&msgh);
  cmhp->cmsg_len = CMSG_LEN(sizeof(int));
  cmhp->cmsg_level = SOL_SOCKET;
  cmhp->cmsg_type = SCM_RIGHTS;
  *((int *) CMSG_DATA(cmhp)) = sfd;
  printf("auth_send.c: Sent file descriptor: sfd = %d\n", sfd);
  printf("auth_send.c: cmhp->cmsg_len = %d\n", (int)cmhp->cmsg_len);
  
  printf("auth_send.c: Sending via datagram socket\n");
  ns = sendmsg(sfd, &msgh, 0);
  if (ns == -1)
    {
      perror ("sendmsg");
      exit(EXIT_FAILURE);
    }
  printf("auth_send.c: sendmsg() returned %ld bytes\n", (long) ns);
  
  err = __USEPORT (AUTH, auth_user_authenticate (port,
						   rendezvous, MACH_MSG_TYPE_MAKE_SEND,
						   &newport));
 out:
  printf ("auth_send.c: newport=%d\n", (int)newport);
  __mach_port_deallocate (__mach_task_self (), rendezvous);
  __mach_port_deallocate (__mach_task_self (), newport);

  if (err)
    {
      printf ("auth_send.c: err = %d\n", err);
      exit(EXIT_FAILURE);
    }
  else
    exit(EXIT_SUCCESS);
}
/* test of auth_user/server authenticate: recv part */

#ifndef _GNU_SOURCE
#define _GNU_SOURCE
#endif
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <error.h>
#include <sys/types.h>
#include <sys/un.h>
#include <unistd.h>
#include <hurd/hurd_types.h>
#include <hurd.h>
#include <hurd/id.h>
#include <mach.h>
#include <sys/socket.h>

#define SOCK_PATH "auth_socket"

int main (void)
{
  __uid_t euids_buf[CMGROUP_MAX], auids_buf[CMGROUP_MAX];
  __uid_t *euids = euids_buf, *auids = auids_buf;
  __gid_t egids_buf[CMGROUP_MAX], agids_buf[CMGROUP_MAX];
  __gid_t *egids = egids_buf, *agids = agids_buf;
  size_t neuids = CMGROUP_MAX, nauids = CMGROUP_MAX;
  size_t negids = CMGROUP_MAX, nagids = CMGROUP_MAX;

  mach_port_t rendezvous;
  mach_port_t newport = MACH_PORT_NULL;
  error_t err;
  struct msghdr msgh;
  struct iovec iov;
  int sfd, data;
  struct sockaddr_un addr = { 0 };
  ssize_t nr;
  //char rbuf[30];
  int cspc = CMSG_SPACE(sizeof(int));
  union {
    struct cmsghdr cmh;
    char control[cspc];
  } control_un;
  struct cmsghdr *cmhp = NULL;

  /* Create socket bound to well-known address */
  err = remove (SOCK_PATH);
  if (err == -1 && errno != ENOENT)
    {
      perror ("remove");
      exit(EXIT_FAILURE);
    }

  addr.sun_family = AF_UNIX;
  strncpy(addr.sun_path, SOCK_PATH, sizeof(addr.sun_path) - 1);
  sfd = socket (AF_UNIX, SOCK_DGRAM, 0);
  if (sfd == -1)
    {
      perror ("socket");
      exit(EXIT_FAILURE);
    }

  printf("auth_recv.c: Socket file descriptor = %d\n", sfd);

  err = bind (sfd, (struct sockaddr *) &addr, sizeof(struct sockaddr_un));
  if (err == -1) {
    close(sfd);
    perror ("bind");
    exit(EXIT_FAILURE);
  }

  printf ("auth_recv.c: Receiving via datagram socket\n");

  /* Receive data */
  msgh.msg_iov = &iov;
  msgh.msg_iovlen = 1;
  iov.iov_base = &data;
  iov.iov_len = sizeof(int);

  msgh.msg_name = NULL;               /* We don't need address of peer */
  msgh.msg_namelen = 0;
  msgh.msg_control = control_un.control;
  msgh.msg_controllen = sizeof(control_un.control);
  fprintf(stderr, "auth_recv.c:msgh.msg_controllen = %d\n", (int)msgh.msg_controllen);

  /* Receive real plus ancillary data */
  nr = recvmsg(sfd, &msgh, 0);
  if (nr == -1)
    {
      perror ("recvmsg");
      exit(EXIT_FAILURE);
    }
  fprintf(stderr, "auth_recv.c: recvmsg() returned %ld\n", (long) nr);

  if (nr > 0)
    fprintf(stderr, "auth_recv.c: Received data = %d\n", data);
  rendezvous = data;
  /* Get the received file descriptor (which is typically a different
     file descriptor number than was used in the sending process) */
  int i = 0;
  for (cmhp = CMSG_FIRSTHDR(&msgh);
       cmhp != NULL;
       cmhp = CMSG_NXTHDR(&msgh, cmhp))
    {
      printf("auth_recv.c: cmhp->cmsg_len[%d] = %d\n", i, (int)cmhp->cmsg_len);
      i++;
      if (cmhp == NULL)
	{
	  perror("bad cmsg header cmhp == NULL");
	  exit(EXIT_FAILURE);
	}
      if (cmhp->cmsg_level != SOL_SOCKET)
	{
	  perror("cmsg_level != SOL_SOCKET");
	  exit(EXIT_FAILURE);
	}
      if (cmhp->cmsg_type != SCM_RIGHTS)
	{
	  printf("cmsg_type != SCM_RIGHTS");
	  exit(EXIT_FAILURE);
	}
      int *rfdptr = (int *)CMSG_DATA(cmhp);
      printf("auth_recv.c: Received file descriptor = %d\n", *rfdptr);
    }

  if (MACH_PORT_VALID (rendezvous))
    printf ("auth_recv.c: rendezvous valid\n");
  else
    printf ("auth_recv.c: rendezvous not valid\n");
  err = mach_port_mod_refs (mach_task_self (), rendezvous,
			    MACH_PORT_RIGHT_SEND, +1);
  if (err)
    {
      printf ("auth_recv.c: mach_port_mod_refs() err = %d\n", err);
      mach_port_deallocate (mach_task_self (), rendezvous);
      goto out;
    }
  do
    err = __USEPORT
      (AUTH, auth_server_authenticate (port,
				       rendezvous, MACH_MSG_TYPE_COPY_SEND,
				       newport, MACH_MSG_TYPE_COPY_SEND,
				       &euids, &neuids, &auids, &nauids,
				       &egids, &negids, &agids, &nagids));
  while (err == EINTR);

  mach_port_deallocate (mach_task_self (), rendezvous);
  mach_port_deallocate (mach_task_self (), newport);

  if (err)
    goto out;

  /* Print *id */
  printf("auth_recv.c: Received ids: auid=%ld, euid=%ld, agid=%ld, egid=%ld\n",
	 (long) euids[0], (long) auids[0],
	 (long) egids[0], (long) agids[0]);

 out:
  if (err)
    {
      printf ("auth_recv.c: err = %d\n", err);
      exit(EXIT_FAILURE);
    }
  else
    exit(EXIT_SUCCESS);
}

Reply via email to