1package types
2
3// Reference: https://www.ietf.org/rfc/rfc4120.txt
4// Section: 5.2.7
5import (
6	"fmt"
7	"time"
8
9	"github.com/jcmturner/gofork/encoding/asn1"
10	"gopkg.in/jcmturner/gokrb5.v7/iana/patype"
11)
12
13// PAData implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.2.7
14type PAData struct {
15	PADataType  int32  `asn1:"explicit,tag:1"`
16	PADataValue []byte `asn1:"explicit,tag:2"`
17}
18
19// PADataSequence implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.2.7
20type PADataSequence []PAData
21
22// MethodData implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.9.1
23type MethodData []PAData
24
25// PAEncTimestamp implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.2.7.2
26type PAEncTimestamp EncryptedData
27
28// PAEncTSEnc implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.2.7.2
29type PAEncTSEnc struct {
30	PATimestamp time.Time `asn1:"generalized,explicit,tag:0"`
31	PAUSec      int       `asn1:"explicit,optional,tag:1"`
32}
33
34// Contains tests if a PADataSequence contains PA Data of a certain type.
35func (pas *PADataSequence) Contains(patype int32) bool {
36	for _, pa := range *pas {
37		if pa.PADataType == patype {
38			return true
39		}
40	}
41	return false
42}
43
44// GetPAEncTSEncAsnMarshalled returns the bytes of a PAEncTSEnc.
45func GetPAEncTSEncAsnMarshalled() ([]byte, error) {
46	t := time.Now().UTC()
47	p := PAEncTSEnc{
48		PATimestamp: t,
49		PAUSec:      int((t.UnixNano() / int64(time.Microsecond)) - (t.Unix() * 1e6)),
50	}
51	b, err := asn1.Marshal(p)
52	if err != nil {
53		return b, fmt.Errorf("error mashaling PAEncTSEnc: %v", err)
54	}
55	return b, nil
56}
57
58// ETypeInfoEntry implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.2.7.4
59type ETypeInfoEntry struct {
60	EType int32  `asn1:"explicit,tag:0"`
61	Salt  []byte `asn1:"explicit,optional,tag:1"`
62}
63
64// ETypeInfo implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.2.7.4
65type ETypeInfo []ETypeInfoEntry
66
67// ETypeInfo2Entry implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.2.7.5
68type ETypeInfo2Entry struct {
69	EType     int32  `asn1:"explicit,tag:0"`
70	Salt      string `asn1:"explicit,optional,generalstring,tag:1"`
71	S2KParams []byte `asn1:"explicit,optional,tag:2"`
72}
73
74// ETypeInfo2 implements RFC 4120 types: https://tools.ietf.org/html/rfc4120#section-5.2.7.5
75type ETypeInfo2 []ETypeInfo2Entry
76
77// PAReqEncPARep PA Data Type
78type PAReqEncPARep struct {
79	ChksumType int32  `asn1:"explicit,tag:0"`
80	Chksum     []byte `asn1:"explicit,tag:1"`
81}
82
83// Unmarshal bytes into the PAData
84func (pa *PAData) Unmarshal(b []byte) error {
85	_, err := asn1.Unmarshal(b, pa)
86	return err
87}
88
89// Unmarshal bytes into the PADataSequence
90func (pas *PADataSequence) Unmarshal(b []byte) error {
91	_, err := asn1.Unmarshal(b, pas)
92	return err
93}
94
95// Unmarshal bytes into the PAReqEncPARep
96func (pa *PAReqEncPARep) Unmarshal(b []byte) error {
97	_, err := asn1.Unmarshal(b, pa)
98	return err
99}
100
101// Unmarshal bytes into the PAEncTimestamp
102func (pa *PAEncTimestamp) Unmarshal(b []byte) error {
103	_, err := asn1.Unmarshal(b, pa)
104	return err
105}
106
107// Unmarshal bytes into the PAEncTSEnc
108func (pa *PAEncTSEnc) Unmarshal(b []byte) error {
109	_, err := asn1.Unmarshal(b, pa)
110	return err
111}
112
113// Unmarshal bytes into the ETypeInfo
114func (a *ETypeInfo) Unmarshal(b []byte) error {
115	_, err := asn1.Unmarshal(b, a)
116	return err
117}
118
119// Unmarshal bytes into the ETypeInfoEntry
120func (a *ETypeInfoEntry) Unmarshal(b []byte) error {
121	_, err := asn1.Unmarshal(b, a)
122	return err
123}
124
125// Unmarshal bytes into the ETypeInfo2
126func (a *ETypeInfo2) Unmarshal(b []byte) error {
127	_, err := asn1.Unmarshal(b, a)
128	return err
129}
130
131// Unmarshal bytes into the ETypeInfo2Entry
132func (a *ETypeInfo2Entry) Unmarshal(b []byte) error {
133	_, err := asn1.Unmarshal(b, a)
134	return err
135}
136
137// GetETypeInfo returns an ETypeInfo from the PAData.
138func (pa *PAData) GetETypeInfo() (d ETypeInfo, err error) {
139	if pa.PADataType != patype.PA_ETYPE_INFO {
140		err = fmt.Errorf("PAData does not contain PA EType Info data. TypeID Expected: %v; Actual: %v", patype.PA_ETYPE_INFO, pa.PADataType)
141		return
142	}
143	_, err = asn1.Unmarshal(pa.PADataValue, &d)
144	return
145}
146
147// GetETypeInfo2 returns an ETypeInfo2 from the PAData.
148func (pa *PAData) GetETypeInfo2() (d ETypeInfo2, err error) {
149	if pa.PADataType != patype.PA_ETYPE_INFO2 {
150		err = fmt.Errorf("PAData does not contain PA EType Info 2 data. TypeID Expected: %v; Actual: %v", patype.PA_ETYPE_INFO2, pa.PADataType)
151		return
152	}
153	_, err = asn1.Unmarshal(pa.PADataValue, &d)
154	return
155}
156