Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allowed service uris #257

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -8,5 +8,5 @@ group :ldap do
end

group :active_resource do
gem "activeresource", ">= 2.3.12", "< 4.0"
gem "activeresource", ">= 2.3.12", "< 5.2"
end
8 changes: 6 additions & 2 deletions config/config.example.yml
Original file line number Diff line number Diff line change
Expand Up @@ -534,10 +534,14 @@ log:
#downcase_username: true

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

#allowed_service_uris:
# - https://myservice.com/login/cas

#allowed_service_ips:
# - 127.0.0.1
# - 192.168.0.0/24
2 changes: 1 addition & 1 deletion db/migrate/001_create_initial_structure.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class CreateInitialStructure < ActiveRecord::Migration
class CreateInitialStructure < ActiveRecord::Migration[4.2]
def self.up
# Oracle table names cannot exceed 30 chars...
# See http://code.google.com/p/rubycas-server/issues/detail?id=15
Expand Down
2 changes: 1 addition & 1 deletion db/migrate/002_add_indexes_for_performance.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
class AddIndexesForPerformance < ActiveRecord::Migration
class AddIndexesForPerformance < ActiveRecord::Migration[4.2]
def self.up
add_index :casserver_lt, :ticket
add_index :casserver_st, :ticket
Expand Down
4 changes: 2 additions & 2 deletions lib/casserver/model/consumable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,12 @@ def cleanup(max_lifetime, max_unconsumed_lifetime)
Time.now - max_lifetime,
Time.now - max_unconsumed_lifetime]

expired_tickets_count = count(:conditions => conditions)
expired_tickets_count = where(conditions).count

$LOG.debug("Destroying #{expired_tickets_count} expired #{self.name.demodulize}"+
"#{'s' if expired_tickets_count > 1}.") if expired_tickets_count > 0

destroy_all(conditions)
where(conditions).destroy_all
end
end
end
Expand Down
24 changes: 20 additions & 4 deletions lib/casserver/server.rb
Original file line number Diff line number Diff line change
Expand Up @@ -322,7 +322,11 @@ def self.init_database!

begin
if @service
if @renew
if !service_allowed?(@service)
$LOG.warn("Disallowed service '#{@service}'.")
@message = {:type => 'mistake',
:message => t.error.disallowed_service}
elsif @renew
$LOG.info("Authentication renew explicitly requested. Proceeding with CAS login for service #{@service.inspect}.")
elsif tgt && !tgt_error
$LOG.debug("Valid ticket granting ticket detected.")
Expand Down Expand Up @@ -409,6 +413,13 @@ def self.init_database!
@username.downcase!
end

if [email protected]? && !service_allowed?(@service)
@message = {:type => 'mistake',
:message => t.error.disallowed_service}
status 400
return render @template_engine, :login
end

if error = validate_login_ticket(@lt)
@message = {:type => 'mistake', :message => error}
# generate another login ticket to allow for re-submitting the form
Expand Down Expand Up @@ -532,9 +543,8 @@ def self.init_database!
st.destroy
end

pgts = CASServer::Model::ProxyGrantingTicket.find(:all,
:conditions => [CASServer::Model::ServiceTicket.quoted_table_name+".username = ?", tgt.username],
:include => :service_ticket)
pgts = CASServer::Model::ProxyGrantingTicket.where(casserver_st: { username: tgt.username }).
joins(:service_ticket)
pgts.each do |pgt|
$LOG.debug("Deleting Proxy-Granting Ticket '#{pgt}' for user '#{pgt.service_ticket.username}'")
pgt.destroy
Expand Down Expand Up @@ -766,6 +776,12 @@ def compile_template(engine, data, options, views)
super engine, data, options, views
end

def service_allowed?(service)
allowed_uris = Array(settings.config[:allowed_service_uris])

allowed_uris.empty? || allowed_uris.include?(service)
end

def ip_allowed?(ip)
require 'ipaddr'

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

