Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
rapid7
GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/kerberos/model/s4u_user_id.rb
31164 views
1
# -*- coding: binary -*-
2
3
module Rex
4
module Proto
5
module Kerberos
6
module Model
7
# This class provides a representation of the S4UUserID structure
8
# as defined in the Kerberos protocol.
9
class S4uUserId < Element
10
# @!attribute nonce
11
# @return [Integer] The nonce in KDC-REQ-BODY
12
attr_accessor :nonce
13
# @!attribute cname
14
# @return [Rex::Proto::Kerberos::Model::PrincipalName, nil] The principal name (optional)
15
attr_accessor :cname
16
# @!attribute crealm
17
# @return [String] The realm
18
attr_accessor :crealm
19
# @!attribute subject_certificate
20
# @return [String, nil] The subject certificate (optional)
21
attr_accessor :subject_certificate
22
# @!attribute options
23
# @return [String, nil] The options (optional)
24
attr_accessor :options
25
26
##
27
# //S4UUserID::= SEQUENCE {
28
# // nonce[0] UInt32, --the nonce in KDC - REQ - BODY
29
# // cname[1] PrincipalName OPTIONAL,
30
# // --Certificate mapping hints
31
# // crealm[2] Realm,
32
# // subject-certificate[3] OCTET STRING OPTIONAL,
33
# // options[4] BIT STRING OPTIONAL,
34
# // ...
35
# //}
36
37
38
def initialize(name, impersonate_type, realm, nonce)
39
self.nonce = nonce
40
# Set cname name_type based on dMSA flag
41
self.cname = Rex::Proto::Kerberos::Model::PrincipalName.new(
42
name_type: impersonate_type == 'dmsa' ? NameType::NT_PRINCIPAL : NameType::NT_ENTERPRISE,
43
name_string: [name]
44
)
45
self.crealm = realm
46
47
# Default options
48
self.options = impersonate_type == 'dmsa' ? ::Rex::Proto::Kerberos::Model::PaS4uX509UserOptions::UNCONDITIONAL_DELEGATION | ::Rex::Proto::Kerberos::Model::PaS4uX509UserOptions::SIGN_REPLY : ::Rex::Proto::Kerberos::Model::PaS4uX509UserOptions::SIGN_REPLY
49
end
50
51
# Decodes the S4UUserID from an input
52
#
53
# @param input [String, OpenSSL::ASN1::ASN1Data] the input to decode from
54
# @return [self] if decoding succeeds
55
# @raise [Rex::Proto::Kerberos::Model::Error::KerberosDecodingError] if decoding doesn't succeed
56
def decode(input)
57
case input
58
when String
59
decode_string(input)
60
when OpenSSL::ASN1::ASN1Data
61
decode_asn1(input)
62
else
63
raise ::Rex::Proto::Kerberos::Model::Error::KerberosDecodingError, 'Failed to decode S4UUserID, invalid input'
64
end
65
66
self
67
end
68
69
# Encodes the S4UUserID into an ASN.1 String
70
#
71
# @return [String]
72
def encode
73
elems = []
74
elems << OpenSSL::ASN1::ASN1Data.new([encode_nonce], 0, :CONTEXT_SPECIFIC)
75
elems << OpenSSL::ASN1::ASN1Data.new([encode_cname], 1, :CONTEXT_SPECIFIC) if cname
76
elems << OpenSSL::ASN1::ASN1Data.new([encode_crealm], 2, :CONTEXT_SPECIFIC)
77
elems << OpenSSL::ASN1::ASN1Data.new([encode_subject_certificate], 3, :CONTEXT_SPECIFIC) if subject_certificate
78
# Convert options to a byte array
79
options_bytes = [self.options].pack('N') # Pack as a big-endian unsigned 32-bit integer
80
elems << OpenSSL::ASN1::ASN1Data.new([OpenSSL::ASN1::BitString.new(options_bytes)], 4, :CONTEXT_SPECIFIC)
81
82
83
seq = OpenSSL::ASN1::Sequence.new(elems)
84
85
seq.to_der
86
end
87
88
private
89
90
# Encodes the nonce attribute
91
#
92
# @return [OpenSSL::ASN1::Integer]
93
def encode_nonce
94
OpenSSL::ASN1::Integer.new(nonce)
95
end
96
97
# Encodes the cname attribute
98
#
99
# @return [String]
100
def encode_cname
101
cname.encode
102
end
103
104
# Encodes the crealm attribute
105
#
106
# @return [OpenSSL::ASN1::GeneralString]
107
def encode_crealm
108
OpenSSL::ASN1::GeneralString.new(crealm)
109
end
110
111
# Encodes the subject_certificate attribute
112
#
113
# @return [OpenSSL::ASN1::OctetString]
114
def encode_subject_certificate
115
OpenSSL::ASN1::OctetString.new(subject_certificate)
116
end
117
118
# Encodes the options attribute
119
#
120
# @return [OpenSSL::ASN1::BitString]
121
def encode_options
122
OpenSSL::ASN1::BitString.new(options)
123
end
124
125
# Decodes the S4UUserID from a String
126
#
127
# @param input [String] the input to decode from
128
def decode_string(input)
129
asn1 = OpenSSL::ASN1.decode(input)
130
131
decode_asn1(asn1)
132
end
133
134
# Decodes the S4UUserID from an OpenSSL::ASN1::Sequence
135
#
136
# @param input [OpenSSL::ASN1::Sequence] the input to decode from
137
def decode_asn1(input)
138
seq_values = input.value
139
140
seq_values.each do |val|
141
case val.tag
142
when 0
143
self.nonce = val.value[0].value.to_i
144
when 1
145
self.cname = Rex::Proto::Kerberos::Model::PrincipalName.decode(val.value[0])
146
when 2
147
self.crealm = val.value[0].value
148
when 3
149
self.subject_certificate = val.value[0].value
150
when 4
151
self.options = val.value[0].value
152
else
153
raise ::Rex::Proto::Kerberos::Model::Error::KerberosDecodingError, 'Failed to decode S4UUserID SEQUENCE'
154
end
155
end
156
end
157
end
158
end
159
end
160
end
161
end
162