Fixed logic error; multi host chicken and egg finger printing causes hosts to never join
This commit is contained in:
@@ -107,7 +107,10 @@ func (s *Server) handleConn(ctx context.Context, raw net.Conn) {
|
||||
if err := tlsConn.HandshakeContext(ctx); err != nil {
|
||||
return
|
||||
}
|
||||
peerID := peerNodeIDFromConnState(tlsConn.ConnectionState())
|
||||
state := tlsConn.ConnectionState()
|
||||
peerID := peerNodeIDFromConnState(state)
|
||||
peerFP := peerFingerprintFromConnState(state)
|
||||
trusted := s.peerTrusted(peerFP)
|
||||
|
||||
for {
|
||||
body, err := readFrame(tlsConn)
|
||||
@@ -120,6 +123,14 @@ func (s *Server) handleConn(ctx context.Context, raw net.Conn) {
|
||||
return
|
||||
}
|
||||
|
||||
// Until the peer is trusted, only the bootstrap call (Join) is
|
||||
// allowed through. Everything else gets a clear error so the
|
||||
// caller knows to re-run `qu node add`.
|
||||
if !trusted && req.Method != MethodJoin {
|
||||
_ = writeError(tlsConn, req.ID, "peer not trusted; run `qu node add` first")
|
||||
continue
|
||||
}
|
||||
|
||||
fn, exists := s.handlers[req.Method]
|
||||
if !exists {
|
||||
_ = writeError(tlsConn, req.ID, "unknown method: "+req.Method)
|
||||
@@ -134,9 +145,26 @@ func (s *Server) handleConn(ctx context.Context, raw net.Conn) {
|
||||
if err := writeResult(tlsConn, req.ID, result); err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
// A successful Join writes the caller into our trust store;
|
||||
// re-check so subsequent calls on this same connection (or
|
||||
// after reconnect) flow through normally.
|
||||
if req.Method == MethodJoin && !trusted {
|
||||
trusted = s.peerTrusted(peerFP)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// peerTrusted reports whether peerFP is in our trust store. Returns
|
||||
// false on empty input so a missing/parse-failed cert is never trusted.
|
||||
func (s *Server) peerTrusted(peerFP string) bool {
|
||||
if peerFP == "" {
|
||||
return false
|
||||
}
|
||||
_, ok := s.assets.Trust.LookupByFingerprint(peerFP)
|
||||
return ok
|
||||
}
|
||||
|
||||
// Client opens and pools one mTLS connection per peer node ID. Each
|
||||
// connection serialises outstanding calls under a mutex; concurrent
|
||||
// calls to different peers proceed in parallel.
|
||||
@@ -321,3 +349,13 @@ func peerNodeIDFromConnState(cs tls.ConnectionState) string {
|
||||
}
|
||||
return cs.PeerCertificates[0].Subject.CommonName
|
||||
}
|
||||
|
||||
// peerFingerprintFromConnState computes the SPKI fingerprint of the
|
||||
// peer's leaf cert, matching the format the trust store stores. An
|
||||
// empty result means the peer presented no cert.
|
||||
func peerFingerprintFromConnState(cs tls.ConnectionState) string {
|
||||
if len(cs.PeerCertificates) == 0 {
|
||||
return ""
|
||||
}
|
||||
return fingerprintOf(cs.PeerCertificates[0])
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user