1 // Copyright 2020 PDFium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "public/fpdf_signature.h"
6 
7 #include "core/fpdfapi/parser/cpdf_array.h"
8 #include "core/fpdfapi/parser/cpdf_dictionary.h"
9 #include "core/fpdfapi/parser/cpdf_document.h"
10 #include "fpdfsdk/cpdfsdk_helpers.h"
11 #include "third_party/base/stl_util.h"
12 
13 namespace {
14 
CollectSignatures(CPDF_Document * doc)15 std::vector<CPDF_Dictionary*> CollectSignatures(CPDF_Document* doc) {
16   std::vector<CPDF_Dictionary*> signatures;
17   CPDF_Dictionary* root = doc->GetRoot();
18   if (!root)
19     return signatures;
20 
21   const CPDF_Dictionary* acro_form = root->GetDictFor("AcroForm");
22   if (!acro_form)
23     return signatures;
24 
25   const CPDF_Array* fields = acro_form->GetArrayFor("Fields");
26   if (!fields)
27     return signatures;
28 
29   CPDF_ArrayLocker locker(fields);
30   for (auto& field : locker) {
31     CPDF_Dictionary* field_dict = field->GetDict();
32     if (field_dict && field_dict->GetNameFor("FT") == "Sig")
33       signatures.push_back(field_dict);
34   }
35   return signatures;
36 }
37 
38 }  // namespace
39 
FPDF_GetSignatureCount(FPDF_DOCUMENT document)40 FPDF_EXPORT int FPDF_CALLCONV FPDF_GetSignatureCount(FPDF_DOCUMENT document) {
41   auto* doc = CPDFDocumentFromFPDFDocument(document);
42   if (!doc)
43     return -1;
44 
45   return pdfium::CollectionSize<int>(CollectSignatures(doc));
46 }
47 
48 FPDF_EXPORT FPDF_SIGNATURE FPDF_CALLCONV
FPDF_GetSignatureObject(FPDF_DOCUMENT document,int index)49 FPDF_GetSignatureObject(FPDF_DOCUMENT document, int index) {
50   auto* doc = CPDFDocumentFromFPDFDocument(document);
51   if (!doc)
52     return nullptr;
53 
54   std::vector<CPDF_Dictionary*> signatures = CollectSignatures(doc);
55   if (!pdfium::IndexInBounds(signatures, index))
56     return nullptr;
57 
58   return FPDFSignatureFromCPDFDictionary(signatures[index]);
59 }
60 
61 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetContents(FPDF_SIGNATURE signature,void * buffer,unsigned long length)62 FPDFSignatureObj_GetContents(FPDF_SIGNATURE signature,
63                              void* buffer,
64                              unsigned long length) {
65   CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
66   if (!signature_dict)
67     return 0;
68 
69   CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
70   if (!value_dict)
71     return 0;
72 
73   ByteString contents = value_dict->GetStringFor("Contents");
74   unsigned long contents_len = contents.GetLength();
75   if (buffer && length >= contents_len)
76     memcpy(buffer, contents.c_str(), contents_len);
77 
78   return contents_len;
79 }
80 
81 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetByteRange(FPDF_SIGNATURE signature,int * buffer,unsigned long length)82 FPDFSignatureObj_GetByteRange(FPDF_SIGNATURE signature,
83                               int* buffer,
84                               unsigned long length) {
85   CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
86   if (!signature_dict)
87     return 0;
88 
89   CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
90   if (!value_dict)
91     return 0;
92 
93   const CPDF_Array* byte_range = value_dict->GetArrayFor("ByteRange");
94   if (!byte_range)
95     return 0;
96 
97   unsigned long byte_range_len = byte_range->size();
98   if (buffer && length >= byte_range_len) {
99     for (size_t i = 0; i < byte_range_len; ++i)
100       buffer[i] = byte_range->GetIntegerAt(i);
101   }
102 
103   return byte_range_len;
104 }
105 
106 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetSubFilter(FPDF_SIGNATURE signature,char * buffer,unsigned long length)107 FPDFSignatureObj_GetSubFilter(FPDF_SIGNATURE signature,
108                               char* buffer,
109                               unsigned long length) {
110   CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
111   if (!signature_dict)
112     return 0;
113 
114   CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
115   if (!value_dict || !value_dict->KeyExist("SubFilter"))
116     return 0;
117 
118   ByteString sub_filter = value_dict->GetNameFor("SubFilter");
119   return NulTerminateMaybeCopyAndReturnLength(sub_filter, buffer, length);
120 }
121 
122 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetReason(FPDF_SIGNATURE signature,void * buffer,unsigned long length)123 FPDFSignatureObj_GetReason(FPDF_SIGNATURE signature,
124                            void* buffer,
125                            unsigned long length) {
126   CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
127   if (!signature_dict)
128     return 0;
129 
130   CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
131   if (!value_dict)
132     return 0;
133 
134   const CPDF_Object* obj = value_dict->GetObjectFor("Reason");
135   if (!obj || !obj->IsString())
136     return 0;
137 
138   return Utf16EncodeMaybeCopyAndReturnLength(obj->GetUnicodeText(), buffer,
139                                              length);
140 }
141 
142 FPDF_EXPORT unsigned long FPDF_CALLCONV
FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature,char * buffer,unsigned long length)143 FPDFSignatureObj_GetTime(FPDF_SIGNATURE signature,
144                          char* buffer,
145                          unsigned long length) {
146   CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
147   if (!signature_dict)
148     return 0;
149 
150   CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
151   if (!value_dict)
152     return 0;
153 
154   const CPDF_Object* obj = value_dict->GetObjectFor("M");
155   if (!obj || !obj->IsString())
156     return 0;
157 
158   return NulTerminateMaybeCopyAndReturnLength(obj->GetString(), buffer, length);
159 }
160 
161 FPDF_EXPORT unsigned int FPDF_CALLCONV
FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature)162 FPDFSignatureObj_GetDocMDPPermission(FPDF_SIGNATURE signature) {
163   int permission = 0;
164   CPDF_Dictionary* signature_dict = CPDFDictionaryFromFPDFSignature(signature);
165   if (!signature_dict)
166     return permission;
167 
168   CPDF_Dictionary* value_dict = signature_dict->GetDictFor("V");
169   if (!value_dict)
170     return permission;
171 
172   CPDF_Array* references = value_dict->GetArrayFor("Reference");
173   if (!references)
174     return permission;
175 
176   CPDF_ArrayLocker locker(references);
177   for (auto& reference : locker) {
178     CPDF_Dictionary* reference_dict = reference->GetDict();
179     if (!reference_dict)
180       continue;
181 
182     ByteString transform_method = reference_dict->GetNameFor("TransformMethod");
183     if (transform_method != "DocMDP")
184       continue;
185 
186     CPDF_Dictionary* transform_params =
187         reference_dict->GetDictFor("TransformParams");
188     if (!transform_params)
189       continue;
190 
191     // Valid values are 1, 2 and 3; 2 is the default.
192     permission = transform_params->GetIntegerFor("P", 2);
193     if (permission < 1 || permission > 3)
194       permission = 0;
195 
196     return permission;
197   }
198 
199   return permission;
200 }
201