Write a missing signing request and give up on a handshake that never returns.
A certificate already on disk still has to be renewable, and a reflector that never finishes TLS must not hold the session past the login timers. Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
+28
-8
@@ -159,18 +159,34 @@ func (f *framed) Write(p []byte) (int, error) {
|
||||
|
||||
func (f *framed) setMax(n uint32) { f.max.Store(n) }
|
||||
|
||||
func (f *framed) startTLS(ctx context.Context, cfg *tls.Config) error {
|
||||
var errTLSTimeout = errors.New("tls timeout")
|
||||
|
||||
func (s *Station) startTLS(ctx context.Context, f *framed, cfg *tls.Config, until time.Time) error {
|
||||
select {
|
||||
case f.upgrade <- cfg:
|
||||
case <-ctx.Done():
|
||||
return ctx.Err()
|
||||
}
|
||||
_ = f.conn.SetReadDeadline(time.Now())
|
||||
wait := until.Sub(s.clock.Now())
|
||||
if wait < 0 {
|
||||
wait = 0
|
||||
}
|
||||
timer := s.clock.NewTimer(wait)
|
||||
defer timer.Stop()
|
||||
select {
|
||||
case err := <-f.up:
|
||||
return err
|
||||
case <-ctx.Done():
|
||||
_ = f.conn.SetDeadline(time.Now())
|
||||
return ctx.Err()
|
||||
case <-timer.C():
|
||||
_ = f.conn.SetDeadline(time.Now())
|
||||
select {
|
||||
case <-f.up:
|
||||
case <-ctx.Done():
|
||||
}
|
||||
return errTLSTimeout
|
||||
}
|
||||
}
|
||||
|
||||
@@ -348,7 +364,11 @@ func (s *Station) session(ctx context.Context, conn net.Conn, major uint16) erro
|
||||
switch reason {
|
||||
case "tcp":
|
||||
tcpRx = now.Add(15 * time.Second)
|
||||
err := s.onFrame(ctx, wire, major, tcpf, &ph, &authed, &client, &haveCert, done, &udpCh, &udpErr, &udpReady, &lastTCP)
|
||||
limit := tcpRx
|
||||
if udpRx.Before(limit) {
|
||||
limit = udpRx
|
||||
}
|
||||
err := s.onFrame(ctx, wire, major, tcpf, &ph, &authed, &client, &haveCert, done, &udpCh, &udpErr, &udpReady, &lastTCP, limit)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -428,7 +448,7 @@ func (s *Station) onClock(now time.Time) {
|
||||
}
|
||||
}
|
||||
|
||||
func (s *Station) onFrame(ctx context.Context, wire *framed, major uint16, f frame, ph *phase, authed *bool, client *tls.Certificate, haveCert *bool, done chan struct{}, udpCh *chan []byte, udpErr *chan error, udpReady *bool, lastTCP *time.Time) error {
|
||||
func (s *Station) onFrame(ctx context.Context, wire *framed, major uint16, f frame, ph *phase, authed *bool, client *tls.Certificate, haveCert *bool, done chan struct{}, udpCh *chan []byte, udpErr *chan error, udpReady *bool, lastTCP *time.Time, limit time.Time) error {
|
||||
switch f.typ {
|
||||
case tcpHeartbeat:
|
||||
return nil
|
||||
@@ -443,7 +463,7 @@ func (s *Station) onFrame(ctx context.Context, wire *framed, major uint16, f fra
|
||||
if major < 3 {
|
||||
return s.onV2(wire, f, ph, authed, done, udpCh, udpErr, udpReady, lastTCP)
|
||||
}
|
||||
return s.onV3(ctx, wire, f, ph, authed, client, haveCert, done, udpCh, udpErr, udpReady, lastTCP)
|
||||
return s.onV3(ctx, wire, f, ph, authed, client, haveCert, done, udpCh, udpErr, udpReady, lastTCP, limit)
|
||||
}
|
||||
|
||||
func (s *Station) onReflectorError(body []byte, major uint16) error {
|
||||
@@ -520,7 +540,7 @@ func (s *Station) answerChallenge(w io.Writer, body []byte, lastTCP *time.Time)
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Station) onV3(ctx context.Context, wire *framed, f frame, ph *phase, authed *bool, client *tls.Certificate, haveCert *bool, done chan struct{}, udpCh *chan []byte, udpErr *chan error, udpReady *bool, lastTCP *time.Time) error {
|
||||
func (s *Station) onV3(ctx context.Context, wire *framed, f frame, ph *phase, authed *bool, client *tls.Certificate, haveCert *bool, done chan struct{}, udpCh *chan []byte, udpErr *chan error, udpReady *bool, lastTCP *time.Time, limit time.Time) error {
|
||||
switch f.typ {
|
||||
case tcpCAInfo:
|
||||
if *ph != phCA {
|
||||
@@ -536,7 +556,7 @@ func (s *Station) onV3(ctx context.Context, wire *framed, f frame, ph *phase, au
|
||||
if *ph != phStart {
|
||||
return nil
|
||||
}
|
||||
return s.onStartEncryption(ctx, wire, ph, client, haveCert)
|
||||
return s.onStartEncryption(ctx, wire, ph, client, haveCert, limit)
|
||||
case tcpCsrReq:
|
||||
return s.sendCSR(wire, lastTCP)
|
||||
case tcpAuthChallenge:
|
||||
@@ -658,7 +678,7 @@ func (s *Station) onCABundle(w io.Writer, body []byte, ph *phase, lastTCP *time.
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *Station) onStartEncryption(ctx context.Context, wire *framed, ph *phase, client *tls.Certificate, haveCert *bool) error {
|
||||
func (s *Station) onStartEncryption(ctx context.Context, wire *framed, ph *phase, client *tls.Certificate, haveCert *bool, limit time.Time) error {
|
||||
pair, present, fatal := prepareIdentity(s.cfg.certificateDir, s.cfg.callsign)
|
||||
if fatal != "" {
|
||||
s.endFatal(fatal, true)
|
||||
@@ -675,7 +695,7 @@ func (s *Station) onStartEncryption(ctx context.Context, wire *framed, ph *phase
|
||||
if err != nil {
|
||||
return s.retry("TLS handshake failed")
|
||||
}
|
||||
if err := wire.startTLS(ctx, cfg); err != nil {
|
||||
if err := s.startTLS(ctx, wire, cfg, limit); err != nil {
|
||||
if errors.Is(err, errHostMismatch) {
|
||||
return s.retry("Reflector certificate does not match the host")
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user