cache.go 2.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  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, bool) {
  49. if e, ok := cl.Cache.GetEntry(spn); ok {
  50. //If within time window of ticket return it
  51. if time.Now().After(e.AuthTime) && time.Now().Before(e.EndTime) {
  52. return e.Ticket, true
  53. } else if time.Now().Before(e.RenewTill) {
  54. e, err := cl.RenewTicket(e)
  55. if err != nil {
  56. return e.Ticket, false
  57. }
  58. return e.Ticket, true
  59. }
  60. }
  61. var tkt types.Ticket
  62. return tkt, false
  63. }
  64. // Renew a cache entry ticket
  65. func (cl *Client) RenewTicket(e CacheEntry) (CacheEntry, error) {
  66. spn := e.Ticket.SName
  67. _, tgsRep, err := cl.TGSExchange(spn, e.Ticket, e.SessionKey, true)
  68. if err != nil {
  69. return e, err
  70. }
  71. e = cl.Cache.AddEntry(
  72. tgsRep.Ticket,
  73. tgsRep.DecryptedEncPart.AuthTime,
  74. tgsRep.DecryptedEncPart.EndTime,
  75. tgsRep.DecryptedEncPart.RenewTill,
  76. tgsRep.DecryptedEncPart.Key,
  77. )
  78. return e, nil
  79. }