diff --git a/app/controllers/authorizations_controller.rb b/app/controllers/authorizations_controller.rb index e09a0c5180057ac8b417230a555f4f498cd24a43..71d86631d16cc71c4a9d1308f1564044ed8bfb40 100644 --- a/app/controllers/authorizations_controller.rb +++ b/app/controllers/authorizations_controller.rb @@ -60,22 +60,23 @@ class AuthorizationsController < ApplicationController # @param [String] enc_signed_string A Base64 encoded string with app_url;pod_url;time;nonce # @param [String] sig A Base64 encoded signature of the decoded signed_string with public_key. - # @param [String] public_key The application's public key to verify sig with. + # @param [OpenSSL::PKey::RSA] public_key The application's public key to verify sig with. + # @return [String] 'ok' or an error message. def verify( enc_signed_string, sig, public_key) signed_string = Base64.decode64(enc_signed_string) split = signed_string.split(';') time = split[2] nonce = split[3] - return 'blank public key' if public_key.blank? + return 'blank public key' if public_key.n.nil? + return 'key too small, use at least 2048 bits' if public_key.n.num_bits < 2048 return "invalid time" unless valid_time?(time) return 'invalid nonce' unless valid_nonce?(nonce) return 'invalid signature' unless verify_signature(signed_string, Base64.decode64(sig), public_key) 'ok' end - def verify_signature(challenge, signature, serialized_pub_key) - public_key = OpenSSL::PKey::RSA.new(serialized_pub_key) + def verify_signature(challenge, signature, public_key) public_key.verify(OpenSSL::Digest::SHA256.new, signature, challenge) end diff --git a/app/models/app_config.rb b/app/models/app_config.rb index f84a0f46cdbfcb919fc97706522181ee9371d546..37d558714b5c92099b3f1171f07abdee320e789e 100644 --- a/app/models/app_config.rb +++ b/app/models/app_config.rb @@ -5,7 +5,11 @@ require 'uri' class AppConfig < Settingslogic - source File.join(Rails.root, "config", "application.yml") + if Rails.env == 'test' + source File.join(Rails.root, "config", "application.yml.example") + else + source File.join(Rails.root, "config", "application.yml") + end namespace Rails.env def self.load! @@ -94,4 +98,4 @@ HELP end return @@pod_uri end -end \ No newline at end of file +end diff --git a/spec/chubbies/Gemfile b/spec/chubbies/Gemfile index 6c1075bdc63f105e1ebbed8374f0e61c663d8f07..e756b9bb8c0b807f379521502908943e5c022cc8 100644 --- a/spec/chubbies/Gemfile +++ b/spec/chubbies/Gemfile @@ -7,5 +7,5 @@ gem 'json' gem 'shotgun' gem 'sqlite3' gem 'activerecord', '3.0.3' -gem 'diaspora-client', :path => "~/work/diaspora-client" +gem 'diaspora-client', :path => "~/workspace/diaspora-client" #:git => 'git@github.com:diaspora/diaspora-client.git' diff --git a/spec/chubbies/Gemfile.lock b/spec/chubbies/Gemfile.lock index 687d76bae0b1da13dcf1a438f06043a51f37353a..b9370ee7c2d6e7eca835f4757bc0089b10f77cb7 100644 --- a/spec/chubbies/Gemfile.lock +++ b/spec/chubbies/Gemfile.lock @@ -1,5 +1,5 @@ PATH - remote: ~/work/diaspora-client + remote: ~/workspace/diaspora-client specs: diaspora-client (0.0.0) activerecord diff --git a/spec/chubbies/chubbies.private.pem b/spec/chubbies/chubbies.private.pem index 13c7a9d51e18a59041e4ed6bc5f52d17e981bde8..de262a185822717c5209f098a8de4cebc07a5d4b 100644 --- a/spec/chubbies/chubbies.private.pem +++ b/spec/chubbies/chubbies.private.pem @@ -1,15 +1,27 @@ -----BEGIN RSA PRIVATE KEY----- -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 -----END RSA PRIVATE KEY----- diff --git a/spec/chubbies/chubbies.public.pem b/spec/chubbies/chubbies.public.pem index d7905d77259efcc1935afcb6bb2af851c08f6b3c..c1f5857b7e3bb7f2033f55eab00c19e110293c5d 100644 --- a/spec/chubbies/chubbies.public.pem +++ b/spec/chubbies/chubbies.public.pem @@ -1,6 +1,8 @@ ------BEGIN PUBLIC KEY----- -MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC6PThqopA0Sv1ZrWp+wKz6SPQw -WzS2IEGRV1eBE2LEvMk5K2MKjZqDF6SeolCPQsDww03qIxbtzXiVFtjBaiDw+fLp -bnX3VcfoMlfV3IKMPjD8eFUE2ke3tJzHeXLfXhHq5ubX1PrXcsNwHeNrtvviv9G2 -BhYMjwi49T0YS27rhwIDAQAB ------END PUBLIC KEY----- +-----BEGIN RSA PUBLIC KEY----- +MIIBCgKCAQEA6YpLa9kYE0Uh/9fiXOFs8i64ZMR3Nyw4o7YB/X6V1QV195CoXoLr +ayFZqDc1N+WTjKurHISIqXsOjOnpHfrbptXri7qXwMyLDAtgSd+NlTWSnJXJlP03 +VrdoUp+dtfKTakhDwBFNrdB+vCAzPve6+6ZEMQZGF+YZBfq7VEPG4iKZQ34C3lZI +fEZlpZQak5tUNWXS5V9uBxAEi1KgoxdQQR3uEctLfQS/QQZ4SNTNVMJsLm6cxHVh +Q5ekXqtpfjM328T8/B+EU4qv+YC2wlHuwL7ztT6/m5rcVtmeunuQVkQueOEZbr6S +6X4du2+4q1/bkmnAS0f28ZcGlnScOz+XqQIDAQAB +-----END RSA PUBLIC KEY----- diff --git a/spec/controllers/authorizations_controller_spec.rb b/spec/controllers/authorizations_controller_spec.rb index c0ca0b3a43a776accfef7ed6a8271ce81bf291bb..a8f1102b3a5a706991b7942398a2ee6f644bd1af 100644 --- a/spec/controllers/authorizations_controller_spec.rb +++ b/spec/controllers/authorizations_controller_spec.rb @@ -5,6 +5,13 @@ require 'spec_helper' describe AuthorizationsController do + RSA = OpenSSL::PKey::RSA + + before :all do + @private_key = RSA.generate(2048) + @public_key = @private_key.public_key + end + before do sign_in :user, alice @controller.stub(:current_user).and_return(alice) @@ -22,11 +29,13 @@ describe AuthorizationsController do "description" => "The best way to chub.", "homepage_url" => "http://chubbi.es/", "icon_url" => "#", - 'public_key' => 'public_key!' - }.to_json + "permissions_overview" => "I will use the permissions this way!", + } + + packaged_manifest = {:public_key => @public_key.export, :jwt => JWT.encode(manifest, @private_key, "RS256")}.to_json stub_request(:get, "http://chubbi.es/manifest.json"). - to_return(:status => 200, :body => manifest, :headers => {}) + to_return(:status => 200, :body => packaged_manifest, :headers => {}) @params_hash = {:type => 'client_associate', :manifest_url => "http://chubbi.es/manifest.json" } end @@ -51,7 +60,11 @@ describe AuthorizationsController do end it 'verifies the signable string validity(time,nonce,sig)' do - @controller.should_receive(:verify).with('signed_string', 'sig', 'public_key!') + @controller.should_receive(:verify){|a,b,c| + a.should == 'signed_string' + b.should == 'sig' + c.export.should == @public_key.export + } post :token, @params_hash.merge!({:signed_string => 'signed_string', :signature => 'sig'}) end end @@ -95,40 +108,44 @@ describe AuthorizationsController do end it 'checks for valid time' do @controller.should_receive(:valid_time?).with(@time.to_i.to_s) - @controller.verify(Base64.encode64(@signable_string), @sig, 'public_key!') + @controller.verify(Base64.encode64(@signable_string), @sig, @public_key) end it 'checks the signature' do - @controller.should_receive(:verify_signature).with(@signable_string, 'sig', 'public_key!') - @controller.verify(Base64.encode64(@signable_string), @sig, 'public_key!') + @controller.should_receive(:verify_signature).with(@signable_string, 'sig', @public_key) + @controller.verify(Base64.encode64(@signable_string), @sig, @public_key) end it 'checks for valid nonce' do @controller.should_receive(:valid_nonce?).with(@nonce) - @controller.verify(Base64.encode64(@signable_string), @sig, 'public_key!') + @controller.verify(Base64.encode64(@signable_string), @sig, @public_key) end it 'checks for public key' do - @controller.verify(Base64.encode64(@signable_string), @sig, '').should == "blank public key" + @controller.verify(Base64.encode64(@signable_string), @sig, RSA.new()).should == "blank public key" + end + + it 'checks key size' do + short_key = RSA.generate(100) + RSA.stub!(:new).and_return(short_key) + @controller.verify(Base64.encode64(@signable_string), @sig, RSA.generate(100).public_key). + should == "key too small, use at least 2048 bits" end end describe '#verify_signature' do before do - @private_key = OpenSSL::PKey::RSA.new(File.read(Rails.root + "spec/chubbies/chubbies.private.pem")) @sig = @private_key.sign(OpenSSL::Digest::SHA256.new, @signable_string) end it 'returns true if the signature is valid' do - @public_key = File.read(Rails.root + "spec/chubbies/chubbies.public.pem") @controller.verify_signature(@signable_string, @sig, @public_key).should be_true end it 'returns false if the signature is invalid' do @signable_string = "something else" - @public_key = File.read(Rails.root + "spec/chubbies/chubbies.public.pem") @controller.verify_signature(@signable_string, @sig, @public_key).should be_false end end diff --git a/spec/models/app_config_spec.rb b/spec/models/app_config_spec.rb index d2f974c5eb8c5f584940c833104ac0ee235dcf5b..9c0762059c96aaa35a48f8b916b8a61fe88332fc 100644 --- a/spec/models/app_config_spec.rb +++ b/spec/models/app_config_spec.rb @@ -142,6 +142,8 @@ describe AppConfig do describe ".pod_uri" do it "properly parses the pod_url" do + AppConfig.pod_uri = nil + AppConfig[:pod_url] = "http://example.org" pod_uri = AppConfig[:pod_uri] pod_uri.scheme.should == "http" pod_uri.host.should == "example.org" @@ -152,7 +154,7 @@ describe AppConfig do describe "when setting pod_url" do context "with a symbol" do it "clears the cached pod_uri" do - AppConfig[:pod_uri].host.should == "example.org" + AppConfig[:pod_uri].host.should_not == "joindiaspora.com" AppConfig[:pod_url] = "http://joindiaspora.com" AppConfig[:pod_uri].host.should == "joindiaspora.com" end @@ -163,7 +165,7 @@ describe AppConfig do end context "with a string" do it "clears the cached pod_uri" do - AppConfig[:pod_uri].host.should == "example.org" + AppConfig[:pod_uri].host.should_not == "joindiaspora.com" AppConfig['pod_url'] = "http://joindiaspora.com" AppConfig[:pod_uri].host.should == "joindiaspora.com" end @@ -174,4 +176,4 @@ describe AppConfig do end end end -end \ No newline at end of file +end