diff options
| -rw-r--r-- | NEWS | 8 | ||||
| -rw-r--r-- | etrn.c | 4 | ||||
| -rw-r--r-- | fetchmail.h | 1 | ||||
| -rw-r--r-- | odmr.c | 4 | ||||
| -rw-r--r-- | sink.c | 81 | ||||
| -rw-r--r-- | smtp.c | 52 | ||||
| -rw-r--r-- | smtp.h | 19 | 
7 files changed, 85 insertions, 84 deletions
@@ -22,6 +22,14 @@ change.  MA = Matthias Andree, ESR = Eric S. Raymond, RF = Rob Funk.)  -------------------------------------------------------------------------------- +fetchmail 6.3.2 (to be released): + +* SMTP/LMTP cleanup to fix these two bugs: +  - switch back to SMTP after having tried LMTP hosts (multiple smtphost hosts) +  - switch back to LMTP after sending a bounce. +  The patch removes the global state variable that was the root of this problem. +  Patch by Sunil Shetye. (MA) +  fetchmail 6.3.1 (released 2005-12-19):  # SECURITY FIX IN THIS RELEASE @@ -25,7 +25,7 @@ static int etrn_ok (int sock, char *argbuf)  {      int ok; -    ok = SMTP_ok(sock); +    ok = SMTP_ok(sock, SMTP_MODE);      if (ok == SM_UNRECOVERABLE)  	return(PS_PROTOCOL);      else @@ -40,7 +40,7 @@ static int etrn_getrange(int sock, struct query *ctl, const char *id,      char buf [MSGBUFSIZE+1];      struct idlist *qnp;		/* pointer to Q names */ -    if ((ok = SMTP_ehlo(sock, fetchmailhost,  +    if ((ok = SMTP_ehlo(sock, SMTP_MODE, fetchmailhost,  			ctl->server.esmtp_name, ctl->server.esmtp_password,  			&opts)))      { diff --git a/fetchmail.h b/fetchmail.h index 3b673865..a638df9e 100644 --- a/fetchmail.h +++ b/fetchmail.h @@ -344,6 +344,7 @@ struct query      int wehavesentauthnote;	/* We've sent an authorization failure note */      int wedged;			/* wedged by auth failures or timeouts? */      char *smtphost;		/* actual SMTP host we connected to */ +    char smtphostmode;		/* what's the actual SMTP host's wire protocol? */      int smtp_socket;		/* socket descriptor for SMTP connection */      unsigned int uid;		/* UID of user to deliver to */      struct idlist *skipped;	/* messages skipped on the mail server */ @@ -35,7 +35,7 @@ static int odmr_ok (int sock, char *argbuf)  {      int ok; -    ok = SMTP_ok(sock); +    ok = SMTP_ok(sock, SMTP_MODE);      if (ok == SM_UNRECOVERABLE)  	return(PS_PROTOCOL);      else @@ -51,7 +51,7 @@ static int odmr_getrange(int sock, struct query *ctl, const char *id,      char buf [MSGBUFSIZE+1];      struct idlist *qnp;		/* pointer to Q names */ -    if ((ok = SMTP_ehlo(sock, fetchmailhost,  +    if ((ok = SMTP_ehlo(sock, SMTP_MODE, fetchmailhost,   			ctl->server.esmtp_name, ctl->server.esmtp_password,  			&opts)))      { @@ -58,7 +58,7 @@ void smtp_close(struct query *ctl, int sayquit)      if (ctl->smtp_socket != -1)      {  	if (sayquit) -	    SMTP_quit(ctl->smtp_socket); +	    SMTP_quit(ctl->smtp_socket, ctl->smtphostmode);  	SockClose(ctl->smtp_socket);  	ctl->smtp_socket = -1;      } @@ -68,8 +68,6 @@ void smtp_close(struct query *ctl, int sayquit)  int smtp_open(struct query *ctl)  /* try to open a socket to the appropriate SMTP server for this query */   { -    char *parsed_host = NULL; -      /* maybe it's time to close the socket in order to force delivery */      if (last_smtp_ok > 0 && time((time_t *)NULL) - last_smtp_ok > mytimeout)      { @@ -106,6 +104,7 @@ int smtp_open(struct query *ctl)  	struct idlist	*idp;  	const char *id_me = run.invisible ? ctl->server.truename : fetchmailhost;  	int oldphase = phase; +	char *parsed_host = NULL;  	errno = 0; @@ -126,13 +125,14 @@ int smtp_open(struct query *ctl)  	    ctl->smtphost = idp->id;  /* remember last host tried. */  	    if (ctl->smtphost[0]=='/')  	    { -		ctl->listener = LMTP_MODE; +		ctl->smtphostmode = LMTP_MODE;  		xfree(parsed_host);  		if ((ctl->smtp_socket = UnixOpen(ctl->smtphost))==-1)  		    continue;  	    }  	    else  	    { +		ctl->smtphostmode = ctl->listener;  		parsed_host = xstrdup(idp->id);  		if ((cp = strrchr(parsed_host, '/')))  		{ @@ -157,12 +157,9 @@ int smtp_open(struct query *ctl)  		return(ctl->smtp_socket); /* success */  	    } -	    /* are we doing SMTP or LMTP? */ -	    SMTP_setmode(ctl->listener); -  	    /* first, probe for ESMTP */ -	    if (SMTP_ok(ctl->smtp_socket) == SM_OK && -		    SMTP_ehlo(ctl->smtp_socket, id_me,  +	    if (SMTP_ok(ctl->smtp_socket, ctl->smtphostmode) == SM_OK && +		    SMTP_ehlo(ctl->smtp_socket, ctl->smtphostmode, id_me,  			ctl->server.esmtp_name, ctl->server.esmtp_password,  			&ctl->server.esmtp_options) == SM_OK)  		break;  /* success */ @@ -189,8 +186,8 @@ int smtp_open(struct query *ctl)  		}  	    } -	    if (SMTP_ok(ctl->smtp_socket) == SM_OK &&  -		    SMTP_helo(ctl->smtp_socket, id_me) == SM_OK) +	    if (SMTP_ok(ctl->smtp_socket, ctl->smtphostmode) == SM_OK && +		    SMTP_helo(ctl->smtp_socket, ctl->smtphostmode, id_me) == SM_OK)  		break;  /* success */  	    smtp_close(ctl, 0); @@ -273,8 +270,6 @@ static int send_bouncemail(struct query *ctl, struct msgblk *msg,      bounce_to = (run.bouncemail ? msg->return_path : run.postmaster); -    SMTP_setmode(SMTP_MODE); -      /* can't just use fetchmailhost here, it might be localhost */      if (fqdn_of_host == NULL)  	fqdn_of_host = host_fqdn(0); /* can't afford to bail out and @@ -287,18 +282,18 @@ static int send_bouncemail(struct query *ctl, struct msgblk *msg,      if ((sock = SockOpen("localhost", SMTP_PORT, NULL)) == -1)  	return(FALSE); -    if (SMTP_ok(sock) != SM_OK) +    if (SMTP_ok(sock, SMTP_MODE) != SM_OK)      {  	SockClose(sock);  	return FALSE;      } -    if (SMTP_helo(sock, fetchmailhost) != SM_OK -	|| SMTP_from(sock, "<>", (char *)NULL) != SM_OK -	|| SMTP_rcpt(sock, bounce_to) != SM_OK -	|| SMTP_data(sock) != SM_OK)  +    if (SMTP_helo(sock, SMTP_MODE, fetchmailhost) != SM_OK +	|| SMTP_from(sock, SMTP_MODE, "<>", (char *)NULL) != SM_OK +	|| SMTP_rcpt(sock, SMTP_MODE, bounce_to) != SM_OK +	|| SMTP_data(sock, SMTP_MODE) != SM_OK)      { -	SMTP_quit(sock); +	SMTP_quit(sock, SMTP_MODE);  	SockClose(sock);  	return(FALSE);      } @@ -411,7 +406,8 @@ static int send_bouncemail(struct query *ctl, struct msgblk *msg,      }      SockPrintf(sock, "--%s--\r\n", boundary);  -    if (SMTP_eom(sock) != SM_OK || SMTP_quit(sock)) +    if (SMTP_eom(sock, SMTP_MODE) != SM_OK +	    || SMTP_quit(sock, SMTP_MODE) != SM_OK)      {  	SockClose(sock);  	return(FALSE); @@ -504,7 +500,7 @@ static int handle_smtp_report(struct query *ctl, struct msgblk *msg)       */      if (smtperr >= 400)  	report(stderr, GT_("%cMTP error: %s\n"),  -	      ctl->listener, +	      ctl->smtphostmode,  	      responses[0]);      switch (smtperr) @@ -588,7 +584,7 @@ static int handle_smtp_report_without_bounce(struct query *ctl, struct msgblk *m      if (smtperr >= 400)  	report(stderr, GT_("%cMTP error: %s\n"),  -	      ctl->listener, +	      ctl->smtphostmode,  	      smtp_response);      switch (smtperr) @@ -903,7 +899,8 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg,  	ap = addr;      } -    if ((smtp_err = SMTP_from(ctl->smtp_socket, ap, options)) == SM_UNRECOVERABLE) +    if ((smtp_err = SMTP_from(ctl->smtp_socket, ctl->smtphostmode, +		    ap, options)) == SM_UNRECOVERABLE)      {  	smtp_close(ctl, 0);  	return(PS_TRANSIENT); @@ -912,7 +909,7 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg,      {  	int err = handle_smtp_report(ctl, msg); /* map to PS_TRANSIENT or PS_REFUSED */ -	SMTP_rset(ctl->smtp_socket);    /* stay on the safe side */ +	SMTP_rset(ctl->smtp_socket, ctl->smtphostmode);    /* stay on the safe side */  	return(err);      } @@ -930,7 +927,8 @@ static int open_smtp_sink(struct query *ctl, struct msgblk *msg,  	{  	    const char *address;  	    address = rcpt_address (ctl, idp->id, 1); -	    if ((smtp_err = SMTP_rcpt(ctl->smtp_socket, address)) == SM_UNRECOVERABLE) +	    if ((smtp_err = SMTP_rcpt(ctl->smtp_socket, ctl->smtphostmode, +			    address)) == SM_UNRECOVERABLE)  	    {  		smtp_close(ctl, 0);  transient: @@ -962,14 +960,14 @@ transient:  		    if (outlevel >= O_VERBOSE)  			report(stderr,  			      GT_("%cMTP listener doesn't like recipient address `%s'\n"), -			      ctl->listener, address); +			      ctl->smtphostmode, address);  		    break;  		    case PS_REFUSED:  		    if (outlevel >= O_VERBOSE)  			report(stderr,  			      GT_("%cMTP listener doesn't really like recipient address `%s'\n"), -			      ctl->listener, address); +			      ctl->smtphostmode, address);  		    break;  		}  	    } @@ -980,7 +978,7 @@ transient:  	     * crap. If one of the recipients returned PS_TRANSIENT,  	     * we return exactly that.  	     */ -	    SMTP_rset(ctl->smtp_socket);        /* required by RFC1870 */ +	    SMTP_rset(ctl->smtp_socket, ctl->smtphostmode);        /* required by RFC1870 */  	    goto transient;      }  #ifdef EXPLICIT_BOUNCE_ON_BAD_ADDRESS @@ -1010,10 +1008,10 @@ transient:  	{  	    if (outlevel >= O_VERBOSE)  		report(stderr, GT_("no address matches; no postmaster set.\n")); -	    SMTP_rset(ctl->smtp_socket);	/* required by RFC1870 */ +	    SMTP_rset(ctl->smtp_socket, ctl->smtphostmode);	/* required by RFC1870 */  	    return(PS_REFUSED);  	} -	if ((smtp_err = SMTP_rcpt(ctl->smtp_socket, +	if ((smtp_err = SMTP_rcpt(ctl->smtp_socket, ctl->smtphostmode,  		rcpt_address (ctl, run.postmaster, 0))) == SM_UNRECOVERABLE)  	{  	    smtp_close(ctl, 0); @@ -1022,7 +1020,7 @@ transient:  	if (smtp_err != SM_OK)  	{  	    report(stderr, GT_("can't even send to %s!\n"), run.postmaster); -	    SMTP_rset(ctl->smtp_socket);	/* required by RFC1870 */ +	    SMTP_rset(ctl->smtp_socket, ctl->smtphostmode);	/* required by RFC1870 */  	    return(PS_REFUSED);  	} @@ -1034,7 +1032,8 @@ transient:       * Tell the listener we're ready to send data.       * Some listeners (like zmailer) may return antispam errors here.       */ -    if ((smtp_err = SMTP_data(ctl->smtp_socket)) == SM_UNRECOVERABLE) +    if ((smtp_err = SMTP_data(ctl->smtp_socket, ctl->smtphostmode)) +	    == SM_UNRECOVERABLE)      {  	smtp_close(ctl, 0);  	return(PS_TRANSIENT); @@ -1042,7 +1041,7 @@ transient:      if (smtp_err != SM_OK)      {  	int err = handle_smtp_report(ctl, msg); -	SMTP_rset(ctl->smtp_socket);    /* stay on the safe side */ +	SMTP_rset(ctl->smtp_socket, ctl->smtphostmode);    /* stay on the safe side */  	return(err);      } @@ -1243,7 +1242,7 @@ int open_sink(struct query *ctl, struct msgblk *msg,      else if (!ctl->mda)      {  	report(stderr, GT_("%cMTP connect to %s failed\n"), -	       ctl->listener, +	       ctl->smtphostmode,  	       ctl->smtphost ? ctl->smtphost : "localhost");  #ifndef FALLBACK_MDA @@ -1356,7 +1355,8 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward)      else if (forward)      {  	/* write message terminator */ -	if ((smtp_err = SMTP_eom(ctl->smtp_socket)) == SM_UNRECOVERABLE) +	if ((smtp_err = SMTP_eom(ctl->smtp_socket, ctl->smtphostmode)) +		== SM_UNRECOVERABLE)  	{  	    smtp_close(ctl, 0);  	    return(FALSE); @@ -1365,13 +1365,13 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward)  	{  	    if (handle_smtp_report(ctl, msg) != PS_REFUSED)  	    { -	        SMTP_rset(ctl->smtp_socket);    /* stay on the safe side */ +	        SMTP_rset(ctl->smtp_socket, ctl->smtphostmode);    /* stay on the safe side */  		return(FALSE);  	    }  	    else  	    {  		report(stderr, GT_("SMTP listener refused delivery\n")); -	        SMTP_rset(ctl->smtp_socket);    /* stay on the safe side */ +	        SMTP_rset(ctl->smtp_socket, ctl->smtphostmode);    /* stay on the safe side */  		return(TRUE);  	    }  	} @@ -1386,11 +1386,11 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward)  	 * otherwise the message will get left in the queue and resent  	 * to people who got it the first time.  	 */ -	if (ctl->listener == LMTP_MODE) +	if (ctl->smtphostmode == LMTP_MODE)  	{  	    if (lmtp_responses == 0)  	    { -		SMTP_ok(ctl->smtp_socket);  +		SMTP_ok(ctl->smtp_socket, ctl->smtphostmode);  		/*  		 * According to RFC2033, 503 is the only legal response @@ -1423,7 +1423,8 @@ int close_sink(struct query *ctl, struct msgblk *msg, flag forward)  		responses = xmalloc(sizeof(char *) * lmtp_responses);  		for (errors = i = 0; i < lmtp_responses; i++)  		{ -		    if ((smtp_err = SMTP_ok(ctl->smtp_socket)) == SM_UNRECOVERABLE) +		    if ((smtp_err = SMTP_ok(ctl->smtp_socket, ctl->smtphostmode)) +			    == SM_UNRECOVERABLE)  		    {  			smtp_close(ctl, 0);  			goto unrecov; @@ -39,23 +39,15 @@ static struct opt extensions[] =  char smtp_response[MSGBUFSIZE]; -static char smtp_mode = 'S'; - -void SMTP_setmode(char sl) -/* set whether we are speaking SMTP or LMTP */ -{ -    smtp_mode = sl; -} - -int SMTP_helo(int sock,const char *host) +int SMTP_helo(int sock, char smtp_mode, const char *host)  /* send a "HELO" message to the SMTP listener */  {    int ok;    SockPrintf(sock,"HELO %s\r\n", host);    if (outlevel >= O_MONITOR) -      report(stdout, "SMTP> HELO %s\n", host); -  ok = SMTP_ok(sock); +      report(stdout, "%cMTP> HELO %s\n", smtp_mode, host); +  ok = SMTP_ok(sock, smtp_mode);    return ok;  } @@ -66,7 +58,7 @@ static void SMTP_auth_error(int sock, const char *msg)      if (outlevel >= O_MONITOR) report(stdout, msg);  } -static void SMTP_auth(int sock, char *username, char *password, char *buf) +static void SMTP_auth(int sock, char smtp_mode, char *username, char *password, char *buf)  /* ESMTP Authentication support for fetchmail by Wojciech Polak */  {	  	int c; @@ -115,7 +107,7 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf)  		to64frombits(b64buf, tmp, strlen(tmp));  		SockPrintf(sock, "%s\r\n", b64buf); -		SMTP_ok(sock); +		SMTP_ok(sock, smtp_mode);  	}  	else if (strstr(buf, "PLAIN")) {  		int len; @@ -131,7 +123,7 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf)  		}  		to64frombits(b64buf, tmp, len);  		SockPrintf(sock, "AUTH PLAIN %s\r\n", b64buf); -		SMTP_ok(sock); +		SMTP_ok(sock, smtp_mode);  	}  	else if (strstr(buf, "LOGIN")) {  		if (outlevel >= O_MONITOR) @@ -170,12 +162,12 @@ static void SMTP_auth(int sock, char *username, char *password, char *buf)  		}  		to64frombits(b64buf, password, strlen(password));  		SockPrintf(sock, "%s\r\n", b64buf); -		SMTP_ok(sock); +		SMTP_ok(sock, smtp_mode);  	}  	return;  } -int SMTP_ehlo(int sock, const char *host, char *name, char *password, int *opt) +int SMTP_ehlo(int sock, char smtp_mode, const char *host, char *name, char *password, int *opt)  /* send a "EHLO" message to the SMTP listener, return extension status bits */  {    struct opt *hp; @@ -209,7 +201,7 @@ int SMTP_ehlo(int sock, const char *host, char *name, char *password, int *opt)  	  }        if ((smtp_response[0] == '1' || smtp_response[0] == '2' || smtp_response[0] == '3') && smtp_response[3] == ' ') {  	  if (*opt & ESMTP_AUTH) -		SMTP_auth(sock, name, password, auth_response); +		SMTP_auth(sock, smtp_mode, name, password, auth_response);  	  return SM_OK;        }        else if (smtp_response[3] != '-') @@ -218,7 +210,7 @@ int SMTP_ehlo(int sock, const char *host, char *name, char *password, int *opt)    return SM_UNRECOVERABLE;  } -int SMTP_from(int sock, const char *from, const char *opts) +int SMTP_from(int sock, char smtp_mode, const char *from, const char *opts)  /* send a "MAIL FROM:" message to the SMTP listener */  {      int ok; @@ -233,11 +225,11 @@ int SMTP_from(int sock, const char *from, const char *opts)      SockPrintf(sock,"%s\r\n", buf);      if (outlevel >= O_MONITOR)  	report(stdout, "%cMTP> %s\n", smtp_mode, buf); -    ok = SMTP_ok(sock); +    ok = SMTP_ok(sock, smtp_mode);      return ok;  } -int SMTP_rcpt(int sock, const char *to) +int SMTP_rcpt(int sock, char smtp_mode, const char *to)  /* send a "RCPT TO:" message to the SMTP listener */  {    int ok; @@ -245,11 +237,11 @@ int SMTP_rcpt(int sock, const char *to)    SockPrintf(sock,"RCPT TO:<%s>\r\n", to);    if (outlevel >= O_MONITOR)        report(stdout, "%cMTP> RCPT TO:<%s>\n", smtp_mode, to); -  ok = SMTP_ok(sock); +  ok = SMTP_ok(sock, smtp_mode);    return ok;  } -int SMTP_data(int sock) +int SMTP_data(int sock, char smtp_mode)  /* send a "DATA" message to the SMTP listener */  {    int ok; @@ -257,11 +249,11 @@ int SMTP_data(int sock)    SockPrintf(sock,"DATA\r\n");    if (outlevel >= O_MONITOR)        report(stdout, "%cMTP> DATA\n", smtp_mode); -  ok = SMTP_ok(sock); +  ok = SMTP_ok(sock, smtp_mode);    return ok;  } -int SMTP_rset(int sock) +int SMTP_rset(int sock, char smtp_mode)  /* send a "RSET" message to the SMTP listener */  {    int ok; @@ -269,11 +261,11 @@ int SMTP_rset(int sock)    SockPrintf(sock,"RSET\r\n");    if (outlevel >= O_MONITOR)        report(stdout, "%cMTP> RSET\n", smtp_mode); -  ok = SMTP_ok(sock); +  ok = SMTP_ok(sock, smtp_mode);    return ok;  } -int SMTP_quit(int sock) +int SMTP_quit(int sock, char smtp_mode)  /* send a "QUIT" message to the SMTP listener */  {    int ok; @@ -281,11 +273,11 @@ int SMTP_quit(int sock)    SockPrintf(sock,"QUIT\r\n");    if (outlevel >= O_MONITOR)        report(stdout, "%cMTP> QUIT\n", smtp_mode); -  ok = SMTP_ok(sock); +  ok = SMTP_ok(sock, smtp_mode);    return ok;  } -int SMTP_eom(int sock) +int SMTP_eom(int sock, char smtp_mode)  /* send a message data terminator to the SMTP listener */  {    int ok; @@ -298,7 +290,7 @@ int SMTP_eom(int sock)     * When doing LMTP, must process many of these at the outer level.      */    if (smtp_mode == 'S') -      ok = SMTP_ok(sock); +      ok = SMTP_ok(sock, smtp_mode);    else        ok = SM_OK; @@ -307,7 +299,7 @@ int SMTP_eom(int sock)  time_t last_smtp_ok = 0; -int SMTP_ok(int sock) +int SMTP_ok(int sock, char smtp_mode)  /* returns status of SMTP connection */  {      SIGHANDLERTYPE alrmsave; @@ -25,16 +25,15 @@  extern time_t last_smtp_ok; -void SMTP_setmode(char); -int SMTP_helo(int socket,const char *host); -int SMTP_ehlo(int socket,const char *host, char *name, char *passwd, int *opt); -int SMTP_from(int socket,const char *from,const char *opts); -int SMTP_rcpt(int socket,const char *to); -int SMTP_data(int socket); -int SMTP_eom(int socket); -int SMTP_rset(int socket); -int SMTP_quit(int socket); -int SMTP_ok(int socket); +int SMTP_helo(int socket, char smtp_mode, const char *host); +int SMTP_ehlo(int socket, char smtp_mode, const char *host, char *name, char *passwd, int *opt); +int SMTP_from(int socket, char smtp_mode, const char *from,const char *opts); +int SMTP_rcpt(int socket, char smtp_mode, const char *to); +int SMTP_data(int socket, char smtp_mode); +int SMTP_eom(int socket, char smtp_mode); +int SMTP_rset(int socket, char smtp_mode); +int SMTP_quit(int socket, char smtp_mode); +int SMTP_ok(int socket, char smtp_mode);  extern char smtp_response[MSGBUFSIZE];  | 
