From c820c48595e9623971bcedc1166639ee86274ccd Mon Sep 17 00:00:00 2001 From: larabr <7375870+larabr@users.noreply.github.com> Date: Thu, 22 Jul 2021 16:32:00 +0200 Subject: [PATCH] Allow to ignore malformed packets --- openpgp.d.ts | 3 ++- src/config/config.js | 10 +++++++--- src/packet/packetlist.js | 5 +++-- test/general/config.js | 12 ++++++------ test/general/packet.js | 21 ++++++++++----------- 5 files changed, 28 insertions(+), 23 deletions(-) diff --git a/openpgp.d.ts b/openpgp.d.ts index 58eccfeec..9e975cb19 100644 --- a/openpgp.d.ts +++ b/openpgp.d.ts @@ -321,7 +321,8 @@ interface Config { minRSABits: number; passwordCollisionCheck: boolean; revocationsExpire: boolean; - tolerant: boolean; + ignoreUnsupportedPackets: boolean; + ignoreMalformedPackets: boolean; versionString: string; commentString: string; allowInsecureDecryptionWithSigningKeys: boolean; diff --git a/src/config/config.js b/src/config/config.js index 25c878d4c..44579f5b1 100644 --- a/src/config/config.js +++ b/src/config/config.js @@ -136,10 +136,14 @@ export default { minBytesForWebCrypto: 1000, /** * @memberof module:config - * @property {Boolean} tolerant Ignore unsupported/unrecognizable packets instead of throwing an error + * @property {Boolean} ignoreUnsupportedPackets Ignore unsupported/unrecognizable packets on parsing instead of throwing an error */ - tolerant: true, - + ignoreUnsupportedPackets: true, + /** + * @memberof module:config + * @property {Boolean} ignoreMalformedPackets Ignore malformed packets on parsing instead of throwing an error + */ + ignoreMalformedPackets: false, /** * @memberof module:config * @property {Boolean} showVersion Whether to include {@link module:config/config.versionString} in armored messages diff --git a/src/packet/packetlist.js b/src/packet/packetlist.js index aee167b47..250316a14 100644 --- a/src/packet/packetlist.js +++ b/src/packet/packetlist.js @@ -82,8 +82,9 @@ class PacketList extends Array { await packet.read(parsed.packet, config); await writer.write(packet); } catch (e) { - const isTolerableError = config.tolerant && e instanceof UnsupportedError; - if (!isTolerableError || supportsStreaming(parsed.tag)) { + const throwUnsupportedError = !config.ignoreUnsupportedPackets && e instanceof UnsupportedError; + const throwMalformedError = !config.ignoreMalformedPackets && !(e instanceof UnsupportedError); + if (throwUnsupportedError || throwMalformedError || supportsStreaming(parsed.tag)) { // The packets that support streaming are the ones that contain message data. // Those are also the ones we want to be more strict about and throw on parse errors // (since we likely cannot process the message without these packets anyway). diff --git a/test/general/config.js b/test/general/config.js index 71f6005f0..2ba9daaf3 100644 --- a/test/general/config.js +++ b/test/general/config.js @@ -8,11 +8,11 @@ module.exports = () => describe('Custom configuration', function() { const message = await openpgp.readMessage({ armoredMessage }); message.packets.findPacket(openpgp.SymEncryptedSessionKeyPacket.tag).version = 1; // unsupported SKESK version - const config = { tolerant: true }; + const config = { ignoreUnsupportedPackets: true }; const parsedMessage = await openpgp.readMessage({ armoredMessage: message.armor(), config }); expect(parsedMessage.packets.length).to.equal(1); - config.tolerant = false; + config.ignoreUnsupportedPackets = false; await expect( openpgp.readMessage({ armoredMessage: message.armor(), config }) ).to.be.rejectedWith(/Version 1 of the SKESK packet is unsupported/); @@ -30,11 +30,11 @@ vAFM3jjrAQDgJPXsv8PqCrLGDuMa/2r6SgzYd03aw/xt1WM6hgUvhQD+J54Z const signature = await openpgp.readSignature({ armoredSignature }); signature.packets[0].signatureData[0] = 1; // set unsupported signature version - const config = { tolerant: true }; + const config = { ignoreUnsupportedPackets: true }; const parsedSignature = await openpgp.readSignature({ armoredSignature: signature.armor(), config }); expect(parsedSignature.packets.length).to.equal(0); - config.tolerant = false; + config.ignoreUnsupportedPackets = false; await expect( openpgp.readSignature({ armoredSignature: signature.armor(), config }) ).to.be.rejectedWith(/Version 1 of the signature packet is unsupported/); @@ -43,10 +43,10 @@ vAFM3jjrAQDgJPXsv8PqCrLGDuMa/2r6SgzYd03aw/xt1WM6hgUvhQD+J54Z it('openpgp.readKey', async function() { const { privateKey: armoredKey } = await openpgp.generateKey({ userIDs:[{ name:'test', email:'test@a.it' }] }); await expect( - openpgp.readKey({ armoredKey, config: { tolerant: false, maxUserIDLength: 2 } }) + openpgp.readKey({ armoredKey, config: { ignoreUnsupportedPackets: false, maxUserIDLength: 2 } }) ).to.be.rejectedWith(/User ID string is too long/); await expect( - openpgp.readKey({ armoredKey, config: { tolerant: true, maxUserIDLength: 2 } }) + openpgp.readKey({ armoredKey, config: { ignoreUnsupportedPackets: true, maxUserIDLength: 2 } }) ).to.be.rejectedWith(/User ID string is too long/); }); diff --git a/test/general/packet.js b/test/general/packet.js index e9458e275..e86b79fc0 100644 --- a/test/general/packet.js +++ b/test/general/packet.js @@ -950,7 +950,7 @@ V+HOQJQxXJkVRYa3QrFUehiMzTeqqMdgC6ZqJy7+ }); describe('PacketList parsing', function () { - it('Ignores unknown packet version with tolerant mode enabled', async function() { + it('Ignores unknown packet version with `config.ignoreUnsupportedPackets` enabled', async function() { const armoredSignature = `-----BEGIN PGP SIGNATURE----- iQFKBAEBCgA0FiEEdOyNPagqedqiXfEMa6Ve2Dq64bsFAlszXwQWHHRlc3Qtd2tk @@ -968,11 +968,11 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu signaturePacket.signatureData[0] = 1; packets.push(signaturePacket); const bytes = packets.write(); - const parsed = await openpgp.PacketList.fromBinary(bytes, allAllowedPackets, { ...openpgp.config, tolerant: true }); + const parsed = await openpgp.PacketList.fromBinary(bytes, allAllowedPackets, { ...openpgp.config, ignoreUnsupportedPackets: true }); expect(parsed.length).to.equal(0); }); - it('Throws on unknown packet version with tolerant mode disabled', async function() { + it('Throws on unknown packet version with `config.ignoreUnsupportedPackets` disabled', async function() { const armoredSignature = `-----BEGIN PGP SIGNATURE----- iQFKBAEBCgA0FiEEdOyNPagqedqiXfEMa6Ve2Dq64bsFAlszXwQWHHRlc3Qtd2tk @@ -991,7 +991,7 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu packets.push(signaturePacket); const bytes = packets.write(); await expect( - openpgp.PacketList.fromBinary(bytes, allAllowedPackets, { ...openpgp.config, tolerant: false }) + openpgp.PacketList.fromBinary(bytes, allAllowedPackets, { ...openpgp.config, ignoreUnsupportedPackets: false }) ).to.be.rejectedWith(/Version 1 of the signature packet is unsupported/); }); @@ -999,20 +999,19 @@ kePFjAnu9cpynKXu3usf8+FuBw2zLsg1Id1n7ttxoAte416KjBN9lFBt8mcu const packets = new openpgp.PacketList(); packets.push(new openpgp.LiteralDataPacket()); const bytes = packets.write(); - await expect(openpgp.PacketList.fromBinary(bytes, {}, { ...openpgp.config, tolerant: false })).to.be.rejectedWith(/Packet not allowed in this context/); - await expect(openpgp.PacketList.fromBinary(bytes, {}, { ...openpgp.config, tolerant: true })).to.be.rejectedWith(/Packet not allowed in this context/); + await expect(openpgp.PacketList.fromBinary(bytes, {}, { ...openpgp.config, ignoreUnsupportedPackets: false, ignoreMalformedPackets: false })).to.be.rejectedWith(/Packet not allowed in this context/); + await expect(openpgp.PacketList.fromBinary(bytes, {}, { ...openpgp.config, ignoreUnsupportedPackets: true, ignoreMalformedPackets: true })).to.be.rejectedWith(/Packet not allowed in this context/); }); - it('Throws on parsing errors even with tolerant mode enabled', async function () { + it('Throws on parsing errors `config.ignoreMalformedPackets` disabled', async function () { const packets = new openpgp.PacketList(); packets.push(openpgp.UserIDPacket.fromObject({ name:'test', email:'test@a.it' })); const bytes = packets.write(); await expect( - openpgp.PacketList.fromBinary(bytes, allAllowedPackets, { ...openpgp.config, maxUserIDLength: 2, tolerant: false }) - ).to.be.rejectedWith(/User ID string is too long/); - await expect( - openpgp.PacketList.fromBinary(bytes, allAllowedPackets, { ...openpgp.config, maxUserIDLength: 2, tolerant: true }) + openpgp.PacketList.fromBinary(bytes, allAllowedPackets, { ...openpgp.config, maxUserIDLength: 2, ignoreMalformedPackets: false }) ).to.be.rejectedWith(/User ID string is too long/); + const parsed = await openpgp.PacketList.fromBinary(bytes, allAllowedPackets, { ...openpgp.config, maxUserIDLength: 2, ignoreMalformedPackets: true }); + expect(parsed.length).to.equal(0); }); }); });