mutt_socket.c |    9 ++-
 mutt_socket.h |    1 +
 mutt_tunnel.c |  133 +++++++++------------------------------------------------
 mutt_tunnel.h |    3 +-
 4 files changed, 30 insertions(+), 116 deletions(-)


# HG changeset patch
# User Michael Elkins <[email protected]>
# Date 1360876625 0
# Branch HEAD
# Node ID 3882b5ebe3d25f695059d17761706a5d3d3b3e5f
# Parent  3e22d65af90a022b1502c728264dd5915e172f4b
Enable support for TLS over $tunnel connections

Make $tunnel a special case of raw_socket_{open,close} rather than separate
callbacks so that TLS support can be layered on top.  The tls_socket_* calls
are hardcoded to use raw_socket_*, which did not work with tunnels.

Use UNIX domain sockets rather than pipes to communicate with the $tunnel child
process.  This yields a single, bi-directional file descriptor that has the
same interface as a AF_INET socket.

diff --git a/mutt_socket.c b/mutt_socket.c
--- a/mutt_socket.c
+++ b/mutt_socket.c
@@ -286,9 +286,7 @@
   conn->next = Connections;
   Connections = conn;
 
-  if (Tunnel && *Tunnel)
-    mutt_tunnel_socket_setup (conn);
-  else if (account->flags & M_ACCT_SSL) 
+  if (account->flags & M_ACCT_SSL) 
   {
 #if defined(USE_SSL)
     if (mutt_ssl_socket_setup (conn) < 0)
@@ -391,7 +389,7 @@
 
 int raw_socket_close (CONNECTION *conn)
 {
-  return close (conn->fd);
+  return conn->tunnel_pid ?  tunnel_socket_close(conn) : close (conn->fd);
 }
 
 int raw_socket_read (CONNECTION* conn, char* buf, size_t len)
@@ -443,6 +441,9 @@
 
   char *host_idna = NULL;
   
+  if (Tunnel && *Tunnel)
+    return tunnel_socket_open(conn);
+
 #ifdef HAVE_GETADDRINFO
 /* --- IPv4/6 --- */
 
diff --git a/mutt_socket.h b/mutt_socket.h
--- a/mutt_socket.h
+++ b/mutt_socket.h
@@ -40,6 +40,7 @@
 
   int fd;
   int available;
+  pid_t tunnel_pid;
 
   struct _connection *next;
 
diff --git a/mutt_tunnel.c b/mutt_tunnel.c
--- a/mutt_tunnel.c
+++ b/mutt_tunnel.c
@@ -22,7 +22,6 @@
 #endif
 
 #include "mutt.h"
-#include "mutt_socket.h"
 #include "mutt_tunnel.h"
 
 #include <netinet/in.h>
@@ -32,53 +31,21 @@
 #include <fcntl.h>
 #include <errno.h>
 
-/* -- data types -- */
-typedef struct
+int tunnel_socket_open (CONNECTION *conn)
 {
+  int fd[2];
   pid_t pid;
-  int readfd;
-  int writefd;
-} TUNNEL_DATA;
-
-/* forward declarations */
-static int tunnel_socket_open (CONNECTION*);
-static int tunnel_socket_close (CONNECTION*);
-static int tunnel_socket_read (CONNECTION* conn, char* buf, size_t len);
-static int tunnel_socket_write (CONNECTION* conn, const char* buf, size_t len);
-static int tunnel_socket_poll (CONNECTION* conn);
-
-/* -- public functions -- */
-int mutt_tunnel_socket_setup (CONNECTION *conn)
-{
-  conn->conn_open = tunnel_socket_open;
-  conn->conn_close = tunnel_socket_close;
-  conn->conn_read = tunnel_socket_read;
-  conn->conn_write = tunnel_socket_write;
-  conn->conn_poll = tunnel_socket_poll;
-
-  return 0;
-}
-
-static int tunnel_socket_open (CONNECTION *conn)
-{
-  TUNNEL_DATA* tunnel;
-  int pid;
-  int rc;
-  int pin[2], pout[2];
-
-  tunnel = (TUNNEL_DATA*) safe_malloc (sizeof (TUNNEL_DATA));
-  conn->sockdata = tunnel;
 
   mutt_message (_("Connecting with \"%s\"..."), Tunnel);
 
-  if ((rc = pipe (pin)) == -1)
+  /*
+   * Use a UNIX domain socket rather than a pair of pipes so that the higher
+   * level TLS code doesn't need to be concerned with separate file descriptors
+   * for reading and writing.
+   */
+  if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) != 0)
   {
-    mutt_perror ("pipe");
-    return -1;
-  }
-  if ((rc = pipe (pout)) == -1)
-  {
-    mutt_perror ("pipe");
+    mutt_perror ("socketpair");
     return -1;
   }
 
