Abhilash S.L | 3b49463 | 2019-07-16 15:51:09 +0530 | [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 | "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 { |
| 18 | authenticator-vno [0] INTEGER (5), |
| 19 | crealm [1] Realm, |
| 20 | cname [2] PrincipalName, |
| 21 | cksum [3] Checksum OPTIONAL, |
| 22 | cusec [4] Microseconds, |
| 23 | ctime [5] KerberosTime, |
| 24 | subkey [6] EncryptionKey OPTIONAL, |
| 25 | seq-number [7] UInt32 OPTIONAL, |
| 26 | authorization-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 |
| 39 | type 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. |
| 52 | func 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. |
| 70 | func (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. |
| 87 | func (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. |
| 93 | func (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 | } |