masqmail

view src/masqmail.h @ 323:29de6a1c4538

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:47:27 +0200
parents 55b7bde95d37
children 9149d893eb52
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
59 typedef struct _address {
60 gchar *address;
61 gchar *local_part;
62 gchar *domain;
63 gint flags;
64 GList *children;
65 struct _address *parent;
66 } address;
68 #define addr_mark_delivered(addr) { addr->flags |= ADDR_FLAG_DELIVERED; }
69 #define addr_unmark_delivered(addr) { addr->flags &= ~ADDR_FLAG_DELIVERED; }
70 #define addr_is_delivered(addr) ((addr->flags & ADDR_FLAG_DELIVERED) != 0 )
72 #define addr_mark_defered(addr) { addr->flags |= ADDR_FLAG_DEFERED; }
73 #define addr_unmark_defered(addr) { addr->flags &= ~ADDR_FLAG_DEFERED; }
74 #define addr_is_defered(addr) ((addr->flags & ADDR_FLAG_DEFERED) != 0 )
76 #define addr_mark_failed(addr) { addr->flags |= ADDR_FLAG_FAILED; }
77 #define addr_unmark_failed(addr) { addr->flags &= ~ADDR_FLAG_FAILED; }
78 #define addr_is_failed(addr) ((addr->flags & ADDR_FLAG_FAILED) != 0 )
80 typedef struct _connect_route {
81 gchar *name;
82 gchar *filename;
84 gboolean is_local_net;
85 gboolean last_route;
87 GList *allowed_senders;
88 GList *denied_senders;
89 GList *allowed_recipients;
90 GList *denied_recipients;
92 interface *mail_host;
93 gboolean connect_error_fail;
94 GList *resolve_list;
95 gchar *helo_name;
96 gboolean do_correct_helo;
97 gboolean instant_helo;
98 gboolean do_pipelining;
99 gchar *auth_name;
100 gchar *auth_login;
101 gchar *auth_secret;
102 gchar *wrapper;
104 gchar *set_h_from_domain;
105 gchar *set_h_reply_to_domain;
106 gchar *set_return_path_domain;
107 GList *map_h_from_addresses;
108 GList *map_h_reply_to_addresses;
109 GList *map_h_mail_followup_to_addresses;
110 GList *map_return_path_addresses;
111 gboolean expand_h_sender_domain;
112 gboolean expand_h_sender_address;
114 gchar *pipe;
115 gboolean pipe_fromline;
116 gboolean pipe_fromhack;
117 } connect_route;
119 typedef struct _masqmail_conf {
120 gint mail_uid;
121 gint mail_gid;
123 gint orig_uid;
124 gint orig_gid;
126 gboolean run_as_user;
128 gchar *mail_dir;
129 gchar *lock_dir;
130 gchar *spool_dir;
131 gchar *log_dir;
133 gint debug_level;
134 gboolean use_syslog;
135 guint log_max_pri;
137 gchar *host_name;
138 GList *local_hosts;
139 GList *local_addresses;
140 GList *not_local_addresses;
141 GList *local_nets;
142 GList *listen_addresses;
144 /* ANSI C defines unsigned long to be at least 32bit
145 i.e. ca. 4GB max; that should be enough. */
146 gulong max_msg_size;
148 gboolean do_save_envelope_to;
150 gboolean defer_all;
151 gboolean do_relay;
153 GList *ident_trusted_nets;
155 gboolean do_queue;
157 gboolean do_verbose;
159 gchar *mbox_default;
160 GList *mbox_users;
161 GList *mda_users;
163 gchar *mda;
164 gboolean mda_fromline;
165 gboolean mda_fromhack;
167 gboolean pipe_fromline;
168 gboolean pipe_fromhack;
170 gchar *alias_file;
171 int (*localpartcmp) (const char *, const char *);
173 GList *local_net_routes;
174 GList *connect_routes; /* list of pairs which point to lists */
176 gchar *online_query;
178 gchar *errmsg_file;
179 gchar *warnmsg_file;
180 GList *warn_intervals;
181 gint max_defer_time;
183 gchar *log_user;
184 } masqmail_conf;
186 extern masqmail_conf conf;
188 typedef struct _table_pair {
189 gchar *key;
190 gpointer *value;
191 } table_pair;
194 /* must match the contents of prot_names[] in accept.c */
195 typedef enum _prot_id {
196 PROT_LOCAL = 0,
197 PROT_SMTP,
198 PROT_ESMTP,
199 PROT_NUM
200 } prot_id;
202 extern gchar *prot_names[];
204 typedef enum _header_id {
205 HEAD_FROM = 0,
206 HEAD_SENDER,
207 HEAD_TO,
208 HEAD_CC,
209 HEAD_BCC,
210 HEAD_DATE,
211 HEAD_MESSAGE_ID,
212 HEAD_REPLY_TO,
213 HEAD_SUBJECT,
214 HEAD_RETURN_PATH,
215 HEAD_ENVELOPE_TO,
216 HEAD_RECEIVED,
217 HEAD_NUM_IDS,
218 HEAD_STATUS,
219 HEAD_UNKNOWN = HEAD_NUM_IDS,
220 HEAD_NONE = -1,
221 } header_id;
223 typedef struct _header_name {
224 gchar *header;
225 header_id id;
226 } header_name;
228 typedef struct _header {
229 header_id id;
230 gchar *header;
231 gchar *value;
232 } header;
235 typedef struct _message {
236 gchar *uid;
238 gchar *received_host;
239 prot_id received_prot;
240 gchar *ident;
241 gint transfer_id; /* for multiple messages per transfer */
243 address *return_path;
244 GList *rcpt_list;
245 GList *non_rcpt_list;
247 GList *hdr_list;
248 GList *data_list;
250 gint data_size;
251 time_t received_time;
252 time_t warned_time;
254 gchar *full_sender_name;
255 } message;
257 typedef struct _msg_out {
258 message *msg;
260 address *return_path;
261 GList *rcpt_list;
263 GList *hdr_list;
264 GList *xtra_hdr_list;
265 } msg_out;
267 typedef struct _msgout_perhost {
268 gchar *host;
269 GList *msgout_list;
270 } msgout_perhost;
272 /* flags for accept() */
273 #define ACC_RCPT_FROM_HEAD 0x08 /* -t option, get rcpts from headers */
274 #define ACC_DOT_IGNORE 0x10 /* a dot on a line itself does not end the message (-oi option) */
275 #define ACC_MAIL_FROM_HEAD 0x40 /* get return path from header */
276 #define ACC_NODOT_RELAX 0x80 /* do not be picky if message ist not terminated by a dot on a line */
277 #define ACC_SAVE_ENVELOPE_TO 0x0100 /* save an existent Envelope-to header as X-Orig-Envelope-to */
279 #define DLVR_LOCAL 0x01
280 #define DLVR_LAN 0x02
281 #define DLVR_ONLINE 0x04
282 #define DLVR_ALL (DLVR_LOCAL|DLVR_LAN|DLVR_ONLINE)
284 /* transport flags */
285 #define MSGSTR_FROMLINE 0x01
286 #define MSGSTR_FROMHACK 0x02
288 typedef enum _accept_error {
289 AERR_OK = 0,
290 AERR_TIMEOUT,
291 AERR_EOF,
292 AERR_OVERFLOW,
293 AERR_SYNTAX,
294 AERR_NOSPOOL,
295 AERR_NORCPT,
296 AERR_SIZE, /* max msg size exeeded (SMTP SIZE) */
297 AERR_UNKNOWN
298 } accept_error;
300 #define BUF_LEN 1024
301 #define MAX_ADDRESS 256
302 #define MAX_DATALINE 4096
304 typedef enum _smtp_cmd_id {
305 SMTP_HELO = 0,
306 SMTP_EHLO,
307 SMTP_MAIL_FROM,
308 SMTP_RCPT_TO,
309 SMTP_DATA,
310 SMTP_QUIT,
311 SMTP_RSET,
312 SMTP_NOOP,
313 SMTP_HELP,
314 SMTP_NUM_IDS,
315 SMTP_EOF = -1,
316 SMTP_ERROR = -2,
317 } smtp_cmd_id;
319 typedef struct _smtp_cmd {
320 smtp_cmd_id id;
321 gchar *cmd;
322 } smtp_cmd;
324 typedef struct _smtp_connection {
325 gchar *remote_host;
327 prot_id prot;
328 gint next_id;
330 gboolean helo_seen;
331 gboolean from_seen;
332 gboolean rcpt_seen;
334 message *msg;
335 } smtp_connection;
337 /* alias.c*/
338 gboolean addr_is_local(address * addr);
339 GList *alias_expand(GList * alias_table, GList * rcpt_list, GList * non_rcpt_list);
341 /* child.c */
342 int child(const char *command);
344 /* conf.c */
345 void init_conf();
346 gboolean read_conf(gchar * filename);
347 connect_route *read_route(gchar * filename, gboolean is_local_net);
348 GList *read_route_list(GList * rf_list, gboolean is_local_net);
349 void destroy_route(connect_route * r);
350 void destroy_route_list(GList * list);
351 connect_route *create_local_route();
353 /* expand.c */
354 GList *var_table_rcpt(GList * var_table, address * rcpt);
355 GList *var_table_msg(GList * var_table, message * msg);
356 GList *var_table_conf(GList * var_table);
357 gint expand(GList * var_list, gchar * format, gchar * result, gint result_len);
359 /* message.c */
360 message *create_message(void);
361 void destroy_message(message * msg);
362 void destroy_msg_list(GList * msg_list);
363 void msg_free_data(message * msg);
364 gint msg_calc_size(message * msg, gboolean is_smtp);
366 msg_out *create_msg_out(message * msg);
367 msg_out *clone_msg_out(msg_out * msgout_orig);
368 GList *create_msg_out_list(GList * msg_list);
369 void destroy_msg_out(msg_out * msgout);
370 void destroy_msg_out_list(GList * msgout_list);
372 /* address.c */
373 address *create_address(gchar * path, gboolean is_rfc821);
374 address *create_address_qualified(gchar * path, gboolean is_rfc821, gchar * domain);
375 address *create_address_pipe(gchar * path);
376 void destroy_address(address * addr);
377 address *copy_modify_address(const address * orig, gchar * l_part, gchar * dom);
378 #define copy_address(addr) copy_modify_address(addr, NULL, NULL)
379 gboolean addr_isequal(address * addr1, address * addr2, int (*cmpfunc) (const char*, const char*));
380 gboolean addr_isequal_parent(address * addr1, address * addr2, int (*cmpfunc) (const char*, const char*));
381 address *addr_find_ancestor(address * addr);
382 gboolean addr_is_delivered_children(address * addr);
383 gboolean addr_is_finished_children(address * addr);
384 gchar *addr_string(address * addr);
386 /* accept.c */
387 accept_error accept_message(FILE * in, message * msg, guint flags);
388 accept_error accept_message_prepare(message * msg, guint flags);
390 /* header.c */
391 gchar *rec_timestamp();
392 GList *find_header(GList * hdr_list, header_id id, gchar * hdr_str);
393 void header_unfold(header * hdr);
394 void header_fold(header * hdr, unsigned int maxlen);
395 header *create_header(header_id id, gchar * fmt, ...);
396 void destroy_header(header * hdr);
397 header *copy_header(header * hdr);
398 header *get_header(gchar * line);
400 /* smtp_in.c */
401 void smtp_in(FILE * in, FILE * out, gchar * remote_host, gchar * ident);
403 /* listen.c */
404 void listen_port(GList * addr_list, gint qival, char *argv[]);
406 /* parse.c */
407 gboolean split_address(const gchar * path, gchar ** local_part, gchar ** domain, gboolean is_rfc821);
408 gboolean parse_address_rfc822(gchar * string, gchar ** local_begin, gchar ** local_end, gchar ** domain_begin, gchar ** domain_end, gchar ** address_end);
409 gboolean parse_address_rfc821(gchar * string, gchar ** local_begin, gchar ** local_end, gchar ** domain_begin, gchar ** domain_end, gchar ** address_end);
410 address *_create_address(gchar * string, gchar ** end, gboolean is_rfc821);
411 address *create_address_rfc821(gchar * string, gchar ** end);
412 address *create_address_rfc822(gchar * string, gchar ** end);
413 GList *addr_list_append_rfc822(GList * addr_list, gchar * string, gchar * domain);
415 /* connect.c */
416 mxip_addr *connect_hostlist(int *psockfd, gchar * host, guint port, GList * addr_list);
417 mxip_addr *connect_resolvelist(int *psockfd, gchar * host, guint port, GList * res_funcs);
419 /* deliver.c */
420 void msg_rcptlist_local(GList * rcpt_list, GList **, GList **);
421 gboolean deliver_local(msg_out * msgout);
422 gboolean deliver_msglist_host(connect_route * route, GList * msg_list, gchar * host, GList * res_list);
423 gboolean deliver_route_msgout_list(connect_route * route, GList * msgout_list);
424 gboolean deliver_route_msg_list(connect_route * route, GList * msgout_list);
425 gboolean deliver_finish(msg_out * msgout);
426 gboolean deliver_finish_list(GList * msgout_list);
427 gboolean deliver_msg_list(GList * msg_list, guint flags);
428 gboolean deliver(message * msg);
430 /* fail_msg.c */
431 gboolean fail_msg(message * msg, gchar * template, GList * failed_rcpts, gchar * err_fmt, va_list args);
432 gboolean warn_msg(message * msg, gchar * template, GList * failed_rcpts, gchar * err_fmt, va_list args);
434 /* interface.c */
435 gboolean init_sockaddr(struct sockaddr_in *name, interface * iface);
436 int make_server_socket(interface * iface);
438 /* local.c */
439 gboolean append_file(message * msg, GList * hdr_list, gchar * user);
440 gboolean pipe_out(message * msg, GList * hdr_list, address * rcpt, gchar * cmd, guint flags);
442 /* log.c */
443 gchar *ext_strerror(int err);
444 gboolean logopen(void);
445 void logclose(void);
446 void vlogwrite(int pri, const char *fmt, va_list args);
447 void logwrite(int pri, const char *fmt, ...);
448 void debugf(const char *fmt, ...);
449 void vdebugf(const char *fmt, va_list args);
450 void maillog(const char *fmt, ...);
452 /* spool.c */
453 gboolean spool_read_data(message * msg);
454 message *msg_spool_read(gchar * uid, gboolean do_readdata);
455 gboolean spool_write(message * msg, gboolean do_writedata);
456 gboolean spool_lock(gchar * uid);
457 gboolean spool_unlock(gchar * uid);
458 gboolean spool_delete_all(message * msg);
460 /* queue.c */
461 GList *read_queue(gboolean do_readdata);
462 gboolean queue_run(void);
463 gboolean queue_run_online(void);
464 void queue_list(void);
465 gboolean queue_delete(gchar * uid);
467 /* online.c */
468 gchar *online_query();
470 /* permissions.c */
471 gboolean is_ingroup(uid_t uid, gid_t gid);
472 void set_euidgid(gint uid, gint gid, uid_t * old_uid, gid_t * old_gid);
473 void set_identity(uid_t old_uid, gchar * task_name);
475 /* rewrite.c */
476 gboolean set_address_header_domain(header * hdr, gchar * domain);
477 gboolean map_address_header(header * hdr, GList * table);
479 /* route.c */
480 msgout_perhost *create_msgout_perhost(gchar * host);
481 void destroy_msgout_perhost(msgout_perhost * mo_ph);
482 void rewrite_headers(msg_out * msgout, connect_route * route);
483 void split_rcpts(GList* rcpt_list, GList* localnets, GList** rl_local, GList** rl_localnet, GList** rl_others);
484 gboolean route_strip_msgout(connect_route * route, msg_out * msgout);
485 msg_out *route_prepare_msgout(connect_route * route, msg_out * msgout);
486 GList *route_msgout_list(connect_route * route, GList * msgout_list);
487 gboolean route_sender_is_allowed(connect_route * route, address * ret_path);
488 void route_split_rcpts(connect_route * route, GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list);
490 /* tables.c */
491 table_pair *create_pair(gchar * key, gpointer value);
492 table_pair *create_pair_string(gchar * key, gpointer value);
493 table_pair *parse_table_pair(gchar * line, char delim);
494 gpointer *table_find_func(GList * table_list, gchar * key, int (*cmp_func) (const char *, const char *));
495 gpointer *table_find(GList * table_list, gchar * key);
496 gpointer *table_find_case(GList * table_list, gchar * key);
497 gpointer *table_find_fnmatch(GList * table_list, gchar * key);
498 GList *table_read(gchar * fname, gchar delim);
499 void destroy_table(GList * table);
501 /* timeival.c */
502 gint time_interval(gchar * str);
504 /* permissions.c */
505 gboolean is_privileged_user(uid_t uid);
507 /* other things */
509 #define foreach(list, node)\
510 for((node) = g_list_first(list);\
511 (node);\
512 (node) = g_list_next(node))
514 #ifdef ENABLE_DEBUG
515 #define DEBUG(level) if(level <= conf.debug_level)
516 #else
517 /* hopefully the compiler optmizes this away... */
518 #define DEBUG(level) if(0)
519 #endif
521 #define LOG_VERBOSE 0x100
523 #ifndef HAVE_GETLINE
524 #define getline(buf, size, file) getdelim(buf, size, '\n', file)
525 #endif
527 #ifndef HAVE_FDATASYNC
528 #define fdatasync(fd) fsync(fd)
529 #endif
531 #ifndef CONF_DIR
532 #define CONF_DIR "/etc/masqmail"
533 #endif
535 #define CONF_FILE CONF_DIR"/masqmail.conf"
537 #define PIDFILEDIR "/var/run/masqmail/"
539 #ifndef va_copy
540 #ifdef __va_copy
541 #define va_copy(ap1, ap2) __va_copy(ap1, ap2)
542 #else
543 #define va_copy(ap1, ap2) G_VA_COPY(ap1, ap2)
544 #endif
545 #endif
547 /* *BSD needs this: */
548 extern char **environ;