From: Wietse Venema Date: Sat, 2 Apr 2005 05:00:00 +0000 (-0500) Subject: postfix-2.3-20050402 X-Git-Tag: v2.3-RC1~85 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=e060cb9490787856d6c10b6d8adbdf44398c3165;p=thirdparty%2Fpostfix.git postfix-2.3-20050402 --- diff --git a/postfix/.indent.pro b/postfix/.indent.pro index 08e5e99d6..984448ac3 100644 --- a/postfix/.indent.pro +++ b/postfix/.indent.pro @@ -120,6 +120,7 @@ -TMIME_INFO -TMIME_STACK -TMIME_STATE +-TMIME_STATE_DETAIL -TMIME_TOKEN -TMKMAP -TMKMAP_DB diff --git a/postfix/HISTORY b/postfix/HISTORY index 16e094cb3..404cecfcc 100644 --- a/postfix/HISTORY +++ b/postfix/HISTORY @@ -10588,6 +10588,24 @@ Apologies for any names omitted. dsn_vstring_update() module. File: global/dsn_util.h, global/pipe_command.c. +20050401 + + Cleanup: ignore incorrect enhanced status codes (such as + 5xx reply followed by a 4.x.x status), and don't look for + enhanced status codes unless the server replies with a + [245]XX reply. Files: smtp/smtp_chat.c, lmtp/lmtp_chat.c. + +20050402 + + Feature: enhanced status code support for errors found by + the MIME processor. Files: global/mime_state.c, + cleanup/cleanup_message.c, smtp/smtp_proto.c. + + Cleanup: updated error messages about MIME processing + errors in the SMTP client. These errors are no longer + specific to 8bit->7bit conversion; they can also happen + with generic address mapping. File: smtp/smtp_proto.c. + Open problems: Med: disable header address rewriting after XCLIENT? diff --git a/postfix/src/cleanup/cleanup_message.c b/postfix/src/cleanup/cleanup_message.c index 51be87e99..f8524f749 100644 --- a/postfix/src/cleanup/cleanup_message.c +++ b/postfix/src/cleanup/cleanup_message.c @@ -697,6 +697,7 @@ static void cleanup_message_headerbody(CLEANUP_STATE *state, int type, const char *buf, int len) { char *myname = "cleanup_message_headerbody"; + MIME_STATE_DETAIL *detail; /* * Copy text record to the output. @@ -715,7 +716,8 @@ static void cleanup_message_headerbody(CLEANUP_STATE *state, int type, state->mime_errs &= ~MIME_ERR_TRUNC_HEADER; if (state->mime_errs && state->reason == 0) { state->errs |= CLEANUP_STAT_CONT; - state->reason = mystrdup(mime_state_error(state->mime_errs)); + detail = mime_state_detail(state->mime_errs); + state->reason = dsn_prepend(detail->dsn, detail->text); } state->mime_state = mime_state_free(state->mime_state); if ((state->xtra_offset = vstream_ftell(state->dst)) < 0) diff --git a/postfix/src/global/mail_version.h b/postfix/src/global/mail_version.h index 1fb39eadc..66f9a453b 100644 --- a/postfix/src/global/mail_version.h +++ b/postfix/src/global/mail_version.h @@ -20,7 +20,7 @@ * Patches change the patchlevel and the release date. Snapshots change the * release date only. */ -#define MAIL_RELEASE_DATE "20050401" +#define MAIL_RELEASE_DATE "20050402" #define MAIL_VERSION_NUMBER "2.3" #define VAR_MAIL_VERSION "mail_version" diff --git a/postfix/src/global/mime_state.c b/postfix/src/global/mime_state.c index f5bd56056..409e1231d 100644 --- a/postfix/src/global/mime_state.c +++ b/postfix/src/global/mime_state.c @@ -32,6 +32,17 @@ /* /* const char *mime_state_error(error_code) /* int error_code; +/* +/* typedef struct { +/* .in +4 +/* const int code; /* internal error code */ +/* const char *dsn; /* RFC 3463 */ +/* const char *text; /* descriptive text */ +/* .in -4 +/* } MIME_STATE_DETAIL; +/* +/* MIME_STATE_DETAIL *mime_state_detail(error_code) +/* int error_code; /* DESCRIPTION /* This module implements a one-pass MIME processor with optional /* 8-bit to quoted-printable conversion. @@ -70,6 +81,11 @@ /* specified error code. When multiple errors are specified it /* reports what it deems the most serious one. /* +/* mime_state_detail() returns a table entry with error +/* information for the specified error code. When multiple +/* errors are specified it reports what it deems the most +/* serious one. +/* /* Arguments: /* .IP body_out /* The output routine for body lines. It receives unmodified input @@ -1015,27 +1031,51 @@ int mime_state_update(MIME_STATE *state, int rec_type, } } + /* + * Mime error to (DSN, text) mapping. Order matters; more serious errors + * must precede less serious errors, because the error-to-text conversion + * can report only one error. + */ +static MIME_STATE_DETAIL mime_err_detail[] = { + MIME_ERR_NESTING, "5.6.0", "MIME nesting exceeds safety limit", + MIME_ERR_TRUNC_HEADER, "5.6.0", "message header length exceeds safety limit", + MIME_ERR_8BIT_IN_HEADER, "5.6.0", "improper use of 8-bit data in message header", + MIME_ERR_8BIT_IN_7BIT_BODY, "5.6.0", "improper use of 8-bit data in message body", + MIME_ERR_ENCODING_DOMAIN, "5.6.0", "invalid message/* or multipart/* encoding domain", + 0, +}; + /* mime_state_error - error code to string */ const char *mime_state_error(int error_code) { + MIME_STATE_DETAIL *mp; + if (error_code == 0) msg_panic("mime_state_error: there is no error"); - if (error_code & MIME_ERR_NESTING) - return ("MIME nesting exceeds safety limit"); - if (error_code & MIME_ERR_TRUNC_HEADER) - return ("message header length exceeds safety limit"); - if (error_code & MIME_ERR_8BIT_IN_HEADER) - return ("improper use of 8-bit data in message header"); - if (error_code & MIME_ERR_8BIT_IN_7BIT_BODY) - return ("improper use of 8-bit data in message body"); - if (error_code & MIME_ERR_ENCODING_DOMAIN) - return ("invalid message/* or multipart/* encoding domain"); + for (mp = mime_err_detail; mp->code; mp++) + if (mp->code & error_code) + return (mp->text); msg_panic("mime_state_error: unknown error code %d", error_code); } +/* mime_state_detail - error code to table entry with assorted data */ + +MIME_STATE_DETAIL *mime_state_detail(int error_code) +{ + MIME_STATE_DETAIL *mp; + + if (error_code == 0) + msg_panic("mime_state_detail: there is no error"); + for (mp = mime_err_detail; mp->code; mp++) + if (mp->code & error_code) + return (mp); + msg_panic("mime_state_detail: unknown error code %d", error_code); +} + #ifdef TEST +#include #include #include #include diff --git a/postfix/src/global/mime_state.h b/postfix/src/global/mime_state.h index a3318c881..820be4288 100644 --- a/postfix/src/global/mime_state.h +++ b/postfix/src/global/mime_state.h @@ -33,7 +33,6 @@ typedef void (*MIME_STATE_ERR_PRINT) (void *, int, const char *); extern MIME_STATE *mime_state_alloc(int, MIME_STATE_HEAD_OUT, MIME_STATE_ANY_END, MIME_STATE_BODY_OUT, MIME_STATE_ANY_END, MIME_STATE_ERR_PRINT, void *); extern int mime_state_update(MIME_STATE *, int, const char *, int); extern MIME_STATE *mime_state_free(MIME_STATE *); -extern const char *mime_state_error(int); /* * Processing options. @@ -58,12 +57,21 @@ extern const char *mime_state_error(int); /* * Processing errors, not necessarily lethal. */ +typedef struct { + const int code; /* internal error code */ + const char *dsn; /* RFC 3463 */ + const char *text; /* descriptive text */ +} MIME_STATE_DETAIL; + #define MIME_ERR_NESTING (1<<0) #define MIME_ERR_TRUNC_HEADER (1<<1) #define MIME_ERR_8BIT_IN_HEADER (1<<2) #define MIME_ERR_8BIT_IN_7BIT_BODY (1<<3) #define MIME_ERR_ENCODING_DOMAIN (1<<4) +extern MIME_STATE_DETAIL *mime_state_detail(int); +extern const char *mime_state_error(int); + /* * Header classes. Look at the header_opts argument to find out if something * is a MIME header in a primary or nested section. diff --git a/postfix/src/lmtp/lmtp_chat.c b/postfix/src/lmtp/lmtp_chat.c index f42790691..170e7f9dd 100644 --- a/postfix/src/lmtp/lmtp_chat.c +++ b/postfix/src/lmtp/lmtp_chat.c @@ -232,17 +232,23 @@ LMTP_RESP *lmtp_chat_resp(LMTP_STATE *state) /* * Extract RFC 821 reply code and RFC 2034 detail code. Use a default * detail code if none was given. + * + * Ignore out-of-protocol enhanced status codes: codes that accompany 3XX + * replies, or codes whose initial digit is out of sync with the reply + * code. */ DSN_CLASS(rdata.dsn) = 0; if (three_digs != 0) { rdata.code = atoi(STR(state->buffer)); - for (cp = STR(state->buffer) + 4; *cp == ' '; cp++) - /* void */ ; - if ((len = dsn_valid(cp)) > 0) { - DSN_UPDATE(rdata.dsn, cp, len); - } else if (strchr("245", STR(state->buffer)[0]) != 0) { - DSN_UPDATE(rdata.dsn, "0.0.0", sizeof("0.0.0") - 1); - DSN_CLASS(rdata.dsn) = STR(state->buffer)[0]; + if (strchr("245", STR(state->buffer)[0]) != 0) { + for (cp = STR(state->buffer) + 4; *cp == ' '; cp++) + /* void */ ; + if ((len = dsn_valid(cp)) > 0 && *cp == *STR(state->buffer)) { + DSN_UPDATE(rdata.dsn, cp, len); + } else { + DSN_UPDATE(rdata.dsn, "0.0.0", sizeof("0.0.0") - 1); + DSN_CLASS(rdata.dsn) = STR(state->buffer)[0]; + } } } else { rdata.code = 0; diff --git a/postfix/src/smtp/smtp_chat.c b/postfix/src/smtp/smtp_chat.c index 889ce0fe1..aad0929a9 100644 --- a/postfix/src/smtp/smtp_chat.c +++ b/postfix/src/smtp/smtp_chat.c @@ -255,17 +255,23 @@ SMTP_RESP *smtp_chat_resp(SMTP_SESSION *session) /* * Extract RFC 821 reply code and RFC 2034 detail. Use a default detail * code if none was given. + * + * Ignore out-of-protocol enhanced status codes: codes that accompany 3XX + * replies, or codes whose initial digit is out of sync with the reply + * code. */ DSN_CLASS(rdata.dsn) = 0; if (three_digs != 0) { rdata.code = atoi(STR(session->buffer)); - for (cp = STR(session->buffer) + 4; *cp == ' '; cp++) - /* void */ ; - if ((len = dsn_valid(cp)) > 0) { - DSN_UPDATE(rdata.dsn, cp, len); - } else if (strchr("245", STR(session->buffer)[0]) != 0) { - DSN_UPDATE(rdata.dsn, "0.0.0", sizeof("0.0.0") - 1); - DSN_CLASS(rdata.dsn) = STR(session->buffer)[0]; + if (strchr("245", STR(session->buffer)[0]) != 0) { + for (cp = STR(session->buffer) + 4; *cp == ' '; cp++) + /* void */ ; + if ((len = dsn_valid(cp)) > 0 && *cp == *STR(session->buffer)) { + DSN_UPDATE(rdata.dsn, cp, len); + } else { + DSN_UPDATE(rdata.dsn, "0.0.0", sizeof("0.0.0") - 1); + DSN_CLASS(rdata.dsn) = STR(session->buffer)[0]; + } } } else { rdata.code = 0; diff --git a/postfix/src/smtp/smtp_proto.c b/postfix/src/smtp/smtp_proto.c index 1cfbb6815..3ab9eac2b 100644 --- a/postfix/src/smtp/smtp_proto.c +++ b/postfix/src/smtp/smtp_proto.c @@ -819,6 +819,7 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, NOCLOBBER int mail_from_rejected; NOCLOBBER int downgrading; int mime_errs; + MIME_STATE_DETAIL *detail; /* * Macros for readability. @@ -1378,9 +1379,9 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, vstring_str(session->scratch), VSTRING_LEN(session->scratch)); if (mime_errs) { - smtp_mesg_fail(state, "5.6.5", 554, - "MIME 7-bit conversion failed: %s", - mime_state_error(mime_errs)); + detail = mime_state_detail(mime_errs); + smtp_mesg_fail(state, detail->dsn, 554, "%s", + detail->text); RETURN(0); } } @@ -1396,13 +1397,14 @@ static int smtp_loop(SMTP_STATE *state, NOCLOBBER int send_state, * ending in newline via /usr/sbin/sendmail while MIME input * processing is turned off, and MIME 8bit->7bit conversion * is requested upon delivery. + * + * Or some error while doing generic address mapping. */ mime_errs = mime_state_update(session->mime_state, rec_type, "", 0); if (mime_errs) { - smtp_mesg_fail(state, "5.6.5", 554, - "MIME 7-bit conversion failed: %s", - mime_state_error(mime_errs)); + detail = mime_state_detail(mime_errs); + smtp_mesg_fail(state, detail->dsn, 554, "%s", detail->text); RETURN(0); } } else if (prev_type == REC_TYPE_CONT) /* missing newline */ diff --git a/postfix/src/util/Makefile.in b/postfix/src/util/Makefile.in index 34685b848..17917a2c2 100644 --- a/postfix/src/util/Makefile.in +++ b/postfix/src/util/Makefile.in @@ -392,6 +392,12 @@ inet_proto: $(LIB) stream_test: stream_test.c $(LIB) $(CC) $(CFLAGS) -o $@ $@.c $(LIB) $(SYSLIBS) +gcctest: gccw.c gccw.ref + rm -f gccw.o + make gccw.o 2>&1 | sed "s/\`/'/g; s/return-/return /" | sort >gccw.tmp + diff gccw.ref gccw.tmp + rm -f gccw.o gccw.tmp + tests: valid_hostname_test mac_expand_test dict_test unescape_test \ hex_quote_test ctable_test inet_addr_list_test base64_code_test \ attr_scan64_test attr_scan0_test dict_pcre_test host_port_test \ diff --git a/postfix/src/util/gccw.c b/postfix/src/util/gccw.c new file mode 100644 index 000000000..d3421fe59 --- /dev/null +++ b/postfix/src/util/gccw.c @@ -0,0 +1,58 @@ + /* + * This is is a regression test for all the things that gcc is meant to warn + * about. + * + * gcc version 3 breaks several tests: + * + * -W does not report missing return value + * + * -Wunused does not report unused parameter + */ + +#include +#include + +jmp_buf jbuf; + + /* -Wmissing-prototypes: no previous prototype for 'test1' */ + /* -Wimplicit: return type defaults to `int' */ +test1(void) +{ + /* -Wunused: unused variable `foo' */ + int foo; + + /* -Wparentheses: suggest parentheses around && within || */ + printf("%d\n", 1 && 2 || 3 && 4); + /* -W: statement with no effect */ + 0; + /* BROKEN in gcc 3 */ + /* -W: control reaches end of non-void function */ +} + + + /* -W??????: unused parameter `foo' */ +void test2(int foo) +{ + enum { + a = 10, b = 15} moe; + int bar; + + /* -Wuninitialized: 'bar' might be used uninitialized in this function */ + /* -Wformat: format argument is not a pointer (arg 2) */ + printf("%s\n", bar); + /* -Wformat: too few arguments for format */ + printf("%s%s\n", "bar"); + /* -Wformat: too many arguments for format */ + printf("%s\n", "bar", "bar"); + + /* -Wswitch: enumeration value `b' not handled in switch */ + switch (moe) { + case a: + return; + } +} + + /* -Wstrict-prototypes: function declaration isn't a prototype */ +void test3() +{ +} diff --git a/postfix/src/util/gccw.ref b/postfix/src/util/gccw.ref new file mode 100644 index 000000000..7616c2995 --- /dev/null +++ b/postfix/src/util/gccw.ref @@ -0,0 +1,18 @@ +gcc -Wall -Wno-comment -Wformat -Wimplicit -Wmissing-prototypes -Wparentheses -Wstrict-prototypes -Wswitch -Wuninitialized -Wunused -DUSE_TLS -DHAS_PCRE -I/usr/local/include -DSNAPSHOT -g -O -I. -DFREEBSD5 -c gccw.c +gccw.c: At top level: +gccw.c: At top level: +gccw.c: In function 'test1': +gccw.c: In function 'test2': +gccw.c:20: warning: no previous prototype for 'test1' +gccw.c:20: warning: return type defaults to 'int' +gccw.c:22: warning: unused variable 'foo' +gccw.c:25: warning: suggest parentheses around && within || +gccw.c:27: warning: statement with no effect +gccw.c:30: warning: control reaches end of non-void function +gccw.c:35: warning: no previous prototype for 'test2' +gccw.c:38: warning: 'bar' might be used uninitialized in this function +gccw.c:42: warning: format argument is not a pointer (arg 2) +gccw.c:44: warning: too few arguments for format +gccw.c:46: warning: too many arguments for format +gccw.c:52: warning: enumeration value 'b' not handled in switch +gccw.c:57: warning: function declaration isn't a prototype