From 78af78b0a5637922b9eec407da5fbd7ab2930422 Mon Sep 17 00:00:00 2001 From: Hivert Quentin Date: Wed, 11 Nov 2026 20:23:11 +0100 Subject: [PATCH] #3027: do not store secret for aliases --- Documentation/SOGoInstallationGuide.asciidoc | 7 +++++++ SoObjects/SOGo/SOGoUserManager.m | 14 ++++++++++++-- 2 files changed, 19 insertions(+), 2 deletions(-) diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index 6c484d4f7..546191d81 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -431,6 +431,13 @@ Defaults to `localhost`. See `memcached_servers_parse(3)` for details on the syntax. +SOGo trusts the content of memcached: it caches, among other things, the +users' attributes and a hash of their password, which is used to validate +DAV and ActiveSync authentications. memcached has no authentication by +default, so it must only be reachable by SOGo: bind it to `localhost` (or a +Unix socket) or protect it with a firewall or SASL, and don't share the +instance with other applications. + |S |SOGoCacheCleanupInterval |Parameter used to set the expiration (in seconds) of each object in the cache. diff --git a/SoObjects/SOGo/SOGoUserManager.m b/SoObjects/SOGo/SOGoUserManager.m index a89256b25..f2590d524 100644 --- a/SoObjects/SOGo/SOGoUserManager.m +++ b/SoObjects/SOGo/SOGoUserManager.m @@ -1107,18 +1107,28 @@ static const NSString *kObfuscatedSecondaryEmailKey = @"obfuscatedSecondaryEmail withLogin: (NSString *) login { NSEnumerator *emails; - NSString *key, *user_json; + NSString *key, *user_json, *email_json; + NSMutableDictionary *emailUser; user_json = [newUser jsonRepresentation]; [[SOGoCache sharedCache] setUserAttributes: user_json forLogin: login]; if (![newUser isKindOfClass: NSNullK]) { + // The cached password hash only belongs to the entry of the login + // that authenticated: don't copy it under the user's other addresses, + // otherwise an address shared with another account would accept this + // user's password. A login with an address is checked against the + // authentication source and then cached by checkLogin:. + emailUser = [[newUser mutableCopy] autorelease]; + [emailUser removeObjectForKey: @"password"]; + email_json = [emailUser jsonRepresentation]; + emails = [[newUser objectForKey: @"emails"] objectEnumerator]; while ((key = [emails nextObject])) { if (![key isEqualToString: login]) - [[SOGoCache sharedCache] setUserAttributes: user_json + [[SOGoCache sharedCache] setUserAttributes: email_json forLogin: key]; } }