Reuse additionalAllowedPackets object

This commit is contained in:
Daniel Huigens 2025-06-06 13:10:39 +02:00
parent 5d8d7b5175
commit 1aedcbe5b6
No known key found for this signature in database
GPG Key ID: CB064A128FA90686
3 changed files with 43 additions and 43 deletions

View File

@ -1,5 +1,4 @@
import enums from '../enums';
import type { Config } from '../config';
export class GrammarError extends Error {
constructor(...params: any[]) {
@ -39,11 +38,10 @@ export class MessageGrammarValidator {
* NB: padding, marker and unknown packets are expected to already be filtered out on parsing,
* and are not accepted by `recordPacket`.
* @param packet - packet to validate
* @param config - needed to determine the `additionalAllowedPackets`: these are allowed anywhere in the sequence, except they cannot precede a OPS packet
* @param additionalAllowedPackets - object containing packets which are allowed anywhere in the sequence, except they cannot precede a OPS packet
* @throws {GrammarError} on invalid `packet` input
*/
recordPacket(packet: enums.packet, config: Config) {
const additionalAllowedPacketsTags = new Set(config.additionalAllowedPackets.map(c => c.tag));
recordPacket(packet: enums.packet, additionalAllowedPackets?: { [key in enums.packet]: any }) {
switch (this.state) {
case MessageType.EmptyMessage:
case MessageType.StandaloneAdditionalAllowedData:
@ -79,7 +77,7 @@ export class MessageGrammarValidator {
this.state = MessageType.EncryptedSessionKeys;
return;
default:
if (!additionalAllowedPacketsTags.has(packet)) {
if (!additionalAllowedPackets?.[packet]) {
throw new GrammarError(`Unexpected packet ${packet} in state ${this.state}`);
}
this.state = MessageType.StandaloneAdditionalAllowedData;
@ -94,7 +92,7 @@ export class MessageGrammarValidator {
this.state = MessageType.PlaintextOrEncryptedData;
return;
default:
if (!additionalAllowedPacketsTags.has(packet)) {
if (!additionalAllowedPackets?.[packet]) {
throw new GrammarError(`Unexpected packet ${packet} in state ${this.state}`);
}
this.state = MessageType.PlaintextOrEncryptedData;
@ -118,7 +116,7 @@ export class MessageGrammarValidator {
this.state = MessageType.PlaintextOrEncryptedData;
return;
default:
if (!additionalAllowedPacketsTags.has(packet)) {
if (!additionalAllowedPackets?.[packet]) {
throw new GrammarError(`Unexpected packet ${packet} in state ${this.state}`);
}
this.state = MessageType.EncryptedSessionKeys;

View File

@ -70,8 +70,10 @@ class PacketList extends Array {
* @async
*/
async read(bytes, allowedPackets, config = defaultConfig, grammarValidator = null, delayErrors = false) {
let additionalAllowedPackets;
if (config.additionalAllowedPackets.length) {
allowedPackets = { ...allowedPackets, ...util.constructAllowedPackets(config.additionalAllowedPackets) };
additionalAllowedPackets = util.constructAllowedPackets(config.additionalAllowedPackets);
allowedPackets = { ...allowedPackets, ...additionalAllowedPackets };
}
this.stream = streamTransformPair(bytes, async (readable, writable) => {
const reader = streamGetReader(readable);
@ -95,7 +97,7 @@ class PacketList extends Array {
// Unknown packets throw in the call above, we ignore them
// in the grammar checker.
try {
grammarValidator?.recordPacket(parsed.tag, config);
grammarValidator?.recordPacket(parsed.tag, additionalAllowedPackets);
} catch (e) {
if (config.enforceGrammar) {
throw e;

View File

@ -1379,85 +1379,85 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu
it('valid nested signed messages should be valid', () => {
// Sig | OPS | Literal | Sig
const m1 = new MessageGrammarValidator();
m1.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets: [] });
m1.recordPacket(openpgp.enums.packet.onePassSignature, { additionalAllowedPackets: [] });
m1.recordPacket(openpgp.enums.packet.literalData, { additionalAllowedPackets: [] });
m1.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets: [] });
m1.recordPacket(openpgp.enums.packet.signature);
m1.recordPacket(openpgp.enums.packet.onePassSignature);
m1.recordPacket(openpgp.enums.packet.literalData);
m1.recordPacket(openpgp.enums.packet.signature);
expect(() => m1.recordEnd()).to.not.throw();
// OPS | Sig | Literal | Sig
const m2 = new MessageGrammarValidator();
m2.recordPacket(openpgp.enums.packet.onePassSignature, { additionalAllowedPackets: [] });
m2.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets: [] });
m2.recordPacket(openpgp.enums.packet.literalData, { additionalAllowedPackets: [] });
m2.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets: [] });
m2.recordPacket(openpgp.enums.packet.onePassSignature);
m2.recordPacket(openpgp.enums.packet.signature);
m2.recordPacket(openpgp.enums.packet.literalData);
m2.recordPacket(openpgp.enums.packet.signature);
expect(() => m2.recordEnd()).to.not.throw();
// OPS | Sig | Literal - should throw due to missing trailing signature
const m3 = new MessageGrammarValidator();
m3.recordPacket(openpgp.enums.packet.onePassSignature, { additionalAllowedPackets: [] });
m3.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets: [] });
m3.recordPacket(openpgp.enums.packet.literalData, { additionalAllowedPackets: [] });
m3.recordPacket(openpgp.enums.packet.onePassSignature);
m3.recordPacket(openpgp.enums.packet.signature);
m3.recordPacket(openpgp.enums.packet.literalData);
expect(() => m3.recordEnd()).to.throw();
// Sig - should throw due to standalone signature packet
const m4 = new MessageGrammarValidator();
m4.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets: [] });
m4.recordPacket(openpgp.enums.packet.signature);
expect(() => m3.recordEnd()).to.throw();
// ESK | Sig | SEIPD - should throw
const m5 = new MessageGrammarValidator();
m5.recordPacket(openpgp.enums.packet.publicKeyEncryptedSessionKey, { additionalAllowedPackets: [] });
expect(() => m5.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets: [] })).to.throw();
m5.recordPacket(openpgp.enums.packet.publicKeyEncryptedSessionKey);
expect(() => m5.recordPacket(openpgp.enums.packet.signature)).to.throw();
});
it('standalone additional allowed packets should be valid', () => {
const additionalAllowedPackets = [openpgp.PublicKeyPacket];
const additionalAllowedPackets = { [openpgp.PublicKeyPacket.tag]: openpgp.PublicKeyPacket };
// Sig | OPS | PublicKeyPacket | Sig
const m1 = new MessageGrammarValidator();
m1.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets });
m1.recordPacket(openpgp.enums.packet.onePassSignature, { additionalAllowedPackets });
m1.recordPacket(openpgp.enums.packet.publicKey, { additionalAllowedPackets });
m1.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets });
m1.recordPacket(openpgp.enums.packet.signature, additionalAllowedPackets);
m1.recordPacket(openpgp.enums.packet.onePassSignature, additionalAllowedPackets);
m1.recordPacket(openpgp.enums.packet.publicKey, additionalAllowedPackets);
m1.recordPacket(openpgp.enums.packet.signature, additionalAllowedPackets);
expect(() => m1.recordEnd()).to.not.throw();
// OPS | Sig | PublicKeyPacket | Sig
const m2 = new MessageGrammarValidator();
m2.recordPacket(openpgp.enums.packet.onePassSignature, { additionalAllowedPackets });
m2.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets });
m2.recordPacket(openpgp.enums.packet.publicKey, { additionalAllowedPackets });
m2.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets });
m2.recordPacket(openpgp.enums.packet.onePassSignature, additionalAllowedPackets);
m2.recordPacket(openpgp.enums.packet.signature, additionalAllowedPackets);
m2.recordPacket(openpgp.enums.packet.publicKey, additionalAllowedPackets);
m2.recordPacket(openpgp.enums.packet.signature, additionalAllowedPackets);
expect(() => m2.recordEnd()).to.not.throw();
// standalone PublicKeyPacket
const m3 = new MessageGrammarValidator();
m3.recordPacket(openpgp.enums.packet.publicKey, { additionalAllowedPackets });
m3.recordPacket(openpgp.enums.packet.publicKey, additionalAllowedPackets);
expect(() => m3.recordEnd()).to.not.throw();
// OPS | Sig | PublicKey - should throw due to missing trailing signature
const m4 = new MessageGrammarValidator();
m4.recordPacket(openpgp.enums.packet.onePassSignature, { additionalAllowedPackets });
m4.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets });
m4.recordPacket(openpgp.enums.packet.publicKey, { additionalAllowedPackets });
m4.recordPacket(openpgp.enums.packet.onePassSignature, additionalAllowedPackets);
m4.recordPacket(openpgp.enums.packet.signature, additionalAllowedPackets);
m4.recordPacket(openpgp.enums.packet.publicKey, additionalAllowedPackets);
expect(() => m4.recordEnd()).to.throw();
// Sig | PublicKey | Sig | PublicKey - should throw
const m5 = new MessageGrammarValidator();
m5.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets });
m5.recordPacket(openpgp.enums.packet.publicKey, { additionalAllowedPackets });
expect(() => m5.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets })).to.throw();
m5.recordPacket(openpgp.enums.packet.signature, additionalAllowedPackets);
m5.recordPacket(openpgp.enums.packet.publicKey, additionalAllowedPackets);
expect(() => m5.recordPacket(openpgp.enums.packet.signature, additionalAllowedPackets)).to.throw();
// Sig | PublicKey | OPS | PublicKey | Sig - should throw
const m6 = new MessageGrammarValidator();
m6.recordPacket(openpgp.enums.packet.signature, { additionalAllowedPackets });
m6.recordPacket(openpgp.enums.packet.publicKey, { additionalAllowedPackets });
expect(() => m6.recordPacket(openpgp.enums.packet.onePassSignature, { additionalAllowedPackets })).to.throw();
m6.recordPacket(openpgp.enums.packet.signature, additionalAllowedPackets);
m6.recordPacket(openpgp.enums.packet.publicKey, additionalAllowedPackets);
expect(() => m6.recordPacket(openpgp.enums.packet.onePassSignature, additionalAllowedPackets)).to.throw();
});
it('standalone disallowed packets should not be valid', () => {
// standalone PublicKeyPacket
const m1 = new MessageGrammarValidator();
expect(() => m1.recordPacket(openpgp.enums.packet.publicKey, { additionalAllowedPackets: [] })).to.throw();
expect(() => m1.recordPacket(openpgp.enums.packet.publicKey)).to.throw();
});
});