From 050a535b834c54c0ff6bad2144c6d2cd55e0880f Mon Sep 17 00:00:00 2001 From: ale <ale@incal.net> Date: Sun, 1 Jul 2018 09:10:19 +0100 Subject: [PATCH] Properly set the Has2FA bit when U2F is enabled --- backend/model.go | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/backend/model.go b/backend/model.go index 9a9fa95b..6d3cb457 100644 --- a/backend/model.go +++ b/backend/model.go @@ -99,14 +99,26 @@ func newLDAPBackendWithConn(conn ldapConn, base string) (*backend, error) { } func newUser(entry *ldap.Entry) (*accountserver.User, error) { + // Note that some user-level attributes related to + // authentication are stored on the uid= object, while others + // are on the email= object. We set the latter in the GetUser + // function later. + // + // The case of password recovery attributes is more complex: + // the current schema has those on email=, but we'd like to + // move them to uid=, so we currently have to support both. user := &accountserver.User{ - Name: entry.GetAttributeValue("uid"), - Lang: entry.GetAttributeValue(preferredLanguageLDAPAttr), - Has2FA: (entry.GetAttributeValue(totpSecretLDAPAttr) != ""), - //HasEncryptionKeys: (len(entry.GetAttributeValues("storageEncryptionKey")) > 0), - //PasswordRecoveryHint: entry.GetAttributeValue("recoverQuestion"), - U2FRegistrations: decodeU2FRegistrations(entry.GetAttributeValues(u2fRegistrationsLDAPAttr)), + Name: entry.GetAttributeValue("uid"), + Lang: entry.GetAttributeValue(preferredLanguageLDAPAttr), + PasswordRecoveryHint: entry.GetAttributeValue(recoveryHintLDAPAttr), + U2FRegistrations: decodeU2FRegistrations(entry.GetAttributeValues(u2fRegistrationsLDAPAttr)), } + + // The user has 2FA enabled if it has a TOTP secret or U2F keys. + if (entry.GetAttributeValue(totpSecretLDAPAttr) != "") || (len(user.U2FRegistrations) > 0) { + user.Has2FA = true + } + if user.Lang == "" { user.Lang = "en" } @@ -231,7 +243,9 @@ func (tx *backendTX) GetUser(ctx context.Context, username string) (*accountserv // object, a shortcoming of the legacy A/I database model. Set // them on the main User object. if isObjectClass(entry, "virtualMailUser") { - user.PasswordRecoveryHint = entry.GetAttributeValue(recoveryHintLDAPAttr) + if s := entry.GetAttributeValue(recoveryHintLDAPAttr); s != "" { + user.PasswordRecoveryHint = s + } user.AppSpecificPasswords = getASPInfo(decodeAppSpecificPasswords(entry.GetAttributeValues(aspLDAPAttr))) user.HasEncryptionKeys = (entry.GetAttributeValue(storagePublicKeyLDAPAttr) != "") } @@ -277,6 +291,8 @@ func (tx *backendTX) GetUserRecoveryEncryptedPassword(ctx context.Context, user } func (tx *backendTX) SetPasswordRecoveryHint(ctx context.Context, user *accountserver.User, hint, response string) error { + // Write the password recovery attributes on the uid= object, + // as per the new schema. dn := tx.getUserDN(user) tx.setAttr(dn, recoveryHintLDAPAttr, hint) tx.setAttr(dn, recoveryResponseLDAPAttr, response) -- GitLab