Merge pull request #684 from Scrumplex/logging-categories

Prevents private credentials from leaking in the logs of general users
This commit is contained in:
flow 2022-12-28 09:54:23 -08:00 committed by Sefa Eyeoglu
parent 49060beae7
commit 699fce4482
No known key found for this signature in database
GPG Key ID: E13DFD4B47127951
13 changed files with 59 additions and 54 deletions

View File

@ -268,6 +268,8 @@ if(NOT Launcher_FORCE_BUNDLED_LIBS)
find_package(ghc_filesystem QUIET) find_package(ghc_filesystem QUIET)
endif() endif()
include(ECMQtDeclareLoggingCategory)
####################################### Program Info ####################################### ####################################### Program Info #######################################
set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary") set(Launcher_APP_BINARY_NAME "prismlauncher" CACHE STRING "Name of the Launcher binary")

View File

@ -551,6 +551,24 @@ set(ATLAUNCHER_SOURCES
modplatform/atlauncher/ATLShareCode.h modplatform/atlauncher/ATLShareCode.h
) )
######## Logging categories ########
ecm_qt_declare_logging_category(CORE_SOURCES
HEADER Logging.h
IDENTIFIER authCredentials
CATEGORY_NAME "launcher.auth.credentials"
DEFAULT_SEVERITY Warning
DESCRIPTION "Secrets and credentials for debugging purposes"
EXPORT "${Launcher_Name}"
)
if(KDE_INSTALL_LOGGINGCATEGORIESDIR) # only install if there is a standard path for this
ecm_qt_install_logging_categories(
EXPORT "${Launcher_Name}"
DESTINATION "${KDE_INSTALL_LOGGINGCATEGORIESDIR}"
)
endif()
################################ COMPILE ################################ ################################ COMPILE ################################
set(LOGIC_SOURCES set(LOGIC_SOURCES

View File

@ -1,5 +1,6 @@
#include "Parsers.h" #include "Parsers.h"
#include "Json.h" #include "Json.h"
#include "Logging.h"
#include <QJsonDocument> #include <QJsonDocument>
#include <QJsonArray> #include <QJsonArray>
@ -75,9 +76,7 @@ bool getBool(QJsonValue value, bool & out) {
bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) { bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString name) {
qDebug() << "Parsing" << name <<":"; qDebug() << "Parsing" << name <<":";
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
QJsonParseError jsonError; QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
if(jsonError.error) { if(jsonError.error) {
@ -137,9 +136,7 @@ bool parseXTokenResponse(QByteArray & data, Katabasis::Token &output, QString na
bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) { bool parseMinecraftProfile(QByteArray & data, MinecraftProfile &output) {
qDebug() << "Parsing Minecraft profile..."; qDebug() << "Parsing Minecraft profile...";
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
QJsonParseError jsonError; QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
@ -275,9 +272,7 @@ decoded base64 "value":
bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) { bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
qDebug() << "Parsing Minecraft profile..."; qDebug() << "Parsing Minecraft profile...";
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
QJsonParseError jsonError; QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
@ -389,9 +384,7 @@ bool parseMinecraftProfileMojang(QByteArray & data, MinecraftProfile &output) {
bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) { bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output) {
qDebug() << "Parsing Minecraft entitlements..."; qDebug() << "Parsing Minecraft entitlements...";
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
QJsonParseError jsonError; QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
@ -424,9 +417,7 @@ bool parseMinecraftEntitlements(QByteArray & data, MinecraftEntitlement &output)
bool parseRolloutResponse(QByteArray & data, bool& result) { bool parseRolloutResponse(QByteArray & data, bool& result) {
qDebug() << "Parsing Rollout response..."; qDebug() << "Parsing Rollout response...";
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
QJsonParseError jsonError; QJsonParseError jsonError;
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
@ -455,9 +446,7 @@ bool parseRolloutResponse(QByteArray & data, bool& result) {
bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) { bool parseMojangResponse(QByteArray & data, Katabasis::Token &output) {
QJsonParseError jsonError; QJsonParseError jsonError;
qDebug() << "Parsing Mojang response..."; qDebug() << "Parsing Mojang response...";
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError); QJsonDocument doc = QJsonDocument::fromJson(data, &jsonError);
if(jsonError.error) { if(jsonError.error) {
qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString(); qWarning() << "Failed to parse response from api.minecraftservices.com/launcher/login as JSON: " << jsonError.errorString();

View File

@ -3,6 +3,7 @@
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QUuid> #include <QUuid>
#include "Logging.h"
#include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h" #include "minecraft/auth/Parsers.h"
@ -41,9 +42,7 @@ void EntitlementsStep::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender()); auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater(); requestor->deleteLater();
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
// TODO: check presence of same entitlementsRequestId? // TODO: check presence of same entitlementsRequestId?
// TODO: validate JWTs? // TODO: validate JWTs?

View File

@ -2,9 +2,10 @@
#include <QNetworkRequest> #include <QNetworkRequest>
#include "Logging.h"
#include "minecraft/auth/AccountTask.h"
#include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h" #include "minecraft/auth/Parsers.h"
#include "minecraft/auth/AccountTask.h"
#include "net/NetUtils.h" #include "net/NetUtils.h"
LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) { LauncherLoginStep::LauncherLoginStep(AccountData* data) : AuthStep(data) {
@ -51,14 +52,10 @@ void LauncherLoginStep::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender()); auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater(); requestor->deleteLater();
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
if (error != QNetworkReply::NoError) { if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error; qWarning() << "Reply error:" << error;
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
if (Net::isApplicationError(error)) { if (Net::isApplicationError(error)) {
emit finished( emit finished(
AccountTaskState::STATE_FAILED_SOFT, AccountTaskState::STATE_FAILED_SOFT,
@ -76,9 +73,7 @@ void LauncherLoginStep::onRequestDone(
if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) { if(!Parsers::parseMojangResponse(data, m_data->yggdrasilToken)) {
qWarning() << "Could not parse login_with_xbox response..."; qWarning() << "Could not parse login_with_xbox response...";
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
emit finished( emit finished(
AccountTaskState::STATE_FAILED_SOFT, AccountTaskState::STATE_FAILED_SOFT,
tr("Failed to parse the Minecraft access token response.") tr("Failed to parse the Minecraft access token response.")

View File

@ -42,6 +42,7 @@
#include "minecraft/auth/Parsers.h" #include "minecraft/auth/Parsers.h"
#include "Application.h" #include "Application.h"
#include "Logging.h"
using OAuth2 = Katabasis::DeviceFlow; using OAuth2 = Katabasis::DeviceFlow;
using Activity = Katabasis::Activity; using Activity = Katabasis::Activity;
@ -117,14 +118,12 @@ void MSAStep::onOAuthActivityChanged(Katabasis::Activity activity) {
// Succeeded or did not invalidate tokens // Succeeded or did not invalidate tokens
emit hideVerificationUriAndCode(); emit hideVerificationUriAndCode();
QVariantMap extraTokens = m_oauth2->extraTokens(); QVariantMap extraTokens = m_oauth2->extraTokens();
#ifndef NDEBUG
if (!extraTokens.isEmpty()) { if (!extraTokens.isEmpty()) {
qDebug() << "Extra tokens in response:"; qCDebug(authCredentials()) << "Extra tokens in response:";
foreach (QString key, extraTokens.keys()) { foreach (QString key, extraTokens.keys()) {
qDebug() << "\t" << key << ":" << extraTokens.value(key); qCDebug(authCredentials()) << "\t" << key << ":" << extraTokens.value(key);
} }
} }
#endif
emit finished(AccountTaskState::STATE_WORKING, tr("Got ")); emit finished(AccountTaskState::STATE_WORKING, tr("Got "));
return; return;
} }

View File

@ -2,6 +2,7 @@
#include <QNetworkRequest> #include <QNetworkRequest>
#include "Logging.h"
#include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h" #include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h" #include "net/NetUtils.h"
@ -40,9 +41,7 @@ void MinecraftProfileStep::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender()); auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater(); requestor->deleteLater();
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
if (error == QNetworkReply::ContentNotFoundError) { if (error == QNetworkReply::ContentNotFoundError) {
// NOTE: Succeed even if we do not have a profile. This is a valid account state. // NOTE: Succeed even if we do not have a profile. This is a valid account state.
if(m_data->type == AccountType::Mojang) { if(m_data->type == AccountType::Mojang) {

View File

@ -2,6 +2,7 @@
#include <QNetworkRequest> #include <QNetworkRequest>
#include "Logging.h"
#include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h" #include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h" #include "net/NetUtils.h"
@ -43,9 +44,7 @@ void MinecraftProfileStepMojang::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender()); auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater(); requestor->deleteLater();
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
if (error == QNetworkReply::ContentNotFoundError) { if (error == QNetworkReply::ContentNotFoundError) {
// NOTE: Succeed even if we do not have a profile. This is a valid account state. // NOTE: Succeed even if we do not have a profile. This is a valid account state.
if(m_data->type == AccountType::Mojang) { if(m_data->type == AccountType::Mojang) {

View File

@ -4,6 +4,7 @@
#include <QJsonParseError> #include <QJsonParseError>
#include <QJsonDocument> #include <QJsonDocument>
#include "Logging.h"
#include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h" #include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h" #include "net/NetUtils.h"
@ -58,9 +59,7 @@ void XboxAuthorizationStep::onRequestDone(
auto requestor = qobject_cast<AuthRequest *>(QObject::sender()); auto requestor = qobject_cast<AuthRequest *>(QObject::sender());
requestor->deleteLater(); requestor->deleteLater();
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
if (error != QNetworkReply::NoError) { if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error; qWarning() << "Reply error:" << error;
if (Net::isApplicationError(error)) { if (Net::isApplicationError(error)) {

View File

@ -3,7 +3,7 @@
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QUrlQuery> #include <QUrlQuery>
#include "Logging.h"
#include "minecraft/auth/AuthRequest.h" #include "minecraft/auth/AuthRequest.h"
#include "minecraft/auth/Parsers.h" #include "minecraft/auth/Parsers.h"
#include "net/NetUtils.h" #include "net/NetUtils.h"
@ -56,9 +56,7 @@ void XboxProfileStep::onRequestDone(
if (error != QNetworkReply::NoError) { if (error != QNetworkReply::NoError) {
qWarning() << "Reply error:" << error; qWarning() << "Reply error:" << error;
#ifndef NDEBUG qCDebug(authCredentials()) << data;
qDebug() << data;
#endif
if (Net::isApplicationError(error)) { if (Net::isApplicationError(error)) {
emit finished( emit finished(
AccountTaskState::STATE_FAILED_SOFT, AccountTaskState::STATE_FAILED_SOFT,
@ -74,9 +72,7 @@ void XboxProfileStep::onRequestDone(
return; return;
} }
#ifndef NDEBUG qCDebug(authCredentials()) << "XBox profile: " << data;
qDebug() << "XBox profile: " << data;
#endif
emit finished(AccountTaskState::STATE_WORKING, tr("Got Xbox profile")); emit finished(AccountTaskState::STATE_WORKING, tr("Got Xbox profile"));
} }

View File

@ -38,6 +38,15 @@ set( katabasis_PUBLIC
include/katabasis/RequestParameter.h include/katabasis/RequestParameter.h
) )
ecm_qt_declare_logging_category(katabasis_PRIVATE
HEADER KatabasisLogging.h # NOTE: this won't be in src/, but CMAKE_BINARY_DIR/src isn't included by default so this should be fine
IDENTIFIER katabasisCredentials
CATEGORY_NAME "katabasis.credentials"
DEFAULT_SEVERITY Warning
DESCRIPTION "Secrets and credentials from Katabasis"
EXPORT "Katabasis"
)
add_library( Katabasis STATIC ${katabasis_PRIVATE} ${katabasis_PUBLIC} ) add_library( Katabasis STATIC ${katabasis_PRIVATE} ${katabasis_PUBLIC} )
target_link_libraries(Katabasis Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network) target_link_libraries(Katabasis Qt${QT_VERSION_MAJOR}::Core Qt${QT_VERSION_MAJOR}::Network)

View File

@ -1,5 +1,6 @@
#pragma once #pragma once
#include <QLoggingCategory>
#include <QNetworkAccessManager> #include <QNetworkAccessManager>
#include <QNetworkRequest> #include <QNetworkRequest>
#include <QNetworkReply> #include <QNetworkReply>

View File

@ -19,9 +19,11 @@
#include "katabasis/PollServer.h" #include "katabasis/PollServer.h"
#include "katabasis/Globals.h" #include "katabasis/Globals.h"
#include "KatabasisLogging.h"
#include "JsonResponse.h" #include "JsonResponse.h"
namespace { namespace {
// ref: https://tools.ietf.org/html/rfc8628#section-3.2 // ref: https://tools.ietf.org/html/rfc8628#section-3.2
// Exception: Google sign-in uses "verification_url" instead of "*_uri" - we'll accept both. // Exception: Google sign-in uses "verification_url" instead of "*_uri" - we'll accept both.
bool hasMandatoryDeviceAuthParams(const QVariantMap& params) bool hasMandatoryDeviceAuthParams(const QVariantMap& params)
@ -333,9 +335,7 @@ QString DeviceFlow::refreshToken() {
} }
void DeviceFlow::setRefreshToken(const QString &v) { void DeviceFlow::setRefreshToken(const QString &v) {
#ifndef NDEBUG qCDebug(katabasisCredentials) << "new refresh token:" << v;
qDebug() << "DeviceFlow::setRefreshToken" << v << "...";
#endif
token_.refresh_token = v; token_.refresh_token = v;
} }