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.
/* 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*/
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 */
/* 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)
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 */
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 */
/* 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*/
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 */
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 */
/* 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*/
/* 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*/
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 */
/* 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*/
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 */
/* 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*/
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 */
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)
{
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;
}
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
/* 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;
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;
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 */
/* 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*/
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 */
}
if (ob->spa_domain)
- {
if (!(domain = CS expand_string(ob->spa_domain)))
{
if (f.expand_string_forcedfail) return CANCELLED;
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);
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 */
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
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 */
/* 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*/
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 *, ...);
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 **);
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.
*/
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;
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
*/
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;
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 */
{
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");
}
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;
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;
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;
/* 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
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 */
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";
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);
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
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;
}
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;
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;
{
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')
#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);
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)
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
) )
{
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
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
/* 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);
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);
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;
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)
}
#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);
}
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')
}
#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;
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))
* 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])
{
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')
{
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;
/* 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)
{
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;
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)
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:
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];
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);
}
-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 *);
#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];
/* 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,
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)
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)
{
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 */
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
{
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)
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;
}
{
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;
}
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))
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)
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();
(void)close(fd);
HDEBUG(D_acl) debug_printf_indent("----------- cutthrough shutdown (%s) ------------\n", why);
}
-ctblock.ptr = ctbuffer;
+ctctx.outblock.ptr = ctbuffer;
}
void