]> Pileus Git - ~andy/fetchmail/commitdiff
Added plugin/plugout option.
authorEric S. Raymond <esr@thyrsus.com>
Mon, 2 Nov 1998 16:25:09 +0000 (16:25 -0000)
committerEric S. Raymond <esr@thyrsus.com>
Mon, 2 Nov 1998 16:25:09 +0000 (16:25 -0000)
svn path=/trunk/; revision=2168

15 files changed:
NEWS
conf.c
driver.c
fetchmail-FAQ.html
fetchmail.c
fetchmail.h
fetchmail.man
fetchmailconf
options.c
rcfile_l.l
rcfile_y.y
sample.rcfile
sink.c
socket.c
socket.h

diff --git a/NEWS b/NEWS
index b8b52a72c12f07b65ef8aa172083a2ce4fc37313..3a7fefff78902c58eda030c965e07e6c6e7124a6 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -4,6 +4,7 @@ fetchmail-4.6.6 (Fri Oct 30 11:34:20 EST 1998):
 * Fixed a core-dump bug in reply_hack with -v -v on.
 * Fix fetchmailconf to be able to edit properties.
 * Send calling user mail when password authentication fails in daemon mode.
+* Added plugin/plugout features from Felix von Leitner.
 
 There are 247 people on fetchmail-friends and 308 on fetchmail-announce.
 
diff --git a/conf.c b/conf.c
index e9884f22fc632a0206cf314711532462d80e4b51..7625516b139b0814e4e355f6ab9e6f78ba6720a3 100644 (file)
--- a/conf.c
+++ b/conf.c
@@ -270,6 +270,9 @@ void dump_config(struct runctl *runp, struct query *querylist)
            stringdump("monitor", ctl->server.monitor);
 #endif /* linux */
 
+           stringdump("plugin", ctl->server.plugin);
+           stringdump("plugout", ctl->server.plugout);
+
            indent(0);
            fputs("'users': ", stdout);
            indent('[');
index 33c3b48bc5a806fc4dcb27792e73998955c53461..b1617fcacd616d84dad85a59222accb361487a5c 100644 (file)
--- a/driver.c
+++ b/driver.c
@@ -1446,9 +1446,10 @@ const struct method *proto;      /* protocol method table */
 #if INET6
        if ((sock = SockOpen(realhost, 
                             ctl->server.service ? ctl->server.service : protocol->service,
-                            ctl->server.netsec)) == -1)
+                            ctl->server.netsec)) == -1, ctl->server.plugin
+           )
 #else /* INET6 */
-       if ((sock = SockOpen(realhost, port, NULL)) == -1)
+       if ((sock = SockOpen(realhost, port, NULL, ctl->server.plugin)) == -1)
 #endif /* INET6 */
        {
 #if !INET6
index c22d58ae67a2cdb157a7bb66d644c0b8b31dd913..eeacab2fd6ab58c06fcf3c48c719481b0a689839 100644 (file)
@@ -10,7 +10,7 @@
 <table width="100%" cellpadding=0><tr>
 <td width="30%">Back to <a href="index.html">Fetchmail Home Page</a>
 <td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a>
-<td width="30%" align=right>$Date: 1998/10/29 18:21:39 $
+<td width="30%" align=right>$Date: 1998/11/02 16:25:06 $
 </table>
 <HR>
 <H1>Frequently Asked Questions About Fetchmail</H1>
@@ -81,6 +81,7 @@ IP address?</a><br>
 <a href="#K2">K2. How can I use fetchmail with IPv6 and IPsec?</a><br>
 <a href="#K3">K3. How can I get fetchmail to work with ssh?</a><br>
 <a href="#K4">K4. What do I have to do to use the IMAP-GSS protocol?</a><br>
+<a href="#K5">K5. How can I use fetchmail with SSL?</a><br>
 
 <h1>Runtime fatal errors:</h1>
 
@@ -1467,6 +1468,31 @@ belongs to a username different from your kerberos principal. <p>
 Now you don't have to worry about your password appearing in cleartext in
 your .fetchmailrc, or across the network.<p>
 
+<hr>
+<h2><a name="K5">K5. How can I use fetchmail with SSL?</a></h2>
+
+The U.S. government's never-to-be-sufficiently-damned EAR regulations
+prevent me from including SSL library hooks in the distribution.
+However, the First Amendment of the U.S. Constitution hasn't been
+eviscerated (not yet, anyway -- our would-be totalitarians are still
+working on trashing the Second Amendment).<P>
+
+I can therefore <em>tell</em> you, in documentation, that there
+appears to be a way to set up an SSL command chain using the `plugin'
+option (originally designed for handling proxy connections across
+firewalls).<P>
+
+Get your hands on the <a
+href="http://www.psy.uq.edu.au:8080/~ftp/Crypto/">SSLEay</a> code.
+Now make yourself a script called `ssl_connect' that calls the SSLeay
+utility `s_client' as follows:<P>
+
+<pre>
+/usr/local/ssl/bin/s_client -quiet -ssl2 -connect $1:$2
+</pre>
+
+Now add `plugin ssl_connect' to the server options for your connection.<P>
+
 <hr>
 <h2><a name="R1">R1. Fetchmail isn't working, and -v shows `SMTP connect failed' messages.</a></h2>
 
@@ -2184,7 +2210,7 @@ Re-ordering messages is a user-agent function, anyway.<P>
 <table width="100%" cellpadding=0><tr>
 <td width="30%">Back to <a href="index.html">Fetchmail Home Page</a>
 <td width="30%" align=center>To <a href="/~esr/sitemap.html">Site Map</a>
-<td width="30%" align=right>$Date: 1998/10/29 18:21:39 $
+<td width="30%" align=right>$Date: 1998/11/02 16:25:06 $
 </table>
 
 <P><ADDRESS>Eric S. Raymond <A HREF="mailto:esr@thyrsus.com">&lt;esr@snark.thyrsus.com&gt;</A></ADDRESS>
index 75b9d573ee9bee039696cb674227aa1bc8432845..ef40f0b9db2fad63813ad56650e5f5936474ddee 100644 (file)
@@ -759,6 +759,8 @@ static void optmerge(struct query *h2, struct query *h1, int force)
     FLAG_MERGE(server.interface_pair);
 #endif /* linux */
 
+    FLAG_MERGE(server.plugin);
+    FLAG_MERGE(server.plugout);
     FLAG_MERGE(wildcard);
     FLAG_MERGE(remotename);
     FLAG_MERGE(password);
@@ -1491,6 +1493,15 @@ void dump_params (struct runctl *runp, struct query *querylist, flag implicit)
            printf("  No monitor interface specified.\n");
 #endif
 
+       if (ctl->server.plugin)
+           printf("  Server connections will be mode via plugin %s (--plugin %s).\n", ctl->server.plugin, ctl->server.plugin);
+       else if (outlevel >= O_VERBOSE)
+           printf("  No plugin command specified.\n");
+       if (ctl->server.plugout)
+           printf("  Listener connections will be mode via plugout %s (--plugout %s).\n", ctl->server.plugout, ctl->server.plugout);
+       else if (outlevel >= O_VERBOSE)
+           printf("  No plugout command specified.\n");
+
        if (ctl->server.protocol > P_POP2 && (ctl->server.protocol != P_ETRN))
            if (!ctl->oldsaved)
                printf("  No UIDs saved from this host.\n");
index 657804346f2dcde3b2855a1133c9cfecc0fc459c..721a4b8a733383074ec19bc0cae7b29f3f541617 100644 (file)
@@ -199,6 +199,8 @@ struct hostdata             /* shared among all user connections to given server */
     struct interface_pair_s *interface_pair;
 #endif /* linux */
 
+    char *plugin,*plugout;
+
     /* computed for internal use */
     const struct method *base_protocol;        /* relevant protocol method table */
     int poll_count;                    /* count of polls so far */
index 0d33e005289beb7c6ca1257151e8e4ce7a1080c3..27bdc69d2d43df4e8e0fc7084dc842cf5e416b23 100644 (file)
@@ -223,6 +223,20 @@ down host.  This would be particularly annoying for a \fIfetchmail\fR
 running in background.  There is a default timeout which fetchmail -V
 will report.
 .TP
+.B \--plugin
+(Keyword: plugin)
+The plugin option allows you to use an external program to establish the
+TCP connection.  This is useful if you want to use socks or need some
+special firewalling setup.  The program will be looked up in $PATH and
+it will be passed two arguments: the name of the server and the name of
+the port.
+.TP
+.B \--plugout
+(Keyword: plugout)
+Identical to the plugin option above, but this one is used for the SMTP
+connections (which will probably not need it, so it has been separated
+from plugin).
+.TP
 .B \-r folder, --folder folder
 (Keyword: folder[s])
 Causes a specified non-default mail folder on the mailserver (or
@@ -898,7 +912,7 @@ Turn off error logging through syslog(3).
 T}
 .TE
 
-Here are the legal user options:
+Here are the legal server options:
 
 .TS
 l l lw34.
@@ -938,6 +952,12 @@ T}
 monitor        -M      T{
 Specify IP address to monitor for activity
 T}
+plugin         \&      T{
+Specify command through which to make server connections.
+T}
+plugout        \&      T{
+Specify command through which to make listener connections.
+T}
 dns            \&      T{
 Enable DNS lookup for multidrop (default)
 T}
index 5973f81b694b1dce6a4e564b2f8d13b835d01873..52d01c959172ecc515349f70c6d7d3c443d0aecb 100755 (executable)
@@ -71,6 +71,8 @@ class Server:
        self.localdomains = []          # Domains to be considered local
        self.interface = None           # IP address and range
        self.monitor = None             # IP address and range
+       self.plugin = None              # Plugin command for going to server
+       self.plugout = None             # Plugin command for going to listener
        self.netsec = None              # IPV6 security options
        self.users = []                 # List of user entries for site
        Server.typemap = (
@@ -92,6 +94,8 @@ class Server:
            # leave localdomains out
            ('interface', 'String'),
            ('monitor',   'String'),
+           ('plugin',   'String'),
+           ('plugout',  'String'),
            ('netsec',   'String'))
 
     def dump(self, folded):
index f173dd3a9769b535d6d38632ce922fd0edee745e..5a8d2c07a03655292ddd33e0d3d61308c9688c12 100644 (file)
--- a/options.c
+++ b/options.c
 #define LA_EXPUNGE     37
 #define LA_MDA         38
 #define LA_BSMTP       39
-#define LA_NETSEC      40
-#define LA_INTERFACE    41
-#define LA_MONITOR      42
-#define LA_CONFIGDUMP  43
-#define LA_YYDEBUG     44
+#define LA_PLUGIN      40
+#define LA_PLUGOUT     41
+#define LA_NETSEC      42
+#define LA_INTERFACE    43
+#define LA_MONITOR      44
+#define LA_CONFIGDUMP  45
+#define LA_YYDEBUG     46
 
 /* options still left: CDgGhHjJoORwWxXYz */
 static const char *shortoptions = 
@@ -126,6 +128,8 @@ static const struct option longoptions[] = {
   {"interface",        required_argument, (int *) 0, LA_INTERFACE   },
   {"monitor",  required_argument, (int *) 0, LA_MONITOR     },
 #endif /* defined(linux) && !INET6 */
+  {"plugin",   required_argument, (int *) 0, LA_PLUGIN      },
+  {"plugout",  required_argument, (int *) 0, LA_PLUGOUT     },
 
   {"configdump",no_argument,      (int *) 0, LA_CONFIGDUMP  },
 
@@ -495,6 +499,12 @@ struct query *ctl; /* option record to be initialized */
            ctl->server.monitor = xstrdup(optarg);
            break;
 #endif /* defined(linux) && !INET6 */
+       case LA_PLUGIN:
+           ctl->server.plugin = xstrdup(optarg);
+           break;
+       case LA_PLUGOUT:
+           ctl->server.plugout = xstrdup(optarg);
+           break;
 
        case 'y':
        case LA_YYDEBUG:
@@ -550,6 +560,8 @@ struct query *ctl;  /* option record to be initialized */
        P("  -I, --interface   interface required specification\n");
        P("  -M, --monitor     monitor interface for activity\n");
 #endif
+       P("      --plugin      specify external command to open connection\n");
+       P("      --plugout     specify external command to open smtp connection\n");
 
        P("  -p, --protocol    specify retrieval protocol (see man page)\n");
        P("  -U, --uidl        force the use of UIDLs (pop3 only)\n");
index ce67630f7c7d9ca94ac1668e546dcaece99d6ea6..f573c716779869421ee922e6b0d3061c55db2fb3 100644 (file)
@@ -62,6 +62,8 @@ post(connect)?        { return POSTCONNECT; }
 netsec         { return NETSEC; }
 interface      { return INTERFACE; }
 monitor                { return MONITOR; }
+plugin         { return PLUGIN; }
+plugout                { return PLUGIN; }
 batchlimit     { return BATCHLIMIT; }
 fetchlimit     { return FETCHLIMIT; }
 expunge                { return EXPUNGE; }
index 044cf0c3e8a56aca37a93c713c4c0ef74257b139..12851030c57143111450451da93b4dbf76b33b46 100644 (file)
@@ -61,7 +61,7 @@ extern char * yytext;
 %token AUTHENTICATE TIMEOUT KPOP SDPS KERBEROS4 KERBEROS5 KERBEROS
 %token ENVELOPE QVIRTUAL USERNAME PASSWORD FOLDER SMTPHOST MDA BSMTP
 %token SMTPADDRESS SPAMRESPONSE PRECONNECT POSTCONNECT LIMIT
-%token NETSEC INTERFACE MONITOR
+%token NETSEC INTERFACE MONITOR PLUGIN PLUGOUT
 %token IS HERE THERE TO MAP WILDCARD
 %token BATCHLIMIT FETCHLIMIT EXPUNGE PROPERTIES
 %token SET LOGFILE DAEMON SYSLOG IDFILE INVISIBLE POSTMASTER WARNINGS
@@ -219,6 +219,8 @@ serv_option : AKA alias_list
                                        fprintf(stderr, "fetchmail: monitor option is only supported under Linux\n");
 #endif /* defined(linux) && !defined(INET6) */
                                        }
+               | PLUGIN STRING         { current.server.plugin = xstrdup($2); }
+               | PLUGOUT STRING        { current.server.plugout = xstrdup($2); }
                | DNS                   {current.server.dns = FLAG_TRUE;}
                | NO DNS                {current.server.dns = FLAG_FALSE;}
                | NO ENVELOPE           {current.server.envelope = STRING_DISABLED;}
index 158b387b18e2c5a056919470e6201543fbde38e8..5840292d2521d0e26221839886fd6974f4ad9c9e 100644 (file)
@@ -36,6 +36,8 @@
 #   localdomains              -- must be followed by one or more domain names
 #   interface                 -- must be followed by device/IP address/mask
 #   monitor                   -- must be followed by device
+#   plugin                    -- must be followed by a string command name
+#   plugout                   -- must be followed by a string command name
 #   dns
 #   no dns
 #   checkalias                -- do multidrop address comparison by IP address
diff --git a/sink.c b/sink.c
index 14aa8fc47f6634f8ada4416b8defb4cc924b8e1a..17e6406c58ea2a87ec79579a153d78304187916c 100644 (file)
--- a/sink.c
+++ b/sink.c
@@ -111,7 +111,8 @@ static int smtp_open(struct query *ctl)
 #endif /* INET6 */
            }
 
-           if ((ctl->smtp_socket = SockOpen(parsed_host,portnum,NULL)) == -1)
+           if ((ctl->smtp_socket = SockOpen(parsed_host,portnum,NULL,
+                                            ctl->server.plugout)) == -1)
                continue;
 
            /* first, probe for ESMTP */
@@ -128,7 +129,8 @@ static int smtp_open(struct query *ctl)
            ctl->smtp_socket = -1;
 
            /* if opening for ESMTP failed, try SMTP */
-           if ((ctl->smtp_socket = SockOpen(parsed_host,portnum,NULL)) == -1)
+           if ((ctl->smtp_socket = SockOpen(parsed_host,portnum,NULL,
+                                            ctl->server.plugout)) == -1)
                continue;
 
            if (SMTP_ok(ctl->smtp_socket) == SM_OK && 
index 94d3e56b0a8a99be3fc96bb3d357e92c79e883d6..5710796ce4461f4c6c07d126840a7c096ed3ed62 100644 (file)
--- a/socket.c
+++ b/socket.c
@@ -42,43 +42,73 @@ static int h_errno;
 #include <net/security.h>
 #endif /* NET_SECURITY */
 
+static int handle_plugin(const char *host,
+                        const char *service, const char *plugin)
+/* get a socket mediated through a given external command */
+{
+    if (plugin) 
+    {
+       int fds[2];
+       if (socketpair(AF_UNIX,SOCK_STREAM,0,fds))
+       {
+           error(0, 0, "fetchmail: socketpair failed: %s(%d)",strerror(errno),errno);
+           return -1;
+       }
+       if (!fork())
+       {
+           dup2(fds[0],0);
+           dup2(fds[0],1);
+           if (outlevel >= O_VERBOSE)
+               error(0, 0, "running %s %s %s", plugin, host, service);
+           execlp(plugin,plugin,host,service,0);
+           error(0, 0, "execl(%s) failed: %s (%d)",
+                 plugin, strerror(errno), errno);
+           exit(0);
+       }
+       return fds[1];
+    }
+}
+
 #if INET6
-int SockOpen(const char *host, const char *service, const char *options)
+int SockOpen(const char *host, const char *service, const char *options,
+            const char *plugin)
 {
-  int i;
-  struct addrinfo *ai, req;
+    int i;
+    struct addrinfo *ai, req;
 #if NET_SECURITY
-  void *request = NULL;
-  int requestlen;
+    void *request = NULL;
+    int requestlen;
 #endif /* NET_SECURITY */
 
-  memset(&req, 0, sizeof(struct addrinfo));
-  req.ai_socktype = SOCK_STREAM;
+    if (plugin)
+       return handle_plugin(host,service,plugin);
+    memset(&req, 0, sizeof(struct addrinfo));
+    req.ai_socktype = SOCK_STREAM;
 
-  if (i = getaddrinfo(host, service, &req, &ai)) {
-    error(0, 0, "fetchmail: getaddrinfo(%s.%s): %s(%d)", host, service, gai_strerror(i), i);
-    return -1;
-  };
+    if (i = getaddrinfo(host, service, &req, &ai)) {
+       error(0, 0, "fetchmail: getaddrinfo(%s.%s): %s(%d)", host, service, gai_strerror(i), i);
+       return -1;
+    };
 
 #if NET_SECURITY
-  if (!options)
-    requestlen = 0;
-  else
-    if (net_security_strtorequest((char *)options, &request, &requestlen))
-      goto ret;
+    if (!options)
+       requestlen = 0;
+    else
+       if (net_security_strtorequest((char *)options, &request, &requestlen))
+           goto ret;
 
-  i = inner_connect(ai, request, requestlen, NULL, NULL, "fetchmail", NULL);
-  if (request)
-    free(request);
+    i = inner_connect(ai, request, requestlen, NULL, NULL, "fetchmail", NULL);
+    if (request)
+       free(request);
 
-ret:
+ ret:
 #else /* NET_SECURITY */
-  i = inner_connect(ai, NULL, 0, NULL, NULL, "fetchmail", NULL);
+    i = inner_connect(ai, NULL, 0, NULL, NULL, "fetchmail", NULL);
 #endif /* NET_SECURITY */
 
-  freeaddrinfo(ai);
+    freeaddrinfo(ai);
 
-  return i;
+    return i;
 };
 #else /* INET6 */
 #ifndef HAVE_INET_ATON
@@ -91,7 +121,8 @@ ret:
 #endif
 #endif /* HAVE_INET_ATON */
 
-int SockOpen(const char *host, int clientPort, const char *options)
+int SockOpen(const char *host, int clientPort, const char *options,
+            const char *plugin)
 {
     int sock;
 #ifndef HAVE_INET_ATON
@@ -100,6 +131,12 @@ int SockOpen(const char *host, int clientPort, const char *options)
     struct sockaddr_in ad;
     struct hostent *hp;
 
+    if (plugin) {
+      char buf[10];
+      sprintf(buf,"%d",clientPort);
+      return handle_plugin(host,buf,plugin);
+    }
+
     memset(&ad, 0, sizeof(ad));
     ad.sin_family = AF_INET;
 
index a9882ce18f5ed3c4930c868856c410b3b65c54c9..fdc395d97542fa5e24e6313d33bd963f90ee4e22 100644 (file)
--- a/socket.h
+++ b/socket.h
@@ -9,9 +9,11 @@
 
 /* Create a new client socket; returns (FILE *)NULL on error */
 #if INET6
-int SockOpen(const char *host, const char *service, const char *options);
+int SockOpen(const char *host, const char *service, const char *options,
+            const char *plugin);
 #else /* INET6 */
-int SockOpen(const char *host, int clientPort, const char *options);
+int SockOpen(const char *host, int clientPort, const char *options,
+            const char *plugin);
 #endif /* INET6 */
 
 /*