diff --git a/ChangeLog.txt b/ChangeLog.txt index b214eb2b..11e35caa 100644 --- a/ChangeLog.txt +++ b/ChangeLog.txt @@ -170,6 +170,9 @@ Client library: gives access to reason codes for each of the unsubscription requests. - Add `mosquitto_property_remove`, for removing properties from property lists. +- Add `on_ext_auth()` callback to allow handling MQTT v5 extended authentication. +- Add `mosquitto_ext_auth_continue()` function to continue an MQTT v5 extended + authentication. Clients: - Add `-W` timeout support to Windows. diff --git a/include/mosquitto/libmosquitto_auth.h b/include/mosquitto/libmosquitto_auth.h index 30480596..a9df5454 100644 --- a/include/mosquitto/libmosquitto_auth.h +++ b/include/mosquitto/libmosquitto_auth.h @@ -56,6 +56,26 @@ extern "C" { */ libmosq_EXPORT int mosquitto_username_pw_set(struct mosquitto *mosq, const char *username, const char *password); +/* + * Function: mosquitto_ext_auth_continue + * + * Use within an on_ext_auth callback only. + * + * Call to continue the MQTT v5 extended authentication flow. + * + * Parameters: + * mosq - a valid mosquitto instance. + * auth_method - the authentication method as provided in the on_ext_auth callback + * auth_data - authentication data to send to the broker, or NULL + * auth_data_len - the length of auth_data, in bytes, or 0 + * + * Returns: + * MOSQ_ERR_SUCCESS - on success. + * MOSQ_ERR_INVAL - if the input parameters were invalid. + * MOSQ_ERR_NOMEM - if an out of memory condition occurred. + */ +libmosq_EXPORT int mosquitto_ext_auth_continue(struct mosquitto *context, const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props); + #ifdef __cplusplus } #endif diff --git a/include/mosquitto/libmosquitto_callbacks.h b/include/mosquitto/libmosquitto_callbacks.h index c522e00d..b560ee45 100644 --- a/include/mosquitto/libmosquitto_callbacks.h +++ b/include/mosquitto/libmosquitto_callbacks.h @@ -410,6 +410,38 @@ libmosq_EXPORT void mosquitto_unsubscribe_v5_callback_set(struct mosquitto *mosq */ libmosq_EXPORT void mosquitto_unsubscribe2_v5_callback_set(struct mosquitto *mosq, void (*on_unsubscribe)(struct mosquitto *, void *, int, int, const int *, const mosquitto_property *props)); +/* + * Function: mosquitto_ext_auth_callback_set + * + * Set the callback for extended authentication. This should be used if you + * want to support MQTT v5.0 extended authentication. + * + * mosq - a valid mosquitto instance. + * on_ext_auth - a callback function in the following form: + * void callback(struct mosquitto *mosq, void *obj, const char *auth_method, int auth_data_len, const void *auth_data, const mosquitto_property *props) + * + * Callback Parameters: + * mosq - the mosquitto instance making the callback. + * obj - the user data provided in + * auth_method - the authentication method provided by the broker + * auth_data_len - the length of auth_data in bytes + * auth_data - the authentication data, or NULL + * props - list of MQTT 5 properties sent + * note that this includes the auth-method and auth-data + * properties, so you cannot use it directly with + * mosquitto_ext_auth_continue and must instead create your + * own property list + * + * Callback Return: + * MOSQ_ERR_SUCCESS - if you accept the authentication data + * MOSQ_ERR_AUTH - if the authentication should fail + * MOSQ_ERR_NOMEM - on out of memory + * + * See Also: + * + */ +void mosquitto_ext_auth_callback_set(struct mosquitto *mosq, int (*on_auth)(struct mosquitto *, void *, const char *, uint16_t, const void *, const mosquitto_property *props)); + /* * Function: mosquitto_log_callback_set * diff --git a/include/mosquitto/libmosquittopp.h b/include/mosquitto/libmosquittopp.h index 4d99e240..3226526e 100644 --- a/include/mosquitto/libmosquittopp.h +++ b/include/mosquitto/libmosquittopp.h @@ -120,6 +120,7 @@ class mosqpp_EXPORT mosquittopp { void message_retry_set(unsigned int message_retry); void user_data_set(void *userdata); int tls_set(const char *cafile, const char *capath=NULL, const char *certfile=NULL, const char *keyfile=NULL, int (*pw_callback)(char *buf, int size, int rwflag, void *userdata)=NULL); + int ext_auth_continue(const char *auth_method, uint16_t auth_data_len=0, const void *auth_data=NULL, const mosquitto_property *properties=NULL); int tls_opts_set(int cert_reqs, const char *tls_version=NULL, const char *ciphers=NULL); int tls_insecure_set(bool value); int tls_psk_set(const char *psk, const char *identity, const char *ciphers=NULL); @@ -156,6 +157,7 @@ class mosqpp_EXPORT mosquittopp { virtual void on_unsubscribe_v5(int /*mid*/, const mosquitto_property * /*props*/) {return;} virtual void on_log(int /*level*/, const char * /*str*/) {return;} virtual void on_error() {return;} + virtual int on_ext_auth(const char * /*auth_method*/, uint16_t /*auth_data_len*/, const void * /*auth_data*/, const mosquitto_property * /*props*/) {return MOSQ_ERR_AUTH;} }; } diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 187b9498..4db1074a 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -10,6 +10,7 @@ set(C_SRC alias_mosq.c alias_mosq.h callbacks.c connect.c + extended_auth.c handle_auth.c handle_connack.c handle_disconnect.c diff --git a/lib/Makefile b/lib/Makefile index d7ef9b93..602a5955 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -46,6 +46,7 @@ OBJS= \ alias_mosq.o \ callbacks.o \ connect.o \ + extended_auth.o \ handle_auth.o \ handle_connack.o \ handle_disconnect.o \ diff --git a/lib/callbacks.c b/lib/callbacks.c index 5e7490ba..a8eff182 100644 --- a/lib/callbacks.c +++ b/lib/callbacks.c @@ -136,6 +136,14 @@ void mosquitto_log_callback_set(struct mosquitto *mosq, void (*on_log)(struct mo } +void mosquitto_ext_auth_callback_set(struct mosquitto *mosq, int (*on_ext_auth)(struct mosquitto *, void *, const char *, uint16_t, const void *, const mosquitto_property *props)) +{ + pthread_mutex_lock(&mosq->callback_mutex); + mosq->on_ext_auth = on_ext_auth; + pthread_mutex_unlock(&mosq->callback_mutex); +} + + void callback__on_pre_connect(struct mosquitto *mosq) { void (*on_pre_connect)(struct mosquitto *, void *userdata); @@ -286,3 +294,20 @@ void callback__on_disconnect(struct mosquitto *mosq, int rc, const mosquitto_pro } mosq->callback_depth--; } + +int callback__on_ext_auth(struct mosquitto *mosq, const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *properties) +{ + int rc = MOSQ_ERR_AUTH; + int (*on_ext_auth)(struct mosquitto *, void *userdata, const char *, uint16_t, const void *, const mosquitto_property *props); + + pthread_mutex_lock(&mosq->callback_mutex); + on_ext_auth = mosq->on_ext_auth; + pthread_mutex_unlock(&mosq->callback_mutex); + + mosq->callback_depth++; + if(on_ext_auth){ + rc = on_ext_auth(mosq, mosq->userdata, auth_method, auth_data_len, auth_data, properties); + } + mosq->callback_depth--; + return rc; +} diff --git a/lib/callbacks.h b/lib/callbacks.h index fb33d547..8acc21ea 100644 --- a/lib/callbacks.h +++ b/lib/callbacks.h @@ -27,5 +27,6 @@ void callback__on_message(struct mosquitto *mosq, const struct mosquitto_message void callback__on_subscribe(struct mosquitto *mosq, int mid, int qos_count, const int *granted_qos, const mosquitto_property *props); void callback__on_unsubscribe(struct mosquitto *mosq, int mid, int reason_code_count, const int *reason_codes, const mosquitto_property *props); void callback__on_disconnect(struct mosquitto *mosq, int rc, const mosquitto_property *props); +int callback__on_ext_auth(struct mosquitto *mosq, const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *properties); #endif diff --git a/lib/cpp/mosquittopp.cpp b/lib/cpp/mosquittopp.cpp index 2d3b5d86..683e88ca 100644 --- a/lib/cpp/mosquittopp.cpp +++ b/lib/cpp/mosquittopp.cpp @@ -125,6 +125,14 @@ static void on_unsubscribe_v5_wrapper(struct mosquitto *mosq, void *userdata, in } +static int on_ext_auth_wrapper(struct mosquitto *mosq, void *userdata, const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props) +{ + class mosquittopp *m = (class mosquittopp *)userdata; + UNUSED(mosq); + return m->on_ext_auth(auth_method, auth_data_len, auth_data, props); +} + + static void on_log_wrapper(struct mosquitto *mosq, void *userdata, int level, const char *str) { class mosquittopp *m = (class mosquittopp *)userdata; @@ -273,6 +281,7 @@ void mosquitto_callbacks_set(struct mosquitto *mosq) { mosquitto_subscribe_v5_callback_set(mosq, on_subscribe_v5_wrapper); mosquitto_unsubscribe_callback_set(mosq, on_unsubscribe_wrapper); mosquitto_unsubscribe_v5_callback_set(mosq, on_unsubscribe_v5_wrapper); + mosquitto_ext_auth_callback_set(mosq, on_ext_auth_wrapper); mosquitto_log_callback_set(mosq, on_log_wrapper); } } @@ -345,6 +354,11 @@ int mosquittopp::disconnect_v5(int reason_code, const mosquitto_property *proper return mosquitto_disconnect_v5(m_mosq, reason_code, properties); } +int mosquittopp::ext_auth_continue(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *properties) +{ + return mosquitto_ext_auth_continue(m_mosq, auth_method, auth_data_len, auth_data, properties); +} + int mosquittopp::socket() { return mosquitto_socket(m_mosq); diff --git a/lib/extended_auth.c b/lib/extended_auth.c new file mode 100644 index 00000000..949ef5b0 --- /dev/null +++ b/lib/extended_auth.c @@ -0,0 +1,64 @@ +/* +Copyright (c) 2019-2024 Roger Light + +All rights reserved. This program and the accompanying materials +are made available under the terms of the Eclipse Public License 2.0 +and Eclipse Distribution License v1.0 which accompany this distribution. + +The Eclipse Public License is available at + https://www.eclipse.org/legal/epl-2.0/ +and the Eclipse Distribution License is available at + http://www.eclipse.org/org/documents/edl-v10.php. + +SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause + +Contributors: + Roger Light - initial implementation and documentation. +*/ + +#include "config.h" + +#include "mosquitto/mqtt_protocol.h" +#include "packet_mosq.h" +#include "property_mosq.h" +#include "util_mosq.h" + +int mosquitto_ext_auth_continue(struct mosquitto *context, const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *input_props) +{ + struct mosquitto__packet *packet = NULL; + int rc; + uint32_t remaining_length; + mosquitto_property *properties = NULL; + + rc = mosquitto_property_copy_all(&properties, input_props); + if(rc) return rc; + + if(!context || context->protocol != mosq_p_mqtt5 || !auth_method) return MOSQ_ERR_PROTOCOL; + + remaining_length = 1; + + rc = mosquitto_property_add_string(&properties, MQTT_PROP_AUTHENTICATION_METHOD, auth_method); + if(rc) goto error; + + 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) goto error; + } + + remaining_length += mosquitto_property_get_remaining_length(properties); + + rc = packet__check_oversize(context, remaining_length); + if(rc) goto error; + + rc = packet__alloc(&packet, CMD_AUTH, remaining_length); + if(rc) goto error; + + packet__write_byte(packet, MQTT_RC_CONTINUE_AUTHENTICATION); + property__write_all(packet, properties, true); + mosquitto_property_free_all(&properties); + + return packet__queue(context, packet); +error: + mosquitto_property_free_all(&properties); + return rc; +} diff --git a/lib/handle_auth.c b/lib/handle_auth.c index 5907e483..796289cc 100644 --- a/lib/handle_auth.c +++ b/lib/handle_auth.c @@ -21,6 +21,7 @@ Contributors: #include #include +#include "callbacks.h" #include "logging_mosq.h" #include "mosquitto_internal.h" #include "mosquitto/mqtt_protocol.h" @@ -33,6 +34,9 @@ int handle__auth(struct mosquitto *mosq) { int rc = 0; uint8_t reason_code; + char *auth_method = NULL; + void *auth_data = NULL; + uint16_t auth_data_len = 0; mosquitto_property *properties = NULL; if(!mosq) return MOSQ_ERR_INVAL; @@ -49,7 +53,11 @@ int handle__auth(struct mosquitto *mosq) rc = property__read_all(CMD_AUTH, &mosq->in_packet, &properties); if(rc) return rc; - mosquitto_property_free_all(&properties); /* FIXME - TEMPORARY UNTIL PROPERTIES PROCESSED */ - return MOSQ_ERR_SUCCESS; + mosquitto_property_read_string(properties, MQTT_PROP_AUTHENTICATION_METHOD, &auth_method, false); + mosquitto_property_read_binary(properties, MQTT_PROP_AUTHENTICATION_DATA, &auth_data, &auth_data_len, false); + rc = callback__on_ext_auth(mosq, auth_method, auth_data_len, auth_data, properties); + mosquitto_property_free_all(&properties); + + return rc; } diff --git a/lib/linker.version b/lib/linker.version index b1313f6d..7f8dbd0a 100644 --- a/lib/linker.version +++ b/lib/linker.version @@ -144,6 +144,8 @@ MOSQ_1.7 { MOSQ_2.1 { global: + mosquitto_ext_auth_callback_set; + mosquitto_ext_auth_continue; mosquitto_pre_connect_callback_set; mosquitto_topic_matches_sub_with_pattern; mosquitto_sub_matches_acl; diff --git a/lib/mosquitto_internal.h b/lib/mosquitto_internal.h index b48c00d2..f4fd487f 100644 --- a/lib/mosquitto_internal.h +++ b/lib/mosquitto_internal.h @@ -405,6 +405,7 @@ struct mosquitto { void (*on_unsubscribe)(struct mosquitto *, void *userdata, int mid); void (*on_unsubscribe_v5)(struct mosquitto *, void *userdata, int mid, const mosquitto_property *props); void (*on_unsubscribe2_v5)(struct mosquitto *, void *userdata, int mid, int reason_code_count, const int *reason_codes, const mosquitto_property *props); + int (*on_ext_auth)(struct mosquitto *, void *userdata, const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props); void (*on_log)(struct mosquitto *, void *userdata, int level, const char *str); /*void (*on_error)();*/ char *host; diff --git a/test/lib/01-extended-auth-continue.py b/test/lib/01-extended-auth-continue.py new file mode 100755 index 00000000..bccbe799 --- /dev/null +++ b/test/lib/01-extended-auth-continue.py @@ -0,0 +1,28 @@ +#!/usr/bin/env python3 + +from mosq_test_helper import * +import mqtt5_rc + +def do_test(conn, data): + props = mqtt5_props.gen_uint32_prop(mqtt5_props.PROP_MAXIMUM_PACKET_SIZE, 1000) + props += mqtt5_props.gen_uint16_prop(mqtt5_props.PROP_RECEIVE_MAXIMUM, 20) + connect_packet = mosq_test.gen_connect("01-extended-auth", proto_ver=5, properties=props) + + props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "test-method") + props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "test-request") # This is really a binary property + auth_continue_b2c = 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, "test-method") + props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "test-reply") # This is really a binary property + auth_continue_c2b = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_CONTINUE_AUTHENTICATION, properties=props) + connack_packet = mosq_test.gen_connack(rc=0, proto_ver=5) + + disconnect_packet = mosq_test.gen_disconnect(proto_ver=5) + + mosq_test.do_receive_send(conn, connect_packet, auth_continue_b2c, "auth_b2c") + mosq_test.do_receive_send(conn, auth_continue_c2b, connack_packet, "connack") + mosq_test.expect_packet(conn, "disconnect", disconnect_packet) + + +mosq_test.client_test("c/01-extended-auth-continue.test", [], do_test, None) +mosq_test.client_test("cpp/01-extended-auth-continue.test", [], do_test, None) diff --git a/test/lib/01-extended-auth-failure.py b/test/lib/01-extended-auth-failure.py new file mode 100755 index 00000000..1e04ef68 --- /dev/null +++ b/test/lib/01-extended-auth-failure.py @@ -0,0 +1,24 @@ +#!/usr/bin/env python3 + +from mosq_test_helper import * +import mqtt5_rc + +def do_test(conn, data): + props = mqtt5_props.gen_uint32_prop(mqtt5_props.PROP_MAXIMUM_PACKET_SIZE, 1000) + props += mqtt5_props.gen_uint16_prop(mqtt5_props.PROP_RECEIVE_MAXIMUM, 20) + connect_packet = mosq_test.gen_connect("01-extended-auth", proto_ver=5, properties=props) + + props = mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_METHOD, "test-method") + props += mqtt5_props.gen_string_prop(mqtt5_props.PROP_AUTHENTICATION_DATA, "test-request") # This is really a binary property + auth_continue_b2c = mosq_test.gen_auth(reason_code=mqtt5_rc.MQTT_RC_CONTINUE_AUTHENTICATION, properties=props) + + disconnect_packet = mosq_test.gen_disconnect(proto_ver=5) + + mosq_test.do_receive_send(conn, connect_packet, auth_continue_b2c, "auth_b2c") + p = conn.recv(1) + if len(p) == 1: + exit(1) + + +mosq_test.client_test("c/01-extended-auth-failure.test", [], do_test, None) +mosq_test.client_test("cpp/01-extended-auth-failure.test", [], do_test, None) diff --git a/test/lib/Makefile b/test/lib/Makefile index 5f010bda..9016d2a2 100644 --- a/test/lib/Makefile +++ b/test/lib/Makefile @@ -30,6 +30,8 @@ test : test-compile ./01-con-discon-will.py ./01-con-discon-will-v5.py ./01-con-discon-will-clear.py + ./01-extended-auth-continue.py + ./01-extended-auth-failure.py ./01-keepalive-pingreq.py ./01-no-clean-session.py ./01-server-keepalive-pingreq.py diff --git a/test/lib/c/01-extended-auth-continue.c b/test/lib/c/01-extended-auth-continue.c new file mode 100644 index 00000000..d808c266 --- /dev/null +++ b/test/lib/c/01-extended-auth-continue.c @@ -0,0 +1,89 @@ +#include +#include +#include +#include +#include +#include + +static int run = -1; + +static void on_connect(struct mosquitto *mosq, void *obj, int rc, int flags, const mosquitto_property *properties) +{ + (void)obj; + (void)rc; + (void)flags; + (void)properties; + + /* FIXME - should verify flags and all properties here. */ + if(rc){ + exit(1); + }else{ + mosquitto_disconnect(mosq); + } +} + +static int on_ext_auth(struct mosquitto *mosq, void *obj, const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *properties) +{ + (void)obj; + (void)auth_data; + (void)auth_data_len; + (void)properties; + + if(strcmp(auth_method, "test-method")){ + run = 1; + return MOSQ_ERR_AUTH; + } + if(auth_data_len == 0 || (!auth_data || strcmp(auth_data, "test-request"))){ + run = 1; + return MOSQ_ERR_AUTH; + } + return mosquitto_ext_auth_continue(mosq, auth_method, strlen("test-reply"), "test-reply", NULL); +} + +static void on_disconnect(struct mosquitto *mosq, void *obj, int rc, const mosquitto_property *properties) +{ + (void)mosq; + (void)obj; + (void)properties; + + /* FIXME - should verify flags and all properties here. */ + run = rc; +} + +int main(int argc, char *argv[]) +{ + int rc; + struct mosquitto *mosq; + int port; + mosquitto_property *props = NULL; + + if(argc < 2){ + return 1; + } + port = atoi(argv[1]); + + mosquitto_lib_init(); + + mosq = mosquitto_new("01-extended-auth", true, NULL); + if(mosq == NULL){ + return 1; + } + mosquitto_int_option(mosq, MOSQ_OPT_PROTOCOL_VERSION, 5); + mosquitto_connect_v5_callback_set(mosq, on_connect); + mosquitto_ext_auth_callback_set(mosq, on_ext_auth); + mosquitto_disconnect_v5_callback_set(mosq, on_disconnect); + + mosquitto_property_add_int32(&props, MQTT_PROP_MAXIMUM_PACKET_SIZE, 1000); + rc = mosquitto_connect_bind_v5(mosq, "localhost", port, 60, NULL, props); + mosquitto_property_free_all(&props); + if(rc != MOSQ_ERR_SUCCESS) return rc; + + while(run == -1){ + mosquitto_loop(mosq, -1, 1); + } + + mosquitto_destroy(mosq); + + mosquitto_lib_cleanup(); + return run; +} diff --git a/test/lib/c/01-extended-auth-failure.c b/test/lib/c/01-extended-auth-failure.c new file mode 100644 index 00000000..2db090c1 --- /dev/null +++ b/test/lib/c/01-extended-auth-failure.c @@ -0,0 +1,83 @@ +#include +#include +#include +#include +#include +#include + +static int run = -1; + +static void on_connect(struct mosquitto *mosq, void *obj, int rc, int flags, const mosquitto_property *properties) +{ + (void)obj; + (void)rc; + (void)flags; + (void)properties; + + /* FIXME - should verify flags and all properties here. */ + if(rc){ + exit(1); + }else{ + mosquitto_disconnect(mosq); + } +} + +static int on_ext_auth(struct mosquitto *mosq, void *obj, const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *properties) +{ + (void)mosq; + (void)obj; + (void)auth_method; + (void)auth_data; + (void)auth_data_len; + (void)properties; + + return MOSQ_ERR_AUTH; +} + +static void on_disconnect(struct mosquitto *mosq, void *obj, int rc, const mosquitto_property *properties) +{ + (void)mosq; + (void)obj; + (void)properties; + + /* FIXME - should verify flags and all properties here. */ + run = rc; +} + +int main(int argc, char *argv[]) +{ + int rc; + struct mosquitto *mosq; + int port; + mosquitto_property *props = NULL; + + if(argc < 2){ + return 1; + } + port = atoi(argv[1]); + + mosquitto_lib_init(); + + mosq = mosquitto_new("01-extended-auth", true, NULL); + if(mosq == NULL){ + return 1; + } + mosquitto_int_option(mosq, MOSQ_OPT_PROTOCOL_VERSION, 5); + mosquitto_connect_v5_callback_set(mosq, on_connect); + mosquitto_ext_auth_callback_set(mosq, on_ext_auth); + mosquitto_disconnect_v5_callback_set(mosq, on_disconnect); + + mosquitto_property_add_int32(&props, MQTT_PROP_MAXIMUM_PACKET_SIZE, 1000); + rc = mosquitto_connect_bind_v5(mosq, "localhost", port, 60, NULL, props); + mosquitto_property_free_all(&props); + if(rc != MOSQ_ERR_SUCCESS) return rc; + + while(run == -1){ + mosquitto_loop(mosq, -1, 1); + } + + mosquitto_destroy(mosq); + + mosquitto_lib_cleanup(); + return run; +} diff --git a/test/lib/c/CMakeLists.txt b/test/lib/c/CMakeLists.txt index 4e60249c..7b8cdb0f 100644 --- a/test/lib/c/CMakeLists.txt +++ b/test/lib/c/CMakeLists.txt @@ -4,6 +4,8 @@ set(BINARIES 01-con-discon-will 01-con-discon-will-clear 01-con-discon-will-v5 + 01-extended-auth-continue + 01-extended-auth-failure 01-keepalive-pingreq 01-no-clean-session 01-pre-connect-callback diff --git a/test/lib/c/Makefile b/test/lib/c/Makefile index 1483ac54..11349c15 100644 --- a/test/lib/c/Makefile +++ b/test/lib/c/Makefile @@ -13,6 +13,8 @@ SRC = \ 01-con-discon-will.c \ 01-con-discon-will-v5.c \ 01-con-discon-will-clear.c \ + 01-extended-auth-continue.c \ + 01-extended-auth-failure.c \ 01-keepalive-pingreq.c \ 01-no-clean-session.c \ 01-pre-connect-callback.c \ diff --git a/test/lib/cpp/01-extended-auth-continue.cpp b/test/lib/cpp/01-extended-auth-continue.cpp new file mode 100644 index 00000000..aae0737f --- /dev/null +++ b/test/lib/cpp/01-extended-auth-continue.cpp @@ -0,0 +1,84 @@ +#include +#include +#include + +static int run = -1; + +class mosquittopp_test : public mosqpp::mosquittopp +{ + public: + mosquittopp_test(const char *id); + + void on_connect_v5(int rc, int flags, const mosquitto_property *props); + void on_disconnect_v5(int rc, const mosquitto_property *props); + int on_ext_auth(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props); +}; + +mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id) +{ +} + +void mosquittopp_test::on_connect_v5(int rc, int flags, const mosquitto_property *props) +{ + assert(flags == 0); + assert(props); + assert(mosqpp::property_check_all(CMD_CONNACK, props) == MOSQ_ERR_SUCCESS); + + if(rc){ + exit(1); + }else{ + disconnect(); + } +} + +void mosquittopp_test::on_disconnect_v5(int rc, const mosquitto_property *props) +{ + assert(props == NULL); + run = rc; +} + + +int mosquittopp_test::on_ext_auth(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props) +{ + assert(props != NULL); + + if(strcmp(auth_method, "test-method")){ + run = 1; + return MOSQ_ERR_AUTH; + } + if(auth_data_len == 0 || (!auth_data || strcmp((const char *)auth_data, "test-request"))){ + run = 1; + return MOSQ_ERR_AUTH; + } + return ext_auth_continue(auth_method, strlen("test-reply"), "test-reply", NULL); +} + + +int main(int argc, char *argv[]) +{ + mosquittopp_test *mosq; + mosquitto_property *props = NULL; + int rc; + + assert(argc == 2); + int port = atoi(argv[1]); + + mosqpp::lib_init(); + + mosq = new mosquittopp_test("01-extended-auth"); + mosq->int_option(MOSQ_OPT_PROTOCOL_VERSION, 5); + + mosquitto_property_add_int32(&props, MQTT_PROP_MAXIMUM_PACKET_SIZE, 1000); + rc = mosq->connect_v5("localhost", port, 60, NULL, props); + mosquitto_property_free_all(&props); + if(rc != MOSQ_ERR_SUCCESS) return rc; + + while(run == -1){ + mosq->loop(); + } + delete mosq; + + mosqpp::lib_cleanup(); + + return run; +} diff --git a/test/lib/cpp/01-extended-auth-failure.cpp b/test/lib/cpp/01-extended-auth-failure.cpp new file mode 100644 index 00000000..1d2fcf3e --- /dev/null +++ b/test/lib/cpp/01-extended-auth-failure.cpp @@ -0,0 +1,78 @@ +#include +#include +#include + +static int run = -1; + +class mosquittopp_test : public mosqpp::mosquittopp +{ + public: + mosquittopp_test(const char *id); + + void on_connect_v5(int rc, int flags, const mosquitto_property *props); + void on_disconnect_v5(int rc, const mosquitto_property *props); + int on_ext_auth(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props); +}; + +mosquittopp_test::mosquittopp_test(const char *id) : mosqpp::mosquittopp(id) +{ +} + +void mosquittopp_test::on_connect_v5(int rc, int flags, const mosquitto_property *props) +{ + assert(flags == 0); + assert(props); + assert(mosqpp::property_check_all(CMD_CONNACK, props) == MOSQ_ERR_SUCCESS); + + if(rc){ + exit(1); + }else{ + disconnect(); + } +} + +void mosquittopp_test::on_disconnect_v5(int rc, const mosquitto_property *props) +{ + assert(props == NULL); + run = rc; +} + + +int mosquittopp_test::on_ext_auth(const char *auth_method, uint16_t auth_data_len, const void *auth_data, const mosquitto_property *props) +{ + (void)auth_method; + (void)auth_data_len; + (void)auth_data; + (void)props; + return MOSQ_ERR_AUTH; +} + + +int main(int argc, char *argv[]) +{ + mosquittopp_test *mosq; + mosquitto_property *props = NULL; + int rc; + + assert(argc == 2); + int port = atoi(argv[1]); + + mosqpp::lib_init(); + + mosq = new mosquittopp_test("01-extended-auth"); + mosq->int_option(MOSQ_OPT_PROTOCOL_VERSION, 5); + + mosquitto_property_add_int32(&props, MQTT_PROP_MAXIMUM_PACKET_SIZE, 1000); + rc = mosq->connect_v5("localhost", port, 60, NULL, props); + mosquitto_property_free_all(&props); + if(rc != MOSQ_ERR_SUCCESS) return rc; + + while(run == -1){ + mosq->loop(); + } + delete mosq; + + mosqpp::lib_cleanup(); + + return run; +} diff --git a/test/lib/cpp/CMakeLists.txt b/test/lib/cpp/CMakeLists.txt index cb819e82..e71ed7ef 100644 --- a/test/lib/cpp/CMakeLists.txt +++ b/test/lib/cpp/CMakeLists.txt @@ -4,6 +4,8 @@ set(BINARIES 01-con-discon-will-clear 01-con-discon-will 01-con-discon-will-v5 + 01-extended-auth-continue + 01-extended-auth-failure 01-keepalive-pingreq 01-no-clean-session 01-pre-connect-callback diff --git a/test/lib/cpp/Makefile b/test/lib/cpp/Makefile index 7e8a2b73..29664c68 100644 --- a/test/lib/cpp/Makefile +++ b/test/lib/cpp/Makefile @@ -12,6 +12,8 @@ SRC = \ 01-con-discon-will-clear.cpp \ 01-con-discon-will-v5.cpp \ 01-con-discon-will.cpp \ + 01-extended-auth-continue.cpp \ + 01-extended-auth-failure.cpp \ 01-keepalive-pingreq.cpp \ 01-no-clean-session.cpp \ 01-pre-connect-callback.cpp \ diff --git a/test/lib/test.py b/test/lib/test.py index a8ac951e..ee29a18b 100755 --- a/test/lib/test.py +++ b/test/lib/test.py @@ -9,6 +9,8 @@ tests = [ (1, './01-con-discon-will-clear.py'), (1, './01-con-discon-will-v5.py'), (1, './01-con-discon-will.py'), + (1, './01-extended-auth-complete.py'), + (1, './01-extended-auth-failure.py'), (1, './01-keepalive-pingreq.py'), (1, './01-no-clean-session.py'), (1, './01-server-keepalive-pingreq.py'),