diff options
author | Tim Hinderliter <tim@opscode.com> | 2009-11-19 18:36:06 -0800 |
---|---|---|
committer | Tim Hinderliter <tim@opscode.com> | 2009-11-19 18:36:06 -0800 |
commit | f073834372d4fceb3073bf9f5790d9b7420368dd (patch) | |
tree | 7d59e2200234a3757bbdfe0eeaaaa2955884efd9 /lib/mixlib/authentication/signatureverification.rb | |
parent | 6d3e91681cc5725f018fda66f368435d9e27a9a3 (diff) | |
download | mixlib-authentication-f073834372d4fceb3073bf9f5790d9b7420368dd.tar.gz |
Modified to handle both Merb and Passenger, as they pass the File part of a
multipart form upload differently. Added unit tests for this and other
behaviors.
Diffstat (limited to 'lib/mixlib/authentication/signatureverification.rb')
-rw-r--r-- | lib/mixlib/authentication/signatureverification.rb | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/lib/mixlib/authentication/signatureverification.rb b/lib/mixlib/authentication/signatureverification.rb index c010515..4383007 100644 --- a/lib/mixlib/authentication/signatureverification.rb +++ b/lib/mixlib/authentication/signatureverification.rb @@ -38,6 +38,7 @@ module Mixlib # X-Ops-UserId: <user_id> # X-Ops-Timestamp: # X-Ops-Content-Hash: + # X-Ops-Authorization-#{line_number} def authenticate_user_request(request, user_lookup, time_skew=(15*60)) Mixlib::Authentication::Log.debug "Initializing header auth : #{request.inspect}" @@ -63,27 +64,38 @@ module Mixlib @request_signature = headers.find_all { |h| h[0].to_s =~ /^x_ops_authorization_/ }.sort { |x,y| x.to_s <=> y.to_s}.map { |i| i[1] }.join("\n") Mixlib::Authentication::Log.debug "Reconstituted request signature: #{@request_signature}" - # Any file that's included in the request is hashed if it's there. Otherwise, - # we hash the body. Look for files by looking for objects that respond to - # the read call. + # Pull out any file that was attached to this request, using multipart + # form uploads. + # Depending on the server we're running in, multipart form uploads are + # handed to us differently. + # - In Passenger (Cookbooks Community Site), the File is handed to us + # directly in the params hash. The name is whatever the client used, + # its value is therefore a File or Tempfile. + # - In Merb (Chef server), the File is wrapped. The original parameter + # name used for the file is passed in with a Hash value. Within the hash + # is a name/value pair named 'file' which actually contains the Tempfile + # instance. file_param = request.params.values.find { |value| value.respond_to?(:read) } - @hashed_body = if file_param - Mixlib::Authentication::Log.debug "Digesting file_param: '#{file_param.inspect}'" - if file_param.respond_to?(:has_key?) - tempfile = file_param[:tempfile] - digester.hash_file(tempfile) - elsif file_param.respond_to?(:read) - digester.hash_file(file_param) - else - digester.hash_body(file_param) - end - else - body = request.raw_post - Mixlib::Authentication::Log.debug "Digesting body: '#{body}'" - digester.hash_body(body) - end + # No file_param; we're running in Merb, or it's just not there.. + if file_param.nil? + hash_param = request.params.values.find { |value| value.respond_to?(:has_key?) } # Hash responds to :has_key? . + if !hash_param.nil? + file_param = hash_param.values.find { |value| value.respond_to?(:read) } # File/Tempfile responds to :read. + end + end + # Any file that's included in the request is hashed if it's there. Otherwise, + # we hash the body. + if file_param + Mixlib::Authentication::Log.debug "Digesting file_param: '#{file_param.inspect}'" + @hashed_body = digester.hash_file(file_param) + else + body = request.raw_post + Mixlib::Authentication::Log.debug "Digesting body: '#{body}'" + @hashed_body = digester.hash_body(body) + end + Mixlib::Authentication::Log.debug "Authenticating user : #{user_id}, User secret is : #{@user_secret}, Request signature is :\n#{@request_signature}, Auth HTTP header is :\n#{headers[:authorization]}, Hashed Body is : #{@hashed_body}" #BUGBUG Not doing anything with the signing description yet [cb] @@ -94,7 +106,7 @@ module Mixlib timeskew_is_acceptable = timestamp_within_bounds?(Time.parse(timestamp), Time.now) hashes_match = @content_hash == hashed_body rescue StandardError=>se - raise StandardError,"Failed to authenticate user request. Most likely missing a necessary header: #{se.message}" + raise StandardError,"Failed to authenticate user request. Most likely missing a necessary header: #{se.message}", se.backtrace end Mixlib::Authentication::Log.debug "Candidate Block is: '#{candidate_block}'\nRequest decrypted block is: '#{request_decrypted_block}'\nCandidate content hash is: #{hashed_body}\nRequest Content Hash is: '#{@content_hash}'\nSignatures match: #{signatures_match}, Allowed Time Skew: #{timeskew_is_acceptable}, Hashes match?: #{hashes_match}\n" |