From 5f8f6b221e832ff507e772a4097f8ef172363eb0 Mon Sep 17 00:00:00 2001 From: Hivert Quentin Date: Thu, 13 Nov 2025 15:02:42 +0100 Subject: [PATCH] wip --- SoObjects/SOGo/SOGoUser.h | 2 +- SoObjects/SOGo/SOGoUser.m | 21 +++++++++++++++++++-- SoObjects/SOGo/SOGoUserSettings.h | 1 + SoObjects/SOGo/SOGoUserSettings.m | 23 +++++++++++++++++++++++ UI/MainUI/SOGoRootPage.m | 4 ++-- UI/PreferencesUI/UIxPreferences.m | 4 ++-- 6 files changed, 48 insertions(+), 7 deletions(-) diff --git a/SoObjects/SOGo/SOGoUser.h b/SoObjects/SOGo/SOGoUser.h index 7cb85ef37..457712026 100644 --- a/SoObjects/SOGo/SOGoUser.h +++ b/SoObjects/SOGo/SOGoUser.h @@ -124,7 +124,7 @@ - (BOOL) isSuperUser; - (BOOL) canAuthenticate; -- (NSString *) totpKey; +- (NSString *) totpKey: (bool) isCheck; /* resource */ - (BOOL) isResource; diff --git a/SoObjects/SOGo/SOGoUser.m b/SoObjects/SOGo/SOGoUser.m index 9df14f3af..458c17506 100644 --- a/SoObjects/SOGo/SOGoUser.m +++ b/SoObjects/SOGo/SOGoUser.m @@ -1299,7 +1299,7 @@ static const NSString *kEncryptedUserNamePrefix = @"uenc"; return [authValue boolValue]; } -- (NSString *) totpKey +- (NSString *) totpKey: (bool) isCheck { #if defined(MFA_CONFIG) NSString *key, *result; @@ -1308,7 +1308,24 @@ static const NSString *kEncryptedUserNamePrefix = @"uenc"; size_t s_len, secret_len; - key = [[[self userSettings] userPrivateSalt] substringToIndex: 12]; + //Until 5.12.4, SOGo had two problems with totp: + // * It was not renew after a user disable it/renable it. + // * The length was too small: 12 instead of the recommanded 20 + + if(![_defaults totpEnabled]) + { + //Totp was not enabled + //Only renew if this is not a check (happen when the user enable it for the first time and save its preferences + //the saveAction will check the totp code but [_defaults totpEnabled] is still False ) + key = [[self userSettings] userCurrentTotpKey: !isCheck]; + } + else + { + //Totp currently enabled + key = [[self userSettings] userCurrentTotpKey: NO]; + } + + //key = [[[self userSettings] userPrivateSalt] substringToIndex: 12]; s = [key UTF8String]; s_len = strlen(s); diff --git a/SoObjects/SOGo/SOGoUserSettings.h b/SoObjects/SOGo/SOGoUserSettings.h index 280943953..a397fc1fe 100644 --- a/SoObjects/SOGo/SOGoUserSettings.h +++ b/SoObjects/SOGo/SOGoUserSettings.h @@ -35,6 +35,7 @@ - (NSArray *) subscribedCalendars; - (NSArray *) subscribedAddressBooks; - (NSString *) userPrivateSalt; +- (NSString *) userCurrentTotpKey: (bool) renew; - (NSString *) userPublicSalt; - (void)enableForceResetPassword; - (void)disableForceResetPassword; diff --git a/SoObjects/SOGo/SOGoUserSettings.m b/SoObjects/SOGo/SOGoUserSettings.m index f4f6d58a6..c0e56efdb 100644 --- a/SoObjects/SOGo/SOGoUserSettings.m +++ b/SoObjects/SOGo/SOGoUserSettings.m @@ -116,6 +116,29 @@ static Class SOGoUserProfileKlass = Nil; return salt; } +- (NSString *) userCurrentTotpKey: (bool) renew +{ + NSMutableDictionary *values; + NSString *key; + + key = [[self dictionaryForKey: @"General"] objectForKey: @"totpKey"]; + + if (!key || renew) + { + key = [[[[NSProcessInfo processInfo] globallyUniqueString] asSHA1String] substringToIndex: 20]; + values = [self objectForKey: @"General"]; + + if (!values) + values = [NSMutableDictionary dictionary]; + + [values setObject: key forKey: @"totpKey"]; + [self setObject: values forKey: @"General"]; + [self synchronize]; + } + + return key; +} + - (void) enableForceResetPassword { [self setObject: [NSNumber numberWithInt:1] forKey: @"ForceResetPassword"]; diff --git a/UI/MainUI/SOGoRootPage.m b/UI/MainUI/SOGoRootPage.m index 79533e42d..e8b07d731 100644 --- a/UI/MainUI/SOGoRootPage.m +++ b/UI/MainUI/SOGoRootPage.m @@ -338,7 +338,7 @@ static const NSString *kJwtKey = @"jwt"; const auto time_step = OATH_TOTP_DEFAULT_TIME_STEP_SIZE; const auto digits = 6; - real_secret = [[loggedInUser totpKey] UTF8String]; + real_secret = [[loggedInUser totpKey: YES] UTF8String]; auto result = oath_init(); auto t = time(NULL); @@ -372,7 +372,7 @@ static const NSString *kJwtKey = @"jwt"; return [self responseWithStatus: 403 andJSONRepresentation: json]; } - } // if ([verificationCode length] == 6 && [verificationCode unsignedIntValue] > 0) + } else { if ([us dictionaryForKey: @"General"] && ![[us dictionaryForKey: @"General"] objectForKey: @"PrivateSalt"]) diff --git a/UI/PreferencesUI/UIxPreferences.m b/UI/PreferencesUI/UIxPreferences.m index 9e2e66bf8..c8fae8007 100644 --- a/UI/PreferencesUI/UIxPreferences.m +++ b/UI/PreferencesUI/UIxPreferences.m @@ -1123,7 +1123,7 @@ static NSArray *reminderValues = nil; - (NSString *) totpKey { - return [[context activeUser] totpKey]; + return [[context activeUser] totpKey: NO]; } // @@ -1910,7 +1910,7 @@ static NSArray *reminderValues = nil; const auto time_step = OATH_TOTP_DEFAULT_TIME_STEP_SIZE; const auto digits = 6; - real_secret = [[user totpKey] UTF8String]; + real_secret = [[user totpKey: YES] UTF8String]; auto result = oath_init(); auto t = time(NULL);