net-tns 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/LICENSE +202 -0
- data/bin/tns_oradb_version.rb +15 -0
- data/bin/tns_sid_enumeration.rb +52 -0
- data/bin/tns_sid_list.rb +43 -0
- data/lib/net/tns/client.rb +94 -0
- data/lib/net/tns/connection.rb +201 -0
- data/lib/net/tns/exceptions.rb +34 -0
- data/lib/net/tns/gem_version.rb +5 -0
- data/lib/net/tns/helpers/string_helpers.rb +49 -0
- data/lib/net/tns/packet.rb +82 -0
- data/lib/net/tns/packets/abort_packet.rb +12 -0
- data/lib/net/tns/packets/accept_packet.rb +19 -0
- data/lib/net/tns/packets/ack_packet.rb +7 -0
- data/lib/net/tns/packets/attention_packet.rb +9 -0
- data/lib/net/tns/packets/connect_packet.rb +55 -0
- data/lib/net/tns/packets/control_packet.rb +7 -0
- data/lib/net/tns/packets/data_packet.rb +20 -0
- data/lib/net/tns/packets/marker_packet.rb +18 -0
- data/lib/net/tns/packets/null_packet.rb +7 -0
- data/lib/net/tns/packets/redirect_packet.rb +10 -0
- data/lib/net/tns/packets/refuse_packet.rb +12 -0
- data/lib/net/tns/packets/resend_packet.rb +7 -0
- data/lib/net/tns/version.rb +15 -0
- data/lib/net/tns.rb +20 -0
- data/lib/net/tti/client.rb +90 -0
- data/lib/net/tti/connection.rb +142 -0
- data/lib/net/tti/crypto.rb +189 -0
- data/lib/net/tti/data_types/chunked_string.rb +63 -0
- data/lib/net/tti/data_types/key_value_pair.rb +25 -0
- data/lib/net/tti/data_types.rb +2 -0
- data/lib/net/tti/exceptions.rb +62 -0
- data/lib/net/tti/message.rb +50 -0
- data/lib/net/tti/messages/data_type_negotiation_request.rb +133 -0
- data/lib/net/tti/messages/data_type_negotiation_response.rb +9 -0
- data/lib/net/tti/messages/error_message.rb +14 -0
- data/lib/net/tti/messages/function_call.rb +46 -0
- data/lib/net/tti/messages/function_calls/authentication.rb +45 -0
- data/lib/net/tti/messages/function_calls/authentication_x64.rb +42 -0
- data/lib/net/tti/messages/function_calls/authentication_x86.rb +53 -0
- data/lib/net/tti/messages/function_calls/pre_authentication_response.rb +32 -0
- data/lib/net/tti/messages/protocol_negotiation_request.rb +29 -0
- data/lib/net/tti/messages/protocol_negotiation_response.rb +44 -0
- data/lib/net/tti.rb +18 -0
- metadata +128 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
require 'openssl'
|
2
|
+
|
3
|
+
module Net::TTI
|
4
|
+
class Crypto
|
5
|
+
# Generates the encrypted password and encrypted client session key for
|
6
|
+
# authentication with a 10g server.
|
7
|
+
#
|
8
|
+
# @param username [String] The username for authentication.
|
9
|
+
# @param password [String] The password for authentication.
|
10
|
+
# @param enc_server_session_key [String] The encrypted server session key.
|
11
|
+
# provided by the server. This should be a 32-byte binary packed string.
|
12
|
+
# @return [Array<String>] The encrypted password and the encrypted client
|
13
|
+
# session key to use to authenticate with the server. These are returned
|
14
|
+
# as binary packed strings.
|
15
|
+
def self.get_10g_auth_values( username, password, enc_server_session_key )
|
16
|
+
# Hash the password and pad it to 16 bytes. This will be used as the key
|
17
|
+
# for encrypting the client session key and decrypting the server session key.
|
18
|
+
password_hash = hash_password_10g( username, password )
|
19
|
+
password_hash += "\0" * 8
|
20
|
+
|
21
|
+
# TODO: make random client session key
|
22
|
+
client_session_key = "FAF5034314546426F329B1DAB1CDC5B8FF94349E0875623160350B0E13A0DA36".tns_unhexify
|
23
|
+
|
24
|
+
# Encrypt client session key and decrypt the server session key, using the
|
25
|
+
# password hash as a key.
|
26
|
+
enc_client_session_key = openssl_encrypt( "AES-128-CBC", password_hash, nil, client_session_key )
|
27
|
+
server_session_key = openssl_decrypt( "AES-128-CBC", password_hash, nil, enc_server_session_key )
|
28
|
+
|
29
|
+
# Make the combined session key hash. This is used as the key to encrypt
|
30
|
+
# the password.
|
31
|
+
combo_session_key = create_combined_session_key_hash_10g( server_session_key, client_session_key )
|
32
|
+
|
33
|
+
# TODO: make random salt
|
34
|
+
salt = "4C31AFE05F3B012C0AE9AB0CDFF0C508".tns_unhexify
|
35
|
+
# Encrypt the salted password
|
36
|
+
enc_password = openssl_encrypt( "AES-128-CBC", combo_session_key, nil, salt + password, true )
|
37
|
+
|
38
|
+
return enc_password, enc_client_session_key
|
39
|
+
end
|
40
|
+
|
41
|
+
# Generates the encrypted password and encrypted client session key for
|
42
|
+
# authentication with an 11g server.
|
43
|
+
#
|
44
|
+
# @param password [String] The password for authentication.
|
45
|
+
# @param enc_server_session_key [String] The encrypted server session key.
|
46
|
+
# provided by the server. This should be a 48-byte binary packed string.
|
47
|
+
# @param auth_vfr_data [String] The value from the AUTH_VFR_DATA key-value
|
48
|
+
# pair provided by the server.
|
49
|
+
# @return [Array<String>] The encrypted password and the encrypted client
|
50
|
+
# session key to use to authenticate with the server. These are returned
|
51
|
+
# as binary packed strings.
|
52
|
+
def self.get_11g_auth_values( password, enc_server_session_key, auth_vfr_data )
|
53
|
+
# Hash the password and auth_vfr_data and pad it to 24 bytes. This will be
|
54
|
+
# used as the key for encrypting the client session key and decrypting the
|
55
|
+
# server session key.
|
56
|
+
password_hash = sha1_digest( password + auth_vfr_data ) + ("\0" * 4)
|
57
|
+
|
58
|
+
# TODO: make random client session key
|
59
|
+
client_session_key = "080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808080808".tns_unhexify
|
60
|
+
|
61
|
+
# Encrypt client session key and decrypt the server session key, using the
|
62
|
+
# password hash as a key.
|
63
|
+
enc_client_session_key = openssl_encrypt( "AES-192-CBC", password_hash, nil, client_session_key )
|
64
|
+
server_session_key = openssl_decrypt( "AES-192-CBC", password_hash, nil, enc_server_session_key )
|
65
|
+
|
66
|
+
# Make the combined session key hash. This is used as the key to encrypt
|
67
|
+
# the password.
|
68
|
+
combo_session_key = create_combined_session_key_hash_11g( server_session_key, client_session_key )
|
69
|
+
|
70
|
+
# TODO: make random salt
|
71
|
+
salt = "4C31AFE05F3B012C0AE9AB0CDFF0C508".tns_unhexify
|
72
|
+
# Encrypt the salted password
|
73
|
+
enc_password = openssl_encrypt( "AES-192-CBC", combo_session_key, nil, salt + password, true )
|
74
|
+
|
75
|
+
return enc_password, enc_client_session_key
|
76
|
+
end
|
77
|
+
|
78
|
+
|
79
|
+
|
80
|
+
# Generates the password hash for use in 10g authentication.
|
81
|
+
#
|
82
|
+
# @param username [String] The username for authentication.
|
83
|
+
# @param password [String] The password for authentication.
|
84
|
+
# @return [String] The password hash, as a binary packed string.
|
85
|
+
def self.hash_password_10g( username, password )
|
86
|
+
uspw = (username + password).upcase().encode( Encoding::UTF_16BE )
|
87
|
+
key = "0123456789abcdef".tns_unhexify # fixed key used for 10g hashing
|
88
|
+
|
89
|
+
# Pad the username-password to an 8-byte boundary
|
90
|
+
if ( uspw.length % 4 > 0 )
|
91
|
+
padding_length = 4 - ( uspw.length % 4 )
|
92
|
+
uspw += ("\0".encode( Encoding::UTF_16BE )) * padding_length
|
93
|
+
end
|
94
|
+
|
95
|
+
key2 = openssl_encrypt( "DES-CBC", key, nil, uspw, false )
|
96
|
+
key2 = key2[-8,8]
|
97
|
+
|
98
|
+
pwhash = openssl_encrypt( "DES-CBC", key2, nil, uspw, false )
|
99
|
+
pwhash = pwhash[-8,8]
|
100
|
+
end
|
101
|
+
|
102
|
+
# Generates the combined session key hash, for use in encrypting the
|
103
|
+
# password in authentication.
|
104
|
+
#
|
105
|
+
# @param server_session_key [String] The unencrypted server session key, as
|
106
|
+
# a binary packed string.
|
107
|
+
# @param client_session_key [String] The unencrypted client session key, as
|
108
|
+
# a binary packed string.
|
109
|
+
# @return [String] The hash of the combined session key, as a binary packed
|
110
|
+
# string.
|
111
|
+
def self.create_combined_session_key_hash_10g( server_session_key, client_session_key )
|
112
|
+
# Unpack the session keys into byte arrays
|
113
|
+
server_key_bytes = server_session_key.unpack( "C*" )
|
114
|
+
client_key_bytes = client_session_key.unpack( "C*" )
|
115
|
+
combo_session_key = ""
|
116
|
+
|
117
|
+
# XOR bytes 17-32 of the session keys to make the combined session key
|
118
|
+
for byte_itr in (16..31)
|
119
|
+
combo_session_key += (server_key_bytes[ byte_itr ] ^ client_key_bytes[ byte_itr ]).chr
|
120
|
+
end
|
121
|
+
|
122
|
+
# Hash the combined session key
|
123
|
+
return md5_digest( combo_session_key )
|
124
|
+
end
|
125
|
+
|
126
|
+
# Generates the combined session key hash, for use in encrypting the
|
127
|
+
# password in authentication.
|
128
|
+
#
|
129
|
+
# @param server_session_key [String] The unencrypted server session key, as
|
130
|
+
# a binary packed string.
|
131
|
+
# @param client_session_key [String] The unencrypted client session key, as
|
132
|
+
# a binary packed string.
|
133
|
+
# @return [String] The hash of the combined session key, as a binary packed
|
134
|
+
# string.
|
135
|
+
def self.create_combined_session_key_hash_11g( server_session_key, client_session_key )
|
136
|
+
# make combined session key
|
137
|
+
server_key_bytes = server_session_key.unpack( "C*" )
|
138
|
+
client_key_bytes = client_session_key.unpack( "C*" )
|
139
|
+
combo_session_key = ""
|
140
|
+
for byte_itr in (16..39)
|
141
|
+
combo_session_key += (server_key_bytes[ byte_itr ] ^ client_key_bytes[ byte_itr ]).chr
|
142
|
+
end
|
143
|
+
|
144
|
+
# hash combined session key
|
145
|
+
combo_session_key = ( md5_digest(combo_session_key[0,16]) +
|
146
|
+
md5_digest(combo_session_key[16,combo_session_key.length]) )
|
147
|
+
combo_session_key = combo_session_key[0,24]
|
148
|
+
|
149
|
+
return combo_session_key
|
150
|
+
end
|
151
|
+
|
152
|
+
|
153
|
+
# Helper function for encryption.
|
154
|
+
def self.openssl_encrypt( cipher, key, iv, data, padding=false )
|
155
|
+
cipher = OpenSSL::Cipher::Cipher.new( cipher )
|
156
|
+
cipher.encrypt
|
157
|
+
cipher.key = key
|
158
|
+
cipher.iv = iv unless iv.nil?
|
159
|
+
cipher.padding = 0 unless padding
|
160
|
+
|
161
|
+
ciphertext = cipher.update( data ) + cipher.final
|
162
|
+
end
|
163
|
+
|
164
|
+
# Helper function for decryption.
|
165
|
+
def self.openssl_decrypt( cipher, key, iv, data, padding=false )
|
166
|
+
cipher = OpenSSL::Cipher::Cipher.new( cipher )
|
167
|
+
cipher.decrypt
|
168
|
+
cipher.key = key
|
169
|
+
cipher.iv = iv unless iv.nil?
|
170
|
+
cipher.padding = 0 unless padding
|
171
|
+
|
172
|
+
ciphertext = cipher.update( data ) + cipher.final
|
173
|
+
end
|
174
|
+
|
175
|
+
# @return the MD5 digest (as a binary string) for the given input string
|
176
|
+
def self.md5_digest(input_str)
|
177
|
+
digester=Digest::MD5.new()
|
178
|
+
digester.update(input_str)
|
179
|
+
return digester.digest
|
180
|
+
end
|
181
|
+
|
182
|
+
# @return the SHA1 digest (as a binary string) for the given input string
|
183
|
+
def self.sha1_digest(input_str)
|
184
|
+
digester=Digest::SHA1.new()
|
185
|
+
digester.update(input_str)
|
186
|
+
return digester.digest
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,63 @@
|
|
1
|
+
require "bindata"
|
2
|
+
|
3
|
+
module Net
|
4
|
+
module TTI
|
5
|
+
module DataTypes
|
6
|
+
class ChunkedString < BinData::BasePrimitive
|
7
|
+
# The marker to indicate that a string is being divided into multiple chunks
|
8
|
+
MULTI_CHUNK_MARKER = 0xFE
|
9
|
+
MULTI_CHUNK_TERMINATOR = 0x00
|
10
|
+
# The apparent maximum chunk length used by Oracle TNS implementations
|
11
|
+
MAX_CHUNK_LENGTH = 0x40
|
12
|
+
|
13
|
+
def sensible_default
|
14
|
+
return ""
|
15
|
+
end
|
16
|
+
|
17
|
+
def read_and_return_value(io)
|
18
|
+
begin
|
19
|
+
length = unmarshal_uint8(io)
|
20
|
+
rescue EOFError
|
21
|
+
return ""
|
22
|
+
end
|
23
|
+
|
24
|
+
if length == MULTI_CHUNK_MARKER
|
25
|
+
data = ""
|
26
|
+
while (length = unmarshal_uint8(io)) != MULTI_CHUNK_TERMINATOR
|
27
|
+
data += io.readbytes(length)
|
28
|
+
end
|
29
|
+
|
30
|
+
return data
|
31
|
+
else
|
32
|
+
return io.readbytes(length)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
def value_to_binary_string(value)
|
37
|
+
return "" if value.empty?
|
38
|
+
|
39
|
+
if value.length > MAX_CHUNK_LENGTH
|
40
|
+
value_index = 0
|
41
|
+
|
42
|
+
binary_string = ""
|
43
|
+
binary_string << [MULTI_CHUNK_MARKER].pack("C")
|
44
|
+
while value_index < value.length
|
45
|
+
chunk = value[value_index, MAX_CHUNK_LENGTH]
|
46
|
+
binary_string << [chunk.length, chunk].pack("Ca*")
|
47
|
+
value_index += MAX_CHUNK_LENGTH
|
48
|
+
end
|
49
|
+
binary_string << [MULTI_CHUNK_TERMINATOR].pack("C")
|
50
|
+
else
|
51
|
+
return [value.length, value].pack("Ca*")
|
52
|
+
end
|
53
|
+
end
|
54
|
+
|
55
|
+
private
|
56
|
+
def unmarshal_uint8(io)
|
57
|
+
int_string = io.readbytes(1)
|
58
|
+
return int_string.unpack("C").first
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require "bindata"
|
2
|
+
require "net/tti/data_types/chunked_string"
|
3
|
+
|
4
|
+
module Net
|
5
|
+
module TTI
|
6
|
+
module DataTypes
|
7
|
+
class KeyValuePair < BinData::Record
|
8
|
+
# In earlier dialects, the 4 bytes before the strings appeared to contain
|
9
|
+
# the total length of the string. In more recent dialects, this no longer
|
10
|
+
# seems to be the case. However, a 32-bit null here still appears to
|
11
|
+
# signal that there is no value.
|
12
|
+
uint32le :unknown1, :value => lambda {kvp_key.length}
|
13
|
+
chunked_string :kvp_key, :onlyif => lambda {unknown1 != 0}
|
14
|
+
uint32le :unknown2, :value => lambda {kvp_value.length}
|
15
|
+
chunked_string :kvp_value, :onlyif => lambda {unknown2 != 0}
|
16
|
+
uint32le :flags
|
17
|
+
|
18
|
+
def set(key, value)
|
19
|
+
self.kvp_key.data = key
|
20
|
+
self.kvp_value.data = value
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Net::TTI
|
2
|
+
module Exceptions
|
3
|
+
class TTIException < StandardError
|
4
|
+
end
|
5
|
+
|
6
|
+
class ProtocolException < TTIException
|
7
|
+
end
|
8
|
+
|
9
|
+
class UnsupportedTarget < TTIException
|
10
|
+
end
|
11
|
+
|
12
|
+
class UnsupportedPlatform < UnsupportedTarget
|
13
|
+
def initialize( platform )
|
14
|
+
super( "Unsupported platform: #{platform}" )
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class UnsupportedTNSVersion < UnsupportedTarget
|
19
|
+
def initialize( version )
|
20
|
+
super( "Unsupported version: #{version}" )
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
class ErrorMessageReceived < TTIException
|
27
|
+
ERROR_REGEX = /ORA\-(\d+)(?:\:\ (.*))?/
|
28
|
+
ERROR_REGEX_INDEX_CODE = 1
|
29
|
+
ERROR_REGEX_INDEX_DESCRIPTION = 2
|
30
|
+
|
31
|
+
# Attempts to parse and return the "ORA-xxxxx" error code from the error message
|
32
|
+
# @return [Integer] A numeric error code, or nil if the code could not be determined
|
33
|
+
def error_code()
|
34
|
+
matches = ERROR_REGEX.match( self.message )
|
35
|
+
error_code = matches[ERROR_REGEX_INDEX_CODE] unless( matches.nil? or matches[ERROR_REGEX_INDEX_CODE].nil? )
|
36
|
+
error_code = error_code.to_i unless error_code.nil?
|
37
|
+
return error_code
|
38
|
+
end
|
39
|
+
|
40
|
+
|
41
|
+
# Attempts to parse and return the error description after the "ORA-xxxxx"
|
42
|
+
# error code in the error message
|
43
|
+
# @return [String] A string containing the error description, or nil if the description could not be determined
|
44
|
+
def error_description()
|
45
|
+
matches = ERROR_REGEX.match( self.message )
|
46
|
+
return matches[ERROR_REGEX_INDEX_DESCRIPTION] unless( matches.nil? or matches[ERROR_REGEX_INDEX_DESCRIPTION].nil? )
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
class AuthenticationError < ErrorMessageReceived
|
51
|
+
end
|
52
|
+
|
53
|
+
class InvalidCredentialsError < AuthenticationError
|
54
|
+
end
|
55
|
+
|
56
|
+
class AccountLockedOutError < AuthenticationError
|
57
|
+
end
|
58
|
+
|
59
|
+
class PasswordExpiredError < AuthenticationError
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require "bindata"
|
2
|
+
|
3
|
+
module Net
|
4
|
+
module TTI
|
5
|
+
class Message < BinData::Record
|
6
|
+
TTC_CODE_PROTOCOL_NEGOTIATION = 0x1
|
7
|
+
TTC_CODE_DATA_TYPE_NEGOTIATION = 0x2
|
8
|
+
TTC_CODE_FUNCTION_CALL = 0x3
|
9
|
+
TTC_CODE_ERROR = 0x4
|
10
|
+
TTC_CODE_OK = 0x8
|
11
|
+
|
12
|
+
# BinData fields
|
13
|
+
uint8 :ttc_code, :initial_value => :_ttc_code
|
14
|
+
|
15
|
+
def _ttc_code
|
16
|
+
raise NotImplementedError
|
17
|
+
end
|
18
|
+
private :_ttc_code
|
19
|
+
|
20
|
+
def self.handles_response_for_ttc_code(ttc_code)
|
21
|
+
@@ttc_classes ||= {}
|
22
|
+
@@ttc_codes ||= {}
|
23
|
+
if @@ttc_classes.has_key?(ttc_code)
|
24
|
+
existing_class = @@ttc_classes[ttc_code]
|
25
|
+
raise("Duplicate TTC response handlers defined: #{existing_class} and #{self} both have TTC code of #{ttc_code}")
|
26
|
+
end
|
27
|
+
|
28
|
+
@@ttc_classes[ttc_code] = self
|
29
|
+
@@ttc_codes[self] = ttc_code
|
30
|
+
return nil
|
31
|
+
end
|
32
|
+
|
33
|
+
def self.from_data_string( raw_message )
|
34
|
+
ttc_code = raw_message[0].unpack("C").first
|
35
|
+
|
36
|
+
unless message_class = @@ttc_classes[ ttc_code ]
|
37
|
+
raise Net::TNS::Exceptions::TnsException.new( "Unknown TTC code: #{ttc_code}" )
|
38
|
+
end
|
39
|
+
|
40
|
+
new_message = message_class.new
|
41
|
+
new_message.read( raw_message )
|
42
|
+
|
43
|
+
return new_message
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
require "pathname"
|
50
|
+
Dir.glob("#{Pathname.new(__FILE__).dirname}/messages/**/*.rb") { |file| require file }
|
@@ -0,0 +1,133 @@
|
|
1
|
+
module Net
|
2
|
+
module TTI
|
3
|
+
class DataTypeNegotiationRequest < Message
|
4
|
+
# BinData fields
|
5
|
+
|
6
|
+
# Not sure why this is duplicated, but clients always send the same
|
7
|
+
# character set in both fields.
|
8
|
+
# Character sets:
|
9
|
+
# 0x00b2 (178) - US-ASCII
|
10
|
+
# 0x0369 (873) - UTF-8
|
11
|
+
uint16le :charset1
|
12
|
+
uint16le :charset2
|
13
|
+
uint8 :unknown1
|
14
|
+
uint8 :unknown2_length, :value => lambda { unknown2.length }
|
15
|
+
string :unknown2
|
16
|
+
uint8 :unknown3_length, :value => lambda { unknown3.length }
|
17
|
+
string :unknown3
|
18
|
+
string :unknown4
|
19
|
+
|
20
|
+
UNKNOWN4_LINUX = (
|
21
|
+
"800000003c3c3c80000000d007000100010001000000020002000a0000000800" +
|
22
|
+
"0800010000000c000c000a000000170017000100000018001800010000001900" +
|
23
|
+
"190018001900010000001a001a0019001a00010000001b001b000a001b000100" +
|
24
|
+
"00001c001c0016001c00010000001d001d0017001d00010000001e001e001700" +
|
25
|
+
"1e00010000001f001f0019001f0001000000200020000a002000010000002100" +
|
26
|
+
"21000a002100010000000a000a00010000000b000b0001000000280028000100" +
|
27
|
+
"0000290029000100000075007500010000007800780001000001220122000100" +
|
28
|
+
"0001230123000101230001000001240124000100000125012500010000012601" +
|
29
|
+
"2600010000012a012a00010000012b012b00010000012c012c00010000012d01" +
|
30
|
+
"2d00010000012e012e00010000012f012f000100000130013000010000013101" +
|
31
|
+
"3100010000013201320001000001330133000100000134013400010000013501" +
|
32
|
+
"3500010000013601360001000001370137000100000138013800010000013901" +
|
33
|
+
"3900010000013b013b00010000013c013c00010000013d013d00010000013e01" +
|
34
|
+
"3e00010000013f013f0001000001400140000100000141014100010000014201" +
|
35
|
+
"4200010000014301430001000001470147000100000148014800010000014901" +
|
36
|
+
"4900010000014b014b00010000014d014d00010000014e014e00010000014f01" +
|
37
|
+
"4f00010000015001500001000001510151000100000152015200010000015301" +
|
38
|
+
"5300010000015401540001000001550155000100000156015600010000015701" +
|
39
|
+
"57000101570001000001580158000100000159015900010000015a015a000100" +
|
40
|
+
"00015c015c00010000015d015d00010000016201620001000001630163000100" +
|
41
|
+
"000167016700010000016b016b00010000017c017c0001014200010000017d01" +
|
42
|
+
"7d00010000017e017e00010000017f017f000100000180018000010000018101" +
|
43
|
+
"8100010000018201820001000001830183000100000184018400010000018501" +
|
44
|
+
"8500010000018601860001000001870187000100000189018900010000018a01" +
|
45
|
+
"8a00010000018b018b00010000018c018c00010000018d018d00010000018e01" +
|
46
|
+
"8e00010000018f018f0001000001900190000100000191019100010000019401" +
|
47
|
+
"9400010125000100000195019500010000019601960001000001970197000100" +
|
48
|
+
"00019d019d00010000019e019e00010000019f019f0001000001a001a0000100" +
|
49
|
+
"0001a101a10001000001a201a20001000001a301a30001000001a401a4000100" +
|
50
|
+
"0001a501a50001000001a601a60001000001a701a70001000001a801a8000100" +
|
51
|
+
"0001a901a90001000001aa01aa0001000001ab01ab0001000001ad01ad000100" +
|
52
|
+
"0001ae01ae0001000001af01af0001000001b001b00001000001b101b1000100" +
|
53
|
+
"0001c101c10001000001c201c2000101250001000001c601c60001000001c701" +
|
54
|
+
"c70001000001c801c80001000001c901c90001000001ca01ca0001019f000100" +
|
55
|
+
"0001cb01cb000101a00001000001cc01cc000101a20001000001cd01cd000101" +
|
56
|
+
"a30001000001ce01ce000101b10001000001cf01cf000101220001000001d201" +
|
57
|
+
"d20001000001d301d3000101ab0001000001d401d40001000001d501d5000100" +
|
58
|
+
"0001d601d60001000001d701d70001000001d801d80001000001d901d9000100" +
|
59
|
+
"0001da01da0001000001db01db0001000001dc01dc0001000001dd01dd000100" +
|
60
|
+
"0001de01de0001000001df01df0001000001e001e00001000001e101e1000100" +
|
61
|
+
"0001e201e20001000001e301e30001016b0001000001e401e40001000001e501" +
|
62
|
+
"e50001000001e601e60001000001ea01ea0001000001eb01eb0001000001ec01" +
|
63
|
+
"ec0001000001ed01ed0001000001ee01ee0001000001ef01ef0001000001f001" +
|
64
|
+
"f00001000001f201f20001000001f301f30001000001f401f40001000001f501" +
|
65
|
+
"f50001000001f601f60001000001fd01fd0001000001fe01fe00010000020102" +
|
66
|
+
"0100010000020202020001000002040204000100000205020500010000020602" +
|
67
|
+
"0600010000020702070001000002080208000100000209020900010000020a02" +
|
68
|
+
"0a00010000020b020b00010000020c020c00010000020d020d00010000020e02" +
|
69
|
+
"0e00010000020f020f0001000002100210000100000211021100010000021202" +
|
70
|
+
"1200010000021302130001000002140214000100000215021500010000021602" +
|
71
|
+
"1600010000021702170001000002180218000100000219021900010000021a02" +
|
72
|
+
"1a00010000021b021b00010000021c021c00010000021d021d00010000021e02" +
|
73
|
+
"1e00010000021f021f0001000002200220000100000221022100010000022202" +
|
74
|
+
"2200010000022302230001000002240224000100000225022500010000022602" +
|
75
|
+
"2600010000022702270001000002280228000100000229022900010000022a02" +
|
76
|
+
"2a00010000022b022b00010000022c022c00010000022d022d00010000022e02" +
|
77
|
+
"2e00010000022f022f0001000002310231000100000232023200010000023302" +
|
78
|
+
"3300010000023402340001000002370237000100000238023800010000023902" +
|
79
|
+
"3900010000023a023a00010000023b023b00010000023c023c00010000023d02" +
|
80
|
+
"3d00010000023e023e00010000023f023f000100000240024000010000024102" +
|
81
|
+
"4100010000024202420001000002430243000100000244024400010000024502" +
|
82
|
+
"4500010000024602460001000002470247000100000248024800010000024902" +
|
83
|
+
"490001000000030002000a000000040002000a00000005000100010000000600" +
|
84
|
+
"02000a000000070002000a00000009000100010000000d0000000e0000000f00" +
|
85
|
+
"1700010000001000000011000000120000001300000014000000150000001600" +
|
86
|
+
"00002700780001015d0001012600010000003a003a0001000000440002000a00" +
|
87
|
+
"000045000000460000004a006d00010000004c0000005b0002000a0000005e00" +
|
88
|
+
"0100010000005f00170001000000600060000100000061006000010000006400" +
|
89
|
+
"6400010000006500650001000000660066000100000068000000690000006a00" +
|
90
|
+
"6a00010000006c006d00010000006d006d00010000006e006f00010000006f00" +
|
91
|
+
"6f00010000007000700001000000710071000100000072007200010000007300" +
|
92
|
+
"7300010000007400660001000000760000007700000079007900010000007a00" +
|
93
|
+
"7a00010000007b007b0001000000880000009200920001000000930093000100" +
|
94
|
+
"0000980002000a000000990002000a0000009a0002000a0000009b0001000100" +
|
95
|
+
"00009c000c000a000000ac0002000a000000b200b20001000000b300b3000100" +
|
96
|
+
"0000b400b40001000000b500b50001000000b600b60001000000b700b7000100" +
|
97
|
+
"0000b8000c000a000000b900b20001000000ba00b30001000000bb00b4000100" +
|
98
|
+
"0000bc00b50001000000bd00b60001000000be00b70001000000bf000000c000" +
|
99
|
+
"0000c300700001000000c400710001000000c500720001000000d000d0000100" +
|
100
|
+
"0000d1000000e700e70001000000e800e70001000000e900e90001000000f100" +
|
101
|
+
"6d0001000002030203000100000000").tns_unhexify
|
102
|
+
|
103
|
+
def _ttc_code()
|
104
|
+
TTC_CODE_DATA_TYPE_NEGOTIATION
|
105
|
+
end
|
106
|
+
private :_ttc_code
|
107
|
+
|
108
|
+
def self.create_request(platform)
|
109
|
+
request = self.new
|
110
|
+
request.character_set = 0x00b2
|
111
|
+
request.unknown1 = 0x02
|
112
|
+
request.unknown2 = "060101010d01010401010101010101ffff0308030001003f01073f010101010301".tns_unhexify
|
113
|
+
request.unknown3 = "0201000018".tns_unhexify
|
114
|
+
|
115
|
+
case platform
|
116
|
+
when :linux
|
117
|
+
request.unknown4 = UNKNOWN4_LINUX
|
118
|
+
when :windows
|
119
|
+
request.unknown4 = "800000003c3c3c80000000d007".tns_unhexify
|
120
|
+
else
|
121
|
+
raise Net::TTI::Exceptions::UnsupportedPlatform.new( platform )
|
122
|
+
end
|
123
|
+
|
124
|
+
return request
|
125
|
+
end
|
126
|
+
|
127
|
+
def character_set=(charset)
|
128
|
+
self.charset1 = charset
|
129
|
+
self.charset2 = charset
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
module Net
|
2
|
+
module TTI
|
3
|
+
class ErrorMessage < Message
|
4
|
+
handles_response_for_ttc_code TTC_CODE_ERROR
|
5
|
+
|
6
|
+
# BinData fields
|
7
|
+
string :unknown1, :read_length => 6
|
8
|
+
uint16le :unknown2
|
9
|
+
string :unknown3, :read_length => lambda { unknown2 == 0x01 ? 87 : 57 }
|
10
|
+
uint8 :message_length
|
11
|
+
string :message, :read_length => lambda { message_length }
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Net
|
2
|
+
module TTI
|
3
|
+
class FunctionCall < Message
|
4
|
+
handles_response_for_ttc_code TTC_CODE_FUNCTION_CALL
|
5
|
+
|
6
|
+
FUNCTION_CODE_PRE_AUTH = 0x76
|
7
|
+
FUNCTION_CODE_AUTH = 0x73
|
8
|
+
|
9
|
+
# BinData fields
|
10
|
+
# The function code: 0x76 => preauth, 0x73 => auth
|
11
|
+
uint8 :function_code, :initial_value => :_function_code
|
12
|
+
uint8 :sequence_number, :initial_value => :_sequence_number
|
13
|
+
|
14
|
+
def _ttc_code
|
15
|
+
return TTC_CODE_FUNCTION_CALL
|
16
|
+
end
|
17
|
+
private :_ttc_code
|
18
|
+
|
19
|
+
def _function_code
|
20
|
+
raise NotImplementedError
|
21
|
+
end
|
22
|
+
private :_function_code
|
23
|
+
|
24
|
+
def _sequence_number
|
25
|
+
@@seq_num ||= 0
|
26
|
+
@@seq_num += 1
|
27
|
+
return @@seq_num
|
28
|
+
end
|
29
|
+
private :_sequence_number
|
30
|
+
|
31
|
+
def to_binary_s
|
32
|
+
if sequence_number == 0
|
33
|
+
sequence_number = FunctionCall.next_sequence_number
|
34
|
+
end
|
35
|
+
|
36
|
+
super
|
37
|
+
end
|
38
|
+
|
39
|
+
def self.next_sequence_number
|
40
|
+
@@last_sequence_number ||= 0
|
41
|
+
@@last_sequence_number = (@@last_sequence_number + 1) % 256
|
42
|
+
return @@last_sequence_number
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,45 @@
|
|
1
|
+
require "net/tti/data_types"
|
2
|
+
|
3
|
+
module Net
|
4
|
+
module TTI
|
5
|
+
class Authentication < FunctionCall
|
6
|
+
LOGON_MODE_PRE_AUTH = 0x00000001
|
7
|
+
LOGON_MODE_AUTH = 0x00000101
|
8
|
+
|
9
|
+
def self.create_pre_auth_request(target_architecture)
|
10
|
+
case target_architecture
|
11
|
+
when :x86
|
12
|
+
return PreAuthenticationX86.new
|
13
|
+
when :x64
|
14
|
+
return PreAuthenticationX64.new
|
15
|
+
else
|
16
|
+
raise Net::TTI::Exceptions::UnsupportedPlatform.new(target_architecture)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.create_auth_request(target_architecture)
|
21
|
+
case target_architecture
|
22
|
+
when :x86
|
23
|
+
return AuthenticationX86.new
|
24
|
+
when :x64
|
25
|
+
return AuthenticationX64.new
|
26
|
+
else
|
27
|
+
raise Net::TTI::Exceptions::UnsupportedPlatform.new(target_architecture)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def add_parameter( key, value, flags=0 )
|
32
|
+
kvp = DataTypes::KeyValuePair.new( :kvp_key => key, :kvp_value => value, :flags => flags )
|
33
|
+
self.parameters << kvp
|
34
|
+
end
|
35
|
+
|
36
|
+
def enc_client_session_key=(enc_client_session_key)
|
37
|
+
add_parameter( "AUTH_SESSKEY", enc_client_session_key.tns_hexify.upcase, 1 )
|
38
|
+
end
|
39
|
+
|
40
|
+
def enc_password=(enc_password)
|
41
|
+
add_parameter( "AUTH_PASSWORD", enc_password.tns_hexify.upcase )
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|