Commit 2277a750 authored by Pawel Polanski's avatar Pawel Polanski
Browse files

Certificate validation added to Symbian's signing process

Reviewed-by: Tobias Hunger
parent 52d18e7e
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "certificatepathchooser.h"
#include <QMessageBox>
#include "s60certificateinfo.h"
CertificatePathChooser::CertificatePathChooser(QWidget *parent) :
Utils::PathChooser(parent)
{
}
bool CertificatePathChooser::validatePath(const QString &path, QString *errorMessage)
{
if (Utils::PathChooser::validatePath(path, errorMessage))
return S60CertificateInfo::validateCertificate(path, errorMessage) == S60CertificateInfo::CertificateValid;
return false;
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef CERTIFICATEPATHCHOOSER_H
#define CERTIFICATEPATHCHOOSER_H
#include "utils/pathchooser.h"
class CertificatePathChooser : public Utils::PathChooser
{
Q_DISABLE_COPY(CertificatePathChooser)
Q_OBJECT
public:
explicit CertificatePathChooser(QWidget *parent = 0);
virtual bool validatePath(const QString &path, QString *errorMessage = 0);
};
#endif // CERTIFICATEPATHCHOOSER_H
......@@ -21,7 +21,9 @@ SOURCES += $$PWD/s60devices.cpp \
$$PWD/s60createpackageparser.cpp \
$$PWD/passphraseforkeydialog.cpp \
$$PWD/s60deployconfiguration.cpp \
$$PWD/s60deployconfigurationwidget.cpp
$$PWD/s60deployconfigurationwidget.cpp \
$$PWD/s60certificateinfo.cpp \
$$PWD/certificatepathchooser.cpp
HEADERS += $$PWD/s60devices.h \
$$PWD/s60devicespreferencepane.h \
$$PWD/s60manager.h \
......@@ -42,6 +44,8 @@ HEADERS += $$PWD/s60devices.h \
$$PWD/s60createpackageparser.h \
$$PWD/passphraseforkeydialog.h \
$$PWD/s60deployconfiguration.h \
$$PWD/s60deployconfigurationwidget.h
$$PWD/s60deployconfigurationwidget.h \
$$PWD/s60certificateinfo.h \
$$PWD/certificatepathchooser.h
FORMS += $$PWD/s60devicespreferencepane.ui \
$$PWD/s60createpackagestep.ui
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#include "s60certificateinfo.h"
#include <QDateTime>
#include <QFileInfo>
#include <QCoreApplication>
#include <botan/x509cert.h>
S60CertificateInfo::CertificateState S60CertificateInfo::validateCertificate(const QString &certFilePath, QString *errorString)
{
bool certFileCorrupted = false;
CertificateState result = CertificateValid;
Botan::X509_Certificate *certificate = 0;
try {
certificate = new Botan::X509_Certificate(certFilePath.toStdString());
if (certificate) {
const char * const CERTIFICATE_DATE_FORMAT = "yyyy/M/d h:mm:ss UTC";
QDateTime startTime = QDateTime::fromString(QString::fromStdString(certificate->start_time()),
QLatin1String(CERTIFICATE_DATE_FORMAT));
QDateTime startTimeUTC(startTime.date(), startTime.time(), Qt::UTC);
QDateTime endTime = QDateTime::fromString(QString::fromStdString(certificate->end_time()),
QLatin1String(CERTIFICATE_DATE_FORMAT));
QDateTime endTimeUTC(endTime.date(), endTime.time(), Qt::UTC);
QDateTime currentTime(QDateTime::currentDateTimeUtc());
if (currentTime > endTimeUTC) {
if (errorString)
*errorString = QCoreApplication::translate(
"S60Utils::validateCertificate",
"The \"%1\" certificate has already expired and cannot be used.\nExpiration date: %2.")
.arg(QFileInfo(certFilePath).fileName())
.arg(endTimeUTC.toLocalTime().toString());
result = CertificateError;
} else if (currentTime < startTimeUTC) {
if (errorString)
*errorString = QCoreApplication::translate(
"S60Utils::validateCertificate",
"The \"%1\" certificate is not yet valid.\nValid from: %2.")
.arg(QFileInfo(certFilePath).fileName())
.arg(startTimeUTC.toLocalTime().toString());
result = CertificateWarning; //This certificate may be valid in the near future
}
} else
certFileCorrupted = true;
} catch (Botan::Exception &e) {
Q_UNUSED(e)
certFileCorrupted = true;
}
delete certificate;
if (certFileCorrupted) {
if (errorString)
*errorString = QCoreApplication::translate(
"S60Utils::validateCertificate",
"The \"%1\" certificate is not a valid X.509 certificate.")
.arg(QFileInfo(certFilePath).baseName());
result = CertificateError;
}
return result;
}
/**************************************************************************
**
** This file is part of Qt Creator
**
** Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies).
**
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** Commercial Usage
**
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
**
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file. Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** If you are unsure which license is appropriate for your use, please
** contact the sales department at http://qt.nokia.com/contact.
**
**************************************************************************/
#ifndef S60CERTIFICATEINFO_H
#define S60CERTIFICATEINFO_H
class S60CertificateInfo
{
public:
enum CertificateState {
CertificateValid,
CertificateWarning,
CertificateError
};
static CertificateState validateCertificate(const QString &certFilePath, QString *errorString = 0);
};
#endif // S60CERTIFICATEINFO_H
......@@ -37,6 +37,7 @@
#include "abldparser.h"
#include "sbsv2parser.h"
#include "passphraseforkeydialog.h"
#include "s60certificateinfo.h"
#include <coreplugin/coreconstants.h>
......@@ -191,6 +192,9 @@ bool S60CreatePackageStep::init()
m_makeCmd = tmp;
}
if (signingMode() == SignCustom && !validateCustomSigningResources())
return false;
m_environment = qt4BuildConfiguration()->environment();
m_cancel = false;
......@@ -352,22 +356,6 @@ void S60CreatePackageStep::run(QFutureInterface<bool> &fi)
bool S60CreatePackageStep::createOnePackage()
{
// Setup everything...
Q_ASSERT(!m_process);
m_process = new QProcess();
m_process->setEnvironment(m_environment.toStringList());
connect(m_process, SIGNAL(readyReadStandardOutput()),
this, SLOT(processReadyReadStdOutput()),
Qt::DirectConnection);
connect(m_process, SIGNAL(readyReadStandardError()),
this, SLOT(processReadyReadStdError()),
Qt::DirectConnection);
connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(packageDone(int, QProcess::ExitStatus)),
Qt::DirectConnection);
// Setup arguments:
m_args.clear();
if (m_createSmartInstaller) {
......@@ -380,9 +368,7 @@ bool S60CreatePackageStep::createOnePackage()
else
m_args << QLatin1String("sis");
if (signingMode() == SignCustom
&& !customSignaturePath().isEmpty() && QFileInfo(customSignaturePath()).exists()
&& !customKeyPath().isEmpty() && QFileInfo(customKeyPath()).exists()) {
if (signingMode() == SignCustom) {
m_args << QLatin1String(MAKE_CERTIFICATE_ARGUMENT) + QDir::toNativeSeparators(customSignaturePath())
<< QLatin1String(MAKE_KEY_ARGUMENT) + QDir::toNativeSeparators(customKeyPath());
......@@ -398,6 +384,23 @@ bool S60CreatePackageStep::createOnePackage()
if (!wd.exists())
wd.mkpath(wd.absolutePath());
// Setup process...
Q_ASSERT(!m_process);
m_process = new QProcess();
m_process->setEnvironment(m_environment.toStringList());
connect(m_process, SIGNAL(readyReadStandardOutput()),
this, SLOT(processReadyReadStdOutput()),
Qt::DirectConnection);
connect(m_process, SIGNAL(readyReadStandardError()),
this, SLOT(processReadyReadStdError()),
Qt::DirectConnection);
connect(m_process, SIGNAL(finished(int, QProcess::ExitStatus)),
this, SLOT(packageDone(int, QProcess::ExitStatus)),
Qt::DirectConnection);
m_process->setWorkingDirectory(wd.absolutePath());
// Setup parsers:
......@@ -437,6 +440,58 @@ bool S60CreatePackageStep::createOnePackage()
return true;
}
bool S60CreatePackageStep::validateCustomSigningResources()
{
Q_ASSERT(signingMode() == SignCustom);
QString errorString;
if (customSignaturePath().isEmpty())
errorString = tr("Certificate file has not heen defined. "
"Please define certificate file in the project's options.");
else if (!QFileInfo(customSignaturePath()).exists())
errorString = tr("Certificate file \"%1\" does not exist. "
"Please define certificate file in the project's options.").arg(customSignaturePath());
if (customKeyPath().isEmpty())
errorString = tr("Key file has not heen defined. "
"Please define certificate file in the project's options.");
else if (!QFileInfo(customKeyPath()).exists())
errorString = tr("Key file \"%1\" does not exist. "
"Please define certificate file in the project's options.").arg(customKeyPath());
if (!errorString.isEmpty()) {
emit addOutput(errorString, BuildStep::ErrorMessageOutput);
emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error,
errorString,
QString(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
return false;
}
S60CertificateInfo::CertificateState certState = S60CertificateInfo::validateCertificate(customSignaturePath(), &errorString);
switch (certState) {
case S60CertificateInfo::CertificateError:
emit addOutput(errorString, BuildStep::ErrorMessageOutput);
emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Error,
errorString,
QString(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
return false;
case S60CertificateInfo::CertificateWarning:
emit addOutput(errorString, BuildStep::MessageOutput);
emit addTask(ProjectExplorer::Task(ProjectExplorer::Task::Warning,
errorString,
QString(), -1,
ProjectExplorer::Constants::TASK_CATEGORY_BUILDSYSTEM));
break;
default:
break;
}
return true;
}
void S60CreatePackageStep::packageWarningDialogDone()
{
if (m_patchWarningDialog)
......@@ -828,8 +883,13 @@ QString S60CreatePackageStepConfigWidget::summaryText() const
QString text;
switch(m_signStep->signingMode()) {
case S60CreatePackageStep::SignCustom:
text = tr("signed with certificate %1 and key file %2")
.arg(m_signStep->customSignaturePath(), m_signStep->customKeyPath());
if (!m_signStep->customSignaturePath().isEmpty()
&& !m_signStep->customKeyPath().isEmpty())
text = tr("signed with \"%1\" certificate and \"%2\" key file")
.arg(QFileInfo(m_signStep->customSignaturePath()).fileName(),
QFileInfo(m_signStep->customKeyPath()).fileName());
else
text = tr("signed with a certificate and a key that need to be defined");
break;
case S60CreatePackageStep::NotSigned:
text = tr("not signed");
......
......@@ -138,6 +138,7 @@ private:
void setupProcess();
bool createOnePackage();
bool validateCustomSigningResources();
QString generateKeyId(const QString &keyPath) const;
QString loadPassphraseForKey(const QString &keyId);
......
......@@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>517</width>
<height>135</height>
<height>156</height>
</rect>
</property>
<property name="windowTitle">
......@@ -87,9 +87,9 @@
</widget>
</item>
<item row="0" column="1">
<widget class="Utils::PathChooser" name="signaturePath" native="true">
<widget class="CertificatePathChooser" name="signaturePath" native="true">
<property name="promptDialogTitle" stdset="0">
<string>Choose certificate file (.cer)</string>
<string>Choose certificate file</string>
</property>
</widget>
</item>
......@@ -167,6 +167,12 @@
<signal>browsingFinished()</signal>
</slots>
</customwidget>
<customwidget>
<class>CertificatePathChooser</class>
<extends>QWidget</extends>
<header location="global">qt4projectmanager/qt-s60/certificatepathchooser.h</header>
<container>1</container>
</customwidget>
</customwidgets>
<resources/>
<connections/>
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment