Exemple #1
0
def test_pades_dss_object_clobber(requests_mock):
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_TWO_FIELDS))
    meta1 = signers.PdfSignatureMetadata(
        field_name='Sig1',
        validation_context=live_testing_vc(requests_mock),
        subfilter=PADES,
        embed_validation_info=True,
    )
    dummy_ref = w.add_object(generic.pdf_string("Hi there")).reference

    out = signers.sign_pdf(w, meta1, signer=FROM_CA, timestamper=DUMMY_TS)
    w = IncrementalPdfFileWriter(out)
    # We're going to reassign the DSS object to another object ID, namely
    #  one that clobbers the dummy_ref object. This should be ample cause
    #  for suspicion.
    dss = w.root['/DSS']
    w.objects[(dummy_ref.generation, dummy_ref.idnum)] = dss
    w.root['/DSS'] = generic.IndirectObject(idnum=dummy_ref.idnum,
                                            generation=dummy_ref.generation,
                                            pdf=w)
    w.update_root()
    out = BytesIO()
    w.write(out)

    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    val_trusted_but_modified(s)
def test_no_refs_in_obj_stm():
    w = writer.PdfFileWriter(stream_xrefs=True)
    obj_stm = w.prepare_object_stream()

    with pytest.raises(TypeError, match='Stream obj.*references'):
        w.add_object(
            generic.IndirectObject(2, 0, w),
            obj_stream=obj_stm
        )
Exemple #3
0
def test_historical_read():
    reader = PdfFileReader(BytesIO(MINIMAL_ONE_FIELD))
    assert reader.total_revisions == 2

    # if this test file is ever replaced, the test will probably have to
    # be rewritten
    root_ref = generic.IndirectObject(1, 0, reader)
    acroform_ref = generic.IndirectObject(6, 0, reader)

    # current value
    current_root = reader.get_object(root_ref.reference, revision=1)
    assert current_root == reader.root
    reader.get_object(acroform_ref.reference, revision=1)

    previous_root = reader.get_object(root_ref.reference, revision=0)
    assert '/AcroForm' not in previous_root
    with pytest.raises(misc.PdfReadError):
        reader.get_object(acroform_ref.reference, revision=0)

    assert Reference(6, 0) in reader.xrefs.explicit_refs_in_revision(1)
    assert Reference(2, 0) in reader.xrefs.explicit_refs_in_revision(0)
    assert Reference(2, 0) not in reader.xrefs.explicit_refs_in_revision(1)
Exemple #4
0
    def add_object(self, obj, obj_stream: Optional[ObjectStream] = None,
                   idnum=None) -> generic.IndirectObject:
        """
        Add a new object to this writer.

        :param obj:
            The object to add.
        :param obj_stream:
            An object stream to add the object to.
        :param idnum:
            Manually specify the object ID of the object to be added.
            This is only allowed for object IDs that have previously been
            allocated using :meth:`allocate_placeholder`.
        :return:
            A :class:`~.generic.IndirectObject` instance referring to
            the object just added.
        """

        if idnum is not None:
            if idnum not in self._allocated_placeholders:
                raise PdfWriteError(
                    "Manually specifying idnum is only allowed for "
                    "references previously allocated using "
                    "allocate_placeholder()."
                )
            preallocated = True
        else:
            preallocated = False
            idnum = self._lastobj_id + 1

        if obj_stream is None:
            self.objects[(0, idnum)] = obj
        elif obj_stream in self.object_streams:
            obj_stream.add_object(idnum, obj)
            self.objs_in_streams[idnum] = obj
        else:
            raise PdfWriteError(
                f'Stream {repr(obj_stream)} is unknown to this PDF writer.'
            )

        if preallocated:
            self._allocated_placeholders.remove(idnum)
        else:
            self._lastobj_id += 1
        return generic.IndirectObject(idnum, 0, self)
Exemple #5
0
def fieldmdp_reference_dictionary(field_mdp_spec: FieldMDPSpec,
                                  md_algorithm: str,
                                  data_ref: generic.Reference):
    data_ref = generic.IndirectObject(data_ref.idnum, data_ref.generation,
                                      data_ref.pdf)
    # this is part of the /Reference entry of the signature object.
    return generic.DictionaryObject({
        pdf_name('/Type'):
        pdf_name('/SigRef'),
        pdf_name('/TransformMethod'):
        pdf_name('/FieldMDP'),
        pdf_name('/Data'):
        data_ref,
        pdf_name('/DigestMethod'):
        pdf_name('/' + md_algorithm.upper()),
        pdf_name('/TransformParams'):
        field_mdp_spec.as_transform_params()
    })
Exemple #6
0
    def allocate_placeholder(self) -> generic.IndirectObject:
        """
        Allocate an object reference to populate later.
        Calls to :meth:`get_object` for this reference will
        return :class:`~.generic.NullObject` until it is populated using
        :meth:`add_object`.

        This method is only relevant in certain advanced contexts where
        an object ID needs to be known before the object it refers
        to can be built; chances are you'll never need it.

        :return:
            A :class:`~.generic.IndirectObject` instance referring to
            the object just allocated.
        """

        idnum = self._lastobj_id + 1
        self._allocated_placeholders.add(idnum)
        self._lastobj_id += 1
        return generic.IndirectObject(idnum, 0, self)
Exemple #7
0
            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()),
                          (RawPdfPath('/WithRefs', '/Arr', 0), 7),
                          (RawPdfPath('/WithRefs', '/String'), 'OK')])
def test_path_access(path, result):
    assert path.access_on(path_test_obj) == result