Use most recent primary user

This commit is contained in:
Daniel Huigens 2018-04-23 13:02:25 +02:00
parent 39c7374d70
commit ceec57672e

View File

@ -258,7 +258,7 @@ function getLatestSignature(signatures, date=new Date()) {
let signature = signatures[0]; let signature = signatures[0];
for (let i = 1; i < signatures.length; i++) { for (let i = 1; i < signatures.length; i++) {
if (signatures[i].created >= signature.created && if (signatures[i].created >= signature.created &&
signatures[i].created <= date) { (signatures[i].created <= date || date === null)) {
signature = signatures[i]; signature = signatures[i];
} }
} }
@ -453,9 +453,7 @@ Key.prototype.verifyPrimaryKey = async function(date=new Date()) {
return enums.keyStatus.invalid; return enums.keyStatus.invalid;
} }
// check for expiration time // check for expiration time
const currentTime = util.normalizeDate(date); if (isDataExpired(primaryKey, selfCertification, date)) {
if ((primaryKey.version === 3 && isDataExpired(primaryKey, null, date)) ||
(primaryKey.version === 4 && isDataExpired(primaryKey, selfCertification, date))) {
return enums.keyStatus.expired; return enums.keyStatus.expired;
} }
return enums.keyStatus.valid; return enums.keyStatus.valid;
@ -471,17 +469,11 @@ Key.prototype.getExpirationTime = async function() {
return getExpirationTime(this.primaryKey); return getExpirationTime(this.primaryKey);
} }
if (this.primaryKey.version === 4) { if (this.primaryKey.version === 4) {
const validUsers = await this.getValidUsers(null, true); const primaryUser = await this.getPrimaryUser(null);
let highest = null; const selfCert = primaryUser.selfCertification;
for (let i = 0; i < validUsers.length; i++) { const keyExpiry = getExpirationTime(this.primaryKey, selfCert);
const selfCert = validUsers[i].selfCertification; const sigExpiry = selfCert.getExpirationTime();
const current = Math.min(+getExpirationTime(this.primaryKey, selfCert), +selfCert.getExpirationTime()); return keyExpiry < sigExpiry ? keyExpiry : sigExpiry;
if (current === Infinity) {
return Infinity;
}
highest = current > highest ? current : highest;
}
return util.normalizeDate(highest);
} }
}; };
@ -495,62 +487,34 @@ Key.prototype.getExpirationTime = async function() {
* @async * @async
*/ */
Key.prototype.getPrimaryUser = async function(date=new Date()) { Key.prototype.getPrimaryUser = async function(date=new Date()) {
let validUsers = await this.getValidUsers(date);
if (!validUsers.length) {
return null;
}
// sort by primary user flag and signature creation time // sort by primary user flag and signature creation time
validUsers = validUsers.sort(function(a, b) { const primaryUser = this.users.map(function(user, index) {
const selfCertification = getLatestSignature(user.selfCertifications, date);
return { index, user, selfCertification };
}).sort(function(a, b) {
const A = a.selfCertification; const A = a.selfCertification;
const B = b.selfCertification; const B = b.selfCertification;
return (A.isPrimaryUserID - B.isPrimaryUserID) || (A.created - B.created); return (A.isPrimaryUserID - B.isPrimaryUserID) || (A.created - B.created);
}); }).pop();
return validUsers.pop(); const { user, selfCertification: cert } = primaryUser;
};
/**
* Returns an array containing all valid users for a key
* @param {Date} date use the given date for verification instead of the current time
* @param {bool} include users with expired certifications
* @returns {Promise<Array<{user: module:key.User,
* selfCertification: module:packet.Signature}>>} The valid user array
* @async
*/
Key.prototype.getValidUsers = async function(date=new Date(), allowExpired=false) {
const { primaryKey } = this;
const validUsers = [];
let lastCreated = null;
let lastPrimaryUserID = null;
// TODO replace when Promise.forEach is implemented
for (let i = 0; i < this.users.length; i++) {
const user = this.users[i];
if (!user.userId) { if (!user.userId) {
return; return null;
} }
const { primaryKey } = this;
const dataToVerify = { userid: user.userId , key: primaryKey }; const dataToVerify = { userid: user.userId , key: primaryKey };
const cert = getLatestSignature(user.selfCertifications);
// skip if certificate is not the most recent
if ((cert.isPrimaryUserID && cert.isPrimaryUserID < lastPrimaryUserID) ||
(!lastPrimaryUserID && cert.created < lastCreated)) {
continue;
}
// skip if certificates is invalid, revoked, or expired // skip if certificates is invalid, revoked, or expired
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
if (!(cert.verified || await cert.verify(primaryKey, dataToVerify))) { if (!(cert.verified || await cert.verify(primaryKey, dataToVerify))) {
continue; return null;
} }
// eslint-disable-next-line no-await-in-loop // eslint-disable-next-line no-await-in-loop
if (cert.revoked || await user.isRevoked(primaryKey, cert, null, date)) { if (cert.revoked || await user.isRevoked(primaryKey, cert, null, date)) {
continue; return null;
} }
if (!allowExpired && cert.isExpired(date)) { if (cert.isExpired(date)) {
continue; return null;
} }
lastPrimaryUserID = cert.isPrimaryUserID; return primaryUser;
lastCreated = cert.created;
validUsers.push({ index: i, user: user, selfCertification: cert });
}
return validUsers;
}; };
/** /**