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

[msmtp-users] Proxy support patch



I've written an patch that allows msmtp to use a socks or html proxy. It
uses the antinat library that can be found at http://antinat.sourceforge.net
The patch is a little rough at the momement, it doesn't take into
account any of the autoconfigure scripts. You have to define HAVE_PROXY
in the config.h manually and make sure that has the correct flags during
linking to see the library. You also have to define what proxy you want
to use at compile time. It does support tls, but only using gnutls.

It's in 'it works for me' condition, so I'm not not sure if it will get
any more polished unless I have a pressing need, but I thought it would
be good to put this out there in case somebody else was needing
something like it. I was just completely unable to find any simple smtp
client that had proxy support that I could use from the command line.

CustaiCo
diff --git a/src/net.c b/src/net.c
index 925af62..edfe6bf 100644
--- a/src/net.c
+++ b/src/net.c
@@ -205,10 +205,12 @@ int net_lib_init(char **errstr)
  * see net.h
  */
 
-void net_close_socket(int fd)
+void net_close_socket(sock_t fd)
 {
 #ifdef W32_NATIVE
     (void)closesocket(fd);
+#elif HAVE_PROXY
+    an_destroy(fd);
 #else
     (void)close(fd);
 #endif
@@ -225,14 +227,15 @@ void net_close_socket(int fd)
  * A 'timeout' <= 0 will be ignored.
  */
 
-int net_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen,
+int net_connect(sock_t fd, const struct sockaddr *serv_addr, socklen_t addrlen,
         int timeout)
 {
 #ifdef W32_NATIVE
     /* TODO: I don't know how to do this on Win32. Please send a patch. */
     return connect(fd, serv_addr, addrlen);
+#elif HAVE_PROXY 
+    return -1;
 #else /* UNIX or DJGPP */
-
     int flags;
     struct timeval tv;
     fd_set rset;
@@ -310,7 +313,7 @@ int net_connect(int fd, const struct sockaddr *serv_addr, socklen_t addrlen,
  * Sets a timeout for inout/output operations on the given socket.
  */
 
-void net_set_io_timeout(int socket, int seconds)
+void net_set_io_timeout(sock_t socket, int seconds)
 {
 #ifdef W32_NATIVE
     DWORD milliseconds;
@@ -321,6 +324,8 @@ void net_set_io_timeout(int socket, int seconds)
         (void)setsockopt(socket, SOL_SOCKET, SO_RCVTIMEO, &milliseconds, sizeof(int));
         (void)setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &milliseconds, sizeof(int));
     }
+#elif HAVE_PROXY 
+    /*this space intentionally left blank */
 #else /* UNIX or DJGPP */
     struct timeval tv;
 
@@ -332,6 +337,7 @@ void net_set_io_timeout(int socket, int seconds)
         (void)setsockopt(socket, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv));
     }
 #endif
+    
 }
 
 
