summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPřemysl Eric Janouch <p@janouch.name>2020-09-04 15:34:33 +0200
committerPřemysl Eric Janouch <p@janouch.name>2020-09-04 16:05:14 +0200
commit1224d9be47e5235f39556d9118c9893ee6e68a4c (patch)
tree4eb042d56f8baa5f036e9c327226523bd9719bb5
parent486cafa6b447d7af296411f7c50d4c078f3eac34 (diff)
downloadpdf-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--LICENSE2
-rw-r--r--README.adoc4
-rw-r--r--pdf-simple-sign.cpp16
-rw-r--r--pdf/pdf.go15
4 files changed, 26 insertions, 11 deletions
diff --git a/LICENSE b/LICENSE
index 19ca8b1..3bfb256 100644
--- a/LICENSE
+++ b/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
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();
diff --git a/pdf/pdf.go b/pdf/pdf.go
index ded8747..d9e4098 100644
--- a/pdf/pdf.go
+++ b/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
// 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 */),