Code

frontend: Handle missing authentication early.
authorSebastian Harl <sh@tokkee.org>
Wed, 14 May 2014 18:55:29 +0000 (20:55 +0200)
committerSebastian Harl <sh@tokkee.org>
Wed, 14 May 2014 18:55:29 +0000 (20:55 +0200)
… and limit the max amount of buffered data for unauthenticated connections in
order reduce the impact of anonymous DoS attempts.

src/frontend/connection.c
t/unit/frontend/connection_test.c

index b91393997d6588cb631779230dc57b19cdf0ea22..dba431049ac8af878f2c6df85779d57012531218 100644 (file)
@@ -265,14 +265,6 @@ command_handle(sdb_conn_t *conn)
        sdb_log(SDB_LOG_DEBUG, "frontend: Handling command %u (len: %u)",
                        conn->cmd, conn->cmd_len);
 
-       if ((! conn->username) && (conn->cmd != CONNECTION_STARTUP)) {
-               const char *errmsg = "Authentication required";
-               sdb_strbuf_sprintf(conn->errbuf, errmsg);
-               sdb_connection_send(conn, CONNECTION_ERROR,
-                               (uint32_t)strlen(errmsg), errmsg);
-               return -1;
-       }
-
        switch (conn->cmd) {
                case CONNECTION_PING:
                        status = sdb_connection_ping(conn);
@@ -379,7 +371,16 @@ command_init(sdb_conn_t *conn)
        conn->cmd = connection_get_int32(conn, 0);
        conn->cmd_len = connection_get_int32(conn, sizeof(uint32_t));
 
-       if (conn->cmd == CONNECTION_IDLE) {
+       if ((! conn->username) && (conn->cmd != CONNECTION_STARTUP)) {
+               const char *errmsg = "Authentication required";
+               sdb_strbuf_sprintf(conn->errbuf, errmsg);
+               sdb_connection_send(conn, CONNECTION_ERROR,
+                               (uint32_t)strlen(errmsg), errmsg);
+               conn->skip_len += conn->cmd_len;
+               conn->cmd = CONNECTION_IDLE;
+               conn->cmd_len = 0;
+       }
+       else if (conn->cmd == CONNECTION_IDLE) {
                const char *errmsg = "Invalid command 0";
                sdb_strbuf_sprintf(conn->errbuf, errmsg);
                sdb_connection_send(conn, CONNECTION_ERROR,
index 43322e02adf00c7c852642e6a685263a44c8f3fd..a069903d1f19b3ef2d82134f39a1060c3e431d7f 100644 (file)
@@ -169,7 +169,7 @@ mock_client(void *arg)
 } /* mock_client */
 
 static void
-connection_setup(sdb_conn_t *conn)
+connection_startup(sdb_conn_t *conn)
 {
        ssize_t check, expected;
 
@@ -191,7 +191,7 @@ connection_setup(sdb_conn_t *conn)
                        "buffer; expected: 0", sdb_strbuf_len(conn->errbuf));
 
        mock_conn_truncate(conn);
-} /* connection_setup */
+} /* connection_startup */
 
 /*
  * tests
@@ -238,7 +238,7 @@ START_TEST(test_conn_setup)
        } golden_data[] = {
                /* code == UINT32_MAX => no data will be sent */
                { UINT32_MAX,         NULL,       NULL },
-               { CONNECTION_IDLE,    "fakedata", "Invalid command 0" },
+               { CONNECTION_IDLE,    "fakedata", "Authentication required" },
                { CONNECTION_PING,    NULL,       "Authentication required" },
                { CONNECTION_STARTUP, "fakeuser", NULL },
                { CONNECTION_PING,    NULL,       NULL },
@@ -308,23 +308,28 @@ START_TEST(test_conn_io)
                const char *err;
        } golden_data[] = {
                /* code == UINT32_MAX => this is a follow-up package */
-               { CONNECTION_PING, 20, "9876543210", 10, NULL },
-               { UINT32_MAX,      -1, "9876543210",  0, NULL },
-               { CONNECTION_IDLE, 20, "9876543210",  0, "Invalid command 0" },
-               { UINT32_MAX,      -1, "9876543210",  0, "Invalid command 0" },
-               { CONNECTION_IDLE, 20, "9876543210",  0, "Invalid command 0" },
-               { UINT32_MAX,      -1, "9876543210",  0, "Invalid command 0" },
-               { CONNECTION_PING, 10, "9876543210",  0, NULL },
-               { CONNECTION_PING, 20, "9876543210", 10, NULL },
-               { UINT32_MAX,      -1, "9876543210",  0, NULL },
+               { CONNECTION_PING,    20, "9876543210",  0, "Authentication required" },
+               { UINT32_MAX,         -1, "9876543210",  0, "Authentication required" },
+               { CONNECTION_PING,    10, "9876543210",  0, "Authentication required" },
+               { CONNECTION_IDLE,    10, "9876543210",  0, "Authentication required" },
+               { CONNECTION_IDLE,    20, "9876543210",  0, "Authentication required" },
+               { UINT32_MAX,         -1, "9876543210",  0, "Authentication required" },
+               { CONNECTION_STARTUP, -1, NULL,          0, NULL },
+               { CONNECTION_PING,    20, "9876543210", 10, NULL },
+               { UINT32_MAX,         -1, "9876543210",  0, NULL },
+               { CONNECTION_IDLE,    20, "9876543210",  0, "Invalid command 0" },
+               { UINT32_MAX,         -1, "9876543210",  0, "Invalid command 0" },
+               { CONNECTION_IDLE,    20, "9876543210",  0, "Invalid command 0" },
+               { UINT32_MAX,         -1, "9876543210",  0, "Invalid command 0" },
+               { CONNECTION_PING,    10, "9876543210",  0, NULL },
+               { CONNECTION_PING,    20, "9876543210", 10, NULL },
+               { UINT32_MAX,         -1, "9876543210",  0, NULL },
        };
 
        size_t i;
 
-       connection_setup(conn);
-
        for (i = 0; i < SDB_STATIC_ARRAY_LEN(golden_data); ++i) {
-               size_t msg_len = strlen(golden_data[i].msg);
+               size_t msg_len = golden_data[i].msg ? strlen(golden_data[i].msg) : 0;
                char buffer[2 * sizeof(uint32_t) + msg_len];
                size_t offset = 0;
 
@@ -332,6 +337,11 @@ START_TEST(test_conn_io)
 
                mock_conn_truncate(conn);
 
+               if (golden_data[i].code == CONNECTION_STARTUP) {
+                       connection_startup(conn);
+                       continue;
+               }
+
                if (golden_data[i].code != UINT32_MAX) {
                        uint32_t tmp;