CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/kerberos/model/error.rb
Views: 11766
1
# -*- coding: binary -*-
2
# frozen_string_literal: true
3
4
module Rex
5
module Proto
6
module Kerberos
7
module Model
8
module Error
9
###
10
# This class represents a Kerberos Error Code as defined in:
11
# https://datatracker.ietf.org/doc/html/rfc4120#section-7.5.9
12
# https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768#table-2-kerberos-ticket-flags)
13
##
14
class ErrorCode
15
# @return [String] the description of the error the code represents
16
attr_reader :description
17
# @return [String] the name of the error code
18
attr_reader :name
19
# @return [Integer] the error code that was given as a return value
20
attr_reader :value
21
22
# @param [String] name the 'name' of the error code (i.e KDC_ERR_NONE)
23
# @param [Integer] value the return value that represents that error (i.e. 0)
24
# @param [String] description the verbose description of the error
25
# @raise [ArgumentError] if any of the parameters are of an invalid type
26
def initialize(name, value, description)
27
raise ArgumentError, 'Invalid Error Name' unless name.is_a?(String) && !name.empty?
28
raise ArgumentError, 'Invalid Error Code Value' unless value.is_a?(Integer)
29
raise ArgumentError, 'Invalid Error Description' unless description.is_a?(String) && !description.empty?
30
31
@name = name
32
@value = value
33
@description = description
34
end
35
36
# Override the equality test for ErrorCodes. Equality is
37
# always tested against the #value of the error code.
38
#
39
# @param other [Object] The object to test equality against
40
# @raise [ArgumentError] if the other object is not either another ErrorCode or a Integer
41
# @return [Boolean] whether the equality test passed
42
def ==(other)
43
if other.is_a? self.class
44
value == other.value
45
elsif other.is_a? Integer
46
value == other
47
elsif other.nil?
48
false
49
else
50
raise ArgumentError, "Cannot compare a #{self.class} to a #{other.class}"
51
end
52
end
53
54
alias === ==
55
56
def to_s
57
"#{name} (#{value}) - #{description}"
58
end
59
end
60
61
# Core Kerberos specification and errors:
62
# https://datatracker.ietf.org/doc/html/rfc4120#section-7.5.9
63
# https://docs.microsoft.com/en-us/windows/security/threat-protection/auditing/event-4768#table-2-kerberos-ticket-flags
64
#
65
# Additional errors added by PKINIT:
66
# https://www.rfc-editor.org/rfc/rfc4556#section-3.1.3
67
module ErrorCodes
68
KDC_ERR_NONE = ErrorCode.new('KDC_ERR_NONE', 0, 'No error')
69
KDC_ERR_NAME_EXP = ErrorCode.new('KDC_ERR_NAME_EXP', 1, "Client's entry in database has expired")
70
KDC_ERR_SERVICE_EXP = ErrorCode.new('KDC_ERR_SERVICE_EXP', 2, "Server's entry in database has expired")
71
KDC_ERR_BAD_PVNO = ErrorCode.new('KDC_ERR_BAD_PVNO', 3, 'Requested protocol version number not supported')
72
KDC_ERR_C_OLD_MAST_KVNO = ErrorCode.new('KDC_ERR_C_OLD_MAST_KVNO', 4, "Client's key encrypted in old master key")
73
KDC_ERR_S_OLD_MAST_KVNO = ErrorCode.new('KDC_ERR_S_OLD_MAST_KVNO', 5, "Server's key encrypted in old master key")
74
KDC_ERR_C_PRINCIPAL_UNKNOWN = ErrorCode.new('KDC_ERR_C_PRINCIPAL_UNKNOWN', 6, 'Client not found in Kerberos database')
75
KDC_ERR_S_PRINCIPAL_UNKNOWN = ErrorCode.new('KDC_ERR_S_PRINCIPAL_UNKNOWN', 7, 'Server not found in Kerberos database')
76
KDC_ERR_PRINCIPAL_NOT_UNIQUE = ErrorCode.new('KDC_ERR_PRINCIPAL_NOT_UNIQUE', 8, 'Multiple principal entries in database')
77
KDC_ERR_NULL_KEY = ErrorCode.new('KDC_ERR_NULL_KEY', 9, 'The client or server has a null key')
78
KDC_ERR_CANNOT_POSTDATE = ErrorCode.new('KDC_ERR_CANNOT_POSTDATE', 10, 'Ticket not eligible for postdating')
79
KDC_ERR_NEVER_VALID = ErrorCode.new('KDC_ERR_NEVER_VALID', 11, 'Requested start time is later than end time')
80
KDC_ERR_POLICY = ErrorCode.new('KDC_ERR_POLICY', 12, 'KDC policy rejects request')
81
KDC_ERR_BADOPTION = ErrorCode.new('KDC_ERR_BADOPTION', 13, 'KDC cannot accommodate requested option')
82
KDC_ERR_ETYPE_NOSUPP = ErrorCode.new('KDC_ERR_ETYPE_NOSUPP', 14, 'KDC has no support for encryption type')
83
KDC_ERR_SUMTYPE_NOSUPP = ErrorCode.new('KDC_ERR_SUMTYPE_NOSUPP', 15, 'KDC has no support for checksum type')
84
KDC_ERR_PADATA_TYPE_NOSUPP = ErrorCode.new('KDC_ERR_PADATA_TYPE_NOSUPP', 16, 'KDC has no support for padata type')
85
KDC_ERR_TRTYPE_NOSUPP = ErrorCode.new('KDC_ERR_TRTYPE_NOSUPP', 17, 'KDC has no support for transited type')
86
KDC_ERR_CLIENT_REVOKED = ErrorCode.new('KDC_ERR_CLIENT_REVOKED', 18, 'Clients credentials have been revoked')
87
KDC_ERR_SERVICE_REVOKED = ErrorCode.new('KDC_ERR_SERVICE_REVOKED', 19, 'Credentials for server have been revoked')
88
KDC_ERR_TGT_REVOKED = ErrorCode.new('KDC_ERR_TGT_REVOKED', 20, 'TGT has been revoked')
89
KDC_ERR_CLIENT_NOTYET = ErrorCode.new('KDC_ERR_CLIENT_NOTYET', 21, 'Client not yet valid - try again later')
90
KDC_ERR_SERVICE_NOTYET = ErrorCode.new('KDC_ERR_SERVICE_NOTYET', 22, 'Server not yet valid - try again later')
91
KDC_ERR_KEY_EXPIRED = ErrorCode.new('KDC_ERR_KEY_EXPIRED', 23, 'Password has expired - change password to reset')
92
KDC_ERR_PREAUTH_FAILED = ErrorCode.new('KDC_ERR_PREAUTH_FAILED', 24, 'Pre-authentication information was invalid')
93
KDC_ERR_PREAUTH_REQUIRED = ErrorCode.new('KDC_ERR_PREAUTH_REQUIRED', 25, 'Additional pre-authentication required')
94
KDC_ERR_SERVER_NOMATCH = ErrorCode.new('KDC_ERR_SERVER_NOMATCH', 26, "Requested server and ticket don't match")
95
KDC_ERR_MUST_USE_USER2USER = ErrorCode.new('KDC_ERR_MUST_USE_USER2USER', 27, 'Server principal valid for user2user only')
96
KDC_ERR_PATH_NOT_ACCEPTED = ErrorCode.new('KDC_ERR_PATH_NOT_ACCEPTED', 28, 'KDC Policy rejects transited path')
97
KDC_ERR_SVC_UNAVAILABLE = ErrorCode.new('KDC_ERR_SVC_UNAVAILABLE', 29, 'A service is not available')
98
KRB_AP_ERR_BAD_INTEGRITY = ErrorCode.new('KRB_AP_ERR_BAD_INTEGRITY', 31, 'Integrity check on decrypted field failed')
99
KRB_AP_ERR_TKT_EXPIRED = ErrorCode.new('KRB_AP_ERR_TKT_EXPIRED', 32, 'Ticket expired')
100
KRB_AP_ERR_TKT_NYV = ErrorCode.new('KRB_AP_ERR_TKT_NYV', 33, 'Ticket not yet valid')
101
KRB_AP_ERR_REPEAT = ErrorCode.new('KRB_AP_ERR_REPEAT', 34, 'Request is a replay')
102
KRB_AP_ERR_NOT_US = ErrorCode.new('KRB_AP_ERR_NOT_US', 35, "The ticket isn't for us")
103
KRB_AP_ERR_BADMATCH = ErrorCode.new('KRB_AP_ERR_BADMATCH', 36, "Ticket and authenticator don't match")
104
KRB_AP_ERR_SKEW = ErrorCode.new('KRB_AP_ERR_SKEW', 37, 'Clock skew too great')
105
KRB_AP_ERR_BADADDR = ErrorCode.new('KRB_AP_ERR_BADADDR', 38, 'Incorrect net address')
106
KRB_AP_ERR_BADVERSION = ErrorCode.new('KRB_AP_ERR_BADVERSION', 39, 'Protocol version mismatch')
107
KRB_AP_ERR_MSG_TYPE = ErrorCode.new('KRB_AP_ERR_MSG_TYPE', 40, 'Invalid msg type')
108
KRB_AP_ERR_MODIFIED = ErrorCode.new('KRB_AP_ERR_MODIFIED', 41, 'Message stream modified')
109
KRB_AP_ERR_BADORDER = ErrorCode.new('KRB_AP_ERR_BADORDER', 42, 'Message out of order')
110
KRB_AP_ERR_BADKEYVER = ErrorCode.new('KRB_AP_ERR_BADKEYVER', 44, 'Specified version of key is not available')
111
KRB_AP_ERR_NOKEY = ErrorCode.new('KRB_AP_ERR_NOKEY', 45, 'Service key not available')
112
KRB_AP_ERR_MUT_FAIL = ErrorCode.new('KRB_AP_ERR_MUT_FAIL', 46, 'Mutual authentication failed')
113
KRB_AP_ERR_BADDIRECTION = ErrorCode.new('KRB_AP_ERR_BADDIRECTION', 47, 'Incorrect message direction')
114
KRB_AP_ERR_METHOD = ErrorCode.new('KRB_AP_ERR_METHOD', 48, 'Alternative authentication method required')
115
KRB_AP_ERR_BADSEQ = ErrorCode.new('KRB_AP_ERR_BADSEQ', 49, 'Incorrect sequence number in message')
116
KRB_AP_ERR_INAPP_CKSUM = ErrorCode.new('KRB_AP_ERR_INAPP_CKSUM', 50, 'Inappropriate type of checksum in message')
117
KRB_AP_PATH_NOT_ACCEPTED = ErrorCode.new('KRB_AP_PATH_NOT_ACCEPTED', 51, 'Policy rejects transited path')
118
KRB_ERR_RESPONSE_TOO_BIG = ErrorCode.new('KRB_ERR_RESPONSE_TOO_BIG', 52, 'Response too big for UDP; retry with TCP')
119
KRB_ERR_GENERIC = ErrorCode.new('KRB_ERR_GENERIC', 60, 'Generic error')
120
KRB_ERR_FIELD_TOOLONG = ErrorCode.new('KRB_ERR_FIELD_TOOLONG', 61, 'Field is too long for this implementation')
121
KDC_ERR_CLIENT_NOT_TRUSTED = ErrorCode.new('KDC_ERR_CLIENT_NOT_TRUSTED', 62, 'PKINIT - KDC_ERR_CLIENT_NOT_TRUSTED')
122
KDC_ERR_KDC_NOT_TRUSTED = ErrorCode.new('KDC_ERR_KDC_NOT_TRUSTED', 63, 'PKINIT - KDC_ERR_KDC_NOT_TRUSTED')
123
KDC_ERR_INVALID_SIG = ErrorCode.new('KDC_ERR_INVALID_SIG', 64, 'PKINIT - KDC_ERR_INVALID_SIG')
124
KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED = ErrorCode.new('KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED', 65, 'PKINIT - KDC_ERR_DH_KEY_PARAMETERS_NOT_ACCEPTED')
125
KDC_ERR_CERTIFICATE_MISMATCH = ErrorCode.new('KDC_ERR_CERTIFICATE_MISMATCH', 66, 'PKINIT - KDC_ERR_CERTIFICATE_MISMATCH')
126
KRB_AP_ERR_NO_TGT = ErrorCode.new('KRB_AP_ERR_NO_TGT', 67, 'No TGT available to validate USER-TO-USER')
127
KDC_ERR_WRONG_REALM = ErrorCode.new('KDC_ERR_WRONG_REALM', 68, 'Wrong Realm / domain')
128
KRB_AP_ERR_USER_TO_USER_REQUIRED = ErrorCode.new('KRB_AP_ERR_USER_TO_USER_REQUIRED', 69, 'Ticket must be for USER-TO-USER')
129
KDC_ERR_CANT_VERIFY_CERTIFICATE = ErrorCode.new('KDC_ERR_CANT_VERIFY_CERTIFICATE', 70, 'PKINIT - KDC_ERR_CANT_VERIFY_CERTIFICATE')
130
KDC_ERR_INVALID_CERTIFICATE = ErrorCode.new('KDC_ERR_INVALID_CERTIFICATE', 71, 'PKINIT - KDC_ERR_INVALID_CERTIFICATE')
131
KDC_ERR_REVOKED_CERTIFICATE = ErrorCode.new('KDC_ERR_REVOKED_CERTIFICATE', 72, 'PKINIT - KDC_ERR_REVOKED_CERTIFICATE')
132
KDC_ERR_REVOCATION_STATUS_UNKNOWN = ErrorCode.new('KDC_ERR_REVOCATION_STATUS_UNKNOWN', 73, 'PKINIT - KDC_ERR_REVOCATION_STATUS_UNKNOWN')
133
KDC_ERR_REVOCATION_STATUS_UNAVAILABLE = ErrorCode.new('KDC_ERR_REVOCATION_STATUS_UNAVAILABLE', 74, 'PKINIT - KDC_ERR_REVOCATION_STATUS_UNAVAILABLE')
134
KDC_ERR_CLIENT_NAME_MISMATCH = ErrorCode.new('KDC_ERR_CLIENT_NAME_MISMATCH', 75, 'PKINIT - KDC_ERR_CLIENT_NAME_MISMATCH')
135
KDC_ERR_KDC_NAME_MISMATCH = ErrorCode.new('KDC_ERR_KDC_NAME_MISMATCH', 76, 'PKINIT - KDC_ERR_KDC_NAME_MISMATCH')
136
KDC_ERR_INCONSISTENT_KEY_PURPOSE = ErrorCode.new('KDC_ERR_INCONSISTENT_KEY_PURPOSE', 77, 'PKINIT - KDC_ERR_INCONSISTENT_KEY_PURPOSE')
137
KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED = ErrorCode.new('KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED', 78, 'PKINIT - KDC_ERR_DIGEST_IN_CERT_NOT_ACCEPTED')
138
KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED = ErrorCode.new('KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED', 79, 'PKINIT - KDC_ERR_PA_CHECKSUM_MUST_BE_INCLUDED')
139
KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED = ErrorCode.new('KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED', 80, 'PKINIT - KDC_ERR_DIGEST_IN_SIGNED_DATA_NOT_ACCEPTED')
140
KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED = ErrorCode.new('KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED', 81, 'PKINIT - KDC_ERR_PUBLIC_KEY_ENCRYPTION_NOT_SUPPORTED')
141
142
# Allow lookup of errors via numerical value
143
ERROR_MAP = ErrorCodes.constants.each_with_object({}) do |const, map|
144
next if const == :ERROR_MAP
145
146
error_code = ErrorCodes.const_get(const)
147
map[error_code.value] = error_code
148
end
149
end
150
151
# Runtime Error which can be raised by the Rex::Proto::Kerberos API
152
class KerberosError < ::StandardError
153
# @return [Rex::Proto::Kerberos::Model::Error::ErrorCode] A ErrorCode generated from a KDC
154
attr_reader :error_code
155
156
# @return [Rex::Proto::Kerberos::Model::KdcResponse, Rex::Proto::Kerberos::Model::EncKdcResponse] The response associated with this error
157
attr_reader :res
158
159
def initialize(message = nil, error_code: nil, res: nil)
160
error_code ||= res&.error_code
161
@error_code = error_code
162
@res = res
163
164
super(message || message_for(error_code))
165
end
166
167
def message_for(error_code)
168
return "Kerberos Error" unless error_code
169
170
if error_code == ErrorCodes::KRB_AP_ERR_SKEW && res&.respond_to?(:stime)
171
now = Time.now
172
skew = (res.stime - now).abs.to_i
173
return "#{error_code}. Local time: #{now}, Server time: #{res.stime}, off by #{skew} seconds"
174
end
175
176
"Kerberos Error - #{error_code}"
177
end
178
end
179
180
# Runtime Decoding Error which can be raised by the Rex::Proto::Kerberos API
181
class KerberosDecodingError < KerberosError
182
def initialize(message = nil)
183
super(message || "Kerberos Decoding Error")
184
end
185
end
186
187
# Runtime Error which can be raised by the Rex::Proto::Kerberos API when the Kerberos target does not support
188
# the chosen Encryption method
189
class KerberosEncryptionNotSupported < KerberosError
190
# @return [Number] One of the encryption types defined within Rex::Proto::Kerberos::Crypto
191
attr_reader :encryption_type
192
193
def initialize(message = nil, encryption_type: nil)
194
super(message || "Kerberos target does not support the required encryption")
195
end
196
end
197
end
198
end
199
end
200
end
201
end
202
203