There are no changes to the code, just rearrangements of functions.
Priority: -6
- Regex: '"lib/.*\.h"'
Priority: -4
+ - Regex: '"conn/.*\.h"'
+ Priority: -3
- Regex: '"mutt\.h"'
Priority: -2
# Main Header 0
--with-sasl \
--with-tokyocabinet
-SUBDIRS = m4 contrib imap ncrypt lib
+SUBDIRS = m4 contrib imap ncrypt lib conn
if BUILD_HCACHE
SUBDIRS += hcache
bin_PROGRAMS = neomutt
-neomutt_SOURCES = account.c addrbook.c address.h alias.c alias.h attach.c \
+neomutt_SOURCES = mutt_account.c addrbook.c address.h alias.c alias.h attach.c \
bcache.c body.c body.h browser.c buffy.c charset.c color.c \
commands.c complete.c compose.c compress.c content.h context.h copy.c \
curs_lib.c curs_main.c edit.c editmsg.c enter.c enter_state.h \
- envelope.c envelope.h filter.c flags.c format_flags.h from.c getdomain.c group.c \
+ envelope.c envelope.h filter.c flags.c format_flags.h from.c group.c \
handler.c hdrline.c header.h headers.c help.c history.c hook.c \
init.c keymap.c main.c mbox.c mbyte.c mbtable.h \
- menu.c mh.c muttlib.c mutt_idna.c mutt_sasl_plain.c mutt_socket.c \
- mutt_tunnel.c mx.c newsrc.c nntp.c options.h pager.c parameter.c parameter.h \
+ menu.c mh.c muttlib.c mutt_idna.c mutt_socket.c \
+ mx.c newsrc.c nntp.c options.h pager.c parameter.c parameter.h \
parse.c pattern.c pattern.h pop.c pop_auth.c pop_lib.c postpone.c \
query.c recvattach.c recvcmd.c rfc1524.c rfc2047.c rfc2231.c rfc3676.c \
rfc822.c safe_asprintf.c score.c send.c sendlib.c sidebar.c signal.c \
LIBIMAP = -Limap -limap
LIBIMAPDEPS = $(top_srcdir)/imap/imap.h imap/libimap.a
+LIBCONN = -Lconn -lconn
+LIBCONNDEPS = $(top_srcdir)/conn/connection.h conn/libconn.a
+
LIBMUTT = -Llib -lmutt
LIBMUTTDEPS = $(top_srcdir)/lib/lib.h lib/libmutt.a
neomutt_LDADD = $(MUTT_LIB_OBJECTS) $(LIBOBJS) $(HCACHE_LIBS) $(NCRYPT_LIBS) \
- $(LIBIMAP) $(LIBMUTT) $(LIBICONV) $(GPGME_LIBS) $(INTLLIBS)
+ $(LIBIMAP) $(LIBCONN) $(LIBMUTT) $(LIBICONV) $(GPGME_LIBS) $(INTLLIBS)
-neomutt_DEPENDENCIES = $(MUTT_LIB_OBJECTS) $(LIBOBJS) $(LIBIMAPDEPS) \
+neomutt_DEPENDENCIES = $(MUTT_LIB_OBJECTS) $(LIBOBJS) $(LIBIMAPDEPS) $(LIBCONNDEPS) \
$(LIBMUTTDEPS) $(HCACHE_DEPS) $(NCRYPT_DEPS) $(INTLDEPS)
DEFS=-DPKGDATADIR=\"$(pkgdatadir)\" -DSYSCONFDIR=\"$(sysconfdir)\" \
AM_CPPFLAGS=-I. -I$(top_srcdir) $(GPGME_CFLAGS)
EXTRA_neomutt_SOURCES = browser.h mbyte.h mutt_idna.c mutt_idna.h \
- mutt_lua.c mutt_sasl.c mutt_notmuch.c mutt_ssl.c mutt_ssl_gnutls.c \
+ mutt_lua.c mutt_notmuch.c \
remailer.c remailer.h resize.c url.h
EXTRA_DIST = account.h attach.h bcache.h browser.h buffy.h \
group.h history.h init.h keymap.h LICENSE.md mailbox.h \
mbyte.h mime.h mutt.h mutt_commands.h \
mutt_curses.h mutt_idna.h mutt_lua.h mutt_menu.h mutt_notmuch.h \
- mutt_options.h mutt_regex.h mutt_sasl.h mutt_sasl_plain.h \
- mutt_socket.h mutt_ssl.h mutt_tunnel.h mx.h myvar.h nntp.h opcodes.h pager.h \
+ mutt_options.h mutt_regex.h \
+ mutt_socket.h mx.h myvar.h nntp.h opcodes.h pager.h \
pgpewrap.c pop.h protos.h README.md README.SSL remailer.c remailer.h \
rfc1524.h rfc2047.h rfc2231.h rfc3676.h rfc822.h sidebar.h \
sort.h txt2c.c txt2c.sh version.h mutt_tags.h
###############################################################################
# neomutt
NEOMUTT= neomutt$(EXEEXT)
-NEOMUTTOBJS= account.o addrbook.o alias.o attach.o bcache.o body.o \
+NEOMUTTOBJS= mutt_account.o addrbook.o alias.o attach.o bcache.o body.o \
browser.o buffy.o charset.o color.o commands.o complete.o \
compose.o compress.o conststrings.o copy.o curs_lib.o \
curs_main.o edit.o editmsg.o enter.o envelope.o filter.o \
- flags.o from.o getdomain.o group.o handler.o hdrline.o \
+ flags.o from.o group.o handler.o hdrline.o \
headers.o help.o history.o hook.o init.o keymap.o main.o \
mbox.o mbyte.o menu.o mh.o muttlib.o mutt_idna.o \
- mutt_sasl_plain.o mutt_socket.o mutt_tags.o mutt_tunnel.o mx.o \
+ mutt_socket.o mutt_tags.o mx.o \
newsrc.o nntp.o pager.o parameter.o parse.o pattern.o pop.o \
pop_auth.o pop_lib.o postpone.o query.o recvattach.o recvcmd.o \
rfc1524.o rfc2047.o rfc2231.o rfc3676.o rfc822.o \
@if HAVE_RESIZETERM
NEOMUTTOBJS+= resize.o
@endif
-@if USE_SSL_OPENSSL
-NEOMUTTOBJS+= mutt_ssl.o
-@endif
-@if USE_SSL_GNUTLS
-NEOMUTTOBJS+= mutt_ssl_gnutls.o
-@endif
@if USE_NOTMUCH
NEOMUTTOBJS+= mutt_notmuch.o
@endif
@if MIXMASTER
NEOMUTTOBJS+= remailer.o
@endif
-@if HAVE_SASL
-NEOMUTTOBJS+= mutt_sasl.o
-@endif
@if USE_LUA
NEOMUTTOBJS+= mutt_lua.o
@endif
MUTTLIBS+= $(LIBIMAP)
ALLOBJS+= $(LIBIMAPOBJS)
+###############################################################################
+# libconn
+LIBCONN= libconn.a
+LIBCONNOBJS= conn/conn_globals.o conn/getdomain.o conn/sasl_plain.o \
+ conn/socket.o conn/tunnel.o
+@if HAVE_SASL
+LIBCONNOBJS+= conn/sasl.o
+@endif
+@if USE_SSL_OPENSSL
+LIBCONNOBJS+= conn/ssl.o
+@endif
+@if USE_SSL_GNUTLS
+LIBCONNOBJS+= conn/ssl_gnutls.o
+@endif
+CLEANFILES+= $(LIBCONN) $(LIBCONNOBJS)
+MUTTLIBS+= $(LIBCONN)
+ALLOBJS+= $(LIBCONNOBJS)
+
###############################################################################
# libhcache
@if USE_HCACHE
$(PWD)/imap:
$(MKDIR_P) $(PWD)/imap
+# libconn
+$(LIBCONN): $(PWD)/conn $(LIBCONNOBJS)
+ $(AR) cr $@ $(LIBCONNOBJS)
+ $(RANLIB) $@
+$(PWD)/conn:
+ $(MKDIR_P) $(PWD)/conn
+
# libhcache
hcache/hcache.o: hcache/hcversion.h
$(LIBHCACHE): $(PWD)/hcache $(LIBHCACHEOBJS)
#include <unistd.h>
#include "lib/lib.h"
#include "bcache.h"
-#include "account.h"
#include "globals.h"
+#include "mutt_account.h"
#include "protos.h"
#include "url.h"
#include <time.h>
#include <unistd.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
-#include "account.h"
#include "attach.h"
#include "body.h"
#include "browser.h"
#include "keymap.h"
#include "mailbox.h"
#include "mbyte.h"
+#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_menu.h"
#include "mutt_regex.h"
-#include "mutt_socket.h"
#include "mx.h"
#include "opcodes.h"
#include "options.h"
#include <sys/stat.h>
#include <unistd.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
#include "alias.h"
#include "attach.h"
#include "mutt_curses.h"
#include "mutt_idna.h"
#include "mutt_menu.h"
-#include "mutt_socket.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
#include "opcodes.h"
AC_DEFINE(USE_SSL,1,[ Define if you want support for SSL. ])
AC_DEFINE(USE_SSL_OPENSSL,1,[ Define if you want support for SSL via OpenSSL. ])
- MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS mutt_ssl.o"
need_ssl=yes
fi
])
+AM_CONDITIONAL(USE_SSL_OPENSSL, test x$need_ssl = xyes)
AC_ARG_WITH([gnutls], AS_HELP_STRING([--with-gnutls@<:@=PFX@:>@],[enable TLS support using gnutls]),
[gnutls_prefix="$withval"], [gnutls_prefix="no"])
AC_DEFINE(USE_SSL, 1, [ Define if you want support for SSL. ])
AC_DEFINE(USE_SSL_GNUTLS, 1, [ Define if you want support for SSL via GNUTLS. ])
- MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS mutt_ssl_gnutls.o"
- need_ssl=yes],
+ need_tls=yes],
[AC_MSG_ERROR([could not find libgnutls])])
fi
+AM_CONDITIONAL(USE_SSL_GNUTLS, test x$need_tls = xyes)
AC_ARG_WITH(sasl, AS_HELP_STRING([--with-sasl@<:@=PFX@:>@],[Use SASL network security library]),
[
AC_SEARCH_LIBS(sasl_encode64, [$sasl_libs],,
AC_MSG_ERROR([could not find sasl lib]),)
- MUTT_LIB_OBJECTS="$MUTT_LIB_OBJECTS mutt_sasl.o"
-
AC_DEFINE(USE_SASL,1,
[ Define if want to use the SASL library for POP/IMAP authentication. ])
need_sasl=yes
fi
AC_CONFIG_FILES(Makefile contrib/Makefile doc/Makefile imap/Makefile
- m4/Makefile po/Makefile.in hcache/Makefile ncrypt/Makefile lib/Makefile)
+ m4/Makefile po/Makefile.in hcache/Makefile ncrypt/Makefile lib/Makefile conn/Makefile)
AC_OUTPUT
AC_MSG_NOTICE([Summary of build options:
--- /dev/null
+## Process this file with automake to produce Makefile.in
+include $(top_srcdir)/flymake.am
+
+AUTOMAKE_OPTIONS = 1.6 foreign
+
+EXTRA_DIST = account.h connection.h sasl.h sasl_plain.h socket.h ssl.h tunnel.h
+
+AM_CPPFLAGS = -I$(top_srcdir)
+
+noinst_LIBRARIES = libconn.a
+
+libconn_a_SOURCES = conn_globals.c getdomain.c sasl_plain.c socket.c tunnel.c
+
+if USE_SASL
+libconn_a_SOURCES += sasl.c
+endif
+if USE_SSL_OPENSSL
+libconn_a_SOURCES += ssl.c
+endif
+if USE_SSL_GNUTLS
+libconn_a_SOURCES += ssl_gnutls.c
+endif
+
--- /dev/null
+/**
+ * @file
+ * Account object
+ *
+ * @authors
+ * Copyright (C) 2000-2005,2008 Brendan Cully <brendan@kublai.com>
+ *
+ * @copyright
+ * This program 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 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program 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
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CONN_ACCOUNT_H
+#define _CONN_ACCOUNT_H
+
+/**
+ * struct Account - Login details for a remote server
+ */
+struct Account
+{
+ char user[64];
+ char login[64];
+ char pass[256];
+ char host[128];
+ unsigned short port;
+ unsigned char type;
+ unsigned char flags;
+};
+
+#endif /* _CONN_ACCOUNT_H */
--- /dev/null
+/**
+ * @file
+ * Connection Library
+ *
+ * @authors
+ * Copyright (C) 2017 Richard Russon <rich@flatcap.org>
+ *
+ * @copyright
+ * This program 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 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program 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
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CONN_CONN_H
+#define _CONN_CONN_H
+
+#include "account.h"
+#include "conn_globals.h"
+#include "connection.h"
+#ifdef USE_SASL
+#include "sasl.h"
+#endif
+#include "sasl_plain.h"
+#include "socket.h"
+#ifdef USE_SSL
+#include "ssl.h"
+#endif
+#include "tunnel.h"
+
+#endif /* _CONN_CONN_H */
--- /dev/null
+/**
+ * @file
+ * Connection Global Variables
+ *
+ * @authors
+ * Copyright (C) 2017 Richard Russon <rich@flatcap.org>
+ *
+ * @copyright
+ * This program 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 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program 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
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+
+short ConnectTimeout; /**< Config: $connect_timeout */
+
+#ifdef USE_SSL
+const char *CertificateFile; /**< Config: $certificate_file */
+const char *EntropyFile; /**< Config: $entropy_file */
+const char *SslCiphers; /**< Config: $ssl_ciphers */
+const char *SslClientCert; /**< Config: $ssl_client_cert */
+#ifdef USE_SSL_GNUTLS
+const char *SslCaCertificatesFile; /**< Config: $ssl_ca_certificates_file */
+short SslMinDhPrimeBits; /**< Config: $ssl_min_dh_prime_bits */
+#endif
+#endif
+
+#ifdef USE_SOCKET
+const char *Preconnect; /**< Config: $preconnect */
+const char *Tunnel; /**< Config: $tunnel */
+#endif /* USE_SOCKET */
--- /dev/null
+/**
+ * @file
+ * Connection Global Variables
+ *
+ * @authors
+ * Copyright (C) 2017 Richard Russon <rich@flatcap.org>
+ *
+ * @copyright
+ * This program 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 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program 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
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CONN_GLOBALS_H
+#define _CONN_GLOBALS_H
+
+extern short ConnectTimeout;
+
+#ifdef USE_SSL
+extern const char *CertificateFile;
+extern const char *EntropyFile;
+extern const char *SslCiphers;
+extern const char *SslClientCert;
+#ifdef USE_SSL_GNUTLS
+extern const char *SslCaCertificatesFile;
+extern short SslMinDhPrimeBits;
+#endif
+#endif
+
+#ifdef USE_SOCKET
+extern const char *Preconnect;
+extern const char *Tunnel;
+#endif
+
+#endif /* _CONN_GLOBALS_H */
--- /dev/null
+/**
+ * @file
+ * An open network connection (socket)
+ *
+ * @authors
+ * Copyright (C) 1998 Brandon Long <blong@fiction.net>
+ * Copyright (C) 1999-2005 Brendan Cully <brendan@kublai.com>
+ *
+ * @copyright
+ * This program 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 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program 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
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CONN_CONNECTION_H
+#define _CONN_CONNECTION_H
+
+#include <stdio.h>
+#include <time.h>
+#include "lib/queue.h"
+#include "account.h"
+
+#define LONG_STRING 1024
+
+/**
+ * struct Connection - An open network connection (socket)
+ */
+struct Connection
+{
+ struct Account account;
+ unsigned int ssf; /**< security strength factor, in bits */
+ void *data;
+
+ char inbuf[LONG_STRING];
+ int bufpos;
+
+ int fd;
+ int available;
+
+ TAILQ_ENTRY(Connection) entries;
+
+ void *sockdata;
+ int (*conn_read)(struct Connection *conn, char *buf, size_t len);
+ int (*conn_write)(struct Connection *conn, const char *buf, size_t count);
+ int (*conn_open)(struct Connection *conn);
+ int (*conn_close)(struct Connection *conn);
+ int (*conn_poll)(struct Connection *conn, time_t wait_secs);
+};
+
+#endif /* _CONN_CONNECTION_H */
#include <sys/socket.h>
#include <time.h>
#include <unistd.h>
-#include "lib/lib.h"
+#include "lib/debug.h"
+#include "lib/memory.h"
+#include "lib/string2.h"
int getdnsdomainname(char *d, size_t len)
{
*/
/* common SASL helper routines */
+/* SASL can stack a protection layer on top of an existing connection.
+ * To handle this, we store a saslconn_t in conn->sockdata, and write
+ * wrappers which en/decode the read/write stream, then replace sockdata
+ * with an embedded copy of the old sockdata and call the underlying
+ * functions (which we've also preserved). I thought about trying to make
+ * a general stackable connection system, but it seemed like overkill -
+ * something is wrong if we have 15 filters on top of a socket. Anyway,
+ * anything else which wishes to stack can use the same method. The only
+ * disadvantage is we have to write wrappers for all the socket methods,
+ * even if we only stack over read and write. Thinking about it, the
+ * abstraction problem is that there is more in Connection than there
+ * needs to be. Ideally it would have only (void*)data and methods. */
#include "config.h"
#include <errno.h>
#include <netdb.h>
#include <sasl/sasl.h>
+#include <stdbool.h>
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
-#include "lib/lib.h"
-#include "mutt_sasl.h"
+#include <time.h>
+#include "lib/debug.h"
+#include "lib/memory.h"
+#include "lib/message.h"
+#include "lib/string2.h"
+#include "sasl.h"
#include "account.h"
-#include "mutt_socket.h"
+#include "connection.h"
+#include "mutt_account.h"
#include "options.h"
#include "protos.h"
+/* arbitrary. SASL will probably use a smaller buffer anyway. OTOH it's
+ * been a while since I've had access to an SASL server which negotiated
+ * a protection buffer. */
+#define MUTT_SASL_MAXBUF 65536
+
+#define IP_PORT_BUFLEN 1024
+
+static sasl_callback_t MuttSaslCallbacks[5];
+
+static sasl_secret_t *secret_ptr = NULL;
+
static int getnameinfo_err(int ret)
{
int err;
return err;
}
-/* arbitrary. SASL will probably use a smaller buffer anyway. OTOH it's
- * been a while since I've had access to an SASL server which negotiated
- * a protection buffer. */
-#define MUTT_SASL_MAXBUF 65536
-
-#define IP_PORT_BUFLEN 1024
-
-static sasl_callback_t MuttSaslCallbacks[5];
-
-static sasl_secret_t *secret_ptr = NULL;
-
/**
* iptostring - Convert IP Address to string
*
return MuttSaslCallbacks;
}
-/**
- * mutt_sasl_client_new - wrapper for sasl_client_new
- *
- * which also sets various security properties. If this turns out to be fine
- * for POP too we can probably stop exporting mutt_sasl_get_callbacks().
- */
-int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
-{
- sasl_security_properties_t secprops;
- struct sockaddr_storage local, remote;
- socklen_t size;
- char iplocalport[IP_PORT_BUFLEN], ipremoteport[IP_PORT_BUFLEN];
- char *plp = NULL;
- char *prp = NULL;
- const char *service = NULL;
- int rc;
-
- if (mutt_sasl_start() != SASL_OK)
- return -1;
-
- switch (conn->account.type)
- {
- case MUTT_ACCT_TYPE_IMAP:
- service = "imap";
- break;
- case MUTT_ACCT_TYPE_POP:
- service = "pop";
- break;
- case MUTT_ACCT_TYPE_SMTP:
- service = "smtp";
- break;
-#ifdef USE_NNTP
- case MUTT_ACCT_TYPE_NNTP:
- service = "nntp";
- break;
-#endif
- default:
- mutt_error(_("Unknown SASL profile"));
- return -1;
- }
-
- size = sizeof(local);
- if (!getsockname(conn->fd, (struct sockaddr *) &local, &size))
- {
- if (iptostring((struct sockaddr *) &local, size, iplocalport, IP_PORT_BUFLEN) == SASL_OK)
- plp = iplocalport;
- else
- mutt_debug(2, "SASL failed to parse local IP address\n");
- }
- else
- mutt_debug(2, "SASL failed to get local IP address\n");
-
- size = sizeof(remote);
- if (!getpeername(conn->fd, (struct sockaddr *) &remote, &size))
- {
- if (iptostring((struct sockaddr *) &remote, size, ipremoteport, IP_PORT_BUFLEN) == SASL_OK)
- prp = ipremoteport;
- else
- mutt_debug(2, "SASL failed to parse remote IP address\n");
- }
- else
- mutt_debug(2, "SASL failed to get remote IP address\n");
-
- mutt_debug(2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
-
- rc = sasl_client_new(service, conn->account.host, plp, prp,
- mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
-
- if (rc != SASL_OK)
- {
- mutt_error(_("Error allocating SASL connection"));
- mutt_sleep(2);
- return -1;
- }
-
- memset(&secprops, 0, sizeof(secprops));
- /* Work around a casting bug in the SASL krb4 module */
- secprops.max_ssf = 0x7fff;
- secprops.maxbufsize = MUTT_SASL_MAXBUF;
- if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
- {
- mutt_error(_("Error setting SASL security properties"));
- return -1;
- }
-
- if (conn->ssf)
- {
- /* I'm not sure this actually has an effect, at least with SASLv2 */
- mutt_debug(2, "External SSF: %d\n", conn->ssf);
- if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &(conn->ssf)) != SASL_OK)
- {
- mutt_error(_("Error setting SASL external security strength"));
- return -1;
- }
- }
- if (conn->account.user[0])
- {
- mutt_debug(2, "External authentication name: %s\n", conn->account.user);
- if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
- {
- mutt_error(_("Error setting SASL external user name"));
- return -1;
- }
- }
-
- return 0;
-}
-
-int mutt_sasl_interact(sasl_interact_t *interaction)
-{
- char prompt[SHORT_STRING];
- char resp[SHORT_STRING];
-
- while (interaction->id != SASL_CB_LIST_END)
- {
- mutt_debug(2, "mutt_sasl_interact: filling in SASL interaction %ld.\n",
- interaction->id);
-
- snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
- resp[0] = '\0';
- if (option(OPT_NO_CURSES) || mutt_get_field(prompt, resp, sizeof(resp), 0))
- return SASL_FAIL;
-
- interaction->len = mutt_strlen(resp) + 1;
- interaction->result = safe_malloc(interaction->len);
- memcpy((char *) interaction->result, resp, interaction->len);
-
- interaction++;
- }
-
- return SASL_OK;
-}
-
/**
* mutt_sasl_conn_open - empty wrapper for underlying open function
*
return rc;
}
-/* SASL can stack a protection layer on top of an existing connection.
- * To handle this, we store a saslconn_t in conn->sockdata, and write
- * wrappers which en/decode the read/write stream, then replace sockdata
- * with an embedded copy of the old sockdata and call the underlying
- * functions (which we've also preserved). I thought about trying to make
- * a general stackable connection system, but it seemed like overkill -
- * something is wrong if we have 15 filters on top of a socket. Anyway,
- * anything else which wishes to stack can use the same method. The only
- * disadvantage is we have to write wrappers for all the socket methods,
- * even if we only stack over read and write. Thinking about it, the
- * abstraction problem is that there is more in Connection than there
- * needs to be. Ideally it would have only (void*)data and methods. */
+/**
+ * mutt_sasl_client_new - wrapper for sasl_client_new
+ *
+ * which also sets various security properties. If this turns out to be fine
+ * for POP too we can probably stop exporting mutt_sasl_get_callbacks().
+ */
+int mutt_sasl_client_new(struct Connection *conn, sasl_conn_t **saslconn)
+{
+ sasl_security_properties_t secprops;
+ struct sockaddr_storage local, remote;
+ socklen_t size;
+ char iplocalport[IP_PORT_BUFLEN], ipremoteport[IP_PORT_BUFLEN];
+ char *plp = NULL;
+ char *prp = NULL;
+ const char *service = NULL;
+ int rc;
+
+ if (mutt_sasl_start() != SASL_OK)
+ return -1;
+
+ switch (conn->account.type)
+ {
+ case MUTT_ACCT_TYPE_IMAP:
+ service = "imap";
+ break;
+ case MUTT_ACCT_TYPE_POP:
+ service = "pop";
+ break;
+ case MUTT_ACCT_TYPE_SMTP:
+ service = "smtp";
+ break;
+#ifdef USE_NNTP
+ case MUTT_ACCT_TYPE_NNTP:
+ service = "nntp";
+ break;
+#endif
+ default:
+ mutt_error(_("Unknown SASL profile"));
+ return -1;
+ }
+
+ size = sizeof(local);
+ if (!getsockname(conn->fd, (struct sockaddr *) &local, &size))
+ {
+ if (iptostring((struct sockaddr *) &local, size, iplocalport, IP_PORT_BUFLEN) == SASL_OK)
+ plp = iplocalport;
+ else
+ mutt_debug(2, "SASL failed to parse local IP address\n");
+ }
+ else
+ mutt_debug(2, "SASL failed to get local IP address\n");
+
+ size = sizeof(remote);
+ if (!getpeername(conn->fd, (struct sockaddr *) &remote, &size))
+ {
+ if (iptostring((struct sockaddr *) &remote, size, ipremoteport, IP_PORT_BUFLEN) == SASL_OK)
+ prp = ipremoteport;
+ else
+ mutt_debug(2, "SASL failed to parse remote IP address\n");
+ }
+ else
+ mutt_debug(2, "SASL failed to get remote IP address\n");
+
+ mutt_debug(2, "SASL local ip: %s, remote ip:%s\n", NONULL(plp), NONULL(prp));
+
+ rc = sasl_client_new(service, conn->account.host, plp, prp,
+ mutt_sasl_get_callbacks(&conn->account), 0, saslconn);
+
+ if (rc != SASL_OK)
+ {
+ mutt_error(_("Error allocating SASL connection"));
+ mutt_sleep(2);
+ return -1;
+ }
+
+ memset(&secprops, 0, sizeof(secprops));
+ /* Work around a casting bug in the SASL krb4 module */
+ secprops.max_ssf = 0x7fff;
+ secprops.maxbufsize = MUTT_SASL_MAXBUF;
+ if (sasl_setprop(*saslconn, SASL_SEC_PROPS, &secprops) != SASL_OK)
+ {
+ mutt_error(_("Error setting SASL security properties"));
+ return -1;
+ }
+
+ if (conn->ssf)
+ {
+ /* I'm not sure this actually has an effect, at least with SASLv2 */
+ mutt_debug(2, "External SSF: %d\n", conn->ssf);
+ if (sasl_setprop(*saslconn, SASL_SSF_EXTERNAL, &(conn->ssf)) != SASL_OK)
+ {
+ mutt_error(_("Error setting SASL external security strength"));
+ return -1;
+ }
+ }
+ if (conn->account.user[0])
+ {
+ mutt_debug(2, "External authentication name: %s\n", conn->account.user);
+ if (sasl_setprop(*saslconn, SASL_AUTH_EXTERNAL, conn->account.user) != SASL_OK)
+ {
+ mutt_error(_("Error setting SASL external user name"));
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
+int mutt_sasl_interact(sasl_interact_t *interaction)
+{
+ char prompt[SHORT_STRING];
+ char resp[SHORT_STRING];
+
+ while (interaction->id != SASL_CB_LIST_END)
+ {
+ mutt_debug(2, "mutt_sasl_interact: filling in SASL interaction %ld.\n",
+ interaction->id);
+
+ snprintf(prompt, sizeof(prompt), "%s: ", interaction->prompt);
+ resp[0] = '\0';
+ if (option(OPT_NO_CURSES) || mutt_get_field(prompt, resp, sizeof(resp), 0))
+ return SASL_FAIL;
+
+ interaction->len = mutt_strlen(resp) + 1;
+ interaction->result = safe_malloc(interaction->len);
+ memcpy((char *) interaction->result, resp, interaction->len);
+
+ interaction++;
+ }
+
+ return SASL_OK;
+}
/**
* mutt_sasl_setup_conn - Set up an SASL connection
/* common SASL helper routines */
-#ifndef _MUTT_SASL_H
-#define _MUTT_SASL_H
+#ifndef _CONN_SASL_H
+#define _CONN_SASL_H
#include <stddef.h>
-#include <time.h>
#include <sasl/sasl.h>
+#include <time.h>
struct Connection;
int (*msasl_poll)(struct Connection *conn, time_t wait_secs);
};
-#endif /* _MUTT_SASL_H */
+#endif /* _CONN_SASL_H */
#include "config.h"
#include <stdio.h>
-#include "lib/lib.h"
-#include "mutt_sasl_plain.h"
-#include "protos.h"
+#include "lib/base64.h"
+#include "lib/string2.h"
size_t mutt_sasl_plain_msg(char *buf, size_t buflen, const char *cmd,
const char *authz, const char *user, const char *pass)
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _MUTT_SASL_PLAIN_H
-#define _MUTT_SASL_PLAIN_H
+#ifndef _CONN_SASL_PLAIN_H
+#define _CONN_SASL_PLAIN_H
#include <stdlib.h>
size_t mutt_sasl_plain_msg(char *buf, size_t buflen, const char *cmd,
const char *authz, const char *user, const char *pass);
-#endif /* _MUTT_SASL_PLAIN_H */
+#endif /* _CONN_SASL_PLAIN_H */
--- /dev/null
+/**
+ * @file
+ * Low-level socket handling
+ *
+ * @authors
+ * Copyright (C) 1998,2000 Michael R. Elkins <me@mutt.org>
+ * Copyright (C) 1999-2006,2008 Brendan Cully <brendan@kublai.com>
+ * Copyright (C) 1999-2000 Tommi Komulainen <Tommi.Komulainen@iki.fi>
+ *
+ * @copyright
+ * This program 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 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program 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
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#include "config.h"
+#include <time.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <idna.h>
+#include <netdb.h>
+#include <netinet/in.h>
+#include <signal.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <sys/select.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <unistd.h>
+#include "lib/debug.h"
+#include "lib/memory.h"
+#include "lib/message.h"
+#include "lib/string2.h"
+#include "account.h"
+#include "conn_globals.h"
+#include "connection.h"
+#include "globals.h"
+#include "options.h"
+#include "protos.h"
+#ifdef USE_SSL
+#include "ssl.h"
+#endif
+
+static int socket_preconnect(void)
+{
+ int rc;
+ int save_errno;
+
+ if (mutt_strlen(Preconnect))
+ {
+ mutt_debug(2, "Executing preconnect: %s\n", Preconnect);
+ rc = mutt_system(Preconnect);
+ mutt_debug(2, "Preconnect result: %d\n", rc);
+ if (rc)
+ {
+ save_errno = errno;
+ mutt_perror(_("Preconnect command failed."));
+ mutt_sleep(1);
+
+ return save_errno;
+ }
+ }
+
+ return 0;
+}
+
+/**
+ * socket_connect - set up to connect to a socket fd
+ */
+static int socket_connect(int fd, struct sockaddr *sa)
+{
+ int sa_size;
+ int save_errno;
+ sigset_t set;
+
+ if (sa->sa_family == AF_INET)
+ sa_size = sizeof(struct sockaddr_in);
+#ifdef HAVE_GETADDRINFO
+ else if (sa->sa_family == AF_INET6)
+ sa_size = sizeof(struct sockaddr_in6);
+#endif
+ else
+ {
+ mutt_debug(1, "Unknown address family!\n");
+ return -1;
+ }
+
+ if (ConnectTimeout > 0)
+ alarm(ConnectTimeout);
+
+ mutt_allow_interrupt(1);
+
+ /* FreeBSD's connect() does not respect SA_RESTART, meaning
+ * a SIGWINCH will cause the connect to fail. */
+ sigemptyset(&set);
+ sigaddset(&set, SIGWINCH);
+ sigprocmask(SIG_BLOCK, &set, NULL);
+
+ save_errno = 0;
+
+ if (connect(fd, sa, sa_size) < 0)
+ {
+ save_errno = errno;
+ mutt_debug(2, "Connection failed. errno: %d...\n", errno);
+ SigInt = 0; /* reset in case we caught SIGINTR while in connect() */
+ }
+
+ if (ConnectTimeout > 0)
+ alarm(0);
+ mutt_allow_interrupt(0);
+ sigprocmask(SIG_UNBLOCK, &set, NULL);
+
+ return save_errno;
+}
+
+/**
+ * mutt_socket_open - Simple wrapper
+ */
+int mutt_socket_open(struct Connection *conn)
+{
+ int rc;
+
+ if (socket_preconnect())
+ return -1;
+
+ rc = conn->conn_open(conn);
+
+ mutt_debug(2, "Connected to %s:%d on fd=%d\n", NONULL(conn->account.host),
+ conn->account.port, conn->fd);
+
+ return rc;
+}
+
+int mutt_socket_close(struct Connection *conn)
+{
+ int rc = -1;
+
+ if (conn->fd < 0)
+ mutt_debug(1, "mutt_socket_close: Attempt to close closed connection.\n");
+ else
+ rc = conn->conn_close(conn);
+
+ conn->fd = -1;
+ conn->ssf = 0;
+
+ return rc;
+}
+
+int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
+{
+ int rc;
+ int sent = 0;
+
+ mutt_debug(dbg, "%d> %s", conn->fd, buf);
+
+ if (conn->fd < 0)
+ {
+ mutt_debug(1, "mutt_socket_write: attempt to write to closed connection\n");
+ return -1;
+ }
+
+ if (len < 0)
+ len = mutt_strlen(buf);
+
+ while (sent < len)
+ {
+ rc = conn->conn_write(conn, buf + sent, len - sent);
+ if (rc < 0)
+ {
+ mutt_debug(1, "mutt_socket_write: error writing (%s), closing socket\n",
+ strerror(errno));
+ mutt_socket_close(conn);
+
+ return -1;
+ }
+
+ if (rc < len - sent)
+ mutt_debug(3, "mutt_socket_write: short write (%d of %d bytes)\n", rc, len - sent);
+
+ sent += rc;
+ }
+
+ return sent;
+}
+
+/**
+ * mutt_socket_poll - poll whether reads would block
+ * @retval >0 There is data to read
+ * @retval 0 Read would block
+ * @retval -1 Connection doesn't support polling
+ */
+int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
+{
+ if (conn->bufpos < conn->available)
+ return conn->available - conn->bufpos;
+
+ if (conn->conn_poll)
+ return conn->conn_poll(conn, wait_secs);
+
+ return -1;
+}
+
+/**
+ * mutt_socket_readchar - simple read buffering to speed things up
+ */
+int mutt_socket_readchar(struct Connection *conn, char *c)
+{
+ if (conn->bufpos >= conn->available)
+ {
+ if (conn->fd >= 0)
+ conn->available = conn->conn_read(conn, conn->inbuf, sizeof(conn->inbuf));
+ else
+ {
+ mutt_debug(
+ 1, "mutt_socket_readchar: attempt to read from closed connection.\n");
+ return -1;
+ }
+ conn->bufpos = 0;
+ if (conn->available == 0)
+ {
+ mutt_error(_("Connection to %s closed"), conn->account.host);
+ mutt_sleep(2);
+ }
+ if (conn->available <= 0)
+ {
+ mutt_socket_close(conn);
+ return -1;
+ }
+ }
+ *c = conn->inbuf[conn->bufpos];
+ conn->bufpos++;
+ return 1;
+}
+
+int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
+{
+ char ch;
+ int i;
+
+ for (i = 0; i < buflen - 1; i++)
+ {
+ if (mutt_socket_readchar(conn, &ch) != 1)
+ {
+ buf[i] = '\0';
+ return -1;
+ }
+
+ if (ch == '\n')
+ break;
+ buf[i] = ch;
+ }
+
+ /* strip \r from \r\n termination */
+ if (i && buf[i - 1] == '\r')
+ i--;
+ buf[i] = '\0';
+
+ mutt_debug(dbg, "%d< %s\n", conn->fd, buf);
+
+ /* number of bytes read, not strlen */
+ return i + 1;
+}
+
+/**
+ * socket_new_conn - allocate and initialise a new connection
+ */
+struct Connection *socket_new_conn(void)
+{
+ struct Connection *conn = NULL;
+
+ conn = safe_calloc(1, sizeof(struct Connection));
+ conn->fd = -1;
+
+ return conn;
+}
+
+int raw_socket_close(struct Connection *conn)
+{
+ return close(conn->fd);
+}
+
+int raw_socket_read(struct Connection *conn, char *buf, size_t len)
+{
+ int rc;
+
+ mutt_allow_interrupt(1);
+ rc = read(conn->fd, buf, len);
+ if (rc == -1)
+ {
+ mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno));
+ mutt_sleep(2);
+ SigInt = 0;
+ }
+ mutt_allow_interrupt(0);
+
+ if (SigInt)
+ {
+ mutt_error(_("Connection to %s has been aborted"), conn->account.host);
+ mutt_sleep(2);
+ SigInt = 0;
+ rc = -1;
+ }
+
+ return rc;
+}
+
+int raw_socket_write(struct Connection *conn, const char *buf, size_t count)
+{
+ int rc;
+
+ mutt_allow_interrupt(1);
+ rc = write(conn->fd, buf, count);
+ if (rc == -1)
+ {
+ mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno));
+ mutt_sleep(2);
+ SigInt = 0;
+ }
+ mutt_allow_interrupt(0);
+
+ if (SigInt)
+ {
+ mutt_error(_("Connection to %s has been aborted"), conn->account.host);
+ mutt_sleep(2);
+ SigInt = 0;
+ rc = -1;
+ }
+
+ return rc;
+}
+
+int raw_socket_poll(struct Connection *conn, time_t wait_secs)
+{
+ fd_set rfds;
+ unsigned long wait_millis, post_t_millis;
+ struct timeval tv, pre_t, post_t;
+ int rv;
+
+ if (conn->fd < 0)
+ return -1;
+
+ wait_millis = wait_secs * 1000UL;
+
+ while (true)
+ {
+ tv.tv_sec = wait_millis / 1000;
+ tv.tv_usec = (wait_millis % 1000) * 1000;
+
+ FD_ZERO(&rfds);
+ FD_SET(conn->fd, &rfds);
+
+ gettimeofday(&pre_t, NULL);
+ rv = select(conn->fd + 1, &rfds, NULL, NULL, &tv);
+ gettimeofday(&post_t, NULL);
+
+ if (rv > 0 || (rv < 0 && errno != EINTR))
+ return rv;
+
+ if (SigInt)
+ mutt_query_exit();
+
+ wait_millis += (pre_t.tv_sec * 1000UL) + (pre_t.tv_usec / 1000);
+ post_t_millis = (post_t.tv_sec * 1000UL) + (post_t.tv_usec / 1000);
+ if (wait_millis <= post_t_millis)
+ return 0;
+ wait_millis -= post_t_millis;
+ }
+}
+
+int raw_socket_open(struct Connection *conn)
+{
+ int rc;
+ int fd;
+
+ char *host_idna = NULL;
+
+#ifdef HAVE_GETADDRINFO
+ /* --- IPv4/6 --- */
+
+ /* "65536\0" */
+ char port[6];
+ struct addrinfo hints;
+ struct addrinfo *res = NULL;
+ struct addrinfo *cur = NULL;
+
+ /* we accept v4 or v6 STREAM sockets */
+ memset(&hints, 0, sizeof(hints));
+
+ if (option(OPT_USE_IPV6))
+ hints.ai_family = AF_UNSPEC;
+ else
+ hints.ai_family = AF_INET;
+
+ hints.ai_socktype = SOCK_STREAM;
+
+ snprintf(port, sizeof(port), "%d", conn->account.port);
+
+#ifdef HAVE_LIBIDN
+ if (idna_to_ascii_lz(conn->account.host, &host_idna, 1) != IDNA_SUCCESS)
+ {
+ mutt_error(_("Bad IDN \"%s\"."), conn->account.host);
+ return -1;
+ }
+#else
+ host_idna = conn->account.host;
+#endif
+
+ if (!option(OPT_NO_CURSES))
+ mutt_message(_("Looking up %s..."), conn->account.host);
+
+ rc = getaddrinfo(host_idna, port, &hints, &res);
+
+#ifdef HAVE_LIBIDN
+ FREE(&host_idna);
+#endif
+
+ if (rc)
+ {
+ mutt_error(_("Could not find the host \"%s\""), conn->account.host);
+ mutt_sleep(2);
+ return -1;
+ }
+
+ if (!option(OPT_NO_CURSES))
+ mutt_message(_("Connecting to %s..."), conn->account.host);
+
+ rc = -1;
+ for (cur = res; cur != NULL; cur = cur->ai_next)
+ {
+ fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
+ if (fd >= 0)
+ {
+ rc = socket_connect(fd, cur->ai_addr);
+ if (rc == 0)
+ {
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ conn->fd = fd;
+ break;
+ }
+ else
+ close(fd);
+ }
+ }
+
+ freeaddrinfo(res);
+
+#else
+ /* --- IPv4 only --- */
+
+ struct sockaddr_in sin;
+ struct hostent *he = NULL;
+
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_port = htons(conn->account.port);
+ sin.sin_family = AF_INET;
+
+#ifdef HAVE_LIBIDN
+ if (idna_to_ascii_lz(conn->account.host, &host_idna, 1) != IDNA_SUCCESS)
+ {
+ mutt_error(_("Bad IDN \"%s\"."), conn->account.host);
+ return -1;
+ }
+#else
+ host_idna = conn->account.host;
+#endif
+
+ if (!option(OPT_NO_CURSES))
+ mutt_message(_("Looking up %s..."), conn->account.host);
+
+ he = gethostbyname(host_idna);
+
+#ifdef HAVE_LIBIDN
+ FREE(&host_idna);
+#endif
+
+ if (!he)
+ {
+ mutt_error(_("Could not find the host \"%s\""), conn->account.host);
+
+ return -1;
+ }
+
+ if (!option(OPT_NO_CURSES))
+ mutt_message(_("Connecting to %s..."), conn->account.host);
+
+ rc = -1;
+ for (int i = 0; he->h_addr_list[i] != NULL; i++)
+ {
+ memcpy(&sin.sin_addr, he->h_addr_list[i], he->h_length);
+ fd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
+
+ if (fd >= 0)
+ {
+ rc = socket_connect(fd, (struct sockaddr *) &sin);
+ if (rc == 0)
+ {
+ fcntl(fd, F_SETFD, FD_CLOEXEC);
+ conn->fd = fd;
+ break;
+ }
+ else
+ close(fd);
+ }
+ }
+
+#endif
+ if (rc)
+ {
+ mutt_error(_("Could not connect to %s (%s)."), conn->account.host,
+ (rc > 0) ? strerror(rc) : _("unknown error"));
+ mutt_sleep(2);
+ return -1;
+ }
+
+ return 0;
+}
--- /dev/null
+/**
+ * @file
+ * Low-level socket handling
+ *
+ * @authors
+ * Copyright (C) 1998 Brandon Long <blong@fiction.net>
+ * Copyright (C) 1999-2005 Brendan Cully <brendan@kublai.com>
+ *
+ * @copyright
+ * This program 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 2 of the License, or (at your option) any later
+ * version.
+ *
+ * This program 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
+ * this program. If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _CONN_SOCKET_H
+#define _CONN_SOCKET_H
+
+#include <stddef.h>
+#include <time.h>
+
+struct Connection;
+
+struct Connection *socket_new_conn(void);
+
+int mutt_socket_open(struct Connection *conn);
+int mutt_socket_close(struct Connection *conn);
+int mutt_socket_poll(struct Connection *conn, time_t wait_secs);
+int mutt_socket_readchar(struct Connection *conn, char *c);
+int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg);
+int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg);
+
+int raw_socket_read(struct Connection *conn, char *buf, size_t len);
+int raw_socket_write(struct Connection *conn, const char *buf, size_t count);
+int raw_socket_open(struct Connection *conn);
+int raw_socket_close(struct Connection *conn);
+int raw_socket_poll(struct Connection *conn, time_t wait_secs);
+
+#endif /* _CONN_SOCKET_H */
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
-#include "lib/lib.h"
-#include "mutt.h"
-#include "mutt_ssl.h"
+#include "lib/debug.h"
+#include "lib/file.h"
+#include "lib/memory.h"
+#include "lib/message.h"
+#include "lib/string2.h"
+#include "ssl.h"
#include "account.h"
-#include "globals.h"
+#include "connection.h"
+#include "conn_globals.h"
#include "keymap.h"
+#include "mutt.h"
+#include "mutt_account.h"
#include "mutt_idna.h"
#include "mutt_menu.h"
-#include "mutt_socket.h"
#include "opcodes.h"
#include "options.h"
#include "protos.h"
+#include "socket.h"
/* Just in case OpenSSL doesn't define DEVRANDOM */
#ifndef DEVRANDOM
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _MUTT_SSL_H
-#define _MUTT_SSL_H
+#ifndef _CONN_SSL_H
+#define _CONN_SSL_H
#ifdef USE_SSL
struct Connection;
int mutt_ssl_socket_setup(struct Connection *conn);
#endif
-#endif /* _MUTT_SSL_H */
+#endif /* _CONN_SSL_H */
#include <gnutls/gnutls.h>
#include <gnutls/x509.h>
#include <regex.h>
+#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/stat.h>
#include <time.h>
-#include "lib/lib.h"
+#include "lib/date.h"
+#include "lib/debug.h"
+#include "lib/file.h"
+#include "lib/memory.h"
+#include "lib/message.h"
+#include "lib/string2.h"
#include "mutt.h"
#include "account.h"
-#include "globals.h"
+#include "conn_globals.h"
+#include "connection.h"
#include "keymap.h"
+#include "mutt_account.h"
#include "mutt_menu.h"
#include "mutt_regex.h"
-#include "mutt_socket.h"
#include "opcodes.h"
#include "options.h"
#include "protos.h"
+#include "socket.h"
/* certificate error bitmap values */
#define CERTERR_VALID 0
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
+#include <time.h>
#include <unistd.h>
-#include "lib/lib.h"
+#include "lib/memory.h"
+#include "lib/message.h"
+#include "lib/string2.h"
#include "mutt.h"
-#include "mutt_tunnel.h"
+#include "tunnel.h"
#include "account.h"
-#include "globals.h"
-#include "mutt_socket.h"
+#include "conn_globals.h"
+#include "connection.h"
#include "protos.h"
+#include "socket.h"
/**
* struct TunnelData - A network tunnel (pair of sockets)
* this program. If not, see <http://www.gnu.org/licenses/>.
*/
-#ifndef _MUTT_TUNNEL_H
-#define _MUTT_TUNNEL_H
+#ifndef _CONN_TUNNEL_H
+#define _CONN_TUNNEL_H
struct Connection;
void mutt_tunnel_socket_setup(struct Connection *conn);
-#endif /* _MUTT_TUNNEL_H */
+#endif /* _CONN_TUNNEL_H */
#include <stdlib.h>
#include <string.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
#include "alias.h"
#include "body.h"
#include "mailbox.h"
#include "mutt_curses.h"
#include "mutt_menu.h"
-#include "mutt_socket.h"
#include "mutt_tags.h"
#include "mx.h"
#include "ncrypt/ncrypt.h"
WHERE char *MessageFormat;
#ifdef USE_SOCKET
-WHERE char *Preconnect;
-WHERE char *Tunnel;
WHERE short NetInc;
#endif /* USE_SOCKET */
#endif /* USE_SMTP */
WHERE char *SpoolFile;
WHERE char *SpamSeparator;
-#ifdef USE_SSL
-WHERE char *CertificateFile;
-WHERE char *SslClientCert;
-WHERE char *EntropyFile;
-WHERE char *SslCiphers;
-#ifdef USE_SSL_GNUTLS
-WHERE short SslMinDhPrimeBits;
-WHERE char *SslCaCertificatesFile;
-#endif
-#endif
WHERE struct MbTable *StatusChars;
WHERE char *StatusFormat;
WHERE char *Tmpdir;
WHERE char *DebugFile;
#endif
-WHERE short ConnectTimeout;
WHERE short History;
WHERE short MenuContext;
WHERE short PagerContext;
#include "config.h"
#include "imap_private.h"
#include "lib/lib.h"
-#include "account.h"
+#include "conn/conn.h"
#include "auth.h"
#include "globals.h"
+#include "mutt_account.h"
#include "mutt_socket.h"
#include "options.h"
#include "protos.h"
#include <string.h>
#include "imap_private.h"
#include "lib/lib.h"
-#include "account.h"
+#include "conn/conn.h"
#include "auth.h"
#include "globals.h"
+#include "mutt_account.h"
#include "mutt_socket.h"
#include "options.h"
#include "protos.h"
#include <string.h>
#include "imap_private.h"
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
-#include "account.h"
#include "auth.h"
#include "globals.h"
+#include "mutt_account.h"
#include "mutt_socket.h"
#include "options.h"
#include "protos.h"
#include <stdio.h>
#include "imap_private.h"
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
-#include "account.h"
#include "auth.h"
#include "globals.h"
+#include "mutt_account.h"
#include "mutt_socket.h"
#include "options.h"
#include "protos.h"
#include "config.h"
#include "imap_private.h"
#include "lib/lib.h"
-#include "account.h"
+#include "conn/conn.h"
#include "auth.h"
#include "globals.h"
-#include "mutt_sasl_plain.h"
+#include "mutt_account.h"
#include "mutt_socket.h"
#include "protos.h"
#include <string.h>
#include "imap_private.h"
#include "lib/lib.h"
-#include "account.h"
+#include "conn/conn.h"
#include "auth.h"
#include "globals.h"
-#include "mutt_sasl.h"
+#include "mutt_account.h"
#include "mutt_socket.h"
#include "options.h"
#include "protos.h"
#include "imap_private.h"
#include "lib/lib.h"
#include "mutt.h"
-#include "account.h"
#include "browser.h"
#include "buffy.h"
#include "context.h"
#include "globals.h"
#include "imap/imap.h"
+#include "mutt_account.h"
#include "mutt_regex.h"
#include "options.h"
#include "protos.h"
#include <time.h>
#include "imap_private.h"
#include "lib/lib.h"
-#include "account.h"
+#include "conn/conn.h"
#include "buffy.h"
#include "context.h"
#include "globals.h"
#include "imap/imap.h"
#include "mailbox.h"
#include "message.h"
+#include "mutt_account.h"
#include "mutt_menu.h"
#include "mutt_socket.h"
#include "mx.h"
#include <unistd.h>
#include "imap_private.h"
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
#include "imap.h"
-#include "account.h"
#include "bcache.h"
#include "body.h"
#include "buffy.h"
#include "imap/imap.h"
#include "mailbox.h"
#include "message.h"
+#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_socket.h"
#include "mutt_tags.h"
#ifdef USE_HCACHE
#include "hcache/hcache.h"
#endif
-#ifdef USE_SSL
-#include "mutt_ssl.h"
-#endif
/**
* check_capabilities - Make sure we can log in to this server
#include <stddef.h>
#include <sys/types.h>
-#include "account.h"
+#include "mutt_account.h"
struct Header;
struct Pattern;
#include <unistd.h>
#include "imap_private.h"
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
#include "message.h"
-#include "account.h"
#include "bcache.h"
#include "body.h"
#include "context.h"
#include "header.h"
#include "imap/imap.h"
#include "mailbox.h"
+#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_socket.h"
#include "mutt_tags.h"
#include <unistd.h>
#include "imap_private.h"
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
-#include "account.h"
#include "bcache.h"
#include "context.h"
#include "globals.h"
#include "imap/imap.h"
#include "mailbox.h"
#include "message.h"
+#include "mutt_account.h"
#include "mutt_socket.h"
#include "mx.h"
#include "options.h"
#include "options.h"
#include "protos.h"
#include "sort.h"
+#include "conn/conn.h"
#ifdef USE_LUA
#include "mutt_lua.h"
#endif
#include <sys/stat.h>
#include <unistd.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
#include "address.h"
#include "alias.h"
#ifdef USE_SIDEBAR
#include "sidebar.h"
#endif
-#ifdef USE_SASL
-#include "mutt_sasl.h"
-#endif
#ifdef USE_IMAP
#include "imap/imap.h"
#endif
#include <string.h>
#include "lib/lib.h"
#include "mutt.h"
-#include "account.h"
+#include "mutt_account.h"
#include "globals.h"
#include "options.h"
#include "protos.h"
#ifndef _MUTT_ACCOUNT_H
#define _MUTT_ACCOUNT_H
+#include "conn/conn.h"
+
struct Url;
/**
#define MUTT_ACCT_PASS (1 << 3)
#define MUTT_ACCT_SSL (1 << 4)
-/**
- * struct Account - Login details for a remote server
- */
-struct Account
-{
- char user[64];
- char login[64];
- char pass[256];
- char host[128];
- unsigned short port;
- unsigned char type;
- unsigned char flags;
-};
-
int mutt_account_match(const struct Account *a1, const struct Account *m2);
int mutt_account_fromurl(struct Account *account, struct Url *url);
void mutt_account_tourl(struct Account *account, struct Url *url);
/**
* @file
- * Low-level socket handling
+ * NeoMutt connections
*
* @authors
- * Copyright (C) 1998,2000 Michael R. Elkins <me@mutt.org>
- * Copyright (C) 1999-2006,2008 Brendan Cully <brendan@kublai.com>
- * Copyright (C) 1999-2000 Tommi Komulainen <Tommi.Komulainen@iki.fi>
+ * Copyright (C) 2000-2007 Brendan Cully <brendan@kublai.com>
*
* @copyright
* This program is free software: you can redistribute it and/or modify it under
*/
#include "config.h"
-#include <errno.h>
-#include <fcntl.h>
-#include <netdb.h>
-#include <netinet/in.h>
-#include <signal.h>
#include <stdio.h>
#include <string.h>
-#include <sys/select.h>
-#include <sys/socket.h>
-#include <sys/time.h>
-#include <unistd.h>
+#include "lib/lib.h"
+#include "lib/queue.h"
+#include "conn/conn.h"
#include "mutt_socket.h"
#include "globals.h"
-#include "mutt_idna.h"
-#include "mutt_tunnel.h"
-#include "options.h"
+#include "mutt_account.h"
#include "protos.h"
#include "url.h"
-#ifdef USE_SSL
-#include "mutt_ssl.h"
-#endif
/* support for multiple socket connections */
static struct ConnectionList Connections = TAILQ_HEAD_INITIALIZER(Connections);
-static int socket_preconnect(void)
-{
- int rc;
- int save_errno;
-
- if (mutt_strlen(Preconnect))
- {
- mutt_debug(2, "Executing preconnect: %s\n", Preconnect);
- rc = mutt_system(Preconnect);
- mutt_debug(2, "Preconnect result: %d\n", rc);
- if (rc)
- {
- save_errno = errno;
- mutt_perror(_("Preconnect command failed."));
- mutt_sleep(1);
-
- return save_errno;
- }
- }
-
- return 0;
-}
-
-/**
- * mutt_socket_open - Simple wrapper
- */
-int mutt_socket_open(struct Connection *conn)
-{
- int rc;
-
- if (socket_preconnect())
- return -1;
-
- rc = conn->conn_open(conn);
-
- mutt_debug(2, "Connected to %s:%d on fd=%d\n", NONULL(conn->account.host),
- conn->account.port, conn->fd);
-
- return rc;
-}
-
-int mutt_socket_close(struct Connection *conn)
-{
- int rc = -1;
-
- if (conn->fd < 0)
- mutt_debug(1, "mutt_socket_close: Attempt to close closed connection.\n");
- else
- rc = conn->conn_close(conn);
-
- conn->fd = -1;
- conn->ssf = 0;
-
- return rc;
-}
-
-int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg)
-{
- int rc;
- int sent = 0;
-
- mutt_debug(dbg, "%d> %s", conn->fd, buf);
-
- if (conn->fd < 0)
- {
- mutt_debug(1, "mutt_socket_write: attempt to write to closed connection\n");
- return -1;
- }
-
- if (len < 0)
- len = mutt_strlen(buf);
-
- while (sent < len)
- {
- rc = conn->conn_write(conn, buf + sent, len - sent);
- if (rc < 0)
- {
- mutt_debug(1, "mutt_socket_write: error writing (%s), closing socket\n",
- strerror(errno));
- mutt_socket_close(conn);
-
- return -1;
- }
-
- if (rc < len - sent)
- mutt_debug(3, "mutt_socket_write: short write (%d of %d bytes)\n", rc, len - sent);
-
- sent += rc;
- }
-
- return sent;
-}
-
-/**
- * mutt_socket_poll - poll whether reads would block
- * @retval >0 There is data to read
- * @retval 0 Read would block
- * @retval -1 Connection doesn't support polling
- */
-int mutt_socket_poll(struct Connection *conn, time_t wait_secs)
-{
- if (conn->bufpos < conn->available)
- return conn->available - conn->bufpos;
-
- if (conn->conn_poll)
- return conn->conn_poll(conn, wait_secs);
-
- return -1;
-}
-
-/**
- * mutt_socket_readchar - simple read buffering to speed things up
- */
-int mutt_socket_readchar(struct Connection *conn, char *c)
-{
- if (conn->bufpos >= conn->available)
- {
- if (conn->fd >= 0)
- conn->available = conn->conn_read(conn, conn->inbuf, sizeof(conn->inbuf));
- else
- {
- mutt_debug(
- 1, "mutt_socket_readchar: attempt to read from closed connection.\n");
- return -1;
- }
- conn->bufpos = 0;
- if (conn->available == 0)
- {
- mutt_error(_("Connection to %s closed"), conn->account.host);
- mutt_sleep(2);
- }
- if (conn->available <= 0)
- {
- mutt_socket_close(conn);
- return -1;
- }
- }
- *c = conn->inbuf[conn->bufpos];
- conn->bufpos++;
- return 1;
-}
-
-int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg)
-{
- char ch;
- int i;
-
- for (i = 0; i < buflen - 1; i++)
- {
- if (mutt_socket_readchar(conn, &ch) != 1)
- {
- buf[i] = '\0';
- return -1;
- }
-
- if (ch == '\n')
- break;
- buf[i] = ch;
- }
-
- /* strip \r from \r\n termination */
- if (i && buf[i - 1] == '\r')
- i--;
- buf[i] = '\0';
-
- mutt_debug(dbg, "%d< %s\n", conn->fd, buf);
-
- /* number of bytes read, not strlen */
- return i + 1;
-}
-
struct ConnectionList *mutt_socket_head(void)
{
return &Connections;
}
}
-/**
- * socket_new_conn - allocate and initialise a new connection
- */
-static struct Connection *socket_new_conn(void)
-{
- struct Connection *conn = NULL;
-
- conn = safe_calloc(1, sizeof(struct Connection));
- conn->fd = -1;
-
- return conn;
-}
-
/**
* mutt_conn_find - Find a connection from a list
*
return conn;
}
-
-int raw_socket_close(struct Connection *conn)
-{
- return close(conn->fd);
-}
-
-int raw_socket_read(struct Connection *conn, char *buf, size_t len)
-{
- int rc;
-
- mutt_allow_interrupt(1);
- rc = read(conn->fd, buf, len);
- if (rc == -1)
- {
- mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno));
- mutt_sleep(2);
- SigInt = 0;
- }
- mutt_allow_interrupt(0);
-
- if (SigInt)
- {
- mutt_error(_("Connection to %s has been aborted"), conn->account.host);
- mutt_sleep(2);
- SigInt = 0;
- rc = -1;
- }
-
- return rc;
-}
-
-int raw_socket_write(struct Connection *conn, const char *buf, size_t count)
-{
- int rc;
-
- mutt_allow_interrupt(1);
- rc = write(conn->fd, buf, count);
- if (rc == -1)
- {
- mutt_error(_("Error talking to %s (%s)"), conn->account.host, strerror(errno));
- mutt_sleep(2);
- SigInt = 0;
- }
- mutt_allow_interrupt(0);
-
- if (SigInt)
- {
- mutt_error(_("Connection to %s has been aborted"), conn->account.host);
- mutt_sleep(2);
- SigInt = 0;
- rc = -1;
- }
-
- return rc;
-}
-
-int raw_socket_poll(struct Connection *conn, time_t wait_secs)
-{
- fd_set rfds;
- unsigned long wait_millis, post_t_millis;
- struct timeval tv, pre_t, post_t;
- int rv;
-
- if (conn->fd < 0)
- return -1;
-
- wait_millis = wait_secs * 1000UL;
-
- while (true)
- {
- tv.tv_sec = wait_millis / 1000;
- tv.tv_usec = (wait_millis % 1000) * 1000;
-
- FD_ZERO(&rfds);
- FD_SET(conn->fd, &rfds);
-
- gettimeofday(&pre_t, NULL);
- rv = select(conn->fd + 1, &rfds, NULL, NULL, &tv);
- gettimeofday(&post_t, NULL);
-
- if (rv > 0 || (rv < 0 && errno != EINTR))
- return rv;
-
- if (SigInt)
- mutt_query_exit();
-
- wait_millis += (pre_t.tv_sec * 1000UL) + (pre_t.tv_usec / 1000);
- post_t_millis = (post_t.tv_sec * 1000UL) + (post_t.tv_usec / 1000);
- if (wait_millis <= post_t_millis)
- return 0;
- wait_millis -= post_t_millis;
- }
-}
-
-/**
- * socket_connect - set up to connect to a socket fd
- */
-static int socket_connect(int fd, struct sockaddr *sa)
-{
- int sa_size;
- int save_errno;
- sigset_t set;
-
- if (sa->sa_family == AF_INET)
- sa_size = sizeof(struct sockaddr_in);
-#ifdef HAVE_GETADDRINFO
- else if (sa->sa_family == AF_INET6)
- sa_size = sizeof(struct sockaddr_in6);
-#endif
- else
- {
- mutt_debug(1, "Unknown address family!\n");
- return -1;
- }
-
- if (ConnectTimeout > 0)
- alarm(ConnectTimeout);
-
- mutt_allow_interrupt(1);
-
- /* FreeBSD's connect() does not respect SA_RESTART, meaning
- * a SIGWINCH will cause the connect to fail. */
- sigemptyset(&set);
- sigaddset(&set, SIGWINCH);
- sigprocmask(SIG_BLOCK, &set, NULL);
-
- save_errno = 0;
-
- if (connect(fd, sa, sa_size) < 0)
- {
- save_errno = errno;
- mutt_debug(2, "Connection failed. errno: %d...\n", errno);
- SigInt = 0; /* reset in case we caught SIGINTR while in connect() */
- }
-
- if (ConnectTimeout > 0)
- alarm(0);
- mutt_allow_interrupt(0);
- sigprocmask(SIG_UNBLOCK, &set, NULL);
-
- return save_errno;
-}
-
-int raw_socket_open(struct Connection *conn)
-{
- int rc;
- int fd;
-
- char *host_idna = NULL;
-
-#ifdef HAVE_GETADDRINFO
- /* --- IPv4/6 --- */
-
- /* "65536\0" */
- char port[6];
- struct addrinfo hints;
- struct addrinfo *res = NULL;
- struct addrinfo *cur = NULL;
-
- /* we accept v4 or v6 STREAM sockets */
- memset(&hints, 0, sizeof(hints));
-
- if (option(OPT_USE_IPV6))
- hints.ai_family = AF_UNSPEC;
- else
- hints.ai_family = AF_INET;
-
- hints.ai_socktype = SOCK_STREAM;
-
- snprintf(port, sizeof(port), "%d", conn->account.port);
-
-#ifdef HAVE_LIBIDN
- if (idna_to_ascii_lz(conn->account.host, &host_idna, 1) != IDNA_SUCCESS)
- {
- mutt_error(_("Bad IDN \"%s\"."), conn->account.host);
- return -1;
- }
-#else
- host_idna = conn->account.host;
-#endif
-
- if (!option(OPT_NO_CURSES))
- mutt_message(_("Looking up %s..."), conn->account.host);
-
- rc = getaddrinfo(host_idna, port, &hints, &res);
-
-#ifdef HAVE_LIBIDN
- FREE(&host_idna);
-#endif
-
- if (rc)
- {
- mutt_error(_("Could not find the host \"%s\""), conn->account.host);
- mutt_sleep(2);
- return -1;
- }
-
- if (!option(OPT_NO_CURSES))
- mutt_message(_("Connecting to %s..."), conn->account.host);
-
- rc = -1;
- for (cur = res; cur != NULL; cur = cur->ai_next)
- {
- fd = socket(cur->ai_family, cur->ai_socktype, cur->ai_protocol);
- if (fd >= 0)
- {
- rc = socket_connect(fd, cur->ai_addr);
- if (rc == 0)
- {
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- conn->fd = fd;
- break;
- }
- else
- close(fd);
- }
- }
-
- freeaddrinfo(res);
-
-#else
- /* --- IPv4 only --- */
-
- struct sockaddr_in sin;
- struct hostent *he = NULL;
-
- memset(&sin, 0, sizeof(sin));
- sin.sin_port = htons(conn->account.port);
- sin.sin_family = AF_INET;
-
-#ifdef HAVE_LIBIDN
- if (idna_to_ascii_lz(conn->account.host, &host_idna, 1) != IDNA_SUCCESS)
- {
- mutt_error(_("Bad IDN \"%s\"."), conn->account.host);
- return -1;
- }
-#else
- host_idna = conn->account.host;
-#endif
-
- if (!option(OPT_NO_CURSES))
- mutt_message(_("Looking up %s..."), conn->account.host);
-
- he = gethostbyname(host_idna);
-
-#ifdef HAVE_LIBIDN
- FREE(&host_idna);
-#endif
-
- if (!he)
- {
- mutt_error(_("Could not find the host \"%s\""), conn->account.host);
-
- return -1;
- }
-
- if (!option(OPT_NO_CURSES))
- mutt_message(_("Connecting to %s..."), conn->account.host);
-
- rc = -1;
- for (int i = 0; he->h_addr_list[i] != NULL; i++)
- {
- memcpy(&sin.sin_addr, he->h_addr_list[i], he->h_length);
- fd = socket(PF_INET, SOCK_STREAM, IPPROTO_IP);
-
- if (fd >= 0)
- {
- rc = socket_connect(fd, (struct sockaddr *) &sin);
- if (rc == 0)
- {
- fcntl(fd, F_SETFD, FD_CLOEXEC);
- conn->fd = fd;
- break;
- }
- else
- close(fd);
- }
- }
-
-#endif
- if (rc)
- {
- mutt_error(_("Could not connect to %s (%s)."), conn->account.host,
- (rc > 0) ? strerror(rc) : _("unknown error"));
- mutt_sleep(2);
- return -1;
- }
-
- return 0;
-}
/**
* @file
- * Low-level socket handling
+ * NeoMutt connections
*
* @authors
- * Copyright (C) 1998 Brandon Long <blong@fiction.net>
- * Copyright (C) 1999-2005 Brendan Cully <brendan@kublai.com>
+ * Copyright (C) 2000-2007 Brendan Cully <brendan@kublai.com>
*
* @copyright
* This program is free software: you can redistribute it and/or modify it under
#ifndef _MUTT_SOCKET_H
#define _MUTT_SOCKET_H
-#include <stddef.h>
-#include "account.h"
-#include "lib/lib.h"
+#include "lib/queue.h"
+#include "conn/conn.h"
+
+struct Account;
/* logging levels */
#define MUTT_SOCK_LOG_CMD 2
*/
TAILQ_HEAD(ConnectionList, Connection);
-/**
- * struct Connection - An open network connection (socket)
- */
-struct Connection
-{
- struct Account account;
- unsigned int ssf; /**< security strength factor, in bits */
- void *data;
-
- char inbuf[LONG_STRING];
- int bufpos;
-
- int fd;
- int available;
-
- TAILQ_ENTRY(Connection) entries;
-
- void *sockdata;
- int (*conn_read)(struct Connection *conn, char *buf, size_t len);
- int (*conn_write)(struct Connection *conn, const char *buf, size_t count);
- int (*conn_open)(struct Connection *conn);
- int (*conn_close)(struct Connection *conn);
- int (*conn_poll)(struct Connection *conn, time_t wait_secs);
-};
-
-int mutt_socket_open(struct Connection *conn);
-int mutt_socket_close(struct Connection *conn);
-int mutt_socket_poll(struct Connection *conn, time_t wait_secs);
-int mutt_socket_readchar(struct Connection *conn, char *c);
-#define mutt_socket_readln(A, B, C) mutt_socket_readln_d(A, B, C, MUTT_SOCK_LOG_CMD)
-int mutt_socket_readln_d(char *buf, size_t buflen, struct Connection *conn, int dbg);
-#define mutt_socket_write(A, B) mutt_socket_write_d(A, B, -1, MUTT_SOCK_LOG_CMD)
-#define mutt_socket_write_n(A, B, C) mutt_socket_write_d(A, B, C, MUTT_SOCK_LOG_CMD)
-int mutt_socket_write_d(struct Connection *conn, const char *buf, int len, int dbg);
-
/* stupid hack for imap_logout_all */
struct ConnectionList *mutt_socket_head(void);
void mutt_socket_free(struct Connection *conn);
struct Connection *mutt_conn_find(const struct Connection *start, const struct Account *account);
-int raw_socket_read(struct Connection *conn, char *buf, size_t len);
-int raw_socket_write(struct Connection *conn, const char *buf, size_t count);
-int raw_socket_open(struct Connection *conn);
-int raw_socket_close(struct Connection *conn);
-int raw_socket_poll(struct Connection *conn, time_t wait_secs);
+#define mutt_socket_readln(A, B, C) mutt_socket_readln_d(A, B, C, MUTT_SOCK_LOG_CMD)
+#define mutt_socket_write(A, B) mutt_socket_write_d(A, B, -1, MUTT_SOCK_LOG_CMD)
+#define mutt_socket_write_n(A, B, C) mutt_socket_write_d(A, B, C, MUTT_SOCK_LOG_CMD)
#endif /* _MUTT_SOCKET_H */
#include <time.h>
#include <unistd.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
-#include "account.h"
#include "bcache.h"
#include "context.h"
#include "format_flags.h"
#include "globals.h"
#include "header.h"
+#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_socket.h"
#include "mx.h"
#include <string.h>
#include <unistd.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
#include "nntp.h"
-#include "account.h"
#include "bcache.h"
#include "body.h"
#include "context.h"
#include "globals.h"
#include "header.h"
#include "mailbox.h"
+#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_socket.h"
#include "mx.h"
#include "protos.h"
#include "thread.h"
#include "url.h"
-#ifdef USE_SSL
-#include "mutt_ssl.h"
-#endif
#ifdef USE_HCACHE
#include "hcache/hcache.h"
#endif
#ifdef USE_SASL
#include <sasl/sasl.h>
#include <sasl/saslutil.h>
-#include "mutt_sasl.h"
#endif
static int nntp_connect_error(struct NntpServer *nserv)
-account.c
addrbook.c
alias.c
attach.c
complete.c
compose.c
compress.c
+conn/conn_globals.c
+conn/getdomain.c
+conn/sasl.c
+conn/sasl_plain.c
+conn/socket.c
+conn/ssl.c
+conn/ssl_gnutls.c
+conn/tunnel.c
copy.c
-ncrypt/crypt.c
-ncrypt/cryptglue.c
-ncrypt/crypt_mod.c
curs_lib.c
curs_main.c
doc/makedoc.c
filter.c
flags.c
from.c
-getdomain.c
group.c
handler.c
hcache/bdb.c
lib/file.c
lib/hash.c
lib/list.c
+lib/mapping.c
lib/md5.c
lib/memory.c
lib/message.c
menu.c
mh.c
muttlib.c
+mutt_account.c
mutt_idna.c
mutt_lua.c
mutt_notmuch.c
-mutt_sasl.c
-mutt_sasl_plain.c
mutt_socket.c
-mutt_ssl.c
-mutt_ssl_gnutls.c
-mutt_tunnel.c
+mutt_tags.c
mx.c
+ncrypt/crypt.c
+ncrypt/cryptglue.c
ncrypt/crypt_gpgme.c
+ncrypt/crypt_mod.c
ncrypt/crypt_mod_pgp_classic.c
ncrypt/crypt_mod_pgp_gpgme.c
ncrypt/crypt_mod_smime_classic.c
#include <string.h>
#include <unistd.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
#include "pop.h"
-#include "account.h"
#include "bcache.h"
#include "body.h"
#include "context.h"
#include "globals.h"
#include "header.h"
#include "mailbox.h"
+#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_socket.h"
#include "mx.h"
#include <stdio.h>
#include <string.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
-#include "account.h"
#include "globals.h"
+#include "mutt_account.h"
#include "mutt_socket.h"
#include "options.h"
#include "pop.h"
#ifdef USE_SASL
#include <sasl/sasl.h>
#include <sasl/saslutil.h>
-#include "mutt_sasl.h"
#endif
#ifdef USE_SASL
#include <stdlib.h>
#include <string.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
-#include "account.h"
#include "context.h"
#include "globals.h"
#include "header.h"
+#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_socket.h"
#include "options.h"
#include "pop.h"
#include "protos.h"
#include "url.h"
-#ifdef USE_SSL
-#include "mutt_ssl.h"
-#endif
/**
* pop_parse_path - Parse a POP mailbox name
#include <sys/stat.h>
#include <unistd.h>
#include "lib/lib.h"
+#include "conn/conn.h"
#include "mutt.h"
-#include "account.h"
#include "address.h"
#include "globals.h"
+#include "mutt_account.h"
#include "mutt_curses.h"
#include "mutt_socket.h"
#include "options.h"
#include "protos.h"
#include "url.h"
-#ifdef USE_SSL
-#include "mutt_ssl.h"
-#endif
#ifdef USE_SASL
#include <sasl/sasl.h>
#include <sasl/saslutil.h>
-#include "mutt_sasl.h"
-#else
-#include "mutt_sasl_plain.h"
#endif
#define smtp_success(x) ((x) / 100 == 2)