notice:
logged_in_as: "You are currently logged in as '%1'. If this is not you, please log in below."
Expand Down
8 changes: 4 additions & 4 deletions rubycas-server.gemspec
Original file line number Diff line number Diff line change
Expand Up @@ -26,17 +26,17 @@ $gemspec = Gem::Specification.new do |s|
s.has_rdoc = true
s.post_install_message = "For more information on RubyCAS-Server, see http://rubycas.github.com"

s.add_dependency("activerecord", ">= 2.3.12", "< 4.0")
s.add_dependency("activesupport", ">= 2.3.12", "< 4.0")
s.add_dependency("activerecord", ">= 3.0", "< 5.2")
s.add_dependency("activesupport", ">= 3.0", "< 5.2")
s.add_dependency("sinatra", "~> 1.0")
s.add_dependency("sinatra-r18n", '~> 1.1.0')
s.add_dependency("sinatra-r18n", '~> 2.1.7')
s.add_dependency("crypt-isaac", "~> 0.9.1")

s.add_development_dependency("rack-test")
s.add_development_dependency("capybara", '1.1.2')
s.add_development_dependency("rspec")
s.add_development_dependency("rspec-core")
s.add_development_dependency("rake", "0.8.7")
s.add_development_dependency("rake", "~> 11.0")
s.add_development_dependency("sqlite3", "~> 1.3.1")
s.add_development_dependency("appraisal", "~> 0.4.1")
s.add_development_dependency("guard", "~> 1.4.0")
Expand Down
6 changes: 4 additions & 2 deletions spec/casserver/utils_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,13 +11,15 @@ module CASServer
let(:params_with_password_filtered) { { 'password' => '******' } }

it 'should log the controller action' do
$LOG.should_receive(:debug).with 'Processing application::instance_eval {}'
$LOG.should_receive(:<<).with "\n"
$LOG.should_receive(:debug).with 'Processing application::instance_exec {}'

subject.log_controller_action('application', params)
end

it 'should filter password parameters in the log' do
$LOG.should_receive(:debug).with "Processing application::instance_eval #{params_with_password_filtered.inspect}"
$LOG.should_receive(:<<).with "\n"
$LOG.should_receive(:debug).with "Processing application::instance_exec #{params_with_password_filtered.inspect}"

subject.log_controller_action('application', params_with_password)
end
Expand Down
44 changes: 44 additions & 0 deletions spec/casserver_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,18 @@
page.should have_content("You have successfully logged in")
end

it "auto-forwards when you're already logged in" do
visit "/login"

fill_in 'username', :with => VALID_USERNAME
fill_in 'password', :with => VALID_PASSWORD
click_button 'login-submit'

visit "/login?service="+CGI.escape(@target_service)

page.current_url.should =~ /^#{Regexp.escape(@target_service)}\/?\?ticket=ST\-[1-9rA-Z]+/
end

it "fails to log in with invalid password" do
visit "/login"
fill_in 'username', :with => VALID_USERNAME
Expand Down Expand Up @@ -92,6 +104,38 @@
#page.should have_xpath("<script>alert(32)</script>")
end

describe 'service_uri validation' do
let(:service) { 'http://imposter.com/' }

it "doesn't redirect back to untrusted services" do
visit "/login?service="+CGI.escape(service)

page.should have_content("The target service is not allowed")

fill_in 'username', :with => VALID_USERNAME
fill_in 'password', :with => VALID_PASSWORD

click_button 'login-submit'

page.should have_content("The target service is not allowed")
end

it "doesn't redirect back when already logged in" do
visit "/login"

fill_in 'username', :with => VALID_USERNAME
fill_in 'password', :with => VALID_PASSWORD

click_button 'login-submit'

visit "/login?service="+CGI.escape(service)

page.should have_content("The target service is not allowed")
end

end


end # describe '/login'


Expand Down
5 changes: 4 additions & 1 deletion spec/config/default_config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -50,4 +50,7 @@ enable_single_sign_out: true
#downcase_username: true

allowed_service_ips:
- 127.0.0.0/24
- 127.0.0.0/24

allowed_service_uris:
- http://my.app.test