updated salmon to let us not always encrypt the header
This commit is contained in:
parent
5ae96efdf6
commit
6b0507949c
7 changed files with 73 additions and 115 deletions
|
|
@ -4,12 +4,14 @@
|
|||
|
||||
class PublicsController < ApplicationController
|
||||
require File.join(Rails.root, '/lib/diaspora/parser')
|
||||
require File.join(Rails.root, '/lib/postzord/receiver/public')
|
||||
include Diaspora::Parser
|
||||
|
||||
skip_before_filter :set_header_data
|
||||
skip_before_filter :which_action_and_user
|
||||
skip_before_filter :set_grammatical_gender
|
||||
before_filter :allow_cross_origin, :only => [:hcard, :host_meta, :webfinger]
|
||||
before_filter :check_for_xml, :only => [:receive, :receive_public]
|
||||
|
||||
respond_to :html
|
||||
respond_to :xml, :only => :post
|
||||
|
|
@ -47,12 +49,12 @@ class PublicsController < ApplicationController
|
|||
render :text => params['hub.challenge'], :status => 202, :layout => false
|
||||
end
|
||||
|
||||
def receive
|
||||
if params[:xml].nil?
|
||||
render :nothing => true, :status => 422
|
||||
return
|
||||
end
|
||||
def receive_public
|
||||
Postzord::Receiver::Public.new(params[:xml])
|
||||
render :nothing => true, :status => :ok
|
||||
end
|
||||
|
||||
def receive
|
||||
person = Person.where(:guid => params[:guid]).first
|
||||
|
||||
if person.nil? || person.owner_id.nil?
|
||||
|
|
@ -66,4 +68,15 @@ class PublicsController < ApplicationController
|
|||
|
||||
render :nothing => true, :status => 202
|
||||
end
|
||||
|
||||
|
||||
private
|
||||
|
||||
def check_for_xml
|
||||
if params[:xml].nil?
|
||||
render :nothing => true, :status => 422
|
||||
return
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
|
|
|||
|
|
@ -102,7 +102,7 @@ class Post < ActiveRecord::Base
|
|||
return local_post
|
||||
end
|
||||
elsif !local_post
|
||||
if self.save
|
||||
if self.save
|
||||
user.contact_for(person).receive_post(self)
|
||||
user.notify_if_mentioned(self)
|
||||
Rails.logger.info("event=receive payload_type=#{self.class} update=false status=complete sender=#{self.diaspora_handle}")
|
||||
|
|
|
|||
|
|
@ -122,6 +122,7 @@ Diaspora::Application.routes.draw do
|
|||
get 'hcard/users/:guid' => :hcard
|
||||
get '.well-known/host-meta' => :host_meta
|
||||
post 'receive/users/:guid' => :receive
|
||||
post 'receive/public' => :receive_public
|
||||
get 'hub' => :hub
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -83,7 +83,7 @@ ActiveRecord::Schema.define(:version => 20110911213207) do
|
|||
t.datetime "updated_at"
|
||||
end
|
||||
|
||||
add_index "conversation_visibilities", ["conversation_id", "person_id"], :name => "index_conversation_visibilities_usefully", :unique => true
|
||||
add_index "conversation_visibilities", ["conversation_id", "person_id"], :name => "index_conversation_visibilities_on_conversation_id_and_person_id", :unique => true
|
||||
add_index "conversation_visibilities", ["conversation_id"], :name => "index_conversation_visibilities_on_conversation_id"
|
||||
add_index "conversation_visibilities", ["person_id"], :name => "index_conversation_visibilities_on_person_id"
|
||||
|
||||
|
|
|
|||
|
|
@ -54,37 +54,47 @@ module Salmon
|
|||
salmon
|
||||
end
|
||||
|
||||
def self.parse(xml, user)
|
||||
def self.parse(xml, user=nil)
|
||||
slap = self.new
|
||||
doc = Nokogiri::XML(xml)
|
||||
|
||||
sig_doc = doc.search('entry')
|
||||
|
||||
### Header ##
|
||||
decrypted_header = user.decrypt(doc.search('encrypted_header').text)
|
||||
header_doc = Nokogiri::XML(decrypted_header)
|
||||
header_doc = slap.salmon_header(doc, user)
|
||||
slap.author_email= header_doc.search('uri').text.split("acct:").last
|
||||
slap.aes_key = header_doc.search('aes_key').text
|
||||
slap.iv = header_doc.search('iv').text
|
||||
|
||||
slap.magic_sig = MagicSigEnvelope.parse sig_doc
|
||||
|
||||
if 'base64url' == slap.magic_sig.encoding
|
||||
|
||||
key_hash = {'key' => slap.aes_key, 'iv' => slap.iv}
|
||||
slap.parsed_data = user.aes_decrypt(decode64url(slap.magic_sig.data), key_hash)
|
||||
slap.sig = slap.magic_sig.sig
|
||||
else
|
||||
raise ArgumentError, "Magic Signature data must be encoded with base64url, was #{slap.magic_sig.encoding}"
|
||||
end
|
||||
|
||||
key_hash = {'key' => slap.aes_key, 'iv' => slap.iv}
|
||||
slap.parsed_data = slap.parse_data(key_hash, user)
|
||||
slap.sig = slap.magic_sig.sig
|
||||
slap.data_type = slap.magic_sig.data_type
|
||||
|
||||
raise ArgumentError, "Magic Signature data must be signed with RSA-SHA256, was #{slap.magic_sig.alg}" unless 'RSA-SHA256' == slap.magic_sig.alg
|
||||
|
||||
slap
|
||||
end
|
||||
|
||||
def parse_data(key_hash, user)
|
||||
data = SalmonSlap.decode64url(self.magic_sig.data)
|
||||
if user.present?
|
||||
user.aes_decrypt(data, key_hash)
|
||||
else
|
||||
data
|
||||
end
|
||||
end
|
||||
|
||||
# @return [Nokogiri::Doc]
|
||||
def salmon_header(doc, user)
|
||||
if user.present?
|
||||
decrypted_header = user.decrypt(doc.search('encrypted_header').text)
|
||||
Nokogiri::XML(decrypted_header)
|
||||
else
|
||||
doc.search('header')
|
||||
end
|
||||
end
|
||||
|
||||
def xml_for person
|
||||
xml =<<ENTRY
|
||||
<?xml version='1.0' encoding='UTF-8'?>
|
||||
|
|
@ -190,10 +200,20 @@ HEADER
|
|||
env = self.new
|
||||
ns = {'me'=>'http://salmon-protocol.org/ns/magic-env'}
|
||||
env.encoding = doc.search('//me:env/me:encoding', ns).text.strip
|
||||
|
||||
if env.encoding != 'base64url'
|
||||
raise ArgumentError, "Magic Signature data must be encoded with base64url, was #{slap.magic_sig.encoding}"
|
||||
end
|
||||
|
||||
env.data = doc.search('//me:env/me:data', ns).text
|
||||
env.alg = doc.search('//me:env/me:alg', ns).text.strip
|
||||
env.sig = doc.search('//me:env/me:sig', ns).text
|
||||
env.data_type = doc.search('//me:env/me:data', ns).first['type'].strip
|
||||
|
||||
unless 'RSA-SHA256' == env.alg
|
||||
raise ArgumentError, "Magic Signature data must be signed with RSA-SHA256, was #{env.alg}"
|
||||
end
|
||||
|
||||
env
|
||||
end
|
||||
|
||||
|
|
|
|||
|
|
@ -20,6 +20,24 @@ describe PublicsController do
|
|||
end
|
||||
end
|
||||
|
||||
describe '#receive_public' do
|
||||
it 'succeeds' do
|
||||
post :receive_public, :xml => "<stuff/>"
|
||||
response.should be_success
|
||||
end
|
||||
|
||||
it 'returns a 422 if no xml is passed' do
|
||||
post :receive_public
|
||||
response.code.should == '422'
|
||||
end
|
||||
|
||||
it 'calls Postzord::Receiver:Public' do
|
||||
xml = "stuff"
|
||||
Postzord::Receiver::Public.should_receive(:new).with(xml)
|
||||
post :receive_public, :xml => xml
|
||||
end
|
||||
end
|
||||
|
||||
describe '#receive' do
|
||||
let(:xml) { "<walruses></walruses>" }
|
||||
|
||||
|
|
|
|||
|
|
@ -1,94 +0,0 @@
|
|||
# Copyright (c) 2010, Diaspora Inc. This file is
|
||||
# licensed under the Affero General Public License version 3 or later. See
|
||||
# the COPYRIGHT file.
|
||||
|
||||
require 'spec_helper'
|
||||
|
||||
describe Salmon do
|
||||
let(:user){alice}
|
||||
let(:user2) {eve}
|
||||
let(:user3) {Factory.create(:user)}
|
||||
let(:post){ user.post :status_message, :text => "hi", :to => user.aspects.create(:name => "sdg").id }
|
||||
|
||||
let!(:created_salmon) {Salmon::SalmonSlap.create(user, post.to_diaspora_xml)}
|
||||
|
||||
describe '#create' do
|
||||
|
||||
it 'has data in the magic envelope' do
|
||||
created_salmon.magic_sig.data.should_not be nil
|
||||
end
|
||||
|
||||
it 'has no parsed_data' do
|
||||
created_salmon.parsed_data.should be nil
|
||||
end
|
||||
|
||||
it 'sets aes and iv key' do
|
||||
created_salmon.aes_key.should_not be nil
|
||||
created_salmon.iv.should_not be nil
|
||||
end
|
||||
|
||||
it 'makes the data in the signature encrypted with that key' do
|
||||
key_hash = {'key' => created_salmon.aes_key, 'iv' => created_salmon.iv}
|
||||
decoded_string = Salmon::SalmonSlap.decode64url(created_salmon.magic_sig.data)
|
||||
user.aes_decrypt(decoded_string, key_hash).should == post.to_diaspora_xml
|
||||
end
|
||||
end
|
||||
|
||||
describe '#xml_for' do
|
||||
let(:xml) {created_salmon.xml_for user2.person}
|
||||
|
||||
it 'has a encrypted header field' do
|
||||
xml.include?("encrypted_header").should be true
|
||||
end
|
||||
|
||||
it 'the encrypted_header field should contain the aes key' do
|
||||
doc = Nokogiri::XML(xml)
|
||||
decrypted_header = user2.decrypt(doc.search('encrypted_header').text)
|
||||
decrypted_header.include?(created_salmon.aes_key).should be true
|
||||
end
|
||||
end
|
||||
|
||||
context 'marshaling' do
|
||||
let(:xml) {created_salmon.xml_for user2.person}
|
||||
let(:parsed_salmon) { Salmon::SalmonSlap.parse(xml, user2)}
|
||||
|
||||
it 'should parse out the aes key' do
|
||||
parsed_salmon.aes_key.should == created_salmon.aes_key
|
||||
end
|
||||
|
||||
it 'should parse out the iv' do
|
||||
parsed_salmon.iv.should == created_salmon.iv
|
||||
end
|
||||
it 'should parse out the authors diaspora_handle' do
|
||||
parsed_salmon.author_email.should == user.person.diaspora_handle
|
||||
|
||||
end
|
||||
|
||||
describe '#author' do
|
||||
it 'should reference a local author' do
|
||||
parsed_salmon.author.should == user.person
|
||||
end
|
||||
|
||||
it 'should fail if no author is found' do
|
||||
parsed_salmon.author_email = 'tom@tom.joindiaspora.com'
|
||||
|
||||
|
||||
proc {parsed_salmon.author.public_key}.should raise_error "did you remember to async webfinger?"
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
it 'verifies the signature for the sender' do
|
||||
parsed_salmon.verified_for_key?(user.public_key).should be true
|
||||
end
|
||||
|
||||
it 'contains the original data' do
|
||||
parsed_salmon.parsed_data.should == post.to_diaspora_xml
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
|
||||
end
|
||||
Loading…
Reference in a new issue