[BUG/PATCH] cgi/session.rb

the following program with fail both the way it is, and using the commented
section:

   ~ > cat a.cgi
   #! /usr/local/bin/ruby

   require 'cgi'
   require 'cgi/session'

   cgi = CGI::new

   database_manager = CGI::Session::FileStore

   session =
   =begin
     begin
       s = CGI::Session::new cgi, 'database_manager' => database_manager, 'new_session' => false
       s.delete
       s
     rescue ArgumentError
       CGI::Session::new cgi, 'database_manager' => database_manager, 'new_session' => true
     end
   =end
       CGI::Session::new cgi, 'database_manager' => database_manager

   session.close

   this_time = Time::now
   last_time = session['last_time'] || this_time
   session['last_time'] = this_time
   session.close

   content = ''
   content << "<hr> THIS_TIME @ <b>#{ this_time }</b> <hr>"
   content << "<hr> LAST_TIME @ <b>#{ last_time }</b> <hr>"

   cgi.out{ content }

in either case a new session is __always__ created. the docs say:

...
   # A CGI::Session instance is created from a CGI object. By default,
   # this CGI::Session instance will start a new session if none currently
   # exists, or continue the current session for this client if one does
   # exist. The +new_session+ option can be used to either always or
   # never create a new session. See #new() for more details.
...

so there is no way to re-use a session attm. this seems serious. i think this
patch addresses the issue:

[ahoward@localhost build/ruby-1.8.2/lib/] diff -u -b -B cgi/session.rb.org cgi/session.rb
--- cgi/session.rb.org 2005-09-13 20:52:14.000000000 -0600
+++ cgi/session.rb 2005-09-13 20:53:32.000000000 -0600
@@ -244,7 +244,7 @@
      # end

···

#
      def initialize(request, option={})
- @new_session = false
+ @new_session = nil
        session_key = option['session_key'] || '_session_id'
        session_id = option['session_id']
        unless session_id
@@ -381,10 +381,11 @@
          md5 = Digest::MD5.hexdigest(id)[0,16]
         @path = dir+"/"+prefix+md5+suffix
         unless File::exist? @path
- unless session.new_session
+ unless session.new_session.nil?
              raise CGI::Session::NoSession, "uninitialized session"
            end
           @hash = {}
+ update
         end
        end

and, indeed, with the change the following works as expected/doccumented:

   #! /usr/local/bin/ruby
   require 'cgi'
   require './cgi/session'

   cgi = CGI::new
   content = ''
   database_manager = CGI::Session::FileStore
   this_time = Time::now

   begin
     session = CGI::Session::new cgi, 'database_manager' => database_manager
     last_time = session['last_time'] || this_time
     session['last_time'] = this_time
     session.close

     content << "<hr> THIS_TIME @ <b>#{ this_time }</b> <hr>"
     content << "<hr> LAST_TIME @ <b>#{ last_time }</b> <hr>"
   rescue Exception => e
     m, c, b = e.message, e.class, e.backtrace.join("\n")
     content << "<pre>#{ m } (#{ c })\n#{ b }</pre>"
   end
   cgi.out{ content }

hopefully this hasn't already been fixed - i searched for a while....

regards.

-a
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

CGI::Session::MemoryStore and CGI::Session::PStore suffer from same issue...
updated patches (in the right order this time):

--- ./cgi/session.rb.org 2005-09-13 20:52:14.000000000 -0600
+++ ./cgi/session.rb 2005-09-13 21:13:22.000000000 -0600
@@ -244,7 +244,7 @@
      # end

···

On Wed, 14 Sep 2005, Ara.T.Howard wrote:

      #
      def initialize(request, option={})
- @new_session = false
+ @new_session = nil
        session_key = option['session_key'] || '_session_id'
        session_id = option['session_id']
        unless session_id
@@ -381,10 +381,11 @@
          md5 = Digest::MD5.hexdigest(id)[0,16]
         @path = dir+"/"+prefix+md5+suffix
         unless File::exist? @path
- unless session.new_session
+ unless session.new_session.nil?
              raise CGI::Session::NoSession, "uninitialized session"
            end
           @hash = {}
+ update
         end
        end

@@ -451,7 +452,7 @@
        def initialize(session, option=nil)
         @session_id = session.session_id
          unless GLOBAL_HASH_TABLE.key?(@session_id)
- unless session.new_session
+ unless session.new_session.nil?
              raise CGI::Session::NoSession, "uninitialized session"
            end
            GLOBAL_HASH_TABLE[@session_id] = {}

--- ./cgi/session/pstore.rb.org 2005-09-13 21:07:52.000000000 -0600
+++ ./cgi/session/pstore.rb 2005-09-13 21:18:21.000000000 -0600
@@ -9,7 +9,7 @@
  # persistent of session data on top of the pstore library. See
  # cgi/session.rb for more details on session storage managers.

