Merge branch 'develop' of github.com:eclipse/mosquitto into develop
This commit is contained in:
commit
dbdd113c86
@ -72,6 +72,7 @@ Broker fixes:
|
||||
- Fix upgrade_outgoing_qos for retained message. Closes #534.
|
||||
- Fix CONNACK message not being sent for unauthorised connect on websockets.
|
||||
Closes #8.
|
||||
- Maximum connections on Windows increased to 2048.
|
||||
|
||||
Client library features:
|
||||
- Outgoing messages with QoS>1 are no longer retried after a timeout period.
|
||||
@ -101,6 +102,7 @@ Client library fixes:
|
||||
- No need to close socket again if setting non-blocking failed. Closes #649.
|
||||
- Fix mosquitto_topic_matches_sub() not correctly matching foo/bar against
|
||||
foo/+/#. Closes #670.
|
||||
- SNI host support added.
|
||||
|
||||
Client features:
|
||||
- Add -F to mosquitto_sub to allow the user to choose the output format.
|
||||
|
@ -589,6 +589,14 @@ int net__socket_connect_step3(struct mosquitto *mosq, const char *host, uint16_t
|
||||
}
|
||||
SSL_set_bio(mosq->ssl, bio, bio);
|
||||
|
||||
/*
|
||||
* required for the SNI resolving
|
||||
*/
|
||||
if(SSL_set_tlsext_host_name(mosq->ssl, host) != 1) {
|
||||
COMPAT_CLOSE(mosq->sock);
|
||||
return MOSQ_ERR_TLS;
|
||||
}
|
||||
|
||||
if(net__socket_connect_tls(mosq)){
|
||||
return MOSQ_ERR_TLS;
|
||||
}
|
||||
|
@ -488,8 +488,11 @@
|
||||
options are affected:</para>
|
||||
<para><option>password_file</option>,
|
||||
<option>acl_file</option>, <option>psk_file</option>,
|
||||
<option>allow_anonymous</option>,
|
||||
<option>allow_zero_length_clientid</option>,
|
||||
<option>auth_plugin</option>,
|
||||
<option>auth_opt_*</option>.</para>
|
||||
<option>auth_opt_*</option>,
|
||||
<option>auto_id_prefix</option>.</para>
|
||||
<para>The default behaviour is for this to be set to
|
||||
<replaceable>false</replaceable>, which maintains the
|
||||
settings behaviour from previous versions of
|
||||
|
@ -142,6 +142,7 @@
|
||||
# affected:
|
||||
#
|
||||
# password_file acl_file psk_file auth_plugin auth_opt_* allow_anonymous
|
||||
# auto_id_prefix allow_zero_length_clientid
|
||||
#
|
||||
# The default behaviour is for this to be set to false, which maintains the
|
||||
# setting behaviour from previous versions of mosquitto.
|
||||
|
@ -168,7 +168,7 @@ install(FILES mosquitto_broker.h mosquitto_plugin.h DESTINATION "${INCLUDEDIR}")
|
||||
|
||||
if (${WITH_TLS} STREQUAL ON)
|
||||
add_executable(mosquitto_passwd mosquitto_passwd.c)
|
||||
target_link_libraries(mosquitto_passwd "${OPENSSL_LIBRARIES}")
|
||||
target_link_libraries(mosquitto_passwd ${OPENSSL_LIBRARIES})
|
||||
install(TARGETS mosquitto_passwd RUNTIME DESTINATION "${BINDIR}" LIBRARY DESTINATION "${LIBDIR}")
|
||||
endif (${WITH_TLS} STREQUAL ON)
|
||||
|
||||
|
20
src/conf.c
20
src/conf.c
@ -149,9 +149,9 @@ static void config__init_reload(struct mosquitto__config *config)
|
||||
config->acl_file = NULL;
|
||||
config->security_options.allow_anonymous = -1;
|
||||
config->allow_duplicate_messages = false;
|
||||
config->allow_zero_length_clientid = true;
|
||||
config->auto_id_prefix = NULL;
|
||||
config->auto_id_prefix_len = 0;
|
||||
config->security_options.allow_zero_length_clientid = true;
|
||||
config->security_options.auto_id_prefix = NULL;
|
||||
config->security_options.auto_id_prefix_len = 0;
|
||||
config->autosave_interval = 1800;
|
||||
config->autosave_on_changes = false;
|
||||
mosquitto__free(config->clientid_prefixes);
|
||||
@ -248,7 +248,7 @@ void config__cleanup(struct mosquitto__config *config)
|
||||
int j;
|
||||
|
||||
mosquitto__free(config->acl_file);
|
||||
mosquitto__free(config->auto_id_prefix);
|
||||
mosquitto__free(config->security_options.auto_id_prefix);
|
||||
mosquitto__free(config->clientid_prefixes);
|
||||
mosquitto__free(config->config_file);
|
||||
mosquitto__free(config->security_options.password_file);
|
||||
@ -704,7 +704,8 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, const
|
||||
}else if(!strcmp(token, "allow_duplicate_messages")){
|
||||
if(conf__parse_bool(&token, "allow_duplicate_messages", &config->allow_duplicate_messages, saveptr)) return MOSQ_ERR_INVAL;
|
||||
}else if(!strcmp(token, "allow_zero_length_clientid")){
|
||||
if(conf__parse_bool(&token, "allow_zero_length_clientid", &config->allow_zero_length_clientid, saveptr)) return MOSQ_ERR_INVAL;
|
||||
conf__set_cur_security_options(config, cur_listener, &cur_security_options);
|
||||
if(conf__parse_bool(&token, "allow_zero_length_clientid", &cur_security_options->allow_zero_length_clientid, saveptr)) return MOSQ_ERR_INVAL;
|
||||
}else if(!strncmp(token, "auth_opt_", 9)){
|
||||
if(!cur_auth_plugin_config){
|
||||
log__printf(NULL, MOSQ_LOG_ERR, "Error: An auth_opt_ option exists in the config file without an auth_plugin.");
|
||||
@ -769,11 +770,12 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, const
|
||||
}
|
||||
if(conf__parse_bool(&token, "auth_plugin_deny_special_chars", &cur_auth_plugin_config->deny_special_chars, saveptr)) return MOSQ_ERR_INVAL;
|
||||
}else if(!strcmp(token, "auto_id_prefix")){
|
||||
if(conf__parse_string(&token, "auto_id_prefix", &config->auto_id_prefix, saveptr)) return MOSQ_ERR_INVAL;
|
||||
if(config->auto_id_prefix){
|
||||
config->auto_id_prefix_len = strlen(config->auto_id_prefix);
|
||||
conf__set_cur_security_options(config, cur_listener, &cur_security_options);
|
||||
if(conf__parse_string(&token, "auto_id_prefix", &cur_security_options->auto_id_prefix, saveptr)) return MOSQ_ERR_INVAL;
|
||||
if(cur_security_options->auto_id_prefix){
|
||||
cur_security_options->auto_id_prefix_len = strlen(cur_security_options->auto_id_prefix);
|
||||
}else{
|
||||
config->auto_id_prefix_len = 0;
|
||||
cur_security_options->auto_id_prefix_len = 0;
|
||||
}
|
||||
}else if(!strcmp(token, "autosave_interval")){
|
||||
if(conf__parse_int(&token, "autosave_interval", &config->autosave_interval, saveptr)) return MOSQ_ERR_INVAL;
|
||||
|
@ -37,7 +37,7 @@ Contributors:
|
||||
# include <libwebsockets.h>
|
||||
#endif
|
||||
|
||||
static char *client_id_gen(struct mosquitto_db *db, int *idlen)
|
||||
static char *client_id_gen(struct mosquitto_db *db, int *idlen, const char *auto_id_prefix, int auto_id_prefix_len)
|
||||
{
|
||||
char *client_id;
|
||||
#ifdef WITH_UUID
|
||||
@ -47,26 +47,26 @@ static char *client_id_gen(struct mosquitto_db *db, int *idlen)
|
||||
#endif
|
||||
|
||||
#ifdef WITH_UUID
|
||||
*idlen = 36 + db->config->auto_id_prefix_len;
|
||||
*idlen = 36 + auto_id_prefix_len;
|
||||
#else
|
||||
*idlen = 64 + db->config->auto_id_prefix_len;
|
||||
*idlen = 64 + auto_id_prefix_len;
|
||||
#endif
|
||||
|
||||
client_id = (char *)mosquitto__calloc((*idlen) + 1, sizeof(char));
|
||||
if(!client_id){
|
||||
return NULL;
|
||||
}
|
||||
if(db->config->auto_id_prefix){
|
||||
memcpy(client_id, db->config->auto_id_prefix, db->config->auto_id_prefix_len);
|
||||
if(auto_id_prefix){
|
||||
memcpy(client_id, auto_id_prefix, auto_id_prefix_len);
|
||||
}
|
||||
|
||||
|
||||
#ifdef WITH_UUID
|
||||
uuid_generate_random(uuid);
|
||||
uuid_unparse_lower(uuid, &client_id[db->config->auto_id_prefix_len]);
|
||||
uuid_unparse_lower(uuid, &client_id[auto_id_prefix_len]);
|
||||
#else
|
||||
for(i=0; i<64; i++){
|
||||
client_id[i+db->config->auto_id_prefix_len] = (rand()%73)+48;
|
||||
client_id[i+auto_id_prefix_len] = (rand()%73)+48;
|
||||
}
|
||||
client_id[i] = '\0';
|
||||
#endif
|
||||
@ -240,12 +240,22 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
|
||||
mosquitto__free(client_id);
|
||||
client_id = NULL;
|
||||
|
||||
if(clean_session == 0 || db->config->allow_zero_length_clientid == false){
|
||||
bool allow_zero_length_clientid;
|
||||
if(db->config->per_listener_settings){
|
||||
allow_zero_length_clientid = context->listener->security_options.allow_zero_length_clientid;
|
||||
}else{
|
||||
allow_zero_length_clientid = db->config->security_options.allow_zero_length_clientid;
|
||||
}
|
||||
if(clean_session == 0 || allow_zero_length_clientid == false){
|
||||
send__connack(context, 0, CONNACK_REFUSED_IDENTIFIER_REJECTED);
|
||||
rc = MOSQ_ERR_PROTOCOL;
|
||||
goto handle_connect_error;
|
||||
}else{
|
||||
client_id = client_id_gen(db, &slen);
|
||||
if(db->config->per_listener_settings){
|
||||
client_id = client_id_gen(db, &slen, context->listener->security_options.auto_id_prefix, context->listener->security_options.auto_id_prefix_len);
|
||||
}else{
|
||||
client_id = client_id_gen(db, &slen, db->config->security_options.auto_id_prefix, db->config->security_options.auto_id_prefix_len);
|
||||
}
|
||||
if(!client_id){
|
||||
rc = MOSQ_ERR_NOMEM;
|
||||
goto handle_connect_error;
|
||||
|
@ -232,6 +232,10 @@ int main(int argc, char *argv[])
|
||||
srand(tv.tv_sec + tv.tv_usec);
|
||||
#endif
|
||||
|
||||
#ifdef WIN32
|
||||
_setmaxstdio(2048);
|
||||
#endif
|
||||
|
||||
memset(&int_db, 0, sizeof(struct mosquitto_db));
|
||||
|
||||
net__init();
|
||||
|
@ -197,6 +197,9 @@ struct mosquitto__security_options {
|
||||
struct mosquitto__auth_plugin_config *auth_plugin_configs;
|
||||
int auth_plugin_config_count;
|
||||
char allow_anonymous;
|
||||
bool allow_zero_length_clientid;
|
||||
char *auto_id_prefix;
|
||||
int auto_id_prefix_len;
|
||||
};
|
||||
|
||||
struct mosquitto__listener {
|
||||
@ -238,9 +241,6 @@ struct mosquitto__config {
|
||||
char *config_file;
|
||||
char *acl_file;
|
||||
bool allow_duplicate_messages;
|
||||
bool allow_zero_length_clientid;
|
||||
char *auto_id_prefix;
|
||||
int auto_id_prefix_len;
|
||||
int autosave_interval;
|
||||
bool autosave_on_changes;
|
||||
char *clientid_prefixes;
|
||||
|
3
test/broker/09-plugin-auth-acl-sub.conf
Normal file
3
test/broker/09-plugin-auth-acl-sub.conf
Normal file
@ -0,0 +1,3 @@
|
||||
port 1888
|
||||
allow_anonymous false
|
||||
auth_plugin c/auth_plugin.so
|
47
test/broker/09-plugin-auth-acl-sub.py
Executable file
47
test/broker/09-plugin-auth-acl-sub.py
Executable file
@ -0,0 +1,47 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Test topic subscription. All topic are allowed but not using wildcard in subscribe.
|
||||
|
||||
import inspect, os, sys
|
||||
# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder
|
||||
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"..")))
|
||||
if cmd_subfolder not in sys.path:
|
||||
sys.path.insert(0, cmd_subfolder)
|
||||
|
||||
import mosq_test
|
||||
|
||||
rc = 1
|
||||
keepalive = 10
|
||||
connect_packet = mosq_test.gen_connect("connect-uname-pwd-test", keepalive=keepalive, username="readonly")
|
||||
connack_packet = mosq_test.gen_connack(rc=0)
|
||||
|
||||
mid = 53
|
||||
subscribe_packet = mosq_test.gen_subscribe(mid, "qos0/test", 0)
|
||||
suback_packet = mosq_test.gen_suback(mid, 0)
|
||||
|
||||
mid_fail = 54
|
||||
subscribe_packet_fail = mosq_test.gen_subscribe(mid_fail, "#", 0)
|
||||
suback_packet_fail = mosq_test.gen_suback(mid_fail, 0x80)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__))
|
||||
|
||||
try:
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=20)
|
||||
sock.send(subscribe_packet)
|
||||
|
||||
if mosq_test.expect_packet(sock, "suback", suback_packet):
|
||||
sock.send(subscribe_packet_fail)
|
||||
if mosq_test.expect_packet(sock, "suback", suback_packet_fail):
|
||||
rc = 0
|
||||
|
||||
sock.close()
|
||||
finally:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
if rc:
|
||||
(stdo, stde) = broker.communicate()
|
||||
print(stde)
|
||||
|
||||
|
||||
exit(rc)
|
||||
|
3
test/broker/09-plugin-auth-defer-unpwd-fail.conf
Normal file
3
test/broker/09-plugin-auth-defer-unpwd-fail.conf
Normal file
@ -0,0 +1,3 @@
|
||||
port 1888
|
||||
allow_anonymous false
|
||||
auth_plugin c/auth_plugin.so
|
33
test/broker/09-plugin-auth-defer-unpwd-fail.py
Executable file
33
test/broker/09-plugin-auth-defer-unpwd-fail.py
Executable file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Test whether a connection fail when using a auth_plugin that defer authentication.
|
||||
|
||||
import inspect, os, sys
|
||||
# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder
|
||||
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"..")))
|
||||
if cmd_subfolder not in sys.path:
|
||||
sys.path.insert(0, cmd_subfolder)
|
||||
|
||||
import mosq_test
|
||||
|
||||
rc = 1
|
||||
keepalive = 10
|
||||
connect_packet = mosq_test.gen_connect("connect-uname-pwd-test", keepalive=keepalive, username="test-username@v2", password="doesNotMatter")
|
||||
connack_packet = mosq_test.gen_connack(rc=5)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__))
|
||||
|
||||
try:
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=20)
|
||||
rc = 0
|
||||
sock.close()
|
||||
finally:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
if rc:
|
||||
(stdo, stde) = broker.communicate()
|
||||
print(stde)
|
||||
|
||||
|
||||
exit(rc)
|
||||
|
4
test/broker/09-plugin-auth-defer-unpwd-success.conf
Normal file
4
test/broker/09-plugin-auth-defer-unpwd-success.conf
Normal file
@ -0,0 +1,4 @@
|
||||
port 1888
|
||||
allow_anonymous false
|
||||
auth_plugin c/auth_plugin.so
|
||||
auth_plugin c/auth_plugin_v2.so
|
34
test/broker/09-plugin-auth-defer-unpwd-success.py
Executable file
34
test/broker/09-plugin-auth-defer-unpwd-success.py
Executable file
@ -0,0 +1,34 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Test whether a connection is successful with correct username and password
|
||||
# when using a two auth_plugin (first will defer, second will accept).
|
||||
|
||||
import inspect, os, sys
|
||||
# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder
|
||||
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"..")))
|
||||
if cmd_subfolder not in sys.path:
|
||||
sys.path.insert(0, cmd_subfolder)
|
||||
|
||||
import mosq_test
|
||||
|
||||
rc = 1
|
||||
keepalive = 10
|
||||
connect_packet = mosq_test.gen_connect("connect-uname-pwd-test", keepalive=keepalive, username="test-username@v2", password="doesNotMatter")
|
||||
connack_packet = mosq_test.gen_connack(rc=0)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__))
|
||||
|
||||
try:
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=20)
|
||||
rc = 0
|
||||
sock.close()
|
||||
finally:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
if rc:
|
||||
(stdo, stde) = broker.communicate()
|
||||
print(stde)
|
||||
|
||||
|
||||
exit(rc)
|
||||
|
3
test/broker/09-plugin-auth-v2-unpwd-fail.conf
Normal file
3
test/broker/09-plugin-auth-v2-unpwd-fail.conf
Normal file
@ -0,0 +1,3 @@
|
||||
port 1888
|
||||
allow_anonymous false
|
||||
auth_plugin c/auth_plugin_v2.so
|
33
test/broker/09-plugin-auth-v2-unpwd-fail.py
Executable file
33
test/broker/09-plugin-auth-v2-unpwd-fail.py
Executable file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Test whether a connection is successful with correct username and password
|
||||
# when using a simple auth_plugin.
|
||||
|
||||
import inspect, os, sys
|
||||
# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder
|
||||
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"..")))
|
||||
if cmd_subfolder not in sys.path:
|
||||
sys.path.insert(0, cmd_subfolder)
|
||||
|
||||
import mosq_test
|
||||
|
||||
rc = 1
|
||||
keepalive = 10
|
||||
connect_packet = mosq_test.gen_connect("connect-uname-pwd-test", keepalive=keepalive, username="test-username", password="wrong")
|
||||
connack_packet = mosq_test.gen_connack(rc=5)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__))
|
||||
|
||||
try:
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=20)
|
||||
rc = 0
|
||||
|
||||
sock.close()
|
||||
finally:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
if rc:
|
||||
(stdo, stde) = broker.communicate()
|
||||
print(stde)
|
||||
|
||||
exit(rc)
|
3
test/broker/09-plugin-auth-v2-unpwd-success.conf
Normal file
3
test/broker/09-plugin-auth-v2-unpwd-success.conf
Normal file
@ -0,0 +1,3 @@
|
||||
port 1888
|
||||
allow_anonymous false
|
||||
auth_plugin c/auth_plugin_v2.so
|
33
test/broker/09-plugin-auth-v2-unpwd-success.py
Executable file
33
test/broker/09-plugin-auth-v2-unpwd-success.py
Executable file
@ -0,0 +1,33 @@
|
||||
#!/usr/bin/env python
|
||||
|
||||
# Test whether a connection is successful with correct username and password
|
||||
# when using a simple auth_plugin.
|
||||
|
||||
import inspect, os, sys
|
||||
# From http://stackoverflow.com/questions/279237/python-import-a-module-from-a-folder
|
||||
cmd_subfolder = os.path.realpath(os.path.abspath(os.path.join(os.path.split(inspect.getfile( inspect.currentframe() ))[0],"..")))
|
||||
if cmd_subfolder not in sys.path:
|
||||
sys.path.insert(0, cmd_subfolder)
|
||||
|
||||
import mosq_test
|
||||
|
||||
rc = 1
|
||||
keepalive = 10
|
||||
connect_packet = mosq_test.gen_connect("connect-uname-pwd-test", keepalive=keepalive, username="test-username", password="cnwTICONIURW")
|
||||
connack_packet = mosq_test.gen_connack(rc=0)
|
||||
|
||||
broker = mosq_test.start_broker(filename=os.path.basename(__file__))
|
||||
|
||||
try:
|
||||
sock = mosq_test.do_client_connect(connect_packet, connack_packet, timeout=20)
|
||||
rc = 0
|
||||
sock.close()
|
||||
finally:
|
||||
broker.terminate()
|
||||
broker.wait()
|
||||
if rc:
|
||||
(stdo, stde) = broker.communicate()
|
||||
print(stde)
|
||||
|
||||
|
||||
exit(rc)
|
@ -100,6 +100,11 @@ endif
|
||||
09 :
|
||||
./09-plugin-auth-unpwd-success.py
|
||||
./09-plugin-auth-unpwd-fail.py
|
||||
./09-plugin-auth-acl-sub.py
|
||||
./09-plugin-auth-v2-unpwd-success.py
|
||||
./09-plugin-auth-v2-unpwd-fail.py
|
||||
./09-plugin-auth-defer-unpwd-success.py
|
||||
./09-plugin-auth-defer-unpwd-fail.py
|
||||
|
||||
10 :
|
||||
./10-listener-mount-point.py
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
CFLAGS=-I../../../lib -I../../../src -Wall -Werror
|
||||
|
||||
all : auth_plugin.so auth_plugin_pwd.so auth_plugin_acl.so 08
|
||||
all : auth_plugin.so auth_plugin_pwd.so auth_plugin_acl.so acl_plugin_v2.so 08
|
||||
|
||||
08 : 08-tls-psk-pub.test 08-tls-psk-bridge.test
|
||||
|
||||
@ -15,6 +15,9 @@ auth_plugin_pwd.so : auth_plugin_pwd.c
|
||||
auth_plugin_acl.so : auth_plugin_acl.c
|
||||
$(CC) ${CFLAGS} -fPIC -shared $^ -o $@
|
||||
|
||||
auth_plugin_v2.so : auth_plugin_v2.c
|
||||
$(CC) ${CFLAGS} -fPIC -shared $^ -o $@
|
||||
|
||||
08-tls-psk-pub.test : 08-tls-psk-pub.c
|
||||
$(CC) ${CFLAGS} $^ -o $@ ../../../lib/libmosquitto.so.1
|
||||
|
||||
|
@ -36,6 +36,8 @@ int mosquitto_auth_acl_check(void *user_data, int access, const struct mosquitto
|
||||
printf("%s\n", username);
|
||||
if(username && !strcmp(username, "readonly") && access == MOSQ_ACL_READ){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else if(username && !strcmp(username, "readonly") && access == MOSQ_ACL_SUBSCRIBE &&!strchr(msg->topic, '#') && !strchr(msg->topic, '+')) {
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
return MOSQ_ERR_ACL_DENIED;
|
||||
}
|
||||
@ -47,6 +49,8 @@ int mosquitto_auth_unpwd_check(void *user_data, const struct mosquitto *client,
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else if(!strcmp(username, "readonly")){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else if(!strcmp(username, "test-username@v2")){
|
||||
return MOSQ_ERR_PLUGIN_DEFER;
|
||||
}else{
|
||||
return MOSQ_ERR_AUTH;
|
||||
}
|
||||
|
67
test/broker/c/auth_plugin_v2.c
Normal file
67
test/broker/c/auth_plugin_v2.c
Normal file
@ -0,0 +1,67 @@
|
||||
#include <string.h>
|
||||
#include <stdbool.h>
|
||||
#include "mosquitto_plugin_v2.h"
|
||||
|
||||
/*
|
||||
* Following constant come from mosquitto.h
|
||||
*
|
||||
* They are copied here to fix value of those constant at the time of MOSQ_AUTH_PLUGIN_VERSION == 2
|
||||
*/
|
||||
enum mosq_err_t {
|
||||
MOSQ_ERR_SUCCESS = 0,
|
||||
MOSQ_ERR_AUTH = 11,
|
||||
MOSQ_ERR_ACL_DENIED = 12
|
||||
};
|
||||
|
||||
int mosquitto_auth_plugin_version(void)
|
||||
{
|
||||
return MOSQ_AUTH_PLUGIN_VERSION;
|
||||
}
|
||||
|
||||
int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count)
|
||||
{
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int mosquitto_auth_plugin_cleanup(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count)
|
||||
{
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int mosquitto_auth_security_init(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count, bool reload)
|
||||
{
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int mosquitto_auth_security_cleanup(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count, bool reload)
|
||||
{
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}
|
||||
|
||||
int mosquitto_auth_acl_check(void *user_data, const char *clientid, const char *username, const char *topic, int access)
|
||||
{
|
||||
if(!strcmp(username, "readonly") && access == MOSQ_ACL_READ){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
return MOSQ_ERR_ACL_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
int mosquitto_auth_unpwd_check(void *user_data, const char *username, const char *password)
|
||||
{
|
||||
if(!strcmp(username, "test-username") && password && !strcmp(password, "cnwTICONIURW")){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else if(!strcmp(username, "readonly")){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else if(!strcmp(username, "test-username@v2")){
|
||||
return MOSQ_ERR_SUCCESS;
|
||||
}else{
|
||||
return MOSQ_ERR_AUTH;
|
||||
}
|
||||
}
|
||||
|
||||
int mosquitto_auth_psk_key_get(void *user_data, const char *hint, const char *identity, char *key, int max_key_len)
|
||||
{
|
||||
return MOSQ_ERR_AUTH;
|
||||
}
|
||||
|
BIN
test/broker/c/auth_plugin_v2.so
Executable file
BIN
test/broker/c/auth_plugin_v2.so
Executable file
Binary file not shown.
228
test/broker/c/mosquitto_plugin_v2.h
Normal file
228
test/broker/c/mosquitto_plugin_v2.h
Normal file
@ -0,0 +1,228 @@
|
||||
/*
|
||||
Copyright (c) 2012-2014 Roger Light <roger@atchoo.org>
|
||||
|
||||
All rights reserved. This program and the accompanying materials
|
||||
are made available under the terms of the Eclipse Public License v1.0
|
||||
and Eclipse Distribution License v1.0 which accompany this distribution.
|
||||
|
||||
The Eclipse Public License is available at
|
||||
http://www.eclipse.org/legal/epl-v10.html
|
||||
and the Eclipse Distribution License is available at
|
||||
http://www.eclipse.org/org/documents/edl-v10.php.
|
||||
|
||||
Contributors:
|
||||
Roger Light - initial implementation and documentation.
|
||||
*/
|
||||
|
||||
#ifndef MOSQUITTO_PLUGIN_H
|
||||
#define MOSQUITTO_PLUGIN_H
|
||||
|
||||
#define MOSQ_AUTH_PLUGIN_VERSION 2
|
||||
|
||||
#define MOSQ_ACL_NONE 0x00
|
||||
#define MOSQ_ACL_READ 0x01
|
||||
#define MOSQ_ACL_WRITE 0x02
|
||||
|
||||
struct mosquitto_auth_opt {
|
||||
char *key;
|
||||
char *value;
|
||||
};
|
||||
|
||||
/*
|
||||
* To create an authentication plugin you must include this file then implement
|
||||
* the functions listed below. The resulting code should then be compiled as a
|
||||
* shared library. Using gcc this can be achieved as follows:
|
||||
*
|
||||
* gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -o plugin.so
|
||||
*
|
||||
* On Mac OS X:
|
||||
*
|
||||
* gcc -I<path to mosquitto_plugin.h> -fPIC -shared plugin.c -undefined dynamic_lookup -o plugin.so
|
||||
*
|
||||
*/
|
||||
|
||||
/* =========================================================================
|
||||
*
|
||||
* Utility Functions
|
||||
*
|
||||
* Use these functions from within your plugin.
|
||||
*
|
||||
* There are also very useful functions in libmosquitto.
|
||||
*
|
||||
* ========================================================================= */
|
||||
|
||||
/*
|
||||
* Function: mosquitto_log_printf
|
||||
*
|
||||
* Write a log message using the broker configured logging.
|
||||
*
|
||||
* Parameters:
|
||||
* level - Log message priority. Can currently be one of:
|
||||
*
|
||||
* MOSQ_LOG_INFO
|
||||
* MOSQ_LOG_NOTICE
|
||||
* MOSQ_LOG_WARNING
|
||||
* MOSQ_LOG_ERR
|
||||
* MOSQ_LOG_DEBUG
|
||||
* MOSQ_LOG_SUBSCRIBE (not recommended for use by plugins)
|
||||
* MOSQ_LOG_UNSUBSCRIBE (not recommended for use by plugins)
|
||||
*
|
||||
* These values are defined in mosquitto.h.
|
||||
*
|
||||
* fmt, ... - printf style format and arguments.
|
||||
*/
|
||||
void mosquitto_log_printf(int level, const char *fmt, ...);
|
||||
|
||||
|
||||
|
||||
/* =========================================================================
|
||||
*
|
||||
* Plugin Functions
|
||||
*
|
||||
* You must implement these functions in your plugin.
|
||||
*
|
||||
* ========================================================================= */
|
||||
|
||||
/*
|
||||
* Function: mosquitto_auth_plugin_version
|
||||
*
|
||||
* The broker will call this function immediately after loading the plugin to
|
||||
* check it is a supported plugin version. Your code must simply return
|
||||
* MOSQ_AUTH_PLUGIN_VERSION.
|
||||
*/
|
||||
int mosquitto_auth_plugin_version(void);
|
||||
|
||||
/*
|
||||
* Function: mosquitto_auth_plugin_init
|
||||
*
|
||||
* Called after the plugin has been loaded and <mosquitto_auth_plugin_version>
|
||||
* has been called. This will only ever be called once and can be used to
|
||||
* initialise the plugin.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* user_data : The pointer set here will be passed to the other plugin
|
||||
* functions. Use to hold connection information for example.
|
||||
* auth_opts : Pointer to an array of struct mosquitto_auth_opt, which
|
||||
* provides the plugin options defined in the configuration file.
|
||||
* auth_opt_count : The number of elements in the auth_opts array.
|
||||
*
|
||||
* Return value:
|
||||
* Return 0 on success
|
||||
* Return >0 on failure.
|
||||
*/
|
||||
int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count);
|
||||
|
||||
/*
|
||||
* Function: mosquitto_auth_plugin_cleanup
|
||||
*
|
||||
* Called when the broker is shutting down. This will only ever be called once.
|
||||
* Note that <mosquitto_auth_security_cleanup> will be called directly before
|
||||
* this function.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* user_data : The pointer provided in <mosquitto_auth_plugin_init>.
|
||||
* auth_opts : Pointer to an array of struct mosquitto_auth_opt, which
|
||||
* provides the plugin options defined in the configuration file.
|
||||
* auth_opt_count : The number of elements in the auth_opts array.
|
||||
*
|
||||
* Return value:
|
||||
* Return 0 on success
|
||||
* Return >0 on failure.
|
||||
*/
|
||||
int mosquitto_auth_plugin_cleanup(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count);
|
||||
|
||||
/*
|
||||
* Function: mosquitto_auth_security_init
|
||||
*
|
||||
* Called when the broker initialises the security functions when it starts up.
|
||||
* If the broker is requested to reload its configuration whilst running,
|
||||
* <mosquitto_auth_security_cleanup> will be called, followed by this function.
|
||||
* In this situation, the reload parameter will be true.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* user_data : The pointer provided in <mosquitto_auth_plugin_init>.
|
||||
* auth_opts : Pointer to an array of struct mosquitto_auth_opt, which
|
||||
* provides the plugin options defined in the configuration file.
|
||||
* auth_opt_count : The number of elements in the auth_opts array.
|
||||
* reload : If set to false, this is the first time the function has
|
||||
* been called. If true, the broker has received a signal
|
||||
* asking to reload its configuration.
|
||||
*
|
||||
* Return value:
|
||||
* Return 0 on success
|
||||
* Return >0 on failure.
|
||||
*/
|
||||
int mosquitto_auth_security_init(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count, bool reload);
|
||||
|
||||
/*
|
||||
* Function: mosquitto_auth_security_cleanup
|
||||
*
|
||||
* Called when the broker cleans up the security functions when it shuts down.
|
||||
* If the broker is requested to reload its configuration whilst running,
|
||||
* this function will be called, followed by <mosquitto_auth_security_init>.
|
||||
* In this situation, the reload parameter will be true.
|
||||
*
|
||||
* Parameters:
|
||||
*
|
||||
* user_data : The pointer provided in <mosquitto_auth_plugin_init>.
|
||||
* auth_opts : Pointer to an array of struct mosquitto_auth_opt, which
|
||||
* provides the plugin options defined in the configuration file.
|
||||
* auth_opt_count : The number of elements in the auth_opts array.
|
||||
* reload : If set to false, this is the first time the function has
|
||||
* been called. If true, the broker has received a signal
|
||||
* asking to reload its configuration.
|
||||
*
|
||||
* Return value:
|
||||
* Return 0 on success
|
||||
* Return >0 on failure.
|
||||
*/
|
||||
int mosquitto_auth_security_cleanup(void *user_data, struct mosquitto_auth_opt *auth_opts, int auth_opt_count, bool reload);
|
||||
|
||||
/*
|
||||
* Function: mosquitto_auth_acl_check
|
||||
*
|
||||
* Called by the broker when topic access must be checked. access will be one
|
||||
* of MOSQ_ACL_READ (for subscriptions) or MOSQ_ACL_WRITE (for publish). Return
|
||||
* MOSQ_ERR_SUCCESS if access was granted, MOSQ_ERR_ACL_DENIED if access was
|
||||
* not granted, or MOSQ_ERR_UNKNOWN for an application specific error.
|
||||
*/
|
||||
int mosquitto_auth_acl_check(void *user_data, const char *clientid, const char *username, const char *topic, int access);
|
||||
|
||||
/*
|
||||
* Function: mosquitto_auth_unpwd_check
|
||||
*
|
||||
* Called by the broker when a username/password must be checked. Return
|
||||
* MOSQ_ERR_SUCCESS if the user is authenticated, MOSQ_ERR_AUTH if
|
||||
* authentication failed, or MOSQ_ERR_UNKNOWN for an application specific
|
||||
* error.
|
||||
*/
|
||||
int mosquitto_auth_unpwd_check(void *user_data, const char *username, const char *password);
|
||||
|
||||
/*
|
||||
* Function: mosquitto_psk_key_get
|
||||
*
|
||||
* Called by the broker when a client connects to a listener using TLS/PSK.
|
||||
* This is used to retrieve the pre-shared-key associated with a client
|
||||
* identity.
|
||||
*
|
||||
* Examine hint and identity to determine the required PSK (which must be a
|
||||
* hexadecimal string with no leading "0x") and copy this string into key.
|
||||
*
|
||||
* Parameters:
|
||||
* user_data : the pointer provided in <mosquitto_auth_plugin_init>.
|
||||
* hint : the psk_hint for the listener the client is connecting to.
|
||||
* identity : the identity string provided by the client
|
||||
* key : a string where the hex PSK should be copied
|
||||
* max_key_len : the size of key
|
||||
*
|
||||
* Return value:
|
||||
* Return 0 on success.
|
||||
* Return >0 on failure.
|
||||
* Return >0 if this function is not required.
|
||||
*/
|
||||
int mosquitto_auth_psk_key_get(void *user_data, const char *hint, const char *identity, char *key, int max_key_len);
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user