diff options
-rw-r--r-- | NEWS | 1 | ||||
-rw-r--r-- | acconfig.h | 5 | ||||
-rw-r--r-- | configure.in | 17 | ||||
-rw-r--r-- | driver.c | 16 | ||||
-rw-r--r-- | etrn.c | 4 | ||||
-rw-r--r-- | fetchmail.c | 33 | ||||
-rw-r--r-- | fetchmail.h | 17 | ||||
-rw-r--r-- | interface.c | 4 | ||||
-rw-r--r-- | options.c | 30 | ||||
-rw-r--r-- | pop3.c | 4 | ||||
-rw-r--r-- | rcfile_l.l | 1 | ||||
-rw-r--r-- | rcfile_y.y | 37 | ||||
-rw-r--r-- | socket.c | 35 | ||||
-rw-r--r-- | socket.h | 4 |
14 files changed, 189 insertions, 19 deletions
@@ -8,6 +8,7 @@ * Allow -c -F to work to flush messages without retrieval. * Read from /etc/fetchmailrc before ~/.fetchmailrc? * Do is_host_alias checks by comparing IP addresses rather than names? +* Make the antispam response configurable. Other TO-DO items: @@ -70,6 +70,11 @@ /* Define if you want OPIE support compiled in */ #undef OPIE +/* Define if you want IPv6 support compiled in */ +#undef INET6 + +/* Define if you want network security support compiled in */ +#undef NETSEC /* Leave that blank line there!! Autoheader needs it. If you're adding to this file, keep in mind: diff --git a/configure.in b/configure.in index 44d453ce..50d653ae 100644 --- a/configure.in +++ b/configure.in @@ -190,6 +190,23 @@ AC_ARG_ENABLE(opie, AC_DEFINE(OPIE,1) ], [with_opie=no]) +AC_ARG_ENABLE(inet6, + [ --enable-inet6 support IPv6 (requires the inet6-apps library)], + [ unset ac_cv_lib_inet6_getaddrinfo; AC_CHECK_LIB(inet6, getaddrinfo,, + [ unset ac_cv_lib_inet6_getaddrinfo; LDFLAGS="$LDFLAGS -L/usr/inet6/lib"; AC_CHECK_LIB(inet6, getaddrinfo,, + [ echo 'configure: cannot find libinet6, which is required for IPv6 support.'; exit 1]) ]) + AC_DEFINE(INET6, 1) ]) + +AC_ARG_ENABLE(netsec, + [ --enable-netsec support network security (req. the inet6-apps library)], + [ unset ac_cv_lib_inet6_net_security_strtorequest; AC_CHECK_LIB(inet6, net_security_strtorequest,, + [ unset ac_cv_lib_inet6_net_security_strtorequest; LDFLAGS="$LDFLAGS -L/usr/inet6/lib"; AC_CHECK_LIB(inet6, net_security_strtorequest,, + [ echo 'configure: cannot find net_security_strtorequest in libinet6, which is required'; + echo ' for network security support. Either it does not exist, or it was'; + echo ' not built with network security support enabled.'; + exit 1]) ]) + AC_DEFINE(NETSEC, 1) ]) + ### use option --with-gssapi=DIR to compile in GSSAPI support AC_ARG_WITH(gssapi, [ --with-gssapi[=DIR] compile in GSSAPI support using libraries in DIR]) @@ -75,7 +75,11 @@ #define SIGCHLD SIGCLD #endif +#if INET6 +#define SMTP_PORT "smtp" /* standard SMTP service port */ +#else /* INET6 */ #define SMTP_PORT 25 /* standard SMTP service port */ +#endif /* INET6 */ #ifndef strstr /* glibc-2.1 declares this as a macro */ extern char *strstr(); /* needed on sysV68 R3V7.1. */ @@ -1639,7 +1643,11 @@ const struct method *proto; /* protocol method table */ { char buf [POPBUFSIZE+1], *realhost; int *msgsizes, len, num, count, new, deletions = 0; +#if INET6 + int fetches, dispatches; +#else /* INET6 */ int port, fetches, dispatches; +#endif /* INET6 */ struct idlist *idp; /* execute pre-initialization command, if any */ @@ -1652,10 +1660,17 @@ const struct method *proto; /* protocol method table */ } /* open a socket to the mail server */ +#if !INET6 port = ctl->server.port ? ctl->server.port : protocol->port; +#endif /* !INET6 */ realhost = ctl->server.via ? ctl->server.via : ctl->server.pollname; +#if INET6 + if ((sock = SockOpen(realhost, ctl->server.service ? ctl->server.service : protocol->service)) == -1) +#else /* INET6 */ if ((sock = SockOpen(realhost, port)) == -1) +#endif /* INET6 */ { +#if !INET6 #ifndef EHOSTUNREACH #define EHOSTUNREACH (-1) #endif @@ -1678,6 +1693,7 @@ const struct method *proto; /* protocol method table */ #endif /* HAVE_RES_SEARCH */ error_complete(0, errno, "local error"); } +#endif /* INET6 */ ok = PS_SOCKET; goto closeUp; } @@ -112,7 +112,11 @@ static int etrn_logout(int sock, struct query *ctl) const static struct method etrn = { "ETRN", /* ESMTP ETRN extension */ +#if INET6 + "smtp", /* standard SMTP port */ +#else /* INET6 */ 25, /* standard SMTP port */ +#endif /* INET6 */ FALSE, /* this is not a tagged protocol */ FALSE, /* this does not use a message delimiter */ etrn_ok, /* parse command response */ diff --git a/fetchmail.c b/fetchmail.c index 995da218..25bb42dc 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -72,6 +72,11 @@ char *home; char *fetchmailhost; /* the name of the host running fetchmail */ char *program_name; /* the name to prefix error messages with */ +#if NETSEC +void *request = NULL; +int requestlen = 0; +#endif /* NETSEC */ + static char *lockfile; /* name of lockfile */ static int querystatus; /* status of query */ static int successes; /* count number of successful polls */ @@ -135,6 +140,15 @@ int main (int argc, char **argv) #ifndef ETRN_ENABLE printf("-ETRN"); #endif /* ETRN_ENABLE */ +#if OPIE + printf("+OPIE"); +#endif /* OPIE */ +#if INET6 + printf("+INET6"); +#endif /* INET6 */ +#if NETSEC + printf("+NETSEC"); +#endif /* NETSEC */ putchar('\n'); /* this is an attempt to help remote debugging */ @@ -410,11 +424,11 @@ int main (int argc, char **argv) } } -#ifdef linux +#if defined(linux) && !INET6 /* interface_approve() does its own error logging */ if (!interface_approve(&ctl->server)) continue; -#endif /* linux */ +#endif /* defined(linux) && !INET6 */ #ifdef HAVE_GETHOSTBYNAME /* @@ -462,7 +476,7 @@ int main (int argc, char **argv) update_str_lists(ctl); #endif /* POP3_ENABLE */ } -#ifdef linux +#if defined(linux) && !INET6 if (ctl->server.monitor) { /* Allow some time for the link to quiesce. One @@ -472,7 +486,7 @@ int main (int argc, char **argv) sleep(3); interface_note_activity(&ctl->server); } -#endif +#endif /* defined(linux) && !INET6 */ } } @@ -718,6 +732,7 @@ static int load_params(int argc, char **argv, int optind) if (ctl->server.timeout == -1) ctl->server.timeout = CLIENT_TIMEOUT; +#if !INET6 /* sanity checks */ if (ctl->server.port < 0) { @@ -733,6 +748,7 @@ static int load_params(int argc, char **argv, int optind) ctl->server.pollname); exit(PS_SYNTAX); } +#endif /* !INET6 */ } } @@ -923,13 +939,22 @@ void dump_params (struct query *ctl) else printf(" Password = '%s'.\n", visbuf(ctl->password)); if (ctl->server.protocol == P_POP3 +#if INET6 + && !strcmp(ctl->server.service, KPOP_PORT) +#else /* INET6 */ && ctl->server.port == KPOP_PORT +#endif /* INET6 */ && ctl->server.preauthenticate == A_KERBEROS_V4) printf(" Protocol is KPOP"); else printf(" Protocol is %s", showproto(ctl->server.protocol)); +#if INET6 + if (ctl->server.service) + printf(" (using service %s)", ctl->server.service); +#else /* INET6 */ if (ctl->server.port) printf(" (using port %d)", ctl->server.port); +#endif /* INET6 */ else if (outlevel == O_VERBOSE) printf(" (using default port)"); if (ctl->server.uidl) diff --git a/fetchmail.h b/fetchmail.h index 72e59ed8..2b42de37 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -13,7 +13,11 @@ #define P_ETRN 8 #define P_IMAP_GSS 9 +#if INET6 +#define KPOP_PORT "kpop" +#else /* INET6 */ #define KPOP_PORT 1109 +#endif /* INET6 */ /* preauthentication types */ #define A_PASSWORD 0 /* password or inline authentication */ @@ -93,7 +97,11 @@ struct hostdata /* shared among all user connections to given server */ struct idlist *akalist; /* server name first, then akas */ struct idlist *localdomains; /* list of pass-through domains */ int protocol; /* protocol type */ +#if INET6 + char *service; +#else /* INET6 */ int port; /* TCP/IP service port number */ +#endif /* INET6 */ int interval; /* # cycles to skip between polls */ int preauthenticate; /* preauthentication mode to try */ int timeout; /* inactivity timout in seconds */ @@ -181,7 +189,11 @@ struct query struct method { char *name; /* protocol name */ +#if INET6 + char *service; +#else /* INET6 */ int port; /* service port */ +#endif /* INET6 */ flag tagged; /* if true, generate & expect command tags */ flag delimited; /* if true, accept "." message delimiter */ int (*parse_response)(); /* response_parsing function */ @@ -243,6 +255,11 @@ extern char *home; /* home directory of invoking user */ extern char *fetchmailhost; /* the name of the host running fetchmail */ extern int pass; /* number of re-polling pass */ +#if NETSEC +extern void *request; +extern int requestlen; +#endif /* NETSEC */ + /* prototypes for globally callable functions */ /* error.c: Error reporting */ diff --git a/interface.c b/interface.c index 370d078d..62f14bfb 100644 --- a/interface.c +++ b/interface.c @@ -11,7 +11,7 @@ * Software Foundation; version 2, or (at your option) any later version. */ -#ifdef linux +#if defined(linux) && !defined(INET6) #include "config.h" #include <stdio.h> @@ -253,4 +253,4 @@ int interface_approve(struct hostdata *hp) return(TRUE); } -#endif /* linux */ +#endif /* defined(linux) && !defined(INET6) */ @@ -102,10 +102,10 @@ static const struct option longoptions[] = { {"expunge", required_argument, (int *) 0, LA_EXPUNGE }, {"mda", required_argument, (int *) 0, LA_MDA }, -#ifdef linux +#if defined(linux) && !INET6 {"interface", required_argument, (int *) 0, LA_INTERFACE }, {"monitor", required_argument, (int *) 0, LA_MONITOR }, -#endif +#endif /* defined(linux) && !INET6 */ {"yydebug", no_argument, (int *) 0, LA_YYDEBUG }, @@ -201,7 +201,11 @@ struct query *ctl; /* option record to be initialized */ else if (strcasecmp(optarg,"kpop") == 0) { ctl->server.protocol = P_POP3; +#if INET6 + ctl->server.service = KPOP_PORT; +#else /* INET6 */ ctl->server.port = KPOP_PORT; +#endif /* INET6 */ ctl->server.preauthenticate = A_KERBEROS_V4; } else if (strcasecmp(optarg,"imap") == 0) @@ -223,7 +227,11 @@ struct query *ctl; /* option record to be initialized */ break; case 'P': case LA_PORT: +#if INET6 + ctl->server.service = optarg; +#else /* INET6 */ ctl->server.port = atoi(optarg); +#endif /* INET6 */ break; case 'A': case LA_AUTHENTICATE: @@ -292,6 +300,13 @@ struct query *ctl; /* option record to be initialized */ ((cp = strtok((char *)NULL, ","))); break; case 'S': +#if NETSEC + if (net_security_strtorequest(optarg, request, &requestlen)) { + fprintf(stderr, "fetchmail: net_security_strtorequest(%s, ...) failed!\n", optarg); + errflag++; + }; + break; +#endif /* NETSEC */ case LA_SMTPHOST: strcpy(buf, optarg); cp = strtok(buf, ","); @@ -326,7 +341,7 @@ struct query *ctl; /* option record to be initialized */ ocount++; break; -#ifdef linux +#if defined(linux) && !INET6 case 'I': case LA_INTERFACE: interface_parse(optarg, &ctl->server); @@ -335,7 +350,7 @@ struct query *ctl; /* option record to be initialized */ case LA_MONITOR: ctl->server.monitor = xstrdup(optarg); break; -#endif +#endif /* defined(linux) && !INET6 */ case 'y': case LA_YYDEBUG: @@ -371,7 +386,7 @@ struct query *ctl; /* option record to be initialized */ fputs(" --invisible suppress Received line & enable host spoofing\n", stderr); fputs(" -f, --fetchmailrc specify alternate run control file\n", stderr); fputs(" -i, --idfile specify alternate UIDs file\n", stderr); -#ifdef linux +#if defined(linux) && !INET6 fputs(" -I, --interface interface required specification\n",stderr); fputs(" -M, --monitor monitor interface for activity\n",stderr); #endif @@ -396,7 +411,12 @@ struct query *ctl; /* option record to be initialized */ fputs(" -n, --norewrite don't rewrite header addresses\n", stderr); fputs(" -l, --limit don't fetch messages over given size\n", stderr); +#if NETSEC + fputs(" -S set security request\n", stderr); + fputs(" --smtphost set SMTP forwarding host\n", stderr); +#else /* NETSEC */ fputs(" -S, --smtphost set SMTP forwarding host\n", stderr); +#endif /* NETSEC */ fputs(" -D, --smtpaddress set SMTP delivery domain to use\n", stderr); fputs(" -b, --batchlimit set batch limit for SMTP connections\n", stderr); fputs(" -B, --fetchlimit set fetch limit for server connections\n", stderr); @@ -519,7 +519,11 @@ static int pop3_logout(int sock, struct query *ctl) const static struct method pop3 = { "POP3", /* Post Office Protocol v3 */ +#if INET6 + "pop3", /* standard POP3 port */ +#else /* INET6 */ 110, /* standard POP3 port */ +#endif /* INET6 */ FALSE, /* this is not a tagged protocol */ TRUE, /* this uses a message delimiter */ pop3_ok, /* parse command response */ @@ -35,6 +35,7 @@ via { return VIA; } aka { return AKA; } local(domains) { return LOCALDOMAINS; } proto(col)? { return PROTOCOL; } +service { return SERVICE; } port { return PORT; } interval { return INTERVAL; } auth(enticate)? { return AUTHENTICATE; } @@ -68,7 +68,7 @@ extern char * yytext; %token <sval> STRING %token <number> NUMBER %token NO KEEP FLUSH FETCHALL REWRITE FORCECR STRIPCR PASS8BITS DROPSTATUS -%token DNS PORT UIDL INTERVAL +%token DNS SERVICE PORT UIDL INTERVAL %% @@ -126,11 +126,24 @@ serv_option : AKA alias_list | PROTOCOL KPOP { current.server.protocol = P_POP3; current.server.preauthenticate = A_KERBEROS_V4; +#if INET6 + current.server.service = KPOP_PORT; +#else /* INET6 */ current.server.port = KPOP_PORT; +#endif /* INET6 */ } | UIDL {current.server.uidl = FLAG_TRUE;} | NO UIDL {current.server.uidl = FLAG_FALSE;} - | PORT NUMBER {current.server.port = $2;} + | SERVICE STRING { +#if INET6 + current.server.service = $2; +#endif /* INET6 */ + } + | PORT NUMBER { +#if !INET6 + current.server.port = $2; +#endif /* !INET6 */ + } | INTERVAL NUMBER {current.server.interval = $2;} | AUTHENTICATE PASSWORD {current.server.preauthenticate = A_PASSWORD;} | AUTHENTICATE KERBEROS4 {current.server.preauthenticate = A_KERBEROS_V4;} @@ -151,18 +164,18 @@ serv_option : AKA alias_list | QVIRTUAL STRING {current.server.qvirtual = xstrdup($2);} | INTERFACE STRING { -#ifdef linux +#if defined(linux) && !defined(INET6) interface_parse($2, ¤t.server); -#else +#else /* defined(linux) && !defined(INET6) */ fprintf(stderr, "fetchmail: interface option is only supported under Linux\n"); -#endif /* linux */ +#endif /* defined(linux) && !defined(INET6) */ } | MONITOR STRING { -#ifdef linux +#if defined(linux) && !defined(INET6) current.server.monitor = xstrdup($2); -#else +#else /* defined(linux) && !defined(INET6) */ fprintf(stderr, "fetchmail: monitor option is only supported under Linux\n"); -#endif /* linux */ +#endif /* defined(linux) && !defined(INET6) */ } | DNS {current.server.dns = FLAG_TRUE;} | NO DNS {current.server.dns = FLAG_FALSE;} @@ -412,7 +425,11 @@ static void record_current(void) #define FLAG_FORCE(fld) if (cmd_opts.fld) current.fld = cmd_opts.fld FLAG_FORCE(server.via); FLAG_FORCE(server.protocol); +#if INET6 + FLAG_FORCE(server.service); +#else /* INET6 */ FLAG_FORCE(server.port); +#endif /* INET6 */ FLAG_FORCE(server.interval); FLAG_FORCE(server.preauthenticate); FLAG_FORCE(server.timeout); @@ -471,7 +488,11 @@ void optmerge(struct query *h2, struct query *h1) #define FLAG_MERGE(fld) if (!h2->fld) h2->fld = h1->fld FLAG_MERGE(server.via); FLAG_MERGE(server.protocol); +#if INET6 + FLAG_MERGE(server.service); +#else /* INET6 */ FLAG_MERGE(server.port); +#endif /* INET6 */ FLAG_MERGE(server.interval); FLAG_MERGE(server.preauthenticate); FLAG_MERGE(server.timeout); @@ -28,6 +28,40 @@ #endif #include "socket.h" +#if NETSEC +#if MAIN +void *request = NULL; +int requestlen = 0; +#else /* MAIN */ +extern void *request; +extern int requestlen; +#endif /* MAIN */ +#endif /* NETSEC */ + +#if INET6 +int SockOpen(const char *host, const char *service) +{ + int i; + struct addrinfo *ai, req; + + memset(&req, 0, sizeof(struct addrinfo)); + req.ai_socktype = SOCK_STREAM; + + if (i = getaddrinfo(host, service, &req, &ai)) { + fprintf(stderr, "fetchmail: getaddrinfo(%s.%s): %s(%d)\n", host, service, gai_strerror(i), i); + return -1; + }; + +#if NETSEC + i = inner_connect(ai, request, requestlen, NULL, NULL, "fetchmail", NULL); +#else /* NETSEC */ + i = inner_connect(ai, NULL, 0, NULL, NULL, "fetchmail", NULL); +#endif /* NETSEC */ + freeaddrinfo(ai); + + return i; +}; +#else /* INET6 */ #ifndef INET_ATON #ifndef INADDR_NONE #ifdef INADDR_BROADCAST @@ -84,6 +118,7 @@ int SockOpen(const char *host, int clientPort) return(sock); } +#endif /* INET6 */ #if defined(HAVE_STDARG_H) @@ -8,7 +8,11 @@ #define SOCKET__ /* Create a new client socket; returns (FILE *)NULL on error */ +#if INET6 +int SockOpen(const char *host, const char *service); +#else /* INET6 */ int SockOpen(const char *host, int clientPort); +#endif /* INET6 */ /* Get a string terminated by an '\n' (matches interface of fgets). |