diff options
author | Přemysl Eric Janouch <p@janouch.name> | 2020-09-04 15:34:33 +0200 |
---|---|---|
committer | Přemysl Eric Janouch <p@janouch.name> | 2020-09-04 16:05:14 +0200 |
commit | 1224d9be47e5235f39556d9118c9893ee6e68a4c (patch) | |
tree | 4eb042d56f8baa5f036e9c327226523bd9719bb5 | |
parent | 486cafa6b447d7af296411f7c50d4c078f3eac34 (diff) | |
download | pdf-simple-sign-1224d9be47e5235f39556d9118c9893ee6e68a4c.tar.gz pdf-simple-sign-1224d9be47e5235f39556d9118c9893ee6e68a4c.tar.xz pdf-simple-sign-1224d9be47e5235f39556d9118c9893ee6e68a4c.zip |
Return errors rather than mangle documents
-rw-r--r-- | LICENSE | 2 | ||||
-rw-r--r-- | README.adoc | 4 | ||||
-rw-r--r-- | pdf-simple-sign.cpp | 16 | ||||
-rw-r--r-- | pdf/pdf.go | 15 |
4 files changed, 26 insertions, 11 deletions
@@ -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 purpose with or without fee is hereby granted. diff --git a/README.adoc b/README.adoc index 59bfdef..46bc9ed 100644 --- a/README.adoc +++ b/README.adoc @@ -5,8 +5,8 @@ pdf-simple-sign '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 document may not have any forms or signatures already, as they will be - overwitten + * the document may not have any forms or signatures already, as they would be + overwritten * the document may not employ cross-reference streams, or must constitute a hybrid-reference file at least * the document may not be newer than PDF 1.6 already, or it will get downgraded diff --git a/pdf-simple-sign.cpp b/pdf-simple-sign.cpp index 818270e..b724f69 100644 --- a/pdf-simple-sign.cpp +++ b/pdf-simple-sign.cpp @@ -2,7 +2,7 @@ // // 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 // 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) return "invalid or unsupported page tree"; - // XXX assuming this won't be an indirectly referenced array 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.array.emplace_back(pdf_object::REFERENCE, sigfield_n, 0); pdf.update(page.n, [&]{ pdf.document += pdf_serialize(page); }); // 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>{ {"Fields", {std::vector<pdf_object>{ {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. // 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"}; pdf.update(root_ref->second.n, [&]{ pdf.document += pdf_serialize(root); }); pdf.flush_updates(); @@ -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 // purpose with or without fee is hereby granted. @@ -32,6 +32,7 @@ import ( "crypto/ecdsa" "crypto/rsa" "crypto/x509" + "go.mozilla.org/pkcs7" "golang.org/x/crypto/pkcs12" ) @@ -1166,9 +1167,13 @@ func Sign(document []byte, return nil, errors.New("invalid or unsupported page tree") } - // XXX: Assuming this won't be an indirectly referenced array. annots := page.Dict["Annots"] 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.Array = append(annots.Array, NewReference(sigfieldN, 0)) @@ -1179,7 +1184,11 @@ func Sign(document []byte, }) // 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{ "Fields": NewArray([]Object{NewReference(sigfieldN, 0)}), "SigFlags": NewNumeric(3 /* SignaturesExist | AppendOnly */), |