diff options
| author | Sam Varshavchik | 2018-07-14 22:29:39 -0400 | 
|---|---|---|
| committer | Sam Varshavchik | 2018-07-16 21:20:25 -0400 | 
| commit | 60a63d31b29fea54441fa72e59d5712ca31eb01e (patch) | |
| tree | f5d2d712e79c10c52685310a7b38c67d68b14547 | |
| parent | 2ad535262c59ff73743547594dc6c152d195d07c (diff) | |
| download | courier-libs-60a63d31b29fea54441fa72e59d5712ca31eb01e.tar.bz2 | |
courier-imap: enforce UTF8-correctness as per RFC-6855.
| -rw-r--r-- | imap/imapd.c | 97 | ||||
| -rw-r--r-- | imap/imaplogin.c | 3 | ||||
| -rw-r--r-- | imap/imaptoken.c | 57 | 
3 files changed, 126 insertions, 31 deletions
| diff --git a/imap/imapd.c b/imap/imapd.c index 001dfcb..cf31af4 100644 --- a/imap/imapd.c +++ b/imap/imapd.c @@ -603,17 +603,17 @@ char	*mailbox;  		curtoken->tokentype != IT_ATOM &&  		curtoken->tokentype != IT_QUOTED_STRING)  	{ -		mailbox=0; +		writes(tag); +		writes(" BAD Invalid command\r\n"); +		return (0);  	} -	else -	{ -		if (ok_hierarchy && (mailbox=strrchr(curtoken->tokenbuf, -			HIERCH)) && mailbox[1] == 0) -				*mailbox=0; -		mailbox=decode_valid_mailbox(curtoken->tokenbuf, -			autosubscribe); -	} +	if (ok_hierarchy && (mailbox=strrchr(curtoken->tokenbuf, +					     HIERCH)) && mailbox[1] == 0) +		*mailbox=0; + +	mailbox=decode_valid_mailbox(curtoken->tokenbuf, +				     autosubscribe);  	if ( mailbox == 0)  	{ @@ -3162,8 +3162,9 @@ static int aclcmd(const char *tag)  				curtoken->tokentype != IT_ATOM &&  				curtoken->tokentype != IT_NUMBER)  			{ -				errno=EINVAL; -				return -1; +				writes(tag); +				writes(" BAD Invalid command\r\n"); +				return 0;  			}  			p=imap_foldername_to_filename(enabled_utf8, @@ -3211,6 +3212,10 @@ static int aclcmd(const char *tag)  			free_tempmailboxlist(mblist);  		}  		break; +	case IT_ERROR: +		writes(tag); +		writes(" BAD Invalid command\r\n"); +		return 0;  	}  	rc=0; @@ -4305,7 +4310,11 @@ int	uid=0;  			if (curtoken->tokentype != IT_QUOTED_STRING &&  				curtoken->tokentype != IT_ATOM &&  				curtoken->tokentype != IT_NUMBER) -				return (-1); +			{ +				writes(tag); +				writes(" BAD Invalid command\r\n"); +				return (0); +			}  			reference=imap_foldername_to_filename  				(enabled_utf8, curtoken->tokenbuf);  			if (!reference) @@ -4320,12 +4329,20 @@ int	uid=0;  			if (curtoken->tokentype != IT_QUOTED_STRING &&  				curtoken->tokentype != IT_ATOM &&  				curtoken->tokentype != IT_NUMBER) -				return (-1); +			{ +				free(reference); +				writes(tag); +				writes(" BAD Invalid command\r\n"); +				return(0); +			}  			name=imap_foldername_to_filename(enabled_utf8,  							 curtoken->tokenbuf);  			if (!name) +			{ +				free(reference);  				return -1; +			}  		}  		if (nexttoken()->tokentype != IT_EOL)	return (-1); @@ -4366,7 +4383,11 @@ int	uid=0;  		if (tok->tokentype != IT_NUMBER &&  			tok->tokentype != IT_ATOM &&  			tok->tokentype != IT_QUOTED_STRING) -			return (-1); +		{ +			writes(tag); +			writes(" BAD Invalid command\r\n"); +			return (0); +		}  		mailbox=imap_foldername_to_filename(enabled_utf8,  						    tok->tokenbuf); @@ -4439,7 +4460,11 @@ int	uid=0;  		if (curtoken->tokentype != IT_NUMBER &&  			curtoken->tokentype != IT_ATOM &&  			curtoken->tokentype != IT_QUOTED_STRING) -			return (-1); +		{ +			writes(tag); +			writes(" BAD Invalid command\r\n"); +			return (0); +		}  		mailbox=imap_foldername_to_filename(enabled_utf8,  						    curtoken->tokenbuf); @@ -4716,7 +4741,11 @@ int	uid=0;  		if (curtoken->tokentype != IT_NUMBER &&  			curtoken->tokentype != IT_ATOM &&  			curtoken->tokentype != IT_QUOTED_STRING) -			return (-1); +		{ +			writes(tag); +			writes(" BAD Invalid command\r\n"); +			return 0; +		}  		isdummy=0; @@ -4877,7 +4906,11 @@ int	uid=0;  		if (curtoken->tokentype != IT_NUMBER &&  			curtoken->tokentype != IT_ATOM &&  			curtoken->tokentype != IT_QUOTED_STRING) -			return (-1); +		{ +			writes(tag); +			writes(" BAD Invalid command\r\n"); +			return (0); +		}  		p=strrchr(curtoken->tokenbuf, HIERCH);  		if (p && p[1] == '\0')		/* Ignore hierarchy DELETE */ @@ -4981,7 +5014,7 @@ int	uid=0;  		    curtoken->tokentype != IT_QUOTED_STRING)  		{  			writes(tag); -			writes(" NO Invalid mailbox\r\n"); +			writes(" BAD Invalid command\r\n");  			return (0);  		} @@ -5034,7 +5067,9 @@ int	uid=0;  			curtoken->tokentype != IT_QUOTED_STRING)  		{  			maildir_info_destroy(&mi1); -			return (-1); +			writes(tag); +			writes(" BAD Invalid command\r\n"); +			return (0);  		}  		if ((p=strrchr(curtoken->tokenbuf, HIERCH)) && p[1] == 0) @@ -5206,7 +5241,11 @@ int	uid=0;  		if (curtoken->tokentype != IT_NUMBER &&  			curtoken->tokentype != IT_ATOM &&  			curtoken->tokentype != IT_QUOTED_STRING) -			return (-1); +		{ +			writes(tag); +			writes(" BAD Invalid command\r\n"); +			return (0); +		}  		p=strrchr(curtoken->tokenbuf, HIERCH);  		if (p && p[1] == '\0')		/* Ignore hierarchy DELETE */ @@ -5286,7 +5325,11 @@ int	uid=0;  		if (curtoken->tokentype != IT_NUMBER &&  			curtoken->tokentype != IT_ATOM &&  			curtoken->tokentype != IT_QUOTED_STRING) -			return (-1); +		{ +			writes(tag); +			writes(" BAD Invalid command\r\n"); +			return (0); +		}  		p=strrchr(curtoken->tokenbuf, HIERCH);  		if (p && p[1] == '\0')		/* Ignore hierarchy DELETE */ @@ -5930,6 +5973,14 @@ int	uid=0;  		if (curtoken->tokentype == IT_ATOM &&  			strcmp(curtoken->tokenbuf, "CHARSET") == 0)  		{ +			if (enabled_utf8) +			{ +				writes(tag); +				writes(" NO CHARSET is not valid in UTF8 mode " +				       "as per RFC 6855\r\n"); +				return (0); +			} +  			curtoken=nexttoken();  			if (curtoken->tokentype != IT_ATOM &&  				curtoken->tokentype != IT_QUOTED_STRING) @@ -6279,7 +6330,9 @@ int	uid=0;  			curtoken->tokentype != IT_QUOTED_STRING)  		{  			free(msgset); -			return (-1); +			writes(tag); +			writes(" BAD Invalid command\r\n"); +			return (0);  		}  		mailbox=decode_valid_mailbox(curtoken->tokenbuf, 1); diff --git a/imap/imaplogin.c b/imap/imaplogin.c index a445a35..8e2f9c9 100644 --- a/imap/imaplogin.c +++ b/imap/imaplogin.c @@ -37,7 +37,7 @@  #include	"tcpd/spipe.h"  #include	"numlib/numlib.h"  #include	"tcpd/tlsclient.h" - +#include	"imapd.h"  FILE *debugfile=0;  extern void initcapability(); @@ -47,6 +47,7 @@ extern int have_starttls();  extern int tlsrequired();  extern int authenticate(const char *, char *, int);  unsigned long header_count=0, body_count=0;	/* Dummies */ +int enabled_utf8=0;  extern unsigned long bytes_received_count; /* counter for received bytes (imaptoken.c) */  extern unsigned long bytes_sent_count; /* counter for sent bytes (imapwrite.c) */ diff --git a/imap/imaptoken.c b/imap/imaptoken.c index 7df8846..82dda7c 100644 --- a/imap/imaptoken.c +++ b/imap/imaptoken.c @@ -1,5 +1,5 @@  /* -** Copyright 1998 - 2005 Double Precision, Inc. +** Copyright 1998 - 2018 Double Precision, Inc.  ** See COPYING for distribution information.  */ @@ -16,6 +16,8 @@  #include	<sys/types.h>  #include	<sys/time.h>  #include	"numlib/numlib.h" +#include	"imapd.h" +#include	<courier-unicode.h>  #if	HAVE_UNISTD_H  #include	<unistd.h>  #endif @@ -222,6 +224,11 @@ void smap_readline(char *buffer, size_t bufsize)  #endif +static int ignore_output_func(const char *ptr, size_t cnt, void *ignore) +{ +	return 0; +} +  static struct imaptoken *do_readtoken(int touc)  {  int	c=0; @@ -269,6 +276,8 @@ unsigned l;  	if (c == '"')  	{ +		int bit8=0; +  		l=0;  		while ((c=READ()) != '"')  		{ @@ -280,13 +289,45 @@ unsigned l;  				curtoken.tokentype=IT_ERROR;  				return (&curtoken);  			} -			if (l < 8192) +			if (l >= 8192)  			{ -				appendch(c); +				fprintf(stderr, "ERR: Quoted string literal " +					"overflow, ip=[%s]\n", +					getenv("TCPREMOTEIP")); +				curtoken.tokentype=IT_ERROR;  			} +			if (c & 0x80) +				bit8=1; +			appendch(c);  		}  		appendch(0);  		curtoken.tokentype=IT_QUOTED_STRING; + +		/* +		** Strings must be valid UTF-8. Shortcut check. +		*/ + +		if (bit8) +		{ +			int errptr=0; + +			unicode_convert_handle_t h= +				unicode_convert_init("utf-8", +						     unicode_u_ucs4_native, +						     ignore_output_func, +						     (void *)0); + +			if (unicode_convert(h, curtoken.tokenbuf, +					    strlen(curtoken.tokenbuf))) +			{ +				curtoken.tokentype=IT_ERROR; +			} + +			if (unicode_convert_deinit(h, &errptr) || errptr) +			{ +				curtoken.tokentype=IT_ERROR; +			} +		}  		return (&curtoken);  	} @@ -339,9 +380,10 @@ unsigned l;  	}  	while (c != '\r' && c != '\n' -		&& !isspace((int)(unsigned char)c) -		&& c != '\\' && c != '"' && c != LPAREN_CHAR && c != RPAREN_CHAR -		&& c != '{' && c != '}' && c != LBRACKET_CHAR && c != RBRACKET_CHAR) +	       && !isspace((int)(unsigned char)c) +	       && (((unsigned char)c) & 0x80) == 0 +	       && c != '\\' && c != '"' && c != LPAREN_CHAR && c != RPAREN_CHAR +	       && c != '{' && c != '}' && c != LBRACKET_CHAR && c != RBRACKET_CHAR)  	{  		curtoken.tokentype=IT_ATOM;  		if (l < IT_MAX_ATOM_SIZE) @@ -352,7 +394,7 @@ unsigned l;  		}  		else  		{ -			write_error_exit("max atom size too small");   +			write_error_exit("max atom size too small");  		}  		c=READ();  	} @@ -564,4 +606,3 @@ int ismsgset_str(const char *p)  	if (*p)	return (0);  	return (1);  } -		 | 