-require 'cgi/session'
+require './cgi/session'
  require 'pstore'

  class CGI
@@ -62,7 +62,7 @@
         path = dir+"/"+prefix+md5
         path.untaint
         unless File::exist?(path)
- unless session.new_session
+ unless session.new_session.nil?
              raise CGI::Session::NoSession, "uninitialized session"
            end
           @hash = {}

now i'm noticing that the create of session is not atomic... but that's for
another day.

-a
--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

Hi,

···

In message "Re: [BUG/PATCH] cgi/session.rb" on Wed, 14 Sep 2005 12:00:21 +0900, "Ara.T.Howard" <Ara.T.Howard@noaa.gov> writes:

the following program with fail both the way it is, and using the commented
section:

  ~ > cat a.cgi
  #! /usr/local/bin/ruby

  require 'cgi'
  require 'cgi/session'

  cgi = CGI::new

  database_manager = CGI::Session::FileStore

  session =
  =begin
    begin
      s = CGI::Session::new cgi, 'database_manager' => database_manager, 'new_session' => false
      s.delete
      s
    rescue ArgumentError
      CGI::Session::new cgi, 'database_manager' => database_manager, 'new_session' => true
    end
  =end
      CGI::Session::new cgi, 'database_manager' => database_manager

  session.close

  this_time = Time::now
  last_time = session['last_time'] || this_time
  session['last_time'] = this_time
  session.close

  content = ''
  content << "<hr> THIS_TIME @ <b>#{ this_time }</b> <hr>"
  content << "<hr> LAST_TIME @ <b>#{ last_time }</b> <hr>"

  cgi.out{ content }

in either case a new session is __always__ created. the docs say:

Can you explain how it fails? "the way it is" version seems to work
for me. Perhaps you have expected something different from me.

              matz.

Hi,

At Wed, 14 Sep 2005 12:23:52 +0900,
Ara.T.Howard wrote in [ruby-talk:156036]:

--- ./cgi/session.rb.org 2005-09-13 20:52:14.000000000 -0600
+++ ./cgi/session.rb 2005-09-13 21:13:22.000000000 -0600
@@ -244,7 +244,7 @@
      # end
      #
      def initialize(request, option={})
- @new_session = false
+ @new_session = nil
        session_key = option['session_key'] || '_session_id'
        session_id = option['session_id']
        unless session_id
@@ -381,10 +381,11 @@
          md5 = Digest::MD5.hexdigest(id)[0,16]
         @path = dir+"/"+prefix+md5+suffix
         unless File::exist? @path
- unless session.new_session
+ unless session.new_session.nil?

What does this change?

--- ./cgi/session/pstore.rb.org 2005-09-13 21:07:52.000000000 -0600
+++ ./cgi/session/pstore.rb 2005-09-13 21:18:21.000000000 -0600
@@ -9,7 +9,7 @@
  # persistent of session data on top of the pstore library. See
  # cgi/session.rb for more details on session storage managers.

-require 'cgi/session'
+require './cgi/session'

