#21: Add signature validation during installations [partial]
This commit is contained in:
@@ -65,7 +65,8 @@
|
|||||||
"build/**/*",
|
"build/**/*",
|
||||||
"node_modules/**/*",
|
"node_modules/**/*",
|
||||||
"src/helpers.js",
|
"src/helpers.js",
|
||||||
"public/detect_linux.sh"
|
"public/detect_linux.sh",
|
||||||
|
"public/install_linux.sh"
|
||||||
],
|
],
|
||||||
"linux": {
|
"linux": {
|
||||||
"category": "Utility",
|
"category": "Utility",
|
||||||
|
|||||||
@@ -16,6 +16,7 @@ require.extensions['.sh'] = function (module, filename) {
|
|||||||
module.exports = fs.readFileSync(filename, 'utf8');
|
module.exports = fs.readFileSync(filename, 'utf8');
|
||||||
};
|
};
|
||||||
const detectScript = require('./detect_linux.sh');
|
const detectScript = require('./detect_linux.sh');
|
||||||
|
const installScript = require('./update_linux.sh');
|
||||||
const publicKey =
|
const publicKey =
|
||||||
'-----BEGIN PUBLIC KEY-----\n' +
|
'-----BEGIN PUBLIC KEY-----\n' +
|
||||||
'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' +
|
'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' +
|
||||||
@@ -718,40 +719,38 @@ ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
if (os.platform() === 'win32') {
|
let command;
|
||||||
const executeInstall = () => {
|
let args;
|
||||||
helpers
|
const platform = os.platform();
|
||||||
.executeAsync(data.Source)
|
if (platform === 'win32') {
|
||||||
.then(() => {
|
command = data.Source;
|
||||||
cleanupFiles();
|
} else if (platform === 'darwin') {
|
||||||
closeApplication();
|
command = 'open';
|
||||||
})
|
args = ['-a', 'Finder', data.Source];
|
||||||
.catch(error => {
|
} else if (platform === 'linux') {
|
||||||
|
try {
|
||||||
|
const execPath = path.join(os.tmpdir(), 'install_linux.sh');
|
||||||
|
fs.writeFileSync(execPath, installScript);
|
||||||
|
fs.chmodSync(execPath, '750');
|
||||||
|
command = execPath;
|
||||||
|
args = [data.Source];
|
||||||
|
} catch (e) {
|
||||||
cleanupFiles();
|
cleanupFiles();
|
||||||
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
||||||
Source: data.Source,
|
Source: data.Source,
|
||||||
}, error);
|
}, e);
|
||||||
});
|
|
||||||
};
|
|
||||||
if (hasSignature) {
|
|
||||||
helpers
|
|
||||||
.verifySignature(data.Source, tempSig, tempPub)
|
|
||||||
.then(() => {
|
|
||||||
executeInstall();
|
|
||||||
})
|
|
||||||
.catch(() => {
|
|
||||||
cleanupFiles();
|
|
||||||
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
|
||||||
Source: data.Source,
|
|
||||||
}, 'Failed to verify installation package signature');
|
|
||||||
});
|
|
||||||
} else { // TODO Check Sha256
|
|
||||||
executeInstall();
|
|
||||||
}
|
}
|
||||||
} else if (data.Source.toLocaleLowerCase().endsWith('.dmg')) {
|
} else {
|
||||||
|
cleanupFiles();
|
||||||
|
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
||||||
|
Source: data.Source,
|
||||||
|
}, Error('Platform not supported: ' + os.platform()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (command) {
|
||||||
const executeInstall = () => {
|
const executeInstall = () => {
|
||||||
helpers
|
helpers
|
||||||
.executeAsync('open', ['-a', 'Finder', data.Source])
|
.executeAsync(command, args)
|
||||||
.then(() => {
|
.then(() => {
|
||||||
cleanupFiles();
|
cleanupFiles();
|
||||||
closeApplication();
|
closeApplication();
|
||||||
@@ -764,7 +763,19 @@ ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
if (hasHash) {
|
if (hasSignature) {
|
||||||
|
helpers
|
||||||
|
.verifySignature(data.Source, tempSig, tempPub)
|
||||||
|
.then(() => {
|
||||||
|
executeInstall();
|
||||||
|
})
|
||||||
|
.catch(() => {
|
||||||
|
cleanupFiles();
|
||||||
|
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
||||||
|
Source: data.Source,
|
||||||
|
}, 'Failed to verify installation package signature');
|
||||||
|
});
|
||||||
|
} else if (hasHash) {
|
||||||
helpers
|
helpers
|
||||||
.verifyHash(data.Source, data.Sha256)
|
.verifyHash(data.Source, data.Sha256)
|
||||||
.then(()=> {
|
.then(()=> {
|
||||||
@@ -779,22 +790,6 @@ ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => {
|
|||||||
} else {
|
} else {
|
||||||
executeInstall();
|
executeInstall();
|
||||||
}
|
}
|
||||||
} else if (data.Source.toLocaleLowerCase().endsWith('.appimage')) {
|
|
||||||
cleanupFiles();
|
|
||||||
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
|
||||||
Source: data.Source,
|
|
||||||
}, Error('Not implemented upgrade: ' + data.Source));
|
|
||||||
// TODO Generate and execute script with delay
|
|
||||||
/*helpers
|
|
||||||
.executeAsync(data.Source)
|
|
||||||
.then(() => {
|
|
||||||
closeApplication();
|
|
||||||
})
|
|
||||||
.catch(error => {
|
|
||||||
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
|
||||||
Source: data.Source,
|
|
||||||
}, error);
|
|
||||||
});*/
|
|
||||||
} else {
|
} else {
|
||||||
cleanupFiles();
|
cleanupFiles();
|
||||||
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
|
||||||
|
|||||||
8
public/update_linux.sh
Normal file
8
public/update_linux.sh
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
sleep 5
|
||||||
|
chmod +x "$1"
|
||||||
|
"$1"&
|
||||||
|
|
||||||
|
sleep 1
|
||||||
|
rm -f "$0"
|
||||||
@@ -3,6 +3,7 @@ const path = require('path');
|
|||||||
const os = require('os');
|
const os = require('os');
|
||||||
const axios = require('axios/index');
|
const axios = require('axios/index');
|
||||||
const exec = require('child_process').exec;
|
const exec = require('child_process').exec;
|
||||||
|
const execFile = require('child_process').execFile;
|
||||||
const spawn = require('child_process').spawn;
|
const spawn = require('child_process').spawn;
|
||||||
const Constants = require('./constants');
|
const Constants = require('./constants');
|
||||||
const RandomString = require('randomstring');
|
const RandomString = require('randomstring');
|
||||||
@@ -547,8 +548,7 @@ module.exports.verifySignature = (file, signatureFile, publicKeyFile) => {
|
|||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
const executeVerify = openssl => {
|
const executeVerify = openssl => {
|
||||||
//openssl dgst -sha256 -verify $pubkeyfile -signature signature.sig file
|
//openssl dgst -sha256 -verify $pubkeyfile -signature signature.sig file
|
||||||
const command = '"' + openssl + '" dgst -sha256 -verify "' + publicKeyFile + '" -signature "' + signatureFile + '"';
|
execFile(openssl, ['dgst', '-sha256', '-verify', publicKeyFile, '-signature', signatureFile], res => {
|
||||||
exec(command, res => {
|
|
||||||
if (res.code !== 0) {
|
if (res.code !== 0) {
|
||||||
reject(res);
|
reject(res);
|
||||||
} else {
|
} else {
|
||||||
@@ -571,14 +571,15 @@ module.exports.verifySignature = (file, signatureFile, publicKeyFile) => {
|
|||||||
if (err) {
|
if (err) {
|
||||||
reject(err);
|
reject(err);
|
||||||
} else {
|
} else {
|
||||||
const openssl = path.join(item.value(), 'bin', 'openssl.exe');
|
executeVerify(path.join(item.value(), 'bin', 'openssl.exe'));
|
||||||
executeVerify(openssl);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
reject('Failed to locate \'openssl.exe\'');
|
reject('Failed to locate \'openssl.exe\'');
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
} else if (os.platform() === 'linux') {
|
||||||
|
executeVerify('openssl');
|
||||||
} else {
|
} else {
|
||||||
reject('Platform not supported: ' + os.platform())
|
reject('Platform not supported: ' + os.platform())
|
||||||
}
|
}
|
||||||
@@ -587,13 +588,32 @@ module.exports.verifySignature = (file, signatureFile, publicKeyFile) => {
|
|||||||
|
|
||||||
module.exports.verifyHash = (file, hash) => {
|
module.exports.verifyHash = (file, hash) => {
|
||||||
return new Promise((resolve, reject) => {
|
return new Promise((resolve, reject) => {
|
||||||
if (os.platform() === 'darwin') {
|
const platform = os.platform();
|
||||||
reject('Not implemented');
|
let command;
|
||||||
} else if (os.platform() === 'linux') {
|
let args;
|
||||||
reject('Not implemented');
|
if (platform === 'darwin') {
|
||||||
|
command = 'shasum';
|
||||||
|
args = ['-b', '-a', '256', file];
|
||||||
|
} else if (platform === 'linux') {
|
||||||
|
command = 'sha256sum';
|
||||||
|
args = ['-b', file, '-z'];
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
reject('Platform not supported: ' + os.platform())
|
reject('Platform not supported: ' + os.platform())
|
||||||
}
|
}
|
||||||
|
if (command) {
|
||||||
|
execFile(command, args, (err, stdout) => {
|
||||||
|
if (err) {
|
||||||
|
reject(err);
|
||||||
|
} else {
|
||||||
|
const hash2 = stdout.split(' ')[0].trim().toLowerCase();
|
||||||
|
if (hash2 === hash.toLowerCase()) {
|
||||||
|
resolve();
|
||||||
|
} else {
|
||||||
|
reject('Checksum failed for file');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
@@ -15,7 +15,7 @@
|
|||||||
--heading_other_text_color: var(--heading_text_color);
|
--heading_other_text_color: var(--heading_text_color);
|
||||||
--text_color_transition: color 0.3s;
|
--text_color_transition: color 0.3s;
|
||||||
|
|
||||||
--default_font_size: 4vmin
|
--default_font_size: 4.8vmin
|
||||||
}
|
}
|
||||||
|
|
||||||
* {
|
* {
|
||||||
|
|||||||
Reference in New Issue
Block a user