Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
SUSE:SLE-12-SP2:GA
cyrus-imapd
KOLAB_cyrus-imapd-2.3.18_cross-domain-acls.patch
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File KOLAB_cyrus-imapd-2.3.18_cross-domain-acls.patch of Package cyrus-imapd
Index: cyrus-imapd-2.3.17/imap/mboxlist.c =================================================================== --- cyrus-imapd-2.3.17.orig/imap/mboxlist.c +++ cyrus-imapd-2.3.17/imap/mboxlist.c @@ -1618,7 +1618,7 @@ int mboxlist_setacl(const char *name, co except for "anonymous", "anyone", the global admin and users in the default domain */ if ((cp = strchr(identifier, '@'))) { - if (rights && + if (!config_getswitch(IMAPOPT_ALLOWCROSSDOMAINACLS) && rights && ((domain && strncasecmp(cp+1, domain, strlen(cp+1))) || (!domain && (!config_defdomain || strcasecmp(config_defdomain, cp+1))))) { @@ -1960,6 +1960,7 @@ struct find_rock { int usermboxnamelen; int checkmboxlist; int checkshared; + int crossdomain; int isadmin; struct auth_state *auth_state; int (*proc)(char *, int, int, void *rock); @@ -1977,7 +1978,9 @@ static int find_p(void *rockp, long matchlen; /* don't list mailboxes outside of the default domain */ - if (!rock->domainlen && !rock->isadmin && memchr(key, '!', keylen)) return 0; + if (!rock->domainlen && !rock->isadmin && memchr(key, '!', keylen) && + !config_getswitch(IMAPOPT_ALLOWCROSSDOMAINACLS)) + return 0; minmatch = 0; if (rock->inboxoffset) { @@ -2150,6 +2153,23 @@ static int find_cb(void *rockp, } rock->checkshared = 0; + + if (rock->find_namespace == NAMESPACE_USER && + config_getswitch(IMAPOPT_ALLOWCROSSDOMAINACLS) && !rock->isadmin && + !rock->crossdomain) { + char *cp = strchr(namebuf+rock->inboxoffset, '!'); + if (cp) { + int local_matchlen = (matchlen - 1 - + (cp - (namebuf+rock->inboxoffset))); + if (!strncmp(cp + 1, "user", local_matchlen)) { + r = (*rock->proc)(cp + 1, local_matchlen, 1, + rock->procrock); + return CYRUSDB_DONE; + } + } + } + + r = (*rock->proc)(namebuf+rock->inboxoffset, matchlen, 1, rock->procrock); @@ -2170,6 +2190,91 @@ static int find_cb(void *rockp, return r; } + +static void convert_cross_domain_pattern(char *domainpat, int domainpatlen, + char **converted_pattern, + const char *pattern, int *crossdomainmatch, + const char *domain) +{ + int patternlen = strlen(pattern); + char *domain_pattern, *local_dest; + char *local_pattern, *domain_dest; + int local_prefix_len; + const char *src; + int c; + + domain_dest = domain_pattern = xmalloc(patternlen + 1); + local_dest = local_pattern = xmalloc(patternlen + 1); + src = pattern; + + while ((c = *src++)) { + *local_dest++ = c; + if (c == '.' || c == '*') + break; + } + + local_prefix_len = local_dest - local_pattern; + if (c && c != '.') + local_prefix_len -= 1; + if (strncmp(pattern, "user.", local_prefix_len) == 0) { + /* pattern matches "user.*". so convert the domain part of the + * pattern */ + + if (c == '*') { + /* the pattern can match any domain */ + *domain_dest++ = '*'; + } + else if (c == '.') { + while ((c = *src++)) { + if (c == '.') + break; + if (c == '^') + c = '.'; + *domain_dest++ = (c == '%' ? '*' : c); + if (c == '*') + break; + } + + if (c == '*') { + *local_dest++ = '*'; + } + } + + if (c) { + strcpy(local_dest, src); + } + else { + if (local_dest > local_pattern) { + if (local_dest[-1] == '.') { + local_dest--; + } + } + *local_dest = 0; + } + + if (domain_dest == domain_pattern) { + *domain_dest++ = '*'; + } + *domain_dest++ = '!'; + *domain_dest = 0; + + strncpy(domainpat, domain_pattern, domainpatlen); + domainpat[domainpatlen - 1] = 0; + strncat(domainpat, local_pattern, domainpatlen - strlen(domainpat) - 1); + + *converted_pattern = xstrdup(local_pattern); + *crossdomainmatch = 1; + } + else { + /* pattern doesn't contain an explicit domain part */ + snprintf(domainpat, domainpatlen, "*!%s", pattern); + *crossdomainmatch = 0; + } + + free(domain_pattern); + free(local_pattern); +} + /* * Find all mailboxes that match 'pattern'. * 'isadmin' is nonzero if user is a mailbox admin. 'userid' @@ -2193,8 +2298,11 @@ int mboxlist_findall(struct namespace *n char *p; int prefixlen; int userlen = userid ? strlen(userid) : 0, domainlen = 0; + int domainpat_prefixlen = 0; char domainpat[MAX_MAILBOX_BUFFER] = ""; /* do intra-domain fetches only */ char *pat = NULL; + char *converted_pattern = NULL; + int crossdomainmatch = 0; if (config_virtdomains) { char *domain; @@ -2204,8 +2312,10 @@ int mboxlist_findall(struct namespace *n domainlen = strlen(domain); /* includes separator */ if ((p = strchr(pattern , '!'))) { - if ((p-pattern != domainlen-1) || - strncmp(pattern, domain+1, domainlen-1)) { + if (!(config_getswitch(IMAPOPT_ALLOWCROSSDOMAINACLS) && + !isadmin) && + ((p-pattern != domainlen-1) || + strncmp(pattern, domain+1, domainlen-1))) { /* don't allow cross-domain access */ return IMAP_MAILBOX_BADNAME; } @@ -2213,7 +2323,16 @@ int mboxlist_findall(struct namespace *n pattern = p+1; } - snprintf(domainpat, sizeof(domainpat), "%s!%s", domain+1, pattern); + if (!(config_getswitch(IMAPOPT_ALLOWCROSSDOMAINACLS) && !isadmin)) { + snprintf(domainpat, sizeof(domainpat), "%s!%s", domain+1, pattern); + } + else { + convert_cross_domain_pattern(domainpat, sizeof(domainpat), + &converted_pattern, pattern, + &crossdomainmatch, domain + 1); + if (converted_pattern) + pattern = converted_pattern; + } } if ((p = strrchr(pattern, '@'))) { /* global admin specified mbox@domain */ @@ -2243,6 +2362,7 @@ int mboxlist_findall(struct namespace *n cbrock.auth_state = auth_state; cbrock.checkmboxlist = 0; /* don't duplicate work */ cbrock.checkshared = 0; + cbrock.crossdomain = 0; cbrock.proc = proc; cbrock.procrock = rock; @@ -2302,6 +2422,12 @@ int mboxlist_findall(struct namespace *n prefixlen = p - pattern; *p = '\0'; + /* Find fixed-string domain pattern prefix */ + for (p = domainpat; *p; p++) { + if (*p == '*' || *p == '%' || *p == '?' || *p == '@') break; + } + domainpat_prefixlen = p - domainpat; + /* * If user.X.* or INBOX.* can match pattern, * search for those mailboxes next @@ -2334,6 +2460,7 @@ int mboxlist_findall(struct namespace *n glob_free(&cbrock.g); cbrock.g = glob_init(domainpat, GLOB_HIERARCHY); cbrock.inboxoffset = 0; + cbrock.crossdomain = crossdomainmatch; if (usermboxnamelen) { usermboxname[--usermboxnamelen] = '\0'; cbrock.usermboxname = usermboxname; @@ -2343,7 +2470,7 @@ int mboxlist_findall(struct namespace *n just bother looking at the ones that have the same pattern prefix. */ r = DB->foreach(mbdb, - domainpat, domainlen + prefixlen, + domainpat, domainpat_prefixlen, &find_p, &find_cb, &cbrock, NULL); } @@ -2352,6 +2479,7 @@ int mboxlist_findall(struct namespace *n done: glob_free(&cbrock.g); if (pat) free(pat); + if (converted_pattern) free(converted_pattern); return r; } @@ -2389,6 +2517,7 @@ int mboxlist_findall_alt(struct namespac cbrock.auth_state = auth_state; cbrock.checkmboxlist = 0; /* don't duplicate work */ cbrock.checkshared = 0; + cbrock.crossdomain = 0; cbrock.proc = proc; cbrock.procrock = rock; @@ -3029,6 +3158,7 @@ int mboxlist_findsub(struct namespace *n cbrock.auth_state = auth_state; cbrock.checkmboxlist = !force; cbrock.checkshared = 0; + cbrock.crossdomain = 0; cbrock.proc = proc; cbrock.procrock = rock; @@ -3180,6 +3310,7 @@ int mboxlist_findsub_alt(struct namespac cbrock.auth_state = auth_state; cbrock.checkmboxlist = !force; cbrock.checkshared = 0; + cbrock.crossdomain = 0; cbrock.proc = proc; cbrock.procrock = rock; Index: cyrus-imapd-2.3.17/imap/mboxname.c =================================================================== --- cyrus-imapd-2.3.17.orig/imap/mboxname.c +++ cyrus-imapd-2.3.17/imap/mboxname.c @@ -113,6 +113,8 @@ static int mboxname_tointernal(struct na char *cp; char *atp; int userlen, domainlen = 0, namelen; + int name_has_domain = 0; + const char *name_local_part = NULL; /* Blank the result, just in case */ result[0] = '\0'; @@ -163,6 +165,18 @@ static int mboxname_tointernal(struct na } } + if (config_getswitch(IMAPOPT_ALLOWCROSSDOMAINACLS) && + !namespace->isadmin && + !strncmp(name, "user", 4) && name[4] == namespace->hier_sep) { + name_local_part = strchr(name + 5, namespace->hier_sep); + if (!name_local_part) { + name_local_part = name + strlen(name); + } + domainlen = name_local_part - (name + 5) + 1; + sprintf(result, "%.*s!", domainlen - 1, name + 5); + name_has_domain = 1; + } + /* if no domain specified, we're in the default domain */ } @@ -193,7 +207,13 @@ static int mboxname_tointernal(struct na if (domainlen+namelen > MAX_MAILBOX_NAME) { return IMAP_MAILBOX_BADNAME; } - sprintf(result, "%.*s", namelen, name); + + if (name_has_domain) { + sprintf(result, "user%s", name_local_part ? name_local_part : ""); + } + else { + sprintf(result, "%.*s", namelen, name); + } /* Translate any separators in mailboxname */ mboxname_hiersep_tointernal(namespace, result, 0); @@ -356,6 +376,7 @@ static int mboxname_toexternal(struct na { char *domain = NULL, *cp; size_t domainlen = 0, resultlen; + int append_domain = 1; /* Blank the result, just in case */ result[0] = '\0'; @@ -370,18 +391,29 @@ static int mboxname_toexternal(struct na /* don't use the domain if it matches the user's domain */ if (userid && (cp = strchr(userid, '@')) && (strlen(++cp) == domainlen) && !strncmp(domain, cp, domainlen)) - domain = NULL; + append_domain = 0; } - strcpy(result, name); - - /* Translate any separators in mailboxname */ - mboxname_hiersep_toexternal(namespace, result, 0); + if (config_getswitch(IMAPOPT_ALLOWCROSSDOMAINACLS) && !namespace->isadmin + && domain && !strncmp(name, "user", 4) && + (name[4] == 0 || name[4] == '.')) { + sprintf(result, "user%c%.*s", namespace->hier_sep, domainlen, domain); + if (name[4] != 0) + sprintf(result + domainlen + 5, "%c%s", namespace->hier_sep, + name + 5); + mboxname_hiersep_toexternal(namespace, result + domainlen + 6, 0); + append_domain = 0; + } + else { + strcpy(result, name); + /* Translate any separators in mailboxname */ + mboxname_hiersep_toexternal(namespace, result, 0); + } resultlen = strlen(result); /* Append domain */ - if (domain) { + if (domain && append_domain) { if(resultlen+domainlen+1 > MAX_MAILBOX_NAME) return IMAP_MAILBOX_BADNAME; Index: cyrus-imapd-2.3.17/lib/imapoptions =================================================================== --- cyrus-imapd-2.3.17.orig/lib/imapoptions +++ cyrus-imapd-2.3.17/lib/imapoptions @@ -1278,6 +1278,9 @@ product version in the capabilities */ /* Send mail to mailboxes, which do not exists, to this user. NOTE: This must be an existing local mailbox name. NOT an email address! */ +{ "allowcrossdomainacls", 0, SWITCH } +/* Allow ACL across domain boundaries. */ + /* .SH SEE ALSO .PP
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor