aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHeiko Bernloehr <Heiko.Bernloehr@FreeIT.de>2012-11-14 22:49:41 +0100
committerHeiko Bernloehr <Heiko.Bernloehr@FreeIT.de>2012-11-14 23:08:26 +0100
commit9298117acdf82c9529a12a3ab41baf9d1e86c2f4 (patch)
tree0bbd1e0513c8e8a57cb841ae83e3e99b7e874e86
parentc07fcb616e0db81472889488189dc2f440020ef6 (diff)
downloadecs2-9298117acdf82c9529a12a3ab41baf9d1e86c2f4.tar.gz
ecs2-9298117acdf82c9529a12a3ab41baf9d1e86c2f4.zip
Introduced security fix for redirects.
Now redirects are integrity secured by sha1 message digest. A redirecting participant uses the /sys/auths resource realm attribute to store a message digest over all relevant redirect parameters (for details see [1]). The target participant uses this message digest again and verifies the integrity of the received redirect parameters (Location-Header). [1] see ECSA documentation at ECS->System resources->Auths
-rw-r--r--app/controllers/application_controller.rb7
-rw-r--r--app/models/message.rb22
-rw-r--r--db/migrate/20100922104919_rename_touch_from_ressource_monitors.rb27
-rw-r--r--test/fixtures/ressources.yml5
-rw-r--r--test/functional/messages_controller_test.rb146
-rw-r--r--test/unit/message_test.rb41
6 files changed, 203 insertions, 45 deletions
diff --git a/app/controllers/application_controller.rb b/app/controllers/application_controller.rb
index b098493..ab65daa 100644
--- a/app/controllers/application_controller.rb
+++ b/app/controllers/application_controller.rb
@@ -116,26 +116,31 @@ protected
# error pages
def rescue_body_401
+ @http_error= $!
logger.error $!.to_s
render :text => "#{$!.to_s}\n", :layout => false, :status => 401
end
def rescue_body_500
+ @http_error= $!
logger.error $!.to_s
render :text => "#{$!.to_s}\n", :layout => false, :status => 500
end
def rescue_body_400
+ @http_error= $!
logger.error $!.to_s
render :text => "#{$!.to_s}\n" , :layout => false, :status => 400
end
def rescue_body_403
+ @http_error= $!
logger.error $!.to_s
render :text => "#{$!.to_s}\n" , :layout => false, :status => 403
end
def rescue_body_404
+ @http_error= $!
logger.error $!.to_s
if $!.to_s.blank?
render :text => "The server does not know the ressource\nor the message queue in question is empty.\n" , :layout => false, :status => 404
@@ -145,11 +150,13 @@ protected
end
def rescue_body_409
+ @http_error= $!
logger.error $!.to_s
render :text => "#{$!.to_s}\n" , :layout => false, :status => 409
end
def rescue_body_415(controller_binding)
+ @http_error= $!
logger.error $!.to_s
if $!.to_s.blank?
render :text => "The format of the client data is not supported by the server.\nIf your format is right please doublecheck the encoding !\nIt has to be UTF8 !\n", :layout => false, :status => 415
diff --git a/app/models/message.rb b/app/models/message.rb
index 4a89778..69067d0 100644
--- a/app/models/message.rb
+++ b/app/models/message.rb
@@ -200,7 +200,8 @@ class Message < ActiveRecord::Base
# Preprocess request body if it's a /sys/auths resource.
# Generate a one touch token (hash)
def post_create_auths_resource(participant)
- ttl = 60.seconds
+ ttl_min = 5.seconds
+ ttl = ttl_min + 60.seconds
unless Mime::Type.lookup(self.content_type).to_sym == :json
raise Ecs::InvalidMimetypeException, "Body format has to be in JSON"
end
@@ -210,9 +211,17 @@ class Message < ActiveRecord::Base
raise Ecs::InvalidMessageException, "Invalid JSON body"
end
bks = b.keys
- unless bks.include?("url")
- raise Ecs::InvalidMessageException, "Missing url key"
+
+ # NOTE Assures that there are at least url or realm set -> backward compatibility
+ unless bks.include?("url") or bks.include?("realm")
+ raise Ecs::InvalidMessageException, "You have to provide realm or url attribute"
+ end
+ if bks.include?("realm") and !b["realm"].empty? and !bks.include?("url")
+ b["url"]= b["realm"]
+ elsif bks.include?("url") and !b["url"].empty? and !bks.include?("realm")
+ b["realm"]= b["url"]
end
+
#msg_id = URI.split(b["url"])[5][1..-1].sub(/[^\/]*\/[^\/]*\/(.*)/, '\1').to_i
#begin
# Message.find(msg_id)
@@ -224,10 +233,13 @@ class Message < ActiveRecord::Base
b["sov"] = Time.now.xmlschema
b["eov"] = (Time.now + ttl).xmlschema
when (bks.include?("sov") and !bks.include?("eov"))
+ if Time.parse(b["sov"]) < Time.now
+ raise Ecs::InvalidMessageException, 'sov time is younger then current time'
+ end
b["eov"] = (Time.parse(b["sov"]) + ttl).xmlschema
when (!bks.include?("sov") and bks.include?("eov"))
- if Time.parse(b["eov"]) < Time.now
- raise Ecs::InvalidMessageException, 'eov time is younger then current time'
+ if Time.parse(b["eov"]) < (Time.now + ttl_min)
+ raise Ecs::InvalidMessageException, 'eov time is too young'
end
b["sov"] = Time.now.xmlschema
when (bks.include?("sov") and bks.include?("eov"))
diff --git a/db/migrate/20100922104919_rename_touch_from_ressource_monitors.rb b/db/migrate/20100922104919_rename_touch_from_ressource_monitors.rb
deleted file mode 100644
index 829eea7..0000000
--- a/db/migrate/20100922104919_rename_touch_from_ressource_monitors.rb
+++ /dev/null
@@ -1,27 +0,0 @@
-# Copyright (C) 2007, 2008, 2009, 2010 Heiko Bernloehr (FreeIT.de).
-#
-# This file is part of ECS.
-#
-# ECS is free software: you can redistribute it and/or modify it
-# under the terms of the GNU Affero General Public License as
-# published by the Free Software Foundation, either version 3 of
-# the License, or (at your option) any later version.
-#
-# ECS is distributed in the hope that it will be useful, but
-# WITHOUT ANY WARRANTY; without even the implied warranty of
-# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
-# Affero General Public License for more details.
-#
-# You should have received a copy of the GNU Affero General Public
-# License along with ECS. If not, see <http://www.gnu.org/licenses/>.
-
-
-class RenameTouchFromRessourceMonitors < ActiveRecord::Migration
- def self.up
- rename_column :ressource_monitors, :touch, :monitor_counter
- end
-
- def self.down
- raise ActiveRecord::IrreversibleMigration
- end
-end
diff --git a/test/fixtures/ressources.yml b/test/fixtures/ressources.yml
index d66f17a..f3869d1 100644
--- a/test/fixtures/ressources.yml
+++ b/test/fixtures/ressources.yml
@@ -42,3 +42,8 @@ cc_course:
postroute: false
events: true
+sys_auths:
+ namespace: sys
+ ressource: auths
+ postroute: false
+ events: false
diff --git a/test/functional/messages_controller_test.rb b/test/functional/messages_controller_test.rb
index af6293b..2522617 100644
--- a/test/functional/messages_controller_test.rb
+++ b/test/functional/messages_controller_test.rb
@@ -85,9 +85,9 @@ class MessagesControllerTest < ActionController::TestCase
@request.env["CONTENT_TYPE"] = "text/html"
@request.env["X-EcsAuthId"] = identities(:stgt_id1).name
@request.env["X-EcsReceiverCommunities"] = communities(:suv).name
+ @request.set_REQUEST_URI("/numlab/exercises")
mm_count = MembershipMessage.all.count
post :create
-
assert_response 201
assert_equal assigns(:record).sender, assigns(:participant).id
assert_equal mm_count+1, MembershipMessage.all.count
@@ -98,6 +98,7 @@ class MessagesControllerTest < ActionController::TestCase
@request.env["CONTENT_TYPE"] = "text/html"
@request.env["X-EcsAuthId"] = identities(:stgt_id1).name
@request.env["X-EcsReceiverCommunities"] = communities(:suv).name + "," + communities(:public).name
+ @request.set_REQUEST_URI("/numlab/exercises")
mm_count = MembershipMessage.all.count
post :create
assert_response 201
@@ -110,6 +111,7 @@ class MessagesControllerTest < ActionController::TestCase
@request.env["CONTENT_TYPE"] = "text/html"
@request.env["X-EcsAuthId"] = identities(:stgt_id1).name
@request.env["X-EcsReceiverCommunities"] = communities(:suv).name + "," + communities(:public).id.to_s
+ @request.set_REQUEST_URI("/numlab/exercises")
mm_count = MembershipMessage.all.count
post :create
assert_response 201
@@ -121,6 +123,7 @@ class MessagesControllerTest < ActionController::TestCase
@request.env["RAW_POST_DATA"] = "hallole"
@request.env["X-EcsAuthId"] = identities(:stgt_id1).name
@request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/numlab/exercises")
post :create
assert_response 400
end
@@ -129,6 +132,7 @@ class MessagesControllerTest < ActionController::TestCase
@request.env["CONTENT_TYPE"] = "text/html"
@request.env["X-EcsAuthId"] = identities(:stgt_id1).name
@request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/numlab/exercises")
post :create
assert_response 400
end
@@ -302,18 +306,138 @@ class MessagesControllerTest < ActionController::TestCase
assert_equal "Hallo Ihr da im Radio.", @response.body.strip
end
+# Auths tests
+#
+
+ test "create_auths" do
+ @request.env["RAW_POST_DATA"] = <<-'HERE'
+ {
+ "url":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT",
+ "realm":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT"
+ }
+ HERE
+ @request.env["CONTENT_TYPE"] = "application/json"
+ @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
+ @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/sys/auths")
+ mm_count = MembershipMessage.all.count
+ post :create
+ assert_response 201
+ end
+
+ test "create_auths_url" do
+ @request.env["RAW_POST_DATA"] = <<-'HERE'
+ {
+ "url":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT"
+ }
+ HERE
+ @request.env["CONTENT_TYPE"] = "application/json"
+ @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
+ @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/sys/auths")
+ mm_count = MembershipMessage.all.count
+ post :create
+ assert_response 201
+ end
+
+ test "create_auths_realm" do
+ @request.env["RAW_POST_DATA"] = <<-'HERE'
+ {
+ "realm":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT"
+ }
+ HERE
+ @request.env["CONTENT_TYPE"] = "application/json"
+ @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
+ @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/sys/auths")
+ mm_count = MembershipMessage.all.count
+ post :create
+ assert_response 201
+ end
+
+ test "create_auths_invalid_json_mimetype" do
+ @request.env["RAW_POST_DATA"] = <<-'HERE'
+ {
+ "realm":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT"
+ }
+ HERE
+ @request.env["CONTENT_TYPE"] = "text/html"
+ @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
+ @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/sys/auths")
+ mm_count = MembershipMessage.all.count
+ post :create
+ assert_response 415
+ assert_equal "Body format has to be in JSON", assigns(:http_error).to_s
+ end
+
+ test "create_auths_invalid_json_body" do
+ @request.env["RAW_POST_DATA"] = <<-'HERE'
+ {
+ "realm"::"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT"
+ }
+ HERE
+ @request.env["CONTENT_TYPE"] = "application/json"
+ @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
+ @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/sys/auths")
+ mm_count = MembershipMessage.all.count
+ post :create
+ assert_response 400
+ assert_equal "Invalid JSON body", assigns(:http_error).to_s
+ end
+
+ test "create_auths_eov_younger_than_sov" do
+ @request.env["RAW_POST_DATA"] = <<-'HERE'
+ {
+ "realm":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT",
+ "sov": "2011-03-08T23:25:27+01:00",
+ "eov": "2011-03-08T23:25:17+01:00"
+ }
+ HERE
+ @request.env["CONTENT_TYPE"] = "application/json"
+ @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
+ @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/sys/auths")
+ mm_count = MembershipMessage.all.count
+ post :create
+ assert_response 400
+ assert_equal "invalid times either in sov or eov", assigns(:http_error).to_s
+ end
-# test "create_auths" do
-# @request.env["RAW_POST_DATA"] = '{"url":"http://freeit.de/course1"}'
-# @request.env["CONTENT_TYPE"] = "application/json"
-# @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
-# @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
-# @request.set_REQUEST_URI("/sys/auths")
-# mm_count = MembershipMessage.all.count
-# post :create
-# assert_response 201
-# end
+ test "create_auths_sov_younger_than_current_time" do
+ @request.env["RAW_POST_DATA"] = <<-'HERE'
+ {
+ "realm":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT",
+ "sov": "2011-03-08T23:25:27+01:00"
+ }
+ HERE
+ @request.env["CONTENT_TYPE"] = "application/json"
+ @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
+ @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/sys/auths")
+ mm_count = MembershipMessage.all.count
+ post :create
+ assert_response 400
+ assert_equal "sov time is younger then current time", assigns(:http_error).to_s
+ end
+ test "create_auths_eov_too_young" do
+ @request.env["RAW_POST_DATA"] = <<-"HERE"
+ {
+ "realm":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT",
+ "eov": "#{(Time.now + 1.second).xmlschema}"
+ }
+ HERE
+ @request.env["CONTENT_TYPE"] = "application/json"
+ @request.env["X-EcsAuthId"] = identities(:stgt_id1).name
+ @request.env["X-EcsReceiverMemberships"] = memberships(:ulm_wuv).id.to_s
+ @request.set_REQUEST_URI("/sys/auths")
+ mm_count = MembershipMessage.all.count
+ post :create
+ assert_response 400
+ assert_equal "eov time is too young", assigns(:http_error).to_s
+ end
# anonymous clients
#
diff --git a/test/unit/message_test.rb b/test/unit/message_test.rb
index f1ca8d2..fbe0b21 100644
--- a/test/unit/message_test.rb
+++ b/test/unit/message_test.rb
@@ -59,6 +59,43 @@ class MessageTest < ActiveSupport::TestCase
# number of receivers have to be two
assert_equal 2, Participant.for_message(messages(:numlab_ex1)).uniq.length
end
-end
-
+# Auths
+#
+ test "create_auths" do
+ headers={
+ "X-EcsReceiverMemberships" => "7,2",
+ "CONTENT_TYPE" => "application/json"
+ }
+ raw_post= Hash.new
+ raw_post[:realm]= <<-'HERE'
+ {
+ "realm":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT"
+ }
+ HERE
+ raw_post[:url]= <<-'HERE'
+ {
+ "url":"https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT"
+ }
+ HERE
+ raw_post.each do |k,v|
+ request= TestRequest.new(headers, v)
+ msg= nil
+ assert_nothing_raised do
+ msg= Message.create__(request, "sys", "auths", participants(:ilias_stgt))
+ end
+ assert Mime::Type.lookup(msg.content_type)== :json, "Content-Type is not application/json"
+ assert_equal participants(:ilias_stgt).id, msg.sender, "Unexpected creator of the message"
+ json= nil
+ assert_nothing_raised do
+ json= ActiveSupport::JSON.decode(msg.body)
+ end
+ assert json.keys.include?(k.to_s)
+ assert_equal "https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT", json[k.to_s]
+ assert json.keys.include?(k.to_s)
+ assert_equal "https://ilias.uni-stuttgart.de/goto.php?target=crs_95034&client_id=USTGT", json[k.to_s]
+ assert json.keys.include?("pid")
+ assert_equal participants(:ilias_stgt).id, json["pid"]
+ end
+ end
+end