/** * */ package at.gv.egiz.pdfas.impl.api; import java.io.File; import java.io.UnsupportedEncodingException; import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.Vector; import org.apache.commons.lang.math.NumberUtils; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import at.gv.egiz.pdfas.api.PdfAs; import at.gv.egiz.pdfas.api.analyze.AnalyzeParameters; import at.gv.egiz.pdfas.api.analyze.AnalyzeResult; import at.gv.egiz.pdfas.api.commons.Constants; import at.gv.egiz.pdfas.api.commons.SignatureInformation; import at.gv.egiz.pdfas.api.exceptions.PdfAsException; import at.gv.egiz.pdfas.api.sign.SignParameters; import at.gv.egiz.pdfas.api.sign.SignResult; import at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters; import at.gv.egiz.pdfas.api.verify.VerifyParameters; import at.gv.egiz.pdfas.api.verify.VerifyResult; import at.gv.egiz.pdfas.api.verify.VerifyResults; import at.gv.egiz.pdfas.commandline.CommandlineConnectorChooser; import at.gv.egiz.pdfas.exceptions.ErrorCode; import at.gv.egiz.pdfas.framework.config.SettingsHelper; import at.gv.egiz.pdfas.framework.input.ExtractionStage; import at.gv.egiz.pdfas.framework.signator.SignatorInformation; import at.gv.egiz.pdfas.framework.vfilter.VerificationFilterParameters; import at.gv.egiz.pdfas.impl.api.analyze.AnalyzeResultImpl; import at.gv.egiz.pdfas.impl.api.commons.DataSinkAdapter; import at.gv.egiz.pdfas.impl.api.commons.PdfDataSourceAdapter; import at.gv.egiz.pdfas.impl.api.commons.SignatureInformationAdapter; import at.gv.egiz.pdfas.impl.api.commons.SignatureProfileImpl; import at.gv.egiz.pdfas.impl.api.commons.TextDataSourceAdapter; import at.gv.egiz.pdfas.impl.api.sign.ActualSignaturePositionAdapter; import at.gv.egiz.pdfas.impl.api.sign.SignResultImpl; import at.gv.egiz.pdfas.impl.api.verify.VerifyResultAdapter; import at.gv.egiz.pdfas.impl.api.verify.VerifyResultsImpl; import at.gv.egiz.pdfas.impl.vfilter.VerificationFilterParametersImpl; import at.knowcenter.wag.egov.egiz.PdfAS; import at.knowcenter.wag.egov.egiz.PdfASID; import at.knowcenter.wag.egov.egiz.cfg.SettingsReader; import at.knowcenter.wag.egov.egiz.exceptions.PDFDocumentException; import at.knowcenter.wag.egov.egiz.exceptions.PresentableException; import at.knowcenter.wag.egov.egiz.exceptions.SignatureException; import at.knowcenter.wag.egov.egiz.framework.SignatorFactory; import at.knowcenter.wag.egov.egiz.pdf.NoSignatureHolder; import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder; import at.knowcenter.wag.egov.egiz.pdf.TablePos; import at.knowcenter.wag.egov.egiz.sig.SignatureResponse; import at.knowcenter.wag.egov.egiz.sig.SignatureTypeDefinition; import at.knowcenter.wag.egov.egiz.sig.SignatureTypes; /** * Implementation of the {@link PdfAs} interface. * * @author wprinz */ public class PdfAsObject implements PdfAs { /** * The work directory. */ protected File workDirectory = null; /** * The log. */ private static Log log = LogFactory.getLog(CheckHelper.class); /** * This constructor is for internal use only - use * {@link at.gv.egiz.pdfas.PdfAsFactory} instead. * * @param workDirectory * The work directory. * @throws PdfAsException * Thrown, if the configuration cannot be processed. */ public PdfAsObject(File workDirectory) throws PdfAsException { if (workDirectory == null) { throw new IllegalArgumentException("The work directory must not be null."); } if (!workDirectory.isDirectory()) { throw new IllegalArgumentException("The work directory does not exist or is not a directory. " + workDirectory.getPath()); } this.workDirectory = workDirectory; SettingsReader.initialize(workDirectory.getPath()); reloadConfig(); } /** * @see at.gv.egiz.pdfas.api.PdfAs#reloadConfig() */ public void reloadConfig() throws PdfAsException { SettingsReader.createInstance(); SignatureTypes.createInstance(); } /** * @see at.gv.egiz.pdfas.api.PdfAs#getProfileInformation() */ public List getProfileInformation() throws PdfAsException { log.debug("Collecting profile information."); final String MOA_SIGN_KEY_IDENTIFIER_KEY = "moa.sign.KeyIdentifier"; SettingsReader settings = SettingsReader.getInstance(); final String defaultMoaKeyIdentifiert = settings.getSetting(MOA_SIGN_KEY_IDENTIFIER_KEY, null); SignatureTypes types = SignatureTypes.getInstance(); List profiles = types.getSignatureTypeDefinitions(); List profileInformation = new ArrayList(profiles.size()); Iterator it = profiles.iterator(); while (it.hasNext()) { SignatureTypeDefinition profile = (SignatureTypeDefinition) it.next(); final String profileId = profile.getType(); log.debug("Processing profile \"" + profileId + "\"."); final String moaKeyIdentifier = settings.getSetting("sig_obj." + profileId + "." + MOA_SIGN_KEY_IDENTIFIER_KEY, defaultMoaKeyIdentifiert); // modified by tknall SignatureProfileImpl signatureProfile = new SignatureProfileImpl(profileId, moaKeyIdentifier); // start - added by tknall // signature entries relevant to the search algorithm Properties signatureEntries = new Properties(); // search for table entries String parentPropertyKey = "sig_obj." + profileId + ".table"; log.debug("Looking for subkeys of \"" + parentPropertyKey + "\"."); Vector keysVector = settings.getSettingKeys(parentPropertyKey); if (keysVector != null) { Iterator keyIt = keysVector.iterator(); while (keyIt.hasNext()) { String subKey = (String) keyIt.next(); if (subKey != null && subKey.length() > 0) { String fullKey = parentPropertyKey + "." + subKey; String value = settings.getValueFromKey(fullKey); int lastIndex = fullKey.lastIndexOf("."); if (lastIndex != -1) { String endsWith = fullKey.substring(lastIndex + 1); if (value != null && value.length() > 0) { if (NumberUtils.isDigits(endsWith)) { signatureEntries.setProperty(fullKey, value); } else { log.debug("Ignoring table entry \"" + fullKey + "\" because it does not end with a digit. Therefore it is not relevant for the seach algorithm."); } } else { log.warn("Problem detected with key \"" + fullKey + "\". The value is empty."); } } } } } // search for table entries parentPropertyKey = "sig_obj." + profileId + ".key"; log.debug("Looking for subkeys of \"" + parentPropertyKey + "\"."); keysVector = settings.getSettingKeys(parentPropertyKey); if (keysVector != null) { Iterator keyIt = keysVector.iterator(); while (keyIt.hasNext()) { String subKey = (String) keyIt.next(); if (subKey != null && subKey.length() > 0) { String fullKey = parentPropertyKey + "." + subKey; String value = settings.getValueFromKey(fullKey); if (value != null && value.length() > 0) { signatureEntries.setProperty(fullKey, value); } else { log.warn("Problem detected with key \"" + fullKey + "\". The value is empty."); } } } } // set properties signatureProfile.setSignatureBlockEntries(signatureEntries); // stop - added by tknall profileInformation.add(signatureProfile); } return profileInformation; } /** * @see at.gv.egiz.pdfas.api.PdfAs#sign(at.gv.egiz.pdfas.api.sign.SignParameters) */ public SignResult sign(SignParameters signParameters) throws PdfAsException { CheckHelper.checkSignParameters(signParameters); signParameters.setDocument(PdfAS.applyStrictMode(signParameters.getDocument())); if (signParameters.getSignatureProfileId() == null) { SettingsReader settings = SettingsReader.getInstance(); String defaultProfile = settings.getValueFromKey(SignatureTypes.DEFAULT_TYPE); signParameters.setSignatureProfileId(defaultProfile); } PdfASID signatorId = null; if (signParameters.getSignatureType().equals(Constants.SIGNATURE_TYPE_BINARY)) { signatorId = SignatorFactory.MOST_RECENT_BINARY_SIGNATOR_ID; } if (signParameters.getSignatureType().equals(Constants.SIGNATURE_TYPE_TEXTUAL)) { signatorId = SignatorFactory.MOST_RECENT_TEXTUAL_SIGNATOR_ID; } if (signParameters.getSignatureType().equals(Constants.SIGNATURE_TYPE_DETACHEDTEXTUAL)) { signatorId = SignatorFactory.MOST_RECENT_DETACHEDTEXT_SIGNATOR_ID; } TablePos pos = PosHelper.formTablePos(signParameters.getSignaturePositioning()); String connectorId = CommandlineConnectorChooser.chooseCommandlineConnectorForSign(signParameters.getSignatureDevice()); SignatorInformation si = PdfAS .signCommandline(new PdfDataSourceAdapter(signParameters.getDocument()), new DataSinkAdapter(signParameters.getOutput()), signatorId, connectorId, signParameters.getSignatureProfileId(), pos); return new SignResultImpl(signParameters.getOutput(), si.getSignSignatureObject().getX509Certificate(), new ActualSignaturePositionAdapter(si.getActualTablePos())); } /** * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyParameters) */ public VerifyResults verify(VerifyParameters verifyParameters) throws PdfAsException { CheckHelper.checkVerifyParameters(verifyParameters); AnalyzeParameters ap = new AnalyzeParameters(); fillAnalyzeParametersWithVerifyParameters(ap, verifyParameters); AnalyzeResult analyzeResult = analyze(ap); if (verifyParameters.getSignatureToVerify() != Constants.VERIFY_ALL) { if (verifyParameters.getSignatureToVerify() >= analyzeResult.getSignatures().size()) { throw new SignatureException(312, "The selected signature to be verified doesn't exist. " + verifyParameters.getSignatureToVerify()); } Object stv = analyzeResult.getSignatures().get(verifyParameters.getSignatureToVerify()); List selectedSignature = new ArrayList(1); selectedSignature.add(stv); analyzeResult = new AnalyzeResultImpl(selectedSignature); } VerifyAfterAnalysisParameters vaap = new VerifyAfterAnalysisParameters(); vaap.setAnalyzeResult(analyzeResult); fillVerifyAfterAnalysisParametersWithVerifyParameters(vaap, verifyParameters); return verify(vaap); } /** * Copies all adequate parameters from the {@link VerifyParameters} to the * {@link AnalyzeParameters}. * * @param ap * The {@link AnalyzeParameters}. * @param vp * The {@link VerifyParameters}. */ protected void fillAnalyzeParametersWithVerifyParameters(AnalyzeParameters ap, VerifyParameters vp) { ap.setDocument(vp.getDocument()); ap.setVerifyMode(vp.getVerifyMode()); } /** * Copies all adequate parameters from the {@link VerifyParameters} to the * {@link VerifyAfterAnalysisParameters}. * * @param vaap * The {@link VerifyAfterAnalysisParameters}. * @param vp * The {@link VerifyParameters}. */ protected void fillVerifyAfterAnalysisParametersWithVerifyParameters(VerifyAfterAnalysisParameters vaap, VerifyParameters vp) { vaap.setSignatureDevice(vp.getSignatureDevice()); vaap.setVerificationTime(vp.getVerificationTime()); vaap.setReturnHashInputData(vp.isReturnHashInputData()); } /** * @see at.gv.egiz.pdfas.api.PdfAs#analyze(at.gv.egiz.pdfas.api.analyze.AnalyzeParameters) */ public AnalyzeResult analyze(AnalyzeParameters analyzeParameters) throws PdfAsException { CheckHelper.checkAnalyzeParameters(analyzeParameters); VerificationFilterParameters parametersConfig = SettingsHelper.readVerificationFilterParametersFromSettings(); boolean binaryOnly = parametersConfig.extractBinarySignaturesOnly(); if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_BINARY_ONLY)) { binaryOnly = true; } boolean assumeOnlySB = parametersConfig.assumeOnlySignatureUpdateBlocks(); if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_SEMI_CONSERVATIVE)) { assumeOnlySB = true; } if (analyzeParameters.getVerifyMode().equals(Constants.VERIFY_MODE_FULL_CONSERVATIVE)) { assumeOnlySB = false; } VerificationFilterParameters parameters = new VerificationFilterParametersImpl(binaryOnly, assumeOnlySB, parametersConfig.scanForOldSignatures()); at.gv.egiz.pdfas.framework.input.DataSource inputDataSource = null; if (analyzeParameters.getDocument().getMimeType().equals("application/pdf")) { inputDataSource = new PdfDataSourceAdapter(analyzeParameters.getDocument()); } else { try { inputDataSource = new TextDataSourceAdapter(analyzeParameters.getDocument()); } catch (UnsupportedEncodingException e) { throw new PresentableException(ErrorCode.DOCUMENT_CANNOT_BE_READ, "The characterEncoding is not supported." + analyzeParameters.getDocument().getCharacterEncoding(), e); } } assert inputDataSource != null; ExtractionStage es = new ExtractionStage(); List signature_holders = es.extractSignatureHolders(inputDataSource, parameters); // List sigInfs = new ArrayList(signature_holders.size()); List sigInfs = new ArrayList(); List noSigs = new ArrayList(); Iterator it = signature_holders.iterator(); while (it.hasNext()) { SignatureHolder sh = (SignatureHolder)it.next(); if(sh instanceof NoSignatureHolder) { noSigs.add(sh); } else { SignatureInformation si = new SignatureInformationAdapter(sh); sigInfs.add(si); } } return new AnalyzeResultImpl(sigInfs, noSigs); } /** * @see at.gv.egiz.pdfas.api.PdfAs#verify(at.gv.egiz.pdfas.api.verify.VerifyAfterAnalysisParameters) */ public VerifyResults verify(VerifyAfterAnalysisParameters verifyAfterAnalysisParameters) throws PdfAsException { CheckHelper.checkVerifyAfterAnalysisParameters(verifyAfterAnalysisParameters); List signatures = verifyAfterAnalysisParameters.getAnalyzeResult().getSignatures(); // added by tknall if (signatures == null || signatures.isEmpty()) { throw new PDFDocumentException(ErrorCode.DOCUMENT_NOT_SIGNED, "PDF document not signed."); //$NON-NLS-1$ } List signature_holders = new ArrayList(signatures.size()); Iterator it = signatures.iterator(); while (it.hasNext()) { SignatureInformation si = (SignatureInformation) it.next(); SignatureHolder sh = (SignatureHolder) si.getInternalSignatureInformation(); signature_holders.add(sh); } assert signature_holders.size() == signatures.size(); List results = PdfAS.verifySignatureHolders(signature_holders, verifyAfterAnalysisParameters.getSignatureDevice(), verifyAfterAnalysisParameters.isReturnHashInputData(), verifyAfterAnalysisParameters.getVerificationTime()); List vrs = new ArrayList(results.size()); assert signature_holders.size() == results.size() : "Not all signatures were verified."; for (int i = 0; i < signature_holders.size(); i++) { SignatureResponse response = (SignatureResponse) results.get(i); SignatureHolder holder = (SignatureHolder) signature_holders.get(i); VerifyResult vr = new VerifyResultAdapter(response, holder, verifyAfterAnalysisParameters.getVerificationTime()); vrs.add(vr); } return new VerifyResultsImpl(vrs); } }