handler.go 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217
  1. package main
  2. import (
  3. "crypto/tls"
  4. "encoding/json"
  5. "fmt"
  6. "io/ioutil"
  7. "net/http"
  8. "net/url"
  9. "strings"
  10. "github.com/dgrijalva/jwt-go"
  11. "github.com/labstack/echo"
  12. )
  13. type handler struct{}
  14. type userInfo struct {
  15. Result struct {
  16. Result struct {
  17. Sshpubkeyfp []string `json:"sshpubkeyfp"`
  18. HasKeytab bool `json:"has_keytab"`
  19. Ipasshpubkey []string `json:"ipasshpubkey"`
  20. Cn []string `json:"cn"`
  21. Krbcanonicalname []string `json:"krbcanonicalname"`
  22. Krbticketflags []string `json:"krbticketflags"`
  23. MemberofGroup []string `json:"memberof_group"`
  24. HasPassword bool `json:"has_password"`
  25. Homedirectory []string `json:"homedirectory"`
  26. Nsaccountlock bool `json:"nsaccountlock"`
  27. UID []string `json:"uid"`
  28. Title []string `json:"title"`
  29. Loginshell []string `json:"loginshell"`
  30. Uidnumber []string `json:"uidnumber"`
  31. Preserved bool `json:"preserved"`
  32. Krbextradata []struct {
  33. Base64 string `json:"__base64__"`
  34. } `json:"krbextradata"`
  35. Mail []string `json:"mail"`
  36. MemberofindirectHbacrule []string `json:"memberofindirect_hbacrule"`
  37. Dn string `json:"dn"`
  38. Displayname []string `json:"displayname"`
  39. Mepmanagedentry []string `json:"mepmanagedentry"`
  40. Ipauniqueid []string `json:"ipauniqueid"`
  41. Krbloginfailedcount []string `json:"krbloginfailedcount"`
  42. Krbpwdpolicyreference []string `json:"krbpwdpolicyreference"`
  43. Krbprincipalname []string `json:"krbprincipalname"`
  44. Givenname []string `json:"givenname"`
  45. Krblastadminunlock []struct {
  46. Datetime string `json:"__datetime__"`
  47. } `json:"krblastadminunlock"`
  48. Krbpasswordexpiration []struct {
  49. Datetime string `json:"__datetime__"`
  50. } `json:"krbpasswordexpiration"`
  51. Krblastfailedauth []struct {
  52. Datetime string `json:"__datetime__"`
  53. } `json:"krblastfailedauth"`
  54. Objectclass []string `json:"objectclass"`
  55. Gidnumber []string `json:"gidnumber"`
  56. Gecos []string `json:"gecos"`
  57. Sn []string `json:"sn"`
  58. MemberofSudorule []string `json:"memberof_sudorule"`
  59. Krblastpwdchange []struct {
  60. Datetime string `json:"__datetime__"`
  61. } `json:"krblastpwdchange"`
  62. Initials []string `json:"initials"`
  63. } `json:"result"`
  64. Value string `json:"value"`
  65. Summary interface{} `json:"summary"`
  66. } `json:"result"`
  67. Version string `json:"version"`
  68. Error interface{} `json:"error"`
  69. ID int `json:"id"`
  70. Principal string `json:"principal"`
  71. }
  72. // Most of the code is taken from the echo guide
  73. // https://echo.labstack.com/cookbook/jwt
  74. func (h *handler) login(c echo.Context) error {
  75. username := c.FormValue("username")
  76. password := c.FormValue("password")
  77. _url := "https://ipa.sf.faraborddi.dc/ipa/session/login_password"
  78. method := "POST"
  79. params := url.Values{}
  80. params.Add("user", username)
  81. params.Add("password", password)
  82. payload := strings.NewReader(params.Encode())
  83. tr := &http.Transport{
  84. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  85. }
  86. client := &http.Client{Transport: tr}
  87. req, err := http.NewRequest(method, _url, payload)
  88. audit("Recieved Login request from: " + RealIP)
  89. if err != nil {
  90. fmt.Println(err)
  91. }
  92. req.Header.Add("Referer", "https://ipa.sf.faraborddi.dc/ipa")
  93. req.Header.Add("Content-Type", "application/x-www-form-urlencoded")
  94. req.Header.Add("Accept", "text/plain")
  95. res, err := client.Do(req)
  96. cockie := res.Cookies()
  97. defer res.Body.Close()
  98. //fmt.Println(res.StatusCode)
  99. if res.StatusCode == 200 {
  100. user := getUserInfo(cockie, username)
  101. //fmt.Println(user.Result.Value)
  102. tokens, err := generateTokenPair(user)
  103. if err != nil {
  104. return err
  105. }
  106. return c.JSON(http.StatusOK, tokens)
  107. }
  108. return echo.ErrUnauthorized
  109. }
  110. func getUserInfo(cockie []*http.Cookie, username string) userInfo {
  111. url := "https://ipa.sf.faraborddi.dc/ipa/session/json"
  112. method := "POST"
  113. _json := fmt.Sprintf(`
  114. {
  115. "method": "user_show",
  116. "params": [
  117. [
  118. "%s"
  119. ],
  120. {
  121. "all": true,
  122. "version": "2.215"
  123. }
  124. ],
  125. "id": 0
  126. }
  127. `, username)
  128. payload := strings.NewReader(_json)
  129. tr := &http.Transport{
  130. TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
  131. }
  132. client := &http.Client{Transport: tr}
  133. req, err := http.NewRequest(method, url, payload)
  134. if err != nil {
  135. fmt.Println(err)
  136. }
  137. req.Header.Add("Referer", "https://ipa.sf.faraborddi.dc/ipa")
  138. req.Header.Add("Content-Type", "application/json")
  139. req.Header.Add("Accept", "text/plain")
  140. req.Header.Add("Cookie", cockie[0].Raw)
  141. res, err := client.Do(req)
  142. defer res.Body.Close()
  143. body, err := ioutil.ReadAll(res.Body)
  144. user := userInfo{}
  145. json.Unmarshal(body, &user)
  146. //fmt.Println(user.Result.Value)
  147. //fmt.Println(user.Result.Result.MemberofGroup)
  148. return user
  149. }
  150. // This is the api to refresh tokens
  151. // Most of the code is taken from the jwt-go package's sample codes
  152. // https://godoc.org/github.com/dgrijalva/jwt-go#example-Parse--Hmac
  153. //func (h *handler) token(c echo.Context) error {
  154. // type tokenReqBody struct {
  155. // RefreshToken string `json:"refresh_token"`
  156. // }
  157. // tokenReq := tokenReqBody{}
  158. // c.Bind(&tokenReq)
  159. //
  160. // // Parse takes the token string and a function for looking up the key.
  161. // // The latter is especially useful if you use multiple keys for your application.
  162. // // The standard is to use 'kid' in the head of the token to identify
  163. // // which key to use, but the parsed token (head and claims) is provided
  164. // // to the callback, providing flexibility.
  165. // token, err := jwt.Parse(tokenReq.RefreshToken, func(token *jwt.Token) (interface{}, error) {
  166. // // Don't forget to validate the alg is what you expect:
  167. // if _, ok := token.Method.(*jwt.SigningMethodHMAC); !ok {
  168. // return nil, fmt.Errorf("Unexpected signing method: %v", token.Header["alg"])
  169. // }
  170. //
  171. // // hmacSampleSecret is a []byte containing your secret, e.g. []byte("my_secret_key")
  172. // return []byte("secret"), nil
  173. // })
  174. //
  175. // if claims, ok := token.Claims.(jwt.MapClaims); ok && token.Valid {
  176. // // Get the user record from database or
  177. // // run through your business logic to verify if the user can log in
  178. // if int(claims["sub"].(float64)) == 1 {
  179. //
  180. // newTokenPair, err := generateTokenPair()
  181. // if err != nil {
  182. // return err
  183. // }
  184. //
  185. // return c.JSON(http.StatusOK, newTokenPair)
  186. // }
  187. //
  188. // return echo.ErrUnauthorized
  189. // }
  190. //
  191. // return err
  192. //}
  193. // Most of the code is taken from the echo guide
  194. // https://echo.labstack.com/cookbook/jwt
  195. func (h *handler) private(c echo.Context) error {
  196. user := c.Get("user").(*jwt.Token)
  197. claims := user.Claims.(jwt.MapClaims)
  198. name := claims["name"].(string)
  199. return c.String(http.StatusOK, "Welcome "+name+"!")
  200. }
  201. func (h *handler) findMAC(c echo.Context) error {
  202. user := c.Get("user").(*jwt.Token)
  203. claims := user.Claims.(jwt.MapClaims)
  204. name := claims["name"].(string)
  205. return c.String(http.StatusOK, "Welcome "+name+"!")
  206. }