From 8c7d44c8dc24eaef33bc845b2dba7c38590436ec Mon Sep 17 00:00:00 2001
From: Dave Collins <davec@conformal.com>
Date: Sat, 18 Jan 2014 00:03:31 -0600
Subject: [PATCH] Add authentication deadline to RPC server cnxns.

Previously it was possible to open a connection to the RPC server, never
authenticate, and idle forever.

This is work toward #68.
---
 rpcserver.go    | 12 +++++++++++-
 rpcwebsocket.go |  7 +++++++
 2 files changed, 18 insertions(+), 1 deletion(-)

diff --git a/rpcserver.go b/rpcserver.go
index 1add3136d..407b0bf1c 100644
--- a/rpcserver.go
+++ b/rpcserver.go
@@ -31,6 +31,10 @@ import (
 	"time"
 )
 
+// rpcAuthTimeoutSeconds is the number of seconds a connection to the RPC server
+// is allowed to stay open without authenticating before it is closed.
+const rpcAuthTimeoutSeconds = 10
+
 // Errors
 var (
 	// ErrBadParamsField describes an error where the parameters JSON
@@ -137,7 +141,13 @@ func (s *rpcServer) Start() {
 
 	rpcsLog.Trace("Starting RPC server")
 	rpcServeMux := http.NewServeMux()
-	httpServer := &http.Server{Handler: rpcServeMux}
+	httpServer := &http.Server{
+		Handler: rpcServeMux,
+
+		// Timeout connections which don't complete the initial
+		// handshake within the allowed timeframe.
+		ReadTimeout: time.Second * rpcAuthTimeoutSeconds,
+	}
 	rpcServeMux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
 		if err := s.checkAuth(r); err != nil {
 			jsonAuthFail(w, r, s)
diff --git a/rpcwebsocket.go b/rpcwebsocket.go
index 0bf3550bb..1454bab43 100644
--- a/rpcwebsocket.go
+++ b/rpcwebsocket.go
@@ -18,8 +18,11 @@ import (
 	"github.com/conformal/btcwire"
 	"github.com/conformal/btcws"
 	"sync"
+	"time"
 )
 
+var timeZeroVal time.Time
+
 type ntfnChan chan btcjson.Cmd
 
 type handlerChans struct {
@@ -546,6 +549,10 @@ func (s *rpcServer) RemoveWalletListener(n ntfnChan) {
 // connections from a btcwallet instance.  It reads messages from wallet and
 // sends back replies, as well as notififying wallets of chain updates.
 func (s *rpcServer) walletReqsNotifications(ws *websocket.Conn) {
+	// Clear the read deadline that was set before the websocket hijacked
+	// the connection.
+	ws.SetReadDeadline(timeZeroVal)
+
 	// Add wallet notification channel so this handler receives btcd chain
 	// notifications.
 	n := make(ntfnChan)