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.

Files changed (160) hide show
  1. data/NEWS +40 -0
  2. data/Rakefile +1 -1
  3. data/bin/passenger-install-apache2-module +1 -0
  4. data/bin/passenger-install-nginx-module +2 -0
  5. data/doc/Architectural overview.html +173 -138
  6. data/doc/Security of user switching support.html +147 -109
  7. data/doc/Users guide Apache.html +4 -43
  8. data/doc/Users guide Nginx.html +4 -43
  9. data/doc/cxxapi/Bucket_8h-source.html +1 -1
  10. data/doc/cxxapi/Configuration_8h-source.html +1 -1
  11. data/doc/cxxapi/DirectoryMapper_8h-source.html +1 -1
  12. data/doc/cxxapi/Hooks_8h-source.html +1 -1
  13. data/doc/cxxapi/annotated.html +1 -1
  14. data/doc/cxxapi/classHooks-members.html +1 -1
  15. data/doc/cxxapi/classHooks.html +1 -1
  16. data/doc/cxxapi/classPassenger_1_1DirectoryMapper-members.html +1 -1
  17. data/doc/cxxapi/classPassenger_1_1DirectoryMapper.html +1 -1
  18. data/doc/cxxapi/classes.html +1 -1
  19. data/doc/cxxapi/definitions_8h-source.html +1 -1
  20. data/doc/cxxapi/files.html +1 -1
  21. data/doc/cxxapi/functions.html +1 -1
  22. data/doc/cxxapi/functions_func.html +1 -1
  23. data/doc/cxxapi/graph_legend.html +1 -1
  24. data/doc/cxxapi/group__Configuration.html +1 -1
  25. data/doc/cxxapi/group__Core.html +1 -1
  26. data/doc/cxxapi/group__Hooks.html +1 -1
  27. data/doc/cxxapi/group__Support.html +1 -1
  28. data/doc/cxxapi/main.html +1 -1
  29. data/doc/cxxapi/modules.html +1 -1
  30. data/doc/rdoc/classes/GC.html +4 -4
  31. data/doc/rdoc/classes/PhusionPassenger.html +2 -1
  32. data/doc/rdoc/classes/PhusionPassenger/AbstractInstaller.html +8 -8
  33. data/doc/rdoc/classes/PhusionPassenger/AbstractRequestHandler.html +26 -26
  34. data/doc/rdoc/classes/PhusionPassenger/AbstractServer.html +98 -98
  35. data/doc/rdoc/classes/PhusionPassenger/AbstractServerCollection.html +61 -61
  36. data/doc/rdoc/classes/PhusionPassenger/AppInitError.html +4 -4
  37. data/doc/rdoc/classes/PhusionPassenger/Application.html +14 -14
  38. data/doc/rdoc/classes/PhusionPassenger/ConsoleTextTemplate.html +12 -12
  39. data/doc/rdoc/classes/PhusionPassenger/FrameworkInitError.html +4 -4
  40. data/doc/rdoc/classes/PhusionPassenger/HTMLTemplate.html +12 -12
  41. data/doc/rdoc/classes/PhusionPassenger/InitializationError.html +5 -5
  42. data/doc/rdoc/classes/PhusionPassenger/MessageChannel.html +42 -42
  43. data/doc/rdoc/classes/PhusionPassenger/Rack/ApplicationSpawner.html +33 -33
  44. data/doc/rdoc/classes/PhusionPassenger/Rack/RequestHandler.html +59 -59
  45. data/doc/rdoc/classes/PhusionPassenger/Railz/ApplicationSpawner.html +3 -3
  46. data/doc/rdoc/classes/PhusionPassenger/Railz/FrameworkSpawner.html +7 -7
  47. data/doc/rdoc/classes/PhusionPassenger/SpawnManager.html +23 -23
  48. data/doc/rdoc/classes/PhusionPassenger/UnknownError.html +4 -4
  49. data/doc/rdoc/classes/PhusionPassenger/Utils.html +2 -0
  50. data/doc/rdoc/classes/PhusionPassenger/Utils/PseudoIO.html +16 -16
  51. data/doc/rdoc/classes/PhusionPassenger/VersionNotFound.html +4 -4
  52. data/doc/rdoc/classes/PlatformInfo.html +1 -1
  53. data/doc/rdoc/classes/Signal.html +23 -15
  54. data/doc/rdoc/created.rid +1 -1
  55. data/doc/rdoc/files/DEVELOPERS_TXT.html +1 -1
  56. data/doc/rdoc/files/README.html +1 -1
  57. data/doc/rdoc/files/ext/phusion_passenger/native_support_c.html +1 -1
  58. data/doc/rdoc/files/lib/phusion_passenger/abstract_installer_rb.html +1 -1
  59. data/doc/rdoc/files/lib/phusion_passenger/abstract_request_handler_rb.html +1 -1
  60. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_collection_rb.html +1 -1
  61. data/doc/rdoc/files/lib/phusion_passenger/abstract_server_rb.html +1 -1
  62. data/doc/rdoc/files/lib/phusion_passenger/admin_tools/control_process_rb.html +1 -1
  63. data/doc/rdoc/files/lib/phusion_passenger/admin_tools_rb.html +1 -1
  64. data/doc/rdoc/files/lib/phusion_passenger/application_rb.html +1 -1
  65. data/doc/rdoc/files/lib/phusion_passenger/console_text_template_rb.html +1 -1
  66. data/doc/rdoc/files/lib/phusion_passenger/constants_rb.html +1 -1
  67. data/doc/rdoc/files/lib/phusion_passenger/dependencies_rb.html +1 -1
  68. data/doc/rdoc/files/lib/phusion_passenger/events_rb.html +1 -1
  69. data/doc/rdoc/files/lib/phusion_passenger/exceptions_rb.html +1 -1
  70. data/doc/rdoc/files/lib/phusion_passenger/html_template_rb.html +1 -1
  71. data/doc/rdoc/files/lib/phusion_passenger/message_channel_rb.html +1 -1
  72. data/doc/rdoc/files/lib/phusion_passenger/packaging_rb.html +1 -1
  73. data/doc/rdoc/files/lib/phusion_passenger/platform_info_rb.html +1 -1
  74. data/doc/rdoc/files/lib/phusion_passenger/rack/application_spawner_rb.html +2 -2
  75. data/doc/rdoc/files/lib/phusion_passenger/rack/request_handler_rb.html +2 -2
  76. data/doc/rdoc/files/lib/phusion_passenger/railz/application_spawner_rb.html +1 -1
  77. data/doc/rdoc/files/lib/phusion_passenger/railz/cgi_fixed_rb.html +1 -1
  78. data/doc/rdoc/files/lib/phusion_passenger/railz/framework_spawner_rb.html +1 -1
  79. data/doc/rdoc/files/lib/phusion_passenger/railz/request_handler_rb.html +1 -1
  80. data/doc/rdoc/files/lib/phusion_passenger/simple_benchmarking_rb.html +1 -1
  81. data/doc/rdoc/files/lib/phusion_passenger/spawn_manager_rb.html +1 -1
  82. data/doc/rdoc/files/lib/phusion_passenger/utils_rb.html +9 -9
  83. data/doc/rdoc/files/lib/phusion_passenger/wsgi/application_spawner_rb.html +1 -1
  84. data/doc/rdoc/files/misc/rake/extensions_rb.html +1 -1
  85. data/doc/rdoc/fr_class_index.html +2 -0
  86. data/doc/rdoc/fr_file_index.html +1 -0
  87. data/doc/rdoc/fr_method_index.html +79 -72
  88. data/ext/apache2/Hooks.cpp +4 -2
  89. data/ext/common/StandardApplicationPool.h +4 -2
  90. data/ext/common/Version.h +1 -1
  91. data/ext/nginx/Configuration.c +1 -1
  92. data/ext/oxt/system_calls.cpp +11 -0
  93. data/ext/oxt/system_calls.hpp +2 -1
  94. data/ext/oxt/thread.hpp +97 -1
  95. data/lib/phusion_passenger/constants.rb +1 -1
  96. data/lib/phusion_passenger/dependencies.rb +32 -0
  97. data/lib/phusion_passenger/platform_info.rb +1 -1
  98. data/lib/phusion_passenger/rack/application_spawner.rb +4 -4
  99. data/lib/phusion_passenger/rack/request_handler.rb +2 -5
  100. data/lib/phusion_passenger/railz/application_spawner.rb +13 -2
  101. data/lib/phusion_passenger/utils.rb +12 -4
  102. data/{vendor/rack-1.0.0-git/lib/rack → lib/phusion_passenger/utils}/rewindable_input.rb +19 -3
  103. data/test/ApplicationPoolTest.cpp +1 -1
  104. metadata +13 -59
  105. data/vendor/README +0 -13
  106. data/vendor/README_FOR_PACKAGERS +0 -1
  107. data/vendor/rack-1.0.0-git/COPYING +0 -18
  108. data/vendor/rack-1.0.0-git/KNOWN-ISSUES +0 -18
  109. data/vendor/rack-1.0.0-git/README +0 -353
  110. data/vendor/rack-1.0.0-git/Rakefile +0 -164
  111. data/vendor/rack-1.0.0-git/lib/rack.rb +0 -90
  112. data/vendor/rack-1.0.0-git/lib/rack/adapter/camping.rb +0 -22
  113. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/handler.rb +0 -37
  114. data/vendor/rack-1.0.0-git/lib/rack/auth/abstract/request.rb +0 -37
  115. data/vendor/rack-1.0.0-git/lib/rack/auth/basic.rb +0 -58
  116. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/md5.rb +0 -124
  117. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/nonce.rb +0 -51
  118. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/params.rb +0 -55
  119. data/vendor/rack-1.0.0-git/lib/rack/auth/digest/request.rb +0 -40
  120. data/vendor/rack-1.0.0-git/lib/rack/auth/openid.rb +0 -487
  121. data/vendor/rack-1.0.0-git/lib/rack/builder.rb +0 -63
  122. data/vendor/rack-1.0.0-git/lib/rack/cascade.rb +0 -41
  123. data/vendor/rack-1.0.0-git/lib/rack/chunked.rb +0 -49
  124. data/vendor/rack-1.0.0-git/lib/rack/commonlogger.rb +0 -52
  125. data/vendor/rack-1.0.0-git/lib/rack/conditionalget.rb +0 -47
  126. data/vendor/rack-1.0.0-git/lib/rack/content_length.rb +0 -29
  127. data/vendor/rack-1.0.0-git/lib/rack/content_type.rb +0 -23
  128. data/vendor/rack-1.0.0-git/lib/rack/deflater.rb +0 -96
  129. data/vendor/rack-1.0.0-git/lib/rack/directory.rb +0 -153
  130. data/vendor/rack-1.0.0-git/lib/rack/file.rb +0 -88
  131. data/vendor/rack-1.0.0-git/lib/rack/handler.rb +0 -69
  132. data/vendor/rack-1.0.0-git/lib/rack/handler/cgi.rb +0 -61
  133. data/vendor/rack-1.0.0-git/lib/rack/handler/evented_mongrel.rb +0 -8
  134. data/vendor/rack-1.0.0-git/lib/rack/handler/fastcgi.rb +0 -88
  135. data/vendor/rack-1.0.0-git/lib/rack/handler/lsws.rb +0 -55
  136. data/vendor/rack-1.0.0-git/lib/rack/handler/mongrel.rb +0 -84
  137. data/vendor/rack-1.0.0-git/lib/rack/handler/scgi.rb +0 -59
  138. data/vendor/rack-1.0.0-git/lib/rack/handler/swiftiplied_mongrel.rb +0 -8
  139. data/vendor/rack-1.0.0-git/lib/rack/handler/thin.rb +0 -18
  140. data/vendor/rack-1.0.0-git/lib/rack/handler/webrick.rb +0 -67
  141. data/vendor/rack-1.0.0-git/lib/rack/head.rb +0 -19
  142. data/vendor/rack-1.0.0-git/lib/rack/lint.rb +0 -537
  143. data/vendor/rack-1.0.0-git/lib/rack/lobster.rb +0 -65
  144. data/vendor/rack-1.0.0-git/lib/rack/lock.rb +0 -16
  145. data/vendor/rack-1.0.0-git/lib/rack/methodoverride.rb +0 -27
  146. data/vendor/rack-1.0.0-git/lib/rack/mime.rb +0 -204
  147. data/vendor/rack-1.0.0-git/lib/rack/mock.rb +0 -184
  148. data/vendor/rack-1.0.0-git/lib/rack/recursive.rb +0 -57
  149. data/vendor/rack-1.0.0-git/lib/rack/reloader.rb +0 -106
  150. data/vendor/rack-1.0.0-git/lib/rack/request.rb +0 -248
  151. data/vendor/rack-1.0.0-git/lib/rack/response.rb +0 -183
  152. data/vendor/rack-1.0.0-git/lib/rack/session/abstract/id.rb +0 -142
  153. data/vendor/rack-1.0.0-git/lib/rack/session/cookie.rb +0 -91
  154. data/vendor/rack-1.0.0-git/lib/rack/session/memcache.rb +0 -109
  155. data/vendor/rack-1.0.0-git/lib/rack/session/pool.rb +0 -100
  156. data/vendor/rack-1.0.0-git/lib/rack/showexceptions.rb +0 -349
  157. data/vendor/rack-1.0.0-git/lib/rack/showstatus.rb +0 -106
  158. data/vendor/rack-1.0.0-git/lib/rack/static.rb +0 -38
  159. data/vendor/rack-1.0.0-git/lib/rack/urlmap.rb +0 -55
  160. 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