cache.go 2.4 KB

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