net-tns 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (45) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +202 -0
  3. data/bin/tns_oradb_version.rb +15 -0
  4. data/bin/tns_sid_enumeration.rb +52 -0
  5. data/bin/tns_sid_list.rb +43 -0
  6. data/lib/net/tns/client.rb +94 -0
  7. data/lib/net/tns/connection.rb +201 -0
  8. data/lib/net/tns/exceptions.rb +34 -0
  9. data/lib/net/tns/gem_version.rb +5 -0
  10. data/lib/net/tns/helpers/string_helpers.rb +49 -0
  11. data/lib/net/tns/packet.rb +82 -0
  12. data/lib/net/tns/packets/abort_packet.rb +12 -0
  13. data/lib/net/tns/packets/accept_packet.rb +19 -0
  14. data/lib/net/tns/packets/ack_packet.rb +7 -0
  15. data/lib/net/tns/packets/attention_packet.rb +9 -0
  16. data/lib/net/tns/packets/connect_packet.rb +55 -0
  17. data/lib/net/tns/packets/control_packet.rb +7 -0
  18. data/lib/net/tns/packets/data_packet.rb +20 -0
  19. data/lib/net/tns/packets/marker_packet.rb +18 -0
  20. data/lib/net/tns/packets/null_packet.rb +7 -0
  21. data/lib/net/tns/packets/redirect_packet.rb +10 -0
  22. data/lib/net/tns/packets/refuse_packet.rb +12 -0
  23. data/lib/net/tns/packets/resend_packet.rb +7 -0
  24. data/lib/net/tns/version.rb +15 -0
  25. data/lib/net/tns.rb +20 -0
  26. data/lib/net/tti/client.rb +90 -0
  27. data/lib/net/tti/connection.rb +142 -0
  28. data/lib/net/tti/crypto.rb +189 -0
  29. data/lib/net/tti/data_types/chunked_string.rb +63 -0
  30. data/lib/net/tti/data_types/key_value_pair.rb +25 -0
  31. data/lib/net/tti/data_types.rb +2 -0
  32. data/lib/net/tti/exceptions.rb +62 -0
  33. data/lib/net/tti/message.rb +50 -0
  34. data/lib/net/tti/messages/data_type_negotiation_request.rb +133 -0
  35. data/lib/net/tti/messages/data_type_negotiation_response.rb +9 -0
  36. data/lib/net/tti/messages/error_message.rb +14 -0
  37. data/lib/net/tti/messages/function_call.rb +46 -0
  38. data/lib/net/tti/messages/function_calls/authentication.rb +45 -0
  39. data/lib/net/tti/messages/function_calls/authentication_x64.rb +42 -0
  40. data/lib/net/tti/messages/function_calls/authentication_x86.rb +53 -0
  41. data/lib/net/tti/messages/function_calls/pre_authentication_response.rb +32 -0
  42. data/lib/net/tti/messages/protocol_negotiation_request.rb +29 -0
  43. data/lib/net/tti/messages/protocol_negotiation_response.rb +44 -0
  44. data/lib/net/tti.rb +18 -0
  45. 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,2 @@
1
+ require "net/tti/data_types/chunked_string"
2
+ require "net/tti/data_types/key_value_pair"
@@ -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,9 @@
1
+ module Net
2
+ module TTI
3
+ class DataTypeNegotiationResponse < Message
4
+ handles_response_for_ttc_code TTC_CODE_DATA_TYPE_NEGOTIATION
5
+ # BinData fields
6
+ rest :data
7
+ end
8
+ end
9
+ 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