Policy handling, needed some socket/base pointer rearrangement
authorChristian Thaeter <ct@pipapo.org>
Thu, 11 Oct 2007 15:28:47 +0000 (17:28 +0200)
committerChristian Thaeter <ct@pipapo.org>
Thu, 11 Oct 2007 15:28:47 +0000 (17:28 +0200)
src/main.c
src/rxpd.c
src/rxpd.h

index ed0098b..b4246fa 100644 (file)
@@ -186,12 +186,17 @@ main (int argc, char** argv)
       exit (EXIT_FAILURE);
     }
 
-  if (rxpd->policy && !rxpd_file_load (rxpd->policy))
+  if (rxpd->policy)
     {
-      rxpd_log (rxpd, LOG_ALERT, "Failed loading policy file\n");
-      exit (EXIT_FAILURE);
+      if (rxpd_file_load (rxpd->policy))
+        rxpd_log (rxpd, LOG_INFO, "Loaded policy '%s'\n", rxpd->policy->filename);
+      else
+        {
+          rxpd_log (rxpd, LOG_ALERT, "Failed loading policy file\n");
+          exit (EXIT_FAILURE);
+        }
     }
-
+      
   LLIST_FOREACH (&rxpd->sockets, n)
     {
       struct rxpd_socket* socket = (struct rxpd_socket*)n;
index 6fd52c8..b759402 100644 (file)
@@ -334,6 +334,8 @@ rxpd_socket_new_tcp4 (struct rxpd_base* base, const char* addr, unsigned short p
   if (listen (self->fd, 20) == -1)
     abort ();
 
+  self->rxpd_socket_addr = rxpd_socket_tcp4addr;
+
   event_set (&self->ev, self->fd, EV_READ, rxpd_socket_accept, self);
   llist_insert_tail (&base->sockets, &self->node);
 
@@ -341,6 +343,25 @@ rxpd_socket_new_tcp4 (struct rxpd_base* base, const char* addr, unsigned short p
   return self;
 }
 
+int
+rxpd_socket_tcp4addr (struct rxpd_connection* conn, char* dst, const char* pfx, size_t size)
+{
+  struct sockaddr_in peer;
+  socklen_t len = sizeof (peer);
+  getpeername (conn->fd, (struct sockaddr*)&peer, &len);
+
+  char* addr;
+  addr = inet_ntoa (peer.sin_addr);
+  if (sizeof (":tcp4:") + strlen (pfx) + strlen (addr) > size)
+    return 0;
+
+  strcat (dst, pfx);
+  strcat (dst, ":tcp4:");
+  strcat (dst, addr);
+  return 1;
+}
+
+
 
 void
 rxpd_socket_delete (struct rxpd_socket* self)
@@ -381,7 +402,7 @@ rxpd_socket_accept (int fd, short event, void* ptr)
   struct rxpd_socket* self = ptr;
 
   struct rxpd_connection* conn =
-    rxpd_connection_new (self->base, fd);
+    rxpd_connection_new (self, fd);
 
   rxpd_connection_schedule (conn);
   rxpd_socket_schedule (self);
@@ -491,23 +512,16 @@ rxpd_buffer_printf (struct rxpd_buffer* self, const char* fmt, ...)
 ///
 
 struct rxpd_connection*
-rxpd_connection_new (struct rxpd_base* base, int fd)
+rxpd_connection_new (struct rxpd_socket* socket, int fd)
 {
   struct rxpd_connection* self;
   self = rxpd_malloc (sizeof (struct rxpd_connection));
 
-  socklen_t addr_sz = sizeof (self->peer_addr); 
-  self->fd = accept (fd, (struct sockaddr*)&self->peer_addr, &addr_sz);
+  self->fd = accept (fd, NULL, 0);
   if (self->fd == -1)
     abort ();
 
-  //static int yes = 1;
-  //if (setsockopt (self->fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
-  //  abort ();
-
-
-
-  self->base = base;
+  self->socket = socket;
   self->file = NULL;
   self->tmp_str = NULL;
   llist_init (&self->tmp_list);
@@ -518,7 +532,7 @@ rxpd_connection_new (struct rxpd_base* base, int fd)
   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_parse_cmd, self);
 
   // TODO more info
-  rxpd_log (base, LOG_INFO, "incoming connection\n");
+  rxpd_log (socket->base, LOG_INFO, "incoming connection\n");
   return self;
 }
 
@@ -549,25 +563,65 @@ rxpd_connection_schedule (struct rxpd_connection* self)
   return self;
 }
 
