boat 0.2 → 0.2.1
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.
- data/boat.gemspec +2 -0
- data/lib/boat/client.rb +11 -10
- data/lib/boat/server.rb +11 -14
- data/lib/boat/version.rb +1 -1
- data/server.conf +1 -1
- metadata +18 -4
data/boat.gemspec
CHANGED
data/lib/boat/client.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
require '
|
1
|
+
require 'openssl'
|
2
2
|
require 'socket'
|
3
3
|
|
4
4
|
class Boat::Client
|
@@ -21,7 +21,7 @@ class Boat::Client
|
|
21
21
|
raise Error, response unless response =~ /^251 HMAC-SHA256 (.+)/
|
22
22
|
|
23
23
|
puts "[debug] sending password" if @debug
|
24
|
-
password_hash = HMAC
|
24
|
+
password_hash = OpenSSL::HMAC.hexdigest(OpenSSL::Digest.new('sha256'), key, $1)
|
25
25
|
socket_puts "pass #{password_hash}"
|
26
26
|
response = socket_gets.to_s
|
27
27
|
raise Error, response unless response =~ /^250/
|
@@ -37,16 +37,17 @@ class Boat::Client
|
|
37
37
|
|
38
38
|
size ||= io.respond_to?(:stat) ? io.stat.size : io.length
|
39
39
|
|
40
|
+
digest = OpenSSL::Digest.new('sha256')
|
40
41
|
hash ||= if io.respond_to?(:path)
|
41
|
-
|
42
|
+
digest.file(io.path).hexdigest
|
42
43
|
elsif !io.respond_to?(:read)
|
43
|
-
|
44
|
+
digest.hexdigest(io)
|
44
45
|
else
|
45
46
|
"-"
|
46
47
|
end
|
47
48
|
|
48
|
-
client_salt = [
|
49
|
-
signature = HMAC
|
49
|
+
client_salt = [digest.digest((0..64).inject("") {|r, i| r << rand(256).chr})].pack("m").strip
|
50
|
+
signature = OpenSSL::HMAC.hexdigest(digest, @key, "#{server_salt}#{encoded_filename}#{size}#{hash}#{client_salt}")
|
50
51
|
|
51
52
|
puts "[debug] sending data command" if @debug
|
52
53
|
socket_puts "data #{size} #{hash} #{client_salt} #{signature}"
|
@@ -54,7 +55,7 @@ class Boat::Client
|
|
54
55
|
|
55
56
|
# The server might already have the file with this hash - if so it'll return 255 at this point.
|
56
57
|
if matches = response.strip.match(/\A255 accepted ([0-9a-f]{64})\z/i)
|
57
|
-
confirm_hash = HMAC
|
58
|
+
confirm_hash = OpenSSL::HMAC.hexdigest(digest, @key, "#{client_salt}#{hash}")
|
58
59
|
if matches[1] != confirm_hash
|
59
60
|
raise Error, "Incorrect server signature; the srver may be faking that it received the upload"
|
60
61
|
end
|
@@ -64,7 +65,7 @@ class Boat::Client
|
|
64
65
|
raise Error, response unless response =~ /^253/
|
65
66
|
|
66
67
|
if io.respond_to?(:read)
|
67
|
-
digest = Digest
|
68
|
+
digest = OpenSSL::Digest.new('sha256') if hash == '-'
|
68
69
|
written = 0
|
69
70
|
while data = io.read(@chunk_size)
|
70
71
|
if @debug
|
@@ -86,7 +87,7 @@ class Boat::Client
|
|
86
87
|
|
87
88
|
if response =~ /^254/ # we need to send the hash of the file because we didn't on the DATA line
|
88
89
|
hash = digest.to_s
|
89
|
-
signature = HMAC
|
90
|
+
signature = OpenSSL::HMAC.hexdigest(digest, @key, "#{server_salt}#{encoded_filename}#{size}#{hash}#{client_salt}")
|
90
91
|
|
91
92
|
puts "[debug] sending confirm command" if @debug
|
92
93
|
socket_puts "confirm #{hash} #{signature}\n"
|
@@ -95,7 +96,7 @@ class Boat::Client
|
|
95
96
|
|
96
97
|
raise Error, response unless response && matches = response.strip.match(/\A255 accepted ([0-9a-f]{64})\z/i)
|
97
98
|
|
98
|
-
confirm_hash = HMAC
|
99
|
+
confirm_hash = OpenSSL::HMAC.hexdigest(digest, @key, "#{client_salt}#{hash}")
|
99
100
|
if matches[1] != confirm_hash
|
100
101
|
raise Error, "Incorrect server signature; the srver may be faking that it received the upload"
|
101
102
|
end
|
data/lib/boat/server.rb
CHANGED
@@ -1,7 +1,5 @@
|
|
1
|
-
require '
|
1
|
+
require 'openssl'
|
2
2
|
require 'eventmachine'
|
3
|
-
require 'syslog'
|
4
|
-
require 'digest'
|
5
3
|
require 'fileutils'
|
6
4
|
|
7
5
|
class Boat::Server
|
@@ -22,6 +20,7 @@ class Boat::Server
|
|
22
20
|
@@last_connection_id += 1
|
23
21
|
@connection_id = @@last_connection_id
|
24
22
|
@temporary_files = []
|
23
|
+
@digest = OpenSSL::Digest::Digest.new('sha256')
|
25
24
|
send_data "220 Boat Server #{Boat::VERSION}\n"
|
26
25
|
end
|
27
26
|
|
@@ -59,7 +58,7 @@ class Boat::Server
|
|
59
58
|
send_data "500 USER first\n"
|
60
59
|
else
|
61
60
|
user = @configuration.fetch("users", {}).fetch(@username, nil)
|
62
|
-
expected = HMAC
|
61
|
+
expected = OpenSSL::HMAC.hexdigest(@digest, user["key"], @login_salt) if user
|
63
62
|
if user && expected && args == expected
|
64
63
|
send_data "250 OK\n"
|
65
64
|
@user = user
|
@@ -107,10 +106,10 @@ class Boat::Server
|
|
107
106
|
|
108
107
|
if size >= 1<<31
|
109
108
|
send_data "500 size too large\n"
|
110
|
-
elsif signature != HMAC
|
109
|
+
elsif signature != OpenSSL::HMAC.hexdigest(@digest, @user["key"], "#{@put.fetch(:server_salt)}#{@put.fetch(:filename)}#{size}#{file_hash}#{client_salt}")
|
111
110
|
send_data "500 signature is invalid\n"
|
112
|
-
elsif File.exists?(current_filename = "#{repository_path}/current.#{@put.fetch(:filename)}") && Digest
|
113
|
-
signature = HMAC
|
111
|
+
elsif File.exists?(current_filename = "#{repository_path}/current.#{@put.fetch(:filename)}") && OpenSSL::Digest.new('sha256').file(current_filename).to_s == file_hash
|
112
|
+
signature = OpenSSL::HMAC.hexdigest(@digest, @user["key"], "#{client_salt}#{file_hash}")
|
114
113
|
send_data "255 accepted #{signature}\n"
|
115
114
|
else
|
116
115
|
@put[:temporary_id] = "#{Time.now.to_i}.#{Process.pid}.#{@connection_id}"
|
@@ -121,7 +120,7 @@ class Boat::Server
|
|
121
120
|
:hash => (file_hash unless file_hash == '-'),
|
122
121
|
:client_salt => client_salt,
|
123
122
|
:file_handle => File.open(@put[:temporary_filename], "w"),
|
124
|
-
:digest => Digest
|
123
|
+
:digest => OpenSSL::Digest.new('sha256'))
|
125
124
|
|
126
125
|
@temporary_files << @put[:temporary_filename]
|
127
126
|
|
@@ -156,7 +155,7 @@ class Boat::Server
|
|
156
155
|
file_hash = matches[1].downcase
|
157
156
|
signature = matches[2].downcase
|
158
157
|
|
159
|
-
if signature != HMAC
|
158
|
+
if signature != OpenSSL::HMAC.hexdigest(@digest, @user["key"], "#{@put.fetch(:server_salt)}#{@put.fetch(:filename)}#{@put.fetch(:size)}#{file_hash}#{@put.fetch(:client_salt)}")
|
160
159
|
send_data "500 signature is invalid\n"
|
161
160
|
@put = nil
|
162
161
|
else
|
@@ -167,7 +166,7 @@ class Boat::Server
|
|
167
166
|
end
|
168
167
|
|
169
168
|
def complete_put
|
170
|
-
calculated_hash = @put.fetch(:digest).
|
169
|
+
calculated_hash = @put.fetch(:digest).hexdigest
|
171
170
|
|
172
171
|
if @put.fetch(:hash) != calculated_hash
|
173
172
|
send_data "500 file hash does not match hash supplied by client\n"
|
@@ -195,7 +194,7 @@ class Boat::Server
|
|
195
194
|
end
|
196
195
|
File.symlink(version_filename, symlink_name)
|
197
196
|
|
198
|
-
signature = HMAC
|
197
|
+
signature = OpenSSL::HMAC.hexdigest(@digest, @user["key"], "#{@put.fetch(:client_salt)}#{@put.fetch(:hash)}")
|
199
198
|
send_data "255 accepted #{signature}\n"
|
200
199
|
ensure
|
201
200
|
@put = nil
|
@@ -228,7 +227,7 @@ class Boat::Server
|
|
228
227
|
end
|
229
228
|
|
230
229
|
def random_salt
|
231
|
-
[Digest
|
230
|
+
[OpenSSL::Digest.new('sha256').digest((0..64).inject("") {|r, i| r << rand(256).chr})].pack("m").strip
|
232
231
|
end
|
233
232
|
|
234
233
|
def repository_path
|
@@ -277,8 +276,6 @@ class Boat::Server
|
|
277
276
|
end
|
278
277
|
end
|
279
278
|
|
280
|
-
#Syslog.open 'boat'
|
281
|
-
|
282
279
|
File.umask(0077)
|
283
280
|
EventMachine.run do
|
284
281
|
EventMachine.start_server(
|
data/lib/boat/version.rb
CHANGED
data/server.conf
CHANGED
metadata
CHANGED
@@ -1,12 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: boat
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 21
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 2
|
9
|
-
|
9
|
+
- 1
|
10
|
+
version: 0.2.1
|
10
11
|
platform: ruby
|
11
12
|
authors:
|
12
13
|
- Roger Nesbitt
|
@@ -16,8 +17,21 @@ cert_chain: []
|
|
16
17
|
|
17
18
|
date: 2011-05-30 00:00:00 +12:00
|
18
19
|
default_executable:
|
19
|
-
dependencies:
|
20
|
-
|
20
|
+
dependencies:
|
21
|
+
- !ruby/object:Gem::Dependency
|
22
|
+
name: eventmachine
|
23
|
+
prerelease: false
|
24
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ">="
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
hash: 3
|
30
|
+
segments:
|
31
|
+
- 0
|
32
|
+
version: "0"
|
33
|
+
type: :runtime
|
34
|
+
version_requirements: *id001
|
21
35
|
description: File upload client and server specifically aimed at transferring already-encrypted backups
|
22
36
|
email: []
|
23
37
|
|