Skip to content

Commit 6a78edd

Browse files
committed
add allowed_service_uris config param
1 parent 53c7fb3 commit 6a78edd

File tree

5 files changed

+73
-4
lines changed

5 files changed

+73
-4
lines changed

config/config.example.yml

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -534,10 +534,14 @@ log:
534534
#downcase_username: true
535535

536536
# If you'd like to limit the service hosts that can use CAS for authentication,
537-
# add the individual IPs and IP ranges in CIDR notation below. Leaving this
538-
# setting blank will allow any server to authenticate users via the CAS server
537+
# you can either limit specific service URIs (validating the service parameter),
538+
# or add the individual IPs and IP ranges in CIDR notation below. Leaving these
539+
# settings blank will allow any server to authenticate users via the CAS server
539540
# and potentially harvest sensitive user information.
540541

542+
#allowed_service_uris:
543+
# - https://myservice.com/login/cas
544+
541545
#allowed_service_ips:
542546
# - 127.0.0.1
543547
# - 192.168.0.0/24

lib/casserver/server.rb

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,11 @@ def self.init_database!
322322

323323
begin
324324
if @service
325-
if @renew
325+
if !service_allowed?(@service)
326+
$LOG.warn("Disallowed service '#{@service}'.")
327+
@message = {:type => 'mistake',
328+
:message => t.error.disallowed_service}
329+
elsif @renew
326330
$LOG.info("Authentication renew explicitly requested. Proceeding with CAS login for service #{@service.inspect}.")
327331
elsif tgt && !tgt_error
328332
$LOG.debug("Valid ticket granting ticket detected.")
@@ -409,6 +413,13 @@ def self.init_database!
409413
@username.downcase!
410414
end
411415

416+
if !@service.blank? && !service_allowed?(@service)
417+
@message = {:type => 'mistake',
418+
:message => t.error.disallowed_service}
419+
status 400
420+
return render @template_engine, :login
421+
end
422+
412423
if error = validate_login_ticket(@lt)
413424
@message = {:type => 'mistake', :message => error}
414425
# generate another login ticket to allow for re-submitting the form
@@ -765,6 +776,12 @@ def compile_template(engine, data, options, views)
765776
super engine, data, options, views
766777
end
767778

779+
def service_allowed?(service)
780+
allowed_uris = Array(settings.config[:allowed_service_uris])
781+
782+
allowed_uris.empty? || allowed_uris.include?(service)
783+
end
784+
768785
def ip_allowed?(ip)
769786
require 'ipaddr'
770787

locales/en.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ error:
99
invalid_target_service: "The target service your browser supplied appears to be invalid. Please contact your system administrator for help."
1010
unable_to_authenticate: "The client and server are unable to negotiate authentication. Please try logging in again later."
1111
no_service_parameter_given: "The server cannot fulfill this gateway request because no service parameter was given."
12+
disallowed_service: "The target service is not allowed to authenticate against this CAS server. Please contact your system administrator for help."
1213

1314
notice:
1415
logged_in_as: "You are currently logged in as '%1'. If this is not you, please log in below."

spec/casserver_spec.rb

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,6 +36,18 @@
3636
page.should have_content("You have successfully logged in")
3737
end
3838

39+
it "auto-forwards when you're already logged in" do
40+
visit "/login"
41+
42+
fill_in 'username', :with => VALID_USERNAME
43+
fill_in 'password', :with => VALID_PASSWORD
44+
click_button 'login-submit'
45+
46+
visit "/login?service="+CGI.escape(@target_service)
47+
48+
page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
49+
end
50+
3951
it "fails to log in with invalid password" do
4052
visit "/login"
4153
fill_in 'username', :with => VALID_USERNAME
@@ -92,6 +104,38 @@
92104
#page.should have_xpath("<script>alert(32)</script>")
93105
end
94106

107+
describe 'service_uri validation' do
108+
let(:service) { 'http://imposter.com/' }
109+
110+
it "doesn't redirect back to untrusted services" do
111+
visit "/login?service="+CGI.escape(service)
112+
113+
page.should have_content("The target service is not allowed")
114+
115+
fill_in 'username', :with => VALID_USERNAME
116+
fill_in 'password', :with => VALID_PASSWORD
117+
118+
click_button 'login-submit'
119+
120+
page.should have_content("The target service is not allowed")
121+
end
122+
123+
it "doesn't redirect back when already logged in" do
124+
visit "/login"
125+
126+
fill_in 'username', :with => VALID_USERNAME
127+
fill_in 'password', :with => VALID_PASSWORD
128+
129+
click_button 'login-submit'
130+
131+
visit "/login?service="+CGI.escape(service)
132+
133+
page.should have_content("The target service is not allowed")
134+
end
135+
136+
end
137+
138+
95139
end # describe '/login'
96140

97141

spec/config/default_config.yml

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -50,4 +50,7 @@ enable_single_sign_out: true
5050
#downcase_username: true
5151

5252
allowed_service_ips:
53-
- 127.0.0.0/24
53+
- 127.0.0.0/24
54+
55+
allowed_service_uris:
56+
- http://my.app.test

0 commit comments

Comments
 (0)