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.3KB

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