passenger 2.2.7 → 2.2.8
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of passenger might be problematic. Click here for more details.
- data/NEWS +40 -0
- data/Rakefile +1 -1
- data/bin/passenger-install-apache2-module +1 -0
- data/bin/passenger-install-nginx-module +2 -0
- data/doc/Architectural overview.html +173 -138
- data/doc/Security of user switching support.html +147 -109
- data/doc/Users guide Apache.html +4 -43
- data/doc/Users guide Nginx.html +4 -43
- data/doc/cxxapi/Bucket_8h-source.html +1 -1
- data/doc/cxxapi/Configuration_8h-source.html +1 -1
- data/doc/cxxapi/DirectoryMapper_8h-source.html +1 -1
- data/doc/cxxapi/Hooks_8h-source.html +1 -1
- data/doc/cxxapi/annotated.html +1 -1
- data/doc/cxxapi/classHooks-members.html +1 -1
- data/doc/cxxapi/classHooks.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +1 -1
- data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +1 -1
- data/doc/cxxapi/classes.html +1 -1
- data/doc/cxxapi/definitions_8h-source.html +1 -1
- data/doc/cxxapi/files.html +1 -1
- data/doc/cxxapi/functions.html +1 -1
- data/doc/cxxapi/functions_func.html +1 -1
- data/doc/cxxapi/graph_legend.html +1 -1
- data/doc/cxxapi/group__Configuration.html +1 -1
- data/doc/cxxapi/group__Core.html +1 -1
- data/doc/cxxapi/group__Hooks.html +1 -1
- data/doc/cxxapi/group__Support.html +1 -1
- data/doc/cxxapi/main.html +1 -1
- data/doc/cxxapi/modules.html +1 -1
- data/doc/rdoc/classes/GC.html +4 -4
- data/doc/rdoc/classes/PhusionPassenger.html +2 -1
- data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +8 -8
- data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +26 -26
- data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +98 -98
- data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +61 -61
- data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +4 -4
- data/doc/rdoc/classes/PhusionPassenger/Application.html +14 -14
- data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +12 -12
- data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +4 -4
- data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +12 -12
- data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +5 -5
- data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +42 -42
- data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +33 -33
- data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +59 -59
- data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +3 -3
- data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +7 -7
- data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +23 -23
- data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +4 -4
- data/doc/rdoc/classes/PhusionPassenger/Utils.html +2 -0
- data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +16 -16
- data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +4 -4
- data/doc/rdoc/classes/PlatformInfo.html +1 -1
- data/doc/rdoc/classes/Signal.html +23 -15
- data/doc/rdoc/created.rid +1 -1
- data/doc/rdoc/files/DEVELOPERS_TXT.html +1 -1
- data/doc/rdoc/files/README.html +1 -1
- data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +2 -2
- data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +2 -2
- data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +1 -1
- data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +9 -9
- data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +1 -1
- data/doc/rdoc/files/misc/rake/extensions_rb.html +1 -1
- data/doc/rdoc/fr_class_index.html +2 -0
- data/doc/rdoc/fr_file_index.html +1 -0
- data/doc/rdoc/fr_method_index.html +79 -72
- data/ext/apache2/Hooks.cpp +4 -2
- data/ext/common/StandardApplicationPool.h +4 -2
- data/ext/common/Version.h +1 -1
- data/ext/nginx/Configuration.c +1 -1
- data/ext/oxt/system_calls.cpp +11 -0
- data/ext/oxt/system_calls.hpp +2 -1
- data/ext/oxt/thread.hpp +97 -1
- data/lib/phusion_passenger/constants.rb +1 -1
- data/lib/phusion_passenger/dependencies.rb +32 -0
- data/lib/phusion_passenger/platform_info.rb +1 -1
- data/lib/phusion_passenger/rack/application_spawner.rb +4 -4
- data/lib/phusion_passenger/rack/request_handler.rb +2 -5
- data/lib/phusion_passenger/railz/application_spawner.rb +13 -2
- data/lib/phusion_passenger/utils.rb +12 -4
- data/{vendor/rack-1.0.0-git/lib/rack → lib/phusion_passenger/utils}/rewindable_input.rb +19 -3
- data/test/ApplicationPoolTest.cpp +1 -1
- metadata +13 -59
- data/vendor/README +0 -13
- data/vendor/README_FOR_PACKAGERS +0 -1
- data/vendor/rack-1.0.0-git/COPYING +0 -18
- data/vendor/rack-1.0.0-git/KNOWN-ISSUES +0 -18
- data/vendor/rack-1.0.0-git/README +0 -353
- data/vendor/rack-1.0.0-git/Rakefile +0 -164
- data/vendor/rack-1.0.0-git/lib/rack.rb +0 -90
- data/vendor/rack-1.0.0-git/lib/rack/adapter/camping.rb +0 -22
- data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/handler.rb +0 -37
- data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/request.rb +0 -37
- data/vendor/rack-1.0.0-git/lib/rack/auth/basic.rb +0 -58
- data/vendor/rack-1.0.0-git/lib/rack/auth/digest/md5.rb +0 -124
- data/vendor/rack-1.0.0-git/lib/rack/auth/digest/nonce.rb +0 -51
- data/vendor/rack-1.0.0-git/lib/rack/auth/digest/params.rb +0 -55
- data/vendor/rack-1.0.0-git/lib/rack/auth/digest/request.rb +0 -40
- data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +0 -487
- data/vendor/rack-1.0.0-git/lib/rack/builder.rb +0 -63
- data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +0 -41
- data/vendor/rack-1.0.0-git/lib/rack/chunked.rb +0 -49
- data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +0 -52
- data/vendor/rack-1.0.0-git/lib/rack/conditionalget.rb +0 -47
- data/vendor/rack-1.0.0-git/lib/rack/content_length.rb +0 -29
- data/vendor/rack-1.0.0-git/lib/rack/content_type.rb +0 -23
- data/vendor/rack-1.0.0-git/lib/rack/deflater.rb +0 -96
- data/vendor/rack-1.0.0-git/lib/rack/directory.rb +0 -153
- data/vendor/rack-1.0.0-git/lib/rack/file.rb +0 -88
- data/vendor/rack-1.0.0-git/lib/rack/handler.rb +0 -69
- data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +0 -61
- data/vendor/rack-1.0.0-git/lib/rack/handler/evented_mongrel.rb +0 -8
- data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +0 -88
- data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +0 -55
- data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +0 -84
- data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +0 -59
- data/vendor/rack-1.0.0-git/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
- data/vendor/rack-1.0.0-git/lib/rack/handler/thin.rb +0 -18
- data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +0 -67
- data/vendor/rack-1.0.0-git/lib/rack/head.rb +0 -19
- data/vendor/rack-1.0.0-git/lib/rack/lint.rb +0 -537
- data/vendor/rack-1.0.0-git/lib/rack/lobster.rb +0 -65
- data/vendor/rack-1.0.0-git/lib/rack/lock.rb +0 -16
- data/vendor/rack-1.0.0-git/lib/rack/methodoverride.rb +0 -27
- data/vendor/rack-1.0.0-git/lib/rack/mime.rb +0 -204
- data/vendor/rack-1.0.0-git/lib/rack/mock.rb +0 -184
- data/vendor/rack-1.0.0-git/lib/rack/recursive.rb +0 -57
- data/vendor/rack-1.0.0-git/lib/rack/reloader.rb +0 -106
- data/vendor/rack-1.0.0-git/lib/rack/request.rb +0 -248
- data/vendor/rack-1.0.0-git/lib/rack/response.rb +0 -183
- data/vendor/rack-1.0.0-git/lib/rack/session/abstract/id.rb +0 -142
- data/vendor/rack-1.0.0-git/lib/rack/session/cookie.rb +0 -91
- data/vendor/rack-1.0.0-git/lib/rack/session/memcache.rb +0 -109
- data/vendor/rack-1.0.0-git/lib/rack/session/pool.rb +0 -100
- data/vendor/rack-1.0.0-git/lib/rack/showexceptions.rb +0 -349
- data/vendor/rack-1.0.0-git/lib/rack/showstatus.rb +0 -106
- data/vendor/rack-1.0.0-git/lib/rack/static.rb +0 -38
- data/vendor/rack-1.0.0-git/lib/rack/urlmap.rb +0 -55
- data/vendor/rack-1.0.0-git/lib/rack/utils.rb +0 -522
@@ -1,40 +0,0 @@
|
|
1
|
-
require 'rack/auth/abstract/request'
|
2
|
-
require 'rack/auth/digest/params'
|
3
|
-
require 'rack/auth/digest/nonce'
|
4
|
-
|
5
|
-
module Rack
|
6
|
-
module Auth
|
7
|
-
module Digest
|
8
|
-
class Request < Auth::AbstractRequest
|
9
|
-
|
10
|
-
def method
|
11
|
-
@env['rack.methodoverride.original_method'] || @env['REQUEST_METHOD']
|
12
|
-
end
|
13
|
-
|
14
|
-
def digest?
|
15
|
-
:digest == scheme
|
16
|
-
end
|
17
|
-
|
18
|
-
def correct_uri?
|
19
|
-
(@env['SCRIPT_NAME'].to_s + @env['PATH_INFO'].to_s) == uri
|
20
|
-
end
|
21
|
-
|
22
|
-
def nonce
|
23
|
-
@nonce ||= Nonce.parse(params['nonce'])
|
24
|
-
end
|
25
|
-
|
26
|
-
def params
|
27
|
-
@params ||= Params.parse(parts.last)
|
28
|
-
end
|
29
|
-
|
30
|
-
def method_missing(sym)
|
31
|
-
if params.has_key? key = sym.to_s
|
32
|
-
return params[key]
|
33
|
-
end
|
34
|
-
super
|
35
|
-
end
|
36
|
-
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|
@@ -1,487 +0,0 @@
|
|
1
|
-
# AUTHOR: Scytrin dai Kinthra <scytrin@gmail.com>; blink#ruby-lang@irc.freenode.net
|
2
|
-
|
3
|
-
gem 'ruby-openid', '~> 2' if defined? Gem
|
4
|
-
require 'rack/request'
|
5
|
-
require 'rack/utils'
|
6
|
-
require 'rack/auth/abstract/handler'
|
7
|
-
|
8
|
-
require 'uri'
|
9
|
-
require 'openid'
|
10
|
-
require 'openid/extension'
|
11
|
-
require 'openid/store/memory'
|
12
|
-
|
13
|
-
module Rack
|
14
|
-
class Request
|
15
|
-
def openid_request
|
16
|
-
@env['rack.auth.openid.request']
|
17
|
-
end
|
18
|
-
|
19
|
-
def openid_response
|
20
|
-
@env['rack.auth.openid.response']
|
21
|
-
end
|
22
|
-
end
|
23
|
-
|
24
|
-
module Auth
|
25
|
-
|
26
|
-
# Rack::Auth::OpenID provides a simple method for setting up an OpenID
|
27
|
-
# Consumer. It requires the ruby-openid library from janrain to operate,
|
28
|
-
# as well as a rack method of session management.
|
29
|
-
#
|
30
|
-
# The ruby-openid home page is at http://openidenabled.com/ruby-openid/.
|
31
|
-
#
|
32
|
-
# The OpenID specifications can be found at
|
33
|
-
# http://openid.net/specs/openid-authentication-1_1.html
|
34
|
-
# and
|
35
|
-
# http://openid.net/specs/openid-authentication-2_0.html. Documentation
|
36
|
-
# for published OpenID extensions and related topics can be found at
|
37
|
-
# http://openid.net/developers/specs/.
|
38
|
-
#
|
39
|
-
# It is recommended to read through the OpenID spec, as well as
|
40
|
-
# ruby-openid's documentation, to understand what exactly goes on. However
|
41
|
-
# a setup as simple as the presented examples is enough to provide
|
42
|
-
# Consumer functionality.
|
43
|
-
#
|
44
|
-
# This library strongly intends to utilize the OpenID 2.0 features of the
|
45
|
-
# ruby-openid library, which provides OpenID 1.0 compatiblity.
|
46
|
-
#
|
47
|
-
# NOTE: Due to the amount of data that this library stores in the
|
48
|
-
# session, Rack::Session::Cookie may fault.
|
49
|
-
#
|
50
|
-
# == Examples
|
51
|
-
#
|
52
|
-
# simple_oid = OpenID.new('http://mysite.com/')
|
53
|
-
#
|
54
|
-
# return_oid = OpenID.new('http://mysite.com/', {
|
55
|
-
# :return_to => 'http://mysite.com/openid'
|
56
|
-
# })
|
57
|
-
#
|
58
|
-
# complex_oid = OpenID.new('http://mysite.com/',
|
59
|
-
# :immediate => true,
|
60
|
-
# :extensions => {
|
61
|
-
# ::OpenID::SReg => [['email'],['nickname']]
|
62
|
-
# }
|
63
|
-
# )
|
64
|
-
#
|
65
|
-
# = Advanced
|
66
|
-
#
|
67
|
-
# Most of the functionality of this library is encapsulated such that
|
68
|
-
# expansion and overriding functions isn't difficult nor tricky.
|
69
|
-
# Alternately, to avoid opening up singleton objects or subclassing, a
|
70
|
-
# wrapper rack middleware can be composed to act upon Auth::OpenID's
|
71
|
-
# responses. See #check and #finish for locations of pertinent data.
|
72
|
-
#
|
73
|
-
# == Responses
|
74
|
-
#
|
75
|
-
# To change the responses that Auth::OpenID returns, override the methods
|
76
|
-
# #redirect, #bad_request, #unauthorized, #access_denied, and
|
77
|
-
# #foreign_server_failure.
|
78
|
-
#
|
79
|
-
# Additionally #confirm_post_params is used when the URI would exceed
|
80
|
-
# length limits on a GET request when doing the initial verification
|
81
|
-
# request.
|
82
|
-
#
|
83
|
-
# == Processing
|
84
|
-
#
|
85
|
-
# To change methods of processing completed transactions, override the
|
86
|
-
# methods #success, #setup_needed, #cancel, and #failure. Please ensure
|
87
|
-
# the returned object is a rack compatible response.
|
88
|
-
#
|
89
|
-
# The first argument is an OpenID::Response, the second is a
|
90
|
-
# Rack::Request of the current request, the last is the hash used in
|
91
|
-
# ruby-openid handling, which can be found manually at
|
92
|
-
# env['rack.session'][:openid].
|
93
|
-
#
|
94
|
-
# This is useful if you wanted to expand the processing done, such as
|
95
|
-
# setting up user accounts.
|
96
|
-
#
|
97
|
-
# oid_app = Rack::Auth::OpenID.new realm, :return_to => return_to
|
98
|
-
# def oid_app.success oid, request, session
|
99
|
-
# user = Models::User[oid.identity_url]
|
100
|
-
# user ||= Models::User.create_from_openid oid
|
101
|
-
# request['rack.session'][:user] = user.id
|
102
|
-
# redirect MyApp.site_home
|
103
|
-
# end
|
104
|
-
#
|
105
|
-
# site_map['/openid'] = oid_app
|
106
|
-
# map = Rack::URLMap.new site_map
|
107
|
-
# ...
|
108
|
-
|
109
|
-
class OpenID
|
110
|
-
# Raised if an incompatible session is being used.
|
111
|
-
class NoSession < RuntimeError; end
|
112
|
-
# Raised if an extension not matching specifications is provided.
|
113
|
-
class BadExtension < RuntimeError; end
|
114
|
-
# Possible statuses returned from consumer responses. See definitions
|
115
|
-
# in the ruby-openid library.
|
116
|
-
ValidStatus = [
|
117
|
-
::OpenID::Consumer::SUCCESS,
|
118
|
-
::OpenID::Consumer::FAILURE,
|
119
|
-
::OpenID::Consumer::CANCEL,
|
120
|
-
::OpenID::Consumer::SETUP_NEEDED
|
121
|
-
]
|
122
|
-
|
123
|
-
# The first argument is the realm, identifying the site they are trusting
|
124
|
-
# with their identity. This is required, also treated as the trust_root
|
125
|
-
# in OpenID 1.x exchanges.
|
126
|
-
#
|
127
|
-
# The lits of acceptable options include :return_to, :session_key,
|
128
|
-
# :openid_param, :store, :immediate, :extensions.
|
129
|
-
#
|
130
|
-
# <tt>:return_to</tt> defines the url to return to after the client
|
131
|
-
# authenticates with the openid service provider. This url should point
|
132
|
-
# to where Rack::Auth::OpenID is mounted. If unprovided, the url of
|
133
|
-
# the current request is used.
|
134
|
-
#
|
135
|
-
# <tt>:session_key</tt> defines the key to the session hash in the env.
|
136
|
-
# The default is 'rack.session'.
|
137
|
-
#
|
138
|
-
# <tt>:openid_param</tt> defines at what key in the request parameters to
|
139
|
-
# find the identifier to resolve. As per the 2.0 spec, the default is
|
140
|
-
# 'openid_identifier'.
|
141
|
-
#
|
142
|
-
# <tt>:store</tt> defined what OpenID Store to use for persistant
|
143
|
-
# information. By default a Store::Memory is used.
|
144
|
-
#
|
145
|
-
# <tt>:immediate</tt> as true will make initial requests to be of an
|
146
|
-
# immediate type. This is false by default. See OpenID specification
|
147
|
-
# documentation.
|
148
|
-
#
|
149
|
-
# <tt>:extensions</tt> should be a hash of openid extension
|
150
|
-
# implementations. The key should be the extension module, the value
|
151
|
-
# should be an array of arguments for extension::Request.new().
|
152
|
-
# The hash is iterated over and passed to #add_extension for processing.
|
153
|
-
# Please see #add_extension for further documentation.
|
154
|
-
|
155
|
-
def initialize(realm, options={})
|
156
|
-
realm = URI(realm)
|
157
|
-
raise ArgumentError, "Invalid realm: #{realm}" \
|
158
|
-
unless realm.absolute? \
|
159
|
-
and realm.fragment.nil? \
|
160
|
-
and realm.scheme =~ /^https?$/ \
|
161
|
-
and realm.host =~ /^(\*\.)?#{URI::REGEXP::PATTERN::URIC_NO_SLASH}+/
|
162
|
-
realm.path = '/' if realm.path.empty?
|
163
|
-
@realm = realm.to_s
|
164
|
-
|
165
|
-
if ruri = options[:return_to]
|
166
|
-
ruri = URI(ruri)
|
167
|
-
raise ArgumentError, "Invalid return_to: #{ruri}" \
|
168
|
-
unless ruri.absolute? \
|
169
|
-
and ruri.scheme =~ /^https?$/ \
|
170
|
-
and ruri.fragment.nil?
|
171
|
-
raise ArgumentError, "return_to #{ruri} not within realm #{realm}" \
|
172
|
-
unless self.within_realm?(ruri)
|
173
|
-
@return_to = ruri.to_s
|
174
|
-
end
|
175
|
-
|
176
|
-
@session_key = options[:session_key] || 'rack.session'
|
177
|
-
@openid_param = options[:openid_param] || 'openid_identifier'
|
178
|
-
@store = options[:store] || ::OpenID::Store::Memory.new
|
179
|
-
@immediate = !!options[:immediate]
|
180
|
-
|
181
|
-
@extensions = {}
|
182
|
-
if extensions = options[:extensions]
|
183
|
-
extensions.each do |ext, args|
|
184
|
-
add_extension(ext, *args)
|
185
|
-
end
|
186
|
-
end
|
187
|
-
|
188
|
-
# Undocumented, semi-experimental
|
189
|
-
@anonymous = !!options[:anonymous]
|
190
|
-
end
|
191
|
-
|
192
|
-
attr_reader :realm, :return_to, :session_key, :openid_param, :store,
|
193
|
-
:immediate, :extensions
|
194
|
-
|
195
|
-
# Sets up and uses session data at <tt>:openid</tt> within the session.
|
196
|
-
# Errors in this setup will raise a NoSession exception.
|
197
|
-
#
|
198
|
-
# If the parameter 'openid.mode' is set, which implies a followup from
|
199
|
-
# the openid server, processing is passed to #finish and the result is
|
200
|
-
# returned. However, if there is no appropriate openid information in the
|
201
|
-
# session, a 400 error is returned.
|
202
|
-
#
|
203
|
-
# If the parameter specified by <tt>options[:openid_param]</tt> is
|
204
|
-
# present, processing is passed to #check and the result is returned.
|
205
|
-
#
|
206
|
-
# If neither of these conditions are met, #bad_request is called.
|
207
|
-
|
208
|
-
def call(env)
|
209
|
-
env['rack.auth.openid'] = self
|
210
|
-
env_session = env[@session_key]
|
211
|
-
unless env_session and env_session.is_a?(Hash)
|
212
|
-
raise NoSession, 'No compatible session.'
|
213
|
-
end
|
214
|
-
# let us work in our own namespace...
|
215
|
-
session = (env_session[:openid] ||= {})
|
216
|
-
unless session and session.is_a?(Hash)
|
217
|
-
raise NoSession, 'Incompatible openid session.'
|
218
|
-
end
|
219
|
-
|
220
|
-
request = Rack::Request.new(env)
|
221
|
-
consumer = ::OpenID::Consumer.new(session, @store)
|
222
|
-
|
223
|
-
if mode = request.GET['openid.mode']
|
224
|
-
finish(consumer, session, request)
|
225
|
-
elsif request.GET[@openid_param]
|
226
|
-
check(consumer, session, request)
|
227
|
-
else
|
228
|
-
bad_request
|
229
|
-
end
|
230
|
-
end
|
231
|
-
|
232
|
-
# As the first part of OpenID consumer action, #check retrieves the data
|
233
|
-
# required for completion.
|
234
|
-
#
|
235
|
-
# If all parameters fit within the max length of a URI, a 303 redirect
|
236
|
-
# will be returned. Otherwise #confirm_post_params will be called.
|
237
|
-
#
|
238
|
-
# Any messages from OpenID's request are logged to env['rack.errors']
|
239
|
-
#
|
240
|
-
# <tt>env['rack.auth.openid.request']</tt> is the openid checkid request
|
241
|
-
# instance.
|
242
|
-
#
|
243
|
-
# <tt>session[:openid_param]</tt> is set to the openid identifier
|
244
|
-
# provided by the user.
|
245
|
-
#
|
246
|
-
# <tt>session[:return_to]</tt> is set to the return_to uri given to the
|
247
|
-
# identity provider.
|
248
|
-
|
249
|
-
def check(consumer, session, req)
|
250
|
-
oid = consumer.begin(req.GET[@openid_param], @anonymous)
|
251
|
-
req.env['rack.auth.openid.request'] = oid
|
252
|
-
req.env['rack.errors'].puts(oid.message)
|
253
|
-
p oid if $DEBUG
|
254
|
-
|
255
|
-
## Extension support
|
256
|
-
extensions.each do |ext,args|
|
257
|
-
oid.add_extension(ext::Request.new(*args))
|
258
|
-
end
|
259
|
-
|
260
|
-
session[:openid_param] = req.GET[openid_param]
|
261
|
-
return_to_uri = return_to ? return_to : req.url
|
262
|
-
session[:return_to] = return_to_uri
|
263
|
-
immediate = session.key?(:setup_needed) ? false : immediate
|
264
|
-
|
265
|
-
if oid.send_redirect?(realm, return_to_uri, immediate)
|
266
|
-
redirect(oid.redirect_url(realm, return_to_uri, immediate))
|
267
|
-
else
|
268
|
-
confirm_post_params(oid, realm, return_to_uri, immediate)
|
269
|
-
end
|
270
|
-
rescue ::OpenID::DiscoveryFailure => e
|
271
|
-
# thrown from inside OpenID::Consumer#begin by yadis stuff
|
272
|
-
req.env['rack.errors'].puts( [e.message, *e.backtrace]*"\n" )
|
273
|
-
return foreign_server_failure
|
274
|
-
end
|
275
|
-
|
276
|
-
# This is the final portion of authentication.
|
277
|
-
# If successful, a redirect to the realm is be returned.
|
278
|
-
# Data gathered from extensions are stored in session[:openid] with the
|
279
|
-
# extension's namespace uri as the key.
|
280
|
-
#
|
281
|
-
# Any messages from OpenID's response are logged to env['rack.errors']
|
282
|
-
#
|
283
|
-
# <tt>env['rack.auth.openid.response']</tt> will contain the openid
|
284
|
-
# response.
|
285
|
-
|
286
|
-
def finish(consumer, session, req)
|
287
|
-
oid = consumer.complete(req.GET, req.url)
|
288
|
-
req.env['rack.auth.openid.response'] = oid
|
289
|
-
req.env['rack.errors'].puts(oid.message)
|
290
|
-
p oid if $DEBUG
|
291
|
-
|
292
|
-
if ValidStatus.include?(oid.status)
|
293
|
-
__send__(oid.status, oid, req, session)
|
294
|
-
else
|
295
|
-
invalid_status(oid, req, session)
|
296
|
-
end
|
297
|
-
end
|
298
|
-
|
299
|
-
# The first argument should be the main extension module.
|
300
|
-
# The extension module should contain the constants:
|
301
|
-
# * class Request, should have OpenID::Extension as an ancestor
|
302
|
-
# * class Response, should have OpenID::Extension as an ancestor
|
303
|
-
# * string NS_URI, which defining the namespace of the extension
|
304
|
-
#
|
305
|
-
# All trailing arguments will be passed to extension::Request.new in
|
306
|
-
# #check.
|
307
|
-
# The openid response will be passed to
|
308
|
-
# extension::Response#from_success_response, oid#get_extension_args will
|
309
|
-
# be called on the result to attain the gathered data.
|
310
|
-
#
|
311
|
-
# This method returns the key at which the response data will be found in
|
312
|
-
# the session, which is the namespace uri by default.
|
313
|
-
|
314
|
-
def add_extension(ext, *args)
|
315
|
-
raise BadExtension unless valid_extension?(ext)
|
316
|
-
extensions[ext] = args
|
317
|
-
return ext::NS_URI
|
318
|
-
end
|
319
|
-
|
320
|
-
# Checks the validitity, in the context of usage, of a submitted
|
321
|
-
# extension.
|
322
|
-
|
323
|
-
def valid_extension?(ext)
|
324
|
-
if not %w[NS_URI Request Response].all?{|c| ext.const_defined?(c) }
|
325
|
-
raise ArgumentError, 'Extension is missing constants.'
|
326
|
-
elsif not ext::Response.respond_to?(:from_success_response)
|
327
|
-
raise ArgumentError, 'Response is missing required method.'
|
328
|
-
end
|
329
|
-
return true
|
330
|
-
rescue
|
331
|
-
return false
|
332
|
-
end
|
333
|
-
|
334
|
-
# Checks the provided uri to ensure it'd be considered within the realm.
|
335
|
-
# is currently not compatible with wildcard realms.
|
336
|
-
|
337
|
-
def within_realm? uri
|
338
|
-
uri = URI.parse(uri.to_s)
|
339
|
-
realm = URI.parse(self.realm)
|
340
|
-
return false unless uri.absolute?
|
341
|
-
return false unless uri.path[0, realm.path.size] == realm.path
|
342
|
-
return false unless uri.host == realm.host or realm.host[/^\*\./]
|
343
|
-
# for wildcard support, is awkward with URI limitations
|
344
|
-
realm_match = Regexp.escape(realm.host).
|
345
|
-
sub(/^\*\./,"^#{URI::REGEXP::PATTERN::URIC_NO_SLASH}+.")+'$'
|
346
|
-
return false unless uri.host.match(realm_match)
|
347
|
-
return true
|
348
|
-
end
|
349
|
-
|
350
|
-
alias_method :include?, :within_realm?
|
351
|
-
|
352
|
-
protected
|
353
|
-
|
354
|
-
# Returns an html form page for posting to an Identity Provider if the
|
355
|
-
# GET request would exceed the upper URI length limit.
|
356
|
-
|
357
|
-
def confirm_post_params(oid, realm, return_to, immediate)
|
358
|
-
response = Rack::Response.new '<html>'+
|
359
|
-
'<head><title>Confirm...</title></head>'+
|
360
|
-
'<body>'+oid.form_markup(realm, return_to, immediate)+'</body>'+
|
361
|
-
'</html>'
|
362
|
-
response.finish
|
363
|
-
end
|
364
|
-
|
365
|
-
# Returns a 303 redirect with the destination of that provided by the
|
366
|
-
# argument.
|
367
|
-
|
368
|
-
def redirect(uri)
|
369
|
-
[ 303, {'Content-Type'=>'text/plain', 'Content-Length'=>'0',
|
370
|
-
'Location' => uri},
|
371
|
-
[] ]
|
372
|
-
end
|
373
|
-
|
374
|
-
# Returns an empty 400 response.
|
375
|
-
|
376
|
-
def bad_request
|
377
|
-
[ 400, {'Content-Type'=>'text/plain', 'Content-Length'=>'0'},
|
378
|
-
[''] ]
|
379
|
-
end
|
380
|
-
|
381
|
-
# Returns a basic unauthorized 401 response.
|
382
|
-
|
383
|
-
def unauthorized
|
384
|
-
[ 401, {'Content-Type' => 'text/plain', 'Content-Length' => '13'},
|
385
|
-
['Unauthorized.'] ]
|
386
|
-
end
|
387
|
-
|
388
|
-
# Returns a basic access denied 403 response.
|
389
|
-
|
390
|
-
def access_denied
|
391
|
-
[ 403, {'Content-Type' => 'text/plain', 'Content-Length' => '14'},
|
392
|
-
['Access denied.'] ]
|
393
|
-
end
|
394
|
-
|
395
|
-
# Returns a 503 response to be used if communication with the remote
|
396
|
-
# OpenID server fails.
|
397
|
-
|
398
|
-
def foreign_server_failure
|
399
|
-
[ 503, {'Content-Type'=>'text/plain', 'Content-Length' => '23'},
|
400
|
-
['Foreign server failure.'] ]
|
401
|
-
end
|
402
|
-
|
403
|
-
private
|
404
|
-
|
405
|
-
# Called to complete processing on a successful transaction.
|
406
|
-
# Within the openid session, :openid_identity and :openid_identifier are
|
407
|
-
# set to the user friendly and the standard representation of the
|
408
|
-
# validated identity. All other data in the openid session is cleared.
|
409
|
-
|
410
|
-
def success(oid, request, session)
|
411
|
-
session.clear
|
412
|
-
session[:openid_identity] = oid.display_identifier
|
413
|
-
session[:openid_identifier] = oid.identity_url
|
414
|
-
extensions.keys.each do |ext|
|
415
|
-
label = ext.name[/[^:]+$/].downcase
|
416
|
-
response = ext::Response.from_success_response(oid)
|
417
|
-
session[label] = response.data
|
418
|
-
end
|
419
|
-
redirect(realm)
|
420
|
-
end
|
421
|
-
|
422
|
-
# Called if the Identity Provider indicates further setup by the user is
|
423
|
-
# required.
|
424
|
-
# The identifier is retrived from the openid session at :openid_param.
|
425
|
-
# And :setup_needed is set to true to prevent looping.
|
426
|
-
|
427
|
-
def setup_needed(oid, request, session)
|
428
|
-
identifier = session[:openid_param]
|
429
|
-
session[:setup_needed] = true
|
430
|
-
redirect(req.script_name + '?' + openid_param + '=' + identifier)
|
431
|
-
end
|
432
|
-
|
433
|
-
# Called if the user indicates they wish to cancel identification.
|
434
|
-
# Data within openid session is cleared.
|
435
|
-
|
436
|
-
def cancel(oid, request, session)
|
437
|
-
session.clear
|
438
|
-
access_denied
|
439
|
-
end
|
440
|
-
|
441
|
-
# Called if the Identity Provider indicates the user is unable to confirm
|
442
|
-
# their identity. Data within the openid session is left alone, in case
|
443
|
-
# of swarm auth attacks.
|
444
|
-
|
445
|
-
def failure(oid, request, session)
|
446
|
-
unauthorized
|
447
|
-
end
|
448
|
-
|
449
|
-
# To be called if there is no method for handling the OpenID response
|
450
|
-
# status.
|
451
|
-
|
452
|
-
def invalid_status(oid, request, session)
|
453
|
-
msg = 'Invalid status returned by the OpenID authorization reponse.'
|
454
|
-
[ 500,
|
455
|
-
{'Content-Type'=>'text/plain','Content-Length'=>msg.length.to_s},
|
456
|
-
[msg] ]
|
457
|
-
end
|
458
|
-
end
|
459
|
-
|
460
|
-
# A class developed out of the request to use OpenID as an authentication
|
461
|
-
# middleware. The request will be sent to the OpenID instance unless the
|
462
|
-
# block evaluates to true. For example in rackup, you can use it as such:
|
463
|
-
#
|
464
|
-
# use Rack::Session::Pool
|
465
|
-
# use Rack::Auth::OpenIDAuth, realm, openid_options do |env|
|
466
|
-
# env['rack.session'][:authkey] == a_string
|
467
|
-
# end
|
468
|
-
# run RackApp
|
469
|
-
#
|
470
|
-
# Or simply:
|
471
|
-
#
|
472
|
-
# app = Rack::Auth::OpenIDAuth.new app, realm, openid_options, &auth
|
473
|
-
|
474
|
-
class OpenIDAuth < Rack::Auth::AbstractHandler
|
475
|
-
attr_reader :oid
|
476
|
-
def initialize(app, realm, options={}, &auth)
|
477
|
-
@oid = OpenID.new(realm, options)
|
478
|
-
super(app, &auth)
|
479
|
-
end
|
480
|
-
|
481
|
-
def call(env)
|
482
|
-
to = @authenticator.call(env) ? @app : @oid
|
483
|
-
to.call(env)
|
484
|
-
end
|
485
|
-
end
|
486
|
-
end
|
487
|
-
end
|