Commit 643be57e 643be57eb09fe6485ccc8f4cf3ac9a592c207bb5 by Sergey Poznyakoff

* comsat/Makefile.am: Remove cfg.c

* comsat/cfg.c: Remove.
* comsat/comsat.c: Use MU configuration and acls.
* comsat/comsat.h: Include acl.h
* libproto/maildir/mbox.c (maildir_qfetch): Bugfix.
1 parent b7e41daa
1 2007-12-30 Sergey Poznyakoff <gray@gnu.org.ua> 1 2007-12-30 Sergey Poznyakoff <gray@gnu.org.ua>
2 2
3 * comsat/Makefile.am: Remove cfg.c
4 * comsat/cfg.c: Remove.
5 * comsat/comsat.c: Use MU configuration and acls.
6 * comsat/comsat.h: Include acl.h
7 * libproto/maildir/mbox.c (maildir_qfetch): Bugfix.
8
3 * NEWS: Update. 9 * NEWS: Update.
4 10
5 * frm/testsuite/frm/test.exp: Call mu_init with -noflags option. 11 * frm/testsuite/frm/test.exp: Call mu_init with -noflags option.
......
...@@ -21,7 +21,7 @@ INCLUDES = @MU_COMMON_INCLUDES@ ...@@ -21,7 +21,7 @@ INCLUDES = @MU_COMMON_INCLUDES@
21 21
22 sbin_PROGRAMS = comsatd 22 sbin_PROGRAMS = comsatd
23 23
24 comsatd_SOURCES = action.c cfg.c comsat.c comsat.h 24 comsatd_SOURCES = action.c comsat.c comsat.h
25 25
26 comsatd_LDADD = \ 26 comsatd_LDADD = \
27 ${MU_APP_LIBRARIES}\ 27 ${MU_APP_LIBRARIES}\
......
1 /* This file is part of GNU Mailutils.
2 Copyright (C) 1998, 2001, 2002, 2005, 2007 Free Software Foundation, Inc.
3
4 GNU Mailutils is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Mailutils is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Mailutils; see the file COPYING. If not, write
16 to the Free Software Foundation, Inc., 51 Franklin Street,
17 Fifth Floor, Boston, MA 02110-1301 USA. */
18
19 #include "comsat.h"
20
21 typedef struct netdef netdef_t;
22
23 struct netdef
24 {
25 netdef_t *next;
26 unsigned int ipaddr;
27 unsigned int netmask;
28 };
29
30 #define ACT_ALLOW 0
31 #define ACT_DENY 1
32
33 typedef struct acl acl_t;
34
35 struct acl
36 {
37 acl_t *next;
38 netdef_t *netlist;
39 int action;
40 };
41
42
43 acl_t *acl_head, *acl_tail;
44
45 #define DOTTED_QUAD_LEN 16
46
47 static int
48 read_address (char **line_ptr, char *ptr)
49 {
50 char *startp = *line_ptr;
51 char *endp;
52 int dotcount = 0;
53
54 for (endp = startp; *endp; endp++, ptr++)
55 if (!(isdigit (*endp) || *endp == '.'))
56 break;
57 else if (endp < startp + DOTTED_QUAD_LEN)
58 {
59 if (*endp == '.')
60 dotcount++;
61 *ptr = *endp;
62 }
63 else
64 break;
65 *line_ptr = endp;
66 *ptr = 0;
67 return dotcount;
68 }
69
70 static netdef_t *
71 netdef_parse (char *str)
72 {
73 unsigned int ipaddr, netmask;
74 netdef_t *netdef;
75 char ipbuf[DOTTED_QUAD_LEN+1];
76
77 if (strcmp (str, "any") == 0)
78 {
79 ipaddr = 0;
80 netmask = 0;
81 }
82 else
83 {
84 read_address (&str, ipbuf);
85 ipaddr = inet_addr (ipbuf);
86 if (ipaddr == INADDR_NONE)
87 return NULL;
88 if (*str == 0)
89 netmask = 0xfffffffful;
90 else if (*str != '/')
91 return NULL;
92 else
93 {
94 str++;
95 if (read_address (&str, ipbuf) == 0)
96 {
97 /* netmask length */
98 unsigned int len = strtoul (ipbuf, NULL, 0);
99 if (len > 32)
100 return NULL;
101 netmask = 0xfffffffful >> (32-len);
102 netmask <<= (32-len);
103 }
104 else
105 netmask = inet_network (ipbuf);
106 netmask = htonl (netmask);
107 }
108 }
109
110 netdef = malloc (sizeof *netdef);
111 if (!netdef)
112 {
113 mu_error (_("Out of memory"));
114 exit (1);
115 }
116
117 netdef->next = NULL;
118 netdef->ipaddr = ipaddr;
119 netdef->netmask = netmask;
120
121 return netdef;
122 }
123
124 void
125 read_config (const char *config_file)
126 {
127 FILE *fp;
128 int line;
129 char buf[128];
130 char *ptr;
131
132 if (!config_file)
133 return;
134
135 fp = fopen (config_file, "r");
136 if (!fp)
137 {
138 mu_error (_("Cannot open config file %s: %s"), config_file,
139 mu_strerror (errno));
140 return;
141 }
142
143 line = 0;
144 while ((ptr = fgets (buf, sizeof buf, fp)))
145 {
146 int len, i;
147 int argc;
148 char **argv;
149 int action;
150 netdef_t *head, *tail;
151 acl_t *acl;
152
153 line++;
154 len = strlen (ptr);
155 if (len > 0 && ptr[len-1] == '\n')
156 ptr[--len] = 0;
157
158 while (*ptr && isspace (*ptr))
159 ptr++;
160 if (!*ptr || *ptr == '#')
161 continue;
162
163 mu_argcv_get (ptr, "", NULL, &argc, &argv);
164 if (argc < 2)
165 {
166 mu_error (_("%s:%d: too few fields"), config_file, line);
167 mu_argcv_free (argc, argv);
168 continue;
169 }
170
171 if (strcmp (argv[0], "allow-biffrc") == 0)
172 {
173 if (strcmp (argv[1], "yes") == 0)
174 allow_biffrc = 1;
175 else if (strcmp (argv[1], "no") == 0)
176 allow_biffrc = 0;
177 else
178 mu_error (_("%s:%d: yes or no expected"), config_file, line);
179 }
180 else if (strcmp (argv[0], "max-requests") == 0)
181 maxrequests = strtoul (argv[1], NULL, 0);
182 else if (strcmp (argv[0], "request-control-interval") == 0)
183 request_control_interval = strtoul (argv[1], NULL, 0);
184 else if (strcmp (argv[0], "overflow-control-interval") == 0)
185 overflow_control_interval = strtoul (argv[1], NULL, 0);
186 else if (strcmp (argv[0], "overflow-delay-time") == 0)
187 overflow_delay_time = strtoul (argv[1], NULL, 0);
188 else if (strcmp (argv[0], "max-lines") == 0)
189 maxlines = strtoul (argv[1], NULL, 0);
190 else if (strcmp (argv[0], "acl") == 0)
191 {
192 if (strcmp (argv[1], "allow") == 0)
193 action = ACT_ALLOW;
194 else if (strcmp (argv[1], "deny") == 0)
195 action = ACT_DENY;
196 else
197 {
198 mu_error (_("%s:%d: unknown keyword"), config_file, line);
199 mu_argcv_free (argc, argv);
200 continue;
201 }
202
203 head = tail = NULL;
204 for (i = 2; i < argc; i++)
205 {
206 netdef_t *cur = netdef_parse (argv[i]);
207 if (!cur)
208 {
209 mu_error (_("%s:%d: cannot parse netdef: %s"),
210 config_file, line, argv[i]);
211 continue;
212 }
213 if (!tail)
214 head = cur;
215 else
216 tail->next = cur;
217 tail = cur;
218 }
219
220 mu_argcv_free (argc, argv);
221
222 acl = malloc (sizeof *acl);
223 if (!acl)
224 {
225 mu_error (_("Out of memory"));
226 exit (1);
227 }
228 acl->next = NULL;
229 acl->action = action;
230 acl->netlist = head;
231
232 if (!acl_tail)
233 acl_head = acl;
234 else
235 acl_tail->next = acl;
236 acl_tail = acl;
237 }
238 }
239 fclose (fp);
240 }
241
242 /*NOTE: currently unused. */
243 #if 0
244 static void
245 netdef_free (netdef_t *netdef)
246 {
247 netdef_t *next;
248
249 while (netdef)
250 {
251 next = netdef->next;
252 free (netdef);
253 netdef = next;
254 }
255 }
256
257 static void
258 acl_free (acl_t *acl)
259 {
260 acl_t *next;
261
262 while (acl)
263 {
264 next = acl->next;
265 netdef_free (acl->netlist);
266 free (acl);
267 acl = next;
268 }
269 }
270
271 static void
272 discard_acl (acl_t *mark)
273 {
274 if (mark)
275 {
276 acl_free (mark->next);
277 acl_tail = mark;
278 acl_tail->next = NULL;
279 }
280 else
281 acl_head = acl_tail = NULL;
282 }
283 #endif
284
285 int
286 acl_match (struct sockaddr_in *sa_in)
287 {
288 acl_t *acl;
289 unsigned int ip;
290
291 ip = sa_in->sin_addr.s_addr;
292 for (acl = acl_head; acl; acl = acl->next)
293 {
294 netdef_t *net;
295
296 for (net = acl->netlist; net; net = net->next)
297 {
298 if (net->ipaddr == (ip & net->netmask))
299 return acl->action;
300 }
301 }
302 return ACT_ALLOW;
303 }
...@@ -103,6 +103,7 @@ struct mu_gocs_daemon default_gocs_daemon = { ...@@ -103,6 +103,7 @@ struct mu_gocs_daemon default_gocs_daemon = {
103 int maxlines = 5; 103 int maxlines = 5;
104 char hostname[MAXHOSTNAMELEN]; 104 char hostname[MAXHOSTNAMELEN];
105 const char *username; 105 const char *username;
106 mu_acl_t comsat_acl;
106 107
107 static void comsat_init (void); 108 static void comsat_init (void);
108 static void comsat_daemon_init (void); 109 static void comsat_daemon_init (void);
...@@ -116,7 +117,6 @@ static void change_user (const char *user); ...@@ -116,7 +117,6 @@ static void change_user (const char *user);
116 117
117 static int xargc; 118 static int xargc;
118 static char **xargv; 119 static char **xargv;
119 char *config_file = NULL;
120 int test_mode; 120 int test_mode;
121 121
122 static error_t 122 static error_t
...@@ -125,7 +125,7 @@ comsatd_parse_opt (int key, char *arg, struct argp_state *state) ...@@ -125,7 +125,7 @@ comsatd_parse_opt (int key, char *arg, struct argp_state *state)
125 switch (key) 125 switch (key)
126 { 126 {
127 case 'c': 127 case 'c':
128 config_file = arg; 128 /* FIXME: convert config to the new format and parse it */
129 break; 129 break;
130 130
131 case 't': 131 case 't':
...@@ -138,20 +138,43 @@ comsatd_parse_opt (int key, char *arg, struct argp_state *state) ...@@ -138,20 +138,43 @@ comsatd_parse_opt (int key, char *arg, struct argp_state *state)
138 return 0; 138 return 0;
139 } 139 }
140 140
141 struct mu_cfg_param comsat_cfg_param[] = {
142 { "allow-biffrc", mu_cfg_bool, &allow_biffrc, 0, NULL,
143 N_("Read .biffrc file from the user home directory") },
144 { "max-lines", mu_cfg_int, &maxlines, 0, NULL,
145 N_("Maximum number of message body lines to be output.") },
146 { "max-requests", mu_cfg_uint, &maxrequests, 0, NULL,
147 N_("Maximum number of incoming requests per `request-control-interval' "
148 "seconds.") },
149 { "request-control-interval", mu_cfg_time, &request_control_interval,
150 0, NULL,
151 N_("Set control interval.") },
152 { "overflow-control-interval", mu_cfg_time, &overflow_control_interval,
153 0, NULL,
154 N_("Set overflow control interval.") },
155 { "overflow-delay-time", mu_cfg_time, &overflow_delay_time,
156 0, NULL,
157 N_("Time to sleep after the first overflow occurs.") },
158 { "acl", mu_cfg_section, },
159 { NULL }
160 };
141 161
142 int 162 int
143 main (int argc, char **argv) 163 main (int argc, char **argv)
144 { 164 {
145 int c; 165 int c;
146 int ind; 166 int ind;
147 167
148 /* Native Language Support */ 168 /* Native Language Support */
149 mu_init_nls (); 169 mu_init_nls ();
150 170
151 mu_argp_init (program_version, NULL); 171 mu_argp_init (program_version, NULL);
152 mu_gocs_daemon = default_gocs_daemon; 172 mu_gocs_daemon = default_gocs_daemon;
173 comsat_init ();
174 mu_acl_cfg_init ();
153 175
154 if (mu_app_init (&argp, comsat_argp_capa, NULL, argc, argv, 0, &ind, NULL)) 176 if (mu_app_init (&argp, comsat_argp_capa, comsat_cfg_param, argc, argv, 0,
177 &ind, &comsat_acl))
155 exit (1); 178 exit (1);
156 179
157 argc -= ind; 180 argc -= ind;
...@@ -161,11 +184,6 @@ main (int argc, char **argv) ...@@ -161,11 +184,6 @@ main (int argc, char **argv)
161 { 184 {
162 char *user; 185 char *user;
163 186
164 comsat_init ();
165 if (config_file)
166 read_config (config_file);
167 if (argc == 0)
168 exit (0);
169 if (argc < 2 || argc > 2) 187 if (argc < 2 || argc > 2)
170 { 188 {
171 mu_error (_("Mailbox URL and message QID are required in test mode")); 189 mu_error (_("Mailbox URL and message QID are required in test mode"));
...@@ -198,8 +216,6 @@ main (int argc, char **argv) ...@@ -198,8 +216,6 @@ main (int argc, char **argv)
198 exit (EXIT_FAILURE); 216 exit (EXIT_FAILURE);
199 } 217 }
200 218
201 comsat_init ();
202
203 if (mu_gocs_daemon.mode == MODE_DAEMON) 219 if (mu_gocs_daemon.mode == MODE_DAEMON)
204 { 220 {
205 /* Preserve invocation arguments */ 221 /* Preserve invocation arguments */
...@@ -218,9 +234,6 @@ main (int argc, char **argv) ...@@ -218,9 +234,6 @@ main (int argc, char **argv)
218 mu_debug_set_print (debug, mu_diag_syslog_printer, NULL); 234 mu_debug_set_print (debug, mu_diag_syslog_printer, NULL);
219 } 235 }
220 236
221 if (config_file)
222 read_config (config_file);
223
224 chdir ("/"); 237 chdir ("/");
225 238
226 if (mu_gocs_daemon.mode == MODE_DAEMON) 239 if (mu_gocs_daemon.mode == MODE_DAEMON)
...@@ -370,11 +383,58 @@ comsat_daemon (int port) ...@@ -370,11 +383,58 @@ comsat_daemon (int port)
370 } 383 }
371 384
372 int 385 int
386 check_connection (int fd, struct sockaddr *addr, socklen_t addrlen)
387 {
388 switch (addr->sa_family)
389 {
390 case PF_UNIX:
391 mu_diag_output (MU_DIAG_INFO, _("connect from socket"));
392 break;
393
394 case PF_INET:
395 {
396 struct sockaddr_in *s_in = (struct sockaddr_in *)addr;
397
398 if (comsat_acl)
399 {
400 mu_acl_result_t res;
401
402 int rc = mu_acl_check_sockaddr (comsat_acl, addr, addrlen,
403 &res);
404 if (rc)
405 {
406 mu_error (_("Access from %s blocked: cannot check ACLs: %s"),
407 inet_ntoa (s_in->sin_addr), mu_strerror (rc));
408 return 1;
409 }
410 switch (res)
411 {
412 case mu_acl_result_undefined:
413 mu_diag_output (MU_DIAG_INFO,
414 _("%s: undefined ACL result; access allowed"),
415 inet_ntoa (s_in->sin_addr));
416 break;
417
418 case mu_acl_result_accept:
419 break;
420
421 case mu_acl_result_deny:
422 mu_error (_("Access from %s blocked."),
423 inet_ntoa (s_in->sin_addr));
424 return 1;
425 }
426 }
427 }
428 }
429 return 0;
430 }
431
432 int
373 comsat_main (int fd) 433 comsat_main (int fd)
374 { 434 {
375 int rdlen; 435 int rdlen;
376 int len; 436 int len;
377 struct sockaddr_in sin_from; 437 struct sockaddr fromaddr;
378 char buffer[216]; /*FIXME: Arbitrary size */ 438 char buffer[216]; /*FIXME: Arbitrary size */
379 pid_t pid; 439 pid_t pid;
380 char tty[MAX_TTY_SIZE]; 440 char tty[MAX_TTY_SIZE];
...@@ -382,9 +442,8 @@ comsat_main (int fd) ...@@ -382,9 +442,8 @@ comsat_main (int fd)
382 char *path = NULL; 442 char *path = NULL;
383 mu_message_qid_t qid; 443 mu_message_qid_t qid;
384 444
385 len = sizeof sin_from; 445 len = sizeof fromaddr;
386 rdlen = recvfrom (fd, buffer, sizeof buffer, 0, 446 rdlen = recvfrom (fd, buffer, sizeof buffer, 0, &fromaddr, &len);
387 (struct sockaddr*)&sin_from, &len);
388 if (rdlen <= 0) 447 if (rdlen <= 0)
389 { 448 {
390 if (errno == EINTR) 449 if (errno == EINTR)
...@@ -393,19 +452,16 @@ comsat_main (int fd) ...@@ -393,19 +452,16 @@ comsat_main (int fd)
393 return 1; 452 return 1;
394 } 453 }
395 454
396 if (acl_match (&sin_from)) 455 if (check_connection (fd, &fromaddr, len))
397 { 456 return 1;
398 mu_diag_output (MU_DIAG_ALERT, _("DENIED attempt to connect from %s"),
399 inet_ntoa (sin_from.sin_addr));
400 return 1;
401 }
402 457
403 mu_diag_output (MU_DIAG_INFO, 458 mu_diag_output (MU_DIAG_INFO,
404 ngettext ("Received %d byte from %s", 459 ngettext ("Received %d byte from %s",
405 "Received %d bytes from %s", rdlen), 460 "Received %d bytes from %s", rdlen),
406 rdlen, inet_ntoa (sin_from.sin_addr)); 461 rdlen, inet_ntoa (((struct sockaddr_in*)&fromaddr)->sin_addr));
407 462
408 buffer[rdlen] = 0; 463 buffer[rdlen] = 0;
464 mu_diag_output (MU_DIAG_INFO, "string: %s", buffer);
409 465
410 /* Parse the buffer */ 466 /* Parse the buffer */
411 p = strchr (buffer, '@'); 467 p = strchr (buffer, '@');
...@@ -417,7 +473,13 @@ comsat_main (int fd) ...@@ -417,7 +473,13 @@ comsat_main (int fd)
417 *p++ = 0; 473 *p++ = 0;
418 474
419 qid = p; 475 qid = p;
420 476 p = strchr (qid, ':');
477 if (p)
478 {
479 *p++ = 0;
480 path = p;
481 }
482
421 if (find_user (buffer, tty) != SUCCESS) 483 if (find_user (buffer, tty) != SUCCESS)
422 return 0; 484 return 0;
423 485
......
...@@ -60,6 +60,7 @@ ...@@ -60,6 +60,7 @@
60 #include <mailutils/argcv.h> 60 #include <mailutils/argcv.h>
61 #include <mailutils/nls.h> 61 #include <mailutils/nls.h>
62 #include <mailutils/daemon.h> 62 #include <mailutils/daemon.h>
63 #include <mailutils/acl.h>
63 64
64 #ifndef INADDR_NONE 65 #ifndef INADDR_NONE
65 # define INADDR_NONE -1 66 # define INADDR_NONE -1
...@@ -77,6 +78,4 @@ extern const char *username; ...@@ -77,6 +78,4 @@ extern const char *username;
77 extern char hostname[]; 78 extern char hostname[];
78 extern struct daemon_param daemon_param; 79 extern struct daemon_param daemon_param;
79 80
80 extern void read_config (const char *config_file);
81 int acl_match (struct sockaddr_in *sa_in);
82 void run_user_action (FILE *tty, const char *cr, mu_message_t msg); 81 void run_user_action (FILE *tty, const char *cr, mu_message_t msg);
......
...@@ -669,7 +669,7 @@ maildir_qfetch (struct _amd_data *amd, mu_message_qid_t qid) ...@@ -669,7 +669,7 @@ maildir_qfetch (struct _amd_data *amd, mu_message_qid_t qid)
669 669
670 if (!name) 670 if (!name)
671 return EINVAL; 671 return EINVAL;
672 672 name++;
673 msg = calloc (1, sizeof(*msg)); 673 msg = calloc (1, sizeof(*msg));
674 msg->file_name = strdup (name); 674 msg->file_name = strdup (name);
675 675
......