Skip to content

Commit

Permalink
using sha1 as default mfa algorithm
Browse files Browse the repository at this point in the history
  • Loading branch information
rolandosborne committed Jun 15, 2024
1 parent 1e3290c commit f700113
Show file tree
Hide file tree
Showing 11 changed files with 108 additions and 67 deletions.
12 changes: 6 additions & 6 deletions app/mobile/src/constants/Strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -206,7 +206,7 @@ const Strings = [
selectTopic: 'Select Topic for Sharing',

mfaTitle: 'Multi-Factor Authentication',
mfaSteps: 'Store the SHA256 secret and confirm the verification code',
mfaSteps: 'Store the secret and confirm the verification code',
mfaError: 'verification code error',
mfaDisabled: 'verification temporarily disabled',
mfaConfirm: 'Confirm',
Expand Down Expand Up @@ -417,7 +417,7 @@ const Strings = [
selectTopic: 'Choisissez le sujet à partager',

mfaTitle: 'Authentification Multi-Factor',
mfaSteps: 'Enregistrez le secret SHA256 et confirmez le code de vérification',
mfaSteps: 'Enregistrez le secret et confirmez le code de vérification',
mfaEnter: 'Entrez votre code de vérification',
mfaError: 'erreur de code de vérification',
mfaDisabled: 'vérification temporairement désactivée',
Expand Down Expand Up @@ -629,7 +629,7 @@ const Strings = [
selectTopic: 'Elija un tema para compartir',

mfaTitle: 'Autenticación de Dos Factores',
mfaSteps: 'Guarde el secreto SHA256 y confirme el código de verificación',
mfaSteps: 'Guarde el secreto y confirme el código de verificación',
mfaEnter: 'Ingresa tu código de verificación',
mfaError: 'error de código de verificación',
mfaDisabled: 'verificación temporalmente deshabilitada',
Expand Down Expand Up @@ -841,7 +841,7 @@ const Strings = [
selectTopic: 'Wählen Sie ein Thema zum Teilen aus',

mfaTitle: 'Zwei-Faktor-Authentifizierung',
mfaSteps: 'Speichern Sie das SHA256-Geheimnis und bestätigen Sie den Bestätigungscode',
mfaSteps: 'Speichern Sie das Geheimnis und bestätigen Sie den Bestätigungscode',
mfaEnter: 'Geben Sie Ihren Bestätigungs-Code ein',
mfaError: 'Verifizierungscodefehler',
mfaDisabled: 'Verifizierung vorübergehend deaktiviert',
Expand Down Expand Up @@ -1038,7 +1038,7 @@ const Strings = [
selectTopic: 'Escolha o tópico para compartilhar',

mfaTitle: 'Autenticação de Dois Fatores',
mfaSteps: 'Salve o segredo SHA256 e confirme o código de verificação',
mfaSteps: 'Salve o segredo e confirme o código de verificação',
mfaEnter: 'Digite seu código de verificação',
mfaError: 'erro de código de verificação',
mfaDisabled: 'verificação temporariamente desativada',
Expand Down Expand Up @@ -1233,7 +1233,7 @@ const Strings = [
selectTopic: 'Выберите тему для обмена',

mfaTitle: 'Двухфакторная аутентификация',
mfaSteps: 'Сохраните секрет SHA256 и подтвердите код подтверждения',
mfaSteps: 'Сохраните секрет и подтвердите код подтверждения',
mfaEnter: 'Введите Ваш верификационный код',
mfaError: 'ошибка проверочного кода',
mfaDisabled: 'проверка временно отключена',
Expand Down
6 changes: 5 additions & 1 deletion net/server/internal/api_addAccountApp.go
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,11 @@ func AddAccountApp(w http.ResponseWriter, r *http.Request) {
return;
}

opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA256}
algorithm := otp.AlgorithmSHA256;
if account.MFAAlgorithm == APPMFASHA1 {
algorithm = otp.AlgorithmSHA1
}
opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: algorithm}
if valid, _ := totp.ValidateCustom(code, account.MFASecret, time.Now(), opts); !valid {
err := store.DB.Transaction(func(tx *gorm.DB) error {
if account.MFAFailedTime + APPMFAFailPeriod > curTime {
Expand Down
2 changes: 1 addition & 1 deletion net/server/internal/api_addAdminMFAuth.go
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ func AddAdminMFAuth(w http.ResponseWriter, r *http.Request) {
Issuer: APPMFAIssuer,
AccountName: "admin",
Digits: otp.DigitsSix,
Algorithm: otp.AlgorithmSHA256,
Algorithm: otp.AlgorithmSHA1,
})

err = store.DB.Transaction(func(tx *gorm.DB) error {
Expand Down
2 changes: 1 addition & 1 deletion net/server/internal/api_addMultiFactorAuth.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ func AddMultiFactorAuth(w http.ResponseWriter, r *http.Request) {
Issuer: APPMFAIssuer,
AccountName: account.Handle,
Digits: otp.DigitsSix,
Algorithm: otp.AlgorithmSHA256,
Algorithm: otp.AlgorithmSHA1,
})

err = store.DB.Transaction(func(tx *gorm.DB) error {
Expand Down
9 changes: 7 additions & 2 deletions net/server/internal/api_setAdminAccess.go
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,13 @@ func SetAdminAccess(w http.ResponseWriter, r *http.Request) {
return;
}

secret := getStrConfigValue(CNFMFASecret, "");
opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA256}
secret := getStrConfigValue(CNFMFASecret, "")
algorithm := getStrConfigValue(CNFMFAAlgorithm, APPMFASHA256)
mfaAlgorithm := otp.AlgorithmSHA256
if algorithm == APPMFASHA1 {
mfaAlgorithm = otp.AlgorithmSHA1
}
opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: mfaAlgorithm}
if valid, _ := totp.ValidateCustom(code, secret, time.Now(), opts); !valid {
err := store.DB.Transaction(func(tx *gorm.DB) error {
if failedTime + APPMFAFailPeriod > curTime {
Expand Down
68 changes: 40 additions & 28 deletions net/server/internal/api_setAdminMFAuth.go
Original file line number Diff line number Diff line change
Expand Up @@ -38,39 +38,44 @@ func SetAdminMFAuth(w http.ResponseWriter, r *http.Request) {
return;
}

mfaAlgorithm := APPMFASHA1
secret := getStrConfigValue(CNFMFASecret, "");
opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA256}
opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA1}
if valid, _ := totp.ValidateCustom(code, secret, time.Now(), opts); !valid {
err := store.DB.Transaction(func(tx *gorm.DB) error {
if failedTime + APPMFAFailPeriod > curTime {
if res := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "config_id"}},
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
}).Create(&store.Config{ConfigID: CNFMFAFailedCount, NumValue: failedCount + 1}).Error; res != nil {
return res
}
} else {
if res := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "config_id"}},
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
}).Create(&store.Config{ConfigID: CNFMFAFailedTime, NumValue: curTime}).Error; res != nil {
return res
}
if res := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "config_id"}},
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
}).Create(&store.Config{ConfigID: CNFMFAFailedCount, NumValue: 1}).Error; res != nil {
return res
mfaAlgorithm = APPMFASHA256
opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA256}
if valid, _ := totp.ValidateCustom(code, secret, time.Now(), opts); !valid {
err := store.DB.Transaction(func(tx *gorm.DB) error {
if failedTime + APPMFAFailPeriod > curTime {
if res := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "config_id"}},
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
}).Create(&store.Config{ConfigID: CNFMFAFailedCount, NumValue: failedCount + 1}).Error; res != nil {
return res
}
} else {
if res := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "config_id"}},
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
}).Create(&store.Config{ConfigID: CNFMFAFailedTime, NumValue: curTime}).Error; res != nil {
return res
}
if res := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "config_id"}},
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
}).Create(&store.Config{ConfigID: CNFMFAFailedCount, NumValue: 1}).Error; res != nil {
return res
}
}
return nil
})
if err != nil {
LogMsg("failed to increment fail count");
}
return nil
})
if err != nil {
LogMsg("failed to increment fail count");
}

