/* This file is part of Mailfromd. Copyright (C) 2005-2020 Sergey Poznyakoff This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ #include #include #include #include #include #include #include #include #include #include #include #include #include "dns.h" #define _(String) gettext(String) #define N_(String) String #if defined HAVE_SYSCONF && defined _SC_OPEN_MAX # define getmaxfd() sysconf(_SC_OPEN_MAX) #elif defined (HAVE_GETDTABLESIZE) # define getmaxfd() getdtablesize() #else # define getmaxfd() 256 #endif /* The following defines are borrowed from intprops.h (gnulib) */ /* True if the arithmetic type T is signed. */ #define TYPE_SIGNED(t) (! ((t) 0 < (t) -1)) /* Return zero if T can be determined to be an unsigned type. Otherwise, return 1. When compiling with GCC, INT_STRLEN_BOUND uses this macro to obtain a tighter bound. Otherwise, it overestimates the true bound by one byte when applied to unsigned types of size 2, 4, 16, ... bytes. The symbol signed_type_or_expr__ is private to this header file. */ #if __GNUC__ >= 2 # define signed_type_or_expr__(t) TYPE_SIGNED (__typeof__ (t)) #else # define signed_type_or_expr__(t) 1 #endif /* Bound on length of the string representing an integer type or expression T. Subtract 1 for the sign bit if T is signed; log10 (2.0) < 146/485; add 1 for integer division truncation; add 1 more for a minus sign if needed. */ #define INT_STRLEN_BOUND(t) \ ((sizeof (t) * CHAR_BIT - signed_type_or_expr__ (t)) * 146 / 485 \ + signed_type_or_expr__ (t) + 1) /* Bound on buffer size needed to represent an integer type or expression T, including the terminating null. */ #define INT_BUFSIZE_BOUND(t) (INT_STRLEN_BOUND (t) + 1) /* Size of the buffer able to accomodate mailfromd numeric type */ #define NUMERIC_BUFSIZE_BOUND INT_BUFSIZE_BOUND(long) /* Status values used throughout the program */ typedef enum mf_status_code { mf_success, mf_not_found, mf_failure, mf_temp_failure, mf_timeout, #define mf_status_count (mf_smtp_temp_failure+1) } mf_status; #define mf_resolved(c) ((c) == mf_success || (c) == mf_not_found) const char *mf_status_str(mf_status s); enum smtp_timeout { smtp_timeout_connect, smtp_timeout_initial, smtp_timeout_helo, smtp_timeout_mail, smtp_timeout_rcpt, smtp_timeout_rset, smtp_timeout_quit }; #define SMTP_NUM_TIMEOUT (smtp_timeout_quit+1) #define MF_GETOPT_DEFAULT 0x00 /* Process options in order; don't permute */ #define MF_GETOPT_IN_ORDER 0x01 /* Don't parse configuration files */ #define MF_GETOPT_NO_CONFIG 0x02 void mf_getopt(struct mu_cli_setup *cli, int *pargc, char ***pargv, char **capa, int flags); void mailfromd_version(struct mu_parseopt *po, mu_stream_t stream); int mf_vercmp(const char *a, const char *b, int *pres); void mf_init_nls (void); int parse_time_interval(const char *str, time_t *pint, const char **endp); void dict_init(mu_assoc_t *dict); char *dict_install(mu_assoc_t dict, const char *name, const char *value); void dict_destroy(mu_assoc_t *dict); char *dict_getsym(void *data, const char *str); struct mf_privs { char *user; int allgroups; mu_list_t groups; }; struct mf_gid_list; struct mf_gid_list *mf_gid_list_alloc(void); void mf_gid_list_free(struct mf_gid_list *gl); struct mf_gid_list *mf_gid_list_dup(struct mf_gid_list *src); void mf_gid_list_add(struct mf_gid_list *gl, gid_t gid); void mf_gid_list_array(struct mf_gid_list *gl, size_t *gc, gid_t **gv); int switch_to_privs (uid_t uid, gid_t gid, struct mf_gid_list *); void get_user_groups (struct mf_gid_list *grouplist, const char *user); void mf_priv_setup (struct mf_privs *); void mf_epriv_setup (struct mf_privs *); char **config_array_to_argv (mu_config_value_t *val); char *config_array_to_string (mu_config_value_t *val); int config_cb_timeout (struct timeval *pt, mu_config_value_t *val); int config_cb_time_t(void *data, mu_config_value_t *arg); int config_cb_ignore(void *data, mu_config_value_t *val); int config_cb_lock_retry_count(void *data, mu_config_value_t *val); int config_cb_lock_retry_timeout(void *data, mu_config_value_t *val); void mf_proctitle_init (int argc, char *argv[], char *env[]); void mf_proctitle_format (const char *fmt, ...); int stderr_closed_p(void); int mf_list_compare_string(const void *item, const void *value); struct symtab; struct syment { char *name; unsigned refcnt; }; typedef int (*symtab_enumerator_t)(void *sym, void *data); #define SYMTAB_COPY_KEY 0x1 #define SYMTAB_ICASE 0x2 const char * symtab_strerror(int rc); int symtab_lookup_or_install(struct syment **ent, struct symtab *st, const char *name, int *install); int symtab_lookup_or_install_entry(struct syment **elp, struct symtab *st, struct syment *ent, int *install); void symtab_clear(struct symtab *st); struct symtab *symtab_create(size_t elsize, int flags, void *(*alloc_fun)(size_t), void (*free_fun)(void *)); void symtab_destroy(struct symtab **pst); int symtab_remove(struct symtab *st, const char *name); int symtab_replace(struct symtab *st, struct syment *ent, struct syment **old_ent); int symtab_enumerate(struct symtab *st, symtab_enumerator_t fun, void *data); typedef int (*symtab_selfun)(const struct syment *ent, void *closure); typedef int (*symtab_errfun)(int rc, struct symtab *tab, const char *name, void *closure); typedef int (*symtab_confun)(struct symtab *dst, struct syment *dstent, struct syment *srcent, void *closure); typedef int (*symtab_cpyfun)(struct syment **pdst, struct syment *src, size_t len, void *closure); int symtab_import(struct symtab *dst, struct symtab *src, symtab_selfun selfun, symtab_errfun errfun, symtab_confun confun, symtab_cpyfun cpyfun, void *closure); size_t symtab_count_entries(struct symtab *st); typedef struct transform *transform_t; typedef int (*transform_append_t)(void *, const char *s, size_t len); typedef char *(*transform_reduce_t)(void *); const char *transform_error_string (void); transform_t transform_compile(const char *expr, int cflags); void transform_free(transform_t); char *transform_string (transform_t tf, const char *input, void *slist, transform_append_t append, transform_reduce_t reduce); void close_fds_above(int fd); void close_fds_except(fd_set *exfd); /* logger.c */ #ifdef DEFAULT_SYSLOG_ASYNC # define DEFAULT_LOG_STREAM "syslog:async" #else # define DEFAULT_LOG_STREAM "syslog" #endif #define LOGF_STDERR 0x01 /* Logger uses stderr */ struct logger { char *name; int flags; void (*log_open)(void); void (*log_close)(void); void (*log_fdset)(fd_set *set); void (*log_text)(int, const char *); }; int logger_flags(int mask); int logger_select(const char *name); void logger_open(void); void logger_close(void); void logger_fdset(fd_set *set); void logger_text(int prio, const char *text); #define vlogmsg mu_diag_voutput #define logmsg mu_diag_output /* strmwait.c */ struct timeout_ctl { time_t start; time_t timeout; }; #define UPDATE_TTW(t) do { \ time_t now = time(NULL); \ time_t delta = now - (t).start; \ if ((t).timeout > delta) \ (t).timeout -= delta; \ else \ (t).timeout = 0; \ (t).start = now; \ } while (0) void init_timeout_ctl(struct timeout_ctl *tctl, time_t timeout); int mf_stream_wait(mu_stream_t stream, int flags, struct timeout_ctl *tctl); /* ftimestr.c */ extern char *time_format_string; size_t format_time_str(FILE *fp, time_t timestamp); /* dns.c */ void dnsbase_init(void); mf_status dns_to_mf_status(dns_status stat); dns_status mf_to_dns_status(mf_status stat); mf_status resolve_ipstr_domain(const char *ipstr, const char *domain, char **phbuf); mf_status resolve_ipstr(const char *ipstr, char **phbuf); mf_status resolve_hostname(const char *host, char **pipbuf); /* server.c */ #define MF_SERVER_FOREGROUND 0x01 #define MF_SERVER_NORESTART 0x02 extern void mf_server_log_setup(void); extern mode_t mf_server_umask; extern char *mf_server_user; extern struct mf_gid_list *mf_server_retain_groups; extern char *mf_server_lint_option; void mf_server_check_pidfile(const char *name); void mf_server_save_cmdline(int argc, char **argv); void mf_server_start(const char *program, const char *dir, const char *pidfile, int flags); /* namefixup.c */ void mf_namefixup_register(char **ptr, const char *initval); void mf_file_name_ptr_fixup(char **ptr, char *dir, size_t dirlen); void mf_namefixup_run(char *dir); void mf_namefixup_free(void);