summaryrefslogtreecommitdiffstats
path: root/imap
diff options
context:
space:
mode:
authorSam Varshavchik2018-07-14 22:29:39 -0400
committerSam Varshavchik2018-07-16 21:20:25 -0400
commit60a63d31b29fea54441fa72e59d5712ca31eb01e (patch)
treef5d2d712e79c10c52685310a7b38c67d68b14547 /imap
parent2ad535262c59ff73743547594dc6c152d195d07c (diff)
downloadcourier-libs-60a63d31b29fea54441fa72e59d5712ca31eb01e.tar.bz2
courier-imap: enforce UTF8-correctness as per RFC-6855.
Diffstat (limited to 'imap')
-rw-r--r--imap/imapd.c97
-rw-r--r--imap/imaplogin.c3
-rw-r--r--imap/imaptoken.c57
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);
}
-