Multistep auth, plus reauth, plus tests.
This commit is contained in:
parent
c1776a0b39
commit
2e7dcee342
@ -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);
|
||||
|
||||
/*
|
||||
|
@ -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 {
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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 $@
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
83
src/send_auth.c
Normal 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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
94
test/broker/09-extended-auth-multistep-reauth.py
Executable file
94
test/broker/09-extended-auth-multistep-reauth.py
Executable 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)
|
||||
|
53
test/broker/09-extended-auth-multistep.py
Executable file
53
test/broker/09-extended-auth-multistep.py
Executable 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)
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
||||
|
80
test/broker/c/auth_plugin_extended_multiple.c
Normal file
80
test/broker/c/auth_plugin_extended_multiple.c
Normal 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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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'),
|
||||
|
@ -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):
|
||||
|
Loading…
Reference in New Issue
Block a user