Looking at the process_recipient() code in lmtpengine.c, I'm not sure that the quote-string parsing has been updated fully to reflect
> virtual domains - so I've fiddled around and come up with a version > based on the existing code, and also a complete rewrite. > I enclose the latter as a patch here; it hasn't been rigorously > tested (at all), but has fixed my particular problem.
Hm, a bit of peer review & common sense later, i enclose a copy of said patch which hopefully takes terminal cases better into account and avoids buffer overruns...
M.
______________________________________________________________ Matthew Hodgson [EMAIL PROTECTED] Tel: +44 845 6667778 Systems Analyst, MX Telecom Ltd.
Index: lmtpengine.c =================================================================== RCS file: /cvs/src/cyrus/imap/lmtpengine.c,v retrieving revision 1.96 diff -u -r1.96 lmtpengine.c --- lmtpengine.c 10 Nov 2003 16:42:14 -0000 1.96 +++ lmtpengine.c 7 Jan 2004 20:15:40 -0000 @@ -754,6 +754,7 @@ char *dest; char *user; int r, sl; + int inusername, inquoted; address_data_t *ret = (address_data_t *) xmalloc(sizeof(address_data_t)); int forcedowncase = config_getswitch(IMAPOPT_LMTP_DOWNCASE_RCPT); @@ -781,40 +782,34 @@ addr++; } - if (*addr == '\"') { - addr++; - while (*addr && *addr != '\"') { - if (*addr == '\\') addr++; - *dest++ = *addr++; - } - } - else { - if(forcedowncase) { - /* We should downcase the localpart up to the first + */ - while(*addr != '@' && *addr != '>' && *addr != '+') { - if(*addr == '\\') addr++; - *dest++ = TOLOWER(*addr++); - } - if (*addr == '+') { - while(*addr != '@' && *addr != '>') { - if(*addr == '\\') addr++; - *dest++ = *addr++; - } - } - while ((config_virtdomains || *addr != '@') && *addr != '>') { - if(*addr == '\\') addr++; - *dest++ = TOLOWER(*addr++); - } - } else { - /* Now finish the remainder of the localpart */ - while ((config_virtdomains || *addr != '@') && *addr != '>') { - if (*addr == '\\') addr++; - *dest++ = *addr++; - } - } + inusername = 1; + inquoted = 0; + + while(*addr && (inquoted || ((config_virtdomains || *addr != '@') && *addr != '>'))) { + if (*addr == '\\' && inquoted) { + addr++; + if (!*addr) { break; } + } + + if (*addr == '\"') { + inquoted = inquoted ? 0 : 1; + addr++; + continue; + } + if (*addr == '+' && inusername) { + inusername = 0; + } + + if (forcedowncase && inusername) { + *dest++ = TOLOWER(*addr++); + } + else { + *dest++ = *addr++; + } } + *dest = '\0'; - + r = verify_user(user, ignorequota ? -1 : msg->size, msg->authstate); if (r) { /* we lost */