mirror of
https://github.com/RfidResearchGroup/proxmark3.git
synced 2026-10-22 17:32:33 +00: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:
1 parent
732cc1b82e
commit
c7cf62fcf1
22 files changed
+4742
-10
No files matched your search
@@ -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... }"},
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
@@ -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
|
||||
+95
-6
@@ -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;
|
||||
|
||||
+34
-1
@@ -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" },
|
||||
|
||||
Reference in new issue
Block a user