diff options
Diffstat (limited to 'src/main/java')
21 files changed, 532 insertions, 192 deletions
| diff --git a/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java b/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java index 19f7613..4fec0a1 100644 --- a/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java +++ b/src/main/java/at/gv/egiz/pdfas/api/commons/Constants.java @@ -110,6 +110,8 @@ public final class Constants     * The name of the directory, where temporary files are stored.
     */
    public static final String TEMP_DIR_NAME = "pdfastmp";
 +  
 +  public static final String BKU_HEADER_SIGNATURE_LAYOUT = "SignatureLayout";
  }
 diff --git a/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java b/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java index f6b5602..c51d10a 100644 --- a/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java +++ b/src/main/java/at/gv/egiz/pdfas/exceptions/ErrorCode.java @@ -20,6 +20,7 @@ public final class ErrorCode    public static final int SETTINGS_EXCEPTION = 101;
    public static final int KZ_SETTING_NOT_FOUND = 102;
    public static final int NO_EMBEDABLE_TTF_CONFIGURED_FOR_PDFA = 103;
 +  public static final int INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED = 104;
    public static final int DOCUMENT_CANNOT_BE_READ = 201;
    public static final int TEXT_EXTRACTION_EXCEPTION = 202;
 @@ -44,7 +45,9 @@ public final class ErrorCode    public static final int NON_BINARY_SIGNATURES_PRESENT = 317;  
    public static final int SIGNATURE_VERIFICATION_NOT_SUPPORTED = 371;  
 -  public static final int INVALID_SIGNING_TIME = 372;  
 +  public static final int INVALID_SIGNING_TIME = 372;
 +
 +  public static final int BKU_NOT_SUPPORTED = 373;
    public static final int WEB_EXCEPTION = 330;
 diff --git a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java index a7c5d7a..235a03e 100644 --- a/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java +++ b/src/main/java/at/gv/egiz/pdfas/framework/ConnectorParameters.java @@ -15,93 +15,84 @@ import java.util.Date;   * 
   * @author wprinz
   */
 -public class ConnectorParameters
 -{
 -  /**
 -   * The profile Id to get the connector parameters from.
 -   * 
 -   * <p>
 -   * The there are no explicit parameters for the connector in the profile, the
 -   * default parameters are used.
 -   * </p>
 -   */
 -  protected String profileId = null;
 +public class ConnectorParameters {
 +   /**
 +    * The profile Id to get the connector parameters from.
 +    * 
 +    * <p>
 +    * The there are no explicit parameters for the connector in the profile, the
 +    * default parameters are used.
 +    * </p>
 +    */
 +   protected String profileId = null;
 -  /**
 -   * The signature key identifier to be used or null if it should be read from
 -   * the profile.
 -   * 
 -   * <p>
 -   * Currently this is only used by MOA connectors and identifies the MOA key
 -   * group to be used when signing. If null, the MOA connector reads the key
 -   * from the profile.
 -   * </p>
 -   */
 -  protected String signatureKeyIdentifier = null;
 +   /**
 +    * The signature key identifier to be used or null if it should be read from
 +    * the profile.
 +    * 
 +    * <p>
 +    * Currently this is only used by MOA connectors and identifies the MOA key
 +    * group to be used when signing. If null, the MOA connector reads the key
 +    * from the profile.
 +    * </p>
 +    */
 +   protected String signatureKeyIdentifier = null;
 -  /**
 -   * Tells, if the connector should ask the device to return the hash input
 -   * data.
 -   * 
 -   * <p>
 -   * Note that not all connectors support to return the hash input data - so
 -   * there is no guarantee that the hash value will actually be returned.
 -   * </p>
 -   */
 -  protected boolean returnHashInputData = false;
 +   /**
 +    * Tells, if the connector should ask the device to return the hash input
 +    * data.
 +    * 
 +    * <p>
 +    * Note that not all connectors support to return the hash input data - so
 +    * there is no guarantee that the hash value will actually be returned.
 +    * </p>
 +    */
 +   protected boolean returnHashInputData = false;
 -  /**
 -   * Allows to specify an explicit time of verification.
 -   * 
 -   * <p>
 -   * If null, the device's default behaviour determines the time of
 -   * verification, which is usually the current time.
 -   * </p>
 -   * <p>
 -   * The time of verification usually influences the certificate check. E.g. the
 -   * certificate may not be valid at the time of verification.
 -   * </p>
 -   */
 -  protected Date verificationTime = null;
 +   /**
 +    * Allows to specify an explicit time of verification.
 +    * 
 +    * <p>
 +    * If null, the device's default behaviour determines the time of
 +    * verification, which is usually the current time.
 +    * </p>
 +    * <p>
 +    * The time of verification usually influences the certificate check. E.g.
 +    * the certificate may not be valid at the time of verification.
 +    * </p>
 +    */
 +   protected Date verificationTime = null;
 -  public String getProfileId()
 -  {
 -    return this.profileId;
 -  }
 +   public String getProfileId() {
 +      return this.profileId;
 +   }
 -  public void setProfileId(String profileId)
 -  {
 -    this.profileId = profileId;
 -  }
 -  
 -  public String getSignatureKeyIdentifier()
 -  {
 -    return this.signatureKeyIdentifier;
 -  }
 +   public void setProfileId(String profileId) {
 +      this.profileId = profileId;
 +   }
 -  public void setSignatureKeyIdentifier(String signatureKeyIdentifier)
 -  {
 -    this.signatureKeyIdentifier = signatureKeyIdentifier;
 -  }
 +   public String getSignatureKeyIdentifier() {
 +      return this.signatureKeyIdentifier;
 +   }
 -  public boolean isReturnHashInputData()
 -  {
 -    return this.returnHashInputData;
 -  }
 +   public void setSignatureKeyIdentifier(String signatureKeyIdentifier) {
 +      this.signatureKeyIdentifier = signatureKeyIdentifier;
 +   }
 -  public void setReturnHashInputData(boolean returnHashInputData)
 -  {
 -    this.returnHashInputData = returnHashInputData;
 -  }
 +   public boolean isReturnHashInputData() {
 +      return this.returnHashInputData;
 +   }
 -  public Date getVerificationTime()
 -  {
 -    return this.verificationTime;
 -  }
 +   public void setReturnHashInputData(boolean returnHashInputData) {
 +      this.returnHashInputData = returnHashInputData;
 +   }
 -  public void setVerificationTime(Date verificationTime)
 -  {
 -    this.verificationTime = verificationTime;
 -  }
 +   public Date getVerificationTime() {
 +      return this.verificationTime;
 +   }
 +
 +   public void setVerificationTime(Date verificationTime) {
 +      this.verificationTime = verificationTime;
 +   }
  }
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java b/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java index c56a03e..2073714 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/PdfAS.java @@ -96,7 +96,7 @@ public abstract class PdfAS     * The current version of the pdf-as library. This version string is logged on every invocation
     * of the api or the web application.
     */
 -  public static final String PDFAS_VERSION = "3.0.9-20090319";
 +  public static final String PDFAS_VERSION = "3.0.9-20090417";
    /**
     * The key of the strict mode setting.
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java index af155a1..43c9649 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUHelper.java @@ -9,14 +9,18 @@ import java.security.cert.X509Certificate;  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import java.util.Date;
 +import java.util.Properties;
  import java.util.TimeZone;
  import java.util.regex.Matcher;
  import java.util.regex.Pattern;
 +import javax.servlet.http.HttpServletRequest;
 +
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
 +import at.gv.egiz.pdfas.api.commons.Constants;
  import at.gv.egiz.pdfas.exceptions.external.ExternalErrorException;
  import at.gv.egiz.pdfas.impl.input.helper.DataSourceHelper;
  import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 @@ -582,4 +586,71 @@ public final class BKUHelper      };
      return dateTimeElement;
    }
 +  
 +  public static String getBKUIdentifier(Properties parsedResponseProperties) {
 +     
 +     // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
 +     String bkuServerHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
 +
 +     // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
 +     String bkuUserAgentHeader = parsedResponseProperties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
 +     
 +     String bkuSignatureLayout = parsedResponseProperties.getProperty(BKUPostConnection.BKU_SIGNATURE_LAYOUT_HEADER_KEY);
 +
 +     log.debug("BKU response header \"user-agent\":  " + bkuUserAgentHeader);
 +     log.debug("BKU response header \"server\":  " + bkuServerHeader);
 +     log.trace("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\":  " + bkuSignatureLayout);
 +
 +     String result = null;
 +     
 +     if (bkuServerHeader != null) {
 +        result = bkuServerHeader;
 +     } else if (bkuUserAgentHeader != null) {
 +        result = bkuUserAgentHeader;
 +     } else {
 +        log.warn("Unable to find any BKU identifier (neither header value \"user-agent\" nor \"server\".)");
 +     }
 +     
 +     if (bkuSignatureLayout != null && result != null) {
 +        log.info("BKU response header \"" + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "\" found.");
 +        String signatureLayoutData = " " + Constants.BKU_HEADER_SIGNATURE_LAYOUT + "/" + bkuSignatureLayout;
 +        if (!result.endsWith(signatureLayoutData)) {
 +           log.debug("Appending signature layout value \"" + bkuSignatureLayout + "\" to bku identifier.");
 +           result += signatureLayoutData;
 +        } else {
 +           log.debug("Signature layout already encoded in server/user-agent header.");
 +        }
 +     }
 +     
 +     if (result != null) {
 +        log.debug("Returning BKU identifier \"" + result + "\"");
 +     } else {
 +        log.debug("Returning null BKU identifier.");
 +     }
 +     
 +     return result;
 +  }
 +  
 +  public static String getBKUIdentifier(HttpServletRequest request) {
 +     return getBKUIdentifier(getBKUProperties(request));
 +  }
 +  
 +  public static Properties getBKUProperties(HttpServletRequest request) {
 +     Properties props = new Properties();
 +     String server = request.getHeader("server");
 +     String userAgent = request.getHeader("user-agent");
 +     String signatureLayout = request.getHeader(Constants.BKU_HEADER_SIGNATURE_LAYOUT);
 +     if (server != null) {
 +        props.setProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY, server);
 +     }
 +     if (userAgent != null) {
 +        props.setProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY, userAgent);
 +     }
 +     if (signatureLayout != null) {
 +        props.setProperty(BKUPostConnection.BKU_SIGNATURE_LAYOUT_HEADER_KEY, signatureLayout);
 +     }
 +     return props;
 +  }
 +  
 +  
  }
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java index b582715..d2cffe8 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/BKUPostConnection.java @@ -20,6 +20,7 @@ import org.apache.commons.httpclient.params.HttpMethodParams;  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
 +import at.gv.egiz.pdfas.api.commons.Constants;
  import at.knowcenter.wag.egov.egiz.sig.SignatureData;
  /**
 @@ -39,6 +40,11 @@ public final class BKUPostConnection     * The response Properties key that identifies the BKU Server header.
     */
    public static final String BKU_SERVER_HEADER_KEY = "BKU-Server-Header"; //$NON-NLS-1$
 +  
 +  /**
 +   * The response property that declares the signature layout being applied.
 +   */
 +  public static final String BKU_SIGNATURE_LAYOUT_HEADER_KEY = "BKU-Signature-Layout"; //$NON-NLS-1$
    /**
     * The response Properties key that identifies the BKU User-Agent header.
 @@ -130,6 +136,11 @@ public final class BKUPostConnection         log.warn("BKU response header \"Server\" is empty.");
      }
 +    Header signatureLayoutHeader = post_method.getResponseHeader(Constants.BKU_HEADER_SIGNATURE_LAYOUT); //$NON-NLS-1$
 +    if (signatureLayoutHeader != null) {
 +       response_properties.setProperty(BKU_SIGNATURE_LAYOUT_HEADER_KEY, signatureLayoutHeader.getValue());
 +    }
 +
      log.debug(post_method.getResponseCharSet());
      if (!post_method.getResponseCharSet().equals("UTF-8")) //$NON-NLS-1$
      {
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java index 5164771..100f054 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/DetachedBKUConnector.java @@ -21,10 +21,10 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.Connector;  import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector;
  import at.knowcenter.wag.egov.egiz.sig.connectors.TemplateReplaces;
  import at.knowcenter.wag.egov.egiz.sig.connectors.moa.DetachedLocRefMOAConnector;
 -import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper;
 -import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedIdFormatter;
 -import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.LocRefDetachedMOCCAConnector;
  import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory;
  import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
  import at.knowcenter.wag.egov.egiz.tools.FileHelper;
 @@ -125,24 +125,20 @@ public class DetachedBKUConnector implements Connector, LocalConnector      log.debug("analyzeSignResponse:"); //$NON-NLS-1$
      String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
 -    String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
 -    String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
      BKUHelper.checkResponseForError(response_string);
 -    // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
 -    log.debug("BKU response header \"user-agent\" header:  " + bkuUserAgentHeader);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
 -    log.debug("BKU response header \"server\"     header:  " + bkuServerHeader);
 +    String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
 +    log.debug("BKU identifier: \"" + bkuIdentifier + "\"");
 -    SignSignatureObject so;
 -    if (MOCCAHelper.isMOCCACCEId(bkuServerHeader == null ? bkuUserAgentHeader : bkuServerHeader)) {
 -       log.debug("Evaluating response as MOCCA response.");
 -       so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter());
 -    } else {
 -       so = BKUHelper.parseCreateXMLResponse(response_string, new DetachedIdFormatter());
 +    SignatureLayoutHandler sigLayout;
 +    try {
 +       sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier);
 +    } catch (SettingsException e) {
 +       throw new ConnectorException(e.getErrorCode(), e.getMessage());
      }
 +    
 +    SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string);
      so.response_properties = response_properties;
 @@ -322,17 +318,29 @@ public class DetachedBKUConnector implements Connector, LocalConnector      String verify_request_template = this.environment.getVerifyRequestTemplate();
      String xml_content = null;
 +
 +    // MOA
      if (SigKZIDHelper.isMOASigned(so))
      {
        log.debug("The signature is MOA signed -> getting XML content from DetachedLocRefMOA connector.");
        DetachedLocRefMOAConnector moa_conn = new DetachedLocRefMOAConnector(this.environment.getProfile(), "loc ref not needed here");
        xml_content = moa_conn.prepareXMLContent(data, so);
 -    }
 +
 +      // MOCCA
 +  } else if (SigKZIDHelper.isMOCCASigned(so)) {
 +     log.debug("MOCCA signature detected.");
 +     String algorithmId = SigKZIDHelper.parseAlgorithmId(so.id);
 +     log.debug("Algorithm = " + algorithmId);
 +     LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId);
 +     xml_content = mocca_connector.prepareXMLContent(data, so);
 +  }
 +  // TD
      else
      {
 +      log.debug("TD signature signature detected.");
        xml_content = prepareXMLContent(data, so);
      }
 -
 +    
      String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
      verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.LOC_REF_CONTENT_REPLACE, this.environment.getLocRefContent());
      verify_request_xml = verify_request_xml.replaceFirst(TemplateReplaces.DATE_TIME_REPLACE, BKUHelper.formDateTimeElement(this.params.getVerificationTime(), "sl"));
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java index f30b4b7..e415e98 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/bku/EnvelopedBase64BKUConnector.java @@ -360,13 +360,8 @@ public class EnvelopedBase64BKUConnector implements Connector, LocalConnector      BKUHelper.checkResponseForError(response_string);
 -    // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs
 -    String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
 -    String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
 -    log.debug("BKU response header \"user-agent\" header:  " + bkuUserAgentHeader);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
 -    log.debug("BKU response header \"server\"     header:  " + bkuServerHeader);
 +    String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
 +    log.debug("BKU identifier: \"" + bkuIdentifier + "\"");
      SignSignatureObject so = BKUHelper.parseCreateXMLResponse(response_string, new HotfixIdFormatter());
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java index 6ad5b94..b31d1ec 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/DetachedLocRefMOAConnector.java @@ -107,14 +107,6 @@ public class DetachedLocRefMOAConnector implements Connector      BKUHelper.checkResponseForError(response_string);
 -    // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs
 -    String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
 -    String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
 -    log.debug("BKU response header \"user-agent\" header:  " + bkuUserAgentHeader);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
 -    log.debug("BKU response header \"server\"     header:  " + bkuServerHeader);
 -    
      SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new DetachedLocRefMOAIdFormatter());
      log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java index b309432..a6db63c 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/EnvelopingBase64MOAConnector.java @@ -218,14 +218,6 @@ public class EnvelopingBase64MOAConnector implements Connector      BKUHelper.checkResponseForError(response_string);
 -    // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs
 -    String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
 -    String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
 -    log.debug("BKU response header \"user-agent\" header:  " + bkuUserAgentHeader);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
 -    log.debug("BKU response header \"server\"     header:  " + bkuServerHeader);
 -
      SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new OldMOAIdFormatter());
      log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java index abd2b09..4636e20 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/moa/MOASoapWithAttachmentConnector.java @@ -115,14 +115,6 @@ public class MOASoapWithAttachmentConnector implements Connector      BKUHelper.checkResponseForError(response_string);
 -    // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs
 -    String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
 -    String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
 -    log.debug("BKU response header \"user-agent\" header:  " + bkuUserAgentHeader);
 -    // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
 -    log.debug("BKU response header \"server\"     header:  " + bkuServerHeader);
 -    
      SignSignatureObject so = MOAHelper.parseCreateXMLResponse(response_string, new DetachedLocRefMOAIdFormatter());
      log.debug("analyzeSignResponse finished."); //$NON-NLS-1$
 @@ -189,17 +181,24 @@ public class MOASoapWithAttachmentConnector implements Connector      String xml_content = null;
 +    // MOA
      if (SigKZIDHelper.isMOASigned(so)) {
         log.debug("MOA signature detected.");
         xml_content = prepareXMLContent(data, so);
 +       
 +    // MOCCA
      } else if (SigKZIDHelper.isMOCCASigned(so)) {
         log.debug("MOCCA signature detected.");
 -       LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here");
 +       String algorithmId = SigKZIDHelper.parseAlgorithmId(so.id);
 +       log.debug("Algorithm = " + algorithmId);
 +       LocRefDetachedMOCCAConnector mocca_connector = new LocRefDetachedMOCCAConnector(this.params, "not needed here", algorithmId);
         xml_content = mocca_connector.prepareXMLContent(data, so);
 +    
 +    // TD
      } else {
 -       log.debug("Generic signature (not MOA/MOCCA) signature detected.");
 -      DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.params, "not needed here");
 -      xml_content = bku_connector.prepareXMLContent(data, so);
 +       log.debug("TD signature signature detected.");
 +       DetachedBKUConnector bku_connector = new DetachedBKUConnector(this.params, "not needed here");
 +       xml_content = bku_connector.prepareXMLContent(data, so);
      }
      String verify_request_xml = verify_request_template.replaceFirst(TemplateReplaces.XML_CONTENT_REPLACE, xml_content);
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java index c44f34b..b27edde 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/LocRefDetachedMOCCAConnector.java @@ -12,6 +12,7 @@ import at.gv.egiz.pdfas.exceptions.ErrorCode;  import at.gv.egiz.pdfas.framework.ConnectorParameters;
  import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
  import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
  import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
  import at.knowcenter.wag.egov.egiz.sig.SignatureData;
  import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
 @@ -22,6 +23,9 @@ import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;  import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
  import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
  import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter;
 +import at.knowcenter.wag.egov.egiz.sig.sigkz.SigKZIDHelper;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory;
  import at.knowcenter.wag.egov.egiz.tools.CodingHelper;
  import at.knowcenter.wag.egov.egiz.tools.FileHelper;
 @@ -50,8 +54,19 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector {      * @throws ConnectorException Thrown in case of error.
      */
     public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content) throws ConnectorException {
 +      this(connectorParameters, loc_ref_content, null);
 +   }
 +
 +   /**
 +    * Constructor that builds the configuration environment for this connector according to the
 +    * given profile.
 +    * @param connectorParameters The connectot parameters.
 +    * @param algorithmId The algorithm idenifier.
 +    * @throws ConnectorException Thrown in case of error.
 +    */
 +   public LocRefDetachedMOCCAConnector(ConnectorParameters connectorParameters, String loc_ref_content, String algorithmId) throws ConnectorException {
        this.params = connectorParameters;
 -      this.environment = new Environment(this.params.getProfileId(), loc_ref_content);
 +      this.environment = new Environment(this.params.getProfileId(), loc_ref_content, algorithmId);
     }
     /**
 @@ -116,15 +131,17 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector {        String response_string = response_properties.getProperty(BKUPostConnection.RESPONSE_STRING_KEY);
        BKUHelper.checkResponseForError(response_string);
 -      // TODO[tknall] Parse server type and version in order to prevent unsupported cces from signing pdfs
 -      String bkuServerHeader = response_properties.getProperty(BKUPostConnection.BKU_SERVER_HEADER_KEY);
 -      String bkuUserAgentHeader = response_properties.getProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY);
 -      // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
 -      log.debug("BKU response header \"user-agent\" header:  " + bkuUserAgentHeader);
 -      // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
 -      log.debug("BKU response header \"server\"     header:  " + bkuServerHeader);
 -
 -      SignSignatureObject so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter());
 +      String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
 +      log.debug("BKU identifier: \"" + bkuIdentifier + "\"");
 +      SignatureLayoutHandler sigLayout;
 +      try {
 +         sigLayout = SignatureLayoutHandlerFactory.getSignatureLayoutHandlerInstance(bkuIdentifier);
 +      } catch (SettingsException e) {
 +         throw new ConnectorException(e.getErrorCode(), e.getMessage());
 +      }
 +      
 +//      SignSignatureObject so = MOCCAHelper.parseCreateXMLResponse(response_string, new DetachedMOCIdFormatter());
 +      SignSignatureObject so = sigLayout.parseCreateXMLSignatureResponse(response_string);
        so.response_properties = response_properties;
        log.debug("analyzeSignResponse finished."); 
        return so;
 @@ -275,21 +292,21 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector {        protected static final String TEMPLATE_FILE_PREFIX = "./templates/moc.";
        /**
 -       * signing file template sufix
 +       * signing file template suffix
         */
 -      protected static final String SIGN_TEMPLATE_FILE_SUFIX = ".sign.request.xml";
 +      protected static final String SIGN_TEMPLATE_FILE_SUFFIX = ".sign.request.xml";
        /**
 -       * verifing template file sufix
 +       * verifing template file suffix
         */
        /* signature verification is not supported by mocca
        protected static final String VERIFY_REQUEST_TEMPLATE_FILE_SUFIX = ".verify.request.xml";
         */
        /**
 -       * verifing file template key sufix
 +       * verifing file template key suffix
         */
 -      protected static final String VERIFY_TEMPLATE_SUFIX = ".verify.template.xml";
 +      protected static final String VERIFY_TEMPLATE_SUFFIX = ".verify.template.xml";
        /**
         * The configuration key of the verify request template.
 @@ -343,13 +360,16 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector {        protected String cert_alg_ecdsa = null;
        protected String cert_alg_rsa = null;
 +      
 +      protected String algorithmId = null;
        /**
         * Initializes the environment with a given profile.
         * @param profile The configuration profile.
 +       * @param algorithmId The algorithm identifer.
         * @throws ConnectorException Thrown in case of an error.
         */
 -      public Environment(String profile, String loc_ref_content) throws ConnectorException {
 +      public Environment(String profile, String loc_ref_content, String algorithmId) throws ConnectorException {
           this.profile = profile;
           this.loc_ref_content = loc_ref_content;
 @@ -363,11 +383,16 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector {           this.sign_keybox_identifier = getConnectorValueFromProfile(settings, profile, SIGN_KEYBOX_IDENTIFIER_KEY);
 +         if (algorithmId == null) {
 +            this.algorithmId = settings.getValueFromKey("default.moc.algorithm.id");
 +         } else {
 +            this.algorithmId = algorithmId;
 +         }
           // SIGN REQUEST
           // try specific file
 -         String sign_request_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moc.algorithm.id") + SIGN_TEMPLATE_FILE_SUFIX;
 +         String sign_request_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + SIGN_TEMPLATE_FILE_SUFFIX;
           log.debug("Trying to load specific sign request file " + sign_request_filename);
           this.sign_request_template = FileHelper.readFromFile(SettingsReader.relocateFile(sign_request_filename));
 @@ -410,7 +435,7 @@ public class LocRefDetachedMOCCAConnector implements Connector, LocalConnector {           // load template file
           // try specific file
 -         String verify_filename = TEMPLATE_FILE_PREFIX + settings.getValueFromKey("default.moc.algorithm.id") + VERIFY_TEMPLATE_SUFIX;
 +         String verify_filename = TEMPLATE_FILE_PREFIX + this.algorithmId + VERIFY_TEMPLATE_SUFFIX;
           log.debug("Trying to load specific signature template file " + verify_filename);
           this.verify_template = FileHelper.readFromFile(SettingsReader.relocateFile(verify_filename));
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java index fe23584..7e32230 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/connectors/mocca/MOCCAHelper.java @@ -39,25 +39,6 @@ public final class MOCCAHelper {     private final static Log log = LogFactory.getLog(MOCCAHelper.class);
     /**
 -    * The pattern that identifies a mocca response (that matches the header value "Server" or "User-Agent").
 -    */
 -   private final static Pattern MOCCA_PATTERN  = Pattern.compile("(citizen-card-environment/\\d+(\\.\\d+) MOCCA[ /].*)|(Jetty(.*))");
 -
 -   /**
 -    * Checks if the given header value for "Server" or "User-Agent" respectively indicates that
 -    * the response was from a mocca cce.
 -    * @param cceId The value of the http header "Server" or "User-Agent".
 -    * @see http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung
 -    * @return <code>true</code> if the id points to a mocca response, <code>false</code> if not.
 -    */
 -   public final static boolean isMOCCACCEId(String cceId) {
 -      if (cceId == null) {
 -         return false;
 -      }
 -      return MOCCA_PATTERN.matcher(cceId).matches();
 -   }
 -
 -   /**
      * This method parses the signature creation response of the signature
      * device mocca.
      * 
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java index ae46225..8b9b606 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigid/DetachedMOCIdFormatter.java @@ -16,17 +16,21 @@ import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;   */
  public class DetachedMOCIdFormatter implements IdFormatter {
 -   public static final String SIG_ID_PREFIX = "etsi-moc-1.0";
 -
     /**
      * Key value in property file
      */
 -   public static final String SIG_ID_PROPERTY_KEY = "default.moc.algorithm.id";
 +   private static final String SIG_ID_PROPERTY_KEY = "default.moc.algorithm.id";
     /**
      * The log.
      */
     private static Log log = LogFactory.getLog(DetachedIdFormatter.class);
 +   
 +   private String algorithmId;
 +   
 +   public DetachedMOCIdFormatter(String algorithmId) {
 +      this.algorithmId = algorithmId;
 +   }
     /**
      * @see at.knowcenter.wag.egov.egiz.sig.sigid.IdFormatter#formatIds(java.lang.String[])
 @@ -39,7 +43,7 @@ public class DetachedMOCIdFormatter implements IdFormatter {        } catch (SettingsException e) {
           log.error(e.getMessage(), e);
        }
 -      prefix = StringUtils.defaultIfEmpty(prefix, SIG_ID_PREFIX);
 +      prefix = StringUtils.defaultIfEmpty(this.algorithmId, prefix);
        StringBuffer formattedIds = new StringBuffer(prefix).append("@").append(ids[0]);
        return formattedIds.toString();
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java index 67c5e15..5c3fc07 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/sigkz/SigKZIDHelper.java @@ -3,14 +3,22 @@   */
  package at.knowcenter.wag.egov.egiz.sig.sigkz;
 +import java.util.Iterator;
 +import java.util.Vector;
 +import java.util.regex.Pattern;
 +
  import org.apache.commons.lang.ArrayUtils;
  import org.apache.commons.lang.StringUtils;
  import org.apache.commons.logging.Log;
  import org.apache.commons.logging.LogFactory;
 +import at.gv.egiz.pdfas.exceptions.ErrorCode;
  import at.knowcenter.wag.egov.egiz.PdfASID;
 +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
  import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
  import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException;
 +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
 +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
  import at.knowcenter.wag.egov.egiz.framework.SignatorFactory;
  import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
  import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedLocRefMOAIdFormatter;
 @@ -95,17 +103,34 @@ public final class SigKZIDHelper     * @author tknall
     */
    public static boolean isMOCCASigned(SignSignatureObject so) {
 -     String sig_kz = so.kz;
       String sig_id = so.id;
 -     if (StringUtils.isEmpty(sig_kz) || StringUtils.isEmpty(sig_id)) {
 +     if (StringUtils.isEmpty(sig_id)) {
          return false;
       }
       String[] ids = sig_id.split("@");
       if (ArrayUtils.isEmpty(ids)) {
          return false;
       }
 -     String prefix = ids[0];
 -     return DetachedMOCIdFormatter.SIG_ID_PREFIX.equals(prefix);
 +     String algorithmId = parseAlgorithmId(sig_id);
 +     if (algorithmId == null) {
 +        return false;
 +     } else {
 +        return algorithmId.startsWith("etsi-moc-");
 +     }
 +  }
 +
 +  /**
 +   * @author tknall
 +   */
 +  public static String parseAlgorithmId(String algorithmParameter) {
 +     if (StringUtils.isEmpty(algorithmParameter)) {
 +        return null;
 +     }
 +     String[] ids = algorithmParameter.split("@");
 +     if (ArrayUtils.isEmpty(ids)) {
 +        return null;
 +     }
 +     return ids[0];
    }
    public static boolean isOldBKU(PdfASID sig_kz, String sig_id) throws ConnectorException
 @@ -158,5 +183,34 @@ public final class SigKZIDHelper      return isOldBKU(kz, sig_id);
    }
 +  
 +  public static String getAlgorithmId(String bkuIdentifier) throws SettingsException, SettingNotFoundException, ConnectorException {
 +    SettingsReader sr = SettingsReader.getInstance();
 +
 +    String base = "signaturelayout.pattern";
 +    Vector v = sr.getSettingKeys(base);
 +    
 +    Iterator it = v.iterator();
 +    while (it.hasNext()) {
 +       String subKey = (String) it.next();
 +       String key = base + "." + subKey;
 +       String value = sr.getSetting(key);
 +       Pattern p = Pattern.compile(value);
 +       if (p.matcher(bkuIdentifier).matches()) {
 +          String algKey = "signaturelayout.algorithm.id." + subKey;
 +          String algValue = sr.getSetting(algKey);
 +          return algValue;
 +       }
 +    }
 +    
 +    if ("true".equalsIgnoreCase(sr.getSetting("signaturelayout.strict", "false"))) {
 +       logger.debug("Enforcing bku support check.");
 +       throw new ConnectorException(ErrorCode.BKU_NOT_SUPPORTED, "Unsupported BKU: " + bkuIdentifier);
 +    } else {
 +       logger.debug("bku support check disabled.");
 +       return null;
 +    }
 +    
 +  }
  }
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java new file mode 100644 index 0000000..964908d --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandler.java @@ -0,0 +1,21 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout;
 +
 +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
 +
 +/**
 + * Considers different signature layout characteristics among different versions of citizen card
 + * environments. 
 + * @author tknall
 + */
 +public interface SignatureLayoutHandler {
 +   
 +   /**
 +    * This method parses the CreateXMLSignatureResponse given from a certain signature device.
 +    * 
 +    * @param xmlResponse The response string.
 +    * @return Returns the parsed signature object.
 +    */
 +   public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse) throws ConnectorException;
 +
 +}
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java new file mode 100644 index 0000000..c56b5f6 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/SignatureLayoutHandlerFactory.java @@ -0,0 +1,121 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout;
 +
 +import java.util.Collections;
 +import java.util.HashMap;
 +import java.util.Iterator;
 +import java.util.Map;
 +import java.util.Vector;
 +import java.util.regex.Pattern;
 +
 +import org.apache.commons.logging.Log;
 +import org.apache.commons.logging.LogFactory;
 +
 +import at.gv.egiz.pdfas.exceptions.ErrorCode;
 +import at.knowcenter.wag.egov.egiz.cfg.SettingsReader;
 +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 +import at.knowcenter.wag.egov.egiz.exceptions.SettingNotFoundException;
 +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
 +
 +/**
 + * Returns instances of signature layout handlers based on given bku
 + * identifiers.
 + * 
 + * @author tknall
 + */
 +public class SignatureLayoutHandlerFactory {
 +
 +   /**
 +    * Prefix of configuration keys defining bku identifiers for a signature layout.
 +    */
 +   private final static String SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN = "signaturelayout.pattern";
 +   
 +   /**
 +    * Prefix of configuration keys defining implementations of signature layout handlers.
 +    * @see SignatureLayoutHandler
 +    */
 +   private final static String SIGNATURE_LAYOUT_CONFIG_KEY_IMPL = "signaturelayout.implementation";
 +   
 +   /**
 +    * A map holding instantiated signature layout implementations (for performance reasons).
 +    */
 +   private final static Map instances = Collections.synchronizedMap(new HashMap());
 +
 +   /**
 +    * The log.
 +    */
 +   private static Log log = LogFactory.getLog(SignatureLayoutHandlerFactory.class);
 +   
 +   /**
 +    * Returns an instance of a signature layout handler based on the given bku identifier.
 +    * @param bkuIdentifier The bku identifier (e.g. <code>citizen-card-environment/1.2 MOCCA/1.1.1</code>).
 +    * @return An implementation of a signature layout handler.
 +    * @throws ConnectorException Thrown in case of an error finding a match within the configuration with the given bku identifier.
 +    * @throws SettingsException Thrown in case of an error within the configuration.
 +    */
 +   public static SignatureLayoutHandler getSignatureLayoutHandlerInstance(String bkuIdentifier) throws ConnectorException, SettingsException {
 +      SignatureLayoutHandler signatureLayoutHandler = (SignatureLayoutHandler) instances.get(bkuIdentifier);
 +      
 +      if (signatureLayoutHandler == null) {
 +         SettingsReader sr = SettingsReader.getInstance();
 +
 +         Vector v = sr.getSettingKeys(SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN);
 +         String implValue = null;
 +
 +         Iterator it = v.iterator();
 +         try {
 +            while (it.hasNext()) {
 +               String subKey = (String) it.next();
 +               String key = SIGNATURE_LAYOUT_CONFIG_KEY_PATTERN + "." + subKey;
 +               String value = sr.getSetting(key);
 +               Pattern p = Pattern.compile(value);
 +               if (p.matcher(bkuIdentifier).matches()) {
 +                  String implKey = SIGNATURE_LAYOUT_CONFIG_KEY_IMPL + "." + subKey;
 +                  implValue = sr.getSetting(implKey);
 +               }
 +            }
 +         } catch (SettingNotFoundException e) {
 +            throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, e.getMessage());
 +         }
 +
 +         if (implValue == null) {
 +            throw new ConnectorException(ErrorCode.BKU_NOT_SUPPORTED, "Unsupported BKU: " + bkuIdentifier);
 +         }
 +         
 +         log.debug("Trying to instantiate SignatureLayoutHandler \"" + implValue + "\".");
 +
 +         try {
 +            Class clazz = Class.forName(implValue);
 +            Object obj = clazz.newInstance();
 +            if (!(obj instanceof SignatureLayoutHandler)) {
 +               throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Invalid signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\".");
 +            }
 +            signatureLayoutHandler = (SignatureLayoutHandler) obj;
 +         } catch (InstantiationException e) {
 +            throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Error instantiating signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\".");
 +         } catch (IllegalAccessException e) {
 +            throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Illegal access instantiating signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\".");
 +         } catch (ClassNotFoundException e) {
 +            throw new SettingsException(ErrorCode.INVALID_SIGNATURE_LAYOUT_IMPL_CONFIGURED, "Unable to find signature layout implementation (\"" + implValue + "\") configured for bku identifier \"" + bkuIdentifier + "\".");
 +         }
 +
 +         log.debug("SignatureLayoutHandler successfully instantiated.");
 +         instances.put(bkuIdentifier, signatureLayoutHandler);
 +      } else {
 +         log.trace("SignatureLayoutHandler has already been instantiated. Returning old instance.");
 +      }
 +      
 +      return signatureLayoutHandler;
 +
 +   }
 +
 +   /**
 +    * Verifies that the bku is supported trying to match the given bku identifier.
 +    * @param bkuIdentifier The bku identifier (e.g. <code>citizen-card-environment/1.2 MOCCA/1.1.1</code>).
 +    * @throws ConnectorException Thrown in case of an error (e.g. bku not supported).
 +    * @throws SettingsException Thrown in case of an error within the configuration.
 +    */
 +   public static void verifyBKUSupport(String bkuIdentifier) throws ConnectorException, SettingsException {
 +      getSignatureLayoutHandlerInstance(bkuIdentifier);
 +   }
 +
 +}
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java new file mode 100644 index 0000000..0913b49 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/MOCCASignatureLayout10Handler.java @@ -0,0 +1,24 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca;
 +
 +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper;
 +import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
 +
 +/**
 + * Implementation of a signature layout handler for the first release of mocca.
 + * @author tknall
 + */
 +public class MOCCASignatureLayout10Handler implements SignatureLayoutHandler {
 +
 +   private final static String ALGORITHM_ID = "etsi-moc-1.1";
 +
 +   /**
 +    * Parses the given xmlResponse with respect to the specific signature layout of mocca.
 +    */
 +   public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse) throws ConnectorException {
 +      return MOCCAHelper.parseCreateXMLResponse(xmlResponse, new DetachedMOCIdFormatter(ALGORITHM_ID));
 +   }
 +
 +}
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java new file mode 100644 index 0000000..958370e --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/mocca/OldMOCCASignatureLayoutHandler.java @@ -0,0 +1,24 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout.mocca;
 +
 +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.mocca.MOCCAHelper;
 +import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedMOCIdFormatter;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
 +
 +/**
 + * Implementation of a signature layout handler for the beta version of mocca.
 + * @author tknall
 + */
 +public class OldMOCCASignatureLayoutHandler implements SignatureLayoutHandler {
 +   
 +   private final static String ALGORITHM_ID = "etsi-moc-1.0";
 +
 +   /**
 +    * Parses the given xmlResponse with respect to the specific signature layout of mocca.
 +    */
 +   public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse) throws ConnectorException {
 +      return MOCCAHelper.parseCreateXMLResponse(xmlResponse, new DetachedMOCIdFormatter(ALGORITHM_ID));
 +   }
 +
 +}
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java new file mode 100644 index 0000000..5d6eb96 --- /dev/null +++ b/src/main/java/at/knowcenter/wag/egov/egiz/sig/signaturelayout/td/TrustDeskSignatureLayoutHandler.java @@ -0,0 +1,22 @@ +package at.knowcenter.wag.egov.egiz.sig.signaturelayout.td;
 +
 +import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.SignSignatureObject;
 +import at.knowcenter.wag.egov.egiz.sig.sigid.DetachedIdFormatter;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
 +
 +/**
 + * Implementation of a signature layout handler for trustDesk basic.
 + * @author tknall
 + */
 +public class TrustDeskSignatureLayoutHandler implements SignatureLayoutHandler {
 +
 +   /**
 +    * Parses the given xmlResponse with respect to the specific signature layout of trustDesk basic.
 +    */
 +   public SignSignatureObject parseCreateXMLSignatureResponse(String xmlResponse) throws ConnectorException {
 +      return BKUHelper.parseCreateXMLResponse(xmlResponse, new DetachedIdFormatter());
 +   }
 +
 +}
 diff --git a/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java b/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java index 7947d90..7cf762e 100644 --- a/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java +++ b/src/main/java/at/knowcenter/wag/egov/egiz/web/servlets/DataURLServlet.java @@ -42,13 +42,17 @@ import at.knowcenter.wag.egov.egiz.PdfASID;  import at.knowcenter.wag.egov.egiz.exceptions.ConnectorException;
  import at.knowcenter.wag.egov.egiz.exceptions.InvalidIDException;
  import at.knowcenter.wag.egov.egiz.exceptions.PresentableException;
 +import at.knowcenter.wag.egov.egiz.exceptions.SettingsException;
  import at.knowcenter.wag.egov.egiz.exceptions.SignatorFactoryException;
  import at.knowcenter.wag.egov.egiz.exceptions.SignatureException;
  import at.knowcenter.wag.egov.egiz.pdf.SignatureHolder;
  import at.knowcenter.wag.egov.egiz.sig.SignatureResponse;
  import at.knowcenter.wag.egov.egiz.sig.connectors.ConnectorChooser;
  import at.knowcenter.wag.egov.egiz.sig.connectors.LocalConnector;
 +import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUHelper;
  import at.knowcenter.wag.egov.egiz.sig.connectors.bku.BKUPostConnection;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandler;
 +import at.knowcenter.wag.egov.egiz.sig.signaturelayout.SignatureLayoutHandlerFactory;
  import at.knowcenter.wag.egov.egiz.web.FormFields;
  import at.knowcenter.wag.egov.egiz.web.LocalRequest;
  import at.knowcenter.wag.egov.egiz.web.LocalRequestHelper;
 @@ -200,7 +204,17 @@ public class DataURLServlet extends HttpServlet      log.trace("processSign");
      String xml_response = retrieveXMLResponse(request);
 +    Properties response_properties = BKUHelper.getBKUProperties(request);
 +    String bkuIdentifier = BKUHelper.getBKUIdentifier(response_properties);
 +    log.debug("BKU identifier: \"" + bkuIdentifier + "\"");
 +    
 +    try {
 +       SignatureLayoutHandlerFactory.verifyBKUSupport(bkuIdentifier);
 +    } catch (SettingsException e) {
 +       throw new ConnectorException(e.getErrorCode(), e.getMessage());
 +    }
 +    
      if (isNullResponse(xml_response))
      {
        log.debug("Received a NullOperationResponse -> answering with the first request."); //$NON-NLS-1$
 @@ -210,12 +224,6 @@ public class DataURLServlet extends HttpServlet        log.debug("There are still requests to be performed -> answering with request."); //$NON-NLS-1$
 -      // TODO[tknall] Parse user agent's cce type and version in order to prevent unsupported cces from signing pdfs
 -      // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.dataurl
 -      log.debug("BKU response header \"user-agent\" header:  " + request.getHeader("User-Agent"));
 -      // http://www.buergerkarte.at/konzept/securitylayer/spezifikation/aktuell/bindings/bindings.html#http.kodierung.response.browser
 -      log.debug("BKU response header \"server\"     header:  " + request.getHeader("Server"));
 -      
        LocalRequest local_request = si.localRequest;
        String request_string = local_request.getRequestString();
 @@ -229,16 +237,8 @@ public class DataURLServlet extends HttpServlet      {
        log.debug("Received a normal response -> storing the response."); //$NON-NLS-1$
 -      Properties response_properties = new Properties();
        response_properties.setProperty(BKUPostConnection.RESPONSE_STRING_KEY, xml_response);
 -      String userAgent = request.getHeader("User-Agent");
 -      if (userAgent != null) {
 -         response_properties.setProperty(BKUPostConnection.BKU_USER_AGENT_HEADER_KEY, userAgent);
 -      } else {
 -         log.warn("BKU request/response header \"User-Agent\" is empty.");
 -      }
 -      
        si.response_properties = response_properties;
        log.debug("All requests have been processed -> processing the responses."); //$NON-NLS-1$
 | 
