diff --git a/internal/server/server.go b/internal/server/server.go index ddfd9bd..48c7f3e 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -233,6 +233,7 @@ func (s *Server) handleStream(ctx context.Context, stream *quic.Stream, sess *Se func (s *Server) handleGetChallenge(sess *Session) { challenge := auth.NewChallenge(s.cfg.PoW.Difficulty) + sess.SetChallenge(challenge) if st := sess.Stream(); st != nil { st.WriteFrame(byte(types.OpChallenge), challenge.Marshal()) } @@ -245,7 +246,12 @@ func (s *Server) handleSolve(sess *Session, payload []byte) { return } - challenge := auth.NewChallenge(s.cfg.PoW.Difficulty) + challenge := sess.GetChallenge() + if challenge == nil { + sendOpError(sess.Stream(), types.ErrPoWInvalid, "no challenge issued") + return + } + if err := challenge.Verify(solution, s.cfg.PoW.ChallengeTTL); err != nil { sendOpError(sess.Stream(), types.ErrPoWInvalid, err.Error()) return diff --git a/internal/server/session.go b/internal/server/session.go index f472cc6..3208227 100644 --- a/internal/server/session.go +++ b/internal/server/session.go @@ -4,6 +4,7 @@ import ( "sync" "github.com/apernet/quic-go" + "github.com/niko/qcc/internal/auth" "github.com/niko/qcc/internal/protocol" "github.com/niko/qcc/internal/transport" ) @@ -18,7 +19,8 @@ type Session struct { pubKey [32]byte certDER []byte - activeCallID uint64 + activeCallID uint64 + lastChallenge *auth.PoWChallenge } func NewSession(conn *quic.Conn) *Session { @@ -90,3 +92,15 @@ func (s *Session) ClearCall() { defer s.mu.Unlock() s.activeCallID = 0 } + +func (s *Session) SetChallenge(c *auth.PoWChallenge) { + s.mu.Lock() + defer s.mu.Unlock() + s.lastChallenge = c +} + +func (s *Session) GetChallenge() *auth.PoWChallenge { + s.mu.Lock() + defer s.mu.Unlock() + return s.lastChallenge +}