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); }