chiark / gitweb /
Allow the caller to configure the administration socket permissions.
authorMark Wooding <mdw@distorted.org.uk>
Wed, 14 Mar 2012 19:24:42 +0000 (19:24 +0000)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 14 Mar 2012 21:09:26 +0000 (21:09 +0000)
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
init/tripe.conf
server/admin.c
server/tripe.8.in
server/tripe.c
server/tripe.h

index 9f44d752045239500e7f16aa1db1811c73a99f92..68f8323a035ede723157d79331d8f3f9992b012c 100755 (executable)
@@ -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}
index a2772076c14f49cb0ddf4eec4711798f3e2af44a..7d78ee62efc02e6d940ef8696e32ff82f52384f7 100644 (file)
 ##
 #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.
index 32b35772fc52788792859a3c63b2974b690f6e5a..8eb5ec3ca5a16d3565739ffdea48ff553c75e13f 100644 (file)
@@ -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))
index f43ab5f8ca4b8d9155390618a9a98c80f4ada28e..9721246ff95661b2d9e721d966505791e0d7a325 100644 (file)
@@ -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.
index 2dc03434de57139c6b8fd9b224081d1b1813f155..1e6d406249d5a98f73105fd84513d65d2787dc66 100644 (file)
@@ -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) {
index d1093f7b774874659cde5cd04419dd5a48cc8560..c5694dc13f7170d73c1fa5d9116ab501e19e09e1 100644 (file)
@@ -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 ------------------------------------*/