This file is indexed.

/usr/lib/ruby/vendor_ruby/innate/session.rb is in ruby-innate 2013.02.21-1.

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
169
170
module Innate

  # Mostly ported from Ramaze, but behaves lazy, no session will be created if
  # no session is used.
  #
  # We keep session data in memory until #flush is called, at which point it
  # will be persisted completely into the cache, no question asked.
  #
  # You may store anything in here that you may also store in the corresponding
  # store, usually it's best to keep it to things that are safe to Marshal.
  #
  # The Session instance is compatible with the specification of rack.session.
  #
  # Since the Time class is used to create the cookie expiration timestamp, you
  # will have to keep the ttl in a reasonable range.
  # The maximum value that Time can store on a 32bit system is:
  #   Time.at(2147483647) # => Tue Jan 19 12:14:07 +0900 2038
  #
  # The default expiration time for cookies and the session cache was reduced
  # to a default of 30 days.
  # This was done to be compatible with the maximum ttl of MemCache. You may
  # increase this value if you do not use MemCache to persist your sessions.
  class Session
    include Optioned

    options.dsl do
      o "Key for the session cookie",
        :key, 'innate.sid'
      o "Domain the cookie relates to, unspecified if false",
        :domain, false
      o "Path the cookie relates to",
        :path, '/'
      o "Use secure cookie",
        :secure, false
      o "Time of cookie expiration",
        :expires, nil
      o "Time to live for session cookies and cache, nil/false will prevent setting",
        :ttl, (60 * 60 * 24 * 30) # 30 days
      o "Length of generated Session ID (only applies when using SecureRandom)",
        :sid_length, 64
      o "cookie cannot be accessed through client side script (http://www.owasp.org/index.php/HttpOnly)",
        :httponly, false
    end

    attr_reader :cookie_set, :request, :response, :flash

    def initialize(request, response)
      @request, @response = request, response
      @cookie_set = false
      @force_new_cookie = false
      @cache_sid = nil
      @flash = Flash.new(self)
    end

    # Rack interface

    def store(key, value)
      cache_sid[key] = value
    end
    alias []= store

    def fetch(key, value = nil)
      cache_sid[key]
    end
    alias [] fetch

    def delete(key)
      cache_sid.delete(key)
    end

    def clear
      cache.delete(sid)
      @cache_sid = nil
    end

    # Additional interface

    def flush(response = @response)
      return if !@cache_sid or @cache_sid.empty?

      flash.rotate!
      cache.store(sid, cache_sid, :ttl => options.ttl)
      set_cookie(response)
    end

    def sid
      @sid ||= cookie || generate_sid
    end

    def resid!
      cache_sid
      cache.delete(sid)
      @sid = generate_sid
      @force_new_cookie = true
    end

    private

    def cache_sid
      @cache_sid ||= cache[sid] || {}
    end

    def cookie
      @request.cookies[options.key]
    end

    def cache
      Innate::Cache.session
    end

    def set_cookie(response)
      return if @cookie_set || (!@force_new_cookie && cookie)

      @cookie_set = true
      response.set_cookie(options.key, cookie_value)
      @force_new_cookie = false
    end

    def cookie_value
      o = options
      cookie = {
        :domain => o.domain,
        :path => o.path,
        :secure => o.secure,
        :httponly => o.httponly
      }
      cookie[:expires] = (Time.now + o.ttl) if o.ttl
      cookie.merge!(:value => sid)
    end

    def generate_sid
      begin sid = sid_algorithm end while cache[sid]
      sid
    end

    begin
      require 'securerandom'

      # Using SecureRandom, optional length.
      # SecureRandom is available since Ruby 1.8.7.
      # For Ruby versions earlier than that, you can require the uuidtools gem,
      # which has a drop-in replacement for SecureRandom.
      def sid_algorithm; SecureRandom.hex(options.sid_length); end
    rescue LoadError
      require 'openssl'

      # Using OpenSSL::Random for generation, this is comparable in performance
      # with stdlib SecureRandom and also allows for optional length, it should
      # have the same behaviour as the SecureRandom::hex method of the
      # uuidtools gem.
      def sid_algorithm
        OpenSSL::Random.random_bytes(options.sid_length / 2).unpack('H*')[0]
      end
    rescue LoadError
      warn "Falling back to low-entropy Session ID generation"
      warn "Avoid this by upgrading Ruby, installing OpenSSL, or UUIDTools"

      # Digest::SHA2::hexdigest produces a string of length 64, although
      # collisions are not very likely, the entropy is still very low and
      # length is not optional.
      #
      # Replacing it with OS-provided random data would take a lot of code and
      # won't be as cross-platform as Ruby.
      def sid_algorithm
        entropy = [ srand, rand, Time.now.to_f, rand, $$, rand, object_id ]
        Digest::SHA2.hexdigest(entropy.join)
      end
    end
  end
end