summaryrefslogtreecommitdiff
path: root/lib/cgi/session.rb
diff options
context:
space:
mode:
Diffstat (limited to 'lib/cgi/session.rb')
-rw-r--r--lib/cgi/session.rb97
1 files changed, 64 insertions, 33 deletions
diff --git a/lib/cgi/session.rb b/lib/cgi/session.rb
index 63c5003526..70c7ebca42 100644
--- a/lib/cgi/session.rb
+++ b/lib/cgi/session.rb
@@ -1,3 +1,4 @@
+# frozen_string_literal: true
#
# cgi/session.rb - session support for cgi scripts
#
@@ -163,29 +164,72 @@ class CGI
# Create a new session id.
#
- # The session id is an MD5 hash based upon the time,
- # a random number, and a constant string. This routine
- # is used internally for automatically generated
- # session ids.
+ # The session id is a secure random number by SecureRandom
+ # if possible, otherwise an SHA512 hash based upon the time,
+ # a random number, and a constant string. This routine is
+ # used internally for automatically generated session ids.
def create_new_id
require 'securerandom'
begin
+ # by OpenSSL, or system provided entropy pool
session_id = SecureRandom.hex(16)
rescue NotImplementedError
- require 'digest/md5'
- md5 = Digest::MD5::new
+ # never happens on modern systems
+ require 'digest'
+ d = Digest('SHA512').new
now = Time::now
- md5.update(now.to_s)
- md5.update(String(now.usec))
- md5.update(String(rand(0)))
- md5.update(String($$))
- md5.update('foobar')
- session_id = md5.hexdigest
+ d.update(now.to_s)
+ d.update(String(now.usec))
+ d.update(String(rand(0)))
+ d.update(String($$))
+ d.update('foobar')
+ session_id = d.hexdigest[0, 32]
end
session_id
end
private :create_new_id
+
+ # Create a new file to store the session data.
+ #
+ # This file will be created if it does not exist, or opened if it
+ # does.
+ #
+ # This path is generated under _tmpdir_ from _prefix_, the
+ # digested session id, and _suffix_.
+ #
+ # +option+ is a hash of options for the initializer. The
+ # following options are recognised:
+ #
+ # tmpdir:: the directory to use for storing the FileStore
+ # file. Defaults to Dir::tmpdir (generally "/tmp"
+ # on Unix systems).
+ # prefix:: the prefix to add to the session id when generating
+ # the filename for this session's FileStore file.
+ # Defaults to "cgi_sid_".
+ # suffix:: the prefix to add to the session id when generating
+ # the filename for this session's FileStore file.
+ # Defaults to the empty string.
+ def new_store_file(option={}) # :nodoc:
+ dir = option['tmpdir'] || Dir::tmpdir
+ prefix = option['prefix']
+ suffix = option['suffix']
+ require 'digest/md5'
+ md5 = Digest::MD5.hexdigest(session_id)[0,16]
+ path = dir+"/"
+ path << prefix if prefix
+ path << md5
+ path << suffix if suffix
+ if File::exist? path
+ hash = nil
+ elsif new_session
+ hash = {}
+ else
+ raise NoSession, "uninitialized session"
+ end
+ return path, hash
+ end
+
# Create a new CGI::Session object for +request+.
#
# +request+ is an instance of the +CGI+ class (see cgi.rb).
@@ -370,21 +414,8 @@ class CGI
# This session's FileStore file will be created if it does
# not exist, or opened if it does.
def initialize(session, option={})
- dir = option['tmpdir'] || Dir::tmpdir
- prefix = option['prefix'] || 'cgi_sid_'
- suffix = option['suffix'] || ''
- id = session.session_id
- require 'digest/md5'
- md5 = Digest::MD5.hexdigest(id)[0,16]
- @path = dir+"/"+prefix+md5+suffix
- if File::exist? @path
- @hash = nil
- else
- unless session.new_session
- raise CGI::Session::NoSession, "uninitialized session"
- end
- @hash = {}
- end
+ option = {'prefix' => 'cgi_sid_'}.update(option)
+ @path, @hash = session.new_store_file(option)
end
# Restore session state from the session's FileStore file.
@@ -400,11 +431,11 @@ class CGI
for line in f
line.chomp!
k, v = line.split('=',2)
- @hash[CGI::unescape(k)] = Marshal.restore(CGI::unescape(v))
+ @hash[CGI.unescape(k)] = Marshal.restore(CGI.unescape(v))
end
ensure
- f.close unless f.nil?
- lockf.close if lockf
+ f&.close
+ lockf&.close
end
end
@hash
@@ -418,13 +449,13 @@ class CGI
lockf.flock File::LOCK_EX
f = File.open(@path+".new", File::CREAT|File::TRUNC|File::WRONLY, 0600)
for k,v in @hash
- f.printf "%s=%s\n", CGI::escape(k), CGI::escape(String(Marshal.dump(v)))
+ f.printf "%s=%s\n", CGI.escape(k), CGI.escape(String(Marshal.dump(v)))
end
f.close
File.rename @path+".new", @path
ensure
- f.close if f and !f.closed?
- lockf.close if lockf
+ f&.close
+ lockf&.close
end
end