示例#1
0
def test_no_changes_policy():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD))
    out = signers.sign_pdf(
        w,
        signers.PdfSignatureMetadata(
            field_name='Sig1',
            certify=True,
            docmdp_permissions=fields.MDPPerm.FILL_FORMS),
        signer=FROM_CA,
    )

    w = IncrementalPdfFileWriter(out)
    # do an /Info update
    dt = generic.pdf_date(datetime(2020, 10, 10, tzinfo=pytz.utc))
    info = generic.DictionaryObject({pdf_name('/CreationDate'): dt})
    w.set_info(info)
    w.write_in_place()

    # check with normal diff policy
    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    status = val_trusted(s, extd=True)
    assert status.modification_level == ModificationLevel.LTA_UPDATES
    assert status.docmdp_ok

    # now check with the ultra-strict no-op policy
    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    status = validate_pdf_signature(s, diff_policy=NO_CHANGES_DIFF_POLICY)
    assert isinstance(s.diff_result, SuspiciousModification)
    assert not status.docmdp_ok
示例#2
0
def test_no_field_type():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD))
    out = signers.sign_pdf(w,
                           signers.PdfSignatureMetadata(
                               field_name='Sig1',
                               certify=True,
                               docmdp_permissions=fields.MDPPerm.FILL_FORMS),
                           signer=FROM_CA,
                           in_place=True)

    w = IncrementalPdfFileWriter(out)
    fields._insert_or_get_field_at(
        w,
        w.root['/AcroForm']['/Fields'],
        ('Blah', ),
    )
    meta = signers.PdfSignatureMetadata(field_name='NewSig')
    out = signers.sign_pdf(w, meta, signer=FROM_CA)

    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    status = validate_pdf_signature(
        s, signer_validation_context=SIMPLE_V_CONTEXT())
    assert status.modification_level == ModificationLevel.OTHER
示例#3
0
def test_double_sig_create_deep_field_post_sign():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD))
    # create part of the structure already

    fields._insert_or_get_field_at(
        w,
        w.root['/AcroForm']['/Fields'], ('NewSigs', 'NewSig1'),
        field_obj=generic.DictionaryObject({pdf_name('/FT'):
                                            pdf_name('/Sig')}))

    out = signers.sign_pdf(w,
                           signers.PdfSignatureMetadata(
                               field_name='Sig1',
                               certify=True,
                               docmdp_permissions=fields.MDPPerm.FILL_FORMS),
                           signer=FROM_CA,
                           in_place=True)

    w = IncrementalPdfFileWriter(out)
    fqn = 'NewSigs.NewSig2'
    meta = signers.PdfSignatureMetadata(field_name=fqn)
    out = signers.sign_pdf(w, meta, signer=FROM_CA)

    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    assert s.field_name == 'Sig1'
    status = validate_pdf_signature(
        s, signer_validation_context=SIMPLE_V_CONTEXT())
    # the /Kids array of NewSigs was modified, which we don't allow (right now)
    assert status.modification_level == ModificationLevel.OTHER
示例#4
0
def test_allow_hybrid_sign_validate_allow():
    fname = 'minimal-hybrid-xref.pdf'
    with open(os.path.join(PDF_DATA_DIR, fname), 'rb') as inf:
        w = IncrementalPdfFileWriter(inf, strict=False)
        meta = signers.PdfSignatureMetadata(field_name='Sig1')
        out = signers.PdfSigner(signature_meta=meta, signer=FROM_CA).sign_pdf(w)

    r = PdfFileReader(out, strict=False)
    s = r.embedded_signatures[0]

    vc = SIMPLE_V_CONTEXT()
    val_status = validate_pdf_signature(s, vc)
    assert val_status.bottom_line
示例#5
0
def test_sign_reject_freed(forbid_freeing):

    w = IncrementalPdfFileWriter(BytesIO(MINIMAL_ONE_FIELD))
    out = signers.sign_pdf(
        w,
        signature_meta=signers.PdfSignatureMetadata(field_name='Sig1'),
        signer=FROM_CA)

    # free the ref containing the /Info dictionary
    # since we don't have support for freeing objects in the writer (yet),
    # do it manually
    r = PdfFileReader(out)
    last_startxref = r.last_startxref

    # NOTE the linked list offsets are dummied out, but our Xref parser
    # doesn't care
    len_out = out.seek(0, os.SEEK_END)
    out.write(b'\n'.join([
        b'xref', b'0 1', b'0000000000 65535 f ', b'2 1',
        b'0000000000 00001 f ',
        b'trailer<</Prev %d>>' % last_startxref, b'startxref',
        b'%d' % len_out, b'%%EOF'
    ]))
    r = PdfFileReader(out)
    last_rev = r.xrefs.xref_sections - 1
    some_ref = generic.Reference(2, 0)

    assert some_ref in r.xrefs.refs_freed_in_revision(last_rev)

    sig = r.embedded_signatures[0]
    assert sig.signed_revision == 2

    # make a dummy rule that whitelists our freed object ref

    class AdHocRule(QualifiedWhitelistRule):
        def apply_qualified(self, old: HistoricalResolver,
                            new: HistoricalResolver):
            yield ModificationLevel.LTA_UPDATES, ReferenceUpdate(
                some_ref, paths_checked=RawPdfPath('/Root', '/Pages'))

    val_status = validate_pdf_signature(
        sig,
        SIMPLE_V_CONTEXT(),
        diff_policy=StandardDiffPolicy(DEFAULT_DIFF_POLICY.global_rules +
                                       [AdHocRule()],
                                       DEFAULT_DIFF_POLICY.form_rule,
                                       reject_object_freeing=forbid_freeing))
    if forbid_freeing:
        assert val_status.modification_level == ModificationLevel.OTHER
    else:
        assert val_status.modification_level == ModificationLevel.LTA_UPDATES
示例#6
0
def test_no_diff_summary():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=SELF_SIGN)

    # just do an incremental DSS update
    DocumentSecurityStore.add_dss(
        out, sig_contents=None, certs=(SELF_SIGN.signing_cert,)
    )

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    status = validate_pdf_signature(emb, skip_diff=True)
    assert emb.diff_result is None
    assert status.modification_level is None
    assert not status.docmdp_ok
    assert status.coverage == SignatureCoverageLevel.ENTIRE_REVISION
    assert 'EXTENDED' in status.summary()
示例#7
0
def test_diff_fallback_ok(policy, skip_diff):
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=SELF_SIGN)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    status = validate_pdf_signature(
        emb, diff_policy=policy, skip_diff=skip_diff
    )
    if skip_diff:
        assert emb.diff_result is None
        # docmdp should still be OK without the diff check
        # because the signature covers the entire file
        assert status.docmdp_ok
        assert status.modification_level == ModificationLevel.NONE
    else:
        assert isinstance(emb.diff_result, DiffResult)
        assert status.modification_level == ModificationLevel.NONE
        assert status.docmdp_ok
示例#8
0
def sign_with_sv(sv_spec, sig_meta, signer=FROM_CA, timestamper=DUMMY_TS, *,
                 test_violation=False, add_field_lock=False):
    w = IncrementalPdfFileWriter(
        prepare_sv_field(sv_spec, add_field_lock=add_field_lock)
    )

    pdf_signer = signers.PdfSigner(sig_meta, signer, timestamper=timestamper)
    pdf_signer._ignore_sv = test_violation
    out = pdf_signer.sign_pdf(w)
    r = PdfFileReader(out)
    s = r.embedded_signatures[0]
    status = validate_pdf_signature(s, dummy_ocsp_vc())
    summary = status.pretty_print_details()
    if test_violation:
        assert 'not satisfy the SV constraints' in summary
        assert not status.seed_value_ok
    else:
        assert 'no SV issues' in summary
        assert status.seed_value_ok
    return EmbeddedPdfSignature(r, s.sig_field, s.fq_name)
示例#9
0
def test_simple_sign_tamper():
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=SELF_SIGN)

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    assert emb.field_name == 'Sig1'
    val_untrusted(emb)

    # try tampering with the file
    out.seek(0x9d)
    # this just changes the size of the media box, so the file should remain
    # a valid PDF.
    out.write(b'4')
    out.seek(0)
    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    tampered = validate_pdf_signature(emb, SIMPLE_V_CONTEXT())
    assert not tampered.intact
    assert not tampered.valid
    assert tampered.summary() == 'INVALID'
示例#10
0
def test_tamper_sig_obj(policy, skip_diff):
    w = IncrementalPdfFileWriter(BytesIO(MINIMAL))
    meta = signers.PdfSignatureMetadata(field_name='Sig1')
    out = signers.sign_pdf(w, meta, signer=FROM_CA)

    w = IncrementalPdfFileWriter(out)
    sig_obj = w.prev.embedded_signatures[0].sig_object
    sig_obj['/Bleh'] = generic.BooleanObject(False)
    w.update_container(sig_obj)
    w.write_in_place()

    r = PdfFileReader(out)
    emb = r.embedded_signatures[0]
    status = validate_pdf_signature(emb,
                                    diff_policy=policy,
                                    skip_diff=skip_diff)
    if skip_diff:
        assert emb.diff_result is None
    else:
        assert isinstance(emb.diff_result, SuspiciousModification)
    assert status.coverage == SignatureCoverageLevel.CONTIGUOUS_BLOCK_FROM_START
    assert status.modification_level == ModificationLevel.OTHER
示例#11
0
 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