Skip to content

Capability Declaration and Problem Information Gating Are Incomplete #3634

@LiD0209

Description

@LiD0209

Capability Declaration and Problem Information Gating Are Incomplete

Conclusion

Mosquitto is partially compliant for items 756 and 799.

Item 756 is about Request Problem Information = 0. The broker accepts the
property syntax in CONNECT, but it does not convert that input into a clear,
centralized send-side policy that suppresses forbidden Reason String or User Property fields on later packets.

Item 799 is about Wildcard Subscription Available. The broker-side property
framework knows this capability property, but the normal CONNACK generation
path does not automatically declare Wildcard Subscription Available = 0 when
wildcard subscriptions are disabled.

That means both features are only partially aligned with MQTT 5.0: the codebase
contains some of the necessary building blocks, but the end-to-end behavior is
not implemented in one explicit and standards-driven path.

MQTT Standard Requirement

  • Standard: MQTT 5.0
  • Item 756 section: 3.1.2.11.7 Request Problem Information
  • Item 799 section: 3.2.2.3.12 Wildcard Subscription Available
  • Related section: 4.13 Handling errors

Normative text for item 756:

If the Request Problem Information value is 0, the Server MAY return a Reason
String or User Properties on a CONNACK or DISCONNECT packet, but MUST NOT send
a Reason String or User Properties on any packet other than PUBLISH, CONNACK,
or DISCONNECT.

That means:

  • the server must consume the client-provided Request Problem Information
    value as behavior-changing state
  • after that, later send paths must know whether Reason String and User Property are still permitted
  • this is not satisfied merely because some current ACK paths happen not to add
    those properties today

Normative text for item 799:

A value of 0 indicates that Wildcard Subscriptions are not supported by the
Server.
If not present, then Wildcard Subscriptions are supported.

That means:

  • when the server disables wildcard subscriptions, the MQTT 5 declaration is
    Wildcard Subscription Available = 0
  • clients are expected to learn the capability from CONNACK
  • if the broker never emits the property, clients are forced to assume wildcard
    subscriptions are supported

Relevant Code

Item 756: CONNECT Processing Does Not Consume Request Problem Information

src/property_broker.c processes several CONNECT properties:

while(p){
	switch(mosquitto_property_identifier(p)){
		case MQTT_PROP_SESSION_EXPIRY_INTERVAL:
			context->session_expiry_interval = mosquitto_property_int32_value(p);
			break;

		case MQTT_PROP_RECEIVE_MAXIMUM:
			context->msgs_out.inflight_maximum = mosquitto_property_int16_value(p);
			if(context->msgs_out.inflight_maximum == 0){
				log__printf(NULL, MOSQ_LOG_INFO, "Protocol error from %s: CONNECT packet with receive-maximum = 0.", context->id);
				return MOSQ_ERR_PROTOCOL;
			}
			context->msgs_out.inflight_quota = context->msgs_out.inflight_maximum;
			break;

		case MQTT_PROP_MAXIMUM_PACKET_SIZE:
			context->maximum_packet_size = mosquitto_property_int32_value(p);
			if(context->maximum_packet_size == 0){
				log__printf(NULL, MOSQ_LOG_INFO, "Protocol error from %s: CONNECT packet with maximum-packet-size = 0.", context->id);
				return MOSQ_ERR_PROTOCOL;
			}
			break;

		case MQTT_PROP_TOPIC_ALIAS_MAXIMUM:
			context->alias_max_l2r = mosquitto_property_int16_value(p);
			if(context->alias_max_l2r > context->listener->max_topic_alias_broker){
				context->alias_max_l2r = context->listener->max_topic_alias_broker;
			}
			break;

		default:
			break;
	}
	p = mosquitto_property_next(p);
}

MQTT_PROP_REQUEST_PROBLEM_INFORMATION is not handled here.

That means:

  • the broker parses the CONNECT property list
  • it already consumes several state-changing MQTT 5 properties
  • but it does not store or apply Request Problem Information

So there is no explicit broker-side state saying:

the client requested reduced problem information, so later packets must be gated

Item 756: Property Definitions Exist, but Behavior Is Not Wired Through

libcommon/property_common.c recognizes the property identifier:

case MQTT_PROP_REQUEST_PROBLEM_INFORMATION:

and also treats it as a legal property in the framework.

That means the gap is not "the implementation does not know this property
exists". The gap is that normal broker CONNECT processing does not translate
the property into later send-side enforcement.

Item 799: Normal CONNACK Capability Declaration Omits Wildcard Support

src/send_connack.c automatically adds several capability properties:

if(reason_code < 128 && db.config->retain_available == false){
	rc = mosquitto_property_add_byte(&connack_props, MQTT_PROP_RETAIN_AVAILABLE, 0);
	if(rc){
		mosquitto_property_free_all(&connack_props);
		return rc;
	}
}
if(reason_code < 128 && db.config->max_packet_size > 0){
	rc = mosquitto_property_add_int32(&connack_props, MQTT_PROP_MAXIMUM_PACKET_SIZE, db.config->max_packet_size);
	if(rc){
		mosquitto_property_free_all(&connack_props);
		return rc;
	}
}
if(reason_code < 128 && db.config->max_inflight_messages > 0){
	rc = mosquitto_property_add_int16(&connack_props, MQTT_PROP_RECEIVE_MAXIMUM, db.config->max_inflight_messages);
	if(rc){
		mosquitto_property_free_all(&connack_props);
		return rc;
	}
}
if(context->listener->max_qos != 2){
	rc = mosquitto_property_add_byte(&connack_props, MQTT_PROP_MAXIMUM_QOS, context->listener->max_qos);
	if(rc){
		mosquitto_property_free_all(&connack_props);
		return rc;
	}
}

There is no corresponding block for:

MQTT_PROP_WILDCARD_SUB_AVAILABLE = 0

That means:

  • the broker already has a standard place where it declares negotiated or
    limited capabilities in CONNACK
  • wildcard-subscription capability is not included in that standard path
  • a client that relies on CONNACK capability declarations will not learn that
    wildcard subscriptions are disabled

Item 799: The Property Is Known to the Shared Property Layer

libcommon/property_common.c also recognizes:

case MQTT_PROP_WILDCARD_SUB_AVAILABLE:

So again, the missing part is not syntax support. The missing part is normal
broker-side declaration behavior.

Why This Is Partial

Item 756

Implemented:

  • the property framework knows Request Problem Information
  • the broker parses MQTT 5 CONNECT properties
  • many common ACK paths currently do not attach Reason String or User Property

Missing:

  • no dedicated broker-side state derived from Request Problem Information = 0
  • no centralized later-packet gating rule tied to that state
  • no explicit proof in the normal broker send path that packets are filtered
    because of the MQTT 5 requirement itself

So item 756 is partial, not unsatisfied: there is no blanket evidence that
the broker always violates the rule, but there is also no explicit standards
driven implementation of the rule.

Item 799

Implemented:

  • the property framework knows Wildcard Subscription Available
  • the broker already auto-declares some MQTT 5 capabilities in CONNACK

Missing:

  • no normal CONNACK path that declares Wildcard Subscription Available = 0
    when wildcard subscriptions are disabled
  • no unified broker-side capability advertisement for this case

So item 799 is also partial: the codebase contains the property machinery,
but the concrete broker declaration path is incomplete.

Runtime Evidence

No dedicated runtime artifact was found in this directory for items 756 or
799.

The classification here is therefore:

source-confirmed partial

That means the conclusion is based on direct inspection of the actual Mosquitto
implementation paths rather than on a packet-capture reproducer.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Status: AvailableNo one has claimed responsibility for resolving this issue.

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions