Update module lib/pq to v1.6.0 (#572)
Update module lib/pq to v1.6.0 Reviewed-on: https://kolaente.dev/vikunja/api/pulls/572
This commit is contained in:
49
vendor/github.com/jcmturner/gokrb5/v8/messages/APRep.go
generated
vendored
Normal file
49
vendor/github.com/jcmturner/gokrb5/v8/messages/APRep.go
generated
vendored
Normal file
@ -0,0 +1,49 @@
|
||||
package messages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/msgtype"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
// APRep implements RFC 4120 KRB_AP_REP: https://tools.ietf.org/html/rfc4120#section-5.5.2.
|
||||
type APRep struct {
|
||||
PVNO int `asn1:"explicit,tag:0"`
|
||||
MsgType int `asn1:"explicit,tag:1"`
|
||||
EncPart types.EncryptedData `asn1:"explicit,tag:2"`
|
||||
}
|
||||
|
||||
// EncAPRepPart is the encrypted part of KRB_AP_REP.
|
||||
type EncAPRepPart struct {
|
||||
CTime time.Time `asn1:"generalized,explicit,tag:0"`
|
||||
Cusec int `asn1:"explicit,tag:1"`
|
||||
Subkey types.EncryptionKey `asn1:"optional,explicit,tag:2"`
|
||||
SequenceNumber int64 `asn1:"optional,explicit,tag:3"`
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the APRep struct.
|
||||
func (a *APRep) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, a, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.APREP))
|
||||
if err != nil {
|
||||
return processUnmarshalReplyError(b, err)
|
||||
}
|
||||
expectedMsgType := msgtype.KRB_AP_REP
|
||||
if a.MsgType != expectedMsgType {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a KRB_AP_REP. Expected: %v; Actual: %v", expectedMsgType, a.MsgType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the APRep encrypted part struct.
|
||||
func (a *EncAPRepPart) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, a, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncAPRepPart))
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "AP_REP unmarshal error")
|
||||
}
|
||||
return nil
|
||||
}
|
199
vendor/github.com/jcmturner/gokrb5/v8/messages/APReq.go
generated
vendored
Normal file
199
vendor/github.com/jcmturner/gokrb5/v8/messages/APReq.go
generated
vendored
Normal file
@ -0,0 +1,199 @@
|
||||
package messages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/asn1tools"
|
||||
"github.com/jcmturner/gokrb5/v8/crypto"
|
||||
"github.com/jcmturner/gokrb5/v8/iana"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/keyusage"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/msgtype"
|
||||
"github.com/jcmturner/gokrb5/v8/keytab"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
type marshalAPReq struct {
|
||||
PVNO int `asn1:"explicit,tag:0"`
|
||||
MsgType int `asn1:"explicit,tag:1"`
|
||||
APOptions asn1.BitString `asn1:"explicit,tag:2"`
|
||||
// Ticket needs to be a raw value as it is wrapped in an APPLICATION tag
|
||||
Ticket asn1.RawValue `asn1:"explicit,tag:3"`
|
||||
EncryptedAuthenticator types.EncryptedData `asn1:"explicit,tag:4"`
|
||||
}
|
||||
|
||||
// APReq implements RFC 4120 KRB_AP_REQ: https://tools.ietf.org/html/rfc4120#section-5.5.1.
|
||||
type APReq struct {
|
||||
PVNO int `asn1:"explicit,tag:0"`
|
||||
MsgType int `asn1:"explicit,tag:1"`
|
||||
APOptions asn1.BitString `asn1:"explicit,tag:2"`
|
||||
Ticket Ticket `asn1:"explicit,tag:3"`
|
||||
EncryptedAuthenticator types.EncryptedData `asn1:"explicit,tag:4"`
|
||||
Authenticator types.Authenticator `asn1:"optional"`
|
||||
}
|
||||
|
||||
// NewAPReq generates a new KRB_AP_REQ struct.
|
||||
func NewAPReq(tkt Ticket, sessionKey types.EncryptionKey, auth types.Authenticator) (APReq, error) {
|
||||
var a APReq
|
||||
ed, err := encryptAuthenticator(auth, sessionKey, tkt)
|
||||
if err != nil {
|
||||
return a, krberror.Errorf(err, krberror.KRBMsgError, "error creating Authenticator for AP_REQ")
|
||||
}
|
||||
a = APReq{
|
||||
PVNO: iana.PVNO,
|
||||
MsgType: msgtype.KRB_AP_REQ,
|
||||
APOptions: types.NewKrbFlags(),
|
||||
Ticket: tkt,
|
||||
EncryptedAuthenticator: ed,
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// Encrypt Authenticator
|
||||
func encryptAuthenticator(a types.Authenticator, sessionKey types.EncryptionKey, tkt Ticket) (types.EncryptedData, error) {
|
||||
var ed types.EncryptedData
|
||||
m, err := a.Marshal()
|
||||
if err != nil {
|
||||
return ed, krberror.Errorf(err, krberror.EncodingError, "marshaling error of EncryptedData form of Authenticator")
|
||||
}
|
||||
usage := authenticatorKeyUsage(tkt.SName)
|
||||
ed, err = crypto.GetEncryptedData(m, sessionKey, uint32(usage), tkt.EncPart.KVNO)
|
||||
if err != nil {
|
||||
return ed, krberror.Errorf(err, krberror.EncryptingError, "error encrypting Authenticator")
|
||||
}
|
||||
return ed, nil
|
||||
}
|
||||
|
||||
// DecryptAuthenticator decrypts the Authenticator within the AP_REQ.
|
||||
// sessionKey may simply be the key within the decrypted EncPart of the ticket within the AP_REQ.
|
||||
func (a *APReq) DecryptAuthenticator(sessionKey types.EncryptionKey) error {
|
||||
usage := authenticatorKeyUsage(a.Ticket.SName)
|
||||
ab, e := crypto.DecryptEncPart(a.EncryptedAuthenticator, sessionKey, uint32(usage))
|
||||
if e != nil {
|
||||
return fmt.Errorf("error decrypting authenticator: %v", e)
|
||||
}
|
||||
err := a.Authenticator.Unmarshal(ab)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unmarshaling authenticator: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func authenticatorKeyUsage(pn types.PrincipalName) int {
|
||||
if pn.NameString[0] == "krbtgt" {
|
||||
return keyusage.TGS_REQ_PA_TGS_REQ_AP_REQ_AUTHENTICATOR
|
||||
}
|
||||
return keyusage.AP_REQ_AUTHENTICATOR
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the APReq struct.
|
||||
func (a *APReq) Unmarshal(b []byte) error {
|
||||
var m marshalAPReq
|
||||
_, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.APREQ))
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "unmarshal error of AP_REQ")
|
||||
}
|
||||
if m.MsgType != msgtype.KRB_AP_REQ {
|
||||
return NewKRBError(types.PrincipalName{}, "", errorcode.KRB_AP_ERR_MSG_TYPE, errorcode.Lookup(errorcode.KRB_AP_ERR_MSG_TYPE))
|
||||
}
|
||||
a.PVNO = m.PVNO
|
||||
a.MsgType = m.MsgType
|
||||
a.APOptions = m.APOptions
|
||||
a.EncryptedAuthenticator = m.EncryptedAuthenticator
|
||||
a.Ticket, err = unmarshalTicket(m.Ticket.Bytes)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "unmarshaling error of Ticket within AP_REQ")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal APReq struct.
|
||||
func (a *APReq) Marshal() ([]byte, error) {
|
||||
m := marshalAPReq{
|
||||
PVNO: a.PVNO,
|
||||
MsgType: a.MsgType,
|
||||
APOptions: a.APOptions,
|
||||
EncryptedAuthenticator: a.EncryptedAuthenticator,
|
||||
}
|
||||
var b []byte
|
||||
b, err := a.Ticket.Marshal()
|
||||
if err != nil {
|
||||
return b, err
|
||||
}
|
||||
m.Ticket = asn1.RawValue{
|
||||
Class: asn1.ClassContextSpecific,
|
||||
IsCompound: true,
|
||||
Tag: 3,
|
||||
Bytes: b,
|
||||
}
|
||||
mk, err := asn1.Marshal(m)
|
||||
if err != nil {
|
||||
return mk, krberror.Errorf(err, krberror.EncodingError, "marshaling error of AP_REQ")
|
||||
}
|
||||
mk = asn1tools.AddASNAppTag(mk, asnAppTag.APREQ)
|
||||
return mk, nil
|
||||
}
|
||||
|
||||
// Verify an AP_REQ using service's keytab, spn and max acceptable clock skew duration.
|
||||
// The service ticket encrypted part and authenticator will be decrypted as part of this operation.
|
||||
func (a *APReq) Verify(kt *keytab.Keytab, d time.Duration, cAddr types.HostAddress, snameOverride *types.PrincipalName) (bool, error) {
|
||||
// Decrypt ticket's encrypted part with service key
|
||||
//TODO decrypt with service's session key from its TGT is use-to-user. Need to figure out how to get TGT.
|
||||
//if types.IsFlagSet(&a.APOptions, flags.APOptionUseSessionKey) {
|
||||
// err := a.Ticket.Decrypt(tgt.DecryptedEncPart.Key)
|
||||
// if err != nil {
|
||||
// return false, krberror.Errorf(err, krberror.DecryptingError, "error decrypting encpart of ticket provided using session key")
|
||||
// }
|
||||
//} else {
|
||||
// err := a.Ticket.DecryptEncPart(*kt, &a.Ticket.SName)
|
||||
// if err != nil {
|
||||
// return false, krberror.Errorf(err, krberror.DecryptingError, "error decrypting encpart of service ticket provided")
|
||||
// }
|
||||
//}
|
||||
sname := &a.Ticket.SName
|
||||
if snameOverride != nil {
|
||||
sname = snameOverride
|
||||
}
|
||||
err := a.Ticket.DecryptEncPart(kt, sname)
|
||||
if err != nil {
|
||||
return false, krberror.Errorf(err, krberror.DecryptingError, "error decrypting encpart of service ticket provided")
|
||||
}
|
||||
|
||||
// Check time validity of ticket
|
||||
ok, err := a.Ticket.Valid(d)
|
||||
if err != nil || !ok {
|
||||
return ok, err
|
||||
}
|
||||
|
||||
// Check client's address is listed in the client addresses in the ticket
|
||||
if len(a.Ticket.DecryptedEncPart.CAddr) > 0 {
|
||||
//If client addresses are present check if any of them match the source IP that sent the APReq
|
||||
//If there is no match return KRB_AP_ERR_BADADDR error.
|
||||
if !types.HostAddressesContains(a.Ticket.DecryptedEncPart.CAddr, cAddr) {
|
||||
return false, NewKRBError(a.Ticket.SName, a.Ticket.Realm, errorcode.KRB_AP_ERR_BADADDR, "client address not within the list contained in the service ticket")
|
||||
}
|
||||
}
|
||||
|
||||
// Decrypt authenticator with session key from ticket's encrypted part
|
||||
err = a.DecryptAuthenticator(a.Ticket.DecryptedEncPart.Key)
|
||||
if err != nil {
|
||||
return false, NewKRBError(a.Ticket.SName, a.Ticket.Realm, errorcode.KRB_AP_ERR_BAD_INTEGRITY, "could not decrypt authenticator")
|
||||
}
|
||||
|
||||
// Check CName in authenticator is the same as that in the ticket
|
||||
if !a.Authenticator.CName.Equal(a.Ticket.DecryptedEncPart.CName) {
|
||||
return false, NewKRBError(a.Ticket.SName, a.Ticket.Realm, errorcode.KRB_AP_ERR_BADMATCH, "CName in Authenticator does not match that in service ticket")
|
||||
}
|
||||
|
||||
// Check the clock skew between the client and the service server
|
||||
ct := a.Authenticator.CTime.Add(time.Duration(a.Authenticator.Cusec) * time.Microsecond)
|
||||
t := time.Now().UTC()
|
||||
if t.Sub(ct) > d || ct.Sub(t) > d {
|
||||
return false, NewKRBError(a.Ticket.SName, a.Ticket.Realm, errorcode.KRB_AP_ERR_SKEW, fmt.Sprintf("clock skew with client too large. greater than %v seconds", d))
|
||||
}
|
||||
return true, nil
|
||||
}
|
308
vendor/github.com/jcmturner/gokrb5/v8/messages/KDCRep.go
generated
vendored
Normal file
308
vendor/github.com/jcmturner/gokrb5/v8/messages/KDCRep.go
generated
vendored
Normal file
@ -0,0 +1,308 @@
|
||||
package messages
|
||||
|
||||
// Reference: https://www.ietf.org/rfc/rfc4120.txt
|
||||
// Section: 5.4.2
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/config"
|
||||
"github.com/jcmturner/gokrb5/v8/credentials"
|
||||
"github.com/jcmturner/gokrb5/v8/crypto"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/flags"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/keyusage"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/msgtype"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/patype"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
type marshalKDCRep struct {
|
||||
PVNO int `asn1:"explicit,tag:0"`
|
||||
MsgType int `asn1:"explicit,tag:1"`
|
||||
PAData types.PADataSequence `asn1:"explicit,optional,tag:2"`
|
||||
CRealm string `asn1:"generalstring,explicit,tag:3"`
|
||||
CName types.PrincipalName `asn1:"explicit,tag:4"`
|
||||
// Ticket needs to be a raw value as it is wrapped in an APPLICATION tag
|
||||
Ticket asn1.RawValue `asn1:"explicit,tag:5"`
|
||||
EncPart types.EncryptedData `asn1:"explicit,tag:6"`
|
||||
}
|
||||
|
||||
// KDCRepFields represents the KRB_KDC_REP fields.
|
||||
type KDCRepFields struct {
|
||||
PVNO int
|
||||
MsgType int
|
||||
PAData []types.PAData
|
||||
CRealm string
|
||||
CName types.PrincipalName
|
||||
Ticket Ticket
|
||||
EncPart types.EncryptedData
|
||||
DecryptedEncPart EncKDCRepPart
|
||||
}
|
||||
|
||||
// ASRep implements RFC 4120 KRB_AS_REP: https://tools.ietf.org/html/rfc4120#section-5.4.2.
|
||||
type ASRep struct {
|
||||
KDCRepFields
|
||||
}
|
||||
|
||||
// TGSRep implements RFC 4120 KRB_TGS_REP: https://tools.ietf.org/html/rfc4120#section-5.4.2.
|
||||
type TGSRep struct {
|
||||
KDCRepFields
|
||||
}
|
||||
|
||||
// EncKDCRepPart is the encrypted part of KRB_KDC_REP.
|
||||
type EncKDCRepPart struct {
|
||||
Key types.EncryptionKey `asn1:"explicit,tag:0"`
|
||||
LastReqs []LastReq `asn1:"explicit,tag:1"`
|
||||
Nonce int `asn1:"explicit,tag:2"`
|
||||
KeyExpiration time.Time `asn1:"generalized,explicit,optional,tag:3"`
|
||||
Flags asn1.BitString `asn1:"explicit,tag:4"`
|
||||
AuthTime time.Time `asn1:"generalized,explicit,tag:5"`
|
||||
StartTime time.Time `asn1:"generalized,explicit,optional,tag:6"`
|
||||
EndTime time.Time `asn1:"generalized,explicit,tag:7"`
|
||||
RenewTill time.Time `asn1:"generalized,explicit,optional,tag:8"`
|
||||
SRealm string `asn1:"generalstring,explicit,tag:9"`
|
||||
SName types.PrincipalName `asn1:"explicit,tag:10"`
|
||||
CAddr []types.HostAddress `asn1:"explicit,optional,tag:11"`
|
||||
EncPAData types.PADataSequence `asn1:"explicit,optional,tag:12"`
|
||||
}
|
||||
|
||||
// LastReq part of KRB_KDC_REP.
|
||||
type LastReq struct {
|
||||
LRType int32 `asn1:"explicit,tag:0"`
|
||||
LRValue time.Time `asn1:"generalized,explicit,tag:1"`
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the ASRep struct.
|
||||
func (k *ASRep) Unmarshal(b []byte) error {
|
||||
var m marshalKDCRep
|
||||
_, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.ASREP))
|
||||
if err != nil {
|
||||
return processUnmarshalReplyError(b, err)
|
||||
}
|
||||
if m.MsgType != msgtype.KRB_AS_REP {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate an AS_REP. Expected: %v; Actual: %v", msgtype.KRB_AS_REP, m.MsgType)
|
||||
}
|
||||
//Process the raw ticket within
|
||||
tkt, err := unmarshalTicket(m.Ticket.Bytes)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling Ticket within AS_REP")
|
||||
}
|
||||
k.KDCRepFields = KDCRepFields{
|
||||
PVNO: m.PVNO,
|
||||
MsgType: m.MsgType,
|
||||
PAData: m.PAData,
|
||||
CRealm: m.CRealm,
|
||||
CName: m.CName,
|
||||
Ticket: tkt,
|
||||
EncPart: m.EncPart,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the TGSRep struct.
|
||||
func (k *TGSRep) Unmarshal(b []byte) error {
|
||||
var m marshalKDCRep
|
||||
_, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.TGSREP))
|
||||
if err != nil {
|
||||
return processUnmarshalReplyError(b, err)
|
||||
}
|
||||
if m.MsgType != msgtype.KRB_TGS_REP {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate an TGS_REP. Expected: %v; Actual: %v", msgtype.KRB_TGS_REP, m.MsgType)
|
||||
}
|
||||
//Process the raw ticket within
|
||||
tkt, err := unmarshalTicket(m.Ticket.Bytes)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling Ticket within TGS_REP")
|
||||
}
|
||||
k.KDCRepFields = KDCRepFields{
|
||||
PVNO: m.PVNO,
|
||||
MsgType: m.MsgType,
|
||||
PAData: m.PAData,
|
||||
CRealm: m.CRealm,
|
||||
CName: m.CName,
|
||||
Ticket: tkt,
|
||||
EncPart: m.EncPart,
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into encrypted part of KRB_KDC_REP.
|
||||
func (e *EncKDCRepPart) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, e, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncASRepPart))
|
||||
if err != nil {
|
||||
// Try using tag 26
|
||||
// Ref: RFC 4120 - mentions that some implementations use application tag number 26 wether or not the reply is
|
||||
// a AS-REP or a TGS-REP.
|
||||
_, err = asn1.UnmarshalWithParams(b, e, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncTGSRepPart))
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling encrypted part within KDC_REP")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecryptEncPart decrypts the encrypted part of an AS_REP.
|
||||
func (k *ASRep) DecryptEncPart(c *credentials.Credentials) (types.EncryptionKey, error) {
|
||||
var key types.EncryptionKey
|
||||
var err error
|
||||
if c.HasKeytab() {
|
||||
key, _, err = c.Keytab().GetEncryptionKey(k.CName, k.CRealm, k.EncPart.KVNO, k.EncPart.EType)
|
||||
if err != nil {
|
||||
return key, krberror.Errorf(err, krberror.DecryptingError, "error decrypting AS_REP encrypted part")
|
||||
}
|
||||
}
|
||||
if c.HasPassword() {
|
||||
key, _, err = crypto.GetKeyFromPassword(c.Password(), k.CName, k.CRealm, k.EncPart.EType, k.PAData)
|
||||
if err != nil {
|
||||
return key, krberror.Errorf(err, krberror.DecryptingError, "error decrypting AS_REP encrypted part")
|
||||
}
|
||||
}
|
||||
if !c.HasKeytab() && !c.HasPassword() {
|
||||
return key, krberror.NewErrorf(krberror.DecryptingError, "no secret available in credentials to perform decryption of AS_REP encrypted part")
|
||||
}
|
||||
b, err := crypto.DecryptEncPart(k.EncPart, key, keyusage.AS_REP_ENCPART)
|
||||
if err != nil {
|
||||
return key, krberror.Errorf(err, krberror.DecryptingError, "error decrypting AS_REP encrypted part")
|
||||
}
|
||||
var denc EncKDCRepPart
|
||||
err = denc.Unmarshal(b)
|
||||
if err != nil {
|
||||
return key, krberror.Errorf(err, krberror.EncodingError, "error unmarshaling decrypted encpart of AS_REP")
|
||||
}
|
||||
k.DecryptedEncPart = denc
|
||||
return key, nil
|
||||
}
|
||||
|
||||
// Verify checks the validity of AS_REP message.
|
||||
func (k *ASRep) Verify(cfg *config.Config, creds *credentials.Credentials, asReq ASReq) (bool, error) {
|
||||
//Ref RFC 4120 Section 3.1.5
|
||||
if k.CName.NameType != asReq.ReqBody.CName.NameType || k.CName.NameString == nil {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "CName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.CName, k.CName)
|
||||
}
|
||||
for i := range k.CName.NameString {
|
||||
if k.CName.NameString[i] != asReq.ReqBody.CName.NameString[i] {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "CName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.CName, k.CName)
|
||||
}
|
||||
}
|
||||
if k.CRealm != asReq.ReqBody.Realm {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "CRealm in response does not match what was requested. Requested: %s; Reply: %s", asReq.ReqBody.Realm, k.CRealm)
|
||||
}
|
||||
key, err := k.DecryptEncPart(creds)
|
||||
if err != nil {
|
||||
return false, krberror.Errorf(err, krberror.DecryptingError, "error decrypting EncPart of AS_REP")
|
||||
}
|
||||
if k.DecryptedEncPart.Nonce != asReq.ReqBody.Nonce {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "possible replay attack, nonce in response does not match that in request")
|
||||
}
|
||||
if k.DecryptedEncPart.SName.NameType != asReq.ReqBody.SName.NameType || k.DecryptedEncPart.SName.NameString == nil {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "SName in response does not match what was requested. Requested: %v; Reply: %v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)
|
||||
}
|
||||
for i := range k.CName.NameString {
|
||||
if k.DecryptedEncPart.SName.NameString[i] != asReq.ReqBody.SName.NameString[i] {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "SName in response does not match what was requested. Requested: %+v; Reply: %+v", asReq.ReqBody.SName, k.DecryptedEncPart.SName)
|
||||
}
|
||||
}
|
||||
if k.DecryptedEncPart.SRealm != asReq.ReqBody.Realm {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "SRealm in response does not match what was requested. Requested: %s; Reply: %s", asReq.ReqBody.Realm, k.DecryptedEncPart.SRealm)
|
||||
}
|
||||
if len(asReq.ReqBody.Addresses) > 0 {
|
||||
if !types.HostAddressesEqual(k.DecryptedEncPart.CAddr, asReq.ReqBody.Addresses) {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "addresses listed in the AS_REP does not match those listed in the AS_REQ")
|
||||
}
|
||||
}
|
||||
t := time.Now().UTC()
|
||||
if t.Sub(k.DecryptedEncPart.AuthTime) > cfg.LibDefaults.Clockskew || k.DecryptedEncPart.AuthTime.Sub(t) > cfg.LibDefaults.Clockskew {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "clock skew with KDC too large. Greater than %v seconds", cfg.LibDefaults.Clockskew.Seconds())
|
||||
}
|
||||
// RFC 6806 https://tools.ietf.org/html/rfc6806.html#section-11
|
||||
if asReq.PAData.Contains(patype.PA_REQ_ENC_PA_REP) && types.IsFlagSet(&k.DecryptedEncPart.Flags, flags.EncPARep) {
|
||||
if len(k.DecryptedEncPart.EncPAData) < 2 || !k.DecryptedEncPart.EncPAData.Contains(patype.PA_FX_FAST) {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "KDC did not respond appropriately to FAST negotiation")
|
||||
}
|
||||
for _, pa := range k.DecryptedEncPart.EncPAData {
|
||||
if pa.PADataType == patype.PA_REQ_ENC_PA_REP {
|
||||
var pafast types.PAReqEncPARep
|
||||
err := pafast.Unmarshal(pa.PADataValue)
|
||||
if err != nil {
|
||||
return false, krberror.Errorf(err, krberror.EncodingError, "KDC FAST negotiation response error, could not unmarshal PA_REQ_ENC_PA_REP")
|
||||
}
|
||||
etype, err := crypto.GetChksumEtype(pafast.ChksumType)
|
||||
if err != nil {
|
||||
return false, krberror.Errorf(err, krberror.ChksumError, "KDC FAST negotiation response error")
|
||||
}
|
||||
ab, _ := asReq.Marshal()
|
||||
if !etype.VerifyChecksum(key.KeyValue, ab, pafast.Chksum, keyusage.KEY_USAGE_AS_REQ) {
|
||||
return false, krberror.Errorf(err, krberror.ChksumError, "KDC FAST negotiation response checksum invalid")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// DecryptEncPart decrypts the encrypted part of an TGS_REP.
|
||||
func (k *TGSRep) DecryptEncPart(key types.EncryptionKey) error {
|
||||
b, err := crypto.DecryptEncPart(k.EncPart, key, keyusage.TGS_REP_ENCPART_SESSION_KEY)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.DecryptingError, "error decrypting TGS_REP EncPart")
|
||||
}
|
||||
var denc EncKDCRepPart
|
||||
err = denc.Unmarshal(b)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling encrypted part")
|
||||
}
|
||||
k.DecryptedEncPart = denc
|
||||
return nil
|
||||
}
|
||||
|
||||
// Verify checks the validity of the TGS_REP message.
|
||||
func (k *TGSRep) Verify(cfg *config.Config, tgsReq TGSReq) (bool, error) {
|
||||
if k.CName.NameType != tgsReq.ReqBody.CName.NameType || k.CName.NameString == nil {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "CName type in response does not match what was requested. Requested: %+v; Reply: %+v", tgsReq.ReqBody.CName, k.CName)
|
||||
}
|
||||
for i := range k.CName.NameString {
|
||||
if k.CName.NameString[i] != tgsReq.ReqBody.CName.NameString[i] {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "CName in response does not match what was requested. Requested: %+v; Reply: %+v", tgsReq.ReqBody.CName, k.CName)
|
||||
}
|
||||
}
|
||||
if k.Ticket.Realm != tgsReq.ReqBody.Realm {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "realm in response ticket does not match what was requested. Requested: %s; Reply: %s", tgsReq.ReqBody.Realm, k.Ticket.Realm)
|
||||
}
|
||||
if k.DecryptedEncPart.Nonce != tgsReq.ReqBody.Nonce {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "possible replay attack, nonce in response does not match that in request")
|
||||
}
|
||||
//if k.Ticket.SName.NameType != tgsReq.ReqBody.SName.NameType || k.Ticket.SName.NameString == nil {
|
||||
// return false, krberror.NewErrorf(krberror.KRBMsgError, "SName in response ticket does not match what was requested. Requested: %v; Reply: %v", tgsReq.ReqBody.SName, k.Ticket.SName)
|
||||
//}
|
||||
//for i := range k.Ticket.SName.NameString {
|
||||
// if k.Ticket.SName.NameString[i] != tgsReq.ReqBody.SName.NameString[i] {
|
||||
// return false, krberror.NewErrorf(krberror.KRBMsgError, "SName in response ticket does not match what was requested. Requested: %+v; Reply: %+v", tgsReq.ReqBody.SName, k.Ticket.SName)
|
||||
// }
|
||||
//}
|
||||
//if k.DecryptedEncPart.SName.NameType != tgsReq.ReqBody.SName.NameType || k.DecryptedEncPart.SName.NameString == nil {
|
||||
// return false, krberror.NewErrorf(krberror.KRBMsgError, "SName in response does not match what was requested. Requested: %v; Reply: %v", tgsReq.ReqBody.SName, k.DecryptedEncPart.SName)
|
||||
//}
|
||||
//for i := range k.DecryptedEncPart.SName.NameString {
|
||||
// if k.DecryptedEncPart.SName.NameString[i] != tgsReq.ReqBody.SName.NameString[i] {
|
||||
// return false, krberror.NewErrorf(krberror.KRBMsgError, "SName in response does not match what was requested. Requested: %+v; Reply: %+v", tgsReq.ReqBody.SName, k.DecryptedEncPart.SName)
|
||||
// }
|
||||
//}
|
||||
if k.DecryptedEncPart.SRealm != tgsReq.ReqBody.Realm {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "SRealm in response does not match what was requested. Requested: %s; Reply: %s", tgsReq.ReqBody.Realm, k.DecryptedEncPart.SRealm)
|
||||
}
|
||||
if len(k.DecryptedEncPart.CAddr) > 0 {
|
||||
if !types.HostAddressesEqual(k.DecryptedEncPart.CAddr, tgsReq.ReqBody.Addresses) {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "addresses listed in the TGS_REP does not match those listed in the TGS_REQ")
|
||||
}
|
||||
}
|
||||
if time.Since(k.DecryptedEncPart.StartTime) > cfg.LibDefaults.Clockskew || k.DecryptedEncPart.StartTime.Sub(time.Now().UTC()) > cfg.LibDefaults.Clockskew {
|
||||
if time.Since(k.DecryptedEncPart.AuthTime) > cfg.LibDefaults.Clockskew || k.DecryptedEncPart.AuthTime.Sub(time.Now().UTC()) > cfg.LibDefaults.Clockskew {
|
||||
return false, krberror.NewErrorf(krberror.KRBMsgError, "clock skew with KDC too large. Greater than %v seconds.", cfg.LibDefaults.Clockskew.Seconds())
|
||||
}
|
||||
}
|
||||
return true, nil
|
||||
}
|
432
vendor/github.com/jcmturner/gokrb5/v8/messages/KDCReq.go
generated
vendored
Normal file
432
vendor/github.com/jcmturner/gokrb5/v8/messages/KDCReq.go
generated
vendored
Normal file
@ -0,0 +1,432 @@
|
||||
package messages
|
||||
|
||||
// Reference: https://www.ietf.org/rfc/rfc4120.txt
|
||||
// Section: 5.4.1
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"math"
|
||||
"math/big"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/asn1tools"
|
||||
"github.com/jcmturner/gokrb5/v8/config"
|
||||
"github.com/jcmturner/gokrb5/v8/crypto"
|
||||
"github.com/jcmturner/gokrb5/v8/iana"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/flags"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/keyusage"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/msgtype"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/nametype"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/patype"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
type marshalKDCReq struct {
|
||||
PVNO int `asn1:"explicit,tag:1"`
|
||||
MsgType int `asn1:"explicit,tag:2"`
|
||||
PAData types.PADataSequence `asn1:"explicit,optional,tag:3"`
|
||||
ReqBody asn1.RawValue `asn1:"explicit,tag:4"`
|
||||
}
|
||||
|
||||
// KDCReqFields represents the KRB_KDC_REQ fields.
|
||||
type KDCReqFields struct {
|
||||
PVNO int
|
||||
MsgType int
|
||||
PAData types.PADataSequence
|
||||
ReqBody KDCReqBody
|
||||
Renewal bool
|
||||
}
|
||||
|
||||
// ASReq implements RFC 4120 KRB_AS_REQ: https://tools.ietf.org/html/rfc4120#section-5.4.1.
|
||||
type ASReq struct {
|
||||
KDCReqFields
|
||||
}
|
||||
|
||||
// TGSReq implements RFC 4120 KRB_TGS_REQ: https://tools.ietf.org/html/rfc4120#section-5.4.1.
|
||||
type TGSReq struct {
|
||||
KDCReqFields
|
||||
}
|
||||
|
||||
type marshalKDCReqBody struct {
|
||||
KDCOptions asn1.BitString `asn1:"explicit,tag:0"`
|
||||
CName types.PrincipalName `asn1:"explicit,optional,tag:1"`
|
||||
Realm string `asn1:"generalstring,explicit,tag:2"`
|
||||
SName types.PrincipalName `asn1:"explicit,optional,tag:3"`
|
||||
From time.Time `asn1:"generalized,explicit,optional,tag:4"`
|
||||
Till time.Time `asn1:"generalized,explicit,tag:5"`
|
||||
RTime time.Time `asn1:"generalized,explicit,optional,tag:6"`
|
||||
Nonce int `asn1:"explicit,tag:7"`
|
||||
EType []int32 `asn1:"explicit,tag:8"`
|
||||
Addresses []types.HostAddress `asn1:"explicit,optional,tag:9"`
|
||||
EncAuthData types.EncryptedData `asn1:"explicit,optional,tag:10"`
|
||||
// Ticket needs to be a raw value as it is wrapped in an APPLICATION tag
|
||||
AdditionalTickets asn1.RawValue `asn1:"explicit,optional,tag:11"`
|
||||
}
|
||||
|
||||
// KDCReqBody implements the KRB_KDC_REQ request body.
|
||||
type KDCReqBody struct {
|
||||
KDCOptions asn1.BitString `asn1:"explicit,tag:0"`
|
||||
CName types.PrincipalName `asn1:"explicit,optional,tag:1"`
|
||||
Realm string `asn1:"generalstring,explicit,tag:2"`
|
||||
SName types.PrincipalName `asn1:"explicit,optional,tag:3"`
|
||||
From time.Time `asn1:"generalized,explicit,optional,tag:4"`
|
||||
Till time.Time `asn1:"generalized,explicit,tag:5"`
|
||||
RTime time.Time `asn1:"generalized,explicit,optional,tag:6"`
|
||||
Nonce int `asn1:"explicit,tag:7"`
|
||||
EType []int32 `asn1:"explicit,tag:8"`
|
||||
Addresses []types.HostAddress `asn1:"explicit,optional,tag:9"`
|
||||
EncAuthData types.EncryptedData `asn1:"explicit,optional,tag:10"`
|
||||
AdditionalTickets []Ticket `asn1:"explicit,optional,tag:11"`
|
||||
}
|
||||
|
||||
// NewASReqForTGT generates a new KRB_AS_REQ struct for a TGT request.
|
||||
func NewASReqForTGT(realm string, c *config.Config, cname types.PrincipalName) (ASReq, error) {
|
||||
sname := types.PrincipalName{
|
||||
NameType: nametype.KRB_NT_SRV_INST,
|
||||
NameString: []string{"krbtgt", realm},
|
||||
}
|
||||
return NewASReq(realm, c, cname, sname)
|
||||
}
|
||||
|
||||
// NewASReqForChgPasswd generates a new KRB_AS_REQ struct for a change password request.
|
||||
func NewASReqForChgPasswd(realm string, c *config.Config, cname types.PrincipalName) (ASReq, error) {
|
||||
sname := types.PrincipalName{
|
||||
NameType: nametype.KRB_NT_PRINCIPAL,
|
||||
NameString: []string{"kadmin", "changepw"},
|
||||
}
|
||||
return NewASReq(realm, c, cname, sname)
|
||||
}
|
||||
|
||||
// NewASReq generates a new KRB_AS_REQ struct for a given SNAME.
|
||||
func NewASReq(realm string, c *config.Config, cname, sname types.PrincipalName) (ASReq, error) {
|
||||
nonce, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt32))
|
||||
if err != nil {
|
||||
return ASReq{}, err
|
||||
}
|
||||
t := time.Now().UTC()
|
||||
// Copy the default options to make this thread safe
|
||||
kopts := types.NewKrbFlags()
|
||||
copy(kopts.Bytes, c.LibDefaults.KDCDefaultOptions.Bytes)
|
||||
kopts.BitLength = c.LibDefaults.KDCDefaultOptions.BitLength
|
||||
a := ASReq{
|
||||
KDCReqFields{
|
||||
PVNO: iana.PVNO,
|
||||
MsgType: msgtype.KRB_AS_REQ,
|
||||
PAData: types.PADataSequence{},
|
||||
ReqBody: KDCReqBody{
|
||||
KDCOptions: kopts,
|
||||
Realm: realm,
|
||||
CName: cname,
|
||||
SName: sname,
|
||||
Till: t.Add(c.LibDefaults.TicketLifetime),
|
||||
Nonce: int(nonce.Int64()),
|
||||
EType: c.LibDefaults.DefaultTktEnctypeIDs,
|
||||
},
|
||||
},
|
||||
}
|
||||
if c.LibDefaults.Forwardable {
|
||||
types.SetFlag(&a.ReqBody.KDCOptions, flags.Forwardable)
|
||||
}
|
||||
if c.LibDefaults.Canonicalize {
|
||||
types.SetFlag(&a.ReqBody.KDCOptions, flags.Canonicalize)
|
||||
}
|
||||
if c.LibDefaults.Proxiable {
|
||||
types.SetFlag(&a.ReqBody.KDCOptions, flags.Proxiable)
|
||||
}
|
||||
if c.LibDefaults.RenewLifetime != 0 {
|
||||
types.SetFlag(&a.ReqBody.KDCOptions, flags.Renewable)
|
||||
a.ReqBody.RTime = t.Add(c.LibDefaults.RenewLifetime)
|
||||
a.ReqBody.RTime = t.Add(time.Duration(48) * time.Hour)
|
||||
}
|
||||
if !c.LibDefaults.NoAddresses {
|
||||
ha, err := types.LocalHostAddresses()
|
||||
if err != nil {
|
||||
return a, fmt.Errorf("could not get local addresses: %v", err)
|
||||
}
|
||||
ha = append(ha, types.HostAddressesFromNetIPs(c.LibDefaults.ExtraAddresses)...)
|
||||
a.ReqBody.Addresses = ha
|
||||
}
|
||||
return a, nil
|
||||
}
|
||||
|
||||
// NewTGSReq generates a new KRB_TGS_REQ struct.
|
||||
func NewTGSReq(cname types.PrincipalName, kdcRealm string, c *config.Config, tgt Ticket, sessionKey types.EncryptionKey, sname types.PrincipalName, renewal bool) (TGSReq, error) {
|
||||
a, err := tgsReq(cname, sname, kdcRealm, renewal, c)
|
||||
if err != nil {
|
||||
return a, err
|
||||
}
|
||||
err = a.setPAData(tgt, sessionKey)
|
||||
return a, err
|
||||
}
|
||||
|
||||
// NewUser2UserTGSReq returns a TGS-REQ suitable for user-to-user authentication (https://tools.ietf.org/html/rfc4120#section-3.7)
|
||||
func NewUser2UserTGSReq(cname types.PrincipalName, kdcRealm string, c *config.Config, clientTGT Ticket, sessionKey types.EncryptionKey, sname types.PrincipalName, renewal bool, verifyingTGT Ticket) (TGSReq, error) {
|
||||
a, err := tgsReq(cname, sname, kdcRealm, renewal, c)
|
||||
if err != nil {
|
||||
return a, err
|
||||
}
|
||||
a.ReqBody.AdditionalTickets = []Ticket{verifyingTGT}
|
||||
types.SetFlag(&a.ReqBody.KDCOptions, flags.EncTktInSkey)
|
||||
err = a.setPAData(clientTGT, sessionKey)
|
||||
return a, err
|
||||
}
|
||||
|
||||
// tgsReq populates the fields for a TGS_REQ
|
||||
func tgsReq(cname, sname types.PrincipalName, kdcRealm string, renewal bool, c *config.Config) (TGSReq, error) {
|
||||
nonce, err := rand.Int(rand.Reader, big.NewInt(math.MaxInt32))
|
||||
if err != nil {
|
||||
return TGSReq{}, err
|
||||
}
|
||||
t := time.Now().UTC()
|
||||
k := KDCReqFields{
|
||||
PVNO: iana.PVNO,
|
||||
MsgType: msgtype.KRB_TGS_REQ,
|
||||
ReqBody: KDCReqBody{
|
||||
KDCOptions: types.NewKrbFlags(),
|
||||
Realm: kdcRealm,
|
||||
CName: cname, // Add the CName to make validation of the reply easier
|
||||
SName: sname,
|
||||
Till: t.Add(c.LibDefaults.TicketLifetime),
|
||||
Nonce: int(nonce.Int64()),
|
||||
EType: c.LibDefaults.DefaultTGSEnctypeIDs,
|
||||
},
|
||||
Renewal: renewal,
|
||||
}
|
||||
if c.LibDefaults.Forwardable {
|
||||
types.SetFlag(&k.ReqBody.KDCOptions, flags.Forwardable)
|
||||
}
|
||||
if c.LibDefaults.Canonicalize {
|
||||
types.SetFlag(&k.ReqBody.KDCOptions, flags.Canonicalize)
|
||||
}
|
||||
if c.LibDefaults.Proxiable {
|
||||
types.SetFlag(&k.ReqBody.KDCOptions, flags.Proxiable)
|
||||
}
|
||||
if c.LibDefaults.RenewLifetime > time.Duration(0) {
|
||||
types.SetFlag(&k.ReqBody.KDCOptions, flags.Renewable)
|
||||
k.ReqBody.RTime = t.Add(c.LibDefaults.RenewLifetime)
|
||||
}
|
||||
if !c.LibDefaults.NoAddresses {
|
||||
ha, err := types.LocalHostAddresses()
|
||||
if err != nil {
|
||||
return TGSReq{}, fmt.Errorf("could not get local addresses: %v", err)
|
||||
}
|
||||
ha = append(ha, types.HostAddressesFromNetIPs(c.LibDefaults.ExtraAddresses)...)
|
||||
k.ReqBody.Addresses = ha
|
||||
}
|
||||
if renewal {
|
||||
types.SetFlag(&k.ReqBody.KDCOptions, flags.Renew)
|
||||
types.SetFlag(&k.ReqBody.KDCOptions, flags.Renewable)
|
||||
}
|
||||
return TGSReq{
|
||||
k,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (k *TGSReq) setPAData(tgt Ticket, sessionKey types.EncryptionKey) error {
|
||||
// Marshal the request and calculate checksum
|
||||
b, err := k.ReqBody.Marshal()
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error marshaling TGS_REQ body")
|
||||
}
|
||||
etype, err := crypto.GetEtype(sessionKey.KeyType)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncryptingError, "error getting etype to encrypt authenticator")
|
||||
}
|
||||
cb, err := etype.GetChecksumHash(sessionKey.KeyValue, b, keyusage.TGS_REQ_PA_TGS_REQ_AP_REQ_AUTHENTICATOR_CHKSUM)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.ChksumError, "error getting etype checksum hash")
|
||||
}
|
||||
|
||||
// Form PAData for TGS_REQ
|
||||
// Create authenticator
|
||||
auth, err := types.NewAuthenticator(tgt.Realm, k.ReqBody.CName)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.KRBMsgError, "error generating new authenticator")
|
||||
}
|
||||
auth.Cksum = types.Checksum{
|
||||
CksumType: etype.GetHashID(),
|
||||
Checksum: cb,
|
||||
}
|
||||
// Create AP_REQ
|
||||
apReq, err := NewAPReq(tgt, sessionKey, auth)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.KRBMsgError, "error generating new AP_REQ")
|
||||
}
|
||||
apb, err := apReq.Marshal()
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error marshaling AP_REQ for pre-authentication data")
|
||||
}
|
||||
k.PAData = types.PADataSequence{
|
||||
types.PAData{
|
||||
PADataType: patype.PA_TGS_REQ,
|
||||
PADataValue: apb,
|
||||
},
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the ASReq struct.
|
||||
func (k *ASReq) Unmarshal(b []byte) error {
|
||||
var m marshalKDCReq
|
||||
_, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.ASREQ))
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling AS_REQ")
|
||||
}
|
||||
expectedMsgType := msgtype.KRB_AS_REQ
|
||||
if m.MsgType != expectedMsgType {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a AS_REQ. Expected: %v; Actual: %v", expectedMsgType, m.MsgType)
|
||||
}
|
||||
var reqb KDCReqBody
|
||||
err = reqb.Unmarshal(m.ReqBody.Bytes)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error processing AS_REQ body")
|
||||
}
|
||||
k.MsgType = m.MsgType
|
||||
k.PAData = m.PAData
|
||||
k.PVNO = m.PVNO
|
||||
k.ReqBody = reqb
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the TGSReq struct.
|
||||
func (k *TGSReq) Unmarshal(b []byte) error {
|
||||
var m marshalKDCReq
|
||||
_, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.TGSREQ))
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling TGS_REQ")
|
||||
}
|
||||
expectedMsgType := msgtype.KRB_TGS_REQ
|
||||
if m.MsgType != expectedMsgType {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a TGS_REQ. Expected: %v; Actual: %v", expectedMsgType, m.MsgType)
|
||||
}
|
||||
var reqb KDCReqBody
|
||||
err = reqb.Unmarshal(m.ReqBody.Bytes)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error processing TGS_REQ body")
|
||||
}
|
||||
k.MsgType = m.MsgType
|
||||
k.PAData = m.PAData
|
||||
k.PVNO = m.PVNO
|
||||
k.ReqBody = reqb
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the KRB_KDC_REQ body struct.
|
||||
func (k *KDCReqBody) Unmarshal(b []byte) error {
|
||||
var m marshalKDCReqBody
|
||||
_, err := asn1.Unmarshal(b, &m)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling KDC_REQ body")
|
||||
}
|
||||
k.KDCOptions = m.KDCOptions
|
||||
if len(k.KDCOptions.Bytes) < 4 {
|
||||
tb := make([]byte, 4-len(k.KDCOptions.Bytes))
|
||||
k.KDCOptions.Bytes = append(tb, k.KDCOptions.Bytes...)
|
||||
k.KDCOptions.BitLength = len(k.KDCOptions.Bytes) * 8
|
||||
}
|
||||
k.CName = m.CName
|
||||
k.Realm = m.Realm
|
||||
k.SName = m.SName
|
||||
k.From = m.From
|
||||
k.Till = m.Till
|
||||
k.RTime = m.RTime
|
||||
k.Nonce = m.Nonce
|
||||
k.EType = m.EType
|
||||
k.Addresses = m.Addresses
|
||||
k.EncAuthData = m.EncAuthData
|
||||
if len(m.AdditionalTickets.Bytes) > 0 {
|
||||
k.AdditionalTickets, err = unmarshalTicketsSequence(m.AdditionalTickets)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling additional tickets")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal ASReq struct.
|
||||
func (k *ASReq) Marshal() ([]byte, error) {
|
||||
m := marshalKDCReq{
|
||||
PVNO: k.PVNO,
|
||||
MsgType: k.MsgType,
|
||||
PAData: k.PAData,
|
||||
}
|
||||
b, err := k.ReqBody.Marshal()
|
||||
if err != nil {
|
||||
var mk []byte
|
||||
return mk, err
|
||||
}
|
||||
m.ReqBody = asn1.RawValue{
|
||||
Class: asn1.ClassContextSpecific,
|
||||
IsCompound: true,
|
||||
Tag: 4,
|
||||
Bytes: b,
|
||||
}
|
||||
mk, err := asn1.Marshal(m)
|
||||
if err != nil {
|
||||
return mk, krberror.Errorf(err, krberror.EncodingError, "error marshaling AS_REQ")
|
||||
}
|
||||
mk = asn1tools.AddASNAppTag(mk, asnAppTag.ASREQ)
|
||||
return mk, nil
|
||||
}
|
||||
|
||||
// Marshal TGSReq struct.
|
||||
func (k *TGSReq) Marshal() ([]byte, error) {
|
||||
m := marshalKDCReq{
|
||||
PVNO: k.PVNO,
|
||||
MsgType: k.MsgType,
|
||||
PAData: k.PAData,
|
||||
}
|
||||
b, err := k.ReqBody.Marshal()
|
||||
if err != nil {
|
||||
var mk []byte
|
||||
return mk, err
|
||||
}
|
||||
m.ReqBody = asn1.RawValue{
|
||||
Class: asn1.ClassContextSpecific,
|
||||
IsCompound: true,
|
||||
Tag: 4,
|
||||
Bytes: b,
|
||||
}
|
||||
mk, err := asn1.Marshal(m)
|
||||
if err != nil {
|
||||
return mk, krberror.Errorf(err, krberror.EncodingError, "error marshaling AS_REQ")
|
||||
}
|
||||
mk = asn1tools.AddASNAppTag(mk, asnAppTag.TGSREQ)
|
||||
return mk, nil
|
||||
}
|
||||
|
||||
// Marshal KRB_KDC_REQ body struct.
|
||||
func (k *KDCReqBody) Marshal() ([]byte, error) {
|
||||
var b []byte
|
||||
m := marshalKDCReqBody{
|
||||
KDCOptions: k.KDCOptions,
|
||||
CName: k.CName,
|
||||
Realm: k.Realm,
|
||||
SName: k.SName,
|
||||
From: k.From,
|
||||
Till: k.Till,
|
||||
RTime: k.RTime,
|
||||
Nonce: k.Nonce,
|
||||
EType: k.EType,
|
||||
Addresses: k.Addresses,
|
||||
EncAuthData: k.EncAuthData,
|
||||
}
|
||||
rawtkts, err := MarshalTicketSequence(k.AdditionalTickets)
|
||||
if err != nil {
|
||||
return b, krberror.Errorf(err, krberror.EncodingError, "error in marshaling KDC request body additional tickets")
|
||||
}
|
||||
//The asn1.rawValue needs the tag setting on it for where it is in the KDCReqBody
|
||||
rawtkts.Tag = 11
|
||||
if len(rawtkts.Bytes) > 0 {
|
||||
m.AdditionalTickets = rawtkts
|
||||
}
|
||||
b, err = asn1.Marshal(m)
|
||||
if err != nil {
|
||||
return b, krberror.Errorf(err, krberror.EncodingError, "error in marshaling KDC request body")
|
||||
}
|
||||
return b, nil
|
||||
}
|
102
vendor/github.com/jcmturner/gokrb5/v8/messages/KRBCred.go
generated
vendored
Normal file
102
vendor/github.com/jcmturner/gokrb5/v8/messages/KRBCred.go
generated
vendored
Normal file
@ -0,0 +1,102 @@
|
||||
package messages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/crypto"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/keyusage"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/msgtype"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
type marshalKRBCred struct {
|
||||
PVNO int `asn1:"explicit,tag:0"`
|
||||
MsgType int `asn1:"explicit,tag:1"`
|
||||
Tickets asn1.RawValue `asn1:"explicit,tag:2"`
|
||||
EncPart types.EncryptedData `asn1:"explicit,tag:3"`
|
||||
}
|
||||
|
||||
// KRBCred implements RFC 4120 KRB_CRED: https://tools.ietf.org/html/rfc4120#section-5.8.1.
|
||||
type KRBCred struct {
|
||||
PVNO int
|
||||
MsgType int
|
||||
Tickets []Ticket
|
||||
EncPart types.EncryptedData
|
||||
DecryptedEncPart EncKrbCredPart
|
||||
}
|
||||
|
||||
// EncKrbCredPart is the encrypted part of KRB_CRED.
|
||||
type EncKrbCredPart struct {
|
||||
TicketInfo []KrbCredInfo `asn1:"explicit,tag:0"`
|
||||
Nouce int `asn1:"optional,explicit,tag:1"`
|
||||
Timestamp time.Time `asn1:"generalized,optional,explicit,tag:2"`
|
||||
Usec int `asn1:"optional,explicit,tag:3"`
|
||||
SAddress types.HostAddress `asn1:"optional,explicit,tag:4"`
|
||||
RAddress types.HostAddress `asn1:"optional,explicit,tag:5"`
|
||||
}
|
||||
|
||||
// KrbCredInfo is the KRB_CRED_INFO part of KRB_CRED.
|
||||
type KrbCredInfo struct {
|
||||
Key types.EncryptionKey `asn1:"explicit,tag:0"`
|
||||
PRealm string `asn1:"generalstring,optional,explicit,tag:1"`
|
||||
PName types.PrincipalName `asn1:"optional,explicit,tag:2"`
|
||||
Flags asn1.BitString `asn1:"optional,explicit,tag:3"`
|
||||
AuthTime time.Time `asn1:"generalized,optional,explicit,tag:4"`
|
||||
StartTime time.Time `asn1:"generalized,optional,explicit,tag:5"`
|
||||
EndTime time.Time `asn1:"generalized,optional,explicit,tag:6"`
|
||||
RenewTill time.Time `asn1:"generalized,optional,explicit,tag:7"`
|
||||
SRealm string `asn1:"optional,explicit,ia5,tag:8"`
|
||||
SName types.PrincipalName `asn1:"optional,explicit,tag:9"`
|
||||
CAddr types.HostAddresses `asn1:"optional,explicit,tag:10"`
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the KRBCred struct.
|
||||
func (k *KRBCred) Unmarshal(b []byte) error {
|
||||
var m marshalKRBCred
|
||||
_, err := asn1.UnmarshalWithParams(b, &m, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.KRBCred))
|
||||
if err != nil {
|
||||
return processUnmarshalReplyError(b, err)
|
||||
}
|
||||
expectedMsgType := msgtype.KRB_CRED
|
||||
if m.MsgType != expectedMsgType {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a KRB_CRED. Expected: %v; Actual: %v", expectedMsgType, m.MsgType)
|
||||
}
|
||||
k.PVNO = m.PVNO
|
||||
k.MsgType = m.MsgType
|
||||
k.EncPart = m.EncPart
|
||||
if len(m.Tickets.Bytes) > 0 {
|
||||
k.Tickets, err = unmarshalTicketsSequence(m.Tickets)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling tickets within KRB_CRED")
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecryptEncPart decrypts the encrypted part of a KRB_CRED.
|
||||
func (k *KRBCred) DecryptEncPart(key types.EncryptionKey) error {
|
||||
b, err := crypto.DecryptEncPart(k.EncPart, key, keyusage.KRB_CRED_ENCPART)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.DecryptingError, "error decrypting KRB_CRED EncPart")
|
||||
}
|
||||
var denc EncKrbCredPart
|
||||
err = denc.Unmarshal(b)
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling encrypted part of KRB_CRED")
|
||||
}
|
||||
k.DecryptedEncPart = denc
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the encrypted part of KRB_CRED.
|
||||
func (k *EncKrbCredPart) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, k, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncKrbCredPart))
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "error unmarshaling EncKrbCredPart")
|
||||
}
|
||||
return nil
|
||||
}
|
83
vendor/github.com/jcmturner/gokrb5/v8/messages/KRBError.go
generated
vendored
Normal file
83
vendor/github.com/jcmturner/gokrb5/v8/messages/KRBError.go
generated
vendored
Normal file
@ -0,0 +1,83 @@
|
||||
// Package messages implements Kerberos 5 message types and methods.
|
||||
package messages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/iana"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/msgtype"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
// KRBError implements RFC 4120 KRB_ERROR: https://tools.ietf.org/html/rfc4120#section-5.9.1.
|
||||
type KRBError struct {
|
||||
PVNO int `asn1:"explicit,tag:0"`
|
||||
MsgType int `asn1:"explicit,tag:1"`
|
||||
CTime time.Time `asn1:"generalized,optional,explicit,tag:2"`
|
||||
Cusec int `asn1:"optional,explicit,tag:3"`
|
||||
STime time.Time `asn1:"generalized,explicit,tag:4"`
|
||||
Susec int `asn1:"explicit,tag:5"`
|
||||
ErrorCode int32 `asn1:"explicit,tag:6"`
|
||||
CRealm string `asn1:"generalstring,optional,explicit,tag:7"`
|
||||
CName types.PrincipalName `asn1:"optional,explicit,tag:8"`
|
||||
Realm string `asn1:"generalstring,explicit,tag:9"`
|
||||
SName types.PrincipalName `asn1:"explicit,tag:10"`
|
||||
EText string `asn1:"generalstring,optional,explicit,tag:11"`
|
||||
EData []byte `asn1:"optional,explicit,tag:12"`
|
||||
}
|
||||
|
||||
// NewKRBError creates a new KRBError.
|
||||
func NewKRBError(sname types.PrincipalName, realm string, code int32, etext string) KRBError {
|
||||
t := time.Now().UTC()
|
||||
return KRBError{
|
||||
PVNO: iana.PVNO,
|
||||
MsgType: msgtype.KRB_ERROR,
|
||||
STime: t,
|
||||
Susec: int((t.UnixNano() / int64(time.Microsecond)) - (t.Unix() * 1e6)),
|
||||
ErrorCode: code,
|
||||
SName: sname,
|
||||
Realm: realm,
|
||||
EText: etext,
|
||||
}
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the KRBError struct.
|
||||
func (k *KRBError) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, k, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.KRBError))
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "KRB_ERROR unmarshal error")
|
||||
}
|
||||
expectedMsgType := msgtype.KRB_ERROR
|
||||
if k.MsgType != expectedMsgType {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a KRB_ERROR. Expected: %v; Actual: %v", expectedMsgType, k.MsgType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Error method implementing error interface on KRBError struct.
|
||||
func (k KRBError) Error() string {
|
||||
etxt := fmt.Sprintf("KRB Error: %s", errorcode.Lookup(k.ErrorCode))
|
||||
if k.EText != "" {
|
||||
etxt = fmt.Sprintf("%s - %s", etxt, k.EText)
|
||||
}
|
||||
return etxt
|
||||
}
|
||||
|
||||
func processUnmarshalReplyError(b []byte, err error) error {
|
||||
switch err.(type) {
|
||||
case asn1.StructuralError:
|
||||
var krberr KRBError
|
||||
tmperr := krberr.Unmarshal(b)
|
||||
if tmperr != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "failed to unmarshal KDC's reply")
|
||||
}
|
||||
return krberr
|
||||
default:
|
||||
return krberror.Errorf(err, krberror.EncodingError, "failed to unmarshal KDC's reply")
|
||||
}
|
||||
}
|
108
vendor/github.com/jcmturner/gokrb5/v8/messages/KRBPriv.go
generated
vendored
Normal file
108
vendor/github.com/jcmturner/gokrb5/v8/messages/KRBPriv.go
generated
vendored
Normal file
@ -0,0 +1,108 @@
|
||||
package messages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/asn1tools"
|
||||
"github.com/jcmturner/gokrb5/v8/crypto"
|
||||
"github.com/jcmturner/gokrb5/v8/iana"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/keyusage"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/msgtype"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
// KRBPriv implements RFC 4120 type: https://tools.ietf.org/html/rfc4120#section-5.7.1.
|
||||
type KRBPriv struct {
|
||||
PVNO int `asn1:"explicit,tag:0"`
|
||||
MsgType int `asn1:"explicit,tag:1"`
|
||||
EncPart types.EncryptedData `asn1:"explicit,tag:3"`
|
||||
DecryptedEncPart EncKrbPrivPart `asn1:"optional,omitempty"` // Not part of ASN1 bytes so marked as optional so unmarshalling works
|
||||
}
|
||||
|
||||
// EncKrbPrivPart is the encrypted part of KRB_PRIV.
|
||||
type EncKrbPrivPart struct {
|
||||
UserData []byte `asn1:"explicit,tag:0"`
|
||||
Timestamp time.Time `asn1:"generalized,optional,explicit,tag:1"`
|
||||
Usec int `asn1:"optional,explicit,tag:2"`
|
||||
SequenceNumber int64 `asn1:"optional,explicit,tag:3"`
|
||||
SAddress types.HostAddress `asn1:"explicit,tag:4"`
|
||||
RAddress types.HostAddress `asn1:"optional,explicit,tag:5"`
|
||||
}
|
||||
|
||||
// NewKRBPriv returns a new KRBPriv type.
|
||||
func NewKRBPriv(part EncKrbPrivPart) KRBPriv {
|
||||
return KRBPriv{
|
||||
PVNO: iana.PVNO,
|
||||
MsgType: msgtype.KRB_PRIV,
|
||||
DecryptedEncPart: part,
|
||||
}
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the KRBPriv struct.
|
||||
func (k *KRBPriv) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, k, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.KRBPriv))
|
||||
if err != nil {
|
||||
return processUnmarshalReplyError(b, err)
|
||||
}
|
||||
expectedMsgType := msgtype.KRB_PRIV
|
||||
if k.MsgType != expectedMsgType {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a KRB_PRIV. Expected: %v; Actual: %v", expectedMsgType, k.MsgType)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the EncKrbPrivPart struct.
|
||||
func (k *EncKrbPrivPart) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, k, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.EncKrbPrivPart))
|
||||
if err != nil {
|
||||
return krberror.Errorf(err, krberror.EncodingError, "KRB_PRIV unmarshal error")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// Marshal the KRBPriv.
|
||||
func (k *KRBPriv) Marshal() ([]byte, error) {
|
||||
tk := KRBPriv{
|
||||
PVNO: k.PVNO,
|
||||
MsgType: k.MsgType,
|
||||
EncPart: k.EncPart,
|
||||
}
|
||||
b, err := asn1.Marshal(tk)
|
||||
if err != nil {
|
||||
return []byte{}, err
|
||||
}
|
||||
b = asn1tools.AddASNAppTag(b, asnAppTag.KRBPriv)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// EncryptEncPart encrypts the DecryptedEncPart within the KRBPriv.
|
||||
// Use to prepare for marshaling.
|
||||
func (k *KRBPriv) EncryptEncPart(key types.EncryptionKey) error {
|
||||
b, err := asn1.Marshal(k.DecryptedEncPart)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
b = asn1tools.AddASNAppTag(b, asnAppTag.EncKrbPrivPart)
|
||||
k.EncPart, err = crypto.GetEncryptedData(b, key, keyusage.KRB_PRIV_ENCPART, 1)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
// DecryptEncPart decrypts the encrypted part of the KRBPriv message.
|
||||
func (k *KRBPriv) DecryptEncPart(key types.EncryptionKey) error {
|
||||
b, err := crypto.DecryptEncPart(k.EncPart, key, keyusage.KRB_PRIV_ENCPART)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decrypting KRBPriv EncPart: %v", err)
|
||||
}
|
||||
err = k.DecryptedEncPart.Unmarshal(b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unmarshaling encrypted part: %v", err)
|
||||
}
|
||||
return nil
|
||||
}
|
43
vendor/github.com/jcmturner/gokrb5/v8/messages/KRBSafe.go
generated
vendored
Normal file
43
vendor/github.com/jcmturner/gokrb5/v8/messages/KRBSafe.go
generated
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
package messages
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/msgtype"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
// KRBSafe implements RFC 4120 KRB_SAFE: https://tools.ietf.org/html/rfc4120#section-5.6.1.
|
||||
type KRBSafe struct {
|
||||
PVNO int `asn1:"explicit,tag:0"`
|
||||
MsgType int `asn1:"explicit,tag:1"`
|
||||
SafeBody KRBSafeBody `asn1:"explicit,tag:2"`
|
||||
Cksum types.Checksum `asn1:"explicit,tag:3"`
|
||||
}
|
||||
|
||||
// KRBSafeBody implements the KRB_SAFE_BODY of KRB_SAFE.
|
||||
type KRBSafeBody struct {
|
||||
UserData []byte `asn1:"explicit,tag:0"`
|
||||
Timestamp time.Time `asn1:"generalized,optional,explicit,tag:1"`
|
||||
Usec int `asn1:"optional,explicit,tag:2"`
|
||||
SequenceNumber int64 `asn1:"optional,explicit,tag:3"`
|
||||
SAddress types.HostAddress `asn1:"explicit,tag:4"`
|
||||
RAddress types.HostAddress `asn1:"optional,explicit,tag:5"`
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the KRBSafe struct.
|
||||
func (s *KRBSafe) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, s, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.KRBSafe))
|
||||
if err != nil {
|
||||
return processUnmarshalReplyError(b, err)
|
||||
}
|
||||
expectedMsgType := msgtype.KRB_SAFE
|
||||
if s.MsgType != expectedMsgType {
|
||||
return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a KRB_SAFE. Expected: %v; Actual: %v", expectedMsgType, s.MsgType)
|
||||
}
|
||||
return nil
|
||||
}
|
265
vendor/github.com/jcmturner/gokrb5/v8/messages/Ticket.go
generated
vendored
Normal file
265
vendor/github.com/jcmturner/gokrb5/v8/messages/Ticket.go
generated
vendored
Normal file
@ -0,0 +1,265 @@
|
||||
package messages
|
||||
|
||||
import (
|
||||
"crypto/rand"
|
||||
"fmt"
|
||||
"log"
|
||||
"time"
|
||||
|
||||
"github.com/jcmturner/gofork/encoding/asn1"
|
||||
"github.com/jcmturner/gokrb5/v8/asn1tools"
|
||||
"github.com/jcmturner/gokrb5/v8/crypto"
|
||||
"github.com/jcmturner/gokrb5/v8/iana"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/adtype"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/asnAppTag"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/errorcode"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/flags"
|
||||
"github.com/jcmturner/gokrb5/v8/iana/keyusage"
|
||||
"github.com/jcmturner/gokrb5/v8/keytab"
|
||||
"github.com/jcmturner/gokrb5/v8/krberror"
|
||||
"github.com/jcmturner/gokrb5/v8/pac"
|
||||
"github.com/jcmturner/gokrb5/v8/types"
|
||||
)
|
||||
|
||||
// Reference: https://www.ietf.org/rfc/rfc4120.txt
|
||||
// Section: 5.3
|
||||
|
||||
// Ticket implements the Kerberos ticket.
|
||||
type Ticket struct {
|
||||
TktVNO int `asn1:"explicit,tag:0"`
|
||||
Realm string `asn1:"generalstring,explicit,tag:1"`
|
||||
SName types.PrincipalName `asn1:"explicit,tag:2"`
|
||||
EncPart types.EncryptedData `asn1:"explicit,tag:3"`
|
||||
DecryptedEncPart EncTicketPart `asn1:"optional"` // Not part of ASN1 bytes so marked as optional so unmarshalling works
|
||||
}
|
||||
|
||||
// EncTicketPart is the encrypted part of the Ticket.
|
||||
type EncTicketPart struct {
|
||||
Flags asn1.BitString `asn1:"explicit,tag:0"`
|
||||
Key types.EncryptionKey `asn1:"explicit,tag:1"`
|
||||
CRealm string `asn1:"generalstring,explicit,tag:2"`
|
||||
CName types.PrincipalName `asn1:"explicit,tag:3"`
|
||||
Transited TransitedEncoding `asn1:"explicit,tag:4"`
|
||||
AuthTime time.Time `asn1:"generalized,explicit,tag:5"`
|
||||
StartTime time.Time `asn1:"generalized,explicit,optional,tag:6"`
|
||||
EndTime time.Time `asn1:"generalized,explicit,tag:7"`
|
||||
RenewTill time.Time `asn1:"generalized,explicit,optional,tag:8"`
|
||||
CAddr types.HostAddresses `asn1:"explicit,optional,tag:9"`
|
||||
AuthorizationData types.AuthorizationData `asn1:"explicit,optional,tag:10"`
|
||||
}
|
||||
|
||||
// TransitedEncoding part of the ticket's encrypted part.
|
||||
type TransitedEncoding struct {
|
||||
TRType int32 `asn1:"explicit,tag:0"`
|
||||
Contents []byte `asn1:"explicit,tag:1"`
|
||||
}
|
||||
|
||||
// NewTicket creates a new Ticket instance.
|
||||
func NewTicket(cname types.PrincipalName, crealm string, sname types.PrincipalName, srealm string, flags asn1.BitString, sktab *keytab.Keytab, eTypeID int32, kvno int, authTime, startTime, endTime, renewTill time.Time) (Ticket, types.EncryptionKey, error) {
|
||||
etype, err := crypto.GetEtype(eTypeID)
|
||||
if err != nil {
|
||||
return Ticket{}, types.EncryptionKey{}, krberror.Errorf(err, krberror.EncryptingError, "error getting etype for new ticket")
|
||||
}
|
||||
ks := etype.GetKeyByteSize()
|
||||
kv := make([]byte, ks, ks)
|
||||
rand.Read(kv)
|
||||
sessionKey := types.EncryptionKey{
|
||||
KeyType: eTypeID,
|
||||
KeyValue: kv,
|
||||
}
|
||||
etp := EncTicketPart{
|
||||
Flags: flags,
|
||||
Key: sessionKey,
|
||||
CRealm: crealm,
|
||||
CName: cname,
|
||||
Transited: TransitedEncoding{},
|
||||
AuthTime: authTime,
|
||||
StartTime: startTime,
|
||||
EndTime: endTime,
|
||||
RenewTill: renewTill,
|
||||
}
|
||||
b, err := asn1.Marshal(etp)
|
||||
if err != nil {
|
||||
return Ticket{}, types.EncryptionKey{}, krberror.Errorf(err, krberror.EncodingError, "error marshalling ticket encpart")
|
||||
}
|
||||
b = asn1tools.AddASNAppTag(b, asnAppTag.EncTicketPart)
|
||||
skey, _, err := sktab.GetEncryptionKey(sname, srealm, kvno, eTypeID)
|
||||
if err != nil {
|
||||
return Ticket{}, types.EncryptionKey{}, krberror.Errorf(err, krberror.EncryptingError, "error getting encryption key for new ticket")
|
||||
}
|
||||
ed, err := crypto.GetEncryptedData(b, skey, keyusage.KDC_REP_TICKET, kvno)
|
||||
if err != nil {
|
||||
return Ticket{}, types.EncryptionKey{}, krberror.Errorf(err, krberror.EncryptingError, "error encrypting ticket encpart")
|
||||
}
|
||||
tkt := Ticket{
|
||||
TktVNO: iana.PVNO,
|
||||
Realm: srealm,
|
||||
SName: sname,
|
||||
EncPart: ed,
|
||||
}
|
||||
return tkt, sessionKey, nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into a Ticket struct.
|
||||
func (t *Ticket) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, t, fmt.Sprintf("application,explicit,tag:%d", asnAppTag.Ticket))
|
||||
return err
|
||||
}
|
||||
|
||||
// Marshal the Ticket.
|
||||
func (t *Ticket) Marshal() ([]byte, error) {
|
||||
b, err := asn1.Marshal(*t)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
b = asn1tools.AddASNAppTag(b, asnAppTag.Ticket)
|
||||
return b, nil
|
||||
}
|
||||
|
||||
// Unmarshal bytes b into the EncTicketPart struct.
|
||||
func (t *EncTicketPart) Unmarshal(b []byte) error {
|
||||
_, err := asn1.UnmarshalWithParams(b, t, fmt.Sprintf("application,explicit,tag:%d", asnAppTag.EncTicketPart))
|
||||
return err
|
||||
}
|
||||
|
||||
// unmarshalTicket returns a ticket from the bytes provided.
|
||||
func unmarshalTicket(b []byte) (t Ticket, err error) {
|
||||
err = t.Unmarshal(b)
|
||||
return
|
||||
}
|
||||
|
||||
// UnmarshalTicketsSequence returns a slice of Tickets from a raw ASN1 value.
|
||||
func unmarshalTicketsSequence(in asn1.RawValue) ([]Ticket, error) {
|
||||
//This is a workaround to a asn1 decoding issue in golang - https://github.com/golang/go/issues/17321. It's not pretty I'm afraid
|
||||
//We pull out raw values from the larger raw value (that is actually the data of the sequence of raw values) and track our position moving along the data.
|
||||
b := in.Bytes
|
||||
// Ignore the head of the asn1 stream (1 byte for tag and those for the length) as this is what tells us its a sequence but we're handling it ourselves
|
||||
p := 1 + asn1tools.GetNumberBytesInLengthHeader(in.Bytes)
|
||||
var tkts []Ticket
|
||||
var raw asn1.RawValue
|
||||
for p < (len(b)) {
|
||||
_, err := asn1.UnmarshalWithParams(b[p:], &raw, fmt.Sprintf("application,tag:%d", asnAppTag.Ticket))
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unmarshaling sequence of tickets failed getting length of ticket: %v", err)
|
||||
}
|
||||
t, err := unmarshalTicket(b[p:])
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("unmarshaling sequence of tickets failed: %v", err)
|
||||
}
|
||||
p += len(raw.FullBytes)
|
||||
tkts = append(tkts, t)
|
||||
}
|
||||
MarshalTicketSequence(tkts)
|
||||
return tkts, nil
|
||||
}
|
||||
|
||||
// MarshalTicketSequence marshals a slice of Tickets returning an ASN1 raw value containing the ticket sequence.
|
||||
func MarshalTicketSequence(tkts []Ticket) (asn1.RawValue, error) {
|
||||
raw := asn1.RawValue{
|
||||
Class: 2,
|
||||
IsCompound: true,
|
||||
}
|
||||
if len(tkts) < 1 {
|
||||
// There are no tickets to marshal
|
||||
return raw, nil
|
||||
}
|
||||
var btkts []byte
|
||||
for i, t := range tkts {
|
||||
b, err := t.Marshal()
|
||||
if err != nil {
|
||||
return raw, fmt.Errorf("error marshaling ticket number %d in sequence of tickets", i+1)
|
||||
}
|
||||
btkts = append(btkts, b...)
|
||||
}
|
||||
// The ASN1 wrapping consists of 2 bytes:
|
||||
// 1st byte -> Identifier Octet - In this case an OCTET STRING (ASN TAG
|
||||
// 2nd byte -> The length (this will be the size indicated in the input bytes + 2 for the additional bytes we add here.
|
||||
// Application Tag:
|
||||
//| Byte: | 8 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
|
||||
//| Value: | 0 | 1 | 1 | From the RFC spec 4120 |
|
||||
//| Explanation | Defined by the ASN1 encoding rules for an application tag | A value of 1 indicates a constructed type | The ASN Application tag value |
|
||||
btkts = append(asn1tools.MarshalLengthBytes(len(btkts)), btkts...)
|
||||
btkts = append([]byte{byte(32 + asn1.TagSequence)}, btkts...)
|
||||
raw.Bytes = btkts
|
||||
// If we need to create the full bytes then identifier octet is "context-specific" = 128 + "constructed" + 32 + the wrapping explicit tag (11)
|
||||
//fmt.Fprintf(os.Stderr, "mRaw fb: %v\n", raw.FullBytes)
|
||||
return raw, nil
|
||||
}
|
||||
|
||||
// DecryptEncPart decrypts the encrypted part of the ticket.
|
||||
// The sname argument can be used to specify which service principal's key should be used to decrypt the ticket.
|
||||
// If nil is passed as the sname then the service principal specified within the ticket it used.
|
||||
func (t *Ticket) DecryptEncPart(keytab *keytab.Keytab, sname *types.PrincipalName) error {
|
||||
if sname == nil {
|
||||
sname = &t.SName
|
||||
}
|
||||
key, _, err := keytab.GetEncryptionKey(*sname, t.Realm, t.EncPart.KVNO, t.EncPart.EType)
|
||||
if err != nil {
|
||||
return NewKRBError(t.SName, t.Realm, errorcode.KRB_AP_ERR_NOKEY, fmt.Sprintf("Could not get key from keytab: %v", err))
|
||||
}
|
||||
return t.Decrypt(key)
|
||||
}
|
||||
|
||||
// Decrypt decrypts the encrypted part of the ticket using the key provided.
|
||||
func (t *Ticket) Decrypt(key types.EncryptionKey) error {
|
||||
b, err := crypto.DecryptEncPart(t.EncPart, key, keyusage.KDC_REP_TICKET)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error decrypting Ticket EncPart: %v", err)
|
||||
}
|
||||
var denc EncTicketPart
|
||||
err = denc.Unmarshal(b)
|
||||
if err != nil {
|
||||
return fmt.Errorf("error unmarshaling encrypted part: %v", err)
|
||||
}
|
||||
t.DecryptedEncPart = denc
|
||||
return nil
|
||||
}
|
||||
|
||||
// GetPACType returns a Microsoft PAC that has been extracted from the ticket and processed.
|
||||
func (t *Ticket) GetPACType(keytab *keytab.Keytab, sname *types.PrincipalName, l *log.Logger) (bool, pac.PACType, error) {
|
||||
var isPAC bool
|
||||
for _, ad := range t.DecryptedEncPart.AuthorizationData {
|
||||
if ad.ADType == adtype.ADIfRelevant {
|
||||
var ad2 types.AuthorizationData
|
||||
err := ad2.Unmarshal(ad.ADData)
|
||||
if err != nil {
|
||||
l.Printf("PAC authorization data could not be unmarshaled: %v", err)
|
||||
continue
|
||||
}
|
||||
if ad2[0].ADType == adtype.ADWin2KPAC {
|
||||
isPAC = true
|
||||
var p pac.PACType
|
||||
err = p.Unmarshal(ad2[0].ADData)
|
||||
if err != nil {
|
||||
return isPAC, p, fmt.Errorf("error unmarshaling PAC: %v", err)
|
||||
}
|
||||
if sname == nil {
|
||||
sname = &t.SName
|
||||
}
|
||||
key, _, err := keytab.GetEncryptionKey(*sname, t.Realm, t.EncPart.KVNO, t.EncPart.EType)
|
||||
if err != nil {
|
||||
return isPAC, p, NewKRBError(t.SName, t.Realm, errorcode.KRB_AP_ERR_NOKEY, fmt.Sprintf("Could not get key from keytab: %v", err))
|
||||
}
|
||||
err = p.ProcessPACInfoBuffers(key, l)
|
||||
return isPAC, p, err
|
||||
}
|
||||
}
|
||||
}
|
||||
return isPAC, pac.PACType{}, nil
|
||||
}
|
||||
|
||||
// Valid checks it the ticket is currently valid. Max duration passed endtime passed in as argument.
|
||||
func (t *Ticket) Valid(d time.Duration) (bool, error) {
|
||||
// Check for future tickets or invalid tickets
|
||||
time := time.Now().UTC()
|
||||
if t.DecryptedEncPart.StartTime.Sub(time) > d || types.IsFlagSet(&t.DecryptedEncPart.Flags, flags.Invalid) {
|
||||
return false, NewKRBError(t.SName, t.Realm, errorcode.KRB_AP_ERR_TKT_NYV, "service ticket provided is not yet valid")
|
||||
}
|
||||
|
||||
// Check for expired ticket
|
||||
if time.Sub(t.DecryptedEncPart.EndTime) > d {
|
||||
return false, NewKRBError(t.SName, t.Realm, errorcode.KRB_AP_ERR_TKT_EXPIRED, "service ticket provided has expired")
|
||||
}
|
||||
|
||||
return true, nil
|
||||
}
|
Reference in New Issue
Block a user