Library starts with "./" directs `require' to load from
current working directory. I guess this isn't intended
change.

···

--
Nobu Nakada

hmmm. it seems there is more to it than i thought, if i browse this script:

   [ahoward@localhost ~]$ cat /var/www/html/acgi/acgi-0.0.0/a.cgi
   #! /usr/local/bin/ruby
   require 'cgi'
   require 'cgi/session'
   require 'cgi/session/pstore'

   cgi = CGI::new
   content = ''
   database_manager = CGI::Session::PStore
   this_time = Time::now

   begin
     session = CGI::Session::new cgi, 'database_manager' => database_manager

     last_time = session['last_time'] || this_time
     session['last_time'] = this_time
     session.close

     content << "THIS_TIME : #{ this_time }\n"
     content << "LAST_TIME : #{ last_time }\n"
     content << "SCRIPT_FILENAME : #{ ENV['SCRIPT_FILENAME'] }\n"
     content << "SESSION_ID : #{ session.session_id }\n"
   rescue Exception => e
     m, c, b = e.message, e.class, e.backtrace.join("\n")
     content << "#{ m } (#{ c })\n#{ b }"
   end
   cgi.out('type' => 'text/plain'){ content }

from, for example:

   http://localhost/acgi/acgi-0.0.0/a.cgi

i get something like:

   THIS_TIME : Tue Sep 13 23:22:41 MDT 2005
   LAST_TIME : Tue Sep 13 23:22:41 MDT 2005
   SCRIPT_FILENAME : /var/www/html/acgi/acgi-0.0.0/a.cgi
   SESSION_ID : 63cdc2ee2c075a914d6943947951b19b

and then refreshing:

   THIS_TIME : Tue Sep 13 23:22:59 MDT 2005
   LAST_TIME : Tue Sep 13 23:22:59 MDT 2005
   SCRIPT_FILENAME : /var/www/html/acgi/acgi-0.0.0/a.cgi
   SESSION_ID : c7d7588139a5270da345ee54c89ed88b

but from:

   http://fortytwo.merseine.nu/acgi/acgi-0.0.0/a.cgi

i will get:

   THIS_TIME : Tue Sep 13 23:23:29 MDT 2005
   LAST_TIME : Tue Sep 13 23:22:17 MDT 2005
   SCRIPT_FILENAME : /var/www/html/acgi/acgi-0.0.0/a.cgi
   SESSION_ID : 814ca3261d52515d3e1d9d608dc80a16

followed by:

   THIS_TIME : Tue Sep 13 23:23:50 MDT 2005
   LAST_TIME : Tue Sep 13 23:23:29 MDT 2005
   SCRIPT_FILENAME : /var/www/html/acgi/acgi-0.0.0/a.cgi
   SESSION_ID : 814ca3261d52515d3e1d9d608dc80a16

so in the first the session is re-created each time and in the second not. so
the bug only appears from localhost? or is this not a bug but expected
behaviour? i'm very tired so perhaps it is ;-( is HTTP_COOKIE handled
differently for localhost or something? i looked in the source both nothing
jumped out at me.

adding HTTP_COOKIE info i see, from http://localhost/acgi/acgi-0.0.0/a.cgi

   THIS_TIME : Tue Sep 13 23:32:26 MDT 2005
   LAST_TIME : Tue Sep 13 23:32:26 MDT 2005
   SCRIPT_FILENAME : /var/www/html/acgi/acgi-0.0.0/a.cgi
   SESSION_ID : 05d50f3762602883a9a00678495757f5
   HTTP_COOKIE : _session_id=5437f16e1ee85101db5a049a8a4a883c; _session_id=d3e4867caa8ea724c6023e91031a2374; _session_id=e17d91c033811031d235e34c1404d188

and from http://fortytwo.merseine.nu/acgi/acgi-0.0.0/a.cgi

   THIS_TIME : Tue Sep 13 23:33:36 MDT 2005
   LAST_TIME : Tue Sep 13 23:32:22 MDT 2005
   SCRIPT_FILENAME : /var/www/html/acgi/acgi-0.0.0/a.cgi
   SESSION_ID : 814ca3261d52515d3e1d9d608dc80a16
   HTTP_COOKIE : _session_id=814ca3261d52515d3e1d9d608dc80a16; _session_id=6058a54f8ca5d206f7c8c35b0800a406

sorry if this ends up being noise - this simply isn't making sense attm.

btw. i've run this

   [ahoward@localhost tmp]$ ls|egrep '^\w{16}$'|xargs -n1 sudo rm -f

out of /tmp many time to clean up old sessions - results are always the same.

-a

···

On Wed, 14 Sep 2005, Yukihiro Matsumoto wrote:

Can you explain how it fails? "the way it is" version seems to work for me.
Perhaps you have expected something different from me.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

Hi,

···

In message "Re: [BUG/PATCH] cgi/session.rb" on Wed, 14 Sep 2005 14:35:50 +0900, "Ara.T.Howard" <Ara.T.Howard@noaa.gov> writes:

so in the first the session is re-created each time and in the second not. so
the bug only appears from localhost? or is this not a bug but expected
behaviour? i'm very tired so perhaps it is ;-( is HTTP_COOKIE handled
differently for localhost or something? i looked in the source both nothing
jumped out at me.

Something must be different. I can't think of anything though.

              matz.

that's right - too tired - going to bed ;-(

-a

···

On Wed, 14 Sep 2005, nobuyoshi nakada wrote:

--- ./cgi/session/pstore.rb.org 2005-09-13 21:07:52.000000000 -0600
+++ ./cgi/session/pstore.rb 2005-09-13 21:18:21.000000000 -0600
@@ -9,7 +9,7 @@
  # persistent of session data on top of the pstore library. See
  # cgi/session.rb for more details on session storage managers.

-require 'cgi/session'
+require './cgi/session'

Library starts with "./" directs `require' to load from
current working directory. I guess this isn't intended
change.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

can you reproduce? or is it just me?

-a

···

On Wed, 14 Sep 2005, Yukihiro Matsumoto wrote:

Hi,

In message "Re: [BUG/PATCH] cgi/session.rb" > on Wed, 14 Sep 2005 14:35:50 +0900, "Ara.T.Howard" <Ara.T.Howard@noaa.gov> writes:

