Avaldatud allikas
Laadi alla allikas ZIP
CH-J Server Manager
Vaata katalooge ja faile konkreetse rakenduse vabastamiseks.
CH-J / Server Manager
339 failid
core-20261014T184258Z-3fbed0b93fdf
Lisatud: Kuupäeva ei registreerita · Ehitatud:
1
"use strict";3
const crypto = require("node:crypto");4
const fs = require("node:fs");5
const path = require("node:path");6
const { execFileSync } = require("node:child_process");8
// TN3179 / TN3178: Local Network privacy uses the executable's LC_UUID.9
// Electron's prebuilt launchers otherwise share it with unrelated applications.10
// Only change launcher UUIDs before signing; leave Electron Framework (and its11
// upstream debugging symbols), native runtimes and installed apps untouched.12
function uuidCommands(bytes) {13
const entries = [];14
const range = (offset, size, end = bytes.length) => {15
if (!Number.isSafeInteger(offset) || !Number.isSafeInteger(size) || offset < 0 || size < 0 || offset + size > end) {16
throw new Error("Invalid Mach-O bounds.");17
}18
};19
const thin = (start, size) => {20
range(start, size);21
range(start, 28, start + size);22
const magic = bytes.readUInt32BE(start);23
const little = magic === 0xcefaedfe || magic === 0xcffaedfe;24
if (![0xcefaedfe, 0xcffaedfe, 0xfeedface, 0xfeedfacf].includes(magic)) throw new Error("Unsupported Mach-O executable.");25
const read = (offset) => little ? bytes.readUInt32LE(offset) : bytes.readUInt32BE(offset);26
const headerSize = [0xcffaedfe, 0xfeedfacf].includes(magic) ? 32 : 28;27
const count = read(start + 16);28
const commandsSize = read(start + 20);29
range(start, headerSize + commandsSize, start + size);30
const end = start + headerSize + commandsSize;31
let cursor = start + headerSize;32
let found = false;33
for (let i = 0; i < count; i++) {34
range(cursor, 8, end);35
const command = read(cursor);36
const commandSize = read(cursor + 4);37
if (commandSize < 8 || commandSize % 4) throw new Error("Invalid Mach-O load command.");38
range(cursor, commandSize, end);39
if (command === 0x1b) {40
if (found || commandSize !== 24) throw new Error("Invalid or duplicate LC_UUID.");41
entries.push({ offset: cursor + 8, cpuType: read(start + 4), cpuSubtype: read(start + 8) });42
found = true;43
}44
cursor += commandSize;45
}46
if (cursor !== end || !found) throw new Error("Mach-O executable must have exactly one LC_UUID per architecture.");47
};48
range(0, 4);49
const magic = bytes.readUInt32BE(0);50
if ([0xcafebabe, 0xbebafeca, 0xcafebabf, 0xbfbafeca].includes(magic)) {51
range(0, 8);52
const little = [0xbebafeca, 0xbfbafeca].includes(magic);53
const fat64 = [0xcafebabf, 0xbfbafeca].includes(magic);54
const read = (offset) => little ? bytes.readUInt32LE(offset) : bytes.readUInt32BE(offset);55
const read64 = (offset) => Number(little ? bytes.readBigUInt64LE(offset) : bytes.readBigUInt64BE(offset));56
const count = read(4);57
const stride = fat64 ? 32 : 20;58
range(8, count * stride);59
if (!count) throw new Error("Empty universal Mach-O executable.");60
let previousEnd = 8 + count * stride;61
for (let i = 0; i < count; i++) {62
const cursor = 8 + i * stride;63
const offset = fat64 ? read64(cursor + 8) : read(cursor + 8);64
const size = fat64 ? read64(cursor + 16) : read(cursor + 12);65
if (offset < previousEnd) throw new Error("Overlapping Mach-O architectures.");66
thin(offset, size);67
previousEnd = offset + size;68
}69
} else thin(0, bytes.length);70
return entries;71
}73
function launcherUuid(identity, entry) {74
const uuid = crypto.createHash("sha256")75
.update(JSON.stringify(["chj-local-network-v1", identity, entry.cpuType, entry.cpuSubtype]))76
.digest().subarray(0, 16);77
uuid[6] = (uuid[6] & 0x0f) | 0x80; // RFC 9562 custom UUID (version 8).78
uuid[8] = (uuid[8] & 0x3f) | 0x80;79
return uuid;80
}82
function readPlist(bundlePath) {83
return JSON.parse(execFileSync("/usr/bin/plutil", ["-convert", "json", "-o", "-", path.join(bundlePath, "Contents", "Info.plist")], { encoding: "utf8" }));84
}86
function processNetworkIdentity(appPath, expected, patch) {87
const info = readPlist(appPath);88
if (info.CFBundleIdentifier !== expected.appId) throw new Error("macOS bundle ID does not match the application identity.");89
if (info.CFBundleShortVersionString !== expected.version) throw new Error("macOS application version differs from package.json.");90
if (!String(info.NSLocalNetworkUsageDescription || "").trim()) throw new Error("macOS app lacks NSLocalNetworkUsageDescription.");91
const payload = crypto.createHash("sha256").update(fs.readFileSync(path.join(appPath, "Contents", "Resources", "app.asar"))).digest("hex");92
const frameworks = path.join(appPath, "Contents", "Frameworks");93
const bundles = [appPath, ...fs.readdirSync(frameworks, { withFileTypes: true })94
.filter((entry) => entry.isDirectory() && entry.name.endsWith(".app"))95
.map((entry) => path.join(frameworks, entry.name))];96
const uuids = new Set();97
const changes = [];98
const result = [];99
for (const bundle of bundles) {100
const plist = bundle === appPath ? info : readPlist(bundle);101
const name = plist.CFBundleExecutable;102
if (!name || path.basename(name) !== name) throw new Error("Invalid CFBundleExecutable.");103
const executable = path.join(bundle, "Contents", "MacOS", name);104
const relativePath = path.relative(appPath, executable).split(path.sep).join("/");105
const bytes = fs.readFileSync(executable);106
const identity = [info.CFBundleIdentifier, plist.CFBundleIdentifier, relativePath, payload];107
let changed = false;108
for (const entry of uuidCommands(bytes)) {109
const uuid = launcherUuid(identity, entry);110
const actual = bytes.subarray(entry.offset, entry.offset + 16);111
if (!actual.equals(uuid)) {112
if (!patch) throw new Error(`macOS launcher has a shared or unexpected LC_UUID: ${relativePath}`);113
uuid.copy(bytes, entry.offset);114
changed = true;115
}116
const hex = uuid.toString("hex");117
if (uuids.has(hex)) throw new Error("Duplicate macOS launcher UUID.");118
uuids.add(hex);119
result.push({ executable: relativePath, uuid: hex });120
}121
if (changed) changes.push({ executable, bytes });122
}123
// Validate every architecture and bundle before changing any output file.124
for (const { executable, bytes } of changes) fs.writeFileSync(executable, bytes);125
return result;126
}128
module.exports = {129
uuidCommands,130
launcherUuid,131
prepareMacNetworkIdentity: (appPath, expected) => processNetworkIdentity(appPath, expected, true),132
verifyMacNetworkIdentity: (appPath, expected) => processNetworkIdentity(appPath, expected, false)133
};SHA-256
da3c63c71d78c38e8fdcdbcec7dd018acbccdd5c81dc032b031ce24178ce2f9fCH-J Proprietary Software License 1.14 · Allikas on esitatud CH-J Proprietary Software License 1.14 all. Selle kättesaadavus ei muuda litsentsitingimusi ega anna täiendavaid õigusi.
Arhiiv SHA-256
3df08cf5e899262a6ce92d7ec2caf5c42b683f1f2b57055662b845ff7dde67a8