This commit is contained in:
DavidXanatos 2023-07-11 22:35:59 +02:00
parent cf87504694
commit 675ef0dfb7
17 changed files with 230 additions and 174 deletions

View File

@ -39,6 +39,7 @@ This project adheres to [Semantic Versioning](http://semver.org/).
- the main injection detour code is now written in C instead of Assembler and can properly report SbieDll.dll loading errors as SBIE2181
- improved session agent startup to be more flexible
- improved SBIEMSG help handling, the link now contains message details allowing to point to a more exact document (if available)
- updated certificate validation code
### Fixed
- fixed uninstall issue in the Sandboxie Classic installer [d1863ff](https://github.com/sandboxie-plus/Sandboxie/commit/d1863ffadfe105c695de71c9e841c2fd568116fe)

View File

@ -1,6 +1,6 @@
/*
* Copyright (C) 2016 wj32
* Copyright (C) 2021 David Xanatos, xanasoft.com
* Copyright (C) 2021-2023 David Xanatos, xanasoft.com
*
* Process Hacker is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
@ -481,27 +481,11 @@ _FX LONGLONG KphGetDateInterval(CSHORT days, CSHORT months, CSHORT years)
return ((LONGLONG)days + (LONGLONG)months * 30ll + (LONGLONG)years * 365ll) * 24ll * 3600ll * 10000000ll; // 100ns steps -> 1sec
}
#define SOFTWARE_NAME L"Sandboxie-Plus"
#include "verify.h"
union _SCertInfo {
ULONGLONG State;
struct {
ULONG
valid : 1, // certificate is active
expired : 1, // certificate is expired but may be active
outdated : 1, // certificate is expired, not anymore valid for the current build
business : 1, // certificate is suitable for business use
evaluation: 1, // evaluation certificate
grace_period: 1, // the certificate is expired and or outdated but we keep it valid for 1 extra month to allof wor a seamless renewal
reservd_1 : 2,
reservd_2 : 8,
reservd_3 : 8,
reservd_4 : 8;
ULONG expirers_in_sec;
};
} Verify_CertInfo = {0};
SCertInfo Verify_CertInfo = { 0 };
_FX NTSTATUS KphValidateCertificate(void)
_FX NTSTATUS KphValidateCertificate()
{
BOOLEAN CertDbg = FALSE;
@ -689,7 +673,7 @@ _FX NTSTATUS KphValidateCertificate(void)
if (NT_SUCCESS(status)) {
Verify_CertInfo.valid = 1;
Verify_CertInfo.active = 1;
if(CertDbg) DbgPrint("Sbie Cert type: %S-%S\n", type, level);
@ -722,89 +706,99 @@ _FX NTSTATUS KphValidateCertificate(void)
level = NULL;
}
// Checks if the certificate is within its validity period, otherwise it has no effect except for UI notification
#define TEST_CERT_DATE(days, months, years) \
if ((cert_date.QuadPart + KphGetDateInterval(days, months, years)) < LocalTime.QuadPart){ \
Verify_CertInfo.expired = 1; \
} \
Verify_CertInfo.expirers_in_sec = (ULONG)(((cert_date.QuadPart + KphGetDateInterval(days, months, years)) - LocalTime.QuadPart) / 10000000ll); // 100ns steps -> 1sec
LARGE_INTEGER expiration_date = { 0 };
// certs with a validity >= 3 months get 1 extra month of functionality
#define TEST_GRACE_PERIODE(days, months, years) \
if (months >= 3 || years > 0){ \
if ((cert_date.QuadPart + KphGetDateInterval(days, months + 1, years)) >= LocalTime.QuadPart) \
Verify_CertInfo.grace_period = 1; \
} \
// Check if the certificate is valid for the current build, failing this locks features out
#define TEST_VALIDITY(days, months, years) \
TEST_CERT_DATE(days, months, years) \
if ((cert_date.QuadPart + KphGetDateInterval(days, months, years)) < BuildDate.QuadPart){ \
Verify_CertInfo.outdated = 1; \
TEST_GRACE_PERIODE(days, months, years) \
if(!Verify_CertInfo.grace_period){ \
Verify_CertInfo.valid = 0; \
status = STATUS_ACCOUNT_EXPIRED; \
} \
}
// Check if the certificate is expired, failing this locks features out
#define TEST_EXPIRATION(days, months, years) \
TEST_CERT_DATE(days, months, years) \
if(Verify_CertInfo.expired == 1) { \
TEST_GRACE_PERIODE(days, months, years) \
if(!Verify_CertInfo.grace_period){ \
Verify_CertInfo.valid = 0; \
status = STATUS_ACCOUNT_EXPIRED; \
} \
}
if (type && _wcsicmp(type, L"CONTRIBUTOR") == 0) {
// forever - nothing to check here
if (!type) // type is mandatory
;
else if (_wcsicmp(type, L"CONTRIBUTOR") == 0)
Verify_CertInfo.type = eCertContributor;
else if (_wcsicmp(type, L"ETERNAL") == 0)
Verify_CertInfo.type = eCertEternal;
else if (_wcsicmp(type, L"BUSINESS") == 0)
Verify_CertInfo.type = eCertBusiness;
else if (_wcsicmp(type, L"EVALUATION") == 0 || _wcsicmp(type, L"TEST") == 0)
Verify_CertInfo.type = eCertEvaluation;
else if (_wcsicmp(type, L"SUBSCRIPTION") == 0)
Verify_CertInfo.type = eCertSubscription;
else if (_wcsicmp(type, L"FAMILY") == 0)
Verify_CertInfo.type = eCertFamily;
// patreon >>>
else if (wcsstr(type, L"PATREON") != NULL) // TYPE: [CLASS]_PATREON-[LEVEL]
{
if(_wcsnicmp(type, L"GREAT", 5) == 0)
Verify_CertInfo.type = eCertGreatPatreon;
else if (_wcsnicmp(type, L"ENTRY", 5) == 0) { // new patreons get only 3 montgs for start
Verify_CertInfo.type = eCertEntryPatreon;
expiration_date.QuadPart = cert_date.QuadPart + KphGetDateInterval(0, 3, 0);
} else
Verify_CertInfo.type = eCertPatreon;
}
else if (type && _wcsicmp(type, L"BUSINESS") == 0) {
Verify_CertInfo.business = 1;
if (level) { // in months
TEST_EXPIRATION(0, (CSHORT)_wtoi(level), 0);
}
else { // 1 year default
TEST_EXPIRATION(0, 0, 1);
}
// <<< patreon
else //if (_wcsicmp(type, L"PERSONAL") == 0 || _wcsicmp(type, L"SUPPORTER") == 0)
{
Verify_CertInfo.type = eCertPersonal;
}
else if (type && _wcsicmp(type, L"EVALUATION") == 0) {
Verify_CertInfo.evaluation = 1;
// evaluation
if (level) { // in days
TEST_EXPIRATION((CSHORT)_wtoi(level), 0, 0);
}
else { // 5 days default
TEST_EXPIRATION(5, 0, 0);
}
if(CertDbg) DbgPrint("Sbie Cert type: %X\n", Verify_CertInfo.type);
if (CERT_IS_TYPE(Verify_CertInfo, eCertEvaluation))
{
expiration_date.QuadPart = cert_date.QuadPart + KphGetDateInterval((CSHORT)(level ? _wtoi(level) : 7), 0, 0); // x days, default 7
}
else /*if (!type || _wcsicmp(type, L"PERSONAL") == 0 || _wcsicmp(type, L"PATREON") == 0 || _wcsicmp(type, L"SUPPORTER") == 0) */ {
// persistent
// scheme 1.1 >>>
else if (CERT_IS_TYPE(Verify_CertInfo, eCertPersonal) || CERT_IS_TYPE(Verify_CertInfo, eCertPatreon))
{
if (level && _wcsicmp(level, L"HUGE") == 0) {
//
}
else if (level && _wcsicmp(level, L"LARGE") == 0 && cert_date.QuadPart < KphGetDate(1,04,2022)) { // valid for all builds released with 2 years
TEST_CERT_DATE(0, 0, 2); // no real expiration just ui reminder - old certs
Verify_CertInfo.type = eCertEternal;
}
else if (level && _wcsicmp(level, L"LARGE") == 0) { // valid for all builds released with 2 years
TEST_VALIDITY(0, 0, 2);
else if (level && _wcsicmp(level, L"LARGE") == 0) { // 2 years - personal
expiration_date.QuadPart = cert_date.QuadPart + KphGetDateInterval(0, 0, 2); // 2 years
}
else if (level && _wcsicmp(level, L"MEDIUM") == 0) { // valid for all builds released with 1 year
TEST_VALIDITY(0, 0, 1);
else if (level && _wcsicmp(level, L"MEDIUM") == 0) { // 1 year - personal
}
// subscriptions
else if (level && _wcsicmp(level, L"TEST") == 0) { // test certificate 5 days only
TEST_EXPIRATION(5, 0, 0);
else if (level && _wcsicmp(level, L"ENTRY") == 0) { // PATREON-ENTRY new patreons get only 3 montgs for start
if(CERT_IS_TYPE(Verify_CertInfo, eCertPatreon))
Verify_CertInfo.type = eCertEntryPatreon;
expiration_date.QuadPart = cert_date.QuadPart + KphGetDateInterval(0, 3, 0);
}
else if (level && _wcsicmp(level, L"ENTRY") == 0) { // patreon entry level, first 3 months, later longer
TEST_EXPIRATION(0, 3, 0);
else if (level && _wcsicmp(type, L"SMALL") == 0) { // 1 year - subscription
Verify_CertInfo.type = eCertSubscription;
}
else /*if (!level || _wcsicmp(level, L"SMALL") == 0)*/ { // valid for 1 year
TEST_EXPIRATION(0, 0, 1);
}
// <<< scheme 1.1
if (CERT_IS_TYPE(Verify_CertInfo, eCertEternal))
expiration_date.QuadPart = -1; // at the end of time (never)
else if(!expiration_date.QuadPart)
expiration_date.QuadPart = cert_date.QuadPart + KphGetDateInterval(0, 0, 1); // default 1 year, unless set differently already
// check if this is a subscription type sertificate
BOOLEAN isSubscription = CERT_IS_SUBSCRIPTION(Verify_CertInfo);
if (expiration_date.QuadPart != -1)
{
// check if this certificate is expired
if (expiration_date.QuadPart < LocalTime.QuadPart)
Verify_CertInfo.expired = 1;
Verify_CertInfo.expirers_in_sec = (ULONG)((expiration_date.QuadPart - LocalTime.QuadPart) / 10000000ll); // 100ns steps -> 1sec
// check if a non subscription type certificate is valid for the current build
if (!isSubscription && expiration_date.QuadPart < BuildDate.QuadPart)
Verify_CertInfo.outdated = 1;
}
// check if the certificate is valid
if (isSubscription ? Verify_CertInfo.expired : Verify_CertInfo.outdated)
{
if (!CERT_IS_TYPE(Verify_CertInfo, eCertEvaluation)) { // non eval certs get 1 month extra
if (expiration_date.QuadPart + KphGetDateInterval(0, 1, 0) >= LocalTime.QuadPart)
Verify_CertInfo.grace_period = 1;
}
if (!Verify_CertInfo.grace_period) {
Verify_CertInfo.active = 0;
status = STATUS_ACCOUNT_EXPIRED;
}
}
}

View File

@ -0,0 +1,88 @@
/*
* Copyright (C) 2021-2023 David Xanatos, xanasoft.com
*
* Process Hacker is free 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.
*
* Process Hacker 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
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Process Hacker. If not, see <http://www.gnu.org/licenses/>.
*/
#define SOFTWARE_NAME L"Sandboxie-Plus"
typedef union _SCertInfo {
unsigned long long State;
struct {
unsigned long
active : 1, // certificate is active
expired : 1, // certificate is expired but may be active
outdated : 1, // certificate is expired, not anymore valid for the current build
unused_1 : 2, // DEPRECTED
grace_period: 1, // the certificate is expired and or outdated but we keep it valid for 1 extra month to allof wor a seamless renewal
reservd_2 : 2,
type : 5,
level : 3,
reservd_3 : 8,
reservd_4 : 8;
unsigned long expirers_in_sec;
};
} SCertInfo;
enum ECertType {
eCertNoType = 0b00000,
eCertEternal = 0b00100,
eCertContributor = 0b00101,
// eCert = 0b00110,
// eCert = 0b00111,
eCertBusiness = 0b01000,
// eCert = 0b01001,
// eCert = 0b01010,
// eCert = 0b01011,
eCertPersonal = 0b01100,
// eCert = 0b01101,
// eCert = 0b01110,
// eCert = 0b01111,
eCertSubscription = 0b10000,
eCertFamily = 0b10001,
// eCert = 0b10010,
// eCert = 0b10011,
// eCertOther = 0b10100,
// eCert = 0b10101,
// eCert = 0b10110,
// eCert = 0b10111,
eCertPatreon = 0b11000,
eCertGreatPatreon = 0b11001,
eCertEntryPatreon = 0b11010,
// eCert = 0b11011,
eCertEvaluation = 0b11100
};
#define CERT_IS_TYPE(cert,t) ((cert.type & 0b11100) == t)
enum ECertLevel {
eCertNoLevel = 0b000,
eCertStandard = 0b010,
eCertAdvanced = 0b100,
eCertMaxLevel = 0b111,
};
#define CERT_IS_SUBSCRIPTION(cert) (CERT_IS_TYPE(cert, eCertBusiness) || CERT_IS_TYPE(cert, eCertSubscription) || cert.type == eCertEntryPatreon || CERT_IS_TYPE(cert, eCertEvaluation))
#define CERT_IS_INSIDER(cert) (CERT_IS_TYPE(cert, eCertEternal) || cert.type == eCertGreatPatreon)

View File

@ -13,7 +13,7 @@ bool TestWriteRight(const QString& Path)
return TestFile.remove();
}
CSettings::CSettings(const QString& AppDir, const QString& AppName, bool bShared, QMap<QString, SSetting> DefaultValues, QObject* qObject) : QObject(qObject)
CSettings::CSettings(const QString& AppDir, const QString& AppName, QMap<QString, SSetting> DefaultValues, QObject* qObject) : QObject(qObject)
{
m_ConfigDir = AppDir;
if (!(m_bPortable = QFile::exists(m_ConfigDir + "/" + AppName + ".ini")))
@ -22,13 +22,9 @@ CSettings::CSettings(const QString& AppDir, const QString& AppName, bool bShared
if (dirs.isEmpty())
m_ConfigDir = QDir::homePath() + "/." + AppName;
//
// if shared is set a new ini is created in the shared location
// and if present take precedence over an ini in a user location
// however if the only existing ini is in a user location it will be used
// if ini is present in the shared location it take precedence over an ini in a user location
//
else if(bShared && dirs.count() > 2 && (
QFile::exists(dirs[1] + "/" + AppName + "/" + AppName + ".ini") ||
!QFile::exists(dirs[0] + "/" + AppName + "/" + AppName + ".ini") ))
else if(dirs.count() > 2 && QFile::exists(dirs[1] + "/" + AppName + "/" + AppName + ".ini"))
m_ConfigDir = dirs[1] + "/" + AppName;
else
m_ConfigDir = dirs[0] + "/" + AppName;

View File

@ -97,7 +97,7 @@ public:
virtual bool IsBlob() const {return true;}
};
CSettings(const QString& AppDir, const QString& AppName, bool bShared = false, QMap<QString, SSetting> DefaultValues = QMap<QString, SSetting>(), QObject* qObject = NULL);
CSettings(const QString& AppDir, const QString& AppName, QMap<QString, SSetting> DefaultValues = QMap<QString, SSetting>(), QObject* qObject = NULL);
virtual ~CSettings();
void DelValue(const QString& key);

View File

@ -221,7 +221,7 @@ void CSbieObject::LogMessage(const QVariant& Message, bool bNotify)
theGUI->OnLogMessage(Message.toString(), bNotify);
}
bool JSbieObject::isCertValid()
bool JSbieObject::testFeature(const QString& name)
{
return g_CertInfo.valid;
return theAPI->GetFeatureStr().contains(name, Qt::CaseInsensitive);
}

View File

@ -156,7 +156,7 @@ public:
QMetaObject::invokeMethod(m_pObject, "LogMessage", Qt::BlockingQueuedConnection, Q_ARG(const QVariant&, Message), Q_ARG(bool, bNotify));
}
Q_INVOKABLE bool isCertValid();
Q_INVOKABLE bool testFeature(const QString& name);
protected:
CBoxEngine* m_pEngine;

View File

@ -171,8 +171,8 @@ void COnlineUpdater::GetUpdates(QObject* receiver, const char* member, const QVa
Query.addQueryItem("language", QLocale::system().name());
QString UpdateKey = GetArguments(g_Certificate, L'\n', L':').value("UPDATEKEY");
if (UpdateKey.isEmpty())
UpdateKey = theAPI->GetGlobalSettings()->GetText("UpdateKey"); // theConf->GetString("Options/UpdateKey");
//if (UpdateKey.isEmpty())
// UpdateKey = theAPI->GetGlobalSettings()->GetText("UpdateKey"); // theConf->GetString("Options/UpdateKey");
//if (UpdateKey.isEmpty())
// UpdateKey = "00000000000000000000000000000000";
if (!UpdateKey.isEmpty())
@ -1029,11 +1029,8 @@ bool COnlineUpdater::IsVersionNewer(const QString& VersionStr)
void COnlineUpdater::UpdateCert(bool bWait)
{
QString UpdateKey; // for now only patreons can update the cert automatically
TArguments args = GetArguments(g_Certificate, L'\n', L':');
if(args.value("TYPE").contains("PATREON"))
UpdateKey = args.value("UPDATEKEY");
if (UpdateKey.isEmpty()) {
// for now only patreons can update the cert automatically
if (!CERT_IS_TYPE(g_CertInfo, eCertPatreon)) {
theGUI->OpenUrl("https://sandboxie-plus.com/go.php?to=sbie-get-cert");
return;
}
@ -1048,6 +1045,7 @@ void COnlineUpdater::UpdateCert(bool bWait)
if (m_RequestManager == NULL)
m_RequestManager = new CNetworkAccessManager(30 * 1000, this);
QString UpdateKey = GetArguments(g_Certificate, L'\n', L':').value("UPDATEKEY");
QUrlQuery Query;
Query.addQueryItem("UpdateKey", UpdateKey);

View File

@ -2139,9 +2139,9 @@ void CSandMan::OnStatusChanged()
uchar UsageFlags = 0;
if (theAPI->GetSecureParam("UsageFlags", &UsageFlags, sizeof(UsageFlags))) {
if (!g_CertInfo.business) {
if (!CERT_IS_TYPE(g_CertInfo, eCertBusiness)) {
if ((UsageFlags & (2 | 1)) != 0) {
if(g_CertInfo.valid)
if(g_CertInfo.active)
appTitle.append(tr(" for Personal use"));
else
appTitle.append(tr(" - for Non-Commercial use ONLY"));
@ -2545,7 +2545,7 @@ void CSandMan::SaveMessageLog(QIODevice* pFile)
bool CSandMan::CheckCertificate(QWidget* pWidget)
{
if (g_CertInfo.valid)
if (g_CertInfo.active)
return true;
//if ((g_FeatureFlags & CSbieAPI::eSbieFeatureCert) == 0) {
@ -2572,13 +2572,8 @@ bool CSandMan::CheckCertificate(QWidget* pWidget)
void CSandMan::UpdateCertState()
{
g_CertInfo.State = theAPI->GetCertState();
if (g_CertInfo.valid)
if (g_CertInfo.active)
{
auto Args = GetArguments(g_Certificate, L'\n', L':');
QString Type = Args.value("TYPE").toUpper();
if (Type.contains("CONTRIBUTOR") || Type.contains("GREAT_PATREON") || Type.contains("HUGE"))
g_CertInfo.insider = true;
// behave as if there would be no certificate at all
if (theConf->GetBool("Debug/IgnoreCertificate", false))
g_CertInfo.State = 0;
@ -2594,7 +2589,7 @@ void CSandMan::UpdateCertState()
// simulate a subscription type certificate having expired
if (theConf->GetBool("Debug/CertFakeOld", false)) {
g_CertInfo.valid = 0;
g_CertInfo.active = 0;
g_CertInfo.expired = 1;
}
@ -2607,22 +2602,22 @@ void CSandMan::UpdateCertState()
// simulate a perpetual use certificate being outside the update window
// and having been applied to a version built after the update window has ended
if (theConf->GetBool("Debug/CertFakeOutdated", false)) {
g_CertInfo.valid = 0;
g_CertInfo.active = 0;
g_CertInfo.expired = 1;
g_CertInfo.outdated = 1;
}
// simulate this being a business certificate - only contributors and other insiders
if (g_CertInfo.insider && theConf->GetBool("Debug/CertFakeBusiness", false))
g_CertInfo.business = 1;
if (CERT_IS_INSIDER(g_CertInfo) && theConf->GetBool("Debug/CertFakeBusiness", false))
g_CertInfo.type = eCertBusiness;
// simulate this being a evaluation certificate
if (theConf->GetBool("Debug/CertFakeEvaluation", false))
g_CertInfo.evaluation = 1;
g_CertInfo.type = eCertBusiness;
}
}
if (g_CertInfo.evaluation)
if (CERT_IS_TYPE(g_CertInfo, eCertEvaluation))
{
if (g_CertInfo.expired)
OnLogMessage(tr("The evaluation period has expired!!!"));

View File

@ -15,8 +15,8 @@ public:
CCertBadge(QWidget* parent = NULL): QLabel(parent)
{
setPixmap(QPixmap(":/Actions/Cert.png").scaled(16, 16, Qt::IgnoreAspectRatio, Qt::SmoothTransformation));
if (!g_CertInfo.valid) {
setToolTip(COptionsWindow::tr("This option requires a valid supporter certificate"));
if (!g_CertInfo.active) {
setToolTip(COptionsWindow::tr("This option requires an active supporter certificate"));
setCursor(Qt::PointingHandCursor);
} else {
setToolTip(COptionsWindow::tr("Supporter exclusive option"));
@ -26,7 +26,7 @@ public:
protected:
void mousePressEvent(QMouseEvent* event)
{
if(!g_CertInfo.valid)
if(!g_CertInfo.active)
theGUI->OpenUrl(QUrl("https://sandboxie-plus.com/go.php?to=sbie-get-cert"));
}
};
@ -38,6 +38,7 @@ void COptionsWindow__AddCertIcon(QWidget* pOriginalWidget)
pLayout->setContentsMargins(0, 0, 0, 0);
pLayout->setSpacing(0);
pLayout->addWidget(new CCertBadge());
pLayout->setAlignment(Qt::AlignLeft);
pOriginalWidget->parentWidget()->layout()->replaceWidget(pOriginalWidget, pWidget);
pLayout->insertWidget(0, pOriginalWidget);
}
@ -64,7 +65,7 @@ void COptionsWindow::CreateGeneral()
connect(ui.lblBoxInfo, SIGNAL(linkActivated(const QString&)), theGUI, SLOT(OpenUrl(const QString&)));
ui.lblSupportCert->setVisible(false);
if (!g_CertInfo.valid)
if (!g_CertInfo.active)
{
ui.lblSupportCert->setVisible(true);
connect(ui.lblSupportCert, SIGNAL(linkActivated(const QString&)), theGUI, SLOT(OpenUrl(const QString&)));

View File

@ -1025,8 +1025,8 @@ void CSettingsWindow::LoadSettings()
ui.chkUpdateAddons->setCheckState(CSettingsWindow__Int2Chk(theConf->GetInt("Options/CheckForAddons", 2)));
ui.chkUpdateIssues->setCheckState(CSettingsWindow__Int2Chk(theConf->GetInt("Options/CheckForIssues", 2)));
//ui.chkUpdateTemplates->setEnabled(g_CertInfo.valid && !g_CertInfo.expired);
ui.chkUpdateIssues->setEnabled(g_CertInfo.valid && !g_CertInfo.expired);
//ui.chkUpdateTemplates->setEnabled(g_CertInfo.active && !g_CertInfo.expired);
ui.chkUpdateIssues->setEnabled(g_CertInfo.active && !g_CertInfo.expired);
}
void CSettingsWindow::UpdateCert()
@ -1043,7 +1043,7 @@ void CSettingsWindow::UpdateCert()
if (g_CertInfo.expired) {
palette.setColor(QPalette::Base, QColor(255, 255, 192));
QString infoMsg = tr("This supporter certificate has expired, please <a href=\"sbie://update/cert\">get an updated certificate</a>.");
if (g_CertInfo.valid) {
if (g_CertInfo.active) {
if (g_CertInfo.grace_period)
infoMsg.append(tr("<br /><font color='red'>Plus features will be disabled in %1 days.</font>").arg((g_CertInfo.expirers_in_sec + 30*60*60*24) / (60*60*24)));
else if (!g_CertInfo.outdated) // must be an expiren medium or large cert on an old build
@ -1069,7 +1069,7 @@ void CSettingsWindow::UpdateCert()
ui.txtCertificate->setPalette(palette);
}
ui.radInsider->setEnabled(g_CertInfo.insider);
ui.radInsider->setEnabled(CERT_IS_INSIDER(g_CertInfo));
}
void CSettingsWindow::UpdateUpdater()
@ -1083,7 +1083,7 @@ void CSettingsWindow::UpdateUpdater()
}
else {
ui.cmbInterval->setEnabled(true);
if (ui.radStable->isChecked() && (!g_CertInfo.valid || g_CertInfo.expired)) {
if (ui.radStable->isChecked() && (!g_CertInfo.active || g_CertInfo.expired)) {
ui.cmbUpdate->setEnabled(false);
ui.cmbUpdate->setCurrentIndex(ui.cmbUpdate->findData("ignore"));
ui.lblRevision->setText(tr("Supporter certificate required"));
@ -1481,7 +1481,7 @@ bool CSettingsWindow::ApplyCertificate(const QByteArray &Certificate, QWidget* w
if (g_CertInfo.expired || g_CertInfo.outdated) {
if(g_CertInfo.outdated)
QMessageBox::information(widget, "Sandboxie-Plus", tr("This certificate is unfortunately not valid for the current build, you need to get a new certificate or downgrade to an earlier build."));
else if(g_CertInfo.valid && !g_CertInfo.grace_period)
else if(g_CertInfo.active && !g_CertInfo.grace_period)
QMessageBox::information(widget, "Sandboxie-Plus", tr("Although this certificate has expired, for the currently installed version plus features remain enabled. However, you will no longer have access to Sandboxie-Live services, including compatibility updates and the online troubleshooting database."));
else
QMessageBox::information(widget, "Sandboxie-Plus", tr("This certificate has unfortunately expired, you need to get a new certificate."));

View File

@ -192,22 +192,7 @@ void WindowsMoveFile(const QString& from, const QString& to);
extern quint32 g_FeatureFlags;
extern QByteArray g_Certificate;
union SCertInfo {
quint64 State;
struct {
quint32
valid : 1, // certificate is active
expired : 1, // certificate is expired but may be active
outdated : 1, // certificate is expired, not anymore valid for the current build
business : 1, // certificate is suitable for business use
evaluation: 1, // evaluation certificate
grace_period: 1, // the certificate is expired and or outdated but we keep it valid for 1 extra month to allof wor a seamless renewal
reservd_1 : 2,
reservd_2 : 8,
reservd_3 : 8,
reservd_4 : 7,
insider : 1;
qint32 expirers_in_sec;
};
};
#include "..\..\Sandboxie\core\drv\verify.h"
extern SCertInfo g_CertInfo;

View File

@ -24,7 +24,7 @@ QDateTime GetSbieInstallationDate()
bool CSupportDialog::IsBusinessUse()
{
if (g_CertInfo.business)
if (CERT_IS_TYPE(g_CertInfo, eCertBusiness))
return true;
uchar UsageFlags = 0;
theAPI->GetSecureParam("UsageFlags", &UsageFlags, sizeof(UsageFlags));
@ -36,14 +36,14 @@ bool CSupportDialog::CheckSupport(bool bOnRun)
bool NoGo = false;
#ifdef INSIDER_BUILD
if (g_CertInfo.valid) {
if (!g_CertInfo.insider) {
if (g_CertInfo.active) {
if (!CERT_IS_INSIDER(g_CertInfo)) {
TArguments args = GetArguments(g_Certificate, L'\n', L':');
if (args.value("TYPE").contains("PATREON")) {
if (QMessageBox::question(NULL, "Sandboxie-Plus", tr("This Insider build requires a special certificate of type GREAT_PATREON, PERSONAL-HUGE, or CONTRIBUTOR.\n"
"If you are a Great Supporter on Patreon already, Sandboxie can check online for an update of your certificate."), QMessageBox::Ok, QMessageBox::Cancel) == QMessageBox::Ok) {
theGUI->m_pUpdater->UpdateCert(true);
if (g_CertInfo.insider)
if (CERT_IS_INSIDER(g_CertInfo))
return false;
}
}
@ -56,7 +56,7 @@ bool CSupportDialog::CheckSupport(bool bOnRun)
NoGo = true;
#else
if (g_CertInfo.valid)
if (g_CertInfo.active)
return false;
QDateTime InstallDate = GetSbieInstallationDate();
@ -131,7 +131,7 @@ bool CSupportDialog::ShowDialog(bool NoGo, int Wait)
QString Message;
#ifdef INSIDER_BUILD
if (!g_CertInfo.insider)
if (!CERT_IS_INSIDER(g_CertInfo))
{
Message += tr("This is a <a href=\"https://sandboxie-plus.com/go.php?to=sbie-insider\">exclusive Insider build</a> of Sandboxie-Plus it is only available to <a href=\"https://sandboxie-plus.com/go.php?to=patreon\">Patreon Supporters</a> on higher tiers as well as to project contributors and owners of a HUGE supporter certificate.");
}
@ -303,11 +303,11 @@ void CSupportDialog::OnButton()
pSettingsWindow->showTab("Support", true);
connect(pSettingsWindow, &CSettingsWindow::Closed, [this]() {
#ifdef INSIDER_BUILD
if (g_CertInfo.valid && !g_CertInfo.insider) {
if (g_CertInfo.active && !CERT_IS_INSIDER(g_CertInfo)) {
TArguments args = GetArguments(g_Certificate, L'\n', L':');
if (args.value("TYPE").contains("PATREON")) {
theGUI->m_pUpdater->UpdateCert(true);
if (g_CertInfo.insider) {
if (CERT_IS_INSIDER(g_CertInfo)) {
accept();
return;
}
@ -317,7 +317,7 @@ void CSupportDialog::OnButton()
return;
}
#endif
if (g_CertInfo.valid)
if (g_CertInfo.active)
accept();
});
}

View File

@ -271,7 +271,7 @@ void CBeginPage::initializePage()
m_pLayout->addItem(new QSpacerItem(10, 10, QSizePolicy::Fixed, QSizePolicy::Expanding), row++, 0);
if (!g_CertInfo.valid || g_CertInfo.expired) {
if (!g_CertInfo.active || g_CertInfo.expired) {
QLabel* pBottomLabel = new QLabel(tr("With a valid <a href=\"https://sandboxie-plus.com/go.php?to=sbie-cert\">supporter certificate</a> the wizard would be even more powerful. "
"It could access the <a href=\"https://sandboxie-plus.com/go.php?to=sbie-issue-db\">online solution database</a> to retrieve the latest troubleshooting instructions."));
connect(pBottomLabel, SIGNAL(linkActivated(const QString&)), theGUI, SLOT(OpenUrl(const QString&)));

View File

@ -486,7 +486,7 @@ CAdvancedPage::CAdvancedPage(QWidget *parent)
QCheckBox* pImageProtection = new QCheckBox(tr("Prevent sandboxes programs installed on host from loading dll's from the sandbox"));
pImageProtection->setToolTip(tr("This feature may reduce compatibility as it also prevents box located processes from writing to host located ones and even starting them."));
pImageProtection->setChecked(theConf->GetBool("BoxDefaults/ImagesProtection", false));
pImageProtection->setEnabled(g_CertInfo.valid);
pImageProtection->setEnabled(g_CertInfo.active);
layout->addWidget(pImageProtection, row++, 1, 1, 3);
registerField("imagesProtection", pImageProtection);

View File

@ -185,7 +185,7 @@ CIntroPage::CIntroPage(QWidget *parent)
uchar BusinessUse = 2;
if (!g_Certificate.isEmpty())
BusinessUse = g_CertInfo.business ? 1 : 0;
BusinessUse = CERT_IS_TYPE(g_CertInfo, eCertBusiness) ? 1 : 0;
else {
uchar UsageFlags = 0;
if (theAPI->GetSecureParam("UsageFlags", &UsageFlags, sizeof(UsageFlags)))
@ -256,7 +256,7 @@ CCertificatePage::CCertificatePage(QWidget *parent)
registerField("useCertificate", m_pCertificate, "plainText");
m_pEvaluate = new QCheckBox(tr("Start evaluation without a certificate for a limited period of time."));
if (g_CertInfo.evaluation) {
if (CERT_IS_TYPE(g_CertInfo, eCertEvaluation)) {
m_pEvaluate->setEnabled(false);
m_pEvaluate->setChecked(true);
}
@ -627,7 +627,7 @@ void CSBUpdate::initializePage()
m_pUpdate->setChecked(true);
m_pStable->setChecked(true);
m_pBottomLabel->setVisible(!g_CertInfo.valid || g_CertInfo.expired);
m_pBottomLabel->setVisible(!g_CertInfo.active || g_CertInfo.expired);
UpdateOptions();
}
@ -651,7 +651,7 @@ void CSBUpdate::UpdateOptions()
m_pStable->setEnabled(m_pVersion->isChecked());
m_pPreview->setEnabled(m_pVersion->isChecked());
m_pInsider->setEnabled(g_CertInfo.insider && m_pVersion->isChecked());
m_pInsider->setEnabled(CERT_IS_INSIDER(g_CertInfo) && m_pVersion->isChecked());
m_pHotfixes->setEnabled(m_pVersion->isChecked());
}

View File

@ -22,17 +22,15 @@ int main(int argc, char *argv[])
*wcsrchr(szPath, L'\\') = L'\0';
QString AppDir = QString::fromWCharArray(szPath);
if (QFile::exists(AppDir + "\\Certificate.dat")) {
if (QFile::exists(AppDir + "\\Certificate.dat"))
CSettingsWindow::LoadCertificate(AppDir + "\\Certificate.dat");
g_CertInfo.business = GetArguments(g_Certificate, L'\n', L':').value("TYPE").toUpper().contains("BUSINESS");
}
// use AppFolder/PlusData when present, else fallback to AppFolder
QString ConfDir = AppDir + "\\PlusData";
if(!QFile::exists(ConfDir))
ConfDir = AppDir;
// use a shared setting location when used in a business environment for easier administration
theConf = new CSettings(ConfDir, "Sandboxie-Plus", g_CertInfo.business);
theConf = new CSettings(ConfDir, "Sandboxie-Plus");
#ifndef _DEBUG
InitMiniDumpWriter(QString("SandMan-v%1").arg(CSandMan::GetVersion()).toStdWString().c_str() , QString(theConf->GetConfigDir()).replace("/", "\\").toStdWString().c_str());