cleaned up some code, removed/improved few comments, better logging
[rxpd.git] / src / rxpd_connection.c
blob51558bd8d6348df66412536bd58e367ad11686e7
1 /*
2 rxpd_connection.c - regex policy daemon
4 Copyright (C)
5 2007, Christian Thaeter <ct@pipapo.org>
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.
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.
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.
22 #include "rxpd.h"
24 struct rxpd_connection*
25 rxpd_connection_new (struct rxpd_socket* socket, int fd)
27 struct rxpd_connection* self;
28 self = rxpd_malloc (sizeof (struct rxpd_connection));
30 self->fd = fd;
31 self->socket = socket;
32 self->file = NULL;
33 self->tmp_str = NULL;
34 llist_init (&self->tmp_list);
36 rxpd_buffer_init (&self->in, fd);
37 rxpd_buffer_init (&self->out, fd);
39 self->connecter = NULL;
41 return self;
44 void
45 rxpd_connection_delete (struct rxpd_connection* self)
47 if (self)
49 close (self->fd);
50 free (self->tmp_str);
51 LLIST_WHILE_HEAD (&self->tmp_list, n)
53 struct rxpd_rule* node = (struct rxpd_rule*)n;
54 rxpd_rule_delete (node);
57 free (self);
60 struct rxpd_connection*
61 rxpd_connection_spawn (struct rxpd_connection* self)
63 if (self)
65 if (self->connecter)
66 rxpd_die ("connection thread already spawned\n");
68 pth_attr_t attr = pth_attr_new ();
70 pth_attr_set (attr, PTH_ATTR_JOINABLE, FALSE);
72 self->connecter = pth_spawn (attr, rxpd_connection_parse_cmd, self);
74 if (!self->connecter)
75 rxpd_die ("failed spawning thread\n");
77 return self;
80 int
81 rxpd_connection_check_policy (struct rxpd_connection* self, char* line)
83 struct rxpd_base* base = self->socket->base;
84 if (base->policy)
86 char buf[256];
87 buf[0] = '\0';
89 if (!self->socket->rxpd_socket_addr (self, buf, line, 256))
91 rxpd_log (base, LOG_ERR, "policy line too long\n");
92 return 0;
95 char* match = NULL;
96 LLIST_FOREACH (&base->policy->rules, n)
98 struct rxpd_rule* rule = (struct rxpd_rule*)n;
99 if (rule->string[0] != '#')
101 if (regexec (&rule->rx, buf, 0, NULL, 0) == 0)
103 match = rule->string;
104 break;
109 if (!match || !RXPD_PREFIXCMP (match, "ACCEPT:"))
111 rxpd_log (base, LOG_WARNING, "policy check: access denied '%s'\n", buf);
112 return 0;
114 rxpd_log (base, LOG_NOTICE, "policy check: permitted '%s'\n", buf);
116 return 1;
119 void*
120 rxpd_connection_parse_cmd (void* ptr)
122 struct rxpd_connection* self = (struct rxpd_connection*) ptr;
123 struct rxpd_base* base = self->socket->base;
125 char* line;
126 line = rxpd_buffer_readline (&self->in);
128 if (!line)
130 rxpd_log (base, LOG_ERR, "no data\n");
131 rxpd_buffer_printf (&self->out, "#ERROR: no data\n");
132 close (self->fd);
133 return NULL;
136 rxpd_log (base, LOG_DEBUG, "parse command '%s'\n", line);
138 static const struct cmd_table
140 enum rxpd_cmd_e nr;
141 const char* cmd;
142 size_t sz;
143 } cmds[] =
145 #define RXPD_CMD(cmd, _) {RXPD_CMD_##cmd, #cmd":", sizeof (#cmd)},
146 RXPD_COMMANDS
147 #undef RXPD_CMD
148 {0, NULL, 0}
151 const struct cmd_table* i;
152 for (i = cmds; i->cmd; ++i)
153 if (strncmp (line, i->cmd, i->sz) == 0)
154 break;
156 if (!i->cmd)
158 rxpd_log (base, LOG_ERR, "no command\n");
159 rxpd_buffer_printf (&self->out, "#ERROR: no command\n");
160 rxpd_connection_delete (self);
161 return NULL;
164 if (!rxpd_connection_check_policy (self, line))
166 rxpd_buffer_printf (&self->out, "#ERROR: access denied\n");
167 rxpd_connection_delete (self);
168 return NULL;
171 if (line[i->sz])
173 // rulename provided
174 self->file = (struct rxpd_file*) psplay_find (&base->files, &line[i->sz]);
176 if (!self->file)
178 self->file = rxpd_file_new (base, &line[i->sz]);
179 if (!self->file)
181 rxpd_log (base, LOG_ERR, "illeagal filename\n");
182 rxpd_buffer_printf (&self->out, "#ERROR: illegal filename\n");
183 rxpd_connection_delete (self);
184 return NULL;
189 // dispatch
190 switch (i->nr)
192 #define RXPD_CMD(cmd, _) \
193 case RXPD_CMD_##cmd: \
194 rxpd_connection_cmd_##cmd (self); \
195 rxpd_connection_delete (self); \
196 break;
198 RXPD_COMMANDS
199 #undef RXPD_CMD
201 return NULL;