Commit bec4d388 bec4d3889cf3527859eb47cd3363783b3bd680c1 by Sergey Poznyakoff

Redo the code for installing tls/sasl transport streams.

* include/mailutils/stream.h (MU_IOCTL_SWAP_STREAM): Remove.
(MU_IOCTL_GET_STREAM, MU_IOCTL_SET_STREAM): New ioctls.
* include/mailutils/sys/stream.h (_MU_SWAP_FIRST_ONLY)
(_MU_SWAP_IOCTL_MUST_SUCCEED): Remove.
(_mu_stream_swap_streams): Remove.
* libmailutils/stream.c (_mu_stream_swap_streams): Remove.

* libmailutils/filter_iconv.c (_icvt_ioctl): Handle MU_IOCTL_GET_STREAM,
MU_IOCTL_SET_STREAM instead of MU_IOCTL_SWAP_STREAM.
* libmailutils/iostream.c (_iostream_ctl): Likewise.
* libmailutils/xscript-stream.c (_xscript_ctl): Likewise.

* imap4d/auth_gsasl.c (restore_and_return): Unref the contents of str.
(auth_gsasl): Use MU_IOCTL_GET_STREAM/MU_IOCTL_SET_STREAM to
change the underlying transport streams.
* imap4d/io.c (imap4d_init_tls_server): Likewise.
* libproto/mailer/smtp_gsasl.c (insert_gsasl_stream): Likewise.
* pop3d/extra.c (pop3d_init_tls_server): Likewise.

* libproto/mailer/smtp_starttls.c (smtp_get_streams)
(smtp_set_streams): New functions.
(smtp_swap_streams): Remove.
(mu_smtp_starttls): Use smtp_get_streams and smtp_set_streams
instead of smtp_swap_streams.
* libproto/pop/pop3_stls.c (pop3_get_streams)
(pop3_set_streams): New functions.
(pop3_swap_streams): Remove.
(mu_pop3_stls): Use pop3_get_streams and pop3_set_streams.

