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.

gpg_key_add.go 4.2KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167
  1. // Copyright 2021 The Gitea Authors. All rights reserved.
  2. // SPDX-License-Identifier: MIT
  3. package asymkey
  4. import (
  5. "context"
  6. "strings"
  7. "code.gitea.io/gitea/models/db"
  8. "code.gitea.io/gitea/modules/log"
  9. "github.com/keybase/go-crypto/openpgp"
  10. )
  11. // __________________ ________ ____ __.
  12. // / _____/\______ \/ _____/ | |/ _|____ ___.__.
  13. // / \ ___ | ___/ \ ___ | <_/ __ < | |
  14. // \ \_\ \| | \ \_\ \ | | \ ___/\___ |
  15. // \______ /|____| \______ / |____|__ \___ > ____|
  16. // \/ \/ \/ \/\/
  17. // _____ .___ .___
  18. // / _ \ __| _/__| _/
  19. // / /_\ \ / __ |/ __ |
  20. // / | \/ /_/ / /_/ |
  21. // \____|__ /\____ \____ |
  22. // \/ \/ \/
  23. // This file contains functions relating to adding GPG Keys
  24. // addGPGKey add key, import and subkeys to database
  25. func addGPGKey(ctx context.Context, key *GPGKey, content string) (err error) {
  26. // Add GPGKeyImport
  27. if err = db.Insert(ctx, &GPGKeyImport{
  28. KeyID: key.KeyID,
  29. Content: content,
  30. }); err != nil {
  31. return err
  32. }
  33. // Save GPG primary key.
  34. if err = db.Insert(ctx, key); err != nil {
  35. return err
  36. }
  37. // Save GPG subs key.
  38. for _, subkey := range key.SubsKey {
  39. if err := addGPGSubKey(ctx, subkey); err != nil {
  40. return err
  41. }
  42. }
  43. return nil
  44. }
  45. // addGPGSubKey add subkeys to database
  46. func addGPGSubKey(ctx context.Context, key *GPGKey) (err error) {
  47. // Save GPG primary key.
  48. if err = db.Insert(ctx, key); err != nil {
  49. return err
  50. }
  51. // Save GPG subs key.
  52. for _, subkey := range key.SubsKey {
  53. if err := addGPGSubKey(ctx, subkey); err != nil {
  54. return err
  55. }
  56. }
  57. return nil
  58. }
  59. // AddGPGKey adds new public key to database.
  60. func AddGPGKey(ownerID int64, content, token, signature string) ([]*GPGKey, error) {
  61. ekeys, err := checkArmoredGPGKeyString(content)
  62. if err != nil {
  63. return nil, err
  64. }
  65. ctx, committer, err := db.TxContext(db.DefaultContext)
  66. if err != nil {
  67. return nil, err
  68. }
  69. defer committer.Close()
  70. keys := make([]*GPGKey, 0, len(ekeys))
  71. verified := false
  72. // Handle provided signature
  73. if signature != "" {
  74. signer, err := openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token), strings.NewReader(signature))
  75. if err != nil {
  76. signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\n"), strings.NewReader(signature))
  77. }
  78. if err != nil {
  79. signer, err = openpgp.CheckArmoredDetachedSignature(ekeys, strings.NewReader(token+"\r\n"), strings.NewReader(signature))
  80. }
  81. if err != nil {
  82. log.Error("Unable to validate token signature. Error: %v", err)
  83. return nil, ErrGPGInvalidTokenSignature{
  84. ID: ekeys[0].PrimaryKey.KeyIdString(),
  85. Wrapped: err,
  86. }
  87. }
  88. ekeys = []*openpgp.Entity{signer}
  89. verified = true
  90. }
  91. if len(ekeys) > 1 {
  92. id2key := map[string]*openpgp.Entity{}
  93. newEKeys := make([]*openpgp.Entity, 0, len(ekeys))
  94. for _, ekey := range ekeys {
  95. id := ekey.PrimaryKey.KeyIdString()
  96. if original, has := id2key[id]; has {
  97. // Coalesce this with the other one
  98. for _, subkey := range ekey.Subkeys {
  99. if subkey.PublicKey == nil {
  100. continue
  101. }
  102. found := false
  103. for _, originalSubkey := range original.Subkeys {
  104. if originalSubkey.PublicKey == nil {
  105. continue
  106. }
  107. if originalSubkey.PublicKey.KeyId == subkey.PublicKey.KeyId {
  108. found = true
  109. break
  110. }
  111. }
  112. if !found {
  113. original.Subkeys = append(original.Subkeys, subkey)
  114. }
  115. }
  116. for name, identity := range ekey.Identities {
  117. if _, has := original.Identities[name]; has {
  118. continue
  119. }
  120. original.Identities[name] = identity
  121. }
  122. continue
  123. }
  124. id2key[id] = ekey
  125. newEKeys = append(newEKeys, ekey)
  126. }
  127. ekeys = newEKeys
  128. }
  129. for _, ekey := range ekeys {
  130. // Key ID cannot be duplicated.
  131. has, err := db.GetEngine(ctx).Where("key_id=?", ekey.PrimaryKey.KeyIdString()).
  132. Get(new(GPGKey))
  133. if err != nil {
  134. return nil, err
  135. } else if has {
  136. return nil, ErrGPGKeyIDAlreadyUsed{ekey.PrimaryKey.KeyIdString()}
  137. }
  138. // Get DB session
  139. key, err := parseGPGKey(ownerID, ekey, verified)
  140. if err != nil {
  141. return nil, err
  142. }
  143. if err = addGPGKey(ctx, key, content); err != nil {
  144. return nil, err
  145. }
  146. keys = append(keys, key)
  147. }
  148. return keys, committer.Commit()
  149. }