From 7160d94e91142412ab7a8252effbd3b8764ad70e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Garc=C3=ADa=20S=C3=A1ez?= Date: Wed, 20 May 2015 18:32:44 +0200 Subject: [PATCH 01/22] Set domain before fetching auth sources In multidomain environment right now we are trying to authenticate against all sources defined in sogo.conf because the domain is not set at this point. In sogo.conf we have to specify the domain a source is useful for, so with this patch instead of 'n' tries of authentication we will perform only 1 (in a scenario where we have 1 source per domain, and we have 'n' domains). --- SoObjects/SOGo/SOGoUserManager.m | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 125ca3fcc..39c91ab60 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -425,9 +425,19 @@ static Class NSNullK; NSEnumerator *authIDs; NSString *currentID; BOOL checkOK; - + SOGoSystemDefaults *sd; + NSRange r; + checkOK = NO; - + + if (*domain == nil) + { + sd = [SOGoSystemDefaults sharedSystemDefaults]; + r = [login rangeOfString: @"@" options: NSBackwardsSearch]; + if ([sd enableDomainBasedUID] && r.location != NSNotFound) + *domain = [login substringFromIndex: (r.location + r.length)]; + } + authIDs = [[self authenticationSourceIDsInDomain: *domain] objectEnumerator]; while (!checkOK && (currentID = [authIDs nextObject])) { From f4963df50f9aca4ebf7dc49b54d6de5159eaa347 Mon Sep 17 00:00:00 2001 From: Ludovic Marcotte Date: Tue, 19 May 2015 13:48:59 -0400 Subject: [PATCH 02/22] (fix) avoid appending the domain unconditionally when SOGoEnableDomainBasedUID is set to YES --- SoObjects/SOGo/SOGoUserFolder.m | 3 ++- SoObjects/SOGo/SOGoUserManager.m | 3 ++- UI/MainUI/SOGoRootPage.m | 6 ++++-- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/SoObjects/SOGo/SOGoUserFolder.m b/SoObjects/SOGo/SOGoUserFolder.m index ba8414b81..2a44128e8 100644 --- a/SoObjects/SOGo/SOGoUserFolder.m +++ b/SoObjects/SOGo/SOGoUserFolder.m @@ -427,7 +427,8 @@ { currentUser = [users objectAtIndex: i]; field = [currentUser objectForKey: @"c_uid"]; - if (enableDomainBasedUID) + if (enableDomainBasedUID && + [field rangeOfString: @"@"].location == NSNotFound) field = [NSString stringWithFormat: @"%@@%@", field, domain]; if (![field isEqualToString: login]) { diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 125ca3fcc..fd8105c0b 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -622,7 +622,8 @@ static Class NSNullK; // internal cache. [currentUser setObject: [newPassword asSHA1String] forKey: @"password"]; sd = [SOGoSystemDefaults sharedSystemDefaults]; - if ([sd enableDomainBasedUID]) + if ([sd enableDomainBasedUID] && + [login rangeOfString: @"@"].location == NSNotFound) userLogin = [NSString stringWithFormat: @"%@@%@", login, domain]; else userLogin = login; diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index df3e944b1..dc9712e88 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -228,7 +228,8 @@ if ([domain isNotNull]) { sd = [SOGoSystemDefaults sharedSystemDefaults]; - if ([sd enableDomainBasedUID]) + if ([sd enableDomainBasedUID] && + [username rangeOfString: @"@"].location == NSNotFound) username = [NSString stringWithFormat: @"%@@%@", username, domain]; } @@ -587,7 +588,8 @@ if ([domain isNotNull]) { sd = [SOGoSystemDefaults sharedSystemDefaults]; - if ([sd enableDomainBasedUID]) + if ([sd enableDomainBasedUID] && + [username rangeOfString: @"@"].location == NSNotFound) username = [NSString stringWithFormat: @"%@@%@", username, domain]; } From 020c8959258928a1e99ec4dafb2e1dedf8eeb9b2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Garc=C3=ADa=20S=C3=A1ez?= Date: Wed, 20 May 2015 11:44:06 +0200 Subject: [PATCH 03/22] Avoid uid+attributes entries on shared cache In multidomain environments this will produce that info@domain1.com can read info@domain2.com emails when info@domain2.com log in after info@domain1.com is already logged in. If multidomain is not enabled, this action is not needed because uid+attributes has been already saved on shared cache --- SoObjects/SOGo/SOGoUserManager.m | 24 ++++++++++-------------- 1 file changed, 10 insertions(+), 14 deletions(-) diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index fd8105c0b..499832780 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -776,24 +776,20 @@ static Class NSNullK; withLogin: (NSString *) login { NSEnumerator *emails; - NSString *key; - - [[SOGoCache sharedCache] - setUserAttributes: [newUser jsonRepresentation] - forLogin: login]; + NSString *key, *user_json; + + user_json = [newUser jsonRepresentation]; + [[SOGoCache sharedCache] setUserAttributes: user_json + forLogin: login]; if (![newUser isKindOfClass: NSNullK]) { - key = [newUser objectForKey: @"c_uid"]; - if (key && ![key isEqualToString: login]) - [[SOGoCache sharedCache] - setUserAttributes: [newUser jsonRepresentation] - forLogin: key]; - emails = [[newUser objectForKey: @"emails"] objectEnumerator]; while ((key = [emails nextObject])) - [[SOGoCache sharedCache] - setUserAttributes: [newUser jsonRepresentation] - forLogin: key]; + { + if (![key isEqualToString: login]) + [[SOGoCache sharedCache] setUserAttributes: user_json + forLogin: key]; + } } } From 76dd53b4619c833ade32a54b0cdcdd545a0d36e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Garc=C3=ADa=20S=C3=A1ez?= Date: Wed, 20 May 2015 12:30:05 +0200 Subject: [PATCH 04/22] Fix conflicts with externalLoginWithEmail + DomainBasedUid On multidomain environment (SOGoEnableDomainBasedUID) with email for imap authentication (SOGoForceExternalLoginWithEmail) we need to use uid@domain instead of just uid in method getEmailForUID --- SoObjects/SOGo/SOGoUserManager.m | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 499832780..d41d57f08 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -362,6 +362,7 @@ static Class NSNullK; NSDictionary *contactInfos; NSString *login; SOGoDomainDefaults *dd; + SOGoSystemDefaults *sd; contactInfos = [self contactInfosForUserWithUIDorEmail: uid inDomain: domain]; @@ -372,10 +373,22 @@ static Class NSNullK; dd = [SOGoDomainDefaults defaultsForDomain: domain]; else dd = [SOGoSystemDefaults sharedSystemDefaults]; - - login = [dd forceExternalLoginWithEmail] ? [self getEmailForUID: uid] : uid; + + if ([dd forceExternalLoginWithEmail]) + { + sd = [SOGoSystemDefaults sharedSystemDefaults]; + if ([sd enableDomainBasedUID]) + // On multidomain environment we must use uid@domain + // for getEmailForUID method + login = [NSString stringWithFormat: @"%@@%@", uid, domain]; + else + login = uid; + login = [self getEmailForUID: login]; + } + else + login = uid; } - + return login; } From 725dea5f6f6f1547cbf6f4e740683e424f3f8fb6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Amor=20Garc=C3=ADa?= Date: Mon, 18 May 2015 14:43:11 +0200 Subject: [PATCH 05/22] Show 'complexity password' error instead of a generic error There is not discrimination between complexity and length errors because LDAP does not return different error codes for each case. --- SoObjects/SOGo/LDAPSource.m | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index 598e56ffe..c651f438e 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -737,7 +737,15 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses } NS_HANDLER { - [self logWithFormat: @"%@", localException]; + if ([[localException name] isEqual: @"LDAPException"] && + ([[[localException userInfo] objectForKey: @"error_code"] intValue] == LDAP_CONSTRAINT_VIOLATION)) + { + *perr = PolicyInsufficientPasswordQuality; + } + else + { + [self logWithFormat: @"%@", localException]; + } } NS_ENDHANDLER ; From cc62576fef5e64fe2fce97937fc5e64fa574413b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Garc=C3=ADa=20S=C3=A1ez?= Date: Wed, 20 May 2015 12:31:25 +0200 Subject: [PATCH 06/22] Avoid cache entries with uid@domain@domain prefix Depend of the current workflow these paths are reached with username as uid and sometimes as uid@domain. So in multidomain environments only append @domain when needed. --- SoObjects/SOGo/SOGoUserManager.m | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index d41d57f08..356bebfca 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -492,23 +492,17 @@ static Class NSNullK; NSString *dictPassword, *username, *jsonUser; SOGoSystemDefaults *dd; BOOL checkOK; - - // We check for cached passwords. If the entry is cached, we - // check this immediately. If not, we'll go directly at the - // authentication source and try to validate there, then cache it. - if (*_domain != nil) + + if (*_domain && [_login rangeOfString: @"@"].location == NSNotFound) username = [NSString stringWithFormat: @"%@@%@", _login, *_domain]; else username = _login; - failedCount = [[SOGoCache sharedCache] failedCountForLogin: username]; - dd = [SOGoSystemDefaults sharedSystemDefaults]; - - // // We check the fail count per user in memcache (per server). If the // fail count reaches X in Y minutes, we deny immediately the // authentications for Z minutes - // + failedCount = [[SOGoCache sharedCache] failedCountForLogin: username]; + dd = [SOGoSystemDefaults sharedSystemDefaults]; if (failedCount) { unsigned int current_time, start_time, delta, block_time; @@ -534,7 +528,9 @@ static Class NSNullK; } } - + // We check for cached passwords. If the entry is cached, we + // check this immediately. If not, we'll go directly at the + // authentication source and try to validate there, then cache it. jsonUser = [[SOGoCache sharedCache] userAttributesForLogin: username]; currentUser = [jsonUser objectFromJSONString]; dictPassword = [currentUser objectForKey: @"password"]; From 7dc333e79013cccc730284151acfe575a2e73af6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Garc=C3=ADa=20S=C3=A1ez?= Date: Wed, 20 May 2015 15:24:00 +0200 Subject: [PATCH 07/22] Fix warning distinct Objective-C type failedCount is a NSDictionary *, not NSMutableDictionary * --- SoObjects/SOGo/SOGoUserManager.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 356bebfca..2cbd2bafa 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -488,7 +488,8 @@ static Class NSNullK; grace: (int *) _grace useCache: (BOOL) useCache { - NSMutableDictionary *currentUser, *failedCount; + NSMutableDictionary *currentUser; + NSDictionary *failedCount; NSString *dictPassword, *username, *jsonUser; SOGoSystemDefaults *dd; BOOL checkOK; From b04b66fd797b4333792554dcad9fee135e8da0a7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20J=2E=20Hern=C3=A1ndez=20Blasco?= Date: Tue, 26 May 2015 21:42:57 +0200 Subject: [PATCH 08/22] Use UTC offset to encode NSCalendarDate in BSON Using name abbreviation in Objective-C is discouraged as it stated in the following link: https://developer.apple.com/library/prerelease/ios/documentation/Cocoa/Reference/Foundation/Classes/NSTimeZone_Class/index.html#//apple_ref/occ/clm/NSTimeZone/timeZoneWithAbbreviation: Indeed, the GNUStep library is generating the name abbreviation using the system tzdata information but parsing this data using GNUStep resources making changes like this: http://mm.icann.org/pipermail/tz-announce/2014-August/000023.html Not working until GNUStep reaches these tzdata changes. Using the UTC offset we are losing the position in planet Earth but it could be considered valid looking at other bson implementations. --- SoObjects/SOGo/BSONCodec.m | 35 ++++++++++++++++++++++++++--------- 1 file changed, 26 insertions(+), 9 deletions(-) diff --git a/SoObjects/SOGo/BSONCodec.m b/SoObjects/SOGo/BSONCodec.m index 99eee87c4..ce4c01e24 100644 --- a/SoObjects/SOGo/BSONCodec.m +++ b/SoObjects/SOGo/BSONCodec.m @@ -1,10 +1,12 @@ -// -// BSONCodec.m -// BSON Codec for Objective-C. -// -// Created by Martin Kou on 8/17/10. -// MIT License, see LICENSE file for details. -// +/* + * BSONCodec.m + * BSON Codec for Objective-C. + * + * Created by Martin Kou on 8/17/10. + * MIT License, see LICENSE file for details. + * + * Adapted by Ludovic Marcotte and Enrique J. Hernández +*/ #import "BSONCodec.h" #import @@ -570,7 +572,7 @@ static NSDictionary *BSONTypes() { NSString *v; - v = [self descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %Z" + v = [self descriptionWithCalendarFormat: @"%Y-%m-%d %H:%M:%S %z" locale: nil]; return [v BSONEncode]; @@ -599,7 +601,22 @@ static NSDictionary *BSONTypes() key = [NSString stringWithFormat: @"%s", timezone]; - if (!(tz = [timezoneCache objectForKey: key])) + /* We may have the zone using the UTC offset + or abbreviation (deprecated) */ + if (timezone && strlen(timezone) > 0 && (timezone[0] == '+' || timezone[0] == '-')) + { + NSCalendarDate *tzDate; + + tzDate = [[NSCalendarDate alloc] initWithString: key + calendarFormat: @"%z" + locale: nil]; + [tzDate autorelease]; + if (tzDate) + tz = [tzDate timeZone]; + else + tz = nil; + } + else if (!(tz = [timezoneCache objectForKey: key])) { tz = [NSTimeZone timeZoneWithAbbreviation: key]; From 76f80c507cf0c3438346bc551458d5a7971d28fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Garc=C3=ADa=20S=C3=A1ez?= Date: Thu, 28 May 2015 12:35:18 +0200 Subject: [PATCH 09/22] safe decoding of secured value This was crashing with invalid value (shorter than it should be or nil value) --- SoObjects/SOGo/SOGoSession.m | 41 ++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 20 deletions(-) diff --git a/SoObjects/SOGo/SOGoSession.m b/SoObjects/SOGo/SOGoSession.m index 235ef371e..c3ae35fb1 100644 --- a/SoObjects/SOGo/SOGoSession.m +++ b/SoObjects/SOGo/SOGoSession.m @@ -157,7 +157,7 @@ // that much about this for now. // + (NSString *) securedValue: (NSString *) theValue - usingKey: (NSString *) theKey + usingKey: (NSString *) theKey { NSData *data; NSString *s; @@ -171,13 +171,12 @@ klen = [data length]; // Get the key - padding it with 0 with key length - pass = (char *)malloc(klen); - memset(pass, 0, klen); + pass = (char *) calloc(klen, sizeof(char)); [theValue getCString: pass maxLength: klen encoding: NSUTF8StringEncoding]; // Target buffer buf = (char *)malloc(klen); - + for (i = 0; i < klen; i++) { buf[i] = key[i] ^ pass[i]; @@ -186,36 +185,38 @@ free(pass); data = [NSData dataWithBytesNoCopy: buf length: klen freeWhenDone: YES]; - + s = [[NSString alloc] initWithData: [data dataByEncodingBase64WithLineLength: 1024] - encoding: NSASCIIStringEncoding]; + encoding: NSASCIIStringEncoding]; return [s autorelease]; } + (NSString *) valueFromSecuredValue: (NSString *) theValue - usingKey: (NSString *) theKey + usingKey: (NSString *) theKey { - NSData *data; + NSData *dataKey, *dataValue; NSString *s; - - char *buf, *key, *pass; - int i, klen; + + char *buf, *key, *value; + size_t i, klen, vlen; // Get the key length and its bytes - data = [theKey dataByDecodingBase64]; - key = (char *)[data bytes]; - klen = [data length]; + dataKey = [theKey dataByDecodingBase64]; + key = (char *)[dataKey bytes]; + klen = [dataKey length]; + + // Get the secured value length and its bytes + dataValue = [theValue dataByDecodingBase64]; + value = (char *)[dataValue bytes]; + vlen = [dataValue length]; - // Get the secured password - pass = (char *)[[theValue dataByDecodingBase64] bytes]; - // Target buffer - buf = (char *)malloc(klen); + buf = (char *) calloc(klen, sizeof(char)); - for (i = 0; i < klen; i++) + for (i = 0; i < klen && i < vlen; i++) { - buf[i] = key[i] ^ pass[i]; + buf[i] = key[i] ^ value[i]; } // buf is now our C string in UTF8 From 1ec53a063c72ba23f9b8481b49c5d987bd64d134 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Juan=20Vall=C3=A9s?= Date: Thu, 28 May 2015 14:47:07 +0200 Subject: [PATCH 10/22] oc-calendar: Improve check for appointment updates The UID was being used to check if the changes in an appointment had been made by its organiser. In this case, the UID is the user name, without taking the domain into account. The `owner` variable, however, is a full email address, so the comparison was never successful. This caused the update notification mail not to be sent. --- .../Appointments/SOGoAppointmentObject.m | 29 +++++++------------ 1 file changed, 10 insertions(+), 19 deletions(-) diff --git a/SoObjects/Appointments/SOGoAppointmentObject.m b/SoObjects/Appointments/SOGoAppointmentObject.m index 64baf52d7..ca18b0271 100644 --- a/SoObjects/Appointments/SOGoAppointmentObject.m +++ b/SoObjects/Appointments/SOGoAppointmentObject.m @@ -2106,32 +2106,23 @@ inRecurrenceExceptionsForEvent: (iCalEvent *) theEvent // if ([[newEvent attendees] count] || [[oldEvent attendees] count]) { - NSString *uid; - + BOOL userIsOrganizer; + // newEvent might be nil here, if we're deleting a RECURRENCE-ID with attendees - // If that's the case, we use the oldEvent for now just to obtain the organizer - // and we'll swap it back to nil once we're done. - if (!newEvent) - newEvent = oldEvent; - - // We fetch the organizer's uid. Sometimes, the recurrence-id will - // have it, sometimes not. If it doesn't, we fetch it from the master event. - uid = [[newEvent organizer] uid]; - - if (!uid && !recurrenceId) - uid = [[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid]; - + // If that's the case, we use the oldEvent to obtain the organizer + if (newEvent) + userIsOrganizer = [newEvent userIsOrganizer: ownerUser]; + else + userIsOrganizer = [oldEvent userIsOrganizer: ownerUser]; + // With Thunderbird 10, if you create a recurring event with an exception // occurence, and invite someone, the PUT will have the organizer in the // recurrence-id and not in the master event. We must fix this, otherwise // SOGo will break. if (!recurrenceId && ![[[[[newEvent parent] events] objectAtIndex: 0] organizer] uid]) [[[[newEvent parent] events] objectAtIndex: 0] setOrganizer: [newEvent organizer]]; - - if (newEvent == oldEvent) - newEvent = nil; - - if (uid && [uid caseInsensitiveCompare: owner] == NSOrderedSame) + + if (userIsOrganizer) { // A RECCURENCE-ID was removed if (!newEvent && oldEvent) From 3dd8bddc0e0e5f8cab3507e36e37f643ea70bea6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Garc=C3=ADa?= Date: Tue, 2 Jun 2015 12:24:32 +0200 Subject: [PATCH 11/22] Revert "(fix) more fixes and clarifications on the mutli-domain settings" This reverts commit d07df554f3d43078dedd74cefe7a63049992c67f. --- Documentation/SOGoInstallationGuide.asciidoc | 12 ++++-------- SoObjects/SOGo/SOGoUser.m | 5 ++--- SoObjects/SOGo/SOGoUserManager.m | 14 +++++++++++++- 3 files changed, 19 insertions(+), 12 deletions(-) diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index 46980463b..5ecd53450 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -2136,8 +2136,7 @@ Multi-domains Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you want your installation to isolate two groups of users, you must -define a distinct authentication source for each _domain_. Your domain keys -must have the same value as your email domain you want to add. Following is +define a distinct authentication source for each _domain_. Following is the same configuration that now includes two domains (acme.com and coyote.com): @@ -2145,7 +2144,7 @@ coyote.com): { ... domains = { - acme.com = { + acme = { SOGoMailDomain = acme.com; SOGoDraftsFolderName = Drafts; SOGoUserSources = ( @@ -2166,7 +2165,7 @@ coyote.com): } ); }; - coyote.com = { + coyote = { SOGoMailDomain = coyote.com; SOGoIMAPServer = imap.coyote.com; SOGoUserSources = ( @@ -2197,7 +2196,7 @@ domains. [cols="3,47,50a"] |======================================================================= |S |SOGoEnableDomainBasedUID -|Parameter used to enable user identification by domain. Users will be +|Parameter used to activate user identification by domain. Users will be able (without being required) to login using the form `username@domain`, meaning that values of _UIDFieldName_ no longer have to be unique among all domains but only within the same domain. Internally, users will @@ -2719,9 +2718,6 @@ h|2.3.0 This will grow the "participant states" field of calendar quick tables to a larger size and add the the "c_description" column to calendar quick tables. -Moreover, if you are using a multi-domain configuration, make sure the keys for -your domains match the email domains you have defined. - h|2.2.8 |The configuration configuration parameters were renamed: diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index fa6459f59..12d028fd3 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -165,9 +165,8 @@ // The domain is probably appended to the username; // make sure it is defined as a domain in the configuration. domain = [newLogin substringFromIndex: (r.location + r.length)]; - if ([[sd domainIds] containsObject: domain] && - ![sd enableDomainBasedUID]) - newLogin = [newLogin substringToIndex: r.location]; + if (![[sd domainIds] containsObject: domain]) + domain = nil; if (domain != nil && ![sd enableDomainBasedUID]) // Login domains are enabled (SOGoLoginDomains) but not diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 21cebce2d..6ee3b4d76 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -514,9 +514,21 @@ static Class NSNullK; if (r.location != NSNotFound) { + NSArray *allDomains; + int i; + *_domain = [username substringFromIndex: r.location+1]; - if (![[[SOGoSystemDefaults sharedSystemDefaults] domainIds] containsObject: *_domain]) + allDomains = [[dd dictionaryForKey: @"domains"] allValues]; + + for (i = 0; i < [allDomains count]; i++) + { + if ([*_domain isEqualToString: [[allDomains objectAtIndex: i] objectForKey: @"SOGoMailDomain"]]) + break; + } + + // We haven't found one + if (i == [allDomains count]) *_domain = nil; } } From 90e11d76f61dd8855f7c6ddb267feb39bf26bc52 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Garc=C3=ADa?= Date: Tue, 2 Jun 2015 12:24:44 +0200 Subject: [PATCH 12/22] Revert "(fix) more multi-domain fixes and cleanups" This reverts commit ed42d1e26b047e9d074a46a1a60c13a65e2d39de. --- SoObjects/SOGo/SOGoUser.m | 8 ++++---- SoObjects/SOGo/SOGoUserManager.m | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 12d028fd3..c1b0f7603 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -165,7 +165,9 @@ // The domain is probably appended to the username; // make sure it is defined as a domain in the configuration. domain = [newLogin substringFromIndex: (r.location + r.length)]; - if (![[sd domainIds] containsObject: domain]) + if ([[sd domainIds] containsObject: domain]) + newLogin = [newLogin substringToIndex: r.location]; + else domain = nil; if (domain != nil && ![sd enableDomainBasedUID]) @@ -197,9 +199,7 @@ // [SOGoUser loginInDomain] only returns the login. r = [realUID rangeOfString: domain options: NSBackwardsSearch|NSCaseInsensitiveSearch]; - // Do NOT strip @domain.com if SOGoEnableDomainBasedUID is enabled since - // the real login most likely is the email address. - if (r.location != NSNotFound && ![sd enableDomainBasedUID]) + if (r.location != NSNotFound) uid = [realUID substringToIndex: r.location-1]; else uid = [NSString stringWithString: realUID]; diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 6ee3b4d76..cfc159c3c 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -912,7 +912,7 @@ static Class NSNullK; { // Remove the "@" prefix used to identified groups in the ACL tables. aUID = [uid hasPrefix: @"@"] ? [uid substringFromIndex: 1] : uid; - if (domain && [aUID rangeOfString: @"@"].location == NSNotFound) + if (domain) cacheUid = [NSString stringWithFormat: @"%@@%@", aUID, domain]; else cacheUid = aUID; From 96d88de564f36e45bf9d82258c1378b881532b7f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Garc=C3=ADa?= Date: Tue, 2 Jun 2015 12:24:56 +0200 Subject: [PATCH 13/22] Revert "Fixed mess regarding uid/realUID" This reverts commit 4f303f8aa26046ecae916c457839d84622b260bb. --- SoObjects/SOGo/SOGoUser.m | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index c1b0f7603..91d3b1b5a 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -197,12 +197,8 @@ // When the user is associated to a domain, the [SOGoUser login] // method returns the combination login@domain while // [SOGoUser loginInDomain] only returns the login. - r = [realUID rangeOfString: domain options: NSBackwardsSearch|NSCaseInsensitiveSearch]; - - if (r.location != NSNotFound) - uid = [realUID substringToIndex: r.location-1]; - else - uid = [NSString stringWithString: realUID]; + uid = [NSString stringWithString: realUID]; + realUID = [NSString stringWithFormat: @"%@@%@", realUID, domain]; } } From 5e84f2817f8ac3e24ad1a9d6c8085fe4d48c44cb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Amor=20Garc=C3=ADa?= Date: Wed, 27 May 2015 16:41:22 +0200 Subject: [PATCH 14/22] sogo-tool: Added create-folder command --- Tools/GNUmakefile | 1 + Tools/SOGoToolCreateFolder.m | 175 +++++++++++++++++++++++++++++++++++ Tools/SOGoToolRestore.h | 48 ++++++++++ Tools/SOGoToolRestore.m | 22 +---- 4 files changed, 226 insertions(+), 20 deletions(-) create mode 100644 Tools/SOGoToolCreateFolder.m create mode 100644 Tools/SOGoToolRestore.h diff --git a/Tools/GNUmakefile b/Tools/GNUmakefile index 869fb52c6..32f9119e4 100644 --- a/Tools/GNUmakefile +++ b/Tools/GNUmakefile @@ -22,6 +22,7 @@ $(SOGO_TOOL)_OBJC_FILES += \ SOGoToolRemoveDoubles.m \ SOGoToolRenameUser.m \ SOGoToolRestore.m \ + SOGoToolCreateFolder.m \ SOGoToolUserPreferences.m \ SOGoToolManageEAS.m TOOL_NAME += $(SOGO_TOOL) diff --git a/Tools/SOGoToolCreateFolder.m b/Tools/SOGoToolCreateFolder.m new file mode 100644 index 000000000..423ec7266 --- /dev/null +++ b/Tools/SOGoToolCreateFolder.m @@ -0,0 +1,175 @@ +/* SOGoToolCreateFolder.m - this file is part of SOGo + * Implementation of create-folder command for sogo-tool + * + * Copyright (C) 2015 Javier Amor Garcia + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + +#import +#import +#import +#import + +#import +#import + +#import +#import + +#import "SOGoToolRestore.h" + +@interface SOGoToolCreateFolder : SOGoToolRestore +{ + NSMutableArray *foldersContents; + NSString *folderType; +} + +@end + +@implementation SOGoToolCreateFolder + ++ (NSString *) command +{ + return @"create-folder"; +} + ++ (NSString *) description +{ + return @"create folders for a user"; +} + +- (id) init +{ + if ((self = [super init])) + { + foldersContents = nil; + folderType = nil; + } + + return self; +} + +- (void) dealloc +{ + [foldersContents release]; + [folderType release]; + [super dealloc]; +} + +- (void) usage +{ + fprintf (stderr, "create-folder user type [displayname ...]\n\n" + " user the user on which the folder(s) will be created\n" + " type type of directory. Calendar or Contacts\n" + " displayname display name(s) for the created folder(s)\n\n" + "Examples: sogo-tool create-folder user1 Calendar cal1 cal2\n" + " sogo-tool create-folder user1 Contacts agenda\n"); +} + +- (BOOL) createNewFolderOfType: (NSString *) type + withContent: (NSDictionary *) content +{ + NSString *folder; + NSString *guid; + GCSFolderManager *fm; + GCSFolder *gcsFolder; + BOOL rc; + + guid = [SOGoObject globallyUniqueObjectId]; + folder= [NSString stringWithFormat: @"/Users/%@/%@/%@", + userID, type, guid]; + fm = [GCSFolderManager defaultFolderManager]; + + rc = [self createFolder: folder withFM: fm]; + if (!rc) + { + NSLog (@"Create directory failed at path %s", folder); + return NO; + } + + gcsFolder = [fm folderAtPath: folder]; + if (!gcsFolder) + { + NSLog (@"folder '%@' could not be created", folder); + return NO; + } + + rc = [self restoreDisplayName: [content objectForKey: @"displayname"] + ofFolder: gcsFolder + withFM: fm]; + return rc; +} + +- (BOOL) proceed +{ + BOOL rc; + NSUInteger count, i; + NSDictionary * content; + + rc = YES; + count = [foldersContents count]; + for (i = 0; i < count; i++) + { + content = [foldersContents objectAtIndex: i]; + if (![self createNewFolderOfType: folderType withContent: content]) + { + rc = NO; + } + } + + return rc; +} + +- (BOOL) parseArguments +{ + NSString *identifier; + NSUInteger count, i; + NSDictionary *content; + + count = [arguments count]; + if (count < 3) + { + [self usage]; + return NO; + } + + identifier = [arguments objectAtIndex: 0]; + if (![self fetchUserID: identifier]) + { + fprintf (stderr, "Invalid user:%s\n", [identifier cString]); + return NO; + } + + folderType = [arguments objectAtIndex: 1]; + if (!([folderType isEqualToString: @"Contacts"] || [folderType isEqualToString: @"Calendar"])) + { + fprintf (stderr, "Invalid folder type:%s\n", [folderType cString]); + return NO; + } + + foldersContents = [[NSMutableArray alloc] init]; + for (i = 2; i < count; i++) + { + content = [NSDictionary dictionaryWithObject: [arguments objectAtIndex: i] + forKey: @"displayname"]; + [foldersContents addObject: content]; + } + + return YES; +} + +@end diff --git a/Tools/SOGoToolRestore.h b/Tools/SOGoToolRestore.h new file mode 100644 index 000000000..f5be03928 --- /dev/null +++ b/Tools/SOGoToolRestore.h @@ -0,0 +1,48 @@ +/* SOGoToolRestore.h - this file is part of SOGo + * Header to allow subclassing of SOGoToolRestore class + * + * Copyright (C) 2015 Javier Amor Garcia + * + * This file is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2, or (at your option) + * any later version. + * + * This file is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; see the file COPYING. If not, write to + * the Free Software Foundation, Inc., 59 Temple Place - Suite 330, + * Boston, MA 02111-1307, USA. + */ + + +#import "SOGoTool.h" + +typedef enum SOGoToolRestoreMode { + SOGoToolRestoreFolderMode, + SOGoToolRestoreFolderDestructiveMode, + SOGoToolRestoreListFoldersMode, + SOGoToolRestorePreferencesMode +} SOGoToolRestoreMode; + +@interface SOGoToolRestore : SOGoTool +{ + NSString *directory; + NSString *userID; + NSString *restoreFolder; + BOOL destructive; /* destructive mode not handled */ + SOGoToolRestoreMode restoreMode; +} + +- (BOOL) fetchUserID: (NSString *) identifier; +- (BOOL) createFolder: (NSString *) folder + withFM: (GCSFolderManager *) fm; +- (BOOL) restoreDisplayName: (NSString *) newDisplayName + ofFolder: (GCSFolder *) gcsFolder + withFM: (GCSFolderManager *) fm; + +@end diff --git a/Tools/SOGoToolRestore.m b/Tools/SOGoToolRestore.m index d3fb601f9..54e3179bd 100644 --- a/Tools/SOGoToolRestore.m +++ b/Tools/SOGoToolRestore.m @@ -45,32 +45,14 @@ #import #import -#import "SOGoTool.h" +#import "SOGoToolRestore.h" /* TODO: - respond to "--help restore" - handle database connectivity errors - handle the case where the restored folder has been deleted - write methods in GDLContentStore to get/update displayname - and storing roles */ - -typedef enum SOGoToolRestoreMode { - SOGoToolRestoreFolderMode, - SOGoToolRestoreFolderDestructiveMode, - SOGoToolRestoreListFoldersMode, - SOGoToolRestorePreferencesMode -} SOGoToolRestoreMode; - -@interface SOGoToolRestore : SOGoTool -{ - NSString *directory; - NSString *userID; - NSString *restoreFolder; - BOOL destructive; /* destructive mode not handled */ - SOGoToolRestoreMode restoreMode; -} - -@end + and storing roles */ @implementation SOGoToolRestore From d92b0341fbd5aa8f7b711a4cec9198dc34ca899c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jes=C3=BAs=20Garc=C3=ADa=20S=C3=A1ez?= Date: Thu, 28 May 2015 17:28:52 +0200 Subject: [PATCH 15/22] sogo-tool restore works in multidomain environments c_uid is not unique globally when multidomain is enabled --- Tools/SOGoToolRestore.m | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/Tools/SOGoToolRestore.m b/Tools/SOGoToolRestore.m index 54e3179bd..a0f411bd9 100644 --- a/Tools/SOGoToolRestore.m +++ b/Tools/SOGoToolRestore.m @@ -40,6 +40,7 @@ #import #import #import +#import #import #import @@ -154,10 +155,22 @@ BOOL rc; SOGoUserManager *lm; NSDictionary *infos; + SOGoSystemDefaults *sd; + NSString *uid = nil; lm = [SOGoUserManager sharedUserManager]; infos = [lm contactInfosForUserWithUIDorEmail: identifier]; - ASSIGN (userID, [infos objectForKey: @"c_uid"]); + if (infos) + { + sd = [SOGoSystemDefaults sharedSystemDefaults]; + if ([sd enableDomainBasedUID]) + uid = [NSString stringWithFormat: @"%@@%@", + [infos objectForKey: @"c_uid"], + [infos objectForKey: @"c_domain"]]; + else + uid = [infos objectForKey: @"c_uid"]; + } + ASSIGN (userID, uid); if (userID) rc = YES; else From 7540cc3e33ba47ec8ca56271db7ae22a2e3d8588 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Amor=20Garc=C3=ADa?= Date: Tue, 3 Mar 2015 17:03:29 +0100 Subject: [PATCH 16/22] oc: can use client data to get recipient address Before this change, the recipient address was only extracted from the sogo user object. This made mail to groups undeliverable. Now if we do not have mail addresses from user object, we try to use parameters from the client call. --- OpenChange/MAPIStoreMessage.m | 98 +++++++++++++++++++++++++---------- 1 file changed, 71 insertions(+), 27 deletions(-) diff --git a/OpenChange/MAPIStoreMessage.m b/OpenChange/MAPIStoreMessage.m index 5d5e03dac..1613171ea 100644 --- a/OpenChange/MAPIStoreMessage.m +++ b/OpenChange/MAPIStoreMessage.m @@ -178,56 +178,100 @@ rtf2html (NSData *compressedRTF) andColumns: (struct SPropTagArray *) columns { NSMutableDictionary *recipientProperties; + enum MAPITAGS prop_tag; + char *displayName = NULL; + char *email = NULL; + enum MAPI_OBJTYPE object_type = 0; + char *smtpAddress = NULL; SOGoUser *recipientUser; NSUInteger count; + NSString *recipientEmail = nil; + NSString *recipientFullName = nil; id value; recipientProperties = [NSMutableDictionary dictionaryWithCapacity: columns->cValues + 2]; + for (count = 0; count < columns->cValues; count++) + { + prop_tag = columns->aulPropTag[count]; + switch(prop_tag) { + case PidTagDisplayName: + displayName = recipient->data[count]; + break; + case PidTagEmailAddress: + email = recipient->data[count]; + break; + case PidTagObjectType: + object_type = *((uint8_t*) recipient->data[count]); + break; + case PidTagSmtpAddress: + smtpAddress = recipient->data[count]; + break; + default: + break; + } + + if (recipient->data[count]) + { + value = NSObjectFromValuePointer (prop_tag, + recipient->data[count]); + if (value) + [recipientProperties setObject: value + forKey: MAPIPropertyKey (prop_tag)]; + } + } + if (recipient->username) { value = [NSString stringWithUTF8String: recipient->username]; [recipientProperties setObject: value forKey: @"x500dn"]; + } + if (object_type == MAPI_MAILUSER && recipient->username) + { + /* values from user object have priority uppon the data passed for the client */ recipientUser = [SOGoUser userWithLogin: [value lowercaseString]]; if (recipientUser) { value = [recipientUser cn]; if ([value length] > 0) - [recipientProperties setObject: value forKey: @"fullName"]; + recipientFullName = value; + value = [[recipientUser allEmails] objectAtIndex: 0]; if ([value length] > 0) - [recipientProperties setObject: value forKey: @"email"]; - } - } - else - { - if (recipient->data[0]) - { - value = [NSString stringWithUTF8String: recipient->data[0]]; - if ([value length] > 0) - [recipientProperties setObject: value forKey: @"fullName"]; - } - if (recipient->data[1]) - { - value = [NSString stringWithUTF8String: recipient->data[1]]; - if ([value length] > 0) - [recipientProperties setObject: value forKey: @"email"]; - } + recipientEmail = value; + } } - for (count = 0; count < columns->cValues; count++) + /* If we do not have values from the user object we try to get them from the parameters */ + if (!recipientFullName && displayName) { - if (recipient->data[count]) - { - value = NSObjectFromValuePointer (columns->aulPropTag[count], - recipient->data[count]); - if (value) - [recipientProperties setObject: value - forKey: MAPIPropertyKey (columns->aulPropTag[count])]; - } + value = [NSString stringWithUTF8String: displayName]; + if ([value length] > 0) + recipientFullName = value; } + if (!recipientEmail && email) + { + value = [NSString stringWithUTF8String: email]; + if ([value length] > 0) + recipientEmail = value; + } + + if (!recipientEmail && smtpAddress) + { + value = [NSString stringWithUTF8String: smtpAddress]; + if ([value length] > 0) + recipientEmail = value; + } + + /* Now we can set the properties if we have them */ + if (recipientFullName) + [recipientProperties setObject: recipientFullName forKey: @"fullName"]; + + if (recipientEmail) + [recipientProperties setObject: recipientEmail forKey: @"email"]; + return recipientProperties; } From 72aab7f83f03468a412c9f933059394829a45fa5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Amor=20Garc=C3=ADa?= Date: Thu, 18 Jun 2015 18:19:02 +0200 Subject: [PATCH 17/22] ActiveSync: can be controlled by module constraint Added 'ActiveSync' module constraint. If constraint is not honored the ActiveSync request returns a forbidden (403). --- ActiveSync/SOGoActiveSyncDispatcher.m | 9 ++++++++ SoObjects/SOGo/LDAPSource.m | 2 ++ SoObjects/SOGo/SOGoUserManager.m | 33 ++++++++++++++++----------- 3 files changed, 31 insertions(+), 13 deletions(-) diff --git a/ActiveSync/SOGoActiveSyncDispatcher.m b/ActiveSync/SOGoActiveSyncDispatcher.m index 7cd0e5c53..c2f64786e 100644 --- a/ActiveSync/SOGoActiveSyncDispatcher.m +++ b/ActiveSync/SOGoActiveSyncDispatcher.m @@ -2753,6 +2753,7 @@ static BOOL debugOn = NO; NSAutoreleasePool *pool; id builder, dom; SEL aSelector; + id activeUser; NSString *cmdName, *deviceId; NSData *d; @@ -2761,6 +2762,14 @@ static BOOL debugOn = NO; ASSIGN(context, theContext); + activeUser = [context activeUser]; + if (![activeUser canAccessModule: @"ActiveSync"]) + { + [theResponse setStatus: 403]; + [self logWithFormat: @"EAS - Forbidden access for user %@", [activeUser loginInDomain]]; + return nil; + } + // Get the device ID, device type and "stash" them deviceId = [[theRequest uri] deviceId]; [context setObject: deviceId forKey: @"DeviceId"]; diff --git a/SoObjects/SOGo/LDAPSource.m b/SoObjects/SOGo/LDAPSource.m index 3ca686386..d537c6aec 100644 --- a/SoObjects/SOGo/LDAPSource.m +++ b/SoObjects/SOGo/LDAPSource.m @@ -1167,6 +1167,8 @@ groupObjectClasses: (NSArray *) newGroupObjectClasses intoLDIFRecord: (NSMutableDictionary *) ldifRecord]; [self _fillConstraints: ldapEntry forModule: @"Mail" intoLDIFRecord: (NSMutableDictionary *) ldifRecord]; + [self _fillConstraints: ldapEntry forModule: @"ActiveSync" + intoLDIFRecord: (NSMutableDictionary *) ldifRecord]; if (contactMapping) [self _applyContactMappingToResult: ldifRecord]; diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 86d198d2b..dcabeb492 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -636,7 +636,7 @@ static Class NSNullK; [currentSource setBindPassword: _pwd]; } } - + return checkOK; } @@ -729,6 +729,12 @@ static Class NSNullK; NSNumber *isGroup; NSArray *c_emails; BOOL access; + NSEnumerator *enumerator; + NSString *access_type; + NSArray *access_types_list = [NSArray arrayWithObjects: @"CalendarAccess", + @"MailAccess", + @"ActiveSyncAccess", + nil]; emails = [NSMutableArray array]; cn = nil; @@ -738,10 +744,10 @@ static Class NSNullK; c_imaplogin = nil; c_sievehostname = nil; - [currentUser setObject: [NSNumber numberWithBool: YES] - forKey: @"CalendarAccess"]; - [currentUser setObject: [NSNumber numberWithBool: YES] - forKey: @"MailAccess"]; + enumerator = [access_types_list objectEnumerator]; + while ((access_type = [enumerator nextObject]) != nil) + [currentUser setObject: [NSNumber numberWithBool: YES] + forKey: access_type]; sogoSources = [[self authenticationSourceIDsInDomain: domain] objectEnumerator]; userEntry = nil; @@ -768,14 +774,15 @@ static Class NSNullK; c_imaplogin = [userEntry objectForKey: @"c_imaplogin"]; if (!c_sievehostname) c_sievehostname = [userEntry objectForKey: @"c_sievehostname"]; - access = [[userEntry objectForKey: @"CalendarAccess"] boolValue]; - if (!access) - [currentUser setObject: [NSNumber numberWithBool: NO] - forKey: @"CalendarAccess"]; - access = [[userEntry objectForKey: @"MailAccess"] boolValue]; - if (!access) - [currentUser setObject: [NSNumber numberWithBool: NO] - forKey: @"MailAccess"]; + + enumerator = [access_types_list objectEnumerator]; + while ((access_type = [enumerator nextObject]) != nil) + { + access = [[userEntry objectForKey: access_type] boolValue]; + if (!access) + [currentUser setObject: [NSNumber numberWithBool: NO] + forKey: access_type]; + } // We check if it's a group isGroup = [userEntry objectForKey: @"isGroup"]; From 67d0d9586986337d5e73769df5e5484d47d6e182 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Garc=C3=ADa?= Date: Fri, 26 Jun 2015 09:35:26 +0200 Subject: [PATCH 18/22] Revert "Revert "Fixed mess regarding uid/realUID"" This reverts commit 96d88de564f36e45bf9d82258c1378b881532b7f. --- SoObjects/SOGo/SOGoUser.m | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 91d3b1b5a..c1b0f7603 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -197,8 +197,12 @@ // When the user is associated to a domain, the [SOGoUser login] // method returns the combination login@domain while // [SOGoUser loginInDomain] only returns the login. - uid = [NSString stringWithString: realUID]; - realUID = [NSString stringWithFormat: @"%@@%@", realUID, domain]; + r = [realUID rangeOfString: domain options: NSBackwardsSearch|NSCaseInsensitiveSearch]; + + if (r.location != NSNotFound) + uid = [realUID substringToIndex: r.location-1]; + else + uid = [NSString stringWithString: realUID]; } } From 3f1a43cc13b223d94a987bbe2a7d00f2f3a7a2c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Garc=C3=ADa?= Date: Fri, 26 Jun 2015 09:35:37 +0200 Subject: [PATCH 19/22] Revert "Revert "(fix) more multi-domain fixes and cleanups"" This reverts commit 90e11d76f61dd8855f7c6ddb267feb39bf26bc52. --- SoObjects/SOGo/SOGoUser.m | 8 ++++---- SoObjects/SOGo/SOGoUserManager.m | 2 +- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index c1b0f7603..12d028fd3 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -165,9 +165,7 @@ // The domain is probably appended to the username; // make sure it is defined as a domain in the configuration. domain = [newLogin substringFromIndex: (r.location + r.length)]; - if ([[sd domainIds] containsObject: domain]) - newLogin = [newLogin substringToIndex: r.location]; - else + if (![[sd domainIds] containsObject: domain]) domain = nil; if (domain != nil && ![sd enableDomainBasedUID]) @@ -199,7 +197,9 @@ // [SOGoUser loginInDomain] only returns the login. r = [realUID rangeOfString: domain options: NSBackwardsSearch|NSCaseInsensitiveSearch]; - if (r.location != NSNotFound) + // Do NOT strip @domain.com if SOGoEnableDomainBasedUID is enabled since + // the real login most likely is the email address. + if (r.location != NSNotFound && ![sd enableDomainBasedUID]) uid = [realUID substringToIndex: r.location-1]; else uid = [NSString stringWithString: realUID]; diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 86d198d2b..c43892978 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -922,7 +922,7 @@ static Class NSNullK; { // Remove the "@" prefix used to identified groups in the ACL tables. aUID = [uid hasPrefix: @"@"] ? [uid substringFromIndex: 1] : uid; - if (domain) + if (domain && [aUID rangeOfString: @"@"].location == NSNotFound) cacheUid = [NSString stringWithFormat: @"%@@%@", aUID, domain]; else cacheUid = aUID; From dc2cc14d25857200aae9ac583532255e9ee031eb Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Garc=C3=ADa?= Date: Fri, 26 Jun 2015 09:35:47 +0200 Subject: [PATCH 20/22] Revert "Revert "(fix) more fixes and clarifications on the mutli-domain settings"" This reverts commit 3dd8bddc0e0e5f8cab3507e36e37f643ea70bea6. --- Documentation/SOGoInstallationGuide.asciidoc | 12 ++++++++---- SoObjects/SOGo/SOGoUser.m | 5 +++-- SoObjects/SOGo/SOGoUserManager.m | 14 +------------- 3 files changed, 12 insertions(+), 19 deletions(-) diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index 5ecd53450..46980463b 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -2136,7 +2136,8 @@ Multi-domains Configuration ~~~~~~~~~~~~~~~~~~~~~~~~~~~ If you want your installation to isolate two groups of users, you must -define a distinct authentication source for each _domain_. Following is +define a distinct authentication source for each _domain_. Your domain keys +must have the same value as your email domain you want to add. Following is the same configuration that now includes two domains (acme.com and coyote.com): @@ -2144,7 +2145,7 @@ coyote.com): { ... domains = { - acme = { + acme.com = { SOGoMailDomain = acme.com; SOGoDraftsFolderName = Drafts; SOGoUserSources = ( @@ -2165,7 +2166,7 @@ coyote.com): } ); }; - coyote = { + coyote.com = { SOGoMailDomain = coyote.com; SOGoIMAPServer = imap.coyote.com; SOGoUserSources = ( @@ -2196,7 +2197,7 @@ domains. [cols="3,47,50a"] |======================================================================= |S |SOGoEnableDomainBasedUID -|Parameter used to activate user identification by domain. Users will be +|Parameter used to enable user identification by domain. Users will be able (without being required) to login using the form `username@domain`, meaning that values of _UIDFieldName_ no longer have to be unique among all domains but only within the same domain. Internally, users will @@ -2718,6 +2719,9 @@ h|2.3.0 This will grow the "participant states" field of calendar quick tables to a larger size and add the the "c_description" column to calendar quick tables. +Moreover, if you are using a multi-domain configuration, make sure the keys for +your domains match the email domains you have defined. + h|2.2.8 |The configuration configuration parameters were renamed: diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 12d028fd3..fa6459f59 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -165,8 +165,9 @@ // The domain is probably appended to the username; // make sure it is defined as a domain in the configuration. domain = [newLogin substringFromIndex: (r.location + r.length)]; - if (![[sd domainIds] containsObject: domain]) - domain = nil; + if ([[sd domainIds] containsObject: domain] && + ![sd enableDomainBasedUID]) + newLogin = [newLogin substringToIndex: r.location]; if (domain != nil && ![sd enableDomainBasedUID]) // Login domains are enabled (SOGoLoginDomains) but not diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index c43892978..e53e9cb99 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -524,21 +524,9 @@ static Class NSNullK; if (r.location != NSNotFound) { - NSArray *allDomains; - int i; - *_domain = [username substringFromIndex: r.location+1]; - allDomains = [[dd dictionaryForKey: @"domains"] allValues]; - - for (i = 0; i < [allDomains count]; i++) - { - if ([*_domain isEqualToString: [[allDomains objectAtIndex: i] objectForKey: @"SOGoMailDomain"]]) - break; - } - - // We haven't found one - if (i == [allDomains count]) + if (![[[SOGoSystemDefaults sharedSystemDefaults] domainIds] containsObject: *_domain]) *_domain = nil; } } From 62b16f4ef35202cbaf37a43f54e589bd051f902d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Enrique=20J=2E=20Hern=C3=A1ndez=20Blasco?= Date: Mon, 29 Jun 2015 23:50:55 +0200 Subject: [PATCH 21/22] oc: Check PidTagObjectType before dereferencing on ModifyRecipients This is crashing when the PidTagObjectType property is set for some recipient and not for others. If the property is missing, then no object type for the recipient is assumed. --- OpenChange/MAPIStoreMessage.m | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/OpenChange/MAPIStoreMessage.m b/OpenChange/MAPIStoreMessage.m index 1613171ea..b842b2d6c 100644 --- a/OpenChange/MAPIStoreMessage.m +++ b/OpenChange/MAPIStoreMessage.m @@ -202,7 +202,8 @@ rtf2html (NSData *compressedRTF) email = recipient->data[count]; break; case PidTagObjectType: - object_type = *((uint8_t*) recipient->data[count]); + if (recipient->data[count]) + object_type = *((uint8_t*) recipient->data[count]); break; case PidTagSmtpAddress: smtpAddress = recipient->data[count]; @@ -229,7 +230,7 @@ rtf2html (NSData *compressedRTF) if (object_type == MAPI_MAILUSER && recipient->username) { - /* values from user object have priority uppon the data passed for the client */ + /* values from user object have priority over data sent by the client */ recipientUser = [SOGoUser userWithLogin: [value lowercaseString]]; if (recipientUser) { From 936c38c43e8c39fa5ad2e00c66456493e2a4f032 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Julio=20Garc=C3=ADa?= Date: Tue, 7 Jul 2015 14:25:17 +0200 Subject: [PATCH 22/22] Remove not needed block in SoObjects/SOGo/SOGoUserManager.m --- SoObjects/SOGo/SOGoUserManager.m | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index 19dab1f26..f93cef7e6 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -443,19 +443,11 @@ static Class NSNullK; checkOK = NO; - if (*domain == nil) - { - sd = [SOGoSystemDefaults sharedSystemDefaults]; - r = [login rangeOfString: @"@" options: NSBackwardsSearch]; - if ([sd enableDomainBasedUID] && r.location != NSNotFound) - *domain = [login substringFromIndex: (r.location + r.length)]; - } - authIDs = [[self authenticationSourceIDsInDomain: *domain] objectEnumerator]; while (!checkOK && (currentID = [authIDs nextObject])) { sogoSource = [_sources objectForKey: currentID]; - + checkOK = [sogoSource checkLogin: login password: password perr: perr