CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutSign UpSign In
rapid7

Real-time collaboration for Jupyter Notebooks, Linux Terminals, LaTeX, VS Code, R IDE, and more,
all in one place. Commercial Alternative to JupyterHub.

GitHub Repository: rapid7/metasploit-framework
Path: blob/master/lib/rex/proto/http/auth_digest.rb
Views: 18091
1
require 'digest'
2
require 'rex/text'
3
4
module Rex
5
module Proto
6
module Http
7
class AuthDigest
8
9
def make_cnonce
10
Digest::MD5.hexdigest '%x' % (::Time.now.to_i + rand(65535))
11
end
12
13
def digest(digest_user, digest_password, method, path, parameters, iis = false)
14
cnonce = make_cnonce
15
nonce_count = 1
16
17
qop = parameters['qop']
18
19
if parameters['algorithm'] =~ /(.*?)(-sess)?$/
20
algorithm = case ::Regexp.last_match(1)
21
when 'MD5' then Digest::MD5
22
when 'MD-5' then Digest::MD5
23
when 'SHA1' then Digest::SHA1
24
when 'SHA-1' then Digest::SHA1
25
when 'SHA2' then Digest::SHA2
26
when 'SHA-2' then Digest::SHA2
27
when 'SHA256' then Digest::SHA256
28
when 'SHA-256' then Digest::SHA256
29
when 'SHA384' then Digest::SHA384
30
when 'SHA-384' then Digest::SHA384
31
when 'SHA512' then Digest::SHA512
32
when 'SHA-512' then Digest::SHA512
33
when 'RMD160' then Digest::RMD160
34
else raise "unknown algorithm \"#{::Regexp.last_match(1)}\""
35
end
36
algstr = parameters['algorithm']
37
sess = ::Regexp.last_match(2)
38
else
39
algorithm = Digest::MD5
40
algstr = 'MD5'
41
sess = false
42
end
43
a1 = if sess
44
[
45
algorithm.hexdigest("#{digest_user}:#{parameters['realm']}:#{digest_password}"),
46
parameters['nonce'],
47
cnonce
48
].join ':'
49
else
50
"#{digest_user}:#{parameters['realm']}:#{digest_password}"
51
end
52
53
ha1 = algorithm.hexdigest(a1)
54
ha2 = algorithm.hexdigest("#{method}:#{path}")
55
56
request_digest = [ha1, parameters['nonce']]
57
request_digest.push(('%08x' % nonce_count), cnonce, qop) if qop
58
request_digest << ha2
59
request_digest = request_digest.join ':'
60
# Same order as IE7
61
return [
62
"Digest username=\"#{digest_user}\"",
63
"realm=\"#{parameters['realm']}\"",
64
"nonce=\"#{parameters['nonce']}\"",
65
"uri=\"#{path}\"",
66
"cnonce=\"#{cnonce}\"",
67
"nc=#{'%08x' % nonce_count}",
68
"algorithm=#{algstr}",
69
"response=\"#{algorithm.hexdigest(request_digest)}\"",
70
# The spec says the qop value shouldn't be enclosed in quotes, but
71
# some versions of IIS require it and Apache accepts it. Chrome
72
# and Firefox both send it without quotes but IE does it this way.
73
# Use the non-compliant-but-everybody-does-it to be as compatible
74
# as possible by default. The user can override if they don't like
75
# it.
76
if iis
77
"qop=\"#{qop}\""
78
else
79
"qop=#{qop}"
80
end,
81
if parameters.key? 'opaque'
82
"opaque=\"#{parameters['opaque']}\""
83
end
84
].compact
85
end
86
end
87
end
88
end
89
end
90
91