Skip to content

Commit

Permalink
track timestamp usage in ticket auth routine
Browse files Browse the repository at this point in the history
  • Loading branch information
itswisdomagain committed Aug 1, 2019
1 parent e3b9ac7 commit a2f89e6
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 7 deletions.
19 changes: 13 additions & 6 deletions v3api/ticketauth.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,8 +41,8 @@ func (v3Api *V3API) validateTicketOwnership(authHeader string) (multiSigAddress

// todo check if ticket belongs to this vsp

// check if timestamp is not yet expired
if err := validateTimestamp(timestamp, v3Api.ticketChallengeMaxAge); err != nil {
// check if timestamp is not yet expired and has not been used previously
if err := v3Api.validateTimestamp(timestamp, v3Api.ticketChallengeMaxAge); err != nil {
log.Warnf("ticket auth timestamp failed validation: %v", err)
return
}
Expand Down Expand Up @@ -97,19 +97,26 @@ func getAuthValueFromParam(paramKeyValue, key string) string {
return ""
}

func validateTimestamp(timestampMessage string, ticketChallengeMaxAge int64) error {
func (v3Api *V3API) validateTimestamp(timestampMessage string, ticketChallengeMaxAge int64) error {
authTimestamp, err := strconv.Atoi(timestampMessage)
if err != nil {
return fmt.Errorf("invalid v3 auth request timestamp %v: %v", timestampMessage, err)
return fmt.Errorf("invalid timestamp value %v: %v", timestampMessage, err)
}

// todo ensure that timestamp had not been used in a previous authentication attempt
// Ensure that timestamp had not been used in a previous authentication attempt.
if v3Api.processedTicketChallenges.containsChallenge(timestampMessage) {
return fmt.Errorf("disallowed reuse of timestamp value %v", timestampMessage)
}

// Ensure that the auth timestamp is not in the future and is not more than 30 seconds into the past.
timestampDelta := time.Now().Unix() - int64(authTimestamp)
if timestampDelta < 0 || timestampDelta > ticketChallengeMaxAge {
return fmt.Errorf("expired v3 auth request timestamp %v compared to %v", timestampMessage, time.Now().Unix())
return fmt.Errorf("expired timestamp value %v", timestampMessage)
}

// Save this timestamp value as used to prevent subsequent reuse.
challengeExpiresIn := ticketChallengeMaxAge - timestampDelta
v3Api.processedTicketChallenges.addChallenge(timestampMessage, challengeExpiresIn)

return nil
}
46 changes: 46 additions & 0 deletions v3api/ticketchallengescache.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,46 @@
package v3api

import (
"sync"
"time"
)

type ticketChallengesCache struct {
sync.Mutex
data map[string]int64 // [timestamp]expiry
}

func newTicketChallengesCache() *ticketChallengesCache {
cache := &ticketChallengesCache{
data: make(map[string]int64, 0),
}

go func() {
for now := range time.Tick(time.Second) {
cache.Lock()
for timestampChallenge, challengeExpiry := range cache.data {
if now.Unix() > challengeExpiry {
delete(cache.data, timestampChallenge)
}
}
cache.Unlock()
}
}()

return cache
}

func (cache *ticketChallengesCache) addChallenge(timestamp string, expiresIn int64) {
cache.Lock()
if _, ok := cache.data[timestamp]; !ok {
cache.data[timestamp] = time.Now().Unix() + expiresIn
}
cache.Unlock()
}

func (cache *ticketChallengesCache) containsChallenge(timestamp string) (exists bool) {
cache.Lock()
_, exists = cache.data[timestamp]
cache.Unlock()
return
}
7 changes: 6 additions & 1 deletion v3api/v3api.go
Original file line number Diff line number Diff line change
@@ -1,15 +1,20 @@
package v3api

import "github.com/decred/dcrstakepool/stakepooldclient"
import (
"github.com/decred/dcrstakepool/stakepooldclient"
)

type V3API struct {
stakepooldConnMan *stakepooldclient.StakepooldManager

ticketChallengeMaxAge int64
processedTicketChallenges *ticketChallengesCache
}

func New(stakepooldConnMan *stakepooldclient.StakepooldManager, ticketChallengeMaxAge int64) *V3API {
return &V3API{
stakepooldConnMan: stakepooldConnMan,
ticketChallengeMaxAge: ticketChallengeMaxAge,
processedTicketChallenges: newTicketChallengesCache(),
}
}

0 comments on commit a2f89e6

Please sign in to comment.