]> git.pond.sub.org Git - empserver/commitdiff
Fix player_login() to obey max_idle for output, too
authorMarkus Armbruster <armbru@pond.sub.org>
Sun, 11 Mar 2012 10:49:46 +0000 (11:49 +0100)
committerMarkus Armbruster <armbru@pond.sub.org>
Thu, 26 Apr 2012 17:43:41 +0000 (19:43 +0200)
player_login() flushes the output queue before receiving input.  The
receive obeys max_idle, the flush doesn't.  Which means a client could
hog the thread indefinitely.

Broken in commit 08b94556 (v4.3.20) "Reimplement max_idle without a
separate thread".  Until then, the idle thread aborted a stuck attempt
to flush output.

Denial of service seems possible.

src/lib/player/login.c

index 31afa27af762ec415a36853923183fdf8bb1aff4..ba415d8bfb28c441195b90a0ad43bea4ab162208 100644 (file)
@@ -76,6 +76,7 @@ static struct cmndstr login_coms[] = {
 void
 player_login(void *ud)
 {
 void
 player_login(void *ud)
 {
+    time_t deadline;
     char buf[128];
     char space[128];
     int ac;
     char buf[128];
     char space[128];
     int ac;
@@ -87,13 +88,14 @@ player_login(void *ud)
     pr_id(player, C_INIT, "Empire server ready\n");
 
     for (;;) {
     pr_id(player, C_INIT, "Empire server ready\n");
 
     for (;;) {
+       deadline = player->curup + minutes(max_idle);
        if (io_outputwaiting(player->iop)) {
        if (io_outputwaiting(player->iop)) {
-           if (io_output(player->iop, (time_t)-1) <= 0)
+           if (io_output(player->iop, deadline) <= 0)
                break;
            continue;
        }
        if (io_gets(player->iop, buf, sizeof(buf)) < 0) {
                break;
            continue;
        }
        if (io_gets(player->iop, buf, sizeof(buf)) < 0) {
-           res = io_input(player->iop, player->curup + minutes(max_idle));
+           res = io_input(player->iop, deadline);
            if (res <= 0) {
                if (res == 0 && !io_eof(player->iop))
                    pr_id(player, C_DATA, "idle connection terminated\n");
            if (res <= 0) {
                if (res == 0 && !io_eof(player->iop))
                    pr_id(player, C_DATA, "idle connection terminated\n");