Better error response to malformed headers (#35278)
This commit is contained in:
		@@ -64,6 +64,9 @@ module SignatureVerification
 | 
			
		||||
    return (@signed_request_actor = actor) if signed_request.verified?(actor)
 | 
			
		||||
 | 
			
		||||
    fail_with! "Verification failed for #{actor.to_log_human_identifier} #{actor.uri}"
 | 
			
		||||
  rescue Mastodon::MalformedHeaderError => e
 | 
			
		||||
    @signature_verification_failure_code = 400
 | 
			
		||||
    fail_with! e.message
 | 
			
		||||
  rescue Mastodon::SignatureVerificationError => e
 | 
			
		||||
    fail_with! e.message
 | 
			
		||||
  rescue *Mastodon::HTTP_CONNECTION_ERRORS => e
 | 
			
		||||
 
 | 
			
		||||
@@ -196,6 +196,8 @@ class SignedRequest
 | 
			
		||||
      return if body_digest == received_digest
 | 
			
		||||
 | 
			
		||||
      raise Mastodon::SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{received_digest}"
 | 
			
		||||
    rescue Starry::ParseError
 | 
			
		||||
      raise Mastodon::MalformedHeaderError, 'Content-Digest could not be parsed. It does not contain a valid RFC8941 dictionary.'
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    def created_time
 | 
			
		||||
 
 | 
			
		||||
@@ -13,6 +13,7 @@ module Mastodon
 | 
			
		||||
  class SyntaxError < Error; end
 | 
			
		||||
  class InvalidParameterError < Error; end
 | 
			
		||||
  class SignatureVerificationError < Error; end
 | 
			
		||||
  class MalformedHeaderError < Error; end
 | 
			
		||||
 | 
			
		||||
  class UnexpectedResponseError < Error
 | 
			
		||||
    attr_reader :response
 | 
			
		||||
 
 | 
			
		||||
@@ -621,6 +621,30 @@ RSpec.describe 'signature verification concern' do
 | 
			
		||||
          )
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
 | 
			
		||||
      context 'with a malformed `Content-Digest` header' do
 | 
			
		||||
        let(:digest_header) { 'SHA-256=:ZOyIygCyaOW6GjVnihtTFtIS9PNmskdyMlNKiuyjfzw=:' }
 | 
			
		||||
        let(:signature_input) do
 | 
			
		||||
          'sig1=("@method" "@target-uri" "content-digest");created=1703066400;keyid="https://remote.domain/users/bob#main-key"'
 | 
			
		||||
        end
 | 
			
		||||
        let(:signature_header) do
 | 
			
		||||
          'sig1=:aXua24cIlBi8akNXg/Vc5pU8fNGXo0f4U2qQk42iWoIaCcH3G+z2edPMQTNM/aZmD0bULqvb/yi6ZXgRls1ereq3OqnvA4JBLKx15O/jLayS/FhR4d/2vaeXuBOYXM7EGXItKkFxEXn3J+FCQPb5wY31GlbljrESjsiZ6gtrSmwryBluQCwMJ59LACzocxbWo42Kv3cpSig2aCu9CYXKC4sCH3eSKjwPtjdlpmX1VkYX5ge+JaZMn7A218ZgZOc9xpPawESOuIF9axcKW5PDEhOwmswFd2G65c8H9kJY6zEnqbArP9lRQMmjuAb011NILClaaRZOOupz2HZUdm+91Q==:' # rubocop:disable Layout/LineLength
 | 
			
		||||
        end
 | 
			
		||||
 | 
			
		||||
        it 'returns `400` (Bad Request)', :aggregate_failures do
 | 
			
		||||
          post '/activitypub/signature_required', params: 'Hello world', headers: {
 | 
			
		||||
            'Host' => 'www.example.com',
 | 
			
		||||
            'Content-Digest' => digest_header,
 | 
			
		||||
            'Signature-Input' => signature_input,
 | 
			
		||||
            'Signature' => signature_header,
 | 
			
		||||
          }
 | 
			
		||||
 | 
			
		||||
          expect(response).to have_http_status(400)
 | 
			
		||||
          expect(response.parsed_body).to match(
 | 
			
		||||
            error: 'Content-Digest could not be parsed. It does not contain a valid RFC8941 dictionary.'
 | 
			
		||||
          )
 | 
			
		||||
        end
 | 
			
		||||
      end
 | 
			
		||||
    end
 | 
			
		||||
 | 
			
		||||
    context 'with an inaccessible key' do
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user