Merge pull request #1236 from syncthing/flag-safe

Reject Index and Request messages with unexpected flags
This commit is contained in:
Audrius Butkevicius 2015-01-11 12:40:40 +00:00
commit c95812353f

View File

@ -71,6 +71,10 @@ var (
ErrClosed = errors.New("connection closed") ErrClosed = errors.New("connection closed")
) )
// Specific variants of empty messages...
type pingMessage struct{ EmptyMessage }
type pongMessage struct{ EmptyMessage }
type Model interface { type Model interface {
// An index was received from the peer device // An index was received from the peer device
Index(deviceID DeviceID, folder string, files []FileInfo) Index(deviceID DeviceID, folder string, files []FileInfo)
@ -289,48 +293,60 @@ func (c *rawConnection) readerLoop() (err error) {
return err return err
} }
switch msg := msg.(type) {
case IndexMessage:
if msg.Flags != 0 {
// We don't currently support or expect any flags.
return fmt.Errorf("protocol error: unknown flags 0x%x in Index(Update) message", msg.Flags)
}
switch hdr.msgType { switch hdr.msgType {
case messageTypeIndex: case messageTypeIndex:
if c.state < stateCCRcvd { if c.state < stateCCRcvd {
return fmt.Errorf("protocol error: index message in state %d", c.state) return fmt.Errorf("protocol error: index message in state %d", c.state)
} }
c.handleIndex(msg.(IndexMessage)) c.handleIndex(msg)
c.state = stateIdxRcvd c.state = stateIdxRcvd
case messageTypeIndexUpdate: case messageTypeIndexUpdate:
if c.state < stateIdxRcvd { if c.state < stateIdxRcvd {
return fmt.Errorf("protocol error: index update message in state %d", c.state) return fmt.Errorf("protocol error: index update message in state %d", c.state)
} }
c.handleIndexUpdate(msg.(IndexMessage)) c.handleIndexUpdate(msg)
}
case messageTypeRequest: case RequestMessage:
if msg.Flags != 0 {
// We don't currently support or expect any flags.
return fmt.Errorf("protocol error: unknown flags 0x%x in Request message", msg.Flags)
}
if c.state < stateIdxRcvd { if c.state < stateIdxRcvd {
return fmt.Errorf("protocol error: request message in state %d", c.state) return fmt.Errorf("protocol error: request message in state %d", c.state)
} }
// Requests are handled asynchronously // Requests are handled asynchronously
go c.handleRequest(hdr.msgID, msg.(RequestMessage)) go c.handleRequest(hdr.msgID, msg)
case messageTypeResponse: case ResponseMessage:
if c.state < stateIdxRcvd { if c.state < stateIdxRcvd {
return fmt.Errorf("protocol error: response message in state %d", c.state) return fmt.Errorf("protocol error: response message in state %d", c.state)
} }
c.handleResponse(hdr.msgID, msg.(ResponseMessage)) c.handleResponse(hdr.msgID, msg)
case messageTypePing: case pingMessage:
c.send(hdr.msgID, messageTypePong, EmptyMessage{}) c.send(hdr.msgID, messageTypePong, pongMessage{})
case messageTypePong: case pongMessage:
c.handlePong(hdr.msgID) c.handlePong(hdr.msgID)
case messageTypeClusterConfig: case ClusterConfigMessage:
if c.state != stateInitial { if c.state != stateInitial {
return fmt.Errorf("protocol error: cluster config message in state %d", c.state) return fmt.Errorf("protocol error: cluster config message in state %d", c.state)
} }
go c.receiver.ClusterConfig(c.id, msg.(ClusterConfigMessage)) go c.receiver.ClusterConfig(c.id, msg)
c.state = stateCCRcvd c.state = stateCCRcvd
case messageTypeClose: case CloseMessage:
return errors.New(msg.(CloseMessage).Reason) return errors.New(msg.Reason)
default: default:
return fmt.Errorf("protocol error: %s: unknown message type %#x", c.id, hdr.msgType) return fmt.Errorf("protocol error: %s: unknown message type %#x", c.id, hdr.msgType)
@ -428,8 +444,11 @@ func (c *rawConnection) readMessage() (hdr header, msg encodable, err error) {
} }
msg = resp msg = resp
case messageTypePing, messageTypePong: case messageTypePing:
msg = EmptyMessage{} msg = pingMessage{}
case messageTypePong:
msg = pongMessage{}
case messageTypeClusterConfig: case messageTypeClusterConfig:
var cc ClusterConfigMessage var cc ClusterConfigMessage