session.go 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  1. package client
  2. import (
  3. "fmt"
  4. "gopkg.in/jcmturner/gokrb5.v1/iana/nametype"
  5. "gopkg.in/jcmturner/gokrb5.v1/krberror"
  6. "gopkg.in/jcmturner/gokrb5.v1/messages"
  7. "gopkg.in/jcmturner/gokrb5.v1/types"
  8. "time"
  9. )
  10. // Sessions keyed on the realm name
  11. type sessions map[string]*session
  12. // Client session struct.
  13. type session struct {
  14. Realm string
  15. AuthTime time.Time
  16. EndTime time.Time
  17. RenewTill time.Time
  18. TGT messages.Ticket
  19. SessionKey types.EncryptionKey
  20. SessionKeyExpiration time.Time
  21. }
  22. //
  23. func (cl *Client) AddSession(tkt messages.Ticket, dep messages.EncKDCRepPart) {
  24. s := &session{
  25. Realm: tkt.SName.NameString[1],
  26. AuthTime: dep.AuthTime,
  27. EndTime: dep.EndTime,
  28. RenewTill: dep.RenewTill,
  29. TGT: tkt,
  30. SessionKey: dep.Key,
  31. SessionKeyExpiration: dep.KeyExpiration,
  32. }
  33. cl.sessions[tkt.SName.NameString[1]] = s
  34. cl.EnableAutoSessionRenewal(s)
  35. }
  36. // EnableAutoSessionRenewal turns on the automatic renewal for the client's TGT session.
  37. func (cl *Client) EnableAutoSessionRenewal(s *session) {
  38. // TODO look into using a context here
  39. go func(s *session) {
  40. for {
  41. //Wait until one minute before endtime
  42. w := (s.EndTime.Sub(time.Now().UTC()) * 5) / 6
  43. if w < 0 {
  44. return
  45. }
  46. time.Sleep(w)
  47. cl.updateSession(s)
  48. }
  49. }(s)
  50. }
  51. // RenewTGT renews the client's TGT session.
  52. func (cl *Client) RenewTGT(s *session) error {
  53. spn := types.PrincipalName{
  54. NameType: nametype.KRB_NT_SRV_INST,
  55. NameString: []string{"krbtgt", s.Realm},
  56. }
  57. _, tgsRep, err := cl.TGSExchange(spn, s.TGT.Realm, s.TGT, s.SessionKey, true)
  58. if err != nil {
  59. return krberror.Errorf(err, krberror.KRBMsgError, "Error renewing TGT")
  60. }
  61. s.AuthTime = tgsRep.DecryptedEncPart.AuthTime
  62. s.AuthTime = tgsRep.DecryptedEncPart.AuthTime
  63. s.EndTime = tgsRep.DecryptedEncPart.EndTime
  64. s.RenewTill = tgsRep.DecryptedEncPart.RenewTill
  65. s.TGT = tgsRep.Ticket
  66. s.SessionKey = tgsRep.DecryptedEncPart.Key
  67. s.SessionKeyExpiration = tgsRep.DecryptedEncPart.KeyExpiration
  68. return nil
  69. }
  70. func (cl *Client) updateSession(s *session) error {
  71. if time.Now().UTC().Before(s.RenewTill) {
  72. err := cl.RenewTGT(s)
  73. if err != nil {
  74. return err
  75. }
  76. } else {
  77. err := cl.ASExchange(s.Realm)
  78. if err != nil {
  79. return err
  80. }
  81. }
  82. return nil
  83. }
  84. func (cl *Client) GetSessionFromRealm(realm string) (sess *session, err error) {
  85. var ok bool
  86. sess, ok = cl.sessions[realm]
  87. if !ok {
  88. sess, ok = cl.sessions[cl.Config.LibDefaults.DefaultRealm]
  89. if !ok {
  90. err = fmt.Errorf("client does not have a session for realm %s or for the default realm %s, login first", realm, cl.Config.LibDefaults.DefaultRealm)
  91. return
  92. }
  93. }
  94. return
  95. }
  96. func (cl *Client) GetSessionFromPrincipalName(spn types.PrincipalName) (*session, error) {
  97. realm := cl.Config.ResolveRealm(spn.NameString[1])
  98. return cl.GetSessionFromRealm(realm)
  99. }