github.com/jcmturner/gokrb5/v8@v8.4.4/messages/KRBError.go (about) 1 // Package messages implements Kerberos 5 message types and methods. 2 package messages 3 4 import ( 5 "fmt" 6 "time" 7 8 "github.com/jcmturner/gofork/encoding/asn1" 9 "github.com/jcmturner/gokrb5/v8/asn1tools" 10 "github.com/jcmturner/gokrb5/v8/iana" 11 "github.com/jcmturner/gokrb5/v8/iana/asnAppTag" 12 "github.com/jcmturner/gokrb5/v8/iana/errorcode" 13 "github.com/jcmturner/gokrb5/v8/iana/msgtype" 14 "github.com/jcmturner/gokrb5/v8/krberror" 15 "github.com/jcmturner/gokrb5/v8/types" 16 ) 17 18 // KRBError implements RFC 4120 KRB_ERROR: https://tools.ietf.org/html/rfc4120#section-5.9.1. 19 type KRBError struct { 20 PVNO int `asn1:"explicit,tag:0"` 21 MsgType int `asn1:"explicit,tag:1"` 22 CTime time.Time `asn1:"generalized,optional,explicit,tag:2"` 23 Cusec int `asn1:"optional,explicit,tag:3"` 24 STime time.Time `asn1:"generalized,explicit,tag:4"` 25 Susec int `asn1:"explicit,tag:5"` 26 ErrorCode int32 `asn1:"explicit,tag:6"` 27 CRealm string `asn1:"generalstring,optional,explicit,tag:7"` 28 CName types.PrincipalName `asn1:"optional,explicit,tag:8"` 29 Realm string `asn1:"generalstring,explicit,tag:9"` 30 SName types.PrincipalName `asn1:"explicit,tag:10"` 31 EText string `asn1:"generalstring,optional,explicit,tag:11"` 32 EData []byte `asn1:"optional,explicit,tag:12"` 33 } 34 35 // NewKRBError creates a new KRBError. 36 func NewKRBError(sname types.PrincipalName, realm string, code int32, etext string) KRBError { 37 t := time.Now().UTC() 38 return KRBError{ 39 PVNO: iana.PVNO, 40 MsgType: msgtype.KRB_ERROR, 41 STime: t, 42 Susec: int((t.UnixNano() / int64(time.Microsecond)) - (t.Unix() * 1e6)), 43 ErrorCode: code, 44 SName: sname, 45 Realm: realm, 46 EText: etext, 47 } 48 } 49 50 // Unmarshal bytes b into the KRBError struct. 51 func (k *KRBError) Unmarshal(b []byte) error { 52 _, err := asn1.UnmarshalWithParams(b, k, fmt.Sprintf("application,explicit,tag:%v", asnAppTag.KRBError)) 53 if err != nil { 54 return krberror.Errorf(err, krberror.EncodingError, "KRB_ERROR unmarshal error") 55 } 56 expectedMsgType := msgtype.KRB_ERROR 57 if k.MsgType != expectedMsgType { 58 return krberror.NewErrorf(krberror.KRBMsgError, "message ID does not indicate a KRB_ERROR. Expected: %v; Actual: %v", expectedMsgType, k.MsgType) 59 } 60 return nil 61 } 62 63 // Marshal a KRBError into bytes. 64 func (k *KRBError) Marshal() ([]byte, error) { 65 b, err := asn1.Marshal(*k) 66 if err != nil { 67 return b, krberror.Errorf(err, krberror.EncodingError, "error marshaling KRBError") 68 } 69 b = asn1tools.AddASNAppTag(b, asnAppTag.KRBError) 70 return b, nil 71 } 72 73 // Error method implementing error interface on KRBError struct. 74 func (k KRBError) Error() string { 75 etxt := fmt.Sprintf("KRB Error: %s", errorcode.Lookup(k.ErrorCode)) 76 if k.EText != "" { 77 etxt = fmt.Sprintf("%s - %s", etxt, k.EText) 78 } 79 return etxt 80 } 81 82 func processUnmarshalReplyError(b []byte, err error) error { 83 switch err.(type) { 84 case asn1.StructuralError: 85 var krberr KRBError 86 tmperr := krberr.Unmarshal(b) 87 if tmperr != nil { 88 return krberror.Errorf(err, krberror.EncodingError, "failed to unmarshal KDC's reply") 89 } 90 return krberr 91 default: 92 return krberror.Errorf(err, krberror.EncodingError, "failed to unmarshal KDC's reply") 93 } 94 }