devise-proxy 0.1.4 → 1.0.0
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.
- checksums.yaml +7 -0
- data/.gitignore +4 -0
- data/README.md +5 -1
- data/Rakefile +7 -41
- data/bin/devise-socks.rb +198 -0
- data/bin/mock-socks.rb +40 -0
- data/config.ru +1 -0
- data/devise-proxy.gemspec +19 -57
- data/extra/devise-proxy +57 -0
- data/lib/devise-proxy/authenticator.rb +8 -7
- data/lib/devise-proxy/proxy.rb +21 -7
- data/lib/devise-proxy/version.rb +3 -0
- data/test/helper.rb +0 -1
- data/test/{test_devise-proxy.rb → lib/authenticator_test.rb} +2 -2
- metadata +30 -67
- data/Gemfile +0 -11
- data/Gemfile.lock +0 -34
- data/VERSION +0 -1
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: 1e8feeaa1f3b1d27db430748fd2dc5a108b606a9
|
4
|
+
data.tar.gz: 76d447b4aef5ba2188ab7799194add1614b10991
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 311ccc467db836f3a2455ff0838ab0086bb18ce18b67207b660784b6f91ead1bd71882a295367ad439f15e519093e87c98a6f045462ddcc19a25eae80ea59b34
|
7
|
+
data.tar.gz: 91ce9f5b92fcc20ae4f9c9d6ec08723aa6ca46202e7c36abb771af63dcada2b586dbcfc64a02486cde323c31881898ba12cda09fef50c32fa238a5fe580489b6
|
data/.gitignore
ADDED
data/README.md
CHANGED
@@ -28,6 +28,10 @@ You'll need a config/devise-proxy.yml file to start the application. For example
|
|
28
28
|
port: 3000
|
29
29
|
|
30
30
|
|
31
|
+
## Example Deployment on Linux ##
|
32
|
+
There is a sample init script in extra/. This script will start the proxy as a daemon on port 6969 as a given user ("tater" in our example). Edit
|
33
|
+
for your environment. Note that you may need to edit the "exec" path. In the sample it points to an rvm wrapper script created using the following command: "rvm wrapper ruby-1.9.3 bootup rackup".
|
34
|
+
|
31
35
|
## Troubleshooting ##
|
32
36
|
|
33
37
|
|
@@ -48,4 +52,4 @@ Preston Lee
|
|
48
52
|
|
49
53
|
## Legal ##
|
50
54
|
|
51
|
-
See LICENSE file for details.
|
55
|
+
See LICENSE file for details.
|
data/Rakefile
CHANGED
@@ -1,45 +1,11 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
require 'rubygems'
|
4
|
-
require 'bundler'
|
5
|
-
begin
|
6
|
-
Bundler.setup(:default, :development)
|
7
|
-
rescue Bundler::BundlerError => e
|
8
|
-
$stderr.puts e.message
|
9
|
-
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
-
exit e.status_code
|
11
|
-
end
|
12
|
-
require 'rake'
|
13
|
-
|
14
|
-
require 'jeweler'
|
15
|
-
Jeweler::Tasks.new do |gem|
|
16
|
-
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
-
gem.name = "devise-proxy"
|
18
|
-
gem.homepage = "http://github.com/preston/devise-proxy"
|
19
|
-
gem.license = "BSD"
|
20
|
-
gem.summary = %Q{A standalone Rack Middleware application that authenticates a username/password against a devise-powered backend application before forwarding the original HTTP request to the same application.}
|
21
|
-
gem.description = %Q{A standalone Rack Middleware application that authenticates a username/password against a devise-powered backend application before forwarding the original HTTP request to the same application. Authentication is done on *every* request, so it is advisable to use devise-proxy sparingly.}
|
22
|
-
gem.email = "conmotto@gmail.com"
|
23
|
-
gem.authors = ["Preston Lee"]
|
24
|
-
# dependencies defined in Gemfile
|
25
|
-
end
|
26
|
-
Jeweler::RubygemsDotOrgTasks.new
|
1
|
+
require "bundler/gem_tasks"
|
27
2
|
|
28
3
|
require 'rake/testtask'
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
4
|
+
|
5
|
+
Rake::TestTask.new do |t|
|
6
|
+
t.libs << 'lib/sms-easy'
|
7
|
+
t.test_files = FileList['test/lib/devise-proxy/*_test.rb']
|
8
|
+
t.verbose = true
|
33
9
|
end
|
34
|
-
|
10
|
+
|
35
11
|
task :default => :test
|
36
|
-
|
37
|
-
require 'rdoc/task'
|
38
|
-
Rake::RDocTask.new do |rdoc|
|
39
|
-
version = File.exist?('VERSION') ? File.read('VERSION') : ""
|
40
|
-
|
41
|
-
rdoc.rdoc_dir = 'rdoc'
|
42
|
-
rdoc.title = "devise-proxy #{version}"
|
43
|
-
rdoc.rdoc_files.include('README*')
|
44
|
-
rdoc.rdoc_files.include('lib/**/*.rb')
|
45
|
-
end
|
data/bin/devise-socks.rb
ADDED
@@ -0,0 +1,198 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
|
5
|
+
|
6
|
+
current_dir = File.dirname(File.expand_path(__FILE__))
|
7
|
+
lib_path = File.join(current_dir, '..', 'lib')
|
8
|
+
puts lib_path
|
9
|
+
$LOAD_PATH.unshift lib_path
|
10
|
+
|
11
|
+
require 'yaml'
|
12
|
+
require 'socket'
|
13
|
+
require 'devise-proxy'
|
14
|
+
require 'ruby-debug'
|
15
|
+
require 'ipaddr'
|
16
|
+
|
17
|
+
config_file = File.join(current_dir, '..', 'config', 'devise-proxy.yml')
|
18
|
+
|
19
|
+
if File.exists? config_file
|
20
|
+
CONF = YAML::load(File.open(config_file))
|
21
|
+
auth_host = CONF['authentication']['hostname']
|
22
|
+
auth_port = CONF['authentication']['port']
|
23
|
+
AUTHENTICATOR = DeviseProxy::Authenticator.new(auth_host, auth_port)
|
24
|
+
else
|
25
|
+
puts "\nPlease create a config file prior to starting the proxy using the provided .sample file, at:\n\n\t#{config_file}\n\n"
|
26
|
+
exit 1
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# Subset from the all-knowing Wikipedia:
|
31
|
+
#
|
32
|
+
# http://en.wikipedia.org/wiki/SOCKS
|
33
|
+
#
|
34
|
+
# The authentication methods supported are numbered as follows:
|
35
|
+
# 0x00: No authentication
|
36
|
+
# 0x01: GSSAPI[10]
|
37
|
+
# 0x02: Username/Password[11]
|
38
|
+
# 0x03-0x7F: methods assigned by IANA[12]
|
39
|
+
# 0x80-0xFE: methods reserved for private use
|
40
|
+
|
41
|
+
@@SOCKS4_VERSION = 0x04
|
42
|
+
|
43
|
+
@@SOCKS5_VERSION = 0x05
|
44
|
+
@@SOCKS5_NO_AUTH = 0x00
|
45
|
+
@@SOCKS5_USERNAME_PASSWORD = 0x02
|
46
|
+
@@SOCKS5_NO_ACCEPTABLE_METHODS = 0xFF
|
47
|
+
@@SOCKS5_AUTH_VERSION = 0x01 # "must be 0x01"
|
48
|
+
@@SOCKS5_AUTH_SUCCESS = 0x00
|
49
|
+
@@SOCKS5_AUTH_FAILURE = 0x01 # "any other value = failure, connection must be closed"
|
50
|
+
|
51
|
+
# Client-requested modes.
|
52
|
+
@@SOCKS5_TCP_STREAM_CONNECTION = 0x01
|
53
|
+
@@SOCKS5_PORT_BINDING = 0x02
|
54
|
+
@@SOCKS5_UDP_PORT = 0x03
|
55
|
+
|
56
|
+
@@SOCKS5_ADDRESS_IPV4 = 0x01
|
57
|
+
@@SOCKS5_ADDRESS_DOMAIN = 0x03
|
58
|
+
@@SOCKS5_ADDRESS_IPV6 = 0x04
|
59
|
+
|
60
|
+
|
61
|
+
def log(s)
|
62
|
+
puts "#{Time.now}: '#{s}'"
|
63
|
+
end
|
64
|
+
|
65
|
+
def validate_socks5(client)
|
66
|
+
data = client.recv(1).bytes.to_a
|
67
|
+
# puts "Socks v#{data[0]}"
|
68
|
+
data[0] == @@SOCKS5_VERSION
|
69
|
+
end
|
70
|
+
|
71
|
+
def authenticate(username, password)
|
72
|
+
# debugger
|
73
|
+
result = AUTHENTICATOR.authenticate(username, password)
|
74
|
+
log("Authentication results: #{result}.")
|
75
|
+
return result[0] == '201'
|
76
|
+
end
|
77
|
+
|
78
|
+
def not_supported(msg, client)
|
79
|
+
log(msg)
|
80
|
+
client.close
|
81
|
+
end
|
82
|
+
|
83
|
+
def forward_traffic(client)
|
84
|
+
sock = TCPSocket.new(CONF['forwarding']['hostname'], CONF['forwarding']['port'])
|
85
|
+
req = client.read
|
86
|
+
sock.write(req)
|
87
|
+
resp = sock.read
|
88
|
+
puts(resp)
|
89
|
+
client.write(resp)
|
90
|
+
end
|
91
|
+
|
92
|
+
def read_port(client)
|
93
|
+
port_a = client.recv(2).bytes.to_a
|
94
|
+
port = (port_a[0] << 8) + port_a[1]
|
95
|
+
port
|
96
|
+
end
|
97
|
+
|
98
|
+
def handle_socks5(client)
|
99
|
+
log("Requesting credentials from client.")
|
100
|
+
# debugger
|
101
|
+
challenge_bytes = [@@SOCKS5_VERSION, @@SOCKS5_USERNAME_PASSWORD].pack('C*')
|
102
|
+
log(challenge_bytes.unpack('C*'));
|
103
|
+
client.write(challenge_bytes)
|
104
|
+
ver = client.recv(1).bytes.to_a[0]
|
105
|
+
puts ver
|
106
|
+
if ver != @@SOCKS5_AUTH_VERSION
|
107
|
+
log("Client speaking non-sense.")
|
108
|
+
else
|
109
|
+
username_length = client.recv(1).bytes.to_a[0]
|
110
|
+
username = client.recv(username_length).bytes.to_a.pack('C*')
|
111
|
+
password_length = client.recv(1).bytes.to_a[0]
|
112
|
+
password = client.recv(password_length).bytes.to_a.pack('C*')
|
113
|
+
log("Attempting to authenticate #{username}:#{password}.")
|
114
|
+
success = authenticate(username, password)
|
115
|
+
if(success)
|
116
|
+
|
117
|
+
client.write [@@SOCKS5_AUTH_VERSION, @@SOCKS5_AUTH_SUCCESS].pack('C*')
|
118
|
+
# if validate_socks5(client)
|
119
|
+
client.recv(1)
|
120
|
+
if true
|
121
|
+
conn_type = client.recv(1).bytes.to_a[0]
|
122
|
+
log("Client requested type: #{conn_type}")
|
123
|
+
# case conn_type
|
124
|
+
# when @@SOCKS5_TCP_STREAM_CONNECTION
|
125
|
+
# when @@SOCKS5_PORT_BINDING
|
126
|
+
client.recv(1) # Eat a byte... "reserved, must be 0x00"
|
127
|
+
case client.recv(1).bytes.to_a[0]
|
128
|
+
when @@SOCKS5_ADDRESS_IPV4
|
129
|
+
log('IPv4 mode.')
|
130
|
+
ip = client.recv(4).bytes.to_a
|
131
|
+
port = read_port(client)
|
132
|
+
log("Client requested: #{ip}:#{port}")
|
133
|
+
resp = [@@SOCKS5_VERSION, 0, 0x00, @@SOCKS5_ADDRESS_IPV4] + ip + port_a
|
134
|
+
client.write resp.pack('C*')
|
135
|
+
forward_traffic(client)
|
136
|
+
when @@SOCKS5_ADDRESS_IPV6
|
137
|
+
not_supported("IPv6 not supported.", client)
|
138
|
+
when @@SOCKS5_ADDRESS_DOMAIN
|
139
|
+
log("Domain mode.")
|
140
|
+
domain_length = client.recv(1).bytes.to_a[0]
|
141
|
+
domain = client.recv(domain_length).bytes.to_a.pack('C*')
|
142
|
+
port = read_port(client)
|
143
|
+
log("Client requested: #{domain}:#{port}")
|
144
|
+
resp = [@@SOCKS5_VERSION, 0, 0x00, @@SOCKS5_ADDRESS_DOMAIN] + domain + port_a
|
145
|
+
client.write resp.pack('C*')
|
146
|
+
forward_traffic(client)
|
147
|
+
else
|
148
|
+
not_supported("Unsupported client connection type.", client)
|
149
|
+
end
|
150
|
+
# else
|
151
|
+
# not_supported("Client request mode not supported, sorry!", client);
|
152
|
+
# end
|
153
|
+
else
|
154
|
+
not_supported("Invalid SOCKS version.", client)
|
155
|
+
end
|
156
|
+
else
|
157
|
+
client.write [@@SOCKS5_VERSION, @@SOCKS5_AUTH_FAILURE].pack('C*')
|
158
|
+
client.close
|
159
|
+
end
|
160
|
+
end
|
161
|
+
log("Done with client connection!");
|
162
|
+
end
|
163
|
+
|
164
|
+
PROXY_PORT = 6969
|
165
|
+
server = TCPServer.new PROXY_PORT
|
166
|
+
log("Server started on port #{PROXY_PORT}.")
|
167
|
+
loop do
|
168
|
+
Thread.start(server.accept) do |client|
|
169
|
+
neg_string = client.recv(2).bytes.to_a
|
170
|
+
log("Client connection received.")
|
171
|
+
log(neg_string)
|
172
|
+
case neg_string[0]
|
173
|
+
when @@SOCKS4_VERSION
|
174
|
+
log("SOCKS v4 isn't supported, sorry!")
|
175
|
+
when @@SOCKS5_VERSION
|
176
|
+
num_methods = neg_string[1]
|
177
|
+
log("Socks v5 detected with #{num_methods} potential authentication modes.")
|
178
|
+
methods = client.recv(num_methods).bytes.to_a
|
179
|
+
supported = false
|
180
|
+
methods.each do |m|
|
181
|
+
log("Potential mode: #{m}")
|
182
|
+
supported = true if m == @@SOCKS5_USERNAME_PASSWORD
|
183
|
+
end
|
184
|
+
if supported
|
185
|
+
log("Username/Password authentication is supported!")
|
186
|
+
handle_socks5(client)
|
187
|
+
else
|
188
|
+
client.puts(@@SOCKS5_VERSION)
|
189
|
+
client.puts(@@SOCKS5_NO_ACCEPTABLE_METHODS)
|
190
|
+
end
|
191
|
+
else
|
192
|
+
log("Unknown/Unsupported client negotiation process.")
|
193
|
+
end
|
194
|
+
# (neg_string[0] == 5)
|
195
|
+
client.close
|
196
|
+
end
|
197
|
+
end
|
198
|
+
|
data/bin/mock-socks.rb
ADDED
@@ -0,0 +1,40 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
#
|
3
|
+
|
4
|
+
require 'socket'
|
5
|
+
|
6
|
+
USERNAME = 'admin@example.com'.bytes.to_a
|
7
|
+
PASSWORD = 'passwordo'.bytes.to_a
|
8
|
+
|
9
|
+
s = TCPSocket.new('localhost', 6969)
|
10
|
+
data = [5,2,0,2].pack('C*')
|
11
|
+
puts data.length
|
12
|
+
s.write(data)
|
13
|
+
# r = s.gets
|
14
|
+
puts s.recv(2).bytes.to_a #.pack('C*')
|
15
|
+
|
16
|
+
puts "Sending credentials.."
|
17
|
+
s.write([1].pack('C*'))
|
18
|
+
s.write([USERNAME.length].pack('C*'))
|
19
|
+
s.write(USERNAME.pack('C*'))
|
20
|
+
s.write([PASSWORD.length].pack('C*'))
|
21
|
+
s.write(PASSWORD.pack('C*'))
|
22
|
+
|
23
|
+
# (
|
24
|
+
# [5] +
|
25
|
+
# [USERNAME.length] +
|
26
|
+
# USERNAME +
|
27
|
+
# [PASSWORD.length] +
|
28
|
+
# PASSWORD
|
29
|
+
# ).pack('C*')
|
30
|
+
# )
|
31
|
+
# s.flush
|
32
|
+
|
33
|
+
# write(('5' * 20).unpack('C*'))
|
34
|
+
puts "Waiting for results.."
|
35
|
+
auth_results = s.recv(2).unpack('C*')
|
36
|
+
puts "SOCKS authentication attempt: #{auth_results[1] == 0 ? 'SUCCESS' : 'FAILED'}"
|
37
|
+
|
38
|
+
# s.write
|
39
|
+
|
40
|
+
puts "Done."
|
data/config.ru
CHANGED
data/devise-proxy.gemspec
CHANGED
@@ -1,62 +1,24 @@
|
|
1
|
-
#
|
2
|
-
|
3
|
-
|
4
|
-
|
1
|
+
# coding: utf-8
|
2
|
+
lib = File.expand_path('../lib', __FILE__)
|
3
|
+
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
|
4
|
+
require 'devise-proxy/version'
|
5
5
|
|
6
|
-
Gem::Specification.new do |
|
7
|
-
|
8
|
-
|
6
|
+
Gem::Specification.new do |spec|
|
7
|
+
spec.name = "devise-proxy"
|
8
|
+
spec.version = DeviseProxy::VERSION
|
9
|
+
spec.authors = ["Preston Lee"]
|
10
|
+
spec.email = "preston.lee@prestonlee.com"
|
11
|
+
spec.description = "A standalone Rack Middleware application that authenticates a username/password against a devise-powered backend application before forwarding the original HTTP request to the same application. Authentication is done on *every* request, so it is advisable to use devise-proxy sparingly."
|
12
|
+
spec.summary = "A standalone Rack Middleware application that authenticates a username/password against a devise-powered backend application before forwarding the original HTTP request to the same application."
|
13
|
+
spec.homepage = "https://github.com/preston/devise-proxy"
|
14
|
+
spec.licenses = ["BSD"]
|
9
15
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
s.email = "conmotto@gmail.com"
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"LICENSE",
|
17
|
-
"README.md"
|
18
|
-
]
|
19
|
-
s.files = [
|
20
|
-
"Gemfile",
|
21
|
-
"Gemfile.lock",
|
22
|
-
"LICENSE",
|
23
|
-
"README.md",
|
24
|
-
"Rakefile",
|
25
|
-
"VERSION",
|
26
|
-
"config.ru",
|
27
|
-
"config/devise-proxy.yml.sample",
|
28
|
-
"devise-proxy.gemspec",
|
29
|
-
"lib/devise-proxy.rb",
|
30
|
-
"lib/devise-proxy/authenticator.rb",
|
31
|
-
"lib/devise-proxy/proxy.rb",
|
32
|
-
"test/helper.rb",
|
33
|
-
"test/test_devise-proxy.rb"
|
34
|
-
]
|
35
|
-
s.homepage = "http://github.com/preston/devise-proxy"
|
36
|
-
s.licenses = ["BSD"]
|
37
|
-
s.require_paths = ["lib"]
|
38
|
-
s.rubygems_version = "1.8.24"
|
39
|
-
s.summary = "A standalone Rack Middleware application that authenticates a username/password against a devise-powered backend application before forwarding the original HTTP request to the same application."
|
16
|
+
spec.files = `git ls-files`.split($/)
|
17
|
+
spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
|
18
|
+
spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
|
19
|
+
spec.require_paths = ["lib"]
|
40
20
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
|
45
|
-
s.add_runtime_dependency(%q<rack>, [">= 0"])
|
46
|
-
s.add_development_dependency(%q<shoulda>, [">= 0"])
|
47
|
-
s.add_development_dependency(%q<jeweler>, ["~> 1.8.4"])
|
48
|
-
s.add_development_dependency(%q<rake>, [">= 0"])
|
49
|
-
else
|
50
|
-
s.add_dependency(%q<rack>, [">= 0"])
|
51
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
52
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
53
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
54
|
-
end
|
55
|
-
else
|
56
|
-
s.add_dependency(%q<rack>, [">= 0"])
|
57
|
-
s.add_dependency(%q<shoulda>, [">= 0"])
|
58
|
-
s.add_dependency(%q<jeweler>, ["~> 1.8.4"])
|
59
|
-
s.add_dependency(%q<rake>, [">= 0"])
|
60
|
-
end
|
21
|
+
spec.add_runtime_dependency 'rack', '>= 1.5.2'
|
22
|
+
spec.add_development_dependency 'rake', '>= 10.3.2'
|
61
23
|
end
|
62
24
|
|
data/extra/devise-proxy
ADDED
@@ -0,0 +1,57 @@
|
|
1
|
+
#!/bin/sh
|
2
|
+
#
|
3
|
+
#
|
4
|
+
|
5
|
+
# Source function library.
|
6
|
+
. /etc/rc.d/init.d/functions
|
7
|
+
|
8
|
+
# Source networking configuration.
|
9
|
+
. /etc/sysconfig/network
|
10
|
+
|
11
|
+
# Check that networking is up.
|
12
|
+
[ "$NETWORKING" = "no" ] && exit 0
|
13
|
+
|
14
|
+
exec="/usr/local/rvm/bin/bootup_rackup"
|
15
|
+
prog="devise-proxy"
|
16
|
+
user=tater
|
17
|
+
proxy_home=/home/$user/$prog
|
18
|
+
proxy_port=6969
|
19
|
+
proxy_config=$proxy_home/config.ru
|
20
|
+
pid_file=$proxy_home/$prog.pid
|
21
|
+
|
22
|
+
|
23
|
+
start() {
|
24
|
+
|
25
|
+
echo -n $"Starting $prog: "
|
26
|
+
daemon --user=$user "$exec -p $proxy_port -D -P $pid_file $proxy_config"
|
27
|
+
retval=$?
|
28
|
+
return $retval
|
29
|
+
}
|
30
|
+
|
31
|
+
stop() {
|
32
|
+
echo -n $"Stopping $prog: "
|
33
|
+
killproc -p $pid_file
|
34
|
+
retval=$?
|
35
|
+
return $retval
|
36
|
+
}
|
37
|
+
|
38
|
+
restart() {
|
39
|
+
stop
|
40
|
+
start
|
41
|
+
}
|
42
|
+
|
43
|
+
force_reload() {
|
44
|
+
restart
|
45
|
+
}
|
46
|
+
|
47
|
+
case "$1" in
|
48
|
+
start|stop|restart)
|
49
|
+
$1
|
50
|
+
;;
|
51
|
+
force-reload)
|
52
|
+
force_reload
|
53
|
+
;;
|
54
|
+
*)
|
55
|
+
echo $"Usage: $0 {start|stop|restart|force-reload}"
|
56
|
+
exit 2
|
57
|
+
esac
|
@@ -33,12 +33,13 @@ module DeviseProxy
|
|
33
33
|
|
34
34
|
http = Net::HTTP.new(@host, @port).start
|
35
35
|
resp1 = http.request(sig)
|
36
|
-
puts "Response: #{resp1.code} , Message: #{resp1.message} , Body: #{resp1.body}"
|
36
|
+
# puts "Response: #{resp1.code} , Message: #{resp1.message} , Body: #{resp1.body}"
|
37
37
|
result = []
|
38
|
+
json_resp = JSON.parse(resp1.body)
|
39
|
+
#puts json_resp.inspect
|
40
|
+
@auth_token = json_resp['auth_token']
|
38
41
|
if resp1.code == "200" then
|
39
42
|
puts "logged in"
|
40
|
-
json_resp = JSON.parse(resp1.body)
|
41
|
-
@auth_token = json_resp['auth_token']
|
42
43
|
|
43
44
|
@req_body = {
|
44
45
|
"device" => {
|
@@ -52,19 +53,19 @@ module DeviseProxy
|
|
52
53
|
req.body = @req_body
|
53
54
|
|
54
55
|
response = http.request(req)
|
55
|
-
puts "Response: #{response.code} , Message: #{response.message} , Body: #{response.body}"
|
56
|
+
# puts "Response: #{response.code} , Message: #{response.message} , Body: #{response.body}"
|
56
57
|
|
57
58
|
headers = {}
|
58
59
|
sub_response.each_header do |k,v|
|
59
|
-
headers[k] = v unless k.to_s =~ /
|
60
|
+
headers[k] = v unless k.to_s =~ /content-length|transfer-encoding/i
|
60
61
|
end
|
61
62
|
result = [response.code, headers, response.body]
|
62
63
|
else
|
63
64
|
headers = {}
|
64
65
|
resp1.each_header do |k,v|
|
65
|
-
headers[k] = v unless k.to_s =~ /
|
66
|
+
headers[k] = v unless k.to_s =~ /content-length|transfer-encoding/i
|
66
67
|
end
|
67
|
-
result = [resp1.code, headers, resp1.body]
|
68
|
+
result = [resp1.code, headers, resp1.body, @auth_token]
|
68
69
|
end
|
69
70
|
return result
|
70
71
|
end
|
data/lib/devise-proxy/proxy.rb
CHANGED
@@ -27,7 +27,6 @@ module DeviseProxy
|
|
27
27
|
end
|
28
28
|
|
29
29
|
def call(env)
|
30
|
-
req = Rack::Request.new(env)
|
31
30
|
# puts req.to_yaml
|
32
31
|
|
33
32
|
puts "User agent: #{env['HTTP_USER_AGENT']}"
|
@@ -42,7 +41,7 @@ module DeviseProxy
|
|
42
41
|
email = credentials[0]
|
43
42
|
password = credentials[1]
|
44
43
|
|
45
|
-
puts "Client password credentials email: #{email}, password, #{password}"
|
44
|
+
#puts "Client password credentials email: #{email}, password, #{password}"
|
46
45
|
|
47
46
|
result = [502, {'Content-Type' => 'text/plain'}, ["HTTP 502 - Ah crap! The authenticating proxy seems to be having issues. :-/"]]
|
48
47
|
begin
|
@@ -53,11 +52,13 @@ module DeviseProxy
|
|
53
52
|
|
54
53
|
result = [403, auth[1], [auth[2]]]
|
55
54
|
if allowed
|
55
|
+
env['QUERY_STRING'] = [env['QUERY_STRING'], "auth_token=#{auth[3]}"].reject{|s| s.length < 1}.join('&')
|
56
56
|
|
57
|
+
req = Rack::Request.new(env)
|
57
58
|
method = req.request_method.downcase
|
58
59
|
method[0..0] = method[0..0].upcase
|
59
60
|
|
60
|
-
sub_request = Net::HTTP.const_get(method).new("#{req.path}
|
61
|
+
sub_request = Net::HTTP.const_get(method).new("#{req.path}?#{req.query_string}")
|
61
62
|
|
62
63
|
if sub_request.request_body_permitted? and req.body
|
63
64
|
sub_request.body_stream = req.body
|
@@ -69,18 +70,29 @@ module DeviseProxy
|
|
69
70
|
sub_request["Accept-Encoding"] = req.accept_encoding
|
70
71
|
sub_request["Referer"] = req.referer
|
71
72
|
|
73
|
+
all_cookies = auth[1]['set-cookie'].split(/;/)
|
74
|
+
cookies_array = Array.new
|
75
|
+
all_cookies.each { | cookie |
|
76
|
+
cookies_array.push(cookie.split('; ')[0])
|
77
|
+
}
|
78
|
+
cookies = cookies_array.join('; ')
|
79
|
+
|
80
|
+
sub_request["Cookie"] = cookies
|
81
|
+
|
72
82
|
sub_response = Net::HTTP.start(@host, @port) do |http|
|
73
83
|
http.request(sub_request)
|
74
84
|
end
|
75
85
|
|
76
86
|
headers = {}
|
77
87
|
sub_response.each_header do |k,v|
|
78
|
-
headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding/i
|
88
|
+
headers[k] = v unless k.to_s =~ /cookie|content-length|transfer-encoding|status/i
|
79
89
|
end
|
80
90
|
|
81
|
-
|
91
|
+
body = sub_response.body
|
92
|
+
result = [sub_response.code.to_i, headers, [body]]
|
82
93
|
end
|
83
|
-
rescue
|
94
|
+
rescue Exception => e
|
95
|
+
puts e.message
|
84
96
|
# Probably an I/O issue connecting to the authentication service.
|
85
97
|
end
|
86
98
|
|
@@ -93,7 +105,9 @@ module DeviseProxy
|
|
93
105
|
# end
|
94
106
|
headers['Proxy-Authenticate'] = 'Basic realm="A valid account is required. Please use your registered email address as your username."'
|
95
107
|
headers['Content-Type'] = 'text/plain'
|
96
|
-
|
108
|
+
headers['WWW-Authenticate'] = 'Basic realm="aousntoheunth"'
|
109
|
+
# result = [407, headers, ["Email/Password required!"]]
|
110
|
+
result = [401, headers, ["Email/Password required!"]]
|
97
111
|
end
|
98
112
|
|
99
113
|
|
data/test/helper.rb
CHANGED
metadata
CHANGED
@@ -1,133 +1,96 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: devise-proxy
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
5
|
-
prerelease:
|
4
|
+
version: 1.0.0
|
6
5
|
platform: ruby
|
7
6
|
authors:
|
8
7
|
- Preston Lee
|
9
8
|
autorequire:
|
10
9
|
bindir: bin
|
11
10
|
cert_chain: []
|
12
|
-
date:
|
11
|
+
date: 2014-10-10 00:00:00.000000000 Z
|
13
12
|
dependencies:
|
14
13
|
- !ruby/object:Gem::Dependency
|
15
14
|
name: rack
|
16
15
|
requirement: !ruby/object:Gem::Requirement
|
17
|
-
none: false
|
18
16
|
requirements:
|
19
|
-
- -
|
17
|
+
- - ">="
|
20
18
|
- !ruby/object:Gem::Version
|
21
|
-
version:
|
19
|
+
version: 1.5.2
|
22
20
|
type: :runtime
|
23
21
|
prerelease: false
|
24
22
|
version_requirements: !ruby/object:Gem::Requirement
|
25
|
-
none: false
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
|
-
version:
|
30
|
-
- !ruby/object:Gem::Dependency
|
31
|
-
name: shoulda
|
32
|
-
requirement: !ruby/object:Gem::Requirement
|
33
|
-
none: false
|
34
|
-
requirements:
|
35
|
-
- - ! '>='
|
36
|
-
- !ruby/object:Gem::Version
|
37
|
-
version: '0'
|
38
|
-
type: :development
|
39
|
-
prerelease: false
|
40
|
-
version_requirements: !ruby/object:Gem::Requirement
|
41
|
-
none: false
|
42
|
-
requirements:
|
43
|
-
- - ! '>='
|
44
|
-
- !ruby/object:Gem::Version
|
45
|
-
version: '0'
|
46
|
-
- !ruby/object:Gem::Dependency
|
47
|
-
name: jeweler
|
48
|
-
requirement: !ruby/object:Gem::Requirement
|
49
|
-
none: false
|
50
|
-
requirements:
|
51
|
-
- - ~>
|
52
|
-
- !ruby/object:Gem::Version
|
53
|
-
version: 1.8.4
|
54
|
-
type: :development
|
55
|
-
prerelease: false
|
56
|
-
version_requirements: !ruby/object:Gem::Requirement
|
57
|
-
none: false
|
58
|
-
requirements:
|
59
|
-
- - ~>
|
60
|
-
- !ruby/object:Gem::Version
|
61
|
-
version: 1.8.4
|
26
|
+
version: 1.5.2
|
62
27
|
- !ruby/object:Gem::Dependency
|
63
28
|
name: rake
|
64
29
|
requirement: !ruby/object:Gem::Requirement
|
65
|
-
none: false
|
66
30
|
requirements:
|
67
|
-
- -
|
31
|
+
- - ">="
|
68
32
|
- !ruby/object:Gem::Version
|
69
|
-
version:
|
33
|
+
version: 10.3.2
|
70
34
|
type: :development
|
71
35
|
prerelease: false
|
72
36
|
version_requirements: !ruby/object:Gem::Requirement
|
73
|
-
none: false
|
74
37
|
requirements:
|
75
|
-
- -
|
38
|
+
- - ">="
|
76
39
|
- !ruby/object:Gem::Version
|
77
|
-
version:
|
40
|
+
version: 10.3.2
|
78
41
|
description: A standalone Rack Middleware application that authenticates a username/password
|
79
42
|
against a devise-powered backend application before forwarding the original HTTP
|
80
43
|
request to the same application. Authentication is done on *every* request, so it
|
81
44
|
is advisable to use devise-proxy sparingly.
|
82
|
-
email:
|
83
|
-
executables:
|
45
|
+
email: preston.lee@prestonlee.com
|
46
|
+
executables:
|
47
|
+
- devise-socks.rb
|
48
|
+
- mock-socks.rb
|
84
49
|
extensions: []
|
85
|
-
extra_rdoc_files:
|
86
|
-
- LICENSE
|
87
|
-
- README.md
|
50
|
+
extra_rdoc_files: []
|
88
51
|
files:
|
89
|
-
-
|
90
|
-
- Gemfile.lock
|
52
|
+
- ".gitignore"
|
91
53
|
- LICENSE
|
92
54
|
- README.md
|
93
55
|
- Rakefile
|
94
|
-
-
|
56
|
+
- bin/devise-socks.rb
|
57
|
+
- bin/mock-socks.rb
|
95
58
|
- config.ru
|
96
59
|
- config/devise-proxy.yml.sample
|
97
60
|
- devise-proxy.gemspec
|
61
|
+
- extra/devise-proxy
|
98
62
|
- lib/devise-proxy.rb
|
99
63
|
- lib/devise-proxy/authenticator.rb
|
100
64
|
- lib/devise-proxy/proxy.rb
|
65
|
+
- lib/devise-proxy/version.rb
|
101
66
|
- test/helper.rb
|
102
|
-
- test/
|
103
|
-
homepage:
|
67
|
+
- test/lib/authenticator_test.rb
|
68
|
+
homepage: https://github.com/preston/devise-proxy
|
104
69
|
licenses:
|
105
70
|
- BSD
|
71
|
+
metadata: {}
|
106
72
|
post_install_message:
|
107
73
|
rdoc_options: []
|
108
74
|
require_paths:
|
109
75
|
- lib
|
110
76
|
required_ruby_version: !ruby/object:Gem::Requirement
|
111
|
-
none: false
|
112
77
|
requirements:
|
113
|
-
- -
|
78
|
+
- - ">="
|
114
79
|
- !ruby/object:Gem::Version
|
115
80
|
version: '0'
|
116
|
-
segments:
|
117
|
-
- 0
|
118
|
-
hash: -1230018857575091658
|
119
81
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
120
|
-
none: false
|
121
82
|
requirements:
|
122
|
-
- -
|
83
|
+
- - ">="
|
123
84
|
- !ruby/object:Gem::Version
|
124
85
|
version: '0'
|
125
86
|
requirements: []
|
126
87
|
rubyforge_project:
|
127
|
-
rubygems_version:
|
88
|
+
rubygems_version: 2.2.2
|
128
89
|
signing_key:
|
129
|
-
specification_version:
|
90
|
+
specification_version: 4
|
130
91
|
summary: A standalone Rack Middleware application that authenticates a username/password
|
131
92
|
against a devise-powered backend application before forwarding the original HTTP
|
132
93
|
request to the same application.
|
133
|
-
test_files:
|
94
|
+
test_files:
|
95
|
+
- test/helper.rb
|
96
|
+
- test/lib/authenticator_test.rb
|
data/Gemfile
DELETED
data/Gemfile.lock
DELETED
@@ -1,34 +0,0 @@
|
|
1
|
-
GEM
|
2
|
-
remote: https://rubygems.org/
|
3
|
-
specs:
|
4
|
-
activesupport (3.2.8)
|
5
|
-
i18n (~> 0.6)
|
6
|
-
multi_json (~> 1.0)
|
7
|
-
git (1.2.5)
|
8
|
-
i18n (0.6.1)
|
9
|
-
jeweler (1.8.4)
|
10
|
-
bundler (~> 1.0)
|
11
|
-
git (>= 1.2.5)
|
12
|
-
rake
|
13
|
-
rdoc
|
14
|
-
json (1.7.5)
|
15
|
-
multi_json (1.3.6)
|
16
|
-
rack (1.4.1)
|
17
|
-
rake (0.9.2.2)
|
18
|
-
rdoc (3.12)
|
19
|
-
json (~> 1.4)
|
20
|
-
shoulda (3.3.2)
|
21
|
-
shoulda-context (~> 1.0.1)
|
22
|
-
shoulda-matchers (~> 1.4.1)
|
23
|
-
shoulda-context (1.0.1)
|
24
|
-
shoulda-matchers (1.4.1)
|
25
|
-
activesupport (>= 3.0.0)
|
26
|
-
|
27
|
-
PLATFORMS
|
28
|
-
ruby
|
29
|
-
|
30
|
-
DEPENDENCIES
|
31
|
-
jeweler (~> 1.8.4)
|
32
|
-
rack
|
33
|
-
rake
|
34
|
-
shoulda
|
data/VERSION
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
0.1.4
|