David K. Bainbridge | bd6b288 | 2021-08-26 13:31:02 +0000 | [diff] [blame] | 1 | // Package types provides Kerberos 5 data types. |
| 2 | package types |
| 3 | |
| 4 | import ( |
| 5 | "crypto/rand" |
| 6 | "fmt" |
| 7 | "math" |
| 8 | "math/big" |
| 9 | "time" |
| 10 | |
| 11 | "github.com/jcmturner/gofork/encoding/asn1" |
| 12 | "github.com/jcmturner/gokrb5/v8/asn1tools" |
| 13 | "github.com/jcmturner/gokrb5/v8/iana" |
| 14 | "github.com/jcmturner/gokrb5/v8/iana/asnAppTag" |
| 15 | ) |
| 16 | |
| 17 | // Authenticator - A record containing information that can be shown to have been recently generated using the session |
| 18 | // key known only by the client and server. |
| 19 | // https://tools.ietf.org/html/rfc4120#section-5.5.1 |
| 20 | type Authenticator struct { |
| 21 | AVNO int `asn1:"explicit,tag:0"` |
| 22 | CRealm string `asn1:"generalstring,explicit,tag:1"` |
| 23 | CName PrincipalName `asn1:"explicit,tag:2"` |
| 24 | Cksum Checksum `asn1:"explicit,optional,tag:3"` |
| 25 | Cusec int `asn1:"explicit,tag:4"` |
| 26 | CTime time.Time `asn1:"generalized,explicit,tag:5"` |
| 27 | SubKey EncryptionKey `asn1:"explicit,optional,tag:6"` |
| 28 | SeqNumber int64 `asn1:"explicit,optional,tag:7"` |
| 29 | AuthorizationData AuthorizationData `asn1:"explicit,optional,tag:8"` |
| 30 | } |
| 31 | |
| 32 | // NewAuthenticator creates a new Authenticator. |
| 33 | func NewAuthenticator(realm string, cname PrincipalName) (Authenticator, error) { |
| 34 | seq, err := rand.Int(rand.Reader, big.NewInt(math.MaxUint32)) |
| 35 | if err != nil { |
| 36 | return Authenticator{}, err |
| 37 | } |
| 38 | t := time.Now().UTC() |
| 39 | return Authenticator{ |
| 40 | AVNO: iana.PVNO, |
| 41 | CRealm: realm, |
| 42 | CName: cname, |
| 43 | Cksum: Checksum{}, |
| 44 | Cusec: int((t.UnixNano() / int64(time.Microsecond)) - (t.Unix() * 1e6)), |
| 45 | CTime: t, |
| 46 | SeqNumber: seq.Int64(), |
| 47 | }, nil |
| 48 | } |
| 49 | |
| 50 | // GenerateSeqNumberAndSubKey sets the Authenticator's sequence number and subkey. |
| 51 | func (a *Authenticator) GenerateSeqNumberAndSubKey(keyType int32, keySize int) error { |
| 52 | seq, err := rand.Int(rand.Reader, big.NewInt(math.MaxUint32)) |
| 53 | if err != nil { |
| 54 | return err |
| 55 | } |
| 56 | a.SeqNumber = seq.Int64() |
| 57 | //Generate subkey value |
| 58 | sk := make([]byte, keySize, keySize) |
| 59 | rand.Read(sk) |
| 60 | a.SubKey = EncryptionKey{ |
| 61 | KeyType: keyType, |
| 62 | KeyValue: sk, |
| 63 | } |
| 64 | return nil |
| 65 | } |
| 66 | |
| 67 | // Unmarshal bytes into the Authenticator. |
| 68 | func (a *Authenticator) Unmarshal(b []byte) error { |
| 69 | _, err := asn1.UnmarshalWithParams(b, a, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.Authenticator)) |
| 70 | return err |
| 71 | } |
| 72 | |
| 73 | // Marshal the Authenticator. |
| 74 | func (a *Authenticator) Marshal() ([]byte, error) { |
| 75 | b, err := asn1.Marshal(*a) |
| 76 | if err != nil { |
| 77 | return nil, err |
| 78 | } |
| 79 | b = asn1tools.AddASNAppTag(b, asnAppTag.Authenticator) |
| 80 | return b, nil |
| 81 | } |