Close view-only input, approval-responder and inbound-block gaps in the VNC path

This commit is contained in:
Viktor Liu
2026-08-27 21:07:03 +02:00
parent e426401941
commit ab472f572d
5 changed files with 148 additions and 2 deletions
+10
View File
@@ -1039,6 +1039,16 @@ func (s *Server) acquireVirtualSession(conn net.Conn, header *connectionHeader,
(*connLog).Warn("session rejected: no username provided")
return nil, nil, nil, false
}
// The requested geometry comes off the wire and is handed straight to the X
// server, which allocates a framebuffer for it. The cap the rest of the
// pipeline enforces is only checked once the capturer is up, which is too
// late to stop a peer asking for 65535x65535. Zero means "use the default".
if header.width > maxFramebufferDim || header.height > maxFramebufferDim {
rejectConnection(conn, codeMessage(RejectCodeBadRequest,
fmt.Sprintf("requested geometry out of range: %dx%d", header.width, header.height)))
(*connLog).Warnf("session rejected: requested %dx%d exceeds cap %d", header.width, header.height, maxFramebufferDim)
return nil, nil, nil, false
}
vs, err := s.vmgr.GetOrCreate(header.username, header.width, header.height)
if err != nil {
rejectConnection(conn, codeMessage(RejectCodeSessionError, fmt.Sprintf("create virtual session: %v", err)))
+13 -1
View File
@@ -68,6 +68,12 @@ func (s *session) handleCutText() error {
if _, err := io.ReadFull(s.conn, buf); err != nil {
return fmt.Errorf("read CutText payload: %w", err)
}
// Writing the host clipboard changes host state, so a view-only session
// must not do it either. The payload is read first regardless, to leave the
// stream positioned at the next message.
if s.viewOnly {
return nil
}
s.injector.SetClipboard(latin1ToUTF8(buf))
return nil
}
@@ -184,7 +190,7 @@ func (s *session) handleExtClipProvide(flags uint32, payload []byte) {
s.log.Debugf("parse ext clipboard provide: %v", err)
return
}
if text != "" {
if text != "" && !s.viewOnly {
s.injector.SetClipboard(text)
}
}
@@ -254,6 +260,12 @@ func (s *session) handleTypeText() error {
if _, err := io.ReadFull(s.conn, buf); err != nil {
return fmt.Errorf("read TypeText payload: %w", err)
}
// Synthesized keystrokes are input like any other, so a view-only session
// must not deliver them. The payload is read first regardless, to leave the
// stream positioned at the next message.
if s.viewOnly {
return nil
}
s.injector.TypeText(string(buf))
return nil
}