mirror of
https://github.com/dscalzi/HeliosLauncher.git
synced 2024-12-21 19:22:13 -08:00
Use AthShield for mod verification
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.
This commit is contained in:
parent
5f3e229360
commit
886b29e356
@ -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'))
|
||||
|
Loading…
Reference in New Issue
Block a user