Return errors rather than mangle documents

This commit is contained in:
Přemysl Eric Janouch 2020-09-04 15:34:33 +02:00
parent 486cafa6b4
commit 1224d9be47
Signed by: p
GPG Key ID: A0420B94F92B9493
4 changed files with 26 additions and 11 deletions

View File

@ -1,4 +1,4 @@
Copyright (c) 2017, Přemysl Eric Janouch <p@janouch.name> Copyright (c) 2017 - 2020, Přemysl Eric Janouch <p@janouch.name>
Permission to use, copy, modify, and/or distribute this software for any Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted. purpose with or without fee is hereby granted.

View File

@ -5,8 +5,8 @@ pdf-simple-sign
'pdf-simple-sign' is a simple PDF signer intended for documents produced by 'pdf-simple-sign' is a simple PDF signer intended for documents produced by
the Cairo library. As such, it currently comes with some restrictions: the Cairo library. As such, it currently comes with some restrictions:
* the document may not have any forms or signatures already, as they will be * the document may not have any forms or signatures already, as they would be
overwitten overwritten
* the document may not employ cross-reference streams, or must constitute * the document may not employ cross-reference streams, or must constitute
a hybrid-reference file at least a hybrid-reference file at least
* the document may not be newer than PDF 1.6 already, or it will get downgraded * the document may not be newer than PDF 1.6 already, or it will get downgraded

View File

@ -2,7 +2,7 @@
// //
// pdf-simple-sign: simple PDF signer // pdf-simple-sign: simple PDF signer
// //
// Copyright (c) 2017, Přemysl Eric Janouch <p@janouch.name> // Copyright (c) 2017 - 2020, Přemysl Eric Janouch <p@janouch.name>
// //
// Permission to use, copy, modify, and/or distribute this software for any // Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted. // purpose with or without fee is hereby granted.
@ -869,15 +869,21 @@ static std::string pdf_sign(std::string& document) {
if (page.type != pdf_object::DICT) if (page.type != pdf_object::DICT)
return "invalid or unsupported page tree"; return "invalid or unsupported page tree";
// XXX assuming this won't be an indirectly referenced array
auto& annots = page.dict["Annots"]; auto& annots = page.dict["Annots"];
if (annots.type != pdf_object::ARRAY) if (annots.type != pdf_object::ARRAY) {
// TODO indirectly referenced arrays might not be that hard to support
if (annots.type != pdf_object::END)
return "unexpected Annots";
annots = {pdf_object::ARRAY}; annots = {pdf_object::ARRAY};
}
annots.array.emplace_back(pdf_object::REFERENCE, sigfield_n, 0); annots.array.emplace_back(pdf_object::REFERENCE, sigfield_n, 0);
pdf.update(page.n, [&]{ pdf.document += pdf_serialize(page); }); pdf.update(page.n, [&]{ pdf.document += pdf_serialize(page); });
// 8.6.1 Interactive Form Dictionary // 8.6.1 Interactive Form Dictionary
// XXX assuming there are no forms already, overwriting everything if (root.dict.count("AcroForm"))
return "the document already contains forms, they would be overwritten";
root.dict["AcroForm"] = {std::map<std::string, pdf_object>{ root.dict["AcroForm"] = {std::map<std::string, pdf_object>{
{"Fields", {std::vector<pdf_object>{ {"Fields", {std::vector<pdf_object>{
{pdf_object::REFERENCE, sigfield_n, 0} {pdf_object::REFERENCE, sigfield_n, 0}
@ -887,7 +893,7 @@ static std::string pdf_sign(std::string& document) {
// Upgrade the document version for SHA-256 etc. // Upgrade the document version for SHA-256 etc.
// XXX assuming that it's not newer than 1.6 already -- while Cairo can't currently use a newer // XXX assuming that it's not newer than 1.6 already -- while Cairo can't currently use a newer
// version that 1.5, it's not a bad idea to use cairo_pdf_surface_restrict_to_version() // version than 1.5, it's not a bad idea to use cairo_pdf_surface_restrict_to_version()
root.dict["Version"] = {pdf_object::NAME, "1.6"}; root.dict["Version"] = {pdf_object::NAME, "1.6"};
pdf.update(root_ref->second.n, [&]{ pdf.document += pdf_serialize(root); }); pdf.update(root_ref->second.n, [&]{ pdf.document += pdf_serialize(root); });
pdf.flush_updates(); pdf.flush_updates();

View File

@ -1,5 +1,5 @@
// //
// Copyright (c) 2018, Přemysl Eric Janouch <p@janouch.name> // Copyright (c) 2018 - 2020, Přemysl Eric Janouch <p@janouch.name>
// //
// Permission to use, copy, modify, and/or distribute this software for any // Permission to use, copy, modify, and/or distribute this software for any
// purpose with or without fee is hereby granted. // purpose with or without fee is hereby granted.
@ -32,6 +32,7 @@ import (
"crypto/ecdsa" "crypto/ecdsa"
"crypto/rsa" "crypto/rsa"
"crypto/x509" "crypto/x509"
"go.mozilla.org/pkcs7" "go.mozilla.org/pkcs7"
"golang.org/x/crypto/pkcs12" "golang.org/x/crypto/pkcs12"
) )
@ -1166,9 +1167,13 @@ func Sign(document []byte,
return nil, errors.New("invalid or unsupported page tree") return nil, errors.New("invalid or unsupported page tree")
} }
// XXX: Assuming this won't be an indirectly referenced array.
annots := page.Dict["Annots"] annots := page.Dict["Annots"]
if annots.Kind != Array { if annots.Kind != Array {
// TODO(p): Indirectly referenced arrays might not be
// that hard to support.
if annots.Kind != End {
return nil, errors.New("unexpected Annots")
}
annots = NewArray(nil) annots = NewArray(nil)
} }
annots.Array = append(annots.Array, NewReference(sigfieldN, 0)) annots.Array = append(annots.Array, NewReference(sigfieldN, 0))
@ -1179,7 +1184,11 @@ func Sign(document []byte,
}) })
// 8.6.1 Interactive Form Dictionary // 8.6.1 Interactive Form Dictionary
// XXX: Assuming there are no forms already, overwriting everything. if _, ok := root.Dict["AcroForm"]; ok {
return nil, errors.New("the document already contains forms, " +
"they would be overwritten")
}
root.Dict["AcroForm"] = NewDict(map[string]Object{ root.Dict["AcroForm"] = NewDict(map[string]Object{
"Fields": NewArray([]Object{NewReference(sigfieldN, 0)}), "Fields": NewArray([]Object{NewReference(sigfieldN, 0)}),
"SigFlags": NewNumeric(3 /* SignaturesExist | AppendOnly */), "SigFlags": NewNumeric(3 /* SignaturesExist | AppendOnly */),