mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2025-08-21 05:43:48 -07:00
Merge branch 'RfidResearchGroup:master' into master
This commit is contained in:
commit
ac6916777f
38 changed files with 4875 additions and 57 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()
|
|
@ -440,33 +440,32 @@ int json_dumpfd(const json_t *json, int output, size_t flags) {
|
|||
}
|
||||
|
||||
int json_dump_file(const json_t *json, const char *path, size_t flags) {
|
||||
int result;
|
||||
|
||||
FILE *output = fopen(path, "w");
|
||||
if (!output)
|
||||
FILE *f = fopen(path, "w");
|
||||
if (f == NULL) {
|
||||
return -1;
|
||||
|
||||
result = json_dumpf(json, output, flags);
|
||||
|
||||
if (fclose(output) != 0)
|
||||
return -1;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags) {
|
||||
int res;
|
||||
hashtable_t parents_set;
|
||||
|
||||
if (!(flags & JSON_ENCODE_ANY)) {
|
||||
if (!json_is_array(json) && !json_is_object(json))
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (hashtable_init(&parents_set))
|
||||
int res = json_dumpf(json, f, flags);
|
||||
|
||||
if (fclose(f) != 0)
|
||||
return -1;
|
||||
res = do_dump(json, flags, 0, &parents_set, callback, data);
|
||||
hashtable_close(&parents_set);
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
int json_dump_callback(const json_t *json, json_dump_callback_t callback, void *data, size_t flags) {
|
||||
if (!(flags & JSON_ENCODE_ANY)) {
|
||||
if (!json_is_array(json) && !json_is_object(json)) {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
hashtable_t parents_set;
|
||||
if (hashtable_init(&parents_set)) {
|
||||
return -1;
|
||||
}
|
||||
int res = do_dump(json, flags, 0, &parents_set, callback, data);
|
||||
hashtable_close(&parents_set);
|
||||
return res;
|
||||
}
|
||||
|
|
|
@ -44,7 +44,7 @@ add_library(pm3rrg_rdv4_mbedtls STATIC
|
|||
../../common/mbedtls/x509.c
|
||||
../../common/mbedtls/x509_crl.c
|
||||
../../common/mbedtls/x509_crt.c
|
||||
../../common/mbedtls/net_sockets.c
|
||||
../../common/mbedtls/net_sockets.c
|
||||
)
|
||||
|
||||
target_include_directories(pm3rrg_rdv4_mbedtls PRIVATE ../../common)
|
||||
|
|
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
|
73
client/deps/mqtt/posix_sockets.h
Normal file
73
client/deps/mqtt/posix_sockets.h
Normal file
|
@ -0,0 +1,73 @@
|
|||
#if !defined(__POSIX_SOCKET_TEMPLATE_H__)
|
||||
#define __POSIX_SOCKET_TEMPLATE_H__
|
||||
|
||||
#ifndef _WIN32
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/tcp.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netdb.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
// A template for opening a non-blocking POSIX socket.
|
||||
|
||||
void close_nb_socket(int sockfd);
|
||||
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 */
|
||||
|
||||
struct addrinfo *p, *servinfo;
|
||||
|
||||
/* get address information */
|
||||
int 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 */
|
||||
int sockfd = -1;
|
||||
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 (sockfd != -1) {
|
||||
fcntl(sockfd, F_SETFL, fcntl(sockfd, F_GETFL) | O_NONBLOCK);
|
||||
}
|
||||
|
||||
return sockfd;
|
||||
}
|
||||
|
||||
void close_nb_socket(int sockfd) {
|
||||
if (sockfd != -1) {
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#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.
|
||||
|
91
client/deps/mqtt/win32_sockets.h
Normal file
91
client/deps/mqtt/win32_sockets.h
Normal file
|
@ -0,0 +1,91 @@
|
|||
#if !defined(__WIN32_SOCKET_TEMPLATE_H__)
|
||||
|
||||
#include <stdio.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define WIN32_LEAN_AND_MEAN
|
||||
#include <windows.h>
|
||||
#include <winsock2.h>
|
||||
#include <ws2tcpip.h>
|
||||
|
||||
void close_nb_socket(int sockfd);
|
||||
int open_nb_socket(const char *addr, const char *port);
|
||||
|
||||
int open_nb_socket(const char *addr, const char *port) {
|
||||
|
||||
WSADATA wsaData;
|
||||
int res = WSAStartup(MAKEWORD(2, 2), &wsaData);
|
||||
if (res != 0) {
|
||||
fprintf(stderr, "error: WSAStartup failed with error: %i", res);
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct addrinfo hints;
|
||||
memset(&hints, 0, sizeof(hints));
|
||||
hints.ai_family = AF_UNSPEC; // IPv4 or IPv6
|
||||
hints.ai_socktype = SOCK_STREAM; // Must be TCP
|
||||
hints.ai_protocol = IPPROTO_TCP; //
|
||||
|
||||
struct addrinfo *p, *servinfo;
|
||||
// get address information
|
||||
int rv = getaddrinfo(addr, port, &hints, &servinfo);
|
||||
if (rv != 0) {
|
||||
fprintf(stderr, "error: getaddrinfo: %s", gai_strerror(rv));
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* open the first possible socket */
|
||||
SOCKET hSocket = INVALID_SOCKET;
|
||||
for (p = servinfo; p != NULL; p = p->ai_next) {
|
||||
hSocket = socket(p->ai_family, p->ai_socktype, p->ai_protocol);
|
||||
|
||||
if (hSocket == INVALID_SOCKET) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// connect to server
|
||||
if (connect(hSocket, p->ai_addr, (int)p->ai_addrlen) != INVALID_SOCKET) {
|
||||
break;
|
||||
}
|
||||
|
||||
closesocket(hSocket);
|
||||
hSocket = INVALID_SOCKET;
|
||||
|
||||
}
|
||||
|
||||
// free servinfo
|
||||
freeaddrinfo(servinfo);
|
||||
|
||||
if (p == NULL) { // No address succeeded
|
||||
fprintf(stderr, "error: Could not connect");
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
// make non-blocking
|
||||
if (hSocket != INVALID_SOCKET) {
|
||||
uint32_t mode = 1; // FIONBIO returns size on 32b
|
||||
ioctlsocket(hSocket, FIONBIO, (u_long *)&mode);
|
||||
}
|
||||
|
||||
int flag = 1;
|
||||
res = setsockopt(hSocket, IPPROTO_TCP, TCP_NODELAY, (char *)&flag, sizeof(flag));
|
||||
if (res != 0) {
|
||||
closesocket(hSocket);
|
||||
WSACleanup();
|
||||
return -1;
|
||||
}
|
||||
|
||||
return hSocket;
|
||||
}
|
||||
|
||||
void close_nb_socket(int sockfd) {
|
||||
if (sockfd != -1) {
|
||||
close(sockfd);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -1135,7 +1135,7 @@ int read_iclass_csn(bool loop, bool verbose, bool shallow_mod) {
|
|||
res = PM3_EMALLOC;
|
||||
}
|
||||
}
|
||||
} while (loop && kbd_enter_pressed() == false);
|
||||
} while (loop && (kbd_enter_pressed() == false));
|
||||
|
||||
DropField();
|
||||
return res;
|
||||
|
|
|
@ -781,17 +781,20 @@ int legic_print_type(uint32_t tagtype, uint8_t spaces) {
|
|||
}
|
||||
int legic_get_type(legic_card_select_t *card) {
|
||||
|
||||
if (card == NULL)
|
||||
if (card == NULL) {
|
||||
return PM3_EINVARG;
|
||||
}
|
||||
|
||||
clearCommandBuffer();
|
||||
SendCommandNG(CMD_HF_LEGIC_INFO, NULL, 0);
|
||||
PacketResponseNG resp;
|
||||
if (WaitForResponseTimeout(CMD_HF_LEGIC_INFO, &resp, 1500) == false)
|
||||
if (WaitForResponseTimeout(CMD_HF_LEGIC_INFO, &resp, 1500) == false) {
|
||||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
if (resp.status != PM3_SUCCESS)
|
||||
if (resp.status != PM3_SUCCESS) {
|
||||
return PM3_ESOFT;
|
||||
}
|
||||
|
||||
memcpy(card, resp.data.asBytes, sizeof(legic_card_select_t));
|
||||
return PM3_SUCCESS;
|
||||
|
@ -1527,7 +1530,7 @@ int readLegicUid(bool loop, bool verbose) {
|
|||
PrintAndLogEx(SUCCESS, " MSN: " _GREEN_("%s"), sprint_hex(card.uid + 1, sizeof(card.uid) - 1));
|
||||
legic_print_type(card.cardsize, 0);
|
||||
|
||||
} while (loop && kbd_enter_pressed() == false);
|
||||
} while (loop && (kbd_enter_pressed() == false));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -462,7 +462,7 @@ int CmdLFCommandRead(const char *Cmd) {
|
|||
return PM3_ETIMEOUT;
|
||||
}
|
||||
|
||||
} while (cm && kbd_enter_pressed() == false);
|
||||
} while (cm && (kbd_enter_pressed() == false));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -859,7 +859,7 @@ int CmdLFRead(const char *Cmd) {
|
|||
int ret = PM3_SUCCESS;
|
||||
do {
|
||||
ret = lf_read_internal(realtime, verbose, samples);
|
||||
} while (cm && kbd_enter_pressed() == false);
|
||||
} while (cm && (kbd_enter_pressed() == false));
|
||||
|
||||
if (ret == PM3_SUCCESS) {
|
||||
PrintAndLogEx(SUCCESS, "Got " _YELLOW_("%zu") " samples", g_GraphTraceLen);
|
||||
|
@ -985,7 +985,7 @@ int CmdLFSniff(const char *Cmd) {
|
|||
int ret = PM3_SUCCESS;
|
||||
do {
|
||||
ret = lf_sniff(realtime, verbose, samples);
|
||||
} while (cm && kbd_enter_pressed() == false);
|
||||
} while (cm && (kbd_enter_pressed() == false));
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
@ -349,7 +349,7 @@ static int CmdAWIDReader(const char *Cmd) {
|
|||
do {
|
||||
lf_read(false, 12000);
|
||||
demodAWID(!cm);
|
||||
} while (cm && !kbd_enter_pressed());
|
||||
} while (cm && (kbd_enter_pressed() == false));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -445,7 +445,7 @@ static int CmdEM410xReader(const char *Cmd) {
|
|||
if (break_first && gs_em410xid != 0) {
|
||||
break;
|
||||
}
|
||||
} while (cm && !kbd_enter_pressed());
|
||||
} while (cm && (kbd_enter_pressed() == false));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -243,7 +243,7 @@ static int CmdGuardReader(const char *Cmd) {
|
|||
do {
|
||||
lf_read(false, 10000);
|
||||
demodGuard(!cm);
|
||||
} while (cm && !kbd_enter_pressed());
|
||||
} while (cm && (kbd_enter_pressed() == false));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -215,7 +215,7 @@ static int CmdHIDReader(const char *Cmd) {
|
|||
do {
|
||||
lf_read(false, 16000);
|
||||
demodHID(!cm);
|
||||
} while (cm && !kbd_enter_pressed());
|
||||
} while (cm && (kbd_enter_pressed() == false));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -912,7 +912,7 @@ static int CmdLFHitagReader(const char *Cmd) {
|
|||
if (ht2_get_uid(&uid)) {
|
||||
PrintAndLogEx(SUCCESS, "UID.... " _GREEN_("%08X"), uid);
|
||||
}
|
||||
} while (cm && kbd_enter_pressed() == false);
|
||||
} while (cm && (kbd_enter_pressed() == false));
|
||||
|
||||
return PM3_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -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... }"},
|
||||
|
|
390
client/src/cmdmqtt.c
Normal file
390
client/src/cmdmqtt.c
Normal file
|
@ -0,0 +1,390 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// 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
|
||||
|
||||
#ifndef _WIN32
|
||||
#include "posix_sockets.h" // MQTT networkings examples
|
||||
#else
|
||||
#include "win32_sockets.h" // MQTT networkings examples
|
||||
#endif
|
||||
#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);
|
||||
|
||||
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 ( %s )", _GREEN_("ok"));
|
||||
}
|
||||
} else {
|
||||
PrintAndLogEx(SUCCESS, _GREEN_("%s") " - ( %zu ) " _YELLOW_("%s"), topic_name, published->application_message_size, 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);
|
||||
#ifndef _WIN32
|
||||
pthread_join(*client_daemon, NULL); // Wait for the thread to finish
|
||||
#endif
|
||||
}
|
||||
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, const char *fn) {
|
||||
// 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 name to use for received files"),
|
||||
arg_param_end
|
||||
};
|
||||
CLIExecWithReturn(ctx, Cmd, argtable, true);
|
||||
|
||||
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, filename);
|
||||
}
|
||||
|
||||
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
|
||||
|
|
|
@ -575,10 +575,11 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
|
|||
size_t sentdatalen = 0;
|
||||
while (cdatalen >= sentdatalen) {
|
||||
|
||||
if ((cdatalen - sentdatalen) > DESFIRE_TX_FRAME_MAX_LEN)
|
||||
if ((cdatalen - sentdatalen) > DESFIRE_TX_FRAME_MAX_LEN) {
|
||||
len = DESFIRE_TX_FRAME_MAX_LEN;
|
||||
else
|
||||
} else {
|
||||
len = cdatalen - sentdatalen;
|
||||
}
|
||||
|
||||
size_t sendindx = sentdatalen;
|
||||
size_t sendlen = len;
|
||||
|
@ -657,8 +658,9 @@ static int DesfireExchangeNative(bool activate_field, DesfireContext_t *ctx, uin
|
|||
}
|
||||
pos += buflen;
|
||||
|
||||
if (rcode != MFDES_ADDITIONAL_FRAME)
|
||||
if (rcode != MFDES_ADDITIONAL_FRAME) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (resplen) {
|
||||
|
@ -969,12 +971,14 @@ int DesfireSelectAIDHexNoFieldOn(DesfireContext_t *ctx, uint32_t aid) {
|
|||
ctx->secureChannel = DACNone;
|
||||
int res = DesfireExchangeEx(false, ctx, MFDES_SELECT_APPLICATION, data, 3, &respcode, resp, &resplen, true, 0);
|
||||
if (res == PM3_SUCCESS) {
|
||||
if (resplen != 0)
|
||||
if (resplen != 0) {
|
||||
return PM3_ECARDEXCHANGE;
|
||||
}
|
||||
|
||||
// select operation fail
|
||||
if (respcode != MFDES_S_OPERATION_OK)
|
||||
if (respcode != MFDES_S_OPERATION_OK) {
|
||||
return PM3_EAPDU_FAIL;
|
||||
}
|
||||
|
||||
DesfireClearSession(ctx);
|
||||
ctx->appSelected = (aid != 0x000000);
|
||||
|
|
|
@ -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" },
|
||||
|
|
|
@ -17,14 +17,12 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "proxmark3.h"
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <limits.h>
|
||||
#include <unistd.h>
|
||||
#include <ctype.h>
|
||||
#include <libgen.h> // basename
|
||||
#include <time.h>
|
||||
|
||||
#include "pm3line.h"
|
||||
#include "usart_defs.h"
|
||||
#include "util_posix.h"
|
||||
|
@ -43,7 +41,6 @@
|
|||
#include <locale.h>
|
||||
#endif
|
||||
|
||||
|
||||
static int mainret = PM3_SUCCESS;
|
||||
|
||||
#ifndef LIBPM3
|
||||
|
@ -209,7 +206,6 @@ static void showBanner(void) {
|
|||
|
||||
PrintAndLogEx(NORMAL, " [ " _YELLOW_("%s!")" :coffee: ]", get_quote());
|
||||
// PrintAndLogEx(NORMAL, " [ https://patreon.com/iceman1001/ ]");
|
||||
// PrintAndLogEx(NORMAL, "");
|
||||
// PrintAndLogEx(NORMAL, " Monero");
|
||||
// PrintAndLogEx(NORMAL, " 43mNJLpgBVaTvyZmX9ajcohpvVkaRy1kbZPm8tqAb7itZgfuYecgkRF36rXrKFUkwEGeZedPsASRxgv4HPBHvJwyJdyvQuP");
|
||||
PrintAndLogEx(NORMAL, "");
|
||||
|
|
|
@ -75,6 +75,7 @@ typedef struct {
|
|||
|
||||
|
||||
int calculate_hours_between_dates(const Date_t s, Date_t *e);
|
||||
void add_minutes(Date_t *d, int minutes_to_add);
|
||||
void add_hours(Date_t *d, int hours_to_add);
|
||||
void add_days(Date_t *d, int days_to_add);
|
||||
uint8_t days_in_month(int year, int month);
|
||||
|
|
|
@ -29,7 +29,7 @@ typedef struct {
|
|||
enum {
|
||||
TAG_STATE_RESET = 0x01, // Just powered up, awaiting GetSnr
|
||||
TAG_STATE_ACTIVATING = 0x02, // In activation phase (password mode), sent UID, awaiting reader password
|
||||
TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands
|
||||
// TAG_STATE_ACTIVATED = 0x03, // Activation complete, awaiting read/write commands
|
||||
TAG_STATE_WRITING = 0x04, // In write command, awaiting sector contents to be written
|
||||
} state;
|
||||
uint16_t active_sector;
|
||||
|
|
|
@ -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... }
|
||||
|
|
|
@ -24,7 +24,8 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// iCLASS / PICOPASS
|
||||
//-----------------------------------------------------------------------------
|
||||
#define PICOPASS_BLOCK_SIZE 8
|
||||
#define PICOPASS_BLOCK_SIZE ( 8 )
|
||||
#define PICOPASS_MAX_BYTES ( 4096 ) // # 32k bits = 4096 bytes
|
||||
|
||||
// iCLASS reader flags
|
||||
#define FLAG_ICLASS_READER_INIT 0x01
|
||||
|
@ -197,5 +198,12 @@ typedef struct {
|
|||
} header;
|
||||
} PACKED iclass_card_select_resp_t;
|
||||
|
||||
typedef struct {
|
||||
union {
|
||||
picopass_hdr_t hdr;
|
||||
picopass_ns_hdr_t ns_hdr;
|
||||
} header;
|
||||
uint8_t data[PICOPASS_MAX_BYTES];
|
||||
} PACKED iclass_tag_t;
|
||||
|
||||
#endif // _ICLASS_H_
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue