cache.go 2.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990
  1. package client
  2. import (
  3. "github.com/jcmturner/gokrb5/messages"
  4. "github.com/jcmturner/gokrb5/types"
  5. "strings"
  6. "time"
  7. )
  8. // Client ticket cache.
  9. type Cache struct {
  10. Entries map[string]CacheEntry
  11. }
  12. // Ticket cache entry.
  13. type CacheEntry struct {
  14. Ticket messages.Ticket
  15. AuthTime time.Time
  16. EndTime time.Time
  17. RenewTill time.Time
  18. SessionKey types.EncryptionKey
  19. }
  20. // Create a new client ticket cache.
  21. func NewCache() *Cache {
  22. return &Cache{
  23. Entries: map[string]CacheEntry{},
  24. }
  25. }
  26. // Get a cache entry that matches the SPN.
  27. func (c *Cache) GetEntry(spn string) (CacheEntry, bool) {
  28. e, ok := (*c).Entries[spn]
  29. return e, ok
  30. }
  31. // Add a ticket to the cache.
  32. func (c *Cache) AddEntry(tkt messages.Ticket, authTime, endTime, renewTill time.Time, sessionKey types.EncryptionKey) CacheEntry {
  33. spn := strings.Join(tkt.SName.NameString, "/")
  34. (*c).Entries[spn] = CacheEntry{
  35. Ticket: tkt,
  36. AuthTime: authTime,
  37. EndTime: endTime,
  38. RenewTill: renewTill,
  39. SessionKey: sessionKey,
  40. }
  41. return c.Entries[spn]
  42. }
  43. // Remove the cache entry for the defined SPN.
  44. func (c *Cache) RemoveEntry(spn string) {
  45. delete(c.Entries, spn)
  46. }
  47. // Get a ticket from the cache for the SPN.
  48. // Only a ticket that is currently valid will be returned.
  49. func (cl *Client) GetCachedTicket(spn string) (messages.Ticket, types.EncryptionKey, bool) {
  50. if e, ok := cl.Cache.GetEntry(spn); ok {
  51. //If within time window of ticket return it
  52. if time.Now().UTC().After(e.AuthTime) && time.Now().UTC().Before(e.EndTime) {
  53. return e.Ticket, e.SessionKey, true
  54. } else if time.Now().UTC().Before(e.RenewTill) {
  55. e, err := cl.RenewTicket(e)
  56. if err != nil {
  57. return e.Ticket, e.SessionKey, false
  58. }
  59. return e.Ticket, e.SessionKey, true
  60. }
  61. }
  62. var tkt messages.Ticket
  63. var key types.EncryptionKey
  64. return tkt, key, false
  65. }
  66. // Renew a cache entry ticket
  67. func (cl *Client) RenewTicket(e CacheEntry) (CacheEntry, error) {
  68. spn := e.Ticket.SName
  69. _, tgsRep, err := cl.TGSExchange(spn, e.Ticket, e.SessionKey, true)
  70. if err != nil {
  71. return e, err
  72. }
  73. e = cl.Cache.AddEntry(
  74. tgsRep.Ticket,
  75. tgsRep.DecryptedEncPart.AuthTime,
  76. tgsRep.DecryptedEncPart.EndTime,
  77. tgsRep.DecryptedEncPart.RenewTill,
  78. tgsRep.DecryptedEncPart.Key,
  79. )
  80. return e, nil
  81. }