From 04a3e9823889acaf6c247b224f5f7a0108f8f829 Mon Sep 17 00:00:00 2001 From: Hivert Quentin Date: Thu, 10 Sep 2026 08:11:23 +0200 Subject: [PATCH] fix(pwd): use the proper url for reset password mail part2 --- .devcontainer/conf/sogo/sogo.conf | 2 +- Documentation/SOGoInstallationGuide.asciidoc | 18 +++++++++++++ SoObjects/SOGo/SOGoSystemDefaults.h | 1 + SoObjects/SOGo/SOGoSystemDefaults.m | 5 ++++ UI/MainUI/SOGoRootPage.m | 27 +++++++++++++++++--- 5 files changed, 49 insertions(+), 4 deletions(-) diff --git a/.devcontainer/conf/sogo/sogo.conf b/.devcontainer/conf/sogo/sogo.conf index 75a624071..cb7d4a16e 100644 --- a/.devcontainer/conf/sogo/sogo.conf +++ b/.devcontainer/conf/sogo/sogo.conf @@ -15,9 +15,9 @@ * * * **************************************************************************/ - /* Database configuration (mysql://, postgresql:// or oracle://) */ WOPort = "0.0.0.0:50000"; + /* Database configuration (mysql://, postgresql:// or oracle://) */ // MySQL SOGoProfileURL = "mysql://sogobuild:sogo123@mariadb:3306/sogo/sogo_user_profile"; diff --git a/Documentation/SOGoInstallationGuide.asciidoc b/Documentation/SOGoInstallationGuide.asciidoc index 12a2ab3c2..d3030b38d 100644 --- a/Documentation/SOGoInstallationGuide.asciidoc +++ b/Documentation/SOGoInstallationGuide.asciidoc @@ -840,6 +840,16 @@ Obiously, if your users can connect without specifying a domain, let this parame |S |SOGoPasswordRecoveryEnabled |Boolean enable password recovery with secret question or secondary e-mail. Default value is `NO`. +|S |SOGoPasswordRecoveryBaseURLs +| *Since 5.12.11*. Whitlist of base URL for password reset link. + +`SOGoPasswordRecoveryBaseURLs = ("https://demo.sogo.nu");` +`SOGoPasswordRecoveryBaseURLs = ("https://platform1.sogo.nu", "https://platform2.sogo.nu);` + +Do not end the URLs by '/'. + +No defaults, will trhow an error if empty or unset. + |S |SOGoPasswordRecoveryDomains |List of domains where password recovery is enabled, for example `(example.org, example.net)`. If empty array `()`, disabled for all domains. If not set, enabled for all domains. @@ -2886,6 +2896,11 @@ SOGoMailJunkSettings = { }; ---- +|D |mailJunkIcon +|Choose the Junk icon. For the thumb down `thumb_down`, for a shield `gpp_bad`. + +Defaults to `gppthumb_down_bad`. + |D |SOGoMailKeepDraftsAfterSend |Parameter used to keep mails in the drafts folder once they have been sent by SOGo. Defaults to `NO` when unset. @@ -4284,6 +4299,9 @@ current version of SOGo from the previous release. [cols="100a"] |======================================================================= +h|5.12.11 +|If you enable Password Recovery, new mandatory settings `SOGoPasswordRecoveryBaseURLs` + h|5.11 |Parameters `SOGoGlobalAddressBookFirstEntries` and `SOGoGlobalAddressBookFirstEntriesCount` has been removed. Please use `listRequiresDot` and `globalAddressBookFirstEntriesCount` instead. Signature are now between a div tag to avoid CKEditor changing the content - set `SOGoForceRawHtmlSignature` to `NO` to leave signature (https://bugs.sogo.nu/view.php?id=5920). diff --git a/SoObjects/SOGo/SOGoSystemDefaults.h b/SoObjects/SOGo/SOGoSystemDefaults.h index a7e29c82c..713a1773b 100644 --- a/SoObjects/SOGo/SOGoSystemDefaults.h +++ b/SoObjects/SOGo/SOGoSystemDefaults.h @@ -149,6 +149,7 @@ NSComparisonResult languageSort(id el1, id el2, void *context); - (BOOL) isEasUIDisabled; - (BOOL)isPasswordRecoveryEnabled; +- (NSArray *) passwordRecoveryBaseURLs; - (NSArray *) passwordRecoveryDomains; - (NSString *) JWTSecret; diff --git a/SoObjects/SOGo/SOGoSystemDefaults.m b/SoObjects/SOGo/SOGoSystemDefaults.m index abca1d906..6afbedd7e 100644 --- a/SoObjects/SOGo/SOGoSystemDefaults.m +++ b/SoObjects/SOGo/SOGoSystemDefaults.m @@ -1082,6 +1082,11 @@ NSComparisonResult languageSort(id el1, id el2, void *context) return [self boolForKey: @"SOGoPasswordRecoveryEnabled"]; } +- (NSArray *) passwordRecoveryBaseURLs +{ + return [self stringArrayForKey: @"SOGoPasswordRecoveryBaseURLs"]; +} + - (NSArray *) passwordRecoveryDomains { static NSArray *passwordRecoveryDomains = nil; diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index 90b392acf..5fbe2b042 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -1316,7 +1316,8 @@ static const NSString *kJwtKey = @"jwt"; */ - (WOResponse *) passwordRecoveryEmailAction { - NSString *username, *domain, *mode, *uid, *mailDomain, *fromEmail, *toEmail, *jwtToken, *url, *mailContent, *email; + NSString *username, *domain, *mode, *uid, *mailDomain, *fromEmail, *toEmail, *jwtToken, *url, *mailContent, *email, *serverUrl; + NSArray *baseUrls; NSDictionary *message, *info; WORequest *request; SOGoUserManager *um; @@ -1372,8 +1373,28 @@ static const NSString *kJwtKey = @"jwt"; // Send mail mailer = [SOGoMailer mailerWithDomainDefaults: dd]; - url = [NSString stringWithFormat:@"%@/%@?token=%@" - , [[context serverURL] absoluteString] + //Get Allowed server URL and check if it's OK + baseUrls = [[SOGoSystemDefaults sharedSystemDefaults] passwordRecoveryBaseURLs]; + serverUrl = [[request headers] objectForKey:@"origin"]; + + if(!(baseUrls && [baseUrls count] > 0)) + { + [self logWithFormat: @"Password recovery exception for user %@: empty or unset SOGoPasswordRecoveryBaseURLs", uid]; + response = [self responseWithStatus: 403 + andString: @"Password recovery email in error"]; + return response; + } + + if(![baseUrls containsObject:serverUrl]) + { + [self logWithFormat: @"Password recovery exception for user %@: invalid request header", uid]; + response = [self responseWithStatus: 403 + andString: @"Password recovery email in error"]; + return response; + } + + url = [NSString stringWithFormat:@"%@%@?token=%@" + , serverUrl , [request uri] , jwtToken];