Skip to content
Snippets Groups Projects
Commit 8048964e authored by Emmanuel Lepage Vallee's avatar Emmanuel Lepage Vallee
Browse files

securityeval: Keep an up to date SecurityLevel

There is still a few bugs left, but the infrastructure is complete

Refs #69834
parent 6359b98b
No related branches found
No related tags found
No related merge requests found
......@@ -1753,9 +1753,6 @@ void AccountPrivate::outdate() {
void AccountPrivate::regenSecurityValidation()
{
if (m_pSecurityValidationModel) {
m_pSecurityValidationModel->setTlsCaListCertificate(q_ptr->tlsCaListCertificate());
m_pSecurityValidationModel->setTlsCertificate(q_ptr->tlsCertificate());
m_pSecurityValidationModel->setTlsPrivateKeyCertificate(q_ptr->tlsPrivateKeyCertificate());
m_pSecurityValidationModel->d_ptr->update();
}
}
......
......@@ -568,12 +568,12 @@ bool ContactMethod::operator==(const ContactMethod* other) const
bool ContactMethod::operator==(ContactMethod& other)
{
return &other && this->d_ptr== other.d_ptr;
return this->d_ptr== other.d_ptr;
}
bool ContactMethod::operator==(const ContactMethod& other) const
{
return &other && this->d_ptr== other.d_ptr;
return this->d_ptr== other.d_ptr;
}
/************************************************************************************
......
......@@ -534,7 +534,7 @@ bool Person::operator==(const Person* other) const
bool Person::operator==(const Person& other) const
{
return &other && this->d_ptr == other.d_ptr;
return this->d_ptr == other.d_ptr;
}
///Add a new address to this contact
......
......@@ -35,9 +35,8 @@ public:
SecurityValidationModel::SecurityLevel m_CurrentSecurityLevel;
Account* m_pAccount ;
QHash< int, QHash< int, SecurityFlaw* > > m_hFlaws;
Certificate* m_pCa;
Certificate* m_pCert;
Certificate* m_pPrivateKey;
bool m_isScheduled;
int m_SeverityCount[enum_class_size<SecurityValidationModel::Severity>()];
///Messages to show to the end user
......@@ -54,6 +53,7 @@ public:
public Q_SLOTS:
void update();
void updateReal();
};
......
/****************************************************************************
* Copyright (C) 2013-2015 by Savoir-Faire Linux *
* Copyright (C) 2013-2015 by Savoir-Faire Linux *
* Author : Emmanuel Lepage Vallee <emmanuel.lepage@savoirfairelinux.com> *
* *
* This library is free software; you can redistribute it and/or *
......@@ -19,6 +19,7 @@
//Qt
#include <QtCore/QIdentityProxyModel>
#include <QtCore/QTimer>
//Ring
#include "account.h"
......@@ -196,29 +197,30 @@ public:
virtual QHash<int,QByteArray> roleNames() const override;
private:
//Attributes
QVector<QAbstractItemModel*> m_lSources;
//All source model, in order
///All source model, in order
enum Src {
CA = 0,
PK = 1,
AC = 2,
ER = 3, //TODO
CA = 0, /*!< Rows allocated for the certificate authority */
PK = 1, /*!< Rows allocated for the public certificate */
AC = 2, /*!< Rows allocated for the account settions */
ER = 3, /*!< TODO Rows allocated for runtime error */
};
//This model expect a certain size, get each sections size
///This model expect a certain size, get each sections size
constexpr static const short sizes[] = {
enum_class_size< Certificate :: Checks > (),
enum_class_size< Certificate :: Checks > (),
enum_class_size< SecurityValidationModel :: AccountSecurityFlaw > (),
};
//Get the combined size
///Get the combined size
constexpr inline static int totalSize() {
return sizes[CA] + sizes[PK] + sizes[AC];
}
//Get a modex index from a value
///Get a modex index from a value
constexpr inline static int toModelIdx(const int value) {
return (value >= sizes[CA] + sizes[PK] ? AC : (
value >= sizes[PK] ? PK :
......@@ -234,15 +236,37 @@ private:
};
constexpr const short CombinaisonProxyModel::sizes[];
///Create a callback map for signals to avoid a large switch(){} in the code
static const Matrix1D<SecurityValidationModel::Severity, void(SecurityValidationModel::*)()> m_lSignalMap = {{
/* UNSUPPORTED */ nullptr ,
/* INFORMATION */ &SecurityValidationModel::informationCountChanged ,
/* WARN1NG */ &SecurityValidationModel::warningCountChanged ,
/* ISSUE */ &SecurityValidationModel::issueCountChanged ,
/* ERROR */ &SecurityValidationModel::errorCountChanged ,
/* FATAL_WARNING */ &SecurityValidationModel::fatalWarningCountChanged,
}};
SecurityValidationModelPrivate::SecurityValidationModelPrivate(Account* account, SecurityValidationModel* parent) :
QObject(parent),q_ptr(parent), m_pAccount(account),
m_CurrentSecurityLevel(SecurityValidationModel::SecurityLevel::NONE)
QObject(parent),q_ptr(parent), m_pAccount(account),m_isScheduled(false),
m_CurrentSecurityLevel(SecurityValidationModel::SecurityLevel::NONE),
m_SeverityCount{
/* UNSUPPORTED */ 0,
/* INFORMATION */ 0,
/* WARN1NG */ 0,
/* ISSUE */ 0,
/* ERROR */ 0,
/* FATAL_WARNING */ 0,
}
{
QObject::connect(parent,&SecurityValidationModel::layoutChanged,this,&SecurityValidationModelPrivate::update);
QObject::connect(parent,&SecurityValidationModel::dataChanged ,this,&SecurityValidationModelPrivate::update);
QObject::connect(parent,&SecurityValidationModel::rowsInserted ,this,&SecurityValidationModelPrivate::update);
QObject::connect(parent,&SecurityValidationModel::rowsRemoved ,this,&SecurityValidationModelPrivate::update);
QObject::connect(parent,&SecurityValidationModel::modelReset ,this,&SecurityValidationModelPrivate::update);
//Make sure the security level is updated if something change
QObject::connect(parent,&SecurityValidationModel::layoutChanged , this,&SecurityValidationModelPrivate::update);
QObject::connect(parent,&SecurityValidationModel::dataChanged , this,&SecurityValidationModelPrivate::update);
QObject::connect(parent,&SecurityValidationModel::rowsInserted , this,&SecurityValidationModelPrivate::update);
QObject::connect(parent,&SecurityValidationModel::rowsRemoved , this,&SecurityValidationModelPrivate::update);
QObject::connect(parent,&SecurityValidationModel::modelReset , this,&SecurityValidationModelPrivate::update);
update();
}
......@@ -527,12 +551,6 @@ d_ptr(new SecurityValidationModelPrivate(account,this))
Certificate* caCert = d_ptr->m_pAccount->tlsCaListCertificate ();
Certificate* pkCert = d_ptr->m_pAccount->tlsCertificate ();
if (account) {
d_ptr->m_pCa = caCert ;
d_ptr->m_pCert = pkCert ;
d_ptr->m_pPrivateKey = d_ptr->m_pAccount->tlsPrivateKeyCertificate();
}
PrefixAndSeverityProxyModel* caProxy = caCert ? new PrefixAndSeverityProxyModel(tr("Authority" ),caCert->checksModel()) : nullptr;
PrefixAndSeverityProxyModel* pkProxy = pkCert ? new PrefixAndSeverityProxyModel(tr("Public key"),pkCert->checksModel()) : nullptr;
AccountChecksModel* accChecks = new AccountChecksModel(account);
......@@ -568,7 +586,67 @@ QHash<int,QByteArray> SecurityValidationModel::roleNames() const
void SecurityValidationModelPrivate::update()
{
//TODO
//As this can be called multiple time, only perform the checks once per event loop cycle
if (!m_isScheduled) {
#if QT_VERSION >= 0x050400
QTimer::singleShot(0,this,&SecurityValidationModelPrivate::updateReal);
m_isScheduled = true;
#else //Too bad for 5.3 users
updateReal();
#endif
}
}
void SecurityValidationModelPrivate::updateReal()
{
typedef SecurityValidationModel::Severity Severity ;
typedef SecurityValidationModel::SecurityLevel SecurityLevel;
int countCache[enum_class_size<SecurityValidationModel::Severity>()];
//Reset the counter
for (const Severity s : EnumIterator<Severity>()) {
countCache [(int)s] = m_SeverityCount[(int)s];
m_SeverityCount[(int)s] = 0 ;
}
SecurityLevel maxLevel = SecurityLevel::COMPLETE;
for (int i=0; i < q_ptr->rowCount();i++) {
const QModelIndex& idx = q_ptr->index(i,0);
const Severity severity = qvariant_cast<Severity>(
idx.data((int) SecurityValidationModel::Role::Severity)
);
const SecurityLevel level = qvariant_cast<SecurityLevel>(
idx.data((int) SecurityValidationModel::Role::SecurityLevel )
);
//Increment the count
m_SeverityCount[static_cast<int>(severity)]++;
//Update the maximum level
maxLevel = level < maxLevel ? level : maxLevel;
}
//Notify
for (const Severity s : EnumIterator<Severity>()) {
if (countCache[(int)s] != m_SeverityCount[(int)s] && m_lSignalMap[s])
(q_ptr->*m_lSignalMap[s])();
}
//Update the security level
if (m_CurrentSecurityLevel != maxLevel) {
emit q_ptr->securityLevelChanged();
m_CurrentSecurityLevel = maxLevel;
}
m_isScheduled = false;
}
QModelIndex SecurityValidationModel::getIndex(const SecurityFlaw* flaw)
......@@ -581,19 +659,21 @@ QList<SecurityFlaw*> SecurityValidationModel::currentFlaws()
return d_ptr->m_lCurrentFlaws;
}
void SecurityValidationModel::setTlsCaListCertificate( Certificate* cert )
SecurityValidationModel::SecurityLevel SecurityValidationModel::securityLevel() const
{
d_ptr->m_pCa = cert;
return d_ptr->m_CurrentSecurityLevel;
}
void SecurityValidationModel::setTlsCertificate( Certificate* cert )
{
d_ptr->m_pCert = cert;
}
void SecurityValidationModel::setTlsPrivateKeyCertificate( Certificate* cert )
{
d_ptr->m_pPrivateKey = cert;
}
//Map the array to getters
int SecurityValidationModel::informationCount () const
{ return d_ptr->m_SeverityCount[ (int)Severity::INFORMATION ]; }
int SecurityValidationModel::warningCount () const
{ return d_ptr->m_SeverityCount[ (int)Severity::WARNING ]; }
int SecurityValidationModel::issueCount () const
{ return d_ptr->m_SeverityCount[ (int)Severity::ISSUE ]; }
int SecurityValidationModel::errorCount () const
{ return d_ptr->m_SeverityCount[ (int)Severity::ERROR ]; }
int SecurityValidationModel::fatalWarningCount () const
{ return d_ptr->m_SeverityCount[ (int)Severity::FATAL_WARNING ]; }
#include <securityvalidationmodel.moc>
......@@ -50,40 +50,51 @@ public:
* This class evaluate the overall security of an account.
* It does so by checking various potential flaws, then create
* a metric called SecurityLevel. This model should be used to:
*
*
* 1) List all potential flaws
* 2) Decide if an account can be considered secure
* 3) Decide if a call can be considered secure
*
*
* End users should not have to be security gurus to setup Ring. It is our
* job to do as much as we can to make security configuration as transparent as
* possible.
*
*
* The SecurityLevel is computed by checking all possible flaw. The level cannot be
* higher than a flaw maximum security level. If there is 2 (or more) flaw in the same
* maximum level, the maximum level will be decreased by one (recursively).
*
*
* A flaw severity is used by the client to display the right icon ( (i), /!\, [x] ).
*/
//Properties
Q_PROPERTY(int informationCount READ informationCount NOTIFY informationCountChanged )
Q_PROPERTY(int warningCount READ warningCount NOTIFY warningCountChanged )
Q_PROPERTY(int issueCount READ issueCount NOTIFY issueCountChanged )
Q_PROPERTY(int errorCount READ errorCount NOTIFY errorCountChanged )
Q_PROPERTY(int fatalWarningCount READ fatalWarningCount NOTIFY fatalWarningCountChanged )
Q_PROPERTY(SecurityLevel securityLevel READ securityLevel NOTIFY securityLevelChanged )
///Give the user an overview of the current security state
enum class SecurityLevel {
NONE = 0, /* Security is not functional or severely defective */
WEAK = 1, /* There is some security, but way too many flaws */
MEDIUM = 2, /* The security is probably good enough, but there is issues */
ACCEPTABLE = 3, /* The security is most probably good enough, only minor issues */
STRONG = 4, /* All the non-information items are correct */
COMPLETE = 5, /* Everything, even the recommendations, are correct */
NONE = 0, /*!< Security is not functional or severely defective */
WEAK = 1, /*!< There is some security, but way too many flaws */
MEDIUM = 2, /*!< The security is probably good enough, but there is issues */
ACCEPTABLE = 3, /*!< The security is most probably good enough, only minor issues */
STRONG = 4, /*!< All the non-information items are correct */
COMPLETE = 5, /*!< Everything, even the recommendations, are correct */
COUNT__,
};
Q_ENUMS(SecurityLevel)
///The severity of a given flaw
enum class Severity {
UNSUPPORTED , /*!< This severity is unsupported, to be ignored */
INFORMATION , /*!< Tip and tricks to have better security */
WARNING , /*!< It is a problem, but it wont have other side effects */
ISSUE , /*!< The security is compromised */
ERROR , /*!< It simply wont work (REGISTER) */
FATAL_WARNING, /*!< Registration may work, but it render everything else useless */
UNSUPPORTED = 0, /*!< This severity is unsupported, to be ignored */
INFORMATION = 1, /*!< Tip and tricks to have better security */
WARNING = 2, /*!< It is a problem, but it wont have other side effects */
ISSUE = 3, /*!< The security is compromised */
ERROR = 4, /*!< It simply wont work (REGISTER) */
FATAL_WARNING = 5, /*!< Registration may work, but it render everything else useless */
COUNT__,
};
Q_ENUMS(Severity)
......@@ -103,7 +114,8 @@ public:
///Role for the model
enum class Role {
Severity = 100
Severity = 100,
SecurityLevel = 101,
};
//Constructor
......@@ -117,11 +129,20 @@ public:
//Getter
QList<SecurityFlaw*> currentFlaws();
QModelIndex getIndex(const SecurityFlaw* flaw);
//Setters
void setTlsCaListCertificate ( Certificate* cert );
void setTlsCertificate ( Certificate* cert );
void setTlsPrivateKeyCertificate( Certificate* cert );
int informationCount () const;
int warningCount () const;
int issueCount () const;
int errorCount () const;
int fatalWarningCount() const;
SecurityLevel securityLevel () const;
Q_SIGNALS:
void informationCountChanged ();
void warningCountChanged ();
void issueCountChanged ();
void errorCountChanged ();
void fatalWarningCountChanged();
void securityLevelChanged ();
private:
SecurityValidationModelPrivate* d_ptr;
......@@ -129,5 +150,6 @@ private:
};
Q_DECLARE_METATYPE(SecurityValidationModel*)
Q_DECLARE_METATYPE(SecurityValidationModel::Severity)
Q_DECLARE_METATYPE(SecurityValidationModel::SecurityLevel)
#endif
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment