From a9279e37b649abd11bbc416398cfaf787cd8d865 Mon Sep 17 00:00:00 2001 From: Mark Wooding Date: Wed, 14 Mar 2012 19:24:42 +0000 Subject: [PATCH] Allow the caller to configure the administration socket permissions. Now we can have a group of server administrators. As part of this, move the change of permissions after the change of ownership to avoid a brief window where the wrong group might have access to the socket. --- init/tripe-init.in | 1 + init/tripe.conf | 6 ++++++ server/admin.c | 11 ++++++----- server/tripe.8.in | 12 ++++++++++++ server/tripe.c | 14 +++++++++++--- server/tripe.h | 4 +++- 6 files changed, 39 insertions(+), 9 deletions(-) diff --git a/init/tripe-init.in b/init/tripe-init.in index 9f44d752..68f8323a 100755 --- a/init/tripe-init.in +++ b/init/tripe-init.in @@ -141,6 +141,7 @@ case "$1" in ${port+-S-p}${port} \ ${user+-U}${user} \ ${group+-G}${group} \ + ${sockmode+-m}${sockmode} \ ${trace+-S-T}${trace} \ ${tunnel+-S-n}${tunnel} \ ${miscopts} diff --git a/init/tripe.conf b/init/tripe.conf index a2772076..7d78ee62 100644 --- a/init/tripe.conf +++ b/init/tripe.conf @@ -49,6 +49,12 @@ ## #group=tripe +## The permissions to set on the administration socket. The default is 600, +## which allows only the configured user to connect. Setting 660 allows +## all members of the group to administer the server, which might be useful. +## Setting this to 666 is probably a really bad idea. +#mode=600 + ## Trace options to pass to tripe. The default is no tracing. The setting ## `A-cp' gives maxmimum possible verbosity without leaking important ## secrets. diff --git a/server/admin.c b/server/admin.c index 32b35772..8eb5ec3c 100644 --- a/server/admin.c +++ b/server/admin.c @@ -2213,13 +2213,14 @@ void a_daemon(void) { flags |= F_DAEMON; } * Arguments: @const char *name@ = socket name to create * @uid_t u@ = user to own the socket * @gid_t g@ = group to own the socket + * @mode_t m@ = permissions to set on the socket * * Returns: --- * * Use: Creates the admin listening socket. */ -void a_init(const char *name, uid_t u, gid_t g) +void a_init(const char *name, uid_t u, gid_t g, mode_t m) { int fd; int n = 5; @@ -2275,14 +2276,14 @@ again: close(fd); goto again; } - if (chmod(sun.sun_path, 0600)) { - die(EXIT_FAILURE, "failed to set socket permissions: %s", - strerror(errno)); - } if (chown(sun.sun_path, u, g)) { die(EXIT_FAILURE, "failed to set socket owner: %s", strerror(errno)); } + if (chmod(sun.sun_path, m)) { + die(EXIT_FAILURE, "failed to set socket permissions: %s", + strerror(errno)); + } umask(omask); fdflags(fd, O_NONBLOCK, O_NONBLOCK, FD_CLOEXEC, FD_CLOEXEC); if (listen(fd, 5)) diff --git a/server/tripe.8.in b/server/tripe.8.in index f43ab5f8..9721246f 100644 --- a/server/tripe.8.in +++ b/server/tripe.8.in @@ -55,6 +55,8 @@ tripe \- a simple VPN daemon .IR group ] .RB [ \-a .IR socket ] +.RB [ \-m +.IR mode ] .RB [ \-T .IR trace-opts ] .br @@ -256,6 +258,16 @@ if that's not set either, then a default default of .B "\*(/s/tripesock" is used instead. .TP +.BI "\-m, \-\-admin\-perms=" mode +Permissions (as an octal number) to set on the administration socket. The +default is 600, which allows only the socket owner. Setting 660 allows +members of the +.I group +configured through the +.B \-G +option to connect to the socket, which may be useful. Allowing world access +is a terrible idea. +.TP .BI "\-T, \-\-trace=" trace-opts Allows the enabling or disabling of various internal diagnostics. See below for the list of options. diff --git a/server/tripe.c b/server/tripe.c index 2dc03434..1e6d4062 100644 --- a/server/tripe.c +++ b/server/tripe.c @@ -73,7 +73,7 @@ static void interval(struct timeval *tv, void *v) static void usage(FILE *fp) { pquis(fp, "Usage: $ [-DF] [-d DIR] [-b ADDR] [-p PORT] [-n TUNNEL]\n\ - [-U USER] [-G GROUP] [-a SOCKET] [-T TRACE-OPTS]\n\ + [-U USER] [-G GROUP] [-a SOCKET] [-m MODE] [-T TRACE-OPTS]\n\ [-k PRIV-KEYRING] [-K PUB-KEYRING] [-t KEY-TAG]\n"); } @@ -105,6 +105,7 @@ Options:\n\ -K, --pub-keyring=FILE Get public keys from FILE.\n\ -t, --tag=KEYTAG Use private key labelled TAG.\n\ -a, --admin-socket=FILE Use FILE as the adminstration socket.\n\ +-m, --admin-perms=MODE Permissions to set on admin socket [default 600].\n\ " T( "\ -T, --trace=OPTIONS Turn on tracing options.\n\ " ) "\ @@ -116,6 +117,7 @@ int main(int argc, char *argv[]) const char *kr_priv = "keyring", *kr_pub = "keyring.pub"; const char *tag_priv = 0; const char *csock = SOCKETDIR "/tripesock"; + int csockmode = 0600; const char *dir = CONFIGDIR; const char *p; unsigned port = TRIPE_PORT; @@ -162,6 +164,7 @@ int main(int argc, char *argv[]) { "pub-keyring", OPTF_ARGREQ, 0, 'K' }, { "tag", OPTF_ARGREQ, 0, 't' }, { "admin-socket", OPTF_ARGREQ, 0, 'a' }, + { "admin-perms", OPTF_ARGREQ, 0, 'm' }, #ifndef NTRACE { "trace", OPTF_ARGREQ, 0, 'T' }, #endif @@ -169,7 +172,7 @@ int main(int argc, char *argv[]) { 0, 0, 0, 0 } }; - i = mdwopt(argc, argv, "hvuDFU:G:b:n:p:d:k:K:t:a:" T("T:"), + i = mdwopt(argc, argv, "hvuDFU:G:b:n:p:d:k:K:t:a:m:" T("T:"), opts, 0, 0, 0); if (i < 0) break; @@ -238,6 +241,11 @@ int main(int argc, char *argv[]) case 'a': csock = optarg; break; + case 'm': { + char *p; + csockmode = strtol(optarg, &p, 8); + if (*p) die(EXIT_FAILURE, "bad permissions: `%s'", optarg); + } break; case 't': tag_priv = optarg; break; @@ -289,7 +297,7 @@ int main(int argc, char *argv[]) a_create(STDIN_FILENO, STDOUT_FILENO, af); } ps_split(f & f_daemon); - a_init(csock, u, g); + a_init(csock, u, g, csockmode); u_setugid(u, g); km_init(kr_priv, kr_pub, tag_priv); if (f & f_daemon) { diff --git a/server/tripe.h b/server/tripe.h index d1093f7b..c5694dc1 100644 --- a/server/tripe.h +++ b/server/tripe.h @@ -933,13 +933,15 @@ extern void a_daemon(void); * Arguments: @const char *sock@ = socket name to create * @uid_t u@ = user to own the socket * @gid_t g@ = group to own the socket + * @mode_t m@ = permissions to set on the socket * * Returns: --- * * Use: Creates the admin listening socket. */ -extern void a_init(const char */*sock*/, uid_t /*u*/, gid_t /*g*/); +extern void a_init(const char */*sock*/, + uid_t /*u*/, gid_t /*g*/, mode_t /*m*/); /*----- Mapping with addresses as keys ------------------------------------*/ -- 2.11.0