Extra ticket hash validation before using db/rpc.

Provides extra protection against DoS.
This commit is contained in:
jholdstock 2020-06-15 10:29:18 +01:00 committed by David Hill
parent 5af2f595ac
commit 3a76d44113
3 changed files with 23 additions and 6 deletions

1
go.mod
View File

@ -5,6 +5,7 @@ go 1.13
require (
decred.org/dcrwallet v1.2.3-0.20200519180100-f1aa4c354e05
github.com/decred/dcrd/blockchain/stake/v3 v3.0.0-20200607041702-62fa0661bd57
github.com/decred/dcrd/chaincfg/chainhash v1.0.2
github.com/decred/dcrd/chaincfg/v3 v3.0.0-20200607041702-62fa0661bd57
github.com/decred/dcrd/dcrec v1.0.0
github.com/decred/dcrd/dcrutil/v3 v3.0.0-20200607041702-62fa0661bd57

View File

@ -128,10 +128,10 @@ func (c *DcrdRPC) GetTicketCommitmentAddress(ticketHash string, netParams *chain
// Ensure transaction is a valid ticket.
if !stake.IsSStx(msgTx) {
return "", errors.New("invalid transcation - not sstx")
return "", errors.New("invalid transaction - not sstx")
}
if len(msgTx.TxOut) != 3 {
return "", fmt.Errorf("invalid transcation - expected 3 outputs, got %d", len(msgTx.TxOut))
return "", fmt.Errorf("invalid transaction - expected 3 outputs, got %d", len(msgTx.TxOut))
}
// Get ticket commitment address.

View File

@ -4,6 +4,7 @@ import (
"net/http"
"strings"
"github.com/decred/dcrd/chaincfg/chainhash"
"github.com/decred/vspd/rpc"
"github.com/gin-gonic/gin"
"github.com/gin-gonic/gin/binding"
@ -64,8 +65,8 @@ func requireAdmin() gin.HandlerFunc {
}
}
// withDcrdClient middleware adds a dcrd client to the request
// context for downstream handlers to make use of.
// withDcrdClient middleware adds a dcrd client to the request context for
// downstream handlers to make use of.
func withDcrdClient(dcrd rpc.DcrdConnect) gin.HandlerFunc {
return func(c *gin.Context) {
client, err := dcrd.Client(c, cfg.NetParams)
@ -126,6 +127,21 @@ func vspAuth() gin.HandlerFunc {
}
hash := request.TicketHash
// Before hitting the db or any RPC, ensure this is a valid ticket hash.
// A ticket hash should be 64 chars (MaxHashStringSize) and should parse
// into a chainhash.Hash without error.
if len(hash) != chainhash.MaxHashStringSize {
log.Errorf("Invalid hash from %s: incorrect length", c.ClientIP())
sendErrorWithMsg("invalid ticket hash", errBadRequest, c)
return
}
_, err = chainhash.NewHashFromStr(hash)
if err != nil {
log.Errorf("Invalid hash from %s: %v", c.ClientIP(), err)
sendErrorWithMsg("invalid ticket hash", errBadRequest, c)
return
}
// Check if this ticket already appears in the database.
ticket, ticketFound, err := db.GetTicketByHash(hash)
if err != nil {
@ -134,8 +150,8 @@ func vspAuth() gin.HandlerFunc {
return
}
// If the ticket was found in the database we already know its commitment
// address. Otherwise we need to get it from the chain.
// If the ticket was found in the database, we already know its
// commitment address. Otherwise we need to get it from the chain.
var commitmentAddress string
if ticketFound {
commitmentAddress = ticket.CommitmentAddress