]> mj.ucw.cz Git - subauth.git/commitdiff
Split to directories
authorMartin Mares <mj@ucw.cz>
Wed, 19 Jul 2017 10:35:53 +0000 (12:35 +0200)
committerMartin Mares <mj@ucw.cz>
Wed, 19 Jul 2017 10:35:53 +0000 (12:35 +0200)
Makefile
client/Makefile [new file with mode: 0644]
client/subauth.c [new file with mode: 0644]
configure
server/Makefile [new file with mode: 0644]
server/cmd.c [new file with mode: 0644]
server/subauthd.c [new file with mode: 0644]
server/subauthd.h [new file with mode: 0644]
subauth.c [deleted file]
subauthd.c [deleted file]

index 7ce559d24e36ffb424d680e01d857ff4ec7befa8..d538520cd4dbcfdbb64c7e97e94d79a4414d4eb1 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -20,15 +20,8 @@ EXTRA_RUNDIRS=run
 CFLAGS+=$(LIBUCW_CFLAGS) $(LIBUCW_JSON_CFLAGS)
 LIBS+=$(LIBUCW_LIBS) $(LIBUCW_JSON_LIBS)
 
-# Programs we want to compile
-PROGS+=$(o)/subauthd $(o)/subauth
-
-# And how they are created
-$(o)/subauthd: $(o)/subauthd.o
-$(o)/subauth: $(o)/subauth.o
-
-# Configuration files
-CONFIGS+=subauthd
+include $(s)/server/Makefile
+include $(s)/client/Makefile
 
 # And finally the default rules of the build system
 include $(BUILDSYS)/Makebottom
