KDCReq.go 14 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432
  1. package messages
  2. // Reference: https://www.ietf.org/rfc/rfc4120.txt
  3. // Section: 5.4.1
  4. import (
  5. "crypto/rand"
  6. "fmt"
  7. "math"
  8. "math/big"
  9. "time"
  10. "github.com/jcmturner/gofork/encoding/asn1"
  11. "github.com/jcmturner/gokrb5/v8/asn1tools"
  12. "github.com/jcmturner/gokrb5/v8/config"
  13. "github.com/jcmturner/gokrb5/v8/crypto"
  14. "github.com/jcmturner/gokrb5/v8/iana"
  15. "github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
  16. "github.com/jcmturner/gokrb5/v8/iana/flags"
  17. "github.com/jcmturner/gokrb5/v8/iana/keyusage"
  18. "github.com/jcmturner/gokrb5/v8/iana/msgtype"
  19. "github.com/jcmturner/gokrb5/v8/iana/nametype"
  20. "github.com/jcmturner/gokrb5/v8/iana/patype"
  21. "github.com/jcmturner/gokrb5/v8/krberror"
  22. "github.com/jcmturner/gokrb5/v8/types"
  23. )
  24. type marshalKDCReq struct {
  25. PVNO int `asn1:"explicit,tag:1"`
  26. MsgType int `asn1:"explicit,tag:2"`
  27. PAData types.PADataSequence `asn1:"explicit,optional,tag:3"`
  28. ReqBody asn1.RawValue `asn1:"explicit,tag:4"`
  29. }
  30. // KDCReqFields represents the KRB_KDC_REQ fields.
  31. type KDCReqFields struct {
  32. PVNO int
  33. MsgType int
  34. PAData types.PADataSequence
  35. ReqBody KDCReqBody
  36. Renewal bool
  37. }
  38. // ASReq implements RFC 4120 KRB_AS_REQ: https://tools.ietf.org/html/rfc4120#section-5.4.1.
  39. type ASReq struct {
  40. KDCReqFields
  41. }
  42. // TGSReq implements RFC 4120 KRB_TGS_REQ: https://tools.ietf.org/html/rfc4120#section-5.4.1.
  43. type TGSReq struct {
  44. KDCReqFields
  45. }
  46. type marshalKDCReqBody struct {
  47. KDCOptions asn1.BitString `asn1:"explicit,tag:0"`
  48. CName types.PrincipalName `asn1:"explicit,optional,tag:1"`
  49. Realm string `asn1:"generalstring,explicit,tag:2"`
  50. SName types.PrincipalName `asn1:"explicit,optional,tag:3"`
  51. From time.Time `asn1:"generalized,explicit,optional,tag:4"`
  52. Till time.Time `asn1:"generalized,explicit,tag:5"`
  53. RTime time.Time `asn1:"generalized,explicit,optional,tag:6"`
  54. Nonce int `asn1:"explicit,tag:7"`
  55. EType []int32 `asn1:"explicit,tag:8"`
  56. Addresses []types.HostAddress `asn1:"explicit,optional,tag:9"`
  57. EncAuthData types.EncryptedData `asn1:"explicit,optional,tag:10"`
  58. // Ticket needs to be a raw value as it is wrapped in an APPLICATION tag
  59. AdditionalTickets asn1.RawValue `asn1:"explicit,optional,tag:11"`
  60. }
  61. // KDCReqBody implements the KRB_KDC_REQ request body.
  62. type KDCReqBody struct {
  63. KDCOptions asn1.BitString `asn1:"explicit,tag:0"`
  64. CName types.PrincipalName `asn1:"explicit,optional,tag:1"`
  65. Realm string `asn1:"generalstring,explicit,tag:2"`
  66. SName types.PrincipalName `asn1:"explicit,optional,tag:3"`
  67. From time.Time `asn1:"generalized,explicit,optional,tag:4"`
  68. Till time.Time `asn1:"generalized,explicit,tag:5"`
  69. RTime time.Time `asn1:"generalized,explicit,optional,tag:6"`
  70. Nonce int `asn1:"explicit,tag:7"`
  71. EType []int32 `asn1:"explicit,tag:8"`
  72. Addresses []types.HostAddress `asn1:"explicit,optional,tag:9"`
  73. EncAuthData types.EncryptedData `asn1:"explicit,optional,tag:10"`
  74. AdditionalTickets []Ticket `asn1:"explicit,optional,tag:11"`
  75. }
  76. // NewASReqForTGT generates a new KRB_AS_REQ struct for a TGT request.
  77. func NewASReqForTGT(realm string, c *config.Config, cname types.PrincipalName) (ASReq, error) {
  78. sname := types.PrincipalName{
  79. NameType: nametype.KRB_NT_SRV_INST,
  80. NameString: []string{"krbtgt", realm},
  81. }
  82. return NewASReq(realm, c, cname, sname)
  83. }
  84. // NewASReqForChgPasswd generates a new KRB_AS_REQ struct for a change password request.
  85. func NewASReqForChgPasswd(realm string, c *config.Config, cname types.PrincipalName) (ASReq, error) {
  86. sname := types.PrincipalName{
  87. NameType: nametype.KRB_NT_PRINCIPAL,
  88. NameString: []string{"kadmin", "changepw"},
  89. }
  90. return NewASReq(realm, c, cname, sname)
  91. }
  92. // NewASReq generates a new KRB_AS_REQ struct for a given SNAME.
  93. func NewASReq(realm string, c *config.Config, cname, sname types.PrincipalName) (ASReq, error) {
  94. nonce, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt32))
  95. if err != nil {
  96. return ASReq{}, err
  97. }
  98. t := time.Now().UTC()
  99. // Copy the default options to make this thread safe
  100. kopts := types.NewKrbFlags()
  101. copy(kopts.Bytes, c.LibDefaults.KDCDefaultOptions.Bytes)
  102. kopts.BitLength = c.LibDefaults.KDCDefaultOptions.BitLength
  103. a := ASReq{
  104. KDCReqFields{
  105. PVNO: iana.PVNO,
  106. MsgType: msgtype.KRB_AS_REQ,
  107. PAData: types.PADataSequence{},
  108. ReqBody: KDCReqBody{
  109. KDCOptions: kopts,
  110. Realm: realm,
  111. CName: cname,
  112. SName: sname,
  113. Till: t.Add(c.LibDefaults.TicketLifetime),
  114. Nonce: int(nonce.Int64()),
  115. EType: c.LibDefaults.DefaultTktEnctypeIDs,
  116. },
  117. },
  118. }
  119. if c.LibDefaults.Forwardable {
  120. types.SetFlag(&a.ReqBody.KDCOptions, flags.Forwardable)
  121. }
  122. if c.LibDefaults.Canonicalize {
  123. types.SetFlag(&a.ReqBody.KDCOptions, flags.Canonicalize)
  124. }
  125. if c.LibDefaults.Proxiable {
  126. types.SetFlag(&a.ReqBody.KDCOptions, flags.Proxiable)
  127. }
  128. if c.LibDefaults.RenewLifetime != 0 {
  129. types.SetFlag(&a.ReqBody.KDCOptions, flags.Renewable)
  130. a.ReqBody.RTime = t.Add(c.LibDefaults.RenewLifetime)
  131. a.ReqBody.RTime = t.Add(time.Duration(48) * time.Hour)
  132. }
  133. if !c.LibDefaults.NoAddresses {
  134. ha, err := types.LocalHostAddresses()
  135. if err != nil {
  136. return a, fmt.Errorf("could not get local addresses: %v", err)
  137. }
  138. ha = append(ha, types.HostAddressesFromNetIPs(c.LibDefaults.ExtraAddresses)...)
  139. a.ReqBody.Addresses = ha
  140. }
  141. return a, nil
  142. }
  143. // NewTGSReq generates a new KRB_TGS_REQ struct.
  144. func NewTGSReq(cname types.PrincipalName, kdcRealm string, c *config.Config, tgt Ticket, sessionKey types.EncryptionKey, sname types.PrincipalName, renewal bool) (TGSReq, error) {
  145. a, err := tgsReq(cname, sname, kdcRealm, renewal, c)
  146. if err != nil {
  147. return a, err
  148. }
  149. err = a.setPAData(tgt, sessionKey)
  150. return a, err
  151. }
  152. // NewUser2UserTGSReq returns a TGS-REQ suitable for user-to-user authentication (https://tools.ietf.org/html/rfc4120#section-3.7)
  153. func NewUser2UserTGSReq(cname types.PrincipalName, kdcRealm string, c *config.Config, clientTGT Ticket, sessionKey types.EncryptionKey, sname types.PrincipalName, renewal bool, verifyingTGT Ticket) (TGSReq, error) {
  154. a, err := tgsReq(cname, sname, kdcRealm, renewal, c)
  155. if err != nil {
  156. return a, err
  157. }
  158. a.ReqBody.AdditionalTickets = []Ticket{verifyingTGT}
  159. types.SetFlag(&a.ReqBody.KDCOptions, flags.EncTktInSkey)
  160. err = a.setPAData(clientTGT, sessionKey)
  161. return a, err
  162. }
  163. // tgsReq populates the fields for a TGS_REQ
  164. func tgsReq(cname, sname types.PrincipalName, kdcRealm string, renewal bool, c *config.Config) (TGSReq, error) {
  165. nonce, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt32))
  166. if err != nil {
  167. return TGSReq{}, err
  168. }
  169. t := time.Now().UTC()
  170. k := KDCReqFields{
  171. PVNO: iana.PVNO,
  172. MsgType: msgtype.KRB_TGS_REQ,
  173. ReqBody: KDCReqBody{
  174. KDCOptions: types.NewKrbFlags(),
  175. Realm: kdcRealm,
  176. CName: cname, // Add the CName to make validation of the reply easier
  177. SName: sname,
  178. Till: t.Add(c.LibDefaults.TicketLifetime),
  179. Nonce: int(nonce.Int64()),
  180. EType: c.LibDefaults.DefaultTGSEnctypeIDs,
  181. },
  182. Renewal: renewal,
  183. }
  184. if c.LibDefaults.Forwardable {
  185. types.SetFlag(&k.ReqBody.KDCOptions, flags.Forwardable)
  186. }
  187. if c.LibDefaults.Canonicalize {
  188. types.SetFlag(&k.ReqBody.KDCOptions, flags.Canonicalize)
  189. }
  190. if c.LibDefaults.Proxiable {
  191. types.SetFlag(&k.ReqBody.KDCOptions, flags.Proxiable)
  192. }
  193. if c.LibDefaults.RenewLifetime > time.Duration(0) {
  194. types.SetFlag(&k.ReqBody.KDCOptions, flags.Renewable)
  195. k.ReqBody.RTime = t.Add(c.LibDefaults.RenewLifetime)
  196. }
  197. if !c.LibDefaults.NoAddresses {
  198. ha, err := types.LocalHostAddresses()
  199. if err != nil {
  200. return TGSReq{}, fmt.Errorf("could not get local addresses: %v", err)
  201. }
  202. ha = append(ha, types.HostAddressesFromNetIPs(c.LibDefaults.ExtraAddresses)...)
  203. k.ReqBody.Addresses = ha
  204. }
  205. if renewal {
  206. types.SetFlag(&k.ReqBody.KDCOptions, flags.Renew)
  207. types.SetFlag(&k.ReqBody.KDCOptions, flags.Renewable)
  208. }
  209. return TGSReq{
  210. k,
  211. }, nil
  212. }
  213. func (k *TGSReq) setPAData(tgt Ticket, sessionKey types.EncryptionKey) error {
  214. // Marshal the request and calculate checksum
  215. b, err := k.ReqBody.Marshal()
  216. if err != nil {
  217. return krberror.Errorf(err, krberror.EncodingError, "error marshaling TGS_REQ body")
  218. }
  219. etype, err := crypto.GetEtype(sessionKey.KeyType)
  220. if err != nil {
  221. return krberror.Errorf(err, krberror.EncryptingError, "error getting etype to encrypt authenticator")
  222. }
  223. cb, err := etype.GetChecksumHash(sessionKey.KeyValue, b, keyusage.TGS_REQ_PA_TGS_REQ_AP_REQ_AUTHENTICATOR_CHKSUM)
  224. if err != nil {
  225. return krberror.Errorf(err, krberror.ChksumError, "error getting etype checksum hash")
  226. }
  227. // Form PAData for TGS_REQ
  228. // Create authenticator
  229. auth, err := types.NewAuthenticator(tgt.Realm, k.ReqBody.CName)
  230. if err != nil {
  231. return krberror.Errorf(err, krberror.KRBMsgError, "error generating new authenticator")
  232. }
  233. auth.Cksum = types.Checksum{
  234. CksumType: etype.GetHashID(),
  235. Checksum: cb,
  236. }
  237. // Create AP_REQ
  238. apReq, err := NewAPReq(tgt, sessionKey, auth)
  239. if err != nil {
  240. return krberror.Errorf(err, krberror.KRBMsgError, "error generating new AP_REQ")
  241. }
  242. apb, err := apReq.Marshal()
  243. if err != nil {
  244. return krberror.Errorf(err, krberror.EncodingError, "error marshaling AP_REQ for pre-authentication data")
  245. }
  246. k.PAData = types.PADataSequence{
  247. types.PAData{
  248. PADataType: patype.PA_TGS_REQ,
  249. PADataValue: apb,
  250. },
  251. }
  252. return nil
  253. }
  254. // Unmarshal bytes b into the ASReq struct.
  255. func (k *ASReq) Unmarshal(b []byte) error {
  256. var m marshalKDCReq
  257. _, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.ASREQ))
  258. if err != nil {
  259. return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling AS_REQ")
  260. }
  261. expectedMsgType := msgtype.KRB_AS_REQ
  262. if m.MsgType != expectedMsgType {
  263. return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a AS_REQ. Expected: %v; Actual: %v", expectedMsgType, m.MsgType)
  264. }
  265. var reqb KDCReqBody
  266. err = reqb.Unmarshal(m.ReqBody.Bytes)
  267. if err != nil {
  268. return krberror.Errorf(err, krberror.EncodingError, "error processing AS_REQ body")
  269. }
  270. k.MsgType = m.MsgType
  271. k.PAData = m.PAData
  272. k.PVNO = m.PVNO
  273. k.ReqBody = reqb
  274. return nil
  275. }
  276. // Unmarshal bytes b into the TGSReq struct.
  277. func (k *TGSReq) Unmarshal(b []byte) error {
  278. var m marshalKDCReq
  279. _, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.TGSREQ))
  280. if err != nil {
  281. return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling TGS_REQ")
  282. }
  283. expectedMsgType := msgtype.KRB_TGS_REQ
  284. if m.MsgType != expectedMsgType {
  285. return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a TGS_REQ. Expected: %v; Actual: %v", expectedMsgType, m.MsgType)
  286. }
  287. var reqb KDCReqBody
  288. err = reqb.Unmarshal(m.ReqBody.Bytes)
  289. if err != nil {
  290. return krberror.Errorf(err, krberror.EncodingError, "error processing TGS_REQ body")
  291. }
  292. k.MsgType = m.MsgType
  293. k.PAData = m.PAData
  294. k.PVNO = m.PVNO
  295. k.ReqBody = reqb
  296. return nil
  297. }
  298. // Unmarshal bytes b into the KRB_KDC_REQ body struct.
  299. func (k *KDCReqBody) Unmarshal(b []byte) error {
  300. var m marshalKDCReqBody
  301. _, err := asn1.Unmarshal(b, &m)
  302. if err != nil {
  303. return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling KDC_REQ body")
  304. }
  305. k.KDCOptions = m.KDCOptions
  306. if len(k.KDCOptions.Bytes) < 4 {
  307. tb := make([]byte, 4-len(k.KDCOptions.Bytes))
  308. k.KDCOptions.Bytes = append(tb, k.KDCOptions.Bytes...)
  309. k.KDCOptions.BitLength = len(k.KDCOptions.Bytes) * 8
  310. }
  311. k.CName = m.CName
  312. k.Realm = m.Realm
  313. k.SName = m.SName
  314. k.From = m.From
  315. k.Till = m.Till
  316. k.RTime = m.RTime
  317. k.Nonce = m.Nonce
  318. k.EType = m.EType
  319. k.Addresses = m.Addresses
  320. k.EncAuthData = m.EncAuthData
  321. if len(m.AdditionalTickets.Bytes) > 0 {
  322. k.AdditionalTickets, err = unmarshalTicketsSequence(m.AdditionalTickets)
  323. if err != nil {
  324. return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling additional tickets")
  325. }
  326. }
  327. return nil
  328. }
  329. // Marshal ASReq struct.
  330. func (k *ASReq) Marshal() ([]byte, error) {
  331. m := marshalKDCReq{
  332. PVNO: k.PVNO,
  333. MsgType: k.MsgType,
  334. PAData: k.PAData,
  335. }
  336. b, err := k.ReqBody.Marshal()
  337. if err != nil {
  338. var mk []byte
  339. return mk, err
  340. }
  341. m.ReqBody = asn1.RawValue{
  342. Class: asn1.ClassContextSpecific,
  343. IsCompound: true,
  344. Tag: 4,
  345. Bytes: b,
  346. }
  347. mk, err := asn1.Marshal(m)
  348. if err != nil {
  349. return mk, krberror.Errorf(err, krberror.EncodingError, "error marshaling AS_REQ")
  350. }
  351. mk = asn1tools.AddASNAppTag(mk, asnAppTag.ASREQ)
  352. return mk, nil
  353. }
  354. // Marshal TGSReq struct.
  355. func (k *TGSReq) Marshal() ([]byte, error) {
  356. m := marshalKDCReq{
  357. PVNO: k.PVNO,
  358. MsgType: k.MsgType,
  359. PAData: k.PAData,
  360. }
  361. b, err := k.ReqBody.Marshal()
  362. if err != nil {
  363. var mk []byte
  364. return mk, err
  365. }
  366. m.ReqBody = asn1.RawValue{
  367. Class: asn1.ClassContextSpecific,
  368. IsCompound: true,
  369. Tag: 4,
  370. Bytes: b,
  371. }
  372. mk, err := asn1.Marshal(m)
  373. if err != nil {
  374. return mk, krberror.Errorf(err, krberror.EncodingError, "error marshaling AS_REQ")
  375. }
  376. mk = asn1tools.AddASNAppTag(mk, asnAppTag.TGSREQ)
  377. return mk, nil
  378. }
  379. // Marshal KRB_KDC_REQ body struct.
  380. func (k *KDCReqBody) Marshal() ([]byte, error) {
  381. var b []byte
  382. m := marshalKDCReqBody{
  383. KDCOptions: k.KDCOptions,
  384. CName: k.CName,
  385. Realm: k.Realm,
  386. SName: k.SName,
  387. From: k.From,
  388. Till: k.Till,
  389. RTime: k.RTime,
  390. Nonce: k.Nonce,
  391. EType: k.EType,
  392. Addresses: k.Addresses,
  393. EncAuthData: k.EncAuthData,
  394. }
  395. rawtkts, err := MarshalTicketSequence(k.AdditionalTickets)
  396. if err != nil {
  397. return b, krberror.Errorf(err, krberror.EncodingError, "error in marshaling KDC request body additional tickets")
  398. }
  399. //The asn1.rawValue needs the tag setting on it for where it is in the KDCReqBody
  400. rawtkts.Tag = 11
  401. if len(rawtkts.Bytes) > 0 {
  402. m.AdditionalTickets = rawtkts
  403. }
  404. b, err = asn1.Marshal(m)
  405. if err != nil {
  406. return b, krberror.Errorf(err, krberror.EncodingError, "error in marshaling KDC request body")
  407. }
  408. return b, nil
  409. }