net-tns 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|