ErrResponse(w, http.StatusUnauthorized, errors.New("invalid code"))
return
ErrResponse(w, http.StatusUnauthorized, errors.New("invalid code"))
return
}
}

err := store.DB.Transaction(func(tx *gorm.DB) error {
Expand All @@ -81,6 +86,13 @@ func SetAdminMFAuth(w http.ResponseWriter, r *http.Request) {
}).Create(&store.Config{ConfigID: CNFMFAConfirmed, BoolValue: true}).Error; res != nil {
return res
}
// upsert mfa algorithm
if res := tx.Clauses(clause.OnConflict{
Columns: []clause.Column{{Name: "config_id"}},
DoUpdates: clause.AssignmentColumns([]string{"num_value"}),
}).Create(&store.Config{ConfigID: CNFMFAAlgorithm, StrValue: mfaAlgorithm}).Error; res != nil {
return res
}
return nil
})
if err != nil {
Expand Down
54 changes: 32 additions & 22 deletions net/server/internal/api_setMultiFactorAuth.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,32 +35,37 @@ func SetMultiFactorAuth(w http.ResponseWriter, r *http.Request) {
return;
}

opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA256}
mfaAlgorithm := APPMFASHA1
opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA1}
if valid, _ := totp.ValidateCustom(code, account.MFASecret, time.Now(), opts); !valid {
err := store.DB.Transaction(func(tx *gorm.DB) error {
if account.MFAFailedTime + APPMFAFailPeriod > curTime {
account.MFAFailedCount += 1
if res := tx.Model(account).Update("mfa_failed_count", account.MFAFailedCount).Error; res != nil {
return res
}
} else {
account.MFAFailedTime = curTime
if res := tx.Model(account).Update("mfa_failed_time", account.MFAFailedTime).Error; res != nil {
return res
}
account.MFAFailedCount = 1
if res := tx.Model(account).Update("mfa_failed_count", account.MFAFailedCount).Error; res != nil {
return res
mfaAlgorithm = APPMFASHA256
opts := totp.ValidateOpts{Period: 30, Skew: 1, Digits: otp.DigitsSix, Algorithm: otp.AlgorithmSHA256}
if valid, _ := totp.ValidateCustom(code, account.MFASecret, time.Now(), opts); !valid {
err := store.DB.Transaction(func(tx *gorm.DB) error {
if account.MFAFailedTime + APPMFAFailPeriod > curTime {
account.MFAFailedCount += 1
if res := tx.Model(account).Update("mfa_failed_count", account.MFAFailedCount).Error; res != nil {
return res
}
} else {
account.MFAFailedTime = curTime
if res := tx.Model(account).Update("mfa_failed_time", account.MFAFailedTime).Error; res != nil {
return res
}
account.MFAFailedCount = 1
if res := tx.Model(account).Update("mfa_failed_count", account.MFAFailedCount).Error; res != nil {
return res
}
}
return nil
})
if err != nil {
LogMsg("failed to increment fail count");
}
return nil
})
if err != nil {
LogMsg("failed to increment fail count");
}

ErrResponse(w, http.StatusUnauthorized, errors.New("invalid code"))
return
ErrResponse(w, http.StatusUnauthorized, errors.New("invalid code"))
return
}
}

err = store.DB.Transaction(func(tx *gorm.DB) error {
Expand All @@ -69,6 +74,11 @@ func SetMultiFactorAuth(w http.ResponseWriter, r *http.Request) {
ErrResponse(w, http.StatusInternalServerError, res)
return res
}
account.MFAAlgorithm = mfaAlgorithm;
if res := tx.Model(account).Update("mfa_algorithm", account.MFAAlgorithm).Error; res != nil {
ErrResponse(w, http.StatusInternalServerError, res)
return res
}
account.AccountRevision += 1;
if res := tx.Model(&account).Update("account_revision", account.AccountRevision).Error; res != nil {
return res
Expand Down
6 changes: 6 additions & 0 deletions net/server/internal/appValues.go
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,12 @@ const APPMFAFailPeriod = 300
//APPMFAFailCount limit of login failures in period
const APPMFAFailCount = 4

//APPMFASHA256 internal mfa algorithm sha256
const APPMFASHA256 = "sha256"

//APPMFASHA1 internal mfa alogirthm sha1
const APPMFASHA1 = "sha1"

//AppCardStatus compares cards status with string
func AppCardStatus(status string) bool {
if status == APPCardPending {
Expand Down
3 changes: 3 additions & 0 deletions net/server/internal/configUtil.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,9 @@ const CNFMFAEnabled = "mfa_enabled"
//CNFMFAConfirmed specified if mfa has been confirmed for admin
const CNFMFAConfirmed = "mfa_confirmed"

//CNFMFAAlgorirthm specifies internal mfa alogirhtm to use
const CNFMFAAlgorithm = "mfa_algorithm"

//CNFMFASecret specified the mfa secret
const CNFMFASecret = "mfa_secret"

Expand Down
1 change: 1 addition & 0 deletions net/server/internal/store/schema.go
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ type Account struct {
MFAEnabled bool `gorm:"not null;default:false"`
MFAConfirmed bool `gorm:"not null;default:false"`
MFASecret string
MFAAlgorithm string
MFAFailedTime int64
MFAFailedCount uint
Forward string
Expand Down
12 changes: 6 additions & 6 deletions net/web/src/constants/Strings.js
Original file line number Diff line number Diff line change
Expand Up @@ -193,7 +193,7 @@ export const en = {
securedMessage: 'Sealed Message',

mfaTitle: 'Multi-Factor Authentication',
mfaSteps: 'Store the SHA256 secret and confirm the verification code',
mfaSteps: 'Store the secret and confirm the verification code',
mfaError: 'verification code error',
mfaDisabled: 'verification temporarily disabled',
mfaConfirm: 'Confirm',
Expand Down Expand Up @@ -403,7 +403,7 @@ export const fr = {
sealedMessage: 'Message Sécurisé',

mfaTitle: 'Authentification Multi-Factor',
mfaSteps: 'Enregistrez le secret SHA256 et confirmez le code de vérification',
mfaSteps: 'Enregistrez le secret et confirmez le code de vérification',
mfaEnter: 'Entrez votre code de vérification',
mfaError: 'erreur de code de vérification',
mfaDisabled: 'vérification temporairement désactivée',
Expand Down Expand Up @@ -612,7 +612,7 @@ export const sp = {
sealedMessage: 'Mensaje Seguro',

mfaTitle: 'Autenticación de Dos Factores',
mfaSteps: 'Guarde el secreto SHA256 y confirme el código de verificación',
mfaSteps: 'Guarde el secreto y confirme el código de verificación',
mfaEnter: 'Ingresa tu código de verificación',
mfaError: 'error de código de verificación',
mfaDisabled: 'verificación temporalmente deshabilitada',
Expand Down Expand Up @@ -821,7 +821,7 @@ export const pt = {
sealedMessage: 'Mensagem Segura',

mfaTitle: 'Autenticação de Dois Fatores',
mfaSteps: 'Salve o segredo SHA256 e confirme o código de verificação',
mfaSteps: 'Salve o segredo e confirme o código de verificação',
mfaEnter: 'Digite seu código de verificação',
mfaError: 'erro de código de verificação',
mfaDisabled: 'verificação temporariamente desativada',
Expand Down Expand Up @@ -1030,7 +1030,7 @@ export const de = {
sealedMessage: 'Gesicherte Nachricht',

mfaTitle: 'Zwei-Faktor-Authentifizierung',
mfaSteps: 'Speichern Sie das SHA256-Geheimnis und bestätigen Sie den Bestätigungscode',
mfaSteps: 'Speichern Sie das Geheimnis und bestätigen Sie den Bestätigungscode',
mfaEnter: 'Geben Sie Ihren Bestätigungs-Code ein',
mfaError: 'Verifizierungscodefehler',
mfaDisabled: 'Verifizierung vorübergehend deaktiviert',
Expand Down Expand Up @@ -1239,7 +1239,7 @@ export const ru = {
sealedMessage: 'Защищенное Cообщение',

mfaTitle: 'Двухфакторная аутентификация',
mfaSteps: 'Сохраните секрет SHA256 и подтвердите код подтверждения',
mfaSteps: 'Сохраните секрет и подтвердите код подтверждения',
mfaEnter: 'Введите Ваш верификационный код',
mfaError: 'ошибка проверочного кода',
mfaDisabled: 'проверка временно отключена',
Expand Down

0 comments on commit f700113

Please sign in to comment.