package checker import ( "errors" "strconv" "strings" "github.com/jcmturner/gokrb5/v8/iana/errorcode" "github.com/jcmturner/gokrb5/v8/messages" ) // krbErrorInfo extracts a Kerberos error code (and its short name) from an // error returned by gokrb5. Direct KRBError values are matched via // errors.As; otherwise the error string is parsed, since gokrb5 also // returns wrapped krberror.Krberror values that carry the code only inside // their formatted message. ok is false when no code could be extracted. func krbErrorInfo(err error) (code int32, name string, ok bool) { if err == nil { return 0, "", false } var krbErr messages.KRBError if errors.As(err, &krbErr) { return krbErr.ErrorCode, errorcodeName(krbErr.ErrorCode), true } msg := err.Error() if _, after, found := strings.Cut(msg, "KRB Error: ("); found { if c, _, found := strings.Cut(after, ")"); found { if n, perr := strconv.Atoi(c); perr == nil { return int32(n), errorcodeName(int32(n)), true } } } return 0, "", false } // errorcodeName returns the short symbolic name of a Kerberos error code // (e.g. "KDC_ERR_PREAUTH_REQUIRED"), trimming the numeric/textual padding // gokrb5 wraps around it. func errorcodeName(code int32) string { s := errorcode.Lookup(code) if _, after, ok := strings.Cut(s, ") "); ok { s = after } if before, _, ok := strings.Cut(s, " "); ok { s = before } return s }