kch-rubycas-server 0.8.0.20090715
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.
- data/CHANGELOG.txt +1 -0
- data/History.txt +270 -0
- data/LICENSE.txt +504 -0
- data/Manifest.txt +85 -0
- data/PostInstall.txt +3 -0
- data/README.rdoc +26 -0
- data/Rakefile +4 -0
- data/bin/rubycas-server +13 -0
- data/bin/rubycas-server-ctl +9 -0
- data/config.example.yml +544 -0
- data/config.ru +38 -0
- data/config/hoe.rb +78 -0
- data/config/requirements.rb +15 -0
- data/custom_views.example.rb +11 -0
- data/lib/casserver.rb +58 -0
- data/lib/casserver/authenticators/active_directory_ldap.rb +11 -0
- data/lib/casserver/authenticators/base.rb +48 -0
- data/lib/casserver/authenticators/client_certificate.rb +46 -0
- data/lib/casserver/authenticators/google.rb +54 -0
- data/lib/casserver/authenticators/ldap.rb +147 -0
- data/lib/casserver/authenticators/ntlm.rb +88 -0
- data/lib/casserver/authenticators/open_id.rb +22 -0
- data/lib/casserver/authenticators/sql.rb +102 -0
- data/lib/casserver/authenticators/sql_encrypted.rb +77 -0
- data/lib/casserver/authenticators/sql_md5.rb +19 -0
- data/lib/casserver/authenticators/sql_rest_auth.rb +77 -0
- data/lib/casserver/authenticators/test.rb +19 -0
- data/lib/casserver/cas.rb +322 -0
- data/lib/casserver/conf.rb +75 -0
- data/lib/casserver/controllers.rb +456 -0
- data/lib/casserver/load_picnic.rb +19 -0
- data/lib/casserver/localization.rb +82 -0
- data/lib/casserver/models.rb +265 -0
- data/lib/casserver/postambles.rb +174 -0
- data/lib/casserver/utils.rb +30 -0
- data/lib/casserver/version.rb +9 -0
- data/lib/casserver/views.rb +245 -0
- data/lib/rubycas-server.rb +1 -0
- data/lib/rubycas-server/version.rb +1 -0
- data/po/de_DE/rubycas-server.po +119 -0
- data/po/es_ES/rubycas-server.po +115 -0
- data/po/fr_FR/rubycas-server.po +116 -0
- data/po/ja_JP/rubycas-server.po +118 -0
- data/po/pl_PL/rubycas-server.po +115 -0
- data/po/pt_BR/rubycas-server.po +115 -0
- data/po/ru_RU/rubycas-server.po +110 -0
- data/po/rubycas-server.pot +104 -0
- data/public/themes/cas.css +121 -0
- data/public/themes/notice.png +0 -0
- data/public/themes/ok.png +0 -0
- data/public/themes/simple/bg.png +0 -0
- data/public/themes/simple/login_box_bg.png +0 -0
- data/public/themes/simple/logo.png +0 -0
- data/public/themes/simple/theme.css +28 -0
- data/public/themes/urbacon/bg.png +0 -0
- data/public/themes/urbacon/login_box_bg.png +0 -0
- data/public/themes/urbacon/logo.png +0 -0
- data/public/themes/urbacon/theme.css +33 -0
- data/public/themes/warning.png +0 -0
- data/resources/init.d.sh +58 -0
- data/script/console +10 -0
- data/script/destroy +14 -0
- data/script/generate +14 -0
- data/script/txt2html +82 -0
- data/setup.rb +1585 -0
- data/tasks/deployment.rake +34 -0
- data/tasks/environment.rake +7 -0
- data/tasks/localization.rake +11 -0
- data/tasks/website.rake +17 -0
- data/vendor/isaac_0.9.1/LICENSE +26 -0
- data/vendor/isaac_0.9.1/README +78 -0
- data/vendor/isaac_0.9.1/TODO +3 -0
- data/vendor/isaac_0.9.1/VERSIONS +3 -0
- data/vendor/isaac_0.9.1/crypt/ISAAC.rb +171 -0
- data/vendor/isaac_0.9.1/isaac.gemspec +39 -0
- data/vendor/isaac_0.9.1/setup.rb +596 -0
- data/vendor/isaac_0.9.1/test/TC_ISAAC.rb +76 -0
- metadata +193 -0
@@ -0,0 +1,75 @@
|
|
1
|
+
|
2
|
+
conf_defaults = {
|
3
|
+
:maximum_unused_login_ticket_lifetime => 5.minutes,
|
4
|
+
:maximum_unused_service_ticket_lifetime => 5.minutes, # CAS Protocol Spec, sec. 3.2.1 (recommended expiry time)
|
5
|
+
:maximum_session_lifetime => 1.month, # all tickets are deleted after this period of time
|
6
|
+
:log => {:file => 'casserver.log', :level => 'DEBUG'},
|
7
|
+
:uri_path => "/"
|
8
|
+
}
|
9
|
+
|
10
|
+
if $CONF
|
11
|
+
$CONF.merge_defaults(conf_defaults)
|
12
|
+
else
|
13
|
+
unless $APP_NAME && $APP_ROOT
|
14
|
+
raise "Can't load the RubyCAS-Server configuration because $APP_NAME and/or $APP_ROOT are not defined."
|
15
|
+
end
|
16
|
+
|
17
|
+
require 'picnic/conf'
|
18
|
+
$CONF = Picnic::Conf.new(conf_defaults)
|
19
|
+
$CONF.load_from_file($APP_NAME, $APP_ROOT)
|
20
|
+
end
|
21
|
+
|
22
|
+
$AUTH = []
|
23
|
+
|
24
|
+
unless $CONF[:authenticator]
|
25
|
+
err = "
|
26
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
27
|
+
|
28
|
+
You have not yet defined an authenticator for your CAS server!
|
29
|
+
Please consult the documentation and make the necessary changes to
|
30
|
+
your config file.
|
31
|
+
|
32
|
+
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
|
33
|
+
"
|
34
|
+
raise Picnic::Config::Error, err
|
35
|
+
end
|
36
|
+
|
37
|
+
begin
|
38
|
+
# attempt to instantiate the authenticator
|
39
|
+
if $CONF[:authenticator].instance_of? Array
|
40
|
+
$CONF[:authenticator].each { |authenticator| $AUTH << authenticator[:class].constantize.new}
|
41
|
+
else
|
42
|
+
$AUTH << $CONF[:authenticator][:class].constantize.new
|
43
|
+
end
|
44
|
+
rescue NameError
|
45
|
+
if $CONF[:authenticator].instance_of? Array
|
46
|
+
$CONF[:authenticator].each do |authenticator|
|
47
|
+
if !authenticator[:source].nil?
|
48
|
+
# config.yml explicitly names source file
|
49
|
+
require authenticator[:source]
|
50
|
+
else
|
51
|
+
# the authenticator class hasn't yet been loaded, so lets try to load it from the casserver/authenticators directory
|
52
|
+
auth_rb = authenticator[:class].underscore.gsub('cas_server/', '')
|
53
|
+
require 'casserver/'+auth_rb
|
54
|
+
end
|
55
|
+
$AUTH << authenticator[:class].constantize.new
|
56
|
+
end
|
57
|
+
else
|
58
|
+
if $CONF[:authenticator][:source]
|
59
|
+
# config.yml explicitly names source file
|
60
|
+
require $CONF[:authenticator][:source]
|
61
|
+
else
|
62
|
+
# the authenticator class hasn't yet been loaded, so lets try to load it from the casserver/authenticators directory
|
63
|
+
auth_rb = $CONF[:authenticator][:class].underscore.gsub('cas_server/', '')
|
64
|
+
require 'casserver/'+auth_rb
|
65
|
+
end
|
66
|
+
|
67
|
+
$AUTH << $CONF[:authenticator][:class].constantize.new
|
68
|
+
end
|
69
|
+
end
|
70
|
+
|
71
|
+
$CONF[:static] = {
|
72
|
+
:urls => "/themes",
|
73
|
+
:root => "#{$APP_ROOT}/public"
|
74
|
+
}
|
75
|
+
|
@@ -0,0 +1,456 @@
|
|
1
|
+
# The #.#.# comments (e.g. "2.1.3") refer to section numbers in the CAS protocol spec
|
2
|
+
# under http://www.ja-sig.org/products/cas/overview/protocol/index.html
|
3
|
+
|
4
|
+
require 'casserver/cas'
|
5
|
+
|
6
|
+
module CASServer::Controllers
|
7
|
+
|
8
|
+
# 2.1
|
9
|
+
class Login < R '/', '/login'
|
10
|
+
include CASServer::CAS
|
11
|
+
|
12
|
+
# 2.1.1
|
13
|
+
def get
|
14
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
15
|
+
|
16
|
+
# make sure there's no caching
|
17
|
+
headers['Pragma'] = 'no-cache'
|
18
|
+
headers['Cache-Control'] = 'no-store'
|
19
|
+
headers['Expires'] = (Time.now - 1.year).rfc2822
|
20
|
+
|
21
|
+
# optional params
|
22
|
+
@service = clean_service_url(input['service'])
|
23
|
+
@renew = input['renew']
|
24
|
+
@gateway = input['gateway'] == 'true' || input['gateway'] == '1'
|
25
|
+
|
26
|
+
if tgc = cookies['tgt']
|
27
|
+
tgt, tgt_error = validate_ticket_granting_ticket(tgc)
|
28
|
+
end
|
29
|
+
|
30
|
+
if tgt and !tgt_error
|
31
|
+
@message = {:type => 'notice',
|
32
|
+
:message => _("You are currently logged in as '%s'. If this is not you, please log in below.") % tgt.username }
|
33
|
+
end
|
34
|
+
|
35
|
+
if input['redirection_loop_intercepted']
|
36
|
+
@message = {:type => 'mistake',
|
37
|
+
:message => _("The client and server are unable to negotiate authentication. Please try logging in again later.")}
|
38
|
+
end
|
39
|
+
|
40
|
+
begin
|
41
|
+
if @service
|
42
|
+
if !@renew && tgt && !tgt_error
|
43
|
+
st = generate_service_ticket(@service, tgt.username, tgt)
|
44
|
+
service_with_ticket = service_uri_with_ticket(@service, st)
|
45
|
+
$LOG.info("User '#{tgt.username}' authenticated based on ticket granting cookie. Redirecting to service '#{@service}'.")
|
46
|
+
return redirect(service_with_ticket, :status => 303) # response code 303 means "See Other" (see Appendix B in CAS Protocol spec)
|
47
|
+
elsif @gateway
|
48
|
+
$LOG.info("Redirecting unauthenticated gateway request to service '#{@service}'.")
|
49
|
+
return redirect(@service, :status => 303)
|
50
|
+
end
|
51
|
+
elsif @gateway
|
52
|
+
$LOG.error("This is a gateway request but no service parameter was given!")
|
53
|
+
@message = {:type => 'mistake',
|
54
|
+
:message => _("The server cannot fulfill this gateway request because no service parameter was given.")}
|
55
|
+
end
|
56
|
+
rescue URI::InvalidURIError
|
57
|
+
$LOG.error("The service '#{@service}' is not a valid URI!")
|
58
|
+
@message = {:type => 'mistake',
|
59
|
+
:message => _("The target service your browser supplied appears to be invalid. Please contact your system administrator for help.")}
|
60
|
+
end
|
61
|
+
|
62
|
+
lt = generate_login_ticket
|
63
|
+
|
64
|
+
$LOG.debug("Rendering login form with lt: #{lt}, service: #{@service}, renew: #{@renew}, gateway: #{@gateway}")
|
65
|
+
|
66
|
+
@lt = lt.ticket
|
67
|
+
|
68
|
+
#$LOG.debug(env)
|
69
|
+
|
70
|
+
# If the 'onlyLoginForm' parameter is specified, we will only return the
|
71
|
+
# login form part of the page. This is useful for when you want to
|
72
|
+
# embed the login form in some external page (as an IFRAME, or otherwise).
|
73
|
+
# The optional 'submitToURI' parameter can be given to explicitly set the
|
74
|
+
# action for the form, otherwise the server will try to guess this for you.
|
75
|
+
if input.has_key? 'onlyLoginForm'
|
76
|
+
if @env['HTTP_HOST']
|
77
|
+
guessed_login_uri = "http#{@env['HTTPS'] && @env['HTTPS'] == 'on' ? 's' : ''}://#{@env['REQUEST_URI']}#{self / '/login'}"
|
78
|
+
else
|
79
|
+
guessed_login_uri = nil
|
80
|
+
end
|
81
|
+
|
82
|
+
@form_action = input['submitToURI'] || guessed_login_uri
|
83
|
+
|
84
|
+
if @form_action
|
85
|
+
render :login_form
|
86
|
+
else
|
87
|
+
@status = 500
|
88
|
+
_("Could not guess the CAS login URI. Please supply a submitToURI parameter with your request.")
|
89
|
+
end
|
90
|
+
else
|
91
|
+
render :login
|
92
|
+
end
|
93
|
+
end
|
94
|
+
|
95
|
+
# 2.2
|
96
|
+
def post
|
97
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
98
|
+
|
99
|
+
# 2.2.1 (optional)
|
100
|
+
@service = clean_service_url(input['service'])
|
101
|
+
|
102
|
+
# 2.2.2 (required)
|
103
|
+
@username = input['username']
|
104
|
+
@password = input['password']
|
105
|
+
@lt = input['lt']
|
106
|
+
|
107
|
+
# Remove leading and trailing widespace from username.
|
108
|
+
@username.strip! if @username
|
109
|
+
|
110
|
+
if @username && $CONF[:downcase_username]
|
111
|
+
$LOG.debug("Converting username #{@username.inspect} to lowercase because 'downcase_username' option is enabled.")
|
112
|
+
@username.downcase!
|
113
|
+
end
|
114
|
+
|
115
|
+
if error = validate_login_ticket(@lt)
|
116
|
+
@message = {:type => 'mistake', :message => error}
|
117
|
+
# generate another login ticket to allow for re-submitting the form
|
118
|
+
@lt = generate_login_ticket.ticket
|
119
|
+
@status = 401
|
120
|
+
return render(:login)
|
121
|
+
end
|
122
|
+
|
123
|
+
# generate another login ticket to allow for re-submitting the form after a post
|
124
|
+
@lt = generate_login_ticket.ticket
|
125
|
+
|
126
|
+
if $CONF[:authenticator].instance_of? Array
|
127
|
+
$AUTH.each_index {|auth_index| $AUTH[auth_index].configure($CONF.authenticator[auth_index])}
|
128
|
+
else
|
129
|
+
$AUTH[0].configure($CONF.authenticator)
|
130
|
+
end
|
131
|
+
|
132
|
+
$LOG.debug("Logging in with username: #{@username}, lt: #{@lt}, service: #{@service}, auth: #{$AUTH}")
|
133
|
+
|
134
|
+
credentials_are_valid = false
|
135
|
+
extra_attributes = {}
|
136
|
+
successful_authenticator = nil
|
137
|
+
begin
|
138
|
+
$AUTH.each do |auth|
|
139
|
+
credentials_are_valid = auth.validate(
|
140
|
+
:username => @username,
|
141
|
+
:password => @password,
|
142
|
+
:service => @service,
|
143
|
+
:request => @env
|
144
|
+
)
|
145
|
+
if credentials_are_valid
|
146
|
+
extra_attributes.merge!(auth.extra_attributes) unless auth.extra_attributes.blank?
|
147
|
+
successful_authenticator = auth
|
148
|
+
break
|
149
|
+
end
|
150
|
+
end
|
151
|
+
rescue CASServer::AuthenticatorError => e
|
152
|
+
$LOG.error(e)
|
153
|
+
@message = {:type => 'mistake', :message => e.to_s}
|
154
|
+
return render(:login)
|
155
|
+
end
|
156
|
+
|
157
|
+
if credentials_are_valid
|
158
|
+
$LOG.info("Credentials for username '#{@username}' successfully validated using #{successful_authenticator.class.name}.")
|
159
|
+
$LOG.debug("Authenticator provided additional user attributes: #{extra_attributes.inspect}") unless extra_attributes.blank?
|
160
|
+
|
161
|
+
# 3.6 (ticket-granting cookie)
|
162
|
+
tgt = generate_ticket_granting_ticket(@username, extra_attributes)
|
163
|
+
|
164
|
+
if $CONF.maximum_session_lifetime
|
165
|
+
expires = $CONF.maximum_session_lifetime.to_i.from_now
|
166
|
+
expiry_info = " It will expire on #{expires}."
|
167
|
+
else
|
168
|
+
expiry_info = " It will not expire."
|
169
|
+
end
|
170
|
+
|
171
|
+
if $CONF.maximum_session_lifetime
|
172
|
+
cookies['tgt'] = {
|
173
|
+
:value => tgt.to_s,
|
174
|
+
:expires => Time.now + $CONF.maximum_session_lifetime
|
175
|
+
}
|
176
|
+
else
|
177
|
+
cookies['tgt'] = tgt.to_s
|
178
|
+
end
|
179
|
+
|
180
|
+
$LOG.debug("Ticket granting cookie '#{cookies['tgt'].inspect}' granted to #{@username.inspect}. #{expiry_info}")
|
181
|
+
|
182
|
+
if @service.blank?
|
183
|
+
$LOG.info("Successfully authenticated user '#{@username}' at '#{tgt.client_hostname}'. No service param was given, so we will not redirect.")
|
184
|
+
@message = {:type => 'confirmation', :message => _("You have successfully logged in.")}
|
185
|
+
else
|
186
|
+
@st = generate_service_ticket(@service, @username, tgt)
|
187
|
+
begin
|
188
|
+
service_with_ticket = service_uri_with_ticket(@service, @st)
|
189
|
+
|
190
|
+
$LOG.info("Redirecting authenticated user '#{@username}' at '#{@st.client_hostname}' to service '#{@service}'")
|
191
|
+
return redirect(service_with_ticket, :status => 303) # response code 303 means "See Other" (see Appendix B in CAS Protocol spec)
|
192
|
+
rescue URI::InvalidURIError
|
193
|
+
$LOG.error("The service '#{@service}' is not a valid URI!")
|
194
|
+
@message = {:type => 'mistake',
|
195
|
+
:message => _("The target service your browser supplied appears to be invalid. Please contact your system administrator for help.")}
|
196
|
+
end
|
197
|
+
end
|
198
|
+
else
|
199
|
+
$LOG.warn("Invalid credentials given for user '#{@username}'")
|
200
|
+
@message = {:type => 'mistake', :message => _("Incorrect username or password.")}
|
201
|
+
@status = 401
|
202
|
+
end
|
203
|
+
|
204
|
+
render :login
|
205
|
+
end
|
206
|
+
end
|
207
|
+
|
208
|
+
# 2.3
|
209
|
+
class Logout < R '/logout'
|
210
|
+
include CASServer::CAS
|
211
|
+
|
212
|
+
# 2.3.1
|
213
|
+
def get
|
214
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
215
|
+
|
216
|
+
# The behaviour here is somewhat non-standard. Rather than showing just a blank
|
217
|
+
# "logout" page, we take the user back to the login page with a "you have been logged out"
|
218
|
+
# message, allowing for an opportunity to immediately log back in. This makes it
|
219
|
+
# easier for the user to log out and log in as someone else.
|
220
|
+
@service = clean_service_url(input['service'] || input['destination'])
|
221
|
+
@continue_url = input['url']
|
222
|
+
|
223
|
+
@gateway = input['gateway'] == 'true' || input['gateway'] == '1'
|
224
|
+
|
225
|
+
tgt = CASServer::Models::TicketGrantingTicket.find_by_ticket(cookies['tgt'])
|
226
|
+
|
227
|
+
cookies.delete 'tgt'
|
228
|
+
|
229
|
+
if tgt
|
230
|
+
CASServer::Models::TicketGrantingTicket.transaction do
|
231
|
+
$LOG.debug("Deleting Service/Proxy Tickets for '#{tgt}' for user '#{tgt.username}'")
|
232
|
+
tgt.granted_service_tickets.each do |st|
|
233
|
+
send_logout_notification_for_service_ticket(st) if $CONF.enable_single_sign_out
|
234
|
+
# TODO: Maybe we should do some special handling if send_logout_notification_for_service_ticket fails?
|
235
|
+
# (the above method returns false if the POST results in a non-200 HTTP response).
|
236
|
+
$LOG.debug "Deleting #{st.class.name.demodulize} #{st.ticket.inspect} for service #{st.service}."
|
237
|
+
st.destroy
|
238
|
+
end
|
239
|
+
|
240
|
+
pgts = CASServer::Models::ProxyGrantingTicket.find(:all,
|
241
|
+
:conditions => [CASServer::Models::Base.connection.quote_table_name(CASServer::Models::ServiceTicket.table_name)+".username = ?", tgt.username],
|
242
|
+
:include => :service_ticket)
|
243
|
+
pgts.each do |pgt|
|
244
|
+
$LOG.debug("Deleting Proxy-Granting Ticket '#{pgt}' for user '#{pgt.service_ticket.username}'")
|
245
|
+
pgt.destroy
|
246
|
+
end
|
247
|
+
|
248
|
+
$LOG.debug("Deleting #{tgt.class.name.demodulize} '#{tgt}' for user '#{tgt.username}'")
|
249
|
+
tgt.destroy
|
250
|
+
end
|
251
|
+
|
252
|
+
$LOG.info("User '#{tgt.username}' logged out.")
|
253
|
+
else
|
254
|
+
$LOG.warn("User tried to log out without a valid ticket-granting ticket.")
|
255
|
+
end
|
256
|
+
|
257
|
+
@message = {:type => 'confirmation', :message => _("You have successfully logged out.")}
|
258
|
+
|
259
|
+
@message[:message] +=_(" Please click on the following link to continue:") if @continue_url
|
260
|
+
|
261
|
+
@lt = generate_login_ticket
|
262
|
+
|
263
|
+
if @gateway && @service
|
264
|
+
redirect(@service, :status => 303)
|
265
|
+
elsif @continue_url
|
266
|
+
render :logout
|
267
|
+
else
|
268
|
+
render :login
|
269
|
+
end
|
270
|
+
end
|
271
|
+
end
|
272
|
+
|
273
|
+
# 2.4
|
274
|
+
class Validate < R '/validate'
|
275
|
+
include CASServer::CAS
|
276
|
+
|
277
|
+
# 2.4.1
|
278
|
+
def get
|
279
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
280
|
+
|
281
|
+
# required
|
282
|
+
@service = clean_service_url(input['service'])
|
283
|
+
@ticket = input['ticket']
|
284
|
+
# optional
|
285
|
+
@renew = input['renew']
|
286
|
+
|
287
|
+
st, @error = validate_service_ticket(@service, @ticket)
|
288
|
+
@success = st && !@error
|
289
|
+
|
290
|
+
@username = st.username if @success
|
291
|
+
|
292
|
+
@status = CASServer::Controllers.response_status_from_error(@error) if @error
|
293
|
+
|
294
|
+
render :validate
|
295
|
+
end
|
296
|
+
end
|
297
|
+
|
298
|
+
# 2.5
|
299
|
+
class ServiceValidate < R '/serviceValidate'
|
300
|
+
include CASServer::CAS
|
301
|
+
|
302
|
+
# 2.5.1
|
303
|
+
def get
|
304
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
305
|
+
|
306
|
+
# required
|
307
|
+
@service = clean_service_url(input['service'])
|
308
|
+
@ticket = input['ticket']
|
309
|
+
# optional
|
310
|
+
@pgt_url = input['pgtUrl']
|
311
|
+
@renew = input['renew']
|
312
|
+
|
313
|
+
st, @error = validate_service_ticket(@service, @ticket)
|
314
|
+
@success = st && !@error
|
315
|
+
|
316
|
+
if @success
|
317
|
+
@username = st.username
|
318
|
+
if @pgt_url
|
319
|
+
pgt = generate_proxy_granting_ticket(@pgt_url, st)
|
320
|
+
@pgtiou = pgt.iou if pgt
|
321
|
+
end
|
322
|
+
@extra_attributes = st.granted_by_tgt.extra_attributes || {}
|
323
|
+
end
|
324
|
+
|
325
|
+
@status = CASServer::Controllers.response_status_from_error(@error) if @error
|
326
|
+
|
327
|
+
render :service_validate
|
328
|
+
end
|
329
|
+
end
|
330
|
+
|
331
|
+
# 2.6
|
332
|
+
class ProxyValidate < R '/proxyValidate'
|
333
|
+
include CASServer::CAS
|
334
|
+
|
335
|
+
# 2.6.1
|
336
|
+
def get
|
337
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
338
|
+
|
339
|
+
# required
|
340
|
+
@service = clean_service_url(input['service'])
|
341
|
+
@ticket = input['ticket']
|
342
|
+
# optional
|
343
|
+
@pgt_url = input['pgtUrl']
|
344
|
+
@renew = input['renew']
|
345
|
+
|
346
|
+
@proxies = []
|
347
|
+
|
348
|
+
t, @error = validate_proxy_ticket(@service, @ticket)
|
349
|
+
@success = t && !@error
|
350
|
+
|
351
|
+
@extra_attributes = {}
|
352
|
+
if @success
|
353
|
+
@username = t.username
|
354
|
+
|
355
|
+
if t.kind_of? CASServer::Models::ProxyTicket
|
356
|
+
@proxies << t.granted_by_pgt.service_ticket.service
|
357
|
+
end
|
358
|
+
|
359
|
+
if @pgt_url
|
360
|
+
pgt = generate_proxy_granting_ticket(@pgt_url, t)
|
361
|
+
@pgtiou = pgt.iou if pgt
|
362
|
+
end
|
363
|
+
|
364
|
+
@extra_attributes = t.granted_by_tgt.extra_attributes || {}
|
365
|
+
end
|
366
|
+
|
367
|
+
@status = CASServer::Controllers.response_status_from_error(@error) if @error
|
368
|
+
|
369
|
+
render :proxy_validate
|
370
|
+
end
|
371
|
+
end
|
372
|
+
|
373
|
+
class Proxy < R '/proxy'
|
374
|
+
include CASServer::CAS
|
375
|
+
|
376
|
+
# 2.7
|
377
|
+
def get
|
378
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
379
|
+
|
380
|
+
# required
|
381
|
+
@ticket = input['pgt']
|
382
|
+
@target_service = input['targetService']
|
383
|
+
|
384
|
+
pgt, @error = validate_proxy_granting_ticket(@ticket)
|
385
|
+
@success = pgt && !@error
|
386
|
+
|
387
|
+
if @success
|
388
|
+
@pt = generate_proxy_ticket(@target_service, pgt)
|
389
|
+
end
|
390
|
+
|
391
|
+
@status = CASServer::Controllers.response_status_from_error(@error) if @error
|
392
|
+
|
393
|
+
render :proxy
|
394
|
+
end
|
395
|
+
end
|
396
|
+
|
397
|
+
# Controller for obtaining login tickets.
|
398
|
+
# This is useful when you want to build a custom login form located on a
|
399
|
+
# remote server. Your form will have to include a valid login ticket
|
400
|
+
# value, and this can be fetched from the CAS server using this controller'
|
401
|
+
# POST method.
|
402
|
+
class LoginTicketDispenser < R '/loginTicket'
|
403
|
+
include CASServer::CAS
|
404
|
+
|
405
|
+
def get
|
406
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
407
|
+
$LOG.error("Tried to use login ticket dispenser with get method!")
|
408
|
+
@status = 422
|
409
|
+
_("To generate a login ticket, you must make a POST request.")
|
410
|
+
end
|
411
|
+
|
412
|
+
# Renders a page with a login ticket (and only the login ticket)
|
413
|
+
# in the response body.
|
414
|
+
def post
|
415
|
+
CASServer::Utils::log_controller_action(self.class, input)
|
416
|
+
lt = generate_login_ticket
|
417
|
+
|
418
|
+
$LOG.debug("Dispensing login ticket #{lt} to host #{(@env['HTTP_X_FORWARDED_FOR'] || @env['REMOTE_HOST'] || @env['REMOTE_ADDR']).inspect}")
|
419
|
+
|
420
|
+
@lt = lt.ticket
|
421
|
+
|
422
|
+
@lt
|
423
|
+
end
|
424
|
+
end
|
425
|
+
|
426
|
+
# class Themes < R '/themes/(.+)'
|
427
|
+
# MIME_TYPES = {'.css' => 'text/css', '.js' => 'text/javascript',
|
428
|
+
# '.jpg' => 'image/jpeg'}
|
429
|
+
# PATH = $CONF.themes_dir || File.expand_path(File.dirname(__FILE__))+'/../themes'
|
430
|
+
#
|
431
|
+
# def get(path)
|
432
|
+
# headers['Content-Type'] = MIME_TYPES[path[/\.\w+$/, 0]] || "text/plain"
|
433
|
+
# unless path.include? ".." # prevent directory traversal attacks
|
434
|
+
# headers['X-Sendfile'] = "#{PATH}/#{path}"
|
435
|
+
# data = File.read(headers['X-Sendfile'])
|
436
|
+
# headers['Content-Length'] = data.size.to_s # Rack Camping adapter chokes without this
|
437
|
+
# return data
|
438
|
+
# else
|
439
|
+
# status = "403"
|
440
|
+
# "403 - Invalid path"
|
441
|
+
# end
|
442
|
+
# end
|
443
|
+
# end
|
444
|
+
|
445
|
+
def response_status_from_error(error)
|
446
|
+
case error.code.to_s
|
447
|
+
when /^INVALID_/, 'BAD_PGT'
|
448
|
+
422
|
449
|
+
when 'INTERNAL_ERROR'
|
450
|
+
500
|
451
|
+
else
|
452
|
+
500
|
453
|
+
end
|
454
|
+
end
|
455
|
+
module_function :response_status_from_error
|
456
|
+
end
|