diff options
Diffstat (limited to 'src/b2qt-update-application/tar.cpp')
-rw-r--r-- | src/b2qt-update-application/tar.cpp | 309 |
1 files changed, 0 insertions, 309 deletions
diff --git a/src/b2qt-update-application/tar.cpp b/src/b2qt-update-application/tar.cpp deleted file mode 100644 index c0369ff..0000000 --- a/src/b2qt-update-application/tar.cpp +++ /dev/null @@ -1,309 +0,0 @@ -/**************************************************************************** -** -** Copyright (C) 2014 Digia Plc -** All rights reserved. -** For any questions to Digia, please use the contact form at -** http://qt.digia.com/ -** -** This file is part of Qt Enterprise Embedded. -** -** Licensees holding valid Qt Enterprise licenses may use this file in -** accordance with the Qt Enterprise License Agreement provided with the -** Software or, alternatively, in accordance with the terms contained in -** a written agreement between you and Digia. -** -** If you have questions regarding the use of this file, please use -** the contact form at http://qt.digia.com/ -** -****************************************************************************/ - -#include "tar.h" -#include <QProcess> -#include <QDebug> -#include <openssl/x509.h> -#include <openssl/pem.h> - -static bool isZeroed(const char *ptr, unsigned int size) -{ - while (size) { - if (*ptr) { - return false; - } - ++ptr; - --size; - } - return true; -} - -Tar::Tar(QIODevice *source) - : QObject(source) - , mSource(source) - , mSize(0) - , mRemainingSize(0) - , mRemainingFileBytes(0) - , mProcess(0) - , mState(WaitForHeader) - , x509(0) - , mdctx(0) -{ - // Initialize table with all digests in order to look them up by string later - OpenSSL_add_all_digests(); - - connect(source, &QIODevice::readyRead, this, &Tar::dataIncoming); - connect(source, &QIODevice::aboutToClose, this, &Tar::aboutToClose); -} - -Tar::~Tar() -{ - if (x509) - X509_free(x509); - x509 = 0; - if (mdctx) - EVP_MD_CTX_destroy(mdctx); - mdctx = 0; -} - -const QByteArray &Tar::currentContent() const -{ - return mContent; -} - -unsigned long Tar::currentSize() const -{ - return mSize; -} - -QString Tar::currentFileName() const -{ - if (mHeader.name[sizeof(mHeader.name)-1]) - return QString::fromLatin1(mHeader.name, sizeof(mHeader.name)); - else - return QString::fromLatin1(mHeader.name); -} - -void Tar::dataIncoming() -{ - while (mSource->bytesAvailable() > 512) { - - if (mState == WaitForHeader) { - if (mSource->bytesAvailable() < 512) - return; - if (mSource->read((char*)&mHeader, sizeof(mHeader)) != sizeof(mHeader)) - qFatal("Tar read error"); - if (isZeroed((char*)&mHeader, sizeof(mHeader))) { - qDebug() << "Zero Tar block"; - qDebug() << "Bytes left" << mSource->bytesAvailable(); - mSource->close(); - return; - } - if (mHeader.name[0] == 0) - qFatal("Header starts with 0"); - - mSize = QString::fromLatin1(mHeader.size, sizeof(mHeader.size)-1).toULongLong(0, 8); - mRemainingFileBytes = mSize; - mRemainingSize = mSize; - if (mSize % 512) // padding to 512 byte block - mRemainingSize += 512 - (mSize % 512); - - if (mSize == 0) { - qFatal("Size of file is 0"); - } - - mState = WaitForDecision; - qDebug() << "Started file" << currentFileName() << mSize; - if (x509) - setupMDContext(); - emit startingFile(currentFileName()); - } else if (mState == WaitForDecision) { - return; - } else if (mState == Extract) { - QByteArray ba; - - quint64 bytesToHandle = mRemainingSize; - - if (mSource->bytesAvailable() < mRemainingSize) - bytesToHandle = mSource->bytesAvailable(); - if (bytesToHandle > 60000) - bytesToHandle = 60000; - ba = mSource->read(bytesToHandle); - - updateMDContext(ba); - mProcess->write(ba); - mProcess->waitForBytesWritten(); - mRemainingSize -= ba.size(); - // do not return - } else if (mState == Receive) { - QByteArray ba; - - if (mSource->bytesAvailable() > mRemainingSize) - ba = mSource->read(mRemainingSize); - else - ba = mSource->readAll(); - updateMDContext(ba); - mContent += ba; - mRemainingSize -= ba.size(); - if (mContent.size() > mSize) - mContent.resize(mSize); - // do not return - } else if (mState == Skip) { - QByteArray ba; - - if (mSource->bytesAvailable() > mRemainingSize) { - ba = mSource->read(mRemainingSize); - } else { - ba = mSource->readAll(); - } - updateMDContext(ba); - mRemainingSize -= ba.size(); - // drop data - // do not return - } else if (mState == WaitForContinue) { - return; - } else { - qFatal("Unknown tar state"); - } - - if (mState != WaitForContinue && mState != WaitForHeader && mRemainingSize == 0) { - if (mState == Extract) { - qDebug() << "End tar process"; - // please tar - // it needs 2 zeroed blocks - char buffer[sizeof(mHeader)]; - memset(buffer, 0, sizeof(buffer)); - mProcess->write(buffer, sizeof(buffer)); - mProcess->write(buffer, sizeof(buffer)); - mProcess->waitForBytesWritten(); - mProcess->closeWriteChannel(); - mProcess->waitForFinished(-1); - mProcess->deleteLater(); - mProcess = 0; - } - mState = WaitForContinue; - - emit(endingFile(currentFileName())); - } - - } -} - -void Tar::extractContent(const QString &targetDir) -{ - if (mState == WaitForDecision) { - qDebug() << Q_FUNC_INFO; - mState = Extract; - delete mProcess; - mProcess = new QProcess(this); - mProcess->setProcessChannelMode(QProcess::ForwardedChannels); - mProcess->start("tar", QStringList() << "xvf" << "-" << "-C" << targetDir); - - // if we want to extract a file directly, the header needs to be passed to tar - if (!currentFileName().endsWith(".tar")) - mProcess->write((const char*)&mHeader, sizeof(mHeader)); - } -} - -void Tar::receiveContent() -{ - if (mState == WaitForDecision) - mState = Receive; -} - -void Tar::skipContent() -{ - if (mState == WaitForDecision) - mState = Skip; -} - -void Tar::continueContent() -{ - if (mState == WaitForContinue) { - mState = WaitForHeader; - mSize = 0; - mContent.clear(); - delete mProcess; - mProcess = 0; - } else - qDebug() << "Called" << Q_FUNC_INFO << "in wrong state"; -} - -void Tar::aboutToClose() -{ - if (mState != WaitForHeader) { - qWarning() << "unexpected close"; - } - emit finished(); -} - -bool Tar::setVerificationData(const QString &certificateFileName, const QString &mdType) -{ - if (x509) - qFatal("Setting key twice"); - - // Load key from file - BIO *i = BIO_new(BIO_s_file()); - BIO *o = BIO_new_fp(stdout,BIO_NOCLOSE); - - if ((BIO_read_filename(i, certificateFileName.toLatin1().constData()) <= 0) || - ((x509 = PEM_read_bio_X509_AUX(i, NULL, NULL, NULL)) == NULL)) { - qWarning() << "Invalid certificate, failed to read file" << certificateFileName; - return false; - } - // Showing used certificate - X509_print_ex(o, x509, XN_FLAG_COMPAT, X509_FLAG_COMPAT); - BIO_free(i); - BIO_free(o); - qDebug() << "Using verification key:" << certificateFileName; - - md = EVP_get_digestbyname(mdType.toLatin1().constData()); - if (md == NULL) - qFatal("Digest not found"); - return true; -} - -void Tar::setupMDContext() -{ - if (mdctx) - EVP_MD_CTX_destroy(mdctx); - if (!(mdctx = EVP_MD_CTX_create())) - qFatal("EVP_MD_CTX_create failed"); - - EVP_PKEY *key = X509_get_pubkey(x509); - if (key == NULL) { - qFatal("X509_get_pubkey failed"); - } - - if (md == NULL) - qFatal("No digest set"); - - if (1 != EVP_DigestVerifyInit(mdctx, NULL, md, NULL, key)) - qFatal("EVP_DigestVerifyInit failed"); -} - -void Tar::updateMDContext(QByteArray data) -{ - if (mRemainingFileBytes == 0) - qFatal("Trying to update MD context when no more bytes are expected"); - - if (mRemainingFileBytes < data.size()) - data = data.left(mRemainingFileBytes); - mRemainingFileBytes -= data.size(); - - if (!mdctx) - return; - - if (1 != EVP_DigestVerifyUpdate(mdctx, data.constData(), data.size())) - qFatal("EVP_DigestVerifyUpdate failed"); -} - -bool Tar::checkSignature(const QByteArray &signature) -{ - return 1 == EVP_DigestVerifyFinal(mdctx, (unsigned char*)signature.constData(), signature.size()); -} - -bool Tar::verifyCurrentContent(const QByteArray &signature) -{ - setupMDContext(); - if (1 != EVP_DigestVerifyUpdate(mdctx, mContent.constData(), mContent.size())) - qFatal("EVP_DigestVerifyUpdate failed"); - return checkSignature(signature); -} |