summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorshyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-03 05:34:11 +0000
committershyouhei <shyouhei@b2dd03c8-39d4-4d8f-98ff-823fe69b080e>2009-02-03 05:34:11 +0000
commit299a69922c1811df80805197da8131d5da97ab21 (patch)
treecf390ab2fb1e367f21f832c8f8375ba2bbac990e
parente50a1dc13d0e4e2c41dfe67327463964c3122621 (diff)
merge revision(s) 19774:
* lib/net/pop.rb: check for invalid APOP timestamp. (CVE-2007-1558) [ruby-dev:36631] * test/net/pop/test_pop.rb: ditto. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/branches/ruby_1_8_6@22000 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r--ChangeLog7
-rw-r--r--lib/net/pop.rb2
-rw-r--r--test/net/pop/test_pop.rb132
-rw-r--r--version.h8
4 files changed, 144 insertions, 5 deletions
diff --git a/ChangeLog b/ChangeLog
index 14582e0906..90f7f20302 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+Tue Feb 3 14:33:08 2009 Kazuhiro NISHIYAMA <zn@mbf.nifty.com>
+
+ * lib/net/pop.rb: check for invalid APOP timestamp. (CVE-2007-1558)
+ [ruby-dev:36631]
+
+ * test/net/pop/test_pop.rb: ditto.
+
Mon Feb 2 20:03:00 2009 Nobuyoshi Nakada <nobu@ruby-lang.org>
* time.c (time_mdump, time_mload): preserves GMT status.
diff --git a/lib/net/pop.rb b/lib/net/pop.rb
index 6d1343eded..f896464df9 100644
--- a/lib/net/pop.rb
+++ b/lib/net/pop.rb
@@ -752,7 +752,7 @@ module Net
@socket = sock
@error_occured = false
res = check_response(critical { recv_response() })
- @apop_stamp = res.slice(/<.+>/)
+ @apop_stamp = res.slice(/<[!-~]+@[!-~]+>/)
end
def inspect
diff --git a/test/net/pop/test_pop.rb b/test/net/pop/test_pop.rb
new file mode 100644
index 0000000000..c8aa9a83a8
--- /dev/null
+++ b/test/net/pop/test_pop.rb
@@ -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
diff --git a/version.h b/version.h
index 16458bc95e..12f0db8412 100644
--- a/version.h
+++ b/version.h
@@ -1,15 +1,15 @@
#define RUBY_VERSION "1.8.6"
-#define RUBY_RELEASE_DATE "2009-02-02"
+#define RUBY_RELEASE_DATE "2009-02-03"
#define RUBY_VERSION_CODE 186
-#define RUBY_RELEASE_CODE 20090202
-#define RUBY_PATCHLEVEL 317
+#define RUBY_RELEASE_CODE 20090203
+#define RUBY_PATCHLEVEL 318
#define RUBY_VERSION_MAJOR 1
#define RUBY_VERSION_MINOR 8
#define RUBY_VERSION_TEENY 6
#define RUBY_RELEASE_YEAR 2009
#define RUBY_RELEASE_MONTH 2
-#define RUBY_RELEASE_DAY 2
+#define RUBY_RELEASE_DAY 3
#ifdef RUBY_EXTERN
RUBY_EXTERN const char ruby_version[];