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