Skip to content

Commit a62dad8

Browse files
authored
Merge pull request #5704 from LibreSign/fix/only-validate-real-signatures
fix: only validate real signatures
2 parents 3b0bfae + 6c1d994 commit a62dad8

File tree

1 file changed

+62
-33
lines changed

1 file changed

+62
-33
lines changed

lib/Handler/SignEngine/Pkcs12Handler.php

Lines changed: 62 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -80,18 +80,15 @@ private function getSignatures($resource): iterable {
8080
#[\Override]
8181
public function getCertificateChain($resource): array {
8282
$certificates = [];
83-
$signerCounter = 0;
8483

8584
foreach ($this->getSignatures($resource) as $signature) {
86-
$certificates[$signerCounter] = $this->processSignature($resource, $signature, $signerCounter);
87-
$signerCounter++;
85+
$certificates[] = $this->processSignature($resource, $signature);
8886
}
8987
return $certificates;
9088
}
9189

92-
private function processSignature($resource, ?string $signature, int $signerCounter): array {
93-
$fromFallback = $this->popplerUtilsPdfSignFallback($resource, $signerCounter);
94-
$result = $fromFallback ?: [];
90+
private function processSignature($resource, ?string $signature): array {
91+
$result = [];
9592

9693
if (!$signature) {
9794
$result['chain'][0]['signature_validation'] = $this->getReadableSigState('Digest Mismatch.');
@@ -104,7 +101,7 @@ private function processSignature($resource, ?string $signature, int $signerCoun
104101
$chain = $this->extractCertificateChain($signature);
105102
if (!empty($chain)) {
106103
$result['chain'] = $this->orderCertificates($chain);
107-
$this->enrichLeafWithPopplerData($result, $fromFallback);
104+
$result = $this->enrichLeafWithPopplerData($resource, $result);
108105
}
109106
return $result;
110107
}
@@ -149,33 +146,64 @@ private function extractCertificateChain(string $signature): array {
149146
return $chain;
150147
}
151148

152-
private function enrichLeafWithPopplerData(array &$result, array $fromFallback): void {
153-
if (empty($fromFallback['chain'][0]) || empty($result['chain'][0])) {
154-
return;
149+
private function enrichLeafWithPopplerData($resource, array $result): array {
150+
if (empty($result['chain'])) {
151+
return $result;
155152
}
156153

157-
$popplerData = $fromFallback['chain'][0];
158-
$leafCert = &$result['chain'][0];
159-
160154
$popplerOnlyFields = ['field', 'range', 'certificate_validation'];
155+
if (!isset($result['chain'][0]['subject'])) {
156+
return $result;
157+
}
158+
$needPoppler = false;
161159
foreach ($popplerOnlyFields as $field) {
162-
if (isset($popplerData[$field])) {
163-
$leafCert[$field] = $popplerData[$field];
160+
if (empty($result['chain'][0][$field])) {
161+
$needPoppler = true;
162+
break;
164163
}
165164
}
166-
167-
if (isset($popplerData['signature_validation'])
168-
&& (!isset($leafCert['signature_validation']) || $leafCert['signature_validation']['id'] !== 1)) {
169-
$leafCert['signature_validation'] = $popplerData['signature_validation'];
165+
if (!isset($result['chain'][0]['signature_validation']) || $result['chain'][0]['signature_validation']['id'] !== 1) {
166+
$needPoppler = true;
167+
}
168+
if (!$needPoppler) {
169+
return $result;
170+
}
171+
$popplerChain = $this->chainFromPoppler($result['chain'][0]['subject'], $resource);
172+
if (empty($popplerChain)) {
173+
return $result;
174+
}
175+
foreach ($popplerOnlyFields as $field) {
176+
if (isset($popplerChain[$field])) {
177+
$result['chain'][0][$field] = $popplerChain[$field];
178+
}
170179
}
180+
if (!isset($result['chain'][0]['signature_validation']) || $result['chain'][0]['signature_validation']['id'] !== 1) {
181+
if (isset($popplerChain['signature_validation'])) {
182+
$result['chain'][0]['signature_validation'] = $popplerChain['signature_validation'];
183+
}
184+
}
185+
return $result;
171186
}
172187

173-
private function popplerUtilsPdfSignFallback($resource, int $signerCounter): array {
174-
if (shell_exec('which pdfsig') === null) {
175-
return [];
188+
private function chainFromPoppler(array $subject, $resource): array {
189+
$fromFallback = $this->popplerUtilsPdfSignFallback($resource);
190+
foreach ($fromFallback as $popplerSig) {
191+
if (!isset($popplerSig['chain'][0]['subject'])) {
192+
continue;
193+
}
194+
if ($popplerSig['chain'][0]['subject'] == $subject) {
195+
return $popplerSig['chain'][0];
196+
}
176197
}
198+
return [];
199+
}
200+
201+
private function popplerUtilsPdfSignFallback($resource): array {
177202
if (!empty($this->signaturesFromPoppler)) {
178-
return $this->signaturesFromPoppler[$signerCounter] ?? [];
203+
return $this->signaturesFromPoppler;
204+
}
205+
if (shell_exec('which pdfsig') === null) {
206+
return $this->signaturesFromPoppler;
179207
}
180208
rewind($resource);
181209
$content = stream_get_contents($resource);
@@ -184,7 +212,7 @@ private function popplerUtilsPdfSignFallback($resource, int $signerCounter): arr
184212

185213
$content = shell_exec('env TZ=UTC pdfsig ' . $tempFile);
186214
if (empty($content)) {
187-
return [];
215+
return $this->signaturesFromPoppler;
188216
}
189217
$lines = explode("\n", $content);
190218

@@ -218,13 +246,14 @@ private function popplerUtilsPdfSignFallback($resource, int $signerCounter): arr
218246
$this->signaturesFromPoppler[$lastSignature]['chain'][0]['certificate_validation'] = $this->getReadableCertState($match['value']);
219247
break;
220248
case 'Signed Ranges':
221-
preg_match('/\[(\d+) - (\d+)\], \[(\d+) - (\d+)\]/', $match['value'], $ranges);
222-
$this->signaturesFromPoppler[$lastSignature]['chain'][0]['range'] = [
223-
'offset1' => (int)$ranges[1],
224-
'length1' => (int)$ranges[2],
225-
'offset2' => (int)$ranges[3],
226-
'length2' => (int)$ranges[4],
227-
];
249+
if (preg_match('/\[(\d+) - (\d+)\], \[(\d+) - (\d+)\]/', $match['value'], $ranges)) {
250+
$this->signaturesFromPoppler[$lastSignature]['chain'][0]['range'] = [
251+
'offset1' => (int)$ranges[1],
252+
'length1' => (int)$ranges[2],
253+
'offset2' => (int)$ranges[3],
254+
'length2' => (int)$ranges[4],
255+
];
256+
}
228257
break;
229258
case 'Signature Field Name':
230259
$this->signaturesFromPoppler[$lastSignature]['chain'][0]['field'] = $match['value'];
@@ -238,7 +267,7 @@ private function popplerUtilsPdfSignFallback($resource, int $signerCounter): arr
238267
}
239268
}
240269
}
241-
return $this->signaturesFromPoppler[$signerCounter] ?? [];
270+
return $this->signaturesFromPoppler;
242271
}
243272

244273
private function getReadableSigState(string $status) {
@@ -312,7 +341,7 @@ private function parseDistinguishedNameWithMultipleValues(string $dn): array {
312341
foreach ($pairs as $pair) {
313342
[$key, $value] = explode('=', $pair, 2);
314343
if (empty($key) || empty($value)) {
315-
throw new LibresignException($this->l10n->t('Invalid value: %s.', ['Signer full Distinguished Name: ' . $pair]));
344+
return $result;
316345
}
317346
$key = trim($key);
318347
$value = trim($value);

0 commit comments

Comments
 (0)