Multistep auth, plus reauth, plus tests.

This commit is contained in:
Roger A. Light 2019-04-04 22:08:55 +01:00
parent c1776a0b39
commit 2e7dcee342
22 changed files with 509 additions and 27 deletions

View File

@ -2829,7 +2829,7 @@ libmosq_EXPORT const mosquitto_property *mosquitto_property_read_binary(
const mosquitto_property *proplist,
int identifier,
void **value,
int *len,
uint16_t *len,
bool skip_first);
/*

View File

@ -111,8 +111,8 @@ enum mosquitto_client_state {
mosq_cs_duplicate = 17, /* client that has been taken over by another with the same id */
mosq_cs_disconnect_with_will = 18,
mosq_cs_disused = 19, /* client that has been added to the disused list to be freed */
mosq_cs_authentication = 20, /* Client has sent CONNECT but is still undergoing extended authentication */
mosq_cs_reauthentiction = 21, /* Client is undergoing reauthentication and shouldn't do anything else until complete */
mosq_cs_authenticating = 20, /* Client has sent CONNECT but is still undergoing extended authentication */
mosq_cs_reauthenticating = 21, /* Client is undergoing reauthentication and shouldn't do anything else until complete */
};
enum mosquitto__protocol {

View File

@ -992,7 +992,7 @@ const mosquitto_property *mosquitto_property_read_varint(const mosquitto_propert
}
const mosquitto_property *mosquitto_property_read_binary(const mosquitto_property *proplist, int identifier, void **value, int *len, bool skip_first)
const mosquitto_property *mosquitto_property_read_binary(const mosquitto_property *proplist, int identifier, void **value, uint16_t *len, bool skip_first)
{
const mosquitto_property *p;
if(!proplist || (value && !len) || (!value && len)) return NULL;

View File

@ -40,9 +40,15 @@ int send__disconnect(struct mosquitto *mosq, uint8_t reason_code, const mosquitt
assert(mosq);
#ifdef WITH_BROKER
# ifdef WITH_BRIDGE
log__printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending DISCONNECT", mosq->id);
# endif
# ifdef WITH_BRIDGE
if(mosq->bridge){
log__printf(mosq, MOSQ_LOG_DEBUG, "Bridge %s sending DISCONNECT", mosq->id);
}else
# else
{
log__printf(mosq, MOSQ_LOG_DEBUG, "Sending DISCONNECT to %s (rc%d)", mosq->id, reason_code);
}
# endif
#else
log__printf(mosq, MOSQ_LOG_DEBUG, "Client %s sending DISCONNECT", mosq->id);
#endif

View File

@ -41,6 +41,7 @@ set (MOSQ_SRCS
../lib/read_handle.h
security.c security_default.c
../lib/send_mosq.c ../lib/send_mosq.h
send_auth.c
send_connack.c
../lib/send_connect.c
../lib/send_disconnect.c

View File

@ -47,6 +47,7 @@ OBJS= mosquitto.o \
read_handle.o \
security.o \
security_default.o \
send_auth.o \
send_connack.o \
send_connect.o \
send_disconnect.o \
@ -190,6 +191,9 @@ security.o : security.c mosquitto_broker_internal.h
security_default.o : security_default.c mosquitto_broker_internal.h
${CROSS_COMPILE}${CC} $(BROKER_CFLAGS) -c $< -o $@
send_auth.o : send_auth.c mosquitto_broker_internal.h
${CROSS_COMPILE}${CC} $(BROKER_CFLAGS) -c $< -o $@
send_connect.o : ../lib/send_connect.c ../lib/send_mosq.h
${CROSS_COMPILE}${CC} $(BROKER_CFLAGS) -c $< -o $@

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2018 Roger Light <roger@atchoo.org>
Copyright (c) 2018-2019 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
@ -21,6 +21,7 @@ Contributors:
#include "mosquitto_broker_internal.h"
#include "mqtt_protocol.h"
#include "memory_mosq.h"
#include "packet_mosq.h"
#include "property_mosq.h"
#include "send_mosq.h"
@ -31,23 +32,120 @@ int handle__auth(struct mosquitto_db *db, struct mosquitto *context)
int rc = 0;
uint8_t reason_code = 0;
mosquitto_property *properties = NULL;
char *auth_method = NULL;
void *auth_data = NULL;
uint16_t auth_data_len = 0;
void *auth_data_out = NULL;
uint16_t auth_data_out_len = 0;
if(!context) return MOSQ_ERR_INVAL;
log__printf(NULL, MOSQ_LOG_DEBUG, "Received AUTH from %s", context->id);
if(context->protocol != mosq_p_mqtt5){
if(context->protocol != mosq_p_mqtt5 || context->auth_method == NULL){
return MOSQ_ERR_PROTOCOL;
}
if(context->in_packet.remaining_length > 0){
if(packet__read_byte(&context->in_packet, &reason_code)) return 1;
if(reason_code != MQTT_RC_CONTINUE_AUTHENTICATION
&& reason_code != MQTT_RC_REAUTHENTICATE){
send__disconnect(context, MQTT_RC_PROTOCOL_ERROR, NULL);
return MOSQ_ERR_PROTOCOL;
}
if((reason_code == MQTT_RC_REAUTHENTICATE && context->state != mosq_cs_connected)
|| (reason_code == MQTT_RC_CONTINUE_AUTHENTICATION
&& context->state != mosq_cs_authenticating && context->state != mosq_cs_reauthenticating)){
send__disconnect(context, MQTT_RC_PROTOCOL_ERROR, NULL);
return MOSQ_ERR_PROTOCOL;
}
rc = property__read_all(CMD_AUTH, &context->in_packet, &properties);
if(rc) return rc;
if(rc){
send__disconnect(context, MQTT_RC_UNSPECIFIED, NULL);
return rc;
}
if(mosquitto_property_read_string(properties, MQTT_PROP_AUTHENTICATION_METHOD, &auth_method, false) == NULL){
mosquitto_property_free_all(&properties);
send__disconnect(context, MQTT_RC_UNSPECIFIED, NULL);
return MOSQ_ERR_PROTOCOL;
}
if(!auth_method || strcmp(auth_method, context->auth_method)){
/* No method, or non-matching method */
mosquitto__free(auth_method);
mosquitto_property_free_all(&properties);
send__disconnect(context, MQTT_RC_PROTOCOL_ERROR, NULL);
return MOSQ_ERR_PROTOCOL;
}
mosquitto__free(auth_method);
mosquitto_property_read_binary(properties, MQTT_PROP_AUTHENTICATION_DATA, &auth_data, &auth_data_len, false);
mosquitto_property_free_all(&properties); /* FIXME - TEMPORARY UNTIL PROPERTIES PROCESSED */
}
/* FIXME - Extended auth not currently supported */
send__disconnect(context, MQTT_RC_NOT_AUTHORIZED, NULL);
return 1;
log__printf(NULL, MOSQ_LOG_DEBUG, "Received AUTH from %s (rc%d, %s)", context->id, reason_code, context->auth_method);
if(reason_code == MQTT_RC_REAUTHENTICATE){
/* This is a re-authentication attempt */
context__set_state(context, mosq_cs_reauthenticating);
rc = mosquitto_security_auth_start(db, context, true, auth_data, auth_data_len, &auth_data_out, &auth_data_out_len);
}else{
if(context->state != mosq_cs_reauthenticating){
context__set_state(context, mosq_cs_authenticating);
}
rc = mosquitto_security_auth_continue(db, context, auth_data, auth_data_len, &auth_data_out, &auth_data_out_len);
}
mosquitto__free(auth_data);
if(rc == MOSQ_ERR_SUCCESS){
if(context->state == mosq_cs_authenticating){
return connect__on_authorised(db, context, auth_data_out, auth_data_out_len);
}else{
context__set_state(context, mosq_cs_connected);
rc = send__auth(db, context, MQTT_RC_SUCCESS, auth_data_out, auth_data_out_len);
free(auth_data_out);
return rc;
}
}else if(rc == MOSQ_ERR_AUTH_CONTINUE){
rc = send__auth(db, context, MQTT_RC_CONTINUE_AUTHENTICATION, auth_data_out, auth_data_out_len);
free(auth_data_out);
return rc;
}else{
free(auth_data_out);
if(context->state == mosq_cs_authenticating && context->will){
/* Free will without sending if this is our first authentication attempt */
mosquitto_property_free_all(&context->will->properties);
mosquitto__free(context->will->msg.payload);
mosquitto__free(context->will->msg.topic);
mosquitto__free(context->will);
context->will = NULL;
}
if(rc == MOSQ_ERR_AUTH){
send__connack(db, context, 0, MQTT_RC_NOT_AUTHORIZED, NULL);
if(context->state == mosq_cs_authenticating){
mosquitto__free(context->id);
context->id = NULL;
}
return MOSQ_ERR_PROTOCOL;
}else if(rc == MOSQ_ERR_NOT_SUPPORTED){
/* Client has requested extended authentication, but we don't support it. */
send__connack(db, context, 0, MQTT_RC_BAD_AUTHENTICATION_METHOD, NULL);
if(context->state == mosq_cs_authenticating){
mosquitto__free(context->id);
context->id = NULL;
}
return MOSQ_ERR_PROTOCOL;
}else{
if(context->state == mosq_cs_authenticating){
mosquitto__free(context->id);
context->id = NULL;
}
return rc;
}
}
}

View File

@ -364,7 +364,7 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
int i;
mosquitto_property *properties = NULL;
void *auth_data = NULL;
int auth_data_len = 0;
uint16_t auth_data_len = 0;
void *auth_data_out = NULL;
uint16_t auth_data_out_len = 0;
#ifdef WITH_TLS
@ -817,8 +817,12 @@ int handle__connect(struct mosquitto_db *db, struct mosquitto *context)
if(rc == MOSQ_ERR_SUCCESS){
return connect__on_authorised(db, context, auth_data_out, auth_data_out_len);
}else if(rc == MOSQ_ERR_AUTH_CONTINUE){
return 1; // FIXME
context__set_state(context, mosq_cs_authenticating);
rc = send__auth(db, context, MQTT_RC_CONTINUE_AUTHENTICATION, auth_data_out, auth_data_out_len);
free(auth_data_out);
return rc;
}else{
free(auth_data_out);
if(context->will){
mosquitto_property_free_all(&context->will->properties);
mosquitto__free(context->will->msg.payload);

View File

@ -139,7 +139,7 @@ typedef int (*FUNC_auth_plugin_acl_check_v4)(void *, int, struct mosquitto *, st
typedef int (*FUNC_auth_plugin_unpwd_check_v4)(void *, struct mosquitto *, const char *, const char *);
typedef int (*FUNC_auth_plugin_psk_key_get_v4)(void *, struct mosquitto *, const char *, const char *, char *, int);
typedef int (*FUNC_auth_plugin_auth_start_v4)(void *, struct mosquitto *, const char *, bool, const void *, uint16_t, void **, uint16_t *);
typedef int (*FUNC_auth_plugin_auth_continue_v4)(void *, struct mosquitto *, const char *, const void *, int);
typedef int (*FUNC_auth_plugin_auth_continue_v4)(void *, struct mosquitto *, const char *, const void *, uint16_t, void **, uint16_t *);
typedef int (*FUNC_auth_plugin_init_v3)(void **, struct mosquitto_opt *, int);
typedef int (*FUNC_auth_plugin_cleanup_v3)(void *, struct mosquitto_opt *, int);
@ -564,6 +564,7 @@ int restore_privileges(void);
int send__connack(struct mosquitto_db *db, struct mosquitto *context, int ack, int reason_code, const mosquitto_property *properties);
int send__suback(struct mosquitto *context, uint16_t mid, uint32_t payloadlen, const void *payload);
int send__unsuback(struct mosquitto *context, uint16_t mid, int reason_code_count, uint8_t *reason_codes, const mosquitto_property *properties);
int send__auth(struct mosquitto_db *db, struct mosquitto *context, int reason_code, const void *auth_data, uint16_t auth_data_len);
/* ============================================================
* Network functions
@ -640,6 +641,8 @@ void context__send_will(struct mosquitto_db *db, struct mosquitto *context);
void context__remove_from_by_id(struct mosquitto_db *db, struct mosquitto *context);
void context__set_state(struct mosquitto *context, enum mosquitto_client_state state);
int connect__on_authorised(struct mosquitto_db *db, struct mosquitto *context, void *auth_data_out, uint16_t auth_data_out_len);
/* ============================================================
* Logging functions
* ============================================================ */
@ -688,8 +691,8 @@ int mosquitto_acl_check_default(struct mosquitto_db *db, struct mosquitto *conte
int mosquitto_unpwd_check_default(struct mosquitto_db *db, struct mosquitto *context, const char *username, const char *password);
int mosquitto_psk_key_get_default(struct mosquitto_db *db, struct mosquitto *context, const char *hint, const char *identity, char *key, int max_key_len);
int mosquitto_security_auth_start(struct mosquitto_db *db, struct mosquitto *context, bool reauth, const void *data_in, int data_in_len, void **data_out, uint16_t *data_out_len);
int mosquitto_security_auth_continue(struct mosquitto_db *db, struct mosquitto *context, const void *auth_data, int auth_data_len);
int mosquitto_security_auth_start(struct mosquitto_db *db, struct mosquitto *context, bool reauth, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len);
int mosquitto_security_auth_continue(struct mosquitto_db *db, struct mosquitto *context, const void *data_in, uint16_t data_len, void **data_out, uint16_t *data_out_len);
/* ============================================================
* Session expiry

View File

@ -293,4 +293,6 @@ int mosquitto_auth_psk_key_get(void *user_data, struct mosquitto *client, const
* Return any other relevant positive integer MOSQ_ERR_* to produce an error.
*/
int mosquitto_auth_start(void *user_data, struct mosquitto *client, const char *method, bool reauth, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len);
int mosquitto_auth_continue(void *user_data, struct mosquitto *client, const char *method, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len);
#endif

View File

@ -796,7 +796,7 @@ int mosquitto_psk_key_get(struct mosquitto_db *db, struct mosquitto *context, co
}
int mosquitto_security_auth_start(struct mosquitto_db *db, struct mosquitto *context, bool reauth, const void *data_in, int data_in_len, void **data_out, uint16_t *data_out_len)
int mosquitto_security_auth_start(struct mosquitto_db *db, struct mosquitto *context, bool reauth, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len)
{
int rc = MOSQ_ERR_PLUGIN_DEFER;
int i;
@ -842,3 +842,50 @@ int mosquitto_security_auth_start(struct mosquitto_db *db, struct mosquitto *con
return rc;
}
}
int mosquitto_security_auth_continue(struct mosquitto_db *db, struct mosquitto *context, const void *data_in, uint16_t data_in_len, void **data_out, uint16_t *data_out_len)
{
int rc = MOSQ_ERR_PLUGIN_DEFER;
int i;
struct mosquitto__security_options *opts;
if(!context || !context->listener || !context->auth_method) return MOSQ_ERR_INVAL;
if(!data_out || !data_out_len) return MOSQ_ERR_INVAL;
if(db->config->per_listener_settings){
opts = &context->listener->security_options;
}else{
opts = &db->config->security_options;
}
for(i=0; i<opts->auth_plugin_config_count; i++){
if(opts->auth_plugin_configs[i].plugin.auth_start_v4){
*data_out = NULL;
*data_out_len = 0;
rc = opts->auth_plugin_configs[i].plugin.auth_continue_v4(
opts->auth_plugin_configs[i].plugin.user_data,
context,
context->auth_method,
data_in, data_in_len,
data_out, data_out_len);
if(rc == MOSQ_ERR_SUCCESS){
return MOSQ_ERR_SUCCESS;
}else if(rc == MOSQ_ERR_AUTH_CONTINUE){
return MOSQ_ERR_AUTH_CONTINUE;
}else if(rc == MOSQ_ERR_NOT_SUPPORTED){
rc = MOSQ_ERR_PLUGIN_DEFER;
}else{
return rc;
}
}
}
if(rc == MOSQ_ERR_PLUGIN_DEFER){
return MOSQ_ERR_NOT_SUPPORTED;
}else{
return rc;
}
}

83
src/send_auth.c Normal file
View File

@ -0,0 +1,83 @@
/*
Copyright (c) 2019 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.
*/
#include "config.h"
#include "mosquitto_broker_internal.h"
#include "mqtt_protocol.h"
#include "memory_mosq.h"
#include "packet_mosq.h"
#include "property_mosq.h"
#include "util_mosq.h"
int send__auth(struct mosquitto_db *db, struct mosquitto *context, int reason_code, const void *auth_data, uint16_t auth_data_len)
{
struct mosquitto__packet *packet = NULL;
int rc;
mosquitto_property *properties = NULL;
int proplen, varbytes;
uint32_t remaining_length;
if(context->auth_method == NULL) return MOSQ_ERR_INVAL;
if(context->protocol != mosq_p_mqtt5) return MOSQ_ERR_PROTOCOL;
log__printf(NULL, MOSQ_LOG_DEBUG, "Sending AUTH to %s (rc%d, %s)", context->id, reason_code, context->auth_method);
remaining_length = 1;
rc = mosquitto_property_add_string(&properties, MQTT_PROP_AUTHENTICATION_METHOD, context->auth_method);
if(rc){
mosquitto_property_free_all(&properties);
return rc;
}
if(auth_data != NULL && auth_data_len > 0){
rc = mosquitto_property_add_binary(&properties, MQTT_PROP_AUTHENTICATION_DATA, auth_data, auth_data_len);
if(rc){
mosquitto_property_free_all(&properties);
return rc;
}
}
proplen = property__get_length_all(properties);
varbytes = packet__varint_bytes(proplen);
remaining_length += proplen + varbytes;
if(packet__check_oversize(context, remaining_length)){
mosquitto_property_free_all(&properties);
mosquitto__free(packet);
return MOSQ_ERR_OVERSIZE_PACKET;
}
packet = mosquitto__calloc(1, sizeof(struct mosquitto__packet));
if(!packet) return MOSQ_ERR_NOMEM;
packet->command = CMD_AUTH;
packet->remaining_length = remaining_length;
rc = packet__alloc(packet);
if(rc){
mosquitto_property_free_all(&properties);
mosquitto__free(packet);
return rc;
}
packet__write_byte(packet, reason_code);
property__write_all(packet, properties, true);
mosquitto_property_free_all(&properties);
return packet__queue(context, packet);
}

View File

@ -79,6 +79,7 @@ int send__connack(struct mosquitto_db *db, struct mosquitto *context, int ack, i
rc = packet__alloc(packet);
if(rc){
mosquitto_property_free_all(&connack_props);
mosquitto__free(packet);
return rc;
}

View File

@ -0,0 +1,94 @@
#!/usr/bin/env python
from mosq_test_helper import *
def write_config(filename, port):
with open(filename, 'w') as f:
f.write("port %d\n" % (port))
f.write("auth_plugin c/auth_plugin_extended_multiple.so\n")
port = mosq_test.get_port()
conf_file = os.path.basename(__file__).replace('.py', '.conf')
write_config(conf_file, port)
rc = 1
# First auth
# ==========
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "step1")
connect1_packet = mosq_test.gen_connect("client-params-test", keepalive=42, proto_ver=5, properties=props)
# Server to client
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "1pets")
auth1_1_packet = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_CONTINUE_AUTHENTICATION, properties=props)
# Client to server
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "supercalifragilisticexpialidocious")
auth1_2_packet = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_CONTINUE_AUTHENTICATION, properties=props)
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
connack1_packet = mosq_test.gen_connack(rc=0, proto_ver=5, properties=props)
# Second auth
# ===========
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "step1")
reauth2_packet = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_REAUTHENTICATE, properties=props)
# Server to client
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "1pets")
auth2_1_packet = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_CONTINUE_AUTHENTICATION, properties=props)
# Client to server
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "supercalifragilisticexpialidocious")
auth2_2_packet = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_CONTINUE_AUTHENTICATION, properties=props)
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
auth2_3_packet = mosq_test.gen_auth(reason_code=0, properties=props)
# Third auth - bad due to different method
# ========================================
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "badmethod")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "step1")
reauth3_packet = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_REAUTHENTICATE, properties=props)
# Server to client
disconnect3_packet = mosq_test.gen_disconnect(reason_code=mqtt5_rc.MQTT_RC_PROTOCOL_ERROR, proto_ver=5)
pingreq_packet = mosq_test.gen_pingreq()
pingresp_packet = mosq_test.gen_pingresp()
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
try:
sock = mosq_test.do_client_connect(connect1_packet, auth1_1_packet, timeout=20, port=port, connack_error="auth1")
mosq_test.do_send_receive(sock, auth1_2_packet, connack1_packet, "connack1")
mosq_test.do_send_receive(sock, pingreq_packet, pingresp_packet, "pingresp1")
mosq_test.do_send_receive(sock, reauth2_packet, auth2_1_packet, "auth2_1")
mosq_test.do_send_receive(sock, auth2_2_packet, auth2_3_packet, "auth2_3")
mosq_test.do_send_receive(sock, pingreq_packet, pingresp_packet, "pingresp2")
mosq_test.do_send_receive(sock, reauth3_packet, disconnect3_packet, "disconnect3")
rc = 0
sock.close()
finally:
os.remove(conf_file)
broker.terminate()
broker.wait()
(stdo, stde) = broker.communicate()
if rc:
print(stde.decode('utf-8'))
exit(rc)

View File

@ -0,0 +1,53 @@
#!/usr/bin/env python
from mosq_test_helper import *
def write_config(filename, port):
with open(filename, 'w') as f:
f.write("port %d\n" % (port))
f.write("auth_plugin c/auth_plugin_extended_multiple.so\n")
port = mosq_test.get_port()
conf_file = os.path.basename(__file__).replace('.py', '.conf')
write_config(conf_file, port)
rc = 1
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "step1")
connect_packet = mosq_test.gen_connect("client-params-test", keepalive=42, proto_ver=5, properties=props)
# Server to client
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "1pets")
auth1_packet = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_CONTINUE_AUTHENTICATION, properties=props)
# Client to server
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "supercalifragilisticexpialidocious")
auth2_packet = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_CONTINUE_AUTHENTICATION, properties=props)
props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "mirror")
connack_packet = mosq_test.gen_connack(rc=0, proto_ver=5, properties=props)
broker = mosq_test.start_broker(filename=os.path.basename(__file__), use_conf=True, port=port)
try:
sock = mosq_test.do_client_connect(connect_packet, auth1_packet, timeout=20, port=port, connack_error="auth1")
mosq_test.do_send_receive(sock, auth2_packet, connack_packet)
rc = 0
sock.close()
finally:
os.remove(conf_file)
broker.terminate()
broker.wait()
(stdo, stde) = broker.communicate()
if rc:
print(stde.decode('utf-8'))
exit(rc)

View File

@ -165,6 +165,8 @@ endif
./09-acl-empty-file.py
./09-auth-bad-method.py
./09-extended-auth-change-username.py
./09-extended-auth-multistep-reauth.py
./09-extended-auth-multistep.py
./09-extended-auth-single.py
./09-extended-auth-unsupported.py
./09-plugin-auth-acl-sub-denied.py

View File

@ -10,6 +10,7 @@ PLUGIN_SRC = \
auth_plugin_v2.c \
auth_plugin_context_params.c \
auth_plugin_msg_params.c \
auth_plugin_extended_multiple.c \
auth_plugin_extended_single.c \
auth_plugin_extended_single2.c

View File

@ -0,0 +1,80 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <mosquitto.h>
#include <mosquitto_broker.h>
#include <mosquitto_plugin.h>
int mosquitto_auth_plugin_version(void)
{
return MOSQ_AUTH_PLUGIN_VERSION;
}
int mosquitto_auth_plugin_init(void **user_data, struct mosquitto_opt *auth_opts, int auth_opt_count)
{
return MOSQ_ERR_SUCCESS;
}
int mosquitto_auth_plugin_cleanup(void *user_data, struct mosquitto_opt *auth_opts, int auth_opt_count)
{
return MOSQ_ERR_SUCCESS;
}
int mosquitto_auth_security_init(void *user_data, struct mosquitto_opt *auth_opts, int auth_opt_count, bool reload)
{
return MOSQ_ERR_SUCCESS;
}
int mosquitto_auth_security_cleanup(void *user_data, struct mosquitto_opt *auth_opts, int auth_opt_count, bool reload)
{
return MOSQ_ERR_SUCCESS;
}
int mosquitto_auth_acl_check(void *user_data, int access, struct mosquitto *client, const struct mosquitto_acl_msg *msg)
{
return MOSQ_ERR_PLUGIN_DEFER;
}
int mosquitto_auth_start(void *user_data, struct mosquitto *client, const char *method, bool reauth, const void *data, uint16_t data_len, void **data_out, uint16_t *data_out_len)
{
int i;
if(!strcmp(method, "mirror")){
if(data_len > 0){
*data_out = malloc(data_len);
if(!(*data_out)){
return MOSQ_ERR_NOMEM;
}
for(i=0; i<data_len; i++){
((uint8_t *)(*data_out))[i] = ((uint8_t *)data)[data_len-i-1];
}
*data_out_len = data_len;
return MOSQ_ERR_AUTH_CONTINUE;
}else{
return MOSQ_ERR_INVAL;
}
}
return MOSQ_ERR_NOT_SUPPORTED;
}
int mosquitto_auth_continue(void *user_data, struct mosquitto *client, const char *method, const void *data, uint16_t data_len, void **data_out, uint16_t *data_out_len)
{
int len;
if(!strcmp(method, "mirror")){
if(data_len > 0){
len = strlen("supercalifragilisticexpialidocious")>data_len?data_len:strlen("supercalifragilisticexpialidocious");
if(!memcmp(data, "supercalifragilisticexpialidocious", len)){
return MOSQ_ERR_SUCCESS;
}else{
return MOSQ_ERR_AUTH;
}
}else{
return MOSQ_ERR_INVAL;
}
}
return MOSQ_ERR_NOT_SUPPORTED;
}

View File

@ -72,7 +72,7 @@ int mosquitto_auth_start(void *user_data, struct mosquitto *client, const char *
return MOSQ_ERR_NOT_SUPPORTED;
}
int mosquitto_auth_continue(void *user_data, struct mosquitto *client, const char *method, const void *data, int data_len)
int mosquitto_auth_continue(void *user_data, struct mosquitto *client, const char *method, const void *data, uint16_t data_len, void **data_out, uint16_t *data_out_len)
{
return MOSQ_ERR_AUTH;
}

View File

@ -72,7 +72,7 @@ int mosquitto_auth_start(void *user_data, struct mosquitto *client, const char *
return MOSQ_ERR_NOT_SUPPORTED;
}
int mosquitto_auth_continue(void *user_data, struct mosquitto *client, const char *method, const void *data, int data_len)
int mosquitto_auth_continue(void *user_data, struct mosquitto *client, const char *method, const void *data, uint16_t data_len, void **data_out, uint16_t *data_out_len)
{
return MOSQ_ERR_AUTH;
}

View File

@ -135,6 +135,8 @@ tests = [
(1, './09-acl-empty-file.py'),
(1, './09-auth-bad-method.py'),
(1, './09-extended-auth-change-username.py'),
(1, './09-extended-auth-multistep-reauth.py'),
(1, './09-extended-auth-multistep.py'),
(1, './09-extended-auth-single.py'),
(1, './09-extended-auth-unsupported.py'),
(1, './09-plugin-auth-acl-sub-denied.py'),

View File

@ -312,8 +312,9 @@ def to_string(packet):
(cmd, rl) = struct.unpack('!BB', packet)
return "DISCONNECT, rl="+str(rl)
elif cmd == 0xF0:
# Reserved
return "0xF0"
# AUTH
(cmd, rl) = struct.unpack('!BB', packet)
return "AUTH, rl="+str(rl)
def gen_connect(client_id, clean_session=True, keepalive=60, username=None, password=None, will_topic=None, will_qos=0, will_retain=False, will_payload=b"", proto_ver=4, connect_reserved=False, properties=b"", will_properties=b""):
if (proto_ver&0x7F) == 3 or proto_ver == 0:
@ -556,13 +557,13 @@ def _gen_short(cmd, reason_code=-1, proto_ver=5, properties=None):
properties = mqtt5_props.prop_finalise(properties)
return struct.pack("!BBB", cmd, 1+len(properties), reason_code) + properties
else:
return struct.pack('!BB', 224, 0)
return struct.pack('!BB', cmd, 0)
def gen_disconnect(reason_code=-1, proto_ver=4, properties=None):
return _gen_short(224, reason_code, proto_ver, properties)
return _gen_short(0xE0, reason_code, proto_ver, properties)
def gen_auth(reason_code=-1, properties=None):
return _gen_short(240, 5, properties)
return _gen_short(0xF0, reason_code, 5, properties)
def pack_remaining_length(remaining_length):