From 69193b52b7135321e8c13f65334b3ccceeb601ec Mon Sep 17 00:00:00 2001 From: Carl Howells Date: Mon, 19 Jul 2010 09:56:33 -0700 Subject: [PATCH 01/12] whitespace --- lib/openid/cryptutil.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/openid/cryptutil.rb b/lib/openid/cryptutil.rb index 7f672edf..cd505920 100644 --- a/lib/openid/cryptutil.rb +++ b/lib/openid/cryptutil.rb @@ -37,7 +37,7 @@ def CryptUtil.sha1(text) end def CryptUtil.hmac_sha1(key, text) - if Digest.const_defined? :HMAC + if Digest.const_defined? :HMAC Digest::HMAC.new(key,Digest::SHA1).update(text).digest else return HMAC::SHA1.digest(key, text) @@ -49,7 +49,7 @@ def CryptUtil.sha256(text) end def CryptUtil.hmac_sha256(key, text) - if Digest.const_defined? :HMAC + if Digest.const_defined? :HMAC Digest::HMAC.new(key,Digest::SHA256).update(text).digest else return HMAC::SHA256.digest(key, text) From 669c77ba895fbca6f5a9c4a0c835693c35a6d432 Mon Sep 17 00:00:00 2001 From: Carl Howells Date: Mon, 19 Jul 2010 10:02:37 -0700 Subject: [PATCH 02/12] fix file permissions --- admin/build-docs | 0 admin/fixperms | 0 admin/graph-require.sh | 0 admin/prepare-release | 0 admin/runtests | 0 examples/discover | 0 examples/rails_openid/script/about | 0 examples/rails_openid/script/breakpointer | 0 examples/rails_openid/script/console | 0 examples/rails_openid/script/destroy | 0 examples/rails_openid/script/generate | 0 examples/rails_openid/script/performance/benchmarker | 0 examples/rails_openid/script/performance/profiler | 0 examples/rails_openid/script/plugin | 0 examples/rails_openid/script/process/reaper | 0 examples/rails_openid/script/process/spawner | 0 examples/rails_openid/script/process/spinner | 0 examples/rails_openid/script/runner | 0 examples/rails_openid/script/server | 0 19 files changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 admin/build-docs mode change 100644 => 100755 admin/fixperms mode change 100644 => 100755 admin/graph-require.sh mode change 100644 => 100755 admin/prepare-release mode change 100644 => 100755 admin/runtests mode change 100644 => 100755 examples/discover mode change 100644 => 100755 examples/rails_openid/script/about mode change 100644 => 100755 examples/rails_openid/script/breakpointer mode change 100644 => 100755 examples/rails_openid/script/console mode change 100644 => 100755 examples/rails_openid/script/destroy mode change 100644 => 100755 examples/rails_openid/script/generate mode change 100644 => 100755 examples/rails_openid/script/performance/benchmarker mode change 100644 => 100755 examples/rails_openid/script/performance/profiler mode change 100644 => 100755 examples/rails_openid/script/plugin mode change 100644 => 100755 examples/rails_openid/script/process/reaper mode change 100644 => 100755 examples/rails_openid/script/process/spawner mode change 100644 => 100755 examples/rails_openid/script/process/spinner mode change 100644 => 100755 examples/rails_openid/script/runner mode change 100644 => 100755 examples/rails_openid/script/server diff --git a/admin/build-docs b/admin/build-docs old mode 100644 new mode 100755 diff --git a/admin/fixperms b/admin/fixperms old mode 100644 new mode 100755 diff --git a/admin/graph-require.sh b/admin/graph-require.sh old mode 100644 new mode 100755 diff --git a/admin/prepare-release b/admin/prepare-release old mode 100644 new mode 100755 diff --git a/admin/runtests b/admin/runtests old mode 100644 new mode 100755 diff --git a/examples/discover b/examples/discover old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/about b/examples/rails_openid/script/about old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/breakpointer b/examples/rails_openid/script/breakpointer old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/console b/examples/rails_openid/script/console old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/destroy b/examples/rails_openid/script/destroy old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/generate b/examples/rails_openid/script/generate old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/performance/benchmarker b/examples/rails_openid/script/performance/benchmarker old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/performance/profiler b/examples/rails_openid/script/performance/profiler old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/plugin b/examples/rails_openid/script/plugin old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/process/reaper b/examples/rails_openid/script/process/reaper old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/process/spawner b/examples/rails_openid/script/process/spawner old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/process/spinner b/examples/rails_openid/script/process/spinner old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/runner b/examples/rails_openid/script/runner old mode 100644 new mode 100755 diff --git a/examples/rails_openid/script/server b/examples/rails_openid/script/server old mode 100644 new mode 100755 From 9171ae529a64e95a3edc4326779cd909e366aedf Mon Sep 17 00:00:00 2001 From: Carl Howells Date: Mon, 19 Jul 2010 10:14:16 -0700 Subject: [PATCH 03/12] whitespace --- lib/openid/association.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/openid/association.rb b/lib/openid/association.rb index fd2cd599..4329ae19 100644 --- a/lib/openid/association.rb +++ b/lib/openid/association.rb @@ -134,7 +134,7 @@ def get_message_signature(message) end def ==(other) - (other.class == self.class and + (other.class == self.class and other.handle == self.handle and other.secret == self.secret and From affbf7c0e8d69048838230035a7add428f75d608 Mon Sep 17 00:00:00 2001 From: Carl Howells Date: Mon, 19 Jul 2010 10:28:55 -0700 Subject: [PATCH 04/12] Use constant-time comparison of signatures to mitigate timing attacks --- lib/openid/association.rb | 2 +- lib/openid/cryptutil.rb | 11 +++++++++++ 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/lib/openid/association.rb b/lib/openid/association.rb index 4329ae19..29c29b3c 100644 --- a/lib/openid/association.rb +++ b/lib/openid/association.rb @@ -125,7 +125,7 @@ def check_message_signature(message) raise ProtocolError, "#{message} has no sig." end calculated_sig = get_message_signature(message) - return calculated_sig == message_sig + return CryptUtil.const_eq(calculated_sig, message_sig) end # Get the signature for this message diff --git a/lib/openid/cryptutil.rb b/lib/openid/cryptutil.rb index cd505920..2ae19e1d 100644 --- a/lib/openid/cryptutil.rb +++ b/lib/openid/cryptutil.rb @@ -100,5 +100,16 @@ def CryptUtil.num_to_base64(l) def CryptUtil.base64_to_num(s) return binary_to_num(OpenID::Util.from_base64(s)) end + + def CryptUtil.const_eq(s1, s2) + if s1.length != s2.length + return false + end + result = true + s1.length.times do |i| + result &= (s1[i] == s2[i]) + end + return result + end end end From 7f0ea1d12157da217740fc099e4f3dab9924ebb3 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Mon, 5 Jul 2010 19:16:38 +0800 Subject: [PATCH 05/12] make all tests work on Ruby 1.9.1. Timeout::Error is subclass of RuntimeError not SignalException on Ruby 1.9.1. --- lib/openid/fetchers.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/openid/fetchers.rb b/lib/openid/fetchers.rb index 22c87ac3..d3dfa72d 100644 --- a/lib/openid/fetchers.rb +++ b/lib/openid/fetchers.rb @@ -205,6 +205,8 @@ def fetch(url, body=nil, headers=nil, redirect_limit=REDIRECT_LIMIT) conn.request_post(url.request_uri, body, headers) end } + rescue Timeout::Error => why + raise FetchingError, "Error fetching #{url}: #{why}" rescue RuntimeError => why raise why rescue OpenSSL::SSL::SSLError => why @@ -212,8 +214,6 @@ def fetch(url, body=nil, headers=nil, redirect_limit=REDIRECT_LIMIT) rescue FetchingError => why raise why rescue Exception => why - # Things we've caught here include a Timeout::Error, which descends - # from SignalException. raise FetchingError, "Error fetching #{url}: #{why}" end From fabc53c03248fe0bf862e66d8825b9dbce7b90ca Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Mon, 5 Jul 2010 19:32:03 +0800 Subject: [PATCH 06/12] support encoding introduced since Ruby 1.9. --- lib/openid/fetchers.rb | 20 ++++++++++++++++++++ test/test_fetchers.rb | 29 ++++++++++++++++++++++++++++- 2 files changed, 48 insertions(+), 1 deletion(-) diff --git a/lib/openid/fetchers.rb b/lib/openid/fetchers.rb index d3dfa72d..a7dff2c6 100644 --- a/lib/openid/fetchers.rb +++ b/lib/openid/fetchers.rb @@ -205,6 +205,7 @@ def fetch(url, body=nil, headers=nil, redirect_limit=REDIRECT_LIMIT) conn.request_post(url.request_uri, body, headers) end } + setup_encoding(response) rescue Timeout::Error => why raise FetchingError, "Error fetching #{url}: #{why}" rescue RuntimeError => why @@ -234,5 +235,24 @@ def fetch(url, body=nil, headers=nil, redirect_limit=REDIRECT_LIMIT) return HTTPResponse._from_net_response(response, unparsed_url) end end + + private + def setup_encoding(response) + return unless defined?(::Encoding::ASCII_8BIT) + charset = response.type_params["charset"] + return if charset.nil? + encoding = nil + begin + encoding = Encoding.find(charset) + rescue ArgumentError + end + encoding ||= Encoding::ASCII_8BIT + body = response.body + if body.respond_to?(:force_encoding) + body.force_encoding(encoding) + else + body.set_encoding(encoding) + end + end end end diff --git a/test/test_fetchers.rb b/test/test_fetchers.rb index 7130da55..6b033314 100644 --- a/test/test_fetchers.rb +++ b/test/test_fetchers.rb @@ -1,3 +1,5 @@ +# -*- coding: utf-8 -*- + require 'test/unit' require 'net/http' require 'webrick' @@ -112,7 +114,22 @@ def _redirect_loop assert_block("Fetched too many times.") { @_redirect_counter < 10 } } end - + + UTF8_PAGE_CONTENT = <<-EOHTML + + UTF-8 + こんにちは + +EOHTML + def _utf8_page + lambda { |req, resp| + resp['Content-Type'] = "text/html; charset=utf-8" + body = UTF8_PAGE_CONTENT.dup + body.force_encoding("ASCII-8BIT") if body.respond_to?(:force_encoding) + resp.body = body + } + end + def setup @fetcher = OpenID::StandardFetcher.new @logfile = StringIO.new @@ -138,6 +155,7 @@ def setup } @server.mount_proc('/post', _require_post) @server.mount_proc('/redirect_loop', _redirect_loop) + @server.mount_proc('/utf8_page', _utf8_page) @server.start } @uri = _uri_build @@ -211,6 +229,15 @@ def test_redirect_limit } end + def test_utf8_page + uri = _uri_build('/utf8_page') + response = @fetcher.fetch(uri) + assert_equal(UTF8_PAGE_CONTENT, response.body) + if response.body.respond_to?(:encoding) + assert_equal(Encoding::UTF_8, response.body.encoding) + end + end + def test_cases for path, expected_code, expected_url in @@cases uri = _uri_build(path) From ef53840cd3ff4d207981b75e7646561c1b403bd9 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Mon, 5 Jul 2010 19:42:52 +0800 Subject: [PATCH 07/12] add a test for discovering from UTF-8 HTML. --- test/data/test_discover/openid_utf8.html | 11 +++++++++++ test/test_discover.rb | 14 ++++++++++++++ 2 files changed, 25 insertions(+) create mode 100644 test/data/test_discover/openid_utf8.html diff --git a/test/data/test_discover/openid_utf8.html b/test/data/test_discover/openid_utf8.html new file mode 100644 index 00000000..c98001af --- /dev/null +++ b/test/data/test_discover/openid_utf8.html @@ -0,0 +1,11 @@ + + + + Identity Page for Smoker + + + + +

こんにちは

+ + diff --git a/test/test_discover.rb b/test/test_discover.rb index 13b115ce..71511c3e 100644 --- a/test/test_discover.rb +++ b/test/test_discover.rb @@ -369,6 +369,20 @@ def test_html1And2 } end + def test_html_utf8 + utf8_html = read_data_file('test_discover/openid_utf8.html', false) + utf8_html.force_encoding("UTF-8") if utf8_html.respond_to?(:force_encoding) + services = _discover('text/html', utf8_html, 1) + + _checkService(services[0], + "http://www.myopenid.com/server", + @id_url, + 'http://smoker.myopenid.com/', + nil, + ['1.1'], + false) + end + def test_yadisEmpty services = _discover('application/xrds+xml', read_data_file('test_discover/yadis_0entries.xml', false), From 4ac2e1192e5317e6fec0cec6407ba740b1c7040d Mon Sep 17 00:00:00 2001 From: dbloete Date: Fri, 30 Apr 2010 23:35:37 +0800 Subject: [PATCH 08/12] Extensions for StoreRequest and differentiation for ax modes --- lib/openid/extensions/ax.rb | 33 ++++++++++++++++++++++---- test/test_ax.rb | 46 +++++++++++++++++++++++++++++++++++-- 2 files changed, 72 insertions(+), 7 deletions(-) diff --git a/lib/openid/extensions/ax.rb b/lib/openid/extensions/ax.rb index 55eda8e7..4c8e899e 100644 --- a/lib/openid/extensions/ax.rb +++ b/lib/openid/extensions/ax.rb @@ -110,10 +110,12 @@ def self.to_type_uris(namespace_map, alias_list_s) class FetchRequest < AXMessage attr_reader :requested_attributes attr_accessor :update_url + + MODE = 'fetch_request' def initialize(update_url = nil) super() - @mode = 'fetch_request' + @mode = MODE @requested_attributes = {} @update_url = update_url end @@ -180,7 +182,7 @@ def get_required_attrs def self.from_openid_request(oidreq) message = oidreq.message ax_args = message.get_args(NS_URI) - return nil if ax_args == {} + return nil if ax_args == {} or ax_args['mode'] != MODE req = new req.parse_extension_args(ax_args) @@ -467,11 +469,26 @@ def self.from_success_response(success_response, signed=true) # A store request attribute exchange message representation class StoreRequest < KeyValueMessage + + MODE = 'store_request' + def initialize super - @mode = 'store_request' + @mode = MODE end - + + # Extract a StoreRequest from an OpenID message + # message: OpenID::Message + # return a StoreRequest or nil if AX arguments are not present + def self.from_openid_request(oidreq) + message = oidreq.message + ax_args = message.get_args(NS_URI) + return nil if ax_args.empty? or ax_args['mode'] != MODE + req = new + req.parse_extension_args(ax_args) + req + end + def get_extension_args(aliases=nil) ax_args = new_args kv_args = _get_extension_kv_args(aliases) @@ -499,7 +516,13 @@ def initialize(succeeded = true, error_message = nil) end @error_message = error_message end - + + def self.from_success_response(success_response) + resp = nil + ax_args = success_response.message.get_args(NS_URI) + resp = ax_args.key?('error') ? new(false, ax_args['error']) : new + end + def succeeded? @mode == SUCCESS_MODE end diff --git a/test/test_ax.rb b/test/test_ax.rb index c1dcfb1f..2d17c1f5 100644 --- a/test/test_ax.rb +++ b/test/test_ax.rb @@ -371,7 +371,28 @@ def test_from_openid_request_no_ax ax_req = FetchRequest.from_openid_request(openid_req) assert(ax_req.nil?) end - + + def test_from_openid_request_wrong_ax_mode + uri = 'http://under.the.sea/' + name = 'ext0' + value = 'snarfblat' + + message = OpenID::Message.from_openid_args({ + 'mode' => 'id_res', + 'ns' => OPENID2_NS, + 'ns.ax' => AXMessage::NS_URI, + 'ax.update_url' => 'http://example.com/realm/update_path', + 'ax.mode' => 'store_request', + 'ax.type.' + name => uri, + 'ax.count.' + name => '1', + 'ax.value.' + name + '.1' => value + }) + openid_req = Server::OpenIDRequest.new + openid_req.message = message + ax_req = FetchRequest.from_openid_request(openid_req) + assert(ax_req.nil?) + end + def test_openid_update_url_verification_error openid_req_msg = Message.from_openid_args({ 'mode' => 'checkid_setup', @@ -602,7 +623,28 @@ def test_get_extension_args_empty } assert_equal(eargs, @msg.get_extension_args) end - + + def test_from_openid_request_wrong_ax_mode + uri = 'http://under.the.sea/' + name = 'ext0' + value = 'snarfblat' + + message = OpenID::Message.from_openid_args({ + 'mode' => 'id_res', + 'ns' => OPENID2_NS, + 'ns.ax' => AXMessage::NS_URI, + 'ax.update_url' => 'http://example.com/realm/update_path', + 'ax.mode' => 'fetch_request', + 'ax.type.' + name => uri, + 'ax.count.' + name => '1', + 'ax.value.' + name + '.1' => value + }) + openid_req = Server::OpenIDRequest.new + openid_req.message = message + ax_req = StoreRequest.from_openid_request(openid_req) + assert(ax_req.nil?) + end + def test_get_extension_args_nonempty @msg.set_values(@type_a, ['foo','bar']) aliases = NamespaceMap.new From fb8c6c39374fc7f1f4e6a969b0b47e6186d9aafb Mon Sep 17 00:00:00 2001 From: Igor Russkih Date: Mon, 17 May 2010 22:13:35 +0800 Subject: [PATCH 09/12] Fix of Encoding incompatibility error in ruby1.9: RE is utf-8 and html is ANSI8bit --- lib/openid/consumer/html_parse.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/openid/consumer/html_parse.rb b/lib/openid/consumer/html_parse.rb index 579874ca..fca39456 100644 --- a/lib/openid/consumer/html_parse.rb +++ b/lib/openid/consumer/html_parse.rb @@ -18,7 +18,7 @@ module OpenID [^>]*>.*?<\/script> - /mixu + /mix def OpenID.openid_unescape(s) s.gsub('&','&').gsub('<','<').gsub('>','>').gsub('"','"') From 1e5a40d03671d75341f98f54830ec8e45a520a4c Mon Sep 17 00:00:00 2001 From: Mike Mell Date: Sat, 15 May 2010 01:09:18 +0800 Subject: [PATCH 10/12] The method name was incorrect -- should be signed? not singed? --- lib/openid/consumer/responses.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/openid/consumer/responses.rb b/lib/openid/consumer/responses.rb index 91262398..4947c1ca 100644 --- a/lib/openid/consumer/responses.rb +++ b/lib/openid/consumer/responses.rb @@ -83,7 +83,7 @@ def signed?(ns_uri, ns_key) # Return the specified signed field if available, otherwise # return default def get_signed(ns_uri, ns_key, default=nil) - if singed?(ns_uri, ns_key) + if signed?(ns_uri, ns_key) return @message.get_arg(ns_uri, ns_key, default) else return default From 8f49a81af806407faae7453e7def349dfc715c8a Mon Sep 17 00:00:00 2001 From: Mike Mell Date: Sat, 15 May 2010 01:11:41 +0800 Subject: [PATCH 11/12] When the iname is in the url (e.g. http://example.com/consumer/=mary) the Rails :id must be nullified so that the realm is valid. --- examples/rails_openid/app/controllers/consumer_controller.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/examples/rails_openid/app/controllers/consumer_controller.rb b/examples/rails_openid/app/controllers/consumer_controller.rb index 37dd3bbd..a42b2724 100644 --- a/examples/rails_openid/app/controllers/consumer_controller.rb +++ b/examples/rails_openid/app/controllers/consumer_controller.rb @@ -46,7 +46,7 @@ def start oidreq.return_to_args['force_post']='x'*2048 end return_to = url_for :action => 'complete', :only_path => false - realm = url_for :action => 'index', :only_path => false + realm = url_for :action => 'index', :id => nil, :only_path => false if oidreq.send_redirect?(realm, return_to, params[:immediate]) redirect_to oidreq.redirect_url(realm, return_to, params[:immediate]) From 8e979da19e47a59f93ce9acb5a3b5d535924198d Mon Sep 17 00:00:00 2001 From: Mike Mell Date: Sat, 15 May 2010 01:20:41 +0800 Subject: [PATCH 12/12] Fetch the XRDS one time for all service types --- lib/openid/consumer/discovery.rb | 3 +-- lib/openid/yadis/xrires.rb | 15 ++++----------- 2 files changed, 5 insertions(+), 13 deletions(-) diff --git a/lib/openid/consumer/discovery.rb b/lib/openid/consumer/discovery.rb index 01fe0365..f150d6b6 100644 --- a/lib/openid/consumer/discovery.rb +++ b/lib/openid/consumer/discovery.rb @@ -421,8 +421,7 @@ def self.discover_xri(iname) iname = self.normalize_xri(iname) begin - canonical_id, services = Yadis::XRI::ProxyResolver.new().query( - iname, OpenIDServiceEndpoint::OPENID_TYPE_URIS) + canonical_id, services = Yadis::XRI::ProxyResolver.new().query( iname ) if canonical_id.nil? raise Yadis::XRDSError.new(sprintf('No CanonicalID found for XRI %s', iname)) diff --git a/lib/openid/yadis/xrires.rb b/lib/openid/yadis/xrires.rb index 39439119..e2a14dc7 100644 --- a/lib/openid/yadis/xrires.rb +++ b/lib/openid/yadis/xrires.rb @@ -42,34 +42,27 @@ def query_url(xri, service_type=nil) return XRI.append_args(hxri, args) end - def query(xri, service_types) + def query(xri) # these can be query args or http headers, needn't be both. # headers = {'Accept' => 'application/xrds+xml;sep=true'} canonicalID = nil - services = service_types.collect { |service_type| - url = self.query_url(xri, service_type) + url = self.query_url(xri) begin response = OpenID.fetch(url) rescue - raise XRIHTTPError, ["Could not fetch #{xri}", $!] + raise XRIHTTPError, "Could not fetch #{xri}, #{$!}" end raise XRIHTTPError, "Could not fetch #{xri}" if response.nil? xrds = Yadis::parseXRDS(response.body) canonicalID = Yadis::get_canonical_id(xri, xrds) - Yadis::services(xrds) unless xrds.nil? - } + return canonicalID, Yadis::services(xrds) # TODO: # * If we do get hits for multiple service_types, we're almost # certainly going to have duplicated service entries and # broken priority ordering. - services = services.inject([]) { |flatter, some_services| - flatter += some_services unless some_services.nil? - } - - return canonicalID, services end end