]> mj.ucw.cz Git - subauth.git/commitdiff
Initial commit: just playing...
authorMartin Mares <mj@ucw.cz>
Wed, 19 Jul 2017 09:22:03 +0000 (11:22 +0200)
committerMartin Mares <mj@ucw.cz>
Wed, 19 Jul 2017 09:22:03 +0000 (11:22 +0200)
Makefile [new file with mode: 0644]
configure [new file with mode: 0755]
default.cfg [new file with mode: 0644]
subauth.c [new file with mode: 0644]
subauthd.c [new file with mode: 0644]

diff --git a/Makefile b/Makefile
new file mode 100644 (file)
index 0000000..fedb3da
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,36 @@
+# The default target
+all: runtree programs configs
+
+# Include configuration
+s=.
+-include obj/config.mk
+obj/config.mk:
+       @echo "You need to run configure first." && false
+
+# Do not show strange errors if the BUILDSYS is not set
+# (it happens if noone called configure as reported above)
+ifdef BUILDSYS
+
+# We will use the libucw build system
+include $(BUILDSYS)/Maketop
+
+EXTRA_RUNDIRS=run
+
+# Add the detected flags to all the global flags
+CFLAGS+=$(LIBUCW_CFLAGS)
+LIBS+=$(LIBUCW_LIBS)
+
+# Programs we want to compile
+PROGS+=$(o)/subauthd $(o)/subauth
+
+# And how they are created
+$(o)/subauthd: $(o)/subauthd.o $(LIBUCW)
+$(o)/subauth: $(o)/subauth.o $(LIBUCW)
+
+# Configuration files
+CONFIGS+=subauthd
+
+# And finally the default rules of the build system
+include $(BUILDSYS)/Makebottom
+
+endif
diff --git a/configure b/configure
new file mode 100755 (executable)
index 0000000..3d741cd
--- /dev/null
+++ b/configure
@@ -0,0 +1,44 @@
+#!/usr/bin/perl
+# Configure script for the sub-authentication daemon
+# Inspired by LibUCW examples
+
+use warnings;
+use strict;
+
+our($srcdir, $libdir);
+BEGIN {
+       # Find the sources
+       my $pkgfile = "subauthd.c";
+       if (!defined ($srcdir = $ENV{"SRCDIR"})) {
+               if (-f $pkgfile) {
+                       $srcdir=".";
+               } elsif ($0 =~ m@^(.*)/configure$@ && -f "$1/$pkgfile") {
+                       $srcdir=$1;
+               } else {
+                       die "Don't know how to find myself. Please set SRCDIR manually.\n";
+               }
+       }
+       # Ask pkg-config if libucw is installed and find its configure modules
+       `pkg-config libucw --atleast-version=3.13`;
+       !$? or die "Package `libucw' (version 3.13 or newer) not found. Is PKG_CONFIG_PATH set properly?\n";
+       $libdir=`pkg-config libucw --variable=perl_modules_dir`;
+       chomp $libdir;
+       die "Unable to find the libucw configure system\n" if $? || not defined $libdir;
+}
+use lib $libdir;
+use UCW::Configure;
+
+Init($srcdir, 'default.cfg');
+Log "### Configuring subauthd ###\n\n";
+Include Get("CONFIG");
+# What should be detected?
+require UCW::Configure::Build;
+require UCW::Configure::Paths;
+require UCW::Configure::C;
+require UCW::Configure::Pkg;
+
+# Get some libraries
+UCW::Configure::Pkg::PkgConfig("libucw") or Fail("libUCW is required");
+Finish();
+
+Log "\nConfigured, run `make' to build everything.\n";
diff --git a/default.cfg b/default.cfg
new file mode 100644 (file)
index 0000000..f2062af
--- /dev/null
@@ -0,0 +1,4 @@
+# You can specify default configuration here:
+# Set("SOME_SYMBOL");
+
+1;
diff --git a/subauth.c b/subauth.c
new file mode 100644 (file)
index 0000000..cb64f94
--- /dev/null
+++ b/subauth.c
@@ -0,0 +1,53 @@
+/*
+ *     Sub-authentication Client
+ *
+ *     (c) 2017 Martin Mares <mj@ucw.cz>
+ */
+
+#include <ucw/lib.h>
+#include <ucw/opt.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);
+
+  char msg[] = "Brum!";
+  if (send(sk, msg, sizeof(msg), 0) < 0)
+    die("Send failed: %m");
+
+  return 0;
+}
diff --git a/subauthd.c b/subauthd.c
new file mode 100644 (file)
index 0000000..d8ee471
--- /dev/null
@@ -0,0 +1,227 @@
+/*
+ *     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 <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 4096
+#define MAX_OOB_DATA_SIZE 4096
+
+struct client {
+  struct main_file socket;
+  struct main_timer timer;
+};
+
+static byte packet_buffer[MAX_PACKET_SIZE];
+static byte oob_data_buffer[MAX_OOB_DATA_SIZE];
+
+static void client_close(struct client *c)
+{
+  msg(L_INFO, "Closing connection");
+  file_del(&c->socket);
+  timer_del(&c->timer);
+  close(c->socket.fd);
+}
+
+static void socket_timeout_handler(struct main_timer *tm)
+{
+  struct client *c = tm->data;
+
+  msg(L_INFO, "Client timeout");
+
+  client_close(c);
+}
+
+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;
+    }
+
+  msg(L_INFO, "Got packet: len=%zd", len);
+
+  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, "Credentials: pid=%d uid=%d gid=%d", (int) cred->pid, (int) cred->uid, (int) cred->gid);
+
+  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->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;
+}