From 886b29e3565ddcf2ed1e73016b24685eff3d5ccf Mon Sep 17 00:00:00 2001 From: Sandro Soria Date: Thu, 24 Oct 2024 16:10:14 +0200 Subject: [PATCH] Use AthShield for mod verification MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Implemented mod verification using AthShield when enabled. Added detailed mod identity extraction and validation logic for better integrity checks. Added logs for each verification step and fallback to hash-based identity if the manifest is missing. Grande ligne : quand tu actives ath shield alors il utilise le système Athena's Shield. --- ajouts/version code final/dlAsync.js | 166 ++++++++++++++++----------- 1 file changed, 96 insertions(+), 70 deletions(-) diff --git a/ajouts/version code final/dlAsync.js b/ajouts/version code final/dlAsync.js index 283db1db..bec57824 100644 --- a/ajouts/version code final/dlAsync.js +++ b/ajouts/version code final/dlAsync.js @@ -66,96 +66,122 @@ async function dlAsync(login = true) { } // --------- Mod Verification Logic --------- - const modsDir = path.join(ConfigManager.getDataDirectory(), 'instances', serv.rawServer.id, 'mods') - // Check if mods directory exists, if not, create it - if (!fs.existsSync(modsDir)) { - fs.mkdirSync(modsDir, { recursive: true }) - } + if (athShield.status) { + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.usingAthShield')) - const distroMods = {} - const mdls = serv.modules + const modsDir = path.join(ConfigManager.getDataDirectory(), 'instances', serv.rawServer.id, 'mods') - // Populate expected mod identities and log them - mdls.forEach(mdl => { - if (mdl.rawModule.name.endsWith('.jar')) { - const modPath = path.join(modsDir, mdl.rawModule.name) - const modIdentity = mdl.rawModule.identity || mdl.rawModule.MD5 - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.distributionIdentityError', {'moduleName': mdl.rawModule.name, 'moduleIdentity': modIdentity})) - distroMods[modPath] = modIdentity - } - }) - - // Function to extract mod identity from the jar file - const extractModIdentity = (filePath) => { - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.modIdentityExtraction', {'filePath': filePath})) - const zip = new AdmZip(filePath) - const manifestEntry = zip.getEntry('META-INF/MANIFEST.MF') - - if (manifestEntry) { - const manifestContent = manifestEntry.getData().toString('utf8') - const lines = manifestContent.split('\n') - const identityLine = lines.find(line => line.startsWith('Mod-Id:') || line.startsWith('Implementation-Title:')) - if (identityLine) { - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.manifestIdentityFound', {'filePath': filePath, 'identityLine': identityLine})) - return identityLine.split(':')[1].trim() - } + // Check if mods directory exists, if not, create it + if (!fs.existsSync(modsDir)) { + fs.mkdirSync(modsDir, {recursive: true}) } - // Fall back to a hash if no identity is found - const fileBuffer = fs.readFileSync(filePath) - const hashSum = crypto.createHash('md5') // Use MD5 to match the distribution configuration - hashSum.update(fileBuffer) - const hash = hashSum.digest('hex') - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.identityNotFoundInManifest', {'filePath': filePath, 'hash': hash})) - return hash - } + const distroMods = {} + const mdls = serv.modules - // Validate mods function - const validateMods = () => { - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.startingModValidation')) - const installedMods = fs.readdirSync(modsDir) - let valid = true + // Populate expected mod identities and log them + mdls.forEach(mdl => { + if (mdl.rawModule.name.endsWith('.jar')) { + const modPath = path.join(modsDir, mdl.rawModule.name) + const modIdentity = mdl.rawModule.identity || mdl.rawModule.MD5 + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.distributionIdentityError', { + 'moduleName': mdl.rawModule.name, + 'moduleIdentity': modIdentity + })) + distroMods[modPath] = modIdentity + } + }) - for (let mod of installedMods) { - const modPath = path.join(modsDir, mod) + // Function to extract mod identity from the jar file + const extractModIdentity = (filePath) => { + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.modIdentityExtraction', {'filePath': filePath})) + const zip = new AdmZip(filePath) + const manifestEntry = zip.getEntry('META-INF/MANIFEST.MF') - // Skip validation for mods in the excluded list - if (EXCLUDED_MODS.includes(mod)) { - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.modValidationBypassed', {'mod': mod})) - continue + if (manifestEntry) { + const manifestContent = manifestEntry.getData().toString('utf8') + const lines = manifestContent.split('\n') + const identityLine = lines.find(line => line.startsWith('Mod-Id:') || line.startsWith('Implementation-Title:')) + if (identityLine) { + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.manifestIdentityFound', { + 'filePath': filePath, + 'identityLine': identityLine + })) + return identityLine.split(':')[1].trim() + } } - const expectedIdentity = distroMods[modPath] - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.validatingMod', {'mod': mod})) + // Fall back to a hash if no identity is found + const fileBuffer = fs.readFileSync(filePath) + const hashSum = crypto.createHash('md5') // Use MD5 to match the distribution configuration + hashSum.update(fileBuffer) + const hash = hashSum.digest('hex') + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.identityNotFoundInManifest', { + 'filePath': filePath, + 'hash': hash + })) + return hash + } - if (expectedIdentity) { - const modIdentity = extractModIdentity(modPath) - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.expectedAndCalculatedIdentity', {'expectedIdentity': expectedIdentity, 'mod': mod, 'modIdentity': modIdentity})) + // Validate mods function + const validateMods = () => { + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.startingModValidation')) + const installedMods = fs.readdirSync(modsDir) + let valid = true - if (modIdentity !== expectedIdentity) { - loggerLanding.error(Lang.queryJS('landing.dlAsync.AthShield.modIdentityMismatchError', {'mod': mod, 'expectedIdentity': expectedIdentity, 'modIdentity': modIdentity})) + for (let mod of installedMods) { + const modPath = path.join(modsDir, mod) + + // Skip validation for mods in the excluded list + if (EXCLUDED_MODS.includes(mod)) { + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.modValidationBypassed', {'mod': mod})) + continue + } + + const expectedIdentity = distroMods[modPath] + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.validatingMod', {'mod': mod})) + + if (expectedIdentity) { + const modIdentity = extractModIdentity(modPath) + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.expectedAndCalculatedIdentity', { + 'expectedIdentity': expectedIdentity, + 'mod': mod, + 'modIdentity': modIdentity + })) + + if (modIdentity !== expectedIdentity) { + loggerLanding.error(Lang.queryJS('landing.dlAsync.AthShield.modIdentityMismatchError', { + 'mod': mod, + 'expectedIdentity': expectedIdentity, + 'modIdentity': modIdentity + })) + valid = false + break + } + } else { + loggerLanding.warn(Lang.queryJS('landing.dlAsync.AthShield.expectedIdentityNotFound', {'mod': mod})) valid = false break } - } else { - loggerLanding.warn(Lang.queryJS('landing.dlAsync.AthShield.expectedIdentityNotFound', {'mod': mod})) - valid = false - break } + + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.modValidationCompleted')) + return valid } - loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.modValidationCompleted')) - return valid + // Perform mod validation before proceeding + if (!validateMods()) { + const errorMessage = Lang.queryJS('landing.dlAsync.AthShield.invalidModsDetectedMessage', {'folder': dataPath}) + loggerLanding.error(errorMessage) + showLaunchFailure(errorMessage, null) + return + } + + } else { + loggerLanding.info(Lang.queryJS('landing.dlAsync.AthShield.notUsingAthShield')) } - // Perform mod validation before proceeding - if (!validateMods()) { - const errorMessage = Lang.queryJS('landing.dlAsync.AthShield.invalidModsDetectedMessage', {'folder': dataPath}) - loggerLanding.error(errorMessage) - showLaunchFailure(errorMessage, null) - return - } // --------- End of Mod Verification Logic --------- setLaunchDetails(Lang.queryJS('landing.dlAsync.pleaseWait'))