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

publickey.go 3.5 kB

11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
11 years ago
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177
  1. // Copyright 2014 The Gogs 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 models
  5. import (
  6. "bufio"
  7. "errors"
  8. "fmt"
  9. "io"
  10. "os"
  11. "os/exec"
  12. "path/filepath"
  13. "strings"
  14. "sync"
  15. "time"
  16. "github.com/Unknwon/com"
  17. )
  18. var (
  19. sshOpLocker = sync.Mutex{}
  20. //publicKeyRootPath string
  21. sshPath string
  22. appPath string
  23. // "### autogenerated by gitgos, DO NOT EDIT\n"
  24. tmplPublicKey = "command=\"%s serv key-%d\",no-port-forwarding," +
  25. "no-X11-forwarding,no-agent-forwarding,no-pty %s\n"
  26. )
  27. func exePath() (string, error) {
  28. file, err := exec.LookPath(os.Args[0])
  29. if err != nil {
  30. return "", err
  31. }
  32. return filepath.Abs(file)
  33. }
  34. func homeDir() string {
  35. home, err := com.HomeDir()
  36. if err != nil {
  37. return "/"
  38. }
  39. return home
  40. }
  41. func init() {
  42. var err error
  43. appPath, err = exePath()
  44. if err != nil {
  45. println(err.Error())
  46. os.Exit(2)
  47. }
  48. sshPath = filepath.Join(homeDir(), ".ssh")
  49. }
  50. type PublicKey struct {
  51. Id int64
  52. OwnerId int64 `xorm:"index"`
  53. Name string `xorm:"unique not null"`
  54. Content string `xorm:"text not null"`
  55. Created time.Time `xorm:"created"`
  56. Updated time.Time `xorm:"updated"`
  57. }
  58. func GenAuthorizedKey(keyId int64, key string) string {
  59. return fmt.Sprintf(tmplPublicKey, appPath, keyId, key)
  60. }
  61. func AddPublicKey(key *PublicKey) error {
  62. _, err := orm.Insert(key)
  63. if err != nil {
  64. return err
  65. }
  66. err = SaveAuthorizedKeyFile(key)
  67. if err != nil {
  68. _, err2 := orm.Delete(key)
  69. if err2 != nil {
  70. // TODO: log the error
  71. }
  72. return err
  73. }
  74. return nil
  75. }
  76. // DeletePublicKey deletes SSH key information both in database and authorized_keys file.
  77. func DeletePublicKey(key *PublicKey) (err error) {
  78. has, err := orm.Id(key.Id).Get(key)
  79. if err != nil {
  80. return err
  81. } else if !has {
  82. return errors.New("Public key does not exist")
  83. }
  84. if _, err = orm.Delete(key); err != nil {
  85. return err
  86. }
  87. sshOpLocker.Lock()
  88. defer sshOpLocker.Unlock()
  89. p := filepath.Join(sshPath, "authorized_keys")
  90. tmpP := filepath.Join(sshPath, "authorized_keys.tmp")
  91. fr, err := os.Open(p)
  92. if err != nil {
  93. return err
  94. }
  95. defer fr.Close()
  96. fw, err := os.Create(tmpP)
  97. if err != nil {
  98. return err
  99. }
  100. defer fw.Close()
  101. buf := bufio.NewReader(fr)
  102. for {
  103. line, errRead := buf.ReadString('\n')
  104. line = strings.TrimSpace(line)
  105. if errRead != nil {
  106. if errRead != io.EOF {
  107. return errRead
  108. }
  109. // Reached end of file, if nothing to read then break,
  110. // otherwise handle the last line.
  111. if len(line) == 0 {
  112. break
  113. }
  114. }
  115. // Found the line and copy rest of file.
  116. if strings.Contains(line, key.Content) {
  117. continue
  118. }
  119. // Still finding the line, copy the line that currently read.
  120. if _, err = fw.WriteString(line + "\n"); err != nil {
  121. return err
  122. }
  123. if errRead == io.EOF {
  124. break
  125. }
  126. }
  127. if err = os.Remove(p); err != nil {
  128. return err
  129. }
  130. return os.Rename(tmpP, p)
  131. }
  132. func ListPublicKey(userId int64) ([]PublicKey, error) {
  133. keys := make([]PublicKey, 0)
  134. err := orm.Find(&keys, &PublicKey{OwnerId: userId})
  135. return keys, err
  136. }
  137. func SaveAuthorizedKeyFile(key *PublicKey) error {
  138. sshOpLocker.Lock()
  139. defer sshOpLocker.Unlock()
  140. p := filepath.Join(sshPath, "authorized_keys")
  141. f, err := os.OpenFile(p, os.O_CREATE|os.O_WRONLY|os.O_APPEND, 0600)
  142. if err != nil {
  143. return err
  144. }
  145. defer f.Close()
  146. //os.Chmod(p, 0600)
  147. _, err = f.WriteString(GenAuthorizedKey(key.Id, key.Content))
  148. return err
  149. }