summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorJeremy Harris <jgh146exb@wizmail.org>2015-06-04 20:28:25 +0100
committerJeremy Harris <jgh146exb@wizmail.org>2015-06-04 21:54:52 +0100
commitb3ef41c94af9aefec7b6855cf2ce73ffeaba9d9a (patch)
treeb4a58a99cfca03ab585d109fdf8484bf3b7f87fc /src
parent93893bd908c58f8d97b1847a5b1f933267de3058 (diff)
TLS authenticator
Diffstat (limited to 'src')
-rwxr-xr-xsrc/scripts/MakeLinks2
-rw-r--r--src/src/EDITME1
-rw-r--r--src/src/auths/Makefile3
-rw-r--r--src/src/auths/tls.c80
-rw-r--r--src/src/auths/tls.h30
-rw-r--r--src/src/config.h.defaults1
-rw-r--r--src/src/drtables.c18
-rw-r--r--src/src/exim.c3
-rw-r--r--src/src/smtp_in.c343
-rw-r--r--src/src/tls-openssl.c2
-rw-r--r--src/src/tlscert-openssl.c19
11 files changed, 342 insertions, 160 deletions
diff --git a/src/scripts/MakeLinks b/src/scripts/MakeLinks
index d8c3f1c36..ea6265002 100755
--- a/src/scripts/MakeLinks
+++ b/src/scripts/MakeLinks
@@ -73,7 +73,7 @@ for f in README Makefile b64encode.c b64decode.c call_pam.c call_pwcheck.c \
gsasl_exim.h get_data.c get_no64_data.c heimdal_gssapi.c heimdal_gssapi.h \
md5.c xtextencode.c xtextdecode.c cram_md5.c cram_md5.h plaintext.c plaintext.h \
pwcheck.c pwcheck.h auth-spa.c auth-spa.h dovecot.c dovecot.h sha1.c spa.c \
- spa.h
+ spa.h tls.c tls.h
do
ln -s ../../src/auths/$f $f
done
diff --git a/src/src/EDITME b/src/src/EDITME
index 784c67797..d4811225a 100644
--- a/src/src/EDITME
+++ b/src/src/EDITME
@@ -637,6 +637,7 @@ FIXED_NEVER_USERS=root
# AUTH_HEIMDAL_GSSAPI_PC=heimdal-gssapi
# AUTH_PLAINTEXT=yes
# AUTH_SPA=yes
+# AUTH_TLS=yes
#------------------------------------------------------------------------------
diff --git a/src/src/auths/Makefile b/src/src/auths/Makefile
index c6ef218b2..45d294932 100644
--- a/src/src/auths/Makefile
+++ b/src/src/auths/Makefile
@@ -9,7 +9,7 @@ OBJ = auth-spa.o b64decode.o b64encode.o call_pam.o call_pwcheck.o \
call_radius.o check_serv_cond.o cram_md5.o cyrus_sasl.o dovecot.o \
get_data.o get_no64_data.o gsasl_exim.o heimdal_gssapi.o \
md5.o plaintext.o pwcheck.o sha1.o \
- spa.o xtextdecode.o xtextencode.o
+ spa.o tls.o xtextdecode.o xtextencode.o
auths.a: $(OBJ)
@$(RM_COMMAND) -f auths.a
@@ -43,5 +43,6 @@ gsasl_exim.o: $(HDRS) gsasl_exim.c gsasl_exim.h
heimdal_gssapi.o: $(HDRS) heimdal_gssapi.c heimdal_gssapi.h
plaintext.o: $(HDRS) plaintext.c plaintext.h
spa.o: $(HDRS) spa.c spa.h
+tls.o: $(HDRS) tls.c tls.h
# End
diff --git a/src/src/auths/tls.c b/src/src/auths/tls.c
new file mode 100644
index 000000000..51c096cd0
--- /dev/null
+++ b/src/src/auths/tls.c
@@ -0,0 +1,80 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) Jeremy Harris 2015 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* This file provides an Exim authenticator driver for
+a server to verify a client SSL certificate
+*/
+
+
+#include "../exim.h"
+#include "tls.h"
+
+/* Options specific to the tls authentication mechanism. */
+
+optionlist auth_tls_options[] = {
+ { "server_param", opt_stringptr,
+ (void *)(offsetof(auth_tls_options_block, server_param1)) },
+ { "server_param1", opt_stringptr,
+ (void *)(offsetof(auth_tls_options_block, server_param1)) },
+ { "server_param2", opt_stringptr,
+ (void *)(offsetof(auth_tls_options_block, server_param2)) },
+ { "server_param3", opt_stringptr,
+ (void *)(offsetof(auth_tls_options_block, server_param3)) },
+};
+
+/* Size of the options list. An extern variable has to be used so that its
+address can appear in the tables drtables.c. */
+
+int auth_tls_options_count = nelem(auth_tls_options);
+
+/* Default private options block for the authentication method. */
+
+auth_tls_options_block auth_tls_option_defaults = {
+ NULL, /* server_param1 */
+ NULL, /* server_param2 */
+ NULL, /* server_param3 */
+};
+
+
+/*************************************************
+* Initialization entry point *
+*************************************************/
+
+/* Called for each instance, after its options have been read, to
+enable consistency checks to be done, or anything else that needs
+to be set up. */
+
+void
+auth_tls_init(auth_instance *ablock)
+{
+ablock->public_name = ablock->name; /* needed for core code */
+}
+
+
+
+/*************************************************
+* Server entry point *
+*************************************************/
+
+/* For interface, see auths/README */
+
+int
+auth_tls_server(auth_instance *ablock, uschar *data)
+{
+auth_tls_options_block * ob = (auth_tls_options_block *)ablock->options_block;
+
+if (ob->server_param1)
+ auth_vars[expand_nmax++] = expand_string(ob->server_param1);
+if (ob->server_param2)
+ auth_vars[expand_nmax++] = expand_string(ob->server_param2);
+if (ob->server_param2)
+ auth_vars[expand_nmax++] = expand_string(ob->server_param3);
+return auth_check_serv_cond(ablock);
+}
+
+
+/* End of tls.c */
diff --git a/src/src/auths/tls.h b/src/src/auths/tls.h
new file mode 100644
index 000000000..bf2a2a1c6
--- /dev/null
+++ b/src/src/auths/tls.h
@@ -0,0 +1,30 @@
+/*************************************************
+* Exim - an Internet mail transport agent *
+*************************************************/
+
+/* Copyright (c) Jeremy Harris 2015 */
+/* See the file NOTICE for conditions of use and distribution. */
+
+/* Private structure for the private options. */
+
+typedef struct {
+ uschar * server_param1;
+ uschar * server_param2;
+ uschar * server_param3;
+} auth_tls_options_block;
+
+/* Data for reading the private options. */
+
+extern optionlist auth_tls_options[];
+extern int auth_tls_options_count;
+
+/* Block containing default values. */
+
+extern auth_tls_options_block auth_tls_option_defaults;
+
+/* The entry points for the mechanism */
+
+extern void auth_tls_init(auth_instance *);
+extern int auth_tls_server(auth_instance *, uschar *);
+
+/* End of sa.h */
diff --git a/src/src/config.h.defaults b/src/src/config.h.defaults
index d31f11548..ec5351859 100644
--- a/src/src/config.h.defaults
+++ b/src/src/config.h.defaults
@@ -24,6 +24,7 @@ it's a default value. */
#define AUTH_HEIMDAL_GSSAPI
#define AUTH_PLAINTEXT
#define AUTH_SPA
+#define AUTH_TLS
#define AUTH_VARS 3
diff --git a/src/src/drtables.c b/src/src/drtables.c
index c2d866850..5758a92ac 100644
--- a/src/src/drtables.c
+++ b/src/src/drtables.c
@@ -53,6 +53,10 @@ set to NULL for those that are not compiled into the binary. */
#include "auths/spa.h"
#endif
+#ifdef AUTH_TLS
+#include "auths/tls.h"
+#endif
+
auth_info auths_available[] = {
/* Checking by an expansion condition on plain text */
@@ -155,6 +159,20 @@ auth_info auths_available[] = {
},
#endif
+#ifdef AUTH_TLS
+ {
+ US"tls", /* lookup name */
+ auth_tls_options,
+ &auth_tls_options_count,
+ &auth_tls_option_defaults,
+ sizeof(auth_tls_options_block),
+ auth_tls_init, /* init function */
+ auth_tls_server, /* server function */
+ NULL, /* client function */
+ NULL /* diagnostic function */
+ },
+#endif
+
{ US"", NULL, NULL, NULL, 0, NULL, NULL, NULL, NULL }
};
diff --git a/src/src/exim.c b/src/src/exim.c
index 3eca43b49..81bc51ec7 100644
--- a/src/src/exim.c
+++ b/src/src/exim.c
@@ -937,6 +937,9 @@ fprintf(f, "Authenticators:");
#ifdef AUTH_SPA
fprintf(f, " spa");
#endif
+#ifdef AUTH_TLS
+ fprintf(f, " tls");
+#endif
fprintf(f, "\n");
fprintf(f, "Routers:");
diff --git a/src/src/smtp_in.c b/src/src/smtp_in.c
index b451c48f5..fc3d34c40 100644
--- a/src/src/smtp_in.c
+++ b/src/src/smtp_in.c
@@ -71,6 +71,7 @@ enum {
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 */
+ TLS_AUTH_CMD, /* auto-command at start of SSL */
/* This is a dummy to identify the non-sync commands when pipelining */
@@ -169,6 +170,7 @@ static smtp_cmd_list cmd_list[] = {
{ "auth", sizeof("auth")-1, AUTH_CMD, TRUE, TRUE },
#ifdef SUPPORT_TLS
{ "starttls", sizeof("starttls")-1, STARTTLS_CMD, FALSE, FALSE },
+ { "tls_auth", 0, TLS_AUTH_CMD, FALSE, TRUE },
#endif
/* If you change anything above here, also fix the definitions below. */
@@ -192,6 +194,7 @@ static smtp_cmd_list *cmd_list_end =
#define CMD_LIST_EHLO 2
#define CMD_LIST_AUTH 3
#define CMD_LIST_STARTTLS 4
+#define CMD_LIST_TLS_AUTH 5
/* This list of names is used for performing the smtp_no_mail logging action.
It must be kept in step with the SCH_xxx enumerations. */
@@ -3094,6 +3097,113 @@ smtp_respond(code, len, TRUE, user_msg);
+static int
+smtp_in_auth(auth_instance *au, uschar ** s, uschar ** ss)
+{
+const uschar *set_id = NULL;
+int rc, i;
+
+/* Run the checking code, passing the remainder of the command line as
+data. Initials the $auth<n> variables as empty. Initialize $0 empty and set
+it as the only set numerical variable. The authenticator may set $auth<n>
+and also set other numeric variables. The $auth<n> variables are preferred
+nowadays; the numerical variables remain for backwards compatibility.
+
+Afterwards, have a go at expanding the set_id string, even if
+authentication failed - for bad passwords it can be useful to log the
+userid. On success, require set_id to expand and exist, and put it in
+authenticated_id. Save this in permanent store, as the working store gets
+reset at HELO, RSET, etc. */
+
+for (i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL;
+expand_nmax = 0;
+expand_nlength[0] = 0; /* $0 contains nothing */
+
+rc = (au->info->servercode)(au, smtp_cmd_data);
+if (au->set_id) set_id = expand_string(au->set_id);
+expand_nmax = -1; /* Reset numeric variables */
+for (i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL; /* Reset $auth<n> */
+
+/* The value of authenticated_id is stored in the spool file and printed in
+log lines. It must not contain binary zeros or newline characters. In
+normal use, it never will, but when playing around or testing, this error
+can (did) happen. To guard against this, ensure that the id contains only
+printing characters. */
+
+if (set_id) set_id = string_printing(set_id);
+
+/* For the non-OK cases, set up additional logging data if set_id
+is not empty. */
+
+if (rc != OK)
+ set_id = set_id && *set_id
+ ? string_sprintf(" (set_id=%s)", set_id) : US"";
+
+/* Switch on the result */
+
+switch(rc)
+ {
+ case OK:
+ if (!au->set_id || set_id) /* Complete success */
+ {
+ if (set_id) authenticated_id = string_copy_malloc(set_id);
+ sender_host_authenticated = au->name;
+ authentication_failed = FALSE;
+ authenticated_fail_id = NULL; /* Impossible to already be set? */
+
+ received_protocol =
+ (sender_host_address ? protocols : protocols_local)
+ [pextend + pauthed + (tls_in.active >= 0 ? pcrpted:0)];
+ *s = *ss = US"235 Authentication succeeded";
+ authenticated_by = au;
+ break;
+ }
+
+ /* Authentication succeeded, but we failed to expand the set_id string.
+ Treat this as a temporary error. */
+
+ auth_defer_msg = expand_string_message;
+ /* Fall through */
+
+ case DEFER:
+ if (set_id) authenticated_fail_id = string_copy_malloc(set_id);
+ *s = string_sprintf("435 Unable to authenticate at present%s",
+ auth_defer_user_msg);
+ *ss = string_sprintf("435 Unable to authenticate at present%s: %s",
+ set_id, auth_defer_msg);
+ break;
+
+ case BAD64:
+ *s = *ss = US"501 Invalid base64 data";
+ break;
+
+ case CANCELLED:
+ *s = *ss = US"501 Authentication cancelled";
+ break;
+
+ case UNEXPECTED:
+ *s = *ss = US"553 Initial data not expected";
+ break;
+
+ case FAIL:
+ if (set_id) authenticated_fail_id = string_copy_malloc(set_id);
+ *s = US"535 Incorrect authentication data";
+ *ss = string_sprintf("535 Incorrect authentication data%s", set_id);
+ break;
+
+ default:
+ if (set_id) authenticated_fail_id = string_copy_malloc(set_id);
+ *s = US"435 Internal error";
+ *ss = string_sprintf("435 Internal error%s: return %d from authentication "
+ "check", set_id, rc);
+ break;
+ }
+
+return rc;
+}
+
+
+
/*************************************************
* Initialize for SMTP incoming message *
*************************************************/
@@ -3145,6 +3255,7 @@ cmd_list[CMD_LIST_HELO].is_mail_cmd = TRUE;
cmd_list[CMD_LIST_EHLO].is_mail_cmd = TRUE;
#ifdef SUPPORT_TLS
cmd_list[CMD_LIST_STARTTLS].is_mail_cmd = TRUE;
+cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = TRUE;
#endif
/* Set the local signal handler for SIGTERM - it tries to end off tidily */
@@ -3168,7 +3279,6 @@ while (done <= 0)
uschar *user_msg = NULL;
uschar *recipient = NULL;
uschar *hello = NULL;
- const uschar *set_id = NULL;
uschar *s, *ss;
BOOL was_rej_mail = FALSE;
BOOL was_rcpt = FALSE;
@@ -3181,6 +3291,41 @@ while (done <= 0)
uschar *orcpt = NULL;
int flags;
+#if defined(SUPPORT_TLS) && defined(AUTH_TLS)
+ /* Check once per STARTTLS or SSL-on-connect for a TLS AUTH */
+ if ( tls_in.active >= 0
+ && tls_in.peercert
+ && tls_in.certificate_verified
+ && cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd
+ )
+ {
+ cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = FALSE;
+ if (acl_smtp_auth)
+ {
+ rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, &user_msg, &log_msg);
+ if (rc != OK)
+ {
+ done = smtp_handle_acl_fail(ACL_WHERE_AUTH, rc, user_msg, log_msg);
+ continue;
+ }
+ }
+
+ for (au = auths; au; au = au->next)
+ if (strcmpic(US"tls", au->driver_name) == 0)
+ {
+ smtp_cmd_data = NULL;
+
+ if ((c = smtp_in_auth(au, &s, &ss)) != OK)
+ log_write(0, LOG_MAIN|LOG_REJECT, "%s authenticator failed for %s: %s",
+ au->name, host_and_ident(FALSE), ss);
+ else
+ DEBUG(D_auth) debug_printf("tls auth succeeded\n");
+
+ break;
+ }
+ }
+#endif
+
switch(smtp_read_command(TRUE))
{
/* The AUTH command is not permitted to occur inside a transaction, and may
@@ -3208,13 +3353,13 @@ while (done <= 0)
US"AUTH command used when not advertised");
break;
}
- if (sender_host_authenticated != NULL)
+ if (sender_host_authenticated)
{
done = synprot_error(L_smtp_protocol_error, 503, NULL,
US"already authenticated");
break;
}
- if (sender_address != NULL)
+ if (sender_address)
{
done = synprot_error(L_smtp_protocol_error, 503, NULL,
US"not permitted in mail transaction");
@@ -3223,7 +3368,7 @@ while (done <= 0)
/* Check the ACL */
- if (acl_smtp_auth != NULL)
+ if (acl_smtp_auth)
{
rc = acl_check(ACL_WHERE_AUTH, NULL, acl_smtp_auth, &user_msg, &log_msg);
if (rc != OK)
@@ -3260,122 +3405,23 @@ while (done <= 0)
as a server and which has been advertised (unless, sigh, allow_auth_
unadvertised is set). */
- for (au = auths; au != NULL; au = au->next)
- {
+ for (au = auths; au; au = au->next)
if (strcmpic(s, au->public_name) == 0 && au->server &&
- (au->advertised || allow_auth_unadvertised)) break;
- }
-
- if (au == NULL)
- {
- done = synprot_error(L_smtp_protocol_error, 504, NULL,
- string_sprintf("%s authentication mechanism not supported", s));
- break;
- }
-
- /* Run the checking code, passing the remainder of the command line as
- data. Initials the $auth<n> variables as empty. Initialize $0 empty and set
- it as the only set numerical variable. The authenticator may set $auth<n>
- and also set other numeric variables. The $auth<n> variables are preferred
- nowadays; the numerical variables remain for backwards compatibility.
-
- Afterwards, have a go at expanding the set_id string, even if
- authentication failed - for bad passwords it can be useful to log the
- userid. On success, require set_id to expand and exist, and put it in
- authenticated_id. Save this in permanent store, as the working store gets
- reset at HELO, RSET, etc. */
-
- for (i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL;
- expand_nmax = 0;
- expand_nlength[0] = 0; /* $0 contains nothing */
-
- c = (au->info->servercode)(au, smtp_cmd_data);
- if (au->set_id != NULL) set_id = expand_string(au->set_id);
- expand_nmax = -1; /* Reset numeric variables */
- for (i = 0; i < AUTH_VARS; i++) auth_vars[i] = NULL; /* Reset $auth<n> */
-
- /* The value of authenticated_id is stored in the spool file and printed in
- log lines. It must not contain binary zeros or newline characters. In
- normal use, it never will, but when playing around or testing, this error
- can (did) happen. To guard against this, ensure that the id contains only
- printing characters. */
-
- if (set_id != NULL) set_id = string_printing(set_id);
-
- /* For the non-OK cases, set up additional logging data if set_id
- is not empty. */
-
- if (c != OK)
- {
- if (set_id != NULL && *set_id != 0)
- set_id = string_sprintf(" (set_id=%s)", set_id);
- else set_id = US"";
- }
-
- /* Switch on the result */
+ (au->advertised || allow_auth_unadvertised))
+ break;
- switch(c)
+ if (au)
{
- case OK:
- if (au->set_id == NULL || set_id != NULL) /* Complete success */
- {
- if (set_id != NULL) authenticated_id = string_copy_malloc(set_id);
- sender_host_authenticated = au->name;
- authentication_failed = FALSE;
- authenticated_fail_id = NULL; /* Impossible to already be set? */
-
- received_protocol =
- (sender_host_address ? protocols : protocols_local)
- [pextend + pauthed + (tls_in.active >= 0 ? pcrpted:0)];
- s = ss = US"235 Authentication succeeded";
- authenticated_by = au;
- break;
- }
-
- /* Authentication succeeded, but we failed to expand the set_id string.
- Treat this as a temporary error. */
-
- auth_defer_msg = expand_string_message;
- /* Fall through */
-
- case DEFER:
- if (set_id != NULL) authenticated_fail_id = string_copy_malloc(set_id);
- s = string_sprintf("435 Unable to authenticate at present%s",
- auth_defer_user_msg);
- ss = string_sprintf("435 Unable to authenticate at present%s: %s",
- set_id, auth_defer_msg);
- break;
-
- case BAD64:
- s = ss = US"501 Invalid base64 data";
- break;
-
- case CANCELLED:
- s = ss = US"501 Authentication cancelled";
- break;
-
- case UNEXPECTED:
- s = ss = US"553 Initial data not expected";
- break;
-
- case FAIL:
- if (set_id != NULL) authenticated_fail_id = string_copy_malloc(set_id);
- s = US"535 Incorrect authentication data";
- ss = string_sprintf("535 Incorrect authentication data%s", set_id);
- break;
+ c = smtp_in_auth(au, &s, &ss);
- default:
- if (set_id != NULL) authenticated_fail_id = string_copy_malloc(set_id);
- s = US"435 Internal error";
- ss = string_sprintf("435 Internal error%s: return %d from authentication "
- "check", set_id, c);
- break;
+ smtp_printf("%s\r\n", s);
+ if (c != OK)
+ log_write(0, LOG_MAIN|LOG_REJECT, "%s authenticator failed for %s: %s",
+ au->name, host_and_ident(FALSE), ss);
}
-
- smtp_printf("%s\r\n", s);
- if (c != OK)
- log_write(0, LOG_MAIN|LOG_REJECT, "%s authenticator failed for %s: %s",
- au->name, host_and_ident(FALSE), ss);
+ else
+ done = synprot_error(L_smtp_protocol_error, 504, NULL,
+ string_sprintf("%s authentication mechanism not supported", s));
break; /* AUTH_CMD */
@@ -3661,38 +3707,40 @@ while (done <= 0)
letters, so output the names in upper case, though we actually recognize
them in either case in the AUTH command. */
- if (auths != NULL)
- {
- if (verify_check_host(&auth_advertise_hosts) == OK)
- {
- auth_instance *au;
- BOOL first = TRUE;
- for (au = auths; au != NULL; au = au->next)
- {
- if (au->server && (au->advertise_condition == NULL ||
- expand_check_condition(au->advertise_condition, au->name,
- US"authenticator")))
- {
- int saveptr;
- if (first)
- {
- s = string_cat(s, &size, &ptr, smtp_code, 3);
- s = string_cat(s, &size, &ptr, US"-AUTH", 5);
- first = FALSE;
- auth_advertised = TRUE;
- }
- saveptr = ptr;
- s = string_cat(s, &size, &ptr, US" ", 1);
- s = string_cat(s, &size, &ptr, au->public_name,
- Ustrlen(au->public_name));
- while (++saveptr < ptr) s[saveptr] = toupper(s[saveptr]);
- au->advertised = TRUE;
- }
- else au->advertised = FALSE;
- }
- if (!first) s = string_cat(s, &size, &ptr, US"\r\n", 2);
- }
- }
+ if ( auths
+#if defined(SUPPORT_TLS) && defined(AUTH_TLS)
+ && !sender_host_authenticated
+#endif
+ && verify_check_host(&auth_advertise_hosts) == OK
+ )
+ {
+ auth_instance *au;
+ BOOL first = TRUE;
+ for (au = auths; au; au = au->next)
+ if (au->server && (au->advertise_condition == NULL ||
+ expand_check_condition(au->advertise_condition, au->name,
+ US"authenticator")))
+ {
+ int saveptr;
+ if (first)
+ {
+ s = string_cat(s, &size, &ptr, smtp_code, 3);
+ s = string_cat(s, &size, &ptr, US"-AUTH", 5);
+ first = FALSE;
+ auth_advertised = TRUE;
+ }
+ saveptr = ptr;
+ s = string_cat(s, &size, &ptr, US" ", 1);
+ s = string_cat(s, &size, &ptr, au->public_name,
+ Ustrlen(au->public_name));
+ while (++saveptr < ptr) s[saveptr] = toupper(s[saveptr]);
+ au->advertised = TRUE;
+ }
+ else
+ au->advertised = FALSE;
+
+ if (!first) s = string_cat(s, &size, &ptr, US"\r\n", 2);
+ }
/* Advertise TLS (Transport Level Security) aka SSL (Secure Socket Layer)
if it has been included in the binary, and the host matches
@@ -4667,6 +4715,7 @@ while (done <= 0)
helo_seen = esmtp = auth_advertised = pipelining_advertised = FALSE;
cmd_list[CMD_LIST_EHLO].is_mail_cmd = TRUE;
cmd_list[CMD_LIST_AUTH].is_mail_cmd = TRUE;
+ cmd_list[CMD_LIST_TLS_AUTH].is_mail_cmd = TRUE;
if (sender_helo_name != NULL)
{
store_free(sender_helo_name);
diff --git a/src/src/tls-openssl.c b/src/src/tls-openssl.c
index 456ca8142..9c1bf8632 100644
--- a/src/src/tls-openssl.c
+++ b/src/src/tls-openssl.c
@@ -1024,7 +1024,7 @@ uschar *response_der;
int response_der_len;
DEBUG(D_tls)
- debug_printf("Received TLS status request (OCSP stapling); %s response.",
+ debug_printf("Received TLS status request (OCSP stapling); %s response\n",
cbinfo->u_ocsp.server.response ? "have" : "lack");
tls_in.ocsp = OCSP_NOT_RESP;
diff --git a/src/src/tlscert-openssl.c b/src/src/tlscert-openssl.c
index b100e222b..726303313 100644
--- a/src/src/tlscert-openssl.c
+++ b/src/src/tlscert-openssl.c
@@ -331,7 +331,7 @@ tls_cert_subject_altname(void * cert, uschar * mod)
uschar * list = NULL;
STACK_OF(GENERAL_NAME) * san = (STACK_OF(GENERAL_NAME) *)
X509_get_ext_d2i((X509 *)cert, NID_subject_alt_name, NULL, NULL);
-uschar sep = '\n';
+uschar osep = '\n';
uschar * tag = US"";
uschar * ele;
int match = -1;
@@ -339,16 +339,15 @@ int len;
if (!san) return NULL;
-while (mod)
+while (mod && *mod)
{
- if (*mod == '>' && *++mod) sep = *mod++;
- else if (Ustrcmp(mod, "dns")==0) { match = GEN_DNS; mod += 3; }
- else if (Ustrcmp(mod, "uri")==0) { match = GEN_URI; mod += 3; }
- else if (Ustrcmp(mod, "mail")==0) { match = GEN_EMAIL; mod += 4; }
- else continue;
+ if (*mod == '>' && *++mod) osep = *mod++;
+ else if (Ustrncmp(mod,"dns",3)==0) { match = GEN_DNS; mod += 3; }
+ else if (Ustrncmp(mod,"uri",3)==0) { match = GEN_URI; mod += 3; }
+ else if (Ustrncmp(mod,"mail",4)==0) { match = GEN_EMAIL; mod += 4; }
+ else mod++;
- if (*mod++ != ',')
- break;
+ if (*mod == ',') mod++;
}
while (sk_GENERAL_NAME_num(san) > 0)
@@ -380,7 +379,7 @@ while (sk_GENERAL_NAME_num(san) > 0)
ele = string_copyn(ele, len);
if (Ustrlen(ele) == len) /* ignore any with embedded nul */
- list = string_append_listele(list, sep,
+ list = string_append_listele(list, osep,
match == -1 ? string_sprintf("%s=%s", tag, ele) : ele);
}