rack-tctp 0.9.13 → 0.9.14

Sign up to get free protection for your applications and to get access to all the features.
@@ -1,213 +1,221 @@
1
- require 'openssl'
2
- require 'socket'
3
- require 'radix'
4
-
5
- require 'rack/tctp/engine'
6
-
7
- # HTTP application layer encryption channel. Used for the Trusted Cloud Transfer Protocol (TCTP)
8
- class Rack::TCTP::HALEC
9
- # The SSL engine
10
- attr_reader :engine
11
-
12
- # The URL of this HALEC
13
- attr_accessor :url
14
-
15
- # The private key for a certificate (if any)
16
- attr_reader :private_key
17
-
18
- # A server or client certificate (if any)
19
- attr_reader :certificate
20
-
21
- # The thread for encrypting and decrypting data of this HALEC
22
- attr_reader :async_thread
23
-
24
- # The queue for encrypting and decrypting data
25
- # @return [Queue] The async queue
26
- # @!attr [r] async_queue
27
- def async_queue
28
- unless @async_queue
29
- @async_queue = Queue.new
30
-
31
- @async_thread = Thread.new do
32
- begin
33
- while true
34
- item = @async_queue.pop
35
-
36
- case item[0]
37
- when :encrypt
38
- item[2].call encrypt_data(item[1])
39
- when :decrypt
40
- item[2].call decrypt_data(item[1])
41
- when :call
42
- item[2].call
43
- end
44
- end
45
- rescue Exception => e
46
- #TODO Handle HALEC encryption thread shutdown
47
- #TODO Handle OpenSSL error
48
- puts e
49
- end
50
- end
51
- end
52
-
53
- @async_queue
54
- end
55
-
56
- def initialize(options = {})
57
- @url = options[:url] || nil
58
- end
59
-
60
- # Encrypts +plaintext+ data and either returns the encrypted data or calls a block with it.
61
- # @param [String] plaintext The plaintext
62
- # @return [String] The encrypted data
63
- # @yield Gives the encrypted data to the block
64
- # @yieldparam [String] The encrypted data
65
- def encrypt_data(plaintext, &encrypted)
66
- written = @engine.write plaintext
67
-
68
- if written < plaintext.length
69
- exit -1
70
- end
71
-
72
- read_data = []
73
-
74
- while(read_chunk = @engine.extract)
75
- read_data << read_chunk
76
- end
77
-
78
- if block_given?
79
- read_data.each do |data|
80
- encrypted.call data
81
- end
82
- else
83
- read_data.join
84
- end
85
- end
86
-
87
- # Encrypts +plaintext+ data asynchronously, yielding data to the block when done.
88
- # @param [String] plaintext The plaintext
89
- # @yield Gives the encrypted data to the block
90
- # @yieldparam [String] The encrypted data
91
- def encrypt_data_async(plaintext, &encrypted)
92
- async_queue.push [:encrypt, plaintext, encrypted]
93
- end
94
-
95
- # Decrypts +encrypted+ data and either returns the plaintext or calls a block with it.
96
- # @param [String] encrypted The encrypted data
97
- # @return [String] The plaintext
98
- # @yield Gives the plaintext to the block
99
- # @yieldparam [String] The plaintext
100
- def decrypt_data(encrypted, &decrypted)
101
- injected = @engine.inject encrypted
102
-
103
- if injected < encrypted.length
104
- exit -1
105
- end
106
-
107
- read_data = []
108
-
109
- while(read_chunk = @engine.read)
110
- read_data << read_chunk
111
- end
112
-
113
- if block_given? then
114
- read_data.each do |data|
115
- decrypted.call data
116
- end
117
- else
118
- read_data.join
119
- end
120
- end
121
-
122
- # Decrypts +encrypted+ data asynchronously, yielding data to the block when done.
123
- # @param [String] encrypted The encrypted data
124
- # @yield Gives the decrypted data to the block
125
- # @yieldparam [String] the decrypted data
126
- def decrypt_data_async(encrypted, &decrypted)
127
- async_queue.push [:decrypt, encrypted, decrypted]
128
- end
129
-
130
- # Calls a given block asynchronously, considering the order of all calls to async methods.
131
- def call_async(&block)
132
- async_queue.push [:call, nil, block]
133
- end
134
- end
135
-
136
- # The Client end of an HALEC
137
- class Rack::TCTP::ClientHALEC < Rack::TCTP::HALEC
138
- def initialize(options = {})
139
- super(options)
140
-
141
- @engine = Rack::TCTP::Engine.client
142
- end
143
- end
144
-
145
- # The Server end of an HALEC
146
- class Rack::TCTP::ServerHALEC < Rack::TCTP::HALEC
147
- def initialize(options = {})
148
- super(options)
149
-
150
- if(options[:private_key] && options[:certificate])
151
- @private_key = options[:private_key]
152
- @certificate = options[:certificate]
153
- else
154
- @private_key = self.class.default_key
155
- @certificate = self.class.default_self_signed_certificate
156
- end
157
-
158
- @private_key_file = Tempfile.new('rack_tctp_pk')
159
- @private_key_file.write @private_key.to_s
160
- @private_key_file.close
161
-
162
- @certificate_file = Tempfile.new('rack_tctp_cert')
163
- @certificate_file.write @certificate.to_s
164
- @certificate_file.close
165
-
166
- @engine = Rack::TCTP::Engine.server(@private_key_file.path, @certificate_file.path)
167
- end
168
-
169
- class << self
170
- @default_key
171
- @default_self_signed_certificate
172
-
173
- def initialize
174
- default_key
175
- default_self_signed_certificate
176
-
177
- self
178
- end
179
-
180
- def default_key
181
- @default_key ||= OpenSSL::PKey::RSA.new 2048
182
- end
183
-
184
- def default_self_signed_certificate
185
- @default_self_signed_certificate ||= generate_self_signed_certificate
186
- end
187
-
188
- def generate_self_signed_certificate
189
- name = OpenSSL::X509::Name.parse 'CN=tctp-server/DC=tctp'
190
-
191
- cert = OpenSSL::X509::Certificate.new
192
- cert.version = 2
193
- cert.serial = 0
194
- cert.not_before = Time.now
195
- cert.not_after = Time.now + 3600
196
-
197
- cert.public_key = @default_key.public_key
198
- cert.subject = name
199
-
200
- cert
201
- end
202
-
203
- # The slug URI can contain any HTTP compatible characters
204
- def slug_base
205
- Radix::Base.new(Radix::BASE::B62 + ['-', '_'])
206
- end
207
-
208
- # Generate a new random slug (2^64 possibilities)
209
- def new_slug
210
- slug_base.convert(rand(2**64), 10)
211
- end
212
- end
1
+ require 'openssl'
2
+ require 'socket'
3
+ require 'radix'
4
+
5
+ require 'rack/tctp/engine'
6
+
7
+ # HTTP application layer encryption channel. Used for the Trusted Cloud Transfer Protocol (TCTP)
8
+ class Rack::TCTP::HALEC
9
+ # The SSL engine
10
+ attr_reader :engine
11
+
12
+ # The URL of this HALEC
13
+ attr_accessor :url
14
+
15
+ # The private key for a certificate (if any)
16
+ attr_reader :private_key
17
+
18
+ # A server or client certificate (if any)
19
+ attr_reader :certificate
20
+
21
+ # The thread for encrypting and decrypting data of this HALEC
22
+ attr_reader :async_thread
23
+
24
+ # The queue for encrypting and decrypting data
25
+ # @return [Queue] The async queue
26
+ # @!attr [r] async_queue
27
+ def async_queue
28
+ unless @async_queue
29
+ @async_queue = Queue.new
30
+
31
+ @async_thread = Thread.new do
32
+ begin
33
+ while true
34
+ item = @async_queue.pop
35
+
36
+ case item[0]
37
+ when :encrypt
38
+ item[2].call encrypt_data(item[1])
39
+ when :decrypt
40
+ item[2].call decrypt_data(item[1])
41
+ when :call
42
+ item[2].call
43
+ end
44
+ end
45
+ rescue Exception => e
46
+ #TODO Handle HALEC encryption thread shutdown
47
+ #TODO Handle OpenSSL error
48
+ unless item[0] == :call
49
+ item[2].call e
50
+ end
51
+ end
52
+ end
53
+ end
54
+
55
+ @async_queue
56
+ end
57
+
58
+ def initialize(options = {})
59
+ @url = options[:url] || nil
60
+ end
61
+
62
+ # Encrypts +plaintext+ data and either returns the encrypted data or calls a block with it.
63
+ # @param [String] plaintext The plaintext
64
+ # @return [String] The encrypted data
65
+ # @yield Gives the encrypted data to the block
66
+ # @yieldparam [String] The encrypted data
67
+ def encrypt_data(plaintext, &encrypted)
68
+ written = @engine.write plaintext
69
+
70
+ if written < plaintext.length
71
+ exit -1
72
+ end
73
+
74
+ read_data = []
75
+
76
+ while(read_chunk = @engine.extract)
77
+ read_data << read_chunk
78
+ end
79
+
80
+ if block_given?
81
+ read_data.each do |data|
82
+ encrypted.call data
83
+ end
84
+ else
85
+ read_data.join
86
+ end
87
+ end
88
+
89
+ # Encrypts +plaintext+ data asynchronously, yielding data to the block when done.
90
+ # @param [String] plaintext The plaintext
91
+ # @yield Gives the encrypted data to the block
92
+ # @yieldparam [String|Exception] The encrypted data or an exception
93
+ def encrypt_data_async(plaintext, &encrypted)
94
+ async_queue.push [:encrypt, plaintext, encrypted]
95
+ end
96
+
97
+ # Decrypts +encrypted+ data and either returns the plaintext or calls a block with it.
98
+ # @param [String] encrypted The encrypted data
99
+ # @return [String] The plaintext
100
+ # @yield Gives the plaintext to the block
101
+ # @yieldparam [String] The plaintext
102
+ def decrypt_data(encrypted, &decrypted)
103
+ injected = @engine.inject encrypted
104
+
105
+ unless injected
106
+ exit -1
107
+ end
108
+
109
+ read_data = []
110
+
111
+ begin
112
+ while(read_chunk = @engine.read)
113
+ read_data << read_chunk
114
+ end
115
+ rescue Exception => e
116
+ unless @engine.state == 'SSLOK '
117
+ raise e
118
+ end
119
+ end
120
+
121
+ if block_given? then
122
+ read_data.each do |data|
123
+ decrypted.call data
124
+ end
125
+ else
126
+ read_data.join
127
+ end
128
+ end
129
+
130
+ # Decrypts +encrypted+ data asynchronously, yielding data to the block when done.
131
+ # @param [String] encrypted The encrypted data
132
+ # @yield Gives the decrypted data to the block
133
+ # @yieldparam [String|Exception] the decrypted data or an exception
134
+ def decrypt_data_async(encrypted, &decrypted)
135
+ async_queue.push [:decrypt, encrypted, decrypted]
136
+ end
137
+
138
+ # Calls a given block asynchronously, considering the order of all calls to async methods.
139
+ def call_async(&block)
140
+ async_queue.push [:call, nil, block]
141
+ end
142
+ end
143
+
144
+ # The Client end of an HALEC
145
+ class Rack::TCTP::ClientHALEC < Rack::TCTP::HALEC
146
+ def initialize(options = {})
147
+ super(options)
148
+
149
+ @engine = Rack::TCTP::Engine.client
150
+ end
151
+ end
152
+
153
+ # The Server end of an HALEC
154
+ class Rack::TCTP::ServerHALEC < Rack::TCTP::HALEC
155
+ def initialize(options = {})
156
+ super(options)
157
+
158
+ if(options[:private_key] && options[:certificate])
159
+ @private_key = options[:private_key]
160
+ @certificate = options[:certificate]
161
+ else
162
+ @private_key = self.class.default_key
163
+ @certificate = self.class.default_self_signed_certificate
164
+ end
165
+
166
+ @private_key_file = Tempfile.new('rack_tctp_pk')
167
+ @private_key_file.write @private_key.to_s
168
+ @private_key_file.close
169
+
170
+ @certificate_file = Tempfile.new('rack_tctp_cert')
171
+ @certificate_file.write @certificate.to_s
172
+ @certificate_file.close
173
+
174
+ @engine = Rack::TCTP::Engine.server(@private_key_file.path, @certificate_file.path)
175
+ end
176
+
177
+ class << self
178
+ @default_key
179
+ @default_self_signed_certificate
180
+
181
+ def initialize
182
+ default_key
183
+ default_self_signed_certificate
184
+
185
+ self
186
+ end
187
+
188
+ def default_key
189
+ @default_key ||= OpenSSL::PKey::RSA.new 2048
190
+ end
191
+
192
+ def default_self_signed_certificate
193
+ @default_self_signed_certificate ||= generate_self_signed_certificate
194
+ end
195
+
196
+ def generate_self_signed_certificate
197
+ name = OpenSSL::X509::Name.parse 'CN=tctp-server/DC=tctp'
198
+
199
+ cert = OpenSSL::X509::Certificate.new
200
+ cert.version = 2
201
+ cert.serial = 0
202
+ cert.not_before = Time.now
203
+ cert.not_after = Time.now + 3600
204
+
205
+ cert.public_key = @default_key.public_key
206
+ cert.subject = name
207
+
208
+ cert
209
+ end
210
+
211
+ # The slug URI can contain any HTTP compatible characters
212
+ def slug_base
213
+ Radix::Base.new(Radix::BASE::B62 + ['-', '_'])
214
+ end
215
+
216
+ # Generate a new random slug (2^64 possibilities)
217
+ def new_slug
218
+ slug_base.convert(rand(2**64), 10)
219
+ end
220
+ end
213
221
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: rack-tctp
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.9.13
4
+ version: 0.9.14
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mathias Slawik
@@ -14,84 +14,98 @@ dependencies:
14
14
  name: faker
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - ~>
17
+ - - "~>"
18
18
  - !ruby/object:Gem::Version
19
19
  version: 1.1.2
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
- - - ~>
24
+ - - "~>"
25
25
  - !ruby/object:Gem::Version
26
26
  version: 1.1.2
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: rack-test
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - ~>
31
+ - - "~>"
32
32
  - !ruby/object:Gem::Version
33
33
  version: 0.6.2
34
34
  type: :development
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - ~>
38
+ - - "~>"
39
39
  - !ruby/object:Gem::Version
40
40
  version: 0.6.2
41
41
  - !ruby/object:Gem::Dependency
42
42
  name: test-unit
43
43
  requirement: !ruby/object:Gem::Requirement
44
44
  requirements:
45
- - - ~>
45
+ - - "~>"
46
46
  - !ruby/object:Gem::Version
47
47
  version: 2.5.5
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
- - - ~>
52
+ - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: 2.5.5
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: ruby-prof
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ~>
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
61
  version: 0.13.0
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ~>
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
68
  version: 0.13.0
69
+ - !ruby/object:Gem::Dependency
70
+ name: rake-compiler
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - "~>"
74
+ - !ruby/object:Gem::Version
75
+ version: '0.9'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - "~>"
81
+ - !ruby/object:Gem::Version
82
+ version: '0.9'
69
83
  - !ruby/object:Gem::Dependency
70
84
  name: rest-client
71
85
  requirement: !ruby/object:Gem::Requirement
72
86
  requirements:
73
- - - ~>
87
+ - - "~>"
74
88
  - !ruby/object:Gem::Version
75
89
  version: 1.6.7
76
90
  type: :runtime
77
91
  prerelease: false
78
92
  version_requirements: !ruby/object:Gem::Requirement
79
93
  requirements:
80
- - - ~>
94
+ - - "~>"
81
95
  - !ruby/object:Gem::Version
82
96
  version: 1.6.7
83
97
  - !ruby/object:Gem::Dependency
84
98
  name: radix
85
99
  requirement: !ruby/object:Gem::Requirement
86
100
  requirements:
87
- - - ~>
101
+ - - "~>"
88
102
  - !ruby/object:Gem::Version
89
103
  version: 2.2.0
90
104
  type: :runtime
91
105
  prerelease: false
92
106
  version_requirements: !ruby/object:Gem::Requirement
93
107
  requirements:
94
- - - ~>
108
+ - - "~>"
95
109
  - !ruby/object:Gem::Version
96
110
  version: 2.2.0
97
111
  description: Rack middleware for end-to-end security through TCTP
@@ -101,11 +115,11 @@ extensions:
101
115
  - ext/engine/extconf.rb
102
116
  extra_rdoc_files: []
103
117
  files:
118
+ - ext/engine/engine.c
119
+ - ext/engine/extconf.rb
104
120
  - lib/rack-tctp.rb
105
121
  - lib/rack/tctp.rb
106
122
  - lib/rack/tctp/halec.rb
107
- - ext/engine/engine.c
108
- - ext/engine/extconf.rb
109
123
  homepage: https://github.com/mathiasslawik/rack-tctp
110
124
  licenses:
111
125
  - Apache-2.0
@@ -116,17 +130,17 @@ require_paths:
116
130
  - lib
117
131
  required_ruby_version: !ruby/object:Gem::Requirement
118
132
  requirements:
119
- - - '>='
133
+ - - ">="
120
134
  - !ruby/object:Gem::Version
121
135
  version: '0'
122
136
  required_rubygems_version: !ruby/object:Gem::Requirement
123
137
  requirements:
124
- - - '>='
138
+ - - ">="
125
139
  - !ruby/object:Gem::Version
126
140
  version: '0'
127
141
  requirements: []
128
142
  rubyforge_project:
129
- rubygems_version: 2.0.2
143
+ rubygems_version: 2.2.1
130
144
  signing_key:
131
145
  specification_version: 4
132
146
  summary: Rack TCTP middleware