From 84a9465b14154f3e56a6b772d21e70f1c60bdf47 Mon Sep 17 00:00:00 2001
From: Jakob Heher <jakob.heher@iaik.tugraz.at>
Date: Mon, 8 Aug 2022 13:31:47 +0200
Subject: synchronize pdf-as profile hackery to avoid potential race conditions

---
 .../signer/pdfas/PdfAs4SignatureParameter.java     |  73 ++++-----
 .../at/asit/pdfover/signer/pdfas/PdfAs4Signer.java | 164 +++++++++++----------
 2 files changed, 122 insertions(+), 115 deletions(-)

diff --git a/pdf-over-signer/src/main/java/at/asit/pdfover/signer/pdfas/PdfAs4SignatureParameter.java b/pdf-over-signer/src/main/java/at/asit/pdfover/signer/pdfas/PdfAs4SignatureParameter.java
index 12b617e3..4356f1e0 100644
--- a/pdf-over-signer/src/main/java/at/asit/pdfover/signer/pdfas/PdfAs4SignatureParameter.java
+++ b/pdf-over-signer/src/main/java/at/asit/pdfover/signer/pdfas/PdfAs4SignatureParameter.java
@@ -91,43 +91,46 @@ public class PdfAs4SignatureParameter {
 
         try {
             X509Certificate cert = new X509Certificate(PdfAs4SignatureParameter.class.getResourceAsStream("/example.cer"));
-            PdfAs pdfas = PdfAs4Helper.getPdfAs();
-            Configuration conf = pdfas.getConfiguration();
-            if (sigEmblem != null && !sigEmblem.trim().equals("")) {
-                conf.setValue("sig_obj." + sigProfile + ".value.SIG_LABEL", sigEmblem);
-            }
-            if (sigNote != null) {
-                conf.setValue("sig_obj." + sigProfile + ".value.SIG_NOTE", sigNote);
-            }
-            if (this.signatureProfile == Profile.BASE_LOGO)
-            {
-                int emblemWidth = (this.emblem != null) ? this.emblem.getWidth() : 65;
-                int emblemHeight = (this.emblem != null) ? this.emblem.getHeight() : 65;
-                double aspectRatio = ((double)emblemWidth) / emblemHeight;
-                double targetWidth = 65.0;
-                double targetHeight = 65.0;
-                if (aspectRatio < 1)
-                    targetWidth = 65.0 * aspectRatio;
-                else
-                    targetHeight = 65.0 / aspectRatio;
-                conf.setValue("sig_obj." + sigProfile + ".table.main.Style.padding", "0");
-                conf.setValue("sig_obj." + sigProfile + ".pos", "w:"+targetWidth+";f:0");
-                conf.setValue("sig_obj." + sigProfile + ".table.main.Style.imagescaletofit", targetWidth+";"+targetHeight);
-            }
-            SignParameter param = PdfAsFactory.createSignParameter(conf, null, null);
-            param.setSignatureProfileId(sigProfile);
             
-            Image placeholder = pdfas.generateVisibleSignaturePreview(param, cert, 72 * 4);
-
-            // WORKAROUND for #110, manually paint a black border
-            if (!this.signatureProfile.equals(Profile.BASE_LOGO))
-            {
-                Graphics2D ctx = (Graphics2D)placeholder.getGraphics();
-                ctx.setColor(Color.BLACK);
-                ctx.drawRect(0, 0, placeholder.getWidth(null)-1, placeholder.getHeight(null)-1);
+            PdfAs pdfas = PdfAs4Helper.getPdfAs();
+            synchronized (PdfAs4Helper.class) {
+                Configuration conf = pdfas.getConfiguration();
+                if (sigEmblem != null && !sigEmblem.trim().equals("")) {
+                    conf.setValue("sig_obj." + sigProfile + ".value.SIG_LABEL", sigEmblem);
+                }
+                if (sigNote != null) {
+                    conf.setValue("sig_obj." + sigProfile + ".value.SIG_NOTE", sigNote);
+                }
+                if (this.signatureProfile == Profile.BASE_LOGO)
+                {
+                    int emblemWidth = (this.emblem != null) ? this.emblem.getWidth() : 65;
+                    int emblemHeight = (this.emblem != null) ? this.emblem.getHeight() : 65;
+                    double aspectRatio = ((double)emblemWidth) / emblemHeight;
+                    double targetWidth = 65.0;
+                    double targetHeight = 65.0;
+                    if (aspectRatio < 1)
+                        targetWidth = 65.0 * aspectRatio;
+                    else
+                        targetHeight = 65.0 / aspectRatio;
+                    conf.setValue("sig_obj." + sigProfile + ".table.main.Style.padding", "0");
+                    conf.setValue("sig_obj." + sigProfile + ".pos", "w:"+targetWidth+";f:0");
+                    conf.setValue("sig_obj." + sigProfile + ".table.main.Style.imagescaletofit", targetWidth+";"+targetHeight);
+                }
+                SignParameter param = PdfAsFactory.createSignParameter(conf, null, null);
+                param.setSignatureProfileId(sigProfile);
+                
+                Image placeholder = pdfas.generateVisibleSignaturePreview(param, cert, 72 * 4);
+
+                // WORKAROUND for #110, manually paint a black border
+                if (!this.signatureProfile.equals(Profile.BASE_LOGO))
+                {
+                    Graphics2D ctx = (Graphics2D)placeholder.getGraphics();
+                    ctx.setColor(Color.BLACK);
+                    ctx.drawRect(0, 0, placeholder.getWidth(null)-1, placeholder.getHeight(null)-1);
+                }
+
+                return placeholder;
             }
-
-            return placeholder;
         } catch (Exception e) {
             log.error("Failed to get signature placeholder", e);
             return new BufferedImage(229, 77, BufferedImage.TYPE_INT_RGB);
diff --git a/pdf-over-signer/src/main/java/at/asit/pdfover/signer/pdfas/PdfAs4Signer.java b/pdf-over-signer/src/main/java/at/asit/pdfover/signer/pdfas/PdfAs4Signer.java
index 51e36037..628b5c11 100644
--- a/pdf-over-signer/src/main/java/at/asit/pdfover/signer/pdfas/PdfAs4Signer.java
+++ b/pdf-over-signer/src/main/java/at/asit/pdfover/signer/pdfas/PdfAs4Signer.java
@@ -52,52 +52,55 @@ public class PdfAs4Signer {
 		if (parameter.signaturePosition != null) {
 			sigPos = parameter.getPdfAsSignaturePosition();
 		}
+
 		PdfAs pdfas = PdfAs4Helper.getPdfAs();
-		Configuration config = pdfas.getConfiguration();
-		if (sigEmblem != null && !sigEmblem.trim().isEmpty()) {
-			config.setValue("sig_obj." + sigProfile + ".value.SIG_LABEL", sigEmblem);
-		}
+		synchronized (PdfAs4Helper.class) {
+			Configuration config = pdfas.getConfiguration();
+			if (sigEmblem != null && !sigEmblem.trim().isEmpty()) {
+				config.setValue("sig_obj." + sigProfile + ".value.SIG_LABEL", sigEmblem);
+			}
 
-		if(sigNote != null) {
-			config.setValue("sig_obj." + sigProfile + ".value.SIG_NOTE", sigNote);
-		}
+			if(sigNote != null) {
+				config.setValue("sig_obj." + sigProfile + ".value.SIG_NOTE", sigNote);
+			}
 
-		// TODO encapsulate this parameter magic in PdfAs4SignatureParameter
-		if (parameter.signatureProfile == Profile.BASE_LOGO)
-		{
-			int emblemWidth = (parameter.emblem != null) ? parameter.emblem.getWidth() : 65;
-			int emblemHeight = (parameter.emblem != null) ? parameter.emblem.getHeight() : 65;
-			double aspectRatio = ((double)emblemWidth) / emblemHeight;
-			double targetWidth = 65.0;
-			double targetHeight = 65.0;
-			if (aspectRatio < 1)
-				targetWidth = 65.0 * aspectRatio;
-			else
-				targetHeight = 65.0 / aspectRatio;
-			config.setValue("sig_obj." + sigProfile + ".table.main.Style.padding", "0");
-			config.setValue("sig_obj." + sigProfile + ".pos", "w:"+targetWidth+";f:0");
-			config.setValue("sig_obj." + sigProfile + ".table.main.Style.imagescaletofit", targetWidth+";"+targetHeight);
-		}
+			// TODO encapsulate this parameter magic in PdfAs4SignatureParameter
+			if (parameter.signatureProfile == Profile.BASE_LOGO)
+			{
+				int emblemWidth = (parameter.emblem != null) ? parameter.emblem.getWidth() : 65;
+				int emblemHeight = (parameter.emblem != null) ? parameter.emblem.getHeight() : 65;
+				double aspectRatio = ((double)emblemWidth) / emblemHeight;
+				double targetWidth = 65.0;
+				double targetHeight = 65.0;
+				if (aspectRatio < 1)
+					targetWidth = 65.0 * aspectRatio;
+				else
+					targetHeight = 65.0 / aspectRatio;
+				config.setValue("sig_obj." + sigProfile + ".table.main.Style.padding", "0");
+				config.setValue("sig_obj." + sigProfile + ".pos", "w:"+targetWidth+";f:0");
+				config.setValue("sig_obj." + sigProfile + ".table.main.Style.imagescaletofit", targetWidth+";"+targetHeight);
+			}
 
-		PdfAs4SigningState state = new PdfAs4SigningState();
-		ByteArrayOutputStream output = new ByteArrayOutputStream();
-		DataSource input = new ByteArrayDataSource(parameter.inputDocument.getByteArray());
-		SignParameter param = PdfAsFactory.createSignParameter(config, input, output);
-		if (sigPos != null) {
-			param.setSignaturePosition(sigPos);
-		}
-		param.setSignatureProfileId(sigProfile);
-		String id = UUID.randomUUID().toString();
-		param.setTransactionId(id);
+			PdfAs4SigningState state = new PdfAs4SigningState();
+			ByteArrayOutputStream output = new ByteArrayOutputStream();
+			DataSource input = new ByteArrayDataSource(parameter.inputDocument.getByteArray());
+			SignParameter param = PdfAsFactory.createSignParameter(config, input, output);
+			if (sigPos != null) {
+				param.setSignaturePosition(sigPos);
+			}
+			param.setSignatureProfileId(sigProfile);
+			String id = UUID.randomUUID().toString();
+			param.setTransactionId(id);
 
-		if (parameter.searchForPlaceholderSignatures) {
-			param.getConfiguration().setValue(IConfigurationConstants.PLACEHOLDER_MODE, "1");
-			param.getConfiguration().setValue(IConfigurationConstants.PLACEHOLDER_SEARCH_ENABLED, IConfigurationConstants.TRUE);
-		}
+			if (parameter.searchForPlaceholderSignatures) {
+				param.getConfiguration().setValue(IConfigurationConstants.PLACEHOLDER_MODE, "1");
+				param.getConfiguration().setValue(IConfigurationConstants.PLACEHOLDER_SEARCH_ENABLED, IConfigurationConstants.TRUE);
+			}
 
-		state.signParameter = param;
-		state.output = output;
-		return state;
+			state.signParameter = param;
+			state.output = output;
+			return state;
+		}
 	}
 
 	public static SignResult sign(PdfAs4SigningState state) throws SignatureException {
@@ -106,48 +109,49 @@ public class PdfAs4Signer {
 				throw new SignatureException("Incorrect SigningState!");
 			}
 
-			// Retrieve objects
 			PdfAs pdfas = PdfAs4Helper.getPdfAs();
-
-			SignParameter param = state.signParameter;
-
-			Configuration config = param.getConfiguration();
-			config.setValue(IConfigurationConstants.SL_REQUEST_TYPE,
-					state.useBase64Request ?
-							IConfigurationConstants.SL_REQUEST_TYPE_BASE64 :
-								IConfigurationConstants.SL_REQUEST_TYPE_UPLOAD);
-
-			IPlainSigner signer;
-			if (state.bkuConnector != null) {
-				ISLConnector connector = new PdfAs4BKUSLConnector(state.bkuConnector);
-				signer = new PAdESSigner(connector);
-			} else if (state.hasKeystoreSigner()) {
-				signer = state.getKeystoreSigner();
-			} else {
-				throw new SignatureException("SigningState doesn't have a signer");
-			}
-			param.setPlainSigner(signer);
-
-			pdfas.sign(param);
-
-			SignResult result = new SignResult();
-
-			if (param.getSignaturePosition() != null) {
-				TablePos tp = new TablePos(param.getSignaturePosition());
-				SignaturePosition sp;
-				if (tp.isXauto() && tp.isYauto())
-					sp = new SignaturePosition();
-				else if (tp.isPauto())
-					sp = new SignaturePosition(tp.getPosX(), tp.getPosY());
-				else if (param.getSignatureProfileId().contains(Profile.AMTSSIGNATURBLOCK.name()))
-					sp = new SignaturePosition();
-				else
-					sp = new SignaturePosition(tp.getPosX(), tp.getPosY(), tp.getPage());
-				result.setSignaturePosition(sp);
+			synchronized (PdfAs4Helper.class) {
+				// Retrieve objects
+				SignParameter param = state.signParameter;
+
+				Configuration config = param.getConfiguration();
+				config.setValue(IConfigurationConstants.SL_REQUEST_TYPE,
+						state.useBase64Request ?
+								IConfigurationConstants.SL_REQUEST_TYPE_BASE64 :
+									IConfigurationConstants.SL_REQUEST_TYPE_UPLOAD);
+
+				IPlainSigner signer;
+				if (state.bkuConnector != null) {
+					ISLConnector connector = new PdfAs4BKUSLConnector(state.bkuConnector);
+					signer = new PAdESSigner(connector);
+				} else if (state.hasKeystoreSigner()) {
+					signer = state.getKeystoreSigner();
+				} else {
+					throw new SignatureException("SigningState doesn't have a signer");
+				}
+				param.setPlainSigner(signer);
+
+				pdfas.sign(param);
+
+				SignResult result = new SignResult();
+
+				if (param.getSignaturePosition() != null) {
+					TablePos tp = new TablePos(param.getSignaturePosition());
+					SignaturePosition sp;
+					if (tp.isXauto() && tp.isYauto())
+						sp = new SignaturePosition();
+					else if (tp.isPauto())
+						sp = new SignaturePosition(tp.getPosX(), tp.getPosY());
+					else if (param.getSignatureProfileId().contains(Profile.AMTSSIGNATURBLOCK.name()))
+						sp = new SignaturePosition();
+					else
+						sp = new SignaturePosition(tp.getPosX(), tp.getPosY(), tp.getPage());
+					result.setSignaturePosition(sp);
+				}
+
+				result.setSignedDocument(new ByteArrayDocumentSource(state.output.toByteArray()));
+				return result;
 			}
-
-			result.setSignedDocument(new ByteArrayDocumentSource(state.output.toByteArray()));
-			return result;
 		} catch (PdfAsException | PDFASError e) {
 			throw new SignatureException(e);
 		}
-- 
cgit v1.2.3