Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extend Support escape downcasing for Azure on LogoutResponse #634

Merged
merged 1 commit into from
Feb 1, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion lib/onelogin/ruby-saml/logoutresponse.rb
Original file line number Diff line number Diff line change
Expand Up @@ -212,7 +212,7 @@ def validate_signature
return true unless options.has_key? :get_params
return true unless options[:get_params].has_key? 'Signature'

options[:raw_get_params] = OneLogin::RubySaml::Utils.prepare_raw_get_params(options[:raw_get_params], options[:get_params])
options[:raw_get_params] = OneLogin::RubySaml::Utils.prepare_raw_get_params(options[:raw_get_params], options[:get_params], settings.security[:lowercase_url_encoding])

if options[:get_params]['SigAlg'].nil? && !options[:raw_get_params]['SigAlg'].nil?
options[:get_params]['SigAlg'] = CGI.unescape(options[:raw_get_params]['SigAlg'])
Expand Down
34 changes: 1 addition & 33 deletions lib/onelogin/ruby-saml/slo_logoutrequest.rb
Original file line number Diff line number Diff line change
Expand Up @@ -248,32 +248,8 @@ def validate_signature
return true unless options.has_key? :get_params
return true unless options[:get_params].has_key? 'Signature'

# SAML specifies that the signature should be derived from a concatenation
# of URI-encoded values _as sent by the IDP_:
#
# > Further, note that URL-encoding is not canonical; that is, there are multiple legal encodings for a given
# > value. The relying party MUST therefore perform the verification step using the original URL-encoded
# > values it received on the query string. It is not sufficient to re-encode the parameters after they have been
# > processed by software because the resulting encoding may not match the signer's encoding.
#
# <http://docs.oasis-open.org/security/saml/v2.0/saml-bindings-2.0-os.pdf>
#
# If we don't have the original parts (for backward compatibility) required to correctly verify the signature,
# then fabricate them by re-encoding the parsed URI parameters, and hope that we're lucky enough to use
# the exact same URI-encoding as the IDP. (This is not the case if the IDP is ADFS!)
options[:raw_get_params] ||= {}
if options[:raw_get_params]['SAMLRequest'].nil? && !options[:get_params]['SAMLRequest'].nil?
options[:raw_get_params]['SAMLRequest'] = escape_request_param(options[:get_params]['SAMLRequest'])
end
if options[:raw_get_params]['RelayState'].nil? && !options[:get_params]['RelayState'].nil?
options[:raw_get_params]['RelayState'] = escape_request_param(options[:get_params]['RelayState'])
end
if options[:raw_get_params]['SigAlg'].nil? && !options[:get_params]['SigAlg'].nil?
options[:raw_get_params]['SigAlg'] = escape_request_param(options[:get_params]['SigAlg'])
end
options[:raw_get_params] = OneLogin::RubySaml::Utils.prepare_raw_get_params(options[:raw_get_params], options[:get_params], settings.security[:lowercase_url_encoding])

# If we only received the raw version of SigAlg,
# then parse it back into the decoded params hash for convenience.
if options[:get_params]['SigAlg'].nil? && !options[:raw_get_params]['SigAlg'].nil?
options[:get_params]['SigAlg'] = CGI.unescape(options[:raw_get_params]['SigAlg'])
end
Expand Down Expand Up @@ -335,14 +311,6 @@ def validate_signature

true
end

def escape_request_param(param)
CGI.escape(param).tap do |escaped|
next unless settings.security[:lowercase_url_encoding]

escaped.gsub!(/%[A-Fa-f0-9]{2}/) { |match| match.downcase }
end
end
end
end
end
19 changes: 14 additions & 5 deletions lib/onelogin/ruby-saml/utils.rb
Original file line number Diff line number Diff line change
Expand Up @@ -167,27 +167,36 @@ def self.build_query_from_raw_parts(params)
#
# @param rawparams [Hash] Raw GET Parameters
# @param params [Hash] GET Parameters
# @param lowercase_url_encoding [bool] Lowercase URL Encoding (For ADFS urlencode compatiblity)
# @return [Hash] New raw parameters
#
def self.prepare_raw_get_params(rawparams, params)
def self.prepare_raw_get_params(rawparams, params, lowercase_url_encoding=false)
rawparams ||= {}

if rawparams['SAMLRequest'].nil? && !params['SAMLRequest'].nil?
rawparams['SAMLRequest'] = CGI.escape(params['SAMLRequest'])
rawparams['SAMLRequest'] = escape_request_param(params['SAMLRequest'], lowercase_url_encoding)
end
if rawparams['SAMLResponse'].nil? && !params['SAMLResponse'].nil?
rawparams['SAMLResponse'] = CGI.escape(params['SAMLResponse'])
rawparams['SAMLResponse'] = escape_request_param(params['SAMLResponse'], lowercase_url_encoding)
end
if rawparams['RelayState'].nil? && !params['RelayState'].nil?
rawparams['RelayState'] = CGI.escape(params['RelayState'])
rawparams['RelayState'] = escape_request_param(params['RelayState'], lowercase_url_encoding)
end
if rawparams['SigAlg'].nil? && !params['SigAlg'].nil?
rawparams['SigAlg'] = CGI.escape(params['SigAlg'])
rawparams['SigAlg'] = escape_request_param(params['SigAlg'], lowercase_url_encoding)
end

rawparams
end

def self.escape_request_param(param, lowercase_url_encoding)
CGI.escape(param).tap do |escaped|
next unless lowercase_url_encoding

escaped.gsub!(/%[A-Fa-f0-9]{2}/) { |match| match.downcase }
end
end

# Validate the Signature parameter sent on the HTTP-Redirect binding
# @param params [Hash] Parameters to be used in the validation process
# @option params [OpenSSL::X509::Certificate] cert The Identity provider public certtificate
Expand Down