Commit 9120ef6e authored by Cédric Moreau's avatar Cédric Moreau

Add WoT stability checking before accepting a block with newcomers

parent 0ed0158d
...@@ -197,6 +197,18 @@ function KeyHelper (packetList) { ...@@ -197,6 +197,18 @@ function KeyHelper (packetList) {
return certifs; return certifs;
}; };
this.getCertificationsFromSignatory = function (newcomer){
var primaryUser = key.getPrimaryUser();
var certifs = new PacketList();
if (primaryUser) {
(primaryUser.user.otherCertifications || []).forEach(function(oCert){
if (newcomer.match(new RegExp(oCert.issuerKeyId.toHex().toUpperCase() + '$')))
certifs.push(oCert);
});
}
return certifs;
};
// Give base64 encoded signing subkey packets (subkey + binding) // Give base64 encoded signing subkey packets (subkey + binding)
this.getBase64subkeys = function (){ this.getBase64subkeys = function (){
var bSubkeys = []; var bSubkeys = [];
......
...@@ -55,6 +55,10 @@ function GenericParser (captures, multipleLinesFields, rawerFunc, onError) { ...@@ -55,6 +55,10 @@ function GenericParser (captures, multipleLinesFields, rawerFunc, onError) {
error = 'Document has unkown fields or wrong line ending format'; error = 'Document has unkown fields or wrong line ending format';
if (error) { if (error) {
console.log(error); console.log(error);
// console.log('-----------------');
// console.log('Written:', { str: str });
// console.log('Extract:', { raw: raw });
// console.log('-----------------');
} }
} }
if (typeof done == 'function') if (typeof done == 'function')
......
...@@ -120,7 +120,7 @@ function extractKeyChanges(raw) { ...@@ -120,7 +120,7 @@ function extractKeyChanges(raw) {
if (line.match(/^#####----(F|N|U|L|B):[A-Z0-9]{40}----#####$/)) { if (line.match(/^#####----(F|N|U|L|B):[A-Z0-9]{40}----#####$/)) {
// New key block // New key block
if (currentKC) if (currentKC)
rawKeychanges.push(currentKC); rawKeychanges.push(unix2dos(currentKC));
currentKC = line + '\n'; currentKC = line + '\n';
} else { } else {
// Adding to current // Adding to current
...@@ -128,7 +128,7 @@ function extractKeyChanges(raw) { ...@@ -128,7 +128,7 @@ function extractKeyChanges(raw) {
} }
}); });
if (currentKC) if (currentKC)
rawKeychanges.push(currentKC); rawKeychanges.push(unix2dos(currentKC));
rawKeychanges.forEach(function(kc){ rawKeychanges.forEach(function(kc){
var parsers = require('./.'); var parsers = require('./.');
var obj = parsers.parseKeychange().syncWrite(kc); var obj = parsers.parseKeychange().syncWrite(kc);
......
...@@ -13,9 +13,9 @@ function KeychangeParser (onError) { ...@@ -13,9 +13,9 @@ function KeychangeParser (onError) {
var captures = [ var captures = [
{prop: "type", regexp: /#####----([FNULB]):[A-Z0-9]{40}----#####/}, {prop: "type", regexp: /#####----([FNULB]):[A-Z0-9]{40}----#####/},
{prop: "fingerprint", regexp: /#####----[FNULB]:([A-Z0-9]{40})----#####/}, {prop: "fingerprint", regexp: /#####----[FNULB]:([A-Z0-9]{40})----#####/},
{prop: "keypackets", regexp: /KeyPackets:\n([\s\S]*?)[a-zA-Z]+:/, parser: extractBase64Lines}, {prop: "keypackets", regexp: /KeyPackets:\n([\s\S]*)/, parser: extractBase64Lines},
{prop: "certpackets", regexp: /CertificationPackets:\n([\s\S]*?)[a-zA-Z]+:/, parser: extractBase64Lines}, {prop: "certpackets", regexp: /CertificationPackets:\n([\s\S]*)/, parser: extractBase64Lines},
{prop: "membership", regexp: /Membership:\n([\s\S]*)/, parser: extractMembership}, {prop: "membership", regexp: /Membership:\n([\s\S]*)/, parser: extractMembership},
]; ];
var multilineFields = []; var multilineFields = [];
GenericParser.call(this, captures, multilineFields, rawer.getKeychange, onError); GenericParser.call(this, captures, multilineFields, rawer.getKeychange, onError);
...@@ -50,9 +50,12 @@ function extractBase64Lines(raw) { ...@@ -50,9 +50,12 @@ function extractBase64Lines(raw) {
var validLines = ""; var validLines = "";
var splits = raw.split(/\n/); var splits = raw.split(/\n/);
var lines = splits.slice(0, splits.length - 1); var lines = splits.slice(0, splits.length - 1);
var lineOfBlock = true;
lines.forEach(function(line){ lines.forEach(function(line){
if (line.match(/^[A-Za-z0-9\/+=]{1,64}$/)) { if (lineOfBlock && line.match(/^[A-Za-z0-9\/+=]{1,64}$/)) {
validLines += line + '\n'; validLines += line + '\n';
} else {
lineOfBlock = false;
} }
}); });
return validLines; return validLines;
......
...@@ -13,6 +13,7 @@ var KeySchema = new Schema({ ...@@ -13,6 +13,7 @@ var KeySchema = new Schema({
distanced: [String], // Array of distanced keys fingerprints distanced: [String], // Array of distanced keys fingerprints
certifs: [String], // Array of md5 hashes of packets to integrate certifs: [String], // Array of md5 hashes of packets to integrate
subkeys: [String], // Array of md5 hashes of packets to integrate subkeys: [String], // Array of md5 hashes of packets to integrate
signatories: [String], // Array of md5 hashes of packets to integrate
created: { type: Date, default: Date.now }, created: { type: Date, default: Date.now },
updated: { type: Date, default: Date.now } updated: { type: Date, default: Date.now }
}); });
...@@ -118,6 +119,11 @@ KeySchema.statics.getMembers = function(done){ ...@@ -118,6 +119,11 @@ KeySchema.statics.getMembers = function(done){
Key.find({ member: true }, done); Key.find({ member: true }, done);
}; };
KeySchema.statics.findWhereSignatory = function(signatory, done){
var Key = this.model('Key');
Key.find({ signatories: new RegExp(signatory.substring(24) + '$') }, done);
};
KeySchema.statics.addMember = function(fingerprint, done){ KeySchema.statics.addMember = function(fingerprint, done){
var Key = this.model('Key'); var Key = this.model('Key');
Key.update({ fingerprint: fingerprint }, { member: true }, function (err) { Key.update({ fingerprint: fingerprint }, { member: true }, function (err) {
......
...@@ -43,14 +43,10 @@ LinkSchema.statics.unobsoletesAllLinks = function (done) { ...@@ -43,14 +43,10 @@ LinkSchema.statics.unobsoletesAllLinks = function (done) {
/** /**
* Mark as obsolete the links with an age equal to or below a given date * Mark as obsolete the links with an age equal to or below a given date
**/ **/
LinkSchema.statics.isStillOver3Steps = function (keyToKick, newLinks, done) { LinkSchema.statics.isStillOver3Steps = function (fpr, ofMembers, newLinks, done) {
var Link = this.model('Link'); var Link = this.model('Link');
var fpr = keyToKick.fingerprint; var newCertifiers = newLinks[fpr] || [];
var newCertifiers = newLinks[fpr]; var remainingKeys = ofMembers.slice();
var remainingKeys = [];
keyToKick.distanced.forEach(function(m){
remainingKeys.push(m);
});
// Without self // Without self
remainingKeys = _(remainingKeys).difference([fpr]); remainingKeys = _(remainingKeys).difference([fpr]);
var dist1Links = []; var dist1Links = [];
...@@ -66,7 +62,7 @@ LinkSchema.statics.isStillOver3Steps = function (keyToKick, newLinks, done) { ...@@ -66,7 +62,7 @@ LinkSchema.statics.isStillOver3Steps = function (keyToKick, newLinks, done) {
Link.find({ target: fpr, obsolete: false }, function (err, links) { Link.find({ target: fpr, obsolete: false }, function (err, links) {
dist1Links = []; dist1Links = [];
links.forEach(function(lnk){ links.forEach(function(lnk){
dist1Links.push(lnk.fingerprint); dist1Links.push(lnk.source);
}); });
// Add new certifiers as distance 1 links // Add new certifiers as distance 1 links
dist1Links = _(dist1Links.concat(newCertifiers)).uniq(); dist1Links = _(dist1Links.concat(newCertifiers)).uniq();
...@@ -82,6 +78,12 @@ LinkSchema.statics.isStillOver3Steps = function (keyToKick, newLinks, done) { ...@@ -82,6 +78,12 @@ LinkSchema.statics.isStillOver3Steps = function (keyToKick, newLinks, done) {
async.forEachSeries(remainingKeys, function(member, callback){ async.forEachSeries(remainingKeys, function(member, callback){
// Exists distance 1 link? // Exists distance 1 link?
async.detect(dist1Links, function (dist1member, callbackDist1) { async.detect(dist1Links, function (dist1member, callbackDist1) {
// Look in newLinks
var signatories = newLinks[dist1member];
if (~signatories.indexOf(member)) {
callbackDist1(true);
return;
}
// dist1member signed 'fpr', so here we look for (member => dist1member => fpr sigchain) // dist1member signed 'fpr', so here we look for (member => dist1member => fpr sigchain)
Link.find({ source: member, target: dist1member, obsolete: false }, function (err, links) { Link.find({ source: member, target: dist1member, obsolete: false }, function (err, links) {
if (links && links.length > 0) { if (links && links.length > 0) {
...@@ -112,19 +114,34 @@ LinkSchema.statics.isStillOver3Steps = function (keyToKick, newLinks, done) { ...@@ -112,19 +114,34 @@ LinkSchema.statics.isStillOver3Steps = function (keyToKick, newLinks, done) {
async.waterfall([ async.waterfall([
function (next){ function (next){
// Step 1. Detect distance 1 members from current member (potential dist 2 from 'fpr') // Step 1. Detect distance 1 members from current member (potential dist 2 from 'fpr')
// Look in database
Link.find({ source: member, obsolete: false }, function (err, links) { Link.find({ source: member, obsolete: false }, function (err, links) {
dist2Links = []; dist2Links = [];
links.forEach(function(lnk){ links.forEach(function(lnk){
dist2Links.push(lnk.fingerprint); dist2Links.push(lnk.source);
}); });
next(err); next(err);
}); });
// Look in newLinks
_(newLinks).keys().forEach(function(signed){
newLinks[signed].forEach(function(signatories){
if (~signatories.indexOf(member)) {
dist2links.push(signed);
}
});
});
}, },
function (next){ function (next){
// Step 2. Detect links between distance 2 & distance 1 members // Step 2. Detect links between distance 2 & distance 1 members
async.detect(dist2Links, function (dist2member, callbackDist2) { async.detect(dist2Links, function (dist2member, callbackDist2) {
// Exists distance 1 link? // Exists distance 1 link?
async.detect(dist1Links, function (dist1member, callbackDist1) { async.detect(dist1Links, function (dist1member, callbackDist1) {
// Look in newLinks
var signatories = newLinks[dist1member];
if (~signatories.indexOf(dist2member)) {
callbackDist1(true);
return;
}
// dist1member signed 'fpr', so here we look for (member => dist1member => fpr sigchain) // dist1member signed 'fpr', so here we look for (member => dist1member => fpr sigchain)
Link.find({ source: dist2member, target: dist1member, obsolete: false }, function (err, links) { Link.find({ source: dist2member, target: dist1member, obsolete: false }, function (err, links) {
if (links && links.length > 0) { if (links && links.length > 0) {
......
This diff is collapsed.
...@@ -109,10 +109,17 @@ function PublicKeyService (conn, conf, KeyService) { ...@@ -109,10 +109,17 @@ function PublicKeyService (conn, conf, KeyService) {
var recordedSubKeys = _((keyT && keyT.getHashedSubkeyPackets()) || {}).keys(); var recordedSubKeys = _((keyT && keyT.getHashedSubkeyPackets()) || {}).keys();
var availableSubKeys = _(keyN.getHashedSubkeyPackets()).keys(); var availableSubKeys = _(keyN.getHashedSubkeyPackets()).keys();
// Compute new certifications // Compute new certifications
var hashedCertifs = keyN.getHashedCertifPackets();
var recordedCertifs = _((keyT && keyT.getHashedCertifPackets()) || {}).keys(); var recordedCertifs = _((keyT && keyT.getHashedCertifPackets()) || {}).keys();
var availableCertifs = _(keyN.getHashedCertifPackets()).keys(); var availableCertifs = _(hashedCertifs).keys();
key.subkeys = _(availableSubKeys).difference(recordedSubKeys); key.subkeys = _(availableSubKeys).difference(recordedSubKeys);
key.certifs = _(availableCertifs).difference(recordedCertifs); key.certifs = _(availableCertifs).difference(recordedCertifs);
key.signatories = [];
key.certifs.forEach(function(hash){
var certif = keyhelper.toPacketlist(hashedCertifs[hash]);
var issuer = certif[0].issuerKeyId.toHex().toUpperCase();
key.signatories.push(issuer);
});
key.eligible = keyN.hasValidUdid2(); key.eligible = keyN.hasValidUdid2();
key.save(function (err) { key.save(function (err) {
next(err); next(err);
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment