example-AD.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163
  1. // +build examples
  2. package main
  3. import (
  4. "encoding/hex"
  5. "errors"
  6. "fmt"
  7. "io/ioutil"
  8. "log"
  9. "net/http"
  10. "net/http/httptest"
  11. "os"
  12. "github.com/gorilla/sessions"
  13. "github.com/jcmturner/goidentity/v6"
  14. "github.com/jcmturner/gokrb5/v8/client"
  15. "github.com/jcmturner/gokrb5/v8/config"
  16. "github.com/jcmturner/gokrb5/v8/credentials"
  17. "github.com/jcmturner/gokrb5/v8/keytab"
  18. "github.com/jcmturner/gokrb5/v8/service"
  19. "github.com/jcmturner/gokrb5/v8/spnego"
  20. "github.com/jcmturner/gokrb5/v8/test/testdata"
  21. )
  22. func main() {
  23. s := httpServer()
  24. defer s.Close()
  25. fmt.Printf("Listening on %s\n", s.URL)
  26. l := log.New(os.Stderr, "GOKRB5 Client: ", log.Ldate|log.Ltime|log.Lshortfile)
  27. b, _ := hex.DecodeString(testdata.KEYTAB_TESTUSER1_USER_GOKRB5)
  28. kt := keytab.New()
  29. kt.Unmarshal(b)
  30. c, _ := config.NewFromString(testdata.KRB5_CONF)
  31. cl := client.NewWithKeytab("testuser1", "USER.GOKRB5", kt, c, client.DisablePAFXFAST(true), client.Logger(l))
  32. httpRequest(s.URL, cl)
  33. b, _ = hex.DecodeString(testdata.KEYTAB_TESTUSER2_USER_GOKRB5)
  34. kt = keytab.New()
  35. kt.Unmarshal(b)
  36. c, _ = config.NewFromString(testdata.KRB5_CONF)
  37. cl = client.NewWithKeytab("testuser2", "USER.GOKRB5", kt, c, client.DisablePAFXFAST(true), client.Logger(l))
  38. httpRequest(s.URL, cl)
  39. }
  40. func httpRequest(url string, cl *client.Client) {
  41. l := log.New(os.Stderr, "GOKRB5 Client: ", log.Ldate|log.Ltime|log.Lshortfile)
  42. err := cl.Login()
  43. if err != nil {
  44. l.Fatalf("Error on AS_REQ: %v\n", err)
  45. }
  46. spnegoCl := spnego.NewClient(cl, nil, "HTTP/host.res.gokrb5")
  47. // Make the request for the first time with no session
  48. r, _ := http.NewRequest("GET", url, nil)
  49. httpResp, err := spnegoCl.Do(r)
  50. if err != nil {
  51. l.Fatalf("error making request: %v", err)
  52. }
  53. fmt.Fprintf(os.Stdout, "Response Code: %v\n", httpResp.StatusCode)
  54. content, _ := ioutil.ReadAll(httpResp.Body)
  55. fmt.Fprintf(os.Stdout, "Response Body:\n%s\n", content)
  56. // Make the request again which should use the session
  57. httpResp, err = spnegoCl.Do(r)
  58. if err != nil {
  59. l.Fatalf("error making request: %v", err)
  60. }
  61. fmt.Fprintf(os.Stdout, "Response Code: %v\n", httpResp.StatusCode)
  62. content, _ = ioutil.ReadAll(httpResp.Body)
  63. fmt.Fprintf(os.Stdout, "Response Body:\n%s\n", content)
  64. }
  65. func httpServer() *httptest.Server {
  66. l := log.New(os.Stderr, "GOKRB5 Service Tests: ", log.Ldate|log.Ltime|log.Lshortfile)
  67. b, _ := hex.DecodeString(testdata.KEYTAB_SYSHTTP_RES_GOKRB5)
  68. kt := keytab.New()
  69. kt.Unmarshal(b)
  70. th := http.HandlerFunc(testAppHandler)
  71. s := httptest.NewServer(spnego.SPNEGOKRB5Authenticate(th, kt, service.Logger(l), service.KeytabPrincipal("sysHTTP"), service.SessionManager(NewSessionMgr("gokrb5"))))
  72. return s
  73. }
  74. func testAppHandler(w http.ResponseWriter, r *http.Request) {
  75. creds := goidentity.FromHTTPRequestContext(r)
  76. fmt.Fprint(w, "<html>\n<p><h1>GOKRB5 Handler</h1></p>\n")
  77. if creds != nil && creds.Authenticated() {
  78. fmt.Fprintf(w, "<ul><li>Authenticed user: %s</li>\n", creds.UserName())
  79. fmt.Fprintf(w, "<li>User's realm: %s</li>\n", creds.Domain())
  80. fmt.Fprint(w, "<li>Authz Attributes (Group Memberships):</li><ul>\n")
  81. for _, s := range creds.AuthzAttributes() {
  82. fmt.Fprintf(w, "<li>%v</li>\n", s)
  83. }
  84. fmt.Fprint(w, "</ul>\n")
  85. if ADCredsJSON, ok := creds.Attributes()[credentials.AttributeKeyADCredentials]; ok {
  86. //ADCreds := new(credentials.ADCredentials)
  87. ADCreds := ADCredsJSON.(credentials.ADCredentials)
  88. //err := json.Unmarshal(aj, ADCreds)
  89. //if err == nil {
  90. // Now access the fields of the ADCredentials struct. For example:
  91. fmt.Fprintf(w, "<li>EffectiveName: %v</li>\n", ADCreds.EffectiveName)
  92. fmt.Fprintf(w, "<li>FullName: %v</li>\n", ADCreds.FullName)
  93. fmt.Fprintf(w, "<li>UserID: %v</li>\n", ADCreds.UserID)
  94. fmt.Fprintf(w, "<li>PrimaryGroupID: %v</li>\n", ADCreds.PrimaryGroupID)
  95. fmt.Fprintf(w, "<li>Group SIDs: %v</li>\n", ADCreds.GroupMembershipSIDs)
  96. fmt.Fprintf(w, "<li>LogOnTime: %v</li>\n", ADCreds.LogOnTime)
  97. fmt.Fprintf(w, "<li>LogOffTime: %v</li>\n", ADCreds.LogOffTime)
  98. fmt.Fprintf(w, "<li>PasswordLastSet: %v</li>\n", ADCreds.PasswordLastSet)
  99. fmt.Fprintf(w, "<li>LogonServer: %v</li>\n", ADCreds.LogonServer)
  100. fmt.Fprintf(w, "<li>LogonDomainName: %v</li>\n", ADCreds.LogonDomainName)
  101. fmt.Fprintf(w, "<li>LogonDomainID: %v</li>\n", ADCreds.LogonDomainID)
  102. //}
  103. }
  104. fmt.Fprint(w, "</ul>")
  105. } else {
  106. w.WriteHeader(http.StatusUnauthorized)
  107. fmt.Fprint(w, "Authentication failed")
  108. }
  109. fmt.Fprint(w, "</html>")
  110. return
  111. }
  112. type SessionMgr struct {
  113. skey []byte
  114. store sessions.Store
  115. cookieName string
  116. }
  117. func NewSessionMgr(cookieName string) SessionMgr {
  118. skey := []byte("thisistestsecret") // Best practice is to load this key from a secure location.
  119. return SessionMgr{
  120. skey: skey,
  121. store: sessions.NewCookieStore(skey),
  122. cookieName: cookieName,
  123. }
  124. }
  125. func (smgr SessionMgr) Get(r *http.Request, k string) ([]byte, error) {
  126. s, err := smgr.store.Get(r, smgr.cookieName)
  127. if err != nil {
  128. return nil, err
  129. }
  130. if s == nil {
  131. return nil, errors.New("nil session")
  132. }
  133. b, ok := s.Values[k].([]byte)
  134. if !ok {
  135. return nil, fmt.Errorf("could not get bytes held in session at %s", k)
  136. }
  137. return b, nil
  138. }
  139. func (smgr SessionMgr) New(w http.ResponseWriter, r *http.Request, k string, v []byte) error {
  140. s, err := smgr.store.New(r, smgr.cookieName)
  141. if err != nil {
  142. return fmt.Errorf("could not get new session from session manager: %v", err)
  143. }
  144. s.Values[k] = v
  145. return s.Save(r, w)
  146. }