api_defender.go 4.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176
  1. // Copyright (C) 2019-2022 Nicola Murino
  2. //
  3. // This program is free software: you can redistribute it and/or modify
  4. // it under the terms of the GNU Affero General Public License as published
  5. // by the Free Software Foundation, version 3.
  6. //
  7. // This program is distributed in the hope that it will be useful,
  8. // but WITHOUT ANY WARRANTY; without even the implied warranty of
  9. // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  10. // GNU Affero General Public License for more details.
  11. //
  12. // You should have received a copy of the GNU Affero General Public License
  13. // along with this program. If not, see <https://www.gnu.org/licenses/>.
  14. package httpd
  15. import (
  16. "encoding/hex"
  17. "errors"
  18. "fmt"
  19. "net"
  20. "net/http"
  21. "time"
  22. "github.com/go-chi/render"
  23. "github.com/drakkan/sftpgo/v2/common"
  24. "github.com/drakkan/sftpgo/v2/dataprovider"
  25. "github.com/drakkan/sftpgo/v2/util"
  26. )
  27. func getDefenderHosts(w http.ResponseWriter, r *http.Request) {
  28. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  29. hosts, err := common.GetDefenderHosts()
  30. if err != nil {
  31. sendAPIResponse(w, r, err, "", getRespStatus(err))
  32. return
  33. }
  34. if hosts == nil {
  35. render.JSON(w, r, make([]dataprovider.DefenderEntry, 0))
  36. return
  37. }
  38. render.JSON(w, r, hosts)
  39. }
  40. func getDefenderHostByID(w http.ResponseWriter, r *http.Request) {
  41. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  42. ip, err := getIPFromID(r)
  43. if err != nil {
  44. sendAPIResponse(w, r, err, "", http.StatusBadRequest)
  45. return
  46. }
  47. host, err := common.GetDefenderHost(ip)
  48. if err != nil {
  49. sendAPIResponse(w, r, err, "", getRespStatus(err))
  50. return
  51. }
  52. render.JSON(w, r, host)
  53. }
  54. func deleteDefenderHostByID(w http.ResponseWriter, r *http.Request) {
  55. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  56. ip, err := getIPFromID(r)
  57. if err != nil {
  58. sendAPIResponse(w, r, err, "", http.StatusBadRequest)
  59. return
  60. }
  61. if !common.DeleteDefenderHost(ip) {
  62. sendAPIResponse(w, r, nil, "Not found", http.StatusNotFound)
  63. return
  64. }
  65. sendAPIResponse(w, r, nil, "OK", http.StatusOK)
  66. }
  67. func getBanTime(w http.ResponseWriter, r *http.Request) {
  68. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  69. ip := r.URL.Query().Get("ip")
  70. err := validateIPAddress(ip)
  71. if err != nil {
  72. sendAPIResponse(w, r, err, "", http.StatusBadRequest)
  73. return
  74. }
  75. banStatus := make(map[string]*string)
  76. banTime, err := common.GetDefenderBanTime(ip)
  77. if err != nil {
  78. if _, ok := err.(*util.RecordNotFoundError); ok {
  79. banTime = nil
  80. } else {
  81. sendAPIResponse(w, r, err, "", getRespStatus(err))
  82. return
  83. }
  84. }
  85. var banTimeString *string
  86. if banTime != nil {
  87. rfc3339String := banTime.UTC().Format(time.RFC3339)
  88. banTimeString = &rfc3339String
  89. }
  90. banStatus["date_time"] = banTimeString
  91. render.JSON(w, r, banStatus)
  92. }
  93. func getScore(w http.ResponseWriter, r *http.Request) {
  94. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  95. ip := r.URL.Query().Get("ip")
  96. err := validateIPAddress(ip)
  97. if err != nil {
  98. sendAPIResponse(w, r, err, "", http.StatusBadRequest)
  99. return
  100. }
  101. score, err := common.GetDefenderScore(ip)
  102. if err != nil {
  103. if _, ok := err.(*util.RecordNotFoundError); ok {
  104. score = 0
  105. } else {
  106. sendAPIResponse(w, r, err, "", getRespStatus(err))
  107. return
  108. }
  109. }
  110. scoreStatus := make(map[string]int)
  111. scoreStatus["score"] = score
  112. render.JSON(w, r, scoreStatus)
  113. }
  114. func unban(w http.ResponseWriter, r *http.Request) {
  115. r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
  116. var postBody map[string]string
  117. err := render.DecodeJSON(r.Body, &postBody)
  118. if err != nil {
  119. sendAPIResponse(w, r, err, "", http.StatusBadRequest)
  120. return
  121. }
  122. ip := postBody["ip"]
  123. err = validateIPAddress(ip)
  124. if err != nil {
  125. sendAPIResponse(w, r, err, "", http.StatusBadRequest)
  126. return
  127. }
  128. if common.DeleteDefenderHost(ip) {
  129. sendAPIResponse(w, r, nil, "OK", http.StatusOK)
  130. } else {
  131. sendAPIResponse(w, r, nil, "Not found", http.StatusNotFound)
  132. }
  133. }
  134. func getIPFromID(r *http.Request) (string, error) {
  135. decoded, err := hex.DecodeString(getURLParam(r, "id"))
  136. if err != nil {
  137. return "", errors.New("invalid host id")
  138. }
  139. ip := string(decoded)
  140. err = validateIPAddress(ip)
  141. if err != nil {
  142. return "", err
  143. }
  144. return ip, nil
  145. }
  146. func validateIPAddress(ip string) error {
  147. if ip == "" {
  148. return errors.New("ip address is required")
  149. }
  150. if net.ParseIP(ip) == nil {
  151. return fmt.Errorf("ip address %#v is not valid", ip)
  152. }
  153. return nil
  154. }