Module: Atom::DigestAuth

Included in:
HTTP
Defined in:
lib/atom/http.rb

Constant Summary collapse

CNONCE =
Digest::MD5.hexdigest("%x" % (Time.now.to_i + rand(65535)))
@@nonce_count =
-1

Instance Method Summary collapse

Instance Method Details

#digest_authenticate(req, url, param_string = "") ⇒ Object

HTTP Digest authentication (RFC 2617)



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
# File 'lib/atom/http.rb', line 45

def digest_authenticate(req, url, param_string = "")
  raise "Digest authentication requires a WWW-Authenticate header" if param_string.empty?

  params = parse_wwwauth_digest(param_string)
  qop = params[:qop]

  user, pass = username_and_password_for_realm(url, params[:realm])

  if params[:algorithm] == "MD5"
    a1 = user + ":" + params[:realm] + ":" + pass
  else
    # XXX MD5-sess
    raise "I only support MD5 digest authentication (not #{params[:algorithm].inspect})"
  end

  if qop.nil? or qop.member? "auth"
    a2 = req.method + ":" + req.path
  else
    # XXX auth-int
    raise "only 'auth' qop supported (none of: #{qop.inspect})"
  end

  if qop.nil?
    response = kd(h(a1), params[:nonce] + ":" + h(a2))
  else
    @@nonce_count += 1
    nc = ('%08x' % @@nonce_count)

    # XXX auth-int
    data = "#{params[:nonce]}:#{nc}:#{CNONCE}:#{"auth"}:#{h(a2)}"

    response = kd(h(a1), data)
  end

  header = %Q<Digest username="#{user}", uri="#{req.path}", realm="#{params[:realm]}", response="#{response}", nonce="#{params[:nonce]}">

  if params[:opaque]
    header += %Q<, opaque="#{params[:opaque]}">
  end

  if params[:algorithm] != "MD5"
    header += ", algorithm=#{algo}"
  end

  if qop
    # XXX auth-int
    header += %Q<, nc=#{nc}, cnonce="#{CNONCE}", qop=auth>
  end

  req["Authorization"] = header
end

#h(data) ⇒ Object



41
# File 'lib/atom/http.rb', line 41

def h(data); Digest::MD5.hexdigest(data); end

#kd(secret, data) ⇒ Object



42
# File 'lib/atom/http.rb', line 42

def kd(secret, data); h(secret + ":" + data); end

#parse_wwwauth_digest(param_string) ⇒ Object

quoted-strings plus a few special cases for Digest



27
28
29
30
31
32
33
34
35
36
37
38
39
# File 'lib/atom/http.rb', line 27

def parse_wwwauth_digest param_string
  params = parse_quoted_wwwauth param_string
  qop = params[:qop] ? params[:qop].split(",") : nil

  param_string.gsub(/stale=([^,]*)/) do
    params[:stale] = ($1.downcase == "true")
  end

  params[:algorithm] = "MD5"
  param_string.gsub(/algorithm=([^,]*)/) { params[:algorithm] = $1 }

  params
end