mirror of
https://github.com/DJ2LS/FreeDATA
synced 2024-05-14 08:04:33 +00:00
Merge pull request #463 from DJ2LS/ls-hmac-signing
token based hmac signing Merging this, but needs some updates later after VueJS PR has been merged
This commit is contained in:
commit
89abba8150
|
@ -80,6 +80,8 @@ PouchDB.plugin(require("pouchdb-find"));
|
||||||
//PouchDB.plugin(require('pouchdb-replication'));
|
//PouchDB.plugin(require('pouchdb-replication'));
|
||||||
PouchDB.plugin(require("pouchdb-upsert"));
|
PouchDB.plugin(require("pouchdb-upsert"));
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
var db = new PouchDB(chatDB);
|
var db = new PouchDB(chatDB);
|
||||||
var users = new PouchDB(userDB);
|
var users = new PouchDB(userDB);
|
||||||
|
|
||||||
|
@ -90,14 +92,15 @@ createUserIndex();
|
||||||
// REMOTE SYNC ATTEMPTS
|
// REMOTE SYNC ATTEMPTS
|
||||||
|
|
||||||
//var remoteDB = new PouchDB('http://172.20.10.4:5984/chatDB')
|
//var remoteDB = new PouchDB('http://172.20.10.4:5984/chatDB')
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
||||||
// we need express packages for running pouchdb sync "express-pouchdb"
|
// we need express packages for running pouchdb sync "express-pouchdb"
|
||||||
var express = require('express');
|
var express = require('express');
|
||||||
var app = express();
|
var app = express();
|
||||||
app.use('/chatDB', require('express-pouchdb')(PouchDB));
|
app.use('/', require('express-pouchdb')(PouchDB));
|
||||||
app.listen(5984);
|
app.listen(5984);
|
||||||
|
var db = new PouchDB(chatDB);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
app.use('/chatDB', require('pouchdb-express-router')(PouchDB));
|
app.use('/chatDB', require('pouchdb-express-router')(PouchDB));
|
||||||
|
@ -818,6 +821,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
obj.checksum = "null";
|
obj.checksum = "null";
|
||||||
obj.msg = "null";
|
obj.msg = "null";
|
||||||
obj.status = item.status;
|
obj.status = item.status;
|
||||||
|
obj.hmac_signed = item.hmac_signed;
|
||||||
obj.snr = item.snr;
|
obj.snr = item.snr;
|
||||||
obj.type = "ping";
|
obj.type = "ping";
|
||||||
obj.filename = "null";
|
obj.filename = "null";
|
||||||
|
@ -897,6 +901,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
obj.filetype = splitted_data[7];
|
obj.filetype = splitted_data[7];
|
||||||
//obj.file = btoa(splitted_data[8]);
|
//obj.file = btoa(splitted_data[8]);
|
||||||
obj.file = FD.btoa_FD(splitted_data[8]);
|
obj.file = FD.btoa_FD(splitted_data[8]);
|
||||||
|
obj.hmac_signed = item.hmac_signed;
|
||||||
obj.new = 1;
|
obj.new = 1;
|
||||||
} else if (splitted_data[1] == "req" && splitted_data[2] == "0") {
|
} else if (splitted_data[1] == "req" && splitted_data[2] == "0") {
|
||||||
obj.uuid = uuidv4().toString();
|
obj.uuid = uuidv4().toString();
|
||||||
|
@ -910,6 +915,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
obj.filename = "null";
|
obj.filename = "null";
|
||||||
obj.filetype = "null";
|
obj.filetype = "null";
|
||||||
obj.file = "null";
|
obj.file = "null";
|
||||||
|
obj.hmac_signed = item.hmac_signed;
|
||||||
obj.new = 0;
|
obj.new = 0;
|
||||||
if (config.enable_request_profile == "True") {
|
if (config.enable_request_profile == "True") {
|
||||||
sendUserData(item.dxcallsign);
|
sendUserData(item.dxcallsign);
|
||||||
|
@ -926,6 +932,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
obj.filename = "null";
|
obj.filename = "null";
|
||||||
obj.filetype = "null";
|
obj.filetype = "null";
|
||||||
obj.file = "null";
|
obj.file = "null";
|
||||||
|
obj.hmac_signed = item.hmac_signed;
|
||||||
obj.new = 0;
|
obj.new = 0;
|
||||||
if (config.enable_request_shared_folder == "True") {
|
if (config.enable_request_shared_folder == "True") {
|
||||||
sendSharedFolderList(item.dxcallsign);
|
sendSharedFolderList(item.dxcallsign);
|
||||||
|
@ -947,6 +954,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
obj.filename = "null";
|
obj.filename = "null";
|
||||||
obj.filetype = "null";
|
obj.filetype = "null";
|
||||||
obj.file = "null";
|
obj.file = "null";
|
||||||
|
obj.hmac_signed = item.hmac_signed;
|
||||||
obj.new = 0;
|
obj.new = 0;
|
||||||
if (config.enable_request_shared_folder == "True") {
|
if (config.enable_request_shared_folder == "True") {
|
||||||
sendSharedFolderFile(item.dxcallsign, name);
|
sendSharedFolderFile(item.dxcallsign, name);
|
||||||
|
@ -963,6 +971,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
obj.filename = "null";
|
obj.filename = "null";
|
||||||
obj.filetype = "null";
|
obj.filetype = "null";
|
||||||
obj.file = "null";
|
obj.file = "null";
|
||||||
|
obj.hmac_signed = item.hmac_signed;
|
||||||
obj.new = 0;
|
obj.new = 0;
|
||||||
console.log(splitted_data);
|
console.log(splitted_data);
|
||||||
let userData = new Object();
|
let userData = new Object();
|
||||||
|
@ -992,6 +1001,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
obj.filename = "null";
|
obj.filename = "null";
|
||||||
obj.filetype = "null";
|
obj.filetype = "null";
|
||||||
obj.file = "null";
|
obj.file = "null";
|
||||||
|
obj.hmac_signed = item.hmac_signed;
|
||||||
obj.new = 0;
|
obj.new = 0;
|
||||||
console.log(splitted_data);
|
console.log(splitted_data);
|
||||||
|
|
||||||
|
@ -1006,7 +1016,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
|
|
||||||
//getSetUserInformation(selected_callsign);
|
//getSetUserInformation(selected_callsign);
|
||||||
} else if (splitted_data[1] == "res-2") {
|
} else if (splitted_data[1] == "res-2") {
|
||||||
console.log("In received respons-2");
|
console.log("In received response-2");
|
||||||
let sharedFileInfo = splitted_data[2].split("/", 2);
|
let sharedFileInfo = splitted_data[2].split("/", 2);
|
||||||
|
|
||||||
obj.uuid = uuidv4().toString();
|
obj.uuid = uuidv4().toString();
|
||||||
|
@ -1020,6 +1030,7 @@ ipcRenderer.on("action-new-msg-received", (event, arg) => {
|
||||||
obj.filename = sharedFileInfo[0];
|
obj.filename = sharedFileInfo[0];
|
||||||
obj.filetype = "application/octet-stream";
|
obj.filetype = "application/octet-stream";
|
||||||
obj.file = FD.btoa_FD(sharedFileInfo[1]);
|
obj.file = FD.btoa_FD(sharedFileInfo[1]);
|
||||||
|
obj.hmac_signed = item.hmac_signed;
|
||||||
obj.new = 0;
|
obj.new = 0;
|
||||||
} else {
|
} else {
|
||||||
console.log("no rule matched for handling received data!");
|
console.log("no rule matched for handling received data!");
|
||||||
|
@ -1049,16 +1060,13 @@ update_chat = function (obj) {
|
||||||
}
|
}
|
||||||
return doc;
|
return doc;
|
||||||
});
|
});
|
||||||
obj.attempt = 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
// define attempts
|
|
||||||
if (typeof obj.attempt == "undefined") {
|
|
||||||
var attempt = 1;
|
var attempt = 1;
|
||||||
|
obj.attempt = attempt;
|
||||||
} else {
|
} else {
|
||||||
var attempt = obj.attempt;
|
var attempt = obj.attempt;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
// add percent and bytes per minute if not existing
|
// add percent and bytes per minute if not existing
|
||||||
//console.log(obj.percent)
|
//console.log(obj.percent)
|
||||||
if (typeof obj.percent == "undefined") {
|
if (typeof obj.percent == "undefined") {
|
||||||
|
@ -1387,6 +1395,18 @@ update_chat = function (obj) {
|
||||||
showOsPopUp("Message received from " + obj.dxcallsign, obj.msg);
|
showOsPopUp("Message received from " + obj.dxcallsign, obj.msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// check if message is signed or not for adjusting icon
|
||||||
|
if(typeof obj.hmac_signed !== "undefined" && obj.hmac_signed !== "False"){
|
||||||
|
console.log(hmac_signed)
|
||||||
|
var hmac_signed = '<i class="bi bi-shield-fill-check"></i>';
|
||||||
|
} else {
|
||||||
|
|
||||||
|
var hmac_signed = '<i class="bi bi-shield-x"></i>';
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
var new_message = `
|
var new_message = `
|
||||||
<div class="d-flex align-items-center" style="margin-left: auto;"> <!-- max-width: 75%; -->
|
<div class="d-flex align-items-center" style="margin-left: auto;"> <!-- max-width: 75%; -->
|
||||||
|
|
||||||
|
@ -1401,6 +1421,17 @@ update_chat = function (obj) {
|
||||||
<span class="badge bg-light text-muted">${timestamp}</span>
|
<span class="badge bg-light text-muted">${timestamp}</span>
|
||||||
|
|
||||||
</p>
|
</p>
|
||||||
|
|
||||||
|
|
||||||
|
<span id="msg-${
|
||||||
|
obj._id
|
||||||
|
}-hmac-badge" class="position-absolute top-0 start-100 translate-middle badge rounded-1 bg-secondary border border-white">
|
||||||
|
|
||||||
|
<span id="msg-${
|
||||||
|
obj._id
|
||||||
|
}-hmac-signed" class="">${hmac_signed}</span>
|
||||||
|
</span>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -1925,6 +1956,7 @@ add_obj_to_database = function (obj) {
|
||||||
status: obj.status,
|
status: obj.status,
|
||||||
snr: obj.snr,
|
snr: obj.snr,
|
||||||
attempt: obj.attempt,
|
attempt: obj.attempt,
|
||||||
|
hmac_signed: obj.hmac_signed,
|
||||||
new: obj.new,
|
new: obj.new,
|
||||||
_attachments: {
|
_attachments: {
|
||||||
[obj.filename]: {
|
[obj.filename]: {
|
||||||
|
@ -2173,6 +2205,7 @@ function createChatIndex() {
|
||||||
"status",
|
"status",
|
||||||
"percent",
|
"percent",
|
||||||
"attempt",
|
"attempt",
|
||||||
|
"hmac_signed",
|
||||||
"bytesperminute",
|
"bytesperminute",
|
||||||
"_attachments",
|
"_attachments",
|
||||||
"new",
|
"new",
|
||||||
|
|
|
@ -6,6 +6,8 @@ Created on Sun Dec 27 20:43:40 2020
|
||||||
"""
|
"""
|
||||||
# pylint: disable=invalid-name, line-too-long, c-extension-no-member
|
# pylint: disable=invalid-name, line-too-long, c-extension-no-member
|
||||||
# pylint: disable=import-outside-toplevel, attribute-defined-outside-init
|
# pylint: disable=import-outside-toplevel, attribute-defined-outside-init
|
||||||
|
# pylint: disable=fixme
|
||||||
|
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import base64
|
import base64
|
||||||
|
@ -15,7 +17,8 @@ import time
|
||||||
import uuid
|
import uuid
|
||||||
import lzma
|
import lzma
|
||||||
from random import randrange
|
from random import randrange
|
||||||
|
import hmac
|
||||||
|
import hashlib
|
||||||
import codec2
|
import codec2
|
||||||
import helpers
|
import helpers
|
||||||
import modem
|
import modem
|
||||||
|
@ -326,7 +329,8 @@ class DATA:
|
||||||
# [3] mycallsign with ssid
|
# [3] mycallsign with ssid
|
||||||
# [4] dxcallsign with ssid
|
# [4] dxcallsign with ssid
|
||||||
# [5] attempts
|
# [5] attempts
|
||||||
self.open_dc_and_transmit(data[1], data[2], data[3], data[4], data[5])
|
# [6] hmac salt hash
|
||||||
|
self.open_dc_and_transmit(data[1], data[2], data[3], data[4], data[5], data[6])
|
||||||
|
|
||||||
|
|
||||||
elif data[0] == "FEC_IS_WRITING":
|
elif data[0] == "FEC_IS_WRITING":
|
||||||
|
@ -915,9 +919,27 @@ class DATA:
|
||||||
data_frame = payload[9:]
|
data_frame = payload[9:]
|
||||||
data_frame_crc_received = helpers.get_crc_32(data_frame)
|
data_frame_crc_received = helpers.get_crc_32(data_frame)
|
||||||
|
|
||||||
# Check if data_frame_crc is equal with received crc
|
# check if hmac signing enabled
|
||||||
if data_frame_crc == data_frame_crc_received:
|
if TNC.enable_hmac:
|
||||||
self.arq_process_received_data_frame(data_frame, snr)
|
self.log.info(
|
||||||
|
"[TNC] [HMAC] Enabled",
|
||||||
|
)
|
||||||
|
# now check if we have valid hmac signature - returns salt or bool
|
||||||
|
salt_found = helpers.search_hmac_salt(self.dxcallsign, self.mycallsign, data_frame_crc, data_frame, token_iters=100)
|
||||||
|
|
||||||
|
if salt_found:
|
||||||
|
# hmac digest received
|
||||||
|
self.arq_process_received_data_frame(data_frame, snr, signed=True)
|
||||||
|
|
||||||
|
else:
|
||||||
|
|
||||||
|
# hmac signature wrong
|
||||||
|
self.arq_process_received_data_frame(data_frame, snr, signed=False)
|
||||||
|
elif data_frame_crc == data_frame_crc_received:
|
||||||
|
self.log.warning(
|
||||||
|
"[TNC] [HMAC] Disabled, using CRC",
|
||||||
|
)
|
||||||
|
self.arq_process_received_data_frame(data_frame, snr, signed=False)
|
||||||
else:
|
else:
|
||||||
self.send_data_to_socket_queue(
|
self.send_data_to_socket_queue(
|
||||||
freedata="tnc-message",
|
freedata="tnc-message",
|
||||||
|
@ -1019,18 +1041,21 @@ class DATA:
|
||||||
# Update modes we are listening to
|
# Update modes we are listening to
|
||||||
self.set_listening_modes(False, True, self.mode_list[self.speed_level])
|
self.set_listening_modes(False, True, self.mode_list[self.speed_level])
|
||||||
|
|
||||||
def arq_process_received_data_frame(self, data_frame, snr):
|
def arq_process_received_data_frame(self, data_frame, snr, signed):
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
# transmittion duration
|
# transmittion duration
|
||||||
|
|
||||||
|
signed = "True" if signed else "False"
|
||||||
|
|
||||||
duration = time.time() - self.rx_start_of_transmission
|
duration = time.time() - self.rx_start_of_transmission
|
||||||
self.calculate_transfer_rate_rx(
|
self.calculate_transfer_rate_rx(
|
||||||
self.rx_start_of_transmission, len(ARQ.rx_frame_buffer)
|
self.rx_start_of_transmission, len(ARQ.rx_frame_buffer)
|
||||||
)
|
)
|
||||||
self.log.info("[TNC] ARQ | RX | DATA FRAME SUCCESSFULLY RECEIVED", nacks=self.frame_nack_counter,
|
self.log.info("[TNC] ARQ | RX | DATA FRAME SUCCESSFULLY RECEIVED", nacks=self.frame_nack_counter,
|
||||||
bytesperminute=ARQ.bytes_per_minute, total_bytes=ARQ.total_bytes, duration=duration)
|
bytesperminute=ARQ.bytes_per_minute, total_bytes=ARQ.total_bytes, duration=duration, hmac_signed=signed)
|
||||||
|
|
||||||
# Decompress the data frame
|
# Decompress the data frame
|
||||||
data_frame_decompressed = lzma.decompress(data_frame)
|
data_frame_decompressed = lzma.decompress(data_frame)
|
||||||
|
@ -1125,7 +1150,8 @@ class DATA:
|
||||||
dxcallsign=str(Station.dxcallsign, "UTF-8"),
|
dxcallsign=str(Station.dxcallsign, "UTF-8"),
|
||||||
dxgrid=str(Station.dxgrid, "UTF-8"),
|
dxgrid=str(Station.dxgrid, "UTF-8"),
|
||||||
data=base64_data,
|
data=base64_data,
|
||||||
irs=helpers.bool_to_string(self.is_IRS)
|
irs=helpers.bool_to_string(self.is_IRS),
|
||||||
|
hmac_signed=signed
|
||||||
)
|
)
|
||||||
|
|
||||||
if TNC.enable_stats:
|
if TNC.enable_stats:
|
||||||
|
@ -1150,7 +1176,7 @@ class DATA:
|
||||||
snr=snr,
|
snr=snr,
|
||||||
)
|
)
|
||||||
|
|
||||||
def arq_transmit(self, data_out: bytes):
|
def arq_transmit(self, data_out: bytes, hmac_salt: bytes):
|
||||||
"""
|
"""
|
||||||
Transmit ARQ frame
|
Transmit ARQ frame
|
||||||
|
|
||||||
|
@ -1204,9 +1230,19 @@ class DATA:
|
||||||
tx_start_of_transmission = time.time()
|
tx_start_of_transmission = time.time()
|
||||||
self.calculate_transfer_rate_tx(tx_start_of_transmission, 0, len(data_out))
|
self.calculate_transfer_rate_tx(tx_start_of_transmission, 0, len(data_out))
|
||||||
|
|
||||||
# Append a crc at the beginning and end of file indicators
|
# check if hmac signature is available
|
||||||
frame_payload_crc = helpers.get_crc_32(data_out)
|
if hmac_salt not in ['', False]:
|
||||||
self.log.debug("[TNC] frame payload CRC:", crc=frame_payload_crc.hex())
|
print(data_out)
|
||||||
|
# create hmac digest
|
||||||
|
hmac_digest = hmac.new(hmac_salt, data_out, hashlib.sha256).digest()
|
||||||
|
# truncate to 32bit
|
||||||
|
frame_payload_crc = hmac_digest[:4]
|
||||||
|
self.log.debug("[TNC] frame payload HMAC:", crc=frame_payload_crc.hex())
|
||||||
|
|
||||||
|
else:
|
||||||
|
# Append a crc at the beginning and end of file indicators
|
||||||
|
frame_payload_crc = helpers.get_crc_32(data_out)
|
||||||
|
self.log.debug("[TNC] frame payload CRC:", crc=frame_payload_crc.hex())
|
||||||
|
|
||||||
# Assemble the data frame
|
# Assemble the data frame
|
||||||
data_out = (
|
data_out = (
|
||||||
|
@ -1269,7 +1305,7 @@ class DATA:
|
||||||
tempbuffer = []
|
tempbuffer = []
|
||||||
self.rpt_request_buffer = []
|
self.rpt_request_buffer = []
|
||||||
# Append data frames with n_frames_per_burst to tempbuffer
|
# Append data frames with n_frames_per_burst to tempbuffer
|
||||||
for n_frame in range(0, n_frames_per_burst):
|
for n_frame in range(n_frames_per_burst):
|
||||||
arqheader = bytearray()
|
arqheader = bytearray()
|
||||||
arqheader[:1] = bytes([FR_TYPE.BURST_01.value + n_frame])
|
arqheader[:1] = bytes([FR_TYPE.BURST_01.value + n_frame])
|
||||||
#####arqheader[:1] = bytes([FR_TYPE.BURST_01.value])
|
#####arqheader[:1] = bytes([FR_TYPE.BURST_01.value])
|
||||||
|
@ -1643,7 +1679,7 @@ class DATA:
|
||||||
print(self.rpt_request_buffer)
|
print(self.rpt_request_buffer)
|
||||||
|
|
||||||
tempbuffer_rptframes = []
|
tempbuffer_rptframes = []
|
||||||
for i in range(0, len(missing_area)):
|
for i in range(len(missing_area)):
|
||||||
print(missing_area[i])
|
print(missing_area[i])
|
||||||
missing_frames_buffer_position = missing_area[i] - 1
|
missing_frames_buffer_position = missing_area[i] - 1
|
||||||
tempbuffer_rptframes.append(self.rpt_request_buffer[missing_frames_buffer_position])
|
tempbuffer_rptframes.append(self.rpt_request_buffer[missing_frames_buffer_position])
|
||||||
|
@ -2061,6 +2097,7 @@ class DATA:
|
||||||
mycallsign,
|
mycallsign,
|
||||||
dxcallsign,
|
dxcallsign,
|
||||||
attempts: int,
|
attempts: int,
|
||||||
|
hmac_salt: str
|
||||||
) -> bool:
|
) -> bool:
|
||||||
"""
|
"""
|
||||||
Open data channel and transmit data
|
Open data channel and transmit data
|
||||||
|
@ -2109,7 +2146,7 @@ class DATA:
|
||||||
threading.Event().wait(0.01)
|
threading.Event().wait(0.01)
|
||||||
|
|
||||||
if ARQ.arq_state:
|
if ARQ.arq_state:
|
||||||
self.arq_transmit(data_out)
|
self.arq_transmit(data_out, hmac_salt)
|
||||||
return True
|
return True
|
||||||
|
|
||||||
return False
|
return False
|
||||||
|
|
176
tnc/helpers.py
176
tnc/helpers.py
|
@ -13,6 +13,13 @@ import structlog
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import threading
|
import threading
|
||||||
import mesh
|
import mesh
|
||||||
|
import hashlib
|
||||||
|
import hmac
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
from pathlib import Path
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
log = structlog.get_logger("helpers")
|
log = structlog.get_logger("helpers")
|
||||||
|
|
||||||
|
@ -489,3 +496,172 @@ def return_key_from_object(default, obj, key):
|
||||||
|
|
||||||
def bool_to_string(state):
|
def bool_to_string(state):
|
||||||
return "True" if state else "False"
|
return "True" if state else "False"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
def get_hmac_salt(dxcallsign: bytes, mycallsign: bytes):
|
||||||
|
filename = f"freedata_hmac_STATION_{mycallsign.decode('utf-8')}_REMOTE_{dxcallsign.decode('utf-8')}.txt"
|
||||||
|
if sys.platform in ["linux"]:
|
||||||
|
|
||||||
|
if hasattr(sys, "_MEIPASS"):
|
||||||
|
filepath = getattr(sys, "_MEIPASS") + '/hmac/' + filename
|
||||||
|
else:
|
||||||
|
subfolder = Path('hmac')
|
||||||
|
filepath = subfolder / filename
|
||||||
|
|
||||||
|
|
||||||
|
elif sys.platform in ["darwin"]:
|
||||||
|
if hasattr(sys, "_MEIPASS"):
|
||||||
|
filepath = getattr(sys, "_MEIPASS") + '/hmac/' + filename
|
||||||
|
else:
|
||||||
|
subfolder = Path('hmac')
|
||||||
|
filepath = subfolder / filename
|
||||||
|
|
||||||
|
elif sys.platform in ["win32", "win64"]:
|
||||||
|
if hasattr(sys, "_MEIPASS"):
|
||||||
|
filepath = getattr(sys, "_MEIPASS") + '/hmac/' + filename
|
||||||
|
else:
|
||||||
|
subfolder = Path('hmac')
|
||||||
|
filepath = subfolder / filename
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subfolder = Path('hmac')
|
||||||
|
filepath = subfolder / filename
|
||||||
|
except Exception as e:
|
||||||
|
log.error(
|
||||||
|
"[TNC] [HMAC] File lookup error", file=filepath,
|
||||||
|
)
|
||||||
|
|
||||||
|
# check if file exists else return false
|
||||||
|
if not check_if_file_exists(filepath):
|
||||||
|
return False
|
||||||
|
|
||||||
|
log.info("[SCK] [HMAC] File lookup", file=filepath)
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(filepath, "r") as file:
|
||||||
|
line = file.readlines()
|
||||||
|
hmac_salt = bytes(line[-1], "utf-8").split(b'\n')
|
||||||
|
hmac_salt = hmac_salt[0]
|
||||||
|
return hmac_salt if delete_last_line_from_hmac_list(filepath, -1) else False
|
||||||
|
except Exception as e:
|
||||||
|
log.warning("[SCK] [HMAC] File lookup failed", file=filepath, e=e)
|
||||||
|
return False
|
||||||
|
|
||||||
|
def search_hmac_salt(dxcallsign: bytes, mycallsign: bytes, search_token, data_frame, token_iters):
|
||||||
|
|
||||||
|
filename = f"freedata_hmac_STATION_{mycallsign.decode('utf-8')}_REMOTE_{dxcallsign.decode('utf-8')}.txt"
|
||||||
|
if sys.platform in ["linux"]:
|
||||||
|
|
||||||
|
if hasattr(sys, "_MEIPASS"):
|
||||||
|
filepath = getattr(sys, "_MEIPASS") + '/hmac/' + filename
|
||||||
|
else:
|
||||||
|
subfolder = Path('hmac')
|
||||||
|
filepath = subfolder / filename
|
||||||
|
|
||||||
|
|
||||||
|
elif sys.platform in ["darwin"]:
|
||||||
|
if hasattr(sys, "_MEIPASS"):
|
||||||
|
filepath = getattr(sys, "_MEIPASS") + '/hmac/' + filename
|
||||||
|
else:
|
||||||
|
subfolder = Path('hmac')
|
||||||
|
filepath = subfolder / filename
|
||||||
|
|
||||||
|
elif sys.platform in ["win32", "win64"]:
|
||||||
|
if hasattr(sys, "_MEIPASS"):
|
||||||
|
filepath = getattr(sys, "_MEIPASS") + '/hmac/' + filename
|
||||||
|
else:
|
||||||
|
subfolder = Path('hmac')
|
||||||
|
filepath = subfolder / filename
|
||||||
|
else:
|
||||||
|
try:
|
||||||
|
subfolder = Path('hmac')
|
||||||
|
filepath = subfolder / filename
|
||||||
|
except Exception as e:
|
||||||
|
log.error(
|
||||||
|
"[TNC] [HMAC] File lookup error", file=filepath,
|
||||||
|
)
|
||||||
|
|
||||||
|
# check if file exists else return false
|
||||||
|
if not check_if_file_exists(filepath):
|
||||||
|
log.warning(
|
||||||
|
"[TNC] [HMAC] Token file not found", file=filepath,
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
with open(filepath, "r") as file:
|
||||||
|
token_list = file.readlines()
|
||||||
|
|
||||||
|
token_iters = min(token_iters, len(token_list))
|
||||||
|
for _ in range(1, token_iters + 1):
|
||||||
|
key = token_list[len(token_list) - _][:-1]
|
||||||
|
key = bytes(key, "utf-8")
|
||||||
|
search_digest = hmac.new(key, data_frame, hashlib.sha256).digest()[:4]
|
||||||
|
# TODO: Remove this debugging information if not needed anymore
|
||||||
|
# print("-----------------------------------------")
|
||||||
|
# print(_)
|
||||||
|
# print(f" key-------------{key}")
|
||||||
|
# print(f" key-------------{token_list[len(token_list) - _][:-1]}")
|
||||||
|
# print(f" key-------------{key.hex()}")
|
||||||
|
# print(f" search token----{search_token.hex()}")
|
||||||
|
# print(f" search digest---{search_digest.hex()}")
|
||||||
|
if search_token.hex() == search_digest.hex():
|
||||||
|
token_position = len(token_list) - _
|
||||||
|
delete_last_line_from_hmac_list(filepath, token_position)
|
||||||
|
log.info(
|
||||||
|
"[TNC] [HMAC] Signature found", expected=search_token.hex(),
|
||||||
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
log.warning(
|
||||||
|
"[TNC] [HMAC] Signature not found", expected=search_token.hex(), filepath=filepath,
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
log.warning(
|
||||||
|
"[TNC] [HMAC] Lookup failed", e=e, expected=search_token,
|
||||||
|
)
|
||||||
|
return False
|
||||||
|
|
||||||
|
|
||||||
|
def delete_last_line_from_hmac_list(filepath, position):
|
||||||
|
# check if file exists else return false
|
||||||
|
if not check_if_file_exists(filepath):
|
||||||
|
return False
|
||||||
|
|
||||||
|
try:
|
||||||
|
linearray = []
|
||||||
|
with open(filepath, "r") as file:
|
||||||
|
linearray = file.readlines()[:position]
|
||||||
|
#print(linearray)
|
||||||
|
|
||||||
|
with open(filepath, "w") as file:
|
||||||
|
#print(linearray)
|
||||||
|
for line in linearray:
|
||||||
|
file.write(line)
|
||||||
|
|
||||||
|
return True
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
return False
|
||||||
|
|
||||||
|
def check_if_file_exists(path):
|
||||||
|
try:
|
||||||
|
# check if file size is present and filesize > 0
|
||||||
|
if os.path.isfile(path):
|
||||||
|
filesize = os.path.getsize(path)
|
||||||
|
if filesize > 0:
|
||||||
|
return True
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
else:
|
||||||
|
return False
|
||||||
|
except Exception as e:
|
||||||
|
log.warning(
|
||||||
|
"[TNC] [FILE] Lookup failed", e=e, path=path,
|
||||||
|
)
|
||||||
|
return False
|
10
tnc/main.py
10
tnc/main.py
|
@ -253,6 +253,14 @@ if __name__ == "__main__":
|
||||||
help="Enable mesh protocol",
|
help="Enable mesh protocol",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
PARSER.add_argument(
|
||||||
|
"--hmac",
|
||||||
|
dest="enable_hmac",
|
||||||
|
action="store_true",
|
||||||
|
default=True,
|
||||||
|
help="Enable and set hmac message salt",
|
||||||
|
)
|
||||||
|
|
||||||
ARGS = PARSER.parse_args()
|
ARGS = PARSER.parse_args()
|
||||||
|
|
||||||
# set save to folder state for allowing downloading files to local file system
|
# set save to folder state for allowing downloading files to local file system
|
||||||
|
@ -307,6 +315,8 @@ if __name__ == "__main__":
|
||||||
TCIParam.port = ARGS.tci_port
|
TCIParam.port = ARGS.tci_port
|
||||||
ModemParam.tx_delay = ARGS.tx_delay
|
ModemParam.tx_delay = ARGS.tx_delay
|
||||||
MeshParam.enable_protocol = ARGS.enable_mesh
|
MeshParam.enable_protocol = ARGS.enable_mesh
|
||||||
|
TNC.enable_hmac = ARGS.enable_hmac
|
||||||
|
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
log.error("[DMN] Error reading config file", exception=e)
|
log.error("[DMN] Error reading config file", exception=e)
|
||||||
|
|
152
tnc/mesh.py
152
tnc/mesh.py
|
@ -53,37 +53,33 @@ class MeshRouter():
|
||||||
|
|
||||||
self.log = structlog.get_logger("RF")
|
self.log = structlog.get_logger("RF")
|
||||||
|
|
||||||
self.transmission_time_list = [30, 60, 60, 60, 60, 60, 60,120,120,120,120,120,120, 180, 180, 180, 180, 180,180,360,360,360,360,360,360,
|
self.transmission_time_list = [
|
||||||
60, 60, 60, 60, 60, 60,120,120,120,120,120,120, 180, 180, 180, 180, 180,180,360,360,360,360,360,360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60,120,120,120,120,120,120, 180, 180, 180, 180, 180,180,360,360,360,360,360,360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60,120,120,120,120,120,120, 180, 180, 180, 180, 180,180,360,360,360,360,360,360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60,120,120,120,120,120,120, 180, 180, 180, 180, 180,180,360,360,360,360,360,360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60,120,120,120,120,120,120, 180, 180, 180, 180, 180,180,360,360,360,360,360,360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60,120,120,120,120,120,120, 180, 180, 180, 180, 180,180,360,360,360,360,360,360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60,120,120,120,120,120,120, 180, 180, 180, 180, 180,180,360,360,360,360,360,360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360,
|
||||||
360, 360, 360, 360,
|
60, 90, 120, 180, 180, 180, 180, 180, 180, 360, 360, 360, 360, 360, 360
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
]
|
||||||
360, 360, 360, 360,
|
|
||||||
60, 60, 60, 60, 60, 60, 120, 120, 120, 120, 120, 120, 180, 180, 180, 180, 180, 180, 360, 360,
|
|
||||||
360, 360, 360, 360,
|
|
||||||
]
|
|
||||||
# for testing only: self.transmission_time_list = [30, 30]
|
# for testing only: self.transmission_time_list = [30, 30]
|
||||||
self.signalling_max_attempts = len(self.transmission_time_list)
|
self.signalling_max_attempts = len(self.transmission_time_list)
|
||||||
|
|
||||||
|
@ -453,62 +449,68 @@ class MeshRouter():
|
||||||
|
|
||||||
|
|
||||||
def add_mesh_ping_to_signalling_table(self, destination, origin, frametype, status):
|
def add_mesh_ping_to_signalling_table(self, destination, origin, frametype, status):
|
||||||
timestamp = time.time()
|
try:
|
||||||
#router = ""
|
timestamp = time.time()
|
||||||
#frametype = "PING"
|
#router = ""
|
||||||
payload = ""
|
#frametype = "PING"
|
||||||
attempt = 0
|
payload = ""
|
||||||
|
attempt = 0
|
||||||
|
|
||||||
# [timestamp, destination, origin, frametype, payload, attempt, status]
|
# [timestamp, destination, origin, frametype, payload, attempt, status]
|
||||||
# --------------0------------1---------2---------3--------4---------5--------6-----#
|
# --------------0------------1---------2---------3--------4---------5--------6-----#
|
||||||
new_entry = [timestamp, destination, origin, frametype, payload, attempt, status]
|
new_entry = [timestamp, destination, origin, frametype, payload, attempt, status]
|
||||||
for _, item in enumerate(MESH_SIGNALLING_TABLE):
|
for _, item in enumerate(MESH_SIGNALLING_TABLE):
|
||||||
# update entry if exists
|
# update entry if exists
|
||||||
if destination in item[1] and origin in item[2] and frametype in item[3]:
|
if destination in item[1] and origin in item[2] and frametype in item[3]:
|
||||||
# reset attempts if entry exists and it failed or is acknowledged
|
# reset attempts if entry exists and it failed or is acknowledged
|
||||||
attempt = 0 if item[6] in ["failed", "acknowledged"] else item[5]
|
attempt = 0 if item[6] in ["failed", "acknowledged"] else item[5]
|
||||||
update_entry = [item[0], destination, origin, frametype, "",attempt, status]
|
update_entry = [item[0], destination, origin, frametype, "",attempt, status]
|
||||||
#print(f"UPDATE {MESH_SIGNALLING_TABLE[_]} >>> {update_entry}")
|
#print(f"UPDATE {MESH_SIGNALLING_TABLE[_]} >>> {update_entry}")
|
||||||
|
|
||||||
self.log.info(f"[MESH] [SIGNALLING TABLE] [UPDATE]: {MESH_SIGNALLING_TABLE[_]} >>> ", update=update_entry)
|
self.log.info(f"[MESH] [SIGNALLING TABLE] [UPDATE]: {MESH_SIGNALLING_TABLE[_]} >>> ", update=update_entry)
|
||||||
|
|
||||||
MESH_SIGNALLING_TABLE[_] = update_entry
|
MESH_SIGNALLING_TABLE[_] = update_entry
|
||||||
return
|
return
|
||||||
|
|
||||||
# add new routing entry if not exists
|
# add new routing entry if not exists
|
||||||
if new_entry not in MESH_SIGNALLING_TABLE:
|
if new_entry not in MESH_SIGNALLING_TABLE:
|
||||||
#print(f"INSERT {new_entry} >>> SIGNALLING TABLE")
|
#print(f"INSERT {new_entry} >>> SIGNALLING TABLE")
|
||||||
self.log.info("[MESH] [SIGNALLING TABLE] [INSERT]:", insert=new_entry)
|
self.log.info("[MESH] [SIGNALLING TABLE] [INSERT]:", insert=new_entry)
|
||||||
|
|
||||||
MESH_SIGNALLING_TABLE.append(new_entry)
|
MESH_SIGNALLING_TABLE.append(new_entry)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
self.log.warning(f"[MESH] [SIGNALLING TABLE] [INSERT] [PING] [ERROR] ", e=e)
|
||||||
def add_mesh_ping_ack_to_signalling_table(self, destination, origin, status):
|
def add_mesh_ping_ack_to_signalling_table(self, destination, origin, status):
|
||||||
|
try:
|
||||||
|
timestamp = time.time()
|
||||||
|
#router = ""
|
||||||
|
frametype = "PING-ACK"
|
||||||
|
payload = ""
|
||||||
|
attempt = 0
|
||||||
|
new_entry = [timestamp, destination, origin, frametype, payload, attempt, status]
|
||||||
|
|
||||||
timestamp = time.time()
|
for _, item in enumerate(MESH_SIGNALLING_TABLE):
|
||||||
#router = ""
|
# update entry if exists
|
||||||
frametype = "PING-ACK"
|
if destination in item[1] and origin in item[2] and item[3] in ["PING", "PING-ACK"]:
|
||||||
payload = ""
|
# reset attempts if entry exists and it failed or is acknowledged
|
||||||
attempt = 0
|
attempt = 0 if item[6] in ["failed", "acknowledged"] else item[5]
|
||||||
new_entry = [timestamp, destination, origin, frametype, payload, attempt, status]
|
update_entry = [item[0], destination, origin, "PING-ACK", "", attempt, status]
|
||||||
|
#print(f"UPDATE {MESH_SIGNALLING_TABLE[_]} >>> {update_entry}")
|
||||||
|
self.log.info(f"[MESH] [SIGNALLING TABLE] [UPDATE]: {MESH_SIGNALLING_TABLE[_]} >>> ", update=update_entry)
|
||||||
|
|
||||||
for _, item in enumerate(MESH_SIGNALLING_TABLE):
|
MESH_SIGNALLING_TABLE[_] = update_entry
|
||||||
# update entry if exists
|
return
|
||||||
if destination in item[1] and origin in item[2] and item[3] in ["PING", "PING-ACK"]:
|
|
||||||
# reset attempts if entry exists and it failed or is acknowledged
|
|
||||||
attempt = 0 if item[6] in ["failed", "acknowledged"] else item[5]
|
|
||||||
update_entry = [item[0], destination, origin, "PING-ACK", "", attempt, status]
|
|
||||||
#print(f"UPDATE {MESH_SIGNALLING_TABLE[_]} >>> {update_entry}")
|
|
||||||
self.log.info(f"[MESH] [SIGNALLING TABLE] [UPDATE]: {MESH_SIGNALLING_TABLE[_]} >>> ", update=update_entry)
|
|
||||||
|
|
||||||
MESH_SIGNALLING_TABLE[_] = update_entry
|
# add new routing entry if not exists
|
||||||
return
|
if new_entry not in MESH_SIGNALLING_TABLE:
|
||||||
|
#print(f"INSERT {new_entry} >>> SIGNALLING TABLE")
|
||||||
|
self.log.info(f"[MESH] [SIGNALLING TABLE] [INSERT] >>> ", update=new_entry)
|
||||||
|
|
||||||
# add new routing entry if not exists
|
MESH_SIGNALLING_TABLE.append(new_entry)
|
||||||
if new_entry not in MESH_SIGNALLING_TABLE:
|
except Exception as e:
|
||||||
#print(f"INSERT {new_entry} >>> SIGNALLING TABLE")
|
self.log.warning(f"[MESH] [SIGNALLING TABLE] [INSERT] [PING ACK] [ERROR] ", e=e)
|
||||||
self.log.info(f"[MESH] [SIGNALLING TABLE] [INSERT]: {MESH_SIGNALLING_TABLE[_]} >>> ", update=new_entry)
|
|
||||||
|
|
||||||
MESH_SIGNALLING_TABLE.append(new_entry)
|
|
||||||
|
|
||||||
def enqueue_frame_for_tx(
|
def enqueue_frame_for_tx(
|
||||||
self,
|
self,
|
||||||
|
|
11
tnc/sock.py
11
tnc/sock.py
|
@ -780,9 +780,16 @@ class ThreadedTCPRequestHandler(socketserver.StreamRequestHandler):
|
||||||
raise TypeError
|
raise TypeError
|
||||||
|
|
||||||
binarydata = base64.b64decode(base64data)
|
binarydata = base64.b64decode(base64data)
|
||||||
|
# check if hmac hash is provided
|
||||||
|
try:
|
||||||
|
log.info("[SCK] [HMAC] Looking for salt/token", local=mycallsign, remote=dxcallsign)
|
||||||
|
hmac_salt = helpers.get_hmac_salt(dxcallsign, mycallsign)
|
||||||
|
log.info("[SCK] [HMAC] Salt info", local=mycallsign, remote=dxcallsign, salt=hmac_salt)
|
||||||
|
except Exception:
|
||||||
|
log.warning("[SCK] [HMAC] No salt/token found")
|
||||||
|
hmac_salt = ''
|
||||||
DATA_QUEUE_TRANSMIT.put(
|
DATA_QUEUE_TRANSMIT.put(
|
||||||
["ARQ_RAW", binarydata, arq_uuid, mycallsign, dxcallsign, attempts]
|
["ARQ_RAW", binarydata, arq_uuid, mycallsign, dxcallsign, attempts, hmac_salt]
|
||||||
)
|
)
|
||||||
|
|
||||||
except Exception as err:
|
except Exception as err:
|
||||||
|
|
|
@ -130,7 +130,7 @@ class TCIParam:
|
||||||
|
|
||||||
@dataclass
|
@dataclass
|
||||||
class TNC:
|
class TNC:
|
||||||
version = "0.10.2-alpha.1"
|
version = "0.10.3-alpha.1-hmac-exp4"
|
||||||
host: str = "0.0.0.0"
|
host: str = "0.0.0.0"
|
||||||
port: int = 3000
|
port: int = 3000
|
||||||
SOCKET_TIMEOUT: int = 1 # seconds
|
SOCKET_TIMEOUT: int = 1 # seconds
|
||||||
|
@ -144,6 +144,7 @@ class TNC:
|
||||||
respond_to_call: bool = True # respond to cq, ping, connection request, file request if not in session
|
respond_to_call: bool = True # respond to cq, ping, connection request, file request if not in session
|
||||||
heard_stations = []
|
heard_stations = []
|
||||||
listen: bool = True
|
listen: bool = True
|
||||||
|
enable_hmac: bool = True
|
||||||
|
|
||||||
# ------------
|
# ------------
|
||||||
|
|
||||||
|
|
61
tools/create_hmac_tokes.py
Executable file
61
tools/create_hmac_tokes.py
Executable file
|
@ -0,0 +1,61 @@
|
||||||
|
#!/usr/bin/python3
|
||||||
|
# -*- coding: utf-8 -*-
|
||||||
|
"""
|
||||||
|
Created on 26.08.23
|
||||||
|
|
||||||
|
@author: DJ2LS
|
||||||
|
|
||||||
|
tool for generating HMAC tokens
|
||||||
|
"""
|
||||||
|
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
def create_hmac_salts(dxcallsign: str, mycallsign: str, num_tokens: int):
|
||||||
|
"""
|
||||||
|
Creates a file with tokens for hmac signing
|
||||||
|
|
||||||
|
Args:
|
||||||
|
dxcallsign:
|
||||||
|
mycallsign:
|
||||||
|
int:
|
||||||
|
|
||||||
|
Returns:
|
||||||
|
bool
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
token_array = []
|
||||||
|
for _ in range(num_tokens):
|
||||||
|
token_array.append(np.random.bytes(4).hex())
|
||||||
|
|
||||||
|
# Create and write random strings to a file
|
||||||
|
with open(f"freedata_hmac_STATION_{mycallsign}_REMOTE_{dxcallsign}.txt", "w") as file:
|
||||||
|
for _ in range(len(token_array)):
|
||||||
|
file.write(token_array[_] + '\n')
|
||||||
|
|
||||||
|
# Create and write random strings to a file
|
||||||
|
with open(f"freedata_hmac_STATION_{dxcallsign}_REMOTE_{mycallsign}.txt", "w") as file:
|
||||||
|
for _ in range(len(token_array)):
|
||||||
|
file.write(token_array[_] + '\n')
|
||||||
|
|
||||||
|
print("files created - place them in tnc/hmac folder and share the file with the remote station")
|
||||||
|
|
||||||
|
except Exception:
|
||||||
|
print("error creating hmac file")
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
|
||||||
|
parser = argparse.ArgumentParser(description='FreeDATA token generator')
|
||||||
|
|
||||||
|
parser.add_argument('--dxcallsign', dest="dxcallsign", default='AA0AA', help="Select the destination callsign", type=str)
|
||||||
|
parser.add_argument('--mycallsign', dest="mycallsign", default='AA0AA', help="Select the own callsign", type=str)
|
||||||
|
parser.add_argument('--tokens', dest="tokens", default=1000, help="Amount of tokens to create", type=int)
|
||||||
|
|
||||||
|
args = parser.parse_args()
|
||||||
|
create_hmac_salts(args.dxcallsign, args.mycallsign, int(args.tokens))
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue