masqmail-0.2

view src/masqmail.h @ 179:ec3fe72a3e99

Fixed an important bug with folded headers! g_strconcat() returns a *copy* of the string, but hdr->value still pointed to the old header (which probably was a memory leak, too). If the folded part had been quite small it was likely that the new string was at the same position as the old one, thus making everything go well. But if pretty long headers were folded several times it was likely that the new string was allocated somewhere else in memory, thus breaking things. In result mails to lots of recipients (folded header) were frequently only sent to the ones in the first line. Sorry for the inconvenience.
author meillo@marmaro.de
date Fri, 03 Jun 2011 09:52:17 +0200
parents 349518b940db
children
line source
1 /* MasqMail
2 Copyright (C) 1999-2001 Oliver Kurth
3 Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
5 This program is free software; you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation; either version 2 of the License, or
8 (at your option) any later version.
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
15 You should have received a copy of the GNU General Public License
16 along with this program; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 */
19 #include <config.h>
21 #include <stdio.h>
22 #include <stdarg.h>
23 #include <errno.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #include <ctype.h>
27 #include <unistd.h>
28 #include <pwd.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <time.h>
33 #include <sys/time.h>
34 #include <netinet/in.h>
35 #include <arpa/inet.h>
36 #include <netdb.h>
37 #include <syslog.h>
38 #include <signal.h>
39 #include <fcntl.h>
41 #include <glib.h>
43 #ifdef ENABLE_IDENT
44 #include "libident/ident.h"
45 #endif
47 #include "lookup.h"
49 typedef struct _interface {
50 gchar *address;
51 gint port;
52 } interface;
54 #define ADDR_FLAG_DELIVERED 0x01
55 #define ADDR_FLAG_DEFERED 0x02
56 #define ADDR_FLAG_FAILED 0x04
57 #define ADDR_FLAG_LAST_ROUTE 0x40
58 #define ADDR_FLAG_NOEXPAND 0x80
60 typedef struct _address {
61 gchar *address;
62 gchar *local_part;
63 gchar *domain;
64 gint flags;
65 GList *children;
66 struct _address *parent;
67 } address;
69 #define addr_mark_delivered(addr) { addr->flags |= ADDR_FLAG_DELIVERED; }
70 #define addr_unmark_delivered(addr) { addr->flags &= ~ADDR_FLAG_DELIVERED; }
71 #define addr_is_delivered(addr) ((addr->flags & ADDR_FLAG_DELIVERED) != 0 )
73 #define addr_mark_defered(addr) { addr->flags |= ADDR_FLAG_DEFERED; }
74 #define addr_unmark_defered(addr) { addr->flags &= ~ADDR_FLAG_DEFERED; }
75 #define addr_is_defered(addr) ((addr->flags & ADDR_FLAG_DEFERED) != 0 )
77 #define addr_mark_failed(addr) { addr->flags |= ADDR_FLAG_FAILED; }
78 #define addr_unmark_failed(addr) { addr->flags &= ~ADDR_FLAG_FAILED; }
79 #define addr_is_failed(addr) ((addr->flags & ADDR_FLAG_FAILED) != 0 )
81 typedef struct _connect_route {
82 gchar *name;
83 gchar *filename;
85 gchar *protocol;
87 gboolean is_local_net;
88 gboolean last_route;
90 GList *allowed_return_paths;
91 GList *not_allowed_return_paths;
92 GList *allowed_mail_locals;
93 GList *not_allowed_mail_locals;
94 GList *allowed_rcpt_domains;
95 GList *not_allowed_rcpt_domains;
97 interface *mail_host;
98 gchar *wrapper;
99 gboolean connect_error_fail;
101 gchar *helo_name;
102 gboolean do_correct_helo;
103 gboolean instant_helo;
104 gboolean do_pipelining;
106 gchar *set_h_from_domain;
107 gchar *set_h_reply_to_domain;
108 gchar *set_return_path_domain;
110 GList *map_h_from_addresses;
111 GList *map_h_reply_to_addresses;
112 GList *map_h_mail_followup_to_addresses;
113 GList *map_return_path_addresses;
115 gboolean expand_h_sender_domain;
116 gboolean expand_h_sender_address;
118 GList *resolve_list;
120 gchar *auth_name;
121 gchar *auth_login;
122 gchar *auth_secret;
124 gchar *pop3_login;
126 gchar *pipe;
128 gboolean pipe_fromline;
129 gboolean pipe_fromhack;
130 } connect_route;
132 typedef struct _get_conf {
133 gchar *protocol;
134 gchar *server_name;
135 guint server_port;
136 gchar *wrapper;
137 gchar *login_user;
138 gchar *login_pass;
139 address *address;
140 address *return_path;
141 gboolean do_keep;
142 gboolean do_uidl;
143 gboolean do_uidl_dele;
144 gint max_size;
145 gboolean max_size_delete;
146 gint max_count;
148 GList *resolve_list;
150 } get_conf;
152 typedef struct _masqmail_conf {
153 gint mail_uid;
154 gint mail_gid;
156 gint orig_uid;
157 gint orig_gid;
159 gboolean run_as_user;
161 gchar *mail_dir;
162 gchar *lock_dir;
163 gchar *spool_dir;
164 gchar *log_dir;
166 gint debug_level;
167 gboolean use_syslog;
168 guint log_max_pri;
170 gchar *host_name;
171 GList *local_hosts;
172 GList *local_addresses;
173 GList *not_local_addresses;
174 GList *local_nets;
175 GList *listen_addresses;
177 guint remote_port;
179 /* ANSI C defines unsigned long to be at least 32bit
180 i.e. ca. 4GB max; that should be enough. */
181 gulong max_msg_size;
183 gboolean do_save_envelope_to;
185 gboolean defer_all;
186 gboolean do_relay;
188 GList *ident_trusted_nets;
190 gboolean do_queue;
192 gboolean do_verbose;
194 gchar *mbox_default;
195 GList *mbox_users;
196 GList *mda_users;
197 GList *maildir_users;
199 gchar *mda;
200 gboolean mda_fromline;
201 gboolean mda_fromhack;
203 gboolean pipe_fromline;
204 gboolean pipe_fromhack;
206 gchar *alias_file;
207 int (*alias_local_cmp) (const char *, const char *);
209 GList *local_net_routes;
210 GList *connect_routes; /* list of pairs which point to lists */
212 gchar *online_detect;
213 gchar *online_file;
214 gchar *online_pipe;
215 interface *mserver_iface;
217 GList *get_names;
218 GList *online_gets; /* list of pairs which point to lists */
220 gchar *errmsg_file;
221 gchar *warnmsg_file;
222 GList *warn_intervals;
223 gint max_defer_time;
225 gchar *log_user;
226 } masqmail_conf;
228 extern masqmail_conf conf;
230 typedef struct _table_pair {
231 gchar *key;
232 gpointer *value;
233 } table_pair;
236 typedef enum _prot_id {
237 PROT_LOCAL = 0,
238 PROT_BSMTP,
239 PROT_SMTP,
240 PROT_ESMTP,
241 PROT_POP3,
242 PROT_APOP,
243 PROT_NUM
244 } prot_id;
246 extern gchar *prot_names[];
248 typedef enum _header_id {
249 HEAD_FROM = 0,
250 HEAD_SENDER,
251 HEAD_TO,
252 HEAD_CC,
253 HEAD_BCC,
254 HEAD_DATE,
255 HEAD_MESSAGE_ID,
256 HEAD_REPLY_TO,
257 HEAD_SUBJECT,
258 HEAD_RETURN_PATH,
259 HEAD_ENVELOPE_TO,
260 HEAD_RECEIVED,
261 HEAD_NUM_IDS,
262 HEAD_STATUS,
263 HEAD_UNKNOWN = HEAD_NUM_IDS,
264 HEAD_NONE = -1,
265 } header_id;
267 typedef struct _header_name {
268 gchar *header;
269 header_id id;
270 } header_name;
272 typedef struct _header {
273 header_id id;
274 gchar *header;
275 gchar *value;
276 } header;
279 typedef struct _message {
280 gchar *uid;
282 gchar *received_host;
283 prot_id received_prot;
284 gchar *ident;
285 gint transfer_id; /* for multiple messages per transfer */
287 address *return_path;
288 GList *rcpt_list;
289 GList *non_rcpt_list;
291 GList *hdr_list;
292 GList *data_list;
294 gint data_size;
295 time_t received_time;
296 time_t warned_time;
298 gchar *full_sender_name;
299 } message;
301 typedef struct _msg_out {
302 message *msg;
304 address *return_path;
305 GList *rcpt_list;
307 GList *hdr_list;
308 GList *xtra_hdr_list;
309 } msg_out;
311 typedef struct _msgout_perhost {
312 gchar *host;
313 GList *msgout_list;
314 } msgout_perhost;
316 /* flags for accept() */
317 #define ACC_DEL_RCPTS 0x02 /* -t option, delete rcpts that were given as cmd args */
318 #define ACC_RCPT_FROM_HEAD 0x08 /* -t option, get rcpts from headers */
319 #define ACC_DOT_IGNORE 0x10 /* a dot on a line itself does not end the message (-oi option) */
320 #define ACC_MAIL_FROM_HEAD 0x40 /* get return path from header */
321 #define ACC_NODOT_RELAX 0x80 /* do not be picky if message ist not terminated by a dot on a line */
322 #define ACC_SAVE_ENVELOPE_TO 0x0100 /* save an existent Envelope-to header as X-Orig-Envelope-to */
324 #define DLVR_LOCAL 0x01
325 #define DLVR_LAN 0x02
326 #define DLVR_ONLINE 0x04
327 #define DLVR_ALL (DLVR_LOCAL|DLVR_LAN|DLVR_ONLINE)
329 /* transport flags */
330 #define MSGSTR_FROMLINE 0x01
331 #define MSGSTR_FROMHACK 0x02
333 typedef enum _accept_error {
334 AERR_OK = 0,
335 AERR_TIMEOUT,
336 AERR_EOF,
337 AERR_OVERFLOW,
338 AERR_SYNTAX,
339 AERR_NOSPOOL,
340 AERR_NORCPT,
341 AERR_SIZE, /* max msg size exeeded (SMTP SIZE) */
342 AERR_UNKNOWN
343 } accept_error;
345 #define BUF_LEN 1024
346 #define MAX_ADDRESS 256
347 #define MAX_DATALINE 4096
349 typedef enum _smtp_cmd_id {
350 SMTP_HELO = 0,
351 SMTP_EHLO,
352 SMTP_MAIL_FROM,
353 SMTP_RCPT_TO,
354 SMTP_DATA,
355 SMTP_QUIT,
356 SMTP_RSET,
357 SMTP_NOOP,
358 SMTP_HELP,
359 SMTP_NUM_IDS,
360 SMTP_EOF = -1,
361 SMTP_ERROR = -2,
362 } smtp_cmd_id;
364 typedef struct _smtp_cmd {
365 smtp_cmd_id id;
366 gchar *cmd;
367 } smtp_cmd;
369 typedef struct _smtp_connection {
370 gchar *remote_host;
372 prot_id prot;
373 gint next_id;
375 gboolean helo_seen;
376 gboolean from_seen;
377 gboolean rcpt_seen;
379 message *msg;
380 } smtp_connection;
382 /* alias.c*/
383 gboolean addr_is_local(address * addr);
384 GList *alias_expand(GList * alias_table, GList * rcpt_list, GList * non_rcpt_list);
386 /* child.c */
387 int child(const char *command);
389 /* conf.c */
390 void init_conf();
391 gboolean read_conf(gchar * filename);
392 connect_route *read_route(gchar * filename, gboolean is_local_net);
393 GList *read_route_list(GList * rf_list, gboolean is_local_net);
394 void destroy_route(connect_route * r);
395 void destroy_route_list(GList * list);
396 get_conf *read_get_conf(gchar * filename);
397 void destroy_get_conf(get_conf * gc);
398 connect_route *create_local_route();
400 /* expand.c */
401 GList *var_table_rcpt(GList * var_table, address * rcpt);
402 GList *var_table_msg(GList * var_table, message * msg);
403 GList *var_table_conf(GList * var_table);
404 gint expand(GList * var_list, gchar * format, gchar * result, gint result_len);
406 /* message.c */
407 message *create_message(void);
408 void destroy_message(message * msg);
409 void destroy_msg_list(GList * msg_list);
410 void msg_free_data(message * msg);
411 gint msg_calc_size(message * msg, gboolean is_smtp);
413 msg_out *create_msg_out(message * msg);
414 msg_out *clone_msg_out(msg_out * msgout_orig);
415 GList *create_msg_out_list(GList * msg_list);
416 void destroy_msg_out(msg_out * msgout);
417 void destroy_msg_out_list(GList * msgout_list);
419 /* address.c */
420 address *create_address(gchar * path, gboolean is_rfc821);
421 address *create_address_qualified(gchar * path, gboolean is_rfc821, gchar * domain);
422 address *create_address_pipe(gchar * path);
423 void destroy_address(address * addr);
424 address *copy_modify_address(const address * orig, gchar * l_part, gchar * dom);
425 #define copy_address(addr) copy_modify_address(addr, NULL, NULL)
426 gboolean addr_isequal(address * addr1, address * addr2);
427 gboolean addr_isequal_parent(address * addr1, address * addr2);
428 address *addr_find_ancestor(address * addr);
429 gboolean addr_is_delivered_children(address * addr);
430 gboolean addr_is_finished_children(address * addr);
431 gchar *addr_string(address * addr);
432 gint addr_match(address * addr1, address * addr2);
434 /* accept.c */
435 accept_error accept_message(FILE * in, message * msg, guint flags);
436 accept_error accept_message_prepare(message * msg, guint flags);
438 /* header.c */
439 gchar *rec_timestamp();
440 GList *find_header(GList * hdr_list, header_id id, gchar * hdr_str);
441 void header_unfold(header * hdr);
442 void header_fold(header * hdr);
443 header *create_header(header_id id, gchar * fmt, ...);
444 void destroy_header(header * hdr);
445 header *copy_header(header * hdr);
446 header *get_header(gchar * line);
448 /* smtp_in.c */
449 void smtp_in(FILE * in, FILE * out, gchar * remote_host, gchar * ident);
451 /* listen.c */
452 void listen_port(GList * addr_list, gint qival, char *argv[]);
454 /* parse.c */
455 gboolean split_address(const gchar * path, gchar ** local_part, gchar ** domain, gboolean is_rfc821);
456 gboolean parse_address_rfc822(gchar * string, gchar ** local_begin, gchar ** local_end, gchar ** domain_begin, gchar ** domain_end, gchar ** address_end);
457 gboolean parse_address_rfc821(gchar * string, gchar ** local_begin, gchar ** local_end, gchar ** domain_begin, gchar ** domain_end, gchar ** address_end);
458 address *_create_address(gchar * string, gchar ** end, gboolean is_rfc821);
459 address *create_address_rfc821(gchar * string, gchar ** end);
460 address *create_address_rfc822(gchar * string, gchar ** end);
461 GList *addr_list_append_rfc822(GList * addr_list, gchar * string, gchar * domain);
462 gboolean addr_isequal(address * addr1, address * addr2);
464 /* connect.c */
465 mxip_addr *connect_hostlist(int *psockfd, gchar * host, guint port, GList * addr_list);
466 mxip_addr *connect_resolvelist(int *psockfd, gchar * host, guint port, GList * res_funcs);
468 /* deliver.c */
469 void msg_rcptlist_local(GList * rcpt_list, GList **, GList **);
470 gboolean deliver_local(msg_out * msgout);
471 gboolean deliver_msglist_host(connect_route * route, GList * msg_list, gchar * host, GList * res_list);
472 gboolean deliver_route_msgout_list(connect_route * route, GList * msgout_list);
473 gboolean deliver_route_msg_list(connect_route * route, GList * msgout_list);
474 gboolean deliver_finish(msg_out * msgout);
475 gboolean deliver_finish_list(GList * msgout_list);
476 gboolean deliver_msg_list(GList * msg_list, guint flags);
477 gboolean deliver(message * msg);
479 /* fail_msg.c */
480 gboolean fail_msg(message * msg, gchar * template, GList * failed_rcpts, gchar * err_fmt, va_list args);
481 gboolean warn_msg(message * msg, gchar * template, GList * failed_rcpts, gchar * err_fmt, va_list args);
483 /* get.c */
484 gboolean get_from_file(gchar * fname);
485 gboolean get_from_name(gchar * name);
486 gboolean get_all(void);
487 void get_online(void);
488 void get_daemon(gint gival, char *argv[]);
489 gboolean pop_before_smtp(gchar * fname);
491 /* interface.c */
492 gboolean init_sockaddr(struct sockaddr_in *name, interface * iface);
493 int make_server_socket(interface * iface);
495 /* local.c */
496 gboolean append_file(message * msg, GList * hdr_list, gchar * user);
497 gboolean maildir_out(message * msg, GList * hdr_list, gchar * user, guint flags);
498 gboolean pipe_out(message * msg, GList * hdr_list, address * rcpt, gchar * cmd, guint flags);
500 /* log.c */
501 gchar *ext_strerror(int err);
502 gboolean logopen(void);
503 void logclose(void);
504 void vlogwrite(int pri, const char *fmt, va_list args);
505 void logwrite(int pri, const char *fmt, ...);
506 void debugf(const char *fmt, ...);
507 void vdebugf(const char *fmt, va_list args);
508 void maillog(const char *fmt, ...);
510 /* spool.c */
511 gboolean spool_read_data(message * msg);
512 gboolean spool_read_data(message * msg);
513 message *msg_spool_read(gchar * uid, gboolean do_readdata);
514 gboolean spool_write(message * msg, gboolean do_writedata);
515 gboolean spool_lock(gchar * uid);
516 gboolean spool_unlock(gchar * uid);
517 gboolean spool_delete_all(message * msg);
519 /* queue.c */
520 GList *read_queue(gboolean do_readdata);
521 gboolean queue_run(void);
522 gboolean queue_run_online(void);
523 void queue_list(void);
524 gboolean queue_delete(gchar * uid);
526 /* online.c */
527 gchar *detect_online();
528 void set_online_name(gchar * name);
530 /* permissions.c */
531 gboolean is_ingroup(uid_t uid, gid_t gid);
532 void set_euidgid(gint uid, gint gid, uid_t * old_uid, gid_t * old_gid);
533 void set_identity(uid_t old_uid, gchar * task_name);
535 /* rewrite.c */
536 gboolean set_address_header_domain(header * hdr, gchar * domain);
537 gboolean map_address_header(header * hdr, GList * table);
539 /* route.c */
540 msgout_perhost *create_msgout_perhost(gchar * host);
541 void destroy_msgout_perhost(msgout_perhost * mo_ph);
542 void rewrite_headers(msg_out * msgout, connect_route * route);
543 void rcptlist_with_one_of_hostlist(GList * rcpt_list, GList * host_list, GList **, GList **);
544 void rcptlist_with_addr_is_local(GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list);
545 gboolean route_strip_msgout(connect_route * route, msg_out * msgout);
546 msg_out *route_prepare_msgout(connect_route * route, msg_out * msgout);
547 GList *route_msgout_list(connect_route * route, GList * msgout_list);
548 gboolean route_is_allowed_return_path(connect_route * route, address * ret_path);
549 gboolean route_is_allowed_mail_local(connect_route * route, address * ret_path);
550 void msg_rcptlist_route(connect_route * route, GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list);
552 /* tables.c */
553 table_pair *create_pair(gchar * key, gpointer value);
554 table_pair *create_pair_string(gchar * key, gpointer value);
555 table_pair *parse_table_pair(gchar * line, char delim);
556 gpointer *table_find_func(GList * table_list, gchar * key, int (*cmp_func) (const char *, const char *));
557 gpointer *table_find(GList * table_list, gchar * key);
558 gpointer *table_find_case(GList * table_list, gchar * key);
559 gpointer *table_find_fnmatch(GList * table_list, gchar * key);
560 GList *table_read(gchar * fname, gchar delim);
561 void destroy_table(GList * table);
563 /* timeival.c */
564 gint time_interval(gchar * str, gint * pos);
566 /* permissions.c */
567 gboolean is_privileged_user(uid_t uid);
569 /* other things */
571 #define foreach(list, node)\
572 for((node) = g_list_first(list);\
573 (node);\
574 (node) = g_list_next(node))
576 #ifdef ENABLE_DEBUG
577 #define DEBUG(level) if(level <= conf.debug_level)
578 #else
579 /* hopefully the compiler optmizes this away... */
580 #define DEBUG(level) if(0)
581 #endif
583 #define LOG_VERBOSE 0x100
585 #ifndef HAVE_GETLINE
586 #define getline(buf, size, file) getdelim(buf, size, '\n', file)
587 #endif
589 #ifndef HAVE_FDATASYNC
590 #define fdatasync(fd) fsync(fd)
591 #endif
593 #ifndef CONF_DIR
594 #define CONF_DIR "/etc/masqmail"
595 #endif
597 #define CONF_FILE CONF_DIR"/masqmail.conf"
599 #define PIDFILEDIR "/var/run/masqmail/"
601 #ifndef va_copy
602 #ifdef __va_copy
603 #define va_copy(ap1, ap2) __va_copy(ap1, ap2)
604 #else
605 #define va_copy(ap1, ap2) G_VA_COPY(ap1, ap2)
606 #endif
607 #endif
609 /* *BSD needs this: */
610 extern char **environ;