diff options
Diffstat (limited to 'imap/imapd.c')
| -rw-r--r-- | imap/imapd.c | 533 |
1 files changed, 426 insertions, 107 deletions
diff --git a/imap/imapd.c b/imap/imapd.c index fca7149..78a689c 100644 --- a/imap/imapd.c +++ b/imap/imapd.c @@ -1,5 +1,5 @@ /* -** Copyright 1998 - 2011 Double Precision, Inc. +** Copyright 1998 - 2018 Double Precision, Inc. ** See COPYING for distribution information. */ @@ -85,6 +85,7 @@ #include "maildir/maildirinfo.h" #include "maildir/loginexec.h" #include "rfc822/rfc822.h" +#include "rfc2045/rfc2045.h" #include <courier-unicode.h> #include "maildir/maildirkeywords.h" @@ -140,6 +141,8 @@ char *current_mailbox_acl; dev_t homedir_dev; ino_t homedir_ino; +int enabled_utf8=0; + void rfc2045_error(const char *p) { if (write(2, p, strlen(p)) < 0) @@ -147,6 +150,19 @@ void rfc2045_error(const char *p) _exit(0); } +void writemailbox(const char *mailbox) +{ + char *encoded=imap_filename_to_foldername(enabled_utf8, mailbox); + + if (!encoded) + { + fprintf(stderr, "ERR: imap_filename_to_foldername(%s) failed\n", + mailbox); + exit(1); + } + writeqs(encoded); + free(encoded); +} extern int maildirsize_read(const char *,int *,off_t *,unsigned *,unsigned *,struct stat *); @@ -330,10 +346,10 @@ int is_reserved_name(const char *name) return 0; } -char *decode_valid_mailbox(const char *p, int autosubscribe) +static char *decode_valid_mailbox_utf8(const char *p, int autosubscribe) { struct maildir_info mi; - char *q, *r; + char *r; if (maildir_info_imap_find(&mi, p, getenv("AUTHENTICATED")) < 0) { @@ -342,7 +358,7 @@ char *decode_valid_mailbox(const char *p, int autosubscribe) if (mi.homedir && mi.maildir) { - q=maildir_name2dir(mi.homedir, mi.maildir); + char *q=maildir_name2dir(mi.homedir, mi.maildir); if (q) { @@ -403,6 +419,22 @@ char *decode_valid_mailbox(const char *p, int autosubscribe) return (NULL); } +char *decode_valid_mailbox(const char *mailbox, int autosubscribe) +{ + char *p=imap_foldername_to_filename(enabled_utf8, mailbox); + char *q; + + if (!p) + { + errno=EINVAL; + return NULL; + } + + q=decode_valid_mailbox_utf8(p, autosubscribe); + free(p); + return q; +} + static int decode_date_time(char *p, time_t *tret) { unsigned i; @@ -561,7 +593,7 @@ static char *parse_mailbox_error(const char *tag, ** a real folder (such as this one). */ - int autosubscribe) /* Really DUMP clients that do a LIST, + int autosubscribe) /* Really DUMB clients that do a LIST, ** and don't bother to check if a folder is ** subscribed to, or not (Pine) */ @@ -572,17 +604,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) { @@ -680,19 +712,23 @@ static int store_mailbox(const char *tag, const char *mailbox, struct imapflags *flags, struct libmail_kwMessage *keywords, time_t timestamp, - unsigned long nbytes, + struct imaptoken *curtoken, unsigned long *new_uidv, unsigned long *new_uid) { -char *tmpname; -char *newname; -char *p; -char *e; -FILE *fp; -unsigned long n; -static const char nowrite[]=" NO [ALERT] Cannot create message - no write permission or out of disk space.\r\n"; -int lastnl; -int rb; + unsigned long nbytes=curtoken->tokennum; + char *tmpname; + char *newname; + char *p; + char *e; + FILE *fp; + unsigned long n; + static const char nowrite[]=" NO [ALERT] Cannot create message - no write permission or out of disk space.\r\n"; + int lastnl; + int rb; + int errflag; + struct rfc2045 *rfc2045_parser; + const char *errmsg=nowrite; fp=maildir_mkfilename(mailbox, flags, 0, &tmpname, &newname); @@ -710,6 +746,8 @@ int rb; current_temp_fd=fileno(fp); current_temp_fn=tmpname; + rfc2045_parser=rfc2045_alloc(); + while (nbytes) { read_string(&p, &n, nbytes); @@ -726,31 +764,53 @@ int rb; } else if (e) { + rfc2045_parse(rfc2045_parser, p, e-p); rb = fwrite(p, 1, e-p, fp); } else { + rfc2045_parse(rfc2045_parser, p, n); rb = fwrite(p, 1, n, fp); } n -= rb; p += rb; } } - if (!lastnl) putc('\n', fp); + if (!lastnl) + { + putc('\n', fp); + rfc2045_parse(rfc2045_parser, "\n", 1); + } current_temp_fd=-1; current_temp_fn=NULL; + errflag=0; if (fflush(fp) || ferror(fp)) { fprintf(stderr, "ERR: error storing a message, user=%s, errno=%d\n", getenv("AUTHENTICATED"), errno); + errflag=1; + } + if ((rfc2045_parser->rfcviolation & RFC2045_ERR8BITHEADER) && + curtoken->tokentype != IT_LITERAL8_STRING_START) + { + errmsg=" NO [ALERT] Your IMAP client does not appear to " + "correctly implement Unicode messages, " + "see https://tools.ietf.org/html/rfc6855.html\r\n"; + errflag=1; + } + + rfc2045_free(rfc2045_parser); + + if (errflag) + { fclose(fp); unlink(tmpname); writes(tag); - writes(nowrite); + writes(errmsg); free(tmpname); free(newname); return (-1); @@ -2413,7 +2473,7 @@ static int list_callback(const char *hiersep, different order */ writes("* ACLFAILED \""); - writeqs(mailbox); + writemailbox(mailbox); writes("\""); accessdenied("LIST(MYRIGHTS)", mailbox, @@ -2440,7 +2500,7 @@ static int list_callback(const char *hiersep, different order */ writes("* ACLFAILED \""); - writeqs(mailbox); + writemailbox(mailbox); writes("\""); accessdenied("LIST(ACL)", mailbox, @@ -2480,7 +2540,7 @@ static int list_callback(const char *hiersep, writes(") "); writes(hiersep); writes(" \""); - writeqs(mailbox); + writemailbox(mailbox); writes("\""); if (flags & (LIST_ACL|LIST_MYRIGHTS|LIST_POSTADDRESS)) @@ -2872,6 +2932,18 @@ char *get_myrightson(const char *mailbox) return rights; } +char *get_myrightson_folder(const char *folder) +{ + char *p=imap_foldername_to_filename(enabled_utf8, folder); + char *r; + + if (!p) + return NULL; + + r=get_myrightson(p); + free(p); + return r; +} char *compute_myrights(maildir_aclt_list *l, const char *l_owner) { @@ -3113,26 +3185,37 @@ static int aclcmd(const char *tag) case IT_LPAREN: while ((curtoken=nexttoken_nouc())->tokentype != IT_RPAREN) { + char *p; + if (curtoken->tokentype != IT_QUOTED_STRING && curtoken->tokentype != IT_ATOM && curtoken->tokentype != IT_NUMBER) { + writes(tag); + writes(" BAD Invalid command\r\n"); + return 0; + } + + p=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + if (!p) + { errno=EINVAL; return -1; } - mblist=NULL; - if (mailbox_scan("", curtoken->tokenbuf, 0, + if (mailbox_scan("", p, 0, aclmailbox_scan, &mblist) || aclmailbox_merge(mblist, &mailboxlist)) { + free(p); free_tempmailboxlist(mblist); free_mailboxlist(mailboxlist); return -1; } - + free(p); free_tempmailboxlist(mblist); } break; @@ -3141,17 +3224,27 @@ static int aclcmd(const char *tag) case IT_NUMBER: mblist=NULL; - if (mailbox_scan("", curtoken->tokenbuf, LIST_CHECK1FOLDER, - aclmailbox_scan, &mblist) || - aclmailbox_merge(mblist, &mailboxlist)) - { + char *p=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + + if (mailbox_scan("", p, LIST_CHECK1FOLDER, + aclmailbox_scan, &mblist) || + aclmailbox_merge(mblist, &mailboxlist)) + { + free(p); + free_tempmailboxlist(mblist); + free_mailboxlist(mailboxlist); + return -1; + } + free(p); free_tempmailboxlist(mblist); - free_mailboxlist(mailboxlist); - return -1; } - free_tempmailboxlist(mblist); break; + case IT_ERROR: + writes(tag); + writes(" BAD Invalid command\r\n"); + return 0; } rc=0; @@ -3288,7 +3381,7 @@ static void aclfailed(const char *mailbox, const char *identifier) if (!identifier) { writes("* ACLFAILED \""); - writeqs(mailbox); + writemailbox(mailbox); writes("\" "); writes(strerror(errno)); writes("\r\n"); @@ -3296,7 +3389,7 @@ static void aclfailed(const char *mailbox, const char *identifier) } writes("* RIGHTS-INFO \""); - writeqs(mailbox); + writemailbox(mailbox); writes("\" \""); writeqs(identifier); writes("\" "); @@ -3318,7 +3411,7 @@ static int acl_settable_folder(char *mailbox, if (mi->homedir == NULL || mi->maildir == NULL) { writes("* ACLFAILED \""); - writeqs(mailbox); + writemailbox(mailbox); writes("\" ACLs may not be modified for special mailbox\r\n"); maildir_info_destroy(mi); *mailbox=0; @@ -3481,7 +3574,7 @@ static int aclstore(const char *tag, struct temp_acl_mailbox_list *mailboxes) if (acl_rights[0] == 0) { writes("* ACLFAILED \""); - writeqs(mailboxes[i].mailbox); + writemailbox(mailboxes[i].mailbox); writes("\""); accessdenied("ACL STORE", mailboxes[i].mailbox, @@ -3585,7 +3678,7 @@ static int aclset(const char *tag, struct temp_acl_mailbox_list *mailboxes) { maildir_info_destroy(&mi); writes("* ACLFAILED \""); - writeqs(mailboxes[i].mailbox); + writemailbox(mailboxes[i].mailbox); writes("\""); accessdenied("ACL SET", mailboxes[i].mailbox, ACL_ADMINISTER); @@ -3657,7 +3750,7 @@ static int acldelete(const char *tag, struct temp_acl_mailbox_list *mailboxes) if (acl_rights[0] == 0) { writes("* ACLFAILED \""); - writeqs(mailboxes[i].mailbox); + writemailbox(mailboxes[i].mailbox); writes("\""); accessdenied("ACL DELETE", mailboxes[i].mailbox, @@ -3817,6 +3910,7 @@ static int append(const char *tag, const char *mailbox, const char *path) unsigned long new_uidv, new_uid; char access_rights[8]; struct imaptoken *curtoken; + int need_rparen; if (access(path, 0)) { @@ -3896,9 +3990,35 @@ static int append(const char *tag, const char *mailbox, const char *path) else if (curtoken->tokentype == IT_NIL) curtoken=nexttoken_noparseliteral(); - if (curtoken->tokentype != IT_LITERAL_STRING_START) + need_rparen=0; + + if (enabled_utf8 && curtoken->tokentype == IT_ATOM && + strcmp(curtoken->tokenbuf, "UTF8") == 0) + { + curtoken=nexttoken(); + if (curtoken->tokentype != IT_LPAREN) + { + libmail_kwmDestroy(keywords); + return (-1); + } + + curtoken=nexttoken_noparseliteral(); + if (curtoken->tokentype != IT_LITERAL8_STRING_START) + { + libmail_kwmDestroy(keywords); + + /* Don't break the protocol level */ + convert_literal_tokens(curtoken); + return (-1); + } + need_rparen=1; + } + else if (curtoken->tokentype != IT_LITERAL_STRING_START) { libmail_kwmDestroy(keywords); + + /* Don't break the protocol level */ + convert_literal_tokens(curtoken); return (-1); } @@ -3908,7 +4028,7 @@ static int append(const char *tag, const char *mailbox, const char *path) acl_flags_adjust(access_rights, &flags) ? NULL:keywords, timestamp, - curtoken->tokennum, &new_uidv, &new_uid)) + curtoken, &new_uidv, &new_uid)) { libmail_kwmDestroy(keywords); unread('\n'); @@ -3916,6 +4036,14 @@ static int append(const char *tag, const char *mailbox, const char *path) } libmail_kwmDestroy(keywords); + if (need_rparen) + { + if (nexttoken()->tokentype != IT_RPAREN) + { + return (-1); + } + } + if (nexttoken()->tokentype != IT_EOL) { return (-1); @@ -4121,6 +4249,13 @@ static int validate_charset(const char *tag, char **charset) if (*charset == NULL) *charset=my_strdup("UTF-8"); + if (enabled_utf8 && strcmp(*charset, "UTF-8")) + { + writes(tag); + writes(" BAD [BADCHARSET] Only UTF-8 charset is valid after enabling RFC 6855 support\r\n"); + return (-1); + } + conv=unicode_convert_tou_init(*charset, &ucptr, &ucsize, 1); if (!conv) @@ -4246,8 +4381,15 @@ int uid=0; if (curtoken->tokentype != IT_QUOTED_STRING && curtoken->tokentype != IT_ATOM && curtoken->tokentype != IT_NUMBER) - return (-1); - reference=my_strdup(curtoken->tokenbuf); + { + writes(tag); + writes(" BAD Invalid command\r\n"); + return (0); + } + reference=imap_foldername_to_filename + (enabled_utf8, curtoken->tokenbuf); + if (!reference) + return -1; } curtoken=nexttoken_nouc(); @@ -4258,8 +4400,20 @@ int uid=0; if (curtoken->tokentype != IT_QUOTED_STRING && curtoken->tokentype != IT_ATOM && curtoken->tokentype != IT_NUMBER) - return (-1); - name=my_strdup(curtoken->tokenbuf); + { + 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); @@ -4295,15 +4449,25 @@ int uid=0; { struct imaptoken *tok=nexttoken_nouc(); struct maildir_info mi; + char *mailbox; 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); + } - if (maildir_info_imap_find(&mi, tok->tokenbuf, + mailbox=imap_foldername_to_filename(enabled_utf8, + tok->tokenbuf); + if (!mailbox || + maildir_info_imap_find(&mi, mailbox, getenv("AUTHENTICATED")) < 0) { + if (mailbox) + free(mailbox); writes(tag); writes(" NO Invalid mailbox name.\r\n"); return (0); @@ -4319,19 +4483,21 @@ int uid=0; maildir_info_destroy(&mi); writes(tag); accessdenied("APPEND", - tok->tokenbuf, + mailbox, ACL_INSERT); + free(mailbox); return 0; } - rc=append(tag, tok->tokenbuf, p); + rc=append(tag, mailbox, p); free(p); maildir_info_destroy(&mi); + free(mailbox); return (rc); } else if (mi.mailbox_type == MAILBOXTYPE_OLDSHARED) { - char *p=strchr(tok->tokenbuf, '.'); + char *p=strchr(mailbox, '.'); if (p && (p=maildir_shareddir(".", p+1)) != NULL) { @@ -4342,13 +4508,14 @@ int uid=0; strcat(strcpy(q, p), "/shared"); free(p); - rc=append(tag, tok->tokenbuf, q); + rc=append(tag, mailbox, q); free(q); + free(mailbox); maildir_info_destroy(&mi); return rc; } } - + free(mailbox); writes(tag); accessdenied("APPEND", "folder", ACL_INSERT); return (0); @@ -4358,17 +4525,27 @@ int uid=0; { char qroot[20]; struct maildir_info minfo; - + char *mailbox; curtoken=nexttoken_nouc(); 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); - if (maildir_info_imap_find(&minfo, curtoken->tokenbuf, + if (!mailbox || + maildir_info_imap_find(&minfo, mailbox, getenv("AUTHENTICATED"))) { + if (mailbox) + free(mailbox); writes(tag); writes(" NO Invalid mailbox name.\r\n"); return (0); @@ -4389,13 +4566,14 @@ int uid=0; writes("*"); writes(" QUOTAROOT \""); - writeqs(curtoken->tokenbuf); + writemailbox(mailbox); writes("\" \""); writes(qroot); writes("\"\r\n"); quotainfo_out(qroot); writes(tag); writes(" OK GETQUOTAROOT Ok.\r\n"); + free(mailbox); return(0); } @@ -4407,6 +4585,34 @@ int uid=0; return(0); } + if (strcmp(curtoken->tokenbuf, "ENABLE") == 0) + { + while (nexttoken()->tokentype != IT_EOL) + { + switch (curtoken->tokentype) { + case IT_NUMBER: + case IT_ATOM: + case IT_QUOTED_STRING: + if (strcmp(curtoken->tokenbuf, "UTF8=ACCEPT") + == 0) + { + enabled_utf8=1; + } + continue; + default: + return -1; + } + } + + writes("* ENABLED"); + if (enabled_utf8) + writes(" UTF8=ACCEPT"); + writes("\r\n"); + writes(tag); + writes(" OK Options enabled\r\n"); + return (0); + } + if (strcmp(curtoken->tokenbuf, "GETQUOTA") == 0) { curtoken=nexttoken_nouc(); @@ -4442,7 +4648,14 @@ int uid=0; if ( mailbox == 0) return (0); - orig_mailbox=my_strdup(curtoken->tokenbuf); + orig_mailbox=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + + if (!orig_mailbox) + { + free(mailbox); + return -1; + } curtoken=nexttoken(); oneonly=0; @@ -4521,7 +4734,7 @@ int uid=0; writes("*"); writes(" STATUS \""); - writeqs(orig_mailbox); + writemailbox(orig_mailbox); writes("\" ("); p=""; if (get_messages) @@ -4599,7 +4812,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; @@ -4610,13 +4827,20 @@ int uid=0; isdummy=1; /* Ignore hierarchy creation */ } - if (maildir_info_imap_find(&mi, curtoken->tokenbuf, + mailbox=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + if (!mailbox) + return -1; + + if (maildir_info_imap_find(&mi, mailbox, getenv("AUTHENTICATED"))) { writes(tag); writes(" NO Invalid mailbox name.\r\n"); + free(mailbox); return (0); } + free(mailbox); if (!mi.homedir || !mi.maildir) { @@ -4655,7 +4879,15 @@ int uid=0; } if (isdummy) *p=HIERCH; - orig_mailbox=my_strdup(curtoken->tokenbuf); + orig_mailbox=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + + if (!orig_mailbox) + { + free(mailbox); + maildir_info_destroy(&mi); + return (-1); + } if (nexttoken()->tokentype != IT_EOL) { @@ -4711,7 +4943,7 @@ int uid=0; } writes(tag); writes(" OK \""); - writeqs(orig_mailbox); + writemailbox(orig_mailbox); writes("\" created.\r\n"); /* @@ -4745,7 +4977,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 */ @@ -4757,14 +4993,18 @@ int uid=0; return (0); } - mailbox_name=my_strdup(curtoken->tokenbuf); mailbox=parse_mailbox_error(tag, curtoken, 1, 0); if ( mailbox == 0) + return 0; + + mailbox_name=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + + if (!mailbox_name) { - free(mailbox_name); - return (0); + free(mailbox); + return (-1); } - if (nexttoken()->tokentype != IT_EOL) { free(mailbox_name); @@ -4781,10 +5021,10 @@ int uid=0; return (0); } - if (strncmp(curtoken->tokenbuf, SHARED HIERCHS, - sizeof(SHARED HIERCHS)-1) == 0) + if (strncmp(mailbox_name, SHARED HIERCHS, + sizeof(SHARED HIERCHS)-1) == 0) { - maildir_shared_unsubscribe(0, curtoken->tokenbuf+ + maildir_shared_unsubscribe(0, mailbox_name+ sizeof(SHARED HIERCHS)-1); free(mailbox_name); free(mailbox); @@ -4836,6 +5076,7 @@ int uid=0; char *p; struct maildir_info mi1, mi2; const char *errmsg; + char *mailbox; curtoken=nexttoken_nouc(); @@ -4844,16 +5085,23 @@ int uid=0; curtoken->tokentype != IT_QUOTED_STRING) { writes(tag); - writes(" NO Invalid mailbox\r\n"); + writes(" BAD Invalid command\r\n"); return (0); } if ((p=strrchr(curtoken->tokenbuf, HIERCH)) && p[1] == 0) *p=0; - if (maildir_info_imap_find(&mi1, curtoken->tokenbuf, + mailbox=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + + if (!mailbox) + return -1; + + if (maildir_info_imap_find(&mi1, mailbox, getenv("AUTHENTICATED")) < 0) { + free(mailbox); writes(tag); writes(" NO Invalid mailbox name.\r\n"); return (0); @@ -4861,6 +5109,7 @@ int uid=0; if (mi1.homedir == NULL || mi1.maildir == NULL) { + free(mailbox); maildir_info_destroy(&mi1); writes(tag); writes(" NO Invalid mailbox\r\n"); @@ -4868,11 +5117,12 @@ int uid=0; } { - CHECK_RIGHTSM(curtoken->tokenbuf, + CHECK_RIGHTSM(mailbox, rename_rights, ACL_DELETEFOLDER); if (rename_rights[0] == 0) { + free(mailbox); maildir_info_destroy(&mi1); writes(tag); accessdenied("RENAME", curtoken->tokenbuf, @@ -4880,7 +5130,7 @@ int uid=0; return (0); } } - + free(mailbox); curtoken=nexttoken_nouc(); if (curtoken->tokentype != IT_NUMBER && @@ -4888,7 +5138,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) @@ -4896,22 +5148,33 @@ int uid=0; *p=0; } + mailbox=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + + if (!mailbox) + { + maildir_info_destroy(&mi1); + return -1; + } - if (maildir_info_imap_find(&mi2, curtoken->tokenbuf, + if (maildir_info_imap_find(&mi2, mailbox, getenv("AUTHENTICATED")) < 0) { + free(mailbox); maildir_info_destroy(&mi1); writes(tag); writes(" NO Invalid mailbox name.\r\n"); return (0); } - if (check_parent_create(tag, "RENAME", curtoken->tokenbuf)) + if (check_parent_create(tag, "RENAME", mailbox)) { + free(mailbox); maildir_info_destroy(&mi1); maildir_info_destroy(&mi2); return 0; } + free(mailbox); if (nexttoken()->tokentype != IT_EOL) { @@ -4970,7 +5233,7 @@ int uid=0; if ( mailbox == 0) return (0); - current_mailbox_acl=get_myrightson(curtoken->tokenbuf); + current_mailbox_acl=get_myrightson_folder(curtoken->tokenbuf); if (current_mailbox_acl == NULL) { free(mailbox); @@ -5049,7 +5312,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 */ @@ -5061,7 +5328,10 @@ int uid=0; return (0); } - mailbox=my_strdup(curtoken->tokenbuf); + mailbox=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + if (!mailbox) + return -1; if (nexttoken()->tokentype != IT_EOL) return (-1); @@ -5126,7 +5396,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 */ @@ -5138,7 +5412,12 @@ int uid=0; return (0); } - mailbox=my_strdup(curtoken->tokenbuf); + mailbox=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + + if (!mailbox) + return -1; + if (nexttoken()->tokentype != IT_EOL) return (-1); @@ -5241,7 +5520,10 @@ int uid=0; return 0; free(mailbox); - mailbox=my_strdup(curtoken->tokenbuf); + mailbox=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + if (!mailbox) + return -1; if (maildir_info_imap_find(&mi, mailbox, getenv("AUTHENTICATED")) < 0) @@ -5355,6 +5637,7 @@ int uid=0; maildir_aclt_list l; char *mailbox_owner; char *mb; + char *f; curtoken=nexttoken_nouc(); @@ -5363,22 +5646,29 @@ int uid=0; return 0; free(mb); + f=imap_foldername_to_filename(enabled_utf8, curtoken->tokenbuf); + + if (!f) + return -1; + { - CHECK_RIGHTSM(curtoken->tokenbuf, + CHECK_RIGHTSM(f, acl_rights, ACL_ADMINISTER); if (acl_rights[0] == 0) { writes(tag); - accessdenied("GETACL", curtoken->tokenbuf, + accessdenied("GETACL", f, ACL_ADMINISTER); + free(f); return 0; } } - if (get_acllist(&l, curtoken->tokenbuf, + if (get_acllist(&l, f, &mailbox_owner) < 0) { + free(f); writes(tag); writes(" NO Cannot retrieve ACLs for mailbox.\r\n"); return 0; @@ -5386,13 +5676,14 @@ int uid=0; free(mailbox_owner); writes("* ACL \""); - writeqs(curtoken->tokenbuf); + writemailbox(f); writes("\""); maildir_aclt_list_enum(&l, getacl_cb, NULL); writes("\r\n"); writes(tag); writes(" OK GETACL completed.\r\n"); maildir_aclt_list_destroy(&l); + free(f); return 0; } @@ -5408,9 +5699,14 @@ int uid=0; if (!mb) return 0; free(mb); + mb=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + + if (!mb) + return -1; { - char *myrights=get_myrightson(curtoken->tokenbuf); + char *myrights=get_myrightson(mb); if (!strchr(myrights, ACL_LOOKUP[0]) && !strchr(myrights, ACL_READ[0]) && @@ -5422,23 +5718,23 @@ int uid=0; { free(myrights); writes(tag); - accessdenied("GETACL", curtoken->tokenbuf, + accessdenied("GETACL", mb, ACL_ADMINISTER); + free(mb); return 0; } free(myrights); } - if (get_acllist(&l, curtoken->tokenbuf, + if (get_acllist(&l, mb, &mailbox_owner) < 0) { + free(mb); writes(tag); writes(" NO Cannot retrieve ACLs for mailbox.\r\n"); return 0; } - mb=my_strdup(curtoken->tokenbuf); - switch ((curtoken=nexttoken_nouc())->tokentype) { case IT_QUOTED_STRING: case IT_ATOM: @@ -5452,7 +5748,7 @@ int uid=0; } writes("* LISTRIGHTS \""); - writeqs(mb); + writemailbox(mb); writes("\" \""); writeqs(curtoken->tokenbuf); writes("\""); @@ -5510,6 +5806,7 @@ int uid=0; if (strcmp(curtoken->tokenbuf, "MYRIGHTS") == 0) { char *mb; + char *f; curtoken=nexttoken_nouc(); @@ -5518,8 +5815,12 @@ int uid=0; return 0; free(mb); + f=imap_foldername_to_filename(enabled_utf8, curtoken->tokenbuf); + if (!f) + return -1; + { - char *myrights=get_myrightson(curtoken->tokenbuf); + char *myrights=get_myrightson(f); if (!strchr(myrights, ACL_LOOKUP[0]) && !strchr(myrights, ACL_READ[0]) && @@ -5531,25 +5832,28 @@ int uid=0; { free(myrights); writes(tag); - accessdenied("GETACL", curtoken->tokenbuf, + accessdenied("GETACL", f, ACL_ADMINISTER); + free(f); return 0; } free(myrights); } - mb=get_myrightson(curtoken->tokenbuf); + mb=get_myrightson(f); if (!mb) { + free(f); writes(tag); writes(" NO Cannot retrieve ACLs for mailbox.\r\n"); return 0; } writes("* MYRIGHTS \""); - writeqs(curtoken->tokenbuf); + writemailbox(f); writes("\" \""); + free(f); writeacl1(mb); free(mb); @@ -5740,6 +6044,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) @@ -6089,7 +6401,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); @@ -6117,7 +6431,11 @@ int uid=0; } { - CHECK_RIGHTSM(curtoken->tokenbuf, + char *f=imap_foldername_to_filename(enabled_utf8, + curtoken->tokenbuf); + if (!f) + return -1; + CHECK_RIGHTSM(f, append_rights, ACL_INSERT ACL_DELETEMSGS ACL_SEEN ACL_WRITE); @@ -6126,11 +6444,12 @@ int uid=0; { writes(tag); accessdenied("COPY", - curtoken->tokenbuf, + f, ACL_INSERT); + free(f); return 0; } - + free(f); strcpy(access_rights, append_rights); } |
