masqmail-0.2

view src/masqmail.h @ 171:349518b940db

added support for STARTTLS wrappers added the route config option `instant_helo' which causes masqmail, as SMTP client, not to wait for the server's 220 greeting. Instead if says EHLO right at once. You'll need this for STARTTLS wrappers that usually eat the greeting line.
author meillo@marmaro.de
date Thu, 22 Jul 2010 23:30:05 +0200
parents 5ec5e6637049
children 087e99c7702a
line source
1 /* MasqMail
2 Copyright (C) 1999-2001 Oliver Kurth
4 This program 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 2 of the License, or
7 (at your option) any later version.
9 This program 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 A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
14 You should have received a copy of the GNU General Public License
15 along with this program; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 */
18 #include <config.h>
20 #include <stdio.h>
21 #include <stdarg.h>
22 #include <errno.h>
23 #include <stdlib.h>
24 #include <string.h>
25 #include <ctype.h>
26 #include <unistd.h>
27 #include <pwd.h>
28 #include <sys/types.h>
29 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <time.h>
32 #include <sys/time.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
35 #include <netdb.h>
36 #include <syslog.h>
37 #include <signal.h>
38 #include <fcntl.h>
40 #include <glib.h>
42 #ifdef ENABLE_IDENT
43 #include "libident/ident.h"
44 #endif
46 #include "lookup.h"
48 typedef struct _interface {
49 gchar *address;
50 gint port;
51 } interface;
53 #define ADDR_FLAG_DELIVERED 0x01
54 #define ADDR_FLAG_DEFERED 0x02
55 #define ADDR_FLAG_FAILED 0x04
56 #define ADDR_FLAG_LAST_ROUTE 0x40
57 #define ADDR_FLAG_NOEXPAND 0x80
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 *pop3_login;
125 gchar *pipe;
127 gboolean pipe_fromline;
128 gboolean pipe_fromhack;
129 } connect_route;
131 typedef struct _get_conf {
132 gchar *protocol;
133 gchar *server_name;
134 guint server_port;
135 gchar *wrapper;
136 gchar *login_user;
137 gchar *login_pass;
138 address *address;
139 address *return_path;
140 gboolean do_keep;
141 gboolean do_uidl;
142 gboolean do_uidl_dele;
143 gint max_size;
144 gboolean max_size_delete;
145 gint max_count;
147 GList *resolve_list;
149 } get_conf;
151 typedef struct _masqmail_conf {
152 gint mail_uid;
153 gint mail_gid;
155 gint orig_uid;
156 gint orig_gid;
158 gboolean run_as_user;
160 gchar *mail_dir;
161 gchar *lock_dir;
162 gchar *spool_dir;
163 gchar *log_dir;
165 gint debug_level;
166 gboolean use_syslog;
167 guint log_max_pri;
169 gchar *host_name;
170 GList *local_hosts;
171 GList *local_addresses;
172 GList *not_local_addresses;
173 GList *local_nets;
174 GList *listen_addresses;
176 guint remote_port;
178 /* ANSI C defines unsigned long to be at least 32bit
179 i.e. ca. 4GB max; that should be enough. */
180 gulong max_msg_size;
182 gboolean do_save_envelope_to;
184 gboolean defer_all;
185 gboolean do_relay;
187 GList *ident_trusted_nets;
189 gboolean do_queue;
191 gboolean do_verbose;
193 gchar *mbox_default;
194 GList *mbox_users;
195 GList *mda_users;
196 GList *maildir_users;
198 gchar *mda;
199 gboolean mda_fromline;
200 gboolean mda_fromhack;
202 gboolean pipe_fromline;
203 gboolean pipe_fromhack;
205 gchar *alias_file;
206 int (*alias_local_cmp) (const char *, const char *);
208 GList *local_net_routes;
209 GList *connect_routes; /* list of pairs which point to lists */
211 gchar *online_detect;
212 gchar *online_file;
213 gchar *online_pipe;
214 interface *mserver_iface;
216 GList *get_names;
217 GList *online_gets; /* list of pairs which point to lists */
219 gchar *errmsg_file;
220 gchar *warnmsg_file;
221 GList *warn_intervals;
222 gint max_defer_time;
224 gchar *log_user;
225 } masqmail_conf;
227 extern masqmail_conf conf;
229 typedef struct _table_pair {
230 gchar *key;
231 gpointer *value;
232 } table_pair;
235 typedef enum _prot_id {
236 PROT_LOCAL = 0,
237 PROT_BSMTP,
238 PROT_SMTP,
239 PROT_ESMTP,
240 PROT_POP3,
241 PROT_APOP,
242 PROT_NUM
243 } prot_id;
245 extern gchar *prot_names[];
247 typedef enum _header_id {
248 HEAD_FROM = 0,
249 HEAD_SENDER,
250 HEAD_TO,
251 HEAD_CC,
252 HEAD_BCC,
253 HEAD_DATE,
254 HEAD_MESSAGE_ID,
255 HEAD_REPLY_TO,
256 HEAD_SUBJECT,
257 HEAD_RETURN_PATH,
258 HEAD_ENVELOPE_TO,
259 HEAD_RECEIVED,
260 HEAD_NUM_IDS,
261 HEAD_STATUS,
262 HEAD_UNKNOWN = HEAD_NUM_IDS,
263 HEAD_NONE = -1,
264 } header_id;
266 typedef struct _header_name {
267 gchar *header;
268 header_id id;
269 } header_name;
271 typedef struct _header {
272 header_id id;
273 gchar *header;
274 gchar *value;
275 } header;
278 typedef struct _message {
279 gchar *uid;
281 gchar *received_host;
282 prot_id received_prot;
283 gchar *ident;
284 gint transfer_id; /* for multiple messages per transfer */
286 address *return_path;
287 GList *rcpt_list;
288 GList *non_rcpt_list;
290 GList *hdr_list;
291 GList *data_list;
293 gint data_size;
294 time_t received_time;
295 time_t warned_time;
297 gchar *full_sender_name;
298 } message;
300 typedef struct _msg_out {
301 message *msg;
303 address *return_path;
304 GList *rcpt_list;
306 GList *hdr_list;
307 GList *xtra_hdr_list;
308 } msg_out;
310 typedef struct _msgout_perhost {
311 gchar *host;
312 GList *msgout_list;
313 } msgout_perhost;
315 /* flags for accept() */
316 #define ACC_DEL_RCPTS 0x02 /* -t option, delete rcpts that were given as cmd args */
317 #define ACC_RCPT_FROM_HEAD 0x08 /* -t option, get rcpts from headers */
318 #define ACC_DOT_IGNORE 0x10 /* a dot on a line itself does not end the message (-oi option) */
319 #define ACC_MAIL_FROM_HEAD 0x40 /* get return path from header */
320 #define ACC_NODOT_RELAX 0x80 /* do not be picky if message ist not terminated by a dot on a line */
321 #define ACC_SAVE_ENVELOPE_TO 0x0100 /* save an existent Envelope-to header as X-Orig-Envelope-to */
323 #define DLVR_LOCAL 0x01
324 #define DLVR_LAN 0x02
325 #define DLVR_ONLINE 0x04
326 #define DLVR_ALL (DLVR_LOCAL|DLVR_LAN|DLVR_ONLINE)
328 /* transport flags */
329 #define MSGSTR_FROMLINE 0x01
330 #define MSGSTR_FROMHACK 0x02
332 typedef enum _accept_error {
333 AERR_OK = 0,
334 AERR_TIMEOUT,
335 AERR_EOF,
336 AERR_OVERFLOW,
337 AERR_SYNTAX,
338 AERR_NOSPOOL,
339 AERR_NORCPT,
340 AERR_SIZE, /* max msg size exeeded (SMTP SIZE) */
341 AERR_UNKNOWN
342 } accept_error;
344 #define BUF_LEN 1024
345 #define MAX_ADDRESS 256
346 #define MAX_DATALINE 4096
348 typedef enum _smtp_cmd_id {
349 SMTP_HELO = 0,
350 SMTP_EHLO,
351 SMTP_MAIL_FROM,
352 SMTP_RCPT_TO,
353 SMTP_DATA,
354 SMTP_QUIT,
355 SMTP_RSET,
356 SMTP_NOOP,
357 SMTP_HELP,
358 SMTP_NUM_IDS,
359 SMTP_EOF = -1,
360 SMTP_ERROR = -2,
361 } smtp_cmd_id;
363 typedef struct _smtp_cmd {
364 smtp_cmd_id id;
365 gchar *cmd;
366 } smtp_cmd;
368 typedef struct _smtp_connection {
369 gchar *remote_host;
371 prot_id prot;
372 gint next_id;
374 gboolean helo_seen;
375 gboolean from_seen;
376 gboolean rcpt_seen;
378 message *msg;
379 } smtp_connection;
381 /* alias.c*/
382 gboolean addr_is_local(address * addr);
383 GList *alias_expand(GList * alias_table, GList * rcpt_list, GList * non_rcpt_list);
385 /* child.c */
386 int child(const char *command);
388 /* conf.c */
389 void init_conf();
390 gboolean read_conf(gchar * filename);
391 connect_route *read_route(gchar * filename, gboolean is_local_net);
392 GList *read_route_list(GList * rf_list, gboolean is_local_net);
393 void destroy_route(connect_route * r);
394 void destroy_route_list(GList * list);
395 get_conf *read_get_conf(gchar * filename);
396 void destroy_get_conf(get_conf * gc);
397 connect_route *create_local_route();
399 /* expand.c */
400 GList *var_table_rcpt(GList * var_table, address * rcpt);
401 GList *var_table_msg(GList * var_table, message * msg);
402 GList *var_table_conf(GList * var_table);
403 gint expand(GList * var_list, gchar * format, gchar * result, gint result_len);
405 /* message.c */
406 message *create_message(void);
407 void destroy_message(message * msg);
408 void destroy_msg_list(GList * msg_list);
409 void msg_free_data(message * msg);
410 gint msg_calc_size(message * msg, gboolean is_smtp);
412 msg_out *create_msg_out(message * msg);
413 msg_out *clone_msg_out(msg_out * msgout_orig);
414 GList *create_msg_out_list(GList * msg_list);
415 void destroy_msg_out(msg_out * msgout);
416 void destroy_msg_out_list(GList * msgout_list);
418 /* address.c */
419 address *create_address(gchar * path, gboolean is_rfc821);
420 address *create_address_qualified(gchar * path, gboolean is_rfc821, gchar * domain);
421 address *create_address_pipe(gchar * path);
422 void destroy_address(address * addr);
423 address *copy_modify_address(const address * orig, gchar * l_part, gchar * dom);
424 #define copy_address(addr) copy_modify_address(addr, NULL, NULL)
425 gboolean addr_isequal(address * addr1, address * addr2);
426 gboolean addr_isequal_parent(address * addr1, address * addr2);
427 address *addr_find_ancestor(address * addr);
428 gboolean addr_is_delivered_children(address * addr);
429 gboolean addr_is_finished_children(address * addr);
430 gchar *addr_string(address * addr);
431 gint addr_match(address * addr1, address * addr2);
433 /* accept.c */
434 accept_error accept_message(FILE * in, message * msg, guint flags);
435 accept_error accept_message_prepare(message * msg, guint flags);
437 /* header.c */
438 gchar *rec_timestamp();
439 GList *find_header(GList * hdr_list, header_id id, gchar * hdr_str);
440 void header_unfold(header * hdr);
441 void header_fold(header * hdr);
442 header *create_header(header_id id, gchar * fmt, ...);
443 void destroy_header(header * hdr);
444 header *copy_header(header * hdr);
445 header *get_header(gchar * line);
447 /* smtp_in.c */
448 void smtp_in(FILE * in, FILE * out, gchar * remote_host, gchar * ident);
450 /* listen.c */
451 void listen_port(GList * addr_list, gint qival, char *argv[]);
453 /* parse.c */
454 gboolean split_address(const gchar * path, gchar ** local_part, gchar ** domain, gboolean is_rfc821);
455 gboolean parse_address_rfc822(gchar * string, gchar ** local_begin, gchar ** local_end, gchar ** domain_begin, gchar ** domain_end, gchar ** address_end);
456 gboolean parse_address_rfc821(gchar * string, gchar ** local_begin, gchar ** local_end, gchar ** domain_begin, gchar ** domain_end, gchar ** address_end);
457 address *_create_address(gchar * string, gchar ** end, gboolean is_rfc821);
458 address *create_address_rfc821(gchar * string, gchar ** end);
459 address *create_address_rfc822(gchar * string, gchar ** end);
460 GList *addr_list_append_rfc822(GList * addr_list, gchar * string, gchar * domain);
461 gboolean addr_isequal(address * addr1, address * addr2);
463 /* connect.c */
464 mxip_addr *connect_hostlist(int *psockfd, gchar * host, guint port, GList * addr_list);
465 mxip_addr *connect_resolvelist(int *psockfd, gchar * host, guint port, GList * res_funcs);
467 /* deliver.c */
468 void msg_rcptlist_local(GList * rcpt_list, GList **, GList **);
469 gboolean deliver_local(msg_out * msgout);
470 gboolean deliver_msglist_host(connect_route * route, GList * msg_list, gchar * host, GList * res_list);
471 gboolean deliver_route_msgout_list(connect_route * route, GList * msgout_list);
472 gboolean deliver_route_msg_list(connect_route * route, GList * msgout_list);
473 gboolean deliver_finish(msg_out * msgout);
474 gboolean deliver_finish_list(GList * msgout_list);
475 gboolean deliver_msg_list(GList * msg_list, guint flags);
476 gboolean deliver(message * msg);
478 /* fail_msg.c */
479 gboolean fail_msg(message * msg, gchar * template, GList * failed_rcpts, gchar * err_fmt, va_list args);
480 gboolean warn_msg(message * msg, gchar * template, GList * failed_rcpts, gchar * err_fmt, va_list args);
482 /* get.c */
483 gboolean get_from_file(gchar * fname);
484 gboolean get_from_name(gchar * name);
485 gboolean get_all(void);
486 void get_online(void);
487 void get_daemon(gint gival, char *argv[]);
488 gboolean pop_before_smtp(gchar * fname);
490 /* interface.c */
491 gboolean init_sockaddr(struct sockaddr_in *name, interface * iface);
492 int make_server_socket(interface * iface);
494 /* local.c */
495 gboolean append_file(message * msg, GList * hdr_list, gchar * user);
496 gboolean maildir_out(message * msg, GList * hdr_list, gchar * user, guint flags);
497 gboolean pipe_out(message * msg, GList * hdr_list, address * rcpt, gchar * cmd, guint flags);
499 /* log.c */
500 gchar *ext_strerror(int err);
501 gboolean logopen(void);
502 void logclose(void);
503 void vlogwrite(int pri, const char *fmt, va_list args);
504 void logwrite(int pri, const char *fmt, ...);
505 void debugf(const char *fmt, ...);
506 void vdebugf(const char *fmt, va_list args);
507 void maillog(const char *fmt, ...);
509 /* spool.c */
510 gboolean spool_read_data(message * msg);
511 gboolean spool_read_data(message * msg);
512 message *msg_spool_read(gchar * uid, gboolean do_readdata);
513 gboolean spool_write(message * msg, gboolean do_writedata);
514 gboolean spool_lock(gchar * uid);
515 gboolean spool_unlock(gchar * uid);
516 gboolean spool_delete_all(message * msg);
518 /* queue.c */
519 GList *read_queue(gboolean do_readdata);
520 gboolean queue_run(void);
521 gboolean queue_run_online(void);
522 void queue_list(void);
523 gboolean queue_delete(gchar * uid);
525 /* online.c */
526 gchar *detect_online();
527 void set_online_name(gchar * name);
529 /* permissions.c */
530 gboolean is_ingroup(uid_t uid, gid_t gid);
531 void set_euidgid(gint uid, gint gid, uid_t * old_uid, gid_t * old_gid);
532 void set_identity(uid_t old_uid, gchar * task_name);
534 /* rewrite.c */
535 gboolean set_address_header_domain(header * hdr, gchar * domain);
536 gboolean map_address_header(header * hdr, GList * table);
538 /* route.c */
539 msgout_perhost *create_msgout_perhost(gchar * host);
540 void destroy_msgout_perhost(msgout_perhost * mo_ph);
541 void rewrite_headers(msg_out * msgout, connect_route * route);
542 void rcptlist_with_one_of_hostlist(GList * rcpt_list, GList * host_list, GList **, GList **);
543 void rcptlist_with_addr_is_local(GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list);
544 gboolean route_strip_msgout(connect_route * route, msg_out * msgout);
545 msg_out *route_prepare_msgout(connect_route * route, msg_out * msgout);
546 GList *route_msgout_list(connect_route * route, GList * msgout_list);
547 gboolean route_is_allowed_return_path(connect_route * route, address * ret_path);
548 gboolean route_is_allowed_mail_local(connect_route * route, address * ret_path);
549 void msg_rcptlist_route(connect_route * route, GList * rcpt_list, GList ** p_rcpt_list, GList ** p_non_rcpt_list);
551 /* tables.c */
552 table_pair *create_pair(gchar * key, gpointer value);
553 table_pair *create_pair_string(gchar * key, gpointer value);
554 table_pair *parse_table_pair(gchar * line, char delim);
555 gpointer *table_find_func(GList * table_list, gchar * key, int (*cmp_func) (const char *, const char *));
556 gpointer *table_find(GList * table_list, gchar * key);
557 gpointer *table_find_case(GList * table_list, gchar * key);
558 gpointer *table_find_fnmatch(GList * table_list, gchar * key);
559 GList *table_read(gchar * fname, gchar delim);
560 void destroy_table(GList * table);
562 /* timeival.c */
563 gint time_interval(gchar * str, gint * pos);
565 /* permissions.c */
566 gboolean is_privileged_user(uid_t uid);
568 /* other things */
570 #define foreach(list, node)\
571 for((node) = g_list_first(list);\
572 (node);\
573 (node) = g_list_next(node))
575 #ifdef ENABLE_DEBUG
576 #define DEBUG(level) if(level <= conf.debug_level)
577 #else
578 /* hopefully the compiler optmizes this away... */
579 #define DEBUG(level) if(0)
580 #endif
582 #define LOG_VERBOSE 0x100
584 #ifndef HAVE_GETLINE
585 #define getline(buf, size, file) getdelim(buf, size, '\n', file)
586 #endif
588 #ifndef HAVE_FDATASYNC
589 #define fdatasync(fd) fsync(fd)
590 #endif
592 #ifndef CONF_DIR
593 #define CONF_DIR "/etc/masqmail"
594 #endif
596 #define CONF_FILE CONF_DIR"/masqmail.conf"
598 #define PIDFILEDIR "/var/run/masqmail/"
600 #ifndef va_copy
601 #ifdef __va_copy
602 #define va_copy(ap1, ap2) __va_copy(ap1, ap2)
603 #else
604 #define va_copy(ap1, ap2) G_VA_COPY(ap1, ap2)
605 #endif
606 #endif
608 /* *BSD needs this: */
609 extern char **environ;