@@ -86,12 +53,10 @@
   if ((pid = fork ()) == 0)
   {
     mutt_unblock_signals_system (0);
-    if (dup2 (pout[0], STDIN_FILENO) < 0 || dup2 (pin[1], STDOUT_FILENO) < 0)
+    if (dup2 (fd[0], STDIN_FILENO) < 0 || dup2 (fd[0], STDOUT_FILENO) < 0)
       _exit (127);
-    close (pin[0]);
-    close (pin[1]);
-    close (pout[0]);
-    close (pout[1]);
+    close(fd[0]);
+    close(fd[1]);
     close (STDERR_FILENO);
 
     /* Don't let the subprocess think it can use the controlling tty */
@@ -102,38 +67,30 @@
   }
   mutt_unblock_signals_system (1);
 
+  /* close the child half of the pair */
+  close(fd[0]);
+
   if (pid == -1)
   {
-    close (pin[0]);
-    close (pin[1]);
-    close (pout[0]);
-    close (pout[1]);
+    close(fd[1]);
     mutt_perror ("fork");
     return -1;
   }
-  if (close (pin[1]) < 0 || close (pout[0]) < 0)
-    mutt_perror ("close");
 
-  fcntl (pin[0], F_SETFD, FD_CLOEXEC);
-  fcntl (pout[1], F_SETFD, FD_CLOEXEC);
+  fcntl (fd[1], F_SETFD, FD_CLOEXEC);
 
-  tunnel->readfd = pin[0];
-  tunnel->writefd = pout[1];
-  tunnel->pid = pid;
-
-  conn->fd = 42; /* stupid hack */
+  conn->fd = fd[1];
+  conn->tunnel_pid = pid;
 
   return 0;
 }
 
-static int tunnel_socket_close (CONNECTION* conn)
+int tunnel_socket_close (CONNECTION* conn)
 {
-  TUNNEL_DATA* tunnel = (TUNNEL_DATA*) conn->sockdata;
   int status;
 
-  close (tunnel->readfd);
-  close (tunnel->writefd);
-  waitpid (tunnel->pid, &status, 0);
+  close(conn->fd);
+  waitpid (conn->tunnel_pid, &status, 0);
   if (!WIFEXITED(status) || WEXITSTATUS(status))
   {
     mutt_error(_("Tunnel to %s returned error %d (%s)"), conn->account.host,
@@ -145,49 +102,3 @@
 
   return 0;
 }
-
-static int tunnel_socket_read (CONNECTION* conn, char* buf, size_t len)
-{
-  TUNNEL_DATA* tunnel = (TUNNEL_DATA*) conn->sockdata;
-  int rc;
-
-  rc = read (tunnel->readfd, buf, len);
-  if (rc == -1)
-  {
-    mutt_error (_("Tunnel error talking to %s: %s"), conn->account.host,
-               strerror (errno));
-    mutt_sleep (1);
-  }
-
-  return rc;
-}
-
-static int tunnel_socket_write (CONNECTION* conn, const char* buf, size_t len)
-{
-  TUNNEL_DATA* tunnel = (TUNNEL_DATA*) conn->sockdata;
-  int rc;
-
-  rc = write (tunnel->writefd, buf, len);
-  if (rc == -1)
-  {
-    mutt_error (_("Tunnel error talking to %s: %s"), conn->account.host,
-               strerror (errno));
-    mutt_sleep (1);
-  }
-
-  return rc;
-}
-
-static int tunnel_socket_poll (CONNECTION* conn)
-{
-  TUNNEL_DATA* tunnel = (TUNNEL_DATA*) conn->sockdata;
-  int ofd;
-  int rc;
-
-  ofd = conn->fd;
-  conn->fd = tunnel->readfd;
-  rc = raw_socket_poll (conn);
-  conn->fd = ofd;
-
-  return rc;
-}
diff --git a/mutt_tunnel.h b/mutt_tunnel.h
--- a/mutt_tunnel.h
+++ b/mutt_tunnel.h
@@ -19,6 +19,7 @@
 
 #include "mutt_socket.h"
 
-int mutt_tunnel_socket_setup (CONNECTION *);
+int tunnel_socket_open (CONNECTION *);
+int tunnel_socket_close (CONNECTION *);
 
 #endif /* _MUTT_TUNNEL_H_ */

Reply via email to