Authenticator.go 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100
  1. // Package types provides Kerberos 5 data types.
  2. package types
  3. import (
  4. "crypto/rand"
  5. "fmt"
  6. "math"
  7. "math/big"
  8. "time"
  9. "github.com/jcmturner/gofork/encoding/asn1"
  10. "gopkg.in/jcmturner/gokrb5.v7/asn1tools"
  11. "gopkg.in/jcmturner/gokrb5.v7/iana"
  12. "gopkg.in/jcmturner/gokrb5.v7/iana/asnAppTag"
  13. )
  14. /*Authenticator ::= [APPLICATION 2] SEQUENCE {
  15. authenticator-vno [0] INTEGER (5),
  16. crealm [1] Realm,
  17. cname [2] PrincipalName,
  18. cksum [3] Checksum OPTIONAL,
  19. cusec [4] Microseconds,
  20. ctime [5] KerberosTime,
  21. subkey [6] EncryptionKey OPTIONAL,
  22. seq-number [7] UInt32 OPTIONAL,
  23. authorization-data [8] AuthorizationData OPTIONAL
  24. }
  25. cksum
  26. This field contains a checksum of the application data that
  27. accompanies the KRB_AP_REQ, computed using a key usage value of 10
  28. in normal application exchanges, or 6 when used in the TGS-REQ
  29. PA-TGS-REQ AP-DATA field.
  30. */
  31. // Authenticator - A record containing information that can be shown to have been recently generated using the session key known only by the client and server.
  32. // https://tools.ietf.org/html/rfc4120#section-5.5.1
  33. type Authenticator struct {
  34. AVNO int `asn1:"explicit,tag:0"`
  35. CRealm string `asn1:"generalstring,explicit,tag:1"`
  36. CName PrincipalName `asn1:"explicit,tag:2"`
  37. Cksum Checksum `asn1:"explicit,optional,tag:3"`
  38. Cusec int `asn1:"explicit,tag:4"`
  39. CTime time.Time `asn1:"generalized,explicit,tag:5"`
  40. SubKey EncryptionKey `asn1:"explicit,optional,tag:6"`
  41. SeqNumber int64 `asn1:"explicit,optional,tag:7"`
  42. AuthorizationData AuthorizationData `asn1:"explicit,optional,tag:8"`
  43. }
  44. // NewAuthenticator creates a new Authenticator.
  45. func NewAuthenticator(realm string, cname PrincipalName) (Authenticator, error) {
  46. seq, err := rand.Int(rand.Reader, big.NewInt(math.MaxUint32))
  47. if err != nil {
  48. return Authenticator{}, err
  49. }
  50. t := time.Now().UTC()
  51. return Authenticator{
  52. AVNO: iana.PVNO,
  53. CRealm: realm,
  54. CName: cname,
  55. Cksum: Checksum{},
  56. Cusec: int((t.UnixNano() / int64(time.Microsecond)) - (t.Unix() * 1e6)),
  57. CTime: t,
  58. SeqNumber: seq.Int64(),
  59. }, nil
  60. }
  61. // GenerateSeqNumberAndSubKey sets the Authenticator's sequence number and subkey.
  62. func (a *Authenticator) GenerateSeqNumberAndSubKey(keyType int32, keySize int) error {
  63. seq, err := rand.Int(rand.Reader, big.NewInt(math.MaxUint32))
  64. if err != nil {
  65. return err
  66. }
  67. a.SeqNumber = seq.Int64()
  68. //Generate subkey value
  69. sk := make([]byte, keySize, keySize)
  70. rand.Read(sk)
  71. a.SubKey = EncryptionKey{
  72. KeyType: keyType,
  73. KeyValue: sk,
  74. }
  75. return nil
  76. }
  77. // Unmarshal bytes into the Authenticator.
  78. func (a *Authenticator) Unmarshal(b []byte) error {
  79. _, err := asn1.UnmarshalWithParams(b, a, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.Authenticator))
  80. return err
  81. }
  82. // Marshal the Authenticator.
  83. func (a *Authenticator) Marshal() ([]byte, error) {
  84. b, err := asn1.Marshal(*a)
  85. if err != nil {
  86. return nil, err
  87. }
  88. b = asn1tools.AddASNAppTag(b, asnAppTag.Authenticator)
  89. return b, nil
  90. }