masqmail

view src/masqmail.h @ 304:d5ce2ba71e7b

manual formating of Received: hdrs; changed hdr for local receival Now the Received: headers are much friendlier to read. About folding: We must fold any line at 998 chars before transfer. We should fold the lines we produce at 78 chars. That is what RFC 2821 requests. We should think about it, somewhen. The header for locally (i.e. non-SMTP) received mail is changed to the format postfix uses. This matches RFC 2821 better. The `from' clause should contain a domain or IP, not a user name. Also, the `with' clause should contain a registered standard protocol name, which ``local'' is not.
author markus schnalke <meillo@marmaro.de>
date Thu, 09 Dec 2010 18:28:11 -0300
parents ca2d11aec2a3
children f10a56dc7481
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 gchar *protocol;
86 gboolean is_local_net;
87 gboolean last_route;
89 GList *allowed_return_paths;
90 GList *not_allowed_return_paths;
91 GList *allowed_mail_locals;
92 GList *not_allowed_mail_locals;
93 GList *allowed_rcpt_domains;
94 GList *not_allowed_rcpt_domains;
96 interface *mail_host;
97 gchar *wrapper;
98 gboolean connect_error_fail;
100 gchar *helo_name;
101 gboolean do_correct_helo;
102 gboolean instant_helo;
103 gboolean do_pipelining;
105 gchar *set_h_from_domain;
106 gchar *set_h_reply_to_domain;
107 gchar *set_return_path_domain;
109 GList *map_h_from_addresses;
110 GList *map_h_reply_to_addresses;
111 GList *map_h_mail_followup_to_addresses;
112 GList *map_return_path_addresses;
114 gboolean expand_h_sender_domain;
115 gboolean expand_h_sender_address;
117 GList *resolve_list;
119 gchar *auth_name;
120 gchar *auth_login;
121 gchar *auth_secret;
123 gchar *pipe;
125 gboolean pipe_fromline;
126 gboolean pipe_fromhack;
127 } connect_route;
129 typedef struct _masqmail_conf {
130 gint mail_uid;
131 gint mail_gid;
133 gint orig_uid;
134 gint orig_gid;
136 gboolean run_as_user;
138 gchar *mail_dir;
139 gchar *lock_dir;
140 gchar *spool_dir;
141 gchar *log_dir;
143 gint debug_level;
144 gboolean use_syslog;
145 guint log_max_pri;
147 gchar *host_name;
148 GList *local_hosts;
149 GList *local_addresses;
150 GList *not_local_addresses;
151 GList *local_nets;
152 GList *listen_addresses;
154 /* ANSI C defines unsigned long to be at least 32bit
155 i.e. ca. 4GB max; that should be enough. */
156 gulong max_msg_size;
158 gboolean do_save_envelope_to;
160 gboolean defer_all;
161 gboolean do_relay;
163 GList *ident_trusted_nets;
165 gboolean do_queue;
167 gboolean do_verbose;
169 gchar *mbox_default;
170 GList *mbox_users;
171 GList *mda_users;
173 gchar *mda;
174 gboolean mda_fromline;
175 gboolean mda_fromhack;
177 gboolean pipe_fromline;
178 gboolean pipe_fromhack;
180 gchar *alias_file;
181 int (*localpartcmp) (const char *, const char *);
183 GList *local_net_routes;
184 GList *connect_routes; /* list of pairs which point to lists */
186 gchar *online_detect;
187 gchar *online_file;
188 gchar *online_pipe;
190 gchar *errmsg_file;
191 gchar *warnmsg_file;
192 GList *warn_intervals;
193 gint max_defer_time;
195 gchar *log_user;
196 } masqmail_conf;
198 extern masqmail_conf conf;
200 typedef struct _table_pair {
201 gchar *key;
202 gpointer *value;
203 } table_pair;
206 /* must match the contents of prot_names[] in accept.c */
207 typedef enum _prot_id {
208 PROT_LOCAL = 0,
209 PROT_SMTP,
210 PROT_ESMTP,
211 PROT_NUM
212 } prot_id;
214 extern gchar *prot_names[];
216 typedef enum _header_id {
217 HEAD_FROM = 0,
218 HEAD_SENDER,
219 HEAD_TO,
220 HEAD_CC,
221 HEAD_BCC,
222 HEAD_DATE,
223 HEAD_MESSAGE_ID,
224 HEAD_REPLY_TO,
225 HEAD_SUBJECT,
226 HEAD_RETURN_PATH,
227 HEAD_ENVELOPE_TO,
228 HEAD_RECEIVED,
229 HEAD_NUM_IDS,
230 HEAD_STATUS,
231 HEAD_UNKNOWN = HEAD_NUM_IDS,
232 HEAD_NONE = -1,
233 } header_id;
235 typedef struct _header_name {
236 gchar *header;
237 header_id id;
238 } header_name;
240 typedef struct _header {
241 header_id id;
242 gchar *header;
243 gchar *value;
244 } header;
247 typedef struct _message {
248 gchar *uid;
250 gchar *received_host;
251 prot_id received_prot;
252 gchar *ident;
253 gint transfer_id; /* for multiple messages per transfer */
255 address *return_path;
256 GList *rcpt_list;
257 GList *non_rcpt_list;
259 GList *hdr_list;
260 GList *data_list;
262 gint data_size;
263 time_t received_time;
264 time_t warned_time;
266 gchar *full_sender_name;
267 } message;
269 typedef struct _msg_out {
270 message *msg;
272 address *return_path;
273 GList *rcpt_list;
275 GList *hdr_list;
276 GList *xtra_hdr_list;
277 } msg_out;
279 typedef struct _msgout_perhost {
280 gchar *host;
281 GList *msgout_list;
282 } msgout_perhost;
284 /* flags for accept() */
285 #define ACC_RCPT_FROM_HEAD 0x08 /* -t option, get rcpts from headers */
286 #define ACC_DOT_IGNORE 0x10 /* a dot on a line itself does not end the message (-oi option) */
287 #define ACC_MAIL_FROM_HEAD 0x40 /* get return path from header */
288 #define ACC_NODOT_RELAX 0x80 /* do not be picky if message ist not terminated by a dot on a line */
289 #define ACC_SAVE_ENVELOPE_TO 0x0100 /* save an existent Envelope-to header as X-Orig-Envelope-to */
291 #define DLVR_LOCAL 0x01
292 #define DLVR_LAN 0x02
293 #define DLVR_ONLINE 0x04
294 #define DLVR_ALL (DLVR_LOCAL|DLVR_LAN|DLVR_ONLINE)
296 /* transport flags */
297 #define MSGSTR_FROMLINE 0x01
298 #define MSGSTR_FROMHACK 0x02
300 typedef enum _accept_error {
301 AERR_OK = 0,
302 AERR_TIMEOUT,
303 AERR_EOF,
304 AERR_OVERFLOW,
305 AERR_SYNTAX,
306 AERR_NOSPOOL,
307 AERR_NORCPT,
308 AERR_SIZE, /* max msg size exeeded (SMTP SIZE) */
309 AERR_UNKNOWN
310 } accept_error;
312 #define BUF_LEN 1024
313 #define MAX_ADDRESS 256
314 #define MAX_DATALINE 4096
316 typedef enum _smtp_cmd_id {
317 SMTP_HELO = 0,
318 SMTP_EHLO,
319 SMTP_MAIL_FROM,
320 SMTP_RCPT_TO,
321 SMTP_DATA,
322 SMTP_QUIT,
323 SMTP_RSET,
324 SMTP_NOOP,
325 SMTP_HELP,
326 SMTP_NUM_IDS,
327 SMTP_EOF = -1,
328 SMTP_ERROR = -2,
329 } smtp_cmd_id;
331 typedef struct _smtp_cmd {
332 smtp_cmd_id id;
333 gchar *cmd;
334 } smtp_cmd;
336 typedef struct _smtp_connection {
337 gchar *remote_host;
339 prot_id prot;
340 gint next_id;
342 gboolean helo_seen;
343 gboolean from_seen;
344 gboolean rcpt_seen;
346 message *msg;
347 } smtp_connection;
349 /* alias.c*/
350 gboolean addr_is_local(address * addr);
351 GList *alias_expand(GList * alias_table, GList * rcpt_list, GList * non_rcpt_list);
353 /* child.c */
354 int child(const char *command);
356 /* conf.c */
357 void init_conf();
358 gboolean read_conf(gchar * filename);
359 connect_route *read_route(gchar * filename, gboolean is_local_net);
360 GList *read_route_list(GList * rf_list, gboolean is_local_net);
361 void destroy_route(connect_route * r);
362 void destroy_route_list(GList * list);
363 connect_route *create_local_route();
365 /* expand.c */
366 GList *var_table_rcpt(GList * var_table, address * rcpt);
367 GList *var_table_msg(GList * var_table, message * msg);
368 GList *var_table_conf(GList * var_table);
369 gint expand(GList * var_list, gchar * format, gchar * result, gint result_len);
371 /* message.c */
372 message *create_message(void);
373 void destroy_message(message * msg);
374 void destroy_msg_list(GList * msg_list);
375 void msg_free_data(message * msg);
376 gint msg_calc_size(message * msg, gboolean is_smtp);
378 msg_out *create_msg_out(message * msg);
379 msg_out *clone_msg_out(msg_out * msgout_orig);
380 GList *create_msg_out_list(GList * msg_list);
381 void destroy_msg_out(msg_out * msgout);
382 void destroy_msg_out_list(GList * msgout_list);
384 /* address.c */
385 address *create_address(gchar * path, gboolean is_rfc821);
386 address *create_address_qualified(gchar * path, gboolean is_rfc821, gchar * domain);
387 address *create_address_pipe(gchar * path);
388 void destroy_address(address * addr);
389 address *copy_modify_address(const address * orig, gchar * l_part, gchar * dom);
390 #define copy_address(addr) copy_modify_address(addr, NULL, NULL)
391 gboolean addr_isequal(address * addr1, address * addr2, int (*cmpfunc) (const char*, const char*));
392 gboolean addr_isequal_parent(address * addr1, address * addr2, int (*cmpfunc) (const char*, const char*));
393 address *addr_find_ancestor(address * addr);
394 gboolean addr_is_delivered_children(address * addr);
395 gboolean addr_is_finished_children(address * addr);
396 gchar *addr_string(address * addr);
397 gint addr_match(address * addr1, address * addr2);
399 /* accept.c */
400 accept_error accept_message(FILE * in, message * msg, guint flags);
401 accept_error accept_message_prepare(message * msg, guint flags);
403 /* header.c */
404 gchar *rec_timestamp();
405 GList *find_header(GList * hdr_list, header_id id, gchar * hdr_str);
406 void header_unfold(header * hdr);
407 void header_fold(header * hdr, unsigned int maxlen);
408 header *create_header(header_id id, gchar * fmt, ...);
409 void destroy_header(header * hdr);
410 header *copy_header(header * hdr);
411 header *get_header(gchar * line);
413 /* smtp_in.c */
414 void smtp_in(FILE * in, FILE * out, gchar * remote_host, gchar * ident);
416 /* listen.c */
417 void listen_port(GList * addr_list, gint qival, char *argv[]);
419 /* parse.c */
420 gboolean split_address(const gchar * path, gchar ** local_part, gchar ** domain, gboolean is_rfc821);
421 gboolean parse_address_rfc822(gchar * string, gchar ** local_begin, gchar ** local_end, gchar ** domain_begin, gchar ** domain_end, gchar ** address_end);
422 gboolean parse_address_rfc821(gchar * string, gchar ** local_begin, gchar ** local_end, gchar ** domain_begin, gchar ** domain_end, gchar ** address_end);
423 address *_create_address(gchar * string, gchar ** end, gboolean is_rfc821);
424 address *create_address_rfc821(gchar * string, gchar ** end);
425 address *create_address_rfc822(gchar * string, gchar ** end);
426 GList *addr_list_append_rfc822(GList * addr_list, gchar * string, gchar * domain);
428 /* connect.c */
429 mxip_addr *connect_hostlist(int *psockfd, gchar * host, guint port, GList * addr_list);
430 mxip_addr *connect_resolvelist(int *psockfd, gchar * host, guint port, GList * res_funcs);
432 /* deliver.c */
433 void msg_rcptlist_local(GList * rcpt_list, GList **, GList **);
434 gboolean deliver_local(msg_out * msgout);
435 gboolean deliver_msglist_host(connect_route * route, GList * msg_list, gchar * host, GList * res_list);
436 gboolean deliver_route_msgout_list(connect_route * route, GList * msgout_list);
437 gboolean deliver_route_msg_list(connect_route * route, GList * msgout_list);
438 gboolean deliver_finish(msg_out * msgout);
439 gboolean deliver_finish_list(GList * msgout_list);
440 gboolean deliver_msg_list(GList * msg_list, guint flags);
441 gboolean deliver(message * msg);
443 /* fail_msg.c */
444 gboolean fail_msg(message * msg, gchar * template, GList * failed_rcpts, gchar * err_fmt, va_list args);
445 gboolean warn_msg(message * msg, gchar * template, GList * failed_rcpts, gchar * err_fmt, va_list args);
447 /* interface.c */
448 gboolean init_sockaddr(struct sockaddr_in *name, interface * iface);
449 int make_server_socket(interface * iface);
451 /* local.c */
452 gboolean append_file(message * msg, GList * hdr_list, gchar * user);
453 gboolean pipe_out(message * msg, GList * hdr_list, address * rcpt, gchar * cmd, guint flags);
455 /* log.c */
456 gchar *ext_strerror(int err);
457 gboolean logopen(void);
458 void logclose(void);
459 void vlogwrite(int pri, const char *fmt, va_list args);
460 void logwrite(int pri, const char *fmt, ...);
461 void debugf(const char *fmt, ...);
462 void vdebugf(const char *fmt, va_list args);
463 void maillog(const char *fmt, ...);
465 /* spool.c */
466 gboolean spool_read_data(message * msg);
467 message *msg_spool_read(gchar * uid, gboolean do_readdata);
468 gboolean spool_write(message * msg, gboolean do_writedata);
469 gboolean spool_lock(gchar * uid);
470 gboolean spool_unlock(gchar * uid);
471 gboolean spool_delete_all(message * msg);
473 /* queue.c */
474 GList *read_queue(gboolean do_readdata);
475 gboolean queue_run(void);
476 gboolean queue_run_online(void);
477 void queue_list(void);
478 gboolean queue_delete(gchar * uid);
480 /* online.c */
481 gchar *detect_online();
482 void set_online_name(gchar * name);
484 /* permissions.c */
485 gboolean is_ingroup(uid_t uid, gid_t gid);
486 void set_euidgid(gint uid, gint gid, uid_t * old_uid, gid_t * old_gid);
487 void set_identity(uid_t old_uid, gchar * task_name);
489 /* rewrite.c */
490 gboolean set_address_header_domain(header * hdr, gchar * domain);
491 gboolean map_address_header(header * hdr, GList * table);
493 /* route.c */
494 msgout_perhost *create_msgout_perhost(gchar * host);
495 void destroy_msgout_perhost(msgout_perhost * mo_ph);
496 void rewrite_headers(msg_out * msgout, connect_route * route);
497 void split_rcpts(GList* rcpt_list, GList* localnets, GList** rl_local, GList** rl_localnet, GList** rl_others);
498 gboolean route_strip_msgout(connect_route * route, msg_out * msgout);
499 msg_out *route_prepare_msgout(connect_route * route, msg_out * msgout);
500 GList *route_msgout_list(connect_route * route, GList * msgout_list);
501 gboolean route_is_allowed_return_path(connect_route * route, address * ret_path);
502 gboolean route_is_allowed_mail_local(connect_route * route, address * ret_path);
503 void msg_rcptlist_route(connect_route * route, GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list);
505 /* tables.c */
506 table_pair *create_pair(gchar * key, gpointer value);
507 table_pair *create_pair_string(gchar * key, gpointer value);
508 table_pair *parse_table_pair(gchar * line, char delim);
509 gpointer *table_find_func(GList * table_list, gchar * key, int (*cmp_func) (const char *, const char *));
510 gpointer *table_find(GList * table_list, gchar * key);
511 gpointer *table_find_case(GList * table_list, gchar * key);
512 gpointer *table_find_fnmatch(GList * table_list, gchar * key);
513 GList *table_read(gchar * fname, gchar delim);
514 void destroy_table(GList * table);
516 /* timeival.c */
517 gint time_interval(gchar * str);
519 /* permissions.c */
520 gboolean is_privileged_user(uid_t uid);
522 /* other things */
524 #define foreach(list, node)\
525 for((node) = g_list_first(list);\
526 (node);\
527 (node) = g_list_next(node))
529 #ifdef ENABLE_DEBUG
530 #define DEBUG(level) if(level <= conf.debug_level)
531 #else
532 /* hopefully the compiler optmizes this away... */
533 #define DEBUG(level) if(0)
534 #endif
536 #define LOG_VERBOSE 0x100
538 #ifndef HAVE_GETLINE
539 #define getline(buf, size, file) getdelim(buf, size, '\n', file)
540 #endif
542 #ifndef HAVE_FDATASYNC
543 #define fdatasync(fd) fsync(fd)
544 #endif
546 #ifndef CONF_DIR
547 #define CONF_DIR "/etc/masqmail"
548 #endif
550 #define CONF_FILE CONF_DIR"/masqmail.conf"
552 #define PIDFILEDIR "/var/run/masqmail/"
554 #ifndef va_copy
555 #ifdef __va_copy
556 #define va_copy(ap1, ap2) __va_copy(ap1, ap2)
557 #else
558 #define va_copy(ap1, ap2) G_VA_COPY(ap1, ap2)
559 #endif
560 #endif
562 /* *BSD needs this: */
563 extern char **environ;