[exim-cvs] Refactor authenticators API to take an (opaque) s…

Top Page
Delete this message
Reply to this message
Author: Exim Git Commits Mailing List
Date:  
To: exim-cvs
Subject: [exim-cvs] Refactor authenticators API to take an (opaque) smtp connection context
Gitweb: https://git.exim.org/exim.git/commitdiff/251b9eb4698f569864c35127ddb7c309b92ccecb
Commit:     251b9eb4698f569864c35127ddb7c309b92ccecb
Parent:     6523b984f03bc9de3edae2db65c1c54837e730a8
Author:     Jeremy Harris <jgh146exb@???>
AuthorDate: Wed Aug 29 19:10:41 2018 +0100
Committer:  Jeremy Harris <jgh146exb@???>
CommitDate: Wed Aug 29 20:07:55 2018 +0100


    Refactor authenticators API to take an (opaque) smtp connection context
---
 src/src/auths/README           |   2 +-
 src/src/auths/cram_md5.c       |  16 +++--
 src/src/auths/cram_md5.h       |   3 +-
 src/src/auths/cyrus_sasl.c     |   7 +--
 src/src/auths/cyrus_sasl.h     |   3 +-
 src/src/auths/dovecot.c        |   4 +-
 src/src/auths/gsasl_exim.c     |   7 +--
 src/src/auths/heimdal_gssapi.c |   7 +--
 src/src/auths/plaintext.c      |  31 +++++-----
 src/src/auths/plaintext.h      |   3 +-
 src/src/auths/spa.c            |  22 +++----
 src/src/auths/spa.h            |   3 +-
 src/src/auths/tls.c            |   4 +-
 src/src/functions.h            |   4 +-
 src/src/smtp_out.c             |  11 ++--
 src/src/structs.h              |   3 +-
 src/src/transports/smtp.c      | 136 +++++++++++++++++++----------------------
 src/src/transports/smtp.h      |   3 -
 src/src/verify.c               |  65 ++++++++++----------
 19 files changed, 153 insertions(+), 181 deletions(-)


diff --git a/src/src/auths/README b/src/src/auths/README
index 21b0cda..0e0c097 100644
--- a/src/src/auths/README
+++ b/src/src/auths/README
@@ -68,7 +68,7 @@ CLIENT AUTHENTICATION
The third function performs authentication as a client. It receives a pointer
to the instance block, and four further arguments:

- The smtp_inblock item for the connection to the remote host.
+ The smtp_context item for the connection to the remote host.

The normal command-reading timeout value.

