def test_duplicate_resource(): res1 = PdfResources() res2 = PdfResources() res1[ResourceType.XOBJECT][pdf_name('/Bleh')] = generic.NullObject() res1[ResourceType.PATTERN][pdf_name('/Blih')] = generic.NullObject() res2[ResourceType.XOBJECT][pdf_name('/Bleh')] = generic.NullObject() res2[ResourceType.FONT][pdf_name('/Bluh')] = generic.NullObject() with pytest.raises(ResourceManagementError): res1 += res2
def test_object_free_no_override(): xrefs = [[ b'0 3', b'0000000000 65535 f', b'0000000100 00000 n', b'0000000200 00000 n' ], [b'0 2', b'0000000000 65535 f', b'0000000000 00001 f'], [b'0 2', b'0000000000 65535 f', b'0000000300 00001 n'], [b'0 2', b'0000000000 65535 f', b'0000000000 00002 f']] r = PdfFileReader(BytesIO(fmt_dummy_xrefs(xrefs))) assert r.xrefs.xref_sections == 4 assert r.xrefs[generic.Reference(1, 0)] == generic.NullObject() assert r.xrefs[generic.Reference(1, 1)] == generic.NullObject() assert generic.Reference(1, 0) in r.xrefs.refs_freed_in_revision(1) assert generic.Reference(1, 1) in r.xrefs.refs_freed_in_revision(3)
def test_sv_mdp_type(): sv_dict = fields.SigSeedValueSpec().as_pdf_object() assert '/MDP' not in sv_dict sv_dict = fields.SigSeedValueSpec( seed_signature_type=fields.SeedSignatureType(None)).as_pdf_object() assert sv_dict['/MDP'] == generic.DictionaryObject( {pdf_name('/P'): generic.NumberObject(0)}) sv_dict = fields.SigSeedValueSpec( seed_signature_type=fields.SeedSignatureType( fields.MDPPerm.NO_CHANGES)).as_pdf_object() assert sv_dict['/MDP'] == generic.DictionaryObject( {pdf_name('/P'): generic.NumberObject(1)}) sv_spec = fields.SigSeedValueSpec.from_pdf_object( generic.DictionaryObject({ pdf_name('/MDP'): generic.DictionaryObject({pdf_name('/P'): generic.NumberObject(0)}) })) assert sv_spec.seed_signature_type == fields.SeedSignatureType(None) sv_spec = fields.SigSeedValueSpec.from_pdf_object( generic.DictionaryObject({ pdf_name('/MDP'): generic.DictionaryObject({pdf_name('/P'): generic.NumberObject(2)}) })) assert sv_spec.seed_signature_type == fields.SeedSignatureType( fields.MDPPerm.FILL_FORMS) with pytest.raises(SigningError): fields.SigSeedValueSpec.from_pdf_object( generic.DictionaryObject({ pdf_name('/MDP'): generic.DictionaryObject( {pdf_name('/P'): generic.NumberObject(5)}) })) with pytest.raises(SigningError): fields.SigSeedValueSpec.from_pdf_object( generic.DictionaryObject({ pdf_name('/MDP'): generic.DictionaryObject( {pdf_name('/P'): generic.NullObject()}) })) with pytest.raises(SigningError): fields.SigSeedValueSpec.from_pdf_object( generic.DictionaryObject( {pdf_name('/MDP'): generic.DictionaryObject()})) with pytest.raises(SigningError): fields.SigSeedValueSpec.from_pdf_object( generic.DictionaryObject({pdf_name('/MDP'): generic.NullObject()}))
def test_resource_add_test(): res1 = PdfResources() res2 = PdfResources() res1[ResourceType.XOBJECT][pdf_name('/Bleh')] = generic.NullObject() res1[ResourceType.PATTERN][pdf_name('/Blih')] = generic.NullObject() res2[ResourceType.XOBJECT][pdf_name('/Blah')] = generic.NullObject() res2[ResourceType.FONT][pdf_name('/Bluh')] = generic.NullObject() res1 += res2 res1_dict = res1.as_pdf_object() assert pdf_name('/XObject') in res1_dict assert pdf_name('/Pattern') in res1_dict assert pdf_name('/Font') in res1_dict assert pdf_name('/Bleh') in res1_dict['/XObject'] assert pdf_name('/Blah') in res1_dict['/XObject'] assert pdf_name('/Shading') not in res1_dict
def test_bogus_metadata_manipulation(): # test using a double signature created using Adobe Reader # (uses object streams, XMP metadata updates and all the fun stuff) infile = BytesIO( read_all(PDF_DATA_DIR + '/minimal-two-fields-signed-twice.pdf')) bogus = b'This is bogus data, yay!' def do_check(): r = PdfFileReader(out) print(r.get_object(generic.Reference(2, 0, r), revision=3).data) s = r.embedded_signatures[0] status = validate_pdf_signature(s) assert status.modification_level == ModificationLevel.OTHER w = IncrementalPdfFileWriter(infile) w.root['/Metadata'] = w.add_object(generic.StreamObject(stream_data=bogus)) w.update_root() out = BytesIO() w.write(out) do_check() w = IncrementalPdfFileWriter(infile) metadata_ref = w.root.raw_get('/Metadata') metadata_stream: generic.StreamObject = metadata_ref.get_object() metadata_stream.strip_filters() metadata_stream._data = bogus metadata_stream._encoded_data = None w.mark_update(metadata_ref) out = BytesIO() w.write(out) do_check() w = IncrementalPdfFileWriter(infile) w.root['/Metadata'] = generic.NullObject() w.update_root() out = BytesIO() w.write(out) do_check() w = IncrementalPdfFileWriter(infile) w.root['/Metadata'] = w.add_object(generic.NullObject()) w.update_root() out = BytesIO() w.write(out) do_check()
def test_preallocate(): w = writer.PdfFileWriter() with pytest.raises(misc.PdfWriteError): w.add_object(generic.NullObject(), idnum=20) alloc = w.allocate_placeholder() assert isinstance(alloc.get_object(), generic.NullObject) w.add_object(generic.TextStringObject("Test Test"), idnum=alloc.idnum) assert alloc.get_object() == "Test Test"
def get_object(self, ido): if ido.pdf not in self._resolves_objs_from: raise ValueError( f'Reference {ido} has no relation to this PDF writer.') idnum = ido.idnum generation = ido.generation try: return self.objects[(generation, idnum)] except KeyError: if generation == 0: if idnum in self._allocated_placeholders: return generic.NullObject() try: return self.objs_in_streams[idnum] except KeyError: pass raise KeyError(ido)
def get_object(self, ref, *_args, **_kwargs): if ref.idnum == 0: return generic.TextStringObject('OK') else: return generic.ArrayObject([generic.NumberObject(7)]) path_test_obj = generic.DictionaryObject({ pdf_name('/Blah'): generic.DictionaryObject({ pdf_name('/Bleh'): generic.ArrayObject([generic.NumberObject(5), pdf_name('/Foo')]), pdf_name('/Null'): generic.NullObject(), }), pdf_name('/WithRefs'): generic.DictionaryObject({ pdf_name('/Arr'): generic.IndirectObject(1, 0, PathMockHandler()), pdf_name('/String'): generic.IndirectObject(0, 0, PathMockHandler()) }) }) @pytest.mark.parametrize('path, result', [(RawPdfPath('/Blah', '/Bleh', 1), '/Foo'), (RawPdfPath('/Blah', '/Bleh', 0), 5), (RawPdfPath('/Blah', '/Null'), generic.NullObject()),
def tamper(writer, sig_obj): sig_obj['/FakeContents'] = sig_obj['/Contents'] sig_obj['/Contents'] = generic.NullObject()
meta = signers.PdfSignatureMetadata(field_name='Sig1') out = signers.sign_pdf(w, meta, signer=SELF_SIGN) r = PdfFileReader(out) emb = r.embedded_signatures[0] # Again: # (yes, obviously this also isn't a valid timestamp token, hence the # match=... rule here) with pytest.raises(SignatureValidationError, match='.*must be /DocTimeStamp.*'): validate_pdf_timestamp(emb, validation_context=SIMPLE_V_CONTEXT()) @pytest.mark.parametrize('wrong_subfilter', [ pdf_name('/abcde'), pdf_name("/ETSI.RFC3161"), None, generic.NullObject() ]) @freeze_time('2020-11-01') def test_sig_wrong_subfilter(wrong_subfilter): def tamper(writer, sig_obj): if wrong_subfilter: sig_obj['/SubFilter'] = wrong_subfilter else: del sig_obj['/SubFilter'] out = _tamper_with_sig_obj(tamper) r = PdfFileReader(out) emb = r.embedded_signatures[0] with pytest.raises(SignatureValidationError): val_trusted(emb)
out = signers.sign_pdf(w, meta, signer=FROM_CA) w = IncrementalPdfFileWriter(out) tf = w.root['/AcroForm']['/Fields'][1].get_object() tf['/FT'] = pdf_name('/Sig') w.update_container(tf) out = BytesIO() w.write(out) r = PdfFileReader(out) s = r.embedded_signatures[0] assert s.field_name == 'Sig1' val_trusted_but_modified(s) BOGUS_KIDS_VALUES = [ (generic.NullObject(), False), (generic.ArrayObject(), False), (generic.ArrayObject([generic.NullObject()]), False), (generic.ArrayObject([generic.NullObject()]), True), ] @freeze_time('2020-11-01') @pytest.mark.parametrize('bogus_kids, indirectify', BOGUS_KIDS_VALUES) def test_form_field_kids_tamper(bogus_kids, indirectify): w = IncrementalPdfFileWriter(BytesIO(SIMPLE_FORM)) # sign, then fill meta = signers.PdfSignatureMetadata(field_name='Sig1') out = signers.sign_pdf(w, meta, signer=FROM_CA) w = IncrementalPdfFileWriter(out)