Carlos Velasco via Postfix-users: > > Thus, the Postfix code that handles header update/delete requests > > was still naively skipping the first header, making calls to delete > > the prepended Received-SPF: header ineffective, and mis-directing > > calls to delete the first Milter-visible Received: header, instead > > deleting the invisible Postfix-generated Received: header (wtf). > > > > To maintain protocol compatibility, the Postfix code that handles > > header update/delete requests will need to skip the Postfix-generated > > Received: header, instead of the first message header. > > > > Once that mess is handled with, we can consider adding a flag to > > expose Postfix-generated Received: headers to Milters. > > > I think you are absolutely correct in your analysis. > I've been looking over the code and, although there is a lot I > still don't understand, your yesterday patch seems more a (good) > workaround to the real problem.
Below is a fix that does not break any of the already existng tests :-) and that passes some new tests that I added for this specific case. There is no difference when adding or inserting a header, only when updating or deleting. With this, no change is needed to the Postfix SMTP daemon. It is safe to prepend headers with a Postfix access table or with header/body_checks. They can be deleted or updated as expected. The patch does not include changes to Postfix tests. Wietse --- /var/tmp/postfix-3.9-20231210/src/cleanup/cleanup_milter.c 2023-03-10 09:06:42.000000000 -0500 +++ src/cleanup/cleanup_milter.c 2023-12-12 19:43:50.092647169 -0500 @@ -119,6 +119,7 @@ #include <dsn_util.h> #include <xtext.h> #include <info_log_addr_form.h> +#include <header_opts.h> /* Application-specific. */ @@ -754,14 +755,26 @@ */ } +/* hidden_header - respect milter header hiding protocol */ + +static int hidden_header(VSTRING *buf, ARGV *auto_hdrs, int *hide_done) +{ + char **cpp; + int mask; + + for (cpp = auto_hdrs->argv, mask = 1; *cpp; cpp++, mask <<= 1) + if ((*hide_done & mask) == 0 && strncmp(*cpp, STR(buf), LEN(buf)) == 0) + return (*hide_done |= mask); + return (0); +} + /* cleanup_find_header_start - find specific header instance */ static off_t cleanup_find_header_start(CLEANUP_STATE *state, ssize_t index, const char *header_label, VSTRING *buf, int *prec_type, - int allow_ptr_backup, - int skip_headers) + int allow_ptr_backup) { const char *myname = "cleanup_find_header_start"; off_t curr_offset; /* offset after found record */ @@ -770,7 +783,7 @@ int rec_type = REC_TYPE_ERROR; int last_type; ssize_t len; - int hdr_count = 0; + int hide_done = 0; if (msg_verbose) msg_info("%s: index %ld name \"%s\"", @@ -912,11 +925,10 @@ break; } /* This the start of a message header. */ - else if (hdr_count++ < skip_headers) - /* Reset the saved PTR record and update last_type. */ ; else if ((header_label == 0 || (strncasecmp(header_label, STR(buf), len) == 0 - && (strlen(header_label) == len))) + && (strlen(header_label) == len) + && !hidden_header(buf, state->auto_hdrs, &hide_done))) && --index == 0) { /* If we have a saved PTR record, it points to start of header. */ break; @@ -1182,15 +1194,12 @@ */ #define NO_HEADER_NAME ((char *) 0) #define ALLOW_PTR_BACKUP 1 -#define SKIP_ONE_HEADER 1 -#define DONT_SKIP_HEADERS 0 if (index < 1) index = 1; old_rec_offset = cleanup_find_header_start(state, index, NO_HEADER_NAME, old_rec_buf, &old_rec_type, - ALLOW_PTR_BACKUP, - DONT_SKIP_HEADERS); + ALLOW_PTR_BACKUP); if (old_rec_offset == CLEANUP_FIND_HEADER_IOERROR) /* Warning and errno->error mapping are done elsewhere. */ CLEANUP_INS_HEADER_RETURN(cleanup_milter_error(state, 0)); @@ -1270,8 +1279,7 @@ rec_buf = vstring_alloc(100); old_rec_offset = cleanup_find_header_start(state, index, new_hdr_name, rec_buf, &last_type, - NO_PTR_BACKUP, - SKIP_ONE_HEADER); + NO_PTR_BACKUP); if (old_rec_offset == CLEANUP_FIND_HEADER_IOERROR) /* Warning and errno->error mapping are done elsewhere. */ CLEANUP_UPD_HEADER_RETURN(cleanup_milter_error(state, 0)); @@ -1333,8 +1341,7 @@ rec_buf = vstring_alloc(100); header_offset = cleanup_find_header_start(state, index, hdr_name, rec_buf, - &last_type, NO_PTR_BACKUP, - SKIP_ONE_HEADER); + &last_type, NO_PTR_BACKUP); if (header_offset == CLEANUP_FIND_HEADER_IOERROR) /* Warning and errno->error mapping are done elsewhere. */ CLEANUP_DEL_HEADER_RETURN(cleanup_milter_error(state, 0)); _______________________________________________ Postfix-users mailing list -- postfix-users@postfix.org To unsubscribe send an email to postfix-users-le...@postfix.org