diff --git a/src/src/auths/cram_md5.c b/src/src/auths/cram_md5.c
index b9607b1..8e4794c 100644
--- a/src/src/auths/cram_md5.c
+++ b/src/src/auths/cram_md5.c
@@ -52,8 +52,8 @@ auth_cram_md5_options_block auth_cram_md5_option_defaults = {
 /* Dummy values */
 void auth_cram_md5_init(auth_instance *ablock) {}
 int auth_cram_md5_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_cram_md5_client(auth_instance *ablock, smtp_inblock *inblock,
-  smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_cram_md5_client(auth_instance *ablock, void *sx, int timeout,
+    uschar *buffer, int buffsize) {return 0;}


 #else    /*!MACRO_PREDEF*/


@@ -259,8 +259,7 @@ return auth_check_serv_cond(ablock);
 int
 auth_cram_md5_client(
   auth_instance *ablock,                 /* authenticator block */
-  smtp_inblock *inblock,                 /* input connection */
-  smtp_outblock *outblock,               /* output connection */
+  void * sx,                 /* smtp connextion */
   int timeout,                           /* command timeout */
   uschar *buffer,                        /* for reading response */
   int buffsize)                          /* size of buffer */
@@ -293,10 +292,9 @@ if (!secret || !name)
 /* Initiate the authentication exchange and read the challenge, which arrives
 in base 64. */


-if (smtp_write_command(outblock, SCMD_FLUSH, "AUTH %s\r\n",
-                   ablock->public_name) < 0)
+if (smtp_write_command(sx, SCMD_FLUSH, "AUTH %s\r\n", ablock->public_name) < 0)
   return FAIL_SEND;
-if (!smtp_read_response(inblock, buffer, buffsize, '3', timeout))
+if (!smtp_read_response(sx, buffer, buffsize, '3', timeout))
   return FAIL;


if (b64decode(buffer + 4, &challenge) < 0)
@@ -324,10 +322,10 @@ in big_buffer, but b64encode() returns its result in working store,
so calling smtp_write_command(), which uses big_buffer, is OK. */

buffer[0] = 0;
-if (smtp_write_command(outblock, SCMD_FLUSH, "%s\r\n", b64encode(big_buffer,
+if (smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", b64encode(big_buffer,
p - big_buffer)) < 0) return FAIL_SEND;

-return smtp_read_response(inblock, US buffer, buffsize, '2', timeout)
+return smtp_read_response(sx, US buffer, buffsize, '2', timeout)
? OK : FAIL;
}
#endif /* STAND_ALONE */
diff --git a/src/src/auths/cram_md5.h b/src/src/auths/cram_md5.h
index e1363bf..95644db 100644
--- a/src/src/auths/cram_md5.h
+++ b/src/src/auths/cram_md5.h
@@ -26,7 +26,6 @@ extern auth_cram_md5_options_block auth_cram_md5_option_defaults;

 extern void auth_cram_md5_init(auth_instance *);
 extern int auth_cram_md5_server(auth_instance *, uschar *);
-extern int auth_cram_md5_client(auth_instance *, smtp_inblock *,
-                                smtp_outblock *, int, uschar *, int);
+extern int auth_cram_md5_client(auth_instance *, void *, int, uschar *, int);


/* End of cram_md5.h */
diff --git a/src/src/auths/cyrus_sasl.c b/src/src/auths/cyrus_sasl.c
index 7bb86b8..2cfed7a 100644
--- a/src/src/auths/cyrus_sasl.c
+++ b/src/src/auths/cyrus_sasl.c
@@ -68,8 +68,8 @@ auth_cyrus_sasl_options_block auth_cyrus_sasl_option_defaults = {
/* Dummy values */
void auth_cyrus_sasl_init(auth_instance *ablock) {}
int auth_cyrus_sasl_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_cyrus_sasl_client(auth_instance *ablock, smtp_inblock *inblock,
- smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_cyrus_sasl_client(auth_instance *ablock, void * sx,
+ int timeout, uschar *buffer, int buffsize) {return 0;}
void auth_cyrus_sasl_version_report(FILE *f) {}

 #else   /*!MACRO_PREDEF*/
@@ -529,8 +529,7 @@ auth_cyrus_sasl_version_report(FILE *f)
 int
 auth_cyrus_sasl_client(
   auth_instance *ablock,                 /* authenticator block */
-  smtp_inblock *inblock,                 /* input connection */
-  smtp_outblock *outblock,               /* output connection */
+  void * sx,                  /* connexction */
   int timeout,                           /* command timeout */
   uschar *buffer,                          /* for reading response */
   int buffsize)                          /* size of buffer */
diff --git a/src/src/auths/cyrus_sasl.h b/src/src/auths/cyrus_sasl.h
index 8481054..da6f3cd 100644
--- a/src/src/auths/cyrus_sasl.h
+++ b/src/src/auths/cyrus_sasl.h
@@ -29,8 +29,7 @@ extern auth_cyrus_sasl_options_block auth_cyrus_sasl_option_defaults;


 extern void auth_cyrus_sasl_init(auth_instance *);
 extern int auth_cyrus_sasl_server(auth_instance *, uschar *);
-extern int auth_cyrus_sasl_client(auth_instance *, smtp_inblock *,
-                                smtp_outblock *, int, uschar *, int);
+extern int auth_cyrus_sasl_client(auth_instance *, void *, int, uschar *, int);
 extern void auth_cyrus_sasl_version_report(FILE *f);


/* End of cyrus_sasl.h */
diff --git a/src/src/auths/dovecot.c b/src/src/auths/dovecot.c
index 8c5b411..b1dde06 100644
--- a/src/src/auths/dovecot.c
+++ b/src/src/auths/dovecot.c
@@ -78,8 +78,8 @@ auth_dovecot_options_block auth_dovecot_option_defaults = {
/* Dummy values */
void auth_dovecot_init(auth_instance *ablock) {}
int auth_dovecot_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_dovecot_client(auth_instance *ablock, smtp_inblock *inblock,
- smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_dovecot_client(auth_instance *ablock, void * sx,
+ int timeout, uschar *buffer, int buffsize) {return 0;}

#else /*!MACRO_PREDEF*/

diff --git a/src/src/auths/gsasl_exim.c b/src/src/auths/gsasl_exim.c
index 6611de3..0e3a916 100644
--- a/src/src/auths/gsasl_exim.c
+++ b/src/src/auths/gsasl_exim.c
@@ -84,8 +84,8 @@ auth_gsasl_options_block auth_gsasl_option_defaults = {
/* Dummy values */
void auth_gsasl_init(auth_instance *ablock) {}
int auth_gsasl_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_gsasl_client(auth_instance *ablock, smtp_inblock *inblock,
- smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_gsasl_client(auth_instance *ablock, void * sx,
+ int timeout, uschar *buffer, int buffsize) {return 0;}
void auth_gsasl_version_report(FILE *f) {}

 #else   /*!MACRO_PREDEF*/
@@ -588,8 +588,7 @@ server_callback(Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop, auth_insta
 int
 auth_gsasl_client(
   auth_instance *ablock,                 /* authenticator block */
-  smtp_inblock *inblock,                 /* connection inblock */
-  smtp_outblock *outblock,               /* connection outblock */
+  void * sx,                 /* connection */
   int timeout,                           /* command timeout */
   uschar *buffer,                        /* buffer for reading response */
   int buffsize)                          /* size of buffer */
diff --git a/src/src/auths/heimdal_gssapi.c b/src/src/auths/heimdal_gssapi.c
index eafdccc..3818980 100644
--- a/src/src/auths/heimdal_gssapi.c
+++ b/src/src/auths/heimdal_gssapi.c
@@ -82,8 +82,8 @@ auth_heimdal_gssapi_options_block auth_heimdal_gssapi_option_defaults = {
 /* Dummy values */
 void auth_heimdal_gssapi_init(auth_instance *ablock) {}
 int auth_heimdal_gssapi_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_heimdal_gssapi_client(auth_instance *ablock, smtp_inblock *inblock,
-  smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_heimdal_gssapi_client(auth_instance *ablock, void * sx,
+  int timeout, uschar *buffer, int buffsize) {return 0;}
 void auth_heimdal_gssapi_version_report(FILE *f) {}


 #else   /*!MACRO_PREDEF*/
@@ -578,8 +578,7 @@ exim_gssapi_error_defer(uschar *store_reset_point,
 int
 auth_heimdal_gssapi_client(
   auth_instance *ablock,                 /* authenticator block */
-  smtp_inblock *inblock,                 /* connection inblock */
-  smtp_outblock *outblock,               /* connection outblock */
+  void * sx,                 /* connection */
   int timeout,                           /* command timeout */
   uschar *buffer,                        /* buffer for reading response */
   int buffsize)                          /* size of buffer */
diff --git a/src/src/auths/plaintext.c b/src/src/auths/plaintext.c
index bdd0569..7a0f788 100644
--- a/src/src/auths/plaintext.c
+++ b/src/src/auths/plaintext.c
@@ -40,8 +40,8 @@ auth_plaintext_options_block auth_plaintext_option_defaults = {
 /* Dummy values */
 void auth_plaintext_init(auth_instance *ablock) {}
 int auth_plaintext_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_plaintext_client(auth_instance *ablock, smtp_inblock *inblock,
-  smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_plaintext_client(auth_instance *ablock, void * sx, int timeout,
+    uschar *buffer, int buffsize) {return 0;}


#else /*!MACRO_PREDEF*/

@@ -167,8 +167,7 @@ return auth_check_serv_cond(ablock);
 int
 auth_plaintext_client(
   auth_instance *ablock,                 /* authenticator block */
-  smtp_inblock *inblock,                 /* connection inblock */
-  smtp_outblock *outblock,               /* connection outblock */
+  void * sx,                 /* smtp connextion */
   int timeout,                           /* command timeout */
   uschar *buffer,                        /* buffer for reading response */
   int buffsize)                          /* size of buffer */
@@ -201,8 +200,8 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)))
     uschar *ssave = string_copy(s);
     if (!first)
       {
-      if (smtp_write_command(outblock, SCMD_FLUSH, "*\r\n") >= 0)
-        (void) smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
+      if (smtp_write_command(sx, SCMD_FLUSH, "*\r\n") >= 0)
+        (void) smtp_read_response(sx, US buffer, buffsize, '2', timeout);
       }
     if (f.expand_string_forcedfail)
       {
@@ -236,15 +235,13 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)))
   if (first)
     {
     first = FALSE;
-    if (smtp_write_command(outblock, SCMD_FLUSH, "AUTH %s%s%s\r\n",
-         ablock->public_name, (len == 0)? "" : " ",
-         b64encode(ss, len)) < 0)
+    if (smtp_write_command(sx, SCMD_FLUSH, "AUTH %s%s%s\r\n",
+         ablock->public_name, len == 0 ? "" : " ", b64encode(ss, len)) < 0)
       return FAIL_SEND;
     }
   else
     {
-    if (smtp_write_command(outblock, SCMD_FLUSH, "%s\r\n",
-          b64encode(ss, len)) < 0)
+    if (smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", b64encode(ss, len)) < 0)
       return FAIL_SEND;
     }


@@ -252,7 +249,7 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)))
has succeeded. There may be more data to send, but is there any point
in provoking an error here? */

- if (smtp_read_response(inblock, US buffer, buffsize, '2', timeout)) return OK;
+ if (smtp_read_response(sx, US buffer, buffsize, '2', timeout)) return OK;

/* Not a success response. If errno != 0 there is some kind of transmission
error. Otherwise, check the response code in the buffer. If it starts with
@@ -263,10 +260,10 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)))
/* If there is no more data to send, we have to cancel the authentication
exchange and return ERROR. */

-  if (text == NULL)
+  if (!text)
     {
-    if (smtp_write_command(outblock, SCMD_FLUSH, "*\r\n") >= 0)
-      (void)smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
+    if (smtp_write_command(sx, SCMD_FLUSH, "*\r\n") >= 0)
+      (void)smtp_read_response(sx, US buffer, buffsize, '2', timeout);
     string_format(buffer, buffsize, "Too few items in client_send in %s "
       "authenticator", ablock->name);
     return ERROR;
@@ -287,8 +284,8 @@ while ((s = string_nextinlist(&text, &sep, big_buffer, big_buffer_size)))
     uschar *save_bad = string_copy(buffer);
     if (!ob->client_ignore_invalid_base64)
       {
-      if (smtp_write_command(outblock, SCMD_FLUSH, "*\r\n") >= 0)
-        (void)smtp_read_response(inblock, US buffer, buffsize, '2', timeout);
+      if (smtp_write_command(sx, SCMD_FLUSH, "*\r\n") >= 0)
+        (void)smtp_read_response(sx, US buffer, buffsize, '2', timeout);
       string_format(buffer, buffsize, "Invalid base64 string in server "
         "response \"%s\"", save_bad);
       return CANCELLED;
diff --git a/src/src/auths/plaintext.h b/src/src/auths/plaintext.h
index 6cf3522..4c6d011 100644
--- a/src/src/auths/plaintext.h
+++ b/src/src/auths/plaintext.h
@@ -26,7 +26,6 @@ extern auth_plaintext_options_block auth_plaintext_option_defaults;


 extern void auth_plaintext_init(auth_instance *);
 extern int auth_plaintext_server(auth_instance *, uschar *);
-extern int auth_plaintext_client(auth_instance *, smtp_inblock *,
-                                 smtp_outblock *, int, uschar *, int);
+extern int auth_plaintext_client(auth_instance *, void *, int, uschar *, int);


 /* End of plaintext.h */
diff --git a/src/src/auths/spa.c b/src/src/auths/spa.c
index 50a4fea..97e3b10 100644
--- a/src/src/auths/spa.c
+++ b/src/src/auths/spa.c
@@ -76,8 +76,8 @@ auth_spa_options_block auth_spa_option_defaults = {
 /* Dummy values */
 void auth_spa_init(auth_instance *ablock) {}
 int auth_spa_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_spa_client(auth_instance *ablock, smtp_inblock *inblock,
-  smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_spa_client(auth_instance *ablock, void * sx, int timeout,
+    uschar *buffer, int buffsize) {return 0;}


#else /*!MACRO_PREDEF*/

@@ -268,8 +268,7 @@ return FAIL;
 int
 auth_spa_client(
   auth_instance *ablock,                 /* authenticator block */
-  smtp_inblock *inblock,                 /* connection inblock */
-  smtp_outblock *outblock,               /* connection outblock */
+  void * sx,                 /* connection */
   int timeout,                           /* command timeout */
   uschar *buffer,                        /* buffer for reading response */
   int buffsize)                          /* size of buffer */
@@ -306,7 +305,6 @@ if (!(password = CS expand_string(ob->spa_password)))
   }


 if (ob->spa_domain)
-  {
   if (!(domain = CS expand_string(ob->spa_domain)))
     {
     if (f.expand_string_forcedfail) return CANCELLED;
@@ -315,16 +313,14 @@ if (ob->spa_domain)
           expand_string_message);
     return ERROR;
     }
-  }


/* Original code */

-if (smtp_write_command(outblock, SCMD_FLUSH, "AUTH %s\r\n",
-    ablock->public_name) < 0)
+if (smtp_write_command(sx, SCMD_FLUSH, "AUTH %s\r\n", ablock->public_name) < 0)
   return FAIL_SEND;


/* wait for the 3XX OK message */
-if (!smtp_read_response(inblock, US buffer, buffsize, '3', timeout))
+if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout))
return FAIL;

DSPA("\n\n%s authenticator: using domain %s\n\n", ablock->name, domain);
@@ -336,11 +332,11 @@ spa_bits_to_base64 (US msgbuf, (unsigned char*)&request,
DSPA("\n\n%s authenticator: sending request (%s)\n\n", ablock->name, msgbuf);

/* send the encrypted password */
-if (smtp_write_command(outblock, SCMD_FLUSH, "%s\r\n", msgbuf) < 0)
+if (smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", msgbuf) < 0)
return FAIL_SEND;

/* wait for the auth challenge */
-if (!smtp_read_response(inblock, US buffer, buffsize, '3', timeout))
+if (!smtp_read_response(sx, US buffer, buffsize, '3', timeout))
return FAIL;

/* convert the challenge into the challenge struct */
@@ -353,14 +349,14 @@ spa_bits_to_base64 (US msgbuf, (unsigned char*)&response,
DSPA("\n\n%s authenticator: challenge response (%s)\n\n", ablock->name, msgbuf);

 /* send the challenge response */
-if (smtp_write_command(outblock, SCMD_FLUSH, "%s\r\n", msgbuf) < 0)
+if (smtp_write_command(sx, SCMD_FLUSH, "%s\r\n", msgbuf) < 0)
        return FAIL_SEND;


/* If we receive a success response from the server, authentication
has succeeded. There may be more data to send, but is there any point
in provoking an error here? */

-if (smtp_read_response(inblock, US buffer, buffsize, '2', timeout))
+if (smtp_read_response(sx, US buffer, buffsize, '2', timeout))
return OK;

/* Not a success response. If errno != 0 there is some kind of transmission
diff --git a/src/src/auths/spa.h b/src/src/auths/spa.h
index c140fe5..ca93469 100644
--- a/src/src/auths/spa.h
+++ b/src/src/auths/spa.h
@@ -33,7 +33,6 @@ extern auth_spa_options_block auth_spa_option_defaults;

 extern void auth_spa_init(auth_instance *);
 extern int auth_spa_server(auth_instance *, uschar *);
-extern int auth_spa_client(auth_instance *, smtp_inblock *,
-                                 smtp_outblock *, int, uschar *, int);
+extern int auth_spa_client(auth_instance *, void *, int, uschar *, int);


/* End of spa.h */
diff --git a/src/src/auths/tls.c b/src/src/auths/tls.c
index 2d0d8de..56f5f5e 100644
--- a/src/src/auths/tls.c
+++ b/src/src/auths/tls.c
@@ -45,8 +45,8 @@ auth_tls_options_block auth_tls_option_defaults = {
/* Dummy values */
void auth_tls_init(auth_instance *ablock) {}
int auth_tls_server(auth_instance *ablock, uschar *data) {return 0;}
-int auth_tls_client(auth_instance *ablock, smtp_inblock *inblock,
- smtp_outblock *outblock, int timeout, uschar *buffer, int buffsize) {return 0;}
+int auth_tls_client(auth_instance *ablock, void * sx,
+ int timeout, uschar *buffer, int buffsize) {return 0;}

#else /*!MACRO_PREDEF*/

diff --git a/src/src/functions.h b/src/src/functions.h
index 58cab82..920f3d9 100644
--- a/src/src/functions.h
+++ b/src/src/functions.h
@@ -452,7 +452,7 @@ extern int     smtp_handle_acl_fail(int, int, uschar *, uschar *);
 extern void    smtp_log_no_mail(void);
 extern void    smtp_message_code(uschar **, int *, uschar **, uschar **, BOOL);
 extern void    smtp_proxy_tls(void *, uschar *, size_t, int *, int);
-extern BOOL    smtp_read_response(smtp_inblock *, uschar *, int, int, int);
+extern BOOL    smtp_read_response(void *, uschar *, int, int, int);
 extern void    smtp_reset(void *);
 extern void    smtp_respond(uschar *, int, BOOL, uschar *);
 extern void    smtp_notquit_exit(uschar *, uschar *, uschar *, ...);
@@ -462,7 +462,7 @@ extern int     smtp_setup_msg(void);
 extern BOOL    smtp_start_session(void);
 extern int     smtp_ungetc(int);
 extern BOOL    smtp_verify_helo(void);
-extern int     smtp_write_command(smtp_outblock *, int, const char *, ...) PRINTF_FUNCTION(3,4);
+extern int     smtp_write_command(void *, int, const char *, ...) PRINTF_FUNCTION(3,4);
 #ifdef WITH_CONTENT_SCAN
 extern int     spam(const uschar **);
 extern FILE   *spool_mbox(unsigned long *, const uschar *, uschar **);
diff --git a/src/src/smtp_out.c b/src/src/smtp_out.c
index 31e9a36..6fd0bf7 100644
--- a/src/src/smtp_out.c
+++ b/src/src/smtp_out.c
@@ -444,7 +444,7 @@ return TRUE;
 any error message.


 Arguments:
-  outblock   contains buffer for pipelining, and socket
+  sx         SMTP connection, contains buffer for pipelining, and socket
   mode       buffer, write-with-more-likely, write
   format     a format, starting with one of
              of HELO, MAIL FROM, RCPT TO, DATA, ".", or QUIT.
@@ -457,8 +457,9 @@ Returns:     0 if command added to pipelining buffer, with nothing transmitted
 */


int
-smtp_write_command(smtp_outblock * outblock, int mode, const char *format, ...)
+smtp_write_command(void * sx, int mode, const char *format, ...)
{
+smtp_outblock * outblock = &((smtp_context *)sx)->outblock;
int count;
int rc = 0;
va_list ap;
@@ -623,7 +624,8 @@ also returned after a reading error. In this case buffer[0] will be zero, and
the error code will be in errno.

 Arguments:
-  inblock   the SMTP input block (contains holding buffer, socket, etc.)
+  sx        the SMTP connection (contains input block with holding buffer,
+        socket, etc.)
   buffer    where to put the response
   size      the size of the buffer
   okdigit   the expected first digit of the response
@@ -633,9 +635,10 @@ Returns:    TRUE if a valid, non-error response was received; else FALSE
 */


 BOOL
-smtp_read_response(smtp_inblock *inblock, uschar *buffer, int size, int okdigit,
+smtp_read_response(void * sx, uschar *buffer, int size, int okdigit,
    int timeout)
 {
+smtp_inblock * inblock = &((smtp_context *)sx)->inblock;
 uschar *ptr = buffer;
 int count;


diff --git a/src/src/structs.h b/src/src/structs.h
index bec2b2a..b1df408 100644
--- a/src/src/structs.h
+++ b/src/src/structs.h
@@ -420,8 +420,7 @@ typedef struct auth_info {
     uschar *);                    /* rest of AUTH command */
   int (*clientcode)(              /* client function */
     struct auth_instance *,
-    struct smtp_inblock *,        /* socket and input buffer */
-    struct smtp_outblock *,       /* socket and output buffer */
+    void *,              /* smtp conn, with socket, output and input buffers */
     int,                          /* command timeout */
     uschar *,                     /* buffer for reading response */
     int);                         /* sizeof buffer */
diff --git a/src/src/transports/smtp.c b/src/src/transports/smtp.c
index fb8e17e..0763751 100644
--- a/src/src/transports/smtp.c
+++ b/src/src/transports/smtp.c
@@ -797,7 +797,7 @@ if (sx->pending_MAIL)
   {
   DEBUG(D_transport) debug_printf("%s expect mail\n", __FUNCTION__);
   count--;
-  if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer),
+  if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer),
               '2', ob->command_timeout))
     {
     DEBUG(D_transport) debug_printf("bad response for MAIL\n");
@@ -813,7 +813,7 @@ if (sx->pending_MAIL)
         }
       while (count-- > 0)
         {
-        if (!smtp_read_response(&sx->inblock, flushbuffer, sizeof(flushbuffer),
+        if (!smtp_read_response(sx, flushbuffer, sizeof(flushbuffer),
                    '2', ob->command_timeout)
             && (errno != 0 || flushbuffer[0] == 0))
           break;
@@ -848,7 +848,7 @@ while (count-- > 0)
   addr->host_used = sx->host;


   DEBUG(D_transport) debug_printf("%s expect rcpt\n", __FUNCTION__);
-  if (smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer),
+  if (smtp_read_response(sx, sx->buffer, sizeof(sx->buffer),
               '2', ob->command_timeout))
     {
     yield |= 1;
@@ -968,7 +968,7 @@ previously or in this block, the response is ignored. */
 if (pending_DATA != 0)
   {
   DEBUG(D_transport) debug_printf("%s expect data\n", __FUNCTION__);
-  if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer),
+  if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer),
             '3', ob->command_timeout))
     {
     int code;
@@ -1001,11 +1001,8 @@ return yield;
 /* Do the client side of smtp-level authentication */
 /*
 Arguments:
+  sx        smtp connection
   buffer    EHLO response from server (gets overwritten)
-  addrlist      chain of potential addresses to deliver
-  host          host to deliver to
-  ob        transport options
-  ibp, obp    comms channel control blocks


 Returns:
   OK            Success, or failed (but not required): global "smtp_authenticated" set
@@ -1016,23 +1013,22 @@ Returns:
   FAIL            - response
 */


-int
-smtp_auth(uschar *buffer, unsigned bufsize, address_item *addrlist, host_item *host,
-    smtp_transport_options_block *ob, BOOL is_esmtp,
-    smtp_inblock *ibp, smtp_outblock *obp)
+static int
+smtp_auth(smtp_context * sx, uschar * buffer, unsigned bufsize)
 {
+smtp_transport_options_block * ob = sx->ob;
 int require_auth;
 uschar *fail_reason = US"server did not advertise AUTH support";


f.smtp_authenticated = FALSE;
client_authenticator = client_authenticated_id = client_authenticated_sender = NULL;
-require_auth = verify_check_given_host(&ob->hosts_require_auth, host);
+require_auth = verify_check_given_host(&ob->hosts_require_auth, sx->host);

-if (is_esmtp && !regex_AUTH) regex_AUTH =
+if (sx->esmtp && !regex_AUTH) regex_AUTH =
     regex_must_compile(US"\\n250[\\s\\-]AUTH\\s+([\\-\\w\\s]+)(?:\\n|$)",
       FALSE, TRUE);


-if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
+if (sx->esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
   {
   uschar *names = string_copyn(expand_nstring[1], expand_nlength[1]);
   expand_nmax = -1;                          /* reset */
@@ -1041,7 +1037,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
   regex match above. */


   if (require_auth == OK ||
-      verify_check_given_host(&ob->hosts_try_auth, host) == OK)
+      verify_check_given_host(&ob->hosts_try_auth, sx->host) == OK)
     {
     auth_instance *au;
     fail_reason = US"no common mechanisms were found";
@@ -1089,10 +1085,10 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
     that reflections don't show it. */


     fail_reason = US"authentication attempt(s) failed";
-    obp->authenticating = TRUE;
-    rc = (au->info->clientcode)(au, ibp, obp,
+    sx->outblock.authenticating = TRUE;
+    rc = (au->info->clientcode)(au, sx,
       ob->command_timeout, buffer, bufsize);
-    obp->authenticating = FALSE;
+    sx->outblock.authenticating = FALSE;
     DEBUG(D_transport) debug_printf("%s authenticator yielded %d\n",
       au->name, rc);


@@ -1120,7 +1116,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
       case FAIL:
       if (errno != 0 || buffer[0] != '5') return FAIL;
       log_write(0, LOG_MAIN, "%s authenticator failed H=%s [%s] %s",
-        au->name, host->name, host->address, buffer);
+        au->name, sx->host->name, sx->host->address, buffer);
       break;


       /* Failure by some other means. In effect, the authenticator
@@ -1132,14 +1128,14 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))
       case CANCELLED:
       if (*buffer != 0)
         log_write(0, LOG_MAIN, "%s authenticator cancelled "
-          "authentication H=%s [%s] %s", au->name, host->name,
-          host->address, buffer);
+          "authentication H=%s [%s] %s", au->name, sx->host->name,
+          sx->host->address, buffer);
       break;


       /* Internal problem, message in buffer. */


       case ERROR:
-      set_errno_nohost(addrlist, ERRNO_AUTHPROB, string_copy(buffer),
+      set_errno_nohost(sx->addrlist, ERRNO_AUTHPROB, string_copy(buffer),
             DEFER, FALSE);
       return ERROR;
       }
@@ -1154,7 +1150,7 @@ if (is_esmtp && regex_match_and_setup(regex_AUTH, buffer, 0, -1))


 if (require_auth == OK && !f.smtp_authenticated)
   {
-  set_errno_nohost(addrlist, ERRNO_AUTHFAIL,
+  set_errno_nohost(sx->addrlist, ERRNO_AUTHFAIL,
     string_sprintf("authentication required but %s", fail_reason), DEFER,
     FALSE);
   return DEFER;
@@ -1436,7 +1432,7 @@ there may be more writes (like, the chunk data) done soon. */


 if (chunk_size > 0)
   {
-  if((cmd_count = smtp_write_command(&sx->outblock,
+  if((cmd_count = smtp_write_command(sx,
           flags & tc_reap_prev ? SCMD_FLUSH : SCMD_MORE,
           "BDAT %u%s\r\n", chunk_size, flags & tc_chunk_last ? " LAST" : "")
      ) < 0) return ERROR;
@@ -1479,7 +1475,7 @@ if (sx->pending_BDAT)
   {
   DEBUG(D_transport) debug_printf("look for one response for BDAT\n");


-  if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), '2',
+  if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2',
        ob->command_timeout))
     {
     if (errno == 0 && sx->buffer[0] == '4')
@@ -1729,7 +1725,7 @@ if (!continue_hostname)
 #ifdef TCP_QUICKACK
     (void) setsockopt(sx->cctx.sock, IPPROTO_TCP, TCP_QUICKACK, US &off, sizeof(off));
 #endif
-    good_response = smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer),
+    good_response = smtp_read_response(sx, sx->buffer, sizeof(sx->buffer),
       '2', sx->ob->command_timeout);
 #ifdef EXPERIMENTAL_DSN_INFO
     sx->smtp_greeting = string_copy(sx->buffer);
@@ -1819,11 +1815,11 @@ goto SEND_QUIT;


   if (sx->esmtp)
     {
-    if (smtp_write_command(&sx->outblock, SCMD_FLUSH, "%s %s\r\n",
+    if (smtp_write_command(sx, SCMD_FLUSH, "%s %s\r\n",
          sx->lmtp ? "LHLO" : "EHLO", sx->helo_data) < 0)
       goto SEND_FAILED;
     sx->esmtp_sent = TRUE;
-    if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), '2',
+    if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2',
            sx->ob->command_timeout))
       {
       if (errno != 0 || sx->buffer[0] == 0 || sx->lmtp)
@@ -1852,10 +1848,9 @@ goto SEND_QUIT;
     if (sx->esmtp_sent && (n = Ustrlen(sx->buffer)) < sizeof(sx->buffer)/2)
       { rsp = sx->buffer + n + 1; n = sizeof(sx->buffer) - n; }


-    if (smtp_write_command(&sx->outblock, SCMD_FLUSH, "HELO %s\r\n", sx->helo_data) < 0)
+    if (smtp_write_command(sx, SCMD_FLUSH, "HELO %s\r\n", sx->helo_data) < 0)
       goto SEND_FAILED;
-    good_response = smtp_read_response(&sx->inblock, rsp, n,
-      '2', sx->ob->command_timeout);
+    good_response = smtp_read_response(sx, rsp, n, '2', sx->ob->command_timeout);
 #ifdef EXPERIMENTAL_DSN_INFO
     sx->helo_response = string_copy(rsp);
 #endif
@@ -1955,7 +1950,7 @@ if (  smtp_peer_options & OPTION_TLS
    )  )
   {
   uschar buffer2[4096];
-  if (smtp_write_command(&sx->outblock, SCMD_FLUSH, "STARTTLS\r\n") < 0)
+  if (smtp_write_command(sx, SCMD_FLUSH, "STARTTLS\r\n") < 0)
     goto SEND_FAILED;


/* If there is an I/O error, transmission of this message is deferred. If
@@ -1965,7 +1960,7 @@ if ( smtp_peer_options & OPTION_TLS
STARTTLS, we carry on. This means we will try to send the message in clear,
unless the host is in hosts_require_tls (tested below). */

-  if (!smtp_read_response(&sx->inblock, buffer2, sizeof(buffer2), '2',
+  if (!smtp_read_response(sx, buffer2, sizeof(buffer2), '2',
       sx->ob->command_timeout))
     {
     if (  errno != 0
@@ -2060,7 +2055,7 @@ if (tls_out.active.sock >= 0)
   /* For SMTPS we need to wait for the initial OK response. */
   if (sx->smtps)
     {
-    good_response = smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer),
+    good_response = smtp_read_response(sx, sx->buffer, sizeof(sx->buffer),
       '2', sx->ob->command_timeout);
 #ifdef EXPERIMENTAL_DSN_INFO
     sx->smtp_greeting = string_copy(sx->buffer);
@@ -2077,10 +2072,10 @@ if (tls_out.active.sock >= 0)
       debug_printf("not sending EHLO (host matches hosts_avoid_esmtp)\n");
     }


-  if (smtp_write_command(&sx->outblock, SCMD_FLUSH, "%s %s\r\n",
+  if (smtp_write_command(sx, SCMD_FLUSH, "%s %s\r\n",
         sx->lmtp ? "LHLO" : greeting_cmd, sx->helo_data) < 0)
     goto SEND_FAILED;
-  good_response = smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer),
+  good_response = smtp_read_response(sx, sx->buffer, sizeof(sx->buffer),
     '2', sx->ob->command_timeout);
 #ifdef EXPERIMENTAL_DSN_INFO
   sx->helo_response = string_copy(sx->buffer);
@@ -2209,8 +2204,7 @@ if (continue_hostname == NULL
     the business. The host name and address must be available when the
     authenticator's client driver is running. */


-    switch (yield = smtp_auth(sx->buffer, sizeof(sx->buffer), sx->addrlist, sx->host,
-                  sx->ob, sx->esmtp, &sx->inblock, &sx->outblock))
+    switch (yield = smtp_auth(sx, sx->buffer, sizeof(sx->buffer)))
       {
       default:        goto SEND_QUIT;
       case OK:        break;
@@ -2373,7 +2367,7 @@ FAILED:
 SEND_QUIT:


if (sx->send_quit)
- (void)smtp_write_command(&sx->outblock, SCMD_FLUSH, "QUIT\r\n");
+ (void)smtp_write_command(sx, SCMD_FLUSH, "QUIT\r\n");

 #ifdef SUPPORT_TLS
 if (sx->cctx.tls_ctx)
@@ -2611,7 +2605,7 @@ sx->pending_MAIL = TRUE;     /* The block starts with MAIL */
     }
 #endif


-  rc = smtp_write_command(&sx->outblock, pipelining_active ? SCMD_BUFFER : SCMD_FLUSH,
+  rc = smtp_write_command(sx, pipelining_active ? SCMD_BUFFER : SCMD_FLUSH,
       "MAIL FROM:<%s>%s\r\n", s, sx->buffer);
   }


@@ -2623,7 +2617,7 @@ switch(rc)
     return -5;


   case +1:                /* Cmd was sent */
-    if (!smtp_read_response(&sx->inblock, sx->buffer, sizeof(sx->buffer), '2',
+    if (!smtp_read_response(sx, sx->buffer, sizeof(sx->buffer), '2',
        sx->ob->command_timeout))
       {
       if (errno == 0 && sx->buffer[0] == '4')
@@ -2695,7 +2689,7 @@ for (addr = sx->first_addr, address_count = 0;
     }
 #endif


-  count = smtp_write_command(&sx->outblock, no_flush ? SCMD_BUFFER : SCMD_FLUSH,
+  count = smtp_write_command(sx, no_flush ? SCMD_BUFFER : SCMD_FLUSH,
     "RCPT TO:<%s>%s%s\r\n", rcpt_addr, sx->igquotstr, sx->buffer);


   if (count < 0) return -5;
@@ -3033,7 +3027,7 @@ to send is. */
 if (  !(sx.peer_offered & OPTION_CHUNKING)
    && (sx.ok || (pipelining_active && !mua_wrapper)))
   {
-  int count = smtp_write_command(&sx.outblock, SCMD_FLUSH, "DATA\r\n");
+  int count = smtp_write_command(&sx, SCMD_FLUSH, "DATA\r\n");


   if (count < 0) goto SEND_FAILED;
   switch(sync_responses(&sx, count, sx.ok ? +1 : -1))
@@ -3196,7 +3190,7 @@ else
    * with per non-PRDR. */
   if(sx.prdr_active)
     {
-    sx.ok = smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '3',
+    sx.ok = smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '3',
       sx.ob->final_timeout);
     if (!sx.ok && errno == 0) switch(sx.buffer[0])
       {
@@ -3217,7 +3211,7 @@ else


   if (!sx.lmtp)
     {
-    sx.ok = smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '2',
+    sx.ok = smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2',
       sx.ob->final_timeout);
     if (!sx.ok && errno == 0 && sx.buffer[0] == '4')
       {
@@ -3281,7 +3275,7 @@ else
       if (sx.lmtp)
 #endif
         {
-        if (!smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '2',
+        if (!smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2',
             sx.ob->final_timeout))
           {
           if (errno != 0 || sx.buffer[0] == 0) goto RESPONSE_FAILED;
@@ -3363,7 +3357,7 @@ else
     /* PRDR - get the final, overall response.  For any non-success
     upgrade all the address statuses. */


-        sx.ok = smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer), '2',
+        sx.ok = smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2',
           sx.ob->final_timeout);
         if (!sx.ok)
       {
@@ -3599,13 +3593,13 @@ if (sx.completed_addr && sx.ok && sx.send_quit)
     BOOL pass_message;


     if (sx.send_rset)
-      if (! (sx.ok = smtp_write_command(&sx.outblock, SCMD_FLUSH, "RSET\r\n") >= 0))
+      if (! (sx.ok = smtp_write_command(&sx, SCMD_FLUSH, "RSET\r\n") >= 0))
         {
         msg = US string_sprintf("send() to %s [%s] failed: %s", host->name,
           host->address, strerror(errno));
         sx.send_quit = FALSE;
         }
-      else if (! (sx.ok = smtp_read_response(&sx.inblock, sx.buffer,
+      else if (! (sx.ok = smtp_read_response(&sx, sx.buffer,
           sizeof(sx.buffer), '2', sx.ob->command_timeout)))
         {
         int code;
@@ -3652,9 +3646,9 @@ if (sx.completed_addr && sx.ok && sx.send_quit)
       sx.cctx.tls_ctx = NULL;
       smtp_peer_options = smtp_peer_options_wrap;
       sx.ok = !sx.smtps
-        && smtp_write_command(&sx.outblock, SCMD_FLUSH,
-                      "EHLO %s\r\n", sx.helo_data) >= 0
-        && smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer),
+        && smtp_write_command(&sx, SCMD_FLUSH, "EHLO %s\r\n", sx.helo_data)
+        >= 0
+        && smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer),
                       '2', sx.ob->command_timeout);


       if (sx.ok && f.continue_more)
@@ -3757,7 +3751,7 @@ This change is being made on 31-Jul-98. After over a year of trouble-free
 operation, the old commented-out code was removed on 17-Sep-99. */


SEND_QUIT:
-if (sx.send_quit) (void)smtp_write_command(&sx.outblock, SCMD_FLUSH, "QUIT\r\n");
+if (sx.send_quit) (void)smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n");

END_OFF:

@@ -3821,8 +3815,7 @@ smtp_transport_closedown(transport_instance *tblock)
smtp_transport_options_block *ob =
(smtp_transport_options_block *)tblock->options_block;
client_conn_ctx cctx;
-smtp_inblock inblock;
-smtp_outblock outblock;
+smtp_context sx;
uschar buffer[256];
uschar inbuffer[4096];
uschar outbuffer[16];
@@ -3831,22 +3824,21 @@ uschar outbuffer[16];
cctx.sock = fileno(stdin);
cctx.tls_ctx = cctx.sock == tls_out.active.sock ? tls_out.active.tls_ctx : NULL;

-inblock.cctx = &cctx;
-inblock.buffer = inbuffer;
-inblock.buffersize = sizeof(inbuffer);
-inblock.ptr = inbuffer;
-inblock.ptrend = inbuffer;
-
-outblock.cctx = &cctx;
-outblock.buffersize = sizeof(outbuffer);
-outblock.buffer = outbuffer;
-outblock.ptr = outbuffer;
-outblock.cmd_count = 0;
-outblock.authenticating = FALSE;
-
-(void)smtp_write_command(&outblock, SCMD_FLUSH, "QUIT\r\n");
-(void)smtp_read_response(&inblock, buffer, sizeof(buffer), '2',
- ob->command_timeout);
+sx.inblock.cctx = &cctx;
+sx.inblock.buffer = inbuffer;
+sx.inblock.buffersize = sizeof(inbuffer);
+sx.inblock.ptr = inbuffer;
+sx.inblock.ptrend = inbuffer;
+
+sx.outblock.cctx = &cctx;
+sx.outblock.buffersize = sizeof(outbuffer);
+sx.outblock.buffer = outbuffer;
+sx.outblock.ptr = outbuffer;
+sx.outblock.cmd_count = 0;
+sx.outblock.authenticating = FALSE;
+
+(void)smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n");
+(void)smtp_read_response(&sx, buffer, sizeof(buffer), '2', ob->command_timeout);
(void)close(cctx.sock);
}

diff --git a/src/src/transports/smtp.h b/src/src/transports/smtp.h
index 7127fe3..3219b05 100644
--- a/src/src/transports/smtp.h
+++ b/src/src/transports/smtp.h
@@ -182,9 +182,6 @@ extern void smtp_transport_closedown(transport_instance *);



-extern int     smtp_auth(uschar *, unsigned, address_item *, host_item *,
-         smtp_transport_options_block *, BOOL,
-         smtp_inblock *, smtp_outblock *);
 extern BOOL    smtp_mail_auth_str(uschar *, unsigned,
          address_item *, smtp_transport_options_block *);


diff --git a/src/src/verify.c b/src/src/verify.c
index 7d46c35..8d31f5d 100644
--- a/src/src/verify.c
+++ b/src/src/verify.c
@@ -14,7 +14,7 @@ caching was contributed by Kevin Fleming (but I hacked it around a bit). */

 #define CUTTHROUGH_CMD_TIMEOUT  30    /* timeout for cutthrough-routing calls */
 #define CUTTHROUGH_DATA_TIMEOUT 60    /* timeout for cutthrough-routing calls */
-static smtp_outblock ctblock;
+static smtp_context ctctx;
 uschar ctbuffer[8192];



@@ -409,7 +409,7 @@ if (addr->transport == cutthrough.addr.transport)

     /* Match!  Send the RCPT TO, set done from the response */
     done =
-         smtp_write_command(&ctblock, SCMD_FLUSH, "RCPT TO:<%.1000s>\r\n",
+         smtp_write_command(&ctctx, SCMD_FLUSH, "RCPT TO:<%.1000s>\r\n",
           transport_rcpt_address(addr,
          addr->transport->rcpt_include_affixes)) >= 0
       && cutthrough_response(&cutthrough.cctx, '2', &resp,
@@ -814,9 +814,8 @@ tls_retry_connection:
         XXX We don't care about that for postmaster_full.  Should we? */


         if ((done =
-          smtp_write_command(&sx.outblock, SCMD_FLUSH, "RSET\r\n") >= 0 &&
-          smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer),
-        '2', callout)))
+          smtp_write_command(&sx, SCMD_FLUSH, "RSET\r\n") >= 0 &&
+          smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', callout)))
           break;


         HDEBUG(D_acl|D_v)
@@ -911,9 +910,8 @@ tls_retry_connection:
       cancel_cutthrough_connection(TRUE, US"postmaster verify");
       HDEBUG(D_acl|D_v) debug_printf_indent("Cutthrough cancelled by presence of postmaster verify\n");


-      done = smtp_write_command(&sx.outblock, SCMD_FLUSH, "RSET\r\n") >= 0
-          && smtp_read_response(&sx.inblock, sx.buffer,
-                sizeof(sx.buffer), '2', callout);
+      done = smtp_write_command(&sx, SCMD_FLUSH, "RSET\r\n") >= 0
+          && smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', callout);


       if (done)
     {
@@ -936,9 +934,9 @@ tls_retry_connection:
       done = TRUE;
     else
       done = (options & vopt_callout_fullpm) != 0
-          && smtp_write_command(&sx.outblock, SCMD_FLUSH,
+          && smtp_write_command(&sx, SCMD_FLUSH,
                 "RCPT TO:<postmaster>\r\n") >= 0
-          && smtp_read_response(&sx.inblock, sx.buffer,
+          && smtp_read_response(&sx, sx.buffer,
                 sizeof(sx.buffer), '2', callout);


     /* Sort out the cache record */
@@ -1104,11 +1102,11 @@ no_conn:
        caddr = caddr->parent, parent = parent->parent)
         *(caddr->parent = store_get(sizeof(address_item))) = *parent;


-      ctblock.buffer = ctbuffer;
-      ctblock.buffersize = sizeof(ctbuffer);
-      ctblock.ptr = ctbuffer;
-      /* ctblock.cmd_count = 0; ctblock.authenticating = FALSE; */
-      ctblock.cctx = &cutthrough.cctx;
+      ctctx.outblock.buffer = ctbuffer;
+      ctctx.outblock.buffersize = sizeof(ctbuffer);
+      ctctx.outblock.ptr = ctbuffer;
+      /* ctctx.outblock.cmd_count = 0; ctctx.outblock.authenticating = FALSE; */
+      ctctx.outblock.cctx = &cutthrough.cctx;
       }
     else
       {
@@ -1117,11 +1115,10 @@ no_conn:
         cancel_cutthrough_connection(TRUE, US"not usable for cutthrough");
       if (sx.send_quit)
     {
-    (void) smtp_write_command(&sx.outblock, SCMD_FLUSH, "QUIT\r\n");
+    (void) smtp_write_command(&sx, SCMD_FLUSH, "QUIT\r\n");


     /* Wait a short time for response, and discard it */
-    smtp_read_response(&sx.inblock, sx.buffer, sizeof(sx.buffer),
-      '2', 1);
+    smtp_read_response(&sx, sx.buffer, sizeof(sx.buffer), '2', 1);
     }


       if (sx.cctx.sock >= 0)
@@ -1234,14 +1231,14 @@ if(cutthrough.cctx.sock < 0)
 if(
 #ifdef SUPPORT_TLS
    cutthrough.is_tls
-   ? tls_write(cutthrough.cctx.tls_ctx, ctblock.buffer, n, FALSE)
+   ? tls_write(cutthrough.cctx.tls_ctx, ctctx.outblock.buffer, n, FALSE)
    :
 #endif
-     send(cutthrough.cctx.sock, ctblock.buffer, n, 0) > 0
+     send(cutthrough.cctx.sock, ctctx.outblock.buffer, n, 0) > 0
   )
 {
   transport_count += n;
-  ctblock.ptr= ctblock.buffer;
+  ctctx.outblock.ptr= ctctx.outblock.buffer;
   return TRUE;
 }


@@ -1256,11 +1253,11 @@ _cutthrough_puts(uschar * cp, int n)
 {
 while(n--)
  {
- if(ctblock.ptr >= ctblock.buffer+ctblock.buffersize)
-   if(!cutthrough_send(ctblock.buffersize))
+ if(ctctx.outblock.ptr >= ctctx.outblock.buffer+ctctx.outblock.buffersize)
+   if(!cutthrough_send(ctctx.outblock.buffersize))
      return FALSE;


- *ctblock.ptr++ = *cp++;
+ *ctctx.outblock.ptr++ = *cp++;
}
return TRUE;
}
@@ -1286,7 +1283,7 @@ return;
static BOOL
_cutthrough_flush_send(void)
{
-int n = ctblock.ptr - ctblock.buffer;
+int n = ctctx.outblock.ptr - ctctx.outblock.buffer;

if(n>0)
if(!cutthrough_send(n))
@@ -1323,16 +1320,16 @@ cutthrough_data_puts(US"\r\n", 2);
static uschar
cutthrough_response(client_conn_ctx * cctx, char expect, uschar ** copy, int timeout)
{
-smtp_inblock inblock;
+smtp_context sx;
uschar inbuffer[4096];
uschar responsebuffer[4096];

-inblock.buffer = inbuffer;
-inblock.buffersize = sizeof(inbuffer);
-inblock.ptr = inbuffer;
-inblock.ptrend = inbuffer;
-inblock.cctx = cctx;
-if(!smtp_read_response(&inblock, responsebuffer, sizeof(responsebuffer), expect, timeout))
+sx.inblock.buffer = inbuffer;
+sx.inblock.buffersize = sizeof(inbuffer);
+sx.inblock.ptr = inbuffer;
+sx.inblock.ptrend = inbuffer;
+sx.inblock.cctx = cctx;
+if(!smtp_read_response(&sx, responsebuffer, sizeof(responsebuffer), expect, timeout))
cancel_cutthrough_connection(TRUE, US"target timeout on read");

 if(copy)
@@ -1423,7 +1420,7 @@ if(fd >= 0)
      conn before the final dot.
   */
   client_conn_ctx tmp_ctx = cutthrough.cctx;
-  ctblock.ptr = ctbuffer;
+  ctctx.outblock.ptr = ctbuffer;
   HDEBUG(D_transport|D_acl|D_v) debug_printf_indent("  SMTP>> QUIT\n");
   _cutthrough_puts(US"QUIT\r\n", 6);    /* avoid recursion */
   _cutthrough_flush_send();
@@ -1445,7 +1442,7 @@ if(fd >= 0)
   (void)close(fd);
   HDEBUG(D_acl) debug_printf_indent("----------- cutthrough shutdown (%s) ------------\n", why);
   }
-ctblock.ptr = ctbuffer;
+ctctx.outblock.ptr = ctbuffer;
 }


void