From 1350fbbaf9501f9aac1ca832ca6342f483ed37f5 Mon Sep 17 00:00:00 2001 From: "Tux3 / Mlkj / !Lev.uXFMLA" Date: Sun, 9 Nov 2014 18:04:00 +0100 Subject: [PATCH] Add qtox update-server tools qtox-updater-sign takes data from stdin or as argument, signs it with the updater's private key, and output the signature + the data qtox-updater-genflist generates a flist, a serialized list of AutoUpdater::UpdateFileMeta for the qTox updater --- .../qtox-updater-genflist/main.cpp | 97 +++++++ .../qtox-updater-genflist.pro | 10 + .../qtox-updater-genflist/serialize.cpp | 254 ++++++++++++++++++ .../qtox-updater-genflist/serialize.h | 45 ++++ .../update-server/qtox-updater-sign/main.cpp | 43 +++ .../qtox-updater-sign/qtox-updater-sign.pro | 7 + 6 files changed, 456 insertions(+) create mode 100644 tools/update-server/qtox-updater-genflist/main.cpp create mode 100644 tools/update-server/qtox-updater-genflist/qtox-updater-genflist.pro create mode 100644 tools/update-server/qtox-updater-genflist/serialize.cpp create mode 100644 tools/update-server/qtox-updater-genflist/serialize.h create mode 100644 tools/update-server/qtox-updater-sign/main.cpp create mode 100644 tools/update-server/qtox-updater-sign/qtox-updater-sign.pro diff --git a/tools/update-server/qtox-updater-genflist/main.cpp b/tools/update-server/qtox-updater-genflist/main.cpp new file mode 100644 index 000000000..721751d90 --- /dev/null +++ b/tools/update-server/qtox-updater-genflist/main.cpp @@ -0,0 +1,97 @@ +#include +#include +#include +#include +#include +#include +#include "serialize.h" + +using namespace std; + +/// Pass the target folder as first argument, no spaces allowed. We'll call that dir $TARGET +/// Update the content of $TARGET/files/ before calling this tool +/// We'll generate $TARGET/flist and exit +/// We need qtox-updater-skey in our working directory to sign the flist +/// +/// The generated flist is very simple and just installs everything in the working directory ... + +int main(int argc, char* argv[]) +{ + cout << "qTox updater flist generator" << endl; + + /// First some basic error handling, prepare our handles, ... + if (argc != 2) + { + cout << "ERROR: qtox-updater-genflist takes the target path in argument" << endl; + return 1; + } + + QFile skeyFile("qtox-updater-skey"); + if (!skeyFile.open(QIODevice::ReadOnly)) + { + cout << "ERROR: qtox-updater-genflist can't open the secret (private) key file" << endl; + return 1; + } + QByteArray skeyData = skeyFile.readAll(); + skeyData = QByteArray::fromHex(skeyData); + skeyFile.close(); + + QString target(argv[1]); + + QFile flistFile(target+"/flist"); + if (!flistFile.open(QIODevice::Truncate | QIODevice::WriteOnly)) + { + cout << "ERROR: qtox-updater-genflist can't open the target flist" << endl; + return 1; + } + + QDir fdir(target+"/files/"); + if (!fdir.isReadable()) + { + cout << "ERROR: qtox-updater-genflist can't open the target files directory" << endl; + return 1; + } + + QStringList filesListStr = fdir.entryList(QDir::Files); + + /// Serialize the flist data + QByteArray flistData; + for (QString fileStr : filesListStr) + { + cout << "Adding "< + + This file is part of qTox, a Qt-based graphical interface for Tox. + + This program is libre 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 COPYING file for more details. +*/ + + +#include "serialize.h" + +QByteArray doubleToData(double num) +{ + union + { + char tab[8]; + double n; + } castUnion; + //char n[8]; + //*((double*) n) = num; + + castUnion.n=num; + return QByteArray(castUnion.tab,8); +} + +QByteArray floatToData(float num) +{ + union + { + char tab[4]; + float n; + } castUnion; + + castUnion.n=num; + return QByteArray(castUnion.tab,4); +} + +float dataToFloat(QByteArray data) +{ + union + { + char tab[4]; + float n; + } castUnion; + + castUnion.tab[0]=data.data()[0]; + castUnion.tab[1]=data.data()[1]; + castUnion.tab[2]=data.data()[2]; + castUnion.tab[3]=data.data()[3]; + return castUnion.n; +} + +// Converts a string into PNet string data +QByteArray stringToData(QString str) +{ + QByteArray data(4,0); + // Write the size in a Uint of variable lenght (8-32 bits) + int i=0; + uint num1 = (uint)str.toUtf8().size(); + while (num1 >= 0x80) + { + data[i] = (unsigned char)(num1 | 0x80); i++; + num1 = num1 >> 7; + } + data[i]=num1; + data.resize(i+1); + data+=str.toUtf8(); + return data; +} + +QString dataToString(QByteArray data) +{ + // Variable UInt32 + unsigned char num3; + int num = 0; + int num2 = 0; + int i=0; + do + { + num3 = data[i]; i++; + num |= (num3 & 0x7f) << num2; + num2 += 7; + } while ((num3 & 0x80) != 0); + unsigned int strlen = (uint) num; + + if (!strlen) + return QString(); + + data = data.right(data.size()-i); // Remove the strlen + data.truncate(strlen); + return QString(data); +} + +float dataToRangedSingle(float min, float max, int numberOfBits, QByteArray data) +{ + uint endvalue=0; + uint value=0; + if (numberOfBits <= 8) + { + endvalue = (uchar)data[0]; + goto done; + } + value = (uchar)data[0]; + numberOfBits -= 8; + if (numberOfBits <= 8) + { + endvalue = (value | ((uint) ((uchar)data[1]) << 8)); + goto done; + } + value |= (uint) (((uchar)data[1]) << 8); + numberOfBits -= 8; + if (numberOfBits <= 8) + { + uint num2 = (uint) (((uchar)data[2]) << 0x10); + endvalue = (value | num2); + goto done; + } + value |= (uint) (((uchar)data[2]) << 0x10); + numberOfBits -= 8; + endvalue = (value | ((uint) (((uchar)data[3]) << 0x18))); + goto done; + + done: + + float num = max - min; + int num2 = (((int) 1) << numberOfBits) - 1; + float num3 = endvalue; + float num4 = num3 / ((float) num2); + return (min + (num4 * num)); +} + +QByteArray rangedSingleToData(float value, float min, float max, int numberOfBits) +{ + QByteArray data; + float num = max - min; + float num2 = (value - min) / num; + int num3 = (((int) 1) << numberOfBits) - 1; + uint source = num3 * num2; + + if (numberOfBits <= 8) + { + data += (unsigned char)source; + return data; + } + data += (unsigned char)source; + numberOfBits -= 8; + if (numberOfBits <= 8) + { + data += (unsigned char)source>>8; + return data; + } + data += (unsigned char)source>>8; + numberOfBits -= 8; + if (numberOfBits <= 8) + { + data += (unsigned char)source>>16; + return data; + } + data += (unsigned char)source>>16; + data += (unsigned char)source>>24; + + return data; +} + +uint8_t dataToUint8(QByteArray data) +{ + return (uint8_t)data[0]; +} + +uint16_t dataToUint16(QByteArray data) +{ + return ((uint16_t)(uint8_t)data[0]) + +(((uint16_t)(uint8_t)data[1])<<8); +} + +uint32_t dataToUint32(QByteArray data) +{ + return ((uint32_t)(uint8_t)data[0]) + +(((uint32_t)(uint8_t)data[1])<<8) + +(((uint32_t)(uint8_t)data[2])<<16) + +(((uint32_t)(uint8_t)data[3])<<24); +} + +uint64_t dataToUint64(QByteArray data) +{ + return ((uint64_t)(uint8_t)data[0]) + +(((uint64_t)(uint8_t)data[1])<<8) + +(((uint64_t)(uint8_t)data[2])<<16) + +(((uint64_t)(uint8_t)data[3])<<24) + +(((uint64_t)(uint8_t)data[4])<<32) + +(((uint64_t)(uint8_t)data[5])<<40) + +(((uint64_t)(uint8_t)data[6])<<48) + +(((uint64_t)(uint8_t)data[7])<<56); +} + +unsigned getVUint32Size(QByteArray data) +{ + unsigned lensize=0; + { + unsigned char num3; + do { + num3 = data[lensize]; + lensize++; + } while ((num3 & 0x80) != 0); + } + return lensize; +} + +QByteArray uint8ToData(uint8_t num) +{ + QByteArray data(1,0); + data[0] = (uint8_t)num; + return data; +} + +QByteArray uint16ToData(uint16_t num) +{ + QByteArray data(2,0); + data[0] = (uint8_t)(num & 0xFF); + data[1] = (uint8_t)((num>>8) & 0xFF); + return data; +} + +QByteArray uint32ToData(uint32_t num) +{ + QByteArray data(4,0); + data[0] = (uint8_t)(num & 0xFF); + data[1] = (uint8_t)((num>>8) & 0xFF); + data[2] = (uint8_t)((num>>16) & 0xFF); + data[3] = (uint8_t)((num>>24) & 0xFF); + return data; +} + +QByteArray uint64ToData(uint64_t num) +{ + QByteArray data(8,0); + data[0] = (uint8_t)(num & 0xFF); + data[1] = (uint8_t)((num>>8) & 0xFF); + data[2] = (uint8_t)((num>>16) & 0xFF); + data[3] = (uint8_t)((num>>24) & 0xFF); + data[4] = (uint8_t)((num>>32) & 0xFF); + data[5] = (uint8_t)((num>>40) & 0xFF); + data[6] = (uint8_t)((num>>48) & 0xFF); + data[7] = (uint8_t)((num>>56) & 0xFF); + return data; +} diff --git a/tools/update-server/qtox-updater-genflist/serialize.h b/tools/update-server/qtox-updater-genflist/serialize.h new file mode 100644 index 000000000..54747fe68 --- /dev/null +++ b/tools/update-server/qtox-updater-genflist/serialize.h @@ -0,0 +1,45 @@ +/* + Copyright (C) 2014 by Project Tox + + This file is part of qTox, a Qt-based graphical interface for Tox. + + This program is libre 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 COPYING file for more details. +*/ + + +#ifndef SERIALIZE_H +#define SERIALIZE_H + +#include +#include +#include + +/// Most of those functions are unsafe unless otherwise specified +/// Do not use them on untrusted data (e.g. check a signature first) + +QByteArray doubleToData(double num); +QByteArray floatToData(float num); +float dataToFloat(QByteArray data); +QByteArray stringToData(QString str); +QString dataToString(QByteArray data); +float dataToRangedSingle(float min, float max, int numberOfBits, QByteArray data); +QByteArray rangedSingleToData(float value, float min, float max, int numberOfBits); +uint8_t dataToUint8(QByteArray data); +uint16_t dataToUint16(QByteArray data); +uint32_t dataToUint32(QByteArray data); +uint64_t dataToUint64(QByteArray data); +unsigned getVUint32Size(QByteArray data); +QByteArray uint8ToData(uint8_t num); +QByteArray uint16ToData(uint16_t num); +QByteArray uint32ToData(uint32_t num); +QByteArray uint64ToData(uint64_t num); + +#endif // SERIALIZE_H diff --git a/tools/update-server/qtox-updater-sign/main.cpp b/tools/update-server/qtox-updater-sign/main.cpp new file mode 100644 index 000000000..21a0ef535 --- /dev/null +++ b/tools/update-server/qtox-updater-sign/main.cpp @@ -0,0 +1,43 @@ +#include +#include +#include + +using namespace std; + +int main(int argc, char* argv[]) +{ + QFile io; + QByteArray msg; + if (argc > 1) + { + msg = QByteArray(argv[1]); + } + else + { + io.open(stdin, QIODevice::ReadOnly); + msg = io.readAll(); + io.close(); + } + io.open(stdout, QIODevice::WriteOnly); + + QFile skeyFile("qtox-updater-skey"); + if (!skeyFile.open(QIODevice::ReadOnly)) + { + io.write("ERROR: qtox-updater-sign can't open the secret (private) key file\n"); + io.close(); + return 1; + } + QByteArray skeyData = skeyFile.readAll(); + skeyData = QByteArray::fromHex(skeyData); + skeyFile.close(); + + unsigned char sig[crypto_sign_BYTES]; + crypto_sign_detached(sig, nullptr, (unsigned char*)msg.data(), msg.size(), (unsigned char*)skeyData.data()); + + io.write((char*)sig, crypto_sign_BYTES); + io.write(msg); + io.close(); + + return 0; +} + diff --git a/tools/update-server/qtox-updater-sign/qtox-updater-sign.pro b/tools/update-server/qtox-updater-sign/qtox-updater-sign.pro new file mode 100644 index 000000000..5f9c65af3 --- /dev/null +++ b/tools/update-server/qtox-updater-sign/qtox-updater-sign.pro @@ -0,0 +1,7 @@ +TEMPLATE = app +CONFIG += console c++11 +QT += core + +SOURCES += main.cpp + +LIBS += -lsodium