aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSergey Poznyakoff <gray@gnu.org.ua>2011-01-13 12:47:30 +0200
committerSergey Poznyakoff <gray@gnu.org.ua>2011-01-13 14:25:54 +0200
commitf3a6014780f99091b197f32afeb7f0ec7ca361ce (patch)
treea5e454017db09efa8625b711c7a24d343c58a58c
parent7875612f049fa2fa39e3c7bbf2d82c2908052d77 (diff)
downloadanubis-f3a6014780f99091b197f32afeb7f0ec7ca361ce.tar.gz
anubis-f3a6014780f99091b197f32afeb7f0ec7ca361ce.tar.bz2
Delayed ESMTP authentication: initial implementation.
Anubis can be instructed to postpone ESMTP authentication until MAIL command is issued by the client. This allows for changing authentication credentials in the SMTP section, depending on the envelope information supplied by the client. * src/headers.h (T_ESMTP_AUTH_DELAYED): New flag. (rcfile_call_section): Change signature. * src/mda.c: Update calls to rcfile_call_section. * src/rc-gram.y (rc_run_section): Take additional argument specifying the class of the section to run. (rc_call_section): Remove. All callers changed to use rc_call_section instead. (rc_run_section_list): Remove unused function. * src/rcfile.c (parse_esmtp_kv): New static. (control_parser): Call parse_esmtp_kv as a part of the default handling. (control_kw): New keyword esmtp-auth-delayed. (smtp_rule_parser,smtp_rule_section_init): New functions. (rc_system_init): Call smtp_rule_section_init. (rcfile_call_section): Take additional argument specifying the class of the section to run. * src/rcfile.h (rc_run_section): Change signature. (rc_call_section): Remove. * src/smtprepl.c (smtp_reply_free): Do nothing if argument is NULL. * src/tunnel.c (ehlo_reply): New static. (handle_ehlo): Save reply in ehlo_reply. Don't attempt authentication if T_ESMTP_AUTH_DELAYED is set... (transfer_command): ... do it here instead. * configure.ac: Version 4.1.92 * NEWS: Update. * doc/anubis.texi: Document esmtp-auth-delayed and the use of esmtp-* statements in SMTP sections.
-rw-r--r--NEWS28
-rw-r--r--configure.ac4
-rw-r--r--doc/anubis.texi65
-rw-r--r--src/headers.h7
-rw-r--r--src/mda.c6
-rw-r--r--src/rc-gram.y35
-rw-r--r--src/rcfile.c285
-rw-r--r--src/rcfile.h9
-rw-r--r--src/smtprepl.c11
-rw-r--r--src/tunnel.c65
-rw-r--r--testsuite/etc/add-body-file.pat2
11 files changed, 357 insertions, 160 deletions
diff --git a/NEWS b/NEWS
index 690151f..daf004b 100644
--- a/NEWS
+++ b/NEWS
@@ -1,11 +1,11 @@
-GNU Anubis NEWS -- history of user-visible changes. 2009-11-11
+GNU Anubis NEWS -- history of user-visible changes. 2011-01-13
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008, 2009 The Anubis Team.
See the end of file for copying conditions.
Please send your bug reports to <bug-anubis@gnu.org>.
-* Version 4.1.91 (Git)
+* Version 4.1.92 (Git)
* New operation mode: proxy
@@ -14,9 +14,16 @@ Please send your bug reports to <bug-anubis@gnu.org>.
Command line options take precedence over configuration file
statements.
+* New CONTROL statement esmtp-auth-delayed.
+
+When set to `yes', this statement instructs Anubis to postpone ESMTP
+authentication until MAIL command is issued by the client. This
+allows to change authentication credentials in the SMTP section (see
+below).
+
* SMTP section
-The new rule section "SMTP" is invoked each time an SMTP command
+The new section "SMTP" is invoked each time an SMTP command
is received. This section may alter the command's argument, using the
"modify command", e.g.:
@@ -28,6 +35,21 @@ if command ["mail from:"] "<(.*)>(.*)"
fi
END
+It is also allowed to use esmtp-* keywords in this section, provided
+that `esmtp-auth-delayed yes' is set in the CONTROL section. Changes
+in the ESMTP authentication credentials take effect if they occur
+either before receiving MAIL command from the client, or when handling
+this command, e.g.:
+
+BEGIN SMTP
+if command ["mail from:"] "<smith(\+.*)?@@example.net>"
+ esmtp-auth-id smith
+ esmtp-password guessme
+else
+ esmtp-auth no
+fi
+END
+
* New keywords: log-facility and log-tag
* Guile output
diff --git a/configure.ac b/configure.ac
index 01340e2..8b24c99 100644
--- a/configure.ac
+++ b/configure.ac
@@ -3,7 +3,7 @@ dnl configure.ac
dnl
dnl This file is part of GNU Anubis.
dnl Copyright (C) 2001,2002,2003,2004,2005,2006,2007,2008,2009,
-dnl 2010 The Anubis Team.
+dnl 2010,2011 The Anubis Team.
dnl
dnl GNU Anubis is free software; you can redistribute it and/or modify it
dnl under the terms of the GNU General Public License as published by the
@@ -20,7 +20,7 @@ dnl with GNU Anubis. If not, see <http://www.gnu.org/licenses/>.
dnl
dnl Process this file with autoconf to produce a configure script.
-AC_INIT([GNU Anubis], [4.1.91], [bug-anubis@gnu.org])
+AC_INIT([GNU Anubis], [4.1.92], [bug-anubis@gnu.org])
AC_PREREQ([2.63])
AC_CONFIG_HEADERS([config.h])
AC_CONFIG_AUX_DIR([build])
diff --git a/doc/anubis.texi b/doc/anubis.texi
index b9f47e0..5f5b8c5 100644
--- a/doc/anubis.texi
+++ b/doc/anubis.texi
@@ -14,7 +14,7 @@
@syncodeindex fn cp
@copying
-Copyright @copyright{} 2001, 2002, 2003, 2004, 2007, 2008, 2009
+Copyright @copyright{} 2001, 2002, 2003, 2004, 2007, 2008, 2009, 2011
Wojciech Polak and Sergey Poznyakoff.
Permission is granted to copy, distribute and/or modify this document
@@ -1444,6 +1444,9 @@ The following options set authentication credentials for @acronym{ESMTP}
authentication. They are useful, for example, if your @acronym{MTA}
requires such an authentication, but your @acronym{MUA} does not support it.
+You can also use these statements in a @samp{SMTP} section.
+@xref{Modifying SMTP Commands}, for a detailed description of this feature.
+
@deffn Option esmtp-allowed-mech @var{mech-list}
Defines the list of allowed authentication mechanisms. @var{Mech-list}
is a list of valid authentication mechanism names separated by
@@ -1485,6 +1488,16 @@ This prevents sending user password over an unencrypted connection.
@end deffn
+@deffn Option esmtp-auth-delayed @var{yes-or-no}
+By default, ESMTP authentication is attempted as early as
+possible, normally while handling the client @samp{EHLO} command.
+
+When this statement is set to @samp{yes}, authentication is delayed
+until the client issued the @samp{MAIL} command. This allows you
+to select authentication credentials depending on the sender email.
+For a detailed description of this feature, see @ref{Modifying SMTP Commands}.
+@end deffn
+
@deffn Option esmtp-auth-id @var{authentication-id}
Sets authentication @acronym{ID} (user name).
@end deffn
@@ -2398,12 +2411,12 @@ modify body :extended ["the old \([[:alnum:]]+\)"] "the new \1"
@node Modifying SMTP Commands
@subsection Modifying SMTP Commands
-GNU Anubis makes it possible to modify arguments of
-the @acronym{SMTP} commands. To do so, define a section
-named @samp{SMTP}. Anubis will call this section each time
+GNU Anubis is able to modify arguments of the @acronym{SMTP} commands.
+To instruct it to do so, define a section named @samp{SMTP}.
+Anubis will call this section each time
it receives an @acronym{SMTP} command. This section may contain
any statements allowed for @samp{RULE} section, plus the
-following special flavors of the @samp{modify} statement:
+following special flavor of the @samp{modify} statement:
@deffn Command modify [@var{flags}] command @samp{[}@var{cmd}@samp{]} @var{value}
If the current @acronym{SMTP} command matches @var{cmd}, rewrite it by
@@ -2421,6 +2434,40 @@ END
@end group
@end smallexample
+Additionally, the ESMTP authentication settings (@pxref{ESMTP
+Authentication Settings}) can be used as actions in this section.
+To do so, you must first set @code{esmtp-auth-delayed} to @samp{yes}
+in the @samp{CONTROL} section (@pxref{ESMTP Authentication Settings,
+esmtp-auth-delayed}). Changes in the settings take effect if they
+occur either before the @samp{MAIL} @acronym{SMTP} command, or while
+handling this command.
+
+Consider, for example, the following configuration:
+
+@smallexample
+BEGIN CONTROL
+ mode transparent
+ bind 25
+ remote-mta mail.example.com
+ esmtp-auth-delayed yes
+END
+
+BEGIN SMTP
+if command ["mail from:"] "<smith(\+.*)?@@example.net>"
+ esmtp-auth-id smith
+ esmtp-password guessme
+else
+ esmtp-auth no
+fi
+END
+@end smallexample
+
+It delays ESMTP authentication until the receipt of the @code{MAIL}
+command from the client. Authentication is used only if the mail
+is being sent from @email{smith@@example.net} or any additional mailbox
+of that user (e.g. @email{smith+mbox@@example.net}). Otherwise,
+authentication is disabled.
+
The following points are worth mentioning:
@enumerate 1
@@ -2458,10 +2505,10 @@ It is because by the time @samp{MAIL FROM} is received, the
the server.
@end enumerate
-The final point to notice is that you may use another than the
-default name for that section (if you really want to). To do
-so, define the new name via the @samp{smtp-command-rule} option in the
-@samp{CONTROL} section (@pxref{Basic Settings,,smtp-command-rule}).
+The final point to notice is that you may use an alternative name for
+that section (if you really want to). To do so, define the new name
+via the @samp{smtp-command-rule} option in the @samp{CONTROL} section
+(@pxref{Basic Settings,,smtp-command-rule}).
@node Inserting Files
@subsection Inserting Files
diff --git a/src/headers.h b/src/headers.h
index 3b19aac..c8f8bb2 100644
--- a/src/headers.h
+++ b/src/headers.h
@@ -3,7 +3,7 @@
This file is part of GNU Anubis.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008,
- 2009, 2010 The Anubis Team.
+ 2009, 2010, 2011 The Anubis Team.
GNU Anubis is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -239,6 +239,7 @@ ANUBIS_MODE;
#define T_TRACEFILE_USR 0x08000000
#define T_XELO 0x10000000
#define T_LOCATION_COLUMN 0x20000000
+#define T_ESMTP_AUTH_DELAYED 0x40000000
/* Regexp modifiers */
/* Basic types */
@@ -476,13 +477,13 @@ int anubis_regex_refcnt (RC_REGEX *);
char *anubis_regex_replace (RC_REGEX *, char *, char *);
void anubis_regex_print (RC_REGEX *);
-/* rc.c */
+/* rcfile.c */
void rc_system_init (void);
void auth_tunnel (void);
void open_rcfile (int);
void process_rcfile (int);
void rcfile_process_section (int, char *, void *, MESSAGE);
-void rcfile_call_section (int, char *, void *, MESSAGE);
+void rcfile_call_section (int, char *, char *, void *, MESSAGE);
char *user_rcfile_name (void);
typedef struct eval_env *EVAL_ENV;
diff --git a/src/mda.c b/src/mda.c
index 1e607e0..2f77f46 100644
--- a/src/mda.c
+++ b/src/mda.c
@@ -2,7 +2,7 @@
mda.c
This file is part of GNU Anubis.
- Copyright (C) 2005, 2007, 2009 The Anubis Team.
+ Copyright (C) 2005, 2007, 2009, 2011 The Anubis Team.
GNU Anubis is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -280,7 +280,7 @@ smtp_client_data (struct smtp_client_context *ctx)
process_rcfile (CF_CLIENT);
tmp = message_dup (ctx->msg);
- rcfile_call_section (CF_CLIENT, incoming_mail_rule, NULL, tmp);
+ rcfile_call_section (CF_CLIENT, incoming_mail_rule, "RULE", NULL, tmp);
transfer_header (message_get_header (tmp));
transfer_body (tmp);
@@ -407,7 +407,7 @@ deliver_local_child (const char *recipient, MESSAGE msg)
open_rcfile (CF_CLIENT);
process_rcfile (CF_CLIENT);
- rcfile_call_section (CF_CLIENT, incoming_mail_rule, NULL, msg);
+ rcfile_call_section (CF_CLIENT, incoming_mail_rule, "RULE", NULL, msg);
transfer_header (message_get_header (msg));
transfer_body (msg);
diff --git a/src/rc-gram.y b/src/rc-gram.y
index 44b8b01..5eeb062 100644
--- a/src/rc-gram.y
+++ b/src/rc-gram.y
@@ -3,7 +3,7 @@
rc-gram.y
This file is part of GNU Anubis.
- Copyright (C) 2003, 2004, 2007, 2009 The Anubis Team.
+ Copyright (C) 2003, 2004, 2007, 2009, 2011 The Anubis Team.
GNU Anubis is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -1500,7 +1500,7 @@ inst_eval (struct eval_env *env, RC_INST *inst)
case inst_call:
tracefile (&env->loc, _("Calling %s"), inst->arg);
- rcfile_call_section (env->method, inst->arg,
+ rcfile_call_section (env->method, inst->arg, "RULE",
env->data, env->msg);
break;
@@ -1815,14 +1815,17 @@ eval_section (int method, RC_SECTION *sec, struct rc_secdef *secdef,
void
rc_run_section (int method, RC_SECTION *sec, struct rc_secdef *secdef,
+ const char *class_name,
void *data, MESSAGE msg)
{
if (!sec)
return;
-
+ if (!class_name)
+ class_name = sec->name;
+
for (; secdef->name; secdef++)
{
- if (!strcmp (sec->name, secdef->name))
+ if (!strcmp (secdef->name, class_name))
{
eval_section (method, sec, secdef, data, msg);
return;
@@ -1831,30 +1834,6 @@ rc_run_section (int method, RC_SECTION *sec, struct rc_secdef *secdef,
anubis_error (0, 0, _("Unknown section: %s"), sec->name);
}
-void
-rc_call_section (int method, RC_SECTION *sec, struct rc_secdef *secdef,
- void *data, MESSAGE msg)
-{
- if (!sec)
- return;
-
- for (; secdef->name; secdef++)
- {
- if (!strcmp (secdef->name, "RULE"))
- {
- eval_section (method, sec, secdef, data, msg);
- return;
- }
- }
-}
-
-void
-rc_run_section_list (int method, RC_SECTION *sec,
- struct rc_secdef *secdef)
-{
- for (; sec; sec = sec->next)
- rc_run_section (method, sec, secdef, NULL, NULL);
-}
static int
check_kw (char *ident, int *flags)
diff --git a/src/rcfile.c b/src/rcfile.c
index 84f739b..ef13fb6 100644
--- a/src/rcfile.c
+++ b/src/rcfile.c
@@ -2,7 +2,8 @@
rcfile.c
This file is part of GNU Anubis.
- Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009 The Anubis Team.
+ Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2009,
+ 2011 The Anubis Team.
GNU Anubis is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -259,6 +260,7 @@ process_rcfile (int method)
#define KW_ALLOW_HANG 34
#define KW_LOG_FACILITY 35
#define KW_LOG_TAG 36
+#define KW_ESMTP_AUTH_DELAYED 37
char **
list_to_argv (ANUBIS_LIST list)
@@ -327,6 +329,106 @@ static volatile unsigned long _anubis_hang;
/* List of users who are allowed to use HANG in their profiles */
ANUBIS_LIST allow_hang_users;
+static struct rc_kwdef esmtp_kw[] = {
+ { "esmtp-auth", KW_ESMTP_AUTH, KWF_HIDDEN },
+ { "esmtp-anonymous-token", KW_ESMTP_ANONYMOUS_TOKEN, KWF_HIDDEN },
+ { "esmtp-auth-id", KW_ESMTP_AUTH_ID, KWF_HIDDEN },
+ { "esmtp-authz-id", KW_ESMTP_AUTHZ_ID, KWF_HIDDEN },
+ { "esmtp-password", KW_ESMTP_PASSWORD, KWF_HIDDEN },
+ { "esmtp-service", KW_ESMTP_SERVICE, KWF_HIDDEN },
+ { "esmtp-hostname", KW_ESMTP_HOSTNAME, KWF_HIDDEN },
+ { "esmtp-generic-service", KW_ESMTP_SERVICE, KWF_HIDDEN },
+ { "esmtp-passcode", KW_ESMTP_PASSCODE, KWF_HIDDEN },
+ { "esmtp-realm", KW_ESMTP_REALM, KWF_HIDDEN },
+ { "esmtp-allowed-mech", KW_ESMTP_ALLOWED_MECH },
+ { "esmtp-require-encryption", KW_ESMTP_REQUIRE_ENCRYPTION },
+ { NULL }
+};
+
+static int
+parse_esmtp_kv (int key, ANUBIS_LIST arglist)
+{
+ char *arg = list_item (arglist, 0);
+ switch (key)
+ {
+#if defined (WITH_GSASL)
+ case KW_ESMTP_AUTH:
+ {
+ char *p = strchr (arg, ':');
+ if (p)
+ {
+ *p++ = 0;
+ auth_password = strdup (p);
+ authentication_id = strdup (arg);
+ authorization_id = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ }
+ else
+ topt &= ~T_ESMTP_AUTH;
+ }
+ break;
+
+ case KW_ESMTP_ANONYMOUS_TOKEN:
+ anon_token = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_AUTH_ID:
+ authentication_id = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_AUTHZ_ID:
+ authorization_id = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_PASSWORD:
+ auth_password = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_SERVICE:
+ auth_service = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_HOSTNAME:
+ auth_hostname = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_GENERIC_SERVICE:
+ generic_service_name = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_PASSCODE:
+ auth_passcode = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_REALM:
+ auth_realm = strdup (arg);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_ALLOWED_MECH:
+ anubis_set_client_mech_list (arglist);
+ topt |= T_ESMTP_AUTH;
+ break;
+
+ case KW_ESMTP_REQUIRE_ENCRYPTION:
+ anubis_set_encryption_mech_list (arglist);
+ break;
+
+ default:
+ return 1;
+#endif
+ }
+ return 0;
+}
+
void
control_parser (EVAL_ENV env, int key, ANUBIS_LIST arglist, void *inv_data)
{
@@ -450,77 +552,6 @@ control_parser (EVAL_ENV env, int key, ANUBIS_LIST arglist, void *inv_data)
topt |= T_LOCAL_MTA;
break;
-#if defined (WITH_GSASL)
- case KW_ESMTP_AUTH:
- {
- char *p = strchr (arg, ':');
- if (p)
- {
- *p++ = 0;
- auth_password = strdup (p);
- authentication_id = strdup (arg);
- authorization_id = strdup (arg);
- topt |= T_ESMTP_AUTH;
- }
- }
- break;
-
- case KW_ESMTP_ANONYMOUS_TOKEN:
- anon_token = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_AUTH_ID:
- authentication_id = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_AUTHZ_ID:
- authorization_id = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_PASSWORD:
- auth_password = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_SERVICE:
- auth_service = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_HOSTNAME:
- auth_hostname = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_GENERIC_SERVICE:
- generic_service_name = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_PASSCODE:
- auth_passcode = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_REALM:
- auth_realm = strdup (arg);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_ALLOWED_MECH:
- anubis_set_client_mech_list (arglist);
- topt |= T_ESMTP_AUTH;
- break;
-
- case KW_ESMTP_REQUIRE_ENCRYPTION:
- anubis_set_encryption_mech_list (arglist);
- break;
-
-#endif
-
case KW_LOCAL_DOMAIN:
anubis_domain = strdup (arg);
break;
@@ -622,13 +653,19 @@ control_parser (EVAL_ENV env, int key, ANUBIS_LIST arglist, void *inv_data)
_("Command HANG is not allowed for user `%s'"),
session.clientname);
break;
-
+#if defined (WITH_GSASL)
+ case KW_ESMTP_AUTH_DELAYED:
+ topt |= T_ESMTP_AUTH;
+ setbool (env, arg, topt, T_ESMTP_AUTH_DELAYED);
+ break;
+#endif
default:
- eval_error (2, env,
- _("INTERNAL ERROR at %s:%d: unhandled key %d; "
- "please report"),
- __FILE__, __LINE__,
- key);
+ if (parse_esmtp_kv (key, arglist))
+ eval_error (2, env,
+ _("INTERNAL ERROR at %s:%d: unhandled key %d; "
+ "please report"),
+ __FILE__, __LINE__,
+ key);
}
}
@@ -703,6 +740,7 @@ struct rc_kwdef control_kw[] = {
{ "esmtp-realm", KW_ESMTP_REALM, KWF_HIDDEN },
{ "esmtp-allowed-mech", KW_ESMTP_ALLOWED_MECH },
{ "esmtp-require-encryption", KW_ESMTP_REQUIRE_ENCRYPTION },
+ { "esmtp-auth-delayed", KW_ESMTP_AUTH_DELAYED },
#ifdef USE_SOCKS_PROXY
{ "socks-proxy", KW_SOCKS_PROXY },
{ "socks-v4", KW_SOCKS_V4 },
@@ -875,12 +913,96 @@ rule_section_init (void)
rc_secdef_add_child (sp, &rule_sect_child);
}
+
+void
+smtp_rule_parser (EVAL_ENV env, int key, ANUBIS_LIST arglist, void *inv_data)
+{
+ MESSAGE msg = eval_env_message (env);
+ char *arg = list_item (arglist, 0);
+ char **argv;
+
+ switch (key)
+ {
+ case KW_SIGNATURE_FILE_APPEND:
+ if (strcasecmp ("no", arg))
+ message_append_signature_file (msg);
+ break;
+
+ case KW_BODY_APPEND:
+ message_append_text_file (msg, arg, NULL);
+ break;
+
+ case KW_BODY_CLEAR:
+ message_replace_body (msg, xstrdup (""));
+ break;
+
+ case KW_BODY_CLEAR_APPEND:
+ message_replace_body (msg, xstrdup (""));
+ message_append_text_file (msg, arg, NULL);
+ break;
+
+ case KW_EXTERNAL_BODY_PROCESSOR:
+ argv = list_to_argv (arglist);
+ message_external_proc (msg, argv);
+ argcv_free (-1, argv);
+ break;
+
+ default:
+ if (parse_esmtp_kv (key, arglist))
+ eval_error (2, env,
+ _("INTERNAL ERROR at %s:%d: unhandled key %d; "
+ "please report"),
+ __FILE__, __LINE__,
+ key);
+ }
+}
+
+struct rc_kwdef smtp_rule_kw[] = {
+ { "signature-file-append", KW_SIGNATURE_FILE_APPEND },
+ { "body-append", KW_BODY_APPEND },
+ { "body-clear-append", KW_BODY_CLEAR_APPEND },
+ { "body-clear", KW_BODY_CLEAR },
+ { "external-body-processor", KW_EXTERNAL_BODY_PROCESSOR },
+ /* FIXME: It is supposed that none of the KW_ESMTP defines coincides
+ with any of the above */
+ { "esmtp-auth", KW_ESMTP_AUTH, KWF_HIDDEN },
+ { "esmtp-anonymous-token", KW_ESMTP_ANONYMOUS_TOKEN, KWF_HIDDEN },
+ { "esmtp-auth-id", KW_ESMTP_AUTH_ID, KWF_HIDDEN },
+ { "esmtp-authz-id", KW_ESMTP_AUTHZ_ID, KWF_HIDDEN },
+ { "esmtp-password", KW_ESMTP_PASSWORD, KWF_HIDDEN },
+ { "esmtp-service", KW_ESMTP_SERVICE, KWF_HIDDEN },
+ { "esmtp-hostname", KW_ESMTP_HOSTNAME, KWF_HIDDEN },
+ { "esmtp-generic-service", KW_ESMTP_SERVICE, KWF_HIDDEN },
+ { "esmtp-passcode", KW_ESMTP_PASSCODE, KWF_HIDDEN },
+ { "esmtp-realm", KW_ESMTP_REALM, KWF_HIDDEN },
+ { "esmtp-allowed-mech", KW_ESMTP_ALLOWED_MECH },
+ { NULL }
+};
+
+static struct rc_secdef_child smtp_rule_sect_child = {
+ NULL,
+ CF_CLIENT,
+ smtp_rule_kw,
+ smtp_rule_parser,
+ NULL
+};
+
+void
+smtp_rule_section_init (void)
+{
+ struct rc_secdef *sp = anubis_add_section ("SMTP");
+ sp->allow_prog = 1;
+ sp->prio = prio_system;
+ rc_secdef_add_child (sp, &smtp_rule_sect_child);
+}
+
void
rc_system_init (void)
{
control_section_init ();
translate_section_init ();
rule_section_init ();
+ smtp_rule_section_init ();
#ifdef WITH_GUILE
guile_section_init ();
#endif
@@ -899,16 +1021,17 @@ rcfile_process_section (int method, char *name, void *data, MESSAGE msg)
for (sec = rc_section_lookup (parse_tree, name);
sec; sec = rc_section_lookup (sec->next, name))
- rc_run_section (method, sec, anubis_rc_sections, data, msg);
+ rc_run_section (method, sec, anubis_rc_sections, NULL, data, msg);
}
void
-rcfile_call_section (int method, char *name, void *data, MESSAGE msg)
+rcfile_call_section (int method, char *name, char *class,
+ void *data, MESSAGE msg)
{
RC_SECTION *sec = rc_section_lookup (parse_tree, name);
if (!sec)
info (VERBOSE, _("No such section: %s"), name);
- rc_call_section (method, sec, anubis_rc_sections, data, msg);
+ rc_run_section (method, sec, anubis_rc_sections, class, data, msg);
}
char *
diff --git a/src/rcfile.h b/src/rcfile.h
index a502ece..b88636b 100644
--- a/src/rcfile.h
+++ b/src/rcfile.h
@@ -2,7 +2,7 @@
rcfile.h
This file is part of GNU Anubis.
- Copyright (C) 2003, 2007, 2009 The Anubis Team.
+ Copyright (C) 2003, 2007, 2009, 2011 The Anubis Team.
GNU Anubis is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -228,11 +228,8 @@ RC_SECTION *rc_parse (char *);
RC_SECTION *rc_parse_ep (char *name, RC_ERROR_PRINTER errprn, void *data);
void rc_section_list_destroy (RC_SECTION **);
int rc_run_cond (char *, int, char *);
-void rc_run_section_list (int, RC_SECTION *, struct rc_secdef *);
-void rc_run_section (int, RC_SECTION *, struct rc_secdef *, void *,
- MESSAGE);
-void rc_call_section (int, RC_SECTION *, struct rc_secdef *, void *,
- MESSAGE);
+void rc_run_section (int, RC_SECTION *, struct rc_secdef *, const char *,
+ void *, MESSAGE);
void rc_set_debug_level (char *);
int rc_open (char *);
struct rc_secdef *anubis_add_section (char *);
diff --git a/src/smtprepl.c b/src/smtprepl.c
index b1fd037..8301193 100644
--- a/src/smtprepl.c
+++ b/src/smtprepl.c
@@ -1,5 +1,5 @@
/* This file is part of GNU Anubis.
- Copyright (C) 2009 The Anubis Team.
+ Copyright (C) 2009, 2011 The Anubis Team.
GNU Anubis is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -49,9 +49,12 @@ smtp_reply_new ()
void
smtp_reply_free (ANUBIS_SMTP_REPLY reply)
{
- free (reply->buffer);
- free (reply->line_vec);
- free (reply);
+ if (reply)
+ {
+ free (reply->buffer);
+ free (reply->line_vec);
+ free (reply);
+ }
}
static void
diff --git a/src/tunnel.c b/src/tunnel.c
index 06542ab..e0d8c0b 100644
--- a/src/tunnel.c
+++ b/src/tunnel.c
@@ -3,7 +3,7 @@
This file is part of GNU Anubis.
Copyright (C) 2001, 2002, 2003, 2004, 2005, 2007, 2008,
- 2009, 2010 The Anubis Team.
+ 2009, 2010, 2011 The Anubis Team.
GNU Anubis is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
@@ -34,6 +34,7 @@ static int handle_ehlo (ANUBIS_SMTP_REPLY );
static char *smtp_ehlo_domain_name = NULL;
+static ANUBIS_SMTP_REPLY ehlo_reply = NULL;
char *
get_ehlo_domain (void)
@@ -600,14 +601,16 @@ handle_ehlo (ANUBIS_SMTP_REPLY reply)
{
if (!smtp_ehlo_domain_name)
save_ehlo_domain (smtp_reply_line (reply, 0));
-
- smtp_reply_get (CLIENT, remote_server, reply);
+
+ smtp_reply_free (ehlo_reply);
+ ehlo_reply = smtp_reply_new ();
+ smtp_reply_get (CLIENT, remote_server, ehlo_reply);
- if (smtp_reply_has_capa (reply, "STARTTLS", NULL))
+ if (smtp_reply_has_capa (ehlo_reply, "STARTTLS", NULL))
topt |= T_STARTTLS; /* Yes, we can use the TLS/SSL
encryption. */
- xdatabase_capability (reply);
+ xdatabase_capability (ehlo_reply);
#ifdef USE_SSL
if ((topt & T_SSL_ONEWAY)
@@ -638,7 +641,7 @@ handle_ehlo (ANUBIS_SMTP_REPLY reply)
smtp_reply_free (newreply);
anubis_error (0, 0, _("STARTTLS (ONEWAY) command failed."));
topt &= ~T_SSL_ONEWAY;
- swrite (SERVER, remote_client, smtp_reply_string (reply));
+ swrite (SERVER, remote_client, smtp_reply_string (ehlo_reply));
return 1;
}
smtp_reply_free (newreply);
@@ -649,7 +652,7 @@ handle_ehlo (ANUBIS_SMTP_REPLY reply)
if (!stream)
{
topt &= ~T_SSL_ONEWAY;
- swrite (SERVER, remote_client, smtp_reply_string (reply));
+ swrite (SERVER, remote_client, smtp_reply_string (ehlo_reply));
return 1;
}
@@ -663,7 +666,7 @@ handle_ehlo (ANUBIS_SMTP_REPLY reply)
swrite (CLIENT, remote_server, "EHLO ");
swrite (CLIENT, remote_server, get_ehlo_domain ());
send_eol (CLIENT, remote_server);
- smtp_reply_get (CLIENT, remote_server, reply);
+ smtp_reply_get (CLIENT, remote_server, ehlo_reply);
}
#endif /* USE_SSL */
@@ -676,8 +679,8 @@ handle_ehlo (ANUBIS_SMTP_REPLY reply)
if ((topt & T_STARTTLS) && (!(topt & T_SSL) || (topt & T_SSL_ONEWAY)))
{
size_t n;
- if (smtp_reply_has_capa (reply, "STARTTLS", &n))
- smtp_reply_remove_line (reply, n);
+ if (smtp_reply_has_capa (ehlo_reply, "STARTTLS", &n))
+ smtp_reply_remove_line (ehlo_reply, n);
}
/*
@@ -687,14 +690,22 @@ handle_ehlo (ANUBIS_SMTP_REPLY reply)
if (topt & T_ESMTP_AUTH)
{
size_t n;
- if (smtp_reply_has_capa (reply, "AUTH", &n))
+ if (smtp_reply_has_capa (ehlo_reply, "AUTH", &n))
{
- const char *p = smtp_reply_line (reply, n);
- esmtp_auth (&remote_server, p + 5);
- smtp_reply_remove_line (reply, n);
+ if (!(topt & T_ESMTP_AUTH_DELAYED))
+ {
+ const char *p = smtp_reply_line (ehlo_reply, n);
+ esmtp_auth (&remote_server, p + 9);
+ smtp_reply_remove_line (ehlo_reply, n);
+ topt &= ~T_ESMTP_AUTH;
+ }
}
+ else
+ topt &= ~T_ESMTP_AUTH;
}
-
+
+ smtp_reply_set (reply, smtp_reply_string (ehlo_reply));
+
return 0;
}
@@ -709,12 +720,26 @@ transfer_command (MESSAGE msg)
char *command;
int len;
- rcfile_call_section (CF_CLIENT, smtp_command_rule, NULL, msg);
+ rcfile_call_section (CF_CLIENT, smtp_command_rule, "SMTP", NULL, msg);
asc = list_tail_item (message_get_commands (msg));
if (!asc->value)
command = strdup (asc->key);
- else if (strcasecmp (asc->key, "mail from:") == 0
- || strcasecmp (asc->key, "rcpt to:") == 0)
+ else if (strcasecmp (asc->key, "mail from:") == 0)
+ {
+ if (topt & T_ESMTP_AUTH)
+ {
+ size_t n;
+ if (smtp_reply_has_capa (ehlo_reply, "AUTH", &n))
+ {
+ const char *p = smtp_reply_line (ehlo_reply, n);
+ esmtp_auth (&remote_server, p + 9);
+ smtp_reply_remove_line (ehlo_reply, n);
+ }
+ topt &= ~T_ESMTP_AUTH;
+ }
+ asprintf (&command, "%s%s", asc->key, asc->value);
+ }
+ else if (strcasecmp (asc->key, "rcpt to:") == 0)
asprintf (&command, "%s%s", asc->key, asc->value);
else
asprintf (&command, "%s %s", asc->key, asc->value);
@@ -737,7 +762,7 @@ transfer_command (MESSAGE msg)
}
else
smtp_reply_get (CLIENT, remote_server, reply);
-
+
swrite (SERVER, remote_client, smtp_reply_string (reply));
rstr = smtp_reply_line_ptr (reply, 0);
@@ -776,7 +801,7 @@ process_data (MESSAGE msg)
collect_headers (msg, NULL);
collect_body (msg);
- rcfile_call_section (CF_CLIENT, outgoing_mail_rule, NULL, msg);
+ rcfile_call_section (CF_CLIENT, outgoing_mail_rule, "RULE", NULL, msg);
transfer_header (message_get_header (msg));
transfer_body (msg);
diff --git a/testsuite/etc/add-body-file.pat b/testsuite/etc/add-body-file.pat
index b8d1318..5424ef6 100644
--- a/testsuite/etc/add-body-file.pat
+++ b/testsuite/etc/add-body-file.pat
@@ -22,7 +22,7 @@
:RETCODE 0
:PATTERN
:EXPECT 220
-HELO localhost
+HELO localhost
:EXPECT 250
MAIL FROM:<polak@gnu.org>
:EXPECT 250

Return to:

Send suggestions and report system problems to the System administrator.