bf06dbd3558aacf4d4cde59c73188f39bad89886
[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)
26 {
27   struct rxpd_connection* self;
28   self = rxpd_malloc (sizeof (struct rxpd_connection));
29
30   self->fd = accept (socket->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   self->connecter = NULL;
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       // TODO kill connecter if not self
55
56       close (self->fd);
57       free (self->tmp_str);
58       LLIST_WHILE_HEAD (&self->tmp_list, n)
59         {
60           struct rxpd_rule* node = (struct rxpd_rule*)n;
61           rxpd_rule_delete (node);
62         }
63     }
64   free (self);
65 }
66
67 struct rxpd_connection*
68 rxpd_connection_spawn (struct rxpd_connection* self)
69 {
70   if (self)
71     {
72       if (self->connecter)
73         rxpd_die ("connection thread already spawned\n");
74
75       pth_attr_t attr = pth_attr_new ();
76
77       pth_attr_set (attr, PTH_ATTR_JOINABLE, FALSE);
78
79       self->connecter = pth_spawn (attr, rxpd_connection_parse_cmd, self);
80
81       if (!self->connecter)
82         rxpd_die ("failed spawning thread\n");
83     }
84   return self;
85 }
86
87 int
88 rxpd_connection_check_policy (struct rxpd_connection* self, char* line)
89 {
90   struct rxpd_base* base = self->socket->base;
91   if (base->policy)
92     {
93       char buf[256];
94       buf[0] = '\0';
95
96       if (!self->socket->rxpd_socket_addr (self, buf, line, 256))
97         {
98           rxpd_log (base, LOG_ERR, "policy line too long\n");
99           return 0;
100         }
101
102       rxpd_log (base, LOG_DEBUG, "policy check '%s'\n", buf);
103
104       char* match = NULL;
105       LLIST_FOREACH (&base->policy->rules, n)
106       {
107         struct rxpd_rule* rule = (struct rxpd_rule*)n;
108         if (rule->string[0] != '#')
109           {
110             if (regexec (&rule->rx, buf, 0, NULL, 0) == 0)
111               {
112                 match = rule->string;
113                 break;
114               }
115           }
116       }
117
118       if (!match || strncmp("ACCEPT:", match, sizeof("ACCEPT:")-1) != 0)
119         {
120           rxpd_log (base, LOG_WARNING, "access denied '%s'\n", buf);
121           return 0;
122         }
123     }
124   return 1;
125 }
126
127 void*
128 rxpd_connection_parse_cmd (void* ptr)
129 {
130   struct rxpd_connection* self = (struct rxpd_connection*) ptr;
131   struct rxpd_base* base = self->socket->base;
132
133   char* line;
134   line = rxpd_buffer_readline (&self->in, 0);
135
136   if (!line)
137     {
138       rxpd_log (base, LOG_ERR, "no data\n");
139       rxpd_buffer_printf (&self->out, "#ERROR: no data\n");
140       close (self->fd);
141       return NULL;
142     }
143
144   rxpd_log (base, LOG_DEBUG, "parse command '%s'\n", line);
145
146   static const struct cmd_table
147   {
148     enum rxpd_cmd_e nr;
149     const char* cmd;
150     size_t sz;
151   } cmds[] =
152     {
153 #define RXPD_CMD(cmd, _) {RXPD_CMD_##cmd, #cmd":", sizeof (#cmd)},
154       RXPD_COMMANDS
155 #undef RXPD_CMD
156       {0, NULL, 0}
157     };
158
159   const struct cmd_table* i;
160   for (i = cmds; i->cmd; ++i)
161     if (strncmp (line, i->cmd, i->sz) == 0)
162       break;
163   if (!i->cmd)
164     {
165       rxpd_log (base, LOG_ERR, "no command\n");
166       rxpd_buffer_printf (&self->out, "#ERROR: no command\n");
167       rxpd_connection_delete (self);
168       return NULL;
169     }
170
171   if (!rxpd_connection_check_policy (self, line))
172     {
173       rxpd_buffer_printf (&self->out, "#ERROR: access denied\n");
174       rxpd_connection_delete (self);
175       return NULL;
176     }
177
178   if (line[i->sz])
179     {
180       // rulename provided
181       self->file = (struct rxpd_file*) psplay_find (&base->files, &line[i->sz]);
182
183       if (!self->file)
184         {
185           self->file = rxpd_file_new (base, &line[i->sz]);
186           if (!self->file)
187             {
188               rxpd_log (base, LOG_ERR, "illeagal filename\n");
189               rxpd_buffer_printf (&self->out, "#ERROR: illegal filename\n");
190               rxpd_connection_delete (self);
191               return NULL;
192             }
193         }
194     }
195
196   // dispatch
197   switch (i->nr)
198     {
199 #define RXPD_CMD(cmd, _)                                                        \
200 case RXPD_CMD_##cmd:                                                            
201
202
203   //event_set (&self->ev, self->fd, EV_READ, rxpd_connection_cmd_##cmd, self);    
204   //rxpd_connection_cmd_##cmd (fd, 0, ptr);                                       
205   break;
206       RXPD_COMMANDS
207 #undef RXPD_CMD
208         ;
209     }
210   return NULL;
211 }
212