def _authenticate(req, res)
def _authenticate(req, res)
unless digest_credentials = check_scheme(req)
return false
end
auth_req = split_param_value(digest_credentials)
if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int"
req_params = MustParams + MustParamsAuth
else
req_params = MustParams
end
req_params.each{|key|
unless auth_req.has_key?(key)
error('%s: parameter missing. "%s"', auth_req['username'], key)
raise HTTPStatus::BadRequest
end
}
if !check_uri(req, auth_req)
raise HTTPStatus::BadRequest
end
if auth_req['realm'] != @realm
error('%s: realm unmatch. "%s" for "%s"',
auth_req['username'], auth_req['realm'], @realm)
return false
end
auth_req['algorithm'] ||= 'MD5'
if auth_req['algorithm'].upcase != @algorithm.upcase
error('%s: algorithm unmatch. "%s" for "%s"',
auth_req['username'], auth_req['algorithm'], @algorithm)
return false
end
if (@qop.nil? && auth_req.has_key?('qop')) ||
(@qop && (! @qop.member?(auth_req['qop'])))
error('%s: the qop is not allowed. "%s"',
auth_req['username'], auth_req['qop'])
return false
end
password = @userdb.get_passwd(@realm, auth_req['username'], @reload_db)
unless password
error('%s: the user is not allowed.', auth_req['username'])
return false
end
nonce_is_invalid = false
if @use_opaque
info("@opaque = %s", @opaque.inspect) if $DEBUG
if !(opaque = auth_req['opaque'])
error('%s: opaque is not given.', auth_req['username'])
nonce_is_invalid = true
elsif !(opaque_struct = @opaques[opaque])
error('%s: invalid opaque is given.', auth_req['username'])
nonce_is_invalid = true
elsif !check_opaque(opaque_struct, req, auth_req)
@opaques.delete(auth_req['opaque'])
nonce_is_invalid = true
end
elsif !check_nonce(req, auth_req)
nonce_is_invalid = true
end
if /-sess$/i =~ auth_req['algorithm']
ha1 = hexdigest(password, auth_req['nonce'], auth_req['cnonce'])
else
ha1 = password
end
if auth_req['qop'] == "auth" || auth_req['qop'] == nil
ha2 = hexdigest(req.request_method, auth_req['uri'])
ha2_res = hexdigest("", auth_req['uri'])
elsif auth_req['qop'] == "auth-int"
body_digest = @h.new
req.body { |chunk| body_digest.update(chunk) }
body_digest = body_digest.hexdigest
ha2 = hexdigest(req.request_method, auth_req['uri'], body_digest)
ha2_res = hexdigest("", auth_req['uri'], body_digest)
end
if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int"
param2 = ['nonce', 'nc', 'cnonce', 'qop'].map{|key|
auth_req[key]
}.join(':')
digest = hexdigest(ha1, param2, ha2)
digest_res = hexdigest(ha1, param2, ha2_res)
else
digest = hexdigest(ha1, auth_req['nonce'], ha2)
digest_res = hexdigest(ha1, auth_req['nonce'], ha2_res)
end
if digest != auth_req['response']
error("%s: digest unmatch.", auth_req['username'])
return false
elsif nonce_is_invalid
error('%s: digest is valid, but nonce is not valid.',
auth_req['username'])
return :nonce_is_stale
elsif @use_auth_info_header
auth_info = {
'nextnonce' => generate_next_nonce(req),
'rspauth' => digest_res
}
if @use_opaque
opaque_struct.time = req.request_time
opaque_struct.nonce = auth_info['nextnonce']
opaque_struct.nc = "%08x" % (auth_req['nc'].hex + 1)
end
if auth_req['qop'] == "auth" || auth_req['qop'] == "auth-int"
['qop','cnonce','nc'].each{|key|
auth_info[key] = auth_req[key]
}
end
res[@resp_info_field] = auth_info.keys.map{|key|
if key == 'nc'
key + '=' + auth_info[key]
else
key + "=" + HTTPUtils::quote(auth_info[key])
end
}.join(', ')
end
info('%s: authentication succeeded.', auth_req['username'])
req.user = auth_req['username']
return true
end