KDCRep.go 9.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. package messages
  2. // Reference: https://www.ietf.org/rfc/rfc4120.txt
  3. // Section: 5.4.2
  4. import (
  5. "errors"
  6. "fmt"
  7. "github.com/jcmturner/asn1"
  8. "github.com/jcmturner/gokrb5/config"
  9. "github.com/jcmturner/gokrb5/credentials"
  10. "github.com/jcmturner/gokrb5/crypto"
  11. "github.com/jcmturner/gokrb5/iana/asnAppTag"
  12. "github.com/jcmturner/gokrb5/iana/keyusage"
  13. "github.com/jcmturner/gokrb5/iana/msgtype"
  14. "github.com/jcmturner/gokrb5/keytab"
  15. "github.com/jcmturner/gokrb5/types"
  16. "sort"
  17. "time"
  18. )
  19. type marshalKDCRep struct {
  20. PVNO int `asn1:"explicit,tag:0"`
  21. MsgType int `asn1:"explicit,tag:1"`
  22. PAData types.PADataSequence `asn1:"explicit,optional,tag:2"`
  23. CRealm string `asn1:"generalstring,explicit,tag:3"`
  24. CName types.PrincipalName `asn1:"explicit,tag:4"`
  25. // Ticket needs to be a raw value as it is wrapped in an APPLICATION tag
  26. Ticket asn1.RawValue `asn1:"explicit,tag:5"`
  27. EncPart types.EncryptedData `asn1:"explicit,tag:6"`
  28. }
  29. type KDCRep struct {
  30. PVNO int
  31. MsgType int
  32. PAData []types.PAData
  33. CRealm string
  34. CName types.PrincipalName
  35. Ticket types.Ticket
  36. EncPart types.EncryptedData
  37. DecryptedEncPart EncKDCRepPart
  38. }
  39. type ASRep KDCRep
  40. type TGSRep KDCRep
  41. type EncKDCRepPart struct {
  42. Key types.EncryptionKey `asn1:"explicit,tag:0"`
  43. LastReqs []LastReq `asn1:"explicit,tag:1"`
  44. Nonce int `asn1:"explicit,tag:2"`
  45. KeyExpiration time.Time `asn1:"generalized,explicit,optional,tag:3"`
  46. Flags asn1.BitString `asn1:"explicit,tag:4"`
  47. AuthTime time.Time `asn1:"generalized,explicit,tag:5"`
  48. StartTime time.Time `asn1:"generalized,explicit,optional,tag:6"`
  49. EndTime time.Time `asn1:"generalized,explicit,tag:7"`
  50. RenewTill time.Time `asn1:"generalized,explicit,optional,tag:8"`
  51. SRealm string `asn1:"generalstring,explicit,tag:9"`
  52. SName types.PrincipalName `asn1:"explicit,tag:10"`
  53. CAddr []types.HostAddress `asn1:"explicit,optional,tag:11"`
  54. EncPAData types.PADataSequence `asn1:"explicit,optional,tag:12"`
  55. }
  56. type LastReq struct {
  57. LRType int `asn1:"explicit,tag:0"`
  58. LRValue time.Time `asn1:"generalized,explicit,tag:1"`
  59. }
  60. func (k *ASRep) Unmarshal(b []byte) error {
  61. var m marshalKDCRep
  62. _, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.ASREP))
  63. if err != nil {
  64. return err
  65. }
  66. if m.MsgType != msgtype.KRB_AS_REP {
  67. return errors.New("Message ID does not indicate a KRB_AS_REP")
  68. }
  69. //Process the raw ticket within
  70. k.Ticket, err = types.UnmarshalTicket(m.Ticket.Bytes)
  71. if err != nil {
  72. return err
  73. }
  74. k.PVNO = m.PVNO
  75. k.MsgType = m.MsgType
  76. k.PAData = m.PAData
  77. k.CRealm = m.CRealm
  78. k.CName = m.CName
  79. k.EncPart = m.EncPart
  80. return nil
  81. }
  82. func (k *TGSRep) Unmarshal(b []byte) error {
  83. var m marshalKDCRep
  84. _, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.TGSREP))
  85. if err != nil {
  86. return err
  87. }
  88. if m.MsgType != msgtype.KRB_TGS_REP {
  89. return errors.New("Message ID does not indicate a KRB_TGS_REP")
  90. }
  91. //Process the raw ticket within
  92. k.Ticket, err = types.UnmarshalTicket(m.Ticket.Bytes)
  93. if err != nil {
  94. return err
  95. }
  96. k.PVNO = m.PVNO
  97. k.MsgType = m.MsgType
  98. k.PAData = m.PAData
  99. k.CRealm = m.CRealm
  100. k.CName = m.CName
  101. k.EncPart = m.EncPart
  102. return nil
  103. }
  104. func (e *EncKDCRepPart) Unmarshal(b []byte) error {
  105. _, err := asn1.UnmarshalWithParams(b, e, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncASRepPart))
  106. if err != nil {
  107. // Try using tag 26
  108. /* Ref: RFC 4120
  109. Compatibility note: Some implementations unconditionally send an
  110. encrypted EncTGSRepPart (application tag number 26) in this field
  111. regardless of whether the reply is a AS-REP or a TGS-REP. In the
  112. interest of compatibility, implementors MAY relax the check on the
  113. tag number of the decrypted ENC-PART.*/
  114. _, err = asn1.UnmarshalWithParams(b, e, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncTGSRepPart))
  115. return err
  116. }
  117. return err
  118. }
  119. func (k *ASRep) DecryptEncPart(c *credentials.Credentials) error {
  120. var etype crypto.EType
  121. var key types.EncryptionKey
  122. var err error
  123. if c.HasKeytab() {
  124. etype, err = crypto.GetEtype(k.EncPart.EType)
  125. if err != nil {
  126. return fmt.Errorf("Error getting encryption type: %v", err)
  127. }
  128. key, err = c.Keytab.GetEncryptionKey(k.CName.NameString[0], k.CRealm, k.EncPart.KVNO, k.EncPart.EType)
  129. if err != nil {
  130. return fmt.Errorf("Could not get key from keytab: %v", err)
  131. }
  132. }
  133. if c.HasPassword() {
  134. key, etype, err = crypto.GetKeyFromPassword(c.Password, k.CName, k.CRealm, k.EncPart.EType, k.PAData)
  135. if err != nil {
  136. return fmt.Errorf("Could not derive key from password: %v", err)
  137. }
  138. }
  139. if !c.HasKeytab() && !c.HasPassword() {
  140. return errors.New("No secret available in credentials to preform decryption")
  141. }
  142. b, err := crypto.DecryptEncPart(key.KeyValue, k.EncPart, etype, keyusage.AS_REP_ENCPART)
  143. if err != nil {
  144. return fmt.Errorf("Error decrypting KDC_REP EncPart: %v", err)
  145. }
  146. var denc EncKDCRepPart
  147. err = denc.Unmarshal(b)
  148. if err != nil {
  149. return fmt.Errorf("Error unmarshalling encrypted part: %v", err)
  150. }
  151. k.DecryptedEncPart = denc
  152. return nil
  153. }
  154. func (k *ASRep) IsValid(cfg *config.Config, asReq ASReq) (bool, error) {
  155. //Ref RFC 4120 Section 3.1.5
  156. //TODO change the following to a contains check or slice compare
  157. if k.CName.NameType != asReq.ReqBody.CName.NameType {
  158. return false, fmt.Errorf("CName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.CName, k.CName)
  159. }
  160. sort.Strings(k.CName.NameString)
  161. sort.Strings(asReq.ReqBody.CName.NameString)
  162. for i := range k.CName.NameString {
  163. if k.CName.NameString[i] != asReq.ReqBody.CName.NameString[i] {
  164. return false, fmt.Errorf("CName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.CName, k.CName)
  165. }
  166. }
  167. if k.CRealm != asReq.ReqBody.Realm {
  168. return false, fmt.Errorf("CRealm in response does not match what was requested. Requested: %s; Reply: %s", asReq.ReqBody.Realm, k.CRealm)
  169. }
  170. if k.DecryptedEncPart.Nonce != asReq.ReqBody.Nonce {
  171. return false, errors.New("Possible replay attack, nonce in response does not match that in request")
  172. }
  173. if k.DecryptedEncPart.SName.NameType != asReq.ReqBody.SName.NameType {
  174. return false, fmt.Errorf("SName in response does not match what was requested. Requested: %v; Reply: %v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)
  175. }
  176. sort.Strings(k.DecryptedEncPart.SName.NameString)
  177. sort.Strings(asReq.ReqBody.SName.NameString)
  178. for i := range k.CName.NameString {
  179. if k.DecryptedEncPart.SName.NameString[i] != asReq.ReqBody.SName.NameString[i] {
  180. return false, fmt.Errorf("SName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)
  181. }
  182. }
  183. if k.DecryptedEncPart.SRealm != asReq.ReqBody.Realm {
  184. return false, fmt.Errorf("SRealm in response does not match what was requested. Requested: %s; Reply: %s", asReq.ReqBody.Realm, k.DecryptedEncPart.SRealm)
  185. }
  186. if len(asReq.ReqBody.Addresses) > 0 {
  187. //TODO compare if address list is the same
  188. }
  189. if time.Since(k.DecryptedEncPart.AuthTime) > cfg.LibDefaults.Clockskew || time.Until(k.DecryptedEncPart.AuthTime) > cfg.LibDefaults.Clockskew {
  190. return false, fmt.Errorf("Clock skew with KDC too large. Greater than %v seconds", cfg.LibDefaults.Clockskew.Seconds())
  191. }
  192. return true, nil
  193. }
  194. func (k *TGSRep) DecryptEncPart(kt keytab.Keytab) error {
  195. etype, err := crypto.GetEtype(k.EncPart.EType)
  196. if err != nil {
  197. return fmt.Errorf("Keytab error: %v", err)
  198. }
  199. key, err := kt.GetEncryptionKey(k.CName.NameString[0], k.CRealm, k.EncPart.KVNO, k.EncPart.EType)
  200. if err != nil {
  201. return fmt.Errorf("Could not get key from keytab: %v", err)
  202. }
  203. b, err := crypto.DecryptEncPart(key.KeyValue, k.EncPart, etype, keyusage.AS_REP_ENCPART)
  204. if err != nil {
  205. return fmt.Errorf("Error decrypting KDC_REP EncPart: %v", err)
  206. }
  207. var denc EncKDCRepPart
  208. err = denc.Unmarshal(b)
  209. if err != nil {
  210. return fmt.Errorf("Error unmarshalling encrypted part: %v", err)
  211. }
  212. k.DecryptedEncPart = denc
  213. return nil
  214. }
  215. // TODO put back after type tests complete to help me decide what to do with KDCRep vs ASRep and TGSRep
  216. //func validateKDCRep(k *KDCRep, asReq KDCReq, kt keytab.Keytab) (bool, error) {
  217. // //Ref RFC 4120 Section 3.1.5
  218. // //TODO change the following to a contains check or slice compare
  219. // if k.CName.NameType != asReq.ReqBody.CName.NameType || k.CName.NameString[0] != asReq.ReqBody.CName.NameString[0] {
  220. // return false, fmt.Errorf("CName in response does not match what was requested. Requested: %v; Reply: %v", asReq.ReqBody.CName, k.CName)
  221. // }
  222. // if k.CRealm != asReq.ReqBody.Realm {
  223. // return false, fmt.Errorf("CRealm in response does not match what was requested. Requested: %s; Reply: %s", asReq.ReqBody.Realm, k.CRealm)
  224. // }
  225. // if k.DecryptedEncPart.Key.KeyType == 0 {
  226. // err := k.DecryptEncPart(kt)
  227. // if err != nil {
  228. // return false, fmt.Errorf("Could not decrypt encrypted part of response: %v", err)
  229. // }
  230. // }
  231. // if k.DecryptedEncPart.Nonce != asReq.ReqBody.Nonce {
  232. // return false, errors.New("Possible replay attack, nonce in request does not match that in response")
  233. // }
  234. // //TODO change the following to a contains check or slice compare
  235. // if k.DecryptedEncPart.SName.NameType != asReq.ReqBody.SName.NameType || k.DecryptedEncPart.SName.NameString[0] != asReq.ReqBody.SName.NameString[0] {
  236. // return false, fmt.Errorf("SName in response does not match what was requested. Requested: %v; Reply: %v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)
  237. // }
  238. // if k.DecryptedEncPart.SRealm != asReq.ReqBody.Realm {
  239. // return false, fmt.Errorf("SRealm in response does not match what was requested. Requested: %s; Reply: %s", asReq.ReqBody.Realm, k.DecryptedEncPart.SRealm)
  240. // }
  241. // if len(asReq.ReqBody.Addresses) > 0 {
  242. // //TODO compare if address list is the same
  243. // }
  244. // return true, nil
  245. //}