/usr/lib/ruby/vendor_ruby/net/http/digest_auth.rb is in ruby-net-http-digest-auth 1.4-2.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 | require 'cgi'
require 'digest'
require 'monitor'
require 'net/http'
require 'securerandom'
##
# An implementation of RFC 2617 Digest Access Authentication.
#
# http://www.rfc-editor.org/rfc/rfc2617.txt
#
# Here is a sample usage of DigestAuth on Net::HTTP:
#
# require 'uri'
# require 'net/http'
# require 'net/http/digest_auth'
#
# digest_auth = Net::HTTP::DigestAuth.new
#
# uri = URI.parse 'http://localhost:8000/'
# uri.user = 'username'
# uri.password = 'password'
#
# h = Net::HTTP.new uri.host, uri.port
#
# req = Net::HTTP::Get.new uri.request_uri
#
# res = h.request req
# # res is a 401 response with a WWW-Authenticate header
#
# auth = digest_auth.auth_header uri, res['www-authenticate'], 'GET'
#
# # create a new request with the Authorization header
# req = Net::HTTP::Get.new uri.request_uri
# req.add_field 'Authorization', auth
#
# # re-issue request with Authorization
# res = h.request req
class Net::HTTP::DigestAuth
include MonitorMixin
##
# DigestAuth error class
class Error < RuntimeError; end
##
# Version of Net::HTTP::DigestAuth you are using
VERSION = '1.4'
##
# Creates a new DigestAuth header creator.
def initialize ignored = :ignored
mon_initialize
@nonce_count = -1
end
##
# Creates a digest auth header for +uri+ from the +www_authenticate+ header
# for HTTP method +method+.
#
# The result of this method should be sent along with the HTTP request as
# the "Authorization" header. In Net::HTTP this will look like:
#
# request.add_field 'Authorization', digest_auth.auth_header # ...
#
# See Net::HTTP::DigestAuth for a complete example.
#
# IIS servers handle the "qop" parameter of digest authentication
# differently so you may need to set +iis+ to true for such servers.
def auth_header uri, www_authenticate, method, iis = false
nonce_count = next_nonce
user = CGI.unescape uri.user
password = CGI.unescape uri.password
www_authenticate =~ /^(\w+) (.*)/
challenge = $2
params = {}
challenge.gsub(/(\w+)="(.*?)"/) { params[$1] = $2 }
challenge =~ /algorithm="?(.*?)"?([, ]|$)/
params['algorithm'] = $1 || 'MD5'
if params['algorithm'] =~ /(.*?)(-sess)?$/
algorithm = case $1
when 'MD5' then Digest::MD5
when 'SHA1' then Digest::SHA1
when 'SHA2' then Digest::SHA2
when 'SHA256' then Digest::SHA256
when 'SHA384' then Digest::SHA384
when 'SHA512' then Digest::SHA512
when 'RMD160' then Digest::RMD160
else raise Error, "unknown algorithm \"#{$1}\""
end
sess = $2
end
qop = params['qop']
cnonce = make_cnonce if qop or sess
a1 = if sess then
[ algorithm.hexdigest("#{user}:#{params['realm']}:#{password}"),
params['nonce'],
cnonce,
].join ':'
else
"#{user}:#{params['realm']}:#{password}"
end
ha1 = algorithm.hexdigest a1
ha2 = algorithm.hexdigest "#{method}:#{uri.request_uri}"
request_digest = [ha1, params['nonce']]
request_digest.push(('%08x' % nonce_count), cnonce, qop) if qop
request_digest << ha2
request_digest = request_digest.join ':'
header = [
"Digest username=\"#{user}\"",
"realm=\"#{params['realm']}\"",
"algorithm=#{params['algorithm']}",
if qop.nil? then
elsif iis then
"qop=\"#{qop}\""
else
"qop=#{qop}"
end,
"uri=\"#{uri.request_uri}\"",
"nonce=\"#{params['nonce']}\"",
if qop then
[
"nc=#{'%08x' % @nonce_count}",
"cnonce=\"#{cnonce}\"",
]
end,
"response=\"#{algorithm.hexdigest(request_digest)[0, 32]}\"",
if params.key? 'opaque' then
"opaque=\"#{params['opaque']}\""
end
].compact
header.join ', '
end
##
# Creates a client nonce value that is used across all requests based on the
# current time, process id and a random number
def make_cnonce
Digest::MD5.hexdigest [
Time.now.to_i,
$$,
SecureRandom.random_number(2**32),
].join ':'
end
def next_nonce
synchronize do
@nonce_count += 1
end
end
end
|