From 6b692931c81fd0e09d8d21eb81e05a5f08af8342 Mon Sep 17 00:00:00 2001 From: Andreas Fitzek Date: Tue, 4 Feb 2014 08:36:05 +0100 Subject: Implemented PDF Document permission check --- .../exceptions/PdfAsValidationException.java | 5 + .../at/gv/egiz/pdfas/common/utils/PDFUtils.java | 179 +++++++++++---------- .../resources/resources/messages/common.properties | 1 + .../java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java | 9 ++ 4 files changed, 110 insertions(+), 84 deletions(-) diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/PdfAsValidationException.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/PdfAsValidationException.java index b8a5fc62..95380794 100644 --- a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/PdfAsValidationException.java +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/exceptions/PdfAsValidationException.java @@ -16,6 +16,11 @@ public class PdfAsValidationException extends PdfAsException { this.parameter = parameter; } + public PdfAsValidationException(String msgId, String parameter, Throwable e) { + super(msgId, e); + this.parameter = parameter; + } + @Override protected String localizeMessage(String msgId) { if(parameter != null) { diff --git a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/PDFUtils.java b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/PDFUtils.java index 155f9cfb..8b649034 100644 --- a/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/PDFUtils.java +++ b/pdf-as-common/src/main/java/at/gv/egiz/pdfas/common/utils/PDFUtils.java @@ -1,94 +1,105 @@ package at.gv.egiz.pdfas.common.utils; +import java.util.ArrayList; +import java.util.List; + import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.encryption.AccessPermission; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.List; - +import at.gv.egiz.pdfas.common.exceptions.PdfAsValidationException; public class PDFUtils { - private static final Logger logger = LoggerFactory.getLogger(PDFUtils.class); - - - private static final byte[] signature_pattern = new byte[] { - (byte) 0x0A, (byte) 0x2F, (byte) 0x43, (byte) 0x6F, // ./Co - (byte) 0x6E, (byte) 0x74, (byte) 0x65, (byte) 0x6E, // nten - (byte) 0x74, (byte) 0x73, (byte) 0x20, (byte) 0x0A, // ts . - (byte) 0x2F, (byte) 0x42, (byte) 0x79, (byte) 0x74, // /Byt - (byte) 0x65, (byte) 0x52, (byte) 0x61, (byte) 0x6E, // eRan - (byte) 0x67, (byte) 0x65, (byte) 0x20, (byte) 0x5B, // ge [ - - }; - - private static final byte range_seperation = (byte) 0x20; - private static final byte range_end = (byte) 0x5D; - - private static int extractASCIIInteger(byte[] data, int offset) { - int nextsepp = nextSeperator(data, offset); - - if(nextsepp < offset) { - return -1; - } - - String asciiString = new String(data, offset, nextsepp - offset); - - logger.debug("Extracted " + asciiString); - - return Integer.parseInt(asciiString); - } - - private static int nextSeperator(byte[] data, int offset) { - for(int i = offset; i < data.length; i++) { - if(data[i] == range_seperation) { - return i; - } else if(data[i] == range_end) { - return i; - } - } - return -2; - } - - public static int[] extractSignatureByteRange(byte[] rawPdfData) { - int i = 0; - for(i = rawPdfData.length - 1; i >= 0; i--) { - if(rawPdfData[i] == signature_pattern[0] && - i+signature_pattern.length < rawPdfData.length) { - boolean match = true; - for(int j = 0; j < signature_pattern.length; j++) { - - if(rawPdfData[i+j] != signature_pattern[j]) { - match = false; - break; - } - } - - if(match) { - - int offset = i + signature_pattern.length; - List byteRange = new ArrayList(); - while(offset > 0) { - byteRange.add(extractASCIIInteger(rawPdfData, offset)); - offset = nextSeperator(rawPdfData, offset); - if(rawPdfData[offset] == range_end) { - break; - } - offset++; - } - int[] range = new int[byteRange.size()]; - for(int j = 0; j < byteRange.size(); j++) { - range[j] = byteRange.get(j); - } - return range; - } - } - } - return null; - } - - public static void checkPDFPermissions(PDDocument doc) { - // TODO: Check permission for document - } + private static final Logger logger = LoggerFactory + .getLogger(PDFUtils.class); + + private static final byte[] signature_pattern = new byte[] { (byte) 0x0A, + (byte) 0x2F, (byte) 0x43, (byte) 0x6F, // ./Co + (byte) 0x6E, (byte) 0x74, (byte) 0x65, (byte) 0x6E, // nten + (byte) 0x74, (byte) 0x73, (byte) 0x20, (byte) 0x0A, // ts . + (byte) 0x2F, (byte) 0x42, (byte) 0x79, (byte) 0x74, // /Byt + (byte) 0x65, (byte) 0x52, (byte) 0x61, (byte) 0x6E, // eRan + (byte) 0x67, (byte) 0x65, (byte) 0x20, (byte) 0x5B, // ge [ + + }; + + private static final byte range_seperation = (byte) 0x20; + private static final byte range_end = (byte) 0x5D; + + private static int extractASCIIInteger(byte[] data, int offset) { + int nextsepp = nextSeperator(data, offset); + + if (nextsepp < offset) { + return -1; + } + + String asciiString = new String(data, offset, nextsepp - offset); + + logger.debug("Extracted " + asciiString); + + return Integer.parseInt(asciiString); + } + + private static int nextSeperator(byte[] data, int offset) { + for (int i = offset; i < data.length; i++) { + if (data[i] == range_seperation) { + return i; + } else if (data[i] == range_end) { + return i; + } + } + return -2; + } + + public static int[] extractSignatureByteRange(byte[] rawPdfData) { + int i = 0; + for (i = rawPdfData.length - 1; i >= 0; i--) { + if (rawPdfData[i] == signature_pattern[0] + && i + signature_pattern.length < rawPdfData.length) { + boolean match = true; + for (int j = 0; j < signature_pattern.length; j++) { + + if (rawPdfData[i + j] != signature_pattern[j]) { + match = false; + break; + } + } + + if (match) { + + int offset = i + signature_pattern.length; + List byteRange = new ArrayList(); + while (offset > 0) { + byteRange.add(extractASCIIInteger(rawPdfData, offset)); + offset = nextSeperator(rawPdfData, offset); + if (rawPdfData[offset] == range_end) { + break; + } + offset++; + } + int[] range = new int[byteRange.size()]; + for (int j = 0; j < byteRange.size(); j++) { + range[j] = byteRange.get(j); + } + return range; + } + } + } + return null; + } + + public static void checkPDFPermissions(PDDocument doc) throws PdfAsValidationException { + + AccessPermission accessPermission = doc.getCurrentAccessPermission(); + if (doc.isEncrypted()) { + throw new PdfAsValidationException("error.pdf.sig.12", null); + } + + if (!accessPermission.isOwnerPermission()) { + throw new PdfAsValidationException("error.pdf.sig.12", null); + } + + } } diff --git a/pdf-as-common/src/main/resources/resources/messages/common.properties b/pdf-as-common/src/main/resources/resources/messages/common.properties index 0191bdd9..bdae59ca 100644 --- a/pdf-as-common/src/main/resources/resources/messages/common.properties +++ b/pdf-as-common/src/main/resources/resources/messages/common.properties @@ -36,6 +36,7 @@ error.pdf.sig.08=Signature created by the BKU is not valid error.pdf.sig.09=Signature profile %s not available error.pdf.sig.10=No signature data available error.pdf.sig.11=No data sink available +error.pdf.sig.12=Document is protected #Signature verification errors diff --git a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java index 540fd572..2553ccf3 100644 --- a/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java +++ b/pdf-as-lib/src/main/java/at/gv/egiz/pdfas/lib/impl/PdfAsImpl.java @@ -16,6 +16,7 @@ import org.apache.pdfbox.cos.COSDictionary; import org.apache.pdfbox.cos.COSName; import org.apache.pdfbox.cos.COSString; import org.apache.pdfbox.pdmodel.PDDocument; +import org.apache.pdfbox.pdmodel.encryption.AccessPermission; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -95,6 +96,14 @@ public class PdfAsImpl implements PdfAs, IConfigurationConstants { throw new PdfAsValidationException("error.pdf.sig.11", null); } + try { + PDDocument doc = PDDocument.load(new ByteArrayInputStream(parameter.getDataSource().getByteData())); + PDFUtils.checkPDFPermissions(doc); + doc.close(); + } catch(IOException e) { + throw new PdfAsValidationException("error.pdf.sig.12", null, e); + } + // TODO: verify Sign Parameter } -- cgit v1.2.3