* testsuite/smtpsend.c (main): Uncomment mu_stream_unref on
the carrier.
1 parent 379426a1
......@@ -38,13 +38,8 @@ finish_session (void)
static int
restore_and_return (struct imap4d_auth *ap, mu_stream_t *str, int resp)
{
int rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, str);
if (rc)
{
mu_error (_("%s failed when it should not: %s"), "MU_IOCTL_SWAP_STREAM",
mu_stream_strerror (iostream, rc));
abort ();
}
mu_stream_unref (str[0]);
mu_stream_unref (str[1]);
ap->response = resp;
return imap4d_auth_resp;
}
......@@ -118,11 +113,10 @@ auth_gsasl (struct imap4d_auth *ap)
{
mu_stream_t stream[2], newstream[2];
stream[0] = stream[1] = NULL;
rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream);
rc = mu_stream_ioctl (iostream, MU_IOCTL_GET_STREAM, stream);
if (rc)
{
mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM",
mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM",
mu_stream_strerror (iostream, rc));
ap->response = RESP_NO;
return imap4d_auth_resp;
......@@ -149,8 +143,12 @@ auth_gsasl (struct imap4d_auth *ap)
if (ap->username)
{
if (imap4d_session_setup (ap->username))
{
mu_stream_destroy (&newstream[0]);
mu_stream_destroy (&newstream[1]);
return restore_and_return (ap, stream, RESP_NO);
}
}
/* FIXME: This is not reflected in the transcript. */
io_stream_completion_response (stream[1], ap->command, RESP_OK,
......@@ -158,14 +156,21 @@ auth_gsasl (struct imap4d_auth *ap)
ap->auth_type);
mu_stream_flush (stream[1]);
rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, newstream);
mu_stream_unref (stream[0]);
mu_stream_unref (stream[1]);
rc = mu_stream_ioctl (iostream, MU_IOCTL_SET_STREAM, newstream);
if (rc)
{
mu_error (_("%s failed when it should not: %s"),
"MU_IOCTL_SWAP_STREAM",
"MU_IOCTL_SET_STREAM",
mu_stream_strerror (iostream, rc));
abort ();
}
mu_stream_unref (newstream[0]);
mu_stream_unref (newstream[1]);
util_atexit (finish_session);
return imap4d_auth_ok;
}
......
......@@ -88,11 +88,10 @@ imap4d_init_tls_server ()
mu_stream_t tlsstream, stream[2];
int rc;
stream[0] = stream[1] = NULL;
rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream);
rc = mu_stream_ioctl (iostream, MU_IOCTL_GET_STREAM, stream);
if (rc)
{
mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM",
mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM",
mu_stream_strerror (iostream, rc));
return 1;
}
......@@ -109,16 +108,21 @@ imap4d_init_tls_server ()
mu_stream_destroy (&tlsstream);
return 1;
}
else
mu_stream_unref (stream[0]);
mu_stream_unref (stream[1]);
stream[0] = stream[1] = tlsstream;
rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream);
rc = mu_stream_ioctl (iostream, MU_IOCTL_SET_STREAM, stream);
if (rc)
{
mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM",
mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM",
mu_stream_strerror (iostream, rc));
imap4d_bye (ERR_STREAM_CREATE);
}
mu_stream_unref (stream[0]);
mu_stream_unref (stream[1]);
return 0;
}
#endif
......
......@@ -66,12 +66,13 @@ enum mu_buffer_type
#define MU_IOCTL_ABRIDGE_SEEK MU_IOCTL_SET_SEEK_LIMITS
#define MU_IOCTL_GET_SEEK_LIMITS 5
#define MU_IOCTL_SET_TRANSPORT 6
#define MU_IOCTL_SWAP_STREAM 7
#define MU_IOCTL_GET_STREAM 7
#define MU_IOCTL_SET_STREAM 8
#define MU_IOCTL_LEVEL 8
#define MU_IOCTL_LEVEL 9
#define MU_IOCTL_GET_TRANSPORT_BUFFER 9
#define MU_IOCTL_SET_TRANSPORT_BUFFER 10
#define MU_IOCTL_GET_TRANSPORT_BUFFER 10
#define MU_IOCTL_SET_TRANSPORT_BUFFER 11
#define MU_TRANSPORT_INPUT 0
#define MU_TRANSPORT_OUTPUT 1
......
......@@ -75,11 +75,4 @@ mu_stream_t _mu_stream_create (size_t size, int flags);
void _mu_stream_cleareof (mu_stream_t str);
void _mu_stream_seteof (mu_stream_t str);
#define _MU_SWAP_FIRST_ONLY 0x01
#define _MU_SWAP_IOCTL_MUST_SUCCEED 0x02
int _mu_stream_swap_streams (mu_stream_t stream, mu_stream_t *curtrans,
mu_stream_t *newtrans, int flags);
#endif
......
......@@ -400,7 +400,8 @@ _icvt_ioctl (mu_stream_t stream, int code, void *ptr)
ptrans[1] = NULL;
break;
case MU_IOCTL_SWAP_STREAM:
case MU_IOCTL_GET_STREAM:
case MU_IOCTL_SET_STREAM:
case MU_IOCTL_GET_TRANSPORT_BUFFER:
case MU_IOCTL_SET_TRANSPORT_BUFFER:
return mu_stream_ioctl (s->transport, code, ptr);
......
......@@ -149,10 +149,36 @@ _iostream_ctl (struct _mu_stream *str, int op, void *arg)
sp->transport[_MU_STREAM_OUTPUT] = (mu_stream_t) ptrans[1];
break;
case MU_IOCTL_SWAP_STREAM:
case MU_IOCTL_GET_STREAM:
if (!arg)
return EINVAL;
return _mu_stream_swap_streams (str, sp->transport, arg, 0);
else
{
mu_stream_t *pstr = arg;
pstr[0] = sp->transport[0];
mu_stream_ref (pstr[0]);
pstr[1] = sp->transport[1];
mu_stream_ref (pstr[1]);
}
break;
case MU_IOCTL_SET_STREAM:
if (!arg)
return EINVAL;
else
{
mu_stream_t *pstr = arg;
mu_stream_unref (sp->transport[0]);
sp->transport[0] = pstr[0];
mu_stream_ref (sp->transport[0]);
mu_stream_unref (sp->transport[1]);
sp->transport[1] = pstr[1];
mu_stream_ref (sp->transport[1]);
}
break;
case MU_IOCTL_GET_TRANSPORT_BUFFER:
case MU_IOCTL_SET_TRANSPORT_BUFFER:
......
......@@ -1063,88 +1063,3 @@ mu_stream_clr_flags (mu_stream_t stream, int fl)
return 0;
}
static void
swapstr (mu_stream_t stream, mu_stream_t *curstr, mu_stream_t *newstr)
{
mu_stream_t tmp;
tmp = *newstr;
*newstr = *curstr;
*curstr = tmp;
if (!(stream->flags & MU_STREAM_AUTOCLOSE))
{
if (*newstr)
mu_stream_unref (*newstr);
if (tmp)
mu_stream_ref (tmp);
}
if (!tmp)
mu_stream_seterr (stream, MU_ERR_NO_TRANSPORT, 1);
else if (stream->last_err == MU_ERR_NO_TRANSPORT)
mu_stream_clearerr (stream);
}
static int
swapstr_recursive (mu_stream_t stream, mu_stream_t *curstr,
mu_stream_t *newstr, int flags)
{
mu_stream_t strtab[2];
int rc = ENOSYS;
if (*curstr == NULL && *newstr == NULL)
return 0;
if (*curstr)
{
strtab[0] = *newstr;
strtab[1] = NULL;
rc = mu_stream_ioctl (*curstr, MU_IOCTL_SWAP_STREAM, strtab);
if (rc)
{
if ((flags & _MU_SWAP_IOCTL_MUST_SUCCEED)
|| !(rc == ENOSYS || rc == EINVAL))
return rc;
}
}
if (rc == 0)
*newstr = strtab[0];
else
swapstr (stream, curstr, newstr);
return 0;
}
/* CURTRANS[2] contains I/O transport streams used by STREAM,
NEWTRANS[2] contains another pair of streams.
This function swaps the items of these two arrays using the
MU_IOCTL_SWAP_STREAM ioctl. It is intended for use by STREAM's
ioctl method and is currently used by iostream.c */
int
_mu_stream_swap_streams (mu_stream_t stream, mu_stream_t *curtrans,
mu_stream_t *newtrans, int flags)
{
int rc;
rc = swapstr_recursive (stream, &curtrans[0], &newtrans[0], flags);
if (rc)
return rc;
if (flags & _MU_SWAP_FIRST_ONLY)
return 0;
rc = swapstr_recursive (stream, &curtrans[1], &newtrans[1], flags);
if (rc)
{
int rc1 = swapstr_recursive (stream, &curtrans[0], &newtrans[0], flags);
if (rc1)
{
mu_diag_output (MU_DIAG_CRIT,
_("restoring streams on %p failed: %s"),
stream, mu_strerror (rc1));
abort ();
}
}
return rc;
}
......
......@@ -43,7 +43,8 @@
#define TRANS_READ 0x1
#define TRANS_WRITE 0x2
#define TRANS_DISABLED 0x4
#define FLAG_TO_PFX(c) ((c) - 1)
#define TRANS_IOSTREAM 0x8
#define FLAG_TO_PFX(c) ((c & 0x3) - 1)
static int
word_match (const char *buf, size_t len, int n, const char *word,
......@@ -279,7 +280,26 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg)
sp->logstr = (mu_stream_t) ptrans[1];
break;
case MU_IOCTL_SWAP_STREAM:
case MU_IOCTL_GET_STREAM:
if (!arg)
return EINVAL;
if (!sp->transport)
status = ENOSYS;
else
status = mu_stream_ioctl (sp->transport, op, arg);
if (status == EINVAL || status == ENOSYS)
{
mu_stream_t *pstr = arg;
pstr[0] = sp->transport;
mu_stream_ref (pstr[0]);
pstr[1] = sp->transport;
mu_stream_ref (pstr[1]);
status = 0;
}
break;
case MU_IOCTL_SET_STREAM:
if (!arg)
return EINVAL;
if (!sp->transport)
......@@ -296,24 +316,19 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg)
status = mu_iostream_create (&tmp, pstr[0], pstr[1]);
if (status)
return status;
sp->flags |= TRANS_IOSTREAM;
}
else
tmp = pstr[0];
pstr[0] = sp->transport;
pstr[1] = sp->transport;
sp->transport = tmp;
/* FIXME */
if (!(str->flags & MU_STREAM_AUTOCLOSE))
{
if (pstr[0])
mu_stream_unref (pstr[0]);
if (tmp)
tmp = pstr[0];
mu_stream_ref (tmp);
}
if (tmp)
mu_stream_ref (tmp);
status = 0;
}
mu_stream_unref (sp->transport);
sp->transport = tmp;
}
break;
case MU_IOCTL_GET_TRANSPORT_BUFFER:
......@@ -331,7 +346,8 @@ _xscript_ctl (struct _mu_stream *str, int op, void *arg)
{
int oldlev = sp->level;
sp->level = *(int*)arg;
sp->flags = TRANS_READ | TRANS_WRITE;
sp->flags &= TRANS_DISABLED;
sp->flags |= TRANS_READ | TRANS_WRITE;
*(int*)arg = oldlev;
}
break;
......
......@@ -138,14 +138,8 @@ _smtp_callback (Gsasl *ctx, Gsasl_session *sctx, Gsasl_property prop)
static int
restore_and_return (mu_smtp_t smtp, mu_stream_t *str, int code)
{
int rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, str);
if (rc)
{
mu_error ("%s failed when it should not: %s",
"MU_IOCTL_SWAP_STREAM",
mu_stream_strerror (smtp->carrier, rc));
abort ();
}
mu_stream_unref (str[0]);
mu_stream_unref (str[1]);
return code;
}
......@@ -155,11 +149,10 @@ insert_gsasl_stream (mu_smtp_t smtp, Gsasl_session *sess_ctx)
mu_stream_t stream[2], newstream[2];
int rc;
stream[0] = stream[1] = NULL;
rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, stream);
rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_GET_STREAM, stream);
if (rc)
{
mu_error ("%s failed: %s", "MU_IOCTL_SWAP_STREAM",
mu_error ("%s failed: %s", "MU_IOCTL_GET_STREAM",
mu_stream_strerror (smtp->carrier, rc));
return MU_ERR_FAILURE;
}
......@@ -184,12 +177,16 @@ insert_gsasl_stream (mu_smtp_t smtp, Gsasl_session *sess_ctx)
}
mu_stream_flush (stream[1]);
mu_stream_unref (stream[0]);
mu_stream_unref (stream[1]);
rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, newstream);
rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SET_STREAM, newstream);
mu_stream_unref (newstream[0]);
mu_stream_unref (newstream[1]);
if (rc)
{
mu_error ("%s failed when it should not: %s",
"MU_IOCTL_SWAP_STREAM",
"MU_IOCTL_SET_STREAM",
mu_stream_strerror (smtp->carrier, rc));
abort ();
}
......
......@@ -28,24 +28,52 @@
#include <mailutils/tls.h>
static int
smtp_swap_streams (mu_smtp_t smtp, mu_stream_t *streams)
smtp_get_streams (mu_smtp_t smtp, mu_stream_t *streams)
{
int rc;
if (MU_SMTP_FISSET (smtp, _MU_SMTP_TRACE))
rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SWAP_STREAM, streams);
else if (streams[0] != streams[1])
rc = EINVAL;
rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_GET_STREAM, streams);
else
{
mu_stream_t str = streams[0];
streams[0] = streams[1] = smtp->carrier;
smtp->carrier = str;
streams[0] = smtp->carrier;
mu_stream_ref (streams[0]);
streams[1] = smtp->carrier;
mu_stream_ref (streams[1]);
rc = 0;
}
return rc;
}
static int
smtp_set_streams (mu_smtp_t smtp, mu_stream_t *streams)
{
int rc;
if (MU_SMTP_FISSET (smtp, _MU_SMTP_TRACE))
rc = mu_stream_ioctl (smtp->carrier, MU_IOCTL_SET_STREAM, streams);
else
{
mu_stream_t tmp;
if (streams[0] == streams[1])
{
tmp = streams[0];
mu_stream_ref (tmp);
mu_stream_ref (tmp);
rc = 0;
}
else
rc = mu_iostream_create (&tmp, streams[0], streams[1]);
if (rc == 0)
{
mu_stream_unref (smtp->carrier);
smtp->carrier = tmp;
}
}
return rc;
}
int
mu_smtp_starttls (mu_smtp_t smtp)
{
......@@ -72,12 +100,13 @@ mu_smtp_starttls (mu_smtp_t smtp)
return MU_ERR_FAILURE;
mu_stream_flush (smtp->carrier);
streams[0] = streams[1] = NULL;
status = smtp_swap_streams (smtp, streams);
status = smtp_get_streams (smtp, streams);
MU_SMTP_CHECK_ERROR (smtp, status);
status = mu_tls_client_stream_create (&tlsstream,
streams[0], streams[1], 0);
mu_stream_unref (streams[0]);
mu_stream_unref (streams[1]);
MU_SMTP_CHECK_ERROR (smtp, status);
status = mu_stream_open (tlsstream);
if (status)
......@@ -86,7 +115,9 @@ mu_smtp_starttls (mu_smtp_t smtp)
return status;
}
streams[0] = streams[1] = tlsstream;
status = smtp_swap_streams (smtp, streams);
status = smtp_set_streams (smtp, streams);
mu_stream_unref (streams[0]);
mu_stream_unref (streams[1]);
MU_SMTP_CHECK_ERROR (smtp, status);
/* Invalidate the capability list */
mu_list_destroy (&smtp->capa);
......
......@@ -31,24 +31,52 @@
#include <mailutils/list.h>
static int
pop3_swap_streams (mu_pop3_t pop3, mu_stream_t *streams)
pop3_get_streams (mu_pop3_t pop3, mu_stream_t *streams)
{
int rc;
if (MU_POP3_FISSET (pop3, MU_POP3_TRACE))
rc = mu_stream_ioctl (pop3->carrier, MU_IOCTL_SWAP_STREAM, streams);
else if (streams[0] != streams[1])
rc = EINVAL;
rc = mu_stream_ioctl (pop3->carrier, MU_IOCTL_GET_STREAM, streams);
else
{
mu_stream_t str = streams[0];
streams[0] = streams[1] = pop3->carrier;
pop3->carrier = str;
streams[0] = pop3->carrier;
mu_stream_ref (streams[0]);
streams[1] = pop3->carrier;
mu_stream_ref (streams[1]);
rc = 0;
}
return rc;
}
static int
pop3_set_streams (mu_pop3_t pop3, mu_stream_t *streams)
{
int rc;
if (MU_POP3_FISSET (pop3, MU_POP3_TRACE))
rc = mu_stream_ioctl (pop3->carrier, MU_IOCTL_SET_STREAM, streams);
else
{
mu_stream_t tmp;
if (streams[0] == streams[1])
{
tmp = streams[0];
mu_stream_ref (tmp);
mu_stream_ref (tmp);
rc = 0;
}
else
rc = mu_iostream_create (&tmp, streams[0], streams[1]);
if (rc == 0)
{
mu_stream_unref (pop3->carrier);
pop3->carrier = tmp;
}
}
return rc;
}
/*
* STLS
* We have to assume that the caller check the CAPA and TLS was supported.
......@@ -79,16 +107,19 @@ mu_pop3_stls (mu_pop3_t pop3)
pop3->state = MU_POP3_STLS_CONNECT;
case MU_POP3_STLS_CONNECT:
streams[0] = streams[1] = NULL;
status = pop3_swap_streams (pop3, streams);
status = pop3_get_streams (pop3, streams);
MU_POP3_CHECK_EAGAIN (pop3, status);
status = mu_tls_client_stream_create (&tlsstream,
streams[0], streams[1], 0);
mu_stream_unref (streams[0]);
mu_stream_unref (streams[1]);
MU_POP3_CHECK_EAGAIN (pop3, status);
status = mu_stream_open (tlsstream);
MU_POP3_CHECK_EAGAIN (pop3, status);
streams[0] = streams[1] = tlsstream;
status = pop3_swap_streams (pop3, streams);
status = pop3_set_streams (pop3, streams);
mu_stream_unref (streams[0]);
mu_stream_unref (streams[1]);
MU_POP3_CHECK_EAGAIN (pop3, status);
/* Invalidate the capability list */
mu_list_destroy (&pop3->capa);
......
......@@ -192,16 +192,17 @@ pop3d_init_tls_server ()
mu_stream_t tlsstream, stream[2];
int rc;
stream[0] = stream[1] = NULL;
rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream);
rc = mu_stream_ioctl (iostream, MU_IOCTL_GET_STREAM, stream);
if (rc)
{
mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM",
mu_error (_("%s failed: %s"), "MU_IOCTL_GET_STREAM",
mu_stream_strerror (iostream, rc));
return 1;
}
rc = mu_tls_server_stream_create (&tlsstream, stream[0], stream[1], 0);
mu_stream_unref (stream[0]);
mu_stream_unref (stream[1]);
if (rc)
return 1;
......@@ -216,10 +217,12 @@ pop3d_init_tls_server ()
else
stream[0] = stream[1] = tlsstream;
rc = mu_stream_ioctl (iostream, MU_IOCTL_SWAP_STREAM, stream);
rc = mu_stream_ioctl (iostream, MU_IOCTL_SET_STREAM, stream);
mu_stream_unref (stream[0]);
mu_stream_unref (stream[1]);
if (rc)
{
mu_error (_("%s failed: %s"), "MU_IOCTL_SWAP_STREAM",
mu_error (_("%s failed: %s"), "MU_IOCTL_SET_STREAM",
mu_stream_strerror (iostream, rc));
pop3d_abquit (ERR_IO);
}
......
......@@ -196,7 +196,7 @@ main (int argc, char **argv)
MU_ASSERT (mu_tcp_stream_create (&stream, host, port, MU_STREAM_RDWR));
MU_ASSERT (mu_stream_open (stream));
mu_smtp_set_carrier (smtp, stream);
//mu_stream_unref (stream);
mu_stream_unref (stream);
if (!from)
{
......