diff --git a/Gemfile.lock b/Gemfile.lock index 0b40ff4eb1..a990db2278 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -79,7 +79,7 @@ GEM cocaine (~> 0.5.3) awrence (1.1.1) aws-eventstream (1.1.0) - aws-partitions (1.380.0) + aws-partitions (1.385.0) aws-sdk-core (3.109.1) aws-eventstream (~> 1, >= 1.0.2) aws-partitions (~> 1, >= 1.239.0) @@ -88,7 +88,7 @@ GEM aws-sdk-kms (1.39.0) aws-sdk-core (~> 3, >= 3.109.0) aws-sigv4 (~> 1.1) - aws-sdk-s3 (1.83.0) + aws-sdk-s3 (1.83.1) aws-sdk-core (~> 3, >= 3.109.0) aws-sdk-kms (~> 1) aws-sigv4 (~> 1.1) @@ -583,7 +583,7 @@ GEM simple_form (5.0.3) actionpack (>= 5.0) activemodel (>= 5.0) - simplecov (0.19.0) + simplecov (0.19.1) docile (~> 1.1) simplecov-html (~> 0.11) simplecov-html (0.12.3) @@ -597,12 +597,12 @@ GEM sshkit (1.21.0) net-scp (>= 1.1.2) net-ssh (>= 2.8.0) - stackprof (0.2.15) + stackprof (0.2.16) statsd-ruby (1.4.0) stoplight (2.2.1) streamio-ffmpeg (3.0.2) multi_json (~> 1.8) - strong_migrations (0.7.1) + strong_migrations (0.7.2) activerecord (>= 5) temple (0.8.2) terminal-table (1.8.0) @@ -631,7 +631,7 @@ GEM unf (~> 0.1.0) tzinfo (1.2.7) thread_safe (~> 0.1) - tzinfo-data (1.2020.3) + tzinfo-data (1.2020.4) tzinfo (>= 1.0.0) unf (0.1.4) unf_ext diff --git a/app/controllers/concerns/signature_verification.rb b/app/controllers/concerns/signature_verification.rb index f69c62ec24..fc3978fbbd 100644 --- a/app/controllers/concerns/signature_verification.rb +++ b/app/controllers/concerns/signature_verification.rb @@ -76,6 +76,7 @@ module SignatureVerification raise SignatureVerificationError, 'Signed request date outside acceptable time window' unless matches_time_window? verify_signature_strength! + verify_body_digest! account = account_from_key_id(signature_params['keyId']) @@ -126,10 +127,19 @@ module SignatureVerification def verify_signature_strength! raise SignatureVerificationError, 'Mastodon requires the Date header or (created) pseudo-header to be signed' unless signed_headers.include?('date') || signed_headers.include?('(created)') raise SignatureVerificationError, 'Mastodon requires the Digest header or (request-target) pseudo-header to be signed' unless signed_headers.include?(Request::REQUEST_TARGET) || signed_headers.include?('digest') - raise SignatureVerificationError, 'Mastodon requires the Host header to be signed' unless signed_headers.include?('host') + raise SignatureVerificationError, 'Mastodon requires the Host header to be signed when doing a GET request' if request.get? && !signed_headers.include?('host') raise SignatureVerificationError, 'Mastodon requires the Digest header to be signed when doing a POST request' if request.post? && !signed_headers.include?('digest') end + def verify_body_digest! + return unless signed_headers.include?('digest') + + digests = request.headers['Digest'].split(',').map { |digest| digest.split('=', 2) }.map { |key, value| [key.downcase, value] } + sha256 = digests.assoc('sha-256') + raise SignatureVerificationError, "Mastodon only supports SHA-256 in Digest header. Offered algorithms: #{digests.map(&:first).join(', ')}" if sha256.nil? + raise SignatureVerificationError, "Invalid Digest value. Computed SHA-256 digest: #{body_digest}; given: #{sha256[1]}" if body_digest != sha256[1] + end + def verify_signature(account, signature, compare_signed_string) if account.keypair.public_key.verify(OpenSSL::Digest.new('SHA256'), signature, compare_signed_string) @signed_request_account = account @@ -153,8 +163,6 @@ module SignatureVerification raise SignatureVerificationError, 'Pseudo-header (expires) used but corresponding argument missing' if signature_params['expires'].blank? "(expires): #{signature_params['expires']}" - elsif signed_header == 'digest' - "digest: #{body_digest}" else "#{signed_header}: #{request.headers[to_header_name(signed_header)]}" end @@ -187,7 +195,7 @@ module SignatureVerification end def body_digest - "SHA-256=#{Digest::SHA256.base64digest(request_body)}" + @body_digest ||= Digest::SHA256.base64digest(request_body) end def to_header_name(name) diff --git a/app/controllers/filters_controller.rb b/app/controllers/filters_controller.rb index 76be03e537..0d4c1b97c0 100644 --- a/app/controllers/filters_controller.rb +++ b/app/controllers/filters_controller.rb @@ -10,7 +10,7 @@ class FiltersController < ApplicationController before_action :set_body_classes def index - @filters = current_account.custom_filters + @filters = current_account.custom_filters.order(:phrase) end def new diff --git a/app/javascript/mastodon/components/status.js b/app/javascript/mastodon/components/status.js index c1e1cd172a..be4f0bcca3 100644 --- a/app/javascript/mastodon/components/status.js +++ b/app/javascript/mastodon/components/status.js @@ -460,8 +460,10 @@ class Status extends ImmutablePureComponent {