From 0c3a5b8565fb7148714696eedd3d5adf4fc68641 Mon Sep 17 00:00:00 2001 From: pdp8 Date: Fri, 9 Jun 2023 20:59:20 +0200 Subject: wait for following accept, verify! helper --- activitypub.rb | 91 ++++++++++++++++++++++++---------------------------------- 1 file changed, 38 insertions(+), 53 deletions(-) diff --git a/activitypub.rb b/activitypub.rb index ba763e3..9a57008 100644 --- a/activitypub.rb +++ b/activitypub.rb @@ -61,6 +61,14 @@ post "/inbox" do # server-server end end + when "Accept" + o = action["object"] + case o["type"] + when "Follow" + File.open(File.join("public","following",mention(o['object'])+".json"),"w+"){|f| f.puts o.to_json} + end + #when "Announce" + else p "Unknown action: #{action['type']}" p body @@ -133,14 +141,12 @@ post "/follow/*" do protected! mention = params['splat'][0] actor = actor(mention) - following_path = File.join("public", "following", mention + ".json") follow = { "@context" => "https://www.w3.org/ns/activitystreams", - "id" => File.join(SOCIAL_URL, following_path), + "id" => File.join(SOCIAL_URL, "following", mention + ".json"), "type" => "Follow", "actor" => ACTOR, "object" => actor } send_signed follow, actor - File.open(following_path, "w+") { |f| f.puts follow.to_json } redirect to("/") end @@ -199,30 +205,36 @@ helpers do def verify! # https://github.com/mastodon/mastodon/blob/main/app/controllers/concerns/signature_verification.rb # TODO verify digest - signature_params = {} - request.env["HTTP_SIGNATURE"].split(',').each do |pair| - k, v = pair.split('=') - signature_params[k] = v.gsub('"', '') - end - - key_id = signature_params['keyId'] - headers = signature_params['headers'] - signature = Base64.decode64(signature_params['signature']) - - actor = fetch key_id - key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem']) - - comparison = headers.split(' ').map do |signed_params_name| - if signed_params_name == '(request-target)' - '(request-target): post /inbox' - elsif signed_params_name == 'content-type' - "#{signed_params_name}: #{request.env["CONTENT_TYPE"]}" - else - "#{signed_params_name}: #{request.env["HTTP_" + signed_params_name.upcase]}" + begin + signature_params = {} + request.env["HTTP_SIGNATURE"].split(',').each do |pair| + k, v = pair.split('=') + signature_params[k] = v.gsub('"', '') end - end.join("\n") - halt 400 unless key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison) + key_id = signature_params['keyId'] + headers = signature_params['headers'] + signature = Base64.decode64(signature_params['signature']) + + actor = fetch key_id + key = OpenSSL::PKey::RSA.new(actor['publicKey']['publicKeyPem']) + + comparison = headers.split(' ').map do |signed_params_name| + if signed_params_name == '(request-target)' + '(request-target): post /inbox' + elsif signed_params_name == 'content-type' + "#{signed_params_name}: #{request.env["CONTENT_TYPE"]}" + else + "#{signed_params_name}: #{request.env["HTTP_" + signed_params_name.upcase]}" + end + end.join("\n") + + halt 400 unless key.verify(OpenSSL::Digest.new('SHA256'), signature, comparison) + rescue => e + p request.env["HTTP_SIGNATURE"] + p e + halt 400 + end end end @@ -337,9 +349,7 @@ end def mention actor people = File.read('inbox/people.tsv').split("\n").collect {|l| l.chomp.split("\t")} person = people.select{|p| p[1] == actor} - #p person if person.empty? - #p actor mention = "#{fetch(actor)["preferredUsername"]}@#{URI(actor).host}" File.open('inbox/people.tsv','a'){|f| f.puts "#{mention}\t#{actor}"} mention @@ -358,7 +368,6 @@ def actor mention end def fetch url, accept = 'application/ld+json; profile="https://www.w3.org/ns/activitystreams"', limit = 10 - p url uri = URI(url) http = Net::HTTP.new(uri.host, uri.port) http.use_ssl = true @@ -400,33 +409,9 @@ def send_signed object, url signature = Base64.strict_encode64(keypair.sign(OpenSSL::Digest.new('SHA256'), signed_string)) signed_header = 'keyId="' + ACTOR + '#main-key",algorithm="rsa-sha256",headers="(request-target) host date digest content-type",signature="' + signature + '"' -=begin - uri = URI.parse(fetch(url)["inbox"]) - http = Net::HTTP.new(uri.host, uri.port) - http.use_ssl = true - header = { - 'Content-Type' => 'application/activity+json', - 'Host' => uri.host, - 'Date' => date, - 'Digest' => digest, - 'Signature' => signed_header, - } - request = Net::HTTP::Post.new(uri.request_uri, header) - request.body = body - - p uri, body - http.request(request) - puts "/run/current-system/sw/bin/curl -X POST -H 'Content-Type: application/activity+json' -H 'Host: #{uri.host}' -H 'Date: #{date}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}' #{url}" -=end - `/run/current-system/sw/bin/curl -X POST -H 'Content-Type: application/activity+json' -H 'Host: #{uri.host}' -H 'Date: #{date}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}' #{url}` + puts `/run/current-system/sw/bin/curl -i -X POST -H 'Content-Type: application/activity+json' -H 'Host: #{uri.host}' -H 'Date: #{date}' -H 'Digest: #{digest}' -H 'Signature: #{signed_header}' -d '#{body}' #{fetch(url)['inbox']}` end def inbox uri URI(fetch(uri)["inbox"]).request_uri end - -def verify_signature env - #rescue - #false - #end -end -- cgit v1.2.3