librex 0.0.5 → 0.0.6
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +1 -1
- data/Rakefile +13 -0
- data/lib/rex.rb +4 -1
- data/lib/rex/assembly/nasm.rb +4 -0
- data/lib/rex/compat.rb +31 -1
- data/lib/rex/encoder/alpha2/generic.rb +11 -10
- data/lib/rex/exceptions.rb +1 -1
- data/lib/rex/exploitation/egghunter.rb +27 -0
- data/lib/rex/file.rb +13 -0
- data/lib/rex/io/stream.rb +9 -1
- data/lib/rex/io/stream_abstraction.rb +18 -7
- data/lib/rex/io/stream_server.rb +2 -2
- data/lib/rex/job_container.rb +1 -1
- data/lib/rex/mime/message.rb +5 -4
- data/lib/rex/ole.rb +83 -6
- data/lib/rex/ole/propset.rb +144 -0
- data/lib/rex/parser/ip360_aspl_xml.rb +102 -0
- data/lib/rex/parser/ip360_xml.rb +93 -0
- data/lib/rex/parser/nessus_xml.rb +118 -0
- data/lib/rex/parser/netsparker_xml.rb +94 -0
- data/lib/rex/parser/retina_xml.rb +109 -0
- data/lib/rex/post/meterpreter/channel.rb +15 -8
- data/lib/rex/post/meterpreter/client.rb +32 -3
- data/lib/rex/post/meterpreter/extensions/sniffer/sniffer.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/dir.rb +14 -5
- data/lib/rex/post/meterpreter/extensions/stdapi/fs/file.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket.rb +3 -3
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/tcp_client_channel.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/net/socket_subsystem/udp_channel.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/stdapi.rb +5 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/event_log.rb +16 -8
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process.rb +16 -7
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/process_subsystem/image.rb +1 -1
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/registry_subsystem/registry_key.rb +15 -4
- data/lib/rex/post/meterpreter/extensions/stdapi/sys/thread.rb +13 -7
- data/lib/rex/post/meterpreter/extensions/stdapi/tlv.rb +20 -0
- data/lib/rex/post/meterpreter/extensions/stdapi/webcam/webcam.rb +63 -0
- data/lib/rex/post/meterpreter/packet_dispatcher.rb +18 -7
- data/lib/rex/post/meterpreter/packet_response_waiter.rb +10 -17
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/core.rb +1 -1
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/networkpug.rb +16 -6
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/sniffer.rb +4 -5
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi.rb +2 -0
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/fs.rb +4 -2
- data/lib/rex/post/meterpreter/ui/console/command_dispatcher/stdapi/webcam.rb +157 -0
- data/lib/rex/proto/dhcp/server.rb +8 -4
- data/lib/rex/proto/http/client.rb +19 -45
- data/lib/rex/proto/http/packet.rb +8 -5
- data/lib/rex/proto/http/response.rb +8 -3
- data/lib/rex/proto/http/server.rb +1 -1
- data/lib/rex/proto/proxy/socks4a.rb +4 -4
- data/lib/rex/proto/rfb.rb +19 -0
- data/lib/rex/proto/rfb.rb.ut.rb +37 -0
- data/lib/rex/proto/rfb/cipher.rb +78 -0
- data/lib/rex/proto/rfb/client.rb +207 -0
- data/lib/rex/proto/rfb/constants.rb +52 -0
- data/lib/rex/proto/tftp/server.rb +20 -17
- data/lib/rex/services/local_relay.rb +1 -1
- data/lib/rex/socket.rb +69 -10
- data/lib/rex/socket/comm/local.rb +7 -4
- data/lib/rex/socket/range_walker.rb +14 -1
- data/lib/rex/text.rb +28 -3
- data/lib/rex/text.rb.ut.rb +14 -0
- data/lib/rex/thread_factory.rb +42 -0
- data/lib/rex/ui/text/input/buffer.rb +1 -1
- data/lib/rex/zip/archive.rb +74 -9
- data/lib/rex/zip/entry.rb +6 -1
- metadata +22 -7
@@ -0,0 +1,19 @@
|
|
1
|
+
##
|
2
|
+
# $Id: $
|
3
|
+
##
|
4
|
+
|
5
|
+
##
|
6
|
+
#
|
7
|
+
# RFB protocol support
|
8
|
+
#
|
9
|
+
# by Joshua J. Drake <jduck>
|
10
|
+
#
|
11
|
+
# Based on:
|
12
|
+
# vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
|
13
|
+
# vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
|
14
|
+
#
|
15
|
+
##
|
16
|
+
|
17
|
+
require 'rex/proto/rfb/constants'
|
18
|
+
require 'rex/proto/rfb/cipher'
|
19
|
+
require 'rex/proto/rfb/client'
|
@@ -0,0 +1,37 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
##
|
4
|
+
# $Id: $
|
5
|
+
##
|
6
|
+
|
7
|
+
##
|
8
|
+
#
|
9
|
+
# RFB protocol support
|
10
|
+
#
|
11
|
+
# by Joshua J. Drake <jduck>
|
12
|
+
#
|
13
|
+
# Based on:
|
14
|
+
# vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
|
15
|
+
# vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
|
16
|
+
#
|
17
|
+
##
|
18
|
+
|
19
|
+
require 'rex/socket'
|
20
|
+
require 'rex/proto/rfb'
|
21
|
+
|
22
|
+
sd = Rex::Socket::Tcp.create('PeerHost' => ENV["VNCHOST"], 'PeerPort' => Rex::Proto::RFB::DefaultPort)
|
23
|
+
|
24
|
+
v = Rex::Proto::RFB::Client.new(sd)
|
25
|
+
if not v.connect('password')
|
26
|
+
$stderr.puts v.error
|
27
|
+
exit(1)
|
28
|
+
end
|
29
|
+
|
30
|
+
loop {
|
31
|
+
sret = select([sd],nil,nil,10)
|
32
|
+
puts sret.inspect
|
33
|
+
if sret and sret[0].include? sd
|
34
|
+
buf = sd.sysread(8192)
|
35
|
+
puts "read #{buf.length} bytes: #{buf.inspect}"
|
36
|
+
end
|
37
|
+
}
|
@@ -0,0 +1,78 @@
|
|
1
|
+
##
|
2
|
+
# $Id: $
|
3
|
+
##
|
4
|
+
|
5
|
+
##
|
6
|
+
#
|
7
|
+
# RFB protocol support
|
8
|
+
#
|
9
|
+
# by Joshua J. Drake <jduck>
|
10
|
+
#
|
11
|
+
# Based on:
|
12
|
+
# vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
|
13
|
+
# vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
|
14
|
+
#
|
15
|
+
##
|
16
|
+
|
17
|
+
# Required for VNC authentication
|
18
|
+
require 'openssl'
|
19
|
+
|
20
|
+
module Rex
|
21
|
+
module Proto
|
22
|
+
module RFB
|
23
|
+
|
24
|
+
##
|
25
|
+
# A bit of information about the DES algorithm was found here:
|
26
|
+
# http://www.vidarholen.net/contents/junk/vnc.html
|
27
|
+
#
|
28
|
+
# In addition, VNC uses two individual 8 byte block encryptions rather than
|
29
|
+
# using any block mode (like cbc, ecb, etc).
|
30
|
+
##
|
31
|
+
|
32
|
+
class Cipher
|
33
|
+
|
34
|
+
def self.mangle_password(password)
|
35
|
+
key = ''
|
36
|
+
key = password.dup if password
|
37
|
+
key.slice!(8,key.length) if key.length > 8
|
38
|
+
key << "\x00" * (8 - key.length) if key.length < 8
|
39
|
+
|
40
|
+
# We have to mangle the key so the LSB are kept vs the MSB
|
41
|
+
[key.unpack('B*').first.scan(/.{8}/).map! { |e| e.reverse }.join].pack('B*')
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.encrypt(plain, password)
|
45
|
+
key = self.mangle_password(password)
|
46
|
+
|
47
|
+
# VNC auth does two 8-byte blocks individually instead supporting some block mode
|
48
|
+
cipher = ''
|
49
|
+
2.times { |x|
|
50
|
+
c = OpenSSL::Cipher::Cipher.new('des')
|
51
|
+
c.encrypt
|
52
|
+
c.key = key
|
53
|
+
cipher << c.update(plain[x*8, 8])
|
54
|
+
}
|
55
|
+
|
56
|
+
cipher
|
57
|
+
end
|
58
|
+
|
59
|
+
#
|
60
|
+
# NOTE: The default password is that of winvnc/etc which is used for
|
61
|
+
# encrypting the password(s) on disk/in registry.
|
62
|
+
#
|
63
|
+
def self.decrypt(cipher, password = "\x17\x52\x6b\x06\x23\x4e\x58\x07")
|
64
|
+
key = self.mangle_password(password)
|
65
|
+
|
66
|
+
# NOTE: This only does one 8 byte block
|
67
|
+
plain = ''
|
68
|
+
c = OpenSSL::Cipher::Cipher.new('des')
|
69
|
+
c.decrypt
|
70
|
+
c.key = key
|
71
|
+
c.update(cipher)
|
72
|
+
end
|
73
|
+
|
74
|
+
end
|
75
|
+
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
@@ -0,0 +1,207 @@
|
|
1
|
+
##
|
2
|
+
# $Id: $
|
3
|
+
##
|
4
|
+
|
5
|
+
##
|
6
|
+
#
|
7
|
+
# RFB protocol support
|
8
|
+
#
|
9
|
+
# by Joshua J. Drake <jduck>
|
10
|
+
#
|
11
|
+
# Based on:
|
12
|
+
# vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
|
13
|
+
# vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
|
14
|
+
#
|
15
|
+
# TODO: determine how to detect a view-only session.
|
16
|
+
##
|
17
|
+
|
18
|
+
module Rex
|
19
|
+
module Proto
|
20
|
+
module RFB
|
21
|
+
|
22
|
+
class Client
|
23
|
+
|
24
|
+
def initialize(sock, opts = {})
|
25
|
+
@sock = sock
|
26
|
+
@opts = opts
|
27
|
+
|
28
|
+
@banner = nil
|
29
|
+
@majver = MajorVersion
|
30
|
+
@minver = -1
|
31
|
+
@auth_types = []
|
32
|
+
end
|
33
|
+
|
34
|
+
def read_error_message
|
35
|
+
len = @sock.get_once(4)
|
36
|
+
return 'Unknown error' if not len or len.length != 4
|
37
|
+
|
38
|
+
len = len.unpack("N").first
|
39
|
+
@sock.get_once(len)
|
40
|
+
end
|
41
|
+
|
42
|
+
def handshake
|
43
|
+
@banner = @sock.get_once(12)
|
44
|
+
if not @banner
|
45
|
+
@error = "Unable to obtain banner from server"
|
46
|
+
return false
|
47
|
+
end
|
48
|
+
|
49
|
+
# RFB Protocol Version 3.3 (1998-01)
|
50
|
+
# RFB Protocol Version 3.7 (2003-08)
|
51
|
+
# RFB Protocol Version 3.8 (2007-06)
|
52
|
+
|
53
|
+
if @banner =~ /RFB ([0-9]{3})\.([0-9]{3})/
|
54
|
+
maj = $1.to_i
|
55
|
+
if maj != MajorVersion
|
56
|
+
@error = "Invalid major version number: #{maj}"
|
57
|
+
return false
|
58
|
+
end
|
59
|
+
else
|
60
|
+
@error = "Invalid RFB banner: #{@banner}"
|
61
|
+
return false
|
62
|
+
end
|
63
|
+
|
64
|
+
@minver = $2.to_i
|
65
|
+
|
66
|
+
our_ver = "RFB %03d.%03d\n" % [MajorVersion, @minver]
|
67
|
+
@sock.put(our_ver)
|
68
|
+
|
69
|
+
true
|
70
|
+
end
|
71
|
+
|
72
|
+
def connect(password = nil)
|
73
|
+
return false if not handshake
|
74
|
+
return false if not authenticate(password)
|
75
|
+
return false if not send_client_init
|
76
|
+
true
|
77
|
+
end
|
78
|
+
|
79
|
+
def send_client_init
|
80
|
+
if @opts[:exclusive]
|
81
|
+
@sock.put("\x00") # do share.
|
82
|
+
else
|
83
|
+
@sock.put("\x01") # do share.
|
84
|
+
end
|
85
|
+
end
|
86
|
+
|
87
|
+
def authenticate(password = nil)
|
88
|
+
type = negotiate_authentication
|
89
|
+
return false if not type
|
90
|
+
|
91
|
+
# Authenticate.
|
92
|
+
case type
|
93
|
+
when AuthType::None
|
94
|
+
# Nothing here.
|
95
|
+
|
96
|
+
when AuthType::VNC
|
97
|
+
return false if not negotiate_vnc_auth(password)
|
98
|
+
|
99
|
+
end
|
100
|
+
|
101
|
+
# Handle reading the security result message
|
102
|
+
result = @sock.get_once(4)
|
103
|
+
if not result
|
104
|
+
@error = "Unable to read auth result"
|
105
|
+
return false
|
106
|
+
end
|
107
|
+
|
108
|
+
result = result.unpack('N').first
|
109
|
+
case result
|
110
|
+
when 0
|
111
|
+
return true
|
112
|
+
|
113
|
+
when 1
|
114
|
+
if @minver >= 8
|
115
|
+
msg = read_error_message
|
116
|
+
@error = "Authentication failed: #{msg}"
|
117
|
+
else
|
118
|
+
@error = "Authentication failed"
|
119
|
+
end
|
120
|
+
when 2
|
121
|
+
@error = "Too many authentication attempts"
|
122
|
+
else
|
123
|
+
@error = "Unknown authentication result: #{result}"
|
124
|
+
end
|
125
|
+
|
126
|
+
false
|
127
|
+
end
|
128
|
+
|
129
|
+
def negotiate_authentication
|
130
|
+
# Authentication type negotiation is protocol version specific.
|
131
|
+
if @minver < 7
|
132
|
+
buf = @sock.get_once(4)
|
133
|
+
if not buf
|
134
|
+
@error = "Unable to obtain requested authentication method"
|
135
|
+
return nil
|
136
|
+
end
|
137
|
+
@auth_types = buf.unpack('N')
|
138
|
+
if not @auth_types or @auth_types.first == 0
|
139
|
+
msg = read_error_message
|
140
|
+
@error = "No authentication types available: #{msg}"
|
141
|
+
return nil
|
142
|
+
end
|
143
|
+
else
|
144
|
+
buf = @sock.get_once(1)
|
145
|
+
if not buf
|
146
|
+
@error = "Unable to obtain supported authentication method count"
|
147
|
+
return nil
|
148
|
+
end
|
149
|
+
|
150
|
+
# first byte is number of security types
|
151
|
+
num_types = buf.unpack("C").first
|
152
|
+
if (num_types == 0)
|
153
|
+
msg = read_error_message
|
154
|
+
@error = "No authentication types available: #{msg}"
|
155
|
+
return nil
|
156
|
+
end
|
157
|
+
|
158
|
+
buf = @sock.get_once(num_types)
|
159
|
+
if not buf or buf.length != num_types
|
160
|
+
@error = "Unable to read authentication types"
|
161
|
+
return nil
|
162
|
+
end
|
163
|
+
|
164
|
+
@auth_types = buf.unpack("C*")
|
165
|
+
end
|
166
|
+
|
167
|
+
if not @auth_types or @auth_types.length < 1
|
168
|
+
@error = "No authentication types found"
|
169
|
+
return nil
|
170
|
+
end
|
171
|
+
|
172
|
+
# Select the one we prefer
|
173
|
+
selected = nil
|
174
|
+
selected ||= AuthType::None if @opts[:allow_none] and @auth_types.include? AuthType::None
|
175
|
+
selected ||= AuthType::VNC if @auth_types.include? AuthType::VNC
|
176
|
+
|
177
|
+
if not selected
|
178
|
+
@error = "No supported authentication method found."
|
179
|
+
return nil
|
180
|
+
end
|
181
|
+
|
182
|
+
# For 3.7 and later, clients must state which security-type to use
|
183
|
+
@sock.put([selected].pack('C')) if @minver >= 7
|
184
|
+
|
185
|
+
selected
|
186
|
+
end
|
187
|
+
|
188
|
+
def negotiate_vnc_auth(password = nil)
|
189
|
+
challenge = @sock.get_once(16)
|
190
|
+
if not challenge or challenge.length != 16
|
191
|
+
@error = "Unable to obtain VNC challenge"
|
192
|
+
return false
|
193
|
+
end
|
194
|
+
|
195
|
+
response = Cipher.encrypt(challenge, password)
|
196
|
+
@sock.put(response)
|
197
|
+
|
198
|
+
true
|
199
|
+
end
|
200
|
+
|
201
|
+
attr_reader :error, :majver, :minver, :auth_types
|
202
|
+
attr_reader :view_only
|
203
|
+
end
|
204
|
+
|
205
|
+
end
|
206
|
+
end
|
207
|
+
end
|
@@ -0,0 +1,52 @@
|
|
1
|
+
##
|
2
|
+
# $Id: $
|
3
|
+
##
|
4
|
+
|
5
|
+
##
|
6
|
+
#
|
7
|
+
# RFB protocol support
|
8
|
+
#
|
9
|
+
# by Joshua J. Drake <jduck>
|
10
|
+
#
|
11
|
+
# Based on:
|
12
|
+
# vnc_auth_none contributed by Matteo Cantoni <goony[at]nothink.org>
|
13
|
+
# vnc_auth_login contributed by carstein <carstein.sec[at]gmail.com>
|
14
|
+
#
|
15
|
+
##
|
16
|
+
|
17
|
+
module Rex
|
18
|
+
module Proto
|
19
|
+
module RFB
|
20
|
+
|
21
|
+
DefaultPort = 5900
|
22
|
+
|
23
|
+
# Version information
|
24
|
+
MajorVersion = 3
|
25
|
+
# NOTE: We will emulate whatever minor version the server reports.
|
26
|
+
|
27
|
+
# Security types
|
28
|
+
class AuthType
|
29
|
+
Invalid = 0
|
30
|
+
None = 1
|
31
|
+
VNC = 2
|
32
|
+
RA2 = 5
|
33
|
+
RA2ne = 6
|
34
|
+
Tight = 16
|
35
|
+
Ultra = 17
|
36
|
+
TLS = 18
|
37
|
+
VeNCrypt = 19
|
38
|
+
GtkVncSasl = 20
|
39
|
+
MD5Hash = 21
|
40
|
+
ColinDeanXVP = 22
|
41
|
+
|
42
|
+
def self.to_s(num)
|
43
|
+
self.constants.each { |c|
|
44
|
+
return c.to_s if self.const_get(c) == num
|
45
|
+
}
|
46
|
+
'Unknown'
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
@@ -1,4 +1,4 @@
|
|
1
|
-
# $Id: server.rb
|
1
|
+
# $Id: server.rb 11454 2010-12-30 16:37:58Z hdm $
|
2
2
|
require 'rex/socket'
|
3
3
|
require 'rex/proto/tftp'
|
4
4
|
|
@@ -51,7 +51,7 @@ class Server
|
|
51
51
|
'Context' => context
|
52
52
|
)
|
53
53
|
|
54
|
-
self.thread =
|
54
|
+
self.thread = Rex::ThreadFactory.spawn("TFTPServerMonitor", false) {
|
55
55
|
monitor_socket
|
56
56
|
}
|
57
57
|
end
|
@@ -64,10 +64,10 @@ class Server
|
|
64
64
|
@shutting_down = true
|
65
65
|
|
66
66
|
# Wait a maximum of 30 seconds for all transfers to finish.
|
67
|
-
start = Time.now
|
67
|
+
start = ::Time.now
|
68
68
|
while (self.transfers.length > 0)
|
69
69
|
::IO.select(nil, nil, nil, 0.5)
|
70
|
-
dur = Time.now - start
|
70
|
+
dur = ::Time.now - start
|
71
71
|
break if (dur > 30)
|
72
72
|
end
|
73
73
|
|
@@ -93,7 +93,7 @@ class Server
|
|
93
93
|
# Register an entire directory to serve files from
|
94
94
|
#
|
95
95
|
def set_tftproot(rootdir)
|
96
|
-
@tftproot = rootdir if File.directory?(rootdir)
|
96
|
+
@tftproot = rootdir if ::File.directory?(rootdir)
|
97
97
|
end
|
98
98
|
|
99
99
|
|
@@ -101,7 +101,7 @@ class Server
|
|
101
101
|
# Register a directory to write uploaded files to
|
102
102
|
#
|
103
103
|
def set_output_dir(outdir)
|
104
|
-
@output_dir = outdir if File.directory?(outdir)
|
104
|
+
@output_dir = outdir if ::File.directory?(outdir)
|
105
105
|
end
|
106
106
|
|
107
107
|
|
@@ -153,15 +153,15 @@ class Server
|
|
153
153
|
# entry to the files hash.
|
154
154
|
#
|
155
155
|
def find_file_in_root(fname)
|
156
|
-
fn = File.expand_path(File.join(@tftproot, fname))
|
156
|
+
fn = ::File.expand_path(::File.join(@tftproot, fname))
|
157
157
|
|
158
158
|
# Don't allow directory traversal
|
159
159
|
return nil if fn.index(@tftproot) != 0
|
160
160
|
|
161
|
-
return nil if not File.file?(fn) or not File.readable?(fn)
|
161
|
+
return nil if not ::File.file?(fn) or not ::File.readable?(fn)
|
162
162
|
|
163
163
|
# Read the file contents, and register it as being served once
|
164
|
-
data = data = File.open(fn, "rb") { |fd| fd.read(fd.stat.size) }
|
164
|
+
data = data = ::File.open(fn, "rb") { |fd| fd.read(fd.stat.size) }
|
165
165
|
register_file(fname, data, true)
|
166
166
|
|
167
167
|
# Return the last file in the array
|
@@ -172,7 +172,8 @@ class Server
|
|
172
172
|
attr_accessor :listen_host, :listen_port, :context
|
173
173
|
attr_accessor :sock, :files, :transfers, :uploaded
|
174
174
|
attr_accessor :thread
|
175
|
-
|
175
|
+
|
176
|
+
attr_accessor :incoming_file_hook
|
176
177
|
|
177
178
|
protected
|
178
179
|
|
@@ -185,14 +186,16 @@ protected
|
|
185
186
|
nil
|
186
187
|
end
|
187
188
|
|
188
|
-
|
189
189
|
def save_output(tr)
|
190
190
|
self.uploaded << tr[:file]
|
191
|
+
|
192
|
+
return incoming_file_hook.call(tr) if incoming_file_hook
|
193
|
+
|
191
194
|
if @output_dir
|
192
195
|
fn = tr[:file][:name].split(File::SEPARATOR)[-1]
|
193
196
|
if fn
|
194
|
-
fn = File.join(@output_dir, fn)
|
195
|
-
File.open(fn, "wb") { |fd|
|
197
|
+
fn = ::File.join(@output_dir, fn)
|
198
|
+
::File.open(fn, "wb") { |fd|
|
196
199
|
fd.write(tr[:file][:data])
|
197
200
|
}
|
198
201
|
end
|
@@ -201,7 +204,7 @@ protected
|
|
201
204
|
|
202
205
|
|
203
206
|
def check_retransmission(tr)
|
204
|
-
elapsed = Time.now - tr[:last_sent]
|
207
|
+
elapsed = ::Time.now - tr[:last_sent]
|
205
208
|
if (elapsed >= tr[:timeout])
|
206
209
|
# max retries reached?
|
207
210
|
if (tr[:retries] < 3)
|
@@ -262,7 +265,7 @@ protected
|
|
262
265
|
pkt << chunk
|
263
266
|
|
264
267
|
send_packet(tr[:from], pkt)
|
265
|
-
tr[:last_sent] = Time.now
|
268
|
+
tr[:last_sent] = ::Time.now
|
266
269
|
|
267
270
|
# If the file is a one-serve, mark it as started
|
268
271
|
tr[:file][:started] = true if (tr[:file][:once])
|
@@ -282,7 +285,7 @@ protected
|
|
282
285
|
pkt = [OpAck, tr[:block]].pack('nn')
|
283
286
|
|
284
287
|
send_packet(tr[:from], pkt)
|
285
|
-
tr[:last_sent] = Time.now
|
288
|
+
tr[:last_sent] = ::Time.now
|
286
289
|
|
287
290
|
# If we had a 0-511 byte chunk, we're done.
|
288
291
|
if (tr[:last_size] and tr[:last_size] < tr[:blksize])
|
@@ -355,7 +358,7 @@ protected
|
|
355
358
|
|
356
359
|
#puts "%s %s %s" % [start, fn, mode]
|
357
360
|
|
358
|
-
if
|
361
|
+
if not @shutting_down
|
359
362
|
transfer = {
|
360
363
|
:type => OpWrite,
|
361
364
|
:from => from,
|