[前][次][番号順一覧][スレッド一覧]

ruby-changes:8246

From: kazu <ko1@a...>
Date: Tue, 14 Oct 2008 11:20:49 +0900 (JST)
Subject: [ruby-changes:8246] Ruby:r19774 (ruby_1_8): * lib/net/pop.rb: check for invalid APOP timestamp. (CVE-2007-1558)

kazu	2008-10-14 11:18:50 +0900 (Tue, 14 Oct 2008)

  New Revision: 19774

  http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=19774

  Log:
    * lib/net/pop.rb: check for invalid APOP timestamp. (CVE-2007-1558)
      [ruby-dev:36631]
    
    * test/net/pop/test_pop.rb: ditto.

  Added directories:
    branches/ruby_1_8/test/net/pop/
  Added files:
    branches/ruby_1_8/test/net/pop/test_pop.rb
  Modified files:
    branches/ruby_1_8/ChangeLog
    branches/ruby_1_8/lib/net/pop.rb

Index: ruby_1_8/ChangeLog
===================================================================
--- ruby_1_8/ChangeLog	(revision 19773)
+++ ruby_1_8/ChangeLog	(revision 19774)
@@ -1,3 +1,10 @@
+Tue Oct 14 11:14:26 2008  Kazuhiro NISHIYAMA  <zn@m...>
+
+	* lib/net/pop.rb: check for invalid APOP timestamp. (CVE-2007-1558)
+	  [ruby-dev:36631]
+
+	* test/net/pop/test_pop.rb: ditto.
+
 Sat Oct 11 10:20:17 2008  Nobuyoshi Nakada  <nobu@r...>
 
 	* lib/mkmf.rb (CLEANINGS): uses escaped form tabs to preventing the
Index: ruby_1_8/lib/net/pop.rb
===================================================================
--- ruby_1_8/lib/net/pop.rb	(revision 19773)
+++ ruby_1_8/lib/net/pop.rb	(revision 19774)
@@ -870,7 +870,7 @@
       @socket = sock
       @error_occured = false
       res = check_response(critical { recv_response() })
-      @apop_stamp = res.slice(/<.+>/)
+      @apop_stamp = res.slice(/<[!-~]+@[!-~]+>/)
     end
 
     def inspect
Index: ruby_1_8/test/net/pop/test_pop.rb
===================================================================
--- ruby_1_8/test/net/pop/test_pop.rb	(revision 0)
+++ ruby_1_8/test/net/pop/test_pop.rb	(revision 19774)
@@ -0,0 +1,132 @@
+require 'net/pop'
+require 'test/unit'
+require 'digest/md5'
+
+class TestPOP < Test::Unit::TestCase
+  def setup
+    @users = {'user' => 'pass' }
+    @ok_user = 'user'
+    @stamp_base = "#{$$}.#{Time.now.to_i}@localhost"
+  end
+
+  def test_pop_auth_ok
+    pop_test(false) do |pop|
+      assert_instance_of Net::POP3, pop
+      assert_nothing_raised do
+        pop.start(@ok_user, @users[@ok_user])
+      end
+    end
+  end
+
+  def test_pop_auth_ng
+    pop_test(false) do |pop|
+      assert_instance_of Net::POP3, pop
+      assert_raise Net::POPAuthenticationError do
+        pop.start(@ok_user, 'bad password')
+      end
+    end
+  end
+
+  def test_apop_ok
+    pop_test(@stamp_base) do |pop|
+      assert_instance_of Net::APOP, pop
+      assert_nothing_raised do
+        pop.start(@ok_user, @users[@ok_user])
+      end
+    end
+  end
+
+  def test_apop_ng
+    pop_test(@stamp_base) do |pop|
+      assert_instance_of Net::APOP, pop
+      assert_raise Net::POPAuthenticationError do
+        pop.start(@ok_user, 'bad password')
+      end
+    end
+  end
+
+  def test_apop_invalid
+    pop_test("\x80"+@stamp_base) do |pop|
+      assert_instance_of Net::APOP, pop
+      assert_raise Net::POPAuthenticationError do
+        pop.start(@ok_user, @users[@ok_user])
+      end
+    end
+  end
+
+  def test_apop_invalid_at
+    pop_test(@stamp_base.sub('@', '.')) do |pop|
+      assert_instance_of Net::APOP, pop
+      e = assert_raise Net::POPAuthenticationError do
+        pop.start(@ok_user, @users[@ok_user])
+      end
+    end
+  end
+
+  def pop_test(apop=false)
+    host = 'localhost'
+    server = TCPServer.new(host, 0)
+    port = server.addr[1]
+    thread = Thread.start do
+      sock = server.accept
+      begin
+        pop_server_loop(sock, apop)
+      ensure
+        sock.close
+      end
+    end
+    begin
+      pop = Net::POP3::APOP(apop).new(host, port)
+      #pop.set_debug_output $stderr
+      yield pop
+    ensure
+      begin
+        pop.finish
+      rescue IOError
+        raise unless $!.message == "POP session not yet started"
+      end
+    end
+  ensure
+    server.close
+    thread.value
+  end
+
+  def pop_server_loop(sock, apop)
+    if apop
+      sock.print "+OK ready <#{apop}>\r\n"
+    else
+      sock.print "+OK ready\r\n"
+    end
+    user = nil
+    while line = sock.gets
+      case line
+      when /^USER (.+)\r\n/
+        user = $1
+        if @users.key?(user)
+          sock.print "+OK\r\n"
+        else
+          sock.print "-ERR unknown user\r\n"
+        end
+      when /^PASS (.+)\r\n/
+        if @users[user] == $1
+          sock.print "+OK\r\n"
+        else
+          sock.print "-ERR invalid password\r\n"
+        end
+      when /^APOP (.+) (.+)\r\n/
+        user = $1
+        if apop && Digest::MD5.hexdigest("<#{apop}>#{@users[user]}") == $2
+          sock.print "+OK\r\n"
+        else
+          sock.print "-ERR authentication failed\r\n"
+        end
+      when /^QUIT/
+        sock.print "+OK bye\r\n"
+        return
+      else
+        sock.print "-ERR command not recognized\r\n"
+        return
+      end
+    end
+  end
+end

Property changes on: ruby_1_8/test/net/pop/test_pop.rb
___________________________________________________________________
Name: svn:eol-style
   + LF


--
ML: ruby-changes@q...
Info: http://www.atdot.net/~ko1/quickml/

[前][次][番号順一覧][スレッド一覧]