diff options
-rw-r--r-- | ChangeLog | 7 | ||||
-rw-r--r-- | lib/net/pop.rb | 2 | ||||
-rw-r--r-- | test/net/pop/test_pop.rb | 132 | ||||
-rw-r--r-- | version.h | 8 |
4 files changed, 144 insertions, 5 deletions
@@ -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 6d1343ede..f896464df 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 000000000..c8aa9a83a --- /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 @@ -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[]; |