From 93b82a0f60ce5d8b0938e3f03d86baee8d075162 Mon Sep 17 00:00:00 2001 From: Hivert Quentin Date: Tue, 5 May 2026 10:39:38 +0200 Subject: [PATCH] fix(openid): check the userinfo mail + avoid infinite loop --- SoObjects/SOGo/SOGoOpenIdSession.m | 43 ++++++++++++++++++++++++++++-- UI/MainUI/SOGoRootPage.m | 14 ++++++++++ 2 files changed, 55 insertions(+), 2 deletions(-) diff --git a/SoObjects/SOGo/SOGoOpenIdSession.m b/SoObjects/SOGo/SOGoOpenIdSession.m index 0f658214d..3dfd19d54 100644 --- a/SoObjects/SOGo/SOGoOpenIdSession.m +++ b/SoObjects/SOGo/SOGoOpenIdSession.m @@ -823,13 +823,16 @@ size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer) - (NSMutableDictionary *) fetchUserInfo { NSString *location, *auth, *content; + SOGoSystemDefaults *sd; SimpleOpenIdResponse *response; // WOResponse *response; NSUInteger status; NSMutableDictionary *result; NSDictionary *profile, *headers; NSURL *url; - NSString *email; + NSString *email, *type, *user_domain; + NSRange r; + NSArray *domainsAllowed; result = [NSMutableDictionary dictionary]; [result setObject: @"ok" forKey: @"error"]; @@ -871,6 +874,36 @@ size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer) "email":"myuser@user.com"}*/ if (email = [profile objectForKey: self->openIdEmailParam]) { + //Check the mail domain is ok + + r = [email rangeOfString: @"@"]; + if (r.location != NSNotFound) + user_domain = [email substringFromIndex: r.location+1]; + else + { + [self logWithFormat: @"Error mail from userInfo not a mail %@", email]; + [result setObject: @"mail-error" forKey: @"error"]; + return result; + } + + sd = [SOGoSystemDefaults sharedSystemDefaults]; + if(self->forDomain != nil && [sd doesLoginTypeByDomain]) + { + type = [sd getLoginTypeForDomain: self->forDomain]; + if(type != nil && [type isEqualToString: @"openid"] && ![user_domain isEqualToString: self->forDomain]) + { + [self errorWithFormat: @"Openid userinfo email is not the right domain. Excpected: %@, Got %@", self->forDomain, user_domain]; + [result setObject: @"mail-error" forKey: @"error"]; + return result; + } + } + else if(((domainsAllowed = [sd domainsAllowed]) && [domainsAllowed count] > 0) && ![domainsAllowed containsObject: user_domain]) + { + [self errorWithFormat: @"Openid userinfo email domain is not allowed. Got %@", user_domain]; + [result setObject: @"mail-error" forKey: @"error"]; + return result; + } + if(self->userTokenInterval > 0) [self _saveUserToCache: email]; [result setObject: email forKey: @"login"]; @@ -949,7 +982,7 @@ size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer) } } - //The acces token hasn't work, delete the session in database if needed + //The access token hasn't work, delete the session in database if needed if(self->accessToken) { [[[GCSFolderManager defaultFolderManager] openIdFolder] deleteOpenIdSessionFor: self->accessToken]; @@ -962,6 +995,12 @@ size_t curl_body_function(void *ptr, size_t size, size_t nmemb, void *buffer) //remove old session [[[GCSFolderManager defaultFolderManager] openIdFolder] deleteOpenIdSessionFor: self->accessToken]; } + if([[resultUserInfo objectForKey: @"error"] isEqualToString: @"mail-error"]) + { + //Means there is a problem with the mail get from userInfo (logs wil explained) + //To avoid infinite loop -> openid -> redirect sogo -> useinfo fail -> rediretc to sogo index -> redirect to openid... + return nil; + } return @"anonymous"; } diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index 03c0250e6..79130bc1e 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -685,8 +685,22 @@ static const NSString *kJwtKey = @"jwt"; code = value; [openIdSession fetchToken: code redirect: redirectLocation]; login = [openIdSession login: @""]; + if(!login) + { + //login is nil only if there's a problem with the userInfo mail parameters + response = [self responseWithStatus: 500 andString: @"Openid wrong email, check the log"]; + return response; + } if ([login length]) { + //Check if the user exist in SOGo user source (ldap or sql) + loggedInUser = [SOGoUser userWithLogin: login]; + if(!loggedInUser) + { + [self logWithFormat: @"Mail returned by openid does not exist in user source: %@", login]; + response = [self responseWithStatus: 500 andString: @"Openid wrong email, check the log"]; + return response; + } auth = [[WOApplication application] authenticatorInContext: context]; openIdCookie = [auth cookieWithUsername: login andPassword: [openIdSession getToken]