mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Added support for sending and receiving MQTT messages. It enables end user to quickly upload or share JSON files between them. Given the nature of MQTT, I also worked with @KevTheHermit who has proxdump.com site, where you can upload pm3 dump files and browse. He added support for MQTT uploads, so the process to share a file and it gets also uploaded to proxdump.com is very smooth. Feel free to improve this functionality with TLS etc. For now it looks quite promising.
This commit is contained in:
parent
732cc1b82e
commit
c7cf62fcf1
22 changed files with 4742 additions and 10 deletions
|
@ -3,6 +3,7 @@ All notable changes to this project will be documented in this file.
|
|||
This project uses the changelog in accordance with [keepchangelog](http://keepachangelog.com/). Please use this to write notable changes, which is not the same as git commit log...
|
||||
|
||||
## [unreleased][unreleased]
|
||||
- Added `mqtt` - the pm3 client can now send and receive MQTT messages or json files. (@iceman1001)
|
||||
- Changed `hf iclass wrbl` - replay behavior to use privilege escalation if the macs field is not passed empty(@antiklesys)
|
||||
- Changed `hf iclass restore` - it now supports privilege escalation to restore card content using replay (@antiklesys)
|
||||
- Fixed `hf 15 dump` - now reads sysinfo response correct (@iceman1001)
|
||||
|
|
|
@ -402,6 +402,7 @@ set (TARGET_SOURCES
|
|||
${PM3_ROOT}/client/src/cmdlfvisa2000.c
|
||||
${PM3_ROOT}/client/src/cmdlfzx8211.c
|
||||
${PM3_ROOT}/client/src/cmdmain.c
|
||||
${PM3_ROOT}/client/src/cmdmqtt.c
|
||||
${PM3_ROOT}/client/src/cmdnfc.c
|
||||
${PM3_ROOT}/client/src/cmdparser.c
|
||||
${PM3_ROOT}/client/src/cmdpiv.c
|
||||
|
@ -772,6 +773,7 @@ target_link_libraries(proxmark3 PRIVATE
|
|||
pm3rrg_rdv4_reveng
|
||||
pm3rrg_rdv4_hardnested
|
||||
pm3rrg_rdv4_id48
|
||||
pm3rrg_rdv4_mqtt
|
||||
${ADDITIONAL_LNK})
|
||||
|
||||
if (NOT SKIPPTHREAD EQUAL 1)
|
||||
|
|
|
@ -131,6 +131,12 @@ WHEREAMILIBINC = -I$(WHEREAMILIBPATH)
|
|||
WHEREAMILIB = $(WHEREAMILIBPATH)/libwhereami.a
|
||||
WHEREAMILIBLD =
|
||||
|
||||
## MQTT
|
||||
MQTTLIBPATH = ./deps/mqtt
|
||||
MQTTLIBINC = -I$(MQTTLIBPATH)
|
||||
MQTTLIB = $(MQTTLIBPATH)/mqtt.a
|
||||
MQTTLIBLD =
|
||||
|
||||
##########################
|
||||
# common local libraries #
|
||||
##########################
|
||||
|
@ -239,6 +245,12 @@ STATICLIBS += $(WHEREAMILIB)
|
|||
LDLIBS += $(WHEREAMILIBLD)
|
||||
PM3INCLUDES += $(WHEREAMILIBINC)
|
||||
|
||||
## MQTT
|
||||
# not distributed as system library
|
||||
STATICLIBS += $(MQTTLIB)
|
||||
LDLIBS += $(MQTTLIBLD)
|
||||
PM3INCLUDES += $(MQTTLIBINC)
|
||||
|
||||
####################
|
||||
# system libraries #
|
||||
####################
|
||||
|
@ -682,6 +694,7 @@ SRCS = mifare/aiddesfire.c \
|
|||
cmdlfvisa2000.c \
|
||||
cmdlfzx8211.c \
|
||||
cmdmain.c \
|
||||
cmdmqtt.c \
|
||||
cmdnfc.c \
|
||||
cmdparser.c \
|
||||
cmdpiv.c \
|
||||
|
@ -877,6 +890,7 @@ endif
|
|||
$(Q)$(MAKE) --no-print-directory -C $(REVENGLIBPATH) clean
|
||||
$(Q)$(MAKE) --no-print-directory -C $(TINYCBORLIBPATH) clean
|
||||
$(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) clean
|
||||
$(Q)$(MAKE) --no-print-directory -C $(MQTTLIBPATH) clean
|
||||
@# Just in case someone compiled within these dirs:
|
||||
$(Q)$(MAKE) --no-print-directory -C $(MBEDTLSLIBPATH) clean
|
||||
|
||||
|
@ -974,6 +988,10 @@ ifneq ($(WHEREAMI_FOUND),1)
|
|||
$(Q)$(MAKE) --no-print-directory -C $(WHEREAMILIBPATH) all
|
||||
endif
|
||||
|
||||
$(MQTTLIB): .FORCE
|
||||
$(info [*] MAKE $@)
|
||||
$(Q)$(MAKE) --no-print-directory -C $(MQTTLIBPATH) all
|
||||
|
||||
########
|
||||
# SWIG #
|
||||
########
|
||||
|
|
|
@ -31,3 +31,6 @@ endif()
|
|||
if (NOT TARGET pm3rrg_rdv4_whereami)
|
||||
include(whereami.cmake)
|
||||
endif()
|
||||
if (NOT TARGET pm3rrg_rdv4_mqtt)
|
||||
include(mqtt.cmake)
|
||||
endif()
|
9
client/deps/mqtt.cmake
Normal file
9
client/deps/mqtt.cmake
Normal file
|
@ -0,0 +1,9 @@
|
|||
add_library(pm3rrg_rdv4_mqtt STATIC
|
||||
mqtt/mqtt.c
|
||||
mqtt/mqtt_pal.c
|
||||
)
|
||||
|
||||
target_compile_definitions(pm3rrg_rdv4_mqtt PRIVATE WAI_PM3_TUNED)
|
||||
target_include_directories(pm3rrg_rdv4_mqtt INTERFACE mqtt)
|
||||
target_compile_options(pm3rrg_rdv4_mqtt PRIVATE -Wall -Werror -O3)
|
||||
set_property(TARGET pm3rrg_rdv4_mqtt PROPERTY POSITION_INDEPENDENT_CODE ON)
|
21
client/deps/mqtt/LICENSE
Normal file
21
client/deps/mqtt/LICENSE
Normal file
|
@ -0,0 +1,21 @@
|
|||
MIT License
|
||||
|
||||
Copyright (c) 2018 Liam Bindle
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
14
client/deps/mqtt/Makefile
Normal file
14
client/deps/mqtt/Makefile
Normal file
|
@ -0,0 +1,14 @@
|
|||
MYSRCPATHS =
|
||||
MYINCLUDES =
|
||||
MYCFLAGS = -Wno-bad-function-cast -Wno-switch-enum
|
||||
MYDEFS = -DWAI_PM3_TUNED
|
||||
MYSRCS = \
|
||||
mqtt.c \
|
||||
mqtt_pal.c \
|
||||
|
||||
LIB_A = mqtt.a
|
||||
|
||||
# Transition: remove old directories and objects
|
||||
MYCLEANOLDPATH = ../../mqtt
|
||||
|
||||
include ../../../Makefile.host
|
152
client/deps/mqtt/mbedtls_sockets.h
Normal file
152
client/deps/mqtt/mbedtls_sockets.h
Normal file
|
@ -0,0 +1,152 @@
|
|||
#if !defined(__MBEDTLS_SOCKET_TEMPLATE_H__)
|
||||
#define __MBEDTLS_SOCKET_TEMPLATE_H__
|
||||
|
||||
#include <inttypes.h>
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <mbedtls/error.h>
|
||||
#include <mbedtls/entropy.h>
|
||||
#include <mbedtls/ctr_drbg.h>
|
||||
#include <mbedtls/net_sockets.h>
|
||||
#include <mbedtls/ssl.h>
|
||||
|
||||
#if !defined(MBEDTLS_NET_POLL_READ)
|
||||
/* compat for older mbedtls */
|
||||
#define MBEDTLS_NET_POLL_READ 1
|
||||
#define MBEDTLS_NET_POLL_WRITE 1
|
||||
|
||||
int mbedtls_net_poll(mbedtls_net_context *ctx, uint32_t rw, uint32_t timeout) {
|
||||
/* XXX this is not ideal but good enough for an example */
|
||||
msleep(300);
|
||||
return 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
struct mbedtls_context {
|
||||
mbedtls_net_context net_ctx;
|
||||
mbedtls_ssl_context ssl_ctx;
|
||||
mbedtls_ssl_config ssl_conf;
|
||||
mbedtls_x509_crt ca_crt;
|
||||
mbedtls_entropy_context entropy;
|
||||
mbedtls_ctr_drbg_context ctr_drbg;
|
||||
};
|
||||
|
||||
void failed(const char *fn, int rv);
|
||||
void cert_verify_failed(uint32_t rv);
|
||||
void open_nb_socket(struct mbedtls_context *ctx,
|
||||
const char *hostname,
|
||||
const char *port,
|
||||
const char *ca_file);
|
||||
|
||||
|
||||
void failed(const char *fn, int rv) {
|
||||
char buf[100];
|
||||
mbedtls_strerror(rv, buf, sizeof(buf));
|
||||
printf("%s failed with %x (%s)\n", fn, -rv, buf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
void cert_verify_failed(uint32_t rv) {
|
||||
char buf[512];
|
||||
mbedtls_x509_crt_verify_info(buf, sizeof(buf), "\t", rv);
|
||||
printf("Certificate verification failed (%0" PRIx32 ")\n%s\n", rv, buf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
/*
|
||||
A template for opening a non-blocking mbed TLS connection.
|
||||
*/
|
||||
void open_nb_socket(struct mbedtls_context *ctx,
|
||||
const char *hostname,
|
||||
const char *port,
|
||||
const char *ca_file) {
|
||||
|
||||
const unsigned char *additional = (const unsigned char *)"Pm3 Client";
|
||||
size_t additional_len = 6;
|
||||
int rv;
|
||||
|
||||
mbedtls_net_context *net_ctx = &ctx->net_ctx;
|
||||
mbedtls_ssl_context *ssl_ctx = &ctx->ssl_ctx;
|
||||
mbedtls_ssl_config *ssl_conf = &ctx->ssl_conf;
|
||||
mbedtls_x509_crt *ca_crt = &ctx->ca_crt;
|
||||
mbedtls_entropy_context *entropy = &ctx->entropy;
|
||||
mbedtls_ctr_drbg_context *ctr_drbg = &ctx->ctr_drbg;
|
||||
|
||||
mbedtls_entropy_init(entropy);
|
||||
mbedtls_ctr_drbg_init(ctr_drbg);
|
||||
rv = mbedtls_ctr_drbg_seed(ctr_drbg, mbedtls_entropy_func, entropy,
|
||||
additional, additional_len);
|
||||
if (rv != 0) {
|
||||
failed("mbedtls_ctr_drbg_seed", rv);
|
||||
}
|
||||
|
||||
mbedtls_x509_crt_init(ca_crt);
|
||||
rv = mbedtls_x509_crt_parse_file(ca_crt, ca_file);
|
||||
if (rv != 0) {
|
||||
failed("mbedtls_x509_crt_parse_file", rv);
|
||||
}
|
||||
|
||||
mbedtls_ssl_config_init(ssl_conf);
|
||||
rv = mbedtls_ssl_config_defaults(ssl_conf, MBEDTLS_SSL_IS_CLIENT,
|
||||
MBEDTLS_SSL_TRANSPORT_STREAM,
|
||||
MBEDTLS_SSL_PRESET_DEFAULT);
|
||||
if (rv != 0) {
|
||||
failed("mbedtls_ssl_config_defaults", rv);
|
||||
}
|
||||
mbedtls_ssl_conf_ca_chain(ssl_conf, ca_crt, NULL);
|
||||
mbedtls_ssl_conf_authmode(ssl_conf, MBEDTLS_SSL_VERIFY_OPTIONAL);
|
||||
mbedtls_ssl_conf_rng(ssl_conf, mbedtls_ctr_drbg_random, ctr_drbg);
|
||||
|
||||
mbedtls_net_init(net_ctx);
|
||||
rv = mbedtls_net_connect(net_ctx, hostname, port, MBEDTLS_NET_PROTO_TCP);
|
||||
if (rv != 0) {
|
||||
failed("mbedtls_net_connect", rv);
|
||||
}
|
||||
rv = mbedtls_net_set_nonblock(net_ctx);
|
||||
if (rv != 0) {
|
||||
failed("mbedtls_net_set_nonblock", rv);
|
||||
}
|
||||
|
||||
mbedtls_ssl_init(ssl_ctx);
|
||||
rv = mbedtls_ssl_setup(ssl_ctx, ssl_conf);
|
||||
if (rv != 0) {
|
||||
failed("mbedtls_ssl_setup", rv);
|
||||
}
|
||||
rv = mbedtls_ssl_set_hostname(ssl_ctx, hostname);
|
||||
if (rv != 0) {
|
||||
failed("mbedtls_ssl_set_hostname", rv);
|
||||
}
|
||||
mbedtls_ssl_set_bio(ssl_ctx, net_ctx,
|
||||
mbedtls_net_send, mbedtls_net_recv, NULL);
|
||||
|
||||
for (;;) {
|
||||
rv = mbedtls_ssl_handshake(ssl_ctx);
|
||||
uint32_t want = 0;
|
||||
if (rv == MBEDTLS_ERR_SSL_WANT_READ) {
|
||||
want |= MBEDTLS_NET_POLL_READ;
|
||||
} else if (rv == MBEDTLS_ERR_SSL_WANT_WRITE) {
|
||||
want |= MBEDTLS_NET_POLL_WRITE;
|
||||
} else {
|
||||
break;
|
||||
}
|
||||
rv = mbedtls_net_poll(net_ctx, want, (uint32_t) -1);
|
||||
if (rv < 0) {
|
||||
failed("mbedtls_net_poll", rv);
|
||||
}
|
||||
}
|
||||
if (rv != 0) {
|
||||
failed("mbedtls_ssl_handshake", rv);
|
||||
}
|
||||
uint32_t result = mbedtls_ssl_get_verify_result(ssl_ctx);
|
||||
if (result != 0) {
|
||||
if (result == (uint32_t) -1) {
|
||||
failed("mbedtls_ssl_get_verify_result", (int)result);
|
||||
} else {
|
||||
cert_verify_failed(result);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
1770
client/deps/mqtt/mqtt.c
Normal file
1770
client/deps/mqtt/mqtt.c
Normal file
File diff suppressed because it is too large
Load diff
1640
client/deps/mqtt/mqtt.h
Normal file
1640
client/deps/mqtt/mqtt.h
Normal file
File diff suppressed because it is too large
Load diff
235
client/deps/mqtt/mqtt_pal.c
Normal file
235
client/deps/mqtt/mqtt_pal.c
Normal file
|
@ -0,0 +1,235 @@
|
|||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2018 Liam Bindle
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#include "mqtt.h"
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Implements @ref mqtt_pal_sendall and @ref mqtt_pal_recvall and
|
||||
* any platform-specific helpers you'd like.
|
||||
* @cond Doxygen_Suppress
|
||||
*/
|
||||
|
||||
#if defined(MQTT_USE_CUSTOM_SOCKET_HANDLE)
|
||||
|
||||
/*
|
||||
* In case of MQTT_USE_CUSTOM_SOCKET_HANDLE, a pal implemantation is
|
||||
* provided by the user.
|
||||
*/
|
||||
|
||||
/* Note: Some toolchains complain on an object without symbols */
|
||||
|
||||
int _mqtt_pal_dummy;
|
||||
|
||||
#else /* defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) */
|
||||
|
||||
#if defined(MQTT_USE_MBEDTLS)
|
||||
#include <mbedtls/ssl.h>
|
||||
|
||||
ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags) {
|
||||
enum MQTTErrors error = 0;
|
||||
size_t sent = 0;
|
||||
while (sent < len) {
|
||||
int rv = mbedtls_ssl_write(fd, (const unsigned char *)buf + sent, len - sent);
|
||||
if (rv < 0) {
|
||||
if (rv == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
rv == MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
#if defined(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS)
|
||||
|| rv == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS
|
||||
#endif
|
||||
#if defined(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS)
|
||||
|| rv == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS
|
||||
#endif
|
||||
) {
|
||||
/* should call mbedtls_ssl_write later again */
|
||||
break;
|
||||
}
|
||||
error = MQTT_ERROR_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
/*
|
||||
* Note: rv can be 0 here eg. when mbedtls just flushed
|
||||
* the previous incomplete record.
|
||||
*
|
||||
* Note: we never send an empty TLS record.
|
||||
*/
|
||||
sent += (size_t) rv;
|
||||
}
|
||||
if (sent == 0) {
|
||||
return error;
|
||||
}
|
||||
return (ssize_t)sent;
|
||||
}
|
||||
|
||||
ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags) {
|
||||
const void *const start = buf;
|
||||
enum MQTTErrors error = 0;
|
||||
int rv;
|
||||
do {
|
||||
rv = mbedtls_ssl_read(fd, (unsigned char *)buf, bufsz);
|
||||
if (rv == 0) {
|
||||
/*
|
||||
* Note: mbedtls_ssl_read returns 0 when the underlying
|
||||
* transport was closed without CloseNotify.
|
||||
*
|
||||
* Raise an error to trigger a reconnect.
|
||||
*/
|
||||
error = MQTT_ERROR_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
if (rv < 0) {
|
||||
if (rv == MBEDTLS_ERR_SSL_WANT_READ ||
|
||||
rv == MBEDTLS_ERR_SSL_WANT_WRITE
|
||||
#if defined(MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS)
|
||||
|| rv == MBEDTLS_ERR_SSL_ASYNC_IN_PROGRESS
|
||||
#endif
|
||||
#if defined(MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS)
|
||||
|| rv == MBEDTLS_ERR_SSL_CRYPTO_IN_PROGRESS
|
||||
#endif
|
||||
) {
|
||||
/* should call mbedtls_ssl_read later again */
|
||||
break;
|
||||
}
|
||||
/* Note: MBEDTLS_ERR_SSL_PEER_CLOSE_NOTIFY is handled here. */
|
||||
error = MQTT_ERROR_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
buf = (char *)buf + rv;
|
||||
bufsz -= (unsigned long)rv;
|
||||
} while (bufsz > 0);
|
||||
if (buf == start) {
|
||||
return error;
|
||||
}
|
||||
return (const char *)buf - (const char *)start;
|
||||
}
|
||||
|
||||
#elif defined(__unix__) || defined(__APPLE__) || defined(__NuttX__)
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags) {
|
||||
enum MQTTErrors error = 0;
|
||||
size_t sent = 0;
|
||||
while (sent < len) {
|
||||
ssize_t rv = send(fd, (const char *)buf + sent, len - sent, flags);
|
||||
if (rv < 0) {
|
||||
if (errno == EAGAIN) {
|
||||
/* should call send later again */
|
||||
break;
|
||||
}
|
||||
error = MQTT_ERROR_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
if (rv == 0) {
|
||||
/* is this possible? maybe OS bug. */
|
||||
error = MQTT_ERROR_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
sent += (size_t) rv;
|
||||
}
|
||||
if (sent == 0) {
|
||||
return error;
|
||||
}
|
||||
return (ssize_t)sent;
|
||||
}
|
||||
|
||||
ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags) {
|
||||
const void *const start = buf;
|
||||
enum MQTTErrors error = 0;
|
||||
ssize_t rv;
|
||||
do {
|
||||
rv = recv(fd, buf, bufsz, flags);
|
||||
if (rv == 0) {
|
||||
/*
|
||||
* recv returns 0 when the socket is (half) closed by the peer.
|
||||
*
|
||||
* Raise an error to trigger a reconnect.
|
||||
*/
|
||||
error = MQTT_ERROR_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
if (rv < 0) {
|
||||
if (errno == EAGAIN || errno == EWOULDBLOCK) {
|
||||
/* should call recv later again */
|
||||
break;
|
||||
}
|
||||
/* an error occurred that wasn't "nothing to read". */
|
||||
error = MQTT_ERROR_SOCKET_ERROR;
|
||||
break;
|
||||
}
|
||||
buf = (char *)buf + rv;
|
||||
bufsz -= (unsigned long)rv;
|
||||
} while (bufsz > 0);
|
||||
if (buf == start) {
|
||||
return error;
|
||||
}
|
||||
return (char *)buf - (const char *)start;
|
||||
}
|
||||
|
||||
#elif defined(_MSC_VER) || defined(WIN32)
|
||||
|
||||
#include <errno.h>
|
||||
|
||||
ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags) {
|
||||
size_t sent = 0;
|
||||
while (sent < len) {
|
||||
ssize_t tmp = send(fd, (char *)buf + sent, len - sent, flags);
|
||||
if (tmp < 1) {
|
||||
return MQTT_ERROR_SOCKET_ERROR;
|
||||
}
|
||||
sent += (size_t) tmp;
|
||||
}
|
||||
return sent;
|
||||
}
|
||||
|
||||
ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags) {
|
||||
const char *const start = buf;
|
||||
ssize_t rv;
|
||||
do {
|
||||
rv = recv(fd, buf, bufsz, flags);
|
||||
if (rv > 0) {
|
||||
/* successfully read bytes from the socket */
|
||||
buf = (char *)buf + rv;
|
||||
bufsz -= rv;
|
||||
} else if (rv < 0) {
|
||||
int err = WSAGetLastError();
|
||||
if (err != WSAEWOULDBLOCK) {
|
||||
/* an error occurred that wasn't "nothing to read". */
|
||||
return MQTT_ERROR_SOCKET_ERROR;
|
||||
}
|
||||
}
|
||||
} while (rv > 0 && bufsz > 0);
|
||||
|
||||
return (ssize_t)((char *)buf - start);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#error No PAL!
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* defined(MQTT_USE_CUSTOM_SOCKET_HANDLE) */
|
||||
|
||||
/** @endcond */
|
173
client/deps/mqtt/mqtt_pal.h
Normal file
173
client/deps/mqtt/mqtt_pal.h
Normal file
|
@ -0,0 +1,173 @@
|
|||
#if !defined(__MQTT_PAL_H__)
|
||||
#define __MQTT_PAL_H__
|
||||
|
||||
/*
|
||||
MIT License
|
||||
|
||||
Copyright(c) 2018 Liam Bindle
|
||||
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files(the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions :
|
||||
|
||||
The above copyright notice and this permission notice shall be included in all
|
||||
copies or substantial portions of the Software.
|
||||
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
SOFTWARE.
|
||||
*/
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @file
|
||||
* @brief Includes/supports the types/calls required by the MQTT-C client.
|
||||
*
|
||||
* @note This is the \em only file included in mqtt.h, and mqtt.c. It is therefore
|
||||
* responsible for including/supporting all the required types and calls.
|
||||
*
|
||||
* @defgroup pal Platform abstraction layer
|
||||
* @brief Documentation of the types and calls required to port MQTT-C to a new platform.
|
||||
*
|
||||
* mqtt_pal.h is the \em only header file included in mqtt.c. Therefore, to port MQTT-C to a
|
||||
* new platform the following types, functions, constants, and macros must be defined in
|
||||
* mqtt_pal.h:
|
||||
* - Types:
|
||||
* - \c size_t, \c ssize_t
|
||||
* - \c uint8_t, \c uint16_t, \c uint32_t
|
||||
* - \c va_list
|
||||
* - \c mqtt_pal_time_t : return type of \c MQTT_PAL_TIME()
|
||||
* - \c mqtt_pal_mutex_t : type of the argument that is passed to \c MQTT_PAL_MUTEX_LOCK and
|
||||
* \c MQTT_PAL_MUTEX_RELEASE
|
||||
* - Functions:
|
||||
* - \c memcpy, \c strlen
|
||||
* - \c va_start, \c va_arg, \c va_end
|
||||
* - Constants:
|
||||
* - \c INT_MIN
|
||||
*
|
||||
* Additionally, three macro's are required:
|
||||
* - \c MQTT_PAL_HTONS(s) : host-to-network endian conversion for uint16_t.
|
||||
* - \c MQTT_PAL_NTOHS(s) : network-to-host endian conversion for uint16_t.
|
||||
* - \c MQTT_PAL_TIME() : returns [type: \c mqtt_pal_time_t] current time in seconds.
|
||||
* - \c MQTT_PAL_MUTEX_LOCK(mtx_pointer) : macro that locks the mutex pointed to by \c mtx_pointer.
|
||||
* - \c MQTT_PAL_MUTEX_RELEASE(mtx_pointer) : macro that unlocks the mutex pointed to by
|
||||
* \c mtx_pointer.
|
||||
*
|
||||
* Lastly, \ref mqtt_pal_sendall and \ref mqtt_pal_recvall, must be implemented in mqtt_pal.c
|
||||
* for sending and receiving data using the platforms socket calls.
|
||||
*/
|
||||
|
||||
|
||||
/* UNIX-like platform support */
|
||||
#if defined(__unix__) || defined(__APPLE__) || defined(__NuttX__)
|
||||
#include <limits.h>
|
||||
#include <string.h>
|
||||
#include <stdarg.h>
|
||||
#include <time.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#define MQTT_PAL_HTONS(s) htons(s)
|
||||
#define MQTT_PAL_NTOHS(s) ntohs(s)
|
||||
|
||||
#define MQTT_PAL_TIME() time(NULL)
|
||||
|
||||
typedef time_t mqtt_pal_time_t;
|
||||
typedef pthread_mutex_t mqtt_pal_mutex_t;
|
||||
|
||||
#define MQTT_PAL_MUTEX_INIT(mtx_ptr) pthread_mutex_init(mtx_ptr, NULL)
|
||||
#define MQTT_PAL_MUTEX_LOCK(mtx_ptr) pthread_mutex_lock(mtx_ptr)
|
||||
#define MQTT_PAL_MUTEX_UNLOCK(mtx_ptr) pthread_mutex_unlock(mtx_ptr)
|
||||
|
||||
#if !defined(MQTT_USE_CUSTOM_SOCKET_HANDLE)
|
||||
#if defined(MQTT_USE_MBEDTLS)
|
||||
struct mbedtls_ssl_context;
|
||||
typedef struct mbedtls_ssl_context *mqtt_pal_socket_handle;
|
||||
#else
|
||||
typedef int mqtt_pal_socket_handle;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif defined(_MSC_VER) || defined(WIN32)
|
||||
#include <limits.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
#include <stdint.h>
|
||||
|
||||
typedef SSIZE_T ssize_t;
|
||||
#define MQTT_PAL_HTONS(s) htons(s)
|
||||
#define MQTT_PAL_NTOHS(s) ntohs(s)
|
||||
|
||||
#define MQTT_PAL_TIME() time(NULL)
|
||||
|
||||
typedef time_t mqtt_pal_time_t;
|
||||
typedef CRITICAL_SECTION mqtt_pal_mutex_t;
|
||||
|
||||
#define MQTT_PAL_MUTEX_INIT(mtx_ptr) InitializeCriticalSection(mtx_ptr)
|
||||
#define MQTT_PAL_MUTEX_LOCK(mtx_ptr) EnterCriticalSection(mtx_ptr)
|
||||
#define MQTT_PAL_MUTEX_UNLOCK(mtx_ptr) LeaveCriticalSection(mtx_ptr)
|
||||
|
||||
|
||||
#if !defined(MQTT_USE_CUSTOM_SOCKET_HANDLE)
|
||||
typedef SOCKET mqtt_pal_socket_handle;
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
/**
|
||||
* @brief Sends all the bytes in a buffer.
|
||||
* @ingroup pal
|
||||
*
|
||||
* @param[in] fd The file-descriptor (or handle) of the socket.
|
||||
* @param[in] buf A pointer to the first byte in the buffer to send.
|
||||
* @param[in] len The number of bytes to send (starting at \p buf).
|
||||
* @param[in] flags Flags which are passed to the underlying socket.
|
||||
*
|
||||
* @returns The number of bytes sent if successful, an \ref MQTTErrors otherwise.
|
||||
*
|
||||
* Note about the error handling:
|
||||
* - On an error, if some bytes have been processed already,
|
||||
* this function should return the number of bytes successfully
|
||||
* processed. (partial success)
|
||||
* - Otherwise, if the error is an equivalent of EAGAIN, return 0.
|
||||
* - Otherwise, return MQTT_ERROR_SOCKET_ERROR.
|
||||
*/
|
||||
ssize_t mqtt_pal_sendall(mqtt_pal_socket_handle fd, const void *buf, size_t len, int flags);
|
||||
|
||||
/**
|
||||
* @brief Non-blocking receive all the byte available.
|
||||
* @ingroup pal
|
||||
*
|
||||
* @param[in] fd The file-descriptor (or handle) of the socket.
|
||||
* @param[in] buf A pointer to the receive buffer.
|
||||
* @param[in] bufsz The max number of bytes that can be put into \p buf.
|
||||
* @param[in] flags Flags which are passed to the underlying socket.
|
||||
*
|
||||
* @returns The number of bytes received if successful, an \ref MQTTErrors otherwise.
|
||||
*
|
||||
* Note about the error handling:
|
||||
* - On an error, if some bytes have been processed already,
|
||||
* this function should return the number of bytes successfully
|
||||
* processed. (partial success)
|
||||
* - Otherwise, if the error is an equivalent of EAGAIN, return 0.
|
||||
* - Otherwise, return MQTT_ERROR_SOCKET_ERROR.
|
||||
*/
|
||||
ssize_t mqtt_pal_recvall(mqtt_pal_socket_handle fd, void *buf, size_t bufsz, int flags);
|
||||
|
||||
#if defined(__cplusplus)
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
94
client/deps/mqtt/posix_sockets.h
Normal file
94
client/deps/mqtt/posix_sockets.h
Normal file
|
@ -0,0 +1,94 @@
|
|||
#if !defined(__POSIX_SOCKET_TEMPLATE_H__)
|
||||
#define __POSIX_SOCKET_TEMPLATE_H__
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#if !defined(WIN32)
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#else
|
||||
#include <ws2tcpip.h>
|
||||
#endif
|
||||
#if defined(__VMS)
|
||||
#include <ioctl.h>
|
||||
#endif
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
|
||||
/*
|
||||
A template for opening a non-blocking POSIX socket.
|
||||
*/
|
||||
int open_nb_socket(const char *addr, const char *port);
|
||||
|
||||
int open_nb_socket(const char *addr, const char *port) {
|
||||
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
|
||||
hints.ai_family = AF_UNSPEC; /* IPv4 or IPv6 */
|
||||
hints.ai_socktype = SOCK_STREAM; /* Must be TCP */
|
||||
int sockfd = -1;
|
||||
int rv;
|
||||
struct addrinfo *p, *servinfo;
|
||||
|
||||
/* get address information */
|
||||
rv = getaddrinfo(addr, port, &hints, &servinfo);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "Failed to open socket (getaddrinfo): %s\n", gai_strerror(rv));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* open the first possible socket */
|
||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||
sockfd = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
if (sockfd == -1) continue;
|
||||
|
||||
/* connect to server */
|
||||
rv = connect(sockfd, p->ai_addr, p->ai_addrlen);
|
||||
if (rv == -1) {
|
||||
close(sockfd);
|
||||
sockfd = -1;
|
||||
continue;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
/* free servinfo */
|
||||
freeaddrinfo(servinfo);
|
||||
|
||||
/* make non-blocking */
|
||||
#if !defined(WIN32)
|
||||
if (sockfd != -1) {
|
||||
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
|
||||
}
|
||||
#else
|
||||
if (sockfd != INVALID_SOCKET) {
|
||||
int iMode = 1;
|
||||
ioctlsocket(sockfd, FIONBIO, &iMode);
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(__VMS)
|
||||
/*
|
||||
OpenVMS only partially implements fcntl. It works on file descriptors
|
||||
but silently fails on socket descriptors. So we need to fall back on
|
||||
to the older ioctl system to set non-blocking IO
|
||||
*/
|
||||
int on = 1;
|
||||
if (sockfd != -1) {
|
||||
ioctl(sockfd, FIONBIO, &on);
|
||||
}
|
||||
#endif
|
||||
|
||||
/* return the new socket fd */
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void close_nb_socket(int sockfd);
|
||||
|
||||
void close_nb_socket(int sockfd) {
|
||||
if (sockfd != -1) {
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
#endif
|
15
client/deps/mqtt/readme.md
Normal file
15
client/deps/mqtt/readme.md
Normal file
|
@ -0,0 +1,15 @@
|
|||
|
||||
# Information
|
||||
Source: https://github.com/LiamBindle/MQTT-C
|
||||
License: MIT
|
||||
Authors:
|
||||
|
||||
MQTT-C was initially developed as a CMPT 434 (Winter Term, 2018) final project at the University of Saskatchewan by:
|
||||
|
||||
- Liam Bindle
|
||||
- Demilade Adeoye
|
||||
|
||||
|
||||
# about
|
||||
MQTT-C is an MQTT v3.1.1 client written in C. MQTT is a lightweight publisher-subscriber-based messaging protocol that is commonly used in IoT and networking applications where high-latency and low data-rate links are expected. The purpose of MQTT-C is to provide a portable MQTT client, written in C, for embedded systems and PC's alike. MQTT-C does this by providing a transparent Platform Abstraction Layer (PAL) which makes porting to new platforms easy. MQTT-C is completely thread-safe but can also run perfectly fine on single-threaded systems making MQTT-C well-suited for embedded systems and microcontrollers. Finally, MQTT-C is small; there are only two source files totalling less than 2000 lines.
|
||||
|
|
@ -48,6 +48,7 @@
|
|||
#include "commonutil.h" // ARRAYLEN
|
||||
#include "preferences.h"
|
||||
#include "cliparser.h"
|
||||
#include "cmdmqtt.h"
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
|
@ -338,6 +339,7 @@ static command_t CommandTable[] = {
|
|||
{"hw", CmdHW, AlwaysAvailable, "{ Hardware commands... }"},
|
||||
{"lf", CmdLF, AlwaysAvailable, "{ Low frequency commands... }"},
|
||||
{"mem", CmdFlashMem, IfPm3Flash, "{ Flash memory manipulation... }"},
|
||||
{"mqtt", CmdMqtt, AlwaysAvailable, "{ MQTT commmands... }"},
|
||||
{"nfc", CmdNFC, AlwaysAvailable, "{ NFC commands... }"},
|
||||
{"piv", CmdPIV, AlwaysAvailable, "{ PIV commands... }"},
|
||||
{"reveng", CmdRev, AlwaysAvailable, "{ CRC calculations from RevEng software... }"},
|
||||
|
|
385
client/src/cmdmqtt.c
Normal file
385
client/src/cmdmqtt.c
Normal file
|
@ -0,0 +1,385 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// MQTT commands
|
||||
//-----------------------------------------------------------------------------
|
||||
#include "cmdmqtt.h"
|
||||
|
||||
#include "cmdparser.h"
|
||||
#include "cliparser.h"
|
||||
#include "mqtt.h" // MQTT support
|
||||
//#include "mbedtls_sockets.h" // MQTT networkings examples
|
||||
#include "posix_sockets.h" // MQTT networkings examples
|
||||
#include "util_posix.h" // time
|
||||
#include "fileutils.h"
|
||||
|
||||
|
||||
#define MQTT_BUFFER_SIZE ( 1 << 16 )
|
||||
|
||||
static int CmdHelp(const char *Cmd);
|
||||
|
||||
static void mqtt_publish_callback(void **unused, struct mqtt_response_publish *published) {
|
||||
/* note that published->topic_name is NOT null-terminated (here we'll change it to a c-string) */
|
||||
char *topic_name = (char *) calloc(published->topic_name_size + 1, 1);
|
||||
memcpy(topic_name, published->topic_name, published->topic_name_size);
|
||||
|
||||
PrintAndLogEx(INFO, "rec.. %zu", published->application_message_size);
|
||||
|
||||
const char *msg = published->application_message;
|
||||
|
||||
char *ps = strstr(msg, "Created\": \"proxmark3");
|
||||
if (ps) {
|
||||
int res = saveFileTXT("ice_mqtt", ".json", msg, published->application_message_size, spDefault);
|
||||
if (res == PM3_SUCCESS) {
|
||||
PrintAndLogEx(INFO, "Got a json file, save OK");
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, "[" _GREEN_("%s")"] " _YELLOW_("%s"), topic_name, msg);
|
||||
}
|
||||
free(topic_name);
|
||||
}
|
||||
|
||||
static void *mqtt_client_refresher(void *client) {
|
||||
while (1) {
|
||||
mqtt_sync((struct mqtt_client *) client);
|
||||
msleep(100);
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int mqtt_exit(int status, int sockfd, pthread_t *client_daemon) {
|
||||
close_nb_socket(sockfd);
|
||||
|
||||
if (client_daemon != NULL) {
|
||||
pthread_cancel(*client_daemon);
|
||||
pthread_join(*client_daemon, NULL); // Wait for the thread to finish
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
/*
|
||||
static void mqtt_reconnect_client(struct mqtt_client* client, void **reconnect_state_vptr) {
|
||||
|
||||
struct reconnect_state_t *rs = *((struct reconnect_state_t**) reconnect_state_vptr);
|
||||
|
||||
// Close the clients socket if this isn't the initial reconnect call
|
||||
if (client->error != MQTT_ERROR_INITIAL_RECONNECT) {
|
||||
close_nb_socket(client->socketfd);
|
||||
}
|
||||
|
||||
if (client->error != MQTT_ERROR_INITIAL_RECONNECT) {
|
||||
PrintAndLogEx(INFO, "reconnect_client: called while client was in error state `%s`", mqtt_error_str(client->error));
|
||||
}
|
||||
|
||||
int sockfd = open_nb_socket(rs->hostname, rs->port);
|
||||
if (sockfd == -1) {
|
||||
PrintAndLogEx(FAILED, "Failed to open socket");
|
||||
mqtt_exit(PM3_EFAILED, sockfd, NULL);
|
||||
}
|
||||
|
||||
// Reinitialize the client.
|
||||
mqtt_reinit(client, sockfd, rs->sendbuf, rs->sendbufsz, rs->recvbuf, rs->recvbufsz);
|
||||
|
||||
const char* client_id = NULL;
|
||||
|
||||
uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION;
|
||||
|
||||
mqtt_connect(client, client_id, NULL, NULL, 0, NULL, NULL, connect_flags, 400);
|
||||
|
||||
mqtt_subscribe(client, rs->topic, 0);
|
||||
}
|
||||
*/
|
||||
|
||||
static int mqtt_receive(const char *addr, const char *port, const char *topic) {
|
||||
// open the non-blocking TCP socket (connecting to the broker)
|
||||
int sockfd = open_nb_socket(addr, port);
|
||||
if (sockfd == -1) {
|
||||
PrintAndLogEx(FAILED, "Failed to open socket");
|
||||
return mqtt_exit(PM3_EFAILED, sockfd, NULL);
|
||||
}
|
||||
|
||||
uint8_t sendbuf[MQTT_BUFFER_SIZE]; // 64kb sendbuf should be large enough to hold multiple whole mqtt messages
|
||||
uint8_t recvbuf[MQTT_BUFFER_SIZE]; // 64kb recvbuf should be large enough any whole mqtt message expected to be received
|
||||
|
||||
struct mqtt_client client;
|
||||
|
||||
/*
|
||||
struct reconnect_state_t rs;
|
||||
rs.hostname = addr;
|
||||
rs.port = port;
|
||||
rs.topic = topic;
|
||||
rs.sendbuf = sendbuf;
|
||||
rs.sendbufsz = sizeof(sendbuf);
|
||||
rs.recvbuf = recvbuf;
|
||||
rs.recvbufsz = sizeof(recvbuf);
|
||||
mqtt_init_reconnect(&client, mqtt_reconnect_client, &rs, mqtt_publish_callback);
|
||||
*/
|
||||
|
||||
mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), mqtt_publish_callback);
|
||||
|
||||
char cid[20] = "pm3_";
|
||||
sprintf(cid + strlen(cid), "%02x%02x%02x%02x"
|
||||
, rand() % 0xFF
|
||||
, rand() % 0xFF
|
||||
, rand() % 0xFF
|
||||
, rand() % 0xFF
|
||||
);
|
||||
|
||||
// Ensure we have a clean session
|
||||
uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION;
|
||||
// Send connection request to the broker
|
||||
mqtt_connect(&client, cid, NULL, NULL, 0, NULL, NULL, connect_flags, 400);
|
||||
|
||||
// check that we don't have any errors
|
||||
if (client.error != MQTT_OK) {
|
||||
PrintAndLogEx(FAILED, "error: %s", mqtt_error_str(client.error));
|
||||
return mqtt_exit(PM3_ESOFT, sockfd, NULL);
|
||||
}
|
||||
|
||||
// start a thread to refresh the client (handle egress and ingree client traffic)
|
||||
pthread_t client_daemon;
|
||||
if (pthread_create(&client_daemon, NULL, mqtt_client_refresher, &client)) {
|
||||
PrintAndLogEx(FAILED, "Failed to start client daemon");
|
||||
return mqtt_exit(PM3_ESOFT, sockfd, NULL);
|
||||
}
|
||||
|
||||
// subscribe to a topic with a max QoS level of 0
|
||||
mqtt_subscribe(&client, topic, 0);
|
||||
|
||||
PrintAndLogEx(INFO, _CYAN_("%s") " listening at " _CYAN_("%s:%s") " for " _YELLOW_("%s") " messages", cid, addr, port, topic);
|
||||
PrintAndLogEx(INFO, "Press " _GREEN_("<Enter>") " to exit");
|
||||
|
||||
while (kbd_enter_pressed() == false) {
|
||||
msleep(2000);
|
||||
};
|
||||
|
||||
PrintAndLogEx(INFO, _CYAN_("%s") " disconnecting from " _CYAN_("%s"), cid, addr);
|
||||
return mqtt_exit(PM3_SUCCESS, sockfd, &client_daemon);
|
||||
}
|
||||
|
||||
static int mqtt_send(const char *addr, const char *port, const char *topic, char *msg, const char *fn) {
|
||||
|
||||
uint8_t *data;
|
||||
size_t bytes_read = 0;
|
||||
if (fn != NULL) {
|
||||
int res = loadFile_TXTsafe(fn, "", (void **)&data, &bytes_read, true);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
||||
// open the non-blocking TCP socket (connecting to the broker)
|
||||
int sockfd = open_nb_socket(addr, port);
|
||||
|
||||
if (sockfd == -1) {
|
||||
PrintAndLogEx(FAILED, "Failed to open socket");
|
||||
return mqtt_exit(PM3_EFAILED, sockfd, NULL);
|
||||
}
|
||||
|
||||
struct mqtt_client client;
|
||||
uint8_t sendbuf[MQTT_BUFFER_SIZE];
|
||||
uint8_t recvbuf[MQTT_BUFFER_SIZE];
|
||||
mqtt_init(&client, sockfd, sendbuf, sizeof(sendbuf), recvbuf, sizeof(recvbuf), mqtt_publish_callback);
|
||||
|
||||
char cid[20] = "pm3_";
|
||||
sprintf(cid + strlen(cid), "%02x%02x%02x%02x"
|
||||
, rand() % 0xFF
|
||||
, rand() % 0xFF
|
||||
, rand() % 0xFF
|
||||
, rand() % 0xFF
|
||||
);
|
||||
|
||||
// Ensure we have a clean session
|
||||
uint8_t connect_flags = MQTT_CONNECT_CLEAN_SESSION;
|
||||
// Send connection request to the broker
|
||||
mqtt_connect(&client, cid, NULL, NULL, 0, NULL, NULL, connect_flags, 400);
|
||||
|
||||
// check that we don't have any errors
|
||||
if (client.error != MQTT_OK) {
|
||||
PrintAndLogEx(FAILED, "error: %s", mqtt_error_str(client.error));
|
||||
mqtt_exit(PM3_EFAILED, sockfd, NULL);
|
||||
}
|
||||
|
||||
// start a thread to refresh the client (handle egress and ingree client traffic)
|
||||
pthread_t client_daemon;
|
||||
if (pthread_create(&client_daemon, NULL, mqtt_client_refresher, &client)) {
|
||||
PrintAndLogEx(FAILED, "Failed to start client daemon");
|
||||
mqtt_exit(PM3_EFAILED, sockfd, NULL);
|
||||
|
||||
}
|
||||
|
||||
PrintAndLogEx(INFO, _CYAN_("%s") " is ready", cid);
|
||||
|
||||
if (fn != NULL) {
|
||||
PrintAndLogEx(INFO, "Publishing file...");
|
||||
mqtt_publish(&client, topic, data, bytes_read, MQTT_PUBLISH_QOS_0);
|
||||
} else {
|
||||
PrintAndLogEx(INFO, "Publishing message...");
|
||||
mqtt_publish(&client, topic, msg, strlen(msg) + 1, MQTT_PUBLISH_QOS_0);
|
||||
}
|
||||
|
||||
if (client.error != MQTT_OK) {
|
||||
PrintAndLogEx(INFO, "error: %s", mqtt_error_str(client.error));
|
||||
mqtt_exit(PM3_ESOFT, sockfd, &client_daemon);
|
||||
}
|
||||
|
||||
msleep(4000);
|
||||
|
||||
PrintAndLogEx(INFO, _CYAN_("%s") " disconnecting from " _CYAN_("%s"), cid, addr);
|
||||
return mqtt_exit(PM3_SUCCESS, sockfd, &client_daemon);
|
||||
}
|
||||
|
||||
static int CmdMqttSend(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mqtt send",
|
||||
"This command send MQTT messages. You can send JSON file\n"
|
||||
"Default server: proxdump.com:1883 topic: proxdump\n",
|
||||
"mqtt send --msg \"Hello from Pm3\" --> sending msg to default server/port/topic\n"
|
||||
"mqtt send -f myfile.json --> sending file to default server/port/topic\n"
|
||||
"mqtt send --addr test.mosquitto.org -p 1883 --topic pm3 --msg \"custom mqtt server \"\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0(NULL, "addr", "<str>", "MQTT server address"),
|
||||
arg_str0("p", "port", "<str>", "MQTT server port"),
|
||||
arg_str0(NULL, "topic", "<str>", "MQTT topic"),
|
||||
arg_str0(NULL, "msg", "<str>", "Message to send over MQTT"),
|
||||
arg_str0("f", "file", "<fn>", "file to send"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int alen = 0;
|
||||
char addr[256] = {0x00};
|
||||
int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)addr, sizeof(addr), &alen);
|
||||
|
||||
int plen = 0;
|
||||
char port[10 + 1] = {0x00};
|
||||
res = CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)port, sizeof(port), &plen);
|
||||
|
||||
int tlen = 0;
|
||||
char topic[128] = {0x00};
|
||||
res = CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)topic, sizeof(topic), &tlen);
|
||||
|
||||
int mlen = 0;
|
||||
char msg[128] = {0x00};
|
||||
res = CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)msg, sizeof(msg), &mlen);
|
||||
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 5), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// Error message if... an error occured.
|
||||
if (res) {
|
||||
PrintAndLogEx(FAILED, "Error parsing input strings");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (alen == 0) {
|
||||
strcpy(addr, "proxdump.com");
|
||||
}
|
||||
if (plen == 0) {
|
||||
strcpy(port, "1883");
|
||||
}
|
||||
if (tlen == 0) {
|
||||
strcpy(topic, "proxdump");
|
||||
}
|
||||
|
||||
if (fnlen) {
|
||||
return mqtt_send(addr, port, topic, NULL, filename);
|
||||
}
|
||||
|
||||
if (mlen) {
|
||||
return mqtt_send(addr, port, topic, msg, NULL);
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
static int CmdMqttReceive(const char *Cmd) {
|
||||
CLIParserContext *ctx;
|
||||
CLIParserInit(&ctx, "mqtt receive",
|
||||
"This command receives MQTT messages. JSON text will be saved to file if detected\n"
|
||||
"Default server: proxdump.com:1883 topic: proxdump\n",
|
||||
"mqtt receive --> listening to default server/port/topic\n"
|
||||
"mqtt receive --addr test.mosquitto.org -p 1883 --topic pm3\n"
|
||||
);
|
||||
|
||||
void *argtable[] = {
|
||||
arg_param_begin,
|
||||
arg_str0(NULL, "addr", "<str>", "MQTT server address"),
|
||||
arg_str0("p", "port", "<str>", "MQTT server port"),
|
||||
arg_str0(NULL, "topic", "<str>", "MQTT topic"),
|
||||
arg_str0("f", "file", "<fn>", "file to send"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, false);
|
||||
|
||||
int alen = 0;
|
||||
char addr[256] = {0x00};
|
||||
int res = CLIParamStrToBuf(arg_get_str(ctx, 1), (uint8_t *)addr, sizeof(addr), &alen);
|
||||
|
||||
int plen = 0;
|
||||
char port[10 + 1] = {0x00};
|
||||
res = CLIParamStrToBuf(arg_get_str(ctx, 2), (uint8_t *)port, sizeof(port), &plen);
|
||||
|
||||
int tlen = 0;
|
||||
char topic[128] = {0x00};
|
||||
res = CLIParamStrToBuf(arg_get_str(ctx, 3), (uint8_t *)topic, sizeof(topic), &tlen);
|
||||
|
||||
int fnlen = 0;
|
||||
char filename[FILE_PATH_SIZE] = {0};
|
||||
CLIParamStrToBuf(arg_get_str(ctx, 4), (uint8_t *)filename, FILE_PATH_SIZE, &fnlen);
|
||||
|
||||
CLIParserFree(ctx);
|
||||
|
||||
// Error message if... an error occured.
|
||||
if (res) {
|
||||
PrintAndLogEx(FAILED, "Error parsing input strings");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
if (alen == 0) {
|
||||
strcpy(addr, "proxdump.com");
|
||||
}
|
||||
if (plen == 0) {
|
||||
strcpy(port, "1883");
|
||||
}
|
||||
if (tlen == 0) {
|
||||
strcpy(topic, "proxdump");
|
||||
}
|
||||
|
||||
return mqtt_receive(addr, port, topic);
|
||||
}
|
||||
|
||||
static command_t CommandTable[] = {
|
||||
{"help", CmdHelp, AlwaysAvailable, "This help"},
|
||||
{"send", CmdMqttSend, AlwaysAvailable, "Send messages or json file over MQTT"},
|
||||
{"receive", CmdMqttReceive, AlwaysAvailable, "Receive message or json file over MQTT"},
|
||||
{NULL, NULL, NULL, NULL}
|
||||
};
|
||||
|
||||
static int CmdHelp(const char *Cmd) {
|
||||
(void)Cmd; // Cmd is not used so far
|
||||
CmdsHelp(CommandTable);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int CmdMqtt(const char *Cmd) {
|
||||
clearCommandBuffer();
|
||||
return CmdsParse(CommandTable, Cmd);
|
||||
}
|
26
client/src/cmdmqtt.h
Normal file
26
client/src/cmdmqtt.h
Normal file
|
@ -0,0 +1,26 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) Proxmark3 contributors. See AUTHORS.md for details.
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, either version 3 of the License, or
|
||||
// (at your option) any later version.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License for more details.
|
||||
//
|
||||
// See LICENSE.txt for the text of the license.
|
||||
//-----------------------------------------------------------------------------
|
||||
// MQTT commands
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#ifndef CMDMQTT_H__
|
||||
#define CMDMQTT_H__
|
||||
|
||||
#include "common.h"
|
||||
|
||||
int CmdMqtt(const char *Cmd);
|
||||
|
||||
#endif
|
|
@ -278,7 +278,7 @@ int saveFileEx(const char *preferredName, const char *suffix, const void *data,
|
|||
|
||||
// Opening file for writing in binary mode
|
||||
FILE *f = fopen(fileName, "wb");
|
||||
if (!f) {
|
||||
if (f == NULL) {
|
||||
PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", fileName);
|
||||
free(fileName);
|
||||
return PM3_EFILE;
|
||||
|
@ -291,6 +291,33 @@ int saveFileEx(const char *preferredName, const char *suffix, const void *data,
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int saveFileTXT(const char *preferredName, const char *suffix, const void *data, size_t datalen, savePaths_t e_save_path) {
|
||||
if (data == NULL || datalen == 0) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
char *fileName = newfilenamemcopyEx(preferredName, suffix, e_save_path);
|
||||
if (fileName == NULL) {
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
// We should have a valid filename now, e.g. dumpdata-3.txt
|
||||
|
||||
// Opening file for writing in text mode
|
||||
FILE *f = fopen(fileName, "w");
|
||||
if (f == NULL) {
|
||||
PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", fileName);
|
||||
free(fileName);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
fwrite(data, 1, datalen, f);
|
||||
fflush(f);
|
||||
fclose(f);
|
||||
PrintAndLogEx(SUCCESS, "Saved " _YELLOW_("%zu") " bytes to text file `" _YELLOW_("%s") "`", datalen, fileName);
|
||||
free(fileName);
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int prepareJSON(json_t *root, JSONFileType ftype, uint8_t *data, size_t datalen, bool verbose, void (*callback)(json_t *)) {
|
||||
if (ftype != jsfCustom) {
|
||||
if (data == NULL || datalen == 0) {
|
||||
|
@ -794,8 +821,9 @@ int saveFileJSONroot(const char *preferredName, void *root, size_t flags, bool v
|
|||
}
|
||||
|
||||
int saveFileJSONrootEx(const char *preferredName, const void *root, size_t flags, bool verbose, bool overwrite, savePaths_t e_save_path) {
|
||||
if (root == NULL)
|
||||
if (root == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
char *filename = NULL;
|
||||
if (overwrite)
|
||||
|
@ -975,7 +1003,7 @@ int loadFile_safeEx(const char *preferredName, const char *suffix, void **pdata,
|
|||
}
|
||||
|
||||
FILE *f = fopen(path, "rb");
|
||||
if (!f) {
|
||||
if (f == NULL) {
|
||||
PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path);
|
||||
free(path);
|
||||
return PM3_EFILE;
|
||||
|
@ -1018,6 +1046,58 @@ int loadFile_safeEx(const char *preferredName, const char *suffix, void **pdata,
|
|||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int loadFile_TXTsafe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen, bool verbose) {
|
||||
|
||||
char *path;
|
||||
int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, suffix, false);
|
||||
if (res != PM3_SUCCESS) {
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
if (f == NULL) {
|
||||
PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path);
|
||||
free(path);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
free(path);
|
||||
|
||||
// get filesize in order to malloc memory
|
||||
fseek(f, 0, SEEK_END);
|
||||
long fsize = ftell(f);
|
||||
fseek(f, 0, SEEK_SET);
|
||||
|
||||
if (fsize <= 0) {
|
||||
PrintAndLogEx(FAILED, "error, when getting filesize");
|
||||
fclose(f);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
*pdata = calloc(fsize, sizeof(uint8_t));
|
||||
if (*pdata == NULL) {
|
||||
PrintAndLogEx(WARNING, "Failed to allocate memory");
|
||||
fclose(f);
|
||||
return PM3_EMALLOC;
|
||||
}
|
||||
|
||||
size_t bytes_read = fread(*pdata, 1, fsize, f);
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (bytes_read != fsize) {
|
||||
PrintAndLogEx(FAILED, "error, bytes read mismatch file size");
|
||||
free(*pdata);
|
||||
return PM3_EFILE;
|
||||
}
|
||||
|
||||
*datalen = bytes_read;
|
||||
|
||||
if (verbose) {
|
||||
PrintAndLogEx(SUCCESS, "Loaded " _YELLOW_("%zu") " bytes from text file `" _YELLOW_("%s") "`", bytes_read, preferredName);
|
||||
}
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
||||
int loadFileEML_safe(const char *preferredName, void **pdata, size_t *datalen) {
|
||||
char *path;
|
||||
int res = searchFile(&path, RESOURCES_SUBDIR, preferredName, "", false);
|
||||
|
@ -1121,7 +1201,7 @@ int loadFileNFC_safe(const char *preferredName, void *data, size_t maxdatalen, s
|
|||
}
|
||||
|
||||
FILE *f = fopen(path, "r");
|
||||
if (!f) {
|
||||
if (f == NULL) {
|
||||
PrintAndLogEx(WARNING, "file not found or locked `" _YELLOW_("%s") "`", path);
|
||||
free(path);
|
||||
return PM3_EFILE;
|
||||
|
@ -1446,7 +1526,9 @@ int loadFileJSON(const char *preferredName, void *data, size_t maxdatalen, size_
|
|||
}
|
||||
int loadFileJSONex(const char *preferredName, void *data, size_t maxdatalen, size_t *datalen, bool verbose, void (*callback)(json_t *)) {
|
||||
|
||||
if (data == NULL) return PM3_EINVARG;
|
||||
if (data == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
*datalen = 0;
|
||||
int retval = PM3_SUCCESS;
|
||||
|
@ -2629,6 +2711,10 @@ int detect_nfc_dump_format(const char *preferredName, nfc_df_e *dump_type, bool
|
|||
*dump_type = NFC_DF_14_4A;
|
||||
break;
|
||||
}
|
||||
if (str_startswith(line, "device type: iso15693")) {
|
||||
*dump_type = NFC_DF_15;
|
||||
break;
|
||||
}
|
||||
if (str_startswith(line, "filetype: flipper picopass device")) {
|
||||
*dump_type = NFC_DF_PICOPASS;
|
||||
break;
|
||||
|
@ -2661,6 +2747,8 @@ int detect_nfc_dump_format(const char *preferredName, nfc_df_e *dump_type, bool
|
|||
case NFC_DF_PICOPASS:
|
||||
PrintAndLogEx(INFO, "Detected PICOPASS based dump format");
|
||||
break;
|
||||
case NFC_DF_15:
|
||||
PrintAndLogEx(INFO, "Detected ISO15693 based dump format");
|
||||
case NFC_DF_UNKNOWN:
|
||||
PrintAndLogEx(WARNING, "Failed to detected dump format");
|
||||
break;
|
||||
|
@ -3210,7 +3298,7 @@ int pm3_load_dump(const char *fn, void **pdump, size_t *dumplen, size_t maxdumpl
|
|||
break;
|
||||
}
|
||||
|
||||
if (dumptype == NFC_DF_MFC || dumptype == NFC_DF_MFU || dumptype == NFC_DF_PICOPASS) {
|
||||
if (dumptype == NFC_DF_MFC || dumptype == NFC_DF_MFU || dumptype == NFC_DF_PICOPASS || dumptype == NFC_DF_15) {
|
||||
|
||||
*pdump = calloc(maxdumplen, sizeof(uint8_t));
|
||||
if (*pdump == NULL) {
|
||||
|
@ -3247,6 +3335,7 @@ int pm3_save_dump(const char *fn, uint8_t *d, size_t n, JSONFileType jsft) {
|
|||
PrintAndLogEx(INFO, "No data to save, skipping...");
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
saveFile(fn, ".bin", d, n);
|
||||
saveFileJSON(fn, jsft, d, n, NULL);
|
||||
return PM3_SUCCESS;
|
||||
|
|
|
@ -100,9 +100,16 @@ typedef enum {
|
|||
NFC_DF_14_3A,
|
||||
NFC_DF_14_3B,
|
||||
NFC_DF_14_4A,
|
||||
NFC_DF_15,
|
||||
NFC_DF_PICOPASS,
|
||||
} nfc_df_e;
|
||||
|
||||
typedef enum {
|
||||
ISO15_DF_UNKNOWN,
|
||||
ISO15_DF_V4_BIN,
|
||||
ISO15_DF_V5_BIN
|
||||
} iso15_df_e;
|
||||
|
||||
int fileExists(const char *filename);
|
||||
|
||||
// set a path in the path list g_session.defaultPaths
|
||||
|
@ -116,7 +123,7 @@ void truncate_filename(char *fn, uint16_t maxlen);
|
|||
/**
|
||||
* @brief Utility function to save data to a binary file. This method takes a preferred name, but if that
|
||||
* file already exists, it tries with another name until it finds something suitable.
|
||||
* E.g. dumpdata-15.txt
|
||||
* E.g. dumpdata-15.bin
|
||||
*
|
||||
* @param preferredName
|
||||
* @param suffix the file suffix. Including the ".".
|
||||
|
@ -127,6 +134,19 @@ void truncate_filename(char *fn, uint16_t maxlen);
|
|||
int saveFile(const char *preferredName, const char *suffix, const void *data, size_t datalen);
|
||||
int saveFileEx(const char *preferredName, const char *suffix, const void *data, size_t datalen, savePaths_t e_save_path);
|
||||
|
||||
/**
|
||||
* @brief Utility function to save data to a text file. This method takes a preferred name, but if that
|
||||
* file already exists, it tries with another name until it finds something suitable.
|
||||
* E.g. dumpdata-15.txt
|
||||
*
|
||||
* @param preferredName
|
||||
* @param suffix the file suffix. Including the ".".
|
||||
* @param data The binary data to write to the file
|
||||
* @param datalen the length of the data
|
||||
* @return 0 for ok, 1 for failz
|
||||
*/
|
||||
int saveFileTXT(const char *preferredName, const char *suffix, const void *data, size_t datalen, savePaths_t e_save_path);
|
||||
|
||||
/** STUB
|
||||
* @brief Utility function to save JSON data to a file. This method takes a preferred name, but if that
|
||||
* file already exists, it tries with another name until it finds something suitable.
|
||||
|
@ -190,6 +210,19 @@ int createMfcKeyDump(const char *preferredName, uint8_t sectorsCnt, const sector
|
|||
*/
|
||||
int loadFile_safe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen);
|
||||
int loadFile_safeEx(const char *preferredName, const char *suffix, void **pdata, size_t *datalen, bool verbose);
|
||||
|
||||
/**
|
||||
* @brief Utility function to load a text file. This method takes a preferred name.
|
||||
* E.g. dumpdata-15.json, tries to search for it, and allocated memory.
|
||||
*
|
||||
* @param preferredName
|
||||
* @param suffix the file suffix. Including the ".".
|
||||
* @param data The data array to store the loaded bytes from file
|
||||
* @param datalen the number of bytes loaded from file
|
||||
* @return PM3_SUCCESS for ok, PM3_E* for failz
|
||||
*/
|
||||
int loadFile_TXTsafe(const char *preferredName, const char *suffix, void **pdata, size_t *datalen, bool verbose);
|
||||
|
||||
/**
|
||||
* @brief Utility function to load data from a textfile (EML). This method takes a preferred name.
|
||||
* E.g. dumpdata-15.txt
|
||||
|
|
|
@ -832,6 +832,9 @@ const static vocabulary_t vocabulary[] = {
|
|||
{ 0, "mem spiffs upload" },
|
||||
{ 0, "mem spiffs view" },
|
||||
{ 0, "mem spiffs wipe" },
|
||||
{ 1, "mqtt help" },
|
||||
{ 1, "mqtt send" },
|
||||
{ 1, "mqtt receive" },
|
||||
{ 1, "nfc help" },
|
||||
{ 1, "nfc decode" },
|
||||
{ 0, "nfc type1 read" },
|
||||
|
|
|
@ -1136,7 +1136,7 @@
|
|||
},
|
||||
"help": {
|
||||
"command": "help",
|
||||
"description": "help Use `<command> help` for details of a command prefs { Edit client/device preferences... } -------- ----------------------- Technology ----------------------- analyse { Analyse utils... } data { Plot window / data buffer manipulation... } emv { EMV ISO-14443 / ISO-7816... } hf { High frequency commands... } hw { Hardware commands... } lf { Low frequency commands... } nfc { NFC commands... } piv { PIV commands... } reveng { CRC calculations from RevEng software... } smart { Smart card ISO-7816 commands... } script { Scripting commands... } trace { Trace manipulation... } wiegand { Wiegand format manipulation... } -------- ----------------------- General ----------------------- clear Clear screen hints Turn hints on / off msleep Add a pause in milliseconds rem Add a text line in log file quit exit Exit program --------------------------------------------------------------------------------------- auto available offline: no Run LF SEARCH / HF SEARCH / DATA PLOT / DATA SAVE",
|
||||
"description": "help Use `<command> help` for details of a command prefs { Edit client/device preferences... } -------- ----------------------- Technology ----------------------- analyse { Analyse utils... } data { Plot window / data buffer manipulation... } emv { EMV ISO-14443 / ISO-7816... } hf { High frequency commands... } hw { Hardware commands... } lf { Low frequency commands... } mqtt { MQTT commmands... } nfc { NFC commands... } piv { PIV commands... } reveng { CRC calculations from RevEng software... } smart { Smart card ISO-7816 commands... } script { Scripting commands... } trace { Trace manipulation... } wiegand { Wiegand format manipulation... } -------- ----------------------- General ----------------------- clear Clear screen hints Turn hints on / off msleep Add a pause in milliseconds rem Add a text line in log file quit exit Exit program --------------------------------------------------------------------------------------- auto available offline: no Run LF SEARCH / HF SEARCH / DATA PLOT / DATA SAVE",
|
||||
"notes": [
|
||||
"auto"
|
||||
],
|
||||
|
@ -12331,6 +12331,42 @@
|
|||
],
|
||||
"usage": "mem wipe [-h] [-p <dec>]"
|
||||
},
|
||||
"mqtt help": {
|
||||
"command": "mqtt help",
|
||||
"description": "help This help send Send messages or json file over MQTT receive Receive message or json file over MQTT --------------------------------------------------------------------------------------- mqtt send available offline: yes This command send MQTT messages. You can send JSON file Default server: proxdump.com:1883 topic: proxdump",
|
||||
"notes": [
|
||||
"mqtt send --msg \"Hello from Pm3\" -> sending msg to default server/port/topic",
|
||||
"mqtt send -f myfile.json -> sending file to default server/port/topic",
|
||||
"mqtt send --addr test.mosquitto.org -p 1883 --topic pm3 --msg \"custom mqtt server \""
|
||||
],
|
||||
"offline": true,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"--addr <str> MQTT server address",
|
||||
"-p, --port <str> MQTT server port",
|
||||
"--topic <str> MQTT topic",
|
||||
"--msg <str> Message to send over MQTT",
|
||||
"-f, --file <fn> file to send"
|
||||
],
|
||||
"usage": "mqtt send [-h] [--addr <str>] [-p <str>] [--topic <str>] [--msg <str>] [-f <fn>]"
|
||||
},
|
||||
"mqtt receive": {
|
||||
"command": "mqtt receive",
|
||||
"description": "This command receives MQTT messages. JSON text will be saved to file if detected Default server: proxdump.com:1883 topic: proxdump",
|
||||
"notes": [
|
||||
"mqtt receive -> listening to default server/port/topic",
|
||||
"mqtt receive --addr test.mosquitto.org -p 1883 --topic pm3"
|
||||
],
|
||||
"offline": true,
|
||||
"options": [
|
||||
"-h, --help This help",
|
||||
"--addr <str> MQTT server address",
|
||||
"-p, --port <str> MQTT server port",
|
||||
"--topic <str> MQTT topic",
|
||||
"-f, --file <fn> file to send"
|
||||
],
|
||||
"usage": "mqtt receive [-h] [--addr <str>] [-p <str>] [--topic <str>] [-f <fn>]"
|
||||
},
|
||||
"msleep": {
|
||||
"command": "msleep",
|
||||
"description": "Sleep for given amount of milliseconds",
|
||||
|
@ -13375,8 +13411,8 @@
|
|||
}
|
||||
},
|
||||
"metadata": {
|
||||
"commands_extracted": 768,
|
||||
"commands_extracted": 770,
|
||||
"extracted_by": "PM3Help2JSON v1.00",
|
||||
"extracted_on": "2025-07-06T18:10:18"
|
||||
"extracted_on": "2025-07-08T19:08:23"
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1414,6 +1414,17 @@ Check column "offline" for their availability.
|
|||
|`mem spiffs wipe `|N |`Wipe all files from SPIFFS file system * dangerous *`
|
||||
|
||||
|
||||
### mqtt
|
||||
|
||||
{ MQTT commmands... }
|
||||
|
||||
|command |offline |description
|
||||
|------- |------- |-----------
|
||||
|`mqtt help `|Y |`This help`
|
||||
|`mqtt send `|Y |`Send messages or json file over MQTT`
|
||||
|`mqtt receive `|Y |`Receive message or json file over MQTT`
|
||||
|
||||
|
||||
### nfc
|
||||
|
||||
{ NFC commands... }
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue