cleanup and meta updates for next release
[rxpd] / src / rxpd_connection.c
1 /*
2     rxpd_connection.c - regex policy daemon
3
4   Copyright (C)
5     2007,               Christian Thaeter <ct@pipapo.org>
6
7   This program is free software; you can redistribute it and/or
8   modify it under the terms of the GNU General Public License as
9   published by the Free Software Foundation; either version 2 of the
10   License, or (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program; if not, write to the Free Software
19   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22 #include "rxpd.h"
23
24 struct rxpd_connection*
25 rxpd_connection_new (struct rxpd_socket* socket, int fd)
26 {
27   struct rxpd_connection* self;
28   self = rxpd_malloc (sizeof (struct rxpd_connection));
29
30   self->fd = accept (fd, NULL, 0);
31   if (self->fd == -1)
32     abort ();
33
34   self->socket = socket;
35   self->file = NULL;
36   self->tmp_str = NULL;
37   llist_init (&self->tmp_list);
38
39   rxpd_buffer_init (&self->in, self);
40   rxpd_buffer_init (&self->out, self);
41   
42   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_parse_cmd, self);
43
44   // TODO more info
45   rxpd_log (socket->base, LOG_INFO, "incoming connection\n");
46   return self;
47 }
48
49 void
50 rxpd_connection_delete (struct rxpd_connection* self)
51 {
52   if (self)
53     {
54       event_del (&self->ev);
55       close (self->fd);
56       free (self->tmp_str);
57       LLIST_WHILE_HEAD (&self->tmp_list, n)
58         {
59           struct rxpd_rule* node = (struct rxpd_rule*)n;
60           rxpd_rule_delete (node);
61         }
62     }
63   free (self);
64 }
65
66 struct rxpd_connection*
67 rxpd_connection_schedule (struct rxpd_connection* self)
68 {
69   if (self)
70     {
71       event_add (&self->ev, NULL);
72     }
73   return self;
74 }
75
76 int
77 rxpd_connection_check_policy (struct rxpd_connection* self, char* line)
78 {
79   struct rxpd_base* base = self->socket->base;
80   if (base->policy)
81     {
82       char buf[256];
83       buf[0] = '\0';
84
85       if (!self->socket->rxpd_socket_addr (self, buf, line, 256))
86         {
87           rxpd_log (base, LOG_ERR, "policy line too long\n");
88           return 0;
89         }
90
91       rxpd_log (base, LOG_DEBUG, "policy check '%s'\n", buf);
92
93       char* match = NULL;
94       LLIST_FOREACH (&base->policy->rules, n)
95       {
96         struct rxpd_rule* rule = (struct rxpd_rule*)n;
97         if (rule->string[0] != '#')
98           {
99             if (regexec (&rule->rx, buf, 0, NULL, 0) == 0)
100               {
101                 match = rule->string;
102                 break;
103               }
104           }
105       }
106
107       if (!match || strncmp("ACCEPT:", match, sizeof("ACCEPT:")-1) != 0)
108         {
109           rxpd_log (base, LOG_WARNING, "access denied '%s'\n", buf);
110           return 0;
111         }
112     }
113   return 1;
114 }
115
116 void
117 rxpd_connection_parse_cmd (int fd, short event, void* ptr)
118 {
119   (void) event;
120
121   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
122   struct rxpd_base* base = self->socket->base;
123
124   char* line;
125   line = rxpd_buffer_readline (&self->in, 0);
126
127   if (!line)
128     {
129       rxpd_log (base, LOG_ERR, "no data\n");
130       rxpd_buffer_printf (&self->out, "#ERROR: no data\n");
131       close (fd);
132       return;
133     }
134
135   rxpd_log (base, LOG_DEBUG, "parse command '%s'\n", line);
136
137   static const struct cmd_table
138   {
139     enum rxpd_cmd_e nr;
140     const char* cmd;
141     size_t sz;
142   } cmds[] =
143     {
144 #define RXPD_CMD(cmd, _) {RXPD_CMD_##cmd, #cmd":", sizeof (#cmd)},
145       RXPD_COMMANDS
146 #undef RXPD_CMD
147       {0, NULL, 0}
148     };
149
150   const struct cmd_table* i;
151   for (i = cmds; i->cmd; ++i)
152     if (strncmp (line, i->cmd, i->sz) == 0)
153       break;
154   if (!i->cmd)
155     {
156       rxpd_log (base, LOG_ERR, "no command\n");
157       rxpd_buffer_printf (&self->out, "#ERROR: no command\n");
158       rxpd_connection_delete (self);
159       return;
160     }
161
162   if (!rxpd_connection_check_policy (self, line))
163     {
164       rxpd_buffer_printf (&self->out, "#ERROR: access denied\n");
165       rxpd_connection_delete (self);
166       return;
167     }
168
169   if (line[i->sz])
170     {
171       // rulename provided
172       self->file = (struct rxpd_file*) psplay_find (&base->files, &line[i->sz]);
173
174       if (!self->file)
175         {
176           self->file = rxpd_file_new (base, &line[i->sz]);
177           if (!self->file)
178             {
179               rxpd_log (base, LOG_ERR, "illeagal filename\n");
180               rxpd_buffer_printf (&self->out, "#ERROR: illegal filename\n");
181               rxpd_connection_delete (self);
182               return;
183             }
184         }
185     }
186
187   // dispatch
188   switch (i->nr)
189     {
190 #define RXPD_CMD(cmd, _)                                                        \
191 case RXPD_CMD_##cmd:                                                            \
192   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_cmd_##cmd, self);    \
193   rxpd_connection_cmd_##cmd (fd, 0, ptr);                                       \
194   break;
195       RXPD_COMMANDS
196 #undef RXPD_CMD
197     }
198 }
199