From 8befa29f8124a05ae8e2d51701297a950bd8a493 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Fri, 23 May 2008 19:24:20 +0000 Subject: [PATCH] - client: if GUI RPC auth error, close the socket. This prevents a DoS by sending over and over, filling the send buffer and eventually causing the client to block. - Unix build: if m4 missing, check for gm4 svn path=/trunk/boinc/; revision=15282 --- _autosetup | 2 ++ checkin_notes | 11 +++++++++++ client/gui_rpc_server.C | 12 +++++++++++- client/gui_rpc_server.h | 6 +++++- client/gui_rpc_server_ops.C | 21 +++++++++++++-------- doc/get_platforms.inc | 1 + 6 files changed, 43 insertions(+), 10 deletions(-) diff --git a/_autosetup b/_autosetup index 696f0c79a3..3a1a794040 100755 --- a/_autosetup +++ b/_autosetup @@ -90,6 +90,8 @@ check_version() if test -f /usr/ccs/bin/m4 then echo >/dev/null + elif check_version gm4 1.4; then + have_gm4=yes; else echo "Couldn't find a new-enough version of 'm4', please install one!"; exit 1; diff --git a/checkin_notes b/checkin_notes index d158a79f9b..c2cd74d76a 100644 --- a/checkin_notes +++ b/checkin_notes @@ -4266,3 +4266,14 @@ David May 23 2008 sched/ sched_config.C,h sched_send.C + +David May 23 2008 + - client: if GUI RPC auth error, close the socket. + This prevents a DoS by sending over and over, + filling the send buffer and eventually causing the client to block. + - Unix build: if m4 missing, check for gm4 + + _autosetup + client/ + gui_rpc_server.C,h + gui_rpc_server_ops.C diff --git a/client/gui_rpc_server.C b/client/gui_rpc_server.C index 72bd7623d1..9d8a56053a 100644 --- a/client/gui_rpc_server.C +++ b/client/gui_rpc_server.C @@ -66,6 +66,8 @@ GUI_RPC_CONN::GUI_RPC_CONN(int s): auth_needed = false; au_ss_state = AU_SS_INIT; au_mgr_state = AU_MGR_INIT; + got_auth1 = false; + got_auth2 = false; } GUI_RPC_CONN::~GUI_RPC_CONN() { @@ -414,6 +416,12 @@ void GUI_RPC_CONN_SET::got_select(FDSET_GROUP& fg) { if (FD_ISSET(gr->sock, &fg.read_fds)) { retval = gr->handle_rpc(); if (retval) { + if (log_flags.guirpc_debug) { + msg_printf(NULL, MSG_INFO, + "[guirpc_debug] error %d from handler, closing socket\n", + retval + ); + } delete gr; iter = gui_rpcs.erase(iter); continue; @@ -425,7 +433,9 @@ void GUI_RPC_CONN_SET::got_select(FDSET_GROUP& fg) { void GUI_RPC_CONN_SET::close() { if (log_flags.guirpc_debug) { - msg_printf(NULL, MSG_INFO, "[guirpc_debug] closing GUI RPC socket %d\n", lsock); + msg_printf(NULL, MSG_INFO, + "[guirpc_debug] closing GUI RPC listening socket %d\n", lsock + ); } if (lsock >= 0) { boinc_close_socket(lsock); diff --git a/client/gui_rpc_server.h b/client/gui_rpc_server.h index 79454bad4e..845531efe4 100644 --- a/client/gui_rpc_server.h +++ b/client/gui_rpc_server.h @@ -42,6 +42,10 @@ public: char nonce[256]; bool auth_needed; // if true, don't allow operations other than authentication + bool got_auth1; + bool got_auth2; + // keep track of whether we've got the 2 authentication msgs; + // don't accept more than one of each (to prevent DoS) bool is_local; // connection is from local host int au_ss_state; @@ -55,7 +59,7 @@ public: ~GUI_RPC_CONN(); int handle_rpc(); void handle_auth1(MIOFILE&); - void handle_auth2(char*, MIOFILE&); + int handle_auth2(char*, MIOFILE&); void handle_get_project_config(char* buf, MIOFILE& fout); void handle_get_project_config_poll(char*, MIOFILE& fout); void handle_lookup_account(char* buf, MIOFILE& fout); diff --git a/client/gui_rpc_server_ops.C b/client/gui_rpc_server_ops.C index 0776513562..e4a042b4d3 100644 --- a/client/gui_rpc_server_ops.C +++ b/client/gui_rpc_server_ops.C @@ -68,20 +68,21 @@ void GUI_RPC_CONN::handle_auth1(MIOFILE& fout) { fout.printf("%s\n", nonce); } -void GUI_RPC_CONN::handle_auth2(char* buf, MIOFILE& fout) { +int GUI_RPC_CONN::handle_auth2(char* buf, MIOFILE& fout) { char nonce_hash[256], nonce_hash_correct[256], buf2[256]; if (!parse_str(buf, "", nonce_hash, 256)) { auth_failure(fout); - return; + return ERR_AUTHENTICATOR; } sprintf(buf2, "%s%s", nonce, gstate.gui_rpcs.password); md5_block((const unsigned char*)buf2, (int)strlen(buf2), nonce_hash_correct); if (strcmp(nonce_hash, nonce_hash_correct)) { auth_failure(fout); - return; + return ERR_AUTHENTICATOR; } fout.printf("\n"); auth_needed = false; + return 0; } // client passes its version, but ignore it for now @@ -985,7 +986,7 @@ static void handle_set_cc_config(char* buf, MIOFILE& fout) { int GUI_RPC_CONN::handle_rpc() { char request_msg[4096]; - int n; + int n, retval=0; MIOFILE mf; MFILE m; char* p; @@ -1011,12 +1012,16 @@ int GUI_RPC_CONN::handle_rpc() { mf.printf("\n"); if (match_tag(request_msg, "