diff --git a/client/configurators/xray_configurator.cpp b/client/configurators/xray_configurator.cpp index 60ef2b1d..1260e890 100644 --- a/client/configurators/xray_configurator.cpp +++ b/client/configurators/xray_configurator.cpp @@ -21,14 +21,6 @@ QString XrayConfigurator::prepareServerConfig(const ServerCredentials &credentia // Generate new UUID for client QString clientId = QUuid::createUuid().toString(QUuid::WithoutBraces); - // Create configuration for new client - QString clientConfig = QString(R"( - { - "id": "%1", - "flow": "xtls-rprx-vision" - })") - .arg(clientId); - // Get current server config QString currentConfig = m_serverController->getTextFileFromContainer( container, credentials, amnezia::protocols::xray::serverConfigPath, errorCode); @@ -39,23 +31,46 @@ QString XrayConfigurator::prepareServerConfig(const ServerCredentials &credentia // Parse current config as JSON QJsonDocument doc = QJsonDocument::fromJson(currentConfig.toUtf8()); - if (doc.isNull()) { + if (doc.isNull() || !doc.isObject()) { errorCode = ErrorCode::InternalError; return ""; } QJsonObject serverConfig = doc.object(); - if (!serverConfig.contains("inbounds") || serverConfig["inbounds"].toArray().isEmpty()) { + // Validate server config structure + if (!serverConfig.contains("inbounds")) { + errorCode = ErrorCode::InternalError; + return ""; + } + + QJsonArray inbounds = serverConfig["inbounds"].toArray(); + if (inbounds.isEmpty()) { + errorCode = ErrorCode::InternalError; return ""; } - QJsonArray inbounds = serverConfig["inbounds"].toArray(); QJsonObject inbound = inbounds[0].toObject(); + if (!inbound.contains("settings")) { + errorCode = ErrorCode::InternalError; + return ""; + } + QJsonObject settings = inbound["settings"].toObject(); + if (!settings.contains("clients")) { + errorCode = ErrorCode::InternalError; + return ""; + } + QJsonArray clients = settings["clients"].toArray(); - clients.append(QJsonDocument::fromJson(clientConfig.toUtf8()).object()); + // Create configuration for new client + QJsonObject clientConfig { + {"id", clientId}, + {"flow", "xtls-rprx-vision"} + }; + + clients.append(clientConfig); // Update config settings["clients"] = clients; @@ -95,31 +110,44 @@ QString XrayConfigurator::createConfig(const ServerCredentials &credentials, Doc { // Get client ID from prepareServerConfig QString xrayClientId = prepareServerConfig(credentials, container, containerConfig, errorCode); - if (errorCode != ErrorCode::NoError) { + if (errorCode != ErrorCode::NoError || xrayClientId.isEmpty()) { + errorCode = ErrorCode::InternalError; return ""; } QString config = m_serverController->replaceVars(amnezia::scriptData(ProtocolScriptType::xray_template, container), m_serverController->genVarsForScript(credentials, container, containerConfig)); + + if (config.isEmpty()) { + errorCode = ErrorCode::InternalError; + return ""; + } QString xrayPublicKey = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::PublicKeyPath, errorCode); - if (errorCode != ErrorCode::NoError) { + if (errorCode != ErrorCode::NoError || xrayPublicKey.isEmpty()) { + errorCode = ErrorCode::InternalError; return ""; } xrayPublicKey.replace("\n", ""); QString xrayShortId = m_serverController->getTextFileFromContainer(container, credentials, amnezia::protocols::xray::shortidPath, errorCode); - if (errorCode != ErrorCode::NoError) { + if (errorCode != ErrorCode::NoError || xrayShortId.isEmpty()) { + errorCode = ErrorCode::InternalError; return ""; } xrayShortId.replace("\n", ""); + // Validate all required variables are present + if (!config.contains("$XRAY_CLIENT_ID") || !config.contains("$XRAY_PUBLIC_KEY") || !config.contains("$XRAY_SHORT_ID")) { + errorCode = ErrorCode::InternalError; + return ""; + } + config.replace("$XRAY_CLIENT_ID", xrayClientId); config.replace("$XRAY_PUBLIC_KEY", xrayPublicKey); config.replace("$XRAY_SHORT_ID", xrayShortId); - qDebug() << "===>> xrayClientId: " << xrayClientId; return config; } diff --git a/client/ui/models/clientManagementModel.cpp b/client/ui/models/clientManagementModel.cpp index b54ef90d..675e29ff 100644 --- a/client/ui/models/clientManagementModel.cpp +++ b/client/ui/models/clientManagementModel.cpp @@ -264,9 +264,26 @@ ErrorCode ClientManagementModel::getXrayClients(const DockerContainer container, return ErrorCode::InternalError; } - const QJsonArray clients = serverConfig.object()["inbounds"].toArray()[0].toObject()["settings"].toObject()["clients"].toArray(); + const QJsonObject inbound = serverConfig.object()["inbounds"].toArray()[0].toObject(); + if (!inbound.contains("settings")) { + logger.error() << "Missing settings in xray inbound config"; + return ErrorCode::InternalError; + } + + const QJsonObject settings = inbound["settings"].toObject(); + if (!settings.contains("clients")) { + logger.error() << "Missing clients in xray settings config"; + return ErrorCode::InternalError; + } + + const QJsonArray clients = settings["clients"].toArray(); for (const auto &clientValue : clients) { - QString clientId = clientValue.toObject()["id"].toString(); + const QJsonObject clientObj = clientValue.toObject(); + if (!clientObj.contains("id")) { + logger.error() << "Missing id in xray client config"; + continue; + } + QString clientId = clientObj["id"].toString(); if (!isClientExists(clientId)) { QJsonObject client; @@ -388,8 +405,38 @@ ErrorCode ClientManagementModel::appendClient(const DockerContainer container, c auto protocolConfig = ContainerProps::getProtocolConfigFromContainer(protocol, containerConfig); QString clientId; if (container == DockerContainer::Xray) { - clientId = protocolConfig.value("outbounds").toArray()[0].toObject()["settings"].toObject()["vnext"] - .toArray()[0].toObject()["users"].toArray()[0].toObject()["id"].toString(); + if (!protocolConfig.contains("outbounds")) { + return ErrorCode::InternalError; + } + QJsonArray outbounds = protocolConfig.value("outbounds").toArray(); + if (outbounds.isEmpty()) { + return ErrorCode::InternalError; + } + QJsonObject outbound = outbounds[0].toObject(); + if (!outbound.contains("settings")) { + return ErrorCode::InternalError; + } + QJsonObject settings = outbound["settings"].toObject(); + if (!settings.contains("vnext")) { + return ErrorCode::InternalError; + } + QJsonArray vnext = settings["vnext"].toArray(); + if (vnext.isEmpty()) { + return ErrorCode::InternalError; + } + QJsonObject vnextObj = vnext[0].toObject(); + if (!vnextObj.contains("users")) { + return ErrorCode::InternalError; + } + QJsonArray users = vnextObj["users"].toArray(); + if (users.isEmpty()) { + return ErrorCode::InternalError; + } + QJsonObject user = users[0].toObject(); + if (!user.contains("id")) { + return ErrorCode::InternalError; + } + clientId = user["id"].toString(); } else { clientId = protocolConfig.value(config_key::clientId).toString(); } @@ -725,13 +772,38 @@ ErrorCode ClientManagementModel::revokeXray(const int row, // Remove client from server config QJsonObject configObj = serverConfig.object(); + if (!configObj.contains("inbounds")) { + logger.error() << "Missing inbounds in xray config"; + return ErrorCode::InternalError; + } + QJsonArray inbounds = configObj["inbounds"].toArray(); + if (inbounds.isEmpty()) { + logger.error() << "Empty inbounds array in xray config"; + return ErrorCode::InternalError; + } + QJsonObject inbound = inbounds[0].toObject(); + if (!inbound.contains("settings")) { + logger.error() << "Missing settings in xray inbound config"; + return ErrorCode::InternalError; + } + QJsonObject settings = inbound["settings"].toObject(); + if (!settings.contains("clients")) { + logger.error() << "Missing clients in xray settings"; + return ErrorCode::InternalError; + } + QJsonArray clients = settings["clients"].toArray(); + if (clients.isEmpty()) { + logger.error() << "Empty clients array in xray config"; + return ErrorCode::InternalError; + } for (int i = 0; i < clients.size(); ++i) { - if (clients[i].toObject()["id"].toString() == clientId) { + QJsonObject clientObj = clients[i].toObject(); + if (clientObj.contains("id") && clientObj["id"].toString() == clientId) { clients.removeAt(i); break; }