KRBError.go 2.9 KB

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