@@ -341,10 +347,10 @@ 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,
+int net_open_socket(const char *hostname, int port, int timeout, sock_t *ret_fd,
         char **canonical_name, char **address, char **errstr)
 {
-    int fd;
+    sock_t fd;
     char *port_string;
     struct addrinfo hints;
     struct addrinfo *res0;
@@ -353,6 +359,7 @@ int net_open_socket(const char *hostname, int port, int timeout, int *ret_fd,
     int failure_errno;
     int cause;
     char nameinfo_buffer[NI_MAXHOST];
+#ifndef HAVE_PROXY
 #ifdef HAVE_LIBIDN
     char *hostname_ascii;
 #endif
@@ -374,7 +381,7 @@ int net_open_socket(const char *hostname, int port, int timeout, int *ret_fd,
     error_code = getaddrinfo(hostname_ascii, port_string, &hints, &res0);
     free(hostname_ascii);
 #else
-    error_code = getaddrinfo(hostname, port_string, &hints, &res0);
+    error_code = getaddrinfo(hostname, port_string, &hints, &res0); 
 #endif
     free(port_string);
     if (error_code)
@@ -504,8 +511,18 @@ int net_open_socket(const char *hostname, int port, int timeout, int *ret_fd,
             return NET_ECONNECT;
         }
     }
-
     net_set_io_timeout(fd, timeout);
+#elif HAVE_PROXY
+    fd = an_new_connection();
+    an_set_proxy_url(fd, PROXY_ADDRESS);
+    error_code = an_connect_tohostname(fd,hostname,port);
+    if( error_code != AN_ERROR_SUCCESS )
+    {
+            *errstr = xasprintf(_("cannot connect to %s, port %d"),
+                       hostname, port);
+            return NET_ECONNECT;
+    }
+#endif
     *ret_fd = fd;
     return NET_EOK;
 }
@@ -517,7 +534,7 @@ int net_open_socket(const char *hostname, int port, int timeout, int *ret_fd,
  * Wraps read() to provide buffering for net_gets().
  */
 
-int net_readbuf_read(int fd, readbuf_t *readbuf, char *ptr,
+int net_readbuf_read(sock_t fd, readbuf_t *readbuf, char *ptr,
         char **errstr)
 {
 #ifdef W32_NATIVE
@@ -556,7 +573,11 @@ int net_readbuf_read(int fd, readbuf_t *readbuf, char *ptr,
 
     if (readbuf->count <= 0)
     {
+#ifndef HAVE_PROXY
         readbuf->count = (int)recv(fd, readbuf->buf, sizeof(readbuf->buf), 0);
+#else 
+        readbuf->count = (int)an_recv(fd, readbuf->buf, sizeof(readbuf->buf), 0);
+#endif
         if (readbuf->count < 0)
         {
             if (errno == EINTR)
@@ -595,7 +616,7 @@ int net_readbuf_read(int fd, readbuf_t *readbuf, char *ptr,
  * see net.h
  */
 
-int net_gets(int fd, readbuf_t *readbuf,
+int net_gets(sock_t fd, readbuf_t *readbuf,
         char *str, size_t size, size_t *len, char **errstr)
 {
     char c;
@@ -634,7 +655,7 @@ int net_gets(int fd, readbuf_t *readbuf,
  * see net.h
  */
 
-int net_puts(int fd, const char *s, size_t len, char **errstr)
+int net_puts(sock_t fd, const char *s, size_t len, char **errstr)
 {
 #ifdef W32_NATIVE
 
@@ -677,7 +698,11 @@ int net_puts(int fd, const char *s, size_t len, char **errstr)
     {
         return NET_EOK;
     }
+#ifndef HAVE_PROXY
     if ((ret = send(fd, s, len, 0)) < 0)
+#else
+    if ((ret = an_send(fd,(void *)s, len, 0)) < 0)
+#endif
     {
         if (errno == EINTR)
         {
@@ -717,8 +742,9 @@ int net_puts(int fd, const char *s, size_t len, char **errstr)
 
 char *net_get_canonical_hostname(void)
 {
-    char hostname[256];
     char *canonname = NULL;
+#ifndef HAVE_PROXY
+    char hostname[256];
     struct addrinfo hints;
     struct addrinfo *res0;
 
@@ -743,6 +769,7 @@ char *net_get_canonical_hostname(void)
             freeaddrinfo(res0);
         }
     }
+#endif
 
     if (!canonname)
     {
@@ -765,3 +792,15 @@ void net_lib_deinit(void)
     (void)WSACleanup();
 #endif
 }
+
+#ifdef HAVE_PROXY
+ssize_t net_push_tls(sock_t fd,void* data, size_t size) 
+{
+    return an_send((sock_t)fd, data,size,0);
+}
+
+ssize_t net_pull_tls(sock_t fd,void* data, size_t size) 
+{
+    return an_recv(fd, data,size,0);
+}
+#endif 
diff --git a/src/net.h b/src/net.h
index fde43d9..c7b2eee 100644
--- a/src/net.h
+++ b/src/net.h
@@ -25,6 +25,14 @@
 
 #include "readbuf.h"
 
+#ifdef HAVE_PROXY
+#include <antinat.h>
+#define PROXY_ADDRESS "socks5://127.0.0.1:9050"
+typedef ANCONN sock_t;
+#else
+typedef int sock_t;
+#endif
+
 
 /*
  * If a function with an 'errstr' argument returns a value != NET_EOK,
@@ -68,7 +76,7 @@ int net_lib_init(char **errstr);
  *
  * Used error codes: NET_EHOSTNOTFOUND, NET_ESOCKET, NET_ECONNECT
  */
-int net_open_socket(const char *hostname, int port, int timeout, int *fd,
+int net_open_socket(const char *hostname, int port, int timeout, sock_t *fd,
         char **canonical_name, char **address, char **errstr);
 
 /*
@@ -83,7 +91,7 @@ int net_open_socket(const char *hostname, int port, int timeout, int *fd,
  * all read operations on 'fd'.
  * Used error codes: NET_EIO
  */
-int net_gets(int fd, readbuf_t *readbuf,
+int net_gets(sock_t fd, readbuf_t *readbuf,
         char *str, size_t size, size_t *len, char **errstr);
 
 /*
@@ -92,14 +100,14 @@ int net_gets(int fd, readbuf_t *readbuf,
  * Writes 'len' characters from the string 's' to 'fd'.
  * Used error codes: NET_EIO
  */
-int net_puts(int fd, const char *s, size_t len, char **errstr);
+int net_puts(sock_t fd, const char *s, size_t len, char **errstr);
 
 /*
  * net_close_socket()
  *
  * Closes a socket.
  */
-void net_close_socket(int fd);
+void net_close_socket(sock_t fd);
 
 /*
  * net_get_canonical_hostname()
@@ -116,4 +124,10 @@ char *net_get_canonical_hostname(void);
  */
 void net_lib_deinit(void);
 
+#ifdef HAVE_PROXY
+ssize_t net_push_tls(sock_t fd,void* data, size_t size);
+
+ssize_t net_pull_tls(sock_t fd,void* data, size_t size); 
+#endif
+
 #endif
diff --git a/src/smtp.c b/src/smtp.c
index ee8550e..2c56b2e 100644
--- a/src/smtp.c
+++ b/src/smtp.c
@@ -107,7 +107,9 @@ smtp_server_t smtp_new(FILE *debug, int protocol)
 {
     smtp_server_t srv;
 
+#ifndef HAVE_PROXY
     srv.fd = -1;
+#endif
 #ifdef HAVE_TLS
     tls_clear(&srv.tls);
 #endif /* HAVE_TLS */
diff --git a/src/smtp.h b/src/smtp.h
index 09f32bc..a20f5dc 100644
--- a/src/smtp.h
+++ b/src/smtp.h
@@ -91,7 +91,7 @@ typedef struct
  */
 typedef struct
 {
-    int fd;
+    sock_t fd;
 #ifdef HAVE_TLS
     tls_t tls;
 #endif /* HAVE_TLS */
diff --git a/src/tls.c b/src/tls.c
index 0b16a0c..ba35c12 100644
--- a/src/tls.c
+++ b/src/tls.c
@@ -1371,13 +1371,17 @@ char *openssl_io_error(int error_code, int error_code2,
  * see tls.h
  */
 
-int tls_start(tls_t *tls, int fd, const char *hostname, int no_certcheck,
+int tls_start(tls_t *tls, sock_t fd, const char *hostname, int no_certcheck,
         tls_cert_info_t *tci, char **errstr)
 {
 #ifdef HAVE_LIBGNUTLS
     int error_code;
 
     gnutls_transport_set_ptr(tls->session, (gnutls_transport_ptr_t)fd);
+#ifdef HAVE_PROXY
+    gnutls_transport_set_push_function(tls->session, (gnutls_push_func)net_push_tls);
+    gnutls_transport_set_pull_function(tls->session, (gnutls_pull_func)net_pull_tls);
+#endif
     if ((error_code = gnutls_handshake(tls->session)) < 0)
     {
         if (error_code == GNUTLS_E_INTERRUPTED)
diff --git a/src/tls.h b/src/tls.h
index cc76526..aaa8775 100644
--- a/src/tls.h
+++ b/src/tls.h
@@ -31,6 +31,11 @@
 #endif /* HAVE_LIBSSL */
 
 #include "readbuf.h"
+#include "net.h"
+
+#ifdef HAVE_PROXY
+#include <antinat.h>
+#endif
 
 
 /*
@@ -154,9 +159,8 @@ int tls_init(tls_t *tls,
  * information will be passed in this case.
  * Used error codes: TLS_ELIBFAILED, TLS_ECERT, TLS_EHANDSHAKE
  */
-int tls_start(tls_t *tls, int fd, const char *hostname, int no_certcheck,
+int tls_start(tls_t *tls, sock_t fd, const char *hostname, int no_certcheck,
         tls_cert_info_t *tci, char **errstr);
-
 /*
  * tls_is_active()
  *