463 #ifdef STRCASECMP_IN_STRINGS_H
521 #define PIPE_DICT_TABLE "pipe_command"
522 #define PIPE_DICT_NEXTHOP "nexthop"
523 #define PIPE_DICT_RCPT "recipient"
524 #define PIPE_DICT_ORIG_RCPT "original_recipient"
525 #define PIPE_DICT_SENDER "sender"
526 #define PIPE_DICT_USER "user"
527 #define PIPE_DICT_EXTENSION "extension"
528 #define PIPE_DICT_MAILBOX "mailbox"
529 #define PIPE_DICT_DOMAIN "domain"
530 #define PIPE_DICT_SIZE "size"
531 #define PIPE_DICT_CLIENT_ADDR "client_address"
532 #define PIPE_DICT_CLIENT_NAME "client_hostname"
533 #define PIPE_DICT_CLIENT_PORT "client_port"
534 #define PIPE_DICT_CLIENT_PROTO "client_protocol"
535 #define PIPE_DICT_CLIENT_HELO "client_helo"
536 #define PIPE_DICT_SASL_METHOD "sasl_method"
537 #define PIPE_DICT_SASL_USERNAME "sasl_username"
538 #define PIPE_DICT_SASL_SENDER "sasl_sender"
539 #define PIPE_DICT_QUEUE_ID "queue_id"
545 #define PIPE_FLAG_RCPT (1<<0)
546 #define PIPE_FLAG_USER (1<<1)
547 #define PIPE_FLAG_EXTENSION (1<<2)
548 #define PIPE_FLAG_MAILBOX (1<<3)
549 #define PIPE_FLAG_DOMAIN (1<<4)
550 #define PIPE_FLAG_ORIG_RCPT (1<<5)
556 #define PIPE_OPT_FOLD_BASE (16)
557 #define PIPE_OPT_FOLD_USER (FOLD_ADDR_USER << PIPE_OPT_FOLD_BASE)
558 #define PIPE_OPT_FOLD_HOST (FOLD_ADDR_HOST << PIPE_OPT_FOLD_BASE)
559 #define PIPE_OPT_QUOTE_LOCAL (1 << (PIPE_OPT_FOLD_BASE + 2))
560 #define PIPE_OPT_FINAL_DELIVERY (1 << (PIPE_OPT_FOLD_BASE + 3))
562 #define PIPE_OPT_FOLD_ALL (FOLD_ADDR_ALL << PIPE_OPT_FOLD_BASE)
563 #define PIPE_OPT_FOLD_FLAGS(f) \
564 (((f) & PIPE_OPT_FOLD_ALL) >> PIPE_OPT_FOLD_BASE)
615 #define STR vstring_str
619 static int parse_callback(
int type,
VSTRING *buf,
void *context)
626 static struct cmd_flags cmd_flags[] = {
653 for (p = cmd_flags; ; p++) {
655 msg_warn(
"file %s/%s: service %s: unknown macro name: \"%s\"",
659 }
else if (strcmp(
vstring_str(buf), p->name) == 0) {
670 static void morph_recipient(
VSTRING *buf,
const char *address,
int flags)
692 static ARGV *expand_argv(
const char *service,
char **argv,
717 #define EARLY_RETURN(x) { argv_free(result); vstring_free(buf); return (x); }
720 for (cpp = argv; *cpp; cpp++) {
728 for (i = 0; i < rcpt_list->
len; i++) {
734 morph_recipient(buf, rcpt_list->
info[i].
address, flags);
762 msg_warn(
"no @ in recipient address: %s",
780 msg_warn(
"no @ in recipient address: %s",
796 msg_warn(
"no @ in recipient address: %s",
810 msg_warn(
"no @ in recipient address: %s",
831 static void get_service_params(
PIPE_PARAMS *config,
char *service)
833 const char *myname =
"get_service_params";
850 static void get_service_attr(
PIPE_ATTR *attr,
char **argv)
852 const char *myname =
"get_service_attr";
876 for ( ; *argv != 0; argv++) {
881 if (
strncasecmp(
"flags=", *argv,
sizeof(
"flags=") - 1) == 0) {
882 for (cp = *argv +
sizeof(
"flags=") - 1; *cp; cp++) {
918 msg_fatal(
"unknown flag: %c (ignored)", *cp);
927 else if (
strncasecmp(
"user=", *argv,
sizeof(
"user=") - 1) == 0) {
928 user = *argv +
sizeof(
"user=") - 1;
929 if ((group =
split_at(user,
':')) != 0)
932 if ((pwd = getpwnam(user)) == 0)
933 msg_fatal(
"%s: unknown username: %s", myname, user);
934 attr->
uid = pwd->pw_uid;
936 if ((grp = getgrnam(group)) == 0)
937 msg_fatal(
"%s: unknown group: %s", myname, group);
938 attr->
gid = grp->gr_gid;
940 attr->
gid = pwd->pw_gid;
947 else if (
strncasecmp(
"directory=", *argv,
sizeof(
"directory=") - 1) == 0) {
954 else if (
strncasecmp(
"chroot=", *argv,
sizeof(
"chroot=") - 1) == 0) {
961 else if (
strncasecmp(
"eol=", *argv,
sizeof(
"eol=") - 1) == 0) {
968 else if (
strncasecmp(
"null_sender=", *argv,
sizeof(
"null_sender=") - 1) == 0) {
975 else if (
strncasecmp(
"size=", *argv,
sizeof(
"size=") - 1) == 0) {
976 size = *argv +
sizeof(
"size=") - 1;
978 msg_fatal(
"%s: bad size= value: %s", myname, size);
984 else if (
strncasecmp(
"argv=", *argv,
sizeof(
"argv=") - 1) == 0) {
985 *argv +=
sizeof(
"argv=") - 1;
994 msg_fatal(
"unknown attribute name: %s", *argv);
1001 msg_fatal(
"missing user= command-line attribute");
1003 msg_fatal(
"missing argv= command-line attribute");
1005 msg_fatal(
"user= command-line attribute specifies root privileges");
1007 msg_fatal(
"user= command-line attribute specifies mail system owner %s",
1010 msg_fatal(
"user= command-line attribute specifies privileged group id 0");
1012 msg_fatal(
"user= command-line attribute specifies mail system owner %s group id %ld",
1015 msg_fatal(
"user= command-line attribute specifies mail system %s group id %ld",
1022 msg_info(
"%s: uid %ld, gid %ld, flags %d, size %ld",
1023 myname, (
long) attr->
uid, (
long) attr->
gid,
1029 static int eval_command_status(
int command_status,
char *service,
1043 switch (command_status) {
1058 "delivered via %s service%s", service, saved_text);
1065 service, &why->
dsn);
1082 service, &why->
dsn);
1093 msg_panic(
"eval_command_status: bad status %d", command_status);
1102 static int deliver_message(
DELIVER_REQUEST *request,
char *service,
char **argv)
1104 const char *myname =
"deliver_message";
1110 ARGV *expanded_argv = 0;
1116 #define DELIVER_MSG_CLEANUP() { \
1118 if (expanded_argv) argv_free(expanded_argv); \
1132 if (rcpt_list->
len <= 0)
1135 get_service_params(&conf, service);
1136 get_service_attr(&attr, argv);
1143 dsb_simple(why,
"4.3.5",
"mail system configuration error");
1145 request, &attr, why);
1146 msg_warn(
"pipe flag `D' requires %s_destination_recipient_limit = 1",
1149 return (deliver_status);
1156 dsb_simple(why,
"4.3.5",
"mail system configuration error");
1158 request, &attr, why);
1159 msg_warn(
"pipe flag `O' requires %s_destination_recipient_limit = 1",
1162 return (deliver_status);
1170 msg_info(
"%s: too big: size_limit = %ld, request->data_size = %ld",
1172 dsb_simple(why,
"5.2.3",
"message too large");
1174 request, &attr, why);
1176 return (deliver_status);
1194 rcpt, service, &why->
dsn);
1197 deliver_status |= status;
1200 return (deliver_status);
1213 msg_panic(
"%s: delivered-to enabled with multi-recipient request",
1221 dsb_simple(why,
"5.4.6",
"mail forwarding loop for %s",
1224 request, &attr, why);
1226 return (deliver_status);
1244 if (*sender && (attr.
flags & PIPE_OPT_QUOTE_LOCAL)) {
1276 if ((expanded_argv = expand_argv(service, attr.
command,
1277 rcpt_list, attr.
flags)) == 0) {
1278 dsb_simple(why,
"4.3.5",
"mail system configuration error");
1280 request, &attr, why);
1282 return (deliver_status);
1302 deliver_status = eval_command_status(command_status, service, request,
1310 return (deliver_status);
1315 static void pipe_service(
VSTREAM *client_stream,
char *service,
char **argv)
1329 status = deliver_message(request, service, argv);
1336 static void pre_accept(
char *unused_name,
char **unused_argv)
1341 msg_info(
"table %s has changed -- restarting", table);
1348 static void drop_privileges(
char *unused_name,
char **unused_argv)
1355 static void pre_init(
char *unused_name,
char **unused_argv)
#define PIPE_OPT_FOLD_FLAGS(f)
#define CA_PIPE_CMD_DELIVERED(v)
#define CA_PIPE_CMD_CWD(v)
DSN_BUF * dsb_create(void)
char * mystrdup(const char *str)
#define PIPE_FLAG_EXTENSION
#define PIPE_DICT_EXTENSION
#define PIPE_DICT_ORIG_RCPT
ARGV * argv_free(ARGV *argvp)
NORETURN msg_panic(const char *fmt,...)
#define CA_MAIL_SERVER_STR_TABLE(v)
DSN_BUF * dsb_update(DSN_BUF *dsb, const char *status, const char *action, const char *mtype, const char *mname, const char *dtype, const char *dtext, const char *format,...)
#define DEL_REQ_FLAG_SUCCESS
void deliver_completed(VSTREAM *stream, long offset)
int delivered_hdr_find(DELIVERED_HDR_INFO *info, const char *address)
off_t off_cvt_string(const char *str)
#define PIPE_FLAG_ORIG_RCPT
#define MAIL_COPY_RETURN_PATH
#define DEL_REQ_TRACE_ONLY(f)
VSTRING * vstring_truncate(VSTRING *vp, ssize_t len)
void argv_add(ARGV *argvp,...)
char * var_pipe_dsn_filter
#define PIPE_DICT_CLIENT_NAME
#define DEF_PIPE_DSN_FILTER
#define CA_PIPE_CMD_UID(v)
MAIL_VERSION_STAMP_DECLARE
ARGV * argv_alloc(ssize_t len)
#define CA_MAIL_SERVER_BOUNCE_INIT(v, w)
#define CA_PIPE_CMD_COPY_FLAGS(v)
#define PIPE_STAT_CORRUPT
int strncasecmp(const char *s1, const char *s2, size_t n)
#define DEL_REQ_TRACE_FLAGS(f)
VSTRING * vstring_strcpy(VSTRING *vp, const char *src)
#define VAR_PIPE_DSN_FILTER
#define casefold(dst, src)
int bounce_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn)
#define VSTRING_TERMINATE(vp)
#define VAR_EXPORT_ENVIRON
#define CA_MAIL_SERVER_POST_INIT(v)
int pipe_command(VSTREAM *src, DSN_BUF *why,...)
ARGV * mail_parm_split(const char *name, const char *value)
#define PIPE_DICT_CLIENT_PROTO
#define DSN_FROM_DSN_BUF(dsb)
const char * dict_changed_name(void)
#define CA_PIPE_CMD_EOL(v)
char * fold_addr(VSTRING *result, const char *addr, int flags)
#define DEF_COMMAND_MAXTIME
#define CA_PIPE_CMD_GID(v)
#define MAIL_ADDR_MAIL_DAEMON
int get_mail_conf_time2(const char *, const char *, int, int, int, int)
void msg_warn(const char *fmt,...)
VSTRING * vstring_alloc(ssize_t len)
#define DELIVER_MSG_CLEANUP()
#define CA_PIPE_CMD_TIME_LIMIT(v)
#define VAR_COMMAND_MAXTIME
#define MAIL_VERSION_STAMP_ALLOCATE
#define PIPE_DICT_QUEUE_ID
#define PIPE_DICT_SASL_SENDER
VSTRING * vstring_sprintf(VSTRING *vp, const char *format,...)
#define PIPE_DICT_MAILBOX
#define CA_MAIL_SERVER_TIME_TABLE(v)
int main(int argc, char **argv)
DSN_BUF * dsb_simple(DSN_BUF *dsb, const char *status, const char *format,...)
#define MAIL_COPY_DELIVERED
#define PIPE_DICT_SASL_METHOD
char * trimblanks(char *, ssize_t)
DELIVERED_HDR_INFO * delivered_hdr_init(VSTREAM *fp, off_t offset, int flags)
NORETURN msg_fatal(const char *fmt,...)
off_t vstream_fseek(VSTREAM *stream, off_t offset, int whence)
int dict_update(const char *dict_name, const char *member, const char *value)
#define CA_MAIL_SERVER_PRIVILEGED
int mac_parse(const char *value, MAC_PARSE_FN action, void *context)
void set_eugid(uid_t euid, gid_t egid)
int deliver_request_done(VSTREAM *stream, DELIVER_REQUEST *request, int status)
#define PIPE_DICT_NEXTHOP
#define PIPE_DICT_CLIENT_ADDR
#define CA_PIPE_CMD_ORIG_RCPT(v)
#define CA_PIPE_CMD_CHROOT(v)
const char * dict_eval(const char *dict_name, const char *value, int recursive)
#define quote_822_local(dst, src)
#define CA_PIPE_CMD_SENDER(v)
#define CA_PIPE_CMD_ARGV(v)
#define PIPE_OPT_FOLD_USER
VSTRING * vstring_free(VSTRING *vp)
#define PIPE_FLAG_MAILBOX
NORETURN single_server_main(int, char **, SINGLE_SERVER_FN,...)
char * split_at(char *string, int delimiter)
#define MAC_PARSE_VARNAME
char * var_export_environ
int defer_append(int flags, const char *id, MSG_STATS *stats, RECIPIENT *rcpt, const char *relay, DSN *dsn)
#define PIPE_DICT_CLIENT_PORT
#define PIPE_DICT_SASL_USERNAME
#define MAIL_COPY_ORIG_RCPT
#define PIPE_DICT_CLIENT_HELO
#define CA_MAIL_SERVER_PRE_ACCEPT(v)
int sent(int flags, const char *id, MSG_STATS *stats, RECIPIENT *recipient, const char *relay, DSN *dsn)
DELIVER_REQUEST * deliver_request_read(VSTREAM *stream)
#define CA_PIPE_CMD_EXPORT(v)
#define PIPE_OPT_FOLD_HOST
char * split_at_right(char *string, int delimiter)
#define PIPE_OPT_QUOTE_LOCAL
#define PIPE_OPT_FOLD_ALL
char * vstring_export(VSTRING *vp)
#define PIPE_OPT_FINAL_DELIVERY
void delivered_hdr_free(DELIVERED_HDR_INFO *info)
#define CA_MAIL_SERVER_PRE_INIT(v)
void argv_terminate(ARGV *argvp)
VSTRING * unescape(VSTRING *, const char *)
void msg_info(const char *fmt,...)