mirror of
https://github.com/eclipse-mosquitto/mosquitto.git
synced 2026-03-24 00:45:21 +08:00
Add accept_protocol_versions option.
This commit is contained in:
@@ -58,8 +58,10 @@ Broker:
|
||||
- Add `mosquitto_client_port()` function for plugins.
|
||||
- Add `global_max_clients` option to allow limiting client sessions globally
|
||||
on the broker.
|
||||
- Add `global_max_connections` option to allow limiting client onnections globally
|
||||
- Add `global_max_connections` option to allow limiting client connections globally
|
||||
on the broker.
|
||||
- Add `accept_protocol_versions` option to allow limiting which MQTT protocol
|
||||
versions are allowed for a particular listener.
|
||||
|
||||
Client library:
|
||||
- Add MOSQ_OPT_DISABLE_SOCKETPAIR to allow the disabling of the socketpair
|
||||
|
||||
@@ -1138,6 +1138,29 @@ log_timestamp_format %Y-%m-%dT%H:%M:%S
|
||||
<refsect2>
|
||||
<title>General Options</title>
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
<term><option>accepted_protocol_versions</option> <replaceable>versions</replaceable></term>
|
||||
<listitem>
|
||||
<para>
|
||||
Accepted protocol versions. This sets what versions
|
||||
of the MQTT protocol will be accepted on this
|
||||
listener. Can be any combination of 3, 4, 5 in a
|
||||
comma separated list, e.g.
|
||||
</para>
|
||||
<programlisting>
|
||||
# Allow v5.0 only:
|
||||
listener 1883
|
||||
accept_protocol_versions 5
|
||||
|
||||
# Allow v3.1 and v3.1.1:
|
||||
listener 1884
|
||||
accept_protocol_versions 3, 4</programlisting>
|
||||
<para>
|
||||
Defaults to allowing all versions.
|
||||
</para>
|
||||
<para>Reloaded on reload signal.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><option>bind_address</option> <replaceable>address</replaceable></term>
|
||||
<listitem>
|
||||
|
||||
@@ -296,6 +296,21 @@
|
||||
# cafile, certfile, keyfile, ciphers, and ciphers_tls13 options are supported.
|
||||
#protocol mqtt
|
||||
|
||||
# Accepted protocol versions. This sets what versions of the MQTT protocol will
|
||||
# be accepted on this listener. Can be any combination of 3, 4, 5 in a comma
|
||||
# separated list, e.g.
|
||||
#
|
||||
# # Allow v5.0 only:
|
||||
# listener 1883
|
||||
# accept_protocol_versions 5
|
||||
#
|
||||
# # Allow v3.1 and v3.1.1:
|
||||
# listener 1884
|
||||
# accept_protocol_versions 3, 4
|
||||
#
|
||||
# Defaults to allowing all versions.
|
||||
#accept_protocol_versions 3,4,5
|
||||
|
||||
# Set use_username_as_clientid to true to replace the clientid that a client
|
||||
# connected with with its username. This allows authentication to be tied to
|
||||
# the clientid, which means that it is possible to prevent one client
|
||||
|
||||
26
src/conf.c
26
src/conf.c
@@ -826,7 +826,31 @@ static int config__read_file_core(struct mosquitto__config *config, bool reload,
|
||||
}
|
||||
token = strtok_r((*buf), " ", &saveptr);
|
||||
if(token){
|
||||
if(!strcmp(token, "acl_file")){
|
||||
if(!strcmp(token, "accept_protocol_version")){
|
||||
if(cur_listener == &config->default_listener){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: You must define a listener before using he %s option.", "accept_protocol_version");
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
cur_listener->disable_protocol_v3 = true;
|
||||
cur_listener->disable_protocol_v4 = true;
|
||||
cur_listener->disable_protocol_v5 = true;
|
||||
if(saveptr == NULL){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty %s value in configuration.", "accept_protocol_version");
|
||||
return MOSQ_ERR_INVAL;
|
||||
}
|
||||
token = strtok_r(saveptr, ", \t", &saveptr);
|
||||
while(token){
|
||||
if(!strcmp(token, "3")){
|
||||
cur_listener->disable_protocol_v3 = false;
|
||||
}else if(!strcmp(token, "4")){
|
||||
cur_listener->disable_protocol_v4 = false;
|
||||
}else if(!strcmp(token, "5")){
|
||||
cur_listener->disable_protocol_v5 = false;
|
||||
}
|
||||
|
||||
token = strtok_r(NULL, ", \t", &saveptr);
|
||||
}
|
||||
}else if(!strcmp(token, "acl_file")){
|
||||
conf__set_cur_security_options(config, cur_listener, &cur_security_options);
|
||||
if(reload){
|
||||
mosquitto__free(cur_security_options->acl_file);
|
||||
|
||||
@@ -434,6 +434,19 @@ error_cleanup:
|
||||
}
|
||||
|
||||
|
||||
static int check_protocol_version(struct mosquitto__listener *listener, int protocol_version)
|
||||
{
|
||||
if((protocol_version == 3 && listener->disable_protocol_v3 == false)
|
||||
|| (protocol_version == 4 && listener->disable_protocol_v4 == false)
|
||||
|| (protocol_version == 5 && listener->disable_protocol_v5 == false)
|
||||
){
|
||||
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
return MOSQ_ERR_NOT_SUPPORTED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int handle__connect(struct mosquitto *context)
|
||||
{
|
||||
@@ -503,6 +516,17 @@ int handle__connect(struct mosquitto *context)
|
||||
rc = MOSQ_ERR_PROTOCOL;
|
||||
goto handle_connect_error;
|
||||
}
|
||||
if(check_protocol_version(context->listener, protocol_version)){
|
||||
if(protocol_version == 3 || protocol_version == 4){
|
||||
context->protocol = mosq_p_mqtt311;
|
||||
send__connack(context, 0, CONNACK_REFUSED_PROTOCOL_VERSION, NULL);
|
||||
}else{
|
||||
context->protocol = mosq_p_mqtt5;
|
||||
send__connack(context, 0, MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION, NULL);
|
||||
}
|
||||
rc = MOSQ_ERR_NOT_SUPPORTED;
|
||||
goto handle_connect_error;
|
||||
}
|
||||
if(!strcmp(protocol_name, PROTOCOL_NAME_v31)){
|
||||
if((protocol_version&0x7F) != PROTOCOL_VERSION_v31){
|
||||
if(db.config->connection_messages == true){
|
||||
|
||||
@@ -243,6 +243,9 @@ struct mosquitto__listener {
|
||||
#ifdef WITH_UNIX_SOCKETS
|
||||
char *unix_socket_path;
|
||||
#endif
|
||||
bool disable_protocol_v3;
|
||||
bool disable_protocol_v4;
|
||||
bool disable_protocol_v5;
|
||||
};
|
||||
|
||||
|
||||
|
||||
66
test/broker/01-connect-accept-protocol.py
Executable file
66
test/broker/01-connect-accept-protocol.py
Executable file
@@ -0,0 +1,66 @@
|
||||
#!/usr/bin/env python3
|
||||
|
||||
# Test accept_protocol_version option
|
||||
|
||||
from mosq_test_helper import *
|
||||
|
||||
def write_config(filename, port, accept):
|
||||
with open(filename, 'w') as f:
|
||||
f.write("listener %s\n" % (port))
|
||||
f.write("allow_anonymous true\n")
|
||||
f.write("accept_protocol_version %s\n" % (accept))
|
||||
|
||||
def do_test(accept, expect_success):
|
||||
port = mosq_test.get_port()
|
||||
|
||||
conf_file = os.path.basename(__file__).replace('.py', '.conf')
|
||||
write_config(conf_file, port, accept)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
|
||||
|
||||
try:
|
||||
for proto_ver in [3, 4, 5]:
|
||||
rc = 1
|
||||
connect_packet = mosq_test.gen_connect("accept-protocol-test-%d" % (proto_ver), proto_ver=proto_ver)
|
||||
|
||||
if proto_ver == 5:
|
||||
if proto_ver in expect_success:
|
||||
connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
|
||||
else:
|
||||
connack_packet = mosq_test.gen_connack(rc=mqtt5_rc.MQTT_RC_UNSUPPORTED_PROTOCOL_VERSION, proto_ver=proto_ver, properties=None)
|
||||
else:
|
||||
if proto_ver in expect_success:
|
||||
connack_packet = mosq_test.gen_connack(rc=0, proto_ver=proto_ver)
|
||||
else:
|
||||
connack_packet = mosq_test.gen_connack(rc=1, proto_ver=proto_ver)
|
||||
|
||||
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet, port=port)
|
||||
sock.close()
|
||||
rc = 0
|
||||
except mosq_test.TestError:
|
||||
pass
|
||||
finally:
|
||||
if write_config is not None:
|
||||
os.remove(conf_file)
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
(stdo, stde) = broker.communicate()
|
||||
if rc:
|
||||
print(stde.decode('utf-8'))
|
||||
print("proto_ver=%d" % (proto_ver))
|
||||
exit(rc)
|
||||
|
||||
|
||||
do_test(accept="3,4,5", expect_success=[3, 4, 5])
|
||||
do_test(accept="5,4,3", expect_success=[3, 4, 5])
|
||||
do_test(accept="3 ,4, 5", expect_success=[3, 4, 5])
|
||||
do_test(accept=" , 3 , 4 , 5 ", expect_success=[3, 4, 5])
|
||||
do_test(accept="3", expect_success=[3])
|
||||
do_test(accept="4", expect_success=[4])
|
||||
do_test(accept="5", expect_success=[5])
|
||||
do_test(accept="3,4", expect_success=[3, 4])
|
||||
do_test(accept="3,5", expect_success=[3, 5])
|
||||
do_test(accept="4,3", expect_success=[3, 4])
|
||||
do_test(accept="4,5", expect_success=[4, 5])
|
||||
do_test(accept="5,3", expect_success=[3, 5])
|
||||
@@ -24,6 +24,7 @@ msg_sequence_test:
|
||||
|
||||
01 :
|
||||
./01-connect-575314.py
|
||||
./01-connect-accept-protocol.py
|
||||
./01-connect-allow-anonymous.py
|
||||
./01-connect-disconnect-v5.py
|
||||
./01-connect-global-max-clients.py
|
||||
|
||||
@@ -6,6 +6,7 @@ import ptest
|
||||
tests = [
|
||||
#(ports required, 'path'),
|
||||
(1, './01-connect-575314.py'),
|
||||
(1, './01-connect-accept-protocol.py'),
|
||||
(1, './01-connect-allow-anonymous.py'),
|
||||
(1, './01-connect-disconnect-v5.py'),
|
||||
(1, './01-connect-global-max-clients.py'),
|
||||
|
||||
Reference in New Issue
Block a user