Skip to content

Commit

Permalink
Added checksum validation for downloades packages. Use HTTPS endpoint…
Browse files Browse the repository at this point in the history
… too.
  • Loading branch information
tomas committed Apr 29, 2014
1 parent 5345e2e commit 021ca75
Showing 1 changed file with 78 additions and 41 deletions.
119 changes: 78 additions & 41 deletions lib/conf/package.js
Original file line number Diff line number Diff line change
@@ -1,18 +1,17 @@
var fs = require('fs'),
path = require('path'),
needle = require('needle'),
system = require('./../system'),
rmdir = require('./../utils/rmdir'),
os_name = system.os_name;

var releases_host = 'http://s3.amazonaws.com',
var fs = require('fs'),
path = require('path'),
needle = require('needle'),
createHash = require('crypto').createHash,
system = require('./../system'),
rmdir = require('./../utils/rmdir'),
os_name = system.os_name;

var releases_host = 'https://s3.amazonaws.com',
releases_url = releases_host + '/prey-releases/node-client/',
latest_text = 'latest.txt',
latest_checksums = 'latest/shasums.txt',
checksums = 'shasums.json',
package_format = '.zip';

// TODO: validate checksums

var log = function(str) {
if (process.stdout.writable)
process.stdout.write(str + '\n');
Expand All @@ -25,6 +24,43 @@ var is_greater_than = function(first, second){
return a > b ? true : false;
};

// returns sha1 checksum for file
var checksum_for = function(file, cb) {
var error,
hash = createHash('sha1'),
stream = fs.ReadStream(file);

stream.on('error', function(e) {
if (!error) cb(e);
error = e;
})

stream.on('data', function(d) {
hash.update(d);
});

stream.on('end', function() {
if (!error) cb(null, hash.digest('hex'));
});
}

var verify_checksum = function(url, filename, file, cb) {
log('Fetching checksum: ' + url);
needle.get(url, { parse: true }, function(err, resp) {
if (err) return cb(err);

var checksum = resp.body[filename];
if (!checksum)
return cb(new Error('Unable to retrieve checksum for ' + filename));

log('Got checksum from remote: ' + checksum + '. Calculating file hash...');
checksum_for(file, function(err, res) {
var valid = (res && res.trim() == checksum.trim());
cb(err, valid);
})
})
}

var package = module.exports;

package.new_version_available = function(current, cb) {
Expand All @@ -39,46 +75,33 @@ package.new_version_available = function(current, cb) {
package.get_upstream_version = function(cb){
// log('Checking latest version...');

var done = function(ver) {
// log('Latest upstream version: ' + ver);
cb(null, ver);
}

needle.get(releases_url + latest_text, function(err, resp, body){
if (!err && body != '')
return done(body.toString().trim());

needle.get(releases_url + latest_checksums, function(err, resp, body){
if (err) return cb(err);

var match = body.toString().match(/prey-([\d\.]+)\.zip/);
if (!match)
return cb(new Error('Unable to determine latest version from ' + latest_checksums))
needle.get(releases_url + latest_text, function(err, resp, body) {
var ver = body && body.toString().trim();
log('Latest upstream version: ' + ver);

done(match[1]);
});
cb(err, ver);
});

}

package.get_latest = function(current_version, dest, cb){
package.new_version_available(current_version, function(err, version){
package.new_version_available(current_version, function(err, version) {
if (err || !version)
return cb(err || new Error('Already running latest version.'));

if (fs.existsSync(path.join(dest, version)))
return cb(new Error('Version ' + version + ' already installed.'));

package.get_version(version, dest, function(err){
package.get_version(version, dest, function(err) {
cb(err, version);
});
});
};

package.get_version = function(version, dest, cb){
package.get_version = function(version, dest, cb) {
log('Fetching version ' + version);
package.download_release(version, function(err, file){
package.download_release(version, function(err, file) {
if (err) return cb(err);

package.install(file, dest, function(err, installed_version) {
fs.unlink(file, function() {
cb(err, installed_version);
Expand All @@ -87,23 +110,37 @@ package.get_version = function(version, dest, cb){
});
}

package.download_release = function(version, cb){
var arch = process.arch == 'x64' ? 'x64' : 'x86';
var release = ['prey', os_name, version, arch].join('-') + package_format;
var host_path = releases_url + version + '/';
package.download(host_path + release, cb);
package.download_release = function(version, cb) {

var arch = process.arch == 'x64' ? 'x64' : 'x86',
release = ['prey', os_name, version, arch].join('-') + package_format,
host_path = releases_url + version + '/';

package.download(host_path + release, function(err, file) {

verify_checksum(host_path + checksums, release, file, function(err, valid) {
if (err || !valid)
return cb && cb(err || new Error('Invalid checksum for file: ' + release));

log('File checksum is valid! ' + file)
return cb && cb(null, file);
})
});
}

package.download = function(url, cb){
package.download = function(url, cb) {
log('Downloading package: ' + url);
var file = system.tempfile_path(path.basename(url));

needle.get(url, { output: file }, function(err, resp, data){
return cb(null, file);

needle.get(url, { output: file }, function(err, resp, data) {

if (err || resp.statusCode != 200)
return cb && cb(err || new Error('Unexpected response: \n\n' + data.toString()));

fs.exists(file, function(exists) {
if (!exists) return cb(new Error('File not found!'));
if (!exists) return cb && cb(new Error('File not found!'));

log('Got file: ' + file)
return cb && cb(null, file);
Expand Down

0 comments on commit 021ca75

Please sign in to comment.