From 2d5d3a2f2daae52f81a543011242fa3c737fb62d Mon Sep 17 00:00:00 2001 From: Raphael <raphael@joindiaspora.com> Date: Thu, 15 Jul 2010 13:29:21 -0700 Subject: [PATCH] commit more often --- app/models/comment.rb | 39 +++++++- app/models/post.rb | 54 ++++------- db/seeds/request.rb | 6 ++ gpg/diaspora-test/pubring.gpg | Bin 37824 -> 38446 bytes gpg/diaspora-test/secring.gpg | Bin 1332 -> 2006 bytes gpg/diaspora-test/trustdb.gpg | Bin 1520 -> 1600 bytes lib/encryptable.rb | 33 +++++++ spec/controllers/publics_controller_spec.rb | 2 +- spec/models/person_spec.rb | 1 + spec/spec_helper.rb | 9 +- spec/user_encryption_spec.rb | 99 +++++++++++++++----- 11 files changed, 173 insertions(+), 70 deletions(-) create mode 100644 db/seeds/request.rb create mode 100644 lib/encryptable.rb diff --git a/app/models/comment.rb b/app/models/comment.rb index b1cdc493b9..67918dd96b 100644 --- a/app/models/comment.rb +++ b/app/models/comment.rb @@ -2,12 +2,13 @@ class Comment include MongoMapper::Document include ROXML include Diaspora::Webhooks - + include Encryptable xml_accessor :text xml_accessor :person, :as => Person xml_accessor :post_id + key :text, String timestamps! @@ -25,10 +26,42 @@ class Comment (self.message == other.message) && (self.person.email == other.person.email) end + #ENCRYPTION - protected + before_validation :sign_if_mine, :sign_if_my_post + validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature} - def send_people_comments_on_my_posts + xml_accessor :creator_signature + key :creator_signature, String + key :post_creator_signature, String + + def signable_accessors + accessors = self.class.roxml_attrs.collect{|definition| + definition.accessor} + accessors.delete 'person' + accessors.delete 'creator_signature' + accessors.delete 'post_creator_signature' + accessors + end + + def signable_string + signable_accessors.collect{|accessor| + (self.send accessor.to_sym).to_s}.join ';' + end + + def verify_post_creator_signature + verify_signature(post_creator_signature, post.person) + end + + + protected + def sign_if_my_post + if self.post.person == User.owner + self.post_creator_signature = sign + end + end + + def send_people_comments_on_my_posts if User.owner.mine?(self.post) && !(self.person.is_a? User) self.push_to(self.post.people_with_permissions) end diff --git a/app/models/post.rb b/app/models/post.rb index a4d710f191..9b711d6ce7 100644 --- a/app/models/post.rb +++ b/app/models/post.rb @@ -4,9 +4,9 @@ class Post include MongoMapper::Document include ROXML include Diaspora::Webhooks + include Encryptable xml_accessor :_id - xml_accessor :owner_signature xml_accessor :person, :as => Person key :person_id, ObjectId @@ -44,45 +44,27 @@ class Post end #ENCRYPTION - before_validation :sign_if_mine - validates_true_for :owner_signature, :logic => lambda {self.verify_signature} - - key :owner_signature, String - - def signable_accessors - accessors = self.class.roxml_attrs.collect{|definition| - definition.accessor} - accessors.delete 'person' - accessors.delete 'owner_signature' - accessors - end - - def signable_string - signable_accessors.collect{|accessor| - (self.send accessor.to_sym).to_s}.join ';' - end + validates_true_for :creator_signature, :logic => lambda {self.verify_creator_signature} + + xml_accessor :creator_signature + key :creator_signature, String + + def signable_accessors + accessors = self.class.roxml_attrs.collect{|definition| + definition.accessor} + accessors.delete 'person' + accessors.delete 'creator_signature' + accessors + end - def verify_signature - return false unless owner_signature && person.key_fingerprint - validity = nil - GPGME::verify(owner_signature, signable_string, - {:armor => true, :always_trust => true}){ |signature| - validity = signature.status == GPGME::GPG_ERR_NO_ERROR && - signature.fpr == person.key_fingerprint - } - return validity - end - - protected - def sign_if_mine - if self.person == User.owner - self.owner_signature = GPGME::sign(signable_string,nil, - {:armor=> true, :mode => GPGME::SIG_MODE_DETACH}) + def signable_string + signable_accessors.collect{|accessor| + (self.send accessor.to_sym).to_s}.join ';' end - end - def destroy_comments +protected + def destroy_comments comments.each{|c| c.destroy} end diff --git a/db/seeds/request.rb b/db/seeds/request.rb new file mode 100644 index 0000000000..b0c652ca85 --- /dev/null +++ b/db/seeds/request.rb @@ -0,0 +1,6 @@ + +require 'config/environment' + +Request.all.each{|r| + User.owner.accept_friend_request(r.id) +} diff --git a/gpg/diaspora-test/pubring.gpg b/gpg/diaspora-test/pubring.gpg index 46e8a37d1e84b145278442b92bfe4314e1562434..6949770abe15219a8dcf14b912cd2644bb33bfae 100644 GIT binary patch delta 587 zcmV-R0<`_Wrvk350<gf7f0*I~Og=t>5dr|0qY0$kdxdzTE6fSs<V%@j{w)?B!y-P* za$lg@`d#De9D{5d&Rn~FWH-s4#biak1dDwWGx-9CZ<z-CsBl97pwXl6S>(WcMRqa| zALLYdZ%#zKSpoh(mgvSaG5%;4GrrfXJv6VQN=0)e)bVb`G<U#Ie_L{Go7p#=g+<KI zHre-}^_4)pGMfI`J4IjNXEVf#Se)#A0sIeX0XbS^1fD(f+Ejo=0Aus^2cuPN`3E#& zdU01dM)|yGQLjvemdExQ;HagQapl}Ohr-^vyDb=N^j<11Rb;e6Q)OdsZe$=va%p95 zWFRPLbaZe!FE3<i8gq1EZggdGEoFFNZE$R5E@N+PFDW2AWo&bkK#m&&K0bnzzzHCK zqFix^H1BqmfI|SFffQ5bJU@`~KDWd8Za%D15w%100G=yflUwy`3ruLTL3)z>#vFzz zxQnm?00X#<1WZ0Yf)D}#!5w|QHp|6JRj3MAdABt04O&k#*sJn<L#h|CjHoQC^o3NP z+|Vke1F7u=SOSw}0&bdsY9+%f{t9(}vmm_9g8%~s0sb&~>Jp@W#o*8tYqV#i`x3Ah zmm01}y)Z|ilU2w>^jTjcv+(O82+6<SG6<OslP5SIZ`@a58J=>_dd2bBVE%|n1Q-zl z00{*GOg=t>0vikf3JDORTycmr?{<}H0|1|0O;rypspQg~Zy<YMA-#6DG_9W+0HC1q Z3RkT}oAQf(M*6E$yIWOPz-O=m00VWo2HgMv delta 9 RcmZ3thUvg^rVR%s0{|C;1jzsZ diff --git a/gpg/diaspora-test/secring.gpg b/gpg/diaspora-test/secring.gpg index 81164ee0e2175f201621b3d36808fc614a4e2428..9f945d3f1e68aac39851a98abd25127a806880bd 100644 GIT binary patch delta 659 zcmV;E0&M-X3f2#>GzEW@`vgorK7tVf0GFc)q}+Rjc%v)K3E$*PnPdJf79PVQKFe}n zpxXLf<LexQY#Yv8yM1Ig$)3ezMZN@!eG@bJ0*7yz2K=aSLja)BqwiVdz<fn^G7lf* zRC#YsM7&u6{y&!J#xpVgXcjZR*Q`A>ucJyub0yUAZpAcrz)*i%a&4R0H=Tt=%+EI2 z_n`HaK)f=V{@FW4U*Tsn#EMv)?0o_J4`~58T4V&CJ@eXBfJFdf^Y#a$Rc!eOG-7&j zS2;%cyl7FcOof)m_8Q=*rIm5z+&PEB-nzRj7;E%iDlS!I005pWY^j{;f+MpPB~s;} z+`1oUf%M)BJ+x6mQ)OdsZe$=va%p95WFRPLbaZe!FE3<ib97;DbY*faWq4t2aBO8R zV{dIQDIh#$Y;$FIXk~I`KxJ%mWiDfHZ9a%%1QQVg03rnfOg=t>li&j&f1+G*h&1nZ zm4HJ4pn()q<~%=;@;<l2_-;O|QW3R7^#GnLUz1z)YYR+hvO#*1{Kg!HDY%QU0ssJ< zs02(tK7tSe0Kpx7y*A6mOI4@}S9!NI?+sc{GuW&0d_$@iv5crJs`Q0apWM(Yr30z$ z1y}-;Wdd%RfNCYfEB*>~f3qOG&4T~~1p)prdFm3Re#PL>6>GF-r27)E7nd5YNWCye zp_5g}MD$r-BeU@9A_&R9-!cf94U;E0A8*`OVHuus&w9o2*kJwu0I<VplR-i1Q8KU| zRIUtdx+upu<lY?13o(dE1Q-zl00{*GOg=t>0vikf3JDORTycmrHScznY6AeCGlKBj t91<_~e$6eBBNMFl2Ch*d0G=qQyaCj?7?`a0p;!n(q;h(qyGO7B006xAAsGMw delta 7 Ocmcb{zlCdq2`c~$WCD!< diff --git a/gpg/diaspora-test/trustdb.gpg b/gpg/diaspora-test/trustdb.gpg index 45e0c76adf3c9bab923cb7a571bcdc1d64ff4598..1fec81fc8c39a371e7de456d93e66eb9dd3172ee 100644 GIT binary patch delta 119 zcmeyseSk-RF})z2nVFH5k%581$Ifo`#6a<l>TZmTY7+yMHcwzoU<u%1@aTz{@_gf5 z*%SLXLKnppc9^^`o5}`M4+QEE3PkcU)c@0EI#H98;(YY!!F``5^UFpYR)wlVC}RKs DxWyh- delta 36 scmX@W^MPA{F})z2nVFH5k%581$7cDliGku9)!i5;o^{x~meH970JIAVcK`qY diff --git a/lib/encryptable.rb b/lib/encryptable.rb new file mode 100644 index 0000000000..10a9ac39c0 --- /dev/null +++ b/lib/encryptable.rb @@ -0,0 +1,33 @@ + module Encryptable + def signable_string + "" + end + def verify_creator_signature + verify_signature(creator_signature, person) + end + + def verify_signature(signature, person) + return false unless signature && person.key_fingerprint + validity = nil + GPGME::verify(creator_signature, signable_string, + {:armor => true, :always_trust => true}){ |signature| + puts signature + validity = signature.status == GPGME::GPG_ERR_NO_ERROR && + signature.fpr == person.key_fingerprint + } + return validity + end + + protected + def sign_if_mine + if self.person == User.owner + self.creator_signature = sign + end + end + + def sign + GPGME::sign(signable_string,nil, + {:armor=> true, :mode => GPGME::SIG_MODE_DETACH, :signers => [User.owner.key]}) + end + end + diff --git a/spec/controllers/publics_controller_spec.rb b/spec/controllers/publics_controller_spec.rb index e9539b4641..be297a64fa 100644 --- a/spec/controllers/publics_controller_spec.rb +++ b/spec/controllers/publics_controller_spec.rb @@ -4,7 +4,7 @@ describe PublicsController do render_views before do - @user = Factory.create(:user, :profile => Profile.create( :first_name => "bob", :last_name => "smith")) + @user = Factory.create(:user, :profile => Profile.new( :first_name => "bob", :last_name => "smith")) request.env['warden'] = mock_model(Warden, :authenticate? => @user, :authenticate! => @user, :authenticate => @user) end diff --git a/spec/models/person_spec.rb b/spec/models/person_spec.rb index a882b9849f..72cad89ace 100644 --- a/spec/models/person_spec.rb +++ b/spec/models/person_spec.rb @@ -65,6 +65,7 @@ describe Person do Person.friends.all.count.should == 1 u.unfriend(f.id) Person.friends.all.count.should == 0 + Person.all.count.should == 1 end end diff --git a/spec/spec_helper.rb b/spec/spec_helper.rb index 7273c0d282..79412d92d4 100644 --- a/spec/spec_helper.rb +++ b/spec/spec_helper.rb @@ -42,10 +42,11 @@ end end def stub_signature_verification - Post.any_instance.stubs(:verify_signature).returns(true) - StatusMessage.any_instance.stubs(:verify_signature).returns(true) - Blog.any_instance.stubs(:verify_signature).returns(true) - Bookmark.any_instance.stubs(:verify_signature).returns(true) + Post.any_instance.stubs(:verify_creator_signature).returns(true) + StatusMessage.any_instance.stubs(:verify_creator_signature).returns(true) + Blog.any_instance.stubs(:verify_creator_signature).returns(true) + Bookmark.any_instance.stubs(:verify_creator_signature).returns(true) + Comment.any_instance.stubs(:verify_creator_signature).returns(true) end def unstub_mocha_stubs diff --git a/spec/user_encryption_spec.rb b/spec/user_encryption_spec.rb index af4fcfc4e3..63f4785c9c 100644 --- a/spec/user_encryption_spec.rb +++ b/spec/user_encryption_spec.rb @@ -10,17 +10,21 @@ describe 'user encryption' do end before do unstub_mocha_stubs - @u = Factory.create(:user) - @u.send(:assign_key) - @u.save + @user = Factory.create(:user) + @user.send(:assign_key) + @user.save @person = Factory.create(:person, :key_fingerprint => GPGME.list_keys("Remote Friend").first.subkeys.first.fpr, :profile => Profile.new(:first_name => 'Remote', :last_name => 'Friend'), :email => 'somewhere@else.com', - :url => 'http://distant-example.com/', - :key_fingerprint => '57F553EE2C230991566B7C60D3638485F3960087') - + :url => 'http://distant-example.com/') + @person2 = Factory.create(:person, + :key_fingerprint => GPGME.list_keys("Second Friend").first.subkeys.first.fpr, + :profile => Profile.new(:first_name => 'Second', + :last_name => 'Friend'), + :email => 'elsewhere@else.com', + :url => 'http://distanter-example.com/') end after do @@ -44,18 +48,18 @@ describe 'user encryption' do end it 'should have a key fingerprint' do - @u.key_fingerprint.should_not be nil + @user.key_fingerprint.should_not be nil end it 'should retrieve a user key' do - @u.key.subkeys[0].fpr.should == @u.key_fingerprint + @user.key.subkeys[0].fpr.should == @user.key_fingerprint end describe 'key exchange on friending' do it 'should send over a public key' do Comment.send(:class_variable_get, :@@queue).stub!(:add_post_request) - request = @u.send_friend_request_to("http://example.com/") - Request.build_xml_for([request]).include?( @u.export_key).should be true + request = @user.send_friend_request_to("http://example.com/") + Request.build_xml_for([request]).include?( @user.export_key).should be true end it 'should receive and marshal a public key from a request' do @@ -70,8 +74,9 @@ describe 'user encryption' do xml = Request.build_xml_for [request] person.destroy + personcount = Person.all.count store_objects_from_xml(xml) - Person.all.count.should == 3 + Person.all.count.should == personcount + 1 new_person = Person.first(:url => "http://test.url/") new_person.key_fingerprint.nil?.should == false new_person.id.should == id @@ -83,54 +88,54 @@ describe 'user encryption' do describe 'signing and verifying' do it 'should sign a message on create' do - message = Factory.create(:status_message, :person => @u) - message.verify_signature.should be true + message = Factory.create(:status_message, :person => @user) + message.verify_creator_signature.should be true end it 'should not be able to verify a message from a person without a key' do person = Factory.create(:person, :key_fingerprint => "123") message = Factory.build(:status_message, :person => person) message.save(:validate => false) - message.verify_signature.should be false + message.verify_creator_signature.should be false end it 'should verify a remote signature' do message = Factory.build(:status_message, :person => @person) - message.owner_signature = GPGME.sign(message.signable_string, nil, + message.creator_signature = GPGME.sign(message.signable_string, nil, {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person.key]}) message.save(:validate => false) - message.verify_signature.should be true + message.verify_creator_signature.should be true end it 'should know if the signature is from the wrong person' do message = Factory.build(:status_message, :person => @person) message.save(:validate => false) - message.owner_signature = GPGME.sign(message.signable_string, nil, + message.creator_signature = GPGME.sign(message.signable_string, nil, {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person.key]}) - message.person = @u - message.verify_signature.should be false + message.person = @user + message.verify_creator_signature.should be false end it 'should know if the signature is for the wrong text' do message = Factory.build(:status_message, :person => @person) - message.owner_signature = GPGME.sign(message.signable_string, nil, + message.creator_signature = GPGME.sign(message.signable_string, nil, {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person.key]}) message.message = 'I love VENISON' message.save(:validate => false) - message.verify_signature.should be false + message.verify_creator_signature.should be false end end describe 'sending and recieving signatures' do it 'should contain the signature in the xml' do - message = Factory.create(:status_message, :person => @u) + message = Factory.create(:status_message, :person => @user) xml = message.to_xml.to_s - xml.include?(message.owner_signature).should be true + xml.include?(message.creator_signature).should be true end - it 'the signature should be verified on marshaling' do + it 'A message with an invalid signature should be rejected' do message = Factory.build(:status_message, :person => @person) - message.owner_signature = GPGME.sign(message.signable_string, nil, - {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@u.key]}) + message.creator_signature = GPGME.sign(message.signable_string, nil, + {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@user.key]}) message.save xml = Post.build_xml_for([message]) message.destroy @@ -140,4 +145,46 @@ describe 'user encryption' do end end + describe 'comments' do + before do + @remote_message = Factory.build(:status_message, :person => @person) + @remote_message.creator_signature = GPGME.sign(@remote_message.signable_string, nil, + {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person.key]}) + @remote_message.save + + end + it 'should attach the creator signature if the user is commenting' do + @user.comment "Yeah, it was great", :on => @remote_message + @remote_message.comments.first.verify_creator_signature.should be true + end + + it 'should sign the comment if the user is the post creator' do + message = Factory.create(:status_message, :person => @user) + @user.comment "Yeah, it was great", :on => message + StatusMessage.first.comments.first.verify_creator_signature.should be true + StatusMessage.first.comments.first.verify_post_creator_signature.should be true + end + + it 'should verify a comment made on a remote post by a different friend' do + comment = Comment.new(:person => @person2, :text => "balls", :post => @remote_message) + comment.creator_signature = GPGME.sign(@remote_message.signable_string, nil, + {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person2.key]}) + comment.verify_creator_signature.should be true + + end + + it 'should reject comments on a remote post with only a creator sig' do + comment = Comment.new(:person => @person2, :text => "balls", :post => @remote_message) + comment.creator_signature = GPGME.sign(@remote_message.signable_string, nil, + {:mode => GPGME::SIG_MODE_DETACH, :armor => true, :signers => [@person2.key]}) + comment.verify_creator_signature.should be true + comment.verify_post_creator_signature.should be false + comment.save.should be false + end + + it 'should receive remote comments on a user post with a creator sig' do + + end + + end end -- GitLab