linux.c, yaid.c: Correct policy application for proxied queries.
authorMark Wooding <mdw@distorted.org.uk>
Sun, 21 Oct 2012 14:52:25 +0000 (15:52 +0100)
committerMark Wooding <mdw@distorted.org.uk>
Wed, 24 Oct 2012 09:24:32 +0000 (10:24 +0100)
The apparent remote address for a proxy connection is the gateway, but
in fact the information is going to some remote server.  Therefore, once
we've identified a proxy connection, overwrite the remote address in
the query with the true remote host.

This means fixing up the query structure with the gateway address next
time, so keep track of the connection remote address and restore it on
each query.

linux.c
yaid.c

diff --git a/linux.c b/linux.c
index d7d8475..2c9a1d7 100644 (file)
--- a/linux.c
+++ b/linux.c
@@ -296,21 +296,23 @@ void identify(struct query *q)
        * query is our gateway then don't check the remote address in the
        * field (but do check the port number).
        */
-      if (q->ao->sys->parseaddr(&p, &s[0].addr)) goto next_row;
+      if (q->ao->sys->parseaddr(&p, &s[i].addr)) goto next_row;
       if (*p != ':') break; p++;
-      s[0].port = strtoul(p, 0, 16);
+      s[i].port = strtoul(p, 0, 16);
       if ((i == R && gwp) ?
-           q->s[R].port != s[0].port :
-           !sockeq(q->ao, &q->s[i], &s[0]))
+           q->s[R].port != s[i].port :
+           !sockeq(q->ao, &q->s[i], &s[i]))
        goto next_row;
     }
 
     /* We got to the end, and everything matched.  If we found a UID then
-     * we're done.
+     * we're done.  If the apparent remote address is our gateway then copy
+     * the true one into the query structure.
      */
     if (uid != -1) {
       q->resp = R_UID;
       q->u.uid = uid;
+      if (gwp) q->s[R].addr = s[i].addr;
       goto done;
     }
   next_row:;
diff --git a/yaid.c b/yaid.c
index 601aa51..a99604f 100644 (file)
--- a/yaid.c
+++ b/yaid.c
@@ -55,6 +55,7 @@ struct listen {
 struct client {
   int fd;                              /* The connection to the client */
   selbuf b;                            /* Accumulate lines of input */
+  union addr raddr;                    /* Remote address */
   struct query q;                      /* The clients query and our reply */
   struct sel_timer t;                  /* Timeout for idle or doomed conn */
   struct listen *l;                    /* Back to the listener (and ops) */
@@ -656,6 +657,7 @@ static void client_line(char *line, size_t len, void *p)
   skipws(&q); if (*q) goto bad;
 
   /* Identify the connection.  Act on the result. */
+  c->q.s[R].addr = c->raddr;
   identify(&c->q);
   switch (c->q.resp) {
 
@@ -822,7 +824,7 @@ static void accept_client(int fd, unsigned mode, void *p)
   c->q.ao = l->ao;
 
   /* Collect the local and remote addresses. */
-  l->ao->sockaddr_to_addr(&ssr, &c->q.s[R].addr);
+  l->ao->sockaddr_to_addr(&ssr, &c->raddr);
   ssz = sizeof(ssl);
   if (getsockname(sk, (struct sockaddr *)&ssl, &ssz)) {
     logmsg(0, LOG_ERR,