Nevar pievienot vairāk kā 25 tēmas Tēmai ir jāsākas ar burtu vai ciparu, tā var saturēt domu zīmes ('-') un var būt līdz 35 simboliem gara.

security_u2f.go 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111
  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 setting
  5. import (
  6. "errors"
  7. "net/http"
  8. "code.gitea.io/gitea/models"
  9. "code.gitea.io/gitea/modules/context"
  10. auth "code.gitea.io/gitea/modules/forms"
  11. "code.gitea.io/gitea/modules/log"
  12. "code.gitea.io/gitea/modules/setting"
  13. "code.gitea.io/gitea/modules/web"
  14. "github.com/tstranex/u2f"
  15. )
  16. // U2FRegister initializes the u2f registration procedure
  17. func U2FRegister(ctx *context.Context) {
  18. form := web.GetForm(ctx).(*auth.U2FRegistrationForm)
  19. if form.Name == "" {
  20. ctx.Error(http.StatusConflict)
  21. return
  22. }
  23. challenge, err := u2f.NewChallenge(setting.U2F.AppID, setting.U2F.TrustedFacets)
  24. if err != nil {
  25. ctx.ServerError("NewChallenge", err)
  26. return
  27. }
  28. if err := ctx.Session.Set("u2fChallenge", challenge); err != nil {
  29. ctx.ServerError("Unable to set session key for u2fChallenge", err)
  30. return
  31. }
  32. regs, err := models.GetU2FRegistrationsByUID(ctx.User.ID)
  33. if err != nil {
  34. ctx.ServerError("GetU2FRegistrationsByUID", err)
  35. return
  36. }
  37. for _, reg := range regs {
  38. if reg.Name == form.Name {
  39. ctx.Error(http.StatusConflict, "Name already taken")
  40. return
  41. }
  42. }
  43. if err := ctx.Session.Set("u2fName", form.Name); err != nil {
  44. ctx.ServerError("Unable to set session key for u2fName", err)
  45. return
  46. }
  47. // Here we're just going to try to release the session early
  48. if err := ctx.Session.Release(); err != nil {
  49. // we'll tolerate errors here as they *should* get saved elsewhere
  50. log.Error("Unable to save changes to the session: %v", err)
  51. }
  52. ctx.JSON(http.StatusOK, u2f.NewWebRegisterRequest(challenge, regs.ToRegistrations()))
  53. }
  54. // U2FRegisterPost receives the response of the security key
  55. func U2FRegisterPost(ctx *context.Context) {
  56. response := web.GetForm(ctx).(*u2f.RegisterResponse)
  57. challSess := ctx.Session.Get("u2fChallenge")
  58. u2fName := ctx.Session.Get("u2fName")
  59. if challSess == nil || u2fName == nil {
  60. ctx.ServerError("U2FRegisterPost", errors.New("not in U2F session"))
  61. return
  62. }
  63. challenge := challSess.(*u2f.Challenge)
  64. name := u2fName.(string)
  65. config := &u2f.Config{
  66. // Chrome 66+ doesn't return the device's attestation
  67. // certificate by default.
  68. SkipAttestationVerify: true,
  69. }
  70. reg, err := u2f.Register(*response, *challenge, config)
  71. if err != nil {
  72. ctx.ServerError("u2f.Register", err)
  73. return
  74. }
  75. if _, err = models.CreateRegistration(ctx.User, name, reg); err != nil {
  76. ctx.ServerError("u2f.Register", err)
  77. return
  78. }
  79. ctx.Status(200)
  80. }
  81. // U2FDelete deletes an security key by id
  82. func U2FDelete(ctx *context.Context) {
  83. form := web.GetForm(ctx).(*auth.U2FDeleteForm)
  84. reg, err := models.GetU2FRegistrationByID(form.ID)
  85. if err != nil {
  86. if models.IsErrU2FRegistrationNotExist(err) {
  87. ctx.Status(200)
  88. return
  89. }
  90. ctx.ServerError("GetU2FRegistrationByID", err)
  91. return
  92. }
  93. if reg.UserID != ctx.User.ID {
  94. ctx.Status(401)
  95. return
  96. }
  97. if err := models.DeleteRegistration(reg); err != nil {
  98. ctx.ServerError("DeleteRegistration", err)
  99. return
  100. }
  101. ctx.JSON(http.StatusOK, map[string]interface{}{
  102. "redirect": setting.AppSubURL + "/user/settings/security",
  103. })
  104. }