diff --git a/client/Makefile b/client/Makefile
new file mode 100644 (file)
index 0000000..608c26c
--- /dev/null
@@ -0,0 +1,5 @@
+DIRS+=client
+
+PROGS+=$(o)/client/subauth
+
+$(o)/client/subauth: $(o)/client/subauth.o
diff --git a/client/subauth.c b/client/subauth.c
new file mode 100644 (file)
index 0000000..e597b76
--- /dev/null
@@ -0,0 +1,80 @@
+/*
+ *     Sub-authentication Client
+ *
+ *     (c) 2017 Martin Mares <mj@ucw.cz>
+ */
+
+#include <ucw/lib.h>
+#include <ucw/opt.h>
+#include <ucw-json/json.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "autoconf.h"
+
+static char *socket_path = INSTALL_RUN_DIR "/subauthd.socket";
+
+static const struct opt_section options = {
+  OPT_ITEMS {
+    OPT_HELP("A client to the sub-authentication daemon."),
+    OPT_HELP("Usage: subauth [options]"),
+    OPT_HELP(""),
+    OPT_HELP("Options:"),
+    OPT_HELP_OPTION,
+    OPT_END
+  }
+};
+
+int main(int argc UNUSED, char **argv)
+{
+  opt_parse(&options, argv+1);
+
+  int sk = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+  if (sk < 0)
+    die("socket(PF_UNIX, SOCK_SEQPACKET): %m");
+
+  struct sockaddr_un sun;
+  sun.sun_family = AF_UNIX;
+  if (strlen(socket_path) >= sizeof(sun.sun_path))
+    die("Socket path too long");
+  strcpy(sun.sun_path, socket_path);
+
+  if (connect(sk, (struct sockaddr *) &sun, sizeof(sun)) < 0)
+    die("Cannot connect to %s: %m", socket_path);
+
+  struct fastbuf *out = bfdopen(1, 4096);
+
+  struct json_context *js = json_new();
+  struct json_node *rq = json_new_object(js);
+
+  bprintf(out, ">>> Request:\n");
+  json_write(js, out, rq);
+  bflush(out);
+
+  struct fastbuf *rq_fb = fbgrow_create(4096);
+  json_write(js, rq_fb, rq);
+  byte *rq_buf;
+  uint rq_len = fbgrow_get_buf(rq_fb, &rq_buf);
+  if (send(sk, rq_buf, rq_len, 0) < 0)
+    die("Cannot send request: %m");
+  bclose(rq_fb);
+
+  byte rp_buf[4096];           // FIXME
+  int rp_len = recv(sk, rp_buf, sizeof(rp_buf), 0);
+  if (rp_len < 0)
+    die("Cannot receive reply: %m");
+
+  puts("Parsing reply");
+  struct fastbuf rp_fb;
+  fbbuf_init_read(&rp_fb, rp_buf, rp_len, 0);
+  struct json_node *rp = json_parse(js, &rp_fb);
+  bprintf(out, "<<< Reply:\n");
+  json_write(js, out, rp);
+  bflush(out);
+
+  return 0;
+}
index a9644766cacf664f9da2fc33cc66bf80abf4b312..1b227830c96032fa1f075c4c92f8326e9f935fbd 100755 (executable)
--- a/configure
+++ b/configure
@@ -8,7 +8,7 @@ use strict;
 our($srcdir, $libdir);
 BEGIN {
        # Find the sources
-       my $pkgfile = "subauthd.c";
+       my $pkgfile = "server/subauthd.c";
        if (!defined ($srcdir = $ENV{"SRCDIR"})) {
                if (-f $pkgfile) {
                        $srcdir=".";
diff --git a/server/Makefile b/server/Makefile
new file mode 100644 (file)
index 0000000..54b613f
--- /dev/null
@@ -0,0 +1,6 @@
+DIRS+=server
+
+PROGS+=$(o)/server/subauthd
+CONFIGS+=subauthd
+
+$(o)/server/subauthd: $(addprefix $(o)/server/, subauthd.o cmd.o)
diff --git a/server/cmd.c b/server/cmd.c
new file mode 100644 (file)
index 0000000..5e8b898
--- /dev/null
@@ -0,0 +1,16 @@
+/*
+ *     Sub-authentication Daemon: Commands
+ *
+ *     (c) 2017 Martin Mares <mj@ucw.cz>
+ */
+
+#include <ucw/lib.h>
+
+#include "subauthd.h"
+
+void cmd_error(struct client *c, const char *err)
+{
+  json_object_set(c->reply, "error", json_new_string(c->json, err));
+}
+
+
diff --git a/server/subauthd.c b/server/subauthd.c
new file mode 100644 (file)
index 0000000..56d142f
--- /dev/null
@@ -0,0 +1,305 @@
+/*
+ *     Sub-authentication Daemon
+ *
+ *     (c) 2017 Martin Mares <mj@ucw.cz>
+ */
+
+#include <ucw/lib.h>
+#include <ucw/conf.h>
+#include <ucw/log.h>
+#include <ucw/opt.h>
+#include <ucw/trans.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+#include <sys/un.h>
+#include <unistd.h>
+
+#include "subauthd.h"
+
+static char *socket_path = "subauthd.socket";
+static uint max_connections = ~0U;
+
+static struct main_file listen_socket;
+static uint num_connections;
+
+static byte packet_buffer[MAX_PACKET_SIZE];
+static byte oob_data_buffer[MAX_OOB_DATA_SIZE];
+
+static int socket_read_handler(struct main_file *fi);
+static int socket_write_handler(struct main_file *fi);
+
+static void client_close(struct client *c)
+{
+  msg(L_INFO, "Closing connection");
+  file_del(&c->socket);
+  timer_del(&c->timer);
+  close(c->socket.fd);
+  json_delete(c->json);
+  xfree(c);
+  num_connections--;
+}
+
+static void socket_timeout_handler(struct main_timer *tm)
+{
+  struct client *c = tm->data;
+  msg(L_INFO, "Client timeout");
+  client_close(c);
+}
+
+static void try_send_reply(struct client *c)
+{
+  struct fastbuf fb;
+  fbbuf_init_write(&fb, packet_buffer, MAX_PACKET_SIZE);
+
+  TRANS_TRY
+    {
+      json_write(c->json, &fb, c->reply);
+    }
+  TRANS_CATCH(x)
+    {
+      msg(L_ERROR, "Unable to construct reply, it is probably too long");
+      fbbuf_init_write(&fb, packet_buffer, MAX_PACKET_SIZE);
+      bputs(&fb, "{ \"error\": \"Reply too long\" }\n");
+    }
+  TRANS_END;
+
+  int len = fbbuf_count_written(&fb);
+  msg(L_INFO, "Sending reply of %d bytes", len);
+  if (send(c->socket.fd, packet_buffer, len, 0) < 0)
+    {
+      if (errno == EAGAIN || errno == EINTR)
+       {
+         msg(L_INFO, "Postponed send");
+         c->socket.write_handler = socket_write_handler;
+         file_chg(&c->socket);
+       }
+      msg(L_ERROR, "Client write error: %m");
+      client_close(c);
+    }
+  else
+    {
+      msg(L_INFO, "Reply sent");
+      c->socket.read_handler = socket_read_handler;
+      c->socket.write_handler = NULL;
+      file_chg(&c->socket);
+      timer_add_rel(&c->timer, SOCKET_TIMEOUT);
+    }
+}
+
+static void send_reply(struct client *c)
+{
+  timer_add_rel(&c->timer, SOCKET_TIMEOUT);
+  try_send_reply(c);
+}
+
+static void received_packet(struct client *c, byte *pkt, int len)
+{
+  json_reset(c->json);
+
+  struct fastbuf fb;
+  fbbuf_init_read(&fb, pkt, len, 0);
+
+  c->reply = json_new_object(c->json);
+
+  TRANS_TRY
+    {
+      c->request = json_parse(c->json, &fb);
+    }
+  TRANS_CATCH(x)
+    {
+      cmd_error(c, "Parse error");
+      send_reply(c);
+      return;
+    }
+  TRANS_END;
+
+  cmd_error(c, "OK");
+  send_reply(c);
+}
+
+static int socket_write_handler(struct main_file *fi)
+{
+  struct client *c = fi->data;
+  try_send_reply(c);
+  return HOOK_IDLE;
+}
+
+static int socket_read_handler(struct main_file *fi)
+{
+  struct client *c = fi->data;
+
+  struct iovec iov = {
+    .iov_base = packet_buffer,
+    .iov_len = MAX_PACKET_SIZE,
+  };
+
+  struct msghdr mh = {
+    .msg_iov = &iov,
+    .msg_iovlen = 1,
+    .msg_control = oob_data_buffer,
+    .msg_controllen = MAX_OOB_DATA_SIZE,
+  };
+
+  ssize_t len = recvmsg(fi->fd, &mh, 0);
+  if (len < 0)
+    {
+      if (errno != EAGAIN && errno != EINTR)
+       msg(L_ERROR, "Socket read: %m");
+      return HOOK_IDLE;
+    }
+
+  if (!len)
+    {
+      client_close(c);
+      return HOOK_IDLE;
+    }
+
+  struct ucred *cred = NULL;
+  for (struct cmsghdr *cm = CMSG_FIRSTHDR(&mh); cm; cm = CMSG_NXTHDR(&mh, cm))
+    {
+      if (cm->cmsg_level == SOL_SOCKET)
+       {
+         if (cm->cmsg_type == SCM_RIGHTS)
+           {
+             // We are not interested in receiving file descriptor, but despite
+             // that they could be attached to the message. If it happens, simply
+             // close them.
+             int *fdptr = (int *) CMSG_DATA(cm);
+             int nfd = cm->cmsg_len / sizeof(int);
+             for (int i=0; i<nfd; i++)
+               close(fdptr[i]);
+           }
+         else if (cm->cmsg_type == SCM_CREDENTIALS)
+           {
+             ASSERT(cm->cmsg_len >= sizeof(cred));
+             cred = (struct ucred *) CMSG_DATA(cm);
+           }
+       }
+    }
+
+  if (!cred)
+    {
+      msg(L_ERROR, "Dropping message with no credentials");
+      return HOOK_RETRY;
+    }
+
+  msg(L_INFO, "Got message from UID %d", (int) cred->uid);
+  c->uid = cred->uid;
+
+  fi->read_handler = NULL;
+  file_chg(fi);
+
+  received_packet(c, packet_buffer, len);
+  return HOOK_RETRY;
+}
+
+static int listen_read_handler(struct main_file *fi)
+{
+  struct sockaddr_un client;
+  socklen_t addr_len = sizeof(client);
+
+  int new_sk = accept(fi->fd, &client, &addr_len);
+  if (new_sk < 0)
+    {
+      if (errno != EAGAIN && errno != EINTR)
+       msg(L_ERROR, "Socket accept: %m");
+      return HOOK_IDLE;
+    }
+
+  if (num_connections >= max_connections)
+    {
+      msg(L_WARN, "Too many connections (you might need to increase MaxConnections)");
+      close(new_sk);
+      return HOOK_IDLE;
+    }
+  num_connections++;
+
+  msg(L_INFO, "Accepted connection");
+
+  if (fcntl(new_sk, F_SETFL, fcntl(new_sk, F_GETFL) | O_NONBLOCK) < 0)
+    die("Cannot set O_NONBLOCK: %m");
+
+  struct client *c = xmalloc_zero(sizeof(*c));
+  c->json = json_new();
+
+  c->socket.fd = new_sk;
+  c->socket.read_handler = socket_read_handler;
+  c->socket.data = c;
+  file_add(&c->socket);
+
+  c->timer.handler = socket_timeout_handler;
+  c->timer.data = c;
+  timer_add_rel(&c->timer, SOCKET_TIMEOUT);
+
+  return HOOK_RETRY;
+}
+
+static void init_socket(void)
+{
+  int sk = socket(PF_UNIX, SOCK_SEQPACKET, 0);
+  if (sk < 0)
+    die("socket(PF_UNIX, SOCK_SEQPACKET): %m");
+
+  if (fcntl(sk, F_SETFL, fcntl(sk, F_GETFL) | O_NONBLOCK) < 0)
+    die("Cannot set O_NONBLOCK: %m");
+
+  struct sockaddr_un sun;
+  sun.sun_family = AF_UNIX;
+  if (strlen(socket_path) >= sizeof(sun.sun_path))
+    die("SocketPath too long");
+  strcpy(sun.sun_path, socket_path);
+
+  if (unlink(socket_path) < 0 && errno != ENOENT)
+    die("Cannot unlink old socket %s: %m", socket_path);
+
+  if (bind(sk, (struct sockaddr *) &sun, sizeof(sun)) < 0)
+    die("Cannot bind to %s: %m", socket_path);
+
+  if (listen(sk, 64) < 0)
+    die("listen(): %m");
+
+  int one;
+  if (setsockopt(sk, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0)
+    die("setsockopt(SO_PASSCRED): %m");
+
+  listen_socket.fd = sk;
+  listen_socket.read_handler = listen_read_handler;
+  file_add(&listen_socket);
+
+  msg(L_INFO, "Listening on %s", socket_path);
+}
+
+static struct cf_section daemon_config = {
+  CF_ITEMS {
+    CF_STRING("SocketPath", &socket_path),
+    CF_UINT("MaxConnections", &max_connections),
+    CF_END
+  }
+};
+
+static const struct opt_section options = {
+  OPT_ITEMS {
+    OPT_HELP("A sub-authentication daemon."),
+    OPT_HELP("Usage: subauthd [options]"),
+    OPT_HELP(""),
+    OPT_HELP("Options:"),
+    OPT_HELP_OPTION,
+    OPT_CONF_OPTIONS,
+    OPT_END
+  }
+};
+
+int main(int argc UNUSED, char **argv)
+{
+  cf_def_file = CONFIG_DIR "/subauthd";
+  cf_declare_section("SubauthD", &daemon_config, 0);
+  opt_parse(&options, argv+1);
+
+  main_init();
+  init_socket();
+
+  main_loop();
+  return 0;
+}
diff --git a/server/subauthd.h b/server/subauthd.h
new file mode 100644 (file)
index 0000000..4a104ec
--- /dev/null
@@ -0,0 +1,27 @@
+/*
+ *     Sub-authentication Daemon
+ *
+ *     (c) 2017 Martin Mares <mj@ucw.cz>
+ */
+
+#include "autoconf.h"
+
+#include <ucw/mainloop.h>
+#include <ucw-json/json.h>
+
+#define SOCKET_TIMEOUT 60000           // in ms
+#define MAX_PACKET_SIZE 16384
+#define MAX_OOB_DATA_SIZE 4096
+
+struct client {
+  struct main_file socket;
+  struct main_timer timer;
+  int uid;
+  struct json_context *json;
+  struct json_node *request;
+  struct json_node *reply;
+};
+
+/* cmd.c */
+
+void cmd_error(struct client *c, const char *err);
diff --git a/subauth.c b/subauth.c
deleted file mode 100644 (file)
index e597b76..0000000
--- a/subauth.c
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- *     Sub-authentication Client
- *
- *     (c) 2017 Martin Mares <mj@ucw.cz>
- */
-
-#include <ucw/lib.h>
-#include <ucw/opt.h>
-#include <ucw-json/json.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "autoconf.h"
-
-static char *socket_path = INSTALL_RUN_DIR "/subauthd.socket";
-
-static const struct opt_section options = {
-  OPT_ITEMS {
-    OPT_HELP("A client to the sub-authentication daemon."),
-    OPT_HELP("Usage: subauth [options]"),
-    OPT_HELP(""),
-    OPT_HELP("Options:"),
-    OPT_HELP_OPTION,
-    OPT_END
-  }
-};
-
-int main(int argc UNUSED, char **argv)
-{
-  opt_parse(&options, argv+1);
-
-  int sk = socket(PF_UNIX, SOCK_SEQPACKET, 0);
-  if (sk < 0)
-    die("socket(PF_UNIX, SOCK_SEQPACKET): %m");
-
-  struct sockaddr_un sun;
-  sun.sun_family = AF_UNIX;
-  if (strlen(socket_path) >= sizeof(sun.sun_path))
-    die("Socket path too long");
-  strcpy(sun.sun_path, socket_path);
-
-  if (connect(sk, (struct sockaddr *) &sun, sizeof(sun)) < 0)
-    die("Cannot connect to %s: %m", socket_path);
-
-  struct fastbuf *out = bfdopen(1, 4096);
-
-  struct json_context *js = json_new();
-  struct json_node *rq = json_new_object(js);
-
-  bprintf(out, ">>> Request:\n");
-  json_write(js, out, rq);
-  bflush(out);
-
-  struct fastbuf *rq_fb = fbgrow_create(4096);
-  json_write(js, rq_fb, rq);
-  byte *rq_buf;
-  uint rq_len = fbgrow_get_buf(rq_fb, &rq_buf);
-  if (send(sk, rq_buf, rq_len, 0) < 0)
-    die("Cannot send request: %m");
-  bclose(rq_fb);
-
-  byte rp_buf[4096];           // FIXME
-  int rp_len = recv(sk, rp_buf, sizeof(rp_buf), 0);
-  if (rp_len < 0)
-    die("Cannot receive reply: %m");
-
-  puts("Parsing reply");
-  struct fastbuf rp_fb;
-  fbbuf_init_read(&rp_fb, rp_buf, rp_len, 0);
-  struct json_node *rp = json_parse(js, &rp_fb);
-  bprintf(out, "<<< Reply:\n");
-  json_write(js, out, rp);
-  bflush(out);
-
-  return 0;
-}
diff --git a/subauthd.c b/subauthd.c
deleted file mode 100644 (file)
index bc76ef5..0000000
+++ /dev/null
@@ -1,327 +0,0 @@
-/*
- *     Sub-authentication Daemon
- *
- *     (c) 2017 Martin Mares <mj@ucw.cz>
- */
-
-#include <ucw/lib.h>
-#include <ucw/conf.h>
-#include <ucw/log.h>
-#include <ucw/mainloop.h>
-#include <ucw/opt.h>
-#include <ucw/trans.h>
-#include <ucw-json/json.h>
-
-#include <errno.h>
-#include <fcntl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <unistd.h>
-
-#include "autoconf.h"
-
-static char *socket_path = "subauthd.socket";
-static uint max_connections = ~0U;
-
-static struct main_file listen_socket;
-static uint num_connections;
-
-#define SOCKET_TIMEOUT 60000           // in ms
-#define MAX_PACKET_SIZE 16384
-#define MAX_OOB_DATA_SIZE 4096
-
-struct client {
-  struct main_file socket;
-  struct main_timer timer;
-  int uid;
-  struct json_context *json;
-  struct json_node *request;
-  struct json_node *reply;
-};
-
-static byte packet_buffer[MAX_PACKET_SIZE];
-static byte oob_data_buffer[MAX_OOB_DATA_SIZE];
-
-static int socket_read_handler(struct main_file *fi);
-static int socket_write_handler(struct main_file *fi);
-
-static void client_close(struct client *c)
-{
-  msg(L_INFO, "Closing connection");
-  file_del(&c->socket);
-  timer_del(&c->timer);
-  close(c->socket.fd);
-  json_delete(c->json);
-  xfree(c);
-  num_connections--;
-}
-
-static void cmd_error(struct client *c, const char *err)
-{
-  json_object_set(c->reply, "error", json_new_string(c->json, err));
-}
-
-static void socket_timeout_handler(struct main_timer *tm)
-{
-  struct client *c = tm->data;
-
-  msg(L_INFO, "Client timeout");
-
-  client_close(c);
-}
-
-static void try_send_reply(struct client *c)
-{
-  struct fastbuf fb;
-  fbbuf_init_write(&fb, packet_buffer, MAX_PACKET_SIZE);
-
-  TRANS_TRY
-    {
-      json_write(c->json, &fb, c->reply);
-    }
-  TRANS_CATCH(x)
-    {
-      msg(L_ERROR, "Unable to construct reply, it is probably too long");
-      fbbuf_init_write(&fb, packet_buffer, MAX_PACKET_SIZE);
-      bputs(&fb, "{ \"error\": \"Reply too long\" }\n");
-    }
-  TRANS_END;
-
-  int len = fbbuf_count_written(&fb);
-  msg(L_INFO, "Sending reply of %d bytes", len);
-  if (send(c->socket.fd, packet_buffer, len, 0) < 0)
-    {
-      if (errno == EAGAIN || errno == EINTR)
-       {
-         msg(L_INFO, "Postponed send");
-         c->socket.write_handler = socket_write_handler;
-         file_chg(&c->socket);
-       }
-      msg(L_ERROR, "Client write error: %m");
-      client_close(c);
-    }
-  else
-    {
-      msg(L_INFO, "Reply sent");
-      c->socket.read_handler = socket_read_handler;
-      c->socket.write_handler = NULL;
-      file_chg(&c->socket);
-      timer_add_rel(&c->timer, SOCKET_TIMEOUT);
-    }
-}
-
-static void send_reply(struct client *c)
-{
-  timer_add_rel(&c->timer, SOCKET_TIMEOUT);
-  try_send_reply(c);
-}
-
-static void received_packet(struct client *c, byte *pkt, int len)
-{
-  json_reset(c->json);
-
-  struct fastbuf fb;
-  fbbuf_init_read(&fb, pkt, len, 0);
-
-  c->reply = json_new_object(c->json);
-
-  TRANS_TRY
-    {
-      c->request = json_parse(c->json, &fb);
-    }
-  TRANS_CATCH(x)
-    {
-      cmd_error(c, "Parse error");
-      send_reply(c);
-      return;
-    }
-  TRANS_END;
-
-  cmd_error(c, "OK");
-  send_reply(c);
-}
-
-static int socket_write_handler(struct main_file *fi)
-{
-  struct client *c = fi->data;
-  try_send_reply(c);
-  return HOOK_IDLE;
-}
-
-static int socket_read_handler(struct main_file *fi)
-{
-  struct client *c = fi->data;
-
-  struct iovec iov = {
-    .iov_base = packet_buffer,
-    .iov_len = MAX_PACKET_SIZE,
-  };
-
-  struct msghdr mh = {
-    .msg_iov = &iov,
-    .msg_iovlen = 1,
-    .msg_control = oob_data_buffer,
-    .msg_controllen = MAX_OOB_DATA_SIZE,
-  };
-
-  ssize_t len = recvmsg(fi->fd, &mh, 0);
-  if (len < 0)
-    {
-      if (errno != EAGAIN && errno != EINTR)
-       msg(L_ERROR, "Socket read: %m");
-      return HOOK_IDLE;
-    }
-
-  if (!len)
-    {
-      client_close(c);
-      return HOOK_IDLE;
-    }
-
-  struct ucred *cred = NULL;
-  for (struct cmsghdr *cm = CMSG_FIRSTHDR(&mh); cm; cm = CMSG_NXTHDR(&mh, cm))
-    {
-      if (cm->cmsg_level == SOL_SOCKET)
-       {
-         if (cm->cmsg_type == SCM_RIGHTS)
-           {
-             // We are not interested in receiving file descriptor, but despite
-             // that they could be attached to the message. If it happens, simply
-             // close them.
-             int *fdptr = (int *) CMSG_DATA(cm);
-             int nfd = cm->cmsg_len / sizeof(int);
-             for (int i=0; i<nfd; i++)
-               close(fdptr[i]);
-           }
-         else if (cm->cmsg_type == SCM_CREDENTIALS)
-           {
-             ASSERT(cm->cmsg_len >= sizeof(cred));
-             cred = (struct ucred *) CMSG_DATA(cm);
-           }
-       }
-    }
-
-  if (!cred)
-    {
-      msg(L_ERROR, "Dropping message with no credentials");
-      return HOOK_RETRY;
-    }
-
-  msg(L_INFO, "Got message from UID %d", (int) cred->uid);
-  c->uid = cred->uid;
-
-  fi->read_handler = NULL;
-  file_chg(fi);
-
-  received_packet(c, packet_buffer, len);
-  return HOOK_RETRY;
-}
-
-static int listen_read_handler(struct main_file *fi)
-{
-  struct sockaddr_un client;
-  socklen_t addr_len = sizeof(client);
-
-  int new_sk = accept(fi->fd, &client, &addr_len);
-  if (new_sk < 0)
-    {
-      if (errno != EAGAIN && errno != EINTR)
-       msg(L_ERROR, "Socket accept: %m");
-      return HOOK_IDLE;
-    }
-
-  if (num_connections >= max_connections)
-    {
-      msg(L_WARN, "Too many connections (you might need to increase MaxConnections)");
-      close(new_sk);
-      return HOOK_IDLE;
-    }
-  num_connections++;
-
-  msg(L_INFO, "Accepted connection");
-
-  if (fcntl(new_sk, F_SETFL, fcntl(new_sk, F_GETFL) | O_NONBLOCK) < 0)
-    die("Cannot set O_NONBLOCK: %m");
-
-  struct client *c = xmalloc_zero(sizeof(*c));
-  c->json = json_new();
-
-  c->socket.fd = new_sk;
-  c->socket.read_handler = socket_read_handler;
-  c->socket.data = c;
-  file_add(&c->socket);
-
-  c->timer.handler = socket_timeout_handler;
-  c->timer.data = c;
-  timer_add_rel(&c->timer, SOCKET_TIMEOUT);
-
-  return HOOK_RETRY;
-}
-
-static void init_socket(void)
-{
-  int sk = socket(PF_UNIX, SOCK_SEQPACKET, 0);
-  if (sk < 0)
-    die("socket(PF_UNIX, SOCK_SEQPACKET): %m");
-
-  if (fcntl(sk, F_SETFL, fcntl(sk, F_GETFL) | O_NONBLOCK) < 0)
-    die("Cannot set O_NONBLOCK: %m");
-
-  struct sockaddr_un sun;
-  sun.sun_family = AF_UNIX;
-  if (strlen(socket_path) >= sizeof(sun.sun_path))
-    die("SocketPath too long");
-  strcpy(sun.sun_path, socket_path);
-
-  if (unlink(socket_path) < 0 && errno != ENOENT)
-    die("Cannot unlink old socket %s: %m", socket_path);
-
-  if (bind(sk, (struct sockaddr *) &sun, sizeof(sun)) < 0)
-    die("Cannot bind to %s: %m", socket_path);
-
-  if (listen(sk, 64) < 0)
-    die("listen(): %m");
-
-  int one;
-  if (setsockopt(sk, SOL_SOCKET, SO_PASSCRED, &one, sizeof(one)) < 0)
-    die("setsockopt(SO_PASSCRED): %m");
-
-  listen_socket.fd = sk;
-  listen_socket.read_handler = listen_read_handler;
-  file_add(&listen_socket);
-
-  msg(L_INFO, "Listening on %s", socket_path);
-}
-
-static struct cf_section daemon_config = {
-  CF_ITEMS {
-    CF_STRING("SocketPath", &socket_path),
-    CF_UINT("MaxConnections", &max_connections),
-    CF_END
-  }
-};
-
-static const struct opt_section options = {
-  OPT_ITEMS {
-    OPT_HELP("A sub-authentication daemon."),
-    OPT_HELP("Usage: subauthd [options]"),
-    OPT_HELP(""),
-    OPT_HELP("Options:"),
-    OPT_HELP_OPTION,
-    OPT_CONF_OPTIONS,
-    OPT_END
-  }
-};
-
-int main(int argc UNUSED, char **argv)
-{
-  cf_def_file = CONFIG_DIR "/subauthd";
-  cf_declare_section("SubauthD", &daemon_config, 0);
-  opt_parse(&options, argv+1);
-
-  main_init();
-  init_socket();
-
-  main_loop();
-  return 0;
-}