You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

88 lines
2.1 KiB

  1. // Copyright 2018 The Gitea Authors. All rights reserved.
  2. // Use of this source code is governed by a MIT-style
  3. // license that can be found in the LICENSE file.
  4. package migrations
  5. import (
  6. "crypto/sha256"
  7. "fmt"
  8. "code.gitea.io/gitea/modules/generate"
  9. "code.gitea.io/gitea/modules/timeutil"
  10. "golang.org/x/crypto/pbkdf2"
  11. "xorm.io/xorm"
  12. )
  13. func addScratchHash(x *xorm.Engine) error {
  14. // TwoFactor see models/twofactor.go
  15. type TwoFactor struct {
  16. ID int64 `xorm:"pk autoincr"`
  17. UID int64 `xorm:"UNIQUE"`
  18. Secret string
  19. ScratchToken string
  20. ScratchSalt string
  21. ScratchHash string
  22. LastUsedPasscode string `xorm:"VARCHAR(10)"`
  23. CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
  24. UpdatedUnix timeutil.TimeStamp `xorm:"INDEX updated"`
  25. }
  26. if err := x.Sync2(new(TwoFactor)); err != nil {
  27. return fmt.Errorf("Sync2: %v", err)
  28. }
  29. sess := x.NewSession()
  30. defer sess.Close()
  31. if err := sess.Begin(); err != nil {
  32. return err
  33. }
  34. // transform all tokens to hashes
  35. const batchSize = 100
  36. for start := 0; ; start += batchSize {
  37. tfas := make([]*TwoFactor, 0, batchSize)
  38. if err := sess.Limit(batchSize, start).Find(&tfas); err != nil {
  39. return err
  40. }
  41. if len(tfas) == 0 {
  42. break
  43. }
  44. for _, tfa := range tfas {
  45. // generate salt
  46. salt, err := generate.GetRandomString(10)
  47. if err != nil {
  48. return err
  49. }
  50. tfa.ScratchSalt = salt
  51. tfa.ScratchHash = hashToken(tfa.ScratchToken, salt)
  52. if _, err := sess.ID(tfa.ID).Cols("scratch_salt, scratch_hash").Update(tfa); err != nil {
  53. return fmt.Errorf("couldn't add in scratch_hash and scratch_salt: %v", err)
  54. }
  55. }
  56. }
  57. // Commit and begin new transaction for dropping columns
  58. if err := sess.Commit(); err != nil {
  59. return err
  60. }
  61. if err := sess.Begin(); err != nil {
  62. return err
  63. }
  64. if err := dropTableColumns(sess, "two_factor", "scratch_token"); err != nil {
  65. return err
  66. }
  67. return sess.Commit()
  68. }
  69. func hashToken(token, salt string) string {
  70. tempHash := pbkdf2.Key([]byte(token), []byte(salt), 10000, 50, sha256.New)
  71. return fmt.Sprintf("%x", tempHash)
  72. }