+int
+rxpd_connection_check_policy (struct rxpd_connection* self, char* line)
+{
+  struct rxpd_base* base = self->socket->base;
+  if (base->policy)
+    {
+      char buf[256];
+      buf[0] = '\0';
+
+      if (!self->socket->rxpd_socket_addr (self, buf, line, 256))
+        {
+          rxpd_log (base, LOG_ERR, "policy line too long\n");
+          return 0;
+        }
+
+      rxpd_log (base, LOG_DEBUG, "policy check '%s'\n", buf);
+
+      char* match = NULL;
+      LLIST_FOREACH (&base->policy->rules, n)
+      {
+        struct rxpd_rule* rule = (struct rxpd_rule*)n;
+        if (rule->string[0] != '#')
+          {
+            if (regexec (&rule->rx, buf, 0, NULL, 0) == 0)
+              {
+                match = rule->string;
+                break;
+              }
+          }
+      }
+
+      if (!match || strncmp("ACCEPT:", match, sizeof("ACCEPT:")-1) != 0)
+        {
+          rxpd_log (base, LOG_WARNING, "access denied '%s'\n", buf);
+          return 0;
+        }
+    }
+  return 1;
+}
 void
 rxpd_connection_parse_cmd (int fd, short event, void* ptr)
 {
   (void) event;
 
   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
+  struct rxpd_base* base = self->socket->base;
 
   char* line;
   line = rxpd_buffer_readline (&self->in, 0);
 
   if (!line)
     {
-      rxpd_log (self->base, LOG_ERR, "no data\n");
+      rxpd_log (base, LOG_ERR, "no data\n");
       rxpd_buffer_printf (&self->out, "#ERROR: no data\n");
       close (fd);
       return;
     }
 
-  rxpd_log (self->base, LOG_DEBUG, "parse command '%s'\n", line);
+  rxpd_log (base, LOG_DEBUG, "parse command '%s'\n", line);
 
   static const struct cmd_table
   {
@@ -588,24 +642,30 @@ rxpd_connection_parse_cmd (int fd, short event, void* ptr)
       break;
   if (!i->cmd)
     {
-      rxpd_log (self->base, LOG_ERR, "no command\n");
+      rxpd_log (base, LOG_ERR, "no command\n");
       rxpd_buffer_printf (&self->out, "#ERROR: no command\n");
       rxpd_connection_delete (self);
       return;
     }
-  // TODO policy check here
+
+  if (!rxpd_connection_check_policy (self, line))
+    {
+      rxpd_buffer_printf (&self->out, "#ERROR: access denied\n");
+      rxpd_connection_delete (self);
+      return;
+    }
 
   if (line[i->sz])
     {
       // rulename provided
-      self->file = (struct rxpd_file*) psplay_find (&self->base->files, &line[i->sz]);
+      self->file = (struct rxpd_file*) psplay_find (&base->files, &line[i->sz]);
 
       if (!self->file)
         {
-          self->file = rxpd_file_new (self->base, &line[i->sz]);
+          self->file = rxpd_file_new (base, &line[i->sz]);
           if (!self->file)
             {
-              rxpd_log (self->base, LOG_ERR, "illeagal filename\n");
+              rxpd_log (base, LOG_ERR, "illeagal filename\n");
               rxpd_buffer_printf (&self->out, "#ERROR: illegal filename\n");
               rxpd_connection_delete (self);
               return;
@@ -966,11 +1026,12 @@ rxpd_connection_cmd_LIST (int fd, short event, void* ptr)
   (void) fd;
   (void) event;
   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
+  struct rxpd_base* base = self->socket->base;
 
-  if (psplay_isempty_root (&self->base->files))
+  if (psplay_isempty_root (&base->files))
     rxpd_buffer_printf (&self->out, "#OK:\n");
   else
-    psplay_walk (&self->base->files, NULL, walk_LIST, 0, ptr);
+    psplay_walk (&base->files, NULL, walk_LIST, 0, ptr);
 
   rxpd_connection_delete (self);
 }
@@ -981,8 +1042,9 @@ rxpd_connection_cmd_SHUTDOWN (int fd, short event, void* ptr)
   (void) fd;
   (void) event;
   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
+  struct rxpd_base* base = self->socket->base;
   // destroy all sockets
-  LLIST_WHILE_HEAD (&self->base->sockets, n)
+  LLIST_WHILE_HEAD (&base->sockets, n)
     {
       struct rxpd_socket* socket = (struct rxpd_socket*)n;
       rxpd_socket_delete (socket);
index 5480d60..61fa7db 100644 (file)
@@ -155,12 +155,17 @@ struct rxpd_socket
   int fd;
   struct event ev;
   struct rxpd_base* base;
+  int (*rxpd_socket_addr)(struct rxpd_connection* conn, char* dst, const char* pfx, size_t size);
 };
 
 
 struct rxpd_socket*
 rxpd_socket_new_tcp4 (struct rxpd_base* base, const char* addr, unsigned short port);
 
+int
+rxpd_socket_tcp4addr (struct rxpd_connection* conn, char* dst, const char* pfx, size_t size);
+
+//TODO
 //struct rxpd_socket*
 //rxpd_socket_new_unix (struct rxpd_base* base, const char* name);
 
@@ -213,32 +218,31 @@ struct rxpd_connection
 {
   int fd;
   struct event ev;
-  struct rxpd_base* base;
   struct rxpd_file* file;
+  struct rxpd_socket* socket;
   char* tmp_str;
   llist tmp_list;
 
-  struct sockaddr peer_addr;
-
   struct rxpd_buffer in;
   struct rxpd_buffer out;
 };
 
 
 struct rxpd_connection*
-rxpd_connection_new (struct rxpd_base* base, int accept_fd);
+rxpd_connection_new (struct rxpd_socket* socket, int accept_fd);
 
 void
 rxpd_connection_delete (struct rxpd_connection* self);
 
-
 struct rxpd_connection*
 rxpd_connection_schedule (struct rxpd_connection* self);
 
-
 int
 rxpd_connection_readline (struct rxpd_connection* self);
 
+int
+rxpd_connection_check_policy (struct rxpd_connection* self, char* line);
+
 void
 rxpd_connection_parse_cmd (int fd, short event, void* ptr);