Privileged outgoing connections.
[fwd] / inet.c
diff --git a/inet.c b/inet.c
index 70e5c90..3a4dbd5 100644 (file)
--- a/inet.c
+++ b/inet.c
@@ -1,6 +1,6 @@
 /* -*-c-*-
  *
- * $Id: inet.c,v 1.5 2003/11/25 14:08:23 mdw Exp $
+ * $Id: inet.c,v 1.6 2003/11/29 20:36:07 mdw Exp $
  *
  * Protocol specific definitions for IPv4 sockets
  *
@@ -29,6 +29,9 @@
 /*----- Revision history --------------------------------------------------* 
  *
  * $Log: inet.c,v $
+ * Revision 1.6  2003/11/29 20:36:07  mdw
+ * Privileged outgoing connections.
+ *
  * Revision 1.5  2003/11/25 14:08:23  mdw
  * Debianization.  Socket target options.  Internet binding.
  *
@@ -77,6 +80,7 @@
 #include "fw.h"
 #include "identify.h"
 #include "inet.h"
+#include "privconn.h"
 #include "reffd.h"
 #include "scan.h"
 #include "socket.h"
@@ -101,8 +105,11 @@ typedef struct inet_srcopts {
 
 typedef struct inet_targopts {
   inet_opts io;
+  int ipriv;
 } inet_targopts;
 
+#define ADDRF_PRIVCONN 16u
+
 static inet_srcopts inet_globalsrc =
   { { { 0 }, { INADDR_ANY } }, 0, &inet_globalsrc.acl };
 static inet_targopts inet_globaltarg =
@@ -201,6 +208,7 @@ static addr_opts *inet_inittargopts(void)
 {
   inet_targopts *io = CREATE(inet_targopts);
   *io = inet_globaltarg;
+  io->ipriv = -1;
   return (&io->io.ao);
 }
 
@@ -261,7 +269,8 @@ static int srcopt(scanner *sc, addr_opts *ao)
     if (sc->t == CTOK_WORD && strcmp(sc->d.buf, "from") == 0)
       token(sc);
 
-    if (sc->t == CTOK_WORD && strcmp(sc->d.buf, "priv-port") == 0) {
+    if (sc->t == CTOK_WORD && (strcmp(sc->d.buf, "priv") == 0 ||
+                              strcmp(sc->d.buf, "priv-port") == 0)) {
       acl_addpriv(&io->acltail, act);
       token(sc);
     } else {
@@ -327,6 +336,16 @@ static int targopt(scanner *sc, addr_opts *ao)
     addropt(sc, &io->io);
     CONF_ACCEPT;
   }
+  if (strcmp(sc->d.buf, "priv") == 0 ||
+      strcmp(sc->d.buf, "priv-port") == 0) {
+    token(sc);
+    if (sc->t == '=') token(sc);
+    if (conf_enum(sc, "no,yes", ENUM_ABBREV, "privileged connection status"))
+      io->io.ao.f |= ADDRF_PRIVCONN;
+    else
+      io->io.ao.f &= ~ADDRF_PRIVCONN;
+    CONF_ACCEPT;
+  }
   CONF_END;
 }
 
@@ -340,6 +359,23 @@ static int inet_option(scanner *sc, addr_opts *ao, unsigned type)
   CONF_END;
 }
 
+/* --- @confirm@ --- */
+
+static void inet_confirm(addr *a, unsigned type, addr_opts *ao)
+{
+  inet_addrx *ia = (inet_addrx *)a;
+
+  switch (type) {
+    case ADDR_DEST: {
+      inet_targopts *io = (inet_targopts *)ao;
+      if ((io->io.ao.f & ADDRF_PRIVCONN) &&
+         (io->ipriv = privconn_adddest(ia->sin.sin_addr,
+                                       ia->sin.sin_port)) < 0)
+       die(1, "couldn't add privileged connection target (too late)");
+    } break;
+  }
+}
+
 /* --- @freeopts@ --- */
 
 static void inet_freesrcopts(addr_opts *ao)
@@ -431,6 +467,10 @@ static int inet_connect(addr *a, addr_opts *ao, conn *c, endpt *e)
   inet_targopts *io = (inet_targopts *)ao;
   int fd;
 
+  if (io->ipriv >= 0) {
+    return (privconn_connect(c, sel, io->ipriv, io->io.bind,
+                            starget_connected, e));
+  }
   if ((fd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
     goto fail_0;
   if (io->io.bind.s_addr != INADDR_ANY) {
@@ -456,7 +496,7 @@ fail_0:
 addr_ops inet_ops = {
   "inet",
   inet_read, inet_destroy, inet_print,
-  inet_initsrcopts, inet_option, inet_freesrcopts,
+  inet_initsrcopts, inet_option, inet_confirm, inet_freesrcopts,
   inet_bind, 0, inet_accept,
   inet_inittargopts, inet_freetargopts,
   inet_connect