Skip to content

Commit bb39617

Browse files
committed
Check for invalid values in CONNACK constituting protocol errors
1 parent 40df434 commit bb39617

File tree

1 file changed

+30
-5
lines changed

1 file changed

+30
-5
lines changed

mqttpacket.cpp

Lines changed: 30 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -977,29 +977,49 @@ ConnAckData MqttPacket::parseConnAckData()
977977
result.session_expire = std::min<uint32_t>(readFourBytesToUint32(), result.session_expire);
978978
break;
979979
case Mqtt5Properties::ReceiveMaximum:
980+
{
980981
if (pcounts[1]++ > 0)
981982
throw ProtocolError("Can't specify " + propertyToString(prop) + " more than once", ReasonCodes::ProtocolError);
982983

983-
result.client_receive_max = std::min<uint16_t>(readTwoBytesToUInt16(), result.client_receive_max);
984+
const uint16_t val{readTwoBytesToUInt16()};
985+
if (val == 0)
986+
throw ProtocolError("In CONNACK: ReceiveMax can't be 0", ReasonCodes::ProtocolError);
987+
result.client_receive_max = std::min<uint16_t>(val, result.client_receive_max);
984988
break;
989+
}
985990
case Mqtt5Properties::MaximumQoS:
991+
{
986992
if (pcounts[2]++ > 0)
987993
throw ProtocolError("Can't specify " + propertyToString(prop) + " more than once", ReasonCodes::ProtocolError);
988994

989-
result.max_qos = std::min<uint8_t>(readUint8(), result.max_qos);
995+
const uint8_t val {readUint8()};
996+
if (val > 2)
997+
throw ProtocolError("In CONNACK: QoS must be <= 2", ReasonCodes::ProtocolError);
998+
result.max_qos = std::min<uint8_t>(val, result.max_qos);
990999
break;
1000+
}
9911001
case Mqtt5Properties::RetainAvailable:
1002+
{
9921003
if (pcounts[3]++ > 0)
9931004
throw ProtocolError("Can't specify " + propertyToString(prop) + " more than once", ReasonCodes::ProtocolError);
9941005

995-
result.retained_available = static_cast<bool>(readByte());
1006+
const uint8_t val{readUint8()};
1007+
if (val > 1)
1008+
throw ProtocolError("In CONNACK: RetainAvailable must be <= 1", ReasonCodes::ProtocolError);
1009+
result.retained_available = static_cast<bool>(val);
9961010
break;
1011+
}
9971012
case Mqtt5Properties::MaximumPacketSize:
1013+
{
9981014
if (pcounts[4]++ > 0)
9991015
throw ProtocolError("Can't specify " + propertyToString(prop) + " more than once", ReasonCodes::ProtocolError);
10001016

1001-
result.max_outgoing_packet_size = std::min<uint32_t>(readFourBytesToUint32(), result.max_outgoing_packet_size);
1017+
const uint32_t val {readFourBytesToUint32()};
1018+
if (val == 0)
1019+
throw ProtocolError("In CONNACK: MaximumPacketSize must be > 0", ReasonCodes::ProtocolError);
1020+
result.max_outgoing_packet_size = std::min<uint32_t>(val, result.max_outgoing_packet_size);
10021021
break;
1022+
}
10031023
case Mqtt5Properties::AssignedClientIdentifier:
10041024
if (pcounts[5]++ > 0)
10051025
throw ProtocolError("Can't specify " + propertyToString(prop) + " more than once", ReasonCodes::ProtocolError);
@@ -1039,11 +1059,16 @@ ConnAckData MqttPacket::parseConnAckData()
10391059
readByte();
10401060
break;
10411061
case Mqtt5Properties::SharedSubscriptionAvailable:
1062+
{
10421063
if (pcounts[10]++ > 0)
10431064
throw ProtocolError("Can't specify " + propertyToString(prop) + " more than once", ReasonCodes::ProtocolError);
10441065

1045-
result.shared_subscriptions_available = !!readByte();
1066+
const uint8_t val{readUint8()};
1067+
if (val > 1)
1068+
throw ProtocolError("In CONNACK: SharedSubscriptionAvailable must be <= 1", ReasonCodes::ProtocolError);
1069+
result.shared_subscriptions_available = static_cast<bool>(val);
10461070
break;
1071+
}
10471072
case Mqtt5Properties::ServerKeepAlive:
10481073
if (pcounts[11]++ > 0)
10491074
throw ProtocolError("Can't specify " + propertyToString(prop) + " more than once", ReasonCodes::ProtocolError);

0 commit comments

Comments
 (0)