>so in the first the session is re-created each time and in the second not. so
>the bug only appears from localhost? or is this not a bug but expected
>behaviour? i'm very tired so perhaps it is ;-( is HTTP_COOKIE handled
>differently for localhost or something? i looked in the source both nothing
>jumped out at me.

Something must be different. I can't think of anything though.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

Hi,

···

In message "Re: [BUG/PATCH] cgi/session.rb" on Wed, 14 Sep 2005 14:56:16 +0900, "Ara.T.Howard" <Ara.T.Howard@noaa.gov> writes:

Something must be different. I can't think of anything though.

can you reproduce? or is it just me?

I couldn't. Mine worked fine, even on localhost.

              matz.

I've seen problems in the past where certain versions of Firefox and
other browsers did not handle cookies for localhost and other domains
without '.' in them. This might be the problem. Check your cookie cache
and see if a cookie is being set.

paul

Yukihiro Matsumoto wrote:

···

Hi,

In message "Re: [BUG/PATCH] cgi/session.rb" > on Wed, 14 Sep 2005 14:56:16 +0900, "Ara.T.Howard" <Ara.T.Howard@noaa.gov> writes:

>> Something must be different. I can't think of anything though.
>
>can you reproduce? or is it just me?

I couldn't. Mine worked fine, even on localhost.

              matz.

o.k. - i finally can reproduce from either localhost or hostname. you can see
problem and solution here

   http://fortytwo.merseine.nu/a.cgi

essentially it boils down to Cookie::parse blowing up if multiple comma
separated key=value pairs show up. for example

   harp:~ > ruby -r cgi -e "p( CGI::cookie::parse('k=v0, k=v1') )"
   {"k"=>["v0, k=v1"]}

   harp:~ > ruby -r cgi -e "p( CGI::cookie::parse('k=v0; k=v1') )"
   {"k"=>["v0"]}

of course the question is what, exactly, the http spec has to say about those
raw cookie string formats. i'm certainly no expert here. however, it seems
that mozilla and firefox (latest) both spit out comma separted k=v pairs under
certain condition so it may be wise to handle this case anyhoe. i'm not sure
my patch it the best way to fix - but it was the least amount of code i could
write to fix the issue.

i did a little googling and comma does, in fact, seem to an acceptable k=v
pair separator:

...
   Note: For backward compatibility, the separator in the Cookie header
   is semi-colon (:wink: everywhere. A server SHOULD also accept comma (,)
   as the separator between cookie-values for future compatibility.
...

from

   http://www.ietf.org/rfc/rfc2965.txt

this

   http://wp.netscape.com/newsref/std/cookie_spec.html

also suggests commas may be used as separator since

...
  NAME=VALUE
      This string is a sequence of characters excluding semi-colon, comma and
      white space. If there is a need to place such data in the name or value,
      some encoding method such as URL style %XX encoding is recommended,
      though no encoding is defined or required.
...

and i would assume the reason semi-colon and comma are disallowed is because
they are reserved as pair separators. it doesn't actually say why it is not
allowed, however.

regards.

ps. i never did figure out how/why my browsers decided to place commas in the
HTTP_COOKIE post, but they (mozilla, firefox) both did at several points
during testing (somehow related to browsing from localhost). the cgi just
emulates this behaviour to show the bug.

-a

···

On Wed, 14 Sep 2005, Yukihiro Matsumoto wrote:

Hi,

In message "Re: [BUG/PATCH] cgi/session.rb" > on Wed, 14 Sep 2005 14:56:16 +0900, "Ara.T.Howard" <Ara.T.Howard@noaa.gov> writes:

>> Something must be different. I can't think of anything though.
>
>can you reproduce? or is it just me?

I couldn't. Mine worked fine, even on localhost.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================

this is defintely something to do with it. i've been able to duplicate it
twice today in different servers - but still can't pin down exactly which
conditions trigger it. it seems something to do with having multiple
_session_id fields in HTTP_COOKIE and - possibly - having no prior session
storage. it's like some set of conditions sets it up to fail repeatedly but,
if the conditions arise for it to succeed it will continute to succeed... any
thoughts?

cheers.

-a

···

On Thu, 15 Sep 2005, Paul wrote:

I've seen problems in the past where certain versions of Firefox and other
browsers did not handle cookies for localhost and other domains without '.'
in them. This might be the problem. Check your cookie cache and see if a
cookie is being set.

--

email :: ara [dot] t [dot] howard [at] noaa [dot] gov
phone :: 303.497.6469
Your life dwells amoung the causes of death
Like a lamp standing in a strong breeze. --Nagarjuna

===============================================================================