5219a03668
More info - http://www.postfix.org/XCLIENT_README.html PR: ports/133891 Submitted by: Alexey V.Degtyarev <alexey@renatasystems.org>
347 lines
13 KiB
Text
347 lines
13 KiB
Text
|
|
--- src/globals.c.orig 2007-12-10 18:59:58.297661332 +0300
|
|
+++ src/globals.c 2007-12-10 19:00:22.299029091 +0300
|
|
@@ -621,6 +621,7 @@
|
|
BOOL helo_verified = FALSE;
|
|
BOOL helo_verify_failed = FALSE;
|
|
uschar *helo_verify_hosts = NULL;
|
|
+uschar *xclient_allow_hosts = NULL;
|
|
uschar *hex_digits = US"0123456789abcdef";
|
|
uschar *hold_domains = NULL;
|
|
BOOL host_checking = FALSE;
|
|
--- src/globals.h.orig 2007-12-10 19:11:45.337953260 +0300
|
|
+++ src/globals.h 2007-12-10 19:12:42.341201691 +0300
|
|
@@ -367,6 +367,7 @@
|
|
extern BOOL helo_verified; /* True if HELO verified */
|
|
extern BOOL helo_verify_failed; /* True if attempt failed */
|
|
extern uschar *helo_verify_hosts; /* Hard check HELO argument for these */
|
|
+extern uschar *xclient_allow_hosts; /* Allow XCLIENT command for specified hosts */
|
|
extern uschar *hex_digits; /* Used in several places */
|
|
extern uschar *hold_domains; /* Hold up deliveries to these */
|
|
extern BOOL host_find_failed_syntax;/* DNS syntax check failure */
|
|
--- src/macros.h.orig 2007-08-30 18:31:06.000000000 +0400
|
|
+++ src/macros.h 2007-12-10 17:36:29.512226916 +0300
|
|
@@ -714,7 +714,7 @@
|
|
|
|
enum { SCH_NONE, SCH_AUTH, SCH_DATA, SCH_EHLO, SCH_ETRN, SCH_EXPN, SCH_HELO,
|
|
SCH_HELP, SCH_MAIL, SCH_NOOP, SCH_QUIT, SCH_RCPT, SCH_RSET, SCH_STARTTLS,
|
|
- SCH_VRFY };
|
|
+ SCH_VRFY, SCH_XCLIENT };
|
|
|
|
/* Returns from host_find_by{name,dns}() */
|
|
|
|
--- src/readconf.c.orig 2007-12-10 19:03:32.809885687 +0300
|
|
+++ src/readconf.c 2007-12-10 19:13:37.344336141 +0300
|
|
@@ -404,7 +404,8 @@
|
|
{ "uucp_from_pattern", opt_stringptr, &uucp_from_pattern },
|
|
{ "uucp_from_sender", opt_stringptr, &uucp_from_sender },
|
|
{ "warn_message_file", opt_stringptr, &warn_message_file },
|
|
- { "write_rejectlog", opt_bool, &write_rejectlog }
|
|
+ { "write_rejectlog", opt_bool, &write_rejectlog },
|
|
+ { "xclient_allow_hosts", opt_stringptr, &xclient_allow_hosts },
|
|
};
|
|
|
|
static int optionlist_config_size =
|
|
--- src/smtp_in.c.orig 2007-12-10 15:54:30.000000000 +0300
|
|
+++ src/smtp_in.c 2009-02-03 17:29:33.181798456 +0300
|
|
@@ -63,10 +63,10 @@
|
|
/* These commands are required to be synchronized, i.e. to be the last in a
|
|
block of commands when pipelining. */
|
|
|
|
- HELO_CMD, EHLO_CMD, DATA_CMD, /* These are listed in the pipelining */
|
|
- VRFY_CMD, EXPN_CMD, NOOP_CMD, /* RFC as requiring synchronization */
|
|
- ETRN_CMD, /* This by analogy with TURN from the RFC */
|
|
- STARTTLS_CMD, /* Required by the STARTTLS RFC */
|
|
+ HELO_CMD, EHLO_CMD, XCLIENT_CMD, DATA_CMD, /* These are listed in the pipelining */
|
|
+ VRFY_CMD, EXPN_CMD, NOOP_CMD, /* RFC as requiring synchronization */
|
|
+ ETRN_CMD, /* This by analogy with TURN from the RFC */
|
|
+ STARTTLS_CMD, /* Required by the STARTTLS RFC */
|
|
|
|
/* This is a dummy to identify the non-sync commands when pipelining */
|
|
|
|
@@ -152,6 +152,7 @@
|
|
{ "rset", sizeof("rset")-1, RSET_CMD, FALSE, FALSE }, /* First */
|
|
{ "helo", sizeof("helo")-1, HELO_CMD, TRUE, FALSE },
|
|
{ "ehlo", sizeof("ehlo")-1, EHLO_CMD, TRUE, FALSE },
|
|
+ { "xclient", sizeof("xclient")-1, XCLIENT_CMD, TRUE, FALSE },
|
|
{ "auth", sizeof("auth")-1, AUTH_CMD, TRUE, TRUE },
|
|
#ifdef SUPPORT_TLS
|
|
{ "starttls", sizeof("starttls")-1, STARTTLS_CMD, FALSE, FALSE },
|
|
@@ -184,7 +185,7 @@
|
|
|
|
static uschar *smtp_names[] =
|
|
{
|
|
- US"NONE", US"AUTH", US"DATA", US"EHLO", US"ETRN", US"EXPN", US"HELO",
|
|
+ US"NONE", US"AUTH", US"DATA", US"EHLO", US"ETRN", US"EXPN", US"HELO", US"XCLIENT",
|
|
US"HELP", US"MAIL", US"NOOP", US"QUIT", US"RCPT", US"RSET", US"STARTTLS",
|
|
US"VRFY" };
|
|
|
|
@@ -847,6 +848,205 @@
|
|
}
|
|
|
|
|
|
+/*************************************************
|
|
+* Check XCLIENT line and set sender_address *
|
|
+*************************************************/
|
|
+
|
|
+/* Check the format of a XCLIENT line.
|
|
+ * XCLIENT Command syntax
|
|
+ *
|
|
+ * An example client-server conversation is given at the end of this document.
|
|
+ *
|
|
+ * In SMTP server EHLO replies, the keyword associated with this extension is XCLIENT. It is followed by the names of the attributes that the XCLIENT implementation supports.
|
|
+ *
|
|
+ * The XCLIENT command may be sent at any time, except in the middle of a mail delivery transaction (i.e. between MAIL and DOT, or MAIL and RSET).
|
|
+ * The XCLIENT command may be pipelined when the server supports ESMTP command pipelining.
|
|
+ * To avoid triggering spamware detectors, the command should be sent at the end of a command group.
|
|
+ *
|
|
+ * The syntax of XCLIENT requests is described below.
|
|
+ * Upper case and quoted strings specify terminals, lowercase strings specify meta terminals, and SP is whitespace.
|
|
+ * Although command and attribute names are shown in upper case, they are in fact case insensitive.
|
|
+ *
|
|
+ * xclient-command = XCLIENT 1*( SP attribute-name"="attribute-value )
|
|
+ *
|
|
+ * attribute-name = ( NAME | ADDR | PORT | HELO | PROTO | LOGIN)
|
|
+ *
|
|
+ * attribute-value = xtext
|
|
+ *
|
|
+ * Attribute values are xtext encoded as per RFC 1891.
|
|
+ * The NAME attribute specifies an SMTP client hostname (not an SMTP client address), [UNAVAILABLE] when client hostname lookup failed due to a permanent error, or [TEMPUNAVAIL] when the lookup error condition was transient.
|
|
+ *
|
|
+ * The ADDR attribute specifies an SMTP client numerical IPv4 network address, an IPv6 address prefixed with IPV6:, or [UNAVAILABLE] when the address information is unavailable. Address information is not enclosed with [].
|
|
+ *
|
|
+ * The PORT attribute specifies the SMTP client TCP port number as a decimal number, or [UNAVAILABLE] when the information is unavailable.
|
|
+ * The HELO attribute specifies an SMTP HELO parameter value, or the value [UNAVAILABLE] when the information is unavailable.
|
|
+ * The PROTO attribute specifies either SMTP or ESMTP.
|
|
+ *
|
|
+ * Note 1: syntactically valid NAME and HELO attribute-value elements can be up to 255 characters long.
|
|
+ * The client must not send XCLIENT commands that exceed the 512 character limit for SMTP commands.
|
|
+ * To avoid exceeding the limit the client should send the information in multiple XCLIENT commands; for example, send NAME and ADDR first, then HELO and PROTO.
|
|
+ *
|
|
+ * Note 2: [UNAVAILABLE], [TEMPUNAVAIL] and IPV6: may be specified in upper case, lower case or mixed case.
|
|
+Argument:
|
|
+ s the data portion of the line (already past any white space)
|
|
+
|
|
+Returns: TRUE
|
|
+ FALSE
|
|
+*/
|
|
+
|
|
+/* XCLIENT MACROS */
|
|
+#define XCLIENT_UNAVAIL US"[UNAVAILABLE]"
|
|
+#define XCLIENT_TEMPUNAVAIL US"[TEMPUNAVAIL]"
|
|
+
|
|
+static BOOL
|
|
+smtp_handle_xclient(uschar *s)
|
|
+{
|
|
+ uschar *p, *end, *arg;
|
|
+ int len;
|
|
+ p = s;
|
|
+ end = s + Ustrlen(s);
|
|
+
|
|
+ while (p <= end) {
|
|
+ /* Addr */
|
|
+ if (strncmpic(p, US"ADDR=", 5) == 0) {
|
|
+ p += 5;
|
|
+ arg = p;
|
|
+ while (*p++ != ' ' && p <= end );
|
|
+ len = p - arg;
|
|
+ /* Strip whitespace */
|
|
+ if(*(p - 1) == ' ') {
|
|
+ len --;
|
|
+ }
|
|
+ if (len > 0) {
|
|
+ sender_host_address = string_copy_malloc(string_copyn(arg, len));
|
|
+ }
|
|
+ else {
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+ /* Name */
|
|
+ else if (strncmpic(p, US"NAME=", 5) == 0) {
|
|
+ p += 5;
|
|
+ arg = p;
|
|
+ while (*p++ != ' ' && p <= end );
|
|
+ len = p - arg;
|
|
+ /* Strip whitespace */
|
|
+ if(*(p - 1) == ' ') {
|
|
+ len --;
|
|
+ }
|
|
+ if (len > 0) {
|
|
+ if ((len == sizeof(XCLIENT_UNAVAIL) - 1 && strncmpic(arg, XCLIENT_UNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0) ||
|
|
+ (len == sizeof(XCLIENT_TEMPUNAVAIL) - 1 && strncmpic(arg, XCLIENT_TEMPUNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0)) {
|
|
+ sender_host_name = NULL;
|
|
+ }
|
|
+ else {
|
|
+ sender_host_name = string_copy_malloc(string_copyn(arg, len));
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+ /* Helo */
|
|
+ else if (strncmpic(p, US"HELO=", 5) == 0) {
|
|
+ p += 5;
|
|
+ arg = p;
|
|
+ while (*p++ != ' ' && p <= end );
|
|
+ len = p - arg;
|
|
+ /* Strip whitespace */
|
|
+ if(*(p - 1) == ' ') {
|
|
+ len --;
|
|
+ }
|
|
+
|
|
+ if (len > 0) {
|
|
+ if ((len == sizeof(XCLIENT_UNAVAIL) - 1 && strncmpic(arg, XCLIENT_UNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0) ||
|
|
+ (len == sizeof(XCLIENT_TEMPUNAVAIL) - 1 && strncmpic(arg, XCLIENT_TEMPUNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0)) {
|
|
+ sender_helo_name = NULL;
|
|
+ }
|
|
+ else {
|
|
+ sender_helo_name = string_copy_malloc(string_copyn(arg, len));
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+ /* Port */
|
|
+ else if (strncmpic(p, US"PORT=", 5) == 0) {
|
|
+ p += 5;
|
|
+ arg = p;
|
|
+ while (*p++ != ' ' && p <= end);
|
|
+ len = p - arg;
|
|
+ if(*(p - 1) == ' ') {
|
|
+ len --;
|
|
+ }
|
|
+ if (len > 0) {
|
|
+ if ((len == sizeof(XCLIENT_UNAVAIL) - 1 && strncmpic(arg, XCLIENT_UNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0) ||
|
|
+ (len == sizeof(XCLIENT_TEMPUNAVAIL) - 1 && strncmpic(arg, XCLIENT_TEMPUNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0)) {
|
|
+ sender_host_port = 0;
|
|
+ }
|
|
+ else {
|
|
+ sender_host_port = Uatoi(arg);
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+ /* Login */
|
|
+ else if (strncmpic(p, US"LOGIN=", 6) == 0) {
|
|
+ p += 6;
|
|
+ arg = p;
|
|
+ while (*p++ != ' ' && p <= end);
|
|
+ len = p - arg;
|
|
+ if(*(p - 1) == ' ') {
|
|
+ len --;
|
|
+ }
|
|
+ if (len > 0) {
|
|
+ if ((len == sizeof(XCLIENT_UNAVAIL) - 1 && strncmpic(arg, XCLIENT_UNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0) ||
|
|
+ (len == sizeof(XCLIENT_TEMPUNAVAIL) - 1 && strncmpic(arg, XCLIENT_TEMPUNAVAIL, sizeof (XCLIENT_UNAVAIL) -1) == 0)) {
|
|
+ authenticated_id = NULL;
|
|
+ sender_host_authenticated = NULL;
|
|
+ }
|
|
+ else {
|
|
+ authenticated_id = string_copy_malloc(string_copyn(arg, len));
|
|
+ sender_host_authenticated = "xclient";
|
|
+ authentication_failed = FALSE;
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+ /* Proto */
|
|
+ else if (strncmpic(p, US"PROTO=", 6) == 0) {
|
|
+ p += 6;
|
|
+ arg = p;
|
|
+ while (*p++ != ' ' && p <= end);
|
|
+ len = p - arg;
|
|
+ if(*(p - 1) == ' ') {
|
|
+ len --;
|
|
+ }
|
|
+ if (len > 0) {
|
|
+ if (len == 4 && (strncmpic(arg, US"SMTP", 4) == 0)) {
|
|
+ esmtp = FALSE;
|
|
+ }
|
|
+ else if (len == 5 && (strncmpic(arg, US"ESMTP", 5) == 0)) {
|
|
+ esmtp = TRUE;
|
|
+ }
|
|
+ }
|
|
+ }
|
|
+ else {
|
|
+ return FALSE;
|
|
+ }
|
|
+ }
|
|
+
|
|
+ host_build_sender_fullhost();
|
|
+ return TRUE;
|
|
+}
|
|
+
|
|
+#undef XCLIENT_UNAVAIL
|
|
+#undef XCLIENT_TEMPUNAVAIL
|
|
|
|
/*************************************************
|
|
* Check HELO line and set sender_helo_name *
|
|
@@ -1131,6 +1331,11 @@
|
|
bsmtp_transaction_linecount = receive_linecount;
|
|
break;
|
|
|
|
+ /* Handle XCLIENT command */
|
|
+ case XCLIENT_CMD:
|
|
+ smtp_handle_xclient(smtp_cmd_data);
|
|
+ break;
|
|
+
|
|
|
|
/* The MAIL FROM command requires an address as an operand. All we
|
|
do here is to parse it for syntactic correctness. The form "<>" is
|
|
@@ -3158,7 +3363,50 @@
|
|
toomany = FALSE;
|
|
break; /* HELO/EHLO */
|
|
|
|
+ case XCLIENT_CMD:
|
|
+ HAD(SCH_XCLIENT);
|
|
+ smtp_mailcmd_count++;
|
|
+ if (helo_required && !helo_seen)
|
|
+ {
|
|
+ smtp_printf("503 HELO or EHLO required\r\n");
|
|
+ log_write(0, LOG_MAIN|LOG_REJECT, "rejected XCLIENT from %s: no "
|
|
+ "HELO/EHLO given", host_and_ident(FALSE));
|
|
+ break;
|
|
+ }
|
|
+
|
|
+ /* Check for an operand */
|
|
+ if (smtp_cmd_data[0] == 0)
|
|
+ {
|
|
+ done = synprot_error(L_smtp_syntax_error, 501, NULL,
|
|
+ US"XCLIENT must have at least one operand");
|
|
+ break;
|
|
+ }
|
|
+ if(xclient_allow_hosts != NULL)
|
|
+ {
|
|
+ if (match_isinlist (sender_host_address, &xclient_allow_hosts, ':', NULL, NULL, MCL_NOEXPAND, FALSE, NULL) != OK)
|
|
+ {
|
|
+ done = synprot_error(L_smtp_syntax_error, 550, NULL,
|
|
+ US"XCLIENT is not allowed");
|
|
+ break;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ done = synprot_error(L_smtp_syntax_error, 550, NULL,
|
|
+ US"XCLIENT is not allowed");
|
|
+ break;
|
|
+ }
|
|
+ if(smtp_handle_xclient(smtp_cmd_data) == FALSE)
|
|
+ {
|
|
+ done = synprot_error(L_smtp_syntax_error, 501, NULL,
|
|
+ US"bad command parameter syntax");
|
|
+ break;
|
|
+ }
|
|
+ smtp_code = US"220"; /* Default status code */
|
|
+
|
|
+ smtp_printf("%s XCLIENT success\r\n", smtp_code);
|
|
|
|
+ break; /* XCLIENT */
|
|
/* The MAIL command requires an address as an operand. All we do
|
|
here is to parse it for syntactic correctness. The form "<>" is
|
|
a special case which converts into an empty string. The start/end
|