diff options
-rw-r--r-- | NEWS | 5 | ||||
-rw-r--r-- | README | 2 | ||||
-rw-r--r-- | driver.c | 15 | ||||
-rw-r--r-- | fetchmail.c | 19 | ||||
-rw-r--r-- | fetchmail.h | 2 | ||||
-rw-r--r-- | fetchmail.man | 9 | ||||
-rw-r--r-- | options.c | 15 | ||||
-rw-r--r-- | pop3.c | 70 | ||||
-rw-r--r-- | rcfile_l.l | 1 | ||||
-rw-r--r-- | sample.rcfile | 1 |
10 files changed, 129 insertions, 10 deletions
@@ -32,6 +32,11 @@ features -- * Linux packagers: building fetchmail now generates an RPM specfile for it. +* Kerberos support via KPOP protocol (thanks to Chris Hanson). + +* New --check option for asking server whether there is mail without + actually retrieving or deleting it. + bugs -- * Fix buggy getopt specification of P and p options. @@ -32,6 +32,8 @@ with **. * **POP2, POP3, **APOP, **IMAP support. + ** Support for Kerberos user authentication. + ** Host is auto-probed for a working server if no protocol is specified for the connection. Thus you don't need to know what servers are running on your mail host in advance; the @@ -534,6 +534,15 @@ struct method *proto; goto closeUp; } +#ifdef KERBEROS_V4 + if (queryctl->protocol == P_KPOP) + { + ok = (pop3_kerberos_auth (socket, queryctl)); + if (ok != 0) + goto cleanUp; + } +#endif + /* accept greeting message from mail server */ ok = (protocol->parse_response)(socket, buf); if (alarmed || ok != 0) @@ -560,7 +569,7 @@ struct method *proto; count, count > 1 ? "s" : "", queryctl->servername); - if (count > 0) + if ((count > 0) && (!check_only)) { if (queryctl->mda[0] == '\0') if ((mboxfd = Socket(queryctl->smtphost, SMTP_PORT)) < 0 @@ -659,6 +668,10 @@ struct method *proto; close(socket); goto closeUp; } + else if (check_only) { + ok = ((count > 0) ? PS_SUCCESS : PS_NOMAIL); + goto closeUp; + } else { ok = gen_transact(socket, protocol->exit_cmd); if (ok == 0) diff --git a/fetchmail.c b/fetchmail.c index 8be194b9..b86878d5 100644 --- a/fetchmail.c +++ b/fetchmail.c @@ -54,6 +54,7 @@ int yydebug; /* enable parse debugging */ int poll_interval; /* poll interval in seconds */ char *logfile; /* log file for daemon mode */ int quitmode; /* if --quit was set */ +int check_only; /* if --probe was set */ /* miscellaneous global controls */ char *rcfile; /* path name of rc file */ @@ -309,10 +310,18 @@ char **argv; for (hostp = hostlist; hostp; hostp = hostp->next) if (hostp->active && !(implicitmode && hostp->skip) && !hostp->password[0]) { - (void) sprintf(tmpbuf, "Enter password for %s@%s: ", - hostp->remotename, hostp->servername); - (void) strncpy(hostp->password, - (char *)getpassword(tmpbuf),PASSWORDLEN-1); + if (hostp->protocol == P_KPOP) + /* Server doesn't care what the password is, but there + must be some non-null string here. */ + (void) strncpy(hostp->password, + hostp->remotename, PASSWORDLEN-1); + else + { + (void) sprintf(tmpbuf, "Enter password for %s@%s: ", + hostp->remotename, hostp->servername); + (void) strncpy(hostp->password, + (char *)getpassword(tmpbuf),PASSWORDLEN-1); + } } /* @@ -386,6 +395,7 @@ int proto; case P_POP3: return("POP3"); break; case P_IMAP: return("IMAP"); break; case P_APOP: return("APOP"); break; + case P_KPOP: return("KPOP"); break; default: return("unknown?!?"); break; } } @@ -425,6 +435,7 @@ struct hostrec *queryctl; break; case P_POP3: case P_APOP: + case P_KPOP: return(doPOP3(queryctl)); break; case P_IMAP: diff --git a/fetchmail.h b/fetchmail.h index 99f16c87..d2bfc6d1 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -17,6 +17,7 @@ #define P_POP3 3 #define P_IMAP 4 #define P_APOP 5 +#define P_KPOP 6 /* definitions for buffer sizes -- somewhat arbitrary */ #define POPBUFSIZE 512 /* per RFC 937 */ @@ -110,6 +111,7 @@ extern int yydebug; /* enable parse debugging */ extern int poll_interval; /* poll interval in seconds */ extern char *logfile; /* log file for daemon mode */ extern int quitmode; /* if --quit was set */ +extern int check_only; /* if --check was set */ /* miscellaneous global controls */ extern char *rcfile; /* path name of rc file */ diff --git a/fetchmail.man b/fetchmail.man index 2027b1b0..39ba3594 100644 --- a/fetchmail.man +++ b/fetchmail.man @@ -76,6 +76,10 @@ machine). POP3/IMAP only. Delete old (previously retrieved) messages from the mailserver before retrieving new messages. .TP +.B \-c, --check +Return a status code to indicate whether there is mail waiting, +without actually fetching or deleting mail (see EXIT CODES below). +.TP .B \-f pathname, --fetchmailrc pathname Specify a non-default name for the .I .fetchmailrc @@ -110,6 +114,8 @@ Post Office Protocol 2 Post Office Protocol 3 .IP APOP Use POP3 with MD5 authentication. +.IP KPOP +POP3 with Kerberos authentication. .RE .TP .B \-P, --port @@ -124,7 +130,7 @@ behavior when no folder is specified. .TP .B \-s, --silent Silent mode. Suppresses all progress/status messages that are normally -echoed to stderr during a fetch. If both the +echoed to standard error during a fetch. If both the .B silent and .B verbose @@ -380,6 +386,7 @@ Legal protocol identifiers are pop3 (or POP3) imap (or IMAP) apop (or APOP) + kpop (or APOP) .PP You can use the `noise' keywords \fBand\fR, \fBwith\fR, \fBhas\fR, \fBwants\fR, and \fBoptions\fR anywhere in an entry to make @@ -37,8 +37,9 @@ #define LA_LOGFILE 17 #define LA_QUIT 18 #define LA_NOREWRITE 19 -#define LA_HELP 20 -#define LA_YYDEBUG 21 +#define LA_CHECK 20 +#define LA_HELP 21 +#define LA_YYDEBUG 22 static char *shortoptions = "P:p:VaKkvS:m:sFd:f:u:r:L:qN?"; static struct option longoptions[] = { @@ -62,6 +63,7 @@ static struct option longoptions[] = { {"logfile", required_argument, (int *) 0, LA_LOGFILE }, {"quit", no_argument, (int *) 0, LA_QUIT }, {"norewrite", no_argument, (int *) 0, LA_NOREWRITE }, + {"check", no_argument, (int *) 0, LA_CHECK }, {"help", no_argument, (int *) 0, LA_HELP }, {"yydebug", no_argument, (int *) 0, LA_YYDEBUG }, {(char *) 0, no_argument, (int *) 0, 0 } @@ -150,6 +152,8 @@ struct hostrec *queryctl; queryctl->protocol = P_IMAP; else if (strcasecmp(optarg,"apop") == 0) queryctl->protocol = P_APOP; + else if (strcasecmp(optarg,"kpop") == 0) + queryctl->protocol = P_KPOP; else { fprintf(stderr,"Invalid protocol '%s'\n specified.\n", optarg); errflag++; @@ -201,6 +205,10 @@ struct hostrec *queryctl; case LA_NOREWRITE: queryctl->norewrite = 1; break; + case 'c': + case LA_CHECK: + check_only = 1; + break; case LA_YYDEBUG: yydebug = 1; break; @@ -216,7 +224,7 @@ struct hostrec *queryctl; fputs("usage: fetchmail [options] [server ...]\n", stderr); fputs(" Options are as follows:\n",stderr); fputs(" -?, --help display this option help\n", stderr); - fputs(" -p, --protocol specify pop2, pop3, imap, apop\n", stderr); + fputs(" -p, --protocol specify pop2, pop3, imap, apop, rpop, kpop\n", stderr); fputs(" -V, --version display version info\n", stderr); fputs(" -a, --all retrieve old and new messages\n", stderr); fputs(" -F, --flush delete old messages from server\n", stderr); @@ -231,6 +239,7 @@ struct hostrec *queryctl; fputs(" -u, --username specify users's login on server\n", stderr); fputs(" -r, --remote specify remote folder name\n", stderr); fputs(" -L, --logfile specify logfile name\n", stderr); + fputs(" -c, --check check for messages without retrieving\n", stderr); return(-1); } @@ -14,6 +14,15 @@ #include <config.h> #include <stdio.h> + +#ifdef KERBEROS_V4 +#include <krb.h> +#include <des.h> +/* <netinet/in.h> must be included before "socket.h". */ +#include <netinet/in.h> +#include <netdb.h> +#endif + #include "socket.h" #include "fetchmail.h" @@ -99,6 +108,12 @@ char *greeting; } switch (queryctl->protocol) { + case P_KPOP: +#ifndef KERBEROS_V4 + strcat (buf, "KPOP support not compiled into this executable.\n"); + return(PS_ERROR); +#endif + case P_POP3: if ((gen_transact(socket,"USER %s", queryctl->remotename)) != 0) return(PS_ERROR); @@ -121,6 +136,54 @@ char *greeting; return(0); } +#ifdef KERBEROS_V4 +int +pop3_kerberos_auth (socket, queryctl) + int socket; + struct hostrec * queryctl; +{ + char * host_primary; + KTEXT ticket; + MSG_DAT msg_data; + CREDENTIALS cred; + Key_schedule schedule; + int rem; + + /* Get the primary name of the host. */ + { + struct hostent * hp = (gethostbyname (queryctl->servername)); + if (hp == 0) + { + fprintf (stderr, "MAILHOST unknown: %s\n", queryctl->servername); + return (PS_ERROR); + } + host_primary = ((char *) (malloc ((strlen (hp -> h_name)) + 1))); + strcpy (host_primary, (hp -> h_name)); + } + + ticket = ((KTEXT) (malloc (sizeof (KTEXT_ST)))); + rem + = (krb_sendauth (0L, socket, ticket, "pop", + host_primary, + ((char *) (krb_realmofhost (host_primary))), + ((unsigned long) 0), + (&msg_data), + (&cred), + (schedule), + ((struct sockaddr_in *) 0), + ((struct sockaddr_in *) 0), + "KPOPV0.1")); + free (ticket); + free (host_primary); + if (rem != KSUCCESS) + { + fprintf (stderr, "kerberos error: %s\n", (krb_get_err_text (rem))); + return (PS_ERROR); + } + return (0); +} +#endif /* KERBEROS_V4 */ + static pop3_getrange(socket, queryctl, countp) /* get range of messages to be fetched */ int socket; @@ -213,7 +276,12 @@ struct hostrec *queryctl; fprintf(stderr,"Option --remote is not supported with POP3\n"); return(PS_SYNTAX); } - + if (queryctl->protocol == P_KPOP) + { + struct method kpop_method = pop3; + kpop_method.port = 1109; + return(do_protocol(queryctl, &kpop_method)); + } return(do_protocol(queryctl, &pop3)); } @@ -60,6 +60,7 @@ options {/* EMPTY */} (pop3)|(POP3) { yylval.proto = P_POP3; return PROTO; } (imap)|(IMAP) { yylval.proto = P_IMAP; return PROTO; } (apop)|(APOP) { yylval.proto = P_APOP; return PROTO; } +(kpop)|(KPOP) { yylval.proto = P_KPOP; return PROTO; } (#.*)?\\?\n { prc_lineno++; } /* newline is ignored */ diff --git a/sample.rcfile b/sample.rcfile index 8457576d..29bdfd90 100644 --- a/sample.rcfile +++ b/sample.rcfile @@ -45,6 +45,7 @@ # pop3 (or POP3) # imap (or IMAP) # apop (or APOP) +# kpop (or KPOP) # # Basic format is # server SERVERNAME protocol PROTOCOL username NAME password PASSWORD |