chiark / gitweb /
ipif: Permit specifying interface name, if * is allowed
authorIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 16 Apr 2017 19:12:06 +0000 (20:12 +0100)
committerIan Jackson <ijackson@chiark.greenend.org.uk>
Sun, 16 Apr 2017 19:12:06 +0000 (20:12 +0100)
Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
ipif/service.c

index 5190151..eacfc63 100644 (file)
@@ -30,7 +30,7 @@
  *
  *  The remaining arguments are supplied by the (untrusted) caller:
  *
- *  <local-addr>,<peer-addr>,<mtu>[,[<proto>]]
+ *  <local-addr>,<peer-addr>,<mtu>[,[<proto>][,[<ifnamepat>]]]
  *
  *      As for slattach.  The only supported protocol is slip.
  *      Alternatively, set to `debug' to print debugging info and
@@ -82,6 +82,9 @@
  *      service program directly (not via userv), without needing to set up
  *      permissions in /etc/userv/ipif-networks.
  *
+ *      Only `*' permits interface name patterns other than the default
+ *      value of `userv%d'.
+ *
  *   #...
  *
  *      Comment.  Blank lines are also ignored.
 static const unsigned long gidmaxval= (unsigned long)((gid_t)-2);
 static const char *const protos_ok[]= { "slip", 0 };
 static const int signals[]= { SIGHUP, SIGINT, SIGTERM, 0 };
+static const char default_ifnamepat[]= "userv%d";
 
 static const char *configstr, *proto;
 static unsigned long localaddr, peeraddr, mtu;
 static int localpming, peerpming;
-static int localallow, peerallow, allallow;
+static int localallow, peerallow, ifnameallow, allallow;
+static char *ifnamepat;
 static int nexroutes;
 static struct exroute {
   unsigned long prefix, mask;
@@ -476,6 +481,7 @@ static void pconfig(const char *configstr, int truncated) {
   case '*':
     permit_begin();
     permit_range(0UL,0UL,1,0);
+    ifnameallow= 1;
     return;
     
   case '#':
@@ -575,7 +581,7 @@ static void parseargs(int argc, const char *const *argv) {
   mtu= eat_number(&carg,"mtu", 576,65536, ",",0);
   localallow= peerallow= 0;
 
-  char *protostr = eat_optionalstr(&carg,"protocol","slip");
+  char *protostr= eat_optionalstr(&carg,"protocol","slip");
   if (!strcmp(protostr,"debug")) {
     proto= 0;
   } else {
@@ -584,6 +590,8 @@ static void parseargs(int argc, const char *const *argv) {
         cprotop++);
     if (!proto) fatal("invalid protocol");
   }
+
+  ifnamepat= eat_optionalstr(&carg,"ifname pattern",default_ifnamepat);
   
   addrnet_mustdiffer("local-addr",localaddr,~0UL, "peer-addr",peeraddr,~0UL);
   
@@ -629,6 +637,14 @@ static void checkpermit(void) {
     sprintf(erwhatbuf, "route#%d", i);
     checkallow(exroutes[i].allow, erwhatbuf, exroutes[i].prefixtxt, exroutes[i].masktxt);
   }
+  if (!strcmp(ifnamepat,default_ifnamepat))
+    ifnameallow= 1;
+  if (!ifnameallow) {
+    fprintf(stderr,
+           "userv-ipif service: access denied for interface name %s\n",
+           ifnamepat);
+    allallow= 0;
+  }
   if (!allallow) fatal("access denied");
 }
 
@@ -691,14 +707,13 @@ static int task(const char *desc) {
 }
 
 static void createif(void) {
-  static const char ifnamepat[]= "userv%d";
   struct ifreq ifr;
   int r;
 
   memset(&ifr,0,sizeof(ifr));
   ifr.ifr_flags= IFF_TUN | IFF_NO_PI;
 
-  assert(sizeof(ifr.ifr_name) >= sizeof(ifnamepat));
+  assert(sizeof(ifr.ifr_name) >= strlen(ifnamepat)+1);
   strcpy(ifr.ifr_name, ifnamepat);
 
   tunfd= open("/dev/net/tun", O_RDWR);