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.

156 lines
3.2 KiB

10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
10 years ago
  1. package main
  2. import (
  3. "fmt"
  4. "os"
  5. "os/exec"
  6. "strconv"
  7. "strings"
  8. "github.com/codegangsta/cli"
  9. "github.com/gogits/gogs/models"
  10. )
  11. var (
  12. COMMANDS_READONLY = map[string]int{
  13. "git-upload-pack": models.AU_WRITABLE,
  14. "git upload-pack": models.AU_WRITABLE,
  15. "git-upload-archive": models.AU_WRITABLE,
  16. }
  17. COMMANDS_WRITE = map[string]int{
  18. "git-receive-pack": models.AU_READABLE,
  19. "git receive-pack": models.AU_READABLE,
  20. }
  21. )
  22. var CmdServ = cli.Command{
  23. Name: "serv",
  24. Usage: "This command just should be called by ssh shell",
  25. Description: `
  26. gogs serv provide access auth for repositories`,
  27. Action: runServ,
  28. Flags: []cli.Flag{},
  29. }
  30. func In(b string, sl map[string]int) bool {
  31. _, e := sl[b]
  32. return e
  33. }
  34. func runServ(*cli.Context) {
  35. keys := strings.Split(os.Args[2], "-")
  36. if len(keys) != 2 {
  37. fmt.Println("auth file format error")
  38. return
  39. }
  40. keyId, err := strconv.ParseInt(keys[1], 10, 64)
  41. if err != nil {
  42. fmt.Println("auth file format error")
  43. return
  44. }
  45. user, err := models.GetUserByKeyId(keyId)
  46. if err != nil {
  47. fmt.Println("You have no right to access")
  48. return
  49. }
  50. cmd := os.Getenv("SSH_ORIGINAL_COMMAND")
  51. if cmd == "" {
  52. println("Hi ", user.Name, "! You've successfully authenticated, but Gogs does not provide shell access.")
  53. return
  54. }
  55. verb, args := parseCmd(cmd)
  56. rRepo := strings.Trim(args, "'")
  57. rr := strings.SplitN(rRepo, "/", 2)
  58. if len(rr) != 2 {
  59. println("Unavilable repository", args)
  60. return
  61. }
  62. repoName := rr[1]
  63. if strings.HasSuffix(repoName, ".git") {
  64. repoName = repoName[:len(repoName)-4]
  65. }
  66. isWrite := In(verb, COMMANDS_WRITE)
  67. isRead := In(verb, COMMANDS_READONLY)
  68. switch {
  69. case isWrite:
  70. has, err := models.HasAccess(user.Name, repoName, models.AU_WRITABLE)
  71. if err != nil {
  72. println("Inernel error:", err)
  73. return
  74. }
  75. if !has {
  76. println("You have no right to write this repository")
  77. return
  78. }
  79. case isRead:
  80. has, err := models.HasAccess(user.Name, repoName, models.AU_READABLE)
  81. if err != nil {
  82. println("Inernel error")
  83. return
  84. }
  85. if !has {
  86. has, err = models.HasAccess(user.Name, repoName, models.AU_WRITABLE)
  87. if err != nil {
  88. println("Inernel error")
  89. return
  90. }
  91. }
  92. if !has {
  93. println("You have no right to access this repository")
  94. return
  95. }
  96. default:
  97. println("Unknown command")
  98. return
  99. }
  100. isExist, err := models.IsRepositoryExist(user, repoName)
  101. if err != nil {
  102. println("Inernel error:", err.Error())
  103. return
  104. }
  105. if !isExist {
  106. if isRead {
  107. println("Repository", user.Name+"/"+repoName, "is not exist")
  108. return
  109. } else if isWrite {
  110. _, err := models.CreateRepository(user, repoName, "", "", "", false, true)
  111. if err != nil {
  112. println("Create repository failed")
  113. return
  114. }
  115. }
  116. }
  117. gitcmd := exec.Command(verb, rRepo)
  118. gitcmd.Dir = models.RepoRootPath
  119. gitcmd.Stdout = os.Stdout
  120. gitcmd.Stdin = os.Stdin
  121. gitcmd.Stderr = os.Stderr
  122. err = gitcmd.Run()
  123. if err != nil {
  124. println("execute command error:", err.Error())
  125. }
  126. }
  127. func parseCmd(cmd string) (string, string) {
  128. ss := strings.SplitN(cmd, " ", 2)
  129. if len(ss) != 2 {
  130. return "", ""
  131. }
  132. verb, args := ss[0], ss[1]
  133. if verb == "git" {
  134. ss = strings.SplitN(args, " ", 2)
  135. args = ss[1]
  136. verb = fmt.Sprintf("%s %s", verb, ss[0])
  137. }
  138. return verb, args
  139. }