summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--bin/Makefile15
-rw-r--r--bin/conn.c144
-rw-r--r--bin/conn.h8
-rw-r--r--bin/list.h112
-rw-r--r--bin/lua-privsep.c7
-rw-r--r--bin/lua-privsep.h6
-rw-r--r--bin/privsep-server.c35
7 files changed, 319 insertions, 8 deletions
diff --git a/bin/Makefile b/bin/Makefile
index e0e03cb..de61268 100644
--- a/bin/Makefile
+++ b/bin/Makefile
@@ -1,5 +1,5 @@
-COMPILE_PROG = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $($@_objs) $($@_libs)
+COMPILE_PROG = $(CC) $(CFLAGS) $(LDFLAGS) -o $@ $($@-objs) $($@-libs)
PKGCONF ?= pkg-config
@@ -8,9 +8,16 @@ LUA_PKG ?= lua
LUA_CFLAGS := $(shell $(PKGCONF) --cflags $(LUA_PKG))
LUA_LIBS := $(shell $(PKGCONF) --libs $(LUA_PKG))
-lua-privsep_objs = lua-privsep.o
-lua-privsep_libs = $(LUA_LIBS)
+LIBEV_LIBS := -lev
-lua-privsep: $(lua-privsep_objs)
+privsep-server-objs = privsep-server.o lua-privsep.o conn.o
+privsep-server-libs = $(LUA_LIBS) $(LIBEV_LIBS)
+
+all: privsep-server
+
+privsep-server: $(privsep-server-objs)
$(COMPILE_PROG)
+clean:
+ rm -f $(privsep-server-objs) privsep-server
+
diff --git a/bin/conn.c b/bin/conn.c
new file mode 100644
index 0000000..90777ba
--- /dev/null
+++ b/bin/conn.c
@@ -0,0 +1,144 @@
+
+#include <sys/socket.h>
+#include <sys/un.h>
+
+#include <stdio.h>
+
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <ev.h>
+
+#include "list.h"
+#include "conn.h"
+
+#ifndef DEBUG
+#define log_debug(x) printf("%s\n", x)
+#define log_perror(x) perror(x)
+#endif
+
+#ifndef MSG_MAX_SIZE
+#define MSG_MAX_SIZE 16386
+#endif
+
+static struct ev_io accept_io;
+
+struct conn {
+ struct ev_io io;
+ struct ev_timer timeout;
+ size_t num_read;
+ char msg[MSG_MAX_SIZE];
+};
+
+static void conn_free(struct ev_loop *loop, struct conn *rm)
+{
+ int fd = rm->io.fd;
+
+ ev_io_stop(loop, &rm->io);
+ ev_timer_stop(loop, &rm->timeout);
+ close(fd);
+ free(rm);
+ log_debug("Connection closed");
+}
+
+static void conn_recv_cb (struct ev_loop *loop, struct ev_io *w,
+ int revents)
+{
+ struct conn *conn = container_of(w, struct conn, io);
+ int len, i;
+ char *args;
+
+ len = recv(conn->io.fd, conn->msg, sizeof(conn->msg) - conn->num_read,
+ MSG_DONTWAIT);
+ if (len < 0 && errno == EAGAIN)
+ return;
+ if (len <= 0)
+ goto err;
+
+ conn->num_read += len;
+ if (conn->num_read >= sizeof(conn->msg))
+ goto err;
+
+ call_lua(conn->num_read, conn->msg);
+ return;
+
+err:
+ conn_free(loop, conn);
+}
+
+static void conn_timeout_cb (struct ev_loop *loop, struct ev_timer *t,
+ int revents)
+{
+ log_debug("Connection timed out");
+ conn_free(loop, container_of(t, struct conn, timeout));
+}
+
+static void conn_accept_cb(struct ev_loop *loop, struct ev_io *w,
+ int revents)
+{
+ struct conn *conn;
+ struct sockaddr_storage from;
+ socklen_t fromlen = sizeof(from);
+ int fd;
+
+ fd = accept(w->fd, (struct sockaddr *) &from, &fromlen);
+ if (fd < 0) {
+ log_perror("accept");
+ return;
+ }
+ log_debug("New connection");
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ conn = calloc(1, sizeof(struct conn));
+
+ ev_io_init(&conn->io, conn_recv_cb, fd, EV_READ);
+ ev_io_start(loop, &conn->io);
+ ev_timer_init(&conn->timeout, conn_timeout_cb, 10.0, 0.);
+ ev_timer_start(loop, &conn->timeout);
+}
+
+
+int conn_init(struct ev_loop *loop, const char *socket_path)
+{
+ struct sockaddr_un sun;
+ char *p;
+ int fd;
+
+ memset(&sun, 0, sizeof(sun));
+ sun.sun_family = AF_UNIX;
+ strncpy(sun.sun_path, socket_path, sizeof(sun.sun_path));
+
+ /* create the dir */
+ p = strrchr(sun.sun_path, '/');
+ if (p) {
+ *p = '\0';
+ mkdir(sun.sun_path, 0755);
+ *p = '/';
+ }
+
+ fd = socket(AF_UNIX, SOCK_STREAM, 0);
+ if (fd < 0) {
+ log_perror("socket");
+ return -1;
+ }
+
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ unlink(socket_path);
+ if (bind(fd, (struct sockaddr *) &sun, sizeof(sun)) < 0)
+ goto perr_close;
+
+ if (listen(fd, 5) < 0)
+ goto perr_close;
+
+ ev_io_init(&accept_io, conn_accept_cb, fd, EV_READ);
+ ev_io_start(loop, &accept_io);
+ return 0;
+
+perr_close:
+ log_perror(socket_path);
+ close(fd);
+ return -1;
+
+}
diff --git a/bin/conn.h b/bin/conn.h
new file mode 100644
index 0000000..f5b33a9
--- /dev/null
+++ b/bin/conn.h
@@ -0,0 +1,8 @@
+#ifndef CONN_H
+#define CONN_H
+
+#include <ev.h>
+
+int conn_init(struct ev_loop *loop, const char *socket_path);
+
+#endif
diff --git a/bin/list.h b/bin/list.h
new file mode 100644
index 0000000..1fca5e7
--- /dev/null
+++ b/bin/list.h
@@ -0,0 +1,112 @@
+/* list.h - Single and double linked list macros
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms of the GNU General Public License version 2 or later as
+ * published by the Free Software Foundation.
+ *
+ * See http://www.gnu.org/ for details.
+ *
+ * This is more or less based on the code in the linux kernel. There are
+ * minor differences and this is only a subset of the kernel version.
+ */
+
+#ifndef LIST_H
+#define LIST_H
+
+#ifndef NULL
+#define NULL 0L
+#endif
+
+#ifndef offsetof
+#ifdef __compiler_offsetof
+#define offsetof(TYPE,MEMBER) __compiler_offsetof(TYPE,MEMBER)
+#else
+#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER)
+#endif
+#endif
+
+#ifndef container_of
+#define container_of(ptr, type, member) ({ \
+ const typeof( ((type *)0)->member ) *__mptr = (ptr); \
+ (type *)( (char *)__mptr - offsetof(type,member) );})
+#endif
+
+struct list_head {
+ struct list_head *next, *prev;
+};
+
+#define LIST_INITIALIZER(l) { .next = &l, .prev = &l }
+
+static inline void list_init(struct list_head *list)
+{
+ list->next = list;
+ list->prev = list;
+}
+
+static inline void __list_add(struct list_head *new,
+ struct list_head *prev,
+ struct list_head *next)
+{
+ next->prev = new;
+ new->next = next;
+ new->prev = prev;
+ prev->next = new;
+}
+
+static inline void list_add(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head, head->next);
+}
+
+static inline void list_add_tail(struct list_head *new, struct list_head *head)
+{
+ __list_add(new, head->prev, head);
+}
+
+static inline void __list_del(struct list_head * prev, struct list_head * next)
+{
+ next->prev = prev;
+ prev->next = next;
+}
+
+static inline void list_del(struct list_head *entry)
+{
+ __list_del(entry->prev, entry->next);
+ entry->next = NULL;
+ entry->prev = NULL;
+}
+
+static inline int list_hashed(const struct list_head *n)
+{
+ return n->next != n && n->next != NULL;
+}
+
+static inline int list_empty(const struct list_head *n)
+{
+ return !list_hashed(n);
+}
+
+#define list_next(ptr, type, member) \
+ (list_hashed(ptr) ? container_of((ptr)->next,type,member) : NULL)
+
+#define list_entry(ptr, type, member) container_of(ptr,type,member)
+
+#define list_for_each(pos, head) \
+ for (pos = (head)->next; pos != (head); pos = pos->next)
+
+#define list_for_each_safe(pos, n, head) \
+ for (pos = (head)->next, n = pos->next; pos != (head); \
+ pos = n, n = pos->next)
+
+#define list_for_each_entry(pos, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = list_entry(pos->member.next, typeof(*pos), member))
+
+#define list_for_each_entry_safe(pos, n, head, member) \
+ for (pos = list_entry((head)->next, typeof(*pos), member), \
+ n = list_entry(pos->member.next, typeof(*pos), member); \
+ &pos->member != (head); \
+ pos = n, n = list_entry(n->member.next, typeof(*n), member))
+
+#endif
diff --git a/bin/lua-privsep.c b/bin/lua-privsep.c
index 1e165e1..0307d7c 100644
--- a/bin/lua-privsep.c
+++ b/bin/lua-privsep.c
@@ -32,7 +32,7 @@ static int traceback (lua_State *L) {
return 1;
}
-int main(int argc, char *argv[])
+int call_lua(const char *msg, size_t msglen)
{
const char *luamain = PRIVSEP_PATH "privileged-main.lua";
int i, traceback_index;
@@ -46,10 +46,9 @@ int main(int argc, char *argv[])
if (luaL_loadfile(L, luamain))
return luaL_error(L, "%s", luamain);
- for (i = 1; i < argc; i++)
- lua_pushstring(L, argv[i]);
+ lua_pushlstring(L, msg, msglen);
- if (lua_pcall(L, argc-1, 0, traceback_index))
+ if (lua_pcall(L, 1, 0, traceback_index))
return luaL_error(L, "error");
diff --git a/bin/lua-privsep.h b/bin/lua-privsep.h
new file mode 100644
index 0000000..fae8fcc
--- /dev/null
+++ b/bin/lua-privsep.h
@@ -0,0 +1,6 @@
+#ifndef LUA_PRIVSEP_H
+#define LUA_PRIVSEP_H
+
+int call_lua(const char *msg size_t msglen);
+
+#endif
diff --git a/bin/privsep-server.c b/bin/privsep-server.c
new file mode 100644
index 0000000..76d3f4c
--- /dev/null
+++ b/bin/privsep-server.c
@@ -0,0 +1,35 @@
+
+#include <sys/stat.h>
+#include <stdio.h>
+#include <ev.h>
+
+#ifndef DEFAULT_SOCKET_PATH
+#define DEFAULT_SOCKET_PATH "/var/run/privsep/root.sock"
+#endif
+
+static void sigint_cb(struct ev_loop *loop, ev_signal *w, int revents)
+{
+ ev_break(loop, EVBREAK_ALL);
+}
+
+int main(int argc, char *argv[])
+{
+ int c;
+ const char *socket_path = DEFAULT_SOCKET_PATH;
+ static struct ev_loop *loop;
+ static struct ev_signal signal_watcher;
+
+ loop = ev_default_loop(0);
+
+ if (conn_init(loop, socket_path) < 0)
+ return 1;
+
+ ev_signal_init(&signal_watcher, sigint_cb, SIGINT);
+ ev_signal_start(loop, &signal_watcher);
+
+ ev_run(loop, 0);
+ printf("%s\n", "Shutting down.");
+ ev_loop_destroy(loop);
+ return 0;
+}
+