From: Wietse Venema Date: Mon, 29 Oct 2001 05:00:00 +0000 (-0500) Subject: snapshot-20011029 X-Git-Tag: v1.1.0~38 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=6561eb3f82a2f7285a04ec6a67629d60907b27f2;p=thirdparty%2Fpostfix.git snapshot-20011029 --- diff --git a/postfix/HISTORY b/postfix/HISTORY index a9b3636bf..fffd1d750 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -5487,6 +5487,12 @@ Apologies for any names omitted. Bugfix: there was a minute memory leak when an smtpd access restriction is misconfigured. File: smtpd/smtpd_check.c. +20011010 + + Specify the name of the UNIX-domain socket (instead of + "unknown stream") when a Postfix daemon complains about a + malformed client request. Files: master/*server.c. + 20011010-14 Replaced the internal protocols by (name,value) attribute @@ -5502,10 +5508,29 @@ Apologies for any names omitted. is sent to the originator. Files: cleanup/cleanup.c, cleanup/cleanup_message.c, conf/sample-filter.cf. +20011016 + + Bugfix: As of 20000625, Errors-To: was broken, because the + code to extract the address was not moved from recipient + address rewriting to sender address rewriting. Problem + reported by Roelof Osinga @ nisser.com. File: + cleanup/cleanup_message.c. + +20011029 + + Bugfix: virtual map expansion terminated early because the + detection of self-referential entries was flawed. File: + cleanup/cleanup_map1n.c. + Open problems: Minor: The $process_id_directory setting is not used anywhere in Postfix. Problem reported by Michael Smith, texas.net. + This should either be documented, or better, the code should + issue a warning to set a read-only parameter. Medium: address rewriting should be on/off configurable for envelopes and/or headers. + + Medium: smtpd access maps doesn't understand the recipient + delimiter setting. diff --git a/postfix/conf/main.cf b/postfix/conf/main.cf index 752db3c00..43220c108 100644 --- a/postfix/conf/main.cf +++ b/postfix/conf/main.cf @@ -214,8 +214,6 @@ mail_owner = postfix # # In the case of SMTP, specify a domain, host, host:port, [host]:port, # [address] or [address]:port; the form [host] turns off MX lookups. -# If you specify multiple SMTP destinations, Postfix will try them -# in the specified order. # # If you're connected via UUCP, see also the default_transport parameter. # diff --git a/postfix/conf/sample-misc.cf b/postfix/conf/sample-misc.cf index e1d23a60f..4b2d7d502 100644 --- a/postfix/conf/sample-misc.cf +++ b/postfix/conf/sample-misc.cf @@ -329,8 +329,6 @@ recipient_delimiter = # # In the case of SMTP, specify a domain, host, host:port, [host]:port, # [address] or [address]:port; the form [host] turns off MX lookups. -# If you specify multiple SMTP destinations, Postfix will try them -# in the specified order. # # If you're connected via UUCP, see also the default_transport parameter. # diff --git a/postfix/conf/sample-smtpd.cf b/postfix/conf/sample-smtpd.cf index 081bcb8b0..0a8ba1f84 100644 --- a/postfix/conf/sample-smtpd.cf +++ b/postfix/conf/sample-smtpd.cf @@ -40,7 +40,7 @@ smtpd_banner = $myhostname ESMTP $mail_name # maptype:mapname: look up client name, parent domains, client address, # or networks obtained by stripping octets. # Reject if result is REJECT or "[45]xx text" -# Permit otherwise. +# Permit result is OK or all numerical. # reject_maps_rbl: reject if the reverse client network address # is listed under $maps_rbl_domains. # reject: reject the request. Place this at the end of a restriction. @@ -154,7 +154,7 @@ mynetworks_style = subnet # maptype:mapname: look up client name, parent domains, client address, # or networks obtained by stripping octets. # Reject if result is REJECT or "[45]xx text" -# Permit otherwise. +# Permit result is OK or all numerical. # reject_maps_rbl: reject if the client is listed under $maps_rbl_domains. # reject: reject the request. Place this at the end of a restriction. # permit: permit the request. Place this at the end of a restriction. @@ -191,7 +191,7 @@ smtpd_helo_required = no # check_helo_access maptype:mapname # maptype:mapname: look up HELO hostname or parent domains. # Reject if result is REJECT or "[45]xx text" -# Permit otherwise. +# Permit result is OK or all numerical. # check_client_access maptype:mapname: see smtpd_client_restrictions. # reject: reject the request. Place this at the end of a restriction. # permit: permit the request. Place this at the end of a restriction. @@ -221,7 +221,7 @@ smtpd_helo_restrictions = # check_sender_access maptype:mapname # maptype:mapname: look up sender address, parent domain, or localpart@. # Reject if result is REJECT or "[45]xx text" -# Permit otherwise. +# Permit result is OK or all numerical. # check_client_access maptype:mapname: see smtpd_client_restrictions. # check_helo_access maptype:mapname: see smtpd_helo_restrictions. # reject_non_fqdn_hostname: reject HELO hostname that is not in FQDN form @@ -289,7 +289,7 @@ smtpd_sender_restrictions = # check_recipient_access maptype:mapname # maptype:mapname: look up recipient address, parent domain, or localpart@. # Reject if result is REJECT or "[45]xx text" -# Permit otherwise. +# Permit result is OK or all numerical. # check_client_access maptype:mapname: see smtpd_client_restrictions. # check_helo_access maptype:mapname: see smtpd_helo_restrictions. # check_sender_access maptype:mapname: see smtpd_sender_restrictions. diff --git a/postfix/errors_to b/postfix/errors_to new file mode 100644 index 000000000..e69de29bb diff --git a/postfix/html/faq.html b/postfix/html/faq.html index 394cb330b..9ce25228b 100644 --- a/postfix/html/faq.html +++ b/postfix/html/faq.html @@ -1225,7 +1225,7 @@ commands as root: In order to run hundreds of processes you may have to adjust the per-process open file limit. According to the Solaris +href="http://www.science.uva.nl/pub/solaris/solaris2.html#q3.45">Solaris FAQ, add the following lines to /etc/system on Solaris 2.4 and later:

diff --git a/postfix/html/local.8.html b/postfix/html/local.8.html index c028f65cf..08274fbdf 100644 --- a/postfix/html/local.8.html +++ b/postfix/html/local.8.html @@ -328,6 +328,11 @@ LOCAL(8) LOCAL(8) (exception: root). The string is subject to $name expansions. + mailbox_command_maps + Lookup tables with per-recipient external commands + to use for mailbox delivery. Behavior is as with + mailbox_command. + mailbox_transport Message transport to use for mailbox delivery to all local recipients, whether or not they are found diff --git a/postfix/html/qmqpd.8.html b/postfix/html/qmqpd.8.html index 5d5792ef3..7bed7101b 100644 --- a/postfix/html/qmqpd.8.html +++ b/postfix/html/qmqpd.8.html @@ -102,7 +102,7 @@ QMQPD(8) QMQPD(8) of a problem. This slows down run-away errors. SEE ALSO - http://cr.yp.to/proto/qmqp.html, QMQP protocol + http://cr.yp.to/proto/qmqp.html, QMQP protocol cleanup(8) message canonicalization master(8) process manager syslogd(8) system logging diff --git a/postfix/html/sendmail.1.html b/postfix/html/sendmail.1.html index 6261883ad..282a7bd3e 100644 --- a/postfix/html/sendmail.1.html +++ b/postfix/html/sendmail.1.html @@ -181,12 +181,10 @@ SENDMAIL(1) SENDMAIL(1) -qRsite Schedule immediate delivery of all mail that is - queued for the named site. Depending on the desti- - nation, this uses "fast flush" service, or it has - the same effect as sendmail -q. This is imple- - mented by connecting to the local SMTP server. See - smtpd(8) for more information about the "fast - flush" service. + queued for the named site. This uses "fast flush" + service, and is implemented by connecting to the + local SMTP server at $myhostname. See smtpd(8) for + more information about the "fast flush" service. -qSsite This command is not implemented. Use the slower diff --git a/postfix/man/man1/sendmail.1 b/postfix/man/man1/sendmail.1 index faaa064b4..7db99fb6d 100644 --- a/postfix/man/man1/sendmail.1 +++ b/postfix/man/man1/sendmail.1 @@ -154,9 +154,8 @@ The interval between queue runs. Use the \fBqueue_run_delay\fR configuration parameter instead. .IP \fB-qR\fIsite\fR Schedule immediate delivery of all mail that is queued for the named -\fIsite\fR. Depending on the destination, this uses "fast flush" -service, or it has the same effect as \fBsendmail -q\fR. -This is implemented by connecting to the local SMTP server. +\fIsite\fR. This uses "fast flush" service, and is implemented +by connecting to the local SMTP server at \fB$myhostname\fR. See \fBsmtpd\fR(8) for more information about the "fast flush" service. .IP \fB-qS\fIsite\fR diff --git a/postfix/man/man8/local.8 b/postfix/man/man8/local.8 index c0929a6ac..f0eb862f9 100644 --- a/postfix/man/man8/local.8 +++ b/postfix/man/man8/local.8 @@ -335,6 +335,9 @@ dependent. External command to use for mailbox delivery. The command executes with the recipient privileges (exception: root). The string is subject to $name expansions. +.IP \fBmailbox_command_maps\fR +Lookup tables with per-recipient external commands to use for mailbox +delivery. Behavior is as with \fBmailbox_command\fR. .IP \fBmailbox_transport\fR Message transport to use for mailbox delivery to all local recipients, whether or not they are found in the UNIX passwd database. diff --git a/postfix/src/bounce/Makefile.in b/postfix/src/bounce/Makefile.in index d77256556..e3769be84 100644 --- a/postfix/src/bounce/Makefile.in +++ b/postfix/src/bounce/Makefile.in @@ -65,6 +65,8 @@ bounce.o: ../../include/vstream.h bounce.o: ../../include/stringops.h bounce.o: ../../include/mail_proto.h bounce.o: ../../include/iostuff.h +bounce.o: ../../include/attr.h +bounce.o: ../../include/htable.h bounce.o: ../../include/mail_queue.h bounce.o: ../../include/mail_params.h bounce.o: ../../include/mail_conf.h diff --git a/postfix/src/cleanup/Makefile.in b/postfix/src/cleanup/Makefile.in index 3ed1de67b..46cb770ca 100644 --- a/postfix/src/cleanup/Makefile.in +++ b/postfix/src/cleanup/Makefile.in @@ -72,6 +72,8 @@ cleanup.o: ../../include/mail_conf.h cleanup.o: ../../include/cleanup_user.h cleanup.o: ../../include/mail_proto.h cleanup.o: ../../include/iostuff.h +cleanup.o: ../../include/attr.h +cleanup.o: ../../include/htable.h cleanup.o: ../../include/mail_params.h cleanup.o: ../../include/record.h cleanup.o: ../../include/rec_type.h @@ -93,6 +95,8 @@ cleanup_api.o: ../../include/mail_queue.h cleanup_api.o: ../../include/vstream.h cleanup_api.o: ../../include/mail_proto.h cleanup_api.o: ../../include/iostuff.h +cleanup_api.o: ../../include/attr.h +cleanup_api.o: ../../include/htable.h cleanup_api.o: ../../include/bounce.h cleanup_api.o: ../../include/mail_params.h cleanup_api.o: ../../include/mail_stream.h diff --git a/postfix/src/cleanup/cleanup.c b/postfix/src/cleanup/cleanup.c index cd8091898..594f2bbdf 100644 --- a/postfix/src/cleanup/cleanup.c +++ b/postfix/src/cleanup/cleanup.c @@ -235,8 +235,8 @@ static void cleanup_service(VSTREAM *src, char *unused_service, char **argv) */ attr_print(src, ATTR_FLAG_NONE, ATTR_TYPE_NUM, MAIL_ATTR_STATUS, cleanup_close(state), - ATTR_TYPE_STR, MAIL_ATTR_WHY, state->why_rejected ? - vstring_str(state->why_rejected) : "", + ATTR_TYPE_STR, MAIL_ATTR_WHY, state->reason ? + state->reason : "", ATTR_TYPE_END); cleanup_free(state); diff --git a/postfix/src/cleanup/cleanup.h b/postfix/src/cleanup/cleanup.h index 5e2f38548..955a014ef 100644 --- a/postfix/src/cleanup/cleanup.h +++ b/postfix/src/cleanup/cleanup.h @@ -59,7 +59,7 @@ typedef struct CLEANUP_STATE { off_t xtra_offset; /* start of extra segment */ int end_seen; /* REC_TYPE_END seen */ int rcpt_count; /* recipient count */ - VSTRING *why_rejected; /* REJECT reason */ + char *reason; /* failure reason */ } CLEANUP_STATE; /* diff --git a/postfix/src/cleanup/cleanup_api.c b/postfix/src/cleanup/cleanup_api.c index 37239fbbf..4728be595 100644 --- a/postfix/src/cleanup/cleanup_api.c +++ b/postfix/src/cleanup/cleanup_api.c @@ -31,14 +31,23 @@ /* cleanup_open() creates a new queue file and performs other /* per-message initialization. The result is a handle that should be /* given to the cleanup_control(), cleanup_record(), cleanup_close() -/* and cleanup_close() -/* routines. The name of the queue file is in the queue_id result -/* structure member. +/* and cleanup_free() routines. The name of the queue file is in the +/* queue_id result structure member. /* /* cleanup_control() processes per-message flags specified by the caller. /* These flags control the handling of data errors, and must be set /* before processing the first message record. -/* +/* .IP CLEANUP_FLAG_BOUNCE +/* The cleanup server is responsible for returning undeliverable +/* mail (too many hops, message too large) to the sender. +/* .IP CLEANUP_FLAG_FILTER +/* Enable header/body filtering. This should be enabled only with mail +/* that enters Postfix, not with locally forwarded mail or with bounce +/* messages. +/* .IP CLEANUP_FLAG_EXTRACT +/* Extract recipients from message headers when no recipients are +/* provided in the message envelope records. +/* .PP /* CLEANUP_RECORD() is a macro that processes one message record, /* that copies the result to the queue file, and that maintains a /* little state machine. The last record in a valid message has type @@ -49,8 +58,9 @@ /* /* cleanup_close() closes a queue file. In case of any errors, /* the file is removed. The result value is non-zero in case of -/* problems. Use cleanup_strerror() to translate the result into -/* human_readable text. +/* problems. In some cases a human-readable text can be found in +/* the state->reason member. In all other cases, use cleanup_strerror() +/* to translate the result into human-readable text. /* /* cleanup_free() destroys its argument. /* DIAGNOSTICS @@ -154,10 +164,9 @@ void cleanup_control(CLEANUP_STATE *state, int flags) * definition. */ if ((state->flags = flags) & CLEANUP_FLAG_BOUNCE) { - state->err_mask = - (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE); + state->err_mask = CLEANUP_STAT_MASK_INCOMPLETE; } else { - state->err_mask = CLEANUP_STAT_LETHAL; + state->err_mask = ~CLEANUP_STAT_MASK_EXTRACT_RCPT; } } @@ -167,13 +176,16 @@ int cleanup_close(CLEANUP_STATE *state) { char *junk; int status; - const char *reason; /* - * See if there are any errors. For example, the message is incomplete, - * or it needs to be bounced for lack of recipients. We want to turn on - * the execute bits on a file only when we really want the queue manager - * to process it. + * Ignore recipient extraction alarms if (a) we did (not need to) extract + * recipients, or (b) we did not examine all queue file records. + */ + if (state->recip != 0 || CLEANUP_OUT_OK(state) == 0) + state->errs &= ~CLEANUP_STAT_MASK_EXTRACT_RCPT; + + /* + * Raise these errors only if we examined all queue file records. */ if (CLEANUP_OUT_OK(state)) { if (state->recip == 0) @@ -187,10 +199,11 @@ int cleanup_close(CLEANUP_STATE *state) * because we are about to tell the sender that it can throw away its * copy of the message. */ - if ((state->errs & CLEANUP_STAT_LETHAL) == 0) - state->errs |= mail_stream_finish(state->handle, (VSTRING *) 0); - else + if (state->errs == 0) { + state->errs = mail_stream_finish(state->handle, (VSTRING *) 0); + } else { mail_stream_cleanup(state->handle); + } state->handle = 0; state->dst = 0; @@ -207,35 +220,26 @@ int cleanup_close(CLEANUP_STATE *state) * * Do not log the arrival of a message that will be bounced by the client. * - * XXX CLEANUP_STAT_LETHAL masks errors that are not directly fatal (e.g., - * header buffer overflow is normally allowed to happen), but that can - * indirectly become a problem (e.g., no recipients were extracted from - * message headers because we could not process all the message headers). - * However, cleanup_strerror() prioritizes errors so that it can report - * the cause (e.g., header buffer overflow), which is more useful. - * * XXX When bouncing, should log sender because qmgr won't be able to. */ #define CAN_BOUNCE() \ - ((state->errs & (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE)) == 0 \ + ((state->errs & CLEANUP_STAT_MASK_CANT_BOUNCE) == 0 \ && state->sender != 0 \ && (state->flags & CLEANUP_FLAG_BOUNCE) != 0) - if (state->errs & CLEANUP_STAT_LETHAL) { + if (state->errs != 0) { if (CAN_BOUNCE()) { - reason = cleanup_strerror(state->errs); - if (reason == cleanup_strerror(CLEANUP_STAT_CONT)) - reason = vstring_str(state->why_rejected); if (bounce_append(BOUNCE_FLAG_CLEAN, state->queue_id, state->recip ? state->recip : "unknown", "cleanup", state->time, - "Message processing aborted: %s", - reason) == 0 + "Message processing aborted: %s", state->reason ? + state->reason : cleanup_strerror(state->errs)) == 0 && bounce_flush(BOUNCE_FLAG_CLEAN, MAIL_QUEUE_INCOMING, state->queue_id, state->sender) == 0) { state->errs = 0; } else { - msg_warn("%s: bounce message failure", state->queue_id); + if (var_soft_bounce == 0) + msg_warn("%s: bounce message failure", state->queue_id); state->errs = CLEANUP_STAT_WRITE; } } @@ -258,11 +262,11 @@ int cleanup_close(CLEANUP_STATE *state) */ if (msg_verbose) msg_info("cleanup_close: status %d", state->errs); - status = state->errs & CLEANUP_STAT_LETHAL; + status = state->errs; return (status); } -/* cleanup_close - pay the last respects */ +/* cleanup_free - pay the last respects */ void cleanup_free(CLEANUP_STATE *state) { diff --git a/postfix/src/cleanup/cleanup_map1n.c b/postfix/src/cleanup/cleanup_map1n.c index 6af064a10..72127c180 100644 --- a/postfix/src/cleanup/cleanup_map1n.c +++ b/postfix/src/cleanup/cleanup_map1n.c @@ -101,7 +101,11 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, char *addr, break; } for (count = 0; /* void */ ; count++) { - if (been_here_fixed(been_here, argv->argv[arg]) != 0) + + /* + * Don't expand an address that already expanded into itself. + */ + if (been_here_check_fixed(been_here, argv->argv[arg]) != 0) break; if (count >= MAX_RECURSION) { msg_warn("%s: unreasonable %s map nesting for %s", @@ -118,6 +122,12 @@ ARGV *cleanup_map1n_internal(CLEANUP_STATE *state, char *addr, argv_add(argv, STR(state->temp1), ARGV_END); argv_terminate(argv); } + + /* + * Allow an address to expand into itself once. + */ + if (strcasecmp(saved_lhs, STR(state->temp1)) == 0) + been_here_fixed(been_here, argv->argv[arg]); } myfree(saved_lhs); argv_free(lookup); diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 6843d6c35..e1742a760 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -186,6 +186,12 @@ static void cleanup_rewrite_sender(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts) if (hdr_opts->type == HDR_RESENT_FROM && state->resent_from == 0) state->resent_from = cleanup_extract_internal(state->header_buf, *tpp); + if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt) + state->return_receipt = + cleanup_extract_internal(state->header_buf, *tpp); + if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to) + state->errors_to = + cleanup_extract_internal(state->header_buf, *tpp); } vstring_sprintf(state->header_buf, "%s: ", hdr_opts->name); tok822_externalize(state->header_buf, tree, TOK822_STR_HEAD); @@ -239,12 +245,6 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts) if (cleanup_masq_domains && (cleanup_masq_flags & CLEANUP_MASQ_FLAG_HDR_RCPT)) cleanup_masquerade_tree(*tpp, cleanup_masq_domains); - if (hdr_opts->type == HDR_RETURN_RECEIPT_TO && !state->return_receipt) - state->return_receipt = - cleanup_extract_internal(state->header_buf, *tpp); - if (hdr_opts->type == HDR_ERRORS_TO && !state->errors_to) - state->errors_to = - cleanup_extract_internal(state->header_buf, *tpp); } vstring_sprintf(state->header_buf, "%s: ", hdr_opts->name); tok822_externalize(state->header_buf, tree, TOK822_STR_HEAD); @@ -254,36 +254,28 @@ static void cleanup_rewrite_recip(CLEANUP_STATE *state, HEADER_OPTS *hdr_opts) cleanup_fold_header(state); } -/* cleanup_parse_reject - parse REJECT liune and pick up the reason */ +/* cleanup_check_reject - parse and match header/body REJECT line */ -static const char *cleanup_parse_reject(CLEANUP_STATE *state, const char *value) +static int cleanup_check_reject(CLEANUP_STATE *state, const char *value) { - const char *reason; + const char *reason = value + strcspn(value, " \t"); /* * See if they spelled REJECT right. + * + * XXX The reason should be set only if we have a more severe error than + * anything that was found before. This calls for a cleanup_set_error() + * routine that takes an error code and an optional text. */ - if (strcasecmp(value, "REJECT") == 0) { - reason = "Content rejected"; - } else if (strncasecmp(value, "REJECT ", 7) == 0 - || strncasecmp(value, "REJECT\t", 7) == 0) { - reason = value + 7; - while (*reason && ISSPACE(*reason)) - reason++; - if (*reason == 0) - reason = "Content rejected"; + if (strncasecmp(value, "REJECT", reason - value) == 0) { + if (state->reason == 0) + state->reason = mystrdup(*reason ? reason : + cleanup_strerror(CLEANUP_STAT_CONT)); + state->errs |= CLEANUP_STAT_CONT; + return (1); } else { return (0); } - - /* - * Update the remembered reason if none was stored. - */ - if (state->why_rejected == 0) { - state->why_rejected = vstring_alloc(10); - vstring_strcpy(state->why_rejected, reason); - } - return (reason); } /* cleanup_header - process one complete header line */ @@ -299,14 +291,13 @@ static void cleanup_header(CLEANUP_STATE *state) if ((state->flags & CLEANUP_FLAG_FILTER) && cleanup_header_checks) { char *header = vstring_str(state->header_buf); const char *value; - const char *reason; if ((value = maps_find(cleanup_header_checks, header, 0)) != 0) { - if ((reason = cleanup_parse_reject(state, value)) != 0) { + if (cleanup_check_reject(state, value) != 0) { msg_info("%s: reject: header %.200s; from=<%s> to=<%s>: %s", state->queue_id, header, state->sender, - state->recip ? state->recip : "unknown", reason); - state->errs |= CLEANUP_STAT_CONT; + state->recip ? state->recip : "unknown", + state->reason); } else if (strcasecmp(value, "IGNORE") == 0) { return; } @@ -580,14 +571,13 @@ static void cleanup_message_body(CLEANUP_STATE *state, int type, char *buf, int */ if ((state->flags & CLEANUP_FLAG_FILTER) && cleanup_body_checks) { const char *value; - const char *reason; if ((value = maps_find(cleanup_body_checks, buf, 0)) != 0) { - if ((reason = cleanup_parse_reject(state, value)) != 0) { + if (cleanup_check_reject(state, value) != 0) { msg_info("%s: reject: body %.200s; from=<%s> to=<%s>: %s", state->queue_id, buf, state->sender, - state->recip ? state->recip : "unknown", reason); - state->errs |= CLEANUP_STAT_CONT; + state->recip ? state->recip : "unknown", + state->reason); } else if (strcasecmp(value, "IGNORE") == 0) { return; } diff --git a/postfix/src/cleanup/cleanup_out_recipient.c b/postfix/src/cleanup/cleanup_out_recipient.c index bb283aa3c..147fef30d 100644 --- a/postfix/src/cleanup/cleanup_out_recipient.c +++ b/postfix/src/cleanup/cleanup_out_recipient.c @@ -60,6 +60,7 @@ void cleanup_out_recipient(CLEANUP_STATE *state, char *recip) { ARGV *argv; char **cpp; + int envelope_changed; if (cleanup_virtual_maps == 0) { if (been_here_fixed(state->dups, recip) == 0) @@ -67,9 +68,13 @@ void cleanup_out_recipient(CLEANUP_STATE *state, char *recip) } else { argv = cleanup_map1n_internal(state, recip, cleanup_virtual_maps, cleanup_ext_prop_mask & EXT_PROP_VIRTUAL); + envelope_changed = (argv->argc > 1 || strcmp(recip, argv->argv[0])); for (cpp = argv->argv; *cpp; cpp++) - if (been_here_fixed(state->dups, *cpp) == 0) + if (been_here_fixed(state->dups, *cpp) == 0) { + if (envelope_changed) + cleanup_out_string(state, REC_TYPE_ORCP, recip); cleanup_out_string(state, REC_TYPE_RCPT, *cpp), state->rcpt_count++; + } argv_free(argv); } } diff --git a/postfix/src/cleanup/cleanup_state.c b/postfix/src/cleanup/cleanup_state.c index 615238e48..2206d7a42 100644 --- a/postfix/src/cleanup/cleanup_state.c +++ b/postfix/src/cleanup/cleanup_state.c @@ -84,7 +84,7 @@ CLEANUP_STATE *cleanup_state_alloc(void) state->xtra_offset = -1; state->end_seen = 0; state->rcpt_count = 0; - state->why_rejected = 0; + state->reason = 0; return (state); } @@ -114,7 +114,7 @@ void cleanup_state_free(CLEANUP_STATE *state) if (state->queue_id) myfree(state->queue_id); been_here_free(state->dups); - if (state->why_rejected) - vstring_free(state->why_rejected); + if (state->reason) + myfree(state->reason); myfree((char *) state); } diff --git a/postfix/src/flush/Makefile.in b/postfix/src/flush/Makefile.in index 19b51de28..fc0819df1 100644 --- a/postfix/src/flush/Makefile.in +++ b/postfix/src/flush/Makefile.in @@ -71,6 +71,7 @@ flush.o: ../../include/mail_params.h flush.o: ../../include/mail_queue.h flush.o: ../../include/mail_proto.h flush.o: ../../include/iostuff.h +flush.o: ../../include/attr.h flush.o: ../../include/mail_flush.h flush.o: ../../include/flush_clnt.h flush.o: ../../include/mail_conf.h diff --git a/postfix/src/global/Makefile.in b/postfix/src/global/Makefile.in index b96837dc8..7d5152cb2 100644 --- a/postfix/src/global/Makefile.in +++ b/postfix/src/global/Makefile.in @@ -19,7 +19,7 @@ SRCS = been_here.c bounce.c canon_addr.c cleanup_strerror.c clnt_stream.c \ timed_ipc.c tok822_find.c tok822_node.c tok822_parse.c \ tok822_resolve.c tok822_rewrite.c tok822_tree.c xtext.c bounce_log.c \ flush_clnt.c mail_conf_time.c mbox_conf.c mbox_open.c abounce.c \ - verp_sender.c + verp_sender.c been_here_level.c OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ debug_peer.o debug_process.o defer.o deliver_completed.o \ deliver_flock.o deliver_pass.o deliver_request.o domain_list.o \ @@ -40,7 +40,7 @@ OBJS = been_here.o bounce.o canon_addr.o cleanup_strerror.o clnt_stream.o \ timed_ipc.o tok822_find.o tok822_node.o tok822_parse.o \ tok822_resolve.o tok822_rewrite.o tok822_tree.o xtext.o bounce_log.o \ flush_clnt.o mail_conf_time.o mbox_conf.o mbox_open.o abounce.o \ - verp_sender.o + verp_sender.o been_here_level.o HDRS = been_here.h bounce.h canon_addr.h cleanup_user.h clnt_stream.h \ config.h debug_peer.h debug_process.h defer.h deliver_completed.h \ deliver_flock.h deliver_pass.h deliver_request.h domain_list.h \ @@ -267,6 +267,15 @@ been_here.o: ../../include/vstring.h been_here.o: ../../include/vbuf.h been_here.o: ../../include/stringops.h been_here.o: been_here.h +been_here_level.o: been_here_level.c +been_here_level.o: ../../include/sys_defs.h +been_here_level.o: ../../include/msg.h +been_here_level.o: ../../include/mymalloc.h +been_here_level.o: ../../include/htable.h +been_here_level.o: ../../include/vstring.h +been_here_level.o: ../../include/vbuf.h +been_here_level.o: ../../include/stringops.h +been_here_level.o: been_here.h bounce.o: bounce.c bounce.o: ../../include/sys_defs.h bounce.o: ../../include/msg.h @@ -499,6 +508,15 @@ mail_command_client.o: mail_proto.h mail_command_client.o: ../../include/iostuff.h mail_command_client.o: ../../include/attr.h mail_command_client.o: ../../include/htable.h +mail_command_read.o: mail_command_read.c +mail_command_read.o: ../../include/sys_defs.h +mail_command_read.o: ../../include/vstring.h +mail_command_read.o: ../../include/vbuf.h +mail_command_read.o: ../../include/vstream.h +mail_command_read.o: mail_proto.h +mail_command_read.o: ../../include/iostuff.h +mail_command_read.o: ../../include/attr.h +mail_command_read.o: ../../include/htable.h mail_command_server.o: mail_command_server.c mail_command_server.o: ../../include/sys_defs.h mail_command_server.o: ../../include/vstream.h @@ -507,6 +525,14 @@ mail_command_server.o: mail_proto.h mail_command_server.o: ../../include/iostuff.h mail_command_server.o: ../../include/attr.h mail_command_server.o: ../../include/htable.h +mail_command_write.o: mail_command_write.c +mail_command_write.o: ../../include/sys_defs.h +mail_command_write.o: ../../include/vstream.h +mail_command_write.o: ../../include/vbuf.h +mail_command_write.o: mail_proto.h +mail_command_write.o: ../../include/iostuff.h +mail_command_write.o: ../../include/attr.h +mail_command_write.o: ../../include/htable.h mail_conf.o: mail_conf.c mail_conf.o: ../../include/sys_defs.h mail_conf.o: ../../include/msg.h @@ -568,6 +594,8 @@ mail_connect.o: ../../include/vbuf.h mail_connect.o: ../../include/connect.h mail_connect.o: ../../include/iostuff.h mail_connect.o: ../../include/mymalloc.h +mail_connect.o: ../../include/stringops.h +mail_connect.o: ../../include/vstring.h mail_connect.o: timed_ipc.h mail_connect.o: mail_proto.h mail_connect.o: ../../include/attr.h diff --git a/postfix/src/global/been_here.h b/postfix/src/global/been_here.h index 855001d61..c4f8a5287 100644 --- a/postfix/src/global/been_here.h +++ b/postfix/src/global/been_here.h @@ -28,6 +28,9 @@ typedef struct { #define BH_FLAG_NONE 0 /* no special processing */ #define BH_FLAG_FOLD (1<<0) /* fold case */ + /* + * been_here.c + */ extern BH_TABLE *been_here_init(int, int); extern void been_here_free(BH_TABLE *); extern int been_here_fixed(BH_TABLE *, const char *); @@ -35,6 +38,14 @@ extern int PRINTFLIKE(2, 3) been_here(BH_TABLE *, const char *,...); extern int been_here_check_fixed(BH_TABLE *, const char *); extern int PRINTFLIKE(2, 3) been_here_check(BH_TABLE *, const char *,...); + /* + * been_here_level.c + */ +extern int been_here_level_fixed(BH_TABLE *, int, const char *); +extern int PRINTFLIKE(3, 4) been_here_level(BH_TABLE *, int, const char *,...); +extern int been_here_level_check_fixed(BH_TABLE *, const char *); +extern int PRINTFLIKE(2, 3) been_here_level_check(BH_TABLE *, const char *,...); + /* LICENSE /* .ad /* .fi diff --git a/postfix/src/global/been_here_level.c b/postfix/src/global/been_here_level.c new file mode 100644 index 000000000..8391b87d9 --- /dev/null +++ b/postfix/src/global/been_here_level.c @@ -0,0 +1,239 @@ +/*++ +/* NAME +/* been_here_level 3 +/* SUMMARY +/* detect repeated occurrence of string +/* SYNOPSIS +/* #include +/* +/* int been_here_level_fixed(dup_filter, level, string) +/* BH_TABLE *dup_filter; +/* int level; +/* char *string; +/* +/* int been_here_level(dup_filter, level, format, ...) +/* BH_TABLE *dup_filter; +/* int level; +/* char *format; +/* +/* int been_here_level_check_fixed(dup_filter, level, string) +/* BH_TABLE *dup_filter; +/* int level; +/* char *string; +/* +/* int been_here_level_check(dup_filter, level, format, ...) +/* BH_TABLE *dup_filter; +/* int level; +/* char *format; +/* DESCRIPTION +/* This module implements a simple filter to detect repeated +/* occurrences of character strings. Each string has associated with +/* an integer level, the meaning of which is left up to the application. +/* Otherwise the code is like been_here(3). +/* +/* been_here_level_fixed() looks up a fixed string in the given table, and +/* makes an entry in the table if the string was not found. The result +/* is >= 0 if the string was found, -1 otherwise. +/* +/* been_here_level() formats its arguments, looks up the result in the +/* given table, and makes an entry in the table if the string was +/* not found. The result is >= 0 if the formatted result was +/* found, -1 otherwise. +/* +/* been_here_level_check_fixed() and been_here_level_check() are similar +/* but do not update the duplicate filter. +/* +/* Arguments: +/* .IP size +/* Upper bound on the table size; at most \fIsize\fR strings will +/* be remembered. Specify a value <= 0 to disable the upper bound. +/* .IP flags +/* Requests for special processing. Specify the bitwise OR of zero +/* or more flags: +/* .RS +/* .IP BH_FLAG_FOLD +/* Enable case-insensitive lookup. +/* .IP BH_FLAG_NONE +/* A manifest constant that requests no special processing. +/* .RE +/* .IP dup_filter +/* The table with remembered names +/* .IP level +/* The value that will be returned when the string is found by either +/* been_here_level() or been_here_check_level(). This value must be +/* >= 0. +/* .IP string +/* Fixed search string. +/* .IP format +/* Format for building the search string. +/* LICENSE +/* .ad +/* .fi +/* The Secure Mailer license must be distributed with this software. +/* AUTHOR(S) +/* Wietse Venema +/* IBM T.J. Watson Research +/* P.O. Box 704 +/* Yorktown Heights, NY 10598, USA +/*--*/ + +/* System library. */ + +#include "sys_defs.h" +#include /* 44BSD stdarg.h uses abort() */ +#include + +/* Utility library. */ + +#include +#include +#include +#include +#include + +/* Global library. */ + +#include "been_here.h" + +/* been_here_level - duplicate detector with finer control */ + +int been_here_level(BH_TABLE *dup_filter, int level, const char *fmt,...) +{ + VSTRING *buf = vstring_alloc(100); + int status; + va_list ap; + + /* + * Construct the string to be checked. + */ + va_start(ap, fmt); + vstring_vsprintf(buf, fmt, ap); + va_end(ap); + + /* + * Do the duplicate check. + */ + status = been_here_level_fixed(dup_filter, level, vstring_str(buf)); + + /* + * Cleanup. + */ + vstring_free(buf); + return (status); +} + +/* been_here_level_fixed - duplicate detector */ + +int been_here_level_fixed(BH_TABLE *dup_filter, int level, const char *string) +{ + char *folded_string; + const char *lookup_key; + int status; + HTABLE_INFO *info; + + /* + * Sanity check. + */ + if (level < 0) + msg_panic("been_here_level_fixed: bad level %d", level); + + /* + * Special processing: case insensitive lookup. + */ + if (dup_filter->flags & BH_FLAG_FOLD) { + folded_string = mystrdup(string); + lookup_key = lowercase(folded_string); + } else { + folded_string = 0; + lookup_key = string; + } + + /* + * Do the duplicate check. + */ + if ((info = htable_locate(dup_filter->table, lookup_key)) != 0) { + status = CAST_CHAR_PTR_TO_INT(info->value); + } else { + if (dup_filter->limit <= 0 + || dup_filter->limit > dup_filter->table->used) + htable_enter(dup_filter->table, lookup_key, + CAST_INT_TO_CHAR_PTR(level)); + status = -1; + } + if (msg_verbose) + msg_info("been_here_level: %s: %d", string, status); + + /* + * Cleanup. + */ + if (folded_string) + myfree(folded_string); + + return (status); +} + +/* been_here_level_check - query duplicate detector with finer control */ + +int been_here_level_check(BH_TABLE *dup_filter, const char *fmt,...) +{ + VSTRING *buf = vstring_alloc(100); + int status; + va_list ap; + + /* + * Construct the string to be checked. + */ + va_start(ap, fmt); + vstring_vsprintf(buf, fmt, ap); + va_end(ap); + + /* + * Do the duplicate check. + */ + status = been_here_level_check_fixed(dup_filter, vstring_str(buf)); + + /* + * Cleanup. + */ + vstring_free(buf); + return (status); +} + +/* been_here_level_check_fixed - query duplicate detector */ + +int been_here_level_check_fixed(BH_TABLE *dup_filter, const char *string) +{ + char *folded_string; + const char *lookup_key; + int status; + HTABLE_INFO *info; + + /* + * Special processing: case insensitive lookup. + */ + if (dup_filter->flags & BH_FLAG_FOLD) { + folded_string = mystrdup(string); + lookup_key = lowercase(folded_string); + } else { + folded_string = 0; + lookup_key = string; + } + + /* + * Do the duplicate check. + */ + if ((info = htable_locate(dup_filter->table, lookup_key)) != 0) + status = (-1); + else + status = CAST_CHAR_PTR_TO_INT(info->value); + if (msg_verbose) + msg_info("been_here_level_check: %s: %d", string, status); + + /* + * Cleanup. + */ + if (folded_string) + myfree(folded_string); + + return (status); +} diff --git a/postfix/src/global/cleanup_user.h b/postfix/src/global/cleanup_user.h index 8dff91022..c60565d62 100644 --- a/postfix/src/global/cleanup_user.h +++ b/postfix/src/global/cleanup_user.h @@ -34,7 +34,23 @@ #define CLEANUP_STAT_HOVFL (1<<7) /* Header overflow */ #define CLEANUP_STAT_ROVFL (1<<8) /* Recipient overflow */ -#define CLEANUP_STAT_LETHAL ~(CLEANUP_STAT_HOVFL|CLEANUP_STAT_ROVFL) + /* + * These are set when we can't bounce even if we were asked to. + */ +#define CLEANUP_STAT_MASK_CANT_BOUNCE \ + (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE) + + /* + * These are set when we can't examine every record of a message. + */ +#define CLEANUP_STAT_MASK_INCOMPLETE \ + (CLEANUP_STAT_BAD | CLEANUP_STAT_WRITE | CLEANUP_STAT_SIZE) + + /* + * These are relevant for extracting recipients from headers. + */ +#define CLEANUP_STAT_MASK_EXTRACT_RCPT \ + (CLEANUP_STAT_HOVFL | CLEANUP_STAT_ROVFL | CLEANUP_STAT_RCPT) extern const char *cleanup_strerror(unsigned); diff --git a/postfix/src/global/mail_stream.c b/postfix/src/global/mail_stream.c index 02d50707b..41ae0d38f 100644 --- a/postfix/src/global/mail_stream.c +++ b/postfix/src/global/mail_stream.c @@ -29,8 +29,9 @@ /* void mail_stream_cleanup(info) /* MAIL_STREAM *info; /* -/* int mail_stream_finish(info) +/* int mail_stream_finish(info, why) /* MAIL_STREAM *info; +/* VSTRING *why; /* DESCRIPTION /* This module provides a generic interface to Postfix queue file /* format messages to file, to Postfix server, or to external command. @@ -62,6 +63,7 @@ /* any of the mail_stream_xxx() routines, and destroys the argument. /* The result is any of the status codes defined in . /* It is up to the caller to remove incomplete file objects. +/* The why argument can be a null pointer. /* LICENSE /* .ad /* .fi @@ -123,7 +125,15 @@ static int mail_stream_finish_file(MAIL_STREAM * info, VSTRING *unused_why) /* * Make sure the message makes it to file. Set the execute bit when no - * write error was detected. + * write error was detected. Some people believe that this code has a + * problem if the system crashes before fsync() returns; fchmod() could + * take effect before all the data blocks are written. Wietse claims that + * this is not a problem. Postfix rejects incomplete queue files, even + * when the +x attribute is set. Every Postfix queue file record has a + * type code and a length field. Files with truncated records are + * rejected, as are files with unknown type codes. Every Postfix queue + * file must end with an explicit END record. Postfix queue files without + * END record are discarded. */ if (vstream_fflush(info->stream) || fchmod(vstream_fileno(info->stream), 0700) @@ -168,10 +178,13 @@ static int mail_stream_finish_ipc(MAIL_STREAM * info, VSTRING *why) /* * Receive the peer's completion status. */ - if (attr_scan(info->stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA, - ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, - ATTR_TYPE_STR, MAIL_ATTR_WHY, why, - ATTR_TYPE_END) != 2) + if ((why && attr_scan(info->stream, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA, + ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_STR, MAIL_ATTR_WHY, why, + ATTR_TYPE_END) != 2) + || (!why && attr_scan(info->stream, ATTR_FLAG_MISSING, + ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, + ATTR_TYPE_END) != 1)) status = CLEANUP_STAT_WRITE; /* diff --git a/postfix/src/global/mail_trigger.c b/postfix/src/global/mail_trigger.c index 4d4d61c3f..457f19d6b 100644 --- a/postfix/src/global/mail_trigger.c +++ b/postfix/src/global/mail_trigger.c @@ -79,7 +79,7 @@ int mail_trigger(const char *class, const char *service, */ path = mail_pathname(class, service); if ((status = stat(path, &st)) < 0) { - /* void */ ; + msg_warn("unable to look up %s: %m", path); } else if (S_ISFIFO(st.st_mode)) { status = fifo_trigger(path, req_buf, req_len, var_trigger_timeout); if (status < 0 && S_ISSOCK(st.st_mode)) diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 6508da3b3..d37440660 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -15,7 +15,7 @@ * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" -#define DEF_MAIL_VERSION "Snapshot-20011015" +#define DEF_MAIL_VERSION "Snapshot-20011029" extern char *var_mail_version; /* LICENSE diff --git a/postfix/src/global/pipe_command.c b/postfix/src/global/pipe_command.c index 8c9615a6f..766a41360 100644 --- a/postfix/src/global/pipe_command.c +++ b/postfix/src/global/pipe_command.c @@ -33,11 +33,11 @@ /* or when it appears to be a shell built-in command, otherwise /* the command is executed without invoking a shell. /* One of PIPE_CMD_COMMAND or PIPE_CMD_ARGV must be specified. +/* See also the PIPE_CMD_SHELL attribute below. /* .IP "PIPE_CMD_ARGV (char **)" /* The command is specified as an argument vector. This vector is /* passed without further inspection to the \fIexecvp\fR() routine. /* One of PIPE_CMD_COMMAND or PIPE_CMD_ARGV must be specified. -/* See also the PIPE_CMD_SHELL attribute below. /* .IP "PIPE_CMD_ENV (char **)" /* Additional environment information, in the form of a null-terminated /* list of name, value, name, value, ... elements. By default only the diff --git a/postfix/src/global/rec_type.c b/postfix/src/global/rec_type.c index 3b8f46f05..84e03dd13 100644 --- a/postfix/src/global/rec_type.c +++ b/postfix/src/global/rec_type.c @@ -47,6 +47,7 @@ REC_TYPE_NAME rec_type_names[] = { REC_TYPE_FILT, "content_filter", REC_TYPE_FROM, "sender", REC_TYPE_DONE, "done", + REC_TYPE_ORCP, "envelope-to-recipient", REC_TYPE_RCPT, "recipient", REC_TYPE_WARN, "warning_message_time", REC_TYPE_MESG, "message_content", diff --git a/postfix/src/global/rec_type.h b/postfix/src/global/rec_type.h index 1a89d8c95..58db373a5 100644 --- a/postfix/src/global/rec_type.h +++ b/postfix/src/global/rec_type.h @@ -32,6 +32,7 @@ #define REC_TYPE_FILT 'L' /* loop filter transport */ #define REC_TYPE_FROM 'S' /* sender, required */ #define REC_TYPE_DONE 'D' /* delivered recipient, optional */ +#define REC_TYPE_ORCP 'O' /* envelope-to recipient */ #define REC_TYPE_RCPT 'R' /* todo recipient, optional */ #define REC_TYPE_WARN 'W' /* warning message time */ @@ -54,9 +55,9 @@ * record groups. The first member in each set is the record type that * indicates the end of that record group. */ -#define REC_TYPE_ENVELOPE "MCTFILSDRWV" +#define REC_TYPE_ENVELOPE "MCTFILSDORWV" #define REC_TYPE_CONTENT "XLN" -#define REC_TYPE_EXTRACT "EDRPre" +#define REC_TYPE_EXTRACT "EDORPre" #define REC_TYPE_NOEXTRACT "E" /* diff --git a/postfix/src/lmtp/Makefile.in b/postfix/src/lmtp/Makefile.in index 9821cf6af..c10125b2a 100644 --- a/postfix/src/lmtp/Makefile.in +++ b/postfix/src/lmtp/Makefile.in @@ -132,6 +132,8 @@ lmtp_connect.o: ../../include/timed_connect.h lmtp_connect.o: ../../include/stringops.h lmtp_connect.o: ../../include/mail_params.h lmtp_connect.o: ../../include/mail_proto.h +lmtp_connect.o: ../../include/attr.h +lmtp_connect.o: ../../include/htable.h lmtp_connect.o: ../../include/dns.h lmtp_connect.o: lmtp.h lmtp_connect.o: ../../include/argv.h diff --git a/postfix/src/local/Makefile.in b/postfix/src/local/Makefile.in index ff36cf9bf..5aa5fec5c 100644 --- a/postfix/src/local/Makefile.in +++ b/postfix/src/local/Makefile.in @@ -213,6 +213,7 @@ forward.o: ../../include/vstring_vstream.h forward.o: ../../include/iostuff.h forward.o: ../../include/stringops.h forward.o: ../../include/mail_proto.h +forward.o: ../../include/attr.h forward.o: ../../include/cleanup_user.h forward.o: ../../include/sent.h forward.o: ../../include/record.h @@ -334,13 +335,16 @@ mailbox.o: ../../include/deliver_request.h mailbox.o: ../../include/recipient_list.h mailbox.o: ../../include/mail_proto.h mailbox.o: ../../include/iostuff.h +mailbox.o: ../../include/attr.h mailbox.o: ../../include/mbox_open.h mailbox.o: ../../include/safe_open.h +mailbox.o: ../../include/maps.h +mailbox.o: ../../include/dict.h +mailbox.o: ../../include/argv.h mailbox.o: local.h mailbox.o: ../../include/tok822.h mailbox.o: ../../include/resolve_clnt.h mailbox.o: ../../include/mbox_conf.h -mailbox.o: ../../include/argv.h mailbox.o: biff_notify.h maildir.o: maildir.c maildir.o: ../../include/sys_defs.h @@ -403,6 +407,7 @@ resolve.o: ../../include/htable.h resolve.o: ../../include/mail_proto.h resolve.o: ../../include/vstream.h resolve.o: ../../include/iostuff.h +resolve.o: ../../include/attr.h resolve.o: ../../include/resolve_clnt.h resolve.o: ../../include/rewrite_clnt.h resolve.o: ../../include/tok822.h @@ -446,9 +451,10 @@ unknown.o: ../../include/mail_params.h unknown.o: ../../include/mail_proto.h unknown.o: ../../include/vstream.h unknown.o: ../../include/iostuff.h +unknown.o: ../../include/attr.h +unknown.o: ../../include/htable.h unknown.o: ../../include/bounce.h unknown.o: local.h -unknown.o: ../../include/htable.h unknown.o: ../../include/tok822.h unknown.o: ../../include/resolve_clnt.h unknown.o: ../../include/deliver_request.h diff --git a/postfix/src/local/forward.c b/postfix/src/local/forward.c index 742eb478f..c8fcdc145 100644 --- a/postfix/src/local/forward.c +++ b/postfix/src/local/forward.c @@ -120,6 +120,10 @@ static FORWARD_INFO *forward_open(char *sender) * Contact the cleanup service and save the new mail queue id. Request * that the cleanup service bounces bad messages to the sender so that we * can avoid the trouble of bounce management. + * + * In case you wonder what kind of bounces, examples are "too many hops", + * "message too large", perhaps some others. The reason not to bounce + * ourselves is that we don't really know who the recipients are. */ cleanup = mail_connect(MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP, BLOCKING); if (cleanup == 0) diff --git a/postfix/src/master/Makefile.in b/postfix/src/master/Makefile.in index db445d72a..729a06b2d 100644 --- a/postfix/src/master/Makefile.in +++ b/postfix/src/master/Makefile.in @@ -131,6 +131,8 @@ master_ent.o: ../../include/inet_util.h master_ent.o: ../../include/inet_addr_host.h master_ent.o: ../../include/mail_proto.h master_ent.o: ../../include/iostuff.h +master_ent.o: ../../include/attr.h +master_ent.o: ../../include/htable.h master_ent.o: ../../include/mail_params.h master_ent.o: ../../include/own_inet_addr.h master_ent.o: master_proto.h @@ -205,6 +207,8 @@ master_wakeup.o: ../../include/mail_proto.h master_wakeup.o: ../../include/vstream.h master_wakeup.o: ../../include/vbuf.h master_wakeup.o: ../../include/iostuff.h +master_wakeup.o: ../../include/attr.h +master_wakeup.o: ../../include/htable.h master_wakeup.o: mail_server.h master_wakeup.o: master.h multi_server.o: multi_server.c diff --git a/postfix/src/master/multi_server.c b/postfix/src/master/multi_server.c index 39aab4331..602db54c7 100644 --- a/postfix/src/master/multi_server.c +++ b/postfix/src/master/multi_server.c @@ -273,6 +273,7 @@ static void multi_server_wakeup(int fd) { VSTREAM *stream; char *tmp; + if (msg_verbose) msg_info("connection established fd %d", fd); non_blocking(fd, BLOCKING); @@ -280,7 +281,7 @@ static void multi_server_wakeup(int fd) client_count++; stream = vstream_fdopen(fd, O_RDWR); tmp = concatenate(multi_server_name, " socket", (char *) 0); - vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END); + vstream_control(stream, VSTREAM_CTL_PATH, tmp, VSTREAM_CTL_END); myfree(tmp); timed_ipc_setup(stream); if (multi_server_in_flow_delay && mail_flow_get(1) < 0) diff --git a/postfix/src/nqmgr/Makefile.in b/postfix/src/nqmgr/Makefile.in index ddf61ea73..4ead1237c 100644 --- a/postfix/src/nqmgr/Makefile.in +++ b/postfix/src/nqmgr/Makefile.in @@ -75,6 +75,8 @@ qmgr.o: ../../include/mail_conf.h qmgr.o: ../../include/mail_params.h qmgr.o: ../../include/mail_proto.h qmgr.o: ../../include/iostuff.h +qmgr.o: ../../include/attr.h +qmgr.o: ../../include/htable.h qmgr.o: ../../include/mail_flow.h qmgr.o: ../../include/master_proto.h qmgr.o: ../../include/mail_server.h @@ -136,6 +138,8 @@ qmgr_deliver.o: ../../include/events.h qmgr_deliver.o: ../../include/iostuff.h qmgr_deliver.o: ../../include/mail_queue.h qmgr_deliver.o: ../../include/mail_proto.h +qmgr_deliver.o: ../../include/attr.h +qmgr_deliver.o: ../../include/htable.h qmgr_deliver.o: ../../include/recipient_list.h qmgr_deliver.o: ../../include/mail_params.h qmgr_deliver.o: ../../include/deliver_request.h @@ -283,6 +287,7 @@ qmgr_transport.o: ../../include/vstream.h qmgr_transport.o: ../../include/vbuf.h qmgr_transport.o: ../../include/iostuff.h qmgr_transport.o: ../../include/mail_proto.h +qmgr_transport.o: ../../include/attr.h qmgr_transport.o: ../../include/recipient_list.h qmgr_transport.o: ../../include/mail_conf.h qmgr_transport.o: ../../include/mail_params.h diff --git a/postfix/src/pickup/Makefile.in b/postfix/src/pickup/Makefile.in index 19f5688fc..144288104 100644 --- a/postfix/src/pickup/Makefile.in +++ b/postfix/src/pickup/Makefile.in @@ -67,6 +67,8 @@ pickup.o: ../../include/mail_open_ok.h pickup.o: ../../include/mymalloc.h pickup.o: ../../include/mail_proto.h pickup.o: ../../include/iostuff.h +pickup.o: ../../include/attr.h +pickup.o: ../../include/htable.h pickup.o: ../../include/cleanup_user.h pickup.o: ../../include/mail_date.h pickup.o: ../../include/mail_params.h diff --git a/postfix/src/pickup/pickup.c b/postfix/src/pickup/pickup.c index 03b7df23b..c21c9b886 100644 --- a/postfix/src/pickup/pickup.c +++ b/postfix/src/pickup/pickup.c @@ -295,7 +295,7 @@ static int pickup_copy(VSTREAM *qfile, VSTREAM *cleanup, * bounce, the cleanup service can report only soft errors here. */ rec_fputs(cleanup, REC_TYPE_END, ""); - if (attr_scan(cleanup, ATTR_FLAG_MISSING | ATTR_FLAG_EXTRA, + if (attr_scan(cleanup, ATTR_FLAG_MISSING, ATTR_TYPE_NUM, MAIL_ATTR_STATUS, &status, ATTR_TYPE_END) != 1) return (cleanup_service_error(info, CLEANUP_STAT_WRITE)); diff --git a/postfix/src/postconf/Makefile.in b/postfix/src/postconf/Makefile.in index 1cf467723..d9559dd9a 100644 --- a/postfix/src/postconf/Makefile.in +++ b/postfix/src/postconf/Makefile.in @@ -85,6 +85,7 @@ postconf.o: ../../include/mynetworks.h postconf.o: ../../include/mail_conf.h postconf.o: ../../include/mail_proto.h postconf.o: ../../include/iostuff.h +postconf.o: ../../include/attr.h postconf.o: ../../include/mail_version.h postconf.o: ../../include/mail_params.h postconf.o: ../../include/mail_addr.h diff --git a/postfix/src/postdrop/Makefile.in b/postfix/src/postdrop/Makefile.in index 2d893c3ac..21f69e983 100644 --- a/postfix/src/postdrop/Makefile.in +++ b/postfix/src/postdrop/Makefile.in @@ -65,6 +65,8 @@ postdrop.o: ../../include/msg_syslog.h postdrop.o: ../../include/argv.h postdrop.o: ../../include/mail_proto.h postdrop.o: ../../include/iostuff.h +postdrop.o: ../../include/attr.h +postdrop.o: ../../include/htable.h postdrop.o: ../../include/mail_queue.h postdrop.o: ../../include/mail_params.h postdrop.o: ../../include/mail_conf.h diff --git a/postfix/src/postkick/Makefile.in b/postfix/src/postkick/Makefile.in index 411aa984f..d028e21e6 100644 --- a/postfix/src/postkick/Makefile.in +++ b/postfix/src/postkick/Makefile.in @@ -64,5 +64,7 @@ postkick.o: ../../include/safe.h postkick.o: ../../include/events.h postkick.o: ../../include/mail_proto.h postkick.o: ../../include/iostuff.h +postkick.o: ../../include/attr.h +postkick.o: ../../include/htable.h postkick.o: ../../include/mail_params.h postkick.o: ../../include/mail_conf.h diff --git a/postfix/src/qmgr/Makefile.in b/postfix/src/qmgr/Makefile.in index eaddb56f5..2b04de679 100644 --- a/postfix/src/qmgr/Makefile.in +++ b/postfix/src/qmgr/Makefile.in @@ -73,6 +73,8 @@ qmgr.o: ../../include/mail_conf.h qmgr.o: ../../include/mail_params.h qmgr.o: ../../include/mail_proto.h qmgr.o: ../../include/iostuff.h +qmgr.o: ../../include/attr.h +qmgr.o: ../../include/htable.h qmgr.o: ../../include/mail_flow.h qmgr.o: ../../include/master_proto.h qmgr.o: ../../include/mail_server.h @@ -134,6 +136,8 @@ qmgr_deliver.o: ../../include/events.h qmgr_deliver.o: ../../include/iostuff.h qmgr_deliver.o: ../../include/mail_queue.h qmgr_deliver.o: ../../include/mail_proto.h +qmgr_deliver.o: ../../include/attr.h +qmgr_deliver.o: ../../include/htable.h qmgr_deliver.o: ../../include/recipient_list.h qmgr_deliver.o: ../../include/mail_params.h qmgr_deliver.o: ../../include/deliver_request.h @@ -255,6 +259,7 @@ qmgr_transport.o: ../../include/vstream.h qmgr_transport.o: ../../include/vbuf.h qmgr_transport.o: ../../include/iostuff.h qmgr_transport.o: ../../include/mail_proto.h +qmgr_transport.o: ../../include/attr.h qmgr_transport.o: ../../include/recipient_list.h qmgr_transport.o: ../../include/mail_conf.h qmgr_transport.o: ../../include/mail_params.h diff --git a/postfix/src/qmqpd/Makefile.in b/postfix/src/qmqpd/Makefile.in index 117cf9ea4..8eb77b612 100644 --- a/postfix/src/qmqpd/Makefile.in +++ b/postfix/src/qmqpd/Makefile.in @@ -82,6 +82,8 @@ qmqpd.o: ../../include/record.h qmqpd.o: ../../include/rec_type.h qmqpd.o: ../../include/mail_proto.h qmqpd.o: ../../include/iostuff.h +qmqpd.o: ../../include/attr.h +qmqpd.o: ../../include/htable.h qmqpd.o: ../../include/cleanup_user.h qmqpd.o: ../../include/mail_date.h qmqpd.o: ../../include/mail_conf.h diff --git a/postfix/src/qmqpd/qmqpd.c b/postfix/src/qmqpd/qmqpd.c index f1d599578..40ea80839 100644 --- a/postfix/src/qmqpd/qmqpd.c +++ b/postfix/src/qmqpd/qmqpd.c @@ -436,6 +436,8 @@ static int qmqpd_send_status(QMQPD_STATE *state) /* * One message may suffer from multiple errors, so complain only about * the most severe error. + * + * See also: smtpd.c */ state->where = "sending completion status"; @@ -461,7 +463,8 @@ static int qmqpd_send_status(QMQPD_STATE *state) qmqpd_reply(state, DO_LOG, QMQPD_STAT_HARD, "Error: no recipients specified"); } else { - msg_panic("qmqpd_send_status: unknown status %d", state->err); + qmqpd_reply(state, DO_LOG, QMQPD_STAT_RETRY, + "Error: internal error %d", state->err); } } diff --git a/postfix/src/sendmail/Makefile.in b/postfix/src/sendmail/Makefile.in index b1b738651..13bbb4370 100644 --- a/postfix/src/sendmail/Makefile.in +++ b/postfix/src/sendmail/Makefile.in @@ -73,6 +73,8 @@ sendmail.o: ../../include/set_ugid.h sendmail.o: ../../include/connect.h sendmail.o: ../../include/mail_queue.h sendmail.o: ../../include/mail_proto.h +sendmail.o: ../../include/attr.h +sendmail.o: ../../include/htable.h sendmail.o: ../../include/mail_params.h sendmail.o: ../../include/record.h sendmail.o: ../../include/rec_type.h diff --git a/postfix/src/sendmail/sendmail.c b/postfix/src/sendmail/sendmail.c index 694e99a55..cdf6ad880 100644 --- a/postfix/src/sendmail/sendmail.c +++ b/postfix/src/sendmail/sendmail.c @@ -148,9 +148,8 @@ /* configuration parameter instead. /* .IP \fB-qR\fIsite\fR /* Schedule immediate delivery of all mail that is queued for the named -/* \fIsite\fR. Depending on the destination, this uses "fast flush" -/* service, or it has the same effect as \fBsendmail -q\fR. -/* This is implemented by connecting to the local SMTP server. +/* \fIsite\fR. This uses "fast flush" service, and is implemented +/* by connecting to the local SMTP server at \fB$myhostname\fR. /* See \fBsmtpd\fR(8) for more information about the "fast flush" /* service. /* .IP \fB-qS\fIsite\fR @@ -516,7 +515,7 @@ static void enqueue(const int flags, const char *sender, const char *full_name, if (vstream_ferror(VSTREAM_IN)) msg_fatal("%s(%ld): error reading input: %m", saved_sender, (long) uid); - if ((status = mail_stream_finish(handle, buf)) != 0) + if ((status = mail_stream_finish(handle, (VSTRING *) 0)) != 0) msg_fatal("%s(%ld): %s", saved_sender, (long) uid, cleanup_strerror(status)); if (sendmail_path) { diff --git a/postfix/src/showq/Makefile.in b/postfix/src/showq/Makefile.in index 23d15c420..5c714ef11 100644 --- a/postfix/src/showq/Makefile.in +++ b/postfix/src/showq/Makefile.in @@ -68,6 +68,7 @@ showq.o: ../../include/mail_queue.h showq.o: ../../include/mail_open_ok.h showq.o: ../../include/mail_proto.h showq.o: ../../include/iostuff.h +showq.o: ../../include/attr.h showq.o: ../../include/mail_date.h showq.o: ../../include/mail_params.h showq.o: ../../include/mail_scan_dir.h diff --git a/postfix/src/smtp/Makefile.in b/postfix/src/smtp/Makefile.in index 15f860f61..5f749ea5f 100644 --- a/postfix/src/smtp/Makefile.in +++ b/postfix/src/smtp/Makefile.in @@ -80,6 +80,8 @@ smtp.o: ../../include/mail_error.h smtp.o: ../../include/deliver_pass.h smtp.o: ../../include/mail_proto.h smtp.o: ../../include/iostuff.h +smtp.o: ../../include/attr.h +smtp.o: ../../include/htable.h smtp.o: ../../include/mail_server.h smtp.o: smtp.h smtp.o: smtp_sasl.h diff --git a/postfix/src/smtpd/Makefile.in b/postfix/src/smtpd/Makefile.in index 73a262306..33c3d96ba 100644 --- a/postfix/src/smtpd/Makefile.in +++ b/postfix/src/smtpd/Makefile.in @@ -113,6 +113,8 @@ smtpd.o: ../../include/record.h smtpd.o: ../../include/rec_type.h smtpd.o: ../../include/mail_proto.h smtpd.o: ../../include/iostuff.h +smtpd.o: ../../include/attr.h +smtpd.o: ../../include/htable.h smtpd.o: ../../include/cleanup_user.h smtpd.o: ../../include/mail_date.h smtpd.o: ../../include/mail_conf.h @@ -148,6 +150,8 @@ smtpd_chat.o: ../../include/record.h smtpd_chat.o: ../../include/rec_type.h smtpd_chat.o: ../../include/mail_proto.h smtpd_chat.o: ../../include/iostuff.h +smtpd_chat.o: ../../include/attr.h +smtpd_chat.o: ../../include/htable.h smtpd_chat.o: ../../include/mail_params.h smtpd_chat.o: ../../include/mail_addr.h smtpd_chat.o: ../../include/post_mail.h @@ -226,6 +230,8 @@ smtpd_sasl_proto.o: ../../include/mail_proto.h smtpd_sasl_proto.o: ../../include/vstream.h smtpd_sasl_proto.o: ../../include/vbuf.h smtpd_sasl_proto.o: ../../include/iostuff.h +smtpd_sasl_proto.o: ../../include/attr.h +smtpd_sasl_proto.o: ../../include/htable.h smtpd_sasl_proto.o: ../../include/mail_error.h smtpd_sasl_proto.o: ../../include/name_mask.h smtpd_sasl_proto.o: smtpd.h diff --git a/postfix/src/smtpd/smtpd.c b/postfix/src/smtpd/smtpd.c index 0ecd36fcd..f3954d1b0 100644 --- a/postfix/src/smtpd/smtpd.c +++ b/postfix/src/smtpd/smtpd.c @@ -516,7 +516,7 @@ static void mail_open_stream(SMTPD_STATE *state) MAIL_SERVICE_CLEANUP); if (state->dest == 0 || attr_print(state->dest->stream, ATTR_FLAG_NONE, - ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER, + ATTR_TYPE_NUM, MAIL_ATTR_FLAGS, CLEANUP_FLAG_FILTER, ATTR_TYPE_END) != 0) msg_fatal("unable to connect to the %s %s service", MAIL_CLASS_PRIVATE, MAIL_SERVICE_CLEANUP); @@ -1000,7 +1000,7 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) * Finish the queue file or finish the cleanup conversation. */ if (state->err == 0) - state->err |= mail_stream_finish(state->dest, why = vstring_alloc(10)); + state->err = mail_stream_finish(state->dest, why = vstring_alloc(10)); else mail_stream_cleanup(state->dest); state->dest = 0; @@ -1024,6 +1024,8 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) * Handle any errors. One message may suffer from multiple errors, so * complain only about the most severe error. Forgive any previous client * errors when a message was received successfully. + * + * See also: qmqpd.c */ if (state->err == CLEANUP_STAT_OK) { state->error_count = 0; @@ -1041,15 +1043,14 @@ static int data_cmd(SMTPD_STATE *state, int argc, SMTPD_TOKEN *unused_argv) smtpd_chat_reply(state, "554 Error: too many hops"); } else if ((state->err & CLEANUP_STAT_CONT) != 0) { state->error_mask |= MAIL_ERROR_POLICY; - smtpd_chat_reply(state, "552 Error: %s", STR(why)); + smtpd_chat_reply(state, "552 Error: %s", LEN(why) ? + STR(why) : "content rejected"); } else if ((state->err & CLEANUP_STAT_WRITE) != 0) { state->error_mask |= MAIL_ERROR_RESOURCE; smtpd_chat_reply(state, "451 Error: queue file write error"); - } else if ((state->err & CLEANUP_STAT_RCPT) != 0) { + } else { state->error_mask |= MAIL_ERROR_SOFTWARE; smtpd_chat_reply(state, "451 Error: internal error %d", state->err); - } else { - msg_panic("data_cmd: unknown status %d", state->err); } /* diff --git a/postfix/src/smtpd/smtpd_check.c b/postfix/src/smtpd/smtpd_check.c index afbe44e62..d558c37c3 100644 --- a/postfix/src/smtpd/smtpd_check.c +++ b/postfix/src/smtpd/smtpd_check.c @@ -1158,7 +1158,7 @@ static int i_am_mx(DNS_RR *mx_list) static int permit_mx_primary(DNS_RR *mx_list) { DNS_RR *mx; - int best_pref; + unsigned int best_pref; int status; /* diff --git a/postfix/src/trivial-rewrite/Makefile.in b/postfix/src/trivial-rewrite/Makefile.in index 1065ce0cf..6e97b0ba9 100644 --- a/postfix/src/trivial-rewrite/Makefile.in +++ b/postfix/src/trivial-rewrite/Makefile.in @@ -70,6 +70,8 @@ resolve.o: ../../include/split_at.h resolve.o: ../../include/mail_params.h resolve.o: ../../include/mail_proto.h resolve.o: ../../include/iostuff.h +resolve.o: ../../include/attr.h +resolve.o: ../../include/htable.h resolve.o: ../../include/mail_addr.h resolve.o: ../../include/rewrite_clnt.h resolve.o: ../../include/resolve_local.h @@ -90,6 +92,8 @@ rewrite.o: ../../include/split_at.h rewrite.o: ../../include/mail_params.h rewrite.o: ../../include/mail_proto.h rewrite.o: ../../include/iostuff.h +rewrite.o: ../../include/attr.h +rewrite.o: ../../include/htable.h rewrite.o: ../../include/resolve_local.h rewrite.o: ../../include/tok822.h rewrite.o: ../../include/resolve_clnt.h @@ -123,6 +127,8 @@ trivial-rewrite.o: ../../include/argv.h trivial-rewrite.o: ../../include/mail_params.h trivial-rewrite.o: ../../include/mail_proto.h trivial-rewrite.o: ../../include/iostuff.h +trivial-rewrite.o: ../../include/attr.h +trivial-rewrite.o: ../../include/htable.h trivial-rewrite.o: ../../include/resolve_local.h trivial-rewrite.o: ../../include/mail_conf.h trivial-rewrite.o: ../../include/resolve_clnt.h diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 0d51b9b21..cd039e043 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -24,7 +24,7 @@ SRCS = argv.c argv_split.c attr.c basename.c binhash.c chroot_uid.c \ sane_link.c unescape.c timed_read.c timed_write.c dict_tcp.c \ hex_quote.c dict_alloc.c rand_sleep.c sane_time.c dict_debug.c \ sane_socketpair.c myrand.c netstring.c ctable.c attr_print.c intv.c \ - attr_scan.c attr_table.c base64_code.c + attr_scan.c base64_code.c OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \ close_on_exec.o concatenate.o dict.o dict_db.o dict_dbm.o \ dict_env.o dict_ht.o dict_ldap.o dict_mysql.o dict_ni.o dict_nis.o \ @@ -50,7 +50,7 @@ OBJS = argv.o argv_split.o attr.o basename.o binhash.o chroot_uid.o \ sane_link.o unescape.o timed_read.o timed_write.o dict_tcp.o \ hex_quote.o dict_alloc.o rand_sleep.o sane_time.o dict_debug.o \ sane_socketpair.o myrand.o netstring.o ctable.o attr_print.o intv.o \ - attr_scan.o attr_table.o base64_code.o + attr_scan.o base64_code.o HDRS = argv.h attr.h binhash.h chroot_uid.h connect.h dict.h dict_db.h \ dict_dbm.h dict_env.h dict_ht.h dict_ldap.h dict_mysql.h \ dict_ni.h dict_nis.h dict_nisplus.h dir_forest.h events.h \ @@ -84,7 +84,7 @@ TESTPROG= dict_open dup2_pass_on_exec events exec_command fifo_open \ mystrtok sigdelay translit valid_hostname vstream_popen \ vstring vstring_vstream doze select_bug stream_test mac_expand \ watchdog unescape hex_quote name_mask rand_sleep sane_time ctable \ - inet_addr_list attr_print attr_scan attr_table base64_code + inet_addr_list attr_print attr_scan base64_code LIB_DIR = ../../lib INC_DIR = ../../include @@ -298,11 +298,6 @@ attr_scan: $(LIB) $@.o $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) mv junk $@.o -attr_table: $(LIB) $@.o - mv $@.o junk - $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) - mv junk $@.o - base64_code: $(LIB) $@.o mv $@.o junk $(CC) $(CFLAGS) -DTEST -o $@ $@.c $(LIB) $(SYSLIBS) diff --git a/postfix/src/util/attr.h b/postfix/src/util/attr.h index 4e5febec5..b0b0601c6 100644 --- a/postfix/src/util/attr.h +++ b/postfix/src/util/attr.h @@ -50,17 +50,6 @@ extern int attr_vprint(VSTREAM *, int, va_list); extern int attr_scan(VSTREAM *, int,...); extern int attr_vscan(VSTREAM *, int, va_list); - /* - * attr_table.c. - */ -typedef HTABLE ATTR_TABLE; - -extern ATTR_TABLE *attr_table_create(int); -extern void attr_table_free(ATTR_TABLE *); -extern int attr_table_read(ATTR_TABLE *, int, VSTREAM *); -extern int attr_table_get(ATTR_TABLE *, int,...); -extern int attr_table_vget(ATTR_TABLE *, int, va_list); - /* * attr.c. */ @@ -78,11 +67,6 @@ extern int attr_find(HTABLE *, int,...); #define ATTR_NAME_STR_ARRAY "string_array" #endif - /* - * Testing. - */ -#define BASE64_DECODE(buf, str, len) vstring_strncpy((buf), (str), (len)) - /* LICENSE /* .ad /* .fi diff --git a/postfix/src/util/attr_scan.c b/postfix/src/util/attr_scan.c index 3039f1a94..51320bf5f 100644 --- a/postfix/src/util/attr_scan.c +++ b/postfix/src/util/attr_scan.c @@ -29,6 +29,8 @@ /* (item1 | item2) stands for choice: /* /* .in +5 +/* input :== attr-list +/* .br /* attr-list :== (simple-attr | list-attr)* newline /* .br /* simple-attr :== attr-name colon attr-value newline @@ -227,7 +229,7 @@ int attr_vscan(VSTREAM *fp, int flags, va_list ap) static VSTRING *name_buf = 0; int wanted_type = -1; char *wanted_name; - int *number; + unsigned int *number; VSTRING *string; INTV *number_array; ARGV *string_array; diff --git a/postfix/src/util/attr_table.c b/postfix/src/util/attr_table.c deleted file mode 100644 index 2d69c81ca..000000000 --- a/postfix/src/util/attr_table.c +++ /dev/null @@ -1,439 +0,0 @@ -/*++ -/* NAME -/* attr_table 3 -/* SUMMARY -/* recover attributes from byte stream -/* SYNOPSIS -/* #include -/* -/* ATTR_TABLE *attr_table_create(size) -/* int size; -/* -/* void attr_table_free(attr) -/* ATTR_TABLE *attr; -/* -/* int attr_table_read(attr, flags, fp) -/* ATTR_TABLE *attr; -/* int flags; -/* VSTREAM fp; -/* -/* int attr_table_get(attr, flags, type, name, ...) -/* ATTR_TABLE *attr; -/* int flags; -/* int type; -/* char *name; -/* DESCRIPTION -/* This module provides an alternative process for recovering -/* attribute lists from a byte stream. The process involves the -/* storage in an intermediate attribute table that is subsequently -/* queried. This procedure gives more control to the application, -/* at the cost of complexity and of memory resources. -/* -/* attr_table_create() creates an empty table for storage of -/* the intermediate result from attr_table_read(). -/* -/* attr_table_free() destroys its argument. -/* -/* attr_table_read() reads an attribute list from a byte stream -/* and stores the intermediate result into a table that can be -/* queried with attr_table_get(). -/* -/* attr_table_get() takes zero or more (name, value) scalar or array -/* attribute arguments, and recovers the attribute values from the -/* intermediate attribute table produced by attr_table_read(). -/* -/* Arguments: -/* .IP fp -/* Stream to recover the attributes from. -/* .IP flags -/* The bit-wise OR of zero or more of the following. -/* .RS -/* .IP ATTR_FLAG_MISSING -/* Log a warning when the input attribute list terminates before all -/* requested attributes are recovered. It is always an error when the -/* input stream ends without the newline attribute list terminator. -/* This flag has no effect with attr_table_read(). -/* .IP ATTR_FLAG_EXTRA -/* Log a warning and stop attribute recovery when the input stream -/* contains multiple instances of an attribute. -/* This flag has no effect with attr_table_get(). -/* .IP ATTR_FLAG_NONE -/* For convenience, this value requests none of the above. -/* .RE -/* .IP type -/* The type determines the arguments that follow. -/* .RS -/* .IP "ATTR_TYPE_NUM (char *, int *)" -/* This argument is followed by an attribute name and an integer pointer. -/* This is used for recovering an integer attribute value. -/* .IP "ATTR_TYPE_STR (char *, VSTRING *)" -/* This argument is followed by an attribute name and a VSTRING pointer. -/* This is used for recovering a string attribute value. -/* .IP "ATTR_TYPE_NUM_ARRAY (char *, INTV *)" -/* This argument is followed by an attribute name and an INTV pointer. -/* This is used for recovering an integer array attribute value. -/* .IP "ATTR_TYPE_NUM_ARRAY (char *, ARGV *)" -/* This argument is followed by an attribute name and an ARGV pointer. -/* This is used for recovering a string array attribute value. -/* .IP ATTR_TYPE_END -/* This terminates the requested attribute list. -/* .RE -/* DIAGNOSTICS -/* The result value from attr_table_read() and from attr_table_get() -/* is the number of attributes that were successfully recovered from -/* the input stream (an array-valued attribute counts as one attribute). -/* -/* Panic: interface violation. All system call errors are fatal. -/* SEE ALSO -/* attr_print(3) send attributes over byte stream. -/* LICENSE -/* .ad -/* .fi -/* The Secure Mailer license must be distributed with this software. -/* AUTHOR(S) -/* Wietse Venema -/* IBM T.J. Watson Research -/* P.O. Box 704 -/* Yorktown Heights, NY 10598, USA -/*--*/ - -/* System library. */ - -#include -#include -#include -#include - -/* Utility library. */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* Application-specific. */ - -#define STR(x) vstring_str(x) -#define LEN(x) VSTRING_LEN(x) - -static VSTRING *base64_buf; -static VSTRING *plain_buf; - -/* attr_table_create - create attribute table */ - -ATTR_TABLE *attr_table_create(int size) -{ - return (htable_create(size)); -} - -/* attr_table_free - destroy attribute table */ - -void attr_table_free(ATTR_TABLE *table) -{ - htable_free(table, myfree); -} - -/* attr_table_read - read attribute stream into table */ - -int attr_table_read(ATTR_TABLE *table, int flags, VSTREAM *stream) -{ - char *attr_value; - int attr_count; - int ch; - - if (base64_buf == 0) { - base64_buf = vstring_alloc(10); - plain_buf = vstring_alloc(10); - } - for (attr_count = 0; /* void */ ; attr_count++) { - - /* - * Unexpected end-of-file is always an error. - */ - if ((ch = vstring_get_nonl(base64_buf, stream)) == VSTREAM_EOF) { - msg_warn("unexpected EOF while reading attributes from %s", - VSTREAM_PATH(stream)); - return (attr_count); - } - - /* - * A legitimate end of attribute list is OK. - */ - if (LEN(base64_buf) == 0) - return (attr_count); - - /* - * Split into name and value, but keep the ':' separator so that we - * can distinguish between no value or a zero-length value; decode - * the name but keep the value in one piece, so that we can process - * array-valued attributes. - */ - if ((attr_value = strchr(STR(base64_buf), ':')) != 0) - *attr_value = 0; - if (BASE64_DECODE(plain_buf, STR(base64_buf), attr_value ? - (attr_value - STR(base64_buf)) : LEN(base64_buf)) == 0) { - msg_warn("malformed base64 data from %s: %.100s", - VSTREAM_PATH(stream), STR(base64_buf)); - return (attr_count); - } - if (attr_value != 0) - *attr_value = ':'; - else - attr_value = ""; - - /* - * Stop if there are multiple instances of the same attribute name - * and extra attributes are to be treated as an error. We can - * remember only one instance. - */ - if (htable_locate(table, STR(plain_buf)) != 0) { - if (flags & ATTR_FLAG_EXTRA) { - msg_warn("multiple instances of attribute %s from %s", - STR(plain_buf), VSTREAM_PATH(stream)); - return (attr_count); - } - } else { - htable_enter(table, STR(plain_buf), mystrdup(attr_value)); - } - } -} - -/* attr_conv_string - convert attribute value field to string */ - -static int attr_conv_string(char **src, VSTRING *plain_buf, - const char *attr_name) -{ - char *myname = "attr_table_get"; - extern int var_line_limit; - int limit = var_line_limit * 5 / 4; - char *cp = *src; - int len = 0; - int ch; - - for (;;) { - if ((ch = *(unsigned char *) cp) == 0) - break; - cp++; - if (ch == ':') - break; - len++; - if (len > limit) { - msg_warn("%s: string length > %d characters in attribute %s", - myname, limit, attr_name); - return (-1); - } - } - if (BASE64_DECODE(plain_buf, *src, len) == 0) { - msg_warn("%s: malformed base64 data in attribute %s: %.*s", - myname, attr_name, len > 100 ? 100 : len, *src); - return (-1); - } - if (msg_verbose) - msg_info("%s: name %s value %s", myname, attr_name, STR(plain_buf)); - - *src = cp; - return (ch); -} - -/* attr_conv_number - convert attribute value field to number */ - -static int attr_conv_number(char **src, unsigned *dst, VSTRING *plain_buf, - const char *attr_name) -{ - char *myname = "attr_table_get"; - char junk = 0; - int ch; - - if ((ch = attr_conv_string(src, plain_buf, attr_name)) < 0) - return (-1); - if (sscanf(STR(plain_buf), "%u%c", dst, &junk) != 1 || junk != 0) { - msg_warn("%s: malformed numerical data in attribute %s: %.100s", - myname, attr_name, STR(plain_buf)); - return (-1); - } - return (ch); -} - -/* attr_table_vget - recover attributes from table */ - -int attr_table_vget(ATTR_TABLE *attr, int flags, va_list ap) -{ - char *myname = "attr_table_get"; - int attr_count; - char *attr_name; - char *attr_value; - int attr_type; - int *number; - VSTRING *string; - INTV *number_array; - ARGV *string_array; - unsigned num_val; - int ch; - - if (base64_buf == 0) { - base64_buf = vstring_alloc(10); - plain_buf = vstring_alloc(10); - } - - /* - * Iterate over all (type, name, value) triples. - */ - for (attr_count = 0; /* void */ ; attr_count++) { - - /* - * Determine the next attribute name on the caller's wish list. - */ - attr_type = va_arg(ap, int); - if (attr_type == ATTR_TYPE_END) - return (attr_count); - attr_name = va_arg(ap, char *); - - /* - * Look up the attribute value. Peel off, but keep, the separator - * between name and value. - */ - if ((attr_value = htable_find(attr, attr_name)) == 0) { - if (attr_type != ATTR_TYPE_END - && (flags & ATTR_FLAG_MISSING) != 0) - msg_warn("%s: missing attribute %s", myname, attr_name); - return (attr_count); - } - if ((ch = *(unsigned char *) attr_value) != 0) - attr_value++; - - /* - * Do the requested conversion. If the target attribute is a - * non-array type, disallow sending a multi-valued attribute, and - * disallow sending no value. If the target attribute is an array - * type, allow the sender to send a zero-element array (i.e. no value - * at all). XXX Need to impose a bound on the number of array - * elements. - */ - switch (attr_type) { - case ATTR_TYPE_NUM: - if (ch != ':') { - msg_warn("%s: missing value for attribute %s", - myname, attr_name); - return (attr_count); - } - number = va_arg(ap, int *); - if ((ch = attr_conv_number(&attr_value, number, plain_buf, attr_name)) < 0) - return (attr_count); - if (ch != '\0') { - msg_warn("%s: too many values for attribute %s", - myname, attr_name); - return (attr_count); - } - break; - case ATTR_TYPE_STR: - if (ch != ':') { - msg_warn("%s: missing value for attribute %s", - myname, attr_name); - return (attr_count); - } - string = va_arg(ap, VSTRING *); - if ((ch = attr_conv_string(&attr_value, string, attr_name)) < 0) - return (attr_count); - if (ch != '\0') { - msg_warn("%s: too many values for attribute %s", - myname, attr_name); - return (attr_count); - } - break; - case ATTR_TYPE_NUM_ARRAY: - number_array = va_arg(ap, INTV *); - while (ch != '\0') { - if ((ch = attr_conv_number(&attr_value, &num_val, plain_buf, attr_name)) < 0) - return (attr_count); - intv_add(number_array, 1, num_val); - } - break; - case ATTR_TYPE_STR_ARRAY: - string_array = va_arg(ap, ARGV *); - while (ch != '\0') { - if ((ch = attr_conv_string(&attr_value, plain_buf, attr_name)) < 0) - return (attr_count); - argv_add(string_array, STR(plain_buf), (char *) 0); - } - break; - default: - msg_panic("%s: unknown type code: %d", myname, attr_type); - } - } -} - -/* attr_table_get - recover attributes from table */ - -int attr_table_get(ATTR_TABLE *attr, int flags,...) -{ - va_list ap; - int ret; - - va_start(ap, flags); - ret = attr_table_vget(attr, flags, ap); - va_end(ap); - - return (ret); -} - -#ifdef TEST - - /* - * Proof of concept test program. Mirror image of the attr_scan test - * program. - */ -#include - -int var_line_limit = 2048; - -int main(int unused_argc, char **used_argv) -{ - ATTR_TABLE *attr; - INTV *intv = intv_alloc(1); - ARGV *argv = argv_alloc(1); - VSTRING *str_val = vstring_alloc(1); - int int_val; - int ret; - int i; - - msg_verbose = 1; - msg_vstream_init(used_argv[0], VSTREAM_ERR); - attr = attr_table_create(1); - if (attr_table_read(attr, ATTR_FLAG_EXTRA, VSTREAM_IN) > 0 - && (ret = attr_table_get(attr, - ATTR_FLAG_MISSING, - ATTR_TYPE_NUM, ATTR_NAME_NUM, &int_val, - ATTR_TYPE_STR, ATTR_NAME_STR, str_val, - ATTR_TYPE_NUM_ARRAY, ATTR_NAME_NUM_ARRAY, intv, - ATTR_TYPE_STR_ARRAY, ATTR_NAME_STR_ARRAY, argv, - ATTR_TYPE_END)) == 4) { - vstream_printf("%s %d\n", ATTR_NAME_NUM, int_val); - vstream_printf("%s %s\n", ATTR_NAME_STR, STR(str_val)); - vstream_printf("%s", ATTR_NAME_NUM_ARRAY); - for (i = 0; i < intv->intc; i++) - vstream_printf(" %d", intv->intv[i]); - vstream_printf("\n"); - vstream_printf("%s", ATTR_NAME_STR_ARRAY); - for (i = 0; i < argv->argc; i++) - vstream_printf(" %s", argv->argv[i]); - vstream_printf("\n"); - } else { - vstream_printf("return: %d\n", ret); - } - if (vstream_fflush(VSTREAM_OUT) != 0) - msg_fatal("write error: %m"); - - attr_table_free(attr); - intv_free(intv); - argv_free(argv); - vstring_free(str_val); - - return (0); -} - -#endif