This patch combines several fixes that were already part of last week's snapshot releases. - RFC 822 requires the presence of at least one destination message header. Postfix now generates a generic "To: undisclosed-recipients:;" message header when no destination header is present. The header content is specified with the new undisclosed_recipients_header parameter. - Postfix now understands <(comment)> as SMTP MAIL FROM address, because some broken software needs it. Postfix rejects such illegal address forms with "strict_rfc821_envelopes = yes". - Configuration parameters for one mysql dictionary would become default settings for the next one. This patch was merged into the development Postfix version a while back but apparently that version was on a dead branch. Update by Scott Cotton. - Some Postfix delivery agents would abort on addresses of the form `stuff@.' which could unfortunately be generated locally. - With local delivery, Postfix could insert > or . into the middle of very long lines. - SMTP sessions could time out when the remote client attempted to deliver to a large number of rejected recipients. The SMTP server now flushes unwritten output in-between tarpit delays, to avoid protocol timeouts in pipelined SMTP sessions. - Postfix would incorrectly reject domain names with adjacent `-' characters. A fully-patched version of the source code is being made available via the usual FTP servers, primary site: ftp://ftp.porcupine.org/mirrors/postfix-release/official/ Files: postfix-19991231-patch07.gz, postfix-19991231-pl07.tar.gz and postfix-19991231-pl07.tar.gz.sig. Or, if you use a web browser, ftp://ftp.porcupine.org/mirrors/postfix-release/index.html Happy Postfixing. Wietse Prereq: "Postfix-19991231-pl06" diff -cr ../postfix-19991231-pl06/global/mail_version.h ./global/mail_version.h *** ../postfix-19991231-pl06/global/mail_version.h Tue Mar 28 09:30:17 2000 --- ./global/mail_version.h Thu Apr 13 14:47:12 2000 *************** *** 15,21 **** * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "Postfix-19991231-pl06" extern char *var_mail_version; /* LICENSE --- 15,21 ---- * Version of this program. */ #define VAR_MAIL_VERSION "mail_version" ! #define DEF_MAIL_VERSION "Postfix-19991231-pl07" extern char *var_mail_version; /* LICENSE diff -cr ../postfix-19991231-pl06/HISTORY ./HISTORY *** ../postfix-19991231-pl06/HISTORY Tue Mar 28 09:34:44 2000 --- ./HISTORY Thu May 11 20:40:06 2000 *************** *** 3670,3672 **** --- 3670,3715 ---- be issued in an SMTP session (ex.: NOOP, VRFY, ETRN, RSET). Problem report by Michael Ju. Tokarev @ tls.msk.ru. Files: global/mail_params.h, smtpd/smtpd.c. + + 20000413 + + Bugfix: RFC 822 requires the presence of at least one + destination message header. The cleanup daemon now generates + a generic "To: undisclosed-recipients:;" message header + when no destination header is present. The header content + is specified with the undisclosed_recipients_header parameter. + Problem pointed out by Geoff Gibbs, UK-Human Genome Mapping + Project-Resource Centre. + + 20000416 + + Workaround: allow <(comment)> as SMTP MAIL FROM address. + + 20000423 + + Bugfix: mail_copy() could prepend > or . in the middle of + long lines. Found by code inspection. + + 20000505 + + Bugfix: the SMTP server now flushes unwritten output before + tarpit delays, to avoid protocol timeouts in pipelined + sessions when a client causes lots of errors. Found by + Lamont Jones, HP. File: smtpd/smtpd_chat.c. + + 20000510 + + Bugfix: configuration parameters for one mysql dictionary + would become default settings for the next one. File: + dict_mysql.c. This patch was merged into Postfix a while + back but apparently that Postfix version was nuked when + other parts were redesigned. Update by Scott Cotton. + + Bugfix: some Postfix delivery agents would abort on addresses + of the form `stuff@.' which could be generated only locally. + Found by Patrik Rak. File: trivial-rewrite/resolve.c. + + 20000511 + + Bugfix: Postfix would incorrectly reject domain names with + adjacent - characters. File: util/valid_hostname.c. diff -cr ../postfix-19991231-pl06/INSTALL.sh ./INSTALL.sh *** ../postfix-19991231-pl06/INSTALL.sh Thu Mar 30 10:12:21 2000 --- ./INSTALL.sh Thu Apr 13 13:22:33 2000 *************** *** 332,337 **** --- 332,338 ---- for file in man?/* do (test -f $MANPAGES/$file && cmp -s $file $MANPAGES/$file) || { + echo Updating $MANPAGES/$file... rm -f $MANPAGES/$file cp $file $MANPAGES/$file || exit 1 chmod 644 $MANPAGES/$file || exit 1 diff -cr ../postfix-19991231-pl06/RELEASE_NOTES ./RELEASE_NOTES *** ../postfix-19991231-pl06/RELEASE_NOTES Thu Mar 30 10:06:56 2000 --- ./RELEASE_NOTES Thu May 11 19:40:45 2000 *************** *** 1,3 **** --- 1,11 ---- + Incompatible changes with postfix-19991231-pl07: + ================================================ + + As required by RFC 822, Postfix now inserts a generic destination + message header when no destination header is present. The text is + specified via the undisclosed_recipients_header configuration + parameter (default: "To: undisclosed-recipients:;"). + Incompatible changes with postfix-19991231-pl06: ================================================ diff -cr ../postfix-19991231-pl06/cleanup/cleanup.c ./cleanup/cleanup.c *** ../postfix-19991231-pl06/cleanup/cleanup.c Sun Jan 30 11:09:16 2000 --- ./cleanup/cleanup.c Thu Apr 13 13:39:10 2000 *************** *** 13,19 **** /* The \fBcleanup\fR daemon always performs the following transformations: /* .IP \(bu /* Insert missing message headers: (\fBResent-\fR) \fBFrom:\fR, ! /* \fBMessage-Id:\fR, and \fBDate:\fR. /* .IP \(bu /* Extract envelope recipient addresses from (\fBResent-\fR) \fBTo:\fR, /* \fBCc:\fR and \fBBcc:\fR message headers when no recipients are --- 13,19 ---- /* The \fBcleanup\fR daemon always performs the following transformations: /* .IP \(bu /* Insert missing message headers: (\fBResent-\fR) \fBFrom:\fR, ! /* \fBTo:\fR, \fBMessage-Id:\fR, and \fBDate:\fR. /* .IP \(bu /* Extract envelope recipient addresses from (\fBResent-\fR) \fBTo:\fR, /* \fBCc:\fR and \fBBcc:\fR message headers when no recipients are *************** *** 67,72 **** --- 67,75 ---- /* Address to send a copy of each message that enters the system. /* .IP \fBhopcount_limit\fR /* Limit the number of \fBReceived:\fR message headers. + /* .IP \fBrecipients_witheld_header\fR + /* The header line that is inserted when no recipients were + /* specified in (Resent-)To: or (Resent-)Cc: message headers. /* .SH "Address transformations" /* .ad /* .fi *************** *** 177,182 **** --- 180,186 ---- int var_delay_warn_time; /* delay that triggers warning */ char *var_prop_extension; /* propagate unmatched extension */ char *var_always_bcc; + char *var_rcpt_witheld; /* recipients not disclosed */ /* * Mappings. *************** *** 471,476 **** --- 475,481 ---- VAR_HEADER_CHECKS, DEF_HEADER_CHECKS, &var_header_checks, 0, 0, VAR_PROP_EXTENSION, DEF_PROP_EXTENSION, &var_prop_extension, 0, 0, VAR_ALWAYS_BCC, DEF_ALWAYS_BCC, &var_always_bcc, 0, 0, + VAR_RCPT_WITHELD, DEF_RCPT_WITHELD, &var_rcpt_witheld, 1, 0, 0, }; diff -cr ../postfix-19991231-pl06/cleanup/cleanup_message.c ./cleanup/cleanup_message.c *** ../postfix-19991231-pl06/cleanup/cleanup_message.c Sun Jan 30 13:22:04 2000 --- ./cleanup/cleanup_message.c Thu Apr 13 17:23:31 2000 *************** *** 350,355 **** --- 350,364 ---- cleanup_resent, vstring_str(cleanup_temp1)); } } + + /* + * Add a missing destination header. + */ + #define VISIBLE_RCPT ((1 << HDR_TO) | (1 << HDR_RESENT_TO) | \ + (1 << HDR_CC) | (1 << HDR_RESENT_CC)) + + if ((cleanup_headers_seen & VISIBLE_RCPT) == 0) + cleanup_out_format(REC_TYPE_NORM, "%s", var_rcpt_witheld); } /* cleanup_message - process message content segment */ diff -cr ../postfix-19991231-pl06/global/mail_copy.c ./global/mail_copy.c *** ../postfix-19991231-pl06/global/mail_copy.c Tue Nov 9 10:44:45 1999 --- ./global/mail_copy.c Thu May 11 20:05:01 2000 *************** *** 166,175 **** if (type != REC_TYPE_NORM && type != REC_TYPE_CONT) break; bp = vstring_str(buf); ! if ((flags & MAIL_COPY_QUOTE) && *bp == 'F' && !strncmp(bp, "From ", 5)) ! VSTREAM_PUTC('>', dst); ! if ((flags & MAIL_COPY_DOT) && *bp == '.') ! VSTREAM_PUTC('.', dst); if (VSTRING_LEN(buf) && VSTREAM_FWRITE_BUF(dst, buf) != VSTRING_LEN(buf)) break; if (type == REC_TYPE_NORM && VSTREAM_PUTC('\n', dst) == VSTREAM_EOF) --- 166,177 ---- if (type != REC_TYPE_NORM && type != REC_TYPE_CONT) break; bp = vstring_str(buf); ! if (prev_type == REC_TYPE_NORM) { ! if ((flags & MAIL_COPY_QUOTE) && *bp == 'F' && !strncmp(bp, "From ", 5)) ! VSTREAM_PUTC('>', dst); ! if ((flags & MAIL_COPY_DOT) && *bp == '.') ! VSTREAM_PUTC('.', dst); ! } if (VSTRING_LEN(buf) && VSTREAM_FWRITE_BUF(dst, buf) != VSTRING_LEN(buf)) break; if (type == REC_TYPE_NORM && VSTREAM_PUTC('\n', dst) == VSTREAM_EOF) diff -cr ../postfix-19991231-pl06/global/mail_params.h ./global/mail_params.h *** ../postfix-19991231-pl06/global/mail_params.h Sun Mar 26 17:45:16 2000 --- ./global/mail_params.h Sun Apr 16 12:00:49 2000 *************** *** 215,220 **** --- 215,227 ---- extern char *var_always_bcc; /* + * What to put in the To: header when no recipients were disclosed. + */ + #define VAR_RCPT_WITHELD "undisclosed_recipients_header" + #define DEF_RCPT_WITHELD "To: undisclosed-recipients:;" + extern char *var_rcpt_witheld; + + /* * Standards violation: allow/permit RFC 822-style addresses in SMTP * commands. */ diff -cr ../postfix-19991231-pl06/html/cleanup.8.html ./html/cleanup.8.html *** ../postfix-19991231-pl06/html/cleanup.8.html Thu Mar 30 10:46:16 2000 --- ./html/cleanup.8.html Thu Apr 13 13:40:11 2000 *************** *** 20,26 **** mations: o Insert missing message headers: (Resent-) From:, ! Message-Id:, and Date:. o Extract envelope recipient addresses from (Resent-) To:, Cc: and Bcc: message headers when no recipi- --- 20,26 ---- mations: o Insert missing message headers: (Resent-) From:, ! To:, Message-Id:, and Date:. o Extract envelope recipient addresses from (Resent-) To:, Cc: and Bcc: message headers when no recipi- *************** *** 92,97 **** --- 92,102 ---- hopcount_limit Limit the number of Received: message headers. + recipients_witheld_header + The header line that is inserted when no recipients + were specified in (Resent-)To: or (Resent-)Cc: mes- + sage headers. + Address transformations empty_address_recipient The destination for undeliverable mail from <>. *************** *** 120,130 **** virtual_maps Address mapping lookup table for envelope recipient - addresses. - - Resource controls - duplicate_filter_limit - Limit the number of envelope recipients that are --- 125,130 ---- *************** *** 137,142 **** --- 137,147 ---- CLEANUP(8) CLEANUP(8) + addresses. + + Resource controls + duplicate_filter_limit + Limit the number of envelope recipients that are remembered. header_size_limit *************** *** 163,173 **** IBM T.J. Watson Research P.O. Box 704 Yorktown Heights, NY 10598, USA - - - - - --- 168,173 ---- diff -cr ../postfix-19991231-pl06/man/man8/cleanup.8 ./man/man8/cleanup.8 *** ../postfix-19991231-pl06/man/man8/cleanup.8 Thu Mar 30 10:46:10 2000 --- ./man/man8/cleanup.8 Thu Apr 13 13:40:07 2000 *************** *** 19,25 **** The \fBcleanup\fR daemon always performs the following transformations: .IP \(bu Insert missing message headers: (\fBResent-\fR) \fBFrom:\fR, ! \fBMessage-Id:\fR, and \fBDate:\fR. .IP \(bu Extract envelope recipient addresses from (\fBResent-\fR) \fBTo:\fR, \fBCc:\fR and \fBBcc:\fR message headers when no recipients are --- 19,25 ---- The \fBcleanup\fR daemon always performs the following transformations: .IP \(bu Insert missing message headers: (\fBResent-\fR) \fBFrom:\fR, ! \fBTo:\fR, \fBMessage-Id:\fR, and \fBDate:\fR. .IP \(bu Extract envelope recipient addresses from (\fBResent-\fR) \fBTo:\fR, \fBCc:\fR and \fBBcc:\fR message headers when no recipients are *************** *** 81,86 **** --- 81,89 ---- Address to send a copy of each message that enters the system. .IP \fBhopcount_limit\fR Limit the number of \fBReceived:\fR message headers. + .IP \fBrecipients_witheld_header\fR + The header line that is inserted when no recipients were + specified in (Resent-)To: or (Resent-)Cc: message headers. .SH "Address transformations" .ad .fi diff -cr ../postfix-19991231-pl06/smtpd/smtpd.c ./smtpd/smtpd.c *** ../postfix-19991231-pl06/smtpd/smtpd.c Sun Mar 26 17:58:22 2000 --- ./smtpd/smtpd.c Thu May 11 19:11:58 2000 *************** *** 479,493 **** #define PERMIT_EMPTY_ADDR 1 #define REJECT_EMPTY_ADDR 0 - if (allow_empty_addr && strcmp(STR(arg->vstrval), "<>") == 0) { - if (msg_verbose) - msg_info("%s: empty address", myname); - VSTRING_RESET(arg->vstrval); - VSTRING_TERMINATE(arg->vstrval); - arg->strval = STR(arg->vstrval); - return (0); - } - /* * Some mailers send RFC822-style address forms (with comments and such) * in SMTP envelopes. We cannot blame users for this: the blame is with --- 479,484 ---- *************** *** 519,527 **** } /* ! * Report trouble. Log a warning only if we are going to sleep+reject. */ ! if (naddr != 1 || (strict_rfc821 && (non_addr || *STR(arg->vstrval) != '<'))) { msg_warn("Illegal address syntax from %s in %s command: %s", state->namaddr, state->where, STR(arg->vstrval)); --- 510,520 ---- } /* ! * Report trouble. Log a warning only if we are going to sleep+reject so ! * that attackers can't flood our logfiles. */ ! if ((naddr < 1 && !allow_empty_addr) ! || naddr > 1 || (strict_rfc821 && (non_addr || *STR(arg->vstrval) != '<'))) { msg_warn("Illegal address syntax from %s in %s command: %s", state->namaddr, state->where, STR(arg->vstrval)); *************** *** 537,543 **** if (addr) tok822_internalize(arg->vstrval, addr->head, TOK822_STR_DEFL); else ! vstring_strcat(arg->vstrval, ""); arg->strval = STR(arg->vstrval); /* --- 530,536 ---- if (addr) tok822_internalize(arg->vstrval, addr->head, TOK822_STR_DEFL); else ! vstring_strcpy(arg->vstrval, ""); arg->strval = STR(arg->vstrval); /* diff -cr ../postfix-19991231-pl06/smtpd/smtpd_chat.c ./smtpd/smtpd_chat.c *** ../postfix-19991231-pl06/smtpd/smtpd_chat.c Wed Apr 7 20:41:55 1999 --- ./smtpd/smtpd_chat.c Thu May 11 21:21:49 2000 *************** *** 133,138 **** --- 133,139 ---- void smtpd_chat_reply(SMTPD_STATE *state, char *format,...) { va_list ap; + int slept = 0; va_start(ap, format); vstring_vsprintf(state->buffer, format, ap); *************** *** 149,159 **** * errors within a session. */ if (state->error_count > var_smtpd_soft_erlim) ! sleep(state->error_count); else if (STR(state->buffer)[0] == '4' || STR(state->buffer)[0] == '5') ! sleep(var_smtpd_err_sleep); smtp_fputs(STR(state->buffer), LEN(state->buffer), state->client); } /* print_line - line_wrap callback */ --- 150,168 ---- * errors within a session. */ if (state->error_count > var_smtpd_soft_erlim) ! sleep(slept = state->error_count); else if (STR(state->buffer)[0] == '4' || STR(state->buffer)[0] == '5') ! sleep(slept = var_smtpd_err_sleep); smtp_fputs(STR(state->buffer), LEN(state->buffer), state->client); + + /* + * Flush unsent output AFTER writing instead of before sleeping (so that + * vstream_fflush() flushes the output half of a bidirectional stream). + * Pipelined error responses could result in client-side timeouts. + */ + if (slept) + (vstream_fflush(state->client)); } /* print_line - line_wrap callback */ diff -cr ../postfix-19991231-pl06/trivial-rewrite/resolve.c ./trivial-rewrite/resolve.c *** ../postfix-19991231-pl06/trivial-rewrite/resolve.c Mon Dec 27 17:07:06 1999 --- ./trivial-rewrite/resolve.c Thu May 11 19:24:13 2000 *************** *** 27,33 **** /* /* resolve_proto() implements the client-server protocol: /* read one address in FQDN form, reply with a (transport, ! /* nexthop, internalized recipient) triple. /* /* resolve_addr() gives direct access to the address resolving /* engine. It resolves an internalized address to a (transport, --- 27,33 ---- /* /* resolve_proto() implements the client-server protocol: /* read one address in FQDN form, reply with a (transport, ! /* nexthop, internalized recipient) triple. /* /* resolve_addr() gives direct access to the address resolving /* engine. It resolves an internalized address to a (transport, *************** *** 110,119 **** while (tree->head) { /* ! * Strip trailing dot. */ ! if (tree->tail->type == '.') tok822_free_tree(tok822_sub_keep_before(tree, tree->tail)); /* * A lone empty string becomes the postmaster. --- 110,121 ---- while (tree->head) { /* ! * Strip trailing dot or @. */ ! if (tree->tail->type == '.' || tree->tail->type == '@') { tok822_free_tree(tok822_sub_keep_before(tree, tree->tail)); + continue; + } /* * A lone empty string becomes the postmaster. diff -cr ../postfix-19991231-pl06/util/dict_mysql.c ./util/dict_mysql.c *** ../postfix-19991231-pl06/util/dict_mysql.c Sun Mar 26 14:24:36 2000 --- ./util/dict_mysql.c Thu May 11 19:22:15 2000 *************** *** 201,209 **** /* * plmysql_query - process a MySQL query. Return MYSQL_RES* on success. ! * On failure, log failure and try other db instances. ! * on failure of all db instances, return 0; ! * close unnecessary active connections */ static MYSQL_RES *plmysql_query(PLMYSQL *PLDB, --- 201,209 ---- /* * plmysql_query - process a MySQL query. Return MYSQL_RES* on success. ! * On failure, log failure and try other db instances. ! * on failure of all db instances, return 0; ! * close unnecessary active connections */ static MYSQL_RES *plmysql_query(PLMYSQL *PLDB, *************** *** 361,380 **** int i; char *nameval; char *hosts; - /* the name of the dict for processing the mysql options file */ MYSQL_NAME *name = (MYSQL_NAME *) mymalloc(sizeof(MYSQL_NAME)); ARGV *hosts_argv; ! ! dict_load_file(mysqlcf_path, mysqlcf_path); /* mysql username lookup */ ! if ((nameval = (char *) dict_lookup(mysqlcf_path, "user")) == NULL) name->username = mystrdup(""); else name->username = mystrdup(nameval); if (msg_verbose) msg_info("mysqlname_parse(): set username to '%s'", name->username); /* password lookup */ ! if ((nameval = (char *) dict_lookup(mysqlcf_path, "password")) == NULL) name->password = mystrdup(""); else name->password = mystrdup(nameval); --- 361,389 ---- int i; char *nameval; char *hosts; MYSQL_NAME *name = (MYSQL_NAME *) mymalloc(sizeof(MYSQL_NAME)); ARGV *hosts_argv; ! VSTRING *opt_dict_name; ! ! /* ! * setup a dict containing info in the mysql cf file. the dict has a ! * name, and a path. The name must be distinct from the path, or the ! * dict interface gets confused. The name must be distinct for two ! * different paths, or the configuration info will cache across different ! * mysql maps, which can be confusing. ! */ ! opt_dict_name = vstring_alloc(64); ! vstring_sprintf(opt_dict_name, "mysql opt dict %s", mysqlcf_path); ! dict_load_file(vstring_str(opt_dict_name), mysqlcf_path); /* mysql username lookup */ ! if ((nameval = (char *) dict_lookup(vstring_str(opt_dict_name), "user")) == NULL) name->username = mystrdup(""); else name->username = mystrdup(nameval); if (msg_verbose) msg_info("mysqlname_parse(): set username to '%s'", name->username); /* password lookup */ ! if ((nameval = (char *) dict_lookup(vstring_str(opt_dict_name), "password")) == NULL) name->password = mystrdup(""); else name->password = mystrdup(nameval); *************** *** 382,388 **** msg_info("mysqlname_parse(): set password to '%s'", name->password); /* database name lookup */ ! if ((nameval = (char *) dict_lookup(mysqlcf_path, "dbname")) == NULL) msg_fatal("%s: mysql options file does not include database name", mysqlcf_path); else name->dbname = mystrdup(nameval); --- 391,397 ---- msg_info("mysqlname_parse(): set password to '%s'", name->password); /* database name lookup */ ! if ((nameval = (char *) dict_lookup(vstring_str(opt_dict_name), "dbname")) == NULL) msg_fatal("%s: mysql options file does not include database name", mysqlcf_path); else name->dbname = mystrdup(nameval); *************** *** 390,396 **** msg_info("mysqlname_parse(): set database name to '%s'", name->dbname); /* table lookup */ ! if ((nameval = (char *) dict_lookup(mysqlcf_path, "table")) == NULL) msg_fatal("%s: mysql options file does not include table name", mysqlcf_path); else name->table = mystrdup(nameval); --- 399,405 ---- msg_info("mysqlname_parse(): set database name to '%s'", name->dbname); /* table lookup */ ! if ((nameval = (char *) dict_lookup(vstring_str(opt_dict_name), "table")) == NULL) msg_fatal("%s: mysql options file does not include table name", mysqlcf_path); else name->table = mystrdup(nameval); *************** *** 398,404 **** msg_info("mysqlname_parse(): set table name to '%s'", name->table); /* select field lookup */ ! if ((nameval = (char *) dict_lookup(mysqlcf_path, "select_field")) == NULL) msg_fatal("%s: mysql options file does not include select field", mysqlcf_path); else name->select_field = mystrdup(nameval); --- 407,413 ---- msg_info("mysqlname_parse(): set table name to '%s'", name->table); /* select field lookup */ ! if ((nameval = (char *) dict_lookup(vstring_str(opt_dict_name), "select_field")) == NULL) msg_fatal("%s: mysql options file does not include select field", mysqlcf_path); else name->select_field = mystrdup(nameval); *************** *** 406,412 **** msg_info("mysqlname_parse(): set select_field to '%s'", name->select_field); /* where field lookup */ ! if ((nameval = (char *) dict_lookup(mysqlcf_path, "where_field")) == NULL) msg_fatal("%s: mysql options file does not include where field", mysqlcf_path); else name->where_field = mystrdup(nameval); --- 415,421 ---- msg_info("mysqlname_parse(): set select_field to '%s'", name->select_field); /* where field lookup */ ! if ((nameval = (char *) dict_lookup(vstring_str(opt_dict_name), "where_field")) == NULL) msg_fatal("%s: mysql options file does not include where field", mysqlcf_path); else name->where_field = mystrdup(nameval); *************** *** 414,420 **** msg_info("mysqlname_parse(): set where_field to '%s'", name->where_field); /* additional conditions */ ! if ((nameval = (char *) dict_lookup(mysqlcf_path, "additional_conditions")) == NULL) name->additional_conditions = mystrdup(""); else name->additional_conditions = mystrdup(nameval); --- 423,429 ---- msg_info("mysqlname_parse(): set where_field to '%s'", name->where_field); /* additional conditions */ ! if ((nameval = (char *) dict_lookup(vstring_str(opt_dict_name), "additional_conditions")) == NULL) name->additional_conditions = mystrdup(""); else name->additional_conditions = mystrdup(nameval); *************** *** 422,428 **** msg_info("mysqlname_parse(): set additional_conditions to '%s'", name->additional_conditions); /* mysql server hosts */ ! if ((nameval = (char *) dict_lookup(mysqlcf_path, "hosts")) == NULL) hosts = mystrdup(""); else hosts = mystrdup(nameval); --- 431,437 ---- msg_info("mysqlname_parse(): set additional_conditions to '%s'", name->additional_conditions); /* mysql server hosts */ ! if ((nameval = (char *) dict_lookup(vstring_str(opt_dict_name), "hosts")) == NULL) hosts = mystrdup(""); else hosts = mystrdup(nameval); *************** *** 448,453 **** --- 457,463 ---- } } myfree(hosts); + vstring_free(opt_dict_name); argv_free(hosts_argv); return name; } *************** *** 455,461 **** /* * plmysql_init - initalize a MYSQL database. ! * Return NULL on failure, or a PLMYSQL * on success. */ static PLMYSQL *plmysql_init(char *hostnames[], int len_hosts) --- 465,471 ---- /* * plmysql_init - initalize a MYSQL database. ! * Return NULL on failure, or a PLMYSQL * on success. */ static PLMYSQL *plmysql_init(char *hostnames[], int len_hosts) diff -cr ../postfix-19991231-pl06/util/valid_hostname.c ./util/valid_hostname.c *** ../postfix-19991231-pl06/util/valid_hostname.c Sat Mar 6 12:02:29 1999 --- ./util/valid_hostname.c Thu May 11 20:35:47 2000 *************** *** 81,92 **** } if (!ISDIGIT(ch)) non_numeric = 1; ! } else if (ch == '.' || ch == '-') { if (label_length == 0 || cp[1] == 0) { msg_warn("%s: misplaced delimiter: %.100s", myname, name); return (0); } label_length = 0; } else { msg_warn("%s: invalid character %d(decimal): %.100s", myname, ch, name); --- 81,98 ---- } if (!ISDIGIT(ch)) non_numeric = 1; ! } else if (ch == '.') { if (label_length == 0 || cp[1] == 0) { msg_warn("%s: misplaced delimiter: %.100s", myname, name); return (0); } label_length = 0; + } else if (ch == '-') { + label_length++; + if (label_length == 1 || cp[1] == 0 || cp[1] == '.') { + msg_warn("%s: misplaced hyphen: %.100s", myname, name); + return (0); + } } else { msg_warn("%s: invalid character %d(decimal): %.100s", myname, ch, name); diff -cr ../postfix-19991231-pl06/util/valid_hostname.in ./util/valid_hostname.in *** ../postfix-19991231-pl06/util/valid_hostname.in Sat Mar 6 10:42:37 1999 --- ./util/valid_hostname.in Thu May 11 20:40:57 2000 *************** *** 26,28 **** --- 26,38 ---- 1.2.3.4f 1.2.3.f4 1.2.3.f + -.a.b + a.-.b + a.b.- + -aa.b.b + aa-.b.b + a.-bb.b + a.bb-.b + a.b.-bb + a.b.bb- + a-a.b-b diff -cr ../postfix-19991231-pl06/util/valid_hostname.ref ./util/valid_hostname.ref *** ../postfix-19991231-pl06/util/valid_hostname.ref Sat Mar 6 12:03:31 1999 --- ./util/valid_hostname.ref Thu May 11 20:40:58 2000 *************** *** 70,72 **** --- 70,101 ---- ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2.3.f4 ./valid_hostname: testing: "1.2.3.f" ./valid_hostname: warning: valid_hostaddr: invalid character 102(decimal): 1.2.3.f + ./valid_hostname: testing: "-.a.b" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: -.a.b + ./valid_hostname: warning: valid_hostaddr: invalid character 45(decimal): -.a.b + ./valid_hostname: testing: "a.-.b" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.-.b + ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.-.b + ./valid_hostname: testing: "a.b.-" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.- + ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.- + ./valid_hostname: testing: "-aa.b.b" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: -aa.b.b + ./valid_hostname: warning: valid_hostaddr: invalid character 45(decimal): -aa.b.b + ./valid_hostname: testing: "aa-.b.b" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: aa-.b.b + ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): aa-.b.b + ./valid_hostname: testing: "a.-bb.b" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.-bb.b + ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.-bb.b + ./valid_hostname: testing: "a.bb-.b" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.bb-.b + ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.bb-.b + ./valid_hostname: testing: "a.b.-bb" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.-bb + ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.-bb + ./valid_hostname: testing: "a.b.bb-" + ./valid_hostname: warning: valid_hostname: misplaced hyphen: a.b.bb- + ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a.b.bb- + ./valid_hostname: testing: "a-a.b-b" + ./valid_hostname: warning: valid_hostaddr: invalid character 97(decimal): a-a.b-b