* 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.
stringdump("monitor", ctl->server.monitor);
#endif /* linux */
+ stringdump("plugin", ctl->server.plugin);
+ stringdump("plugout", ctl->server.plugout);
+
indent(0);
fputs("'users': ", stdout);
indent('[');
#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
<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>
<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>
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>
<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"><esr@snark.thyrsus.com></A></ADDRESS>
FLAG_MERGE(server.interface_pair);
#endif /* linux */
+ FLAG_MERGE(server.plugin);
+ FLAG_MERGE(server.plugout);
FLAG_MERGE(wildcard);
FLAG_MERGE(remotename);
FLAG_MERGE(password);
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");
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 */
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
T}
.TE
-Here are the legal user options:
+Here are the legal server options:
.TS
l l lw34.
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}
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 = (
# leave localdomains out
('interface', 'String'),
('monitor', 'String'),
+ ('plugin', 'String'),
+ ('plugout', 'String'),
('netsec', 'String'))
def dump(self, folded):
#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 =
{"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 },
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:
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");
netsec { return NETSEC; }
interface { return INTERFACE; }
monitor { return MONITOR; }
+plugin { return PLUGIN; }
+plugout { return PLUGIN; }
batchlimit { return BATCHLIMIT; }
fetchlimit { return FETCHLIMIT; }
expunge { return EXPUNGE; }
%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
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;}
# 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
#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 */
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 &&
#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
#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
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;
/* 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 */
/*