Mercurial > trustbridge
view ui/createcertlistdialog.cpp @ 851:5a4fc27db446
Merge
author | Emanuel Schuetze <emanuel@intevation.de> |
---|---|
date | Wed, 30 Jul 2014 17:00:03 +0200 |
parents | 75cd2fbf9ac6 |
children | bd2cb6bdb1c5 |
line wrap: on
line source
/* Copyright (C) 2014 by Bundesamt für Sicherheit in der Informationstechnik * Software engineering by Intevation GmbH * * This file is Free Software under the GNU GPL (v>=2) * and comes with ABSOLUTELY NO WARRANTY! * See LICENSE.txt for details. */ #include "createcertlistdialog.h" #include "sslhelp.h" #include "administratorwindow.h" #include <QDebug> #include <QMessageBox> #include <QDir> #include <QPushButton> #include <QGroupBox> #include <QHBoxLayout> #include <QVBoxLayout> #include <QLabel> #include <QFileDialog> #include <QStandardPaths> #include <polarssl/pk.h> CreateCertListDialog::CreateCertListDialog(AdministratorWindow *parent) : QDialog(parent), mAdminWindow(parent), mPk(NULL) { setWindowTitle(tr("Save certificate list")); setupGUI(); resize(500, 200); mKeyFile->setText(mAdminWindow->settings()->value("LastKey", QString()).toString()); mSaveDir->setText(mAdminWindow->settings()->value("LastOutputDir", QString()).toString()); if (!mKeyFile->text().isEmpty()) { loadKeyFile(mKeyFile->text()); } } void CreateCertListDialog::setupGUI() { /* Top level layout / widgets */ QVBoxLayout *topLayout = new QVBoxLayout; QVBoxLayout *headerLayout = new QVBoxLayout; QHBoxLayout *headerSubLayout = new QHBoxLayout; QHBoxLayout *centerLayout = new QHBoxLayout; QHBoxLayout *bottomLayout = new QHBoxLayout; QVBoxLayout *labelLayout = new QVBoxLayout; QVBoxLayout *fieldLayout = new QVBoxLayout; QVBoxLayout *buttonLayout = new QVBoxLayout; QLabel *header = new QLabel("<h3>" + tr("Save certificate list") + "</h3>"); QLabel *description = new QLabel( tr("Save all managed root certificates in a new, signed certificate list.")); headerSubLayout->insertSpacing(0, 40); headerSubLayout->addWidget(description); QFrame *headerSeparator = new QFrame(); headerSeparator->setFrameShape(QFrame::HLine); headerSeparator->setFrameShadow(QFrame::Sunken); headerLayout->addWidget(header); headerLayout->addLayout(headerSubLayout); headerLayout->addWidget(headerSeparator); headerLayout->insertSpacing(3, 10); QLabel *certLabel = new QLabel(tr("Select signing key:")); QLabel *saveLabel = new QLabel(tr("Select output folder:")); labelLayout->addWidget(certLabel); labelLayout->addWidget(saveLabel); mKeyFile = new QLineEdit(); mSaveDir = new QLineEdit(); fieldLayout->addWidget(mKeyFile); fieldLayout->addWidget(mSaveDir); QPushButton *certSelect = new QPushButton("..."); certSelect->setFixedWidth(30); connect(certSelect, SIGNAL(clicked()), this, SLOT(openCertificateSelect())); QPushButton *saveSelect = new QPushButton("..."); connect(saveSelect, SIGNAL(clicked()), this, SLOT(openSaveLocation())); saveSelect->setFixedWidth(30); buttonLayout->addWidget(certSelect); buttonLayout->addWidget(saveSelect); QString footerText = tr("In addition, each certificate list will be saved " "automatically in the archive directory:\n"); footerText.append(QStandardPaths::writableLocation( QStandardPaths::DataLocation)); QLabel *footer = new QLabel(footerText); centerLayout->addLayout(labelLayout); centerLayout->addLayout(fieldLayout); centerLayout->addLayout(buttonLayout); QPushButton *create = new QPushButton(tr("Save list")); connect(create, SIGNAL(clicked()), this, SLOT(createList())); QPushButton *cancel = new QPushButton(tr("Cancel")); connect(cancel, SIGNAL(clicked()), this, SLOT(close())); bottomLayout->insertStretch(0, 10); bottomLayout->addWidget(create); bottomLayout->addWidget(cancel); QFrame *bottomSeparator = new QFrame(); bottomSeparator->setFrameShape(QFrame::HLine); bottomSeparator->setFrameShadow(QFrame::Sunken); topLayout->addLayout(headerLayout); topLayout->addLayout(centerLayout); topLayout->insertStretch(2, 10); topLayout->addWidget(footer); topLayout->insertSpacing(4, 10); topLayout->addWidget(bottomSeparator); topLayout->addLayout(bottomLayout); setLayout(topLayout); return; } void CreateCertListDialog::showErrorMessage(const QString &msg) { QMessageBox::warning(this, tr("Error!"), msg); } void CreateCertListDialog::loadKeyFile(const QString& fileName) { if (mPk != NULL) { pk_free(mPk); delete mPk; mPk = NULL; } mPk = new pk_context; pk_init(mPk); int ret = pk_parse_keyfile(mPk, mKeyFile->text().toLocal8Bit().constData(), ""); if (ret != 0) { showErrorMessage(tr("Failed to load certificate: %1") .arg(getPolarSSLErrorMsg(ret))); pk_free(mPk); delete mPk; mPk = NULL; return; } /* Check that it is a 3072 bit RSA key as specified */ if (!mPk->pk_info || pk_get_size(mPk) != 3072 || mPk->pk_info->type != POLARSSL_PK_RSA) { showErrorMessage(tr("Only 3072 bit RSA keys are supported by the current format.")); pk_free(mPk); delete mPk; mPk = NULL; return; } } void CreateCertListDialog::openCertificateSelect() { QString keyFile = QFileDialog::getOpenFileName( this, tr("Select certificate"), mKeyFile->text().isEmpty() ? QDir::homePath() : mKeyFile->text(), "*.pem"); mKeyFile->setText(keyFile); mAdminWindow->settings()->setValue("LastKey", keyFile); loadKeyFile(keyFile); return; } void CreateCertListDialog::openSaveLocation() { QString saveDir = QFileDialog::getExistingDirectory( this, tr("Select target location"), mSaveDir->text().isEmpty() ? QDir::homePath() : mSaveDir->text()); mAdminWindow->settings()->setValue("LastOutputDir", saveDir); mSaveDir->setText(saveDir); } CreateCertListDialog::~CreateCertListDialog() { if (mPk) { pk_free(mPk); delete mPk; mPk = NULL; } } bool CreateCertListDialog::writeList(const QList<Certificate>& certs, const QString& filePath, const QDateTime& listDate, pk_context *pk) { /* Build up the list data */ QByteArray listData("F:1\r\nD:"); listData.append(listDate.toString(Qt::ISODate) + "\r\n"); foreach (const Certificate& cert, certs) { listData.append(cert.base64Line() + "\r\n"); } QByteArray signature = rsaSignSHA256Hash(sha256sum(listData), pk); if (signature.size() != 3072 / 8) { qDebug() << "Signature creation returned signature of invalid size."; return false; } listData.prepend("\r\n"); listData.prepend(signature.toBase64()); listData.prepend("S:"); QFile outputFile(filePath); if (!outputFile.open(QIODevice::WriteOnly)) { qDebug() << "Failed to open output file: " << filePath; return false; } if (outputFile.write(listData) != listData.size()) { qDebug() << "Failed to write list: " << filePath; outputFile.close(); return false; } outputFile.close(); return true; } void CreateCertListDialog::createList() { if (!mPk) { showErrorMessage(tr("Please select a valid rsa key.")); } if (mSaveDir->text().isEmpty()) { showErrorMessage(tr("Please select an output location first.")); } QDateTime currentDateTimeUtc = QDateTime::currentDateTimeUtc(); QString fileName = QString::fromLatin1("certificates-") .append(currentDateTimeUtc.toString(("yyyyMMddHHmmss"))) .append(".txt"); QString filePath = mSaveDir->text().append("/").append(fileName); if (!writeList(mAdminWindow->certificates(), filePath, currentDateTimeUtc, mPk)) { showErrorMessage(tr("Failed to write list to: %1").arg(filePath)); } QFile outputFile(filePath); /* Archive the list */ QDir archiveDir(QStandardPaths::writableLocation(QStandardPaths::DataLocation)); if (!archiveDir.mkpath(archiveDir.path())) { showErrorMessage(tr("Failed to create archive location.")); return; } if (!outputFile.copy(archiveDir.filePath(fileName))) { showErrorMessage(tr("Failed Archive a copy.")); return; } QString curCerts = archiveDir.filePath("current_certificates.txt"); if (QFile::exists(curCerts)) { if (!QFile::remove(curCerts)) { showErrorMessage(tr("Failed to update current_certificates.txt")); return; } } if (!outputFile.copy(curCerts)) { showErrorMessage(tr("Failed to write current_certificates file.")); return; } QString keyFingerprint; { /* Calculate sha256 sum of the der key */ unsigned char output_buf[16000]; /* Buf size taken from examples */ int ret; ret = pk_write_key_der (mPk, output_buf, 16000); if (ret <= 0) { showErrorMessage(tr("Failed to calculate key hash.")); return; } QByteArray derKey((const char*)output_buf, ret); QByteArray fp = sha256sum(derKey); for (int i=0; i < fp.size(); i++) { keyFingerprint += QString("%1").arg( (unsigned char)(fp[i]), 0, 16).rightJustified(2, '0'); if (i != fp.size() - 1) { keyFingerprint += ":"; } } keyFingerprint = keyFingerprint.toUpper(); } mAdminWindow->logChanges(curCerts, keyFingerprint); QMessageBox::information(this, "", tr("Saved certificate list:\n%1").arg(fileName)); close(); }