ASExchange.go 3.0 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. package client
  2. import (
  3. "errors"
  4. "fmt"
  5. "github.com/jcmturner/gokrb5/crypto"
  6. "github.com/jcmturner/gokrb5/iana/errorcode"
  7. "github.com/jcmturner/gokrb5/iana/patype"
  8. "github.com/jcmturner/gokrb5/messages"
  9. "github.com/jcmturner/gokrb5/types"
  10. "sort"
  11. )
  12. // Login the client with the KDC via an AS exchange.
  13. func (cl *Client) Login() error {
  14. return cl.ASExchange()
  15. }
  16. // Perform an AS exchange for the client to retrieve a TGT.
  17. func (cl *Client) ASExchange() error {
  18. if !cl.IsConfigured() {
  19. return errors.New("Client is not configured correctly.")
  20. }
  21. a := messages.NewASReq(cl.Config, cl.Credentials.Username)
  22. b, err := a.Marshal()
  23. if err != nil {
  24. return fmt.Errorf("Error marshalling AS_REQ: %v", err)
  25. }
  26. rb, err := cl.SendToKDC(b)
  27. if err != nil {
  28. return fmt.Errorf("Error sending AS_REQ to KDC: %v", err)
  29. }
  30. var ar messages.ASRep
  31. err = ar.Unmarshal(rb)
  32. if err != nil {
  33. //A KRBError may have been returned instead.
  34. var krberr messages.KRBError
  35. err = krberr.Unmarshal(rb)
  36. if err != nil {
  37. return fmt.Errorf("Could not unmarshal data returned from KDC: %v", err)
  38. }
  39. if krberr.ErrorCode == errorcode.KDC_ERR_PREAUTH_REQUIRED {
  40. paTSb, err := types.GetPAEncTSEncAsnMarshalled()
  41. if err != nil {
  42. return fmt.Errorf("Error creating PAEncTSEnc for Pre-Authentication: %v", err)
  43. }
  44. sort.Sort(sort.Reverse(sort.IntSlice(cl.Config.LibDefaults.Default_tkt_enctype_ids)))
  45. etype, err := crypto.GetEtype(cl.Config.LibDefaults.Default_tkt_enctype_ids[0])
  46. if err != nil {
  47. return fmt.Errorf("Error creating etype: %v", err)
  48. }
  49. //paEncTS, err := crypto.GetEncryptedData(paTSb, etype, cl.Config.LibDefaults.Default_realm, cl.Credentials.Username, cl.Credentials.Keytab, 1)
  50. key, err := cl.Credentials.Keytab.GetEncryptionKey(cl.Credentials.Username, cl.Config.LibDefaults.Default_realm, 1, etype.GetETypeID())
  51. paEncTS, err := crypto.GetEncryptedData(paTSb, key, 0, 1)
  52. if err != nil {
  53. return fmt.Errorf("Error encrypting pre-authentication timestamp: %v", err)
  54. }
  55. pa := types.PAData{
  56. PADataType: patype.PA_ENC_TIMESTAMP,
  57. PADataValue: paEncTS.Cipher,
  58. }
  59. a.PAData = append(a.PAData, pa)
  60. b, err := a.Marshal()
  61. if err != nil {
  62. return fmt.Errorf("Error marshalling AS_REQ: %v", err)
  63. }
  64. rb, err := cl.SendToKDC(b)
  65. if err != nil {
  66. return fmt.Errorf("Error sending AS_REQ to KDC: %v", err)
  67. }
  68. err = ar.Unmarshal(rb)
  69. if err != nil {
  70. return fmt.Errorf("Could not unmarshal data returned from KDC: %v", err)
  71. }
  72. }
  73. return krberr
  74. }
  75. err = ar.DecryptEncPart(cl.Credentials)
  76. if err != nil {
  77. return fmt.Errorf("Error decrypting EncPart of AS_REP: %v", err)
  78. }
  79. if ok, err := ar.IsValid(cl.Config, a); !ok {
  80. return fmt.Errorf("AS_REP is not valid: %v", err)
  81. }
  82. cl.Session = &Session{
  83. AuthTime: ar.DecryptedEncPart.AuthTime,
  84. EndTime: ar.DecryptedEncPart.EndTime,
  85. RenewTill: ar.DecryptedEncPart.RenewTill,
  86. TGT: ar.Ticket,
  87. SessionKey: ar.DecryptedEncPart.Key,
  88. SessionKeyExpiration: ar.DecryptedEncPart.KeyExpiration,
  89. }
  90. return nil
  91. }