factored the source into smaller files covering single functionality
[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 void
116 rxpd_connection_parse_cmd (int fd, short event, void* ptr)
117 {
118   (void) event;
119
120   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
121   struct rxpd_base* base = self->socket->base;
122
123   char* line;
124   line = rxpd_buffer_readline (&self->in, 0);
125
126   if (!line)
127     {
128       rxpd_log (base, LOG_ERR, "no data\n");
129       rxpd_buffer_printf (&self->out, "#ERROR: no data\n");
130       close (fd);
131       return;
132     }
133
134   rxpd_log (base, LOG_DEBUG, "parse command '%s'\n", line);
135
136   static const struct cmd_table
137   {
138     enum rxpd_cmd_e nr;
139     const char* cmd;
140     size_t sz;
141   } cmds[] =
142     {
143 #define RXPD_CMD(cmd) {RXPD_CMD_##cmd, #cmd":", sizeof (#cmd)},
144       RXPD_COMMANDS
145 #undef RXPD_CMD
146       {0, NULL, 0}
147     };
148
149   const struct cmd_table* i;
150   for (i = cmds; i->cmd; ++i)
151     if (strncmp (line, i->cmd, i->sz) == 0)
152       break;
153   if (!i->cmd)
154     {
155       rxpd_log (base, LOG_ERR, "no command\n");
156       rxpd_buffer_printf (&self->out, "#ERROR: no command\n");
157       rxpd_connection_delete (self);
158       return;
159     }
160
161   if (!rxpd_connection_check_policy (self, line))
162     {
163       rxpd_buffer_printf (&self->out, "#ERROR: access denied\n");
164       rxpd_connection_delete (self);
165       return;
166     }
167
168   if (line[i->sz])
169     {
170       // rulename provided
171       self->file = (struct rxpd_file*) psplay_find (&base->files, &line[i->sz]);
172
173       if (!self->file)
174         {
175           self->file = rxpd_file_new (base, &line[i->sz]);
176           if (!self->file)
177             {
178               rxpd_log (base, LOG_ERR, "illeagal filename\n");
179               rxpd_buffer_printf (&self->out, "#ERROR: illegal filename\n");
180               rxpd_connection_delete (self);
181               return;
182             }
183         }
184     }
185
186   // dispatch
187   switch (i->nr)
188     {
189 #define RXPD_CMD(cmd)                                                           \
190 case RXPD_CMD_##cmd:                                                            \
191   event_set (&self->ev, self->fd, EV_READ, rxpd_connection_cmd_##cmd, self);    \
192   rxpd_connection_cmd_##cmd (fd, 0, ptr);                                       \
193   break;
194       RXPD_COMMANDS
195 #undef RXPD_CMD
196     }
197 }
198