[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [msmtp-users] Proxy support patch



Hi!

I don't use a proxy myself; I have a few questions about SOCKS support
in general and your patch in particular:

1. Is there any need for anything except SOCKS5? It has been around for
ages, does anybody really still need SOCKS4?

2. Nobody protects the SOCKS5 protocol with TLS, right?

3. Is there a valid use case for SOCKS5 authentication? It only
supports unprotected user/password transmission (well, and GSSAPI, but
nobody uses that). This makes it pretty useless.

If we only need SOCKS5 without TLS and possibly also without
authentication, then SOCKS5 integration could be done by only
extending net_open_socket(), as sketched in the attached
patch. Or am I missing something?

Martin


On Tue, 7 Oct 2014 11:46:24 +0000, CustaiCo wrote:
> I have completed the work to add proxying to msmtp without any
> dependancy on any other library. Initially I was just linking against
> the proxychains code. I thought I had the everything working then I
> tried to send a message and it did not work. At that time I realized
> there was basically one function I needed out of the entire thing, and
> even that function needed cleaning, and that I was supending more time
> trying to get it's brain dead interface working than I was doing
> useful things.
> 
> Included is completely untested ipv6 support when using a proxy. I've
> written it in a way that I *think* ipv6 should but I have no way to
> actually test this due to lack of one that supports the protocol. The
> proxy name and address are still defined at compile time. I still
> haven't changed the auto configuration macros to add proxy.h and
> proxy.c to the build.
> 
> Because of how cleanly seperated the network code is from the rest of
> the application, I'm fairly sure that there should be no leaks, unless
> the ssl library decides to open it's own connections for no reason. I
> haven't looked at my traffic during use to confirm it.
> 
> CustaiCo

diff --git a/src/net.c b/src/net.c
index 925af62..f1e62e8 100644
--- a/src/net.c
+++ b/src/net.c
@@ -3,7 +3,7 @@
  *
  * This file is part of msmtp, an SMTP client.
  *
- * Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2012
+ * Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2012, 2014
  * Martin Lambers <marlam@...23...>
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -341,8 +341,12 @@ void net_set_io_timeout(int socket, int seconds)
  * see net.h
  */
 
-int net_open_socket(const char *hostname, int port, int timeout, int *ret_fd,
-        char **canonical_name, char **address, char **errstr)
+int net_open_socket(
+        const char *proxy_hostname, int proxy_port,
+        const char *hostname, int port,
+        int timeout,
+        int *ret_fd, char **canonical_name, char **address,
+        char **errstr)
 {
     int fd;
     char *port_string;
@@ -357,6 +361,54 @@ int net_open_socket(const char *hostname, int port, int timeout, int *ret_fd,
     char *hostname_ascii;
 #endif
 
+    if (proxy_hostname)
+    {
+        error_code = net_open_socket(NULL, -1, proxy_hostname, proxy_port,
+                timeout, &fd, NULL, NULL, errstr);
+        if (error_code != NET_EOK)
+        {
+            return error_code;
+        }
+        // call function that implements SOCKS5 CONNECT without authentication:
+        //     send:
+        //     1 byte 0x05 (SOCKS5)
+        //     1 byte 0x00 (zero auth methods supported)
+        //     receive:
+        //     1 byte 0x05 (SOCKS5)
+        //     1 byte 0x00 (no auth)
+        //     send:
+        //     1 byte 0x05 (SOCKS5)
+        //     1 byte 0x01 (establish TCP connection aka CONNECT)
+        //     1 byte 0x00 (reserved)
+        //     1 byte 0x03 (domain name) (or IPv4 / IPv6? really necessary?)
+        //     1 byte LLLL (length of domain name)
+        //     LLLL bytes  (domain name)
+        //     2 bytes PPP (port number, network byte order)
+        //     receive:
+        //     1 byte 0x05 (SOCKS5)
+        //     1 byte 0x?? (status success or error code)
+        //     1 byte 0x00 (reserved)
+        //     1 byte 0x?? (address type; ignore)
+        //     4/1+X/16 bytes (address; ignore)
+        //     2 bytes     (port; ignore)
+        if (socks5_status != 0x00)
+        {
+            net_close_socket(fd);
+            *errstr = ...;
+            return NET_EPROXY;
+        }
+        *ret_fd = fd;
+        if (canonical_name)
+        {
+            *canonical_name = NULL;
+        }
+        if (address)
+        {
+            *address = NULL;
+        }
+        return NET_EOK;
+    }
+
     hints.ai_family = PF_UNSPEC;
     hints.ai_socktype = SOCK_STREAM;
     hints.ai_flags = 0;
diff --git a/src/net.h b/src/net.h
index fde43d9..77c880b 100644
--- a/src/net.h
+++ b/src/net.h
@@ -3,7 +3,7 @@
  *
  * This file is part of msmtp, an SMTP client.
  *
- * Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007, 2008
+ * Copyright (C) 2000, 2003, 2004, 2005, 2006, 2007, 2008, 2014
  * Martin Lambers <marlam@...23...>
  *
  *   This program is free software; you can redistribute it and/or modify
@@ -38,6 +38,7 @@
 #define NET_ESOCKET             3       /* Cannot create socket */
 #define NET_ECONNECT            4       /* Cannot connect */
 #define NET_EIO                 5       /* Input/output error */
+#define NET_EPROXY              6       /* Proxy failure */
 
 /*
  * net_lib_init()
@@ -52,6 +53,8 @@ int net_lib_init(char **errstr);
  * net_open_socket()
  *
  * Opens a TCP socket to 'hostname':'port'.
+ * 'proxy_hostname' and 'proxy_port' define a SOCKS5 proxy to use, unless they
+ * are NULL/-1, in which case no proxy will be used.
  * 'hostname' may be a host name or a network address.
  * 'timeout' is measured in secondes. If it is <= 0, no timeout will be set,
  * which means that the OS dependent default timeout value will be used.
@@ -66,10 +69,14 @@ int net_lib_init(char **errstr);
  * The strings must be deallocated when not used anymore.
  * The file descriptor is returned in 'fd'. It can be closed with close().
  *
- * Used error codes: NET_EHOSTNOTFOUND, NET_ESOCKET, NET_ECONNECT
+ * Used error codes: NET_EHOSTNOTFOUND, NET_ESOCKET, NET_ECONNECT, NET_EPROXY
  */
-int net_open_socket(const char *hostname, int port, int timeout, int *fd,
-        char **canonical_name, char **address, char **errstr);
+int net_open_socket(
+        const char *proxy_hostname, int proxy_port,
+        const char *hostname, int port,
+        int timeout,
+        int *fd, char **canonical_name, char **address,
+        char **errstr);
 
 /*
  * net_gets()