Return errors rather than mangle documents
This commit is contained in:
parent
486cafa6b4
commit
1224d9be47
2
LICENSE
2
LICENSE
|
@ -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.
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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();
|
||||||
|
|
15
pdf/pdf.go
15
pdf/pdf.go
|
@ -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 */),
|
||||||
|
|
Loading…
Reference in New Issue