Class | Net::IMAP::DigestMD5Authenticator
In: | net/imap.rb
Parent: | Object

Authenticator for the "DIGEST-MD5" authentication type. See authenticate().

### Methods

new process

### Constants

STAGE_ONE | = | :stage_one
STAGE_TWO | = | :stage_two

### Public Class methods

new(user, password, authname = nil)

[Source]

    # File net/imap.rb, line 3154
          def initialize(user, password, authname = nil)
            @user, @password, @authname = user, password, authname
            @nc, @stage = {}, STAGE_ONE
          end

### Public Instance methods

process(challenge)

[Source]

    # File net/imap.rb, line 3089
          def process(challenge)
            case @stage
            when STAGE_ONE
              @stage = STAGE_TWO
              sparams = {}
              c = StringScanner.new(challenge)
              while c.scan(/(?:\s*,)?\s*(\w+)=("(?:[^\\"]+|\\.)*"|[^,]+)\s*/)
                k, v = c[1], c[2]
                if v =~ /^"(.*)"$/
                  v = $1
                  if v =~ /,/
                    v = v.split(',')
                  end
                end
                sparams[k] = v
              end

              raise DataFormatError, "Bad Challenge: '#{challenge}'" unless c.rest.size == 0
              raise Error, "Server does not support auth (qop = #{sparams['qop'].join(',')})" unless sparams['qop'].include?("auth")

              response = {
                :nonce => sparams['nonce'],
                :username => @user,
                :realm => sparams['realm'],
                :cnonce => Digest::MD5.hexdigest("%.15f:%.15f:%d" % [Time.now.to_f, rand, Process.pid.to_s]),
                'digest-uri''digest-uri' => 'imap/' + sparams['realm'],
                :qop => 'auth',
                :maxbuf => 65535,
                :nc => "%08d" % nc(sparams['nonce']),
                :charset => sparams['charset'],
              }

              response[:authzid] = @authname unless @authname.nil?

              # now, the real thing
              a0 = Digest::MD5.digest( [ response.values_at(:username, :realm), @password ].join(':') )

              a1 = [ a0, response.values_at(:nonce,:cnonce) ].join(':')
              a1 << ':' + response[:authzid] unless response[:authzid].nil?

              a2 = "AUTHENTICATE:" + response['digest-uri''digest-uri']
              a2 << ":00000000000000000000000000000000" if response[:qop] and response[:qop] =~ /^auth-(?:conf|int)$/

              response[:response] = Digest::MD5.hexdigest(
                [
                 Digest::MD5.hexdigest(a1),
                 response.values_at(:nonce, :nc, :cnonce, :qop),
                 Digest::MD5.hexdigest(a2)
                ].join(':')
              )

              return response.keys.map { |k| qdval(k.to_s, response[k]) }.join(',')
            when STAGE_TWO
              @stage = nil
              # if at the second stage, return an empty string
              if challenge =~ /rspauth=/
                return ''
              else
                raise ResponseParseError, challenge
              end
            else
              raise ResponseParseError, challenge
            end
          end

[Validate]