cache.go 2.1 KB

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