Blame SOURCES/memcached-CVE-2013-7239.patch

4b0545
commit 87c1cf0f20be20608d3becf854e9cf0910f4ad32
4b0545
Author: 伊藤洋也 <hiroyan@gmail.com>
4b0545
Date:   Fri Dec 20 18:49:54 2013 +0000
4b0545
4b0545
    explicitly record sasl auth states
4b0545
    
4b0545
    It was previously possible to bypass authentication due to implicit
4b0545
    state management.  Now we explicitly consider ourselves
4b0545
    unauthenticated on any new connections and authentication attempts.
4b0545
    
4b0545
    bug316
4b0545
    
4b0545
    Signed-off-by: Dustin Sallings <dustin@spy.net>
4b0545
4b0545
diff --git a/memcached.c b/memcached.c
4b0545
index f129865..3a79fba 100644
4b0545
--- a/memcached.c
4b0545
+++ b/memcached.c
4b0545
@@ -457,6 +457,7 @@ conn *conn_new(const int sfd, enum conn_states init_state,
4b0545
     c->iovused = 0;
4b0545
     c->msgcurr = 0;
4b0545
     c->msgused = 0;
4b0545
+    c->authenticated = false;
4b0545
 
4b0545
     c->write_and_go = init_state;
4b0545
     c->write_and_free = 0;
4b0545
@@ -1637,6 +1638,8 @@ static void init_sasl_conn(conn *c) {
4b0545
     if (!settings.sasl)
4b0545
         return;
4b0545
 
4b0545
+    c->authenticated = false;
4b0545
+
4b0545
     if (!c->sasl_conn) {
4b0545
         int result=sasl_server_new("memcached",
4b0545
                                    NULL,
4b0545
@@ -1771,6 +1774,7 @@ static void process_bin_complete_sasl_auth(conn *c) {
4b0545
 
4b0545
     switch(result) {
4b0545
     case SASL_OK:
4b0545
+        c->authenticated = true;
4b0545
         write_bin_response(c, "Authenticated", 0, 0, strlen("Authenticated"));
4b0545
         pthread_mutex_lock(&c->thread->stats.mutex);
4b0545
         c->thread->stats.auth_cmds++;
4b0545
@@ -1807,11 +1811,7 @@ static bool authenticated(conn *c) {
4b0545
         rv = true;
4b0545
         break;
4b0545
     default:
4b0545
-        if (c->sasl_conn) {
4b0545
-            const void *uname = NULL;
4b0545
-            sasl_getprop(c->sasl_conn, SASL_USERNAME, &uname);
4b0545
-            rv = uname != NULL;
4b0545
-        }
4b0545
+        rv = c->authenticated;
4b0545
     }
4b0545
 
4b0545
     if (settings.verbose > 1) {
4b0545
diff --git a/memcached.h b/memcached.h
4b0545
index 45b3213..7c212d5 100644
4b0545
--- a/memcached.h
4b0545
+++ b/memcached.h
4b0545
@@ -376,6 +376,7 @@ typedef struct conn conn;
4b0545
 struct conn {
4b0545
     int    sfd;
4b0545
     sasl_conn_t *sasl_conn;
4b0545
+    bool authenticated;
4b0545
     enum conn_states  state;
4b0545
     enum bin_substates substate;
4b0545
     struct event event;
4b0545
diff --git a/t/binary-sasl.t b/t/binary-sasl.t
4b0545
index 69a05c2..85ef069 100755
4b0545
--- a/t/binary-sasl.t
4b0545
+++ b/t/binary-sasl.t
4b0545
@@ -13,7 +13,7 @@ use Test::More;
4b0545
 
4b0545
 if (supports_sasl()) {
4b0545
     if ($ENV{'RUN_SASL_TESTS'}) {
4b0545
-        plan tests => 25;
4b0545
+        plan tests => 33;
4b0545
     } else {
4b0545
         plan skip_all => 'Skipping SASL tests';
4b0545
         exit 0;
4b0545
@@ -229,6 +229,38 @@ $check->('x','somevalue');
4b0545
 }
4b0545
 $empty->('x');
4b0545
 
4b0545
+{
4b0545
+    my $mc = MC::Client->new;
4b0545
+
4b0545
+    # Attempt bad authentication.
4b0545
+    is ($mc->authenticate('testuser', 'wrongpassword'), 0x20, "bad auth");
4b0545
+
4b0545
+    # This should fail because $mc is not authenticated
4b0545
+    my ($status, $val)= $mc->set('x', "somevalue");
4b0545
+    ok($status, "this fails to authenticate");
4b0545
+    cmp_ok($status,'==',ERR_AUTH_ERROR, "error code matches");
4b0545
+}
4b0545
+$empty->('x', 'somevalue');
4b0545
+
4b0545
+{
4b0545
+    my $mc = MC::Client->new;
4b0545
+
4b0545
+    # Attempt bad authentication.
4b0545
+    is ($mc->authenticate('testuser', 'wrongpassword'), 0x20, "bad auth");
4b0545
+
4b0545
+    # Mix an authenticated connection and an unauthenticated connection to
4b0545
+    # confirm c->authenticated is not shared among connections
4b0545
+    my $mc2 = MC::Client->new;
4b0545
+    is ($mc2->authenticate('testuser', 'testpass'), 0, "authenticated");
4b0545
+    my ($status, $val)= $mc2->set('x', "somevalue");
4b0545
+    ok(! $status);
4b0545
+
4b0545
+    # This should fail because $mc is not authenticated
4b0545
+    ($status, $val)= $mc->set('x', "somevalue");
4b0545
+    ok($status, "this fails to authenticate");
4b0545
+    cmp_ok($status,'==',ERR_AUTH_ERROR, "error code matches");
4b0545
+}
4b0545
+
4b0545
 # check the SASL stats, make sure they track things correctly
4b0545
 # note: the enabled or not is presence checked in stats.t
4b0545
 
4b0545
@@ -241,8 +273,8 @@ $empty->('x');
4b0545
 
4b0545
 {
4b0545
     my %stats = $mc->stats('');
4b0545
-    is ($stats{'auth_cmds'}, 2, "auth commands counted");
4b0545
-    is ($stats{'auth_errors'}, 1, "auth errors correct");
4b0545
+    is ($stats{'auth_cmds'}, 5, "auth commands counted");
4b0545
+    is ($stats{'auth_errors'}, 3, "auth errors correct");
4b0545
 }
4b0545
 
4b0545