From: Richard Russon Date: Sat, 28 Oct 2017 14:24:44 +0000 (+0100) Subject: build: Create a Connection Library (libconn) X-Git-Tag: neomutt-20171208~70 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=f2b81bd35527d40eaff547635aa3d69eff54fe95;p=neomutt build: Create a Connection Library (libconn) There are no changes to the code, just rearrangements of functions. --- diff --git a/.clang-format b/.clang-format index a1e7be2a8..45aef4e95 100644 --- a/.clang-format +++ b/.clang-format @@ -18,6 +18,8 @@ IncludeCategories: Priority: -6 - Regex: '"lib/.*\.h"' Priority: -4 + - Regex: '"conn/.*\.h"' + Priority: -3 - Regex: '"mutt\.h"' Priority: -2 # Main Header 0 diff --git a/Makefile.am b/Makefile.am index ee8c5975e..2da83a2f1 100644 --- a/Makefile.am +++ b/Makefile.am @@ -22,7 +22,7 @@ AM_DISTCHECK_CONFIGURE_FLAGS = \ --with-sasl \ --with-tokyocabinet -SUBDIRS = m4 contrib imap ncrypt lib +SUBDIRS = m4 contrib imap ncrypt lib conn if BUILD_HCACHE SUBDIRS += hcache @@ -42,15 +42,15 @@ BUILT_SOURCES = conststrings.c git_ver.h 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 \ @@ -62,13 +62,16 @@ nodist_neomutt_SOURCES = $(BUILT_SOURCES) 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)\" \ @@ -77,7 +80,7 @@ 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 \ @@ -86,8 +89,8 @@ 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 diff --git a/Makefile.autosetup b/Makefile.autosetup index 33ab69cd1..b304d2504 100644 --- a/Makefile.autosetup +++ b/Makefile.autosetup @@ -53,14 +53,14 @@ ALL_FILES!= (cd $(SRCDIR) && git ls-tree -r --name-only HEAD 2>/dev/null) \ ############################################################################### # 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 \ @@ -75,21 +75,12 @@ NEOMUTTOBJS+= wcscasecmp.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 @@ -143,6 +134,24 @@ CLEANFILES+= $(LIBIMAP) $(LIBIMAPOBJS) 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 @@ -224,6 +233,13 @@ $(LIBIMAP): $(PWD)/imap $(LIBIMAPOBJS) $(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) diff --git a/bcache.c b/bcache.c index 3624aa45e..a29c87f67 100644 --- a/bcache.c +++ b/bcache.c @@ -31,8 +31,8 @@ #include #include "lib/lib.h" #include "bcache.h" -#include "account.h" #include "globals.h" +#include "mutt_account.h" #include "protos.h" #include "url.h" diff --git a/browser.c b/browser.c index f3652b192..9d9a0d9e2 100644 --- a/browser.c +++ b/browser.c @@ -40,8 +40,8 @@ #include #include #include "lib/lib.h" +#include "conn/conn.h" #include "mutt.h" -#include "account.h" #include "attach.h" #include "body.h" #include "browser.h" @@ -53,10 +53,10 @@ #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" diff --git a/compose.c b/compose.c index b91ab0dc9..08f13dbea 100644 --- a/compose.c +++ b/compose.c @@ -33,6 +33,7 @@ #include #include #include "lib/lib.h" +#include "conn/conn.h" #include "mutt.h" #include "alias.h" #include "attach.h" @@ -49,7 +50,6 @@ #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" diff --git a/configure.ac b/configure.ac index fec9cc41f..2bf28c57c 100644 --- a/configure.ac +++ b/configure.ac @@ -532,10 +532,10 @@ AC_ARG_WITH(ssl, AS_HELP_STRING([--with-ssl@<:@=PFX@:>@],[Enable TLS support usi 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"]) @@ -563,10 +563,10 @@ if test "$gnutls_prefix" != "no" && test x"$need_ssl" != xyes; then 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]), [ @@ -581,8 +581,6 @@ AC_ARG_WITH(sasl, AS_HELP_STRING([--with-sasl@<:@=PFX@:>@],[Use SASL network sec 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 @@ -948,7 +946,7 @@ if test x$full_doc != xno; then 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: diff --git a/conn/Makefile.am b/conn/Makefile.am new file mode 100644 index 000000000..46cf6d60d --- /dev/null +++ b/conn/Makefile.am @@ -0,0 +1,23 @@ +## 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 + diff --git a/conn/account.h b/conn/account.h new file mode 100644 index 000000000..467f9664a --- /dev/null +++ b/conn/account.h @@ -0,0 +1,40 @@ +/** + * @file + * Account object + * + * @authors + * Copyright (C) 2000-2005,2008 Brendan Cully + * + * @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 . + */ + +#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 */ diff --git a/conn/conn.h b/conn/conn.h new file mode 100644 index 000000000..19af3420d --- /dev/null +++ b/conn/conn.h @@ -0,0 +1,39 @@ +/** + * @file + * Connection Library + * + * @authors + * Copyright (C) 2017 Richard Russon + * + * @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 . + */ + +#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 */ diff --git a/conn/conn_globals.c b/conn/conn_globals.c new file mode 100644 index 000000000..bc137b54b --- /dev/null +++ b/conn/conn_globals.c @@ -0,0 +1,41 @@ +/** + * @file + * Connection Global Variables + * + * @authors + * Copyright (C) 2017 Richard Russon + * + * @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 . + */ + +#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 */ diff --git a/conn/conn_globals.h b/conn/conn_globals.h new file mode 100644 index 000000000..dbcf7e438 --- /dev/null +++ b/conn/conn_globals.h @@ -0,0 +1,44 @@ +/** + * @file + * Connection Global Variables + * + * @authors + * Copyright (C) 2017 Richard Russon + * + * @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 . + */ + +#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 */ diff --git a/conn/connection.h b/conn/connection.h new file mode 100644 index 000000000..cfa079054 --- /dev/null +++ b/conn/connection.h @@ -0,0 +1,59 @@ +/** + * @file + * An open network connection (socket) + * + * @authors + * Copyright (C) 1998 Brandon Long + * Copyright (C) 1999-2005 Brendan Cully + * + * @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 . + */ + +#ifndef _CONN_CONNECTION_H +#define _CONN_CONNECTION_H + +#include +#include +#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 */ diff --git a/getdomain.c b/conn/getdomain.c similarity index 97% rename from getdomain.c rename to conn/getdomain.c index ff4baeace..f471a07a5 100644 --- a/getdomain.c +++ b/conn/getdomain.c @@ -26,7 +26,9 @@ #include #include #include -#include "lib/lib.h" +#include "lib/debug.h" +#include "lib/memory.h" +#include "lib/string2.h" int getdnsdomainname(char *d, size_t len) { diff --git a/mutt_sasl.c b/conn/sasl.c similarity index 98% rename from mutt_sasl.c rename to conn/sasl.c index ef92ea8a3..6b530a54c 100644 --- a/mutt_sasl.c +++ b/conn/sasl.c @@ -21,21 +21,50 @@ */ /* 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 #include #include +#include #include #include #include -#include "lib/lib.h" -#include "mutt_sasl.h" +#include +#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; @@ -84,17 +113,6 @@ static int getnameinfo_err(int ret) 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 * @@ -269,139 +287,6 @@ static sasl_callback_t *mutt_sasl_get_callbacks(struct Account *account) 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 * @@ -573,18 +458,138 @@ static int mutt_sasl_conn_poll(struct Connection *conn, time_t wait_secs) 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 diff --git a/mutt_sasl.h b/conn/sasl.h similarity index 96% rename from mutt_sasl.h rename to conn/sasl.h index e1a390209..19e593675 100644 --- a/mutt_sasl.h +++ b/conn/sasl.h @@ -22,12 +22,12 @@ /* common SASL helper routines */ -#ifndef _MUTT_SASL_H -#define _MUTT_SASL_H +#ifndef _CONN_SASL_H +#define _CONN_SASL_H #include -#include #include +#include struct Connection; @@ -59,4 +59,4 @@ struct SaslData int (*msasl_poll)(struct Connection *conn, time_t wait_secs); }; -#endif /* _MUTT_SASL_H */ +#endif /* _CONN_SASL_H */ diff --git a/mutt_sasl_plain.c b/conn/sasl_plain.c similarity index 95% rename from mutt_sasl_plain.c rename to conn/sasl_plain.c index d3c71d6a5..2cca94842 100644 --- a/mutt_sasl_plain.c +++ b/conn/sasl_plain.c @@ -22,9 +22,8 @@ #include "config.h" #include -#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) diff --git a/mutt_sasl_plain.h b/conn/sasl_plain.h similarity index 95% rename from mutt_sasl_plain.h rename to conn/sasl_plain.h index 4413363a5..a919de9ff 100644 --- a/mutt_sasl_plain.h +++ b/conn/sasl_plain.h @@ -20,8 +20,8 @@ * this program. If not, see . */ -#ifndef _MUTT_SASL_PLAIN_H -#define _MUTT_SASL_PLAIN_H +#ifndef _CONN_SASL_PLAIN_H +#define _CONN_SASL_PLAIN_H #include @@ -45,4 +45,4 @@ 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 */ diff --git a/conn/socket.c b/conn/socket.c new file mode 100644 index 000000000..a49a8137f --- /dev/null +++ b/conn/socket.c @@ -0,0 +1,526 @@ +/** + * @file + * Low-level socket handling + * + * @authors + * Copyright (C) 1998,2000 Michael R. Elkins + * Copyright (C) 1999-2006,2008 Brendan Cully + * Copyright (C) 1999-2000 Tommi Komulainen + * + * @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 . + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; +} diff --git a/conn/socket.h b/conn/socket.h new file mode 100644 index 000000000..2dcc20bf9 --- /dev/null +++ b/conn/socket.h @@ -0,0 +1,47 @@ +/** + * @file + * Low-level socket handling + * + * @authors + * Copyright (C) 1998 Brandon Long + * Copyright (C) 1999-2005 Brendan Cully + * + * @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 . + */ + +#ifndef _CONN_SOCKET_H +#define _CONN_SOCKET_H + +#include +#include + +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 */ diff --git a/mutt_ssl.c b/conn/ssl.c similarity index 99% rename from mutt_ssl.c rename to conn/ssl.c index 3ef4caf60..8701670cd 100644 --- a/mutt_ssl.c +++ b/conn/ssl.c @@ -41,18 +41,24 @@ #include #include #include -#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 diff --git a/mutt_ssl.h b/conn/ssl.h similarity index 93% rename from mutt_ssl.h rename to conn/ssl.h index 9aa27bb94..c14ccf746 100644 --- a/mutt_ssl.h +++ b/conn/ssl.h @@ -20,8 +20,8 @@ * this program. If not, see . */ -#ifndef _MUTT_SSL_H -#define _MUTT_SSL_H +#ifndef _CONN_SSL_H +#define _CONN_SSL_H #ifdef USE_SSL struct Connection; @@ -30,4 +30,4 @@ int mutt_ssl_starttls(struct Connection *conn); int mutt_ssl_socket_setup(struct Connection *conn); #endif -#endif /* _MUTT_SSL_H */ +#endif /* _CONN_SSL_H */ diff --git a/mutt_ssl_gnutls.c b/conn/ssl_gnutls.c similarity index 99% rename from mutt_ssl_gnutls.c rename to conn/ssl_gnutls.c index c6d0a1311..9712d4da1 100644 --- a/mutt_ssl_gnutls.c +++ b/conn/ssl_gnutls.c @@ -25,22 +25,30 @@ #include #include #include +#include #include #include #include #include #include -#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 diff --git a/mutt_tunnel.c b/conn/tunnel.c similarity index 96% rename from mutt_tunnel.c rename to conn/tunnel.c index 282a908ba..a03891384 100644 --- a/mutt_tunnel.c +++ b/conn/tunnel.c @@ -29,14 +29,18 @@ #include #include #include +#include #include -#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) diff --git a/mutt_tunnel.h b/conn/tunnel.h similarity index 91% rename from mutt_tunnel.h rename to conn/tunnel.h index 82abc8ac1..0332f6f0b 100644 --- a/mutt_tunnel.h +++ b/conn/tunnel.h @@ -18,11 +18,11 @@ * this program. If not, see . */ -#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 */ diff --git a/curs_main.c b/curs_main.c index 7c4d7db86..970a30891 100644 --- a/curs_main.c +++ b/curs_main.c @@ -32,6 +32,7 @@ #include #include #include "lib/lib.h" +#include "conn/conn.h" #include "mutt.h" #include "alias.h" #include "body.h" @@ -45,7 +46,6 @@ #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" diff --git a/globals.h b/globals.h index 23421a15f..5fd8e97ba 100644 --- a/globals.h +++ b/globals.h @@ -105,8 +105,6 @@ WHERE char *MimeTypeQueryCommand; WHERE char *MessageFormat; #ifdef USE_SOCKET -WHERE char *Preconnect; -WHERE char *Tunnel; WHERE short NetInc; #endif /* USE_SOCKET */ @@ -167,16 +165,6 @@ WHERE char *SmtpUrl; #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; @@ -241,7 +229,6 @@ WHERE short DebugLevel; WHERE char *DebugFile; #endif -WHERE short ConnectTimeout; WHERE short History; WHERE short MenuContext; WHERE short PagerContext; diff --git a/imap/auth_anon.c b/imap/auth_anon.c index 802f47e5d..de33b7f66 100644 --- a/imap/auth_anon.c +++ b/imap/auth_anon.c @@ -33,9 +33,10 @@ #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" diff --git a/imap/auth_cram.c b/imap/auth_cram.c index 986b3525d..8dc3af5c0 100644 --- a/imap/auth_cram.c +++ b/imap/auth_cram.c @@ -35,9 +35,10 @@ #include #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" diff --git a/imap/auth_gss.c b/imap/auth_gss.c index 3875ca9cc..2b1fff683 100644 --- a/imap/auth_gss.c +++ b/imap/auth_gss.c @@ -36,10 +36,11 @@ #include #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" diff --git a/imap/auth_login.c b/imap/auth_login.c index 1faf2c0b2..952e3a0b2 100644 --- a/imap/auth_login.c +++ b/imap/auth_login.c @@ -34,10 +34,11 @@ #include #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" diff --git a/imap/auth_plain.c b/imap/auth_plain.c index 61b9c5d7a..60a378840 100644 --- a/imap/auth_plain.c +++ b/imap/auth_plain.c @@ -34,10 +34,10 @@ #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" diff --git a/imap/auth_sasl.c b/imap/auth_sasl.c index 69ffa179a..84e02ca63 100644 --- a/imap/auth_sasl.c +++ b/imap/auth_sasl.c @@ -38,10 +38,10 @@ #include #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" diff --git a/imap/browse.c b/imap/browse.c index 900471133..d25e427f8 100644 --- a/imap/browse.c +++ b/imap/browse.c @@ -44,12 +44,12 @@ #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" diff --git a/imap/command.c b/imap/command.c index f0245badb..ebf11b1c7 100644 --- a/imap/command.c +++ b/imap/command.c @@ -47,7 +47,7 @@ #include #include "imap_private.h" #include "lib/lib.h" -#include "account.h" +#include "conn/conn.h" #include "buffy.h" #include "context.h" #include "globals.h" @@ -55,6 +55,7 @@ #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" diff --git a/imap/imap.c b/imap/imap.c index 367bfcff9..59fa6a4b1 100644 --- a/imap/imap.c +++ b/imap/imap.c @@ -81,9 +81,9 @@ #include #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" @@ -94,6 +94,7 @@ #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" @@ -106,9 +107,6 @@ #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 diff --git a/imap/imap.h b/imap/imap.h index 0d3f609bd..94fb2c892 100644 --- a/imap/imap.h +++ b/imap/imap.h @@ -46,7 +46,7 @@ #include #include -#include "account.h" +#include "mutt_account.h" struct Header; struct Pattern; diff --git a/imap/message.c b/imap/message.c index a4cf0c0aa..fd09adfee 100644 --- a/imap/message.c +++ b/imap/message.c @@ -49,9 +49,9 @@ #include #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" @@ -60,6 +60,7 @@ #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" diff --git a/imap/util.c b/imap/util.c index 641db17f2..a104894b7 100644 --- a/imap/util.c +++ b/imap/util.c @@ -77,8 +77,8 @@ #include #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" @@ -86,6 +86,7 @@ #include "imap/imap.h" #include "mailbox.h" #include "message.h" +#include "mutt_account.h" #include "mutt_socket.h" #include "mx.h" #include "options.h" diff --git a/init.h b/init.h index 726d2baca..1f14d4d6c 100644 --- a/init.h +++ b/init.h @@ -40,6 +40,7 @@ #include "options.h" #include "protos.h" #include "sort.h" +#include "conn/conn.h" #ifdef USE_LUA #include "mutt_lua.h" #endif diff --git a/main.c b/main.c index fc8e6a011..d844f51fb 100644 --- a/main.c +++ b/main.c @@ -38,6 +38,7 @@ #include #include #include "lib/lib.h" +#include "conn/conn.h" #include "mutt.h" #include "address.h" #include "alias.h" @@ -61,9 +62,6 @@ #ifdef USE_SIDEBAR #include "sidebar.h" #endif -#ifdef USE_SASL -#include "mutt_sasl.h" -#endif #ifdef USE_IMAP #include "imap/imap.h" #endif diff --git a/account.c b/mutt_account.c similarity index 99% rename from account.c rename to mutt_account.c index 97671278a..db532b3eb 100644 --- a/account.c +++ b/mutt_account.c @@ -25,7 +25,7 @@ #include #include "lib/lib.h" #include "mutt.h" -#include "account.h" +#include "mutt_account.h" #include "globals.h" #include "options.h" #include "protos.h" diff --git a/account.h b/mutt_account.h similarity index 88% rename from account.h rename to mutt_account.h index 59541d6c4..c3637138d 100644 --- a/account.h +++ b/mutt_account.h @@ -25,6 +25,8 @@ #ifndef _MUTT_ACCOUNT_H #define _MUTT_ACCOUNT_H +#include "conn/conn.h" + struct Url; /** @@ -46,20 +48,6 @@ enum AccountType #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); diff --git a/mutt_socket.c b/mutt_socket.c index cb41d6464..032a6c308 100644 --- a/mutt_socket.c +++ b/mutt_socket.c @@ -1,11 +1,9 @@ /** * @file - * Low-level socket handling + * NeoMutt connections * * @authors - * Copyright (C) 1998,2000 Michael R. Elkins - * Copyright (C) 1999-2006,2008 Brendan Cully - * Copyright (C) 1999-2000 Tommi Komulainen + * Copyright (C) 2000-2007 Brendan Cully * * @copyright * This program is free software: you can redistribute it and/or modify it under @@ -23,202 +21,20 @@ */ #include "config.h" -#include -#include -#include -#include -#include #include #include -#include -#include -#include -#include +#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; @@ -241,19 +57,6 @@ void mutt_socket_free(struct Connection *conn) } } -/** - * 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 * @@ -317,293 +120,3 @@ struct Connection *mutt_conn_find(const struct Connection *start, const struct A 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; -} diff --git a/mutt_socket.h b/mutt_socket.h index e766f5eb7..ed3ff4ea8 100644 --- a/mutt_socket.h +++ b/mutt_socket.h @@ -1,10 +1,9 @@ /** * @file - * Low-level socket handling + * NeoMutt connections * * @authors - * Copyright (C) 1998 Brandon Long - * Copyright (C) 1999-2005 Brendan Cully + * Copyright (C) 2000-2007 Brendan Cully * * @copyright * This program is free software: you can redistribute it and/or modify it under @@ -24,9 +23,10 @@ #ifndef _MUTT_SOCKET_H #define _MUTT_SOCKET_H -#include -#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 @@ -38,50 +38,13 @@ */ 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 */ diff --git a/newsrc.c b/newsrc.c index 8309514a5..b1ce4c653 100644 --- a/newsrc.c +++ b/newsrc.c @@ -33,13 +33,14 @@ #include #include #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" diff --git a/nntp.c b/nntp.c index 2d4e446c5..25f204545 100644 --- a/nntp.c +++ b/nntp.c @@ -28,9 +28,9 @@ #include #include #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" @@ -38,6 +38,7 @@ #include "globals.h" #include "header.h" #include "mailbox.h" +#include "mutt_account.h" #include "mutt_curses.h" #include "mutt_socket.h" #include "mx.h" @@ -46,16 +47,12 @@ #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 #include -#include "mutt_sasl.h" #endif static int nntp_connect_error(struct NntpServer *nserv) diff --git a/po/POTFILES.in b/po/POTFILES.in index 93362aad3..e915cf059 100644 --- a/po/POTFILES.in +++ b/po/POTFILES.in @@ -1,4 +1,3 @@ -account.c addrbook.c alias.c attach.c @@ -12,10 +11,15 @@ commands.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 @@ -26,7 +30,6 @@ envelope.c filter.c flags.c from.c -getdomain.c group.c handler.c hcache/bdb.c @@ -64,6 +67,7 @@ lib/exit.c lib/file.c lib/hash.c lib/list.c +lib/mapping.c lib/md5.c lib/memory.c lib/message.c @@ -75,17 +79,17 @@ mbyte.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 diff --git a/pop.c b/pop.c index a9912ea7a..76b8a9850 100644 --- a/pop.c +++ b/pop.c @@ -29,9 +29,9 @@ #include #include #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" @@ -39,6 +39,7 @@ #include "globals.h" #include "header.h" #include "mailbox.h" +#include "mutt_account.h" #include "mutt_curses.h" #include "mutt_socket.h" #include "mx.h" diff --git a/pop_auth.c b/pop_auth.c index 9b8c200fc..c3e5bcf9f 100644 --- a/pop_auth.c +++ b/pop_auth.c @@ -25,9 +25,10 @@ #include #include #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" @@ -36,7 +37,6 @@ #ifdef USE_SASL #include #include -#include "mutt_sasl.h" #endif #ifdef USE_SASL diff --git a/pop_lib.c b/pop_lib.c index ed7f5401e..7fc5fd1de 100644 --- a/pop_lib.c +++ b/pop_lib.c @@ -29,20 +29,18 @@ #include #include #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 diff --git a/smtp.c b/smtp.c index 05493e072..7aa9afb00 100644 --- a/smtp.c +++ b/smtp.c @@ -32,24 +32,19 @@ #include #include #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 #include -#include "mutt_sasl.h" -#else -#include "mutt_sasl_plain.h" #endif #define smtp_success(x) ((x) / 100 == 2)