Commit 7d68b3cd 7d68b3cd17901190e6030327230df8e124161643 by Sergey Poznyakoff

Imap client: implement starttls.

* include/mailutils/imap.h (mu_imap_starttls): New proto.
* include/mailutils/imapio.h: Use mu_imapio_t instead of struct _mu_imapio *.
* include/mailutils/sys/imap.h (MU_IMAP_CLIENT_STARTTLS_RX): New state.
* libmailutils/imapio/transport.c: New file.
* libmailutils/imapio/Makefile.am (libimapio_la_SOURCES): Add transport.c
* libproto/imap/starttls.c: New file.
* libproto/imap/Makefile.am (libmu_imap_la_SOURCES): Add starttls.c.
* libproto/imap/capability.c (mu_imap_capability): Bugfix: set up
comparator and reclaim function after successful return from mu_list_map.
* libproto/imap/capatst.c (mu_imap_capability_test): Clear MU_IMAP_RESP
bit.
* libproto/imap/err.c (mu_imap_strerror): Return errstr only if
MU_IMAP_RESP is set.
* mu/imap.c: Implement starttls.
1 parent f675ddc7
......@@ -51,6 +51,8 @@ int mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter);
int mu_imap_capability_test (mu_imap_t imap, const char *name,
const char **pret);
int mu_imap_starttls (mu_imap_t imap);
int mu_imap_login (mu_imap_t imap, const char *user, const char *pass);
int mu_imap_logout (mu_imap_t imap);
......
......@@ -38,22 +38,22 @@ int mu_imapio_get_words (mu_imapio_t io, size_t *pwc, char ***pwv);
int mu_imapio_send (mu_imapio_t io, const char *buf, size_t bytes);
int mu_imapio_printf (mu_imapio_t io, const char *fmt, ...);
int mu_imapio_send_literal_string (struct _mu_imapio *io, const char *buffer);
int mu_imapio_send_literal_stream (struct _mu_imapio *io, mu_stream_t stream,
int mu_imapio_send_literal_string (mu_imapio_t io, const char *buffer);
int mu_imapio_send_literal_stream (mu_imapio_t io, mu_stream_t stream,
mu_off_t size);
int mu_imapio_send_qstring (struct _mu_imapio *io, const char *buffer);
int mu_imapio_send_qstring_unfold (struct _mu_imapio *io, const char *buffer,
int mu_imapio_send_qstring (mu_imapio_t io, const char *buffer);
int mu_imapio_send_qstring_unfold (mu_imapio_t io, const char *buffer,
int unfold);
int mu_imapio_send_command_v (struct _mu_imapio *io, const char *tag,
int mu_imapio_send_command_v (mu_imapio_t io, const char *tag,
int argc, char const **argv, const char *extra);
int mu_imapio_send_command (struct _mu_imapio *io, const char *tag,
int mu_imapio_send_command (mu_imapio_t io, const char *tag,
char const *cmd, ...);
int mu_imapio_send_command_e (struct _mu_imapio *io, const char *tag,
int mu_imapio_send_command_e (mu_imapio_t io, const char *tag,
char const *cmd, ...);
int mu_imapio_send_flags (struct _mu_imapio *io, int flags);
int mu_imapio_send_time (struct _mu_imapio *io, struct tm *tm,
int mu_imapio_send_flags (mu_imapio_t io, int flags);
int mu_imapio_send_time (mu_imapio_t io, struct tm *tm,
struct mu_timezone *tz);
int mu_imapio_trace_enable (mu_imapio_t io);
......@@ -62,12 +62,15 @@ int mu_imapio_get_trace (mu_imapio_t io);
void mu_imapio_trace_payload (mu_imapio_t io, int val);
int mu_imapio_get_trace_payload (mu_imapio_t io);
int mu_imapio_get_streams (mu_imapio_t io, mu_stream_t *streams);
int mu_imapio_set_streams (mu_imapio_t io, mu_stream_t *streams);
int mu_imapio_getbuf (mu_imapio_t io, char **pptr, size_t *psize);
int mu_imapio_reply_string (struct _mu_imapio *io, size_t start, char **pbuf);
int mu_imapio_reply_string (mu_imapio_t io, size_t start, char **pbuf);
int mu_imapio_last_error (struct _mu_imapio *io);
void mu_imapio_clearerr (struct _mu_imapio *io);
int mu_imapio_last_error (mu_imapio_t io);
void mu_imapio_clearerr (mu_imapio_t io);
int mu_imap_flag_to_attribute (const char *item, int *attr);
int mu_imap_format_flags (mu_stream_t str, int flags);
......
......@@ -70,6 +70,7 @@ enum mu_imap_client_state
MU_IMAP_CLIENT_SUBSCRIBE_RX,
MU_IMAP_CLIENT_UNSUBSCRIBE_RX,
MU_IMAP_CLIENT_LSUB_RX,
MU_IMAP_CLIENT_STARTTLS_RX,
MU_IMAP_CLIENT_CLOSING
};
......
......@@ -33,6 +33,7 @@ libimapio_la_SOURCES = \
sendcmde.c\
time.c\
trace.c\
transport.c\
words.c\
xscript.c
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 1999, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
2009, 2010, 2011 Free Software Foundation, Inc.
GNU Mailutils is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3, or (at your option)
any later version.
GNU Mailutils is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with GNU Mailutils. If not, see <http://www.gnu.org/licenses/>. */
#include <config.h>
#include <errno.h>
#include <mailutils/types.h>
#include <mailutils/stream.h>
#include <mailutils/diag.h>
#include <mailutils/imapio.h>
#include <mailutils/sys/imapio.h>
int
mu_imapio_get_streams (struct _mu_imapio *io, mu_stream_t *streams)
{
int rc;
mu_stream_flush (io->_imap_stream);
if (io->_imap_transcript)
rc = mu_stream_ioctl (io->_imap_stream, MU_IOCTL_SUBSTREAM,
MU_IOCTL_OP_GET, streams);
else
{
streams[0] = io->_imap_stream;
mu_stream_ref (streams[0]);
streams[1] = io->_imap_stream;
mu_stream_ref (streams[1]);
rc = 0;
}
return rc;
}
int
mu_imapio_set_streams (struct _mu_imapio *io, mu_stream_t *streams)
{
int rc;
if (io->_imap_transcript)
rc = mu_stream_ioctl (io->_imap_stream, MU_IOCTL_SUBSTREAM,
MU_IOCTL_OP_SET, 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 (io->_imap_stream);
io->_imap_stream = tmp;
}
}
return rc;
}
......@@ -62,6 +62,7 @@ libmu_imap_la_SOURCES = \
select.c\
state.c\
status.c\
starttls.c\
store.c\
subscribe.c\
tag.c\
......
......@@ -94,14 +94,7 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
return 0;
return mu_list_get_iterator (imap->capa, piter);
}
mu_list_clear (imap->capa);
}
else
{
status = mu_list_create (&imap->capa);
MU_IMAP_CHECK_ERROR (imap, status);
mu_list_set_comparator (imap->capa, capa_comp);
mu_list_set_destroy_item (imap->capa, mu_list_free_item);
mu_list_destroy (&imap->capa);
}
switch (imap->client_state)
......@@ -124,6 +117,9 @@ mu_imap_capability (mu_imap_t imap, int reread, mu_iterator_t *piter)
return MU_ERR_REPLY;
else
{
mu_list_set_comparator (imap->capa, capa_comp);
mu_list_set_destroy_item (imap->capa, mu_list_free_item);
if (piter)
status = mu_list_get_iterator (imap->capa, piter);
else
......
......@@ -31,5 +31,6 @@ mu_imap_capability_test (mu_imap_t imap, const char *name, const char **pret)
rc = mu_imap_capability (imap, 0, NULL);
if (rc)
return rc;
MU_IMAP_FCLR (imap, MU_IMAP_RESP);
return mu_list_locate (imap->capa, (void*) name, (void**)pret);
}
......
......@@ -62,11 +62,12 @@ mu_imap_strerror (mu_imap_t imap, const char **pstr)
*pstr = "(imap not initialized)";
return EINVAL;
}
if (imap->errstr)
if (MU_IMAP_FISSET (imap, MU_IMAP_RESP))
{
*pstr = imap->errstr;
return 0;
}
*pstr = "(no error)";
*pstr = "(no recent reply)";
return MU_ERR_NOENT;
}
......
/* GNU Mailutils -- a suite of utilities for electronic mail
Copyright (C) 2010, 2011 Free Software Foundation, Inc.
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 3 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General
Public License along with this library. If not, see
<http://www.gnu.org/licenses/>. */
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <stdlib.h>
#include <string.h>
#include <mailutils/errno.h>
#include <mailutils/stream.h>
#include <mailutils/tls.h>
#include <mailutils/imap.h>
#include <mailutils/sys/imap.h>
int
mu_imap_starttls (mu_imap_t imap)
{
#ifdef WITH_TLS
int status;
mu_stream_t tlsstream, streams[2];
if (imap == NULL)
return EINVAL;
if (!imap->io)
return MU_ERR_NO_TRANSPORT;
if (imap->session_state == MU_IMAP_SESSION_INIT)
return MU_ERR_SEQ;
status = mu_imap_capability_test (imap, "STARTTLS", NULL);
if (status == MU_ERR_NOENT)
return ENOSYS;
else if (status)
return status;
switch (imap->client_state)
{
case MU_IMAP_CLIENT_READY:
status = _mu_imap_tag_next (imap);
MU_IMAP_CHECK_EAGAIN (imap, status);
status = mu_imapio_printf (imap->io, "%s STARTTLS\r\n", imap->tag_str);
MU_IMAP_CHECK_ERROR (imap, status);
MU_IMAP_FCLR (imap, MU_IMAP_RESP);
imap->client_state = MU_IMAP_CLIENT_STARTTLS_RX;
case MU_IMAP_CLIENT_STARTTLS_RX:
status = _mu_imap_response (imap, NULL, NULL);
MU_IMAP_CHECK_EAGAIN (imap, status);
switch (imap->resp_code)
{
case MU_IMAP_OK:
status = mu_imapio_get_streams (imap->io, streams);
MU_IMAP_CHECK_EAGAIN (imap, status);
status = mu_tls_client_stream_create (&tlsstream,
streams[0], streams[1], 0);
mu_stream_unref (streams[0]);
mu_stream_unref (streams[1]);
MU_IMAP_CHECK_EAGAIN (imap, status);
streams[0] = streams[1] = tlsstream;
status = mu_imapio_set_streams (imap->io, streams);
mu_stream_unref (streams[0]);
mu_stream_unref (streams[1]);
MU_IMAP_CHECK_EAGAIN (imap, status);
/* Invalidate the capability list */
mu_list_destroy (&imap->capa);
status = 0;
break;
case MU_IMAP_NO:
status = MU_ERR_FAILURE;
break;
case MU_IMAP_BAD:
status = MU_ERR_BADREPLY;
break;
}
imap->client_state = MU_IMAP_CLIENT_READY;
break;
default:
status = EINPROGRESS;
}
return status;
#else
return ENOSYS;
#endif
}
......@@ -455,6 +455,15 @@ com_connect (int argc, char **argv)
}
static int
com_starttls (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
int status = mu_imap_starttls (imap);
if (status)
report_failure ("starttls", status);
return 0;
}
static int
com_logout (int argc MU_ARG_UNUSED, char **argv MU_ARG_UNUSED)
{
int status = 0;
......@@ -988,6 +997,10 @@ struct mutool_command imap_comtab[] = {
com_disconnect,
NULL,
N_("close connection") },
{ "starttls", 1, 1, 0,
com_starttls,
NULL,
N_("Establish TLS encrypted channel") },
{ "login", 2, 3, 0,
com_login,
N_("USER [PASS]"),
......