diff options
Diffstat (limited to 'actionpack/lib/action_dispatch/middleware')
9 files changed, 69 insertions, 29 deletions
diff --git a/actionpack/lib/action_dispatch/middleware/cookies.rb b/actionpack/lib/action_dispatch/middleware/cookies.rb index e565c03a8a..533925ebe1 100644 --- a/actionpack/lib/action_dispatch/middleware/cookies.rb +++ b/actionpack/lib/action_dispatch/middleware/cookies.rb @@ -43,6 +43,10 @@ module ActionDispatch        get_header Cookies::ENCRYPTED_SIGNED_COOKIE_SALT      end +    def authenticated_encrypted_cookie_salt +      get_header Cookies::AUTHENTICATED_ENCRYPTED_COOKIE_SALT +    end +      def secret_token        get_header Cookies::SECRET_TOKEN      end @@ -149,6 +153,7 @@ module ActionDispatch      SIGNED_COOKIE_SALT = "action_dispatch.signed_cookie_salt".freeze      ENCRYPTED_COOKIE_SALT = "action_dispatch.encrypted_cookie_salt".freeze      ENCRYPTED_SIGNED_COOKIE_SALT = "action_dispatch.encrypted_signed_cookie_salt".freeze +    AUTHENTICATED_ENCRYPTED_COOKIE_SALT = "action_dispatch.authenticated_encrypted_cookie_salt".freeze      SECRET_TOKEN = "action_dispatch.secret_token".freeze      SECRET_KEY_BASE = "action_dispatch.secret_key_base".freeze      COOKIES_SERIALIZER = "action_dispatch.cookies_serializer".freeze @@ -207,6 +212,9 @@ module ActionDispatch        # If +secrets.secret_key_base+ and +secrets.secret_token+ (deprecated) are both set,        # legacy cookies signed with the old key generator will be transparently upgraded.        # +      # If +config.action_dispatch.encrypted_cookie_salt+ and +config.action_dispatch.encrypted_signed_cookie_salt+ +      # are both set, legacy cookies encrypted with HMAC AES-256-CBC will be transparently upgraded. +      #        # This jar requires that you set a suitable secret for the verification on your app's +secrets.secret_key_base+.        #        # Example: @@ -219,6 +227,8 @@ module ActionDispatch          @encrypted ||=            if upgrade_legacy_signed_cookies?              UpgradeLegacyEncryptedCookieJar.new(self) +          elsif upgrade_legacy_hmac_aes_cbc_cookies? +            UpgradeLegacyHmacAesCbcCookieJar.new(self)            else              EncryptedCookieJar.new(self)            end @@ -240,6 +250,13 @@ module ActionDispatch          def upgrade_legacy_signed_cookies?            request.secret_token.present? && request.secret_key_base.present?          end + +        def upgrade_legacy_hmac_aes_cbc_cookies? +          request.secret_key_base.present?                       && +            request.authenticated_encrypted_cookie_salt.present? && +            request.encrypted_signed_cookie_salt.present?        && +            request.encrypted_cookie_salt.present? +        end      end      # Passing the ActiveSupport::MessageEncryptor::NullSerializer downstream @@ -415,8 +432,7 @@ module ActionDispatch          end        end -      mattr_accessor :always_write_cookie -      self.always_write_cookie = false +      mattr_accessor :always_write_cookie, default: false        private @@ -576,9 +592,11 @@ module ActionDispatch              "Read the upgrade documentation to learn more about this new config option."          end -        secret = key_generator.generate_key(request.encrypted_cookie_salt || "")[0, ActiveSupport::MessageEncryptor.key_len] -        sign_secret = key_generator.generate_key(request.encrypted_signed_cookie_salt || "") -        @encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer) +        cipher = "aes-256-gcm" +        key_len = ActiveSupport::MessageEncryptor.key_len(cipher) +        secret = key_generator.generate_key(request.authenticated_encrypted_cookie_salt || "")[0, key_len] + +        @encryptor = ActiveSupport::MessageEncryptor.new(secret, cipher: cipher, serializer: ActiveSupport::MessageEncryptor::NullSerializer)        end        private @@ -603,6 +621,32 @@ module ActionDispatch        include VerifyAndUpgradeLegacySignedMessage      end +    # UpgradeLegacyHmacAesCbcCookieJar is used by ActionDispatch::Session::CookieStore +    # to upgrade cookies encrypted with AES-256-CBC with HMAC to AES-256-GCM +    class UpgradeLegacyHmacAesCbcCookieJar < EncryptedCookieJar +      def initialize(parent_jar) +        super + +        secret = key_generator.generate_key(request.encrypted_cookie_salt || "")[0, ActiveSupport::MessageEncryptor.key_len] +        sign_secret = key_generator.generate_key(request.encrypted_signed_cookie_salt || "") + +        @legacy_encryptor = ActiveSupport::MessageEncryptor.new(secret, sign_secret, cipher: "aes-256-cbc", digest: digest, serializer: ActiveSupport::MessageEncryptor::NullSerializer) +      end + +      def decrypt_and_verify_legacy_encrypted_message(name, signed_message) +        deserialize(name, @legacy_encryptor.decrypt_and_verify(signed_message)).tap do |value| +          self[name] = { value: value } +        end +      rescue ActiveSupport::MessageVerifier::InvalidSignature, ActiveSupport::MessageEncryptor::InvalidMessage +        nil +      end + +      private +        def parse(name, signed_message) +          super || decrypt_and_verify_legacy_encrypted_message(name, signed_message) +        end +    end +      def initialize(app)        @app = app      end diff --git a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb index 1c720c5a8e..d42b35a4cf 100644 --- a/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/debug_exceptions.rb @@ -1,6 +1,6 @@ -require "action_dispatch/http/request" -require "action_dispatch/middleware/exception_wrapper" -require "action_dispatch/routing/inspector" +require_relative "../http/request" +require_relative "exception_wrapper" +require_relative "../routing/inspector"  require "action_view"  require "action_view/base" @@ -10,7 +10,7 @@ module ActionDispatch    # This middleware is responsible for logging exceptions and    # showing a debugging page in case the request is local.    class DebugExceptions -    RESCUES_TEMPLATE_PATH = File.expand_path("../templates", __FILE__) +    RESCUES_TEMPLATE_PATH = File.expand_path("templates", __dir__)      class DebugView < ActionView::Base        def debug_params(params) diff --git a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb index 397f0a8b92..08b4541d24 100644 --- a/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb +++ b/actionpack/lib/action_dispatch/middleware/exception_wrapper.rb @@ -3,9 +3,7 @@ require "rack/utils"  module ActionDispatch    class ExceptionWrapper -    cattr_accessor :rescue_responses -    @@rescue_responses = Hash.new(:internal_server_error) -    @@rescue_responses.merge!( +    cattr_accessor :rescue_responses, default: Hash.new(:internal_server_error).merge!(        "ActionController::RoutingError"               => :not_found,        "AbstractController::ActionNotFound"           => :not_found,        "ActionController::MethodNotAllowed"           => :method_not_allowed, @@ -21,9 +19,7 @@ module ActionDispatch        "Rack::QueryParser::InvalidParameterError"     => :bad_request      ) -    cattr_accessor :rescue_templates -    @@rescue_templates = Hash.new("diagnostics") -    @@rescue_templates.merge!( +    cattr_accessor :rescue_templates, default: Hash.new("diagnostics").merge!(        "ActionView::MissingTemplate"         => "missing_template",        "ActionController::RoutingError"      => "routing_error",        "AbstractController::ActionNotFound"  => "unknown_action", diff --git a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb index 21ccf5a097..31979fa576 100644 --- a/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/abstract_store.rb @@ -1,8 +1,8 @@  require "rack/utils"  require "rack/request"  require "rack/session/abstract/id" -require "action_dispatch/middleware/cookies" -require "action_dispatch/request/session" +require_relative "../cookies" +require_relative "../../request/session"  module ActionDispatch    module Session diff --git a/actionpack/lib/action_dispatch/middleware/session/cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/cache_store.rb index 71274bc13a..4babeb6354 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cache_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cache_store.rb @@ -1,4 +1,4 @@ -require "action_dispatch/middleware/session/abstract_store" +require_relative "abstract_store"  module ActionDispatch    module Session diff --git a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb index 57d325a9d8..496f221617 100644 --- a/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/cookie_store.rb @@ -1,5 +1,5 @@  require "active_support/core_ext/hash/keys" -require "action_dispatch/middleware/session/abstract_store" +require_relative "abstract_store"  require "rack/session/cookie"  module ActionDispatch diff --git a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb index ee2b1f26ad..bc2b1c9b12 100644 --- a/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb +++ b/actionpack/lib/action_dispatch/middleware/session/mem_cache_store.rb @@ -1,4 +1,4 @@ -require "action_dispatch/middleware/session/abstract_store" +require_relative "abstract_store"  begin    require "rack/session/dalli"  rescue LoadError => e diff --git a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb index 5a99714ec2..db84ff48e9 100644 --- a/actionpack/lib/action_dispatch/middleware/show_exceptions.rb +++ b/actionpack/lib/action_dispatch/middleware/show_exceptions.rb @@ -1,5 +1,5 @@ -require "action_dispatch/http/request" -require "action_dispatch/middleware/exception_wrapper" +require_relative "../http/request" +require_relative "exception_wrapper"  module ActionDispatch    # This middleware rescues any exception returned by the application diff --git a/actionpack/lib/action_dispatch/middleware/static.rb b/actionpack/lib/action_dispatch/middleware/static.rb index 5d10129d21..fb99f13a1c 100644 --- a/actionpack/lib/action_dispatch/middleware/static.rb +++ b/actionpack/lib/action_dispatch/middleware/static.rb @@ -6,11 +6,11 @@ module ActionDispatch    # When initialized, it can accept optional HTTP headers, which will be set    # when a response containing a file's contents is delivered.    # -  # This middleware will render the file specified in `env["PATH_INFO"]` +  # This middleware will render the file specified in <tt>env["PATH_INFO"]</tt>    # where the base path is in the +root+ directory. For example, if the +root+ -  # is set to `public/`, then a request with `env["PATH_INFO"]` of -  # `assets/application.js` will return a response with the contents of a file -  # located at `public/assets/application.js` if the file exists. If the file +  # is set to +public/+, then a request with <tt>env["PATH_INFO"]</tt> of +  # +assets/application.js+ will return a response with the contents of a file +  # located at +public/assets/application.js+ if the file exists. If the file    # does not exist, a 404 "File not Found" response will be returned.    class FileHandler      def initialize(root, index: "index", headers: {}) @@ -23,8 +23,8 @@ module ActionDispatch      # correct read permissions, the return value is a URI-escaped string      # representing the filename. Otherwise, false is returned.      # -    # Used by the `Static` class to check the existence of a valid file -    # in the server's `public/` directory (see Static#call). +    # Used by the +Static+ class to check the existence of a valid file +    # in the server's +public/+ directory (see Static#call).      def match?(path)        path = ::Rack::Utils.unescape_path path        return false unless ::Rack::Utils.valid_path? path @@ -99,7 +99,7 @@ module ActionDispatch    # This middleware will attempt to return the contents of a file's body from    # disk in the response. If a file is not found on disk, the request will be    # delegated to the application stack. This middleware is commonly initialized -  # to serve assets from a server's `public/` directory. +  # to serve assets from a server's +public/+ directory.    #    # This middleware verifies the path to ensure that only files    # living in the root directory can be rendered. A request cannot  | 
