devise-proxy 0.1.4 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|