This file is indexed.

/usr/lib/ruby/vendor_ruby/mechanize/http/www_authenticate_parser.rb is in ruby-mechanize 2.3-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
# coding: BINARY

require 'strscan'

##
# Parses the WWW-Authenticate HTTP header into separate challenges.

class Mechanize::HTTP::WWWAuthenticateParser

  attr_accessor :scanner # :nodoc:

  ##
  # Creates a new header parser for WWW-Authenticate headers

  def initialize
    @scanner = nil
  end

  ##
  # Parsers the header.  Returns an Array of challenges as strings

  def parse www_authenticate
    challenges = []
    @scanner = StringScanner.new www_authenticate

    while true do
      break if @scanner.eos?
      challenge = Mechanize::HTTP::AuthChallenge.new

      scheme = auth_scheme

      if scheme == 'Negotiate'
        scan_comma_spaces
      end

      next unless scheme
      challenge.scheme = scheme

      space = spaces

      if scheme == 'NTLM' then
        if space then
          challenge.params = @scanner.scan(/.*/)
        end

        challenges << challenge
        next
      end

      next unless space

      params = {}

      while true do
        pos = @scanner.pos
        name, value = auth_param

        unless name then
          challenge.params = params
          challenges << challenge
          break if @scanner.eos?

          @scanner.pos = pos # rewind
          challenge = '' # a token should be next, new challenge
          break
        else
          params[name] = value
        end

        spaces

        return nil unless ',' == @scanner.peek(1) or @scanner.eos?

        @scanner.scan(/(, *)+/)
      end
    end

    challenges
  end

  ##
  #   1*SP
  #
  # Parses spaces

  def spaces
    @scanner.scan(/ +/)
  end

  ##
  # scans a comma followed by spaces
  # needed for Negotiation, NTLM
  #

  def scan_comma_spaces
    @scanner.scan(/, +/)
  end

  ##
  #   token = 1*<any CHAR except CTLs or separators>
  #
  # Parses a token

  def token
    @scanner.scan(/[^\000-\037\177()<>@,;:\\"\/\[\]?={} ]+/)
  end

  ##
  #   auth-scheme = token
  #
  # Parses an auth scheme (a token)

  alias auth_scheme token

  ##
  #   auth-param = token "=" ( token | quoted-string )
  #
  # Parses an auth parameter

  def auth_param
    return nil unless name = token
    return nil unless @scanner.scan(/=/)

    value = if @scanner.peek(1) == '"' then
              quoted_string
            else
              token
            end

    return nil unless value

    return name, value
  end

  ##
  #   quoted-string = ( <"> *(qdtext | quoted-pair ) <"> )
  #   qdtext        = <any TEXT except <">>
  #   quoted-pair   = "\" CHAR
  #
  # For TEXT, the rules of RFC 2047 are ignored.

  def quoted_string
    return nil unless @scanner.scan(/"/)

    text = ''

    while true do
      chunk = @scanner.scan(/[\r\n \t\041\043-\176\200-\377]+/) # not "

      if chunk then
        text << chunk

        text << @scanner.get_byte if
          chunk.end_with? '\\' and '"' == @scanner.peek(1)
      else
        if '"' == @scanner.peek(1) then
          @scanner.get_byte
          break
        else
          return nil
        end
      end
    end

    text
  end

end