#21: Add signature validation during installations [partial]

This commit is contained in:
Scott E. Graves
2019-04-17 21:16:57 -05:00
parent 77094630b2
commit 946b54f2e6
6 changed files with 92 additions and 68 deletions

View File

@@ -65,7 +65,8 @@
"build/**/*",
"node_modules/**/*",
"src/helpers.js",
"public/detect_linux.sh"
"public/detect_linux.sh",
"public/install_linux.sh"
],
"linux": {
"category": "Utility",

View File

@@ -16,6 +16,7 @@ require.extensions['.sh'] = function (module, filename) {
module.exports = fs.readFileSync(filename, 'utf8');
};
const detectScript = require('./detect_linux.sh');
const installScript = require('./update_linux.sh');
const publicKey =
'-----BEGIN PUBLIC KEY-----\n' +
'MIIEIjANBgkqhkiG9w0BAQEFAAOCBA8AMIIECgKCBAEKfZmq5mMAtD4kSt2Gc/5J\n' +
@@ -718,40 +719,38 @@ ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => {
}
};
if (os.platform() === 'win32') {
const executeInstall = () => {
helpers
.executeAsync(data.Source)
.then(() => {
cleanupFiles();
closeApplication();
})
.catch(error => {
let command;
let args;
const platform = os.platform();
if (platform === 'win32') {
command = data.Source;
} else if (platform === 'darwin') {
command = 'open';
args = ['-a', 'Finder', data.Source];
} 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();
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {
Source: data.Source,
}, error);
});
};
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();
}, e);
}
} 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 = () => {
helpers
.executeAsync('open', ['-a', 'Finder', data.Source])
.executeAsync(command, args)
.then(() => {
cleanupFiles();
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
.verifyHash(data.Source, data.Sha256)
.then(()=> {
@@ -779,22 +790,6 @@ ipcMain.on(Constants.IPC_Install_Upgrade, (event, data) => {
} else {
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 {
cleanupFiles();
standardIPCReply(event, Constants.IPC_Install_Upgrade_Reply, {

8
public/update_linux.sh Normal file
View File

@@ -0,0 +1,8 @@
#!/bin/sh
sleep 5
chmod +x "$1"
"$1"&
sleep 1
rm -f "$0"

View File

@@ -3,6 +3,7 @@ const path = require('path');
const os = require('os');
const axios = require('axios/index');
const exec = require('child_process').exec;
const execFile = require('child_process').execFile;
const spawn = require('child_process').spawn;
const Constants = require('./constants');
const RandomString = require('randomstring');
@@ -547,8 +548,7 @@ module.exports.verifySignature = (file, signatureFile, publicKeyFile) => {
return new Promise((resolve, reject) => {
const executeVerify = openssl => {
//openssl dgst -sha256 -verify $pubkeyfile -signature signature.sig file
const command = '"' + openssl + '" dgst -sha256 -verify "' + publicKeyFile + '" -signature "' + signatureFile + '"';
exec(command, res => {
execFile(openssl, ['dgst', '-sha256', '-verify', publicKeyFile, '-signature', signatureFile], res => {
if (res.code !== 0) {
reject(res);
} else {
@@ -571,14 +571,15 @@ module.exports.verifySignature = (file, signatureFile, publicKeyFile) => {
if (err) {
reject(err);
} else {
const openssl = path.join(item.value(), 'bin', 'openssl.exe');
executeVerify(openssl);
executeVerify(path.join(item.value(), 'bin', 'openssl.exe'));
}
});
} else {
reject('Failed to locate \'openssl.exe\'');
}
});
} else if (os.platform() === 'linux') {
executeVerify('openssl');
} else {
reject('Platform not supported: ' + os.platform())
}
@@ -587,13 +588,32 @@ module.exports.verifySignature = (file, signatureFile, publicKeyFile) => {
module.exports.verifyHash = (file, hash) => {
return new Promise((resolve, reject) => {
if (os.platform() === 'darwin') {
reject('Not implemented');
} else if (os.platform() === 'linux') {
reject('Not implemented');
const platform = os.platform();
let command;
let args;
if (platform === 'darwin') {
command = 'shasum';
args = ['-b', '-a', '256', file];
} else if (platform === 'linux') {
command = 'sha256sum';
args = ['-b', file, '-z'];
}
else {
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');
}
}
});
}
});
};

View File

@@ -15,7 +15,7 @@
--heading_other_text_color: var(--heading_text_color);
--text_color_transition: color 0.3s;
--default_font_size: 4vmin
--default_font_size: 4.8vmin
}
* {