masqmail

view src/masqmail.h @ 421:f37384470855

Changed lockdir to /var/lock/masqmail; Create lockdir and piddir on startup. Moved the lockdir out of the spool dir. (When /var/lock is a ramdisk we do well to have the lock files there.) Added the new configure option --with-lockdir to change that location. Nontheless, if we run_as_user, then lock files are always stored in the spool dir directly. Instead of installing the lockdir and piddir at installation time, we create them on startup time now if they are missing. This is necessary if lockdir or piddir are a tmpfs.
author markus schnalke <meillo@marmaro.de>
date Wed, 30 May 2012 09:38:38 +0200
parents 8fedb93e9b72
children 5593964ec779
line source
1 /*
2 ** MasqMail
3 ** Copyright (C) 1999-2001 Oliver Kurth
4 ** Copyright (C) 2010 markus schnalke <meillo@marmaro.de>
5 **
6 ** This program is free software; you can redistribute it and/or modify
7 ** it under the terms of the GNU General Public License as published by
8 ** the Free Software Foundation; either version 2 of the License, or
9 ** (at your option) any later version.
10 **
11 ** This program is distributed in the hope that it will be useful,
12 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
13 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 ** GNU General Public License for more details.
15 **
16 ** You should have received a copy of the GNU General Public License
17 ** along with this program; if not, write to the Free Software
18 ** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 */
20 #include <config.h>
22 #include <stdio.h>
23 #include <stdarg.h>
24 #include <errno.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #include <ctype.h>
28 #include <unistd.h>
29 #include <pwd.h>
30 #include <sys/types.h>
31 #include <sys/socket.h>
32 #include <netinet/in.h>
33 #include <time.h>
34 #include <sys/time.h>
35 #include <netinet/in.h>
36 #include <arpa/inet.h>
37 #include <netdb.h>
38 #include <syslog.h>
39 #include <signal.h>
40 #include <fcntl.h>
42 #include <glib.h>
44 #include "lookup.h"
46 typedef struct _interface {
47 gchar *address;
48 gint port;
49 } interface;
51 #define ADDR_FLAG_DELIVERED 0x01
52 #define ADDR_FLAG_DEFERED 0x02
53 #define ADDR_FLAG_FAILED 0x04
54 #define ADDR_FLAG_LAST_ROUTE 0x40
56 typedef struct _address {
57 gchar *address; /* full addr string: `markus <meillo@marmaro.de>' */
58 gchar *local_part; /* in this example: `meillo' */
59 gchar *domain; /* in this example: `marmaro.de' */
60 gint flags;
61 GList *children;
62 struct _address *parent;
63 } address;
65 #define addr_mark_delivered(addr) { addr->flags |= ADDR_FLAG_DELIVERED; }
66 #define addr_unmark_delivered(addr) { addr->flags &= ~ADDR_FLAG_DELIVERED; }
67 #define addr_is_delivered(addr) ((addr->flags & ADDR_FLAG_DELIVERED) != 0 )
69 #define addr_mark_defered(addr) { addr->flags |= ADDR_FLAG_DEFERED; }
70 #define addr_unmark_defered(addr) { addr->flags &= ~ADDR_FLAG_DEFERED; }
71 #define addr_is_defered(addr) ((addr->flags & ADDR_FLAG_DEFERED) != 0 )
73 #define addr_mark_failed(addr) { addr->flags |= ADDR_FLAG_FAILED; }
74 #define addr_unmark_failed(addr) { addr->flags &= ~ADDR_FLAG_FAILED; }
75 #define addr_is_failed(addr) ((addr->flags & ADDR_FLAG_FAILED) != 0 )
77 typedef struct _connect_route {
78 gchar *name;
79 gchar *filename;
81 gboolean is_perma;
82 gboolean last_route;
84 GList *allowed_senders;
85 GList *denied_senders;
86 GList *allowed_recipients;
87 GList *denied_recipients;
89 interface *mail_host;
90 gboolean connect_error_fail;
91 GList *resolve_list;
92 gchar *helo_name;
93 gboolean do_correct_helo;
94 gboolean instant_helo;
95 gboolean do_pipelining;
96 gchar *auth_name;
97 gchar *auth_login;
98 gchar *auth_secret;
99 gchar *wrapper;
101 gchar *set_h_from_domain;
102 gchar *set_h_reply_to_domain;
103 gchar *set_return_path_domain;
104 GList *map_h_from_addresses;
105 GList *map_h_reply_to_addresses;
106 GList *map_h_mail_followup_to_addresses;
107 GList *map_return_path_addresses;
108 gboolean expand_h_sender_domain;
109 gboolean expand_h_sender_address;
111 gchar *pipe;
112 gboolean pipe_fromline;
113 gboolean pipe_fromhack;
114 } connect_route;
116 typedef struct _masqmail_conf {
117 gint mail_uid;
118 gint mail_gid;
120 gint orig_uid;
121 gint orig_gid;
123 gboolean run_as_user;
125 gchar *mail_dir;
126 gchar *lock_dir;
127 gchar *spool_dir;
128 gchar *log_dir;
130 gint debug_level;
131 gboolean use_syslog;
133 gchar *host_name;
134 GList *local_hosts;
135 GList *local_addresses;
136 GList *not_local_addresses;
137 GList *listen_addresses;
139 /*
140 ** ANSI C defines unsigned long to be at least 32bit
141 ** i.e. ca. 4GB max; that should be enough.
142 */
143 gulong max_msg_size;
145 gboolean do_save_envelope_to;
147 gboolean defer_all;
148 gboolean do_relay;
150 gboolean do_queue;
152 gboolean do_verbose;
154 gchar *mbox_default;
155 GList *mbox_users;
156 GList *mda_users;
158 gchar *mda;
159 gboolean mda_fromline;
160 gboolean mda_fromhack;
162 gboolean pipe_fromline;
163 gboolean pipe_fromhack;
165 gchar *alias_file;
166 int (*localpartcmp) (const char *, const char *);
167 gchar *globalias_file;
169 GList *perma_routes;
170 GList *query_routes; /* list of pairs which point to lists */
172 gchar *online_query;
174 gchar *errmsg_file;
175 gchar *warnmsg_file;
176 GList *warn_intervals;
177 gint max_defer_time;
179 gchar *log_user;
180 } masqmail_conf;
182 extern masqmail_conf conf;
184 typedef struct _table_pair {
185 gchar *key;
186 gpointer *value;
187 } table_pair;
190 /* must match the contents of prot_names[] in accept.c */
191 typedef enum _prot_id {
192 PROT_LOCAL = 0,
193 PROT_SMTP,
194 PROT_ESMTP,
195 PROT_NUM
196 } prot_id;
198 extern gchar *prot_names[];
200 typedef enum _header_id {
201 HEAD_FROM = 0,
202 HEAD_SENDER,
203 HEAD_TO,
204 HEAD_CC,
205 HEAD_BCC,
206 HEAD_DATE,
207 HEAD_MESSAGE_ID,
208 HEAD_REPLY_TO,
209 HEAD_SUBJECT,
210 HEAD_RETURN_PATH,
211 HEAD_ENVELOPE_TO,
212 HEAD_RECEIVED,
213 HEAD_NUM_IDS,
214 HEAD_STATUS,
215 HEAD_UNKNOWN = HEAD_NUM_IDS,
216 HEAD_NONE = -1,
217 } header_id;
219 typedef struct _header_name {
220 gchar *header;
221 header_id id;
222 } header_name;
224 typedef struct _header {
225 header_id id;
226 gchar *header;
227 gchar *value;
228 } header;
231 typedef struct _message {
232 gchar *uid;
234 gchar *received_host;
235 prot_id received_prot;
236 gchar *ident;
237 gint transfer_id; /* for multiple messages per transfer */
239 address *return_path;
240 GList *rcpt_list;
241 GList *non_rcpt_list;
243 GList *hdr_list;
244 GList *data_list;
246 gint data_size;
247 time_t received_time;
248 time_t warned_time;
250 gchar *full_sender_name;
251 } message;
253 typedef struct _msg_out {
254 message *msg;
256 address *return_path;
257 GList *rcpt_list;
259 GList *hdr_list;
260 GList *xtra_hdr_list; /* rewritten headers */
261 } msg_out;
263 typedef struct _msgout_perhost {
264 gchar *host;
265 GList *msgout_list;
266 } msgout_perhost;
268 /* flags for accept() */
269 #define ACC_RCPT_FROM_HEAD 0x08 /* -t option, get rcpts from headers */
270 #define ACC_DOT_IGNORE 0x10 /* a dot on a line itself does not end the message (-oi option) */
271 #define ACC_MAIL_FROM_HEAD 0x40 /* get return path from header */
272 #define ACC_NODOT_RELAX 0x80 /* do not be picky if message ist not terminated by a dot on a line */
273 #define ACC_SAVE_ENVELOPE_TO 0x0100 /* save an existent Envelope-to header as X-Orig-Envelope-to */
275 #define DLVR_LOCAL 0x01
276 #define DLVR_ONLINE 0x02
277 #define DLVR_ALL (DLVR_LOCAL|DLVR_ONLINE)
279 /* transport flags */
280 #define MSGSTR_FROMLINE 0x01
281 #define MSGSTR_FROMHACK 0x02
283 typedef enum _accept_error {
284 AERR_OK = 0,
285 AERR_TIMEOUT,
286 AERR_EOF,
287 AERR_OVERFLOW,
288 AERR_SYNTAX,
289 AERR_NOSPOOL,
290 AERR_NORCPT,
291 AERR_SIZE, /* max msg size exeeded (SMTP SIZE) */
292 AERR_UNKNOWN
293 } accept_error;
295 #define BUF_LEN 1024
296 #define MAX_ADDRESS 256
297 #define MAX_DATALINE 4096
299 typedef enum _smtp_cmd_id {
300 SMTP_HELO = 0,
301 SMTP_EHLO,
302 SMTP_MAIL_FROM,
303 SMTP_RCPT_TO,
304 SMTP_DATA,
305 SMTP_QUIT,
306 SMTP_RSET,
307 SMTP_NOOP,
308 SMTP_HELP,
309 SMTP_NUM_IDS,
310 SMTP_EOF = -1,
311 SMTP_ERROR = -2,
312 } smtp_cmd_id;
314 typedef struct _smtp_cmd {
315 smtp_cmd_id id;
316 gchar *cmd;
317 } smtp_cmd;
319 typedef struct _smtp_connection {
320 gchar *remote_host;
322 prot_id prot;
323 gint next_id;
325 gboolean helo_seen;
326 gboolean from_seen;
327 gboolean rcpt_seen;
329 message *msg;
330 } smtp_connection;
332 /* alias.c*/
333 gboolean addr_is_local(address *addr);
334 GList *alias_expand(GList *alias_table, GList *rcpt_list, GList *non_rcpt_list,
335 int doglob);
337 /* child.c */
338 int child(const char *command);
340 /* conf.c */
341 void init_conf();
342 gboolean read_conf(gchar *filename);
343 connect_route *read_route(gchar *filename, gboolean is_perma);
344 GList *read_route_list(GList *rf_list, gboolean is_perma);
345 void destroy_route(connect_route *r);
346 void destroy_route_list(GList *list);
348 /* expand.c */
349 GList *var_table_rcpt(GList *var_table, address *rcpt);
350 GList *var_table_msg(GList *var_table, message *msg);
351 GList *var_table_conf(GList *var_table);
352 gint expand(GList *var_list, gchar *format, gchar *result, gint result_len);
354 /* message.c */
355 message *create_message(void);
356 void destroy_message(message *msg);
357 void destroy_msg_list(GList *msg_list);
358 void msg_free_data(message *msg);
359 gint msg_calc_size(message *msg, gboolean is_smtp);
361 msg_out *create_msg_out(message *msg);
362 msg_out *clone_msg_out(msg_out *msgout_orig);
363 void destroy_msg_out(msg_out *msgout);
364 void destroy_msg_out_list(GList *msgout_list);
366 /* address.c */
367 address *create_address(gchar *path, gboolean is_rfc821);
368 address *create_address_qualified(gchar *path, gboolean is_rfc821, gchar *domain);
369 address *create_address_pipe(gchar *path);
370 void destroy_address(address *addr);
371 address *copy_modify_address(const address *orig, gchar *l_part, gchar *dom);
372 #define copy_address(addr) copy_modify_address(addr, NULL, NULL)
373 gboolean addr_isequal(address *addr1, address *addr2, int (*cmpfunc) (const char*, const char*));
374 gboolean addr_isequal_parent(address *addr1, address *addr2, int (*cmpfunc) (const char*, const char*));
375 address *addr_find_ancestor(address *addr);
376 gboolean addr_is_delivered_children(address *addr);
377 gboolean addr_is_finished_children(address *addr);
378 gchar *addr_string(address *addr);
380 /* accept.c */
381 accept_error accept_message(FILE *in, message *msg, guint flags);
382 accept_error accept_message_prepare(message *msg, guint flags);
384 /* header.c */
385 gchar *rec_timestamp();
386 GList *find_header(GList *hdr_list, header_id id, gchar *hdr_str);
387 void header_unfold(header *hdr);
388 void header_fold(header *hdr, unsigned int maxlen);
389 header *create_header(header_id id, gchar *fmt, ...);
390 void destroy_header(header *hdr);
391 header *copy_header(header *hdr);
392 header *get_header(gchar *line);
394 /* smtp_in.c */
395 void smtp_in(FILE *in, FILE *out, gchar *remote_host, gchar *ident);
397 /* listen.c */
398 void listen_port(GList *addr_list, gint qival, char *argv[]);
400 /* parse.c */
401 gboolean split_address(const gchar *path, gchar **local_part, gchar **domain, gboolean is_rfc821);
402 gboolean parse_address_rfc822(gchar *string, gchar **local_begin, gchar **local_end, gchar **domain_begin, gchar **domain_end, gchar **address_end);
403 gboolean parse_address_rfc821(gchar *string, gchar **local_begin, gchar **local_end, gchar **domain_begin, gchar **domain_end, gchar **address_end);
404 address *_create_address(gchar *string, gchar **end, gboolean is_rfc821);
405 address *create_address_rfc821(gchar *string, gchar **end);
406 address *create_address_rfc822(gchar *string, gchar **end);
407 GList *addr_list_append_rfc822(GList *addr_list, gchar *string, gchar *domain);
409 /* connect.c */
410 mxip_addr *connect_hostlist(int *psockfd, gchar *host, guint port, GList *addr_list);
411 mxip_addr *connect_resolvelist(int *psockfd, gchar *host, guint port, GList *res_funcs);
413 /* deliver.c */
414 void msg_rcptlist_local(GList *rcpt_list, GList **, GList **);
415 gboolean deliver_local(msg_out *msgout);
416 gboolean deliver_msglist_host(connect_route *route, GList *msg_list, gchar *host, GList *res_list);
417 gboolean deliver_route_msgout_list(connect_route *route, GList *msgout_list);
418 gboolean deliver_route_msg_list(connect_route *route, GList *msgout_list);
419 gboolean deliver_finish(msg_out *msgout);
420 gboolean deliver_msg_list(GList *msg_list, guint flags);
421 gboolean deliver(message *msg);
423 /* fail_msg.c */
424 gboolean fail_msg(message *msg, gchar *template, GList *failed_rcpts, gchar *err_fmt, va_list args);
425 gboolean warn_msg(message *msg, gchar *template, GList *failed_rcpts, gchar *err_fmt, va_list args);
427 /* interface.c */
428 gboolean init_sockaddr(struct sockaddr_in *name, interface *iface);
429 int make_server_socket(interface *iface);
431 /* local.c */
432 gboolean append_file(message *msg, GList *hdr_list, gchar *user);
433 gboolean pipe_out(message *msg, GList *hdr_list, address *rcpt, gchar *cmd, guint flags);
435 /* log.c */
436 gchar *ext_strerror(int err);
437 gboolean logopen(void);
438 void logclose(void);
439 void vlogwrite(int pri, const char *fmt, va_list args);
440 void logwrite(int pri, const char *fmt, ...);
441 void debugf(const char *fmt, ...);
442 void vdebugf(const char *fmt, va_list args);
443 void maillog(const char *fmt, ...);
445 /* spool.c */
446 gboolean spool_read_data(message *msg);
447 message *msg_spool_read(gchar *uid);
448 gboolean spool_write(message *msg, gboolean do_writedata);
449 gboolean spool_lock(gchar *uid);
450 gboolean spool_unlock(gchar *uid);
451 gboolean spool_delete_all(message *msg);
453 /* queue.c */
454 GList *read_queue(void);
455 gboolean queue_run(void);
456 gboolean queue_run_online(void);
457 void queue_list(void);
458 gboolean queue_delete(gchar *uid);
460 /* online.c */
461 gchar *online_query();
463 /* permissions.c */
464 gboolean is_ingroup(uid_t uid, gid_t gid);
465 void set_euidgid(gint uid, gint gid, uid_t *old_uid, gid_t *old_gid);
466 void set_identity(uid_t old_uid, gchar *task_name);
468 /* rewrite.c */
469 gboolean set_address_header_domain(header *hdr, gchar *domain);
470 gboolean map_address_header(header *hdr, GList *table);
472 /* route.c */
473 msgout_perhost *create_msgout_perhost(gchar *host);
474 void destroy_msgout_perhost(msgout_perhost *mo_ph);
475 void rewrite_headers(msg_out *msgout, connect_route *route);
476 void split_rcpts(GList *rcpt_list, GList *localnets, GList **rl_local, GList **rl_localnet, GList **rl_others);
477 GList *local_rcpts(GList *rcpt_list);
478 GList *remote_rcpts(GList *rcpt_list);
479 gboolean route_strip_msgout(connect_route *route, msg_out *msgout);
480 msg_out *route_prepare_msgout(connect_route *route, msg_out *msgout);
481 GList *route_msgout_list(connect_route *route, GList *msgout_list);
482 gboolean route_sender_is_allowed(connect_route *route, address *ret_path);
483 void route_split_rcpts(connect_route *route, GList *rcpt_list, GList **p_rcpt_list, GList **p_non_rcpt_list);
485 /* tables.c */
486 table_pair *create_pair(gchar *key, gpointer value);
487 table_pair *create_pair_string(gchar *key, gpointer value);
488 table_pair *parse_table_pair(gchar *line, char delim);
489 gpointer *table_find_func(GList *table_list, gchar *key, int (*cmp_func) (const char *, const char *));
490 gpointer *table_find(GList *table_list, gchar *key);
491 gpointer *table_find_case(GList *table_list, gchar *key);
492 gpointer *table_find_fnmatch(GList *table_list, gchar *key);
493 GList *table_read(gchar *fname, gchar delim);
494 void destroy_table(GList *table);
496 /* timeival.c */
497 gint time_interval(gchar *str);
499 /* permissions.c */
500 gboolean is_privileged_user(uid_t uid);
502 /* other things */
504 #define foreach(list, node)\
505 for((node) = g_list_first(list);\
506 (node);\
507 (node) = g_list_next(node))
509 #ifdef ENABLE_DEBUG
510 #define DEBUG(level) if(level <= conf.debug_level)
511 #else
512 /* hopefully the compiler optmizes this away... */
513 #define DEBUG(level) if(0)
514 #endif
516 #define LOG_VERBOSE 0x100
518 #ifndef HAVE_GETLINE
519 #define getline(buf, size, file) getdelim(buf, size, '\n', file)
520 #endif
522 #ifndef HAVE_FDATASYNC
523 #define fdatasync(fd) fsync(fd)
524 #endif
526 #ifndef CONF_DIR
527 #define CONF_DIR "/etc/masqmail"
528 #endif
530 #define CONF_FILE CONF_DIR"/masqmail.conf"
532 #ifndef PID_DIR
533 #define PID_DIR "/var/run"
534 #endif
536 #ifndef va_copy
537 #ifdef __va_copy
538 #define va_copy(ap1, ap2) __va_copy(ap1, ap2)
539 #else
540 #define va_copy(ap1, ap2) G_VA_COPY(ap1, ap2)
541 #endif
542 #endif
544 /* *BSD needs this: */
545 extern char **environ;