forked from svrjs/svrjs
117 lines
2.6 KiB
JavaScript
117 lines
2.6 KiB
JavaScript
'use strict';
|
|
|
|
var ocsp = require('../ocsp');
|
|
|
|
function Cache(options) {
|
|
this.options = options || {};
|
|
this.cache = {};
|
|
|
|
// Override methods
|
|
if (this.options.probe)
|
|
this.probe = this.options.probe;
|
|
if (this.options.store)
|
|
this.store = this.options.store;
|
|
if (this.options.filter)
|
|
this.filter = this.options.filter;
|
|
}
|
|
module.exports = Cache;
|
|
|
|
Cache.prototype.filter = function filter(url, callback) {
|
|
callback(null);
|
|
};
|
|
|
|
Cache.prototype.probe = function probe(id, callback) {
|
|
if (this.cache.hasOwnProperty(id))
|
|
callback(null, this.cache[id]);
|
|
else
|
|
callback(null, false);
|
|
};
|
|
|
|
Cache.prototype.store = function store(id, response, maxTime, callback) {
|
|
if (this.cache.hasOwnProperty(id))
|
|
clearTimeout(this.cache[id].timer);
|
|
var self = this;
|
|
this.cache[id] = {
|
|
response: response,
|
|
timer: setTimeout(function() {
|
|
delete self.cache[id];
|
|
}, maxTime)
|
|
};
|
|
|
|
callback(null, null);
|
|
};
|
|
|
|
Cache.prototype.request = function request(id, data, callback) {
|
|
var self = this;
|
|
|
|
function done(err, response) {
|
|
if (callback)
|
|
callback(err, response);
|
|
callback = null;
|
|
}
|
|
|
|
function onResponse(err, ocsp) {
|
|
if (err)
|
|
return done(err);
|
|
|
|
// Respond early
|
|
done(null, ocsp);
|
|
|
|
// Try parsing and caching response
|
|
self.getMaxStoreTime(ocsp, function(err, maxTime) {
|
|
if (err)
|
|
return;
|
|
|
|
self.store(id, ocsp, maxTime, function() {
|
|
// No-op
|
|
});
|
|
});
|
|
}
|
|
|
|
// Check that url isn't blacklisted
|
|
this.filter(data.url, function(err) {
|
|
if (err)
|
|
return done(err, null);
|
|
|
|
ocsp.utils.getResponse(data.url, data.ocsp, onResponse);
|
|
});
|
|
|
|
};
|
|
|
|
Cache.prototype.getMaxStoreTime = function getMaxStoreTime(response, callback) {
|
|
var basic;
|
|
try {
|
|
basic = ocsp.utils.parseResponse(response).value;
|
|
} catch (e) {
|
|
return callback(e);
|
|
}
|
|
|
|
// Not enough responses
|
|
if (basic.tbsResponseData.responses.length === 0)
|
|
return callback(new Error('No OCSP responses'));
|
|
|
|
var responses = basic.tbsResponseData.responses;
|
|
|
|
// Every response should be positive
|
|
var good = responses.every(function(response) {
|
|
return response.certStatus.type === 'good';
|
|
});
|
|
|
|
// No good - no cache
|
|
if (!good)
|
|
return callback(new Error('Some OCSP responses are not good'));
|
|
|
|
// Find minimum nextUpdate time
|
|
var nextUpdate = 0;
|
|
for (var i = 0; i < responses.length; i++) {
|
|
var response = responses[i];
|
|
var responseNext = response.nextUpdate;
|
|
if (!responseNext)
|
|
continue;
|
|
|
|
if (nextUpdate === 0 || nextUpdate > responseNext)
|
|
nextUpdate = responseNext;
|
|
}
|
|
|
|
return callback(null, Math.max(0, nextUpdate - new Date()));
|
|
};
|