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)



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

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



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

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

#kd(secret, data) ⇒ Object



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

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

#parse_wwwauth_digest(param_string) ⇒ Object

quoted-strings plus a few special cases for Digest



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

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