aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--NEWS3
-rw-r--r--conf.c8
-rw-r--r--configure.in7
-rw-r--r--fetchmail-features.html6
-rw-r--r--fetchmail.c42
-rw-r--r--fetchmail.h2
-rw-r--r--fetchmail.man38
-rwxr-xr-xfetchmailconf10
-rw-r--r--interface.c171
-rw-r--r--options.c10
-rw-r--r--rcfile_y.y14
11 files changed, 265 insertions, 46 deletions
diff --git a/NEWS b/NEWS
index 5f29565d..cb216c12 100644
--- a/NEWS
+++ b/NEWS
@@ -6,6 +6,9 @@
Release Notes:
+fetchmail-4.7.8 ():
+* FreeBSD support for interface and monitor options by Andy Doran <ad@psn.ie>.
+
fetchmail-4.7.7 (Tue Feb 2 18:57:04 EST 1999):
* Fixed off-by-one error in batchlimit logic (thanks to Brian Warner).
* Added MD5 checksums to web page.
diff --git a/conf.c b/conf.c
index b12c8d76..e7f9f9c9 100644
--- a/conf.c
+++ b/conf.c
@@ -132,8 +132,10 @@ void dump_config(struct runctl *runp, struct query *querylist)
* We need this in order to know whether `interface' and `monitor'
* are valid options or not.
*/
-#ifdef linux
+#if defined(linux)
fputs("os_type = 'linux'\n", stdout);
+#elif defined(__FreeBSD__)
+ fputs("os_type = 'freebsd'\n", stdout);
#else
fputs("os_type = 'generic'\n", stdout);
#endif
@@ -275,10 +277,10 @@ void dump_config(struct runctl *runp, struct query *querylist)
listdump("aka", ctl->server.akalist);
listdump("localdomains", ctl->server.localdomains);
-#ifdef linux
+#if defined(linux) || defined(__FreeBSD__)
stringdump("interface", ctl->server.interface);
stringdump("monitor", ctl->server.monitor);
-#endif /* linux */
+#endif /* linux || __FreeBSD__ */
stringdump("plugin", ctl->server.plugin);
stringdump("plugout", ctl->server.plugout);
diff --git a/configure.in b/configure.in
index 56098371..32ae87e1 100644
--- a/configure.in
+++ b/configure.in
@@ -57,6 +57,13 @@ then
fi
fi
+# Check for FreeBSD special case: -lkvm needed
+if test `uname` = "FreeBSD"
+then
+ echo "Adding -lkvm to standard libraries"
+ LIBS="$LIBS -lkvm"
+fi
+
# i18n
# Arnaldo Carvalho de Melo <acme@conectiva.com.br>
# Sat Nov 7 15:39:03 EDT 1998
diff --git a/fetchmail-features.html b/fetchmail-features.html
index 191197dc..a243bfea 100644
--- a/fetchmail-features.html
+++ b/fetchmail-features.html
@@ -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: 1999/01/10 00:10:42 $
+<td width="30%" align=right>$Date: 1999/02/07 17:03:04 $
</table>
<HR>
@@ -18,6 +18,8 @@
<H2>Since 4.0:</H2>
<UL>
+<LI>The interface and monitor options now work with freeBSD.
+
<LI> Fetchmail now sends RFC1894-conformant bouncemail on SMTP and LMTP errors.
<LI> Full support for LMTP according to RFC2033.
@@ -166,7 +168,7 @@ get-mail, gwpop, pimp-1.0, pop-perl5-1.2, popc, popmail-1.6 and upop.<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: 1999/01/10 00:10:42 $
+<td width="30%" align=right>$Date: 1999/02/07 17:03:04 $
</table>
<P><ADDRESS>Eric S. Raymond <A HREF="mailto:esr@thyrsus.com">&lt;esr@snark.thyrsus.com&gt;</A></ADDRESS>
diff --git a/fetchmail.c b/fetchmail.c
index 116adafa..47133a93 100644
--- a/fetchmail.c
+++ b/fetchmail.c
@@ -19,6 +19,9 @@
#include <syslog.h>
#endif
#include <pwd.h>
+#ifdef __FreeBSD__
+#include <grp.h>
+#endif
#include <errno.h>
#include <sys/time.h>
#include <sys/types.h>
@@ -137,6 +140,27 @@ void itimerthread(void* dummy) {
}
#endif
+#ifdef __FreeBSD__
+/* drop SGID kmem privileage until we need it */
+static void dropprivs(void)
+{
+ struct group *gr;
+ gid_t egid;
+ gid_t rgid;
+
+ egid = getegid();
+ rgid = getgid();
+ gr = getgrgid(egid);
+
+ if (gr && !strcmp(gr->gr_name, "kmem"))
+ {
+ extern void interface_set_gids(gid_t egid, gid_t rgid);
+ interface_set_gids(egid, rgid);
+ setegid(rgid);
+ }
+}
+#endif
+
int main (int argc, char **argv)
{
int st, bkgd = FALSE;
@@ -147,6 +171,10 @@ int main (int argc, char **argv)
char *netrc_file, *tmpbuf;
pid_t pid;
+#ifdef __FreeBSD__
+ dropprivs();
+#endif
+
envquery(argc, argv);
#ifdef ENABLE_NLS
bindtextdomain(PACKAGE, LOCALEDIR);
@@ -548,11 +576,11 @@ int main (int argc, char **argv)
}
}
-#if defined(linux) && !INET6
+#if (defined(linux) && !INET6) || defined(__FreeBSD__)
/* interface_approve() does its own error logging */
if (!interface_approve(&ctl->server))
continue;
-#endif /* defined(linux) && !INET6 */
+#endif /* (defined(linux) && !INET6) || defined(__FreeBSD__) */
querystatus = query_host(ctl);
@@ -577,7 +605,7 @@ int main (int argc, char **argv)
((querystatus!=PS_NOMAIL) || (outlevel==O_DEBUG)))
report(stdout, _("Query status=%d\n"), querystatus);
-#if defined(linux) && !INET6
+#if (defined(linux) && !INET6) || defined (__FreeBSD__)
if (ctl->server.monitor)
{
/*
@@ -588,7 +616,7 @@ int main (int argc, char **argv)
sleep(3);
interface_note_activity(&ctl->server);
}
-#endif /* defined(linux) && !INET6 */
+#endif /* (defined(linux) && !INET6) || defined(__FreeBSD__) */
}
}
@@ -803,11 +831,11 @@ static void optmerge(struct query *h2, struct query *h1, int force)
FLAG_MERGE(server.checkalias);
FLAG_MERGE(server.uidl);
-#ifdef linux
+#if defined(linux) || defined(__FreeBSD__)
FLAG_MERGE(server.interface);
FLAG_MERGE(server.monitor);
FLAG_MERGE(server.interface_pair);
-#endif /* linux */
+#endif /* linux || defined(__FreeBSD__) */
FLAG_MERGE(server.plugin);
FLAG_MERGE(server.plugout);
@@ -1584,7 +1612,7 @@ static void dump_params (struct runctl *runp,
}
}
}
-#ifdef linux
+#if defined(linux) || defined(__FreeBSD__)
if (ctl->server.interface)
printf(_(" Connection must be through interface %s.\n"), ctl->server.interface);
else if (outlevel >= O_VERBOSE)
diff --git a/fetchmail.h b/fetchmail.h
index fa8a0e9e..e0e53933 100644
--- a/fetchmail.h
+++ b/fetchmail.h
@@ -195,7 +195,7 @@ struct hostdata /* shared among all user connections to given server */
flag checkalias; /* resolve aliases by comparing IPs? */
-#ifdef linux
+#if defined(linux) || defined(__FreeBSD__)
char *interface;
char *monitor;
int monitor_io;
diff --git a/fetchmail.man b/fetchmail.man
index 6eb9a289..0cb7f688 100644
--- a/fetchmail.man
+++ b/fetchmail.man
@@ -413,7 +413,9 @@ etc.). The field before the second slash is the acceptable IP address.
The field after the second slash is a mask which specifies a range of
IP addresses to accept. If no mask is present 255.255.255.255 is
assumed (i.e. an exact match). This option is currently only supported
-under Linux.
+under Linux and FreeBSD. Please see the
+.B monitor
+section for below for FreeBSD specific information.
.TP
.B \-M interface, --monitor interface
(Keyword: monitor)
@@ -422,7 +424,16 @@ after a period of inactivity (e.g. PPP links) to remain up
indefinitely. This option identifies a system TCP/IP interface to be
monitored for activity. After each poll interval, if the link is up but
no other activity has occurred on the link, then the poll will be
-skipped. This option is currently only supported under Linux.
+skipped. This option is currently only supported under Linux and FreeBSD.
+For the
+.B monitor
+and
+.B interface
+options to work for non root users under FreeBSD, the fetchmail binary
+must be installed SGID kmem. This would be a security hole, but
+fetchmail runs with the effective GID set to that of the kmem group
+.I only
+when interface data is being collected.
.TP
.B \-A, --auth
(Keyword: auth[enticate])
@@ -1702,7 +1713,8 @@ successfully retrieved mail. Otherwise the returned error status is
that of the last host queried.
.SH AUTHOR
-Eric S. Raymond <esr@snark.thyrsus.com>.
+Eric S. Raymond <esr@snark.thyrsus.com>. Too many other people to
+name here have contributed code and patches.
This program is descended from and replaces
.IR popclient ,
by Carl Harris <ceharris@mal.com>; the internals have become quite different,
@@ -1767,16 +1779,16 @@ mailserver-side filter that consolidates the contents of all envelope
headers into a single one (procmail, mailagent, or maildrop can be
orogrammed to do this fairly easily).
.PP
-Use of any of the supported protocols other than POP3 with OTP or RPA, APOP,
-KPOP, IMAP-K4, IMAP-GSS, or ETRN requires that the program send unencrypted
-passwords over the TCP/IP connection to the mailserver. This creates
-a risk that name/password pairs might be snaffled with a packet
-sniffer or more sophisticated monitoring software. Under Linux, the
---interface option can be used to restrict polling to availability of
-a specific interface device with a specific local IP address, but
-snooping is still possible if (a) either host has a network device
-that can be opened in promiscuous mode, or (b) the intervening network
-link can be tapped.
+Use of any of the supported protocols other than POP3 with OTP or RPA,
+APOP, KPOP, IMAP-K4, IMAP-GSS, or ETRN requires that the program send
+unencrypted passwords over the TCP/IP connection to the mailserver.
+This creates a risk that name/password pairs might be snaffled with a
+packet sniffer or more sophisticated monitoring software. Under Linux
+and FreeBSD, the --interface option can be used to restrict polling to
+availability of a specific interface device with a specific local IP
+address, but snooping is still possible if (a) either host has a
+network device that can be opened in promiscuous mode, or (b) the
+intervening network link can be tapped.
.PP
Use of the %F or %T escapes in an mda option could open a security
hole, because they pass text manipulable by an attacker to a shell
diff --git a/fetchmailconf b/fetchmailconf
index 846ed1d7..576774f9 100755
--- a/fetchmailconf
+++ b/fetchmailconf
@@ -832,8 +832,8 @@ fetchmail from triggering an expensive dial-out if the
interface is not already active.
The `interface' and `monitor' options are available
-only for Linux systems. See the fetchmail manual page
-for details on these.
+only for Linux and freeBSD systems. See the fetchmail
+manual page for details on these.
The `netsec' option will be configurable only if fetchmail
was compiled with IPV6 support. If you need to use it,
@@ -1006,16 +1006,16 @@ class ServerEdit(Frame, MyWidget):
self.server.localdomains, None, None, mdropwin, multihelp)
mdropwin.pack(fill=X)
- if os_type == 'linux' or 'netsec' in feature_options:
+ if os_type == 'linux' or os_type == 'freebsd' or 'netsec' in feature_options:
secwin = Frame(rightwin, relief=RAISED, bd=5)
Label(secwin, text="Security").pack(side=TOP)
# Don't actually let users set this. KPOP sets it implicitly
# ButtonBar(secwin, 'Authorization mode:',
# self.auth, authlist, 1, None).pack(side=TOP)
- if os_type == 'linux' or 'interface' in dictmembers:
+ if os_type == 'linux' or os_type == 'freebsd' or 'interface' in dictmembers:
LabeledEntry(secwin, 'IP range to check before poll:',
self.interface, leftwidth).pack(side=TOP, fill=X)
- if os_type == 'linux' or 'monitor' in dictmembers:
+ if os_type == 'linux' or os_type == 'freebsd' or 'monitor' in dictmembers:
LabeledEntry(secwin, 'Interface to monitor:',
self.monitor, leftwidth).pack(side=TOP, fill=X)
if 'netsec' in feature_options or 'netsec' in dictmembers:
diff --git a/interface.c b/interface.c
index fafc32d4..75d975f9 100644
--- a/interface.c
+++ b/interface.c
@@ -4,14 +4,19 @@
* This module was implemented by George M. Sipe <gsipe@mindspring.com>
* or <gsipe@acm.org> and is:
*
- * Copyright (c) 1996,1997 by George M. Sipe - ALL RIGHTS RESERVED
+ * Copyright (c) 1996,1997 by George M. Sipe
+ *
+ * FreeBSD specific portions written by and Copyright (c) 1999
+ * Andy Doran <ad@psn.ie>.
*
* This is free software; you can redistribute it and/or modify it under
* the terms of the GNU General Public License as published by the Free
* Software Foundation; version 2, or (at your option) any later version.
*/
+#include <sys/types.h>
+#include <sys/param.h>
-#if defined(linux) && !defined(INET6)
+#if (defined(linux) && !defined(INET6)) || defined(__FreeBSD__)
#include "config.h"
#include <stdio.h>
@@ -27,6 +32,14 @@
#include <netinet/in.h>
#include <arpa/inet.h>
#include <net/if.h>
+#if defined(__FreeBSD__)
+#if __FreeBSD_version >= 300001
+#include <net/if_var.h>
+#endif
+#include <kvm.h>
+#include <nlist.h>
+#include <sys/fcntl.h>
+#endif
#include "config.h"
#include "fetchmail.h"
#include "i18n.h"
@@ -66,6 +79,9 @@ void interface_init(void)
}
}
+
+#if defined(linux)
+
static int _get_ifinfo_(int socket_fd, FILE *stats_file, const char *ifname,
ifinfo_t *ifinfo)
/* get active network interface information - return non-zero upon success */
@@ -156,6 +172,155 @@ static int get_ifinfo(const char *ifname, ifinfo_t *ifinfo)
return(result);
}
+#elif defined __FreeBSD__
+
+static kvm_t *kvmfd;
+static struct nlist symbols[] =
+{
+ {"_ifnet"},
+ {NULL}
+};
+static u_long ifnet_savedaddr;
+static gid_t if_rgid;
+static gid_t if_egid;
+
+void
+interface_set_gids(gid_t egid, gid_t rgid)
+{
+ if_rgid = rgid;
+ if_egid = egid;
+}
+
+static int
+openkvm(void)
+{
+ if ((kvmfd = kvm_open(NULL, NULL, NULL, O_RDONLY, NULL)) == NULL)
+ return FALSE;
+
+ if (kvm_nlist(kvmfd, symbols) < 0)
+ return FALSE;
+
+ if (kvm_read(kvmfd, (unsigned long) symbols[0].n_value, &ifnet_savedaddr, sizeof(unsigned long)) == -1)
+ return FALSE;
+
+ return TRUE;
+}
+
+static int
+get_ifinfo(const char *ifname, ifinfo_t *ifinfo)
+{
+ char tname[16];
+ char iname[16];
+ struct ifnet ifnet;
+ unsigned long ifnet_addr = ifnet_savedaddr;
+#if __FreeBSD_version >= 300001
+ struct ifnethead ifnethead;
+ struct ifaddrhead ifaddrhead;
+#endif
+ struct ifaddr ifaddr;
+ unsigned long ifaddr_addr;
+ struct sockaddr sa;
+ unsigned long sa_addr;
+ uint i;
+
+ if (if_egid)
+ setegid(if_egid);
+
+ for (i = 0; ifname[i] && ifname[i] != '/'; i++)
+ iname[i] = ifname[i];
+
+ iname[i] = '\0';
+
+ if (!kvmfd)
+ {
+ if (!openkvm())
+ {
+ report(stderr, 0, _("Unable to open kvm interface. Make sure fetchmail is SGID kmem."));
+ if (if_egid)
+ setegid(if_rgid);
+ exit(1);
+ }
+ }
+
+#if __FreeBSD_version >= 300001
+ kvm_read(kvmfd, ifnet_savedaddr, (char *) &ifnethead, sizeof ifnethead);
+ ifnet_addr = (u_long) ifnethead.tqh_first;
+#else
+ ifnet_addr = ifnet_savedaddr;
+#endif
+
+ while (ifnet_addr)
+ {
+ kvm_read(kvmfd, ifnet_addr, &ifnet, sizeof(ifnet));
+ kvm_read(kvmfd, (unsigned long) ifnet.if_name, tname, sizeof tname);
+ snprintf(tname, sizeof tname - 1, "%s%d", tname, ifnet.if_unit);
+
+ if (!strcmp(tname, iname))
+ {
+ if (!(ifnet.if_flags & IFF_UP))
+ {
+ if (if_egid)
+ setegid(if_rgid);
+ return 0;
+ }
+
+ ifinfo->rx_packets = ifnet.if_ipackets;
+ ifinfo->tx_packets = ifnet.if_opackets;
+
+#if __FreeBSD_version >= 300001
+ ifaddr_addr = (u_long) ifnet.if_addrhead.tqh_first;
+#else
+ ifaddr_addr = (u_long) ifnet.if_addrlist;
+#endif
+
+ while(ifaddr_addr)
+ {
+ kvm_read(kvmfd, ifaddr_addr, &ifaddr, sizeof(ifaddr));
+ kvm_read(kvmfd, (u_long)ifaddr.ifa_addr, &sa, sizeof(sa));
+
+ if (sa.sa_family != AF_INET)
+ {
+#if __FreeBSD_version >= 300001
+ ifaddr_addr = (u_long) ifaddr.ifa_link.tqe_next;
+#else
+ ifaddr_addr = (u_long) ifaddr.ifa_next;
+#endif
+ continue;
+ }
+
+ ifinfo->addr.s_addr = *(u_long *)(sa.sa_data + 2);
+ kvm_read(kvmfd, (u_long)ifaddr.ifa_dstaddr, &sa, sizeof(sa));
+ ifinfo->dstaddr.s_addr = *(u_long *)(sa.sa_data + 2);
+ kvm_read(kvmfd, (u_long)ifaddr.ifa_netmask, &sa, sizeof(sa));
+ ifinfo->netmask.s_addr = *(u_long *)(sa.sa_data + 2);
+
+ if (if_egid)
+ setegid(if_rgid);
+
+ return 1;
+ }
+
+ if (if_egid)
+ setegid(if_rgid);
+
+ return 0;
+ }
+
+#if __FreeBSD_version >= 300001
+ ifnet_addr = (u_long) ifnet.if_link.tqe_next;
+#else
+ ifnet_addr = (unsigned long) ifnet.if_next;
+#endif
+ }
+
+ if (if_egid)
+ setegid(if_rgid);
+
+ return 0;
+}
+#endif /* defined __FreeBSD__ */
+
+
#ifndef HAVE_INET_ATON
/*
* Note: This is not a true replacement for inet_aton(), as it won't
@@ -313,4 +478,4 @@ int interface_approve(struct hostdata *hp)
return(TRUE);
}
-#endif /* defined(linux) && !defined(INET6) */
+#endif /* (defined(linux) && !defined(INET6)) || defined(__FreeBSD__) */
diff --git a/options.c b/options.c
index 31150162..0832b892 100644
--- a/options.c
+++ b/options.c
@@ -128,10 +128,10 @@ static const struct option longoptions[] = {
{"netsec", required_argument, (int *) 0, LA_NETSEC },
#endif /* INET6 */
-#if defined(linux) && !INET6
+#if (defined(linux) && !INET6) || defined(__FreeBSD__)
{"interface", required_argument, (int *) 0, LA_INTERFACE },
{"monitor", required_argument, (int *) 0, LA_MONITOR },
-#endif /* defined(linux) && !INET6 */
+#endif /* (defined(linux) && !INET6) || defined(__FreeBSD__) */
{"plugin", required_argument, (int *) 0, LA_PLUGIN },
{"plugout", required_argument, (int *) 0, LA_PLUGOUT },
@@ -498,7 +498,7 @@ struct query *ctl; /* option record to be initialized */
#endif /* NET_SECURITY */
break;
-#if defined(linux) && !INET6
+#if (defined(linux) && !INET6) || defined(__FreeBSD__)
case 'I':
case LA_INTERFACE:
interface_parse(optarg, &ctl->server);
@@ -507,7 +507,7 @@ struct query *ctl; /* option record to be initialized */
case LA_MONITOR:
ctl->server.monitor = xstrdup(optarg);
break;
-#endif /* defined(linux) && !INET6 */
+#endif /* (defined(linux) && !INET6) || defined(__FreeBSD__) */
case LA_PLUGIN:
ctl->server.plugin = xstrdup(optarg);
break;
@@ -565,7 +565,7 @@ struct query *ctl; /* option record to be initialized */
P(_(" -f, --fetchmailrc specify alternate run control file\n"));
P(_(" -i, --idfile specify alternate UIDs file\n"));
P(_(" --postmaster specify recipient of last resort\n"));
-#if defined(linux) && !INET6
+#if (defined(linux) && !INET6) || defined(__FreeBSD__)
P(_(" -I, --interface interface required specification\n"));
P(_(" -M, --monitor monitor interface for activity\n"));
#endif
diff --git a/rcfile_y.y b/rcfile_y.y
index d688198c..19e788d5 100644
--- a/rcfile_y.y
+++ b/rcfile_y.y
@@ -207,18 +207,18 @@ serv_option : AKA alias_list
#endif /* NET_SECURITY */
}
| INTERFACE STRING {
-#if defined(linux) && !defined(INET6)
+#if (defined(linux) && !defined(INET6)) || defined(__FreeBSD__)
interface_parse($2, &current.server);
-#else /* defined(linux) && !defined(INET6) */
- fprintf(stderr, "fetchmail: interface option is only supported under Linux\n");
-#endif /* defined(linux) && !defined(INET6) */
+#else /* (defined(linux) && !defined(INET6)) || defined(__FreeBSD__) */
+ fprintf(stderr, "fetchmail: interface option is only supported under Linux and FreeBSD\n");
+#endif /* (defined(linux) && !defined(INET6)) || defined(__FreeBSD__) */
}
| MONITOR STRING {
-#if defined(linux) && !defined(INET6)
+#if (defined(linux) && !defined(INET6)) || defined(__FreeBSD__)
current.server.monitor = xstrdup($2);
-#else /* defined(linux) && !defined(INET6) */
+#else /* (defined(linux) && !defined(INET6)) || defined(__FreeBSD__) */
fprintf(stderr, "fetchmail: monitor option is only supported under Linux\n");
-#endif /* defined(linux) && !defined(INET6) */
+#endif /* (defined(linux) && !defined(INET6) || defined(__FreeBSD__)) */
}
| PLUGIN STRING { current.server.plugin = xstrdup($2); }
| PLUGOUT STRING { current.server.plugout = xstrdup($2); }