From 32d17447a258188b2d534bcb0bf65a659ba7b7d0 Mon Sep 17 00:00:00 2001 From: mcentner Date: Fri, 29 Aug 2008 12:11:34 +0000 Subject: Initial import. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@1 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd | 877 +++++++++++++++++++++ .../at/gv/egiz/bku/slcommands/schema/xml.xsd | 145 ++++ .../bku/slcommands/schema/xmldsig-core-schema.xsd | 308 ++++++++ .../bku/slcommands/schema/xmldsig-transforms.xsd | 41 + .../slexceptions/SLExceptionMessages.properties | 97 +++ .../slexceptions/SLExceptionMessages_de.properties | 98 +++ 6 files changed, 1566 insertions(+) create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xml.xsd create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xmldsig-core-schema.xsd create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xmldsig-transforms.xsd create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties (limited to 'bkucommon/src/main/resources') diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd new file mode 100644 index 00000000..594e4415 --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd @@ -0,0 +1,877 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xml.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xml.xsd new file mode 100644 index 00000000..eeb9db56 --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xml.xsd @@ -0,0 +1,145 @@ + + + + + + See http://www.w3.org/XML/1998/namespace.html and + http://www.w3.org/TR/REC-xml for information about this namespace. + + This schema document describes the XML namespace, in a form + suitable for import by other schema documents. + + Note that local names in this namespace are intended to be defined + only by the World Wide Web Consortium or its subgroups. The + following names are currently defined in this namespace and should + not be used with conflicting semantics by any Working Group, + specification, or document instance: + + base (as an attribute name): denotes an attribute whose value + provides a URI to be used as the base for interpreting any + relative URIs in the scope of the element on which it + appears; its value is inherited. This name is reserved + by virtue of its definition in the XML Base specification. + + id (as an attribute name): denotes an attribute whose value + should be interpreted as if declared to be of type ID. + This name is reserved by virtue of its definition in the + xml:id specification. + + lang (as an attribute name): denotes an attribute whose value + is a language code for the natural language of the content of + any element; its value is inherited. This name is reserved + by virtue of its definition in the XML specification. + + space (as an attribute name): denotes an attribute whose + value is a keyword indicating what whitespace processing + discipline is intended for the content of the element; its + value is inherited. This name is reserved by virtue of its + definition in the XML specification. + + Father (in any context at all): denotes Jon Bosak, the chair of + the original XML Working Group. This name is reserved by + the following decision of the W3C XML Plenary and + XML Coordination groups: + + In appreciation for his vision, leadership and dedication + the W3C XML Plenary on this 10th day of February, 2000 + reserves for Jon Bosak in perpetuity the XML name + xml:Father + + + + + This schema defines attributes and an attribute group + suitable for use by + schemas wishing to allow xml:base, xml:lang, xml:space or xml:id + attributes on elements they define. + + To enable this, such a schema must import this schema + for the XML namespace, e.g. as follows: + <schema . . .> + . . . + <import namespace="http://www.w3.org/XML/1998/namespace" + schemaLocation="http://www.w3.org/2001/xml.xsd"/> + + Subsequently, qualified reference to any of the attributes + or the group defined below will have the desired effect, e.g. + + <type . . .> + . . . + <attributeGroup ref="xml:specialAttrs"/> + + will define a type which will schema-validate an instance + element with any of those attributes + + + + In keeping with the XML Schema WG's standard versioning + policy, this schema document will persist at + http://www.w3.org/2007/08/xml.xsd. + At the date of issue it can also be found at + http://www.w3.org/2001/xml.xsd. + The schema document at that URI may however change in the future, + in order to remain compatible with the latest version of XML Schema + itself, or with the XML namespace itself. In other words, if the XML + Schema or XML namespaces change, the version of this document at + http://www.w3.org/2001/xml.xsd will change + accordingly; the version at + http://www.w3.org/2007/08/xml.xsd will not change. + + + + + + Attempting to install the relevant ISO 2- and 3-letter + codes as the enumerated possible values is probably never + going to be a realistic possibility. See + RFC 3066 at http://www.ietf.org/rfc/rfc3066.txt and the IANA registry + at http://www.iana.org/assignments/lang-tag-apps.htm for + further information. + + The union allows for the 'un-declaration' of xml:lang with + the empty string. + + + + + + + + + + + + + + + + + + + + + + + + See http://www.w3.org/TR/xmlbase/ for + information about this attribute. + + + + + + See http://www.w3.org/TR/xml-id/ for + information about this attribute. + + + + + + + + + + + diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xmldsig-core-schema.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xmldsig-core-schema.xsd new file mode 100644 index 00000000..8422fdfa --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xmldsig-core-schema.xsd @@ -0,0 +1,308 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xmldsig-transforms.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xmldsig-transforms.xsd new file mode 100644 index 00000000..25fdec88 --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/xmldsig-transforms.xsd @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties new file mode 100644 index 00000000..8e0a09bc --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties @@ -0,0 +1,97 @@ +# Copyright 2008 Federal Chancellery Austria and +# Graz University of Technology +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +test.noerror=This is a test error-message. No error occurred. + +ec1000=Unclassified error. +ec2000=Unclassified error in the transport binding. +ec2001=HTTP/HTTPS binding: DataURL cannot be resolved. +ec2002=HTTP/HTTPS binding: StylesheetURL cannot be resolved. +ec2003=HTTP/HTTPS binding: RedirectURL cannot be resolved. +ec2004=HTTP/HTTPS binding: XMLRequest parameter missing. +ec2005=HTTP/HTTPS binding: Unknown parameter encoding. +ec2006=HTTP/HTTPS binding: Incorrect parameter encoding. +ec2007=HTTP/HTTPS binding: DataURL server transmits error or unexpected response. +ec2008=HTTP/HTTPS binding: Error in stylesheet obtained from the StylesheetURL. +ec2009=HTTP/HTTPS binding: HTTP request to local CCE directed to unauthorised URL. +ec2010=HTTPS binding: Error while establishing the TLS connection. +ec3000=Unclassified error in the XML structure of the command request. +ec3001=XML structure of the command request is not well formed. +ec3002=XML structure of the command request does not comply with the Security Layer schema. +ec3003=XML structure of the command request contains an invalid combination of optional elements or attributes. +ec3004=XML structure contains an element or attribute whose syntax does not match the Security Layer specification. +ec3005=Protocol version of Security Layer not supported. +ec4000=Unclassified error while processing command. +ec4001=Unknown key box identifier. +ec4002=Unknown info box identifier. +ec4003=Date to be signed cannot be resolved. +ec4004=Supplementary object cannot be resolved. +ec4005=Date to be encrypted cannot be resolved. +ec4006=Algorithm (signature, encryption, digest, canonicalisation, transformation) not supported. +ec4007=Error while executing algorithm (signature, encryption, digest, canonicalisation, transformation). +ec4008=Error while parsing CMS message +ec4009=No matching decryption key. +ec4010=Info box command parameters do not match info box type. +ec4011=Command not implemented. +ec4100=XML document in which the signature is to be integrated cannot be resolved. +ec4101=XML document in which the signature is to be integrated cannot be parsed. +ec4102=Signature cannot be integrated in the existing XML document at the specified location. +ec4103=Signature certificate not contained in the CMS signature. +ec4104=Signed data not contained in the CMS signature or XML request. +ec4105=XML document containing the signature to be verified cannot be resolved. +ec4106=XML document containing the signature to be verified cannot be parsed. +ec4107=There is no XML signature at the specified location within the XML document. +ec4108=Encrypted date cannot be inserted in the existing XML document at the specified location. +ec4109=Existing XML document is required but missing. +ec4110=Existing XML document cannot be resolved. +ec4111=Existing XML document cannot be parsed. +ec4112=Encrypted data encryption keys cannot be inserted in the existing XML document at the specified location. +ec4113=Data to be decrypted not contained in either the CMS message or XML request. +ec4114=XML document to be decrypted cannot be resolved. +ec4115=XML document to be decrypted cannot be parsed. +ec4116=At least one specified encryption element cannot be found in the XML document to be decrypted. +ec4117=No encryption element for binary response. +ec4118=Date to be hashed cannot be resolved. +ec4119=Date for which the hash value is to be verified cannot be resolved. +ec4120=Selected info box identifier already allocated. +ec4121=Info box with specified identifier does not exist. +ec4122=Contents of the selected info box cannot be displayed as XML. +ec4123=Associative array: No entry for the specified key. +ec5000=Unclassified error in the viewer component. +ec5001=Display of data of the mime type specified in the command request not supported. +ec5002=Character encoding of the data to be displayed is invalid or not supported. +ec5003=Data to be displayed contains unsupported characters. +ec5004=Standard display format: HTML does not conform to specification. +ec5005=Standard display format: CSS does not conform to specification. +ec5006=Standard display format: Format of an embedded image does not conform to specification. +ec5007=Standard display format: Signature for embedded images missing or does not conform to specification. +ec6000=Unclassified cancelling by the citizen. +ec6001=Cancelled by the citizen via the user interface. +ec6002=Cancelled because of insufficient rights to execute command. + +# 3xxx +# + +ec3000.unclassified=Error in the XML structure of the command request. {0} +ec3002.invalid=XML structure of the command request does not comply with the Security Layer schema. {0} + +# 4xxx +# + +ec4000.infobox.invalid=The infobox '{0}' contains invalid content. +ec4000.idlink.transfomation.failed=Failed to transform CompressedIdentityLink with Stylesheet {0}. +ec4002.infobox.unknown=Unknown info box identifier {0}. +ec4003.not.resolved=Data to be signed cannot be resolved from URI={0}. +ec4011.notimplemented=Command {0} not implemented. diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties new file mode 100644 index 00000000..cf52a4c3 --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties @@ -0,0 +1,98 @@ +# Copyright 2008 Federal Chancellery Austria and +# Graz University of Technology +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +test.noerror=Das ist eine Test-Fehlermeldung. Es ist kein Fehler aufgetreten. + +ec1000=Unklassifizierter Fehler. +ec2000=Unklassifizierter Fehler in der Transportbindung. +ec2001=HTTP/HTTPS-Bindung: DataURL kann nicht aufgelöst werden. +ec2002=HTTP/HTTPS-Bindung: StylesheetURL kann nicht aufgelöst werden. +ec2003=HTTP/HTTPS-Bindung: RedirectURL kann nicht aufgelöst werden. +ec2004=HTTP/HTTPS-Bindung: Parameter XMLRequest fehlt. +ec2005=HTTP/HTTPS-Bindung: Unbekannte Kodierung der Parameter. +ec2006=HTTP/HTTPS-Bindung: Fehlerhafte Kodierung der Parameter. +ec2007=HTTP/HTTPS-Bindung: DataURL-Server sendet Fehler oder unerwartete Antwort. +ec2008=HTTP/HTTPS-Bindung: Fehler im Stylesheet, der von der StylesheetURL bezogen wurde. +ec2009=HTTP/HTTPS-Bindung: HTTP-Anfrage an lokale BKU wurde an unerlaubte URL gerichtet. +ec2010=HTTPS-Bindung: Fehler beim Aufbau der TLS-Verbindung. +ec3000=Unklassifizierter Fehler in der XML-Struktur der Befehlsanfrage. +ec3001=XML-Struktur der Befehlsanfrage ist nicht wohlgeformt. +ec3002=XML-Struktur der Befehlsanfrage entspricht nicht dem Schema des Security-Layers. +ec3003=XML-Struktur der Befehlsanfrage enthält eine unerlaubte Kombination aus optionalen Elementen oder Attributen. +ec3004=XML-Struktur enthält ein Element oder Attribut, dessen Syntax nicht der Spezifikation des Security-Layer entspricht. +ec3005=Protokollversion des Security-Layer wird nicht unterstützt. +ec4000=Unklassifizierter Fehler in der Befehlsabarbeitung. +ec4001=Unbekannter Keyboxbezeichner. +ec4002=Unbekannter Infoboxbezeichner. +ec4003=Zu signierendes Datum kann nicht aufgelöst werden. +ec4004=Ergänzungsobjekt kann nicht aufgelöst werden. +ec4005=Zu verschlüsselndes Datum kann nicht aufgelöst werden. +ec4006=Algorithmus (Signatur, Verschlüsselung, Digest, Kanonisierung, Transformation) wird nicht unterstützt. +ec4007=Fehler bei der Algorithmusausführung (Signatur, Verschlüsselung, Digest, Kanonisierung, Transformation). +ec4008=Fehler beim Parsen der CMS-Nachricht. +ec4009=Kein passender Entschlüsselungsschlüssel vorhanden. +ec4010=Parameter des Infobox-Befehls passen nicht zum Typ der Infobox. +ec4011=Befehl ist nicht implementiert. +ec4100=XML-Dokument, in das die Signatur integriert werden soll, kann nicht aufgelöst werden. +ec4101=XML-Dokument, in das die Signatur integriert werden soll, kann nicht geparst werden. +ec4102=Signatur kann nicht am spezifizierten Ort in das bestehende XML-Dokument integriert werden. +ec4103=Signatorzertifikat ist nicht in der CMS-Signatur enthalten. +ec4104=Signierte Daten sind weder in der CMS-Signatur noch im XML-Request enthalten. +ec4105=XML-Dokument, das die zu prüfende Signatur enthält, kann nicht aufgelöst werden. +ec4106=XML-Dokument, das die zu prüfende Signatur enthält, kann nicht geparst werden. +ec4107=Am spezifizierten Ort innerhalb des XML-Dokuments befindet sich keine XML-Signatur. +ec4108=Verschlüsseltes Datum kann nicht am spezifizierten Ort in das bestehende XML-Dokument eingefügt werden. +ec4109=Bestehendes XML-Dokument ist notwendig, aber nicht vorhanden. +ec4110=Bestehendes XML-Dokument kann nicht aufgelöst werden. +ec4111=Bestehendes XML-Dokument kann nicht geparst werden. +ec4112=Verschlüsselte Datenverschlüsselungsschlüssel können nicht am spezifizierten Ort in das bestehende XML-Dokument eingefügt werden. +ec4113=Zu entschlüsselnde Daten sind weder in der CMS-Nachricht noch im XML-Request enthalten. +ec4114=Zu entschlüsselndes XML-Dokument kann nicht aufgelöst werden. +ec4115=Zu entschlüsselndes XML-Dokument kann nicht geparst werden. +ec4116=Zumindest ein spezifiziertes Verschlüsselungselement kann nicht im zu entschlüsselnden XML-Dokument gefunden werden. +ec4117=Kein Verschlüsselungselement für Binärantwort vorhanden. +ec4118=Zu hashendes Datum kann nicht aufgelöst werden. +ec4119=Datum, für das der Hashwert zu prüfen ist, kann nicht aufgelöst werden. +ec4120=Gewählter Infoboxbezeichner bereits vergeben. +ec4121=Infobox mit spezifiziertem Bezeichner existiert nicht. +ec4122=Inhalt der ausgewählten Infobox kann nicht als XML dargestellt werden. +ec4123=Assoziatives Array: Zum spezifizierten Schlüssel existiert kein Eintrag. +ec5000=Unklassifizierter Fehler in der Anzeigekomponente. +ec5001=Anzeige von Daten des in der Befehlsanfrage angegebenen Mime-Types wird nicht unterstützt. +ec5002=Zeichenkodierung der anzuzeigenden Daten ist fehlerhaft oder wird nicht unterstützt. +ec5003=Anzuzeigende Daten enhalten nicht unterstützte Zeichen. +ec5004=Standardanzeigeformat: HTML ist nicht spezifikationskonform. +ec5005=Standardanzeigeformat: CSS ist nicht spezifikationskonform. +ec5006=Standardanzeigeformat: Format eines eingebundenen Bildes ist nicht spezifikationskonform. +ec5007=Standardanzeigeformat: Signatur über eingebundene Bilder fehlt oder ist nicht spezifikationskonform. +ec6000=Unklassifizierter Abbruch durch den Bürger. +ec6001=Abbruch durch den Bürger über die Benutzerschnittstelle. +ec6002=Abbruch auf Grund mangelnder Rechte zur Befehlsausführung. + +# 3xxx +# + +ec3000.unclassified=Unklassifizierter Fehler in der XML-Struktur der Befehlsanfrage. {0} +ec3002.invalid=XML-Struktur der Befehlsanfrage entspricht nicht dem Schema des Security-Layers. {0} + +# 4xxx +# + +ec4000.infobox.invalid=Die Infobox '{0}' enthält ungültige Daten. +ec4000.idlink.transfomation.failed=Die komprimierte Personenbindung konnte mit dem Stylesheet {0} nicht transformiert werden. +ec4002.infobox.unknown=Unbekannter Infoboxbezeichner {0}. +ec4003.not.resolved=Zu signierendes Datum kann nicht aufgelöst werden (URI={0}). +ec4011.notimplemented=Befehl {0} ist nicht implementiert. + -- cgit v1.2.3 From 83ffb9a9e1ffcb57e2adda4d48a8f972148897e6 Mon Sep 17 00:00:00 2001 From: clemenso Date: Fri, 5 Sep 2008 13:38:52 +0000 Subject: HashDataInput git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@20 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- bkucommon/pom.xml | 5 +- .../bku/slcommands/impl/HashDataInputImpl.java | 42 + .../bku/slcommands/impl/xsect/STALPrivateKey.java | 218 +-- .../bku/slcommands/impl/xsect/STALSignature.java | 310 ++-- .../egiz/bku/slcommands/impl/xsect/Signature.java | 1855 ++++++++++---------- .../bku/accesscontrol/config/AccessControl.xsd | 128 ++ 6 files changed, 1381 insertions(+), 1177 deletions(-) create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/HashDataInputImpl.java create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/accesscontrol/config/AccessControl.xsd (limited to 'bkucommon/src/main/resources') diff --git a/bkucommon/pom.xml b/bkucommon/pom.xml index 5d105fde..2ccf0766 100644 --- a/bkucommon/pom.xml +++ b/bkucommon/pom.xml @@ -68,11 +68,10 @@ true org.apache.maven.plugins maven-surefire-plugin - true + true \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/HashDataInputImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/HashDataInputImpl.java new file mode 100644 index 00000000..49d3c63f --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/HashDataInputImpl.java @@ -0,0 +1,42 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ +package at.gv.egiz.bku.slcommands.impl; + +import at.gv.egiz.bku.slcommands.impl.xsect.DataObject; +import at.gv.egiz.stal.HashDataInput; +import java.io.InputStream; + +/** + * + * @author clemens + */ +public class HashDataInputImpl implements HashDataInput { + + String refId; + String mimeType; + InputStream hashDataInput; + + public HashDataInputImpl(DataObject dataObject) { + refId = dataObject.getReference().getId(); + mimeType = dataObject.getMimeType(); + hashDataInput = dataObject.getReference().getDigestInputStream(); + } + + @Override + public String getReferenceId() { + return refId; + } + + @Override + public String getMimeType() { + return mimeType; + } + + @Override + public InputStream getHashDataInput() { + return hashDataInput; + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALPrivateKey.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALPrivateKey.java index 64c758c9..25e2d4e5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALPrivateKey.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALPrivateKey.java @@ -14,109 +14,115 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.slcommands.impl.xsect; - -import java.security.PrivateKey; - -import at.gv.egiz.stal.STAL; -import at.gv.egiz.stal.HashDataInputCallback; - -/** - * This class implements a private key used by the {@link STALSignature} class. - * - * @author mcentner - */ -public class STALPrivateKey implements PrivateKey { - - private static final long serialVersionUID = 1L; - - /** - * The STAL implementation. - */ - private STAL stal; - - /** - * The callback interface for obtaining the hash input data. - */ - private HashDataInputCallback hashDataInputCallback; - - /** - * The keybox identifier. - */ - private String keyboxIdentifier; - - /** - * The signature algorithm. - */ - private String algorithm; - - /** - * Creates a new instance of this STALPrivateKey with the given - * stal implementation, signature algorithm, - * keyboxIdentifier and hashDataInputCallback - * interface. - * - * @param stal - * the STAL implementation - * @param algorithm - * the signature algorithm - * @param keyboxIdentifier - * the keybox identifier - * @param hashDataInputCallback - * the interface for obtaining the has input data - */ - public STALPrivateKey(STAL stal, - String algorithm, String keyboxIdentifier, HashDataInputCallback hashDataInputCallback) { - super(); - this.keyboxIdentifier = keyboxIdentifier; - this.hashDataInputCallback = hashDataInputCallback; - this.stal = stal; - this.algorithm = algorithm; - } - - /* (non-Javadoc) - * @see java.security.Key#getAlgorithm() - */ - @Override - public String getAlgorithm() { - return algorithm; - } - - /* (non-Javadoc) - * @see java.security.Key#getEncoded() - */ - @Override - public byte[] getEncoded() { - throw new UnsupportedOperationException("STALPrivateKey does not support the getEncoded() method."); - } - - /* (non-Javadoc) - * @see java.security.Key#getFormat() - */ - @Override - public String getFormat() { - return null; - } - - /** - * @return the STAL implementation - */ - public STAL getStal() { - return stal; - } - - /** - * @return the interface for obtaining the hash data input - */ - public HashDataInputCallback getHashDataInputCallback() { - return hashDataInputCallback; - } - - /** - * @return the keybox identifier - */ - public String getKeyboxIdentifier() { - return keyboxIdentifier; - } - -} +package at.gv.egiz.bku.slcommands.impl.xsect; + +import at.gv.egiz.stal.HashDataInput; +import java.security.PrivateKey; + +import at.gv.egiz.stal.STAL; +//import at.gv.egiz.stal.HashDataInputCallback; +import java.util.List; + +/** + * This class implements a private key used by the {@link STALSignature} class. + * + * @author mcentner + */ +public class STALPrivateKey implements PrivateKey { + + private static final long serialVersionUID = 1L; + + /** + * The STAL implementation. + */ + private STAL stal; + + /** + * The callback interface for obtaining the hash input data. + */ +// private HashDataInputCallback hashDataInputCallback; + + + private List dataObjects; + + /** + * The keybox identifier. + */ + private String keyboxIdentifier; + + /** + * The signature algorithm. + */ + private String algorithm; + + /** + * Creates a new instance of this STALPrivateKey with the given + * stal implementation, signature algorithm, + * keyboxIdentifier and hashDataInputCallback + * interface. + * + * @param stal + * the STAL implementation + * @param algorithm + * the signature algorithm + * @param keyboxIdentifier + * the keybox identifier + * @param hashDataInputCallback + * the interface for obtaining the has input data + */ + public STALPrivateKey(STAL stal, + String algorithm, String keyboxIdentifier, List dataObjects) { + super(); + this.keyboxIdentifier = keyboxIdentifier; + this.dataObjects = dataObjects; + this.stal = stal; + this.algorithm = algorithm; + } + + /* (non-Javadoc) + * @see java.security.Key#getAlgorithm() + */ + @Override + public String getAlgorithm() { + return algorithm; + } + + /* (non-Javadoc) + * @see java.security.Key#getEncoded() + */ + @Override + public byte[] getEncoded() { + throw new UnsupportedOperationException("STALPrivateKey does not support the getEncoded() method."); + } + + /* (non-Javadoc) + * @see java.security.Key#getFormat() + */ + @Override + public String getFormat() { + return null; + } + + /** + * @return the STAL implementation + */ + public STAL getStal() { + return stal; + } + + /** + * @return the interface for obtaining the hash data input + */ + public List getDataObjects() { + + return dataObjects; + } + + /** + * @return the keybox identifier + */ + public String getKeyboxIdentifier() { + return keyboxIdentifier; + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALSignature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALSignature.java index f0fcb891..eba1d96d 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALSignature.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALSignature.java @@ -14,152 +14,164 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.slcommands.impl.xsect; - -import java.io.ByteArrayOutputStream; -import java.security.InvalidKeyException; -import java.security.InvalidParameterException; -import java.security.PrivateKey; -import java.security.PublicKey; -import java.security.SignatureException; -import java.security.SignatureSpi; -import java.util.Collections; -import java.util.List; - -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.STAL; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; -import at.gv.egiz.stal.SignRequest; -import at.gv.egiz.stal.SignResponse; -import at.gv.egiz.stal.HashDataInputCallback; - -/** - * A signature service provider implementation that uses STAL to sign. - * - * @author mcentner - */ -public class STALSignature extends SignatureSpi { - - /** - * The private key. - */ - protected STALPrivateKey privateKey; - - /** - * The to-be signed data. - */ - protected ByteArrayOutputStream data = new ByteArrayOutputStream(); - - /* (non-Javadoc) - * @see java.security.SignatureSpi#engineGetParameter(java.lang.String) - */ - @Override - protected Object engineGetParameter(String param) - throws InvalidParameterException { - throw new InvalidParameterException(); - } - - /* (non-Javadoc) - * @see java.security.SignatureSpi#engineInitSign(java.security.PrivateKey) - */ - @Override - protected void engineInitSign(PrivateKey privateKey) - throws InvalidKeyException { - - if (!(privateKey instanceof STALPrivateKey)) { - throw new InvalidKeyException("STALSignature supports STALKeys only."); - } - - this.privateKey = (STALPrivateKey) privateKey; - - } - - /* (non-Javadoc) - * @see java.security.SignatureSpi#engineInitVerify(java.security.PublicKey) - */ - @Override - protected void engineInitVerify(PublicKey publicKey) - throws InvalidKeyException { - - throw new UnsupportedOperationException("STALSignature does not support signature verification."); - } - - /* (non-Javadoc) - * @see java.security.SignatureSpi#engineSetParameter(java.lang.String, java.lang.Object) - */ - @Override - protected void engineSetParameter(String param, Object value) - throws InvalidParameterException { - } - - /* (non-Javadoc) - * @see java.security.SignatureSpi#engineSign() - */ - @Override - protected byte[] engineSign() throws SignatureException { - - STAL stal = privateKey.getStal(); - - if (stal == null) { - throw new SignatureException("STALSignature requires the STALPrivateKey " + - "to provide a STAL implementation reference."); - } - - HashDataInputCallback signRefDataSupplier = privateKey.getHashDataInputCallback(); - - String keyboxIdentifier = privateKey.getKeyboxIdentifier(); - - if (keyboxIdentifier == null) { - throw new SignatureException("STALSignature requires the STALPrivateKey " + - "to provide a KeyboxIdentifier."); - } - - SignRequest signRequest = new SignRequest(); - signRequest.setKeyIdentifier(keyboxIdentifier); - signRequest.setSignedInfo(data.toByteArray()); - signRequest.setHashDataInput(signRefDataSupplier); - - List responses = stal.handleRequest(Collections.singletonList((STALRequest) signRequest)); - - if (responses == null || responses.size() != 1) { - throw new SignatureException("Failed to access STAL."); - } - - STALResponse response = responses.get(0); - if (response instanceof SignResponse) { - return ((SignResponse) response).getSignatureValue(); - } else if (response instanceof ErrorResponse) { - throw new STALSignatureException(((ErrorResponse) response).getErrorCode()); - } else { - throw new SignatureException("Failed to access STAL."); - } - - } - - /* (non-Javadoc) - * @see java.security.SignatureSpi#engineUpdate(byte) - */ - @Override - protected void engineUpdate(byte b) throws SignatureException { - data.write(b); - } - - /* (non-Javadoc) - * @see java.security.SignatureSpi#engineUpdate(byte[], int, int) - */ - @Override - protected void engineUpdate(byte[] b, int off, int len) - throws SignatureException { - data.write(b, off, len); - } - - /* (non-Javadoc) - * @see java.security.SignatureSpi#engineVerify(byte[]) - */ - @Override - protected boolean engineVerify(byte[] sigBytes) throws SignatureException { - throw new UnsupportedOperationException("STALSignature des not support signature verification."); - } - -} +package at.gv.egiz.bku.slcommands.impl.xsect; + +import at.gv.egiz.bku.slcommands.impl.HashDataInputImpl; +import java.io.ByteArrayOutputStream; +import java.security.InvalidKeyException; +import java.security.InvalidParameterException; +import java.security.PrivateKey; +import java.security.PublicKey; +import java.security.SignatureException; +import java.security.SignatureSpi; +import java.util.Collections; +import java.util.List; + +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.HashDataInput; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; +import at.gv.egiz.stal.SignRequest; +import at.gv.egiz.stal.SignResponse; +//import at.gv.egiz.stal.HashDataInputCallback; +import java.util.ArrayList; + +/** + * A signature service provider implementation that uses STAL to sign. + * + * @author mcentner + */ +public class STALSignature extends SignatureSpi { + +// private static final Log log = LogFactory.getLog(STALSignature.class); + + /** + * The private key. + */ + protected STALPrivateKey privateKey; + + /** + * The to-be signed data. + */ + protected ByteArrayOutputStream data = new ByteArrayOutputStream(); + + /* (non-Javadoc) + * @see java.security.SignatureSpi#engineGetParameter(java.lang.String) + */ + @Override + protected Object engineGetParameter(String param) + throws InvalidParameterException { + throw new InvalidParameterException(); + } + + /* (non-Javadoc) + * @see java.security.SignatureSpi#engineInitSign(java.security.PrivateKey) + */ + @Override + protected void engineInitSign(PrivateKey privateKey) + throws InvalidKeyException { + + if (!(privateKey instanceof STALPrivateKey)) { + throw new InvalidKeyException("STALSignature supports STALKeys only."); + } + + this.privateKey = (STALPrivateKey) privateKey; + + } + + /* (non-Javadoc) + * @see java.security.SignatureSpi#engineInitVerify(java.security.PublicKey) + */ + @Override + protected void engineInitVerify(PublicKey publicKey) + throws InvalidKeyException { + + throw new UnsupportedOperationException("STALSignature does not support signature verification."); + } + + /* (non-Javadoc) + * @see java.security.SignatureSpi#engineSetParameter(java.lang.String, java.lang.Object) + */ + @Override + protected void engineSetParameter(String param, Object value) + throws InvalidParameterException { + } + + /* (non-Javadoc) + * @see java.security.SignatureSpi#engineSign() + */ + @Override + protected byte[] engineSign() throws SignatureException { + + STAL stal = privateKey.getStal(); + + if (stal == null) { + throw new SignatureException("STALSignature requires the STALPrivateKey " + + "to provide a STAL implementation reference."); + } + + String keyboxIdentifier = privateKey.getKeyboxIdentifier(); + + if (keyboxIdentifier == null) { + throw new SignatureException("STALSignature requires the STALPrivateKey " + + "to provide a KeyboxIdentifier."); + } + + // get hashDataInputs (DigestInputStreams) once slcommands.impl.xsect.Signature::sign() was called + List dataObjects = privateKey.getDataObjects(); +// log.debug("got " + dataObjects.size() + " DataObjects, passing HashDataInputs to STAL SignRequest"); + + List hashDataInputs = new ArrayList(); + for (DataObject dataObject : dataObjects) { + hashDataInputs.add(new HashDataInputImpl(dataObject)); + } + + SignRequest signRequest = new SignRequest(); + signRequest.setKeyIdentifier(keyboxIdentifier); + signRequest.setSignedInfo(data.toByteArray()); + signRequest.setHashDataInput(hashDataInputs); + + List responses = stal.handleRequest(Collections.singletonList((STALRequest) signRequest)); + + if (responses == null || responses.size() != 1) { + throw new SignatureException("Failed to access STAL."); + } + + STALResponse response = responses.get(0); + if (response instanceof SignResponse) { + return ((SignResponse) response).getSignatureValue(); + } else if (response instanceof ErrorResponse) { + throw new STALSignatureException(((ErrorResponse) response).getErrorCode()); + } else { + throw new SignatureException("Failed to access STAL."); + } + + } + + /* (non-Javadoc) + * @see java.security.SignatureSpi#engineUpdate(byte) + */ + @Override + protected void engineUpdate(byte b) throws SignatureException { + data.write(b); + } + + /* (non-Javadoc) + * @see java.security.SignatureSpi#engineUpdate(byte[], int, int) + */ + @Override + protected void engineUpdate(byte[] b, int off, int len) + throws SignatureException { + data.write(b, off, len); + } + + /* (non-Javadoc) + * @see java.security.SignatureSpi#engineVerify(byte[]) + */ + @Override + protected boolean engineVerify(byte[] sigBytes) throws SignatureException { + throw new UnsupportedOperationException("STALSignature des not support signature verification."); + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java index 94a4a066..191f8371 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java @@ -14,922 +14,939 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -package at.gv.egiz.bku.slcommands.impl.xsect; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.StringWriter; -import java.io.UnsupportedEncodingException; -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.PrivateKey; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Collections; -import java.util.Date; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.crypto.MarshalException; -import javax.xml.crypto.dom.DOMStructure; -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.crypto.dsig.DigestMethod; -import javax.xml.crypto.dsig.Reference; -import javax.xml.crypto.dsig.SignatureMethod; -import javax.xml.crypto.dsig.SignedInfo; -import javax.xml.crypto.dsig.XMLObject; -import javax.xml.crypto.dsig.XMLSignature; -import javax.xml.crypto.dsig.XMLSignatureException; -import javax.xml.crypto.dsig.XMLSignatureFactory; -import javax.xml.crypto.dsig.dom.DOMSignContext; -import javax.xml.crypto.dsig.keyinfo.KeyInfo; -import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; -import javax.xml.crypto.dsig.keyinfo.X509Data; -import javax.xml.stream.XMLStreamException; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.etsi.uri._01903.v1_1.DataObjectFormatType; -import org.etsi.uri._01903.v1_1.QualifyingPropertiesType; -import org.w3c.dom.DOMConfiguration; -import org.w3c.dom.DOMException; -import org.w3c.dom.Document; -import org.w3c.dom.DocumentFragment; -import org.w3c.dom.Element; -import org.w3c.dom.Node; -import org.w3c.dom.NodeList; -import org.w3c.dom.ls.DOMImplementationLS; -import org.w3c.dom.ls.LSException; -import org.w3c.dom.ls.LSInput; -import org.w3c.dom.ls.LSOutput; -import org.w3c.dom.ls.LSParser; -import org.w3c.dom.ls.LSResourceResolver; -import org.w3c.dom.ls.LSSerializer; - -import at.buergerkarte.namespaces.securitylayer._1.Base64XMLLocRefReqRefContentType; -import at.buergerkarte.namespaces.securitylayer._1.Base64XMLOptRefContentType; -import at.buergerkarte.namespaces.securitylayer._1.DataObjectAssociationType; -import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; -import at.buergerkarte.namespaces.securitylayer._1.SignatureInfoCreationType; -import at.gv.egiz.bku.binding.HttpUtil; -import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.bku.slexceptions.SLRequestException; -import at.gv.egiz.bku.utils.HexDump; -import at.gv.egiz.bku.utils.urldereferencer.StreamData; -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; -import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; -import at.gv.egiz.dom.DOMUtils; -import at.gv.egiz.slbinding.impl.XMLContentType; -import at.gv.egiz.stal.HashDataInputCallback; -import at.gv.egiz.stal.STAL; -import at.gv.egiz.xades.QualifyingPropertiesException; -import at.gv.egiz.xades.QualifyingPropertiesFactory; - -/** - * This class represents an XML-Signature as to be created by the - * security layer command CreateXMLSignatureRequest. - * - * @author mcentner - */ -public class Signature implements HashDataInputCallback { - - /** - * Logging facility. - */ - private static Log log = LogFactory.getLog(Signature.class); - - /** - * The DOM implementation used. - */ - private DOMImplementationLS domImplLS; - - /** - * The SignatureContext for the XMLSignature. - */ - private SignatureContext ctx; - - /** - * The list of {@link DataObject}s for this signature. - */ - private List dataObjects = new ArrayList(); - - /** - * A mapping from the Id-attribute values of this signature's - * ds:References to the corresponding {@link DataObject}s. - */ - private Map dataObjectReferencIds = new HashMap(); - - /** - * The SignatureEnvironment for this signature. - */ - private SignatureLocation signatureLocation; - - /** - * The XML signature. - */ - private XMLSignature xmlSignature; - - /** - * A list of attributes of type xsd:ID to be registered in the {@link DOMSignContext}. - */ - private List idAttributes = new ArrayList(); - - /** - * The signer's X509 certificate. - */ - private X509Certificate signerCertificate; - - /** - * The signing time. - */ - private Date signingTime; - - /** - * Creates a new SLXMLSignature instance. - */ - public Signature(URLDereferencerContext dereferencerContext, - IdValueFactory idValueFactory, - AlgorithmMethodFactory algorithmMethodFactory) { - - domImplLS = DOMUtils.getDOMImplementationLS(); - - ctx = new SignatureContext(); - - ctx.setSignatureFactory(XMLSignatureFactory.getInstance()); - - ctx.setDereferencerContext(dereferencerContext); - ctx.setIdValueFactory(idValueFactory); - ctx.setAlgorithmMethodFactory(algorithmMethodFactory); - - } - - /** - * @return the Document containing this Signature - */ - public Document getDocument() { - return ctx.getDocument(); - } - - /** - * @return the parent Node for this Signature - */ - public Node getParent() { - return (signatureLocation != null) ? signatureLocation.getParent() : null; - } - - /** - * @return the next sibling Node for this Signature - */ - public Node getNextSibling() { - return (signatureLocation != null) ? signatureLocation.getNextSibling() : null; - } - - /** - * @return the XMLSignature - */ - public XMLSignature getXMLSignature() { - return xmlSignature; - } - - /** - * @return the list of {@link Reference}s of this Signature - */ - @SuppressWarnings("unchecked") - public List getReferences() { - return (xmlSignature != null) ? xmlSignature.getSignedInfo().getReferences() : null; - } - - /** - * @return the list of {@link XMLObject}s of this Signature - */ - @SuppressWarnings("unchecked") - public List getXMLObjects() { - return (xmlSignature != null) ? xmlSignature.getObjects() : null; - } - - /** - * Prepares the signature document with the information given by the - * signatureInfo provided. - * - * @param signatureInfo - * the SignatureInfo - * - * @throws SLCommandException - * if processing fails for any reason - * @throws IllegalStateException - * if the parent node has already been set - * @throws NullPointerException - * if signatureInfo is null - */ - public void setSignatureInfo(SignatureInfoCreationType signatureInfo) throws SLCommandException { - - if (signatureLocation != null) { - throw new IllegalStateException("SignatureEnvironment already set."); - } - - Base64XMLOptRefContentType signatureEnvironment = signatureInfo.getSignatureEnvironment(); - - if (signatureEnvironment == null) { - - // no SignatureEnvironment, so we use an empty document and the document as parent - ensureSignatureLocation(); - - } else { - - // parse SignatureEnvrionment and use as document - Document document = parseSignatureEnvironment(signatureEnvironment, signatureInfo.getSupplement()); - ctx.setDocument(document); - - signatureLocation = new SignatureLocation(ctx); - signatureLocation.setSignatureInfo(signatureInfo); - - } - - } - - /** - * Ensures a SignatureLocation for this Signature. - */ - private void ensureSignatureLocation() { - - if (signatureLocation == null) { - Document document = DOMUtils.createDocument(); - ctx.setDocument(document); - - signatureLocation = new SignatureLocation(ctx); - signatureLocation.setParent(document); - } - - } - - /** - * Adds a DataObject with the information given by the - * dataObjectInfo provided to this Signature. - * - * @param dataObjectInfo - * the DataObjectInfo element - * - * @throws SLCommandException - * if adding the DataObject fails - * @throws SLRequestException - * if the information provided by the given - * dataObjectInfo does not conform to the security - * layer specification - * @throws NullPointerException - * if dataObjectInfo is null - */ - public void addDataObject(DataObjectInfoType dataObjectInfo) throws SLCommandException, SLRequestException { - - ensureSignatureLocation(); - - DataObject dataObject = new DataObject(ctx); - dataObject.setDataObjectInfo(dataObjectInfo); - - dataObjects.add(dataObject); - - dataObjectReferencIds.put(dataObject.getReference().getId(), dataObject); - - } - - /** - * Sets the SigningTime qualifying property of this Signature. - * - * @param signingTime the signing time to set - */ - public void setSigningTime(Date signingTime) { - this.signingTime = signingTime; - } - - /** - * Sets the SignerCertificate qualifying property of this Signature. - * - * @param certificate the signer's certificate - */ - public void setSignerCeritifcate(X509Certificate certificate) { - this.signerCertificate = certificate; - } - - /** - * Builds the XMLSignature data structure of this Signature as configured by - * the various setter methods. - * - * @throws SLCommandException if building this signature fails - */ - public void buildXMLSignature() throws SLCommandException { - - List objects = new ArrayList(); - List references = new ArrayList(); - - // add all data objects - for (DataObject dataObject : dataObjects) { - if (dataObject.getXmlObject() != null) { - objects.add(dataObject.getXmlObject()); - } - if (dataObject.getReference() != null) { - references.add(dataObject.getReference()); - } - } - - addXAdESObjectAndReference(objects, references); - - XMLSignatureFactory signatureFactory = ctx.getSignatureFactory(); - AlgorithmMethodFactory algorithmMethodFactory = ctx.getAlgorithmMethodFactory(); - - CanonicalizationMethod cm; - SignatureMethod sm; - try { - cm = algorithmMethodFactory.createCanonicalizationMethod(ctx); - sm = algorithmMethodFactory.createSignatureMethod(ctx); - } catch (NoSuchAlgorithmException e) { - log.error("Failed to get Canonicalization or Signature algorithm.", e); - throw new SLCommandException(4006); - } catch (InvalidAlgorithmParameterException e) { - log.error("Failed to get Canonicalization or Signature algorithm.", e); - throw new SLCommandException(4006); - } - - String siId = ctx.getIdValueFactory().createIdValue("SignedInfo"); - - SignedInfo si = signatureFactory.newSignedInfo(cm, sm, references, siId); - - KeyInfo ki = null; - if (signerCertificate != null) { - KeyInfoFactory kif = KeyInfoFactory.getInstance(); - X509Data x509Data = kif.newX509Data(Collections.singletonList(signerCertificate)); - ki = kif.newKeyInfo(Collections.singletonList(x509Data)); - } - - String signatureId = ctx.getIdValueFactory().createIdValue("Signature"); - String signatureValueId = ctx.getIdValueFactory().createIdValue("SignatureValue"); - - xmlSignature = signatureFactory.newXMLSignature(si, ki, objects, signatureId, signatureValueId); - - } - - /** - * Sign this Signature using the given signContext. - *

- * Call's {@link #buildXMLSignature()} if it has not been called yet. - *

- * - * @param signContext - * the signing context - * - * @throws MarshalException - * if marshalling the XMLSignature fails - * @throws XMLSignatureException - * if signing the XMLSignature fails - * @throws SLCommandException - * if building the XMLSignature fails - * @throws NullPointerException - * if signContext is null - */ - public void sign(DOMSignContext signContext) throws MarshalException, XMLSignatureException, SLCommandException { - - if (xmlSignature == null) { - buildXMLSignature(); - } - - for (IdAttribute idAttribute : idAttributes) { - signContext.setIdAttributeNS(idAttribute.element, idAttribute.namespaceURI, idAttribute.localName); - } - - // DO NOT USE: - // signContext.setProperty("iaik.xml.crypto.dsig.sign-over", Boolean.TRUE); - - signContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE); - - signContext.putNamespacePrefix(XMLSignature.XMLNS, "dsig"); - - signContext.setURIDereferencer(new URIDereferncerAdapter(ctx.getDereferencerContext())); - - try { - xmlSignature.sign(signContext); - } catch (XMLSignatureException e) { - Throwable cause = e.getCause(); - while (cause != null) { - if (cause instanceof STALSignatureException) { - int errorCode = ((STALSignatureException) cause).getErrorCode(); - SLCommandException commandException = new SLCommandException(errorCode); - log.info("Failed to sign signature.", commandException); - throw commandException; - } else { - cause = cause.getCause(); - } - } - throw e; - } - - // debug - if (log.isTraceEnabled()) { - for (DataObject dataObject : dataObjects) { - Reference reference = dataObject.getReference(); - InputStream digestInputStream = reference.getDigestInputStream(); - if (digestInputStream != null) { - String mimeType = dataObject.getMimeType(); - StringBuilder sb = new StringBuilder(); - sb.append("DigestInput for Reference with id='"); - sb.append(reference.getId()); - sb.append("' (MIME-Type="); - sb.append(dataObject.getMimeType()); - sb.append("):\n"); - try { - if (mimeType != null && ( - mimeType.startsWith("text") || - "application/xhtml+xml".equals(mimeType))) { - byte[] b = new byte[512]; - for (int l; (l = digestInputStream.read(b)) != -1;) { - sb.append(new String(b, 0, l)); - } - } else { - sb.append(HexDump.hexDump(digestInputStream)); - } - } catch (IOException e) { - log.error(e); - } - log.trace(sb.toString()); - } else { - log.trace("Reference caching is not enabled."); - } - } - } - - } - - /** - * Sign this Signature using the given stal implementation and - * keyboxIdentifier. - *

- * This method configures an appropriate {@link DOMSignContext} and calls - * {@link #sign(DOMSignContext)}. If {@link #buildXMLSignature()} has not been - * called yet, it is called by this method. - *

- * - * @param stal - * the STAL implementation to use - * @param keyboxIdentifier - * the KeyboxIdentifier to use - * - * @throws MarshalException - * if marshalling this Signature fails - * @throws XMLSignatureException - * if signing this Signature fails - * @throws SLCommandException - * if building this Signature fails - * @throws NullPointerException - * if stal or keyboxIdentifier is - * null - */ - public void sign(STAL stal, String keyboxIdentifier) throws MarshalException, XMLSignatureException, SLCommandException { - - if (stal == null) { - throw new NullPointerException("Argument 'stal' must not be null."); - } - - if (keyboxIdentifier == null) { - throw new NullPointerException("Argument 'keyboxIdentifier' must not be null."); - } - - if (xmlSignature == null) { - buildXMLSignature(); - } - - SignatureMethod signatureMethod = xmlSignature.getSignedInfo().getSignatureMethod(); - String algorithm = signatureMethod.getAlgorithm(); - - PrivateKey privateKey = new STALPrivateKey(stal, algorithm, keyboxIdentifier, this); - - DOMSignContext signContext; - if (getNextSibling() == null) { - signContext = new DOMSignContext(privateKey, getParent()); - } else { - signContext = new DOMSignContext(privateKey, getParent(), getNextSibling()); - } - - sign(signContext); - } - - @Override - public InputStream getHashDataInput(String referenceId) { - - DataObject dataObject = dataObjectReferencIds.get(referenceId); - if (dataObject != null) { - return dataObject.getReference().getDigestInputStream(); - } else { - return null; - } - } - - /** - * Adds the XAdES QualifyingProperties as an - * ds:Object and a corresponding ds:Reference to - * it's SignedProperties element to this Signature. - * - * @param objects - * the list of ds:Objects to add the created - * ds:Object to - * @param references - * the list of ds:References to add the created - * ds:Reference to - * - * @throws SLCommandException - * if creating and adding the XAdES - * QualifyingProperties fails - * @throws NullPointerException - * if objects or references is - * null - */ - private void addXAdESObjectAndReference(List objects, List references) throws SLCommandException { - - QualifyingPropertiesFactory factory = QualifyingPropertiesFactory.getInstance(); - - String idValue = ctx.getIdValueFactory().createIdValue("SignedProperties"); - - Date date = (signingTime != null) ? signingTime : new Date(); - - List signingCertificates; - if (signerCertificate != null) { - signingCertificates = Collections.singletonList(signerCertificate); - } else { - signingCertificates = Collections.emptyList(); - } - - // TODO: report MOA-SP bug - // - // The security layer specification mandates the use of version 1.2.2. of the - // XAdES QualifyingProperties. However MOA-SP supports only version 1.1.1. Therefore, - // the version 1.1.1 is used in order to be compatible with current MOA-SP versions. - - List dataObjectFormats = new ArrayList(); - for (DataObject dataObject : dataObjects) { - if (dataObject.getMimeType() != null && dataObject.getReference() != null) { - Reference reference = dataObject.getReference(); - if (reference.getId() != null) { - String objectReference = "#" + reference.getId(); - dataObjectFormats.add(factory.createDataObjectFormatType( - objectReference, dataObject.getMimeType(), dataObject - .getDescription())); - } - } - } - - JAXBElement qualifyingProperties; - try { - qualifyingProperties = factory.createQualifyingProperties111(date, signingCertificates, idValue, dataObjectFormats); - } catch (QualifyingPropertiesException e) { - log.error("Failed to create QualifyingProperties.", e); - throw new SLCommandException(4000); - } - - DocumentFragment fragment = ctx.getDocument().createDocumentFragment(); - - try { - factory.marshallQualifyingProperties(qualifyingProperties, fragment); - } catch (JAXBException e) { - log.error("Failed to marshal QualifyingProperties.", e); - throw new SLCommandException(4000); - } - - List content = Collections.singletonList(new DOMStructure(fragment.getFirstChild())); - - String objectIdValue = ctx.getIdValueFactory().createIdValue("Object"); - - XMLObject object = ctx.getSignatureFactory().newXMLObject(content, objectIdValue, null, null); - - objects.add(object); - - // TODO: Report MOA-SP Bug - // - // Direct referencing of the SignedPorperties Id-attribute is not supported by MOA-SP - // because the QualifyingProperties are parsed without the XAdES schema. Therefore, - // the shorthand XPointer could not be resolved. - // - // The following workaround uses an XPointer to select the SignedProperties in order - // to allow the signature to be verified with MOA-SP. - - String referenceURI = "#xmlns(xades=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('" - + objectIdValue - + "')/child::xades:QualifyingProperties/child::xades:SignedProperties)"; - DigestMethod dm; - try { - dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); - } catch (NoSuchAlgorithmException e) { - log.error("Failed to get DigestMethod algorithm.", e); - throw new SLCommandException(4006); - } catch (InvalidAlgorithmParameterException e) { - log.error("Failed to get DigestMethod algorithm.", e); - throw new SLCommandException(4006); - } - - String referenceIdValue = ctx.getIdValueFactory().createIdValue("Reference"); - String referenceType = QualifyingPropertiesFactory.SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1; - - Reference reference = ctx.getSignatureFactory().newReference(referenceURI, dm, null, referenceType, referenceIdValue); - - references.add(reference); - - Node child = fragment.getFirstChild(); - if (child instanceof Element) { - NodeList nodes = ((Element) child).getElementsByTagNameNS(QualifyingPropertiesFactory.NS_URI_V1_1_1, "SignedProperties"); - if (nodes.getLength() > 0) { - IdAttribute idAttribute = new IdAttribute(); - idAttribute.element = (Element) nodes.item(0); - idAttribute.namespaceURI = null; - idAttribute.localName = "Id"; - idAttributes.add(idAttribute); - } - } - - } - - /** - * Parse the SignatureEnvironment. - * - * @param signatureEnvironment - * the SignatureEnvironment element - * @param supplements - * an optional list of Supplements (may be - * null) - * - * @return the parsed SignatureEnvironment document - * - * @throws SLCommandException - * if parsing the SignatureEnvironment fails - * @throws NullPointerException - * if signatureEnvironment is null - */ - private Document parseSignatureEnvironment( - Base64XMLOptRefContentType signatureEnvironment, - List supplements) throws SLCommandException { - - if (signatureEnvironment == null) { - throw new NullPointerException("Argument 'signatureEnvironment' must not be null."); - } - - LSInput input; - try { - if (signatureEnvironment.getReference() != null) { - log.debug("SignatureEnvironment contains Reference " + signatureEnvironment.getReference() + "."); - input = createLSInput(signatureEnvironment.getReference()); - } else if (signatureEnvironment.getBase64Content() != null) { - log.debug("SignatureEnvironment contains Base64Content."); - input = createLSInput(signatureEnvironment.getBase64Content()); - } else if (signatureEnvironment.getXMLContent() != null) { - log.debug("SignatureEnvironment contains XMLContent."); - input = createLSInput((XMLContentType) signatureEnvironment.getXMLContent()); - } else { - // the schema does not allow us to reach this point - throw new SLCommandException(4000); - } - } catch (IOException e) { - log.info("XML document in which the signature is to be integrated cannot be resolved.", e); - throw new SLCommandException(4100); - } catch (XMLStreamException e) { - log.info("XML document in which the signature is to be integrated cannot be resolved.", e); - throw new SLCommandException(4100); - } - - LSParser parser = domImplLS.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); - DOMConfiguration domConfig = parser.getDomConfig(); - SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); - domConfig.setParameter("error-handler", errorHandler); - LSResourceResolverAdapter resourceResolver = new LSResourceResolverAdapter(supplements); - domConfig.setParameter("resource-resolver", resourceResolver); - domConfig.setParameter("validate", Boolean.TRUE); - - Document doc; - try { - doc = parser.parse(input); - } catch (DOMException e) { - log.info("XML document in which the signature is to be integrated cannot be parsed.", e); - throw new SLCommandException(4101); - } catch (LSException e) { - log.info("XML document in which the signature is to be integrated cannot be parsed.", e); - throw new SLCommandException(4101); - } - - if (resourceResolver.getError() != null) { - log.info("Failed to resolve resource while parsing SignatureEnvironment document.", resourceResolver.getError()); - // we don't stop here, as we only _try_ to parse validating - } - - if (errorHandler.hasFatalErrors()) { - // log fatal errors - if (log.isInfoEnabled()) { - List errorMessages = errorHandler.getErrorMessages(); - StringBuffer sb = new StringBuffer(); - for (String errorMessage : errorMessages) { - sb.append(" "); - sb.append(errorMessage); - } - log.info("XML document in which the signature is to be integrated cannot be parsed." + sb.toString()); - } - throw new SLCommandException(4101); - } - - // log parsed document - if (log.isTraceEnabled()) { - - StringWriter writer = new StringWriter(); - - writer.write("SignatureEnvironment:\n"); - - LSOutput output = domImplLS.createLSOutput(); - output.setCharacterStream(writer); - output.setEncoding("UTF-8"); - LSSerializer serializer = domImplLS.createLSSerializer(); - serializer.write(doc, output); - - log.trace(writer.toString()); - } - - return doc; - - } - - /** - * Creates an LSInput from the given reference URI. - * - * @param reference - * the reference URL - * - * @return an LSInput from the given reference URI - * - * @throws IOException - * if dereferencing the given reference fails - */ - private LSInput createLSInput(String reference) throws IOException { - - URLDereferencer urlDereferencer = URLDereferencer.getInstance(); - StreamData streamData = urlDereferencer.dereference(reference, ctx.getDereferencerContext()); - - String contentType = streamData.getContentType(); - String charset = HttpUtil.getCharset(contentType, true); - InputStreamReader streamReader; - try { - streamReader = new InputStreamReader(streamData.getStream(), charset); - } catch (UnsupportedEncodingException e) { - log.info("Charset " + charset + " not supported. Using default."); - streamReader = new InputStreamReader(streamData.getStream()); - } - - LSInput input = domImplLS.createLSInput(); - input = domImplLS.createLSInput(); - input.setCharacterStream(streamReader); - - return input; - - } - - /** - * Creates an LSInput from the given content bytes. - * - * @param content - * the content bytes - * - * @return an LSInput from the givne content bytes - */ - private LSInput createLSInput(byte[] content) { - - ByteArrayInputStream inputStream = new ByteArrayInputStream(content); - LSInput input = domImplLS.createLSInput(); - input.setByteStream(inputStream); - - return input; - - } - - /** - * Creates an LSInput from the given XML content. - * - * @param content - * the XML content - * @return an LSInput from the given XML content - * - * @throws XMLStreamException - * if reading the XMLStream from the given XML content fails - */ - private LSInput createLSInput(XMLContentType content) throws XMLStreamException { - - ByteArrayOutputStream redirectedStream = content.getRedirectedStream(); - if (redirectedStream != null) { - LSInput input = domImplLS.createLSInput(); - input.setByteStream(new ByteArrayInputStream(redirectedStream.toByteArray())); - return input; - } else { - return null; - } - - } - - /** - * Represents an xsd:Id-attribute value. - * - * @author mcentner - */ - private class IdAttribute { - - private Element element; - - private String namespaceURI; - - private String localName; - - } - - /** - * An implementation of the LSResourceResolver that uses a list of supplements - * to resolve resources. - * - * @author mcentner - */ - private class LSResourceResolverAdapter implements LSResourceResolver { - - List supplements; - - private LSResourceResolverAdapter( - List supplements) { - this.supplements = supplements; - } - - private Exception error; - - /** - * @return the error - */ - public Exception getError() { - return error; - } - - @Override - public LSInput resolveResource(String type, String namespaceURI, - String publicId, String systemId, String baseURI) { - - if (log.isTraceEnabled()) { - log.trace("Resolve resource :" + - "\n type=" + type + - "\n namespaceURI=" + namespaceURI + - "\n publicId=" + publicId + - "\n systemId=" + systemId + - "\n baseURI=" + baseURI); - } - - if (systemId != null) { - - log.debug("Resolve resource '" + systemId + "'."); - - for (DataObjectAssociationType supplement : supplements) { - - Base64XMLLocRefReqRefContentType content = supplement.getContent(); - if (content != null) { - - String reference = content.getReference(); - if (systemId.equals(reference)) { - - try { - if (content.getLocRefContent() != null) { - log.trace("Resolved resource '" + reference + "' to supplement with LocRefContent."); - return createLSInput(content.getLocRefContent()); - } else if (content.getBase64Content() != null) { - log.trace("Resolved resource '" + reference + "' to supplement with Base64Content."); - return createLSInput(content.getBase64Content()); - } else if (content.getXMLContent() != null) { - log.trace("Resolved resource '" + reference + "' to supplement with XMLContent."); - return createLSInput((XMLContentType) content.getXMLContent()); - } else { - return null; - } - } catch (IOException e) { - log.info("Failed to resolve resource '" + systemId + "' to supplement.", e); - error = e; - return null; - } catch (XMLStreamException e) { - log.info("Failed to resolve resource '" + systemId + "' to supplement.", e); - error = e; - return null; - } - - } - - } - - } - - log.info("Failed to resolve resource '" + systemId + "' to supplement. No such supplement."); - - } - - return null; - - } - - - } - -} +package at.gv.egiz.bku.slcommands.impl.xsect; + +import at.gv.egiz.stal.HashDataInput; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.StringWriter; +import java.io.UnsupportedEncodingException; +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Date; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.crypto.MarshalException; +import javax.xml.crypto.dom.DOMStructure; +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.Reference; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.crypto.dsig.SignedInfo; +import javax.xml.crypto.dsig.XMLObject; +import javax.xml.crypto.dsig.XMLSignature; +import javax.xml.crypto.dsig.XMLSignatureException; +import javax.xml.crypto.dsig.XMLSignatureFactory; +import javax.xml.crypto.dsig.dom.DOMSignContext; +import javax.xml.crypto.dsig.keyinfo.KeyInfo; +import javax.xml.crypto.dsig.keyinfo.KeyInfoFactory; +import javax.xml.crypto.dsig.keyinfo.X509Data; +import javax.xml.stream.XMLStreamException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.etsi.uri._01903.v1_1.DataObjectFormatType; +import org.etsi.uri._01903.v1_1.QualifyingPropertiesType; +import org.w3c.dom.DOMConfiguration; +import org.w3c.dom.DOMException; +import org.w3c.dom.Document; +import org.w3c.dom.DocumentFragment; +import org.w3c.dom.Element; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; +import org.w3c.dom.ls.DOMImplementationLS; +import org.w3c.dom.ls.LSException; +import org.w3c.dom.ls.LSInput; +import org.w3c.dom.ls.LSOutput; +import org.w3c.dom.ls.LSParser; +import org.w3c.dom.ls.LSResourceResolver; +import org.w3c.dom.ls.LSSerializer; + +import at.buergerkarte.namespaces.securitylayer._1.Base64XMLLocRefReqRefContentType; +import at.buergerkarte.namespaces.securitylayer._1.Base64XMLOptRefContentType; +import at.buergerkarte.namespaces.securitylayer._1.DataObjectAssociationType; +import at.buergerkarte.namespaces.securitylayer._1.DataObjectInfoType; +import at.buergerkarte.namespaces.securitylayer._1.SignatureInfoCreationType; +import at.gv.egiz.bku.binding.HttpUtil; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLRequestException; +import at.gv.egiz.bku.utils.HexDump; +import at.gv.egiz.bku.utils.urldereferencer.StreamData; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; +import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; +import at.gv.egiz.dom.DOMUtils; +import at.gv.egiz.slbinding.impl.XMLContentType; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.xades.QualifyingPropertiesException; +import at.gv.egiz.xades.QualifyingPropertiesFactory; + +/** + * This class represents an XML-Signature as to be created by the + * security layer command CreateXMLSignatureRequest. + * + * @author mcentner + */ +public class Signature { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(Signature.class); + + /** + * The DOM implementation used. + */ + private DOMImplementationLS domImplLS; + + /** + * The SignatureContext for the XMLSignature. + */ + private SignatureContext ctx; + + /** + * The list of {@link DataObject}s for this signature. + */ + private List dataObjects = new ArrayList(); + + /** + * A mapping from the Id-attribute values of this signature's + * ds:References to the corresponding {@link DataObject}s. + */ +// private Map dataObjectReferencIds = new HashMap(); + + /** + * The SignatureEnvironment for this signature. + */ + private SignatureLocation signatureLocation; + + /** + * The XML signature. + */ + private XMLSignature xmlSignature; + + /** + * A list of attributes of type xsd:ID to be registered in the {@link DOMSignContext}. + */ + private List idAttributes = new ArrayList(); + + /** + * The signer's X509 certificate. + */ + private X509Certificate signerCertificate; + + /** + * The signing time. + */ + private Date signingTime; + + /** + * Creates a new SLXMLSignature instance. + */ + public Signature(URLDereferencerContext dereferencerContext, + IdValueFactory idValueFactory, + AlgorithmMethodFactory algorithmMethodFactory) { + + domImplLS = DOMUtils.getDOMImplementationLS(); + + ctx = new SignatureContext(); + + ctx.setSignatureFactory(XMLSignatureFactory.getInstance()); + + ctx.setDereferencerContext(dereferencerContext); + ctx.setIdValueFactory(idValueFactory); + ctx.setAlgorithmMethodFactory(algorithmMethodFactory); + + } + + /** + * @return the Document containing this Signature + */ + public Document getDocument() { + return ctx.getDocument(); + } + + /** + * @return the parent Node for this Signature + */ + public Node getParent() { + return (signatureLocation != null) ? signatureLocation.getParent() : null; + } + + /** + * @return the next sibling Node for this Signature + */ + public Node getNextSibling() { + return (signatureLocation != null) ? signatureLocation.getNextSibling() : null; + } + + /** + * @return the XMLSignature + */ + public XMLSignature getXMLSignature() { + return xmlSignature; + } + + /** + * @return the list of {@link Reference}s of this Signature + */ + @SuppressWarnings("unchecked") + public List getReferences() { + return (xmlSignature != null) ? xmlSignature.getSignedInfo().getReferences() : null; + } + + /** + * @return the list of {@link XMLObject}s of this Signature + */ + @SuppressWarnings("unchecked") + public List getXMLObjects() { + return (xmlSignature != null) ? xmlSignature.getObjects() : null; + } + + /** + * Prepares the signature document with the information given by the + * signatureInfo provided. + * + * @param signatureInfo + * the SignatureInfo + * + * @throws SLCommandException + * if processing fails for any reason + * @throws IllegalStateException + * if the parent node has already been set + * @throws NullPointerException + * if signatureInfo is null + */ + public void setSignatureInfo(SignatureInfoCreationType signatureInfo) throws SLCommandException { + + if (signatureLocation != null) { + throw new IllegalStateException("SignatureEnvironment already set."); + } + + Base64XMLOptRefContentType signatureEnvironment = signatureInfo.getSignatureEnvironment(); + + if (signatureEnvironment == null) { + + // no SignatureEnvironment, so we use an empty document and the document as parent + ensureSignatureLocation(); + + } else { + + // parse SignatureEnvrionment and use as document + Document document = parseSignatureEnvironment(signatureEnvironment, signatureInfo.getSupplement()); + ctx.setDocument(document); + + signatureLocation = new SignatureLocation(ctx); + signatureLocation.setSignatureInfo(signatureInfo); + + } + + } + + /** + * Ensures a SignatureLocation for this Signature. + */ + private void ensureSignatureLocation() { + + if (signatureLocation == null) { + Document document = DOMUtils.createDocument(); + ctx.setDocument(document); + + signatureLocation = new SignatureLocation(ctx); + signatureLocation.setParent(document); + } + + } + + /** + * Adds a DataObject with the information given by the + * dataObjectInfo provided to this Signature. + * + * @param dataObjectInfo + * the DataObjectInfo element + * + * @throws SLCommandException + * if adding the DataObject fails + * @throws SLRequestException + * if the information provided by the given + * dataObjectInfo does not conform to the security + * layer specification + * @throws NullPointerException + * if dataObjectInfo is null + */ + public void addDataObject(DataObjectInfoType dataObjectInfo) throws SLCommandException, SLRequestException { + + ensureSignatureLocation(); + + DataObject dataObject = new DataObject(ctx); + dataObject.setDataObjectInfo(dataObjectInfo); + + dataObjects.add(dataObject); + +// dataObjectReferencIds.put(dataObject.getReference().getId(), dataObject); + + } + + /** + * Sets the SigningTime qualifying property of this Signature. + * + * @param signingTime the signing time to set + */ + public void setSigningTime(Date signingTime) { + this.signingTime = signingTime; + } + + /** + * Sets the SignerCertificate qualifying property of this Signature. + * + * @param certificate the signer's certificate + */ + public void setSignerCeritifcate(X509Certificate certificate) { + this.signerCertificate = certificate; + } + + /** + * Builds the XMLSignature data structure of this Signature as configured by + * the various setter methods. + * + * @throws SLCommandException if building this signature fails + */ + public void buildXMLSignature() throws SLCommandException { + + List objects = new ArrayList(); + List references = new ArrayList(); + + // add all data objects + for (DataObject dataObject : dataObjects) { + if (dataObject.getXmlObject() != null) { + objects.add(dataObject.getXmlObject()); + } + if (dataObject.getReference() != null) { + references.add(dataObject.getReference()); + } + } + + addXAdESObjectAndReference(objects, references); + + XMLSignatureFactory signatureFactory = ctx.getSignatureFactory(); + AlgorithmMethodFactory algorithmMethodFactory = ctx.getAlgorithmMethodFactory(); + + CanonicalizationMethod cm; + SignatureMethod sm; + try { + cm = algorithmMethodFactory.createCanonicalizationMethod(ctx); + sm = algorithmMethodFactory.createSignatureMethod(ctx); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get Canonicalization or Signature algorithm.", e); + throw new SLCommandException(4006); + } catch (InvalidAlgorithmParameterException e) { + log.error("Failed to get Canonicalization or Signature algorithm.", e); + throw new SLCommandException(4006); + } + + String siId = ctx.getIdValueFactory().createIdValue("SignedInfo"); + + SignedInfo si = signatureFactory.newSignedInfo(cm, sm, references, siId); + + KeyInfo ki = null; + if (signerCertificate != null) { + KeyInfoFactory kif = KeyInfoFactory.getInstance(); + X509Data x509Data = kif.newX509Data(Collections.singletonList(signerCertificate)); + ki = kif.newKeyInfo(Collections.singletonList(x509Data)); + } + + String signatureId = ctx.getIdValueFactory().createIdValue("Signature"); + String signatureValueId = ctx.getIdValueFactory().createIdValue("SignatureValue"); + + xmlSignature = signatureFactory.newXMLSignature(si, ki, objects, signatureId, signatureValueId); + + } + + /** + * Sign this Signature using the given signContext. + *

+ * Call's {@link #buildXMLSignature()} if it has not been called yet. + *

+ * + * @param signContext + * the signing context + * + * @throws MarshalException + * if marshalling the XMLSignature fails + * @throws XMLSignatureException + * if signing the XMLSignature fails + * @throws SLCommandException + * if building the XMLSignature fails + * @throws NullPointerException + * if signContext is null + */ + public void sign(DOMSignContext signContext) throws MarshalException, XMLSignatureException, SLCommandException { + + if (xmlSignature == null) { + buildXMLSignature(); + } + + for (IdAttribute idAttribute : idAttributes) { + signContext.setIdAttributeNS(idAttribute.element, idAttribute.namespaceURI, idAttribute.localName); + } + + // DO NOT USE: + // signContext.setProperty("iaik.xml.crypto.dsig.sign-over", Boolean.TRUE); + + signContext.setProperty("javax.xml.crypto.dsig.cacheReference", Boolean.TRUE); + + signContext.putNamespacePrefix(XMLSignature.XMLNS, "dsig"); + + signContext.setURIDereferencer(new URIDereferncerAdapter(ctx.getDereferencerContext())); + + try { + xmlSignature.sign(signContext); + } catch (XMLSignatureException e) { + Throwable cause = e.getCause(); + while (cause != null) { + if (cause instanceof STALSignatureException) { + int errorCode = ((STALSignatureException) cause).getErrorCode(); + SLCommandException commandException = new SLCommandException(errorCode); + log.info("Failed to sign signature.", commandException); + throw commandException; + } else { + cause = cause.getCause(); + } + } + throw e; + } + + // debug + if (log.isTraceEnabled()) { + for (DataObject dataObject : dataObjects) { + Reference reference = dataObject.getReference(); + InputStream digestInputStream = reference.getDigestInputStream(); + if (digestInputStream != null) { + String mimeType = dataObject.getMimeType(); + StringBuilder sb = new StringBuilder(); + sb.append("DigestInput for Reference with id='"); + sb.append(reference.getId()); + sb.append("' (MIME-Type="); + sb.append(dataObject.getMimeType()); + sb.append("):\n"); + try { + if (mimeType != null && ( + mimeType.startsWith("text") || + "application/xhtml+xml".equals(mimeType))) { + byte[] b = new byte[512]; + for (int l; (l = digestInputStream.read(b)) != -1;) { + sb.append(new String(b, 0, l)); + } + } else { + sb.append(HexDump.hexDump(digestInputStream)); + } + } catch (IOException e) { + log.error(e); + } + log.trace(sb.toString()); + } else { + log.trace("Reference caching is not enabled."); + } + } + } + + } + + /** + * Sign this Signature using the given stal implementation and + * keyboxIdentifier. + *

+ * This method configures an appropriate {@link DOMSignContext} and calls + * {@link #sign(DOMSignContext)}. If {@link #buildXMLSignature()} has not been + * called yet, it is called by this method. + *

+ * + * @param stal + * the STAL implementation to use + * @param keyboxIdentifier + * the KeyboxIdentifier to use + * + * @throws MarshalException + * if marshalling this Signature fails + * @throws XMLSignatureException + * if signing this Signature fails + * @throws SLCommandException + * if building this Signature fails + * @throws NullPointerException + * if stal or keyboxIdentifier is + * null + */ + public void sign(STAL stal, String keyboxIdentifier) throws MarshalException, XMLSignatureException, SLCommandException { + + if (stal == null) { + throw new NullPointerException("Argument 'stal' must not be null."); + } + + if (keyboxIdentifier == null) { + throw new NullPointerException("Argument 'keyboxIdentifier' must not be null."); + } + + if (xmlSignature == null) { + buildXMLSignature(); + } + + SignatureMethod signatureMethod = xmlSignature.getSignedInfo().getSignatureMethod(); + String algorithm = signatureMethod.getAlgorithm(); + + //don't get hashDataInputs (digestInputStreams) now, only once Signature.sign() was called (cf STALSignature.engineSign) + PrivateKey privateKey = new STALPrivateKey(stal, algorithm, keyboxIdentifier, dataObjects); // hashDataInputs); + + DOMSignContext signContext; + if (getNextSibling() == null) { + signContext = new DOMSignContext(privateKey, getParent()); + } else { + signContext = new DOMSignContext(privateKey, getParent(), getNextSibling()); + } + + sign(signContext); + } + +// @Override +// public HashDataInput getHashDataInput(final String referenceId) { +// final DataObject dataObject = dataObjectReferencIds.get(referenceId); +// if (dataObject != null) { +// return new HashDataInput() { +// +// InputStream hashDataInput = dataObject.getReference().getDigestInputStream(); +// +// @Override +// public String getReferenceId() { +// return referenceId; +// } +// +// @Override +// public String getMimeType() { +// return dataObject.getMimeType(); +// } +// +// @Override +// public InputStream getHashDataInput() { +// return hashDataInput; +// } +// }; +// } +// return null; +// } + + /** + * Adds the XAdES QualifyingProperties as an + * ds:Object and a corresponding ds:Reference to + * it's SignedProperties element to this Signature. + * + * @param objects + * the list of ds:Objects to add the created + * ds:Object to + * @param references + * the list of ds:References to add the created + * ds:Reference to + * + * @throws SLCommandException + * if creating and adding the XAdES + * QualifyingProperties fails + * @throws NullPointerException + * if objects or references is + * null + */ + private void addXAdESObjectAndReference(List objects, List references) throws SLCommandException { + + QualifyingPropertiesFactory factory = QualifyingPropertiesFactory.getInstance(); + + String idValue = ctx.getIdValueFactory().createIdValue("SignedProperties"); + + Date date = (signingTime != null) ? signingTime : new Date(); + + List signingCertificates; + if (signerCertificate != null) { + signingCertificates = Collections.singletonList(signerCertificate); + } else { + signingCertificates = Collections.emptyList(); + } + + // TODO: report MOA-SP bug + // + // The security layer specification mandates the use of version 1.2.2. of the + // XAdES QualifyingProperties. However MOA-SP supports only version 1.1.1. Therefore, + // the version 1.1.1 is used in order to be compatible with current MOA-SP versions. + + List dataObjectFormats = new ArrayList(); + for (DataObject dataObject : dataObjects) { + if (dataObject.getMimeType() != null && dataObject.getReference() != null) { + Reference reference = dataObject.getReference(); + if (reference.getId() != null) { + String objectReference = "#" + reference.getId(); + dataObjectFormats.add(factory.createDataObjectFormatType( + objectReference, dataObject.getMimeType(), dataObject + .getDescription())); + } + } + } + + JAXBElement qualifyingProperties; + try { + qualifyingProperties = factory.createQualifyingProperties111(date, signingCertificates, idValue, dataObjectFormats); + } catch (QualifyingPropertiesException e) { + log.error("Failed to create QualifyingProperties.", e); + throw new SLCommandException(4000); + } + + DocumentFragment fragment = ctx.getDocument().createDocumentFragment(); + + try { + factory.marshallQualifyingProperties(qualifyingProperties, fragment); + } catch (JAXBException e) { + log.error("Failed to marshal QualifyingProperties.", e); + throw new SLCommandException(4000); + } + + List content = Collections.singletonList(new DOMStructure(fragment.getFirstChild())); + + String objectIdValue = ctx.getIdValueFactory().createIdValue("Object"); + + XMLObject object = ctx.getSignatureFactory().newXMLObject(content, objectIdValue, null, null); + + objects.add(object); + + // TODO: Report MOA-SP Bug + // + // Direct referencing of the SignedPorperties Id-attribute is not supported by MOA-SP + // because the QualifyingProperties are parsed without the XAdES schema. Therefore, + // the shorthand XPointer could not be resolved. + // + // The following workaround uses an XPointer to select the SignedProperties in order + // to allow the signature to be verified with MOA-SP. + + String referenceURI = "#xmlns(xades=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('" + + objectIdValue + + "')/child::xades:QualifyingProperties/child::xades:SignedProperties)"; + DigestMethod dm; + try { + dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get DigestMethod algorithm.", e); + throw new SLCommandException(4006); + } catch (InvalidAlgorithmParameterException e) { + log.error("Failed to get DigestMethod algorithm.", e); + throw new SLCommandException(4006); + } + + String referenceIdValue = ctx.getIdValueFactory().createIdValue("Reference"); + String referenceType = QualifyingPropertiesFactory.SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1; + + Reference reference = ctx.getSignatureFactory().newReference(referenceURI, dm, null, referenceType, referenceIdValue); + + references.add(reference); + + Node child = fragment.getFirstChild(); + if (child instanceof Element) { + NodeList nodes = ((Element) child).getElementsByTagNameNS(QualifyingPropertiesFactory.NS_URI_V1_1_1, "SignedProperties"); + if (nodes.getLength() > 0) { + IdAttribute idAttribute = new IdAttribute(); + idAttribute.element = (Element) nodes.item(0); + idAttribute.namespaceURI = null; + idAttribute.localName = "Id"; + idAttributes.add(idAttribute); + } + } + + } + + /** + * Parse the SignatureEnvironment. + * + * @param signatureEnvironment + * the SignatureEnvironment element + * @param supplements + * an optional list of Supplements (may be + * null) + * + * @return the parsed SignatureEnvironment document + * + * @throws SLCommandException + * if parsing the SignatureEnvironment fails + * @throws NullPointerException + * if signatureEnvironment is null + */ + private Document parseSignatureEnvironment( + Base64XMLOptRefContentType signatureEnvironment, + List supplements) throws SLCommandException { + + if (signatureEnvironment == null) { + throw new NullPointerException("Argument 'signatureEnvironment' must not be null."); + } + + LSInput input; + try { + if (signatureEnvironment.getReference() != null) { + log.debug("SignatureEnvironment contains Reference " + signatureEnvironment.getReference() + "."); + input = createLSInput(signatureEnvironment.getReference()); + } else if (signatureEnvironment.getBase64Content() != null) { + log.debug("SignatureEnvironment contains Base64Content."); + input = createLSInput(signatureEnvironment.getBase64Content()); + } else if (signatureEnvironment.getXMLContent() != null) { + log.debug("SignatureEnvironment contains XMLContent."); + input = createLSInput((XMLContentType) signatureEnvironment.getXMLContent()); + } else { + // the schema does not allow us to reach this point + throw new SLCommandException(4000); + } + } catch (IOException e) { + log.info("XML document in which the signature is to be integrated cannot be resolved.", e); + throw new SLCommandException(4100); + } catch (XMLStreamException e) { + log.info("XML document in which the signature is to be integrated cannot be resolved.", e); + throw new SLCommandException(4100); + } + + LSParser parser = domImplLS.createLSParser(DOMImplementationLS.MODE_SYNCHRONOUS, null); + DOMConfiguration domConfig = parser.getDomConfig(); + SimpleDOMErrorHandler errorHandler = new SimpleDOMErrorHandler(); + domConfig.setParameter("error-handler", errorHandler); + LSResourceResolverAdapter resourceResolver = new LSResourceResolverAdapter(supplements); + domConfig.setParameter("resource-resolver", resourceResolver); + domConfig.setParameter("validate", Boolean.TRUE); + + Document doc; + try { + doc = parser.parse(input); + } catch (DOMException e) { + log.info("XML document in which the signature is to be integrated cannot be parsed.", e); + throw new SLCommandException(4101); + } catch (LSException e) { + log.info("XML document in which the signature is to be integrated cannot be parsed.", e); + throw new SLCommandException(4101); + } + + if (resourceResolver.getError() != null) { + log.info("Failed to resolve resource while parsing SignatureEnvironment document.", resourceResolver.getError()); + // we don't stop here, as we only _try_ to parse validating + } + + if (errorHandler.hasFatalErrors()) { + // log fatal errors + if (log.isInfoEnabled()) { + List errorMessages = errorHandler.getErrorMessages(); + StringBuffer sb = new StringBuffer(); + for (String errorMessage : errorMessages) { + sb.append(" "); + sb.append(errorMessage); + } + log.info("XML document in which the signature is to be integrated cannot be parsed." + sb.toString()); + } + throw new SLCommandException(4101); + } + + // log parsed document + if (log.isTraceEnabled()) { + + StringWriter writer = new StringWriter(); + + writer.write("SignatureEnvironment:\n"); + + LSOutput output = domImplLS.createLSOutput(); + output.setCharacterStream(writer); + output.setEncoding("UTF-8"); + LSSerializer serializer = domImplLS.createLSSerializer(); + serializer.write(doc, output); + + log.trace(writer.toString()); + } + + return doc; + + } + + /** + * Creates an LSInput from the given reference URI. + * + * @param reference + * the reference URL + * + * @return an LSInput from the given reference URI + * + * @throws IOException + * if dereferencing the given reference fails + */ + private LSInput createLSInput(String reference) throws IOException { + + URLDereferencer urlDereferencer = URLDereferencer.getInstance(); + StreamData streamData = urlDereferencer.dereference(reference, ctx.getDereferencerContext()); + + String contentType = streamData.getContentType(); + String charset = HttpUtil.getCharset(contentType, true); + InputStreamReader streamReader; + try { + streamReader = new InputStreamReader(streamData.getStream(), charset); + } catch (UnsupportedEncodingException e) { + log.info("Charset " + charset + " not supported. Using default."); + streamReader = new InputStreamReader(streamData.getStream()); + } + + LSInput input = domImplLS.createLSInput(); + input = domImplLS.createLSInput(); + input.setCharacterStream(streamReader); + + return input; + + } + + /** + * Creates an LSInput from the given content bytes. + * + * @param content + * the content bytes + * + * @return an LSInput from the givne content bytes + */ + private LSInput createLSInput(byte[] content) { + + ByteArrayInputStream inputStream = new ByteArrayInputStream(content); + LSInput input = domImplLS.createLSInput(); + input.setByteStream(inputStream); + + return input; + + } + + /** + * Creates an LSInput from the given XML content. + * + * @param content + * the XML content + * @return an LSInput from the given XML content + * + * @throws XMLStreamException + * if reading the XMLStream from the given XML content fails + */ + private LSInput createLSInput(XMLContentType content) throws XMLStreamException { + + ByteArrayOutputStream redirectedStream = content.getRedirectedStream(); + if (redirectedStream != null) { + LSInput input = domImplLS.createLSInput(); + input.setByteStream(new ByteArrayInputStream(redirectedStream.toByteArray())); + return input; + } else { + return null; + } + + } + + /** + * Represents an xsd:Id-attribute value. + * + * @author mcentner + */ + private class IdAttribute { + + private Element element; + + private String namespaceURI; + + private String localName; + + } + + /** + * An implementation of the LSResourceResolver that uses a list of supplements + * to resolve resources. + * + * @author mcentner + */ + private class LSResourceResolverAdapter implements LSResourceResolver { + + List supplements; + + private LSResourceResolverAdapter( + List supplements) { + this.supplements = supplements; + } + + private Exception error; + + /** + * @return the error + */ + public Exception getError() { + return error; + } + + @Override + public LSInput resolveResource(String type, String namespaceURI, + String publicId, String systemId, String baseURI) { + + if (log.isTraceEnabled()) { + log.trace("Resolve resource :" + + "\n type=" + type + + "\n namespaceURI=" + namespaceURI + + "\n publicId=" + publicId + + "\n systemId=" + systemId + + "\n baseURI=" + baseURI); + } + + if (systemId != null) { + + log.debug("Resolve resource '" + systemId + "'."); + + for (DataObjectAssociationType supplement : supplements) { + + Base64XMLLocRefReqRefContentType content = supplement.getContent(); + if (content != null) { + + String reference = content.getReference(); + if (systemId.equals(reference)) { + + try { + if (content.getLocRefContent() != null) { + log.trace("Resolved resource '" + reference + "' to supplement with LocRefContent."); + return createLSInput(content.getLocRefContent()); + } else if (content.getBase64Content() != null) { + log.trace("Resolved resource '" + reference + "' to supplement with Base64Content."); + return createLSInput(content.getBase64Content()); + } else if (content.getXMLContent() != null) { + log.trace("Resolved resource '" + reference + "' to supplement with XMLContent."); + return createLSInput((XMLContentType) content.getXMLContent()); + } else { + return null; + } + } catch (IOException e) { + log.info("Failed to resolve resource '" + systemId + "' to supplement.", e); + error = e; + return null; + } catch (XMLStreamException e) { + log.info("Failed to resolve resource '" + systemId + "' to supplement.", e); + error = e; + return null; + } + + } + + } + + } + + log.info("Failed to resolve resource '" + systemId + "' to supplement. No such supplement."); + + } + + return null; + + } + + + } + +} diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/accesscontrol/config/AccessControl.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/accesscontrol/config/AccessControl.xsd new file mode 100644 index 00000000..9031ea78 --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/accesscontrol/config/AccessControl.xsd @@ -0,0 +1,128 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + -- cgit v1.2.3 From 76bb812a3254be530e403f8db8c01323a31b30c1 Mon Sep 17 00:00:00 2001 From: wbauer Date: Thu, 11 Sep 2008 13:03:44 +0000 Subject: git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@33 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKUOnline/pom.xml | 317 ++++++++------- .../at/gv/egiz/bku/online/conf/Configurator.java | 21 +- .../egiz/bku/online/conf/SpringConfigurator.java | 17 + .../gv/egiz/bku/online/webapp/ResultServlet.java | 246 ++++++------ .../egiz/bku/online/webapp/SpringBKUServlet.java | 6 +- .../gv/egiz/bku/online/conf/defaultConf.properties | 2 + BKUOnline/src/main/resources/log4j.properties | 21 +- .../src/main/webapp/WEB-INF/applicationContext.xml | 4 +- BKUOnline/src/main/webapp/appletPage.jsp | 8 +- .../main/java/at/gv/egiz/bku/binding/DataUrl.java | 22 +- .../at/gv/egiz/bku/binding/DataUrlConnection.java | 6 +- .../gv/egiz/bku/binding/DataUrlConnectionImpl.java | 444 +++++++++++---------- .../gv/egiz/bku/binding/DataUrlConnectionSPI.java | 9 +- .../egiz/bku/slcommands/impl/ErrorResultImpl.java | 14 +- .../slexceptions/SLExceptionMessages.properties | 165 ++++---- .../slexceptions/SLExceptionMessages_en.properties | 97 +++++ .../gv/egiz/bku/binding/TestDataUrlConnection.java | 9 +- 17 files changed, 812 insertions(+), 596 deletions(-) create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties (limited to 'bkucommon/src/main/resources') diff --git a/BKUOnline/pom.xml b/BKUOnline/pom.xml index a0e45cf6..d31367a8 100644 --- a/BKUOnline/pom.xml +++ b/BKUOnline/pom.xml @@ -1,141 +1,180 @@ - - - bku - at.gv.egiz - 1.0-SNAPSHOT - - 4.0.0 - at.gv.egiz - BKUOnline - war - BKU Online - 1.0-SNAPSHOT - - - at.gv.egiz - bkucommon - 1.0-SNAPSHOT - - - commons-logging - commons-logging - - - org.springframework - spring-core - 2.5.5 - - - javax.servlet - servlet-api - 2.5 - provided - - - org.springframework - spring-web - 2.5.5 - - - at.gv.egiz - STALService - 1.0-SNAPSHOT - compile - - - - - com.sun.xml.ws - - jaxws-rt - 2.1.4 - - - - - - Tomcat60 - - - - - maven-dependency-plugin - - - copyapplet - - copy - - - - - at.gv.egiz - BKUApplet - 1.0-SNAPSHOT - - - commons-logging - commons-logging - - - iaik - iaik_jce_me4se - - - ${project.build.directory}/${project.build.finalName}/applet - - - - - - - + + + bku + at.gv.egiz + 1.0-SNAPSHOT + + 4.0.0 + at.gv.egiz + BKUOnline + war + BKU Online + 1.0-SNAPSHOT + + + + tlc + TLC Repository + http://commons.ucalgary.ca/pub/m2 + + + + + + at.gv.egiz + bkucommon + 1.0-SNAPSHOT + + + at.gv.egiz + BKUViewer + 1.0-SNAPSHOT + + + commons-logging + commons-logging + + + org.springframework + spring-core + 2.5.5 + + + javax.servlet + servlet-api + 2.5 + provided + + + org.springframework + spring-web + 2.5.5 + + + at.gv.egiz + STALService + 1.0-SNAPSHOT + compile + + + + + com.sun.xml.ws + + jaxws-rt + 2.1.4 + + + + + + Tomcat60 + + + scm:svn:svn://svn.egovlabs.gv.at/svnroot/mocca/trunk/BKUOnline + scm:svn:svn://svn.egovlabs.gv.at/svnroot/mocca/trunk/BKUOnline + scm:svn:svn://svn.egovlabs.gv.at/svnroot/mocca/trunk/BKUOnline + + + + + maven-dependency-plugin + + + copyapplet + + copy + + + + + at.gv.egiz + BKUApplet + 1.0-SNAPSHOT + + + commons-logging + commons-logging + + + iaik + iaik_jce_me4se + + + ${project.build.directory}/${project.build.finalName}/applet + + + + + + + maven-war-plugin + 2.0.2 + + + + true + + + + + + ${project.version}-r${buildNumber} + + + + + + + org.codehaus.mojo + maven-buildnumber-plugin + 0.9.6 + + + validate + + create + + + + + false + false + + + + diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/Configurator.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/Configurator.java index de577139..c09abcc1 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/Configurator.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/Configurator.java @@ -17,8 +17,10 @@ package at.gv.egiz.bku.online.conf; import iaik.security.ecc.provider.ECCProvider; +import iaik.security.provider.IAIK; import iaik.xml.crypto.XSecProvider; +import java.io.IOException; import java.net.HttpURLConnection; import java.security.Provider; import java.security.Security; @@ -29,22 +31,30 @@ import javax.net.ssl.HttpsURLConnection; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.bku.binding.DataUrl; +import at.gv.egiz.bku.binding.DataUrlConnection; +import at.gv.egiz.bku.slcommands.impl.xsect.DataObject; import at.gv.egiz.bku.slcommands.impl.xsect.STALProvider; -import iaik.security.provider.IAIK; /** * * TODO currently only the code to get started. */ -public class Configurator { +public abstract class Configurator { private Log log = LogFactory.getLog(Configurator.class); + + private static Configurator instance = new SpringConfigurator(); protected Properties properties; - public Configurator() { + protected Configurator() { } + public static Configurator getInstance() { + return instance; + } + protected void configUrlConnections() { HttpsURLConnection.setFollowRedirects(false); HttpURLConnection.setFollowRedirects(false); @@ -65,9 +75,14 @@ public class Configurator { log.debug(sb.toString()); } + protected void configViewer() { + DataObject.enableHashDataInputValidation(Boolean.parseBoolean(properties.getProperty("ValidateHashDataInputs"))); + } + public void configure() { configureProviders(); configUrlConnections(); + configViewer(); } public void setConfiguration(Properties props) { diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java index 545a69c9..9fe91708 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java @@ -49,6 +49,8 @@ import org.springframework.context.ResourceLoaderAware; import org.springframework.core.io.Resource; import org.springframework.core.io.ResourceLoader; +import at.gv.egiz.bku.binding.DataUrl; +import at.gv.egiz.bku.binding.DataUrlConnection; import at.gv.egiz.bku.slexceptions.SLRuntimeException; public class SpringConfigurator extends Configurator implements @@ -71,9 +73,24 @@ public class SpringConfigurator extends Configurator implements } } + public void configureVersion() { + Properties p = new Properties(); + try { + p.load(resourceLoader.getResource("META-INF/MANIFEST.MF").getInputStream()); + String version = p.getProperty("Implementation-Build"); + properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, "citizen-card-environment/1.2 MOCCA "+version); + DataUrl.setConfiguration(properties); + log.debug("Setting user agent to: "+properties.getProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY)); + } catch (IOException e) { + log.error(e); + } + } + + public void configure() { super.configure(); configureSSL(); + configureVersion(); } private Set getCACerts() throws IOException, diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java index bc3edf18..28c714c1 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/ResultServlet.java @@ -1,121 +1,129 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package at.gv.egiz.bku.online.webapp; - -import java.io.IOException; -import java.util.Iterator; - -import javax.servlet.ServletConfig; -import javax.servlet.ServletException; -import javax.servlet.http.HttpServletRequest; -import javax.servlet.http.HttpServletResponse; -import javax.servlet.http.HttpSession; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.binding.HTTPBindingProcessor; -import at.gv.egiz.bku.binding.IdFactory; - -/** - * Delivers the result to the browser - * - */ -public class ResultServlet extends SpringBKUServlet { - - private final static Log log = LogFactory.getLog(ResultServlet.class); - - private String encoding = "UTF-8"; - private String expiredPage = "./expiredError.jsp"; - - public ResultServlet() { - } - - private void myInit() { - String enc = getServletContext().getInitParameter("responseEncoding"); - if (enc != null) { - log.debug("Init default encoding to: "+enc); - encoding = enc; - } - String expP = getServletConfig().getInitParameter("expiredPage"); - if (expP != null) { - log.debug("Init expired page to: "+expP); - expiredPage = expP; - } - } - - @Override - public void init() throws ServletException { - super.init(); - myInit(); - } - - @Override - public void init(ServletConfig config) throws ServletException { - super.init(config); - myInit(); - } - - - - protected void doPost(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, IOException { - doGet(req, resp); - } - - protected void doGet(HttpServletRequest req, HttpServletResponse resp) - throws ServletException, java.io.IOException { - - HttpSession session = req.getSession(false); - if (session == null) { - resp.sendRedirect(expiredPage); - return; - } - String sessionId = session.getId(); - if (sessionId == null) { - resp.sendRedirect(expiredPage); - return; - } - log.debug("Got a result request for session: " + sessionId); - HTTPBindingProcessor bp = (HTTPBindingProcessor) getBindingProcessorManager().getBindingProcessor( - IdFactory.getInstance().createId(sessionId)); - if (bp == null) { - session.invalidate(); - resp.sendRedirect(expiredPage); - return; - } - - if (bp.getRedirectURL() != null) { - resp.sendRedirect(bp.getRedirectURL()); - return; - } - resp.setStatus(bp.getResponseCode()); - resp.setHeader("Cache-Control","no-store"); //HTTP 1.1 - resp.setHeader("Pragma","no-cache"); //HTTP 1.0 - resp.setDateHeader ("Expires", 0); - for (Iterator it = bp.getResponseHeaders().keySet() - .iterator(); it.hasNext();) { - String header = it.next(); - resp.setHeader(header, bp.getResponseHeaders().get(header)); - } - resp.setContentType(bp.getResultContentType()); - resp.setCharacterEncoding(encoding); - bp.writeResultTo(resp.getOutputStream(), encoding); + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.online.webapp; + +import java.io.IOException; +import java.util.Iterator; + +import javax.servlet.ServletConfig; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.HttpSession; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.binding.HTTPBindingProcessor; +import at.gv.egiz.bku.binding.HttpUtil; +import at.gv.egiz.bku.binding.IdFactory; +import at.gv.egiz.bku.online.conf.Configurator; + +/** + * Delivers the result to the browser + * + */ +public class ResultServlet extends SpringBKUServlet { + + private final static Log log = LogFactory.getLog(ResultServlet.class); + public final static String USER_AGENT_PROPERTY_KEY = "UserAgent"; + + private String encoding = "UTF-8"; + private String expiredPage = "./expiredError.jsp"; + + public ResultServlet() { + } + + private void myInit() { + String enc = getServletContext().getInitParameter("responseEncoding"); + if (enc != null) { + log.debug("Init default encoding to: " + enc); + encoding = enc; + } + String expP = getServletConfig().getInitParameter("expiredPage"); + if (expP != null) { + log.debug("Init expired page to: " + expP); + expiredPage = expP; + } + } + + @Override + public void init() throws ServletException { + super.init(); + myInit(); + } + + @Override + public void init(ServletConfig config) throws ServletException { + super.init(config); + myInit(); + } + + protected void doPost(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, IOException { + doGet(req, resp); + } + + protected void doGet(HttpServletRequest req, HttpServletResponse resp) + throws ServletException, java.io.IOException { + + HttpSession session = req.getSession(false); + if (session == null) { + resp.sendRedirect(expiredPage); + return; + } + String sessionId = session.getId(); + if (sessionId == null) { + resp.sendRedirect(expiredPage); + return; + } + log.debug("Got a result request for session: " + sessionId); + HTTPBindingProcessor bp = (HTTPBindingProcessor) getBindingProcessorManager() + .getBindingProcessor(IdFactory.getInstance().createId(sessionId)); + if (bp == null) { + session.invalidate(); + resp.sendRedirect(expiredPage); + return; + } + + if (bp.getRedirectURL() != null) { + resp.sendRedirect(bp.getRedirectURL()); + return; + } + resp.setStatus(bp.getResponseCode()); + resp.setHeader("Cache-Control", "no-store"); // HTTP 1.1 + resp.setHeader("Pragma", "no-cache"); // HTTP 1.0 + resp.setDateHeader("Expires", 0); + if (Configurator.getInstance().getProperty(USER_AGENT_PROPERTY_KEY) != null) { + resp.setHeader(HttpUtil.HTTP_HEADER_USER_AGENT, Configurator.getInstance().getProperty( + USER_AGENT_PROPERTY_KEY)); + } else { + resp.setHeader(HttpUtil.HTTP_HEADER_USER_AGENT, + "citizen-card-environment/1.2 MOCCA Unknown"); + } + for (Iterator it = bp.getResponseHeaders().keySet().iterator(); it + .hasNext();) { + String header = it.next(); + resp.setHeader(header, bp.getResponseHeaders().get(header)); + } + resp.setContentType(bp.getResultContentType()); + resp.setCharacterEncoding(encoding); + bp.writeResultTo(resp.getOutputStream(), encoding); session.invalidate(); - getBindingProcessorManager().removeBindingProcessor(bp.getId()); - } -} + getBindingProcessorManager().removeBindingProcessor(bp.getId()); + } +} diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java index 6ee537b1..ec062e42 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/webapp/SpringBKUServlet.java @@ -19,13 +19,13 @@ package at.gv.egiz.bku.online.webapp; import javax.servlet.http.HttpServlet; import at.gv.egiz.bku.binding.BindingProcessorManager; +import at.gv.egiz.bku.online.conf.Configurator; public abstract class SpringBKUServlet extends HttpServlet { - public final static String BEAN_NAME="bindingProcessorManager"; - + public final static String BEAN_NAME="bindingProcessorManager"; + protected BindingProcessorManager getBindingProcessorManager() { return (BindingProcessorManager) getServletContext().getAttribute(BEAN_NAME); } - } diff --git a/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties b/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties index 108f8624..cdc2bfad 100644 --- a/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties +++ b/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties @@ -39,3 +39,5 @@ SSL.sslProtocol=TLS # ------------ END SSL Config -------------------- +ValidateHashDataInputs=true + diff --git a/BKUOnline/src/main/resources/log4j.properties b/BKUOnline/src/main/resources/log4j.properties index ed14b424..58f09511 100644 --- a/BKUOnline/src/main/resources/log4j.properties +++ b/BKUOnline/src/main/resources/log4j.properties @@ -13,9 +13,8 @@ # See the License for the specific language governing permissions and # limitations under the License. -# loglever DEBUG, appender STDOUT -log4j.rootLogger=TRACE, STDOUT -#log4j.logger.at.gv.egiz.slbinding.RedirectEventFilter=DEBUG, STDOUT + +log4j.rootLogger=TRACE, STDOUT, file # STDOUT appender log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender @@ -24,11 +23,11 @@ log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout #log4j.appender.STDOUT.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n log4j.appender.STDOUT.layout.ConversionPattern=%-5p | %t | %c %x - %m%n -### FILE appender -#log4j.appender.file=org.apache.log4j.RollingFileAppender -#log4j.appender.file.maxFileSize=100KB -#log4j.appender.file.maxBackupIndex=9 -#log4j.appender.file.File=egovbus_ca.log -#log4j.appender.file.threshold=info -#log4j.appender.file.layout=org.apache.log4j.PatternLayout -#log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p %c{1}:%L - %m%n \ No newline at end of file +# FILE appender +log4j.appender.file=org.apache.log4j.RollingFileAppender +log4j.appender.file.maxFileSize=500KB +log4j.appender.file.maxBackupIndex=9 +log4j.appender.file.File=${catalina.home}/logs/bkuonline.log +log4j.appender.file.threshold=trace +log4j.appender.file.layout=org.apache.log4j.PatternLayout +log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %5p | %t | %c{1}:%L - %m%n \ No newline at end of file diff --git a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml index f87d09f5..04b07ba4 100644 --- a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml @@ -45,8 +45,8 @@ - + diff --git a/BKUOnline/src/main/webapp/appletPage.jsp b/BKUOnline/src/main/webapp/appletPage.jsp index 684a8dca..fdd7072f 100644 --- a/BKUOnline/src/main/webapp/appletPage.jsp +++ b/BKUOnline/src/main/webapp/appletPage.jsp @@ -25,15 +25,15 @@ diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java index 8eaeacbd..a8477ece 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java @@ -16,13 +16,14 @@ */ package at.gv.egiz.bku.binding; -import java.net.MalformedURLException; -import java.net.URL; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.Properties; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slexceptions.SLRuntimeException; /** * Used to handle DataUrl connections as specified in the CCE's HTTP protocol binding. @@ -30,7 +31,8 @@ import at.gv.egiz.bku.slexceptions.SLRuntimeException; */ public class DataUrl { private static DataUrlConnectionSPI defaultDataUrlConnection = new DataUrlConnectionImpl(); - private static Log log = LogFactory.getLog(DataUrl.class); + private static Log log = LogFactory.getLog(DataUrl.class); + private static Properties configuration; private URL url; @@ -58,5 +60,9 @@ public class DataUrl { log.error(e); throw new SLRuntimeException("Cannot instantiate a dataurlconnection:",e); } + } + + public static void setConfiguration(Properties props) { + configuration = props; } } \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java index 6d654639..c6ffa32a 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java @@ -34,14 +34,16 @@ import at.gv.egiz.bku.slcommands.SLResult; */ public interface DataUrlConnection { - public static final String DEFAULT_USERAGENT = "citizen-card-environment/1.2 BKU2 1.0"; + public static final String DEFAULT_USERAGENT = "citizen-card-environment/1.2 MOCCA Unknown"; public static final String FORMPARAM_RESPONSETYPE = "ResponseType"; public static final String DEFAULT_RESPONSETYPE = "HTTP-Security-Layer-RESPONSE"; public static final String FORMPARAM_XMLRESPONSE = "XMLResponse"; public static final String FORMPARAM_BINARYRESPONSE = "BinaryResponse"; public static final String XML_RESPONSE_ENCODING = "UTF-8"; - + + public final static String USER_AGENT_PROPERTY_KEY="UserAgent"; + public String getProtocol(); public URL getUrl(); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java index 9f5d70cb..bb0314b5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java @@ -1,221 +1,235 @@ /* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package at.gv.egiz.bku.binding; - -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.OutputStream; -import java.net.HttpURLConnection; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Set; - -import javax.net.ssl.HttpsURLConnection; - -import org.apache.commons.httpclient.methods.multipart.FilePart; -import org.apache.commons.httpclient.methods.multipart.Part; -import org.apache.commons.httpclient.methods.multipart.StringPart; - -import at.gv.egiz.bku.binding.multipart.InputStreamPartSource; -import at.gv.egiz.bku.binding.multipart.SLResultPart; -import at.gv.egiz.bku.slcommands.SLResult; -import at.gv.egiz.bku.slcommands.SLResult.SLResultType; -import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.bku.utils.StreamUtil; -import at.gv.egiz.bku.utils.binding.Protocol; - -/** - * not thread-safe thus newInsance always returns a new object - * - */ -public class DataUrlConnectionImpl implements DataUrlConnectionSPI { - - public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP, - Protocol.HTTPS }; - protected X509Certificate serverCertificate; - protected Protocol protocol; - protected URL url; - private HttpURLConnection connection; - protected Map requestHttpHeaders; - protected ArrayList formParams; - protected String boundary; - - protected DataUrlResponse result; - - public String getProtocol() { - if (protocol == null) { - return null; - } - return protocol.toString(); - } - - /** - * opens a connection sets the headers gets the server certificate - * - * @throws java.net.SocketTimeoutException - * @throws java.io.IOException - * @pre url != null - * @pre httpHeaders != null - */ - public void connect() throws SocketTimeoutException, IOException { - connection = (HttpURLConnection) url.openConnection(); - + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.binding; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import javax.net.ssl.HttpsURLConnection; + +import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.Part; +import org.apache.commons.httpclient.methods.multipart.StringPart; + +import at.gv.egiz.bku.binding.multipart.InputStreamPartSource; +import at.gv.egiz.bku.binding.multipart.SLResultPart; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.SLResult.SLResultType; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.binding.Protocol; + +/** + * not thread-safe thus newInsance always returns a new object + * + */ +public class DataUrlConnectionImpl implements DataUrlConnectionSPI { + + public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP, + Protocol.HTTPS }; + protected X509Certificate serverCertificate; + protected Protocol protocol; + protected URL url; + private HttpURLConnection connection; + protected Map requestHttpHeaders; + protected ArrayList formParams; + protected String boundary; + protected Properties config = null; + + protected DataUrlResponse result; + + public String getProtocol() { + if (protocol == null) { + return null; + } + return protocol.toString(); + } + + /** + * opens a connection sets the headers gets the server certificate + * + * @throws java.net.SocketTimeoutException + * @throws java.io.IOException + * @pre url != null + * @pre httpHeaders != null + */ + public void connect() throws SocketTimeoutException, IOException { + connection = (HttpURLConnection) url.openConnection(); + // FIXXME move this to config. - HttpURLConnection.setFollowRedirects(false); - - - connection.setDoOutput(true); - Set headers = requestHttpHeaders.keySet(); - Iterator headerIt = headers.iterator(); - while (headerIt.hasNext()) { - String name = headerIt.next(); - connection.setRequestProperty(name, requestHttpHeaders.get(name)); - } - connection.connect(); - if (connection instanceof HttpsURLConnection) { - HttpsURLConnection ssl = (HttpsURLConnection) connection; - X509Certificate[] certs = (X509Certificate[]) ssl.getServerCertificates(); - if ((certs != null) && (certs.length >= 1)) { - serverCertificate = certs[0]; - } - } - } - - public X509Certificate getServerCertificate() { - return serverCertificate; - } - - public void setHTTPHeader(String name, String value) { - if (name != null && value != null) { - requestHttpHeaders.put(name, value); - } - } - - public void setHTTPFormParameter(String name, InputStream data, - String contentType, String charSet, String transferEncoding) { - InputStreamPartSource source = new InputStreamPartSource(null, data); - FilePart formParam = new FilePart(name, source, contentType, charSet); - if (transferEncoding != null) { - formParam.setTransferEncoding(transferEncoding); - } else { - formParam.setTransferEncoding(null); - } - formParams.add(formParam); - } - - /** - * send all formParameters - * - * @throws java.io.IOException - */ - public void transmit(SLResult slResult) throws IOException { - SLResultPart slResultPart = new SLResultPart(slResult, - XML_RESPONSE_ENCODING); - if (slResult.getResultType() == SLResultType.XML) { - slResultPart.setTransferEncoding(null); - slResultPart.setContentType(slResult.getMimeType()); - slResultPart.setCharSet(XML_RESPONSE_ENCODING); - } else { - slResultPart.setTransferEncoding(null); - slResultPart.setContentType(slResult.getMimeType()); - } - formParams.add(slResultPart); - - OutputStream os = connection.getOutputStream(); - - Part[] parts = new Part[formParams.size()]; - Part.sendParts(os, formParams.toArray(parts), boundary.getBytes()); - os.close(); + HttpURLConnection.setFollowRedirects(false); + + connection.setDoOutput(true); + Set headers = requestHttpHeaders.keySet(); + Iterator headerIt = headers.iterator(); + while (headerIt.hasNext()) { + String name = headerIt.next(); + connection.setRequestProperty(name, requestHttpHeaders.get(name)); + } + connection.connect(); + if (connection instanceof HttpsURLConnection) { + HttpsURLConnection ssl = (HttpsURLConnection) connection; + X509Certificate[] certs = (X509Certificate[]) ssl.getServerCertificates(); + if ((certs != null) && (certs.length >= 1)) { + serverCertificate = certs[0]; + } + } + } + + public X509Certificate getServerCertificate() { + return serverCertificate; + } + + public void setHTTPHeader(String name, String value) { + if (name != null && value != null) { + requestHttpHeaders.put(name, value); + } + } + + public void setHTTPFormParameter(String name, InputStream data, + String contentType, String charSet, String transferEncoding) { + InputStreamPartSource source = new InputStreamPartSource(null, data); + FilePart formParam = new FilePart(name, source, contentType, charSet); + if (transferEncoding != null) { + formParam.setTransferEncoding(transferEncoding); + } else { + formParam.setTransferEncoding(null); + } + formParams.add(formParam); + } + + /** + * send all formParameters + * + * @throws java.io.IOException + */ + public void transmit(SLResult slResult) throws IOException { + SLResultPart slResultPart = new SLResultPart(slResult, + XML_RESPONSE_ENCODING); + if (slResult.getResultType() == SLResultType.XML) { + slResultPart.setTransferEncoding(null); + slResultPart.setContentType(slResult.getMimeType()); + slResultPart.setCharSet(XML_RESPONSE_ENCODING); + } else { + slResultPart.setTransferEncoding(null); + slResultPart.setContentType(slResult.getMimeType()); + } + formParams.add(slResultPart); + + OutputStream os = connection.getOutputStream(); + + Part[] parts = new Part[formParams.size()]; + Part.sendParts(os, formParams.toArray(parts), boundary.getBytes()); + os.close(); // MultipartRequestEntity PostMethod - result = new DataUrlResponse(url.toString(), connection.getResponseCode(), - connection.getInputStream()); - - Map responseHttpHeaders = new HashMap(); - Map> httpHeaders = connection.getHeaderFields(); - for (Iterator keyIt = httpHeaders.keySet().iterator(); keyIt - .hasNext();) { - String key = keyIt.next(); - StringBuffer value = new StringBuffer(); - for (String val : httpHeaders.get(key)) { - value.append(val); - value.append(HttpUtil.SEPERATOR[0]); - } - String valString = value.substring(0, value.length() - 1); - if ((key != null)&&(value.length() > 0)) { - responseHttpHeaders.put(key, valString); - } - } - result.setResponseHttpHeaders(responseHttpHeaders); - } - - @Override - public DataUrlResponse getResponse() throws IOException { - return result; - } - - /** - * inits protocol, url, httpHeaders, formParams - * - * @param url - * must not be null - */ - @Override - public void init(URL url) { - - for (int i = 0; i < SUPPORTED_PROTOCOLS.length; i++) { - if (SUPPORTED_PROTOCOLS[i].toString().equalsIgnoreCase(url.getProtocol())) { - protocol = SUPPORTED_PROTOCOLS[i]; - break; - } - } - if (protocol == null) { - throw new SLRuntimeException("Protocol " + url.getProtocol() - + " not supported for data url"); - } - this.url = url; - boundary = "--" + IdFactory.getInstance().createId().toString(); - requestHttpHeaders = new HashMap(); - requestHttpHeaders.put(HttpUtil.HTTP_HEADER_USER_AGENT, DEFAULT_USERAGENT); - requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, - HttpUtil.MULTIPART_FOTMDATA + HttpUtil.SEPERATOR[0] - + HttpUtil.MULTIPART_FOTMDATA_BOUNDARY + "=" + boundary); - - formParams = new ArrayList(); - StringPart responseType = new StringPart(FORMPARAM_RESPONSETYPE, - DEFAULT_RESPONSETYPE); - responseType.setCharSet("UTF-8"); - responseType.setTransferEncoding(null); - formParams.add(responseType); - } - - @Override - public DataUrlConnectionSPI newInstance() { - return new DataUrlConnectionImpl(); + result = new DataUrlResponse(url.toString(), connection.getResponseCode(), + connection.getInputStream()); + + Map responseHttpHeaders = new HashMap(); + Map> httpHeaders = connection.getHeaderFields(); + for (Iterator keyIt = httpHeaders.keySet().iterator(); keyIt + .hasNext();) { + String key = keyIt.next(); + StringBuffer value = new StringBuffer(); + for (String val : httpHeaders.get(key)) { + value.append(val); + value.append(HttpUtil.SEPERATOR[0]); + } + String valString = value.substring(0, value.length() - 1); + if ((key != null) && (value.length() > 0)) { + responseHttpHeaders.put(key, valString); + } + } + result.setResponseHttpHeaders(responseHttpHeaders); } - @Override - public URL getUrl() { - return url; - } + @Override + public DataUrlResponse getResponse() throws IOException { + return result; + } + + /** + * inits protocol, url, httpHeaders, formParams + * + * @param url + * must not be null + */ + @Override + public void init(URL url) { + + for (int i = 0; i < SUPPORTED_PROTOCOLS.length; i++) { + if (SUPPORTED_PROTOCOLS[i].toString().equalsIgnoreCase(url.getProtocol())) { + protocol = SUPPORTED_PROTOCOLS[i]; + break; + } + } + if (protocol == null) { + throw new SLRuntimeException("Protocol " + url.getProtocol() + + " not supported for data url"); + } + this.url = url; + boundary = "--" + IdFactory.getInstance().createId().toString(); + requestHttpHeaders = new HashMap(); + if ((config != null) + && (config.getProperty(USER_AGENT_PROPERTY_KEY) != null)) { + requestHttpHeaders.put(HttpUtil.HTTP_HEADER_USER_AGENT, config + .getProperty(USER_AGENT_PROPERTY_KEY)); + } else { + requestHttpHeaders + .put(HttpUtil.HTTP_HEADER_USER_AGENT, DEFAULT_USERAGENT); + + } + requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, + HttpUtil.MULTIPART_FOTMDATA + HttpUtil.SEPERATOR[0] + + HttpUtil.MULTIPART_FOTMDATA_BOUNDARY + "=" + boundary); + + formParams = new ArrayList(); + StringPart responseType = new StringPart(FORMPARAM_RESPONSETYPE, + DEFAULT_RESPONSETYPE); + responseType.setCharSet("UTF-8"); + responseType.setTransferEncoding(null); + formParams.add(responseType); + } + + @Override + public DataUrlConnectionSPI newInstance() { + DataUrlConnectionSPI uc = new DataUrlConnectionImpl(); + uc.setConfiguration(config); + return uc; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public void setConfiguration(Properties config) { + this.config = config; + } } \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionSPI.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionSPI.java index 9e5a66f8..80cc3a0b 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionSPI.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionSPI.java @@ -17,6 +17,7 @@ package at.gv.egiz.bku.binding; import java.net.URL; +import java.util.Properties; /** * Prototype of a DataurlconnectionSPI @@ -36,7 +37,13 @@ public interface DataUrlConnectionSPI extends DataUrlConnection { * Initializes the DataUrlConnection * @param url */ - public void init(URL url); + public void init(URL url); + + /** + * Sets configuration parameters for this connection + * @param config + */ + public void setConfiguration(Properties config); } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java index 555f83bd..fb624211 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java @@ -16,12 +16,14 @@ */ package at.gv.egiz.bku.slcommands.impl; -import at.buergerkarte.namespaces.securitylayer._1.ErrorResponseType; -import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; -import at.gv.egiz.bku.slcommands.ErrorResult; -import at.gv.egiz.bku.slexceptions.SLException; - -import javax.xml.transform.Result; +import java.util.Locale; + +import javax.xml.transform.Result; + +import at.buergerkarte.namespaces.securitylayer._1.ErrorResponseType; +import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.gv.egiz.bku.slcommands.ErrorResult; +import at.gv.egiz.bku.slexceptions.SLException; /** * This class implements the security layer result ErrorResponse. diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties index 8e0a09bc..cf52a4c3 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties @@ -13,85 +13,86 @@ # See the License for the specific language governing permissions and # limitations under the License. -test.noerror=This is a test error-message. No error occurred. - -ec1000=Unclassified error. -ec2000=Unclassified error in the transport binding. -ec2001=HTTP/HTTPS binding: DataURL cannot be resolved. -ec2002=HTTP/HTTPS binding: StylesheetURL cannot be resolved. -ec2003=HTTP/HTTPS binding: RedirectURL cannot be resolved. -ec2004=HTTP/HTTPS binding: XMLRequest parameter missing. -ec2005=HTTP/HTTPS binding: Unknown parameter encoding. -ec2006=HTTP/HTTPS binding: Incorrect parameter encoding. -ec2007=HTTP/HTTPS binding: DataURL server transmits error or unexpected response. -ec2008=HTTP/HTTPS binding: Error in stylesheet obtained from the StylesheetURL. -ec2009=HTTP/HTTPS binding: HTTP request to local CCE directed to unauthorised URL. -ec2010=HTTPS binding: Error while establishing the TLS connection. -ec3000=Unclassified error in the XML structure of the command request. -ec3001=XML structure of the command request is not well formed. -ec3002=XML structure of the command request does not comply with the Security Layer schema. -ec3003=XML structure of the command request contains an invalid combination of optional elements or attributes. -ec3004=XML structure contains an element or attribute whose syntax does not match the Security Layer specification. -ec3005=Protocol version of Security Layer not supported. -ec4000=Unclassified error while processing command. -ec4001=Unknown key box identifier. -ec4002=Unknown info box identifier. -ec4003=Date to be signed cannot be resolved. -ec4004=Supplementary object cannot be resolved. -ec4005=Date to be encrypted cannot be resolved. -ec4006=Algorithm (signature, encryption, digest, canonicalisation, transformation) not supported. -ec4007=Error while executing algorithm (signature, encryption, digest, canonicalisation, transformation). -ec4008=Error while parsing CMS message -ec4009=No matching decryption key. -ec4010=Info box command parameters do not match info box type. -ec4011=Command not implemented. -ec4100=XML document in which the signature is to be integrated cannot be resolved. -ec4101=XML document in which the signature is to be integrated cannot be parsed. -ec4102=Signature cannot be integrated in the existing XML document at the specified location. -ec4103=Signature certificate not contained in the CMS signature. -ec4104=Signed data not contained in the CMS signature or XML request. -ec4105=XML document containing the signature to be verified cannot be resolved. -ec4106=XML document containing the signature to be verified cannot be parsed. -ec4107=There is no XML signature at the specified location within the XML document. -ec4108=Encrypted date cannot be inserted in the existing XML document at the specified location. -ec4109=Existing XML document is required but missing. -ec4110=Existing XML document cannot be resolved. -ec4111=Existing XML document cannot be parsed. -ec4112=Encrypted data encryption keys cannot be inserted in the existing XML document at the specified location. -ec4113=Data to be decrypted not contained in either the CMS message or XML request. -ec4114=XML document to be decrypted cannot be resolved. -ec4115=XML document to be decrypted cannot be parsed. -ec4116=At least one specified encryption element cannot be found in the XML document to be decrypted. -ec4117=No encryption element for binary response. -ec4118=Date to be hashed cannot be resolved. -ec4119=Date for which the hash value is to be verified cannot be resolved. -ec4120=Selected info box identifier already allocated. -ec4121=Info box with specified identifier does not exist. -ec4122=Contents of the selected info box cannot be displayed as XML. -ec4123=Associative array: No entry for the specified key. -ec5000=Unclassified error in the viewer component. -ec5001=Display of data of the mime type specified in the command request not supported. -ec5002=Character encoding of the data to be displayed is invalid or not supported. -ec5003=Data to be displayed contains unsupported characters. -ec5004=Standard display format: HTML does not conform to specification. -ec5005=Standard display format: CSS does not conform to specification. -ec5006=Standard display format: Format of an embedded image does not conform to specification. -ec5007=Standard display format: Signature for embedded images missing or does not conform to specification. -ec6000=Unclassified cancelling by the citizen. -ec6001=Cancelled by the citizen via the user interface. -ec6002=Cancelled because of insufficient rights to execute command. - -# 3xxx -# - -ec3000.unclassified=Error in the XML structure of the command request. {0} -ec3002.invalid=XML structure of the command request does not comply with the Security Layer schema. {0} - -# 4xxx -# - -ec4000.infobox.invalid=The infobox '{0}' contains invalid content. -ec4000.idlink.transfomation.failed=Failed to transform CompressedIdentityLink with Stylesheet {0}. -ec4002.infobox.unknown=Unknown info box identifier {0}. -ec4003.not.resolved=Data to be signed cannot be resolved from URI={0}. -ec4011.notimplemented=Command {0} not implemented. +test.noerror=Das ist eine Test-Fehlermeldung. Es ist kein Fehler aufgetreten. + +ec1000=Unklassifizierter Fehler. +ec2000=Unklassifizierter Fehler in der Transportbindung. +ec2001=HTTP/HTTPS-Bindung: DataURL kann nicht aufgelöst werden. +ec2002=HTTP/HTTPS-Bindung: StylesheetURL kann nicht aufgelöst werden. +ec2003=HTTP/HTTPS-Bindung: RedirectURL kann nicht aufgelöst werden. +ec2004=HTTP/HTTPS-Bindung: Parameter XMLRequest fehlt. +ec2005=HTTP/HTTPS-Bindung: Unbekannte Kodierung der Parameter. +ec2006=HTTP/HTTPS-Bindung: Fehlerhafte Kodierung der Parameter. +ec2007=HTTP/HTTPS-Bindung: DataURL-Server sendet Fehler oder unerwartete Antwort. +ec2008=HTTP/HTTPS-Bindung: Fehler im Stylesheet, der von der StylesheetURL bezogen wurde. +ec2009=HTTP/HTTPS-Bindung: HTTP-Anfrage an lokale BKU wurde an unerlaubte URL gerichtet. +ec2010=HTTPS-Bindung: Fehler beim Aufbau der TLS-Verbindung. +ec3000=Unklassifizierter Fehler in der XML-Struktur der Befehlsanfrage. +ec3001=XML-Struktur der Befehlsanfrage ist nicht wohlgeformt. +ec3002=XML-Struktur der Befehlsanfrage entspricht nicht dem Schema des Security-Layers. +ec3003=XML-Struktur der Befehlsanfrage enthält eine unerlaubte Kombination aus optionalen Elementen oder Attributen. +ec3004=XML-Struktur enthält ein Element oder Attribut, dessen Syntax nicht der Spezifikation des Security-Layer entspricht. +ec3005=Protokollversion des Security-Layer wird nicht unterstützt. +ec4000=Unklassifizierter Fehler in der Befehlsabarbeitung. +ec4001=Unbekannter Keyboxbezeichner. +ec4002=Unbekannter Infoboxbezeichner. +ec4003=Zu signierendes Datum kann nicht aufgelöst werden. +ec4004=Ergänzungsobjekt kann nicht aufgelöst werden. +ec4005=Zu verschlüsselndes Datum kann nicht aufgelöst werden. +ec4006=Algorithmus (Signatur, Verschlüsselung, Digest, Kanonisierung, Transformation) wird nicht unterstützt. +ec4007=Fehler bei der Algorithmusausführung (Signatur, Verschlüsselung, Digest, Kanonisierung, Transformation). +ec4008=Fehler beim Parsen der CMS-Nachricht. +ec4009=Kein passender Entschlüsselungsschlüssel vorhanden. +ec4010=Parameter des Infobox-Befehls passen nicht zum Typ der Infobox. +ec4011=Befehl ist nicht implementiert. +ec4100=XML-Dokument, in das die Signatur integriert werden soll, kann nicht aufgelöst werden. +ec4101=XML-Dokument, in das die Signatur integriert werden soll, kann nicht geparst werden. +ec4102=Signatur kann nicht am spezifizierten Ort in das bestehende XML-Dokument integriert werden. +ec4103=Signatorzertifikat ist nicht in der CMS-Signatur enthalten. +ec4104=Signierte Daten sind weder in der CMS-Signatur noch im XML-Request enthalten. +ec4105=XML-Dokument, das die zu prüfende Signatur enthält, kann nicht aufgelöst werden. +ec4106=XML-Dokument, das die zu prüfende Signatur enthält, kann nicht geparst werden. +ec4107=Am spezifizierten Ort innerhalb des XML-Dokuments befindet sich keine XML-Signatur. +ec4108=Verschlüsseltes Datum kann nicht am spezifizierten Ort in das bestehende XML-Dokument eingefügt werden. +ec4109=Bestehendes XML-Dokument ist notwendig, aber nicht vorhanden. +ec4110=Bestehendes XML-Dokument kann nicht aufgelöst werden. +ec4111=Bestehendes XML-Dokument kann nicht geparst werden. +ec4112=Verschlüsselte Datenverschlüsselungsschlüssel können nicht am spezifizierten Ort in das bestehende XML-Dokument eingefügt werden. +ec4113=Zu entschlüsselnde Daten sind weder in der CMS-Nachricht noch im XML-Request enthalten. +ec4114=Zu entschlüsselndes XML-Dokument kann nicht aufgelöst werden. +ec4115=Zu entschlüsselndes XML-Dokument kann nicht geparst werden. +ec4116=Zumindest ein spezifiziertes Verschlüsselungselement kann nicht im zu entschlüsselnden XML-Dokument gefunden werden. +ec4117=Kein Verschlüsselungselement für Binärantwort vorhanden. +ec4118=Zu hashendes Datum kann nicht aufgelöst werden. +ec4119=Datum, für das der Hashwert zu prüfen ist, kann nicht aufgelöst werden. +ec4120=Gewählter Infoboxbezeichner bereits vergeben. +ec4121=Infobox mit spezifiziertem Bezeichner existiert nicht. +ec4122=Inhalt der ausgewählten Infobox kann nicht als XML dargestellt werden. +ec4123=Assoziatives Array: Zum spezifizierten Schlüssel existiert kein Eintrag. +ec5000=Unklassifizierter Fehler in der Anzeigekomponente. +ec5001=Anzeige von Daten des in der Befehlsanfrage angegebenen Mime-Types wird nicht unterstützt. +ec5002=Zeichenkodierung der anzuzeigenden Daten ist fehlerhaft oder wird nicht unterstützt. +ec5003=Anzuzeigende Daten enhalten nicht unterstützte Zeichen. +ec5004=Standardanzeigeformat: HTML ist nicht spezifikationskonform. +ec5005=Standardanzeigeformat: CSS ist nicht spezifikationskonform. +ec5006=Standardanzeigeformat: Format eines eingebundenen Bildes ist nicht spezifikationskonform. +ec5007=Standardanzeigeformat: Signatur über eingebundene Bilder fehlt oder ist nicht spezifikationskonform. +ec6000=Unklassifizierter Abbruch durch den Bürger. +ec6001=Abbruch durch den Bürger über die Benutzerschnittstelle. +ec6002=Abbruch auf Grund mangelnder Rechte zur Befehlsausführung. + +# 3xxx +# + +ec3000.unclassified=Unklassifizierter Fehler in der XML-Struktur der Befehlsanfrage. {0} +ec3002.invalid=XML-Struktur der Befehlsanfrage entspricht nicht dem Schema des Security-Layers. {0} + +# 4xxx +# + +ec4000.infobox.invalid=Die Infobox '{0}' enthält ungültige Daten. +ec4000.idlink.transfomation.failed=Die komprimierte Personenbindung konnte mit dem Stylesheet {0} nicht transformiert werden. +ec4002.infobox.unknown=Unbekannter Infoboxbezeichner {0}. +ec4003.not.resolved=Zu signierendes Datum kann nicht aufgelöst werden (URI={0}). +ec4011.notimplemented=Befehl {0} ist nicht implementiert. + diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties new file mode 100644 index 00000000..8e0a09bc --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties @@ -0,0 +1,97 @@ +# Copyright 2008 Federal Chancellery Austria and +# Graz University of Technology +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +test.noerror=This is a test error-message. No error occurred. + +ec1000=Unclassified error. +ec2000=Unclassified error in the transport binding. +ec2001=HTTP/HTTPS binding: DataURL cannot be resolved. +ec2002=HTTP/HTTPS binding: StylesheetURL cannot be resolved. +ec2003=HTTP/HTTPS binding: RedirectURL cannot be resolved. +ec2004=HTTP/HTTPS binding: XMLRequest parameter missing. +ec2005=HTTP/HTTPS binding: Unknown parameter encoding. +ec2006=HTTP/HTTPS binding: Incorrect parameter encoding. +ec2007=HTTP/HTTPS binding: DataURL server transmits error or unexpected response. +ec2008=HTTP/HTTPS binding: Error in stylesheet obtained from the StylesheetURL. +ec2009=HTTP/HTTPS binding: HTTP request to local CCE directed to unauthorised URL. +ec2010=HTTPS binding: Error while establishing the TLS connection. +ec3000=Unclassified error in the XML structure of the command request. +ec3001=XML structure of the command request is not well formed. +ec3002=XML structure of the command request does not comply with the Security Layer schema. +ec3003=XML structure of the command request contains an invalid combination of optional elements or attributes. +ec3004=XML structure contains an element or attribute whose syntax does not match the Security Layer specification. +ec3005=Protocol version of Security Layer not supported. +ec4000=Unclassified error while processing command. +ec4001=Unknown key box identifier. +ec4002=Unknown info box identifier. +ec4003=Date to be signed cannot be resolved. +ec4004=Supplementary object cannot be resolved. +ec4005=Date to be encrypted cannot be resolved. +ec4006=Algorithm (signature, encryption, digest, canonicalisation, transformation) not supported. +ec4007=Error while executing algorithm (signature, encryption, digest, canonicalisation, transformation). +ec4008=Error while parsing CMS message +ec4009=No matching decryption key. +ec4010=Info box command parameters do not match info box type. +ec4011=Command not implemented. +ec4100=XML document in which the signature is to be integrated cannot be resolved. +ec4101=XML document in which the signature is to be integrated cannot be parsed. +ec4102=Signature cannot be integrated in the existing XML document at the specified location. +ec4103=Signature certificate not contained in the CMS signature. +ec4104=Signed data not contained in the CMS signature or XML request. +ec4105=XML document containing the signature to be verified cannot be resolved. +ec4106=XML document containing the signature to be verified cannot be parsed. +ec4107=There is no XML signature at the specified location within the XML document. +ec4108=Encrypted date cannot be inserted in the existing XML document at the specified location. +ec4109=Existing XML document is required but missing. +ec4110=Existing XML document cannot be resolved. +ec4111=Existing XML document cannot be parsed. +ec4112=Encrypted data encryption keys cannot be inserted in the existing XML document at the specified location. +ec4113=Data to be decrypted not contained in either the CMS message or XML request. +ec4114=XML document to be decrypted cannot be resolved. +ec4115=XML document to be decrypted cannot be parsed. +ec4116=At least one specified encryption element cannot be found in the XML document to be decrypted. +ec4117=No encryption element for binary response. +ec4118=Date to be hashed cannot be resolved. +ec4119=Date for which the hash value is to be verified cannot be resolved. +ec4120=Selected info box identifier already allocated. +ec4121=Info box with specified identifier does not exist. +ec4122=Contents of the selected info box cannot be displayed as XML. +ec4123=Associative array: No entry for the specified key. +ec5000=Unclassified error in the viewer component. +ec5001=Display of data of the mime type specified in the command request not supported. +ec5002=Character encoding of the data to be displayed is invalid or not supported. +ec5003=Data to be displayed contains unsupported characters. +ec5004=Standard display format: HTML does not conform to specification. +ec5005=Standard display format: CSS does not conform to specification. +ec5006=Standard display format: Format of an embedded image does not conform to specification. +ec5007=Standard display format: Signature for embedded images missing or does not conform to specification. +ec6000=Unclassified cancelling by the citizen. +ec6001=Cancelled by the citizen via the user interface. +ec6002=Cancelled because of insufficient rights to execute command. + +# 3xxx +# + +ec3000.unclassified=Error in the XML structure of the command request. {0} +ec3002.invalid=XML structure of the command request does not comply with the Security Layer schema. {0} + +# 4xxx +# + +ec4000.infobox.invalid=The infobox '{0}' contains invalid content. +ec4000.idlink.transfomation.failed=Failed to transform CompressedIdentityLink with Stylesheet {0}. +ec4002.infobox.unknown=Unknown info box identifier {0}. +ec4003.not.resolved=Data to be signed cannot be resolved from URI={0}. +ec4011.notimplemented=Command {0} not implemented. diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/binding/TestDataUrlConnection.java b/bkucommon/src/test/java/at/gv/egiz/bku/binding/TestDataUrlConnection.java index 45e38674..8a607b80 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/binding/TestDataUrlConnection.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/binding/TestDataUrlConnection.java @@ -25,6 +25,7 @@ import java.security.cert.X509Certificate; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -124,5 +125,11 @@ public class TestDataUrlConnection implements DataUrlConnectionSPI { @Override public URL getUrl() { return url; - } + } + + @Override + public void setConfiguration(Properties config) { + // TODO Auto-generated method stub + + } } -- cgit v1.2.3 From 5702f241064f90106e8495f3cf23b6e6798d6501 Mon Sep 17 00:00:00 2001 From: wbauer Date: Wed, 1 Oct 2008 10:49:31 +0000 Subject: added project for local MOCCA git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@79 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKULocalApp/pom.xml | 93 ++++------- .../java/at/gv/egiz/bku/local/app/BKULauncher.java | 15 -- .../java/at/gv/egiz/bku/local/app/Container.java | 23 +-- BKULocalApp/src/main/resources/splash.png | Bin 0 -> 54978 bytes .../egiz/bku/online/conf/SpringConfigurator.java | 1 + .../service/impl/RequestBrokerSTALFactory.java | 2 +- .../egiz/stal/service/impl/STALRequestBroker.java | 2 +- .../stal/service/impl/STALRequestBrokerImpl.java | 2 +- .../gv/egiz/bku/online/conf/defaultConf.properties | 2 +- .../slexceptions/SLExceptionMessages.properties | 3 +- .../slexceptions/SLExceptionMessages_de.properties | 3 +- .../slexceptions/SLExceptionMessages_en.properties | 1 + utils/pom.xml | 181 +++++++++------------ 13 files changed, 119 insertions(+), 209 deletions(-) create mode 100644 BKULocalApp/src/main/resources/splash.png (limited to 'bkucommon/src/main/resources') diff --git a/BKULocalApp/pom.xml b/BKULocalApp/pom.xml index e2d17d7c..9ad6f50b 100644 --- a/BKULocalApp/pom.xml +++ b/BKULocalApp/pom.xml @@ -28,76 +28,41 @@ + + org.apache.maven.plugins + maven-jar-plugin + + + + true + at.gv.egiz.bku.local.app.BKULauncher + + + + - maven-dependency-plugin - - - - copywar - - copy - - - - - at.gv.egiz - BKULocal - 1.0-SNAPSHOT - war - - - - ${project.build.directory}/classes - - - - - unpack-dependencies - - unpack-dependencies - - - javax/xml/crypto/**, demo/**, - junit/**, w3/**, org/etsi/**, META-INF/** - ${project.build.directory}/classes - true - true - - - - + maven-dependency-plugin + + + copy-dependencies + package + + copy-dependencies + + + ${project.build.directory} + false + false + true + + + + - - maven-jar-plugin - - - - sign - - - - - - false - false - - false - true - - - test-applet signer - ./keystore.ks - storepass - keypass - true - - - - commons-logging commons-logging diff --git a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/BKULauncher.java b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/BKULauncher.java index 091843e1..9a953f9e 100644 --- a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/BKULauncher.java +++ b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/BKULauncher.java @@ -168,20 +168,6 @@ public class BKULauncher implements BKUControllerInterface { } } - public void jwsHack() { - InputStream is = getClass().getClassLoader().getResourceAsStream( - "BKULocal-1.0-SNAPSHOT.war"); - File f = new File(System.getProperty("user.home") + "/.mocca/war"); - f.mkdirs(); - try { - OutputStream os = new FileOutputStream(new File(f, "mocca.war")); - StreamUtil.copyStream(is, os); - os.close(); - } catch (Exception e) { - log.error(e); - } - } - /** * @param args */ @@ -189,7 +175,6 @@ public class BKULauncher implements BKUControllerInterface { try { BKULauncher launcher = new BKULauncher(); - //launcher.jwsHack(); launcher.checkConfig(args); launcher.startUpServer(); launcher.initTrayIcon(); diff --git a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java index 690639f4..a8a6431a 100644 --- a/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java +++ b/BKULocalApp/src/main/java/at/gv/egiz/bku/local/app/Container.java @@ -2,6 +2,8 @@ package at.gv.egiz.bku.local.app; import java.io.File; import java.io.IOException; +import java.net.URL; +import java.net.URLClassLoader; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -12,7 +14,6 @@ import org.mortbay.jetty.handler.DefaultHandler; import org.mortbay.jetty.handler.HandlerCollection; import org.mortbay.jetty.nio.SelectChannelConnector; import org.mortbay.jetty.security.SslSocketConnector; -import org.mortbay.jetty.webapp.WebAppClassLoader; import org.mortbay.jetty.webapp.WebAppContext; import org.mortbay.thread.QueuedThreadPool; @@ -26,8 +27,6 @@ public class Container { } public void init() { - Thread.currentThread().setContextClassLoader(ClassLoader.getSystemClassLoader()); - log.debug("-----------------> "+ClassLoader.getSystemClassLoader()); server = new Server(); QueuedThreadPool qtp = new QueuedThreadPool(); qtp.setMaxThreads(5); @@ -56,21 +55,9 @@ public class Container { WebAppContext webappcontext = new WebAppContext(); webappcontext.setContextPath("/"); webappcontext.setExtractWAR(false); - - File tmpDir = new File(System.getProperty("user.home") + "/.mocca/tmp"); - // tmpDir.mkdirs(); - // webappcontext.setTempDirectory(tmpDir); - try { - File f = new File(System.getProperty("user.home") - + "/.mocca/war/mocca.war"); - log.debug("Deploying war: " + f.getCanonicalPath()); - if (!f.exists()) { - log.error("WAR file does not exist, cannot run MOCCA"); - } - webappcontext.setWar(f.getParent()); - } catch (IOException e) { - log.error(e); - } + System.out.println(getClass().getClassLoader().getResource("log4j.properties")); + webappcontext.setWar("BKULocal-1.0-SNAPSHOT.war"); + handlers.setHandlers(new Handler[] { webappcontext, new DefaultHandler() }); server.setHandler(handlers); diff --git a/BKULocalApp/src/main/resources/splash.png b/BKULocalApp/src/main/resources/splash.png new file mode 100644 index 00000000..72c1d868 Binary files /dev/null and b/BKULocalApp/src/main/resources/splash.png differ diff --git a/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java b/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java index a369d829..6030c1c0 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java +++ b/BKUOnline/src/main/java/at/gv/egiz/bku/online/conf/SpringConfigurator.java @@ -60,6 +60,7 @@ public class SpringConfigurator extends Configurator implements if ((appletTimeout != null)) { try { long ato = Long.parseLong(appletTimeout); + log.debug("Setting applet timeout to:"+ato); RequestBrokerSTALFactory.setTimeout(ato); } catch (NumberFormatException nfe) { log.error("Cannot set Applettimeout", nfe); diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java index 45ee67d0..9c4aca28 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/RequestBrokerSTALFactory.java @@ -32,7 +32,7 @@ import at.gv.egiz.stal.STALFactory; */ public class RequestBrokerSTALFactory implements STALFactory { - private static long timeout; + private static long timeout = -1; @Override public STAL createSTAL() { diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java index af886eec..63eac311 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBroker.java @@ -32,7 +32,7 @@ import java.util.List; */ public interface STALRequestBroker extends STAL { - public static final int ERR_6000 = 6000; + public static final int ERR_4500 = 4500; public static final long DEFAULT_TIMEOUT_MS = 1000*60*5; //5mn public List connect(); diff --git a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java index bfa83dd4..4aa5130a 100644 --- a/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java +++ b/BKUOnline/src/main/java/at/gv/egiz/stal/service/impl/STALRequestBrokerImpl.java @@ -150,7 +150,7 @@ public class STALRequestBrokerImpl implements STALRequestBroker { // reqMon.setHashDataInput(null); requests.clear(); //TODO sync on requests? hashDataInputs.clear(); - return Collections.singletonList((STALResponse) new ErrorResponse(ERR_6000)); + return Collections.singletonList((STALResponse) new ErrorResponse(ERR_4500)); } } log.trace("consuming responses"); diff --git a/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties b/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties index d7fc5ae9..9766ae26 100644 --- a/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties +++ b/BKUOnline/src/main/resources/at/gv/egiz/bku/online/conf/defaultConf.properties @@ -48,4 +48,4 @@ AppletTimeout=300000 #HTTPProxyHost=taranis.iaik.tugraz.at #HTTPProxyPort=8888 -#DefaultSocketTimeout=200 +DefaultSocketTimeout=200 diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties index cf52a4c3..73409c8b 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties @@ -68,7 +68,8 @@ ec4119=Datum, f ec4120=Gewählter Infoboxbezeichner bereits vergeben. ec4121=Infobox mit spezifiziertem Bezeichner existiert nicht. ec4122=Inhalt der ausgewählten Infobox kann nicht als XML dargestellt werden. -ec4123=Assoziatives Array: Zum spezifizierten Schlüssel existiert kein Eintrag. +ec4123=Assoziatives Array: Zum spezifizierten Schlüssel existiert kein Eintrag. +ec4500=Die Sitzung ist abgelaufen. ec5000=Unklassifizierter Fehler in der Anzeigekomponente. ec5001=Anzeige von Daten des in der Befehlsanfrage angegebenen Mime-Types wird nicht unterstützt. ec5002=Zeichenkodierung der anzuzeigenden Daten ist fehlerhaft oder wird nicht unterstützt. diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties index cf52a4c3..73409c8b 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties @@ -68,7 +68,8 @@ ec4119=Datum, f ec4120=Gewählter Infoboxbezeichner bereits vergeben. ec4121=Infobox mit spezifiziertem Bezeichner existiert nicht. ec4122=Inhalt der ausgewählten Infobox kann nicht als XML dargestellt werden. -ec4123=Assoziatives Array: Zum spezifizierten Schlüssel existiert kein Eintrag. +ec4123=Assoziatives Array: Zum spezifizierten Schlüssel existiert kein Eintrag. +ec4500=Die Sitzung ist abgelaufen. ec5000=Unklassifizierter Fehler in der Anzeigekomponente. ec5001=Anzeige von Daten des in der Befehlsanfrage angegebenen Mime-Types wird nicht unterstützt. ec5002=Zeichenkodierung der anzuzeigenden Daten ist fehlerhaft oder wird nicht unterstützt. diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties index 8e0a09bc..91ca20e8 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties @@ -69,6 +69,7 @@ ec4120=Selected info box identifier already allocated. ec4121=Info box with specified identifier does not exist. ec4122=Contents of the selected info box cannot be displayed as XML. ec4123=Associative array: No entry for the specified key. +ec4500=The session expired. ec5000=Unclassified error in the viewer component. ec5001=Display of data of the mime type specified in the command request not supported. ec5002=Character encoding of the data to be displayed is invalid or not supported. diff --git a/utils/pom.xml b/utils/pom.xml index 7408f12b..d6b58234 100644 --- a/utils/pom.xml +++ b/utils/pom.xml @@ -1,108 +1,77 @@ - - - bku - at.gv.egiz - 1.0-SNAPSHOT - - 4.0.0 - at.gv.egiz - utils - BKU Utils - jar - 1.0-SNAPSHOT - http://bku.egiz.gv.at - - - - - - - - commons-logging - commons-logging - - - iaik - iaik_jce_full_signed - - - iaik - iaik_ecc_signed - - - iaik - iaik_xsect - - - - + + + bku + at.gv.egiz + 1.0-SNAPSHOT + + 4.0.0 + at.gv.egiz + utils + BKU Utils + jar + 1.0-SNAPSHOT + http://bku.egiz.gv.at + + + + + + + + commons-logging + commons-logging + + + iaik + iaik_jce_full_signed + + + iaik + iaik_ecc_signed + + + iaik + iaik_xsect + + + + -- cgit v1.2.3 From 4d27cbd65e358f9ae778b6911e8de527e86f6bda Mon Sep 17 00:00:00 2001 From: mcentner Date: Mon, 3 Nov 2008 14:31:47 +0000 Subject: Localization default language set to German (de). git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@141 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../gv/egiz/bku/online/applet/Messages.properties | 58 ------------- .../egiz/bku/online/applet/Messages_de.properties | 42 --------- .../at/gv/egiz/bku/gui/Messages.properties | 85 ++++++++++--------- .../at/gv/egiz/bku/gui/Messages_de.properties | 62 -------------- .../at/gv/egiz/bku/gui/Messages_en.properties | 62 ++++++++++++++ .../slexceptions/SLExceptionMessages_de.properties | 99 ---------------------- .../main/java/at/gv/egiz/smcc/util/SMCCHelper.java | 4 +- .../resources/at/gv/egiz/smcc/ACOSCard.properties | 2 +- .../at/gv/egiz/smcc/ACOSCard_de.properties | 21 ----- .../at/gv/egiz/smcc/ACOSCard_en.properties | 21 ----- .../at/gv/egiz/smcc/STARCOSCard.properties | 4 +- .../at/gv/egiz/smcc/STARCOSCard_de.properties | 20 ----- .../at/gv/egiz/smcc/STARCOSCard_en.properties | 20 ----- 13 files changed, 110 insertions(+), 390 deletions(-) delete mode 100644 BKUApplet/src/main/resources/at/gv/egiz/bku/online/applet/Messages.properties delete mode 100644 BKUApplet/src/main/resources/at/gv/egiz/bku/online/applet/Messages_de.properties delete mode 100644 BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_de.properties create mode 100644 BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties delete mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties delete mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard_de.properties delete mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard_en.properties delete mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard_de.properties delete mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard_en.properties (limited to 'bkucommon/src/main/resources') diff --git a/BKUApplet/src/main/resources/at/gv/egiz/bku/online/applet/Messages.properties b/BKUApplet/src/main/resources/at/gv/egiz/bku/online/applet/Messages.properties deleted file mode 100644 index 752004e8..00000000 --- a/BKUApplet/src/main/resources/at/gv/egiz/bku/online/applet/Messages.properties +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright 2008 Federal Chancellery Austria and -# Graz University of Technology -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -------- BEGIN bootstrap applet -----------# -java16required=This Applet requires Java 1.6 or higher to run. \ - Please download and install a recent version of Java. \ -

For Windows, Linux and Solaris plattforms you can download Java from \ - http://java.sun.com/javase/downloads.\ -

- -failedtostart=Failed to start Applet. \ -

{0}

-# -------- END bootstrap applet -----------# - - -applet.name=Online Citicen Card Environment (CCE) - -nopcscsupport=The Java plattform does not seem to provide \ -a PC/SC interface to acces a smartcard. - -nocardterminal=Can not find a connected smartcard reader.\ -

Either there is no smartcard reader connected, or \ - no PC/SC driver is installed for a connected smartcard reader.

- -insertcard=Please insert your citicen card (B\u00FCrgerkarte) into your \ - smartcard reader. - -unsupportedcard=The inserted smartcard is not supported.\ -

Please insert your citicen card (B\u00FCrgerkarte) \ - into your smartcard reader.

- -enterpin=Please enter {0} \(min {1}, max {2} digits\). - -enterpinretries=Please enter {0} \(min {1}, max {2} digits, {3} retries left\). - -pinwrong=Entered PIN is wrong. - -button.ok=Ok - -button.cancel=Cancel - -status.findpcsc=Looking for PC/SC support - -status.findsupportedcard=Looking for a supported smartcard - -failed.WS=Webservice cannot be reached. \ No newline at end of file diff --git a/BKUApplet/src/main/resources/at/gv/egiz/bku/online/applet/Messages_de.properties b/BKUApplet/src/main/resources/at/gv/egiz/bku/online/applet/Messages_de.properties deleted file mode 100644 index e6b815e9..00000000 --- a/BKUApplet/src/main/resources/at/gv/egiz/bku/online/applet/Messages_de.properties +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright 2008 Federal Chancellery Austria and -# Graz University of Technology -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# -------- BEGIN bootstrap applet -----------# -java16required=Dieses Applet ben\u00F6tigt Java Version 1.6 oder h\u00F6her. \ - Bitte installieren sie eine aktulle Version von Java. \ -

F\u00FCr Windows, Linux and Solaris kann Java von \ - http://java.sun.com/javase/downloads \ - heruntergeladen werden.

- -failedtostart=Das Applet konnte nicht gestartet werden. \ -

{0}

-# -------- END bootstrap applet -----------# - -applet.name=Online B\u00FCrgerkartenumgebung (BKU) - -nopcscsupport=Die Java-Installation stellt keine \ - PC/SC-Schnittstelle zum Zugriff auf eine Chipkarte zur Verf\u00FCgung. - -nocardterminal=Es konnte kein Chipkartenleser gefunden werden.\ -

Entweder, es ist kein Chipkartenleser angeschlossen, oder \ - f\u00FCr den angeschlossenen Chipkartenleser ist kein PC/SC-Treiber \ - installiert.

- -insertcard=Bitte stecken Sie ihre B\u00FCrgerkarte in den Chipkartenleser. - -unsupportedcard=Die gesteckte Chipkarte wird nicht unterst\u00FCtzt.\ -

Bitte stecken Sie ihre B\u00FCrgerkare in den Chipkartenleser

- -failed.WS=Das Webservice kann nicht erreicht werden. \ No newline at end of file diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties index 2e6b7b14..aeabc5c1 100644 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages.properties @@ -13,49 +13,50 @@ # See the License for the specific language governing permissions and # limitations under the License. -title.welcome=Welcome -title.insertcard=Please insert your citizen-card into the reader -title.cardnotsupported=This card is not supported -title.cardpin=Enter {0} -title.sign=Create signature -title.error=Error -title.retry=Wrong PIN -title.wait=Please wait -title.hashdata=Signature data -windowtitle.save=Save signature data -windowtitle.savedir=Save signature data to directory -windowtitle.overwrite=Overwrite file? -message.wait=Please wait... -message.insertcard=Please insert your citizen-card into the reader -message.enterpin=Enter {0} -message.hashdatalink=Display signature data -message.hashdata=Signature data: -message.hashdatalist={0} signature data objects: -message.retries={0} tries left -message.overwrite=Overwrite {0}? +title.welcome=Willkommen +title.insertcard=Bitte B\u00FCrgerkarte in den Kartenleser stecken +title.cardnotsupported=Die Karte wird nicht unterst\u00FCtzt +title.cardpin={0} eingeben +title.sign=Signatur erstellen +title.error=Fehler +title.retry=Falscher PIN +title.wait=Bitte warten +title.hashdata=Signaturdaten +windowtitle.save=Signaturdaten speichern +windowtitle.savedir=Signaturdaten in Verzeichnis speichern +windowtitle.overwrite=Datei \u00FCberschreiben? +message.wait=Bitte warten... +message.insertcard=Bitte die B\u00FCrgerkarte in den Kartenleser stecken +message.enterpin={0} eingeben +message.hashdatalink=Signaturdaten anzeigen +message.hashdata=Signaturdaten: +message.hashdatalist={0} Signaturdaten: +message.retries=Noch {0} Versuch(e) +message.overwrite=M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben? label.pin={0}: -label.pinsize=({0} digits) +label.pinsize=({0} stellig) button.ok=OK -button.cancel=Cancel -button.back=Back -button.sign=Sign -button.save=Save... -mimetype.desc.xml=XML-files (.xml) -mimetype.desc.html=HTML-files (.html, .htm) -mimetype.desc.xhtml=XHTML-files (.xhtml) -mimetype.desc.txt=Textfiles (.txt) -mimetype.desc.pdf=Adobe PDF-files (.pdf) -mimetype.desc.bin=Binary files (.bin) -save.hashdatainput.prefix=signaturedata +button.cancel=Abbrechen +button.back=Zur\u00FCck +button.sign=Signieren +button.save=Speichern... +mimetype.desc.xml=XML-Dateien (.xml) +mimetype.desc.html=HTML-Dateien (.html, .htm) +mimetype.desc.xhtml=XHTML-Dateien (.xhtml) +mimetype.desc.txt=Textdateien (.txt) +mimetype.desc.pdf=Adobe PDF-Dateien (.pdf) +mimetype.desc.bin=Bin\u00E4rdateien (.bin) +save.hashdatainput.prefix=Signaturdaten # Error Messages -error.no.hashdata=No signature data available: {0} -error.display.hashdata=Could not display signature data: {0} -error.write.hashdata=Could not save signature data: {0} -error.invalid.hash=Invalid signature data: {0} -error.ws.unreachable=Web-service unreachable: {0} -error.pcsc=No PC/SC interface for smartcard access provided -error.cardterminal=Could not find smartcard reader -error.unknown=An error occured: {0} -error.card.locked=Citizen-card is locked -error.card.notactivated=Citizen-card not activated \ No newline at end of file +error.no.hashdata=Keine Signaturdaten verf\u00FCgbar: {0} +error.display.hashdata=Signaturdaten konnten nicht dargestellt werden: {0} +error.write.hashdata=Die Signaturdaten konnten nicht gespeichert werden: {0} +error.invalid.hash=Die Signaturdaten sind ung\u00FCltig: {0} +error.ws.unreachable=Das Web-Service ist nicht erreichbar: {0} +error.pcsc=Es konnte keine PC/SC Schnittstelle gefunden werden +error.cardterminal=Es konnte kein Smartcard-Leser gefunden werden +error.unknown=Leider trat ein Fehler auf: {0} +error.test=Fehler1 {0} - Fehler2 {1} +error.card.locked=B\u00FCrgerkarte ist gesperrt +error.card.notactivated=B\u00FCrgerkartenfunktion ist nicht aktiviert \ No newline at end of file diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_de.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_de.properties deleted file mode 100644 index af0cb016..00000000 --- a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_de.properties +++ /dev/null @@ -1,62 +0,0 @@ -# Copyright 2008 Federal Chancellery Austria and -# Graz University of Technology -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -title.welcome=Willkommen -title.insertcard=Bitte B\u00FCrgerkarte in den Kartenleser stecken -title.cardnotsupported=Die Karte wird nicht unterst\u00FCtzt -title.cardpin={0} eingeben -title.sign=Signatur erstellen -title.error=Fehler -title.retry=Falscher PIN -title.wait=Bitte warten -title.hashdata=Signaturdaten -windowtitle.save=Signaturdaten speichern -windowtitle.savedir=Signaturdaten in Verzeichnis speichern -windowtitle.overwrite=Datei \u00FCberschreiben? -message.wait=Bitte warten... -message.insertcard=Bitte die B\u00FCrgerkarte in den Kartenleser stecken -message.enterpin={0} eingeben -message.hashdatalink=Signaturdaten anzeigen -message.hashdata=Signaturdaten: -message.hashdatalist={0} Signaturdaten: -message.retries=Noch {0} Versuch(e) -message.overwrite=M\u00F6chten Sie das existierende Dokument {0} \u00FCberschreiben? -label.pin={0}: -label.pinsize=({0} stellig) -button.ok=OK -button.cancel=Abbrechen -button.back=Zur\u00FCck -button.sign=Signieren -button.save=Speichern... -mimetype.desc.xml=XML-Dateien (.xml) -mimetype.desc.html=HTML-Dateien (.html, .htm) -mimetype.desc.xhtml=XHTML-Dateien (.xhtml) -mimetype.desc.txt=Textdateien (.txt) -mimetype.desc.pdf=Adobe PDF-Dateien (.pdf) -mimetype.desc.bin=Bin\u00E4rdateien (.bin) -save.hashdatainput.prefix=Signaturdaten - -# Error Messages -error.no.hashdata=Keine Signaturdaten verf\u00FCgbar: {0} -error.display.hashdata=Signaturdaten konnten nicht dargestellt werden: {0} -error.write.hashdata=Die Signaturdaten konnten nicht gespeichert werden: {0} -error.invalid.hash=Die Signaturdaten sind ung\u00FCltig: {0} -error.ws.unreachable=Das Web-Service ist nicht erreichbar: {0} -error.pcsc=Java(TM) scheint keine PC/SC Schnittstelle f\u00FCr den Smartcard-Zugriff zur Verf\u00FCgung zu stellen. -error.cardterminal=Es konnte kein Smartcard-Leser gefunden werden.

Entweder ist kein Leser angeschlossen oder kein PC/SC Treiber installiert.

-error.unknown=Leider trat ein Fehler auf: {0} -error.test=Fehler1 {0} - Fehler2 {1} -error.card.locked=B\u00FCrgerkarte ist gesperrt -error.card.notactivated=B\u00FCrgerkartenfunktion ist nicht aktiviert \ No newline at end of file diff --git a/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties new file mode 100644 index 00000000..3b8ac1bc --- /dev/null +++ b/BKUCommonGUI/src/main/resources/at/gv/egiz/bku/gui/Messages_en.properties @@ -0,0 +1,62 @@ +# Copyright 2008 Federal Chancellery Austria and +# Graz University of Technology +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +title.welcome=Welcome +title.insertcard=Please insert your citizen-card into the reader +title.cardnotsupported=This card is not supported +title.cardpin=Enter {0} +title.sign=Create signature +title.error=Error +title.retry=Wrong PIN +title.wait=Please wait +title.hashdata=Signature data +windowtitle.save=Save signature data +windowtitle.savedir=Save signature data to directory +windowtitle.overwrite=Overwrite file? +message.wait=Please wait... +message.insertcard=Please insert your citizen-card into the reader +message.enterpin=Enter {0} +message.hashdatalink=Display signature data +message.hashdata=Signature data: +message.hashdatalist={0} signature data objects: +message.retries={0} tries left +message.overwrite=Overwrite {0}? +label.pin={0}: +label.pinsize=({0} digits) +button.ok=OK +button.cancel=Cancel +button.back=Back +button.sign=Sign +button.save=Save... +mimetype.desc.xml=XML-files (.xml) +mimetype.desc.html=HTML-files (.html, .htm) +mimetype.desc.xhtml=XHTML-files (.xhtml) +mimetype.desc.txt=Textfiles (.txt) +mimetype.desc.pdf=Adobe PDF-files (.pdf) +mimetype.desc.bin=Binary files (.bin) +save.hashdatainput.prefix=signaturedata + +# Error Messages +error.no.hashdata=No signature data available: {0} +error.display.hashdata=Could not display signature data: {0} +error.write.hashdata=Could not save signature data: {0} +error.invalid.hash=Invalid signature data: {0} +error.ws.unreachable=Web-service unreachable: {0} +error.pcsc=No PC/SC interface for smartcard access provided +error.cardterminal=Could not find smartcard reader +error.unknown=An error occured: {0} +error.test=Error1 {0} - Error2 {1} +error.card.locked=Citizen-card is locked +error.card.notactivated=Citizen-card not activated \ No newline at end of file diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties deleted file mode 100644 index 73409c8b..00000000 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_de.properties +++ /dev/null @@ -1,99 +0,0 @@ -# Copyright 2008 Federal Chancellery Austria and -# Graz University of Technology -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -test.noerror=Das ist eine Test-Fehlermeldung. Es ist kein Fehler aufgetreten. - -ec1000=Unklassifizierter Fehler. -ec2000=Unklassifizierter Fehler in der Transportbindung. -ec2001=HTTP/HTTPS-Bindung: DataURL kann nicht aufgelöst werden. -ec2002=HTTP/HTTPS-Bindung: StylesheetURL kann nicht aufgelöst werden. -ec2003=HTTP/HTTPS-Bindung: RedirectURL kann nicht aufgelöst werden. -ec2004=HTTP/HTTPS-Bindung: Parameter XMLRequest fehlt. -ec2005=HTTP/HTTPS-Bindung: Unbekannte Kodierung der Parameter. -ec2006=HTTP/HTTPS-Bindung: Fehlerhafte Kodierung der Parameter. -ec2007=HTTP/HTTPS-Bindung: DataURL-Server sendet Fehler oder unerwartete Antwort. -ec2008=HTTP/HTTPS-Bindung: Fehler im Stylesheet, der von der StylesheetURL bezogen wurde. -ec2009=HTTP/HTTPS-Bindung: HTTP-Anfrage an lokale BKU wurde an unerlaubte URL gerichtet. -ec2010=HTTPS-Bindung: Fehler beim Aufbau der TLS-Verbindung. -ec3000=Unklassifizierter Fehler in der XML-Struktur der Befehlsanfrage. -ec3001=XML-Struktur der Befehlsanfrage ist nicht wohlgeformt. -ec3002=XML-Struktur der Befehlsanfrage entspricht nicht dem Schema des Security-Layers. -ec3003=XML-Struktur der Befehlsanfrage enthält eine unerlaubte Kombination aus optionalen Elementen oder Attributen. -ec3004=XML-Struktur enthält ein Element oder Attribut, dessen Syntax nicht der Spezifikation des Security-Layer entspricht. -ec3005=Protokollversion des Security-Layer wird nicht unterstützt. -ec4000=Unklassifizierter Fehler in der Befehlsabarbeitung. -ec4001=Unbekannter Keyboxbezeichner. -ec4002=Unbekannter Infoboxbezeichner. -ec4003=Zu signierendes Datum kann nicht aufgelöst werden. -ec4004=Ergänzungsobjekt kann nicht aufgelöst werden. -ec4005=Zu verschlüsselndes Datum kann nicht aufgelöst werden. -ec4006=Algorithmus (Signatur, Verschlüsselung, Digest, Kanonisierung, Transformation) wird nicht unterstützt. -ec4007=Fehler bei der Algorithmusausführung (Signatur, Verschlüsselung, Digest, Kanonisierung, Transformation). -ec4008=Fehler beim Parsen der CMS-Nachricht. -ec4009=Kein passender Entschlüsselungsschlüssel vorhanden. -ec4010=Parameter des Infobox-Befehls passen nicht zum Typ der Infobox. -ec4011=Befehl ist nicht implementiert. -ec4100=XML-Dokument, in das die Signatur integriert werden soll, kann nicht aufgelöst werden. -ec4101=XML-Dokument, in das die Signatur integriert werden soll, kann nicht geparst werden. -ec4102=Signatur kann nicht am spezifizierten Ort in das bestehende XML-Dokument integriert werden. -ec4103=Signatorzertifikat ist nicht in der CMS-Signatur enthalten. -ec4104=Signierte Daten sind weder in der CMS-Signatur noch im XML-Request enthalten. -ec4105=XML-Dokument, das die zu prüfende Signatur enthält, kann nicht aufgelöst werden. -ec4106=XML-Dokument, das die zu prüfende Signatur enthält, kann nicht geparst werden. -ec4107=Am spezifizierten Ort innerhalb des XML-Dokuments befindet sich keine XML-Signatur. -ec4108=Verschlüsseltes Datum kann nicht am spezifizierten Ort in das bestehende XML-Dokument eingefügt werden. -ec4109=Bestehendes XML-Dokument ist notwendig, aber nicht vorhanden. -ec4110=Bestehendes XML-Dokument kann nicht aufgelöst werden. -ec4111=Bestehendes XML-Dokument kann nicht geparst werden. -ec4112=Verschlüsselte Datenverschlüsselungsschlüssel können nicht am spezifizierten Ort in das bestehende XML-Dokument eingefügt werden. -ec4113=Zu entschlüsselnde Daten sind weder in der CMS-Nachricht noch im XML-Request enthalten. -ec4114=Zu entschlüsselndes XML-Dokument kann nicht aufgelöst werden. -ec4115=Zu entschlüsselndes XML-Dokument kann nicht geparst werden. -ec4116=Zumindest ein spezifiziertes Verschlüsselungselement kann nicht im zu entschlüsselnden XML-Dokument gefunden werden. -ec4117=Kein Verschlüsselungselement für Binärantwort vorhanden. -ec4118=Zu hashendes Datum kann nicht aufgelöst werden. -ec4119=Datum, für das der Hashwert zu prüfen ist, kann nicht aufgelöst werden. -ec4120=Gewählter Infoboxbezeichner bereits vergeben. -ec4121=Infobox mit spezifiziertem Bezeichner existiert nicht. -ec4122=Inhalt der ausgewählten Infobox kann nicht als XML dargestellt werden. -ec4123=Assoziatives Array: Zum spezifizierten Schlüssel existiert kein Eintrag. -ec4500=Die Sitzung ist abgelaufen. -ec5000=Unklassifizierter Fehler in der Anzeigekomponente. -ec5001=Anzeige von Daten des in der Befehlsanfrage angegebenen Mime-Types wird nicht unterstützt. -ec5002=Zeichenkodierung der anzuzeigenden Daten ist fehlerhaft oder wird nicht unterstützt. -ec5003=Anzuzeigende Daten enhalten nicht unterstützte Zeichen. -ec5004=Standardanzeigeformat: HTML ist nicht spezifikationskonform. -ec5005=Standardanzeigeformat: CSS ist nicht spezifikationskonform. -ec5006=Standardanzeigeformat: Format eines eingebundenen Bildes ist nicht spezifikationskonform. -ec5007=Standardanzeigeformat: Signatur über eingebundene Bilder fehlt oder ist nicht spezifikationskonform. -ec6000=Unklassifizierter Abbruch durch den Bürger. -ec6001=Abbruch durch den Bürger über die Benutzerschnittstelle. -ec6002=Abbruch auf Grund mangelnder Rechte zur Befehlsausführung. - -# 3xxx -# - -ec3000.unclassified=Unklassifizierter Fehler in der XML-Struktur der Befehlsanfrage. {0} -ec3002.invalid=XML-Struktur der Befehlsanfrage entspricht nicht dem Schema des Security-Layers. {0} - -# 4xxx -# - -ec4000.infobox.invalid=Die Infobox '{0}' enthält ungültige Daten. -ec4000.idlink.transfomation.failed=Die komprimierte Personenbindung konnte mit dem Stylesheet {0} nicht transformiert werden. -ec4002.infobox.unknown=Unbekannter Infoboxbezeichner {0}. -ec4003.not.resolved=Zu signierendes Datum kann nicht aufgelöst werden (URI={0}). -ec4011.notimplemented=Befehl {0} ist nicht implementiert. - diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java index 15971497..4dae7975 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/SMCCHelper.java @@ -87,7 +87,7 @@ public class SMCCHelper { ATR atr = newCards.get(cardTerminal).getATR(); log.trace("Found supported card (" + signatureCard.toString() + ") " + "in terminal '" + cardTerminal.getName() + "', ATR = " - + toString(atr.getHistoricalBytes()) + "."); + + toString(atr.getBytes()) + "."); resultCode = CARD_FOUND; break; @@ -97,7 +97,7 @@ public class SMCCHelper { ATR atr = c.getATR(); log.info("Found unsupported card" + " in terminal '" + cardTerminal.getName() + "', ATR = " - + toString(atr.getHistoricalBytes()) + "."); + + toString(atr.getBytes()) + "."); } else { log.info("Found unsupported card in terminal '" + cardTerminal.getName() + "' without ATR"); diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard.properties index 9142841c..d2bbe4f9 100644 --- a/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard.properties +++ b/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard.properties @@ -17,5 +17,5 @@ # and open the template in the editor. dec.pin.name=Geheimhaltungs-PIN -sig.pin.name=Signature-PIN +sig.pin.name=Signatur-PIN inf.pin.name=Infobox-PIN diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard_de.properties b/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard_de.properties deleted file mode 100644 index d2bbe4f9..00000000 --- a/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard_de.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2008 Federal Chancellery Austria and -# Graz University of Technology -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -dec.pin.name=Geheimhaltungs-PIN -sig.pin.name=Signatur-PIN -inf.pin.name=Infobox-PIN diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard_en.properties b/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard_en.properties deleted file mode 100644 index 9142841c..00000000 --- a/smcc/src/main/resources/at/gv/egiz/smcc/ACOSCard_en.properties +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright 2008 Federal Chancellery Austria and -# Graz University of Technology -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -dec.pin.name=Geheimhaltungs-PIN -sig.pin.name=Signature-PIN -inf.pin.name=Infobox-PIN diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard.properties index 77935333..6fa5f0fa 100644 --- a/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard.properties +++ b/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard.properties @@ -16,5 +16,5 @@ # To change this template, choose Tools | Templates # and open the template in the editor. -sig.pin.name=Signature-PIN -card.pin.name=Card-PIN +sig.pin.name=Signatur-PIN +card.pin.name=Karten-PIN diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard_de.properties b/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard_de.properties deleted file mode 100644 index 6fa5f0fa..00000000 --- a/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard_de.properties +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2008 Federal Chancellery Austria and -# Graz University of Technology -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -sig.pin.name=Signatur-PIN -card.pin.name=Karten-PIN diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard_en.properties b/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard_en.properties deleted file mode 100644 index 77935333..00000000 --- a/smcc/src/main/resources/at/gv/egiz/smcc/STARCOSCard_en.properties +++ /dev/null @@ -1,20 +0,0 @@ -# Copyright 2008 Federal Chancellery Austria and -# Graz University of Technology -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -# To change this template, choose Tools | Templates -# and open the template in the editor. - -sig.pin.name=Signature-PIN -card.pin.name=Card-PIN -- cgit v1.2.3 From 99134c1be5db0fedadc051922e70c9bf563ce16d Mon Sep 17 00:00:00 2001 From: wbauer Date: Tue, 2 Dec 2008 10:13:09 +0000 Subject: Changed SLCommandFactory configuration mechanism and moved the actual configuration to spring's application context git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@231 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKUOnline/pom.xml | 1 - .../src/main/webapp/WEB-INF/applicationContext.xml | 41 +++++-- .../webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar | Bin 0 -> 182140 bytes bkucommon/pom.xml | 5 + .../gv/egiz/bku/slcommands/SLCommandFactory.java | 124 ++++++++++----------- .../impl/CreateXMLSignatureResultImpl.java | 2 +- .../slcommands/impl/InfoboxReadResultFileImpl.java | 2 +- .../gv/egiz/bku/slcommands/impl/SLResultImpl.java | 2 +- .../egiz/bku/slcommands/testApplicationContext.xml | 36 ++++++ .../egiz/bku/binding/HttpBindingProcessorTest.java | 13 ++- .../egiz/bku/slcommands/SLCommandFactoryTest.java | 9 ++ pom.xml | 51 ++++++--- 12 files changed, 189 insertions(+), 97 deletions(-) create mode 100644 BKUOnline/src/main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml (limited to 'bkucommon/src/main/resources') diff --git a/BKUOnline/pom.xml b/BKUOnline/pom.xml index 53025800..1ea2c1a1 100644 --- a/BKUOnline/pom.xml +++ b/BKUOnline/pom.xml @@ -37,7 +37,6 @@ org.springframework spring-core - 2.5.5 javax.servlet diff --git a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml index 4069cdc9..9c7194dd 100644 --- a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml @@ -18,15 +18,33 @@ - - - + + + + + + + + + + + + @@ -46,16 +64,17 @@ - - + + - + init-method="configure" scope="singleton"> + - + - - - + + + \ No newline at end of file diff --git a/BKUOnline/src/main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar b/BKUOnline/src/main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar new file mode 100644 index 00000000..74f00509 Binary files /dev/null and b/BKUOnline/src/main/webapp/applet/BKUApplet-1.0.2-SNAPSHOT.jar differ diff --git a/bkucommon/pom.xml b/bkucommon/pom.xml index e0cb1f7c..beb4b3c7 100644 --- a/bkucommon/pom.xml +++ b/bkucommon/pom.xml @@ -57,6 +57,11 @@ iaik_pki compile + + org.springframework + spring-context + test +
diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java index e13b29a1..9c98ef8a 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java @@ -16,40 +16,37 @@ */ package at.gv.egiz.bku.slcommands; -import java.io.IOException; -import java.net.URL; -import java.util.HashMap; -import java.util.Map; - -import javax.xml.XMLConstants; -import javax.xml.bind.JAXBContext; -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.bind.UnmarshalException; -import javax.xml.bind.Unmarshaller; -import javax.xml.namespace.QName; -import javax.xml.stream.XMLEventReader; -import javax.xml.stream.XMLInputFactory; -import javax.xml.stream.XMLStreamException; -import javax.xml.transform.Source; -import javax.xml.transform.stream.StreamSource; -import javax.xml.validation.Schema; -import javax.xml.validation.SchemaFactory; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.xml.sax.SAXException; -import org.xml.sax.SAXParseException; - -import at.gv.egiz.bku.slcommands.impl.CreateXMLSignatureCommandImpl; -import at.gv.egiz.bku.slcommands.impl.InfoboxReadCommandImpl; -import at.gv.egiz.bku.slcommands.impl.NullOperationCommandImpl; -import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.bku.slexceptions.SLExceptionMessages; -import at.gv.egiz.bku.slexceptions.SLRequestException; -import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.slbinding.RedirectEventFilter; -import at.gv.egiz.slbinding.RedirectUnmarshallerListener; +import java.io.IOException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; + +import javax.xml.XMLConstants; +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.bind.UnmarshalException; +import javax.xml.bind.Unmarshaller; +import javax.xml.namespace.QName; +import javax.xml.stream.XMLEventReader; +import javax.xml.stream.XMLInputFactory; +import javax.xml.stream.XMLStreamException; +import javax.xml.transform.Source; +import javax.xml.transform.stream.StreamSource; +import javax.xml.validation.Schema; +import javax.xml.validation.SchemaFactory; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.xml.sax.SAXException; +import org.xml.sax.SAXParseException; + +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.bku.slexceptions.SLRequestException; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.slbinding.RedirectEventFilter; +import at.gv.egiz.slbinding.RedirectUnmarshallerListener; public class SLCommandFactory { @@ -72,29 +69,30 @@ public class SLCommandFactory { /** * Schema for Security Layer command validation. */ - private static Schema slSchema; + private Schema slSchema; /** * The JAXBContext. */ - private static JAXBContext jaxbContext; + private JAXBContext jaxbContext; /** * The map of : to implementation class of the * corresponding {@link SLCommand}. */ - private static Map> slRequestTypeMap = new HashMap>(); - - - static { - - // TODO: implement dynamic registration - - // register all known implementation classes - putImplClass(SLCommand.NAMESPACE_URI, "NullOperationRequest", - NullOperationCommandImpl.class); - putImplClass(SLCommand.NAMESPACE_URI, "InfoboxReadRequest", - InfoboxReadCommandImpl.class); - putImplClass(SLCommand.NAMESPACE_URI, "CreateXMLSignatureRequest", - CreateXMLSignatureCommandImpl.class); + private Map> slRequestTypeMap = new HashMap>(); + + /** + * Configures the singleton instance with command implementations + * @param commandImplMap + * @throws ClassNotFoundException + */ + @SuppressWarnings("unchecked") + public void setCommandImpl(Map commandImplMap) throws ClassNotFoundException { + ClassLoader cl = getClass().getClassLoader(); + for (String key : commandImplMap.keySet()) { + Class impl = (Class) cl.loadClass(commandImplMap.get(key)); + log.debug("Registering sl command implementation for :"+key+ "; implementation class: "+impl.getCanonicalName()); + slRequestTypeMap.put(key, impl); + } } /** @@ -110,7 +108,7 @@ public class SLCommandFactory { * the implementation class, or null to deregister a * currently registered class */ - public static void putImplClass(String namespaceUri, String localname, + public void setImplClass(String namespaceUri, String localname, Class slCommandClass) { if (slCommandClass != null) { slRequestTypeMap.put(namespaceUri + ":" + localname, slCommandClass); @@ -128,7 +126,7 @@ public class SLCommandFactory { * @return the implementation class, or null if no class is * registered for the given name */ - public static Class getImplClass(QName name) { + public Class getImplClass(QName name) { String namespaceURI = name.getNamespaceURI(); String localPart = name.getLocalPart(); return slRequestTypeMap.get(namespaceURI + ":" + localPart); @@ -139,14 +137,14 @@ public class SLCommandFactory { * * @param slSchema the schema to validate Security Layer commands with */ - public static void setSLSchema(Schema slSchema) { - SLCommandFactory.slSchema = slSchema; + public void setSLSchema(Schema slSchema) { + this.slSchema = slSchema; } /** * @return the jaxbContext */ - public static JAXBContext getJaxbContext() { + public JAXBContext getJaxbContext() { ensureJaxbContext(); return jaxbContext; } @@ -154,14 +152,14 @@ public class SLCommandFactory { /** * @param jaxbContext the jaxbContext to set */ - public static void setJaxbContext(JAXBContext jaxbContext) { - SLCommandFactory.jaxbContext = jaxbContext; + public void setJaxbContext(JAXBContext jaxbContext) { + this.jaxbContext = jaxbContext; } /** * Initialize the JAXBContext. */ - private synchronized static void ensureJaxbContext() { + private synchronized void ensureJaxbContext() { if (jaxbContext == null) { try { String slPkg = at.buergerkarte.namespaces.securitylayer._1.ObjectFactory.class.getPackage().getName(); @@ -177,7 +175,7 @@ public class SLCommandFactory { /** * Initialize the security layer schema. */ - private synchronized static void ensureSchema() { + private synchronized void ensureSchema() { if (slSchema == null) { try { SchemaFactory schemaFactory = SchemaFactory.newInstance(XMLConstants.W3C_XML_SCHEMA_NS_URI); @@ -194,7 +192,7 @@ public class SLCommandFactory { } Schema schema = schemaFactory.newSchema(sources); log.debug("Schema successfully created."); - SLCommandFactory.setSLSchema(schema); + setSLSchema(schema); } catch (SAXException e) { log.error("Failed to load security layer schema.", e); throw new SLRuntimeException("Failed to load security layer schema.", e); @@ -211,9 +209,9 @@ public class SLCommandFactory { */ public synchronized static SLCommandFactory getInstance() { if (instance == null) { - ensureJaxbContext(); - ensureSchema(); - instance = new SLCommandFactory(); + instance = new SLCommandFactory(); + instance.ensureJaxbContext(); + instance.ensureSchema(); } return instance; } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java index 092a13c4..4969c85a 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java @@ -84,7 +84,7 @@ public class CreateXMLSignatureResultImpl extends SLResultImpl { DocumentFragment fragment = doc.createDocumentFragment(); - JAXBContext jaxbContext = SLCommandFactory.getJaxbContext(); + JAXBContext jaxbContext = SLCommandFactory.getInstance().getJaxbContext(); try { Marshaller marshaller = jaxbContext.createMarshaller(); marshaller.marshal(createCreateXMLSignatureResponse, fragment); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java index 6f41b562..78e2e7fa 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java @@ -95,7 +95,7 @@ public class InfoboxReadResultFileImpl extends SLResultImpl implements JAXBElement infoboxReadResponse = factory.createInfoboxReadResponse(infoboxReadResponseType); - JAXBContext context = SLCommandFactory.getJaxbContext(); + JAXBContext context = SLCommandFactory.getInstance().getJaxbContext(); try { Marshaller marshaller = context.createMarshaller(); marshaller.marshal(infoboxReadResponse, doc); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java index 7306b237..80bbdca8 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java @@ -85,7 +85,7 @@ public abstract class SLResultImpl implements SLResult { private Marshaller getMarshaller() { try { - JAXBContext context = SLCommandFactory.getJaxbContext(); + JAXBContext context = SLCommandFactory.getInstance().getJaxbContext(); Marshaller marshaller = context.createMarshaller(); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); return marshaller; diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml new file mode 100644 index 00000000..885e35f3 --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/binding/HttpBindingProcessorTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/binding/HttpBindingProcessorTest.java index 6a0792d5..58941401 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/binding/HttpBindingProcessorTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/binding/HttpBindingProcessorTest.java @@ -27,7 +27,10 @@ import java.util.List; import java.util.Map; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; import at.gv.egiz.bku.binding.MultiTestDataUrlConnection.DataSourceProvider; import at.gv.egiz.bku.utils.StreamUtil; @@ -80,7 +83,15 @@ public class HttpBindingProcessorTest { protected Map serverHeaderMap; protected Map clientHeaderMap; protected TestDataUrlConnection server; - + + protected static ApplicationContext appCtx; + + @BeforeClass + public static void setUpClass() { + appCtx = new ClassPathXmlApplicationContext("at/gv/egiz/bku/slcommands/testApplicationContext.xml"); + } + + @Before public void setUp() throws IOException { server = new TestDataUrlConnection(); diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java index 7b35723d..e0b09508 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java @@ -25,7 +25,10 @@ import javax.xml.transform.Source; import javax.xml.transform.stream.StreamSource; import org.junit.Before; +import org.junit.BeforeClass; import org.junit.Test; +import org.springframework.context.ApplicationContext; +import org.springframework.context.support.ClassPathXmlApplicationContext; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLRequestException; @@ -33,9 +36,15 @@ import at.gv.egiz.bku.slexceptions.SLRuntimeException; public class SLCommandFactoryTest { + protected static ApplicationContext appCtx; SLCommandFactory factory; SLCommandContext context; + @BeforeClass + public static void setUpClass() { + appCtx = new ClassPathXmlApplicationContext("at/gv/egiz/bku/slcommands/testApplicationContext.xml"); + } + @Before public void setUp() { factory = SLCommandFactory.getInstance(); diff --git a/pom.xml b/pom.xml index 874dce5b..74c449e8 100644 --- a/pom.xml +++ b/pom.xml @@ -1,4 +1,5 @@ - + 4.0.0 at.gv.egiz bku @@ -38,15 +39,15 @@ - scm:svn:svn://svn.egovlabs.gv.at/svnroot/mocca/trunk - scm:svn:svn+ssh://svn.egovlabs.gv.at/svnroot/mocca/trunk + scm:svn:svn://svn.egovlabs.gv.at/svnroot/mocca/trunk + scm:svn:svn+ssh://svn.egovlabs.gv.at/svnroot/mocca/trunk svn://svn.egovlabs.gv.at/svnroot/mocca/trunk E-Government Innovation Center (EGIZ) http://www.egiz.gv.at - + @@ -56,20 +57,21 @@ + 1.6 1.6 1.6 true true - UTF-8 + UTF-8 + + + + maven-resources-plugin + + UTF-8 - - maven-resources-plugin - - UTF-8 - - maven-assembly-plugin org.apache.maven.plugins @@ -83,16 +85,17 @@ + jaxws-maven-plugin org.codehaus.mojo 1.10 - org.apache.maven.plugins - maven-release-plugin - 2.0-beta-7 + org.apache.maven.plugins + maven-release-plugin + 2.0-beta-7 @@ -105,7 +108,8 @@ + ${basedir}/src/main/assemblies/assembly-server.xml + @@ -219,6 +224,16 @@ 3.1 compile + + org.springframework + spring-core + 2.5.5 + + + org.springframework + spring-context + 2.5.5 +
\ No newline at end of file -- cgit v1.2.3 From 3aadcf8f877a560bed75af7e0db918aa26ef2a03 Mon Sep 17 00:00:00 2001 From: mcentner Date: Thu, 4 Dec 2008 10:00:31 +0000 Subject: Refactoring of infobox implementation. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@232 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../src/main/webapp/WEB-INF/applicationContext.xml | 34 ++ .../src/main/webapp/WEB-INF/applicationContext.xml | 17 + .../main/java/at/gv/egiz/bku/binding/DataUrl.java | 1 + .../bku/binding/LegacyDataUrlConnectionImpl.java | 230 +++++++++ .../java/at/gv/egiz/bku/conf/Configurator.java | 41 +- .../egiz/bku/slcommands/InfoboxUpdateCommand.java | 23 + .../egiz/bku/slcommands/InfoboxUpdateResult.java | 21 + .../slcommands/impl/AbstractAssocArrayInfobox.java | 284 ++++++++++ .../slcommands/impl/AbstractBinaryFileInfobox.java | 68 +++ .../impl/AbstractInfoboxCommandImpl.java | 55 ++ .../bku/slcommands/impl/AbstractInfoboxImpl.java | 26 + .../bku/slcommands/impl/AssocArrayInfobox.java | 27 + .../bku/slcommands/impl/BinaryFileInfobox.java | 27 + .../slcommands/impl/CertificatesInfoboxImpl.java | 112 ++++ .../impl/CreateXMLSignatureCommandImpl.java | 37 +- .../slcommands/impl/IdentityLinkInfoboxImpl.java | 291 +++++++++++ .../at/gv/egiz/bku/slcommands/impl/Infobox.java | 53 ++ .../egiz/bku/slcommands/impl/InfoboxFactory.java | 151 ++++++ .../slcommands/impl/InfoboxReadCommandImpl.java | 569 ++------------------- .../bku/slcommands/impl/InfoboxReadResultImpl.java | 3 +- .../slcommands/impl/InfoboxUpdateCommandImpl.java | 158 ++++++ .../slcommands/impl/InfoboxUpdateResultImpl.java | 43 ++ .../gv/egiz/bku/slcommands/impl/SLCommandImpl.java | 107 +--- .../at/gv/egiz/bku/slcommands/impl/STALHelper.java | 218 ++++++++ .../egiz/bku/slcommands/testApplicationContext.xml | 36 -- .../egiz/bku/slcommands/testApplicationContext.xml | 53 ++ 26 files changed, 1968 insertions(+), 717 deletions(-) create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateCommand.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateResult.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AssocArrayInfobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BinaryFileInfobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CertificatesInfoboxImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxFactory.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateCommandImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java delete mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml create mode 100644 bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml (limited to 'bkucommon/src/main/resources') diff --git a/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml b/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml index 1d09aa7e..5ac12ece 100644 --- a/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKULocal/src/main/webapp/WEB-INF/applicationContext.xml @@ -48,6 +48,40 @@ + + + + + + + + + + + + + + + + + + + + + + diff --git a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml index 9c7194dd..321e1e98 100644 --- a/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml +++ b/BKUOnline/src/main/webapp/WEB-INF/applicationContext.xml @@ -45,6 +45,23 @@ + + + + + + + + + + + + diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java index d462ac60..531772cf 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java @@ -65,5 +65,6 @@ public class DataUrl { public static void setConfiguration(Properties props) { configuration = props; + defaultDataUrlConnection.setConfiguration(configuration); } } \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java new file mode 100644 index 00000000..5339d689 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java @@ -0,0 +1,230 @@ +package at.gv.egiz.bku.binding; + + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStream; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.net.HttpURLConnection; +import java.net.SocketTimeoutException; +import java.net.URL; +import java.net.URLEncoder; +import java.security.cert.X509Certificate; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; + +import javax.net.ssl.HttpsURLConnection; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.SLResult.SLResultType; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.binding.Protocol; + +/** + * not thread-safe thus newInsance always returns a new object + * + */ +public class LegacyDataUrlConnectionImpl implements DataUrlConnectionSPI { + + private final static Log log = LogFactory.getLog(DataUrlConnectionImpl.class); + + public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP, + Protocol.HTTPS }; + protected X509Certificate serverCertificate; + protected Protocol protocol; + protected URL url; + private HttpURLConnection connection; + protected Map requestHttpHeaders; + protected Map formParams; + protected String boundary; + protected Properties config = null; + + protected DataUrlResponse result; + + public String getProtocol() { + if (protocol == null) { + return null; + } + return protocol.toString(); + } + + /** + * opens a connection sets the headers gets the server certificate + * + * @throws java.net.SocketTimeoutException + * @throws java.io.IOException + * @pre url != null + * @pre httpHeaders != null + */ + public void connect() throws SocketTimeoutException, IOException { + connection = (HttpURLConnection) url.openConnection(); + connection.setDoOutput(true); + Set headers = requestHttpHeaders.keySet(); + Iterator headerIt = headers.iterator(); + while (headerIt.hasNext()) { + String name = headerIt.next(); + connection.setRequestProperty(name, requestHttpHeaders.get(name)); + } + log.trace("Connecting to: "+url); + connection.connect(); + if (connection instanceof HttpsURLConnection) { + HttpsURLConnection ssl = (HttpsURLConnection) connection; + X509Certificate[] certs = (X509Certificate[]) ssl.getServerCertificates(); + if ((certs != null) && (certs.length >= 1)) { + log.trace("Server certificate: "+certs[0]); + serverCertificate = certs[0]; + } + } + } + + public X509Certificate getServerCertificate() { + return serverCertificate; + } + + public void setHTTPHeader(String name, String value) { + if (name != null && value != null) { + requestHttpHeaders.put(name, value); + } + } + + public void setHTTPFormParameter(String name, InputStream data, + String contentType, String charSet, String transferEncoding) { + StringBuilder sb = new StringBuilder(); + try { + InputStreamReader reader = new InputStreamReader(data, (charSet != null) ? charSet : "UTF-8"); + char[] c = new char[512]; + for (int l; (l = reader.read(c)) != -1;) { + sb.append(c, 0, l); + } + } catch (IOException e) { + throw new SLRuntimeException("Failed to set HTTP form parameter.", e); + } + formParams.put(name, sb.toString()); + } + + /** + * send all formParameters + * + * @throws java.io.IOException + */ + public void transmit(SLResult slResult) throws IOException { + StringWriter writer = new StringWriter(); + slResult.writeTo(new StreamResult(writer)); + formParams.put( + (slResult.getResultType() == SLResultType.XML) + ? DataUrlConnection.FORMPARAM_XMLRESPONSE + : DataUrlConnection.FORMPARAM_BINARYRESPONSE, + writer.toString()); + + OutputStream os = connection.getOutputStream(); + OutputStreamWriter streamWriter = new OutputStreamWriter(os, HttpUtil.DEFAULT_CHARSET); + + log.trace("Sending data"); + Iterator keys = formParams.keySet().iterator(); + while(keys.hasNext()) { + String key = keys.next(); + streamWriter.write(URLEncoder.encode(key, "UTF-8")); + streamWriter.write("="); + streamWriter.write(URLEncoder.encode(formParams.get(key), "UTF-8")); + if (keys.hasNext()) { + streamWriter.write("&"); + } + } + streamWriter.flush(); + os.close(); + + // MultipartRequestEntity PostMethod + InputStream is = null; + try { + is = connection.getInputStream(); + } catch (IOException iox) { + log.info(iox); + } + log.trace("Reading response"); + result = new DataUrlResponse(url.toString(), connection.getResponseCode(), is); + Map responseHttpHeaders = new HashMap(); + Map> httpHeaders = connection.getHeaderFields(); + for (Iterator keyIt = httpHeaders.keySet().iterator(); keyIt + .hasNext();) { + String key = keyIt.next(); + StringBuffer value = new StringBuffer(); + for (String val : httpHeaders.get(key)) { + value.append(val); + value.append(HttpUtil.SEPERATOR[0]); + } + String valString = value.substring(0, value.length() - 1); + if ((key != null) && (value.length() > 0)) { + responseHttpHeaders.put(key, valString); + } + } + result.setResponseHttpHeaders(responseHttpHeaders); + } + + @Override + public DataUrlResponse getResponse() throws IOException { + return result; + } + + /** + * inits protocol, url, httpHeaders, formParams + * + * @param url + * must not be null + */ + @Override + public void init(URL url) { + + for (int i = 0; i < SUPPORTED_PROTOCOLS.length; i++) { + if (SUPPORTED_PROTOCOLS[i].toString().equalsIgnoreCase(url.getProtocol())) { + protocol = SUPPORTED_PROTOCOLS[i]; + break; + } + } + if (protocol == null) { + throw new SLRuntimeException("Protocol " + url.getProtocol() + + " not supported for data url"); + } + this.url = url; + requestHttpHeaders = new HashMap(); + if ((config != null) + && (config.getProperty(USER_AGENT_PROPERTY_KEY) != null)) { + requestHttpHeaders.put(HttpUtil.HTTP_HEADER_USER_AGENT, config + .getProperty(USER_AGENT_PROPERTY_KEY)); + } else { + requestHttpHeaders + .put(HttpUtil.HTTP_HEADER_USER_AGENT, DEFAULT_USERAGENT); + + } + requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, + HttpUtil.APPLICATION_URL_ENCODED); + + formParams = new HashMap(); + } + + @Override + public DataUrlConnectionSPI newInstance() { + DataUrlConnectionSPI uc = new LegacyDataUrlConnectionImpl(); + uc.setConfiguration(config); + return uc; + } + + @Override + public URL getUrl() { + return url; + } + + @Override + public void setConfiguration(Properties config) { + this.config = config; + } +} \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java index 9ed99190..6078de36 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java @@ -187,28 +187,29 @@ public abstract class Configurator { } public void configureVersion() { - Properties p = new Properties(); - try { - InputStream is = getManifest(); - if (is != null) { - p.load(getManifest()); - String version = p.getProperty("Implementation-Build"); - properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, - "citizen-card-environment/1.2 MOCCA " + version); - DataUrl.setConfiguration(properties); - log - .debug("Setting user agent to: " - + properties - .getProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY)); - } else { - log.warn("Cannot read manifest"); - properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, - "citizen-card-environment/1.2 MOCCA UNKNOWN"); - DataUrl.setConfiguration(properties); + if (properties.getProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY) == null) { + Properties p = new Properties(); + try { + InputStream is = getManifest(); + if (is != null) { + p.load(getManifest()); + String version = p.getProperty("Implementation-Build"); + properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, + "citizen-card-environment/1.2 MOCCA " + version); + log + .debug("Setting user agent to: " + + properties + .getProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY)); + } else { + log.warn("Cannot read manifest"); + properties.setProperty(DataUrlConnection.USER_AGENT_PROPERTY_KEY, + "citizen-card-environment/1.2 MOCCA UNKNOWN"); + } + } catch (IOException e) { + log.error(e); } - } catch (IOException e) { - log.error(e); } + DataUrl.setConfiguration(properties); } public void configure() { diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateCommand.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateCommand.java new file mode 100644 index 00000000..c2974785 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateCommand.java @@ -0,0 +1,23 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands; + +public interface InfoboxUpdateCommand extends SLCommand { + + public String getInfoboxIdentifier(); + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateResult.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateResult.java new file mode 100644 index 00000000..d180facf --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/InfoboxUpdateResult.java @@ -0,0 +1,21 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands; + +public interface InfoboxUpdateResult extends SLResult { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java new file mode 100644 index 00000000..e49ed6c0 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java @@ -0,0 +1,284 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.slcommands.impl; + +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.regex.Pattern; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.buergerkarte.namespaces.securitylayer._1.InfoboxAssocArrayPairType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadDataAssocArrayType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.buergerkarte.namespaces.securitylayer._1.XMLContentType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadKeys; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadPairs; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadValue; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; + +/** + * An abstract base class for {@link Infobox} implementations of type associative array. + * + * @author mcentner + */ +public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl + implements AssocArrayInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(AbstractAssocArrayInfobox.class); + + /** + * The search string pattern. + */ + public static final String SEARCH_STRING_PATTERN = ".&&[^/](/.&&[^/])*"; + + /** + * @return the keys available in this infobox. + */ + public abstract String[] getKeys(); + + /** + * @return true if the values are XML entities, or false otherwise. + */ + public abstract boolean isValuesAreXMLEntities(); + + /** + * Returns a key to value mapping for the given keys. + * + * @param keys a list of keys + * @param cmdCtx the command context + * + * @return a key to value mapping for the given keys. + * + * @throws SLCommandException if obtaining the values fails + */ + public abstract Map getValues(List keys, SLCommandContext cmdCtx) throws SLCommandException; + + /** + * Returns all keys that match the given searchString. + * + * @param searchString the search string + * + * @return all keys that match the given searchString + * + * @throws SLCommandException if the given search string is invalid + */ + protected List selectKeys(String searchString) throws SLCommandException { + + if ("*".equals(searchString) || "**".equals(searchString)) { + return Arrays.asList(getKeys()); + } + + if (Pattern.matches(SEARCH_STRING_PATTERN, searchString)) { + +// for (int i = 0; i < searchString.length(); i++) { +// int codePoint = searchString.codePointAt(i); +// +// } + + // TODO : build pattern + return Collections.emptyList(); + } else { + log.info("Got invalid search string '" + searchString + "'"); + throw new SLCommandException(4010); + } + + } + + /** + * Read all keys specified by readKeys. + * + * @param readKeys + * the ReadKeys element + * @param cmdCtx + * the command context + * @return a corresponding InfoboxReadResult + * + * @throws SLCommandException + * if the ReadKeys element is invalid or obtaining the corresponding + * values fails + */ + protected InfoboxReadResult readKeys(ReadKeys readKeys, SLCommandContext cmdCtx) throws SLCommandException { + + List selectedKeys = selectKeys(readKeys.getSearchString()); + + if (readKeys.isUserMakesUnique() && selectedKeys.size() > 1) { + log.info("UserMakesUnique not supported"); + // TODO: give more specific error message + throw new SLCommandException(4010); + } + + ObjectFactory objectFactory = new ObjectFactory(); + + InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory + .createInfoboxReadDataAssocArrayType(); + + List keys = infoboxReadDataAssocArrayType.getKey(); + keys.addAll(selectedKeys); + + return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); + + } + + /** + * Read all pairs specified by readPairs. + * + * @param readPairs + * the readPairs element + * @param cmdCtx + * the command context + * @return a corresponding InfoboxReadResult + * + * @throws SLCommandException + * if the ReadPairs element is invalid or obtaining the corresponding + * values fails + */ + protected InfoboxReadResult readPairs(ReadPairs readPairs, SLCommandContext cmdCtx) throws SLCommandException { + + if (readPairs.isValuesAreXMLEntities() && !isValuesAreXMLEntities()) { + log.info("Got valuesAreXMLEntities=" + readPairs + " but infobox type is binary."); + throw new SLCommandException(4010); + } + + if (!readPairs.isValuesAreXMLEntities() && isValuesAreXMLEntities()) { + log.info("Got valuesAreXMLEntities=" + readPairs + " but infobox type is XML."); + throw new SLCommandException(4010); + } + + List selectedKeys = selectKeys(readPairs.getSearchString()); + + if (readPairs.isUserMakesUnique() && selectedKeys.size() > 1) { + log.info("UserMakesUnique not supported"); + // TODO: give more specific error message + throw new SLCommandException(4010); + } + + ObjectFactory objectFactory = new ObjectFactory(); + + InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory.createInfoboxReadDataAssocArrayType(); + + Map values = getValues(selectedKeys, cmdCtx); + for (String key : selectedKeys) { + InfoboxAssocArrayPairType infoboxAssocArrayPairType = objectFactory.createInfoboxAssocArrayPairType(); + infoboxAssocArrayPairType.setKey(key); + Object value = values.get(key); + if (value instanceof byte[]) { + infoboxAssocArrayPairType.setBase64Content((byte[]) value); + } else { + infoboxAssocArrayPairType.setXMLContent((XMLContentType) value); + } + infoboxReadDataAssocArrayType.getPair().add(infoboxAssocArrayPairType); + } + + return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); + } + + /** + * Read the value specified by readPairs. + * + * @param readValue + * the readValue element + * @param cmdCtx + * the command context + * @return a corresponding InfoboxReadResult + * + * @throws SLCommandException + * if the ReadValue element is invalid or obtaining the corresponding + * values fails + */ + protected InfoboxReadResult readValue(ReadValue readValue, SLCommandContext cmdCtx) throws SLCommandException { + + if (readValue.isValueIsXMLEntity() && !isValuesAreXMLEntities()) { + log.info("Got valuesAreXMLEntities=" + readValue + " but infobox type is binary."); + throw new SLCommandException(4010); + } + + if (!readValue.isValueIsXMLEntity() && isValuesAreXMLEntities()) { + log.info("Got valuesAreXMLEntities=" + readValue + " but infobox type is XML."); + throw new SLCommandException(4010); + } + + List selectedKeys; + + if (Arrays.asList(getKeys()).contains(readValue.getKey())) { + selectedKeys = Collections.singletonList(readValue.getKey()); + } else { + selectedKeys = Collections.emptyList(); + } + + ObjectFactory objectFactory = new ObjectFactory(); + + InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory.createInfoboxReadDataAssocArrayType(); + + Map values = getValues(selectedKeys, cmdCtx); + for (String key : selectedKeys) { + InfoboxAssocArrayPairType infoboxAssocArrayPairType = objectFactory.createInfoboxAssocArrayPairType(); + infoboxAssocArrayPairType.setKey(key); + Object value = values.get(key); + if (value instanceof byte[]) { + infoboxAssocArrayPairType.setBase64Content((byte[]) value); + } else { + infoboxAssocArrayPairType.setXMLContent((XMLContentType) value); + } + infoboxReadDataAssocArrayType.getPair().add(infoboxAssocArrayPairType); + } + + return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); + } + + @Override + public InfoboxReadResult read(InfoboxReadRequestType req, + SLCommandContext cmdCtx) throws SLCommandException { + + InfoboxReadParamsAssocArrayType assocArrayParameters = req + .getAssocArrayParameters(); + + if (assocArrayParameters == null) { + log.info("Infobox type is AssocArray but got no AssocArrayParameters."); + throw new SLCommandException(4010); + } + + if (assocArrayParameters.getReadKeys() != null) { + return readKeys(assocArrayParameters.getReadKeys(), cmdCtx); + } + + if (assocArrayParameters.getReadPairs() != null) { + return readPairs(assocArrayParameters.getReadPairs(), cmdCtx); + } + + // ReadValue + if (assocArrayParameters.getReadValue() != null) { + return readValue(assocArrayParameters.getReadValue(), cmdCtx); + } + + log + .info("Infobox type is AssocArray but got invalid AssocArrayParameters."); + throw new SLCommandException(4010); + + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java new file mode 100644 index 00000000..07ca639c --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractBinaryFileInfobox.java @@ -0,0 +1,68 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsBinaryFileType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; + +/** + * An abstract base class for {@link Infobox} implementations of type binary file. + * + * @author mcentner + */ +public abstract class AbstractBinaryFileInfobox extends AbstractInfoboxImpl implements BinaryFileInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(AbstractBinaryFileInfobox.class); + + /** + * Is this infobox' content an XML entity? + */ + private boolean isXMLEntity = false; + + /** + * @return true if this infobox' content is an XML entity or false otherwise. + */ + public boolean isXMLEntity() { + return isXMLEntity; + } + + /** + * Sets the value returned by {@link #isXMLEntity()} according to the given + * request. + * + * @param request the InfoboxReadRequest + */ + public void setIsXMLEntity(InfoboxReadRequestType request) { + + InfoboxReadParamsBinaryFileType binaryFileParameters = request.getBinaryFileParameters(); + if (binaryFileParameters != null) { + isXMLEntity = binaryFileParameters.isContentIsXMLEntity(); + log.debug("Got ContentIsXMLEntity=" + isXMLEntity + "."); + } + + } + + + + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java new file mode 100644 index 00000000..305769a8 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxCommandImpl.java @@ -0,0 +1,55 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; + +/** + * An abstract base class for implementations of security layer infobox requests. + * + * @author mcentner + * + * @param + */ +public abstract class AbstractInfoboxCommandImpl extends SLCommandImpl { + + /** + * The infobox implementation. + */ + protected Infobox infobox; + + @Override + public void init(SLCommandContext ctx, Object request) + throws SLCommandException { + super.init(ctx, request); + + String infoboxIdentifier = getInfoboxIdentifier(getRequestValue()); + + infobox = InfoboxFactory.getInstance().createInfobox(infoboxIdentifier); + } + + /** + * Returns the infobox identifier given in request. + * + * @param request the request value + * + * @return the infobox identifier givne in request + */ + protected abstract String getInfoboxIdentifier(T request); + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java new file mode 100644 index 00000000..e5c7afcc --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractInfoboxImpl.java @@ -0,0 +1,26 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.slcommands.impl; + +/** + * An abstract base class for {@link Infobox} implementations. + * + * @author mcentner + */ +public abstract class AbstractInfoboxImpl implements Infobox { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AssocArrayInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AssocArrayInfobox.java new file mode 100644 index 00000000..908d95da --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AssocArrayInfobox.java @@ -0,0 +1,27 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.slcommands.impl; + +/** + * An {@link Infobox} of type associative array as defined in Security Layer + * 1.2. + * + * @author mcentner + */ +public interface AssocArrayInfobox extends Infobox { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BinaryFileInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BinaryFileInfobox.java new file mode 100644 index 00000000..c27f9446 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/BinaryFileInfobox.java @@ -0,0 +1,27 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +/** + * An {@link Infobox} of type binary file as defined in Security Layer + * 1.2. + * + * @author mcentner + */ +public interface BinaryFileInfobox extends Infobox { + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CertificatesInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CertificatesInfoboxImpl.java new file mode 100644 index 00000000..0208f137 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CertificatesInfoboxImpl.java @@ -0,0 +1,112 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import java.security.cert.CertificateEncodingException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.STALRequest; + +/** + * An implementation of the {@link Infobox} Certificates as + * specified in Security Layer 1.2. + * + * @author mcentner + */ +public class CertificatesInfoboxImpl extends AbstractAssocArrayInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(CertificatesInfoboxImpl.class); + + /** + * The valid keys. + */ + public static final String[] CERTIFICATES_KEYS = new String[] { + "SecureSignatureKeypair", + "CertifiedKeypair" }; + + @Override + public String getIdentifier() { + return "Certificates"; + } + + @Override + public String[] getKeys() { + return CERTIFICATES_KEYS; + } + + @Override + public boolean isValuesAreXMLEntities() { + return false; + } + + @Override + public Map getValues(List certificates, SLCommandContext cmdCtx) throws SLCommandException { + + STALHelper stalHelper = new STALHelper(cmdCtx.getSTAL()); + + if (certificates != null && !certificates.isEmpty()) { + + List stalRequests = new ArrayList(); + + // get certificates + InfoboxReadRequest infoboxReadRequest; + for (int i = 0; i < certificates.size(); i++) { + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier(certificates.get(i)); + stalRequests.add(infoboxReadRequest); + } + + stalHelper.transmitSTALRequest(stalRequests); + + List x509Certs = stalHelper.getCertificatesFromResponses(); + + Map values = new HashMap(); + + for (int i = 0; i < certificates.size(); i++) { + try { + values.put(certificates.get(i), x509Certs.get(i).getEncoded()); + } catch (CertificateEncodingException e) { + log.error("Failed to encode certificate.", e); + throw new SLCommandException(4000); + } + } + + return values; + + } else { + + return new HashMap(); + + } + + + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureCommandImpl.java index b2e3b303..01686641 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureCommandImpl.java @@ -16,13 +16,11 @@ */ package at.gv.egiz.bku.slcommands.impl; -import java.io.ByteArrayInputStream; import java.security.NoSuchAlgorithmException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.util.Collections; import java.util.Date; +import java.util.List; import javax.xml.crypto.MarshalException; import javax.xml.crypto.URIReferenceException; @@ -48,11 +46,8 @@ import at.gv.egiz.bku.slexceptions.SLException; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLViewerException; import at.gv.egiz.dom.DOMUtils; -import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.InfoboxReadRequest; -import at.gv.egiz.stal.InfoboxReadResponse; import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; /** * This class implements the security layer command @@ -147,33 +142,13 @@ public class CreateXMLSignatureCommandImpl extends InfoboxReadRequest stalRequest = new InfoboxReadRequest(); stalRequest.setInfoboxIdentifier(keyboxIdentifier); - requestSTAL(Collections.singletonList((STALRequest) stalRequest)); - - STALResponse stalResponse = stalResponses.next(); - - if (stalResponse instanceof InfoboxReadResponse) { - byte[] infobox = ((InfoboxReadResponse) stalResponse).getInfoboxValue(); - - try { - CertificateFactory certFactory = CertificateFactory.getInstance("X509"); - signingCertificate = (X509Certificate) certFactory - .generateCertificate(new ByteArrayInputStream(infobox)); - } catch (CertificateException e) { - log.info("Failed to decode signing certificate.", e); - // TODO: issue appropriate error - throw new SLCommandException(4000); - } - - } else if (stalResponse instanceof ErrorResponse) { - ErrorResponse err = (ErrorResponse) stalResponse; - log.info("Received an error response from STAL with code: " - + err.getErrorCode()); - throw new SLCommandException(err.getErrorCode()); - - } else { - log.info("Failed to get signing certificate."); + stalHelper.transmitSTALRequest(Collections.singletonList((STALRequest) stalRequest)); + List certificates = stalHelper.getCertificatesFromResponses(); + if (certificates == null || certificates.size() != 1) { + log.info("Got an unexpected number of certificates from STAL."); throw new SLCommandException(4000); } + signingCertificate = certificates.get(0); } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java new file mode 100644 index 00000000..20d20c9d --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java @@ -0,0 +1,291 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.OutputStream; +import java.net.MalformedURLException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.List; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.JAXBException; +import javax.xml.parsers.DocumentBuilder; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.parsers.ParserConfigurationException; +import javax.xml.transform.Result; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerConfigurationException; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMResult; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.w3c.dom.Document; +import org.w3c.dom.Node; + +import at.buergerkarte.namespaces.personenbindung._20020506_.CompressedIdentityLinkType; +import at.buergerkarte.namespaces.securitylayer._1.AnyChildrenType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.idlink.CompressedIdentityLinkFactory; +import at.gv.egiz.idlink.IdentityLinkTransformer; +import at.gv.egiz.idlink.ans1.IdentityLink; +import at.gv.egiz.stal.InfoboxReadRequest; +import at.gv.egiz.stal.STALRequest; + +/** + * An implementation of the {@link Infobox} IdentityLink as + * specified in Security Layer 1.2 + * + * @author mcentner + */ +public class IdentityLinkInfoboxImpl extends AbstractBinaryFileInfobox { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(IdentityLinkInfoboxImpl.class); + + /** + * The box specific parameter IdentityLinkDomainIdentifier. + */ + public static final String BOX_SPECIFIC_PARAMETER_IDENTITY_LINK_DOMAIN_IDENTIFIER = "IdentityLinkDomainIdentifier"; + + /** + * The value of the box specific parameter IdentityLinkDomainIdentifier. + */ + private String domainIdentifier; + + @Override + public String getIdentifier() { + return "IdentityLink"; + } + + /** + * @return the value of the box specific parameter IdentityLinkDomainIdentifier + */ + public String getDomainIdentifier() { + return domainIdentifier; + } + + @Override + public InfoboxReadResult read(InfoboxReadRequestType req, SLCommandContext cmdCtx) throws SLCommandException { + + AnyChildrenType boxSpecificParameters = req.getBoxSpecificParameters(); + + if (boxSpecificParameters != null) { + // check BoxSpecificParameters + List parameter = boxSpecificParameters.getAny(); + JAXBElement element; + if (parameter != null + && parameter.size() == 1 + && parameter.get(0) instanceof JAXBElement + && SLCommand.NAMESPACE_URI.equals((element = (JAXBElement) parameter.get(0)).getName().getNamespaceURI()) + && BOX_SPECIFIC_PARAMETER_IDENTITY_LINK_DOMAIN_IDENTIFIER.equals(element.getName().getLocalPart()) + && element.getValue() instanceof String) { + domainIdentifier = (String) element.getValue(); + log.debug("Got sl:IdentityLinkDomainIdentifier: " + domainIdentifier); + } else { + log.info("Got invalid BoxSpecificParameters."); + throw new SLCommandException(4010); + } + } + + setIsXMLEntity(req); + + STALHelper stalHelper = new STALHelper(cmdCtx.getSTAL()); + + List stalRequests = new ArrayList(); + + InfoboxReadRequest infoboxReadRequest; + // get raw identity link + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier(getIdentifier()); + infoboxReadRequest.setDomainIdentifier(domainIdentifier); + stalRequests.add(infoboxReadRequest); + + // get certificates + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier("SecureSignatureKeypair"); + stalRequests.add(infoboxReadRequest); + infoboxReadRequest = new InfoboxReadRequest(); + infoboxReadRequest.setInfoboxIdentifier("CertifiedKeypair"); + stalRequests.add(infoboxReadRequest); + + stalHelper.transmitSTALRequest(stalRequests); + log.trace("Got STAL response"); + + IdentityLink identityLink = stalHelper.getIdentityLinkFromResponses(); + List certificates = stalHelper.getCertificatesFromResponses(); + + + CompressedIdentityLinkFactory idLinkFactory = CompressedIdentityLinkFactory.getInstance(); + JAXBElement compressedIdentityLink = idLinkFactory + .createCompressedIdentityLink(identityLink, certificates, getDomainIdentifier()); + + IdentityLinkTransformer identityLinkTransformer = IdentityLinkTransformer.getInstance(); + String issuerTemplate = identityLink.getIssuerTemplate(); + + DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); + DocumentBuilder db; + try { + db = dbf.newDocumentBuilder(); + } catch (ParserConfigurationException e) { + log.error("Failed to create XML document.", e); + throw new SLRuntimeException(e); + } + + Document document = db.newDocument(); + try { + idLinkFactory.marshallCompressedIdentityLink(compressedIdentityLink, document, null, true); + } catch (JAXBException e) { + log.info("Failed to marshall CompressedIdentityLink.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, + new Object[] { getIdentifier() }); + } + + InfoboxReadResultFileImpl result = new InfoboxReadResultFileImpl(); + ByteArrayOutputStream resultBytes = null; + Result xmlResult = (isXMLEntity() || getDomainIdentifier() != null) + ? result.getXmlResult(true) + : new StreamResult((resultBytes = new ByteArrayOutputStream())); + try { + log.trace("Trying to transform identitylink"); + identityLinkTransformer.transformIdLink(issuerTemplate, new DOMSource(document), xmlResult); + } catch (MalformedURLException e) { + log.warn("Malformed issuer template URL '" + issuerTemplate + "'."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } catch (IOException e) { + log.warn("Failed to dereferene issuer template URL '" + issuerTemplate + "'." ,e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } catch (TransformerConfigurationException e) { + log.warn("Failed to create transformation template from issuer template URL '" + issuerTemplate + "'", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } catch (TransformerException e) { + log.info("Faild to transform CompressedIdentityLink.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + + // TODO: Report BUG in IssuerTemplates + // Some IssuerTemplate stylesheets do not consider the pr:Type-Element of the CompressedIdentityLink ... + if (getDomainIdentifier() != null) { + if (xmlResult instanceof DOMResult) { + Node node = ((DOMResult) xmlResult).getNode(); + Node nextSibling = ((DOMResult) xmlResult).getNextSibling(); + Node idLinkNode; + if (nextSibling != null) { + idLinkNode = nextSibling.getPreviousSibling(); + } else if (node != null) { + idLinkNode = node.getFirstChild(); + } else { + log + .error("An IdentityLinkDomainIdentifier of '" + + getDomainIdentifier() + + "' has been given. However, it cannot be set, as the transformation result does not contain a node."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + IdentityLinkTransformer.setDomainIdentifier(idLinkNode, getDomainIdentifier()); + } else { + log + .error("An IdentityLinkDomainIdentifier of '" + + getDomainIdentifier() + + "' has been given. However, it cannot be set, as the transformation result is not of type DOM."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + } + + if (!isXMLEntity()) { + if (resultBytes == null) { + resultBytes = new ByteArrayOutputStream(); + + if (xmlResult instanceof DOMResult) { + Node node = ((DOMResult) xmlResult).getNode(); + Node nextSibling = ((DOMResult) xmlResult).getNextSibling(); + + DOMSource xmlSource; + if (nextSibling != null) { + xmlSource = new DOMSource(nextSibling.getPreviousSibling()); + } else if (node != null) { + xmlSource = new DOMSource(node.getFirstChild()); + } else { + log + .error("IssuerTemplate transformation returned no node."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + TransformerFactory transformerFactory = TransformerFactory.newInstance(); + try { + Transformer transformer = transformerFactory.newTransformer(); + transformer.transform(xmlSource, new StreamResult(resultBytes)); + } catch (TransformerConfigurationException e) { + log.error(e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } catch (TransformerException e) { + log.error(e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + } else if (xmlResult instanceof StreamResult) { + OutputStream outputStream = ((StreamResult) xmlResult).getOutputStream(); + if (outputStream instanceof ByteArrayOutputStream) { + result.setResultBytes(((ByteArrayOutputStream) outputStream).toByteArray()); + } else { + log.error("ContentIsXMLEntity is set to 'false'. However, an XMLResult has already been set."); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, + new Object[] { issuerTemplate }); + } + } + } else { + result.setResultBytes(resultBytes.toByteArray()); + } + } + + return result; + + } + + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java new file mode 100644 index 00000000..a6f8cbb2 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/Infobox.java @@ -0,0 +1,53 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.bku.slcommands.impl; + +import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; + +/** + * An implementation of this interface represents a infobox as defined in + * Security-Layer 1.2. + * + * @author mcentner + */ +public interface Infobox { + + /** + * @return the identifier of this infobox + */ + public String getIdentifier(); + + /** + * Read data from this infobox. + * + * @param request + * the InfoboxReadRequest + * @param cmdCtx + * the command context + * + * @return the data read from this infobox as InfoboxReadResult + * + * @throws SLCommandException + * if reading from this infobox fails + */ + public InfoboxReadResult read(InfoboxReadRequestType request, + SLCommandContext cmdCtx) throws SLCommandException; + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxFactory.java new file mode 100644 index 00000000..4a03fe74 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxFactory.java @@ -0,0 +1,151 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import java.util.HashMap; +import java.util.Map; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; + +/** + * A factory for creating {@link Infobox}es. + * + * @author mcentner + */ +public class InfoboxFactory { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(InfoboxFactory.class); + + /** + * The singleton instance of this InfoboxFactory. + */ + private static InfoboxFactory instance; + + /** + * @return an instance of this InfoboxFactory + */ + public synchronized static InfoboxFactory getInstance() { + if (instance == null) { + instance = new InfoboxFactory(); + } + return instance; + } + + /** + * The mapping of infobox identifier to implementation class. + */ + private HashMap> implementations; + + /** + * Private constructor. + */ + private InfoboxFactory() { + } + + /** + * Sets the mapping of infobox identifier to implementation class name. + * + * @param infoboxImplMap + * a mapping of infobox identifiers to implementation class names + * + * @throws ClassNotFoundException + * if implementation class is not an instance of {@link Infobox} + */ + @SuppressWarnings("unchecked") + public void setInfoboxImpl(Map infoboxImplMap) throws ClassNotFoundException { + HashMap> implMap = new HashMap>(); + ClassLoader cl = getClass().getClassLoader(); + for (String key : infoboxImplMap.keySet()) { + Class impl = (Class) cl.loadClass(infoboxImplMap.get(key)); + log.debug("Registering infobox '" + key + "' implementation '" + impl.getCanonicalName() + "'."); + implementations.put(key, impl); + } + implementations = implMap; + } + + /** + * Returns the configured implementation class for the given + * infoboxIdentifier. + * + * @param infoboxIdentifier + * the infobox identifier + * + * @return the implementation class for the given infobox identifier or + * null if there is no implementation class configured + */ + public Class getImplClass(String infoboxIdentifier) { + if (implementations != null) { + return implementations.get(infoboxIdentifier); + } else { + return null; + } + } + + /** + * Create a new {@link Infobox} instance for the given + * infoboxIdentifier. + * + * @param infoboxIdentifier + * the infobox identifier + * + * @return an {@link Infobox} implementation for the given infobox identifier + * + * @throws SLCommandException + * if there is no implementation for the given infobox identifier + * @throws SLRuntimeException + * if creating an {@link Infobox} instance fails + */ + public Infobox createInfobox(String infoboxIdentifier) throws SLCommandException, SLRuntimeException { + + Class implClass = getImplClass(infoboxIdentifier); + if (implClass == null) { + // infobox not supported + log.info("Unsupported infobox '" + infoboxIdentifier + "."); + throw new SLCommandException(4002, + SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, + new Object[] { infoboxIdentifier }); + } + + // try to instantiate + Infobox infobox; + try { + infobox = implClass.newInstance(); + log.debug("Infobox '" + infobox.getIdentifier() + "' created."); + } catch (InstantiationException e) { + // unexpected error + log.error("Failed to instantiate infobox implementation.", e); + throw new SLRuntimeException(e); + } catch (IllegalAccessException e) { + // unexpected error + log.error("Failed to instantiate infobox implementation.", e); + throw new SLRuntimeException(e); + } + + return infobox; + + } + + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java index c7bb5205..aaa786a6 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadCommandImpl.java @@ -16,67 +16,14 @@ */ package at.gv.egiz.bku.slcommands.impl; -import iaik.asn1.CodingException; -import iaik.asn1.DerCoder; - -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.net.MalformedURLException; -import java.security.cert.CertificateEncodingException; -import java.security.cert.CertificateException; -import java.security.cert.CertificateFactory; -import java.security.cert.X509Certificate; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; -import java.util.regex.Pattern; - -import javax.xml.bind.JAXBElement; -import javax.xml.bind.JAXBException; -import javax.xml.parsers.DocumentBuilder; -import javax.xml.parsers.DocumentBuilderFactory; -import javax.xml.parsers.ParserConfigurationException; -import javax.xml.transform.Result; -import javax.xml.transform.Transformer; -import javax.xml.transform.TransformerConfigurationException; -import javax.xml.transform.TransformerException; -import javax.xml.transform.TransformerFactory; -import javax.xml.transform.dom.DOMResult; -import javax.xml.transform.dom.DOMSource; -import javax.xml.transform.stream.StreamResult; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; -import org.w3c.dom.Document; -import org.w3c.dom.Node; -import at.buergerkarte.namespaces.personenbindung._20020506_.CompressedIdentityLinkType; -import at.buergerkarte.namespaces.securitylayer._1.AnyChildrenType; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxAssocArrayPairType; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadDataAssocArrayType; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsBinaryFileType; import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadRequestType; -import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadKeys; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadPairs; -import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadValue; import at.gv.egiz.bku.slcommands.InfoboxReadCommand; -import at.gv.egiz.bku.slcommands.SLCommand; import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.bku.slexceptions.SLExceptionMessages; -import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.idlink.CompressedIdentityLinkFactory; -import at.gv.egiz.idlink.IdentityLinkTransformer; -import at.gv.egiz.idlink.ans1.IdentityLink; -import at.gv.egiz.stal.InfoboxReadRequest; -import at.gv.egiz.stal.InfoboxReadResponse; -import at.gv.egiz.stal.STALRequest; /** * This class implements the security layer command @@ -88,7 +35,7 @@ import at.gv.egiz.stal.STALRequest; * * @author mcentner */ -public class InfoboxReadCommandImpl extends SLCommandImpl implements +public class InfoboxReadCommandImpl extends AbstractInfoboxCommandImpl implements InfoboxReadCommand { /** @@ -96,511 +43,63 @@ public class InfoboxReadCommandImpl extends SLCommandImplInfoboxIdentifier - */ - protected String infoboxIdentifier; - - /** - * The IdentityLinkDomainIdentifier value of an IdentyLink infobox. - */ - protected String identityLinkDomainIdentifier; - - /** - * The list of certificates to be read from an Certificates infobox. - */ - protected List certificates; - - /** - * The result type. - */ - protected int assocArrayResult; - - /** - * Is content XML entity? - */ - protected boolean isXMLEntity; - @Override public String getName() { return "InfoboxReadRequest"; } - /** - * @return the infoboxIdentifier - */ - public String getInfoboxIdentifier() { - return infoboxIdentifier; - } - + @Override + protected String getInfoboxIdentifier(InfoboxReadRequestType request) { + return request.getInfoboxIdentifier(); + } + @Override public void init(SLCommandContext ctx, Object request) throws SLCommandException { super.init(ctx, request); InfoboxReadRequestType req = getRequestValue(); - - infoboxIdentifier = req.getInfoboxIdentifier(); - - if (INFOBOX_IDENTIFIER_IDENTITY_LINK.equals(infoboxIdentifier)) { - - if (req.getAssocArrayParameters() != null) { - log.info("Got AssocArrayParameters but Infobox type is BinaryFile."); - throw new SLCommandException(4010); - } - - InfoboxReadParamsBinaryFileType binaryFileParameters = req.getBinaryFileParameters(); - if (binaryFileParameters != null) { - isXMLEntity = binaryFileParameters.isContentIsXMLEntity(); - log.debug("Got ContentIsXMLEntity=" + isXMLEntity + "."); - } - - AnyChildrenType boxSpecificParameters = req.getBoxSpecificParameters(); - - if (boxSpecificParameters != null) { - // check BoxSpecificParameters - List parameter = boxSpecificParameters.getAny(); - JAXBElement element; - if (parameter != null - && parameter.size() == 1 - && parameter.get(0) instanceof JAXBElement - && SLCommand.NAMESPACE_URI.equals((element = (JAXBElement) parameter.get(0)).getName().getNamespaceURI()) - && BOX_SPECIFIC_PARAMETER_IDENTITY_LINK_DOMAIN_IDENTIFIER.equals(element.getName().getLocalPart()) - && element.getValue() instanceof String) { - identityLinkDomainIdentifier = (String) element.getValue(); - log.debug("Got sl:IdentityLinkDomainIdentifier: " + identityLinkDomainIdentifier); - } else { - log.info("Got invalid BoxSpecificParameters."); - throw new SLCommandException(4010); - } - } - } else if (INFOBOX_IDENTIFIER_CERTIFICATES.equals(infoboxIdentifier)) { - - if (req.getBinaryFileParameters() != null) { - log.info("Got BinaryFileParameters but Infobox type is AssocArray."); - throw new SLCommandException(4010); - } - - if (req.getBoxSpecificParameters() != null) { - log.info("Got invalid BoxSpecificParameters."); - throw new SLCommandException(4010); - } - - InfoboxReadParamsAssocArrayType assocArrayParameters = req - .getAssocArrayParameters(); - if (assocArrayParameters == null) { - log.info("Infobox type is AssocArray but got no AssocArrayParameters."); - throw new SLCommandException(4010); - } - - // RreadKeys? - if (assocArrayParameters.getReadKeys() != null) { - assocArrayResult = ASSOC_ARRAY_READ_KEYS; - ReadKeys readKeys = assocArrayParameters.getReadKeys(); - certificates = findCertificates(readKeys.getSearchString()); - if (readKeys.isUserMakesUnique() && certificates.size() > 1) { - log.info("UserMakesUnique not supported"); - // TODO: give more specific error message - throw new SLCommandException(4010); - } - } - - // ReadPairs? - if (assocArrayParameters.getReadPairs() != null) { - assocArrayResult = ASSOC_ARRAY_READ_PAIRS; - ReadPairs readPairs = assocArrayParameters.getReadPairs(); - if (readPairs.isValuesAreXMLEntities()) { - log.info("Got valuesAreXMLEntities but infobox type is binary."); - throw new SLCommandException(4010); - } - certificates = findCertificates(readPairs.getSearchString()); - if (readPairs.isUserMakesUnique() && certificates.size() > 1) { - log.info("UserMakesUnique not supported"); - // TODO: give more specific error message - throw new SLCommandException(4010); - } - } - - // ReadValue - if (assocArrayParameters.getReadValue() != null) { - assocArrayResult = ASSOC_ARRAY_READ_VALUE; - ReadValue readValue = assocArrayParameters.getReadValue(); - if (readValue.isValueIsXMLEntity()) { - log.info("Got valuesAreXMLEntities but infobox type is binary."); - throw new SLCommandException(4010); - } - String key = readValue.getKey(); - if (Arrays.asList(INFOXBOX_CERTIFICATES_KEYS).contains(key)) { - certificates = Collections.singletonList(key); - } else { - certificates = Collections.emptyList(); - } - } - - if (assocArrayResult == 0) { - log.info("Infobox type is AssocArray but got invalid AssocArrayParameters."); - throw new SLCommandException(4010); - } - - } else { - throw new SLCommandException(4002, - SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, - new Object[] { infoboxIdentifier }); - } + if (req.getAssocArrayParameters() != null && + !(infobox instanceof AssocArrayInfobox)) { + log.info("Got AssocArrayParameters but Infobox type is not AssocArray."); + throw new SLCommandException(4010); + } + + if (req.getBinaryFileParameters() != null && + !(infobox instanceof BinaryFileInfobox)) { + log.info("Got BinaryFileParameters but Infobox type is not BinaryFile."); + throw new SLCommandException(4010); + } } @Override public SLResult execute() { - try { - if (INFOBOX_IDENTIFIER_IDENTITY_LINK.equals(infoboxIdentifier)) { - return readIdentityLink(); - } else if (INFOBOX_IDENTIFIER_CERTIFICATES.equals(infoboxIdentifier)) { - return readCertificates(); - } else { - throw new SLCommandException(4000); - } - } catch (SLCommandException e) { - return new ErrorResultImpl(e, cmdCtx.getLocale()); - } - } - - /** - * Gets the IdentitiyLink form the next STAL response. - * - * @return the IdentityLink - * - * @throws SLCommandException if getting the IdentitiyLink fails - */ - private IdentityLink getIdentityLinkFromResponses() throws SLCommandException { - - // IdentityLink - InfoboxReadResponse response; - if (hasNextResponse()) { - response = (InfoboxReadResponse) nextResponse(InfoboxReadResponse.class); - byte[] idLink = response.getInfoboxValue(); - try { - return new IdentityLink(DerCoder.decode(idLink)); - } catch (CodingException e) { - log.info("Failed to decode infobox '" + INFOBOX_IDENTIFIER_IDENTITY_LINK + "'.", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, - new Object[] { INFOBOX_IDENTIFIER_IDENTITY_LINK }); - } - } else { - log.info("No infobox '" + INFOBOX_IDENTIFIER_IDENTITY_LINK + "' returned from STAL."); - throw new SLCommandException(4000); - } - - } - - /** - * Gets the list of certificates from the next STAL responses. - * - * @return the list of certificates - * - * @throws SLCommandException if getting the list of certificates fails - */ - private List getCertificatesFromResponses() throws SLCommandException { - - List certificates = new ArrayList(); - - CertificateFactory certFactory; - try { - certFactory = CertificateFactory.getInstance("X509"); - } catch (CertificateException e) { - // we should always be able to get an X509 certificate factory - log.error("CertificateFactory.getInstance(\"X509\") failed.", e); - throw new SLRuntimeException(e); - } - - InfoboxReadResponse response; - while(hasNextResponse()) { - response = (InfoboxReadResponse) nextResponse(InfoboxReadResponse.class); - byte[] cert = response.getInfoboxValue(); - try { - certificates.add((X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(cert))); - } catch (CertificateException e) { - log.info("Failed to decode certificate.", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, - new Object[] { INFOBOX_IDENTIFIER_CERTIFICATES }); - } - } - - return certificates; - - } - - /** - * Uses STAL to read the IdentityLink. - * - * @return the corresponding security layer result - * - * @throws SLCommandException if reading the IdentityLink fails - */ - private SLResult readIdentityLink() throws SLCommandException { - - List stalRequests = new ArrayList(); - - InfoboxReadRequest infoboxReadRequest; - // get raw identity link - infoboxReadRequest = new InfoboxReadRequest(); - infoboxReadRequest.setInfoboxIdentifier(INFOBOX_IDENTIFIER_IDENTITY_LINK); - infoboxReadRequest.setDomainIdentifier(identityLinkDomainIdentifier); - stalRequests.add(infoboxReadRequest); - - // get certificates - infoboxReadRequest = new InfoboxReadRequest(); - infoboxReadRequest.setInfoboxIdentifier("SecureSignatureKeypair"); - stalRequests.add(infoboxReadRequest); - infoboxReadRequest = new InfoboxReadRequest(); - infoboxReadRequest.setInfoboxIdentifier("CertifiedKeypair"); - stalRequests.add(infoboxReadRequest); - - requestSTAL(stalRequests); - log.trace("Got STAL response"); - - IdentityLink identityLink = getIdentityLinkFromResponses(); - List certificates = getCertificatesFromResponses(); - - - CompressedIdentityLinkFactory idLinkFactory = CompressedIdentityLinkFactory.getInstance(); - JAXBElement compressedIdentityLink = idLinkFactory - .createCompressedIdentityLink(identityLink, certificates, identityLinkDomainIdentifier); - - IdentityLinkTransformer identityLinkTransformer = IdentityLinkTransformer.getInstance(); - String issuerTemplate = identityLink.getIssuerTemplate(); - - DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance(); - DocumentBuilder db; - try { - db = dbf.newDocumentBuilder(); - } catch (ParserConfigurationException e) { - log.error("Failed to create XML document.", e); - throw new SLRuntimeException(e); - } - - Document document = db.newDocument(); - try { - idLinkFactory.marshallCompressedIdentityLink(compressedIdentityLink, document, null, true); - } catch (JAXBException e) { - log.info("Failed to marshall CompressedIdentityLink.", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, - new Object[] { INFOBOX_IDENTIFIER_IDENTITY_LINK }); - } - - InfoboxReadResultFileImpl result = new InfoboxReadResultFileImpl(); - ByteArrayOutputStream resultBytes = null; - Result xmlResult = (isXMLEntity || identityLinkDomainIdentifier != null) - ? result.getXmlResult(true) - : new StreamResult((resultBytes = new ByteArrayOutputStream())); + try { - log.trace("Trying to transform identitylink"); - identityLinkTransformer.transformIdLink(issuerTemplate, new DOMSource(document), xmlResult); - } catch (MalformedURLException e) { - log.warn("Malformed issuer template URL '" + issuerTemplate + "'."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } catch (IOException e) { - log.warn("Failed to dereferene issuer template URL '" + issuerTemplate + "'." ,e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } catch (TransformerConfigurationException e) { - log.warn("Failed to create transformation template from issuer template URL '" + issuerTemplate + "'", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } catch (TransformerException e) { - log.info("Faild to transform CompressedIdentityLink.", e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - - // TODO: Report BUG in IssuerTemplates - // Some IssuerTemplate stylesheets do not consider the pr:Type-Element of the CompressedIdentityLink ... - if (identityLinkDomainIdentifier != null) { - if (xmlResult instanceof DOMResult) { - Node node = ((DOMResult) xmlResult).getNode(); - Node nextSibling = ((DOMResult) xmlResult).getNextSibling(); - Node idLinkNode; - if (nextSibling != null) { - idLinkNode = nextSibling.getPreviousSibling(); - } else if (node != null) { - idLinkNode = node.getFirstChild(); - } else { - log - .error("An IdentityLinkDomainIdentifier of '" - + identityLinkDomainIdentifier - + "' has been given. However, it cannot be set, as the transformation result does not contain a node."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - IdentityLinkTransformer.setDomainIdentifier(idLinkNode, identityLinkDomainIdentifier); - } else { - log - .error("An IdentityLinkDomainIdentifier of '" - + identityLinkDomainIdentifier - + "' has been given. However, it cannot be set, as the transformation result is not of type DOM."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - } - - if (!isXMLEntity) { - if (resultBytes == null) { - resultBytes = new ByteArrayOutputStream(); - - if (xmlResult instanceof DOMResult) { - Node node = ((DOMResult) xmlResult).getNode(); - Node nextSibling = ((DOMResult) xmlResult).getNextSibling(); - - DOMSource xmlSource; - if (nextSibling != null) { - xmlSource = new DOMSource(nextSibling.getPreviousSibling()); - } else if (node != null) { - xmlSource = new DOMSource(node.getFirstChild()); - } else { - log - .error("IssuerTemplate transformation returned no node."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - TransformerFactory transformerFactory = TransformerFactory.newInstance(); - try { - Transformer transformer = transformerFactory.newTransformer(); - transformer.transform(xmlSource, new StreamResult(resultBytes)); - } catch (TransformerConfigurationException e) { - log.error(e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } catch (TransformerException e) { - log.error(e); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - } else if (xmlResult instanceof StreamResult) { - OutputStream outputStream = ((StreamResult) xmlResult).getOutputStream(); - if (outputStream instanceof ByteArrayOutputStream) { - result.setResultBytes(((ByteArrayOutputStream) outputStream).toByteArray()); - } else { - log.error("ContentIsXMLEntity is set to 'false'. However, an XMLResult has already been set."); - throw new SLCommandException(4000, - SLExceptionMessages.EC4000_UNCLASSIFIED_IDLINK_TRANSFORMATION_FAILED, - new Object[] { issuerTemplate }); - } - } - } else { - result.setResultBytes(resultBytes.toByteArray()); - } - } - - - return result; - - } - - protected List findCertificates(String searchString) throws SLCommandException { - - if ("*".equals(searchString) || "**".equals(searchString)) { - return Arrays.asList(INFOXBOX_CERTIFICATES_KEYS); + return infobox.read(getRequestValue(), getCmdCtx()); + } catch (SLCommandException e) { + return new ErrorResultImpl(e, getCmdCtx().getLocale()); } - if (Pattern.matches(SEARCH_STRING_PATTERN, searchString)) { - -// for (int i = 0; i < searchString.length(); i++) { -// int codePoint = searchString.codePointAt(i); -// -// } - - // TODO : build pattern - return Collections.emptyList(); + } + + + @Override + public String getIdentityLinkDomainId() { + if (infobox instanceof IdentityLinkInfoboxImpl) { + return ((IdentityLinkInfoboxImpl) infobox).getDomainIdentifier(); } else { - log.info("Got invalid search string '" + searchString + "'"); - throw new SLCommandException(4010); + return null; } - } - private SLResult readCertificates() throws SLCommandException { - - ObjectFactory objectFactory = new ObjectFactory(); - - InfoboxReadDataAssocArrayType infoboxReadDataAssocArrayType = objectFactory - .createInfoboxReadDataAssocArrayType(); - - if (assocArrayResult == ASSOC_ARRAY_READ_KEYS) { - - List keys = infoboxReadDataAssocArrayType.getKey(); - keys.addAll(certificates); - + @Override + public String getInfoboxIdentifier() { + if (infobox != null) { + return infobox.getIdentifier(); } else { - - if (certificates != null && !certificates.isEmpty()) { - - List stalRequests = new ArrayList(); - - // get certificates - InfoboxReadRequest infoboxReadRequest; - for (int i = 0; i < certificates.size(); i++) { - infoboxReadRequest = new InfoboxReadRequest(); - infoboxReadRequest.setInfoboxIdentifier(certificates.get(i)); - stalRequests.add(infoboxReadRequest); - } - - requestSTAL(stalRequests); - - List x509Certs = getCertificatesFromResponses(); - - for (int i = 0; i < certificates.size(); i++) { - InfoboxAssocArrayPairType infoboxAssocArrayPairType = objectFactory.createInfoboxAssocArrayPairType(); - infoboxAssocArrayPairType.setKey(certificates.get(i)); - try { - infoboxAssocArrayPairType.setBase64Content(x509Certs.get(i).getEncoded()); - } catch (CertificateEncodingException e) { - log.error("Failed to encode certificate.", e); - throw new SLCommandException(4000); - } - infoboxReadDataAssocArrayType.getPair().add(infoboxAssocArrayPairType); - } - - } - + return null; } - - return new InfoboxReadResultImpl(infoboxReadDataAssocArrayType); - - } - - @Override - public String getIdentityLinkDomainId() { - return identityLinkDomainIdentifier; } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java index 8904eac6..a2b8ac9f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java @@ -23,8 +23,9 @@ import javax.xml.transform.Templates; import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadDataAssocArrayType; import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadResponseType; import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.gv.egiz.bku.slcommands.InfoboxReadResult; -public class InfoboxReadResultImpl extends SLResultImpl { +public class InfoboxReadResultImpl extends SLResultImpl implements InfoboxReadResult { /** * The InfoboxReadResponse diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateCommandImpl.java new file mode 100644 index 00000000..6d281686 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateCommandImpl.java @@ -0,0 +1,158 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.buergerkarte.namespaces.cardchannel.CommandAPDUType; +import at.buergerkarte.namespaces.cardchannel.ResetType; +import at.buergerkarte.namespaces.cardchannel.ScriptType; +import at.buergerkarte.namespaces.cardchannel.VerifyAPDUType; +import at.buergerkarte.namespaces.securitylayer._1.Base64XMLContentType; +import at.buergerkarte.namespaces.securitylayer._1.InfoboxUpdateRequestType; +import at.gv.egiz.bku.slcommands.InfoboxUpdateCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; + +public class InfoboxUpdateCommandImpl extends + SLCommandImpl implements InfoboxUpdateCommand { + + private static Log log = LogFactory.getLog(InfoboxUpdateCommandImpl.class); + + public static final String INFOBOX_IDENTIFIER_CARD_CHANNEL = "CardChannel"; + + protected String infoboxIdentifier; + + protected List cardChannelScript; + + @Override + public String getInfoboxIdentifier() { + return infoboxIdentifier; + } + + @Override + public void init(SLCommandContext ctx, Object request) + throws SLCommandException { + super.init(ctx, request); + + InfoboxUpdateRequestType req = getRequestValue(); + + infoboxIdentifier = req.getInfoboxIdentifier(); + + if (INFOBOX_IDENTIFIER_CARD_CHANNEL.equals(infoboxIdentifier)) { + + if (req.getAssocArrayParameters() != null) { + log.info("Got AssocArrayParameters but Infobox type is BinaryFile."); + throw new SLCommandException(4010); + } + + Base64XMLContentType binaryFileParameters = req.getBinaryFileParameters(); + if (binaryFileParameters == null) { + log.info("Got no BinaryFileParameters but Infobox type is BinaryFile."); + throw new SLCommandException(4010); + } + + if (binaryFileParameters.getBase64Content() == null) { + log.info("Got Base64Content but ContentIsXMLEntity is true."); + throw new SLCommandException(4010); + } + + List content = binaryFileParameters.getXMLContent().getContent(); + if (content.isEmpty()) { + log.info("Got no XMLContent but ContentIsXMLEntity is true."); + throw new SLCommandException(4010); + } + + for (Object element : content) { + if (!(element instanceof ScriptType)) { + log.info("Infobox identifier is '" + infoboxIdentifier + "' but XMLContent does not contain 'Script'."); + throw new SLCommandException(4010); + } + + setCardChannelScript(((ScriptType) element).getResetOrCommandAPDUOrVerifyAPDU()); + } + + if (getCardChannelScript() == null) { + log.info("Infobox identifier is '" + infoboxIdentifier + "' but XMLContent does not contain 'Script'."); + throw new SLCommandException(4010); + } + + } else { + throw new SLCommandException(4002, + SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, + new Object[] { infoboxIdentifier }); + } + + } + + public List getCardChannelScript() { + return cardChannelScript; + } + + public void setCardChannelScript(List cardChannelScript) { + this.cardChannelScript = cardChannelScript; + } + + @Override + public SLResult execute() { + + try { + if (INFOBOX_IDENTIFIER_CARD_CHANNEL.equals(getInfoboxIdentifier())) { + + executeCardChannelScript(); + return new InfoboxUpdateResultImpl(); + + } else { + throw new SLCommandException(4002, + SLExceptionMessages.EC4002_INFOBOX_UNKNOWN, + new Object[] { infoboxIdentifier }); + } + } catch (SLCommandException e) { + return new ErrorResultImpl(e, cmdCtx.getLocale()); + } + + } + + protected void executeCardChannelScript() throws SLCommandException { + + if (cardChannelScript != null) { + + for (Object element : cardChannelScript) { + if (element instanceof ResetType) { + + } else if (element instanceof CommandAPDUType) { + + } else if (element instanceof VerifyAPDUType) { + + } + } + + } + + } + + @Override + public String getName() { + return "InfoboxUpdateRequest"; + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java new file mode 100644 index 00000000..15064756 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java @@ -0,0 +1,43 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import javax.xml.bind.JAXBElement; +import javax.xml.transform.Result; +import javax.xml.transform.Templates; + +import at.buergerkarte.namespaces.securitylayer._1.InfoboxUpdateResponseType; +import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; +import at.gv.egiz.bku.slcommands.InfoboxUpdateResult; + +public class InfoboxUpdateResultImpl extends SLResultImpl implements + InfoboxUpdateResult { + + protected static JAXBElement RESPONSE; + + static { + ObjectFactory factory = new ObjectFactory(); + InfoboxUpdateResponseType type = factory.createInfoboxUpdateResponseType(); + RESPONSE = factory.createInfoboxUpdateResponse(type); + } + + @Override + public void writeTo(Result result, Templates templates) { + writeTo(RESPONSE, result, templates); + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLCommandImpl.java index 9a3a2984..ed055b69 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLCommandImpl.java @@ -16,22 +16,11 @@ */ package at.gv.egiz.bku.slcommands.impl; -import java.util.Iterator; -import java.util.List; -import java.util.NoSuchElementException; - -import javax.xml.bind.JAXBElement; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.slcommands.SLCommand; -import at.gv.egiz.bku.slcommands.SLCommandContext; -import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.stal.ErrorResponse; -import at.gv.egiz.stal.STAL; -import at.gv.egiz.stal.STALRequest; -import at.gv.egiz.stal.STALResponse; +import javax.xml.bind.JAXBElement; + +import at.gv.egiz.bku.slcommands.SLCommand; +import at.gv.egiz.bku.slcommands.SLCommandContext; +import at.gv.egiz.bku.slexceptions.SLCommandException; /** * This class serves as abstract base class for the implementation of a security @@ -47,19 +36,18 @@ public abstract class SLCommandImpl implements SLCommand { /** * The SLCommandContext for this SLCommand. */ - protected SLCommandContext cmdCtx; + protected SLCommandContext cmdCtx; + + /** + * The STAL helper. + */ + protected STALHelper stalHelper; /** * The request element of this command. */ protected JAXBElement request; - /** - * An iterator over the STALResponses received in - * {@link SLCommandImpl#requestSTAL(List)}. - */ - protected Iterator stalResponses; - @SuppressWarnings("unchecked") @Override public void init(SLCommandContext ctx, Object request) @@ -67,8 +55,8 @@ public abstract class SLCommandImpl implements SLCommand { this.request = (JAXBElement) request; - this.cmdCtx = ctx; - assert this.cmdCtx != null; + this.cmdCtx = ctx; + stalHelper = new STALHelper(cmdCtx.getSTAL()); } @@ -90,73 +78,4 @@ public abstract class SLCommandImpl implements SLCommand { protected SLCommandContext getCmdCtx() { return cmdCtx; } - - /** - * Calls {@link STAL#handleRequest(List)} with the given - * stalRequests. - * - * @param stalRequests - * @throws SLCommandException - */ - protected void requestSTAL(List stalRequests) throws SLCommandException { - List responses = cmdCtx.getSTAL().handleRequest(stalRequests); - if (responses == null) { - Log log = LogFactory.getLog(this.getClass()); - log.info("Received no responses from STAL."); - throw new SLCommandException(4000); - } else if (responses.size() != stalRequests.size()) { - Log log = LogFactory.getLog(this.getClass()); - log.info("Received invalid count of responses from STAL. Expected " - + stalRequests.size() + ", but got " + responses.size() + "."); - // throw new SLCommandException(4000); - } - stalResponses = responses.iterator(); - } - - /** - * @return true if there are more {@link STALResponse}s to be - * fetched with {@link #nextResponse(Class)}, or false - * otherwise. - */ - protected boolean hasNextResponse() { - return (stalResponses != null) ? stalResponses.hasNext() : false; - } - - /** - * Returns the next response of type responseClass that has been - * received by {@link #requestSTAL(List)}. - * - * @param responseClass - * the response must be an instance of - * @return the next response of type responseClass - * - * @throws NoSuchElementException - * if there is no more response - * @throws SLCommandException - * if the next response is of type {@link ErrorResponse} or not of - * type responseClass - */ - protected STALResponse nextResponse( - Class responseClass) throws SLCommandException { - - if (stalResponses == null) { - throw new NoSuchElementException(); - } - - STALResponse response = stalResponses.next(); - - if (response instanceof ErrorResponse) { - throw new SLCommandException(((ErrorResponse) response).getErrorCode()); - } - - if (!(responseClass.isAssignableFrom(response.getClass()))) { - Log log = LogFactory.getLog(this.getClass()); - log.info("Received " + response.getClass() + " from STAL but expected " - + responseClass); - throw new SLCommandException(4000); - } - - return response; - - } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java new file mode 100644 index 00000000..969288c1 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java @@ -0,0 +1,218 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands.impl; + +import iaik.asn1.CodingException; +import iaik.asn1.DerCoder; + +import java.io.ByteArrayInputStream; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slexceptions.SLCommandException; +import at.gv.egiz.bku.slexceptions.SLExceptionMessages; +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.idlink.ans1.IdentityLink; +import at.gv.egiz.stal.ErrorResponse; +import at.gv.egiz.stal.InfoboxReadResponse; +import at.gv.egiz.stal.STAL; +import at.gv.egiz.stal.STALRequest; +import at.gv.egiz.stal.STALResponse; + +/** + * A helper class for transmitting {@link STALRequest}s and obtaining their + * respective {@link STALResponse}s. + * + * @author mcentner + */ +public class STALHelper { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(STALHelper.class); + + /** + * The STAL implementation. + */ + private STAL stal; + + /** + * An iterator over the STALResponses received in + * {@link SLCommandImpl#transmitSTALRequest(List)}. + */ + protected Iterator stalResponses; + + /** + * Creates a new instance of this STALHelper with the given + * stal. + * + * @param stal the STAL to be used + */ + public STALHelper(STAL stal) { + if (stal == null) { + throw new NullPointerException("Argument 'stal' must not be null."); + } + this.stal = stal; + } + + /** + * Calls {@link STAL#handleRequest(List)} with the given + * stalRequests. + * + * @param stalRequests + * @throws SLCommandException + */ + public void transmitSTALRequest(List stalRequests) throws SLCommandException { + List responses = stal.handleRequest(stalRequests); + if (responses == null) { + Log log = LogFactory.getLog(this.getClass()); + log.info("Received no responses from STAL."); + throw new SLCommandException(4000); + } else if (responses.size() != stalRequests.size()) { + Log log = LogFactory.getLog(this.getClass()); + log.info("Received invalid count of responses from STAL. Expected " + + stalRequests.size() + ", but got " + responses.size() + "."); + // throw new SLCommandException(4000); + } + stalResponses = responses.iterator(); + } + + /** + * @return true if there are more {@link STALResponse}s to be + * fetched with {@link #nextResponse(Class)}, or false + * otherwise. + */ + public boolean hasNextResponse() { + return (stalResponses != null) ? stalResponses.hasNext() : false; + } + + /** + * Returns the next response of type responseClass that has been + * received by {@link #transmitSTALRequest(List)}. + * + * @param responseClass + * the response must be an instance of + * @return the next response of type responseClass + * + * @throws NoSuchElementException + * if there is no more response + * @throws SLCommandException + * if the next response is of type {@link ErrorResponse} or not of + * type responseClass + */ + public STALResponse nextResponse( + Class responseClass) throws SLCommandException { + + if (stalResponses == null) { + throw new NoSuchElementException(); + } + + STALResponse response = stalResponses.next(); + + if (response instanceof ErrorResponse) { + throw new SLCommandException(((ErrorResponse) response).getErrorCode()); + } + + if (!(responseClass.isAssignableFrom(response.getClass()))) { + Log log = LogFactory.getLog(this.getClass()); + log.info("Received " + response.getClass() + " from STAL but expected " + + responseClass); + throw new SLCommandException(4000); + } + + return response; + + } + + /** + * Gets the list of certificates from the next STAL responses. + * + * @return the list of certificates + * + * @throws SLCommandException if getting the list of certificates fails + */ + public List getCertificatesFromResponses() throws SLCommandException { + + List certificates = new ArrayList(); + + CertificateFactory certFactory; + try { + certFactory = CertificateFactory.getInstance("X509"); + } catch (CertificateException e) { + // we should always be able to get an X509 certificate factory + log.error("CertificateFactory.getInstance(\"X509\") failed.", e); + throw new SLRuntimeException(e); + } + + InfoboxReadResponse response; + while(hasNextResponse()) { + response = (InfoboxReadResponse) nextResponse(InfoboxReadResponse.class); + byte[] cert = response.getInfoboxValue(); + try { + certificates.add((X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(cert))); + } catch (CertificateException e) { + log.info("Failed to decode certificate.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, + new Object[] { "Certificates" }); + } + } + + return certificates; + + } + + /** + * Gets the IdentitiyLink form the next STAL response. + * + * @return the IdentityLink + * + * @throws SLCommandException if getting the IdentitiyLink fails + */ + public IdentityLink getIdentityLinkFromResponses() throws SLCommandException { + + // IdentityLink + InfoboxReadResponse response; + if (hasNextResponse()) { + response = (InfoboxReadResponse) nextResponse(InfoboxReadResponse.class); + byte[] idLink = response.getInfoboxValue(); + try { + return new IdentityLink(DerCoder.decode(idLink)); + } catch (CodingException e) { + log.info("Failed to decode infobox 'IdentityLink'.", e); + throw new SLCommandException(4000, + SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, + new Object[] { "IdentityLink" }); + } + } else { + log.info("No infobox 'IdentityLink' returned from STAL."); + throw new SLCommandException(4000); + } + + } + + +} diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml deleted file mode 100644 index 885e35f3..00000000 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml +++ /dev/null @@ -1,36 +0,0 @@ - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml new file mode 100644 index 00000000..13365931 --- /dev/null +++ b/bkucommon/src/test/resources/at/gv/egiz/bku/slcommands/testApplicationContext.xml @@ -0,0 +1,53 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file -- cgit v1.2.3 From bd070e82c276afb8c1c3a9ddc3b5712783760881 Mon Sep 17 00:00:00 2001 From: mcentner Date: Tue, 29 Sep 2009 17:36:06 +0000 Subject: Logging issues fixed: - Added possibility to configure logging of BKUWebstart. Logging is now configured from log4j configuration deployed with BKUWebstart in a first step. In a second step the webstart launcher looks for a log4j configuration file in the user's mooca configuration directory and updates the log4j configuration. - Logging of IAIK PKI properly initialized. IAIK PKI does not mess with the log4j configuration any longer. - Changed log4j accordingly (an appender is now needed as IAIK PKI does not reconfigure log4j any longer). Added css-stylesheet to ErrorResponses issued by the BKU to improve the presentation to the user. Changed dependencies of BKUWebStart (see Issue#469 https://egovlabs.gv.at/tracker/index.php?func=detail&aid=469&group_id=13&atid=134). DataURLConnection now uses the request encoding of SL < 1.2. application/x-www-form-urlencoded is now used as default encoding method. multipart/form-data is used only if transfer parameters are present in the request that require a Content-Type parameter. This can only be set with multipart/form-data. This is not in conformance with SL 1.2, however it should improve compatibility with applications. Therefore, removed the ability to configure the DataURLConnection implementation class. DataURLConnection now uses a streaming implementation for encoding of application/x-www-form-urlencoded requests. XWWWFormUrlImputDecoder now uses a streaming implementation for decoding of application/x-www-form-urlencoded requests. Fixed Bug in SLResultPart that caused a binary response to be provided as parameter "XMLResponse" in a multipart/form-data encoded request to DataURL. SLCommandFactory now supports unmarshalling of SL < 1.2 requests in order issue meaningful error messages. Therefore, the marshaling context for response marshaling had to be separated from the marshaling context for requests in order to avoid the marshaling of SL < 1.2 namespace prefixes in SL 1.2 responses. Target attribute in QualifiedProperties is now marshaled. (see Issue#470 https://egovlabs.gv.at/tracker/index.php?func=detail&aid=470&group_id=13&atid=134) Reporting of XML validation errors improved. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@510 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- BKULocal/src/main/resources/log4j.properties | 2 +- BKULocal/src/main/webapp/errorresponse.css | 12 + BKUOnline/src/main/webapp/errorresponse.css | 12 + BKUWebStart/pom.xml | 14 +- .../java/at/gv/egiz/bku/webstart/Configurator.java | 26 +- .../java/at/gv/egiz/bku/webstart/Container.java | 11 +- .../java/at/gv/egiz/bku/webstart/Launcher.java | 22 +- .../gv/egiz/bku/webstart/LogSecurityManager.java | 9 +- .../java/at/gv/egiz/bku/webstart/TLSServerCA.java | 9 +- .../at/gv/egiz/bku/webstart/gui/AboutDialog.java | 7 +- .../bku/webstart/gui/PINManagementInvoker.java | 7 +- BKUWebStart/src/main/resources/log4j.properties | 20 +- .../at/gv/egiz/bku/webstart/ConfiguratorTest.java | 2 - BKUWebStartPackage/pom.xml | 3 +- .../main/java/at/gv/egiz/bku/binding/DataUrl.java | 9 +- .../at/gv/egiz/bku/binding/DataUrlConnection.java | 2 +- .../gv/egiz/bku/binding/DataUrlConnectionImpl.java | 342 ++++++- .../gv/egiz/bku/binding/HTTPBindingProcessor.java | 29 +- .../bku/binding/LegacyDataUrlConnectionImpl.java | 259 ----- .../egiz/bku/binding/XWWWFormUrlInputDecoder.java | 83 +- .../egiz/bku/binding/XWWWFormUrlInputIterator.java | 376 +++++++ .../egiz/bku/binding/multipart/SLResultPart.java | 41 +- .../at/gv/egiz/bku/conf/CertValidatorImpl.java | 24 + .../java/at/gv/egiz/bku/conf/IAIKCommonsLog.java | 144 +++ .../at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java | 59 ++ .../gv/egiz/bku/slcommands/SLCommandFactory.java | 51 +- .../egiz/bku/slcommands/SLMarshallerFactory.java | 172 ++++ .../java/at/gv/egiz/bku/slcommands/SLResult.java | 8 +- .../slcommands/impl/AbstractAssocArrayInfobox.java | 13 +- .../impl/CreateXMLSignatureResultImpl.java | 15 +- .../egiz/bku/slcommands/impl/ErrorResultImpl.java | 6 +- .../bku/slcommands/impl/GetStatusCommandImpl.java | 2 - .../bku/slcommands/impl/GetStatusResultImpl.java | 4 +- .../slcommands/impl/IdentityLinkInfoboxImpl.java | 1 - .../slcommands/impl/InfoboxReadResultFileImpl.java | 15 +- .../bku/slcommands/impl/InfoboxReadResultImpl.java | 4 +- .../slcommands/impl/InfoboxUpdateResultImpl.java | 4 +- .../slcommands/impl/NullOperationResultImpl.java | 4 +- .../gv/egiz/bku/slcommands/impl/SLResultImpl.java | 94 +- .../egiz/bku/slcommands/impl/xsect/DataObject.java | 1 - .../egiz/bku/slcommands/impl/xsect/Signature.java | 18 +- .../egiz/bku/slexceptions/SLExceptionMessages.java | 6 + .../egiz/bku/slexceptions/SLVersionException.java | 28 + .../egiz/bku/slcommands/schema/Core.20020225.xsd | 33 + .../egiz/bku/slcommands/schema/Core.20020831.xsd | 10 + .../slexceptions/SLExceptionMessages.properties | 7 +- .../slexceptions/SLExceptionMessages_en.properties | 4 + .../bku/binding/XWWWFormUrlInputIteratorTest.java | 152 +++ .../egiz/bku/slcommands/SLCommandFactoryTest.java | 7 +- .../impl/CreateXMLSignatureComandImplTest.java | 9 +- .../bku/slcommands/impl/ErrorResultImplTest.java | 2 +- .../slcommands/impl/InfoboxReadComandImplTest.java | 9 +- .../impl/NullOperationResultImplTest.java | 2 +- .../impl/SVPersonendatenInfoboxImplTest.java | 15 +- .../securitylayer/_1/TransformsInfoType.java | 21 +- .../_20020225_/ErrorResponseType.java | 98 ++ .../securitylayer/_20020225_/ObjectFactory.java | 280 ++++++ .../securitylayer/_20020225_/package-info.java | 9 + .../securitylayer/_20020831_/ObjectFactory.java | 112 +++ .../gv/egiz/bku/utils/URLEncodingInputStream.java | 62 ++ .../gv/egiz/bku/utils/URLEncodingOutputStream.java | 134 +++ .../at/gv/egiz/bku/utils/URLEncodingWriter.java | 57 ++ .../java/at/gv/egiz/marshal/MarshallerFactory.java | 12 +- .../java/at/gv/egiz/marshal/NamespacePrefix.java | 34 - .../gv/egiz/marshal/NamespacePrefixMapperImpl.java | 54 +- .../ReportingValidationEventHandler.java | 64 ++ .../gv/egiz/validation/ValidationEventLogger.java | 55 - .../gv/egiz/xades/QualifyingPropertiesFactory.java | 8 +- .../bku/utils/URLEncodingOutputStreamTest.java | 147 +++ utils/src/test/resources/BigRequest.xml | 1060 ++++++++++++++++++++ 70 files changed, 3704 insertions(+), 723 deletions(-) create mode 100644 BKULocal/src/main/webapp/errorresponse.css create mode 100644 BKUOnline/src/main/webapp/errorresponse.css delete mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIterator.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLog.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLMarshallerFactory.java create mode 100644 bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLVersionException.java create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd create mode 100644 bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd create mode 100644 bkucommon/src/test/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIteratorTest.java create mode 100644 utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ErrorResponseType.java create mode 100644 utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ObjectFactory.java create mode 100644 utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/package-info.java create mode 100644 utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020831_/ObjectFactory.java create mode 100644 utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingInputStream.java create mode 100644 utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingOutputStream.java create mode 100644 utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingWriter.java delete mode 100644 utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java create mode 100644 utils/src/main/java/at/gv/egiz/validation/ReportingValidationEventHandler.java delete mode 100644 utils/src/main/java/at/gv/egiz/validation/ValidationEventLogger.java create mode 100644 utils/src/test/java/at/gv/egiz/bku/utils/URLEncodingOutputStreamTest.java create mode 100644 utils/src/test/resources/BigRequest.xml (limited to 'bkucommon/src/main/resources') diff --git a/BKULocal/src/main/resources/log4j.properties b/BKULocal/src/main/resources/log4j.properties index 8dc8644c..86ddc7b4 100644 --- a/BKULocal/src/main/resources/log4j.properties +++ b/BKULocal/src/main/resources/log4j.properties @@ -15,7 +15,7 @@ # assume log4j to be configured by servlet container (java web start) # loglever DEBUG, appender STDOUT -#log4j.rootLogger=DEBUG, STDOUT +log4j.rootLogger=DEBUG, STDOUT # STDOUT appender log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender diff --git a/BKULocal/src/main/webapp/errorresponse.css b/BKULocal/src/main/webapp/errorresponse.css new file mode 100644 index 00000000..41402e71 --- /dev/null +++ b/BKULocal/src/main/webapp/errorresponse.css @@ -0,0 +1,12 @@ +@CHARSET "UTF-8"; +sl\:ErrorResponse {margin: 0.5em; display: block;} +sl\:ErrorCode {display: inline;} +sl\:Info {display: inline;} + +ErrorResponse:lang(de):before {content: "Bei der Verarbeitung der Anfrage durch die Bürgerkartenumgebung ist ein Fehler aufgetreten: "; font-weight: bolder;} +ErrorResponse:before {content: "An error has occoured upon request processing by the citizen card software: "; font-weight: bold;} +ErrorResponse {margin: 0.5em; display: block;} +ErrorCode:lang(de):before {content: "Fehler-Code: ";} +ErrorCode:before {content: "Error Code: ";} +ErrorCode {display: block;} +Info {display: block;} \ No newline at end of file diff --git a/BKUOnline/src/main/webapp/errorresponse.css b/BKUOnline/src/main/webapp/errorresponse.css new file mode 100644 index 00000000..41402e71 --- /dev/null +++ b/BKUOnline/src/main/webapp/errorresponse.css @@ -0,0 +1,12 @@ +@CHARSET "UTF-8"; +sl\:ErrorResponse {margin: 0.5em; display: block;} +sl\:ErrorCode {display: inline;} +sl\:Info {display: inline;} + +ErrorResponse:lang(de):before {content: "Bei der Verarbeitung der Anfrage durch die Bürgerkartenumgebung ist ein Fehler aufgetreten: "; font-weight: bolder;} +ErrorResponse:before {content: "An error has occoured upon request processing by the citizen card software: "; font-weight: bold;} +ErrorResponse {margin: 0.5em; display: block;} +ErrorCode:lang(de):before {content: "Fehler-Code: ";} +ErrorCode:before {content: "Error Code: ";} +ErrorCode {display: block;} +Info {display: block;} \ No newline at end of file diff --git a/BKUWebStart/pom.xml b/BKUWebStart/pom.xml index ca19a0b3..f51f1332 100644 --- a/BKUWebStart/pom.xml +++ b/BKUWebStart/pom.xml @@ -172,6 +172,12 @@ BKUCertificates 1.0 + + iaik + iaik_jce_full_signed + compile + + + @@ -215,6 +222,11 @@ slf4j-log4j12 1.5.8 + + log4j + log4j + compile + diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java index 923a70d9..d8fe3e70 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java @@ -16,8 +16,9 @@ */ package at.gv.egiz.bku.webstart; -import at.gv.egiz.bku.utils.StreamUtil; import iaik.asn1.CodingException; +import iaik.utils.StreamCopier; + import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.BufferedReader; @@ -42,8 +43,10 @@ import java.util.jar.Manifest; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; import java.util.zip.ZipOutputStream; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; + +import org.apache.log4j.PropertyConfigurator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * @@ -71,7 +74,7 @@ public class Configurator { public static final String KEYSTORE_FILE = "keystore.ks"; public static final String PASSWD_FILE = ".secret"; - private static final Log log = LogFactory.getLog(Configurator.class); + private static final Logger log = LoggerFactory.getLogger(Configurator.class); /** currently installed configuration version */ private String version; @@ -110,6 +113,11 @@ public class Configurator { } else { initConfig(configDir); } + // re-configure logging + // TODO: move to appropriate place + String log4jconfig = configDir.getPath() + File.separatorChar + "log4j.properties"; + log.debug("Reconfiguring logging with " + log4jconfig); + PropertyConfigurator.configureAndWatch(log4jconfig); } /** @@ -312,7 +320,7 @@ public class Configurator { ZipEntry entry = new ZipEntry(relativePath.toString()); zip.putNextEntry(entry); BufferedInputStream entryIS = new BufferedInputStream(new FileInputStream(dir)); - StreamUtil.copyStream(entryIS, zip); + new StreamCopier(entryIS, zip).copyStream(); entryIS.close(); zip.closeEntry(); dir.delete(); @@ -341,7 +349,7 @@ public class Configurator { File confTemplateFile = new File(configDir, CONF_TEMPLATE_FILE); InputStream is = Configurator.class.getClassLoader().getResourceAsStream(CONF_TEMPLATE_RESOURCE); OutputStream os = new BufferedOutputStream(new FileOutputStream(confTemplateFile)); - StreamUtil.copyStream(is, os); + new StreamCopier(is, os).copyStream(); os.close(); unzip(confTemplateFile, configDir); confTemplateFile.delete(); @@ -374,7 +382,7 @@ public class Configurator { new File(certsDir, f.substring(0, f.lastIndexOf('/'))).mkdirs(); BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(new File(certsDir, f))); log.debug(f); - StreamUtil.copyStream(Configurator.class.getClassLoader().getResourceAsStream(entry), bos); + new StreamCopier(Configurator.class.getClassLoader().getResourceAsStream(entry), bos).copyStream(); bos.close(); } else { log.trace("ignore " + entry); @@ -399,8 +407,8 @@ public class Configurator { } File f = new File(eF.getParent()); f.mkdirs(); - StreamUtil.copyStream(zipFile.getInputStream(entry), - new FileOutputStream(eF)); + new StreamCopier(zipFile.getInputStream(entry), + new FileOutputStream(eF)).copyStream(); } zipFile.close(); } diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java index 2feae267..4d1fe658 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java @@ -1,6 +1,7 @@ package at.gv.egiz.bku.webstart; -import at.gv.egiz.bku.utils.StreamUtil; +import iaik.utils.StreamCopier; + import java.awt.AWTPermission; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; @@ -24,20 +25,20 @@ import java.security.SecurityPermission; import java.security.cert.Certificate; import java.util.PropertyPermission; import javax.smartcardio.CardPermission; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.mortbay.jetty.Connector; import org.mortbay.jetty.Server; import org.mortbay.jetty.nio.SelectChannelConnector; import org.mortbay.jetty.security.SslSocketConnector; import org.mortbay.jetty.webapp.WebAppContext; import org.mortbay.thread.QueuedThreadPool; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Container { public static final String HTTP_PORT_PROPERTY = "mocca.http.port"; public static final String HTTPS_PORT_PROPERTY = "mocca.http.port"; - private static Log log = LogFactory.getLog(Container.class); + private static Logger log = LoggerFactory.getLogger(Container.class); static { if (log.isDebugEnabled()) { @@ -166,7 +167,7 @@ public class Container { log.debug("copying BKULocal classpath resource to " + webapp); InputStream is = getClass().getClassLoader().getResourceAsStream("BKULocal.war"); OutputStream os = new BufferedOutputStream(new FileOutputStream(webapp)); - StreamUtil.copyStream(is, os); + new StreamCopier(is, os).copyStream(); os.close(); return webapp.getPath(); } diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java index 2bf42ccb..ef7edef1 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java @@ -10,8 +10,6 @@ import java.util.Locale; import java.util.ResourceBundle; import javax.jnlp.UnavailableServiceException; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import com.sun.javaws.security.JavaWebStartSecurity; import java.awt.AWTException; @@ -37,6 +35,8 @@ import javax.jnlp.BasicService; import javax.jnlp.ServiceManager; import javax.swing.JFrame; import org.mortbay.util.MultiException; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; public class Launcher implements BKUControllerInterface, ActionListener { public static final String HELP_COMMAND = "help"; @@ -71,9 +71,10 @@ public class Launcher implements BKUControllerInterface, ActionListener { public static final String SHUTDOWN_COMMAND = "shutdown"; public static final String PIN_COMMAND = "pin"; public static final String ABOUT_COMMAND = "about"; + + private static Logger log = LoggerFactory.getLogger(Launcher.class); - private static Log log = LogFactory.getLog(Launcher.class); - + /** local bku uri */ public static final URL HTTP_SECURITY_LAYER_URL; public static final URL HTTPS_SECURITY_LAYER_URL; @@ -93,7 +94,7 @@ public class Launcher implements BKUControllerInterface, ActionListener { cert = new URL(http, "/installCertificate"); help = new URL(http, "/help"); } catch (MalformedURLException ex) { - log.error(ex); + log.error("Failed to create URL.", ex); } finally { HTTP_SECURITY_LAYER_URL = http; HTTPS_SECURITY_LAYER_URL = https; @@ -132,6 +133,7 @@ public class Launcher implements BKUControllerInterface, ActionListener { public Launcher() { + log.info("Initializing Launcher"); if (log.isTraceEnabled()) { SecurityManager sm = System.getSecurityManager(); if (sm instanceof JavaWebStartSecurity) { @@ -147,7 +149,7 @@ public class Launcher implements BKUControllerInterface, ActionListener { try { initConfig(); } catch (Exception ex) { - log.fatal("Failed to initialize configuration", ex); + log.error("Failed to initialize configuration", ex); trayIcon.displayMessage(messages.getString(CAPTION_ERROR), messages.getString(ERROR_CONFIG), TrayIcon.MessageType.ERROR); throw ex; @@ -156,12 +158,12 @@ public class Launcher implements BKUControllerInterface, ActionListener { startServer(); initFinished(); } catch (BindException ex) { - log.fatal("Failed to launch server, " + ex.getMessage(), ex); + log.error("Failed to launch server, " + ex.getMessage(), ex); trayIcon.displayMessage(messages.getString(CAPTION_ERROR), messages.getString(ERROR_BIND), TrayIcon.MessageType.ERROR); throw ex; } catch (MultiException ex) { - log.fatal("Failed to launch server, " + ex.getMessage(), ex); + log.error("Failed to launch server, " + ex.getMessage(), ex); if (ex.getThrowable(0) instanceof BindException) { trayIcon.displayMessage(messages.getString(CAPTION_ERROR), messages.getString(ERROR_BIND), TrayIcon.MessageType.ERROR); @@ -172,7 +174,7 @@ public class Launcher implements BKUControllerInterface, ActionListener { throw ex; } catch (Exception ex) { ex.printStackTrace(); - log.fatal("Failed to launch server, " + ex.getMessage(), ex); + log.error("Failed to launch server, " + ex.getMessage(), ex); trayIcon.displayMessage(messages.getString(CAPTION_ERROR), messages.getString(ERROR_START), TrayIcon.MessageType.ERROR); throw ex; @@ -379,7 +381,7 @@ public class Launcher implements BKUControllerInterface, ActionListener { launcher.launch(); } catch (Exception ex) { ex.printStackTrace(); - log.debug(ex); + log.debug("Caught exception " + ex.getMessage(), ex); log.info("waiting to shutdown..."); Thread.sleep(5000); log.info("exit"); diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java index 99fd403b..d589812e 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java @@ -20,8 +20,9 @@ import com.sun.javaws.security.JavaWebStartSecurity; import java.io.FileDescriptor; import java.net.InetAddress; import java.security.Permission; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * JVM argument -Djava.security.debug=access,failure @@ -31,7 +32,7 @@ import org.apache.commons.logging.LogFactory; */ public class LogSecurityManager extends SecurityManager { - protected static final Log log = LogFactory.getLog(LogSecurityManager.class); + protected static final Logger log = LoggerFactory.getLogger(LogSecurityManager.class); JavaWebStartSecurity sm; public LogSecurityManager(JavaWebStartSecurity sm) { @@ -182,6 +183,7 @@ public class LogSecurityManager extends SecurityManager { } } + @SuppressWarnings("deprecation") @Override public void checkMulticast(InetAddress maddr, byte ttl) { try { @@ -399,6 +401,7 @@ public class LogSecurityManager extends SecurityManager { // protected Class[] getClassContext() { // log.info("getClassContext"); return sm.getClassContext(); // } + @SuppressWarnings("deprecation") @Override public boolean getInCheck() { log.info("getInCheck"); diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java index 08a06570..745042f8 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java @@ -16,8 +16,6 @@ import iaik.x509.extensions.SubjectAltName; import iaik.x509.extensions.SubjectKeyIdentifier; import java.io.IOException; import java.math.BigInteger; -import java.net.InetAddress; -import java.net.UnknownHostException; import java.security.GeneralSecurityException; import java.security.KeyPair; import java.security.KeyPairGenerator; @@ -27,14 +25,15 @@ import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Random; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + public class TLSServerCA { public static final int CA_VALIDITY_Y = 3; public static final String MOCCA_TLS_SERVER_ALIAS = "server"; public static final int SERVER_VALIDITY_Y = 3; - private final static Log log = LogFactory.getLog(TLSServerCA.class); + private final static Logger log = LoggerFactory.getLogger(TLSServerCA.class); private KeyPair caKeyPair; private X509Certificate caCert; diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java index 1e35af58..ba2c007d 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java @@ -11,7 +11,6 @@ package at.gv.egiz.bku.webstart.gui; -import java.text.Format; import java.text.MessageFormat; import java.util.ResourceBundle; @@ -21,6 +20,11 @@ import java.util.ResourceBundle; */ public class AboutDialog extends javax.swing.JDialog { + /** + * + */ + private static final long serialVersionUID = 1L; + /** Creates new form AboutDialog */ public AboutDialog(java.awt.Frame parent, boolean modal, String version) { super(parent, modal); @@ -33,7 +37,6 @@ public class AboutDialog extends javax.swing.JDialog { * WARNING: Do NOT modify this code. The content of this method is * always regenerated by the Form Editor. */ - @SuppressWarnings("unchecked") // //GEN-BEGIN:initComponents private void initComponents() { diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java index 55e26313..1f14d751 100644 --- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java @@ -21,8 +21,9 @@ import java.awt.TrayIcon; import java.io.IOException; import java.net.HttpURLConnection; import java.util.ResourceBundle; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; /** * GUI is painted using SwingUtilities.invokeLater, but TrayIcon ActionListener Thread (== webstart thread) joined Jetty Thread @@ -31,7 +32,7 @@ import org.apache.commons.logging.LogFactory; */ public class PINManagementInvoker implements Runnable { - private static final Log log = LogFactory.getLog(PINManagementInvoker.class); + private static final Logger log = LoggerFactory.getLogger(PINManagementInvoker.class); TrayIcon trayIcon; ResourceBundle messages; diff --git a/BKUWebStart/src/main/resources/log4j.properties b/BKUWebStart/src/main/resources/log4j.properties index 76562ccf..81832418 100644 --- a/BKUWebStart/src/main/resources/log4j.properties +++ b/BKUWebStart/src/main/resources/log4j.properties @@ -13,23 +13,15 @@ # See the License for the specific language governing permissions and # limitations under the License. -# loglever DEBUG, appender STDOUT -log4j.rootLogger=DEBUG, file -log4j.logger.org.mortbay.log=INFO -log4j.logger.pki=INFO - -#log4j.additivity.pki=false +# root log level INFO, appender file +log4j.rootLogger=INFO, file -# STDOUT appender -log4j.appender.STDOUT=org.apache.log4j.ConsoleAppender -log4j.appender.STDOUT.layout=org.apache.log4j.PatternLayout -#log4j.appender.STDOUT.layout.ConversionPattern=%5p | %d{dd HH:mm:ss,SSS} | %20c | %10t | %m%n -#log4j.appender.STDOUT.layout.ConversionPattern=%-4r [%t] %-5p %c %x - %m%n -log4j.appender.STDOUT.layout.ConversionPattern=%-5p |%d | %t | %c %x- %m%n +# jetty's log level +log4j.logger.org.mortbay.log=INFO -### FILE appender +# file appender log4j.appender.file=org.apache.log4j.DailyRollingFileAppender log4j.appender.file.datePattern='.'yyyy-MM-dd log4j.appender.file.File=${user.home}/.mocca/logs/webstart.log log4j.appender.file.layout=org.apache.log4j.PatternLayout -log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %-5p %c{1}:%L - %m%n \ No newline at end of file +log4j.appender.file.layout.ConversionPattern=%d{ABSOLUTE} %-5p %c{2} - %m%n \ No newline at end of file diff --git a/BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java b/BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java index 0ea126cb..4f5798d5 100644 --- a/BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java +++ b/BKUWebStart/src/test/java/at/gv/egiz/bku/webstart/ConfiguratorTest.java @@ -8,8 +8,6 @@ package at.gv.egiz.bku.webstart; import java.io.File; import java.net.URI; import java.util.zip.ZipOutputStream; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.junit.After; import org.junit.AfterClass; import org.junit.Before; diff --git a/BKUWebStartPackage/pom.xml b/BKUWebStartPackage/pom.xml index 63725fc3..0b226785 100644 --- a/BKUWebStartPackage/pom.xml +++ b/BKUWebStartPackage/pom.xml @@ -1,3 +1,4 @@ + 4.0.0 @@ -22,7 +23,7 @@ process-resources - jnlp-download-servlet + jnlp-single diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java index 1db8c836..d3945253 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrl.java @@ -16,7 +16,6 @@ */ package at.gv.egiz.bku.binding; -import at.gv.egiz.bku.conf.Configuration; import at.gv.egiz.bku.conf.Configurator; import java.net.MalformedURLException; import java.net.URL; @@ -89,13 +88,7 @@ public class DataUrl { if (configuration != null) { String className = configuration.getProperty(Configurator.DATAURLCONNECTION_CONFIG_P); if (className != null) { - try { - log.info("set DataURLConnection class: " + className); - Class c = Class.forName(className); - connection = (DataUrlConnectionSPI) c.newInstance(); - } catch (Exception ex) { - log.error("failed to instantiate DataURL connection " + className, ex); - } + log.warn("Set DataURLConnection class not supported!"); } } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java index f954a017..384cf71c 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnection.java @@ -62,7 +62,7 @@ public interface DataUrlConnection { * @param transferEncoding may be null */ public void setHTTPFormParameter(String name, InputStream data, String contentType, String charSet, String transferEncoding); - + /** * @pre httpHeaders != null * @throws java.net.SocketTimeoutException diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java index 4f2d2e00..b092ba41 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/DataUrlConnectionImpl.java @@ -18,10 +18,14 @@ package at.gv.egiz.bku.binding; import java.io.IOException; import java.io.InputStream; +import java.io.InputStreamReader; import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.net.HttpURLConnection; import java.net.SocketTimeoutException; import java.net.URL; +import java.net.URLEncoder; +import java.nio.charset.Charset; import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.HashMap; @@ -34,6 +38,7 @@ import java.util.Set; import javax.net.ssl.HostnameVerifier; import javax.net.ssl.HttpsURLConnection; import javax.net.ssl.SSLSocketFactory; +import javax.xml.transform.stream.StreamResult; import org.apache.commons.httpclient.methods.multipart.FilePart; import org.apache.commons.httpclient.methods.multipart.Part; @@ -47,32 +52,92 @@ import at.gv.egiz.bku.conf.Configurator; import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slcommands.SLResult.SLResultType; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.utils.URLEncodingWriter; import at.gv.egiz.bku.utils.binding.Protocol; /** - * not thread-safe thus newInsance always returns a new object + * An implementation of the DataUrlConnectionSPI that supports + * multipart/form-data encoding and + * application/x-www-form-urlencoded for compatibility with legacy + * systems. * */ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { private final static Log log = LogFactory.getLog(DataUrlConnectionImpl.class); + + public static final byte[] B_DEFAULT_RESPONSETYPE = DEFAULT_RESPONSETYPE.getBytes(Charset.forName("UTF-8")); + /** + * Supported protocols are HTTP and HTTPS. + */ public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP, Protocol.HTTPS }; + /** + * The X509 certificate of the DataURL server. + */ protected X509Certificate serverCertificate; + + /** + * The protocol of the DataURL. + */ protected Protocol protocol; + + /** + * Use application/x-www-form-urlencoded instead of + * standard conform application/x-www-form-urlencoded. + */ + protected boolean urlEncoded = true; + + /** + * The value of the DataURL. + */ protected URL url; + + /** + * The URLConnection used for communication with the DataURL server. + */ private HttpURLConnection connection; + + /** + * The HTTP request headers. + */ protected Map requestHttpHeaders; - protected ArrayList formParams; + + /** + * The HTTP form parameters. + */ + protected ArrayList httpFormParameter; + + /** + * The boundary for multipart/form-data requests. + */ protected String boundary; + + /** + * The configuration properties. + */ protected Properties config = null; + + /** + * The SSLSocketFactory for HTTPS connections. + */ protected SSLSocketFactory sslSocketFactory; + + /** + * The HostnameVerifier for HTTPS connections. + */ protected HostnameVerifier hostnameVerifier; + /** + * The response of the DataURL server. + */ protected DataUrlResponse result; + /* (non-Javadoc) + * @see at.gv.egiz.bku.binding.DataUrlConnection#getProtocol() + */ public String getProtocol() { if (protocol == null) { return null; @@ -80,13 +145,8 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { return protocol.toString(); } - /** - * opens a connection sets the headers gets the server certificate - * - * @throws java.net.SocketTimeoutException - * @throws java.io.IOException - * @pre url != null - * @pre httpHeaders != null + /* (non-Javadoc) + * @see at.gv.egiz.bku.binding.DataUrlConnection#connect() */ public void connect() throws SocketTimeoutException, IOException { connection = (HttpURLConnection) url.openConnection(); @@ -104,9 +164,26 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { https.setHostnameVerifier(hostnameVerifier); } } else { - log.trace("No secure connection with: "+url+ " class="+connection.getClass()); + log.trace("No secure connection with: " + url + " class=" + + connection.getClass()); } connection.setDoOutput(true); + // Transfer-Encoding: chunked is problematic ... + // e.g. https://issues.apache.org/bugzilla/show_bug.cgi?id=37794 + // ... therefore disabled. + // connection.setChunkedStreamingMode(5*1024); + if (urlEncoded) { + log.debug("Setting DataURL Content-Type to " + + HttpUtil.APPLICATION_URL_ENCODED); + connection.addRequestProperty(HttpUtil.HTTP_HEADER_CONTENT_TYPE, + HttpUtil.APPLICATION_URL_ENCODED); + } else { + log.debug("Setting DataURL Content-Type to " + + HttpUtil.MULTIPART_FOTMDATA_BOUNDARY); + connection.addRequestProperty(HttpUtil.HTTP_HEADER_CONTENT_TYPE, + HttpUtil.MULTIPART_FOTMDATA + HttpUtil.SEPERATOR[0] + + HttpUtil.MULTIPART_FOTMDATA_BOUNDARY + "=" + boundary); + } Set headers = requestHttpHeaders.keySet(); Iterator headerIt = headers.iterator(); while (headerIt.hasNext()) { @@ -125,51 +202,128 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { } } + /* (non-Javadoc) + * @see at.gv.egiz.bku.binding.DataUrlConnection#getServerCertificate() + */ public X509Certificate getServerCertificate() { return serverCertificate; } + /* (non-Javadoc) + * @see at.gv.egiz.bku.binding.DataUrlConnection#setHTTPHeader(java.lang.String, java.lang.String) + */ public void setHTTPHeader(String name, String value) { if (name != null && value != null) { requestHttpHeaders.put(name, value); } } + /* (non-Javadoc) + * @see at.gv.egiz.bku.binding.DataUrlConnection#setHTTPFormParameter(java.lang.String, java.io.InputStream, java.lang.String, java.lang.String, java.lang.String) + */ public void setHTTPFormParameter(String name, InputStream data, String contentType, String charSet, String transferEncoding) { - InputStreamPartSource source = new InputStreamPartSource(null, data); - FilePart formParam = new FilePart(name, source, contentType, charSet); - if (transferEncoding != null) { - formParam.setTransferEncoding(transferEncoding); - } else { - formParam.setTransferEncoding(null); + // if a content type is specified we have to switch to multipart/formdata encoding + if (contentType != null && contentType.length() > 0) { + urlEncoded = false; } - formParams.add(formParam); + httpFormParameter.add(new HTTPFormParameter(name, data, contentType, + charSet, transferEncoding)); } - /** - * send all formParameters - * - * @throws java.io.IOException + + + /* (non-Javadoc) + * @see at.gv.egiz.bku.binding.DataUrlConnection#transmit(at.gv.egiz.bku.slcommands.SLResult) */ public void transmit(SLResult slResult) throws IOException { - SLResultPart slResultPart = new SLResultPart(slResult, - XML_RESPONSE_ENCODING); - if (slResult.getResultType() == SLResultType.XML) { - slResultPart.setTransferEncoding(null); - slResultPart.setContentType(slResult.getMimeType()); - slResultPart.setCharSet(XML_RESPONSE_ENCODING); + log.trace("Sending data"); + if (urlEncoded) { + // + // application/x-www-form-urlencoded (legacy, SL < 1.2) + // + + OutputStream os = connection.getOutputStream(); + OutputStreamWriter streamWriter = new OutputStreamWriter(os, HttpUtil.DEFAULT_CHARSET); + + // ResponseType + streamWriter.write(FORMPARAM_RESPONSETYPE); + streamWriter.write("="); + streamWriter.write(URLEncoder.encode(DEFAULT_RESPONSETYPE, "UTF-8")); + streamWriter.write("&"); + + // XMLResponse / Binary Response + if (slResult.getResultType() == SLResultType.XML) { + streamWriter.write(DataUrlConnection.FORMPARAM_XMLRESPONSE); + } else { + streamWriter.write(DataUrlConnection.FORMPARAM_BINARYRESPONSE); + } + streamWriter.write("="); + streamWriter.flush(); + URLEncodingWriter urlEnc = new URLEncodingWriter(streamWriter); + slResult.writeTo(new StreamResult(urlEnc), false); + urlEnc.flush(); + + // transfer parameters + char[] cbuf = new char[512]; + int len; + for (HTTPFormParameter formParameter : httpFormParameter) { + streamWriter.write("&"); + streamWriter.write(URLEncoder.encode(formParameter.getName(), "UTF-8")); + streamWriter.write("="); + InputStreamReader reader = new InputStreamReader(formParameter.getData(), + (formParameter.getCharSet() != null) + ? formParameter.getCharSet() + : null); + while ((len = reader.read(cbuf)) != -1) { + urlEnc.write(cbuf, 0, len); + } + urlEnc.flush(); + } + streamWriter.close(); + } else { - slResultPart.setTransferEncoding(null); - slResultPart.setContentType(slResult.getMimeType()); - } - formParams.add(slResultPart); + // + // multipart/form-data (conforming to SL 1.2) + // - OutputStream os = connection.getOutputStream(); - log.trace("Sending data"); - Part[] parts = new Part[formParams.size()]; - Part.sendParts(os, formParams.toArray(parts), boundary.getBytes()); - os.close(); + ArrayList parts = new ArrayList(); + + // ResponseType + StringPart responseType = new StringPart(FORMPARAM_RESPONSETYPE, + DEFAULT_RESPONSETYPE, "UTF-8"); + responseType.setTransferEncoding(null); + parts.add(responseType); + + // XMLResponse / Binary Response + SLResultPart slResultPart = new SLResultPart(slResult, + XML_RESPONSE_ENCODING); + if (slResult.getResultType() == SLResultType.XML) { + slResultPart.setTransferEncoding(null); + slResultPart.setContentType(slResult.getMimeType()); + slResultPart.setCharSet(XML_RESPONSE_ENCODING); + } else { + slResultPart.setTransferEncoding(null); + slResultPart.setContentType(slResult.getMimeType()); + } + parts.add(slResultPart); + + // transfer parameters + for (HTTPFormParameter formParameter : httpFormParameter) { + InputStreamPartSource source = new InputStreamPartSource(null, + formParameter.getData()); + FilePart part = new FilePart(formParameter.getName(), source, + formParameter.getContentType(), formParameter.getCharSet()); + part.setTransferEncoding(formParameter.getTransferEncoding()); + parts.add(part); + } + + OutputStream os = connection.getOutputStream(); + Part.sendParts(os, parts.toArray(new Part[parts.size()]), boundary.getBytes()); + os.close(); + + } + // MultipartRequestEntity PostMethod InputStream is = null; try { @@ -241,16 +395,9 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { .put(HttpUtil.HTTP_HEADER_USER_AGENT, Configurator.USERAGENT_DEFAULT); } - requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, - HttpUtil.MULTIPART_FOTMDATA + HttpUtil.SEPERATOR[0] - + HttpUtil.MULTIPART_FOTMDATA_BOUNDARY + "=" + boundary); - - formParams = new ArrayList(); - StringPart responseType = new StringPart(FORMPARAM_RESPONSETYPE, - DEFAULT_RESPONSETYPE); - responseType.setCharSet("UTF-8"); - responseType.setTransferEncoding(null); - formParams.add(responseType); + + httpFormParameter = new ArrayList(); + } @Override @@ -281,4 +428,107 @@ public class DataUrlConnectionImpl implements DataUrlConnectionSPI { public void setHostnameVerifier(HostnameVerifier hostnameVerifier) { this.hostnameVerifier = hostnameVerifier; } + + public class HTTPFormParameter { + + private String name; + + private InputStream data; + + private String contentType; + + private String charSet; + + private String transferEncoding; + + /** + * @param name + * @param data + * @param contentType + * @param charSet + * @param transferEncoding + */ + public HTTPFormParameter(String name, InputStream data, String contentType, + String charSet, String transferEncoding) { + super(); + this.name = name; + this.data = data; + this.contentType = contentType; + this.charSet = charSet; + this.transferEncoding = transferEncoding; + } + + /** + * @return the name + */ + public String getName() { + return name; + } + + /** + * @param name the name to set + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the data + */ + public InputStream getData() { + return data; + } + + /** + * @param data the data to set + */ + public void setData(InputStream data) { + this.data = data; + } + + /** + * @return the contentType + */ + public String getContentType() { + return contentType; + } + + /** + * @param contentType the contentType to set + */ + public void setContentType(String contentType) { + this.contentType = contentType; + } + + /** + * @return the charSet + */ + public String getCharSet() { + return charSet; + } + + /** + * @param charSet the charSet to set + */ + public void setCharSet(String charSet) { + this.charSet = charSet; + } + + /** + * @return the transferEncoding + */ + public String getTransferEncoding() { + return transferEncoding; + } + + /** + * @param transferEncoding the transferEncoding to set + */ + public void setTransferEncoding(String transferEncoding) { + this.transferEncoding = transferEncoding; + } + + + + } } \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java index ef603fc7..a1c4d5fc 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/HTTPBindingProcessor.java @@ -22,6 +22,7 @@ import java.io.InputStreamReader; import java.io.OutputStream; import java.io.OutputStreamWriter; import java.io.Reader; +import java.io.Writer; import java.net.URL; import java.security.cert.X509Certificate; import java.util.ArrayList; @@ -46,6 +47,7 @@ import javax.xml.transform.stream.StreamSource; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import at.gv.egiz.bku.slcommands.ErrorResult; import at.gv.egiz.bku.slcommands.SLCommand; import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slcommands.SLCommandFactory; @@ -635,7 +637,6 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements throw new SLBindingException(2006); } InputDecoder id = InputDecoderFactory.getDecoder(cl, is); - id.setContentType(cl); if (id == null) { log.error("Cannot get inputdecoder for is"); throw new SLException(2006); @@ -730,9 +731,20 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements Templates templates) throws IOException { log.debug("Writing error as result"); ErrorResultImpl error = new ErrorResultImpl(bindingProcessorError, locale); - error.writeTo(new StreamResult(new OutputStreamWriter(os, encoding)), templates); + Writer writer = writeXMLDeclarationAndProcessingInstruction(os, encoding); + error.writeTo(new StreamResult(writer), templates, true); } + protected Writer writeXMLDeclarationAndProcessingInstruction(OutputStream os, String encoding) throws IOException { + if (encoding == null) { + encoding = HttpUtil.DEFAULT_CHARSET; + } + OutputStreamWriter writer = new OutputStreamWriter(os, encoding); + writer.write("\n"); + writer.write("\n"); + return writer; + } + @Override public void writeResultTo(OutputStream os, String encoding) throws IOException { @@ -772,9 +784,16 @@ public class HTTPBindingProcessor extends AbstractBindingProcessor implements return; } else { log.debug("Getting result from invoker"); - OutputStreamWriter osw = new OutputStreamWriter(os, encoding); - slResult.writeTo(new StreamResult(osw), templates); - osw.flush(); + boolean fragment = false; + Writer writer; + if (slResult instanceof ErrorResult) { + writer = writeXMLDeclarationAndProcessingInstruction(os, encoding); + fragment = true; + } else { + writer = new OutputStreamWriter(os, encoding); + } + slResult.writeTo(new StreamResult(writer), templates, fragment); + writer.flush(); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java deleted file mode 100644 index cfccb7f1..00000000 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/LegacyDataUrlConnectionImpl.java +++ /dev/null @@ -1,259 +0,0 @@ -package at.gv.egiz.bku.binding; - - -import at.gv.egiz.bku.conf.Configurator; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.OutputStream; -import java.io.OutputStreamWriter; -import java.io.StringWriter; -import java.net.HttpURLConnection; -import java.net.SocketTimeoutException; -import java.net.URL; -import java.net.URLEncoder; -import java.security.cert.X509Certificate; -import java.util.HashMap; -import java.util.Iterator; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.Set; - -import javax.net.ssl.HostnameVerifier; -import javax.net.ssl.HttpsURLConnection; -import javax.net.ssl.SSLSocketFactory; -import javax.xml.transform.stream.StreamResult; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -import at.gv.egiz.bku.slcommands.SLResult; -import at.gv.egiz.bku.slcommands.SLResult.SLResultType; -import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.bku.utils.binding.Protocol; - -/** - * not thread-safe thus newInsance always returns a new object - * - */ -public class LegacyDataUrlConnectionImpl implements DataUrlConnectionSPI { - - private final static Log log = LogFactory.getLog(LegacyDataUrlConnectionImpl.class); - - public final static Protocol[] SUPPORTED_PROTOCOLS = { Protocol.HTTP, - Protocol.HTTPS }; - protected X509Certificate serverCertificate; - protected Protocol protocol; - protected URL url; - private HttpURLConnection connection; - protected Map requestHttpHeaders; - protected Map formParams; - protected String boundary; - protected Properties config = null; - protected SSLSocketFactory sslSocketFactory; - protected HostnameVerifier hostnameVerifier; - - protected DataUrlResponse result; - - public String getProtocol() { - if (protocol == null) { - return null; - } - return protocol.toString(); - } - - /** - * opens a connection sets the headers gets the server certificate - * - * @throws java.net.SocketTimeoutException - * @throws java.io.IOException - * @pre url != null - * @pre httpHeaders != null - */ - public void connect() throws SocketTimeoutException, IOException { - connection = (HttpURLConnection) url.openConnection(); - if (connection instanceof HttpsURLConnection) { - HttpsURLConnection https = (HttpsURLConnection) connection; - if (sslSocketFactory != null) { - log.debug("Setting custom ssl socket factory for ssl connection"); - https.setSSLSocketFactory(sslSocketFactory); - } - if (hostnameVerifier != null) { - log.debug("Setting custom hostname verifier"); - https.setHostnameVerifier(hostnameVerifier); - } - } - connection.setDoOutput(true); - Set headers = requestHttpHeaders.keySet(); - Iterator headerIt = headers.iterator(); - while (headerIt.hasNext()) { - String name = headerIt.next(); - connection.setRequestProperty(name, requestHttpHeaders.get(name)); - } - log.trace("Connecting to: "+url); - connection.connect(); - if (connection instanceof HttpsURLConnection) { - HttpsURLConnection ssl = (HttpsURLConnection) connection; - X509Certificate[] certs = (X509Certificate[]) ssl.getServerCertificates(); - if ((certs != null) && (certs.length >= 1)) { - log.trace("Server certificate: "+certs[0]); - serverCertificate = certs[0]; - } - } - } - - public X509Certificate getServerCertificate() { - return serverCertificate; - } - - public void setHTTPHeader(String name, String value) { - if (name != null && value != null) { - requestHttpHeaders.put(name, value); - } - } - - public void setHTTPFormParameter(String name, InputStream data, - String contentType, String charSet, String transferEncoding) { - StringBuilder sb = new StringBuilder(); - try { - InputStreamReader reader = new InputStreamReader(data, (charSet != null) ? charSet : "UTF-8"); - char[] c = new char[512]; - for (int l; (l = reader.read(c)) != -1;) { - sb.append(c, 0, l); - } - } catch (IOException e) { - throw new SLRuntimeException("Failed to set HTTP form parameter.", e); - } - formParams.put(name, sb.toString()); - } - - /** - * send all formParameters - * - * @throws java.io.IOException - */ - public void transmit(SLResult slResult) throws IOException { - StringWriter writer = new StringWriter(); - slResult.writeTo(new StreamResult(writer)); - formParams.put( - (slResult.getResultType() == SLResultType.XML) - ? DataUrlConnection.FORMPARAM_XMLRESPONSE - : DataUrlConnection.FORMPARAM_BINARYRESPONSE, - writer.toString()); - - OutputStream os = connection.getOutputStream(); - OutputStreamWriter streamWriter = new OutputStreamWriter(os, HttpUtil.DEFAULT_CHARSET); - - log.trace("Sending data"); - Iterator keys = formParams.keySet().iterator(); - while(keys.hasNext()) { - String key = keys.next(); - streamWriter.write(URLEncoder.encode(key, "UTF-8")); - streamWriter.write("="); - streamWriter.write(URLEncoder.encode(formParams.get(key), "UTF-8")); - if (keys.hasNext()) { - streamWriter.write("&"); - } - } - streamWriter.flush(); - os.close(); - - // MultipartRequestEntity PostMethod - InputStream is = null; - try { - is = connection.getInputStream(); - } catch (IOException iox) { - log.info(iox); - } - log.trace("Reading response"); - result = new DataUrlResponse(url.toString(), connection.getResponseCode(), is); - Map responseHttpHeaders = new HashMap(); - Map> httpHeaders = connection.getHeaderFields(); - for (Iterator keyIt = httpHeaders.keySet().iterator(); keyIt - .hasNext();) { - String key = keyIt.next(); - StringBuffer value = new StringBuffer(); - for (String val : httpHeaders.get(key)) { - value.append(val); - value.append(HttpUtil.SEPERATOR[0]); - } - String valString = value.substring(0, value.length() - 1); - if ((key != null) && (value.length() > 0)) { - responseHttpHeaders.put(key, valString); - } - } - result.setResponseHttpHeaders(responseHttpHeaders); - } - - @Override - public DataUrlResponse getResponse() throws IOException { - return result; - } - - /** - * inits protocol, url, httpHeaders, formParams - * - * @param url - * must not be null - */ - @Override - public void init(URL url) { - - for (int i = 0; i < SUPPORTED_PROTOCOLS.length; i++) { - if (SUPPORTED_PROTOCOLS[i].toString().equalsIgnoreCase(url.getProtocol())) { - protocol = SUPPORTED_PROTOCOLS[i]; - break; - } - } - if (protocol == null) { - throw new SLRuntimeException("Protocol " + url.getProtocol() - + " not supported for data url"); - } - this.url = url; - requestHttpHeaders = new HashMap(); - if ((config != null) - && (config.getProperty(Configurator.USERAGENT_CONFIG_P) != null)) { - log.debug("setting User-Agent header: " + config.getProperty(Configurator.USERAGENT_CONFIG_P)); - requestHttpHeaders.put(HttpUtil.HTTP_HEADER_USER_AGENT, config - .getProperty(Configurator.USERAGENT_CONFIG_P)); - } else { - requestHttpHeaders - .put(HttpUtil.HTTP_HEADER_USER_AGENT, Configurator.USERAGENT_DEFAULT); - - } - requestHttpHeaders.put(HttpUtil.HTTP_HEADER_CONTENT_TYPE, - HttpUtil.APPLICATION_URL_ENCODED); - - formParams = new HashMap(); - } - - @Override - public DataUrlConnectionSPI newInstance() { - DataUrlConnectionSPI uc = new LegacyDataUrlConnectionImpl(); - uc.setConfiguration(config); - uc.setSSLSocketFactory(sslSocketFactory); - uc.setHostnameVerifier(hostnameVerifier); - return uc; - } - - @Override - public URL getUrl() { - return url; - } - - @Override - public void setConfiguration(Properties config) { - this.config = config; - } - - @Override - public void setSSLSocketFactory(SSLSocketFactory socketFactory) { - this.sslSocketFactory = socketFactory; - } - - @Override - public void setHostnameVerifier(HostnameVerifier hostnameVerifier) { - this.hostnameVerifier = hostnameVerifier; - } -} \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java index f4ebe288..69c659e1 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputDecoder.java @@ -16,86 +16,43 @@ */ package at.gv.egiz.bku.binding; -import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.net.URLDecoder; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; +import java.io.InputStream; +import java.util.Iterator; +import java.util.Map; + +import org.apache.commons.fileupload.ParameterParser; -import org.apache.commons.fileupload.ParameterParser; - -import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.bku.utils.StreamUtil; - -/** - * Implementation based on Java's URLDecoder class - * - */ -// FIXME replace this code by a streaming variant public class XWWWFormUrlInputDecoder implements InputDecoder { - - public final static String CHAR_SET = "charset"; - public final static String NAME_VAL_SEP = "="; - public final static String SEP = "\\&"; - - private String contentType; - private InputStream dataStream; - private String charset = "UTF-8"; - - protected List decodeInput(InputStream is) throws IOException { - List result = new LinkedList(); - ByteArrayOutputStream bos = new ByteArrayOutputStream(); - StreamUtil.copyStream(is, bos); - String inputString = new String(bos.toByteArray()); - String[] nameValuePairs = inputString.split(SEP); - //inputString = URLDecoder.decode(inputString, charset); - for (int i = 0; i < nameValuePairs.length; i++) { - String[] fields = nameValuePairs[i].split(NAME_VAL_SEP, 2); - if (fields.length != 2) { - throw new SLRuntimeException("Invalid form encoding, missing value"); - } - String name = URLDecoder.decode(fields[0], charset); - String value =URLDecoder.decode(fields[1], charset); - ByteArrayInputStream bais = new ByteArrayInputStream(value - .getBytes(charset)); - FormParameterImpl fpi = new FormParameterImpl(contentType, name, bais, null); - result.add(fpi); - } - return result; - } - - @SuppressWarnings("unchecked") + + /** + * The MIME type 'application/x-www-form-urlencoded'. + */ + public static final String CONTENT_TYPE = "application/x-www-form-urlencoded"; + + /** + * The form parameter iterator. + */ + protected XWWWFormUrlInputIterator iterator; + + @SuppressWarnings("unchecked") @Override public void setContentType(String contentType) { ParameterParser pp = new ParameterParser(); pp.setLowerCaseNames(true); Map params = pp.parse(contentType, new char[] { ':', ';' }); - if (!params.containsKey("application/x-www-form-urlencoded")) { + if (!params.containsKey(CONTENT_TYPE)) { throw new IllegalArgumentException( "not a url encoded content type specification: " + contentType); } - String cs = params.get(CHAR_SET); - if (cs != null) { - charset = cs; - } - this.contentType = contentType; } @Override public Iterator getFormParameterIterator() { - try { - return decodeInput(dataStream).iterator(); - } catch (IOException e) { - throw new SLRuntimeException(e); - } + return iterator; } @Override public void setInputStream(InputStream is) { - dataStream = is; + iterator = new XWWWFormUrlInputIterator(is); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIterator.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIterator.java new file mode 100644 index 00000000..f052ce05 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIterator.java @@ -0,0 +1,376 @@ +package at.gv.egiz.bku.binding; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FilterInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.nio.charset.Charset; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.NoSuchElementException; + +public class XWWWFormUrlInputIterator implements Iterator { + + public static final byte NAME_VALUE_SEP = '='; + + public static final byte PARAM_SEP = '&'; + + public static final Charset UTF_8 = Charset.forName("UTF-8"); + + /** + * The default buffer size. + */ + protected static final int DEFAULT_BUFFER_SIZE = 4096; + + /** + * Are we done with parsing the input. + */ + protected boolean done = false; + + /** + * The x-www-formdata-urlencoded input stream to be parsed. + */ + protected final InputStream in; + + /** + * The buffer size. + */ + protected int bufferSize = DEFAULT_BUFFER_SIZE; + + /** + * The read buffer. + */ + protected final byte[] buf = new byte[bufferSize]; + + /** + * The read position. + */ + protected int pos; + + /** + * The number of valid bytes in the buffer; + */ + protected int count; + + /** + * The parameter returned by the last call of {@link #next()}; + */ + protected XWWWFormUrlEncodedParameter currentParameter; + + /** + * An IOException that cannot be reported immediately. + */ + protected IOException deferredIOException; + + /** + * Creates a new instance of this x-www-formdata-urlencoded input iterator + * with the given InputStream in to be parsed. + * + * @param in the InputStream to be parsed + */ + public XWWWFormUrlInputIterator(InputStream in) { + this.in = in; + } + + /* (non-Javadoc) + * @see java.util.Iterator#hasNext() + */ + @Override + public boolean hasNext() { + if (done) { + return false; + } + if (currentParameter != null) { + // we have to disconnect the current parameter + // to look for further parameters + try { + currentParameter.formParameterValue.disconnect(); + // fill buffer if empty + if (pos >= count) { + if ((count = in.read(buf)) == -1) { + // done + done = true; + return false; + } + pos = 0; + } + } catch (IOException e) { + deferredIOException = e; + } + } + return true; + } + + @Override + public FormParameter next() { + if (hasNext()) { + // skip separator + pos++; + currentParameter = new XWWWFormUrlEncodedParameter(); + return currentParameter; + } else { + throw new NoSuchElementException(); + } + } + + @Override + public void remove() { + throw new UnsupportedOperationException(); + } + + public class XWWWFormUrlEncodedParameter implements FormParameter { + + /** + * The list of header names. + */ + // x-www-form-urlencoded parameters do not provide headers + protected final List headers = Collections.emptyList(); + + /** + * The name of the form parameter. + */ + protected String formParameterName; + + /** + * The value of the form parameter. + */ + protected URLDecodingInputStream formParameterValue; + + public XWWWFormUrlEncodedParameter() { + // parse parameter name + URLDecodingInputStream urldec = new URLDecodingInputStream(in, NAME_VALUE_SEP); + InputStreamReader reader = new InputStreamReader(urldec, UTF_8); + try { + StringBuilder sb = new StringBuilder(); + char[] b = new char[128]; + for (int l = 0; (l = reader.read(b)) != -1;) { + sb.append(b, 0, l); + } + formParameterName = sb.toString(); + // fill buffer if empty + if (pos >= count) { + if ((count = in.read(buf)) == -1) { + throw new IOException("Invalid URL encoding."); + } + pos = 0; + } + // skip separator + pos++; + } catch (IOException e) { + deferredIOException = e; + formParameterName = ""; + } + formParameterValue = new URLDecodingInputStream(in, PARAM_SEP); + } + + @Override + public String getFormParameterContentType() { + // x-www-form-urlencoded parameters do not specify a content type + return null; + } + + @Override + public String getFormParameterName() { + return formParameterName; + } + + @Override + public InputStream getFormParameterValue() { + if (deferredIOException != null) { + final IOException e = deferredIOException; + deferredIOException = null; + return new InputStream() { + @Override + public int read() throws IOException { + throw e; + } + }; + } else { + return formParameterValue; + } + } + + @Override + public Iterator getHeaderNames() { + return headers.iterator(); + } + + @Override + public String getHeaderValue(String headerName) { + return null; + } + + } + + public class URLDecodingInputStream extends FilterInputStream { + + /** + * Has this stream already been closed. + */ + private boolean closed = false; + + /** + * Has this stream been disconnected. + */ + private boolean disconnected = false; + + /** + * Read until this byte occurs. + */ + protected final byte term; + + /** + * Creates a new instance of this URLDecodingInputStream. + * + * @param in + * @param separator + */ + protected URLDecodingInputStream(InputStream in, byte separator) { + super(in); + this.term = separator; + } + + /* (non-Javadoc) + * @see java.io.FilterInputStream#read() + */ + @Override + public int read() throws IOException { + if (closed) { + throw new IOException("The stream has already been closed."); + } + if (disconnected) { + return in.read(); + } + + if (pos >= count) { + if ((count = in.read(buf)) == -1) { + return -1; + } + pos = 0; + } if (buf[pos] == term) { + return -1; + } else if (buf[pos] == '+') { + pos++; + return ' '; + } else if (buf[pos] == '%') { + if (++pos == count) { + if ((count = in.read(buf)) == -1) { + throw new IOException("Invalid URL encoding."); + } + pos = 0; + } + int c1 = Character.digit(buf[pos], 16); + if (++pos == count) { + if ((count = in.read(buf)) == -1) { + throw new IOException("Invalid URL encoding."); + } + pos = 0; + } + int c2 = Character.digit(buf[pos], 16); + return ((c1 << 4) | c2); + } else { + return buf[pos++]; + } + } + + /* (non-Javadoc) + * @see java.io.FilterInputStream#read(byte[], int, int) + */ + @Override + public int read(byte[] b, int off, int len) throws IOException { + if (closed) { + throw new IOException("The stream has already been closed."); + } + if (disconnected) { + return in.read(b, off, len); + } + + if ((off | len | (off + len) | (b.length - (off + len))) < 0) { + throw new IndexOutOfBoundsException(); + } else if (len == 0) { + return 0; + } + + if (pos >= count) { + if ((count = in.read(buf)) == -1) { + return -1; + } + pos = 0; + } + if (buf[pos] == term) { + return -1; + } + + int l = 0; + for (;;) { + while (pos < count) { + if (l == len || buf[pos] == term) { + return l; + } else if (buf[pos] == '+') { + b[off] = ' '; + } else if (buf[pos] == '%') { + if (++pos == count && (count = in.read(buf)) == -1) { + throw new IOException("Invalid URL encoding."); + } + int c1 = Character.digit(buf[pos], 16); + if (++pos == count && (count = in.read(buf)) == -1) { + throw new IOException("Invalid URL encoding."); + } + int c2 = Character.digit(buf[pos], 16); + b[off] = (byte) ((c1 << 4) | c2); + } else { + b[off] = buf[pos]; + } + pos++; + off++; + l++; + } + if ((count = in.read(buf)) == -1) { + return l; + } + pos = 0; + } + } + + /** + * Disconnect from the InputStream and buffer all remaining data. + * + * @throws IOException + */ + public void disconnect() throws IOException { + if (!disconnected) { + // don't waste space for a buffer if end of stream has already been + // reached + byte[] b = new byte[1]; + if ((read(b)) != -1) { + ByteArrayOutputStream os = new ByteArrayOutputStream(); + os.write(b); + b = new byte[1024]; + for (int l; (l = read(b, 0, b.length)) != -1;) { + os.write(b, 0, l); + } + super.in = new ByteArrayInputStream(os.toByteArray()); + } + disconnected = true; + } + } + + /* (non-Javadoc) + * @see java.io.FilterInputStream#close() + */ + @Override + public void close() throws IOException { + if (!hasNext()) { + // don't close the underlying stream until all parts are read + super.close(); + } + disconnect(); + closed = true; + } + + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java b/bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java index 5585f02e..d896ea9f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/binding/multipart/SLResultPart.java @@ -16,37 +16,56 @@ */ package at.gv.egiz.bku.binding.multipart; +import at.gv.egiz.bku.binding.DataUrlConnection; import at.gv.egiz.bku.slcommands.SLResult; +import at.gv.egiz.bku.slcommands.SLResult.SLResultType; + import java.io.IOException; +import java.io.InputStream; import java.io.OutputStream; import java.io.OutputStreamWriter; import javax.xml.transform.stream.StreamResult; -import org.apache.commons.httpclient.methods.multipart.ByteArrayPartSource; import org.apache.commons.httpclient.methods.multipart.FilePart; +import org.apache.commons.httpclient.methods.multipart.PartSource; -/** - * - * @author clemens - */ public class SLResultPart extends FilePart { protected SLResult slResult; protected String encoding; public SLResultPart(SLResult slResult, String encoding) { - super("XMLResponse", - new ByteArrayPartSource(null, "dummySource".getBytes())); + super((slResult.getResultType() == SLResultType.XML) + ? DataUrlConnection.FORMPARAM_XMLRESPONSE + : DataUrlConnection.FORMPARAM_BINARYRESPONSE, + new PartSource() { + + @Override + public long getLength() { + // may return null, as sendData() is overridden + return 0; + } + + @Override + public String getFileName() { + // return null, to prevent content-disposition header + return null; + } + + @Override + public InputStream createInputStream() throws IOException { + // may return null, as sendData() is overridden below + return null; + } + } + ); this.slResult = slResult; this.encoding = encoding; } @Override protected void sendData(OutputStream out) throws IOException { - slResult.writeTo(new StreamResult(new OutputStreamWriter(out, encoding))); - // slResult.writeTo(new StreamResult(new OutputStreamWriter(System.out, - // encoding))); - // super.sendData(out); + slResult.writeTo(new StreamResult(new OutputStreamWriter(out, encoding)), false); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java index 125233c1..3b2d1b99 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/CertValidatorImpl.java @@ -1,7 +1,9 @@ package at.gv.egiz.bku.conf; +import iaik.logging.LogConfigurationException; import iaik.logging.TransactionId; import iaik.logging.impl.TransactionIdImpl; +import iaik.logging.LoggerConfig; import iaik.pki.DefaultPKIConfiguration; import iaik.pki.DefaultPKIProfile; import iaik.pki.PKIConfiguration; @@ -18,6 +20,7 @@ import iaik.x509.X509Certificate; import java.io.File; import java.util.Date; +import java.util.Properties; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -37,6 +40,27 @@ public class CertValidatorImpl implements CertValidator { * @see at.gv.egiz.bku.conf.CertValidator#init(java.io.File, java.io.File) */ public void init(File certDir, File caDir) { + // initialize IAIK logging for PKI module + log.debug("Configuring logging for IAIK PKI module"); + iaik.logging.LogFactory.configure(new LoggerConfig() { + + @Override + public Properties getProperties() throws LogConfigurationException { + return null; + } + + @Override + public String getNodeId() { + return "pki"; + } + + @Override + public String getFactory() { + return IAIKCommonsLogFactory.class.getName(); + } + }); + + // the parameters specifying the directory certstore CertStoreParameters[] certStoreParameters = { new DefaultDirectoryCertStoreParameters( "CS-001", certDir.getAbsolutePath(), true, false) }; diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLog.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLog.java new file mode 100644 index 00000000..1b7dd189 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLog.java @@ -0,0 +1,144 @@ +/** + * + */ +package at.gv.egiz.bku.conf; + +import iaik.logging.Log; +import iaik.logging.TransactionId; + +/** + * @author mcentner + * + */ +public class IAIKCommonsLog implements Log { + + /** + * The id that will be written to the log if the transactionid == null + */ + public final static String NO_ID = "Null-ID"; + + protected org.apache.commons.logging.Log commonsLog; + + protected String nodeId; + + public IAIKCommonsLog(org.apache.commons.logging.Log log) { + this.commonsLog = log; + } + + /* (non-Javadoc) + * @see iaik.logging.Log#debug(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable) + */ + @Override + public void debug(TransactionId transactionId, Object message, Throwable t) { + if (commonsLog.isDebugEnabled()) { + commonsLog.debug(nodeId + ": " + + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": " + + message, t); + } + } + + /* (non-Javadoc) + * @see iaik.logging.Log#info(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable) + */ + @Override + public void info(TransactionId transactionId, Object message, Throwable t) { + if (commonsLog.isInfoEnabled()) { + commonsLog.info(nodeId + ": " + + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": " + + message, t); + } + } + + /* (non-Javadoc) + * @see iaik.logging.Log#warn(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable) + */ + @Override + public void warn(TransactionId transactionId, Object message, Throwable t) { + if (commonsLog.isWarnEnabled()) { + commonsLog.warn(nodeId + ": " + + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": " + + message, t); + } + } + + /* (non-Javadoc) + * @see iaik.logging.Log#error(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable) + */ + @Override + public void error(TransactionId transactionId, Object message, Throwable t) { + if (commonsLog.isErrorEnabled()) { + commonsLog.error(nodeId + ": " + + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": " + + message, t); + } + } + + /* (non-Javadoc) + * @see iaik.logging.Log#fatal(iaik.logging.TransactionId, java.lang.Object, java.lang.Throwable) + */ + @Override + public void fatal(TransactionId transactionId, Object message, Throwable t) { + if (commonsLog.isFatalEnabled()) { + commonsLog.fatal(nodeId + ": " + + ((transactionId != null) ? transactionId.getLogID() : NO_ID) + ": " + + message, t); + } + } + + /* (non-Javadoc) + * @see iaik.logging.Log#setNodeId(java.lang.String) + */ + @Override + public void setNodeId(String nodeId) { + this.nodeId = nodeId; + } + + /* (non-Javadoc) + * @see iaik.logging.Log#getNodeId() + */ + @Override + public String getNodeId() { + return nodeId; + } + + /* (non-Javadoc) + * @see iaik.logging.Log#isDebugEnabled() + */ + @Override + public boolean isDebugEnabled() { + return commonsLog.isDebugEnabled(); + } + + /* (non-Javadoc) + * @see iaik.logging.Log#isInfoEnabled() + */ + @Override + public boolean isInfoEnabled() { + return commonsLog.isInfoEnabled(); + } + + /* (non-Javadoc) + * @see iaik.logging.Log#isWarnEnabled() + */ + @Override + public boolean isWarnEnabled() { + return commonsLog.isWarnEnabled(); + } + + /* (non-Javadoc) + * @see iaik.logging.Log#isErrorEnabled() + */ + @Override + public boolean isErrorEnabled() { + return commonsLog.isErrorEnabled(); + } + + /* (non-Javadoc) + * @see iaik.logging.Log#isFatalEnabled() + */ + @Override + public boolean isFatalEnabled() { + return commonsLog.isFatalEnabled(); + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java new file mode 100644 index 00000000..14e2c757 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/IAIKCommonsLogFactory.java @@ -0,0 +1,59 @@ +/** + * + */ +package at.gv.egiz.bku.conf; + +import org.apache.commons.logging.impl.WeakHashtable; + +import iaik.logging.Log; +import iaik.logging.LogConfigurationException; +import iaik.logging.LogFactory; + +/** + * @author mcentner + * + */ +public class IAIKCommonsLogFactory extends LogFactory { + + protected WeakHashtable instances = new WeakHashtable(); + + /* (non-Javadoc) + * @see iaik.logging.LogFactory#getInstance(java.lang.String) + */ + @Override + public Log getInstance(String name) throws LogConfigurationException { + org.apache.commons.logging.Log commonsLog = org.apache.commons.logging.LogFactory.getLog(name); + Log log = (Log) instances.get(commonsLog); + if (log == null) { + log = new IAIKCommonsLog(commonsLog); + log.setNodeId(node_id_); + instances.put(commonsLog, log); + } + return log; + } + + /* (non-Javadoc) + * @see iaik.logging.LogFactory#getInstance(java.lang.Class) + */ + @SuppressWarnings("unchecked") + @Override + public Log getInstance(Class clazz) throws LogConfigurationException { + org.apache.commons.logging.Log commonsLog = org.apache.commons.logging.LogFactory.getLog(clazz); + Log log = (Log) instances.get(commonsLog); + if (log == null) { + log = new IAIKCommonsLog(commonsLog); + log.setNodeId(node_id_); + instances.put(commonsLog, log); + } + return log; + } + + /* (non-Javadoc) + * @see iaik.logging.LogFactory#release() + */ + @Override + public void release() { + instances.clear(); + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java index fe27bc54..8e3f6ece 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLCommandFactory.java @@ -28,6 +28,7 @@ import javax.xml.bind.JAXBException; import javax.xml.bind.UnmarshalException; import javax.xml.bind.Unmarshaller; import javax.xml.bind.ValidationEvent; +import javax.xml.bind.ValidationEventLocator; import javax.xml.namespace.QName; import javax.xml.stream.XMLEventReader; import javax.xml.stream.XMLInputFactory; @@ -46,11 +47,11 @@ import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLExceptionMessages; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.slexceptions.SLVersionException; import at.gv.egiz.bku.utils.DebugReader; import at.gv.egiz.slbinding.RedirectEventFilter; import at.gv.egiz.slbinding.RedirectUnmarshallerListener; -import at.gv.egiz.validation.ValidationEventLogger; -import javax.xml.bind.ValidationEventHandler; +import at.gv.egiz.validation.ReportingValidationEventHandler; public class SLCommandFactory { @@ -60,7 +61,9 @@ public class SLCommandFactory { public static final String[] SCHEMA_FILES = new String[]{ "at/gv/egiz/bku/slcommands/schema/xml.xsd", "at/gv/egiz/bku/slcommands/schema/xmldsig-core-schema.xsd", - "at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd" + "at/gv/egiz/bku/slcommands/schema/Core-1.2.xsd", + "at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd", + "at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd" }; /** * Logging facility. @@ -169,7 +172,10 @@ public class SLCommandFactory { String slPkg = at.buergerkarte.namespaces.securitylayer._1.ObjectFactory.class.getPackage().getName(); String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); String cardChannelPkg = at.buergerkarte.namespaces.cardchannel.ObjectFactory.class.getPackage().getName(); - setJaxbContext(JAXBContext.newInstance(slPkg + ":" + xmldsigPkg + ":" + cardChannelPkg)); + String slPkgLegacy1_0 = at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory.class.getPackage().getName(); + String slPkgLegacy1_1 = at.buergerkarte.namespaces.securitylayer._20020831_.ObjectFactory.class.getPackage().getName(); + setJaxbContext(JAXBContext.newInstance(slPkg + ":" + xmldsigPkg + ":" + cardChannelPkg + + ":" + slPkgLegacy1_0 + ":" + slPkgLegacy1_1)); } catch (JAXBException e) { log.error("Failed to setup JAXBContext security layer request.", e); throw new SLRuntimeException(e); @@ -248,26 +254,9 @@ public class SLCommandFactory { SLRequestException { Object object; + ReportingValidationEventHandler validationEventHandler = new ReportingValidationEventHandler(); try { -// ValidatorHandler validator = slSchema.newValidatorHandler(); -// validator.getContentHandler(); -// -// SAXParserFactory spf = SAXParserFactory.newInstance(); -// spf.setNamespaceAware(true); -// XMLReader saxReader = spf.newSAXParser().getXMLReader(); -// //TODO extend validator to implement redirectContentHandler (validate+redirect) -// saxReader.setContentHandler(validator); -// //TODO get a InputSource -// SAXSource saxSource = new SAXSource(saxReader, source); -// -// Unmarshaller unmarshaller = jaxbContext.createUnmarshaller(); -// //turn off duplicate jaxb validation -// unmarshaller.setSchema(null); -// unmarshaller.setListener(listener); -// unmarshaller.unmarshal(saxSource); - - XMLInputFactory inputFactory = XMLInputFactory.newInstance(); XMLEventReader eventReader = inputFactory.createXMLEventReader(source); RedirectEventFilter redirectEventFilter = new RedirectEventFilter(); @@ -279,7 +268,7 @@ public class SLCommandFactory { unmarshaller.setSchema(slSchema); } log.trace("Before unmarshal()."); - unmarshaller.setEventHandler(new ValidationEventLogger()); + unmarshaller.setEventHandler(validationEventHandler); object = unmarshaller.unmarshal(filteredReader); log.trace("After unmarshal()."); } catch (UnmarshalException e) { @@ -288,6 +277,13 @@ public class SLCommandFactory { } else { log.info("Failed to unmarshall security layer request." + e.getMessage()); } + if (validationEventHandler.getErrorEvent() != null) { + // Validation Error + ValidationEvent errorEvent = validationEventHandler.getErrorEvent(); + ValidationEventLocator locator = errorEvent.getLocator(); + throw new SLRequestException(3002, + SLExceptionMessages.EC3002_INVALID, new Object[]{errorEvent.getMessage()}); + } Throwable cause = e.getCause(); if (cause instanceof SAXParseException) { throw new SLRequestException(3000, @@ -328,10 +324,11 @@ public class SLCommandFactory { * if an unexpected error occurs configuring the unmarshaller, if * unmarshalling fails with an unexpected error or if the * corresponding SLCommand could not be instantiated + * @throws SLVersionException */ @SuppressWarnings("unchecked") public SLCommand createSLCommand(Source source, SLCommandContext context) - throws SLCommandException, SLRuntimeException, SLRequestException { + throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { DebugReader dr = null; if (log.isTraceEnabled() && source instanceof StreamSource) { @@ -361,6 +358,12 @@ public class SLCommandFactory { } QName qName = ((JAXBElement) object).getName(); + if (!SLCommand.NAMESPACE_URI.equals(qName.getNamespaceURI())) { + // security layer request version not supported + log.info("Unsupported security layer request version : " + qName.getNamespaceURI()); + throw new SLVersionException(qName.getNamespaceURI()); + } + Class implClass = getImplClass(qName); if (implClass == null) { // command not supported diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLMarshallerFactory.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLMarshallerFactory.java new file mode 100644 index 00000000..e0a375cf --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLMarshallerFactory.java @@ -0,0 +1,172 @@ +/* +* Copyright 2009 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.slcommands; + +import javax.xml.bind.JAXBContext; +import javax.xml.bind.JAXBException; +import javax.xml.bind.Marshaller; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.marshal.MarshallerFactory; + +public class SLMarshallerFactory { + + static Log log = LogFactory.getLog(SLMarshallerFactory.class); + + /** + * The JAXBContext used for result marshaling. + *

+ * Note: Different contexts are used for marshaling and unmarshaling of + * security layer requests and responses to avoid propagation of namespace + * declarations of legacy namespaces into marshaled results. + *

+ * @see #jaxbContextLegacy + */ + protected static JAXBContext context; + + /** + * The JAXBContext used for marshaling of of results in the legacy namespace. + */ + protected static JAXBContext legacyContext; + + // ------------------- initialization on demand idiom ------------------- + // see http://en.wikipedia.org/wiki/Initialization_on_demand_holder_idiom + // ---------------------------------------------------------------------- + + /** + * Private constructor called by {@link SLMarshallerFactoryInstanceHolder}. + */ + private SLMarshallerFactory() { + // context is initialized immediately while the legacy context is initialized only on demand + try { + String slPkg = at.buergerkarte.namespaces.securitylayer._1.ObjectFactory.class.getPackage().getName(); + String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); + String cardChannelPkg = at.buergerkarte.namespaces.cardchannel.ObjectFactory.class.getPackage().getName(); + context = JAXBContext.newInstance(slPkg + ":" + xmldsigPkg + ":" + cardChannelPkg); + } catch (JAXBException e) { + log.error("Failed to setup JAXBContext security layer request.", e); + throw new SLRuntimeException(e); + } + } + + /** + * The lazy instance holder for this SLMarshallerFactory. + */ + private static class SLMarshallerFactoryInstanceHolder { + /** + * The instance returned by {@link SLMarshallerFactory#getInstance()} + */ + private static final SLMarshallerFactory instance = new SLMarshallerFactory(); + } + + /** + * Get an instance of the SLMarshallerFactory. + */ + public static SLMarshallerFactory getInstance() { + return SLMarshallerFactoryInstanceHolder.instance; + } + + // ---------------------------------------------------------------------- + + /** + * Initialize the JAXBContext for the legacy namespace. + */ + private static synchronized void ensureLegacyContext() { + // legacy marshaller is initialized only on demand + if (legacyContext == null) { + try { + String slPkgLegacy1_0 = at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory.class.getPackage().getName(); + String slPkgLegacy1_1 = at.buergerkarte.namespaces.securitylayer._20020831_.ObjectFactory.class.getPackage().getName(); + String xmldsigPkg = org.w3._2000._09.xmldsig_.ObjectFactory.class.getPackage().getName(); + String cardChannelPkg = at.buergerkarte.namespaces.cardchannel.ObjectFactory.class.getPackage().getName(); + legacyContext = JAXBContext.newInstance(slPkgLegacy1_0 + ":" + slPkgLegacy1_1 + ":" + xmldsigPkg + ":" + cardChannelPkg); + } catch (JAXBException e) { + log.error("Failed to setup JAXBContext security layer request.", e); + throw new SLRuntimeException(e); + } + } + } + + /** + * Creates an SL marshaller. + * + * @param formattedOutput + * true if the marshaller should produce formated + * output, false otherwise + * @return an SL marshaller + */ + public Marshaller createMarshaller(boolean formattedOutput) { + return createMarshaller(formattedOutput, false); + } + + /** + * Creates an SL marshaller. + * + * @param formattedOutput + * true if the marshaller should produce formated + * output, false otherwise + * @param fragment + * true if the marshaller should produce a XML fragment + * (omit XML declaration), false otherwise + * @return an SL marshaller + */ + public Marshaller createMarshaller(boolean formattedOutput, boolean fragment) { + try { + return MarshallerFactory.createMarshaller(context, formattedOutput, fragment); + } catch (JAXBException e) { + log.fatal("Failed to marshall error response.", e); + throw new SLRuntimeException("Failed to marshall error response.", e); + } + } + + /** + * Creates a legacy SL marshaller. + * + * @param formattedOutput + * true if the marshaller should produce formated + * output, false otherwise + * @return a legacy SL marshaller + */ + public Marshaller createLegacyMarshaller(boolean formattedOutput) { + return createLegacyMarshaller(formattedOutput, false); + } + + /** + * Creates a legacy SL marshaller. + * + * @param formattedOutput + * true if the marshaller should produce formated + * output, false otherwise + * @param fragment + * true if the marshaller should produce a XML fragment + * (omit XML declaration), false otherwise + * @return a legacy SL marshaller + */ + public Marshaller createLegacyMarshaller(boolean formattedOutput, boolean fragment) { + try { + ensureLegacyContext(); + return MarshallerFactory.createMarshaller(legacyContext, formattedOutput, fragment); + } catch (JAXBException e) { + log.fatal("Failed to marshall error response.", e); + throw new SLRuntimeException("Failed to marshall error response.", e); + } + } + +} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java index 7989a771..e9e483c5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/SLResult.java @@ -32,12 +32,14 @@ public interface SLResult { */ public String getMimeType(); - public void writeTo(Result aResult); + public void writeTo(Result aResult, boolean fragment); /** * - * @param result + * @param result + * @param fragment TODO * @param transformer may be null. */ - public void writeTo(Result result, Templates templates); + public void writeTo(Result result, Templates templates, boolean fragment); + } \ No newline at end of file diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java index ce03dcf9..9a4536e6 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/AbstractAssocArrayInfobox.java @@ -16,7 +16,6 @@ */ package at.gv.egiz.bku.slcommands.impl; -import at.gv.egiz.marshal.NamespacePrefixMapperImpl; import java.io.ByteArrayOutputStream; import java.util.Arrays; import java.util.Collections; @@ -24,7 +23,6 @@ import java.util.List; import java.util.Map; import java.util.regex.Pattern; -import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @@ -42,10 +40,8 @@ import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayTy import at.buergerkarte.namespaces.securitylayer._1.InfoboxReadParamsAssocArrayType.ReadValue; import at.gv.egiz.bku.slcommands.InfoboxReadResult; import at.gv.egiz.bku.slcommands.SLCommandContext; -import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLMarshallerFactory; import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.marshal.MarshallerFactory; -import javax.xml.bind.PropertyException; /** * An abstract base class for {@link Infobox} implementations of type associative array. @@ -255,13 +251,10 @@ public abstract class AbstractAssocArrayInfobox extends AbstractInfoboxImpl } protected byte[] marshallValue(Object jaxbElement) throws SLCommandException { - SLCommandFactory commandFactory = SLCommandFactory.getInstance(); - JAXBContext jaxbContext = commandFactory.getJaxbContext(); - ByteArrayOutputStream result; + Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false); + ByteArrayOutputStream result = new ByteArrayOutputStream(); try { - Marshaller marshaller = MarshallerFactory.createMarshaller(jaxbContext); - result = new ByteArrayOutputStream(); marshaller.marshal(jaxbElement, result); } catch (JAXBException e) { log.info("Failed to marshall infobox content.", e); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java index b352a51e..19df4334 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureResultImpl.java @@ -16,8 +16,6 @@ */ package at.gv.egiz.bku.slcommands.impl; -import at.gv.egiz.marshal.NamespacePrefixMapperImpl; -import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @@ -33,10 +31,8 @@ import org.w3c.dom.Node; import at.buergerkarte.namespaces.securitylayer._1.CreateXMLSignatureResponseType; import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; -import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLMarshallerFactory; import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.marshal.MarshallerFactory; -import javax.xml.bind.PropertyException; /** * This calls implements the result of the security layer command CreateXMLSignature. @@ -86,10 +82,9 @@ public class CreateXMLSignatureResultImpl extends SLResultImpl { JAXBElement createCreateXMLSignatureResponse = factory.createCreateXMLSignatureResponse(createCreateXMLSignatureResponseType); DocumentFragment fragment = doc.createDocumentFragment(); - - JAXBContext jaxbContext = SLCommandFactory.getInstance().getJaxbContext(); + + Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false); try { - Marshaller marshaller = MarshallerFactory.createMarshaller(jaxbContext); marshaller.marshal(createCreateXMLSignatureResponse, fragment); } catch (JAXBException e) { log.error("Failed to marshall 'CreateXMLSignatureResponse'", e); @@ -105,8 +100,8 @@ public class CreateXMLSignatureResultImpl extends SLResultImpl { } @Override - public void writeTo(Result result, Templates templates) { - writeTo(doc, result, templates); + public void writeTo(Result result, Templates templates, boolean fragment) { + writeTo(doc, result, templates, fragment); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java index 5d0f0de0..aedde238 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImpl.java @@ -56,11 +56,11 @@ public class ErrorResultImpl extends SLResultImpl implements ErrorResult { } @Override - public void writeTo(Result result, Templates templates) { + public void writeTo(Result result, Templates templates, boolean fragment) { if (locale == null) { - writeErrorTo(slException, result, templates); + writeErrorTo(slException, result, templates, fragment); } else { - writeErrorTo(slException, result, templates, locale); + writeErrorTo(slException, result, templates, locale, fragment); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java index 46bfe18b..0c2b96f9 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusCommandImpl.java @@ -19,10 +19,8 @@ package at.gv.egiz.bku.slcommands.impl; import at.buergerkarte.namespaces.securitylayer._1.GetStatusRequestType; import at.gv.egiz.bku.slcommands.GetStatusCommand; -import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slexceptions.SLCommandException; -import at.gv.egiz.bku.slexceptions.SLException; import at.gv.egiz.stal.ErrorResponse; import at.gv.egiz.stal.STAL; import at.gv.egiz.stal.STALResponse; diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java index fddd3b0b..fb1f627f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/GetStatusResultImpl.java @@ -45,8 +45,8 @@ public class GetStatusResultImpl extends SLResultImpl implements GetStatusResult } @Override - public void writeTo(Result result, Templates templates) { + public void writeTo(Result result, Templates templates, boolean fragment) { JAXBElement response = of.createGetStatusResponse(responseType); - writeTo(response, result, templates); + writeTo(response, result, templates, fragment); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java index 7a82e43f..160e9589 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/IdentityLinkInfoboxImpl.java @@ -18,7 +18,6 @@ package at.gv.egiz.bku.slcommands.impl; import java.io.ByteArrayOutputStream; import java.io.IOException; -import java.io.OutputStream; import java.net.MalformedURLException; import java.security.cert.X509Certificate; import java.util.ArrayList; diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java index 75e44afa..422b424f 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultFileImpl.java @@ -16,8 +16,6 @@ */ package at.gv.egiz.bku.slcommands.impl; -import at.gv.egiz.marshal.NamespacePrefixMapperImpl; -import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @@ -39,10 +37,8 @@ import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; import at.buergerkarte.namespaces.securitylayer._1.XMLContentType; import at.gv.egiz.bku.slcommands.InfoboxReadResult; import at.gv.egiz.bku.slcommands.SLCommand; -import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLMarshallerFactory; import at.gv.egiz.bku.slexceptions.SLRuntimeException; -import at.gv.egiz.marshal.MarshallerFactory; -import javax.xml.bind.PropertyException; /** * This class implements the result of the security layer command InfoboxReadRequest. @@ -98,10 +94,9 @@ public class InfoboxReadResultFileImpl extends SLResultImpl implements infoboxReadResponseType.setBinaryFileData(base64XMLContentType); JAXBElement infoboxReadResponse = factory.createInfoboxReadResponse(infoboxReadResponseType); - - JAXBContext context = SLCommandFactory.getInstance().getJaxbContext(); + + Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false); try { - Marshaller marshaller = MarshallerFactory.createMarshaller(context); marshaller.marshal(infoboxReadResponse, doc); } catch (JAXBException e) { log.error("Failed to marshal 'InfoboxReadResponse' document.", e); @@ -158,8 +153,8 @@ public class InfoboxReadResultFileImpl extends SLResultImpl implements } @Override - public void writeTo(Result result, Templates templates) { - writeTo(xmlDocument, result, templates); + public void writeTo(Result result, Templates templates, boolean fragment) { + writeTo(xmlDocument, result, templates, fragment); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java index e508941d..271ec955 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadResultImpl.java @@ -55,10 +55,10 @@ public class InfoboxReadResultImpl extends SLResultImpl implements InfoboxReadRe } @Override - public void writeTo(Result result, Templates templates) { + public void writeTo(Result result, Templates templates, boolean fragment) { ObjectFactory objectFactory = new ObjectFactory(); JAXBElement response = objectFactory.createInfoboxReadResponse(infoboxReadResponse); - writeTo(response, result, templates); + writeTo(response, result, templates, fragment); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java index 15064756..e12536ba 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/InfoboxUpdateResultImpl.java @@ -36,8 +36,8 @@ public class InfoboxUpdateResultImpl extends SLResultImpl implements } @Override - public void writeTo(Result result, Templates templates) { - writeTo(RESPONSE, result, templates); + public void writeTo(Result result, Templates templates, boolean fragment) { + writeTo(RESPONSE, result, templates, fragment); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java index 05986f85..87733e39 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImpl.java @@ -41,8 +41,8 @@ public class NullOperationResultImpl extends SLResultImpl implements NullOperati } @Override - public void writeTo(Result result, Templates templates) { - writeTo(RESPONSE, result, templates); + public void writeTo(Result result, Templates templates, boolean fragment) { + super.writeTo(RESPONSE, result, templates, fragment); } } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java index 0452bddf..0077b7b2 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/SLResultImpl.java @@ -17,12 +17,14 @@ package at.gv.egiz.bku.slcommands.impl; import java.io.UnsupportedEncodingException; +import java.math.BigInteger; import java.util.Locale; -import javax.xml.bind.JAXBContext; +import javax.xml.XMLConstants; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; +import javax.xml.transform.OutputKeys; import javax.xml.transform.Result; import javax.xml.transform.Templates; import javax.xml.transform.Transformer; @@ -41,17 +43,15 @@ import org.w3c.dom.Node; import at.buergerkarte.namespaces.securitylayer._1.ErrorResponseType; import at.buergerkarte.namespaces.securitylayer._1.ObjectFactory; -import at.gv.egiz.marshal.NamespacePrefixMapperImpl; -import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLMarshallerFactory; import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slexceptions.SLBindingException; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLException; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.slexceptions.SLVersionException; import at.gv.egiz.bku.utils.DebugOutputStream; import at.gv.egiz.bku.utils.DebugWriter; -import at.gv.egiz.marshal.MarshallerFactory; -import javax.xml.bind.PropertyException; /** * This class serves as an abstract base class for the implementation of a @@ -90,20 +90,18 @@ public abstract class SLResultImpl implements SLResult { return resultingMimeType; } - private Marshaller getMarshaller() { - try { - JAXBContext context = SLCommandFactory.getInstance().getJaxbContext(); - Marshaller marshaller = MarshallerFactory.createMarshaller(context, true); - return marshaller; - } catch (JAXBException e) { - log.fatal("Failed to marshall error response.", e); - throw new SLRuntimeException("Failed to marshall error response.", e); - } + @Override + public void writeTo(Result result, boolean fragment) { + writeTo(result, null, false); } + @Override + public abstract void writeTo(Result result, Templates templates, boolean fragment); + private TransformerHandler getTransformerHandler(Templates templates, Result result) throws SLException { try { SAXTransformerFactory transformerFactory = (SAXTransformerFactory) SAXTransformerFactory.newInstance(); + transformerFactory.setFeature(XMLConstants.FEATURE_SECURE_PROCESSING, true); TransformerHandler transformerHandler = transformerFactory.newTransformerHandler(templates); transformerHandler.setResult(result); return transformerHandler; @@ -119,12 +117,6 @@ public abstract class SLResultImpl implements SLResult { } } - @Override - public void writeTo(Result result) { - writeTo(result, null); - } - - /** * Writes the given response to the SAX result using * the given transform templates. @@ -133,7 +125,7 @@ public abstract class SLResultImpl implements SLResult { * @param result * @param templates */ - protected void writeTo(JAXBElement response, Result result, Templates templates) { + protected void writeTo(JAXBElement response, Result result, Templates templates, boolean fragment) { DebugWriter dw = null; DebugOutputStream ds = null; @@ -154,11 +146,11 @@ public abstract class SLResultImpl implements SLResult { try { transformerHandler = getTransformerHandler(templates, result); } catch (SLException e) { - writeErrorTo(e, result, templates); + writeErrorTo(e, result, templates, fragment); } } - Marshaller marshaller = getMarshaller(); + Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(true); try { if (transformerHandler != null) { marshaller.marshal(response, transformerHandler); @@ -168,7 +160,7 @@ public abstract class SLResultImpl implements SLResult { } catch (JAXBException e) { log.info("Failed to marshall " + response.getName() + " result." , e); SLCommandException commandException = new SLCommandException(4000); - writeErrorTo(commandException, result, templates); + writeErrorTo(commandException, result, templates, fragment); } if (ds != null) { @@ -185,7 +177,7 @@ public abstract class SLResultImpl implements SLResult { } - protected void writeTo(Node node, Result result, Templates templates) { + protected void writeTo(Node node, Result result, Templates templates, boolean fragment) { DebugWriter dw = null; DebugOutputStream ds = null; @@ -205,24 +197,30 @@ public abstract class SLResultImpl implements SLResult { try { TransformerFactory transformerFactory = TransformerFactory.newInstance(); Transformer transformer = transformerFactory.newTransformer(); + if (fragment) { + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + } transformer.transform(new DOMSource(node), result); } catch (TransformerConfigurationException e) { log.error("Failed to create Transformer.", e); - writeErrorTo(new SLException(4000), result, null); + writeErrorTo(new SLException(4000), result, null, fragment); } catch (TransformerException e) { log.error("Failed to transform result.", e); - writeErrorTo(new SLException(4000), result, null); + writeErrorTo(new SLException(4000), result, null, fragment); } } else { try { Transformer transformer = templates.newTransformer(); + if (fragment) { + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "yes"); + } transformer.transform(new DOMSource(node), result); } catch (TransformerConfigurationException e) { log.info("Failed to create transformer.", e); - writeErrorTo(new SLException(2008), result, templates); + writeErrorTo(new SLException(2008), result, templates, fragment); } catch (TransformerException e) { log.error("Failed to transform result.", e); - writeErrorTo(new SLException(2008), result, templates); + writeErrorTo(new SLException(2008), result, templates, fragment); } } @@ -240,11 +238,11 @@ public abstract class SLResultImpl implements SLResult { } - protected void writeErrorTo(SLException slException, Result result, Templates templates) { - writeErrorTo(slException, result, templates, Locale.getDefault()); + protected void writeErrorTo(SLException slException, Result result, Templates templates, boolean fragment) { + writeErrorTo(slException, result, templates, Locale.getDefault(), fragment); } - protected void writeErrorTo(SLException slException, Result result, Templates templates, Locale locale) { + protected void writeErrorTo(SLException slException, Result result, Templates templates, Locale locale, boolean fragment) { TransformerHandler transformerHandler = null; if (templates != null) { @@ -256,13 +254,33 @@ public abstract class SLResultImpl implements SLResult { } } - ObjectFactory factory = new ObjectFactory(); - ErrorResponseType responseType = factory.createErrorResponseType(); - responseType.setErrorCode(slException.getErrorCode()); - responseType.setInfo(slException.getLocalizedMessage(locale)); - JAXBElement response = factory.createErrorResponse(responseType); + Object response; + + Marshaller marshaller; + if (slException instanceof SLVersionException + && ("http://www.buergerkarte.at/namespaces/securitylayer/20020225#" + .equals(((SLVersionException) slException).getNamespaceURI()) || + "http://www.buergerkarte.at/namespaces/securitylayer/20020831#" + .equals(((SLVersionException) slException).getNamespaceURI()))) { + // issue ErrorResponse in the legacy namespace + at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory factory + = new at.buergerkarte.namespaces.securitylayer._20020225_.ObjectFactory(); + at.buergerkarte.namespaces.securitylayer._20020225_.ErrorResponseType errorResponseType = factory + .createErrorResponseType(); + errorResponseType.setErrorCode(BigInteger.valueOf(slException + .getErrorCode())); + errorResponseType.setInfo(slException.getLocalizedMessage(locale)); + response = factory.createErrorResponse(errorResponseType); + marshaller = SLMarshallerFactory.getInstance().createLegacyMarshaller(true, fragment); + } else { + ObjectFactory factory = new ObjectFactory(); + ErrorResponseType responseType = factory.createErrorResponseType(); + responseType.setErrorCode(slException.getErrorCode()); + responseType.setInfo(slException.getLocalizedMessage(locale)); + response = factory.createErrorResponse(responseType); + marshaller = SLMarshallerFactory.getInstance().createMarshaller(true, fragment); + } - Marshaller marshaller = getMarshaller(); try { if (transformerHandler != null) { marshaller.marshal(response, transformerHandler); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java index b64306aa..2088a684 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/DataObject.java @@ -81,7 +81,6 @@ import at.gv.egiz.bku.viewer.ValidationException; import at.gv.egiz.bku.viewer.Validator; import at.gv.egiz.bku.viewer.ValidatorFactory; import at.gv.egiz.dom.DOMUtils; -import at.gv.egiz.marshal.NamespacePrefix; import at.gv.egiz.marshal.NamespacePrefixMapperImpl; import at.gv.egiz.slbinding.impl.XMLContentType; import javax.xml.namespace.NamespaceContext; diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java index 9182e824..26ddb153 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java @@ -16,7 +16,6 @@ */ package at.gv.egiz.bku.slcommands.impl.xsect; -import at.gv.egiz.stal.HashDataInput; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.IOException; @@ -31,9 +30,7 @@ import java.security.cert.X509Certificate; import java.util.ArrayList; import java.util.Collections; import java.util.Date; -import java.util.HashMap; import java.util.List; -import java.util.Map; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; @@ -87,8 +84,6 @@ import at.gv.egiz.bku.utils.urldereferencer.StreamData; import at.gv.egiz.bku.utils.urldereferencer.URLDereferencer; import at.gv.egiz.bku.utils.urldereferencer.URLDereferencerContext; import at.gv.egiz.dom.DOMUtils; -import at.gv.egiz.marshal.NamespacePrefix; -import at.gv.egiz.marshal.NamespacePrefixMapperImpl; import at.gv.egiz.slbinding.impl.XMLContentType; import at.gv.egiz.stal.STAL; import at.gv.egiz.xades.QualifyingPropertiesException; @@ -327,6 +322,8 @@ public class Signature { */ public void buildXMLSignature() throws SLCommandException { + String signatureId = ctx.getIdValueFactory().createIdValue("Signature"); + List objects = new ArrayList(); List references = new ArrayList(); @@ -340,7 +337,7 @@ public class Signature { } } - addXAdESObjectAndReference(objects, references); + addXAdESObjectAndReference(objects, references, signatureId); XMLSignatureFactory signatureFactory = ctx.getSignatureFactory(); AlgorithmMethodFactory algorithmMethodFactory = ctx.getAlgorithmMethodFactory(); @@ -369,7 +366,6 @@ public class Signature { ki = kif.newKeyInfo(Collections.singletonList(x509Data)); } - String signatureId = ctx.getIdValueFactory().createIdValue("Signature"); String signatureValueId = ctx.getIdValueFactory().createIdValue("SignatureValue"); xmlSignature = signatureFactory.newXMLSignature(si, ki, objects, signatureId, signatureValueId); @@ -588,7 +584,7 @@ public class Signature { * @param references * the list of ds:References to add the created * ds:Reference to - * + * @param signatureId TODO * @throws SLCommandException * if creating and adding the XAdES * QualifyingProperties fails @@ -596,7 +592,7 @@ public class Signature { * if objects or references is * null */ - private void addXAdESObjectAndReference(List objects, List references) throws SLCommandException { + private void addXAdESObjectAndReference(List objects, List references, String signatureId) throws SLCommandException { QualifyingPropertiesFactory factory = QualifyingPropertiesFactory.getInstance(); @@ -630,9 +626,11 @@ public class Signature { } } + String target = "#" + signatureId; + JAXBElement qualifyingProperties; try { - qualifyingProperties = factory.createQualifyingProperties111(date, signingCertificates, idValue, dataObjectFormats); + qualifyingProperties = factory.createQualifyingProperties111(target, date, signingCertificates, idValue, dataObjectFormats); } catch (QualifyingPropertiesException e) { log.error("Failed to create QualifyingProperties.", e); throw new SLCommandException(4000); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java b/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java index 5ce5cba1..73ac8d1b 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLExceptionMessages.java @@ -47,4 +47,10 @@ public final class SLExceptionMessages { public static final String EC4011_NOTIMPLEMENTED = "ec4011.notimplemented"; + // + // Legacy error codes + // + + public static final String LEC2901_NOTIMPLEMENTED = "lec2901.notimplemented"; + } diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLVersionException.java b/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLVersionException.java new file mode 100644 index 00000000..45501746 --- /dev/null +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slexceptions/SLVersionException.java @@ -0,0 +1,28 @@ +package at.gv.egiz.bku.slexceptions; + +public class SLVersionException extends SLException { + + private static final long serialVersionUID = 1L; + + protected String namespaceURI; + + public SLVersionException(String namespaceURI) { + super(2901, SLExceptionMessages.LEC2901_NOTIMPLEMENTED, new Object[] {namespaceURI}); + this.namespaceURI = namespaceURI; + } + + public SLVersionException(int errorCode, String namespaceURI) { + super(errorCode); + this.namespaceURI = namespaceURI; + } + + public SLVersionException(int errorCode, String namespaceURI, String message, Object[] arguments) { + super(errorCode, message, arguments); + this.namespaceURI = namespaceURI; + } + + public String getNamespaceURI() { + return namespaceURI; + } + +} diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd new file mode 100644 index 00000000..76d1d7cb --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020225.xsd @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd new file mode 100644 index 00000000..6759d791 --- /dev/null +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slcommands/schema/Core.20020831.xsd @@ -0,0 +1,10 @@ + + + + + + + + + + diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties index 73409c8b..db56184e 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties @@ -95,5 +95,10 @@ ec4000.infobox.invalid=Die Infobox '{0}' enth ec4000.idlink.transfomation.failed=Die komprimierte Personenbindung konnte mit dem Stylesheet {0} nicht transformiert werden. ec4002.infobox.unknown=Unbekannter Infoboxbezeichner {0}. ec4003.not.resolved=Zu signierendes Datum kann nicht aufgelöst werden (URI={0}). -ec4011.notimplemented=Befehl {0} ist nicht implementiert. +ec4011.notimplemented=Befehl {0} ist nicht implementiert. + +# Legacy error messages +# + +lec2901.notimplemented=Die in der Anfrage verwendete Version des Security-Layer Protokolls ({0}) wird nicht mehr unterstützt. diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties index 91ca20e8..6c67ba87 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties @@ -96,3 +96,7 @@ ec4000.idlink.transfomation.failed=Failed to transform CompressedIdentityLink wi ec4002.infobox.unknown=Unknown info box identifier {0}. ec4003.not.resolved=Data to be signed cannot be resolved from URI={0}. ec4011.notimplemented=Command {0} not implemented. + +# Legacy error codes +# +lec2901.notimplemented=The version ({0}) of the security-layer protocol used in the request is not supported. diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIteratorTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIteratorTest.java new file mode 100644 index 00000000..703e4460 --- /dev/null +++ b/bkucommon/src/test/java/at/gv/egiz/bku/binding/XWWWFormUrlInputIteratorTest.java @@ -0,0 +1,152 @@ +package at.gv.egiz.bku.binding; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.net.URLEncoder; +import java.nio.charset.Charset; + +import org.junit.Ignore; +import org.junit.Test; +import static org.junit.Assert.*; + +public class XWWWFormUrlInputIteratorTest { + + @Test + public void testOneParam() throws IOException { + + final String name = "name"; + final String value = "value"; + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OutputStreamWriter w = new OutputStreamWriter(os, Charset.forName("UTF-8")); + w.write(name); + w.write("="); + w.write(value); + w.flush(); + w.close(); + + ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray()); + XWWWFormUrlInputIterator decoder = new XWWWFormUrlInputIterator(in); + + assertTrue(decoder.hasNext()); + FormParameter param = decoder.next(); + assertNotNull(param); + assertEquals(name, param.getFormParameterName()); + InputStream vis = param.getFormParameterValue(); + assertNotNull(vis); + InputStreamReader r = new InputStreamReader(vis); + char[] buf = new char[value.length() + 1]; + int len = r.read(buf); + assertEquals(value.length(), len); + assertEquals(value, new String(buf, 0, len)); + assertFalse(decoder.hasNext()); + Exception ex = null; + try { + decoder.next(); + } catch (Exception e) { + ex = e; + } + assertNotNull(ex); + + } + + @Test + public void testTwoParam() throws IOException { + + final String name1 = "name"; + final String value1 = "value"; + final String name2 = "Name_2"; + final String value2 = "Value 2"; + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OutputStreamWriter w = new OutputStreamWriter(os, Charset.forName("UTF-8")); + w.write(name1); + w.write("="); + w.write(value1); + w.write("&"); + w.write(URLEncoder.encode(name2, "UTF-8")); + w.write("="); + w.write(URLEncoder.encode(value2, "UTF-8")); + w.flush(); + w.close(); + + ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray()); + XWWWFormUrlInputIterator decoder = new XWWWFormUrlInputIterator(in); + + assertTrue(decoder.hasNext()); + FormParameter param = decoder.next(); + assertNotNull(param); + assertEquals(name1, param.getFormParameterName()); + InputStream vis = param.getFormParameterValue(); + assertNotNull(vis); + InputStreamReader r = new InputStreamReader(vis); + char[] buf = new char[value1.length() + 1]; + int len = r.read(buf); + assertEquals(value1.length(), len); + assertEquals(value1, new String(buf, 0, len)); + + assertTrue(decoder.hasNext()); + param = decoder.next(); + assertNotNull(param); + assertEquals(name2, param.getFormParameterName()); + vis = param.getFormParameterValue(); + assertNotNull(vis); + r = new InputStreamReader(vis); + buf = new char[value2.length() + 1]; + len = r.read(buf); + assertEquals(value2.length(), len); + assertEquals(value2, new String(buf, 0, len)); + + assertFalse(decoder.hasNext()); + } + + @Test + public void testURLEnc() throws IOException { + + String name = "name"; + byte[] value = new byte[128]; + for (int i = 0; i < value.length; i++) { + value[i] = (byte) i; + } + + String encValue = URLEncoder.encode(new String(value, "UTF-8"), "ASCII"); + System.out.println(encValue); + + ByteArrayOutputStream os = new ByteArrayOutputStream(); + OutputStreamWriter w = new OutputStreamWriter(os, Charset.forName("UTF-8")); + w.write(name); + w.write("="); + w.write(encValue); + w.flush(); + w.close(); + + ByteArrayInputStream in = new ByteArrayInputStream(os.toByteArray()); + XWWWFormUrlInputIterator decoder = new XWWWFormUrlInputIterator(in); + + assertTrue(decoder.hasNext()); + FormParameter param = decoder.next(); + assertNotNull(param); + assertEquals(name, param.getFormParameterName()); + InputStream vis = param.getFormParameterValue(); + assertNotNull(vis); + byte[] buf = new byte[value.length]; + int len = vis.read(buf); + assertArrayEquals(value, buf); + assertEquals(value.length, len); + assertFalse(decoder.hasNext()); + Exception ex = null; + try { + decoder.next(); + } catch (Exception e) { + ex = e; + } + assertNotNull(ex); + + } + + +} diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java index cd931878..7a087b38 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/SLCommandFactoryTest.java @@ -33,6 +33,7 @@ import org.springframework.context.support.ClassPathXmlApplicationContext; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.slexceptions.SLVersionException; import at.gv.egiz.stal.dummy.DummySTAL; public class SLCommandFactoryTest { @@ -54,7 +55,7 @@ public class SLCommandFactoryTest { } @Test - public void createNullOperationCommand() throws SLCommandException, SLRuntimeException, SLRequestException { + public void createNullOperationCommand() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { Reader requestReader = new StringReader( ""); Source source = new StreamSource(requestReader); @@ -65,7 +66,7 @@ public class SLCommandFactoryTest { } @Test(expected=SLCommandException.class) - public void createUnsupportedCommand() throws SLCommandException, SLRuntimeException, SLRequestException { + public void createUnsupportedCommand() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { Reader requestReader = new StringReader( ""); Source source = new StreamSource(requestReader); @@ -75,7 +76,7 @@ public class SLCommandFactoryTest { } @Test(expected=SLRequestException.class) - public void createMalformedCommand() throws SLCommandException, SLRuntimeException, SLRequestException { + public void createMalformedCommand() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { Reader requestReader = new StringReader( "" + "missplacedContent" + diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java index 8fdec375..4e9b4cd7 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/CreateXMLSignatureComandImplTest.java @@ -41,6 +41,7 @@ import at.gv.egiz.bku.slcommands.impl.xsect.STALProvider; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.slexceptions.SLVersionException; import at.gv.egiz.stal.STAL; import at.gv.egiz.stal.dummy.DummySTAL; //@Ignore @@ -66,7 +67,7 @@ public class CreateXMLSignatureComandImplTest { } @Test - public void testCreateXMLSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testCreateXMLSignatureRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/createxmlsignaturerequest/CreateXMLSignatureRequest.xml"); assertNotNull(inputStream); @@ -76,11 +77,11 @@ public class CreateXMLSignatureComandImplTest { assertTrue(command instanceof CreateXMLSignatureCommand); SLResult result = command.execute(); - result.writeTo(new StreamResult(System.out)); + result.writeTo(new StreamResult(System.out), false); } // @Test(expected=SLCommandException.class) - public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-1.xml"); assertNotNull(inputStream); @@ -90,7 +91,7 @@ public class CreateXMLSignatureComandImplTest { } // @Test(expected=SLCommandException.class) - public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-2.xml"); assertNotNull(inputStream); diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java index f10ca520..aa2bcd62 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/ErrorResultImplTest.java @@ -36,7 +36,7 @@ public class ErrorResultImplTest { ByteArrayOutputStream stream = new ByteArrayOutputStream(); StreamResult result = new StreamResult(stream); - errorResult.writeTo(result); + errorResult.writeTo(result, false); System.out.println(stream.toString()); diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java index b0d11d47..bfc784f7 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/InfoboxReadComandImplTest.java @@ -39,6 +39,7 @@ import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.slexceptions.SLVersionException; import at.gv.egiz.stal.STAL; import at.gv.egiz.stal.dummy.DummySTAL; @@ -63,7 +64,7 @@ public class InfoboxReadComandImplTest { } @Test - public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.xml"); assertNotNull(inputStream); @@ -73,11 +74,11 @@ public class InfoboxReadComandImplTest { assertTrue(command instanceof InfoboxReadCommand); SLResult result = command.execute(); - result.writeTo(new StreamResult(System.out)); + result.writeTo(new StreamResult(System.out), false); } @Test(expected=SLCommandException.class) - public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-1.xml"); assertNotNull(inputStream); @@ -87,7 +88,7 @@ public class InfoboxReadComandImplTest { assertTrue(command instanceof InfoboxReadCommand); } - public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-2.xml"); assertNotNull(inputStream); diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java index 8632b67c..e9b0775f 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/NullOperationResultImplTest.java @@ -33,7 +33,7 @@ public class NullOperationResultImplTest { ByteArrayOutputStream stream = new ByteArrayOutputStream(); StreamResult result = new StreamResult(stream); - nullOperationResult.writeTo(result); + nullOperationResult.writeTo(result, false); System.out.println(stream.toString()); diff --git a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java index f9c60b86..a17f0797 100644 --- a/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java +++ b/bkucommon/src/test/java/at/gv/egiz/bku/slcommands/impl/SVPersonendatenInfoboxImplTest.java @@ -23,7 +23,6 @@ import iaik.asn1.CodingException; import java.io.IOException; import java.io.InputStream; -import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; import javax.xml.bind.JAXBException; import javax.xml.bind.Marshaller; @@ -42,10 +41,12 @@ import at.gv.egiz.bku.slcommands.InfoboxReadCommand; import at.gv.egiz.bku.slcommands.SLCommand; import at.gv.egiz.bku.slcommands.SLCommandContext; import at.gv.egiz.bku.slcommands.SLCommandFactory; +import at.gv.egiz.bku.slcommands.SLMarshallerFactory; import at.gv.egiz.bku.slcommands.SLResult; import at.gv.egiz.bku.slexceptions.SLCommandException; import at.gv.egiz.bku.slexceptions.SLRequestException; import at.gv.egiz.bku.slexceptions.SLRuntimeException; +import at.gv.egiz.bku.slexceptions.SLVersionException; import at.gv.egiz.stal.STAL; import at.gv.egiz.stal.dummy.DummySTAL; @@ -93,9 +94,7 @@ public class SVPersonendatenInfoboxImplTest { JAXBElement ehic = new ObjectFactory().createEHIC(attributeList); - JAXBContext jaxbContext = SLCommandFactory.getInstance().getJaxbContext(); - - Marshaller marshaller = jaxbContext.createMarshaller(); + Marshaller marshaller = SLMarshallerFactory.getInstance().createMarshaller(false); marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); @@ -105,7 +104,7 @@ public class SVPersonendatenInfoboxImplTest { @Ignore @Test - public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testInfboxReadRequest() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.xml"); assertNotNull(inputStream); @@ -115,12 +114,12 @@ public class SVPersonendatenInfoboxImplTest { assertTrue(command instanceof InfoboxReadCommand); SLResult result = command.execute(); - result.writeTo(new StreamResult(System.out)); + result.writeTo(new StreamResult(System.out), false); } @Ignore @Test(expected=SLCommandException.class) - public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testInfboxReadRequestInvalid1() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-1.xml"); assertNotNull(inputStream); @@ -131,7 +130,7 @@ public class SVPersonendatenInfoboxImplTest { } @Ignore - public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException { + public void testInfboxReadRequestInvalid2() throws SLCommandException, SLRuntimeException, SLRequestException, SLVersionException { InputStream inputStream = getClass().getClassLoader().getResourceAsStream("at/gv/egiz/bku/slcommands/infoboxreadcommand/IdentityLink.Binary.Invalid-2.xml"); assertNotNull(inputStream); diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java index 5ee40b95..e4a8f48e 100644 --- a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_1/TransformsInfoType.java @@ -24,11 +24,15 @@ package at.buergerkarte.namespaces.securitylayer._1; +import javax.xml.bind.JAXBElement; import javax.xml.bind.annotation.XmlAccessType; import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlAnyElement; import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlElementRef; import javax.xml.bind.annotation.XmlType; import org.w3._2000._09.xmldsig_.TransformsType; +import org.w3c.dom.Element; /** @@ -58,8 +62,9 @@ import org.w3._2000._09.xmldsig_.TransformsType; }) public class TransformsInfoType { - @XmlElement(name = "Transforms", namespace = "http://www.w3.org/2000/09/xmldsig#") - protected TransformsType transforms; + @XmlElementRef(name = "Transforms", namespace = "http://www.w3.org/2000/09/xmldsig#", type = JAXBElement.class) + @XmlAnyElement(lax = true) + protected Object transforms; @XmlElement(name = "FinalDataMetaInfo", required = true) protected MetaInfoType finalDataMetaInfo; @@ -68,10 +73,12 @@ public class TransformsInfoType { * * @return * possible object is - * {@link TransformsType } + * {@link JAXBElement }{@code <}{@link String }{@code >} + * {@link Object } + * {@link Element } * */ - public TransformsType getTransforms() { + public Object getTransforms() { return transforms; } @@ -80,10 +87,12 @@ public class TransformsInfoType { * * @param value * allowed object is - * {@link TransformsType } + * {@link JAXBElement }{@code <}{@link String }{@code >} + * {@link Object } + * {@link Element } * */ - public void setTransforms(TransformsType value) { + public void setTransforms(Object value) { this.transforms = value; } diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ErrorResponseType.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ErrorResponseType.java new file mode 100644 index 00000000..69b5cd9d --- /dev/null +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ErrorResponseType.java @@ -0,0 +1,98 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.2-b01-fcs +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.09.07 at 09:47:31 AM CEST +// + + +package at.buergerkarte.namespaces.securitylayer._20020225_; + +import java.math.BigInteger; +import javax.xml.bind.annotation.XmlAccessType; +import javax.xml.bind.annotation.XmlAccessorType; +import javax.xml.bind.annotation.XmlElement; +import javax.xml.bind.annotation.XmlType; + + +/** + *

Java class for ErrorResponseType complex type. + * + *

The following schema fragment specifies the expected content contained within this class. + * + *

+ * <complexType name="ErrorResponseType">
+ *   <complexContent>
+ *     <restriction base="{http://www.w3.org/2001/XMLSchema}anyType">
+ *       <sequence>
+ *         <element name="ErrorCode" type="{http://www.w3.org/2001/XMLSchema}integer"/>
+ *         <element name="Info" type="{http://www.w3.org/2001/XMLSchema}string"/>
+ *       </sequence>
+ *     </restriction>
+ *   </complexContent>
+ * </complexType>
+ * 
+ * + * + */ +@XmlAccessorType(XmlAccessType.FIELD) +@XmlType(name = "ErrorResponseType", propOrder = { + "errorCode", + "info" +}) +public class ErrorResponseType { + + @XmlElement(name = "ErrorCode", required = true) + protected BigInteger errorCode; + @XmlElement(name = "Info", required = true) + protected String info; + + /** + * Gets the value of the errorCode property. + * + * @return + * possible object is + * {@link BigInteger } + * + */ + public BigInteger getErrorCode() { + return errorCode; + } + + /** + * Sets the value of the errorCode property. + * + * @param value + * allowed object is + * {@link BigInteger } + * + */ + public void setErrorCode(BigInteger value) { + this.errorCode = value; + } + + /** + * Gets the value of the info property. + * + * @return + * possible object is + * {@link String } + * + */ + public String getInfo() { + return info; + } + + /** + * Sets the value of the info property. + * + * @param value + * allowed object is + * {@link String } + * + */ + public void setInfo(String value) { + this.info = value; + } + +} diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ObjectFactory.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ObjectFactory.java new file mode 100644 index 00000000..a02f9ca1 --- /dev/null +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/ObjectFactory.java @@ -0,0 +1,280 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.2-b01-fcs +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.09.07 at 09:47:31 AM CEST +// + + +package at.buergerkarte.namespaces.securitylayer._20020225_; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the at.buergerkarte.namespaces.securitylayer._20020225_ package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _CreateXMLSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateXMLSignatureRequest"); + private final static QName _InfoboxUpdateRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxUpdateRequest"); + private final static QName _ErrorResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "ErrorResponse"); + private final static QName _VerifyXMLSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "VerifyXMLSignatureResponse"); + private final static QName _CreateSessionKeyResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateSessionKeyResponse"); + private final static QName _GetPropertiesRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "GetPropertiesRequest"); + private final static QName _GetPropertiesResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "GetPropertiesResponse"); + private final static QName _InfoboxAvailableResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxAvailableResponse"); + private final static QName _InfoboxAvailableRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxAvailableRequest"); + private final static QName _CreateSessionKeyRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateSessionKeyRequest"); + private final static QName _InfoboxUpdateResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxUpdateResponse"); + private final static QName _CreateXMLSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateXMLSignatureResponse"); + private final static QName _GetStatusResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "GetStatusResponse"); + private final static QName _CreateCMSSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateCMSSignatureRequest"); + private final static QName _CreateSymmetricSecretRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateSymmetricSecretRequest"); + private final static QName _VerifyXMLSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "VerifyXMLSignatureRequest"); + private final static QName _CreateSymmetricSecretResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateSymmetricSecretResponse"); + private final static QName _CreateCMSSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "CreateCMSSignatureResponse"); + private final static QName _VerifyCMSSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "VerifyCMSSignatureResponse"); + private final static QName _InfoboxReadResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxReadResponse"); + private final static QName _VerifyCMSSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "VerifyCMSSignatureRequest"); + private final static QName _InfoboxReadRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "InfoboxReadRequest"); + private final static QName _GetStatusRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "GetStatusRequest"); + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: at.buergerkarte.namespaces.securitylayer._20020225_ + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link ErrorResponseType } + * + */ + public ErrorResponseType createErrorResponseType() { + return new ErrorResponseType(); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateXMLSignatureRequest") + public JAXBElement createCreateXMLSignatureRequest(Object value) { + return new JAXBElement(_CreateXMLSignatureRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxUpdateRequest") + public JAXBElement createInfoboxUpdateRequest(Object value) { + return new JAXBElement(_InfoboxUpdateRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link ErrorResponseType }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "ErrorResponse") + public JAXBElement createErrorResponse(ErrorResponseType value) { + return new JAXBElement(_ErrorResponse_QNAME, ErrorResponseType.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "VerifyXMLSignatureResponse") + public JAXBElement createVerifyXMLSignatureResponse(Object value) { + return new JAXBElement(_VerifyXMLSignatureResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateSessionKeyResponse") + public JAXBElement createCreateSessionKeyResponse(Object value) { + return new JAXBElement(_CreateSessionKeyResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "GetPropertiesRequest") + public JAXBElement createGetPropertiesRequest(Object value) { + return new JAXBElement(_GetPropertiesRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "GetPropertiesResponse") + public JAXBElement createGetPropertiesResponse(Object value) { + return new JAXBElement(_GetPropertiesResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxAvailableResponse") + public JAXBElement createInfoboxAvailableResponse(Object value) { + return new JAXBElement(_InfoboxAvailableResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxAvailableRequest") + public JAXBElement createInfoboxAvailableRequest(Object value) { + return new JAXBElement(_InfoboxAvailableRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateSessionKeyRequest") + public JAXBElement createCreateSessionKeyRequest(Object value) { + return new JAXBElement(_CreateSessionKeyRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxUpdateResponse") + public JAXBElement createInfoboxUpdateResponse(Object value) { + return new JAXBElement(_InfoboxUpdateResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateXMLSignatureResponse") + public JAXBElement createCreateXMLSignatureResponse(Object value) { + return new JAXBElement(_CreateXMLSignatureResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "GetStatusResponse") + public JAXBElement createGetStatusResponse(Object value) { + return new JAXBElement(_GetStatusResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateCMSSignatureRequest") + public JAXBElement createCreateCMSSignatureRequest(Object value) { + return new JAXBElement(_CreateCMSSignatureRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateSymmetricSecretRequest") + public JAXBElement createCreateSymmetricSecretRequest(Object value) { + return new JAXBElement(_CreateSymmetricSecretRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "VerifyXMLSignatureRequest") + public JAXBElement createVerifyXMLSignatureRequest(Object value) { + return new JAXBElement(_VerifyXMLSignatureRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateSymmetricSecretResponse") + public JAXBElement createCreateSymmetricSecretResponse(Object value) { + return new JAXBElement(_CreateSymmetricSecretResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "CreateCMSSignatureResponse") + public JAXBElement createCreateCMSSignatureResponse(Object value) { + return new JAXBElement(_CreateCMSSignatureResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "VerifyCMSSignatureResponse") + public JAXBElement createVerifyCMSSignatureResponse(Object value) { + return new JAXBElement(_VerifyCMSSignatureResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxReadResponse") + public JAXBElement createInfoboxReadResponse(Object value) { + return new JAXBElement(_InfoboxReadResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "VerifyCMSSignatureRequest") + public JAXBElement createVerifyCMSSignatureRequest(Object value) { + return new JAXBElement(_VerifyCMSSignatureRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "InfoboxReadRequest") + public JAXBElement createInfoboxReadRequest(Object value) { + return new JAXBElement(_InfoboxReadRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", name = "GetStatusRequest") + public JAXBElement createGetStatusRequest(Object value) { + return new JAXBElement(_GetStatusRequest_QNAME, Object.class, null, value); + } + +} diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/package-info.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/package-info.java new file mode 100644 index 00000000..084f6b11 --- /dev/null +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020225_/package-info.java @@ -0,0 +1,9 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.2-b01-fcs +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.09.07 at 09:47:31 AM CEST +// + +@javax.xml.bind.annotation.XmlSchema(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020225#", elementFormDefault = javax.xml.bind.annotation.XmlNsForm.QUALIFIED) +package at.buergerkarte.namespaces.securitylayer._20020225_; diff --git a/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020831_/ObjectFactory.java b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020831_/ObjectFactory.java new file mode 100644 index 00000000..17f6d4b4 --- /dev/null +++ b/utils/src/main/java/at/buergerkarte/namespaces/securitylayer/_20020831_/ObjectFactory.java @@ -0,0 +1,112 @@ +// +// This file was generated by the JavaTM Architecture for XML Binding(JAXB) Reference Implementation, v2.0.2-b01-fcs +// See http://java.sun.com/xml/jaxb +// Any modifications to this file will be lost upon recompilation of the source schema. +// Generated on: 2009.09.07 at 09:47:31 AM CEST +// + + +package at.buergerkarte.namespaces.securitylayer._20020831_; + +import javax.xml.bind.JAXBElement; +import javax.xml.bind.annotation.XmlElementDecl; +import javax.xml.bind.annotation.XmlRegistry; +import javax.xml.namespace.QName; + + +/** + * This object contains factory methods for each + * Java content interface and Java element interface + * generated in the at.buergerkarte.namespaces.securitylayer._20020831_ package. + *

An ObjectFactory allows you to programatically + * construct new instances of the Java representation + * for XML content. The Java representation of XML + * content can consist of schema derived interfaces + * and classes representing the binding of schema + * type definitions, element declarations and model + * groups. Factory methods for each of these are + * provided in this class. + * + */ +@XmlRegistry +public class ObjectFactory { + + private final static QName _CreateXMLSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "CreateXMLSignatureRequest"); + private final static QName _GetPropertiesResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "GetPropertiesResponse"); + private final static QName _VerifyXMLSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "VerifyXMLSignatureResponse"); + private final static QName _VerifyXMLSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "VerifyXMLSignatureRequest"); + private final static QName _VerifyCMSSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "VerifyCMSSignatureResponse"); + private final static QName _CreateXMLSignatureResponse_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "CreateXMLSignatureResponse"); + private final static QName _VerifyCMSSignatureRequest_QNAME = new QName("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "VerifyCMSSignatureRequest"); + + /** + * Create a new ObjectFactory that can be used to create new instances of schema derived classes for package: at.buergerkarte.namespaces.securitylayer._20020831_ + * + */ + public ObjectFactory() { + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "CreateXMLSignatureRequest") + public JAXBElement createCreateXMLSignatureRequest(Object value) { + return new JAXBElement(_CreateXMLSignatureRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "GetPropertiesResponse") + public JAXBElement createGetPropertiesResponse(Object value) { + return new JAXBElement(_GetPropertiesResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "VerifyXMLSignatureResponse") + public JAXBElement createVerifyXMLSignatureResponse(Object value) { + return new JAXBElement(_VerifyXMLSignatureResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "VerifyXMLSignatureRequest") + public JAXBElement createVerifyXMLSignatureRequest(Object value) { + return new JAXBElement(_VerifyXMLSignatureRequest_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "VerifyCMSSignatureResponse") + public JAXBElement createVerifyCMSSignatureResponse(Object value) { + return new JAXBElement(_VerifyCMSSignatureResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "CreateXMLSignatureResponse") + public JAXBElement createCreateXMLSignatureResponse(Object value) { + return new JAXBElement(_CreateXMLSignatureResponse_QNAME, Object.class, null, value); + } + + /** + * Create an instance of {@link JAXBElement }{@code <}{@link Object }{@code >}} + * + */ + @XmlElementDecl(namespace = "http://www.buergerkarte.at/namespaces/securitylayer/20020831#", name = "VerifyCMSSignatureRequest") + public JAXBElement createVerifyCMSSignatureRequest(Object value) { + return new JAXBElement(_VerifyCMSSignatureRequest_QNAME, Object.class, null, value); + } + +} diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingInputStream.java b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingInputStream.java new file mode 100644 index 00000000..28ef6b88 --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingInputStream.java @@ -0,0 +1,62 @@ +/** + * + */ +package at.gv.egiz.bku.utils; + +import java.io.IOException; +import java.io.InputStream; +import java.nio.CharBuffer; + +/** + * @author mcentner + * + */ +public class URLEncodingInputStream extends InputStream { + + private char[] buffer = new char[1]; + + private CharBuffer charBuffer = CharBuffer.wrap(buffer); + + protected Readable in; + + /** + * @param in + */ + public URLEncodingInputStream(Readable in) { + this.in = in; + } + + /* (non-Javadoc) + * @see java.io.InputStream#read() + */ + @Override + public int read() throws IOException { + charBuffer.rewind(); + if (in.read(charBuffer) == -1) { + return -1; + } + if (buffer[0] == '+') { + return ' '; + } else if (buffer[0] == '%') { + charBuffer.rewind(); + if (in.read(charBuffer) == -1) { + throw new IOException("Invalid URL encoding."); + } + int c1 = Character.digit(buffer[0], 16); + charBuffer.rewind(); + if (in.read(charBuffer) == -1) { + throw new IOException("Invalid URL encoding."); + } + int c2 = Character.digit(buffer[0], 16); + if (c1 == -1 || c2 == -1) { + throw new IOException("Invalid URL encoding."); + } + return ((c1 << 4) | c2); + } else { + return buffer[0]; + } + } + + + +} diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingOutputStream.java b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingOutputStream.java new file mode 100644 index 00000000..df42df6d --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingOutputStream.java @@ -0,0 +1,134 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.utils; + +import java.io.IOException; +import java.io.OutputStream; +import java.nio.CharBuffer; +import java.util.BitSet; + +/** + * An URLEncoding RFC3986, Section 2.1 + * OutputStream. + * + * @author mcentner + */ +public class URLEncodingOutputStream extends OutputStream { + + private static final int MAX_BUFFER_SIZE = 512; + + private static final BitSet UNRESERVED = new BitSet(256); + + static { + for (int i = '0'; i <= '9'; i++) { + UNRESERVED.set(i); + } + for (int i = 'a'; i <= 'z'; i++) { + UNRESERVED.set(i); + } + for (int i = 'A'; i <= 'Z'; i++) { + UNRESERVED.set(i); + } + UNRESERVED.set('-'); + UNRESERVED.set('_'); + UNRESERVED.set('.'); + UNRESERVED.set('*'); + UNRESERVED.set(' '); + } + + private static final char[] HEX = new char[] { + '0', '1', '2', '3', '4', '5', '6', '7', + '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' + }; + + private char[] buf; + + protected Appendable out; + + /** + * Creates a new instance of this URLEncodingOutputStream that writes to the + * given Appendable. + *

+ * Note: According to + * http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars the input + * for the {@link #write()} methods should be the UTF-8. + *

+ * + * @param out + */ + public URLEncodingOutputStream(Appendable out) { + this.out = out; + } + + /* (non-Javadoc) + * @see java.io.OutputStream#write(int) + */ + @Override + public void write(int b) throws IOException { + b &= 0xFF; + if (UNRESERVED.get(b)) { + if (b == ' ') { + out.append('+'); + } else { + out.append((char) b); + } + } else { + out.append('%').append(HEX[b >>> 4]).append(HEX[b & 0xF]); + } + + } + + /* (non-Javadoc) + * @see java.io.OutputStream#write(byte[], int, int) + */ + @Override + public void write(byte[] b, int off, int len) throws IOException { + + // ensure a buffer at least double the size of end - start + 1 + // but max + int sz = Math.min(len + 1, MAX_BUFFER_SIZE); + if (buf == null || buf.length < sz) { + buf = new char[sz]; + } + + int bPos = 0; + for (int i = 0; i < len; i++) { + if (bPos + 3 > buf.length) { + // flush buffer + out.append(CharBuffer.wrap(buf, 0, bPos)); + bPos = 0; + } + int c = 0xFF & b[off + i]; + if (UNRESERVED.get(c)) { + if (c == ' ') { + buf[bPos++] = '+'; + } else { + buf[bPos++] = (char) c; + } + } else { + buf[bPos++] = '%'; + buf[bPos++] = HEX[c >>> 4]; + buf[bPos++] = HEX[c & 0xF]; + } + } + out.append(CharBuffer.wrap(buf, 0, bPos)); + + } + + +} diff --git a/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingWriter.java b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingWriter.java new file mode 100644 index 00000000..3ba90265 --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/bku/utils/URLEncodingWriter.java @@ -0,0 +1,57 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */package at.gv.egiz.bku.utils; + +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.Writer; +import java.nio.charset.Charset; + +/** + * An URLEncoding RFC3986, Section + * 2.1 Writer, that uses an UTF-8 encoding according to http://www.w3.org/TR/html40/appendix/notes.html#non-ascii-chars for + * writing non-ASCII characters. + * + * @author mcentner + */ +public class URLEncodingWriter extends Writer { + + protected OutputStreamWriter osw; + + public URLEncodingWriter(Appendable out) { + URLEncodingOutputStream urlEnc = new URLEncodingOutputStream(out); + osw = new OutputStreamWriter(urlEnc, Charset.forName("UTF-8")); + } + + @Override + public void close() throws IOException { + osw.close(); + } + + @Override + public void flush() throws IOException { + osw.flush(); + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + osw.write(cbuf, off, len); + } + +} diff --git a/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java b/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java index ccebcc81..3ac0a86e 100644 --- a/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java +++ b/utils/src/main/java/at/gv/egiz/marshal/MarshallerFactory.java @@ -31,13 +31,17 @@ public class MarshallerFactory { private static final Log log = LogFactory.getLog(MarshallerFactory.class); - public static Marshaller createMarshaller(JAXBContext ctx, boolean formattedOutput) throws JAXBException { + public static Marshaller createMarshaller(JAXBContext ctx, boolean formattedOutput, boolean fragment) throws JAXBException { Marshaller m = ctx.createMarshaller(); try { if (formattedOutput) { log.trace("setting marshaller property FORMATTED_OUTPUT"); m.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, Boolean.TRUE); } + if (fragment) { + log.trace("setting marshaller property FRAGMENT"); + m.setProperty(Marshaller.JAXB_FRAGMENT, Boolean.TRUE); + } log.trace("setting marshaller property NamespacePrefixMapper"); m.setProperty("com.sun.xml.bind.namespacePrefixMapper", new NamespacePrefixMapperImpl()); } catch (PropertyException ex) { @@ -45,8 +49,12 @@ public class MarshallerFactory { } return m; } + + public static Marshaller createMarshaller(JAXBContext ctx, boolean formattedOutput) throws JAXBException { + return createMarshaller(ctx, formattedOutput, false); + } public static Marshaller createMarshaller(JAXBContext ctx) throws JAXBException { - return createMarshaller(ctx, false); + return createMarshaller(ctx, false, false); } } diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java deleted file mode 100644 index 3ae1d0ff..00000000 --- a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefix.java +++ /dev/null @@ -1,34 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package at.gv.egiz.marshal; - -/** - * - * @author Clemens Orthacker - */ -public interface NamespacePrefix { - String CARDCHANNEL_PREFIX = "cc"; - String ECDSA_PREFIX = "ecdsa"; - String PERSONDATA_PREFIX = "pr"; - String SAML10_PREFIX = "saml"; - String SL_PREFIX = "sl"; - String XADES_PREFIX = "xades"; - String XMLDSIG_PREFIX = "dsig"; - String XSI_PREFIX = "xsi"; - -} diff --git a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java index 519f6b1f..e0698977 100644 --- a/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java +++ b/utils/src/main/java/at/gv/egiz/marshal/NamespacePrefixMapperImpl.java @@ -17,6 +17,9 @@ package at.gv.egiz.marshal; //import com.sun.xml.internal.bind.marshaller.NamespacePrefixMapper; +import java.util.HashMap; +import java.util.Map; + import com.sun.xml.bind.marshaller.NamespacePrefixMapper; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; @@ -29,45 +32,32 @@ public class NamespacePrefixMapperImpl extends NamespacePrefixMapper { private static final Log log = LogFactory.getLog(NamespacePrefixMapperImpl.class); + protected static final Map prefixMap = new HashMap(); + + static { + prefixMap.put("http://www.w3.org/2001/XMLSchema-instance", "xsi"); + prefixMap.put("http://www.w3.org/2000/09/xmldsig#", "dsig"); + prefixMap.put("http://www.buergerkarte.at/namespaces/securitylayer/1.2#", "sl"); + prefixMap.put("http://www.buergerkarte.at/cardchannel", "cc"); + prefixMap.put("http://www.w3.org/2001/04/xmldsig-more#", "ecdsa"); + prefixMap.put("http://reference.e-government.gv.at/namespace/persondata/20020228#", "pr"); + prefixMap.put("urn:oasis:names:tc:SAML:1.0:assertion", "saml"); + prefixMap.put("http://uri.etsi.org/01903/v1.1.1#", "xades"); + prefixMap.put("http://www.buergerkarte.at/namespaces/securitylayer/20020225#", "sl10"); + prefixMap.put("http://www.buergerkarte.at/namespaces/securitylayer/20020831#", "sl11"); + } + + @Override public String getPreferredPrefix(String namespaceUri, String suggestion, boolean requirePrefix) { if (log.isTraceEnabled()) { log.trace("prefix for namespace " + namespaceUri + " requested"); } - if ("http://www.w3.org/2001/XMLSchema-instance".equals(namespaceUri)) { - return NamespacePrefix.XSI_PREFIX; - } - - if ("http://www.w3.org/2000/09/xmldsig#".equals(namespaceUri)) { - return NamespacePrefix.XMLDSIG_PREFIX; - } - - if ("http://www.buergerkarte.at/namespaces/securitylayer/1.2#".equals(namespaceUri)) { - return NamespacePrefix.SL_PREFIX; - } - - if ("http://www.buergerkarte.at/cardchannel".equals(namespaceUri)) { - return NamespacePrefix.CARDCHANNEL_PREFIX; - } - - if ("http://www.w3.org/2001/04/xmldsig-more#".equals(namespaceUri)) { - return NamespacePrefix.ECDSA_PREFIX; - } - - if ("http://reference.e-government.gv.at/namespace/persondata/20020228#".equals(namespaceUri)) { - return NamespacePrefix.PERSONDATA_PREFIX; - } - - if ("urn:oasis:names:tc:SAML:1.0:assertion".equals(namespaceUri)) { - return NamespacePrefix.SAML10_PREFIX; - } - - if ("http://uri.etsi.org/01903/v1.1.1#".equals(namespaceUri)) { - return NamespacePrefix.XADES_PREFIX; - } - return suggestion; + String prefix = prefixMap.get(namespaceUri); + + return (prefix != null) ? prefix : suggestion; } /** diff --git a/utils/src/main/java/at/gv/egiz/validation/ReportingValidationEventHandler.java b/utils/src/main/java/at/gv/egiz/validation/ReportingValidationEventHandler.java new file mode 100644 index 00000000..6543c333 --- /dev/null +++ b/utils/src/main/java/at/gv/egiz/validation/ReportingValidationEventHandler.java @@ -0,0 +1,64 @@ +/* + * Copyright 2008 Federal Chancellery Austria and + * Graz University of Technology + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ +package at.gv.egiz.validation; + +import javax.xml.bind.ValidationEvent; +import javax.xml.bind.ValidationEventHandler; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +/** + * + * @author Clemens Orthacker + */ +public class ReportingValidationEventHandler implements ValidationEventHandler { + + protected static final Log log = LogFactory.getLog(ReportingValidationEventHandler.class); + + protected ValidationEvent errorEvent; + + /** + * + * @param event + * @return false, terminate the current unmarshal, validate, or marshal operation after handling this warning/error + * (except for WARNING validation events) + */ + @Override + public boolean handleEvent(ValidationEvent event) { + switch (event.getSeverity()) { + case ValidationEvent.WARNING: + log.info(event.getMessage()); + return true; + case ValidationEvent.ERROR: + log.warn(event.getMessage()); + errorEvent = event; + return false; + case ValidationEvent.FATAL_ERROR: + log.error(event.getMessage()); + errorEvent = event; + return false; + default: + log.debug(event.getMessage()); + return false; + } + } + + public ValidationEvent getErrorEvent() { + return errorEvent; + } + +} diff --git a/utils/src/main/java/at/gv/egiz/validation/ValidationEventLogger.java b/utils/src/main/java/at/gv/egiz/validation/ValidationEventLogger.java deleted file mode 100644 index 0fafdd7f..00000000 --- a/utils/src/main/java/at/gv/egiz/validation/ValidationEventLogger.java +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright 2008 Federal Chancellery Austria and - * Graz University of Technology - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package at.gv.egiz.validation; - -import javax.xml.bind.ValidationEvent; -import javax.xml.bind.ValidationEventHandler; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -/** - * - * @author Clemens Orthacker - */ -public class ValidationEventLogger implements ValidationEventHandler { - - protected static final Log log = LogFactory.getLog(ValidationEventLogger.class); - - /** - * - * @param event - * @return false, terminate the current unmarshal, validate, or marshal operation after handling this warning/error - * (except for WARNING validation events) - */ - @Override - public boolean handleEvent(ValidationEvent event) { - switch (event.getSeverity()) { - case ValidationEvent.WARNING: - log.info(event.getMessage()); - return true; - case ValidationEvent.ERROR: - log.warn(event.getMessage()); - return false; - case ValidationEvent.FATAL_ERROR: - log.error(event.getMessage()); - return false; - default: - log.debug(event.getMessage()); - return false; - } - } -} diff --git a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java index 71ca1db9..82cba624 100644 --- a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java +++ b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java @@ -16,8 +16,6 @@ */ package at.gv.egiz.xades; -import at.gv.egiz.marshal.MarshallerFactory; -import at.gv.egiz.marshal.NamespacePrefixMapperImpl; import java.math.BigInteger; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -51,6 +49,8 @@ import org.w3._2000._09.xmldsig_.DigestMethodType; import org.w3._2000._09.xmldsig_.X509IssuerSerialType; import org.w3c.dom.Node; +import at.gv.egiz.marshal.MarshallerFactory; + public class QualifyingPropertiesFactory { public static String NS_URI_V1_1_1 = "http://uri.etsi.org/01903/v1.1.1#"; @@ -155,7 +155,7 @@ public class QualifyingPropertiesFactory { return dataObjectFormatType; } - public JAXBElement createQualifyingProperties111(Date signingTime, List certificates, String idValue, List dataObjectFormats) throws QualifyingPropertiesException { + public JAXBElement createQualifyingProperties111(String target, Date signingTime, List certificates, String idValue, List dataObjectFormats) throws QualifyingPropertiesException { GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -206,6 +206,8 @@ public class QualifyingPropertiesFactory { QualifyingPropertiesType qualifyingPropertiesType = qpFactory.createQualifyingPropertiesType(); qualifyingPropertiesType.setSignedProperties(signedPropertiesType); + qualifyingPropertiesType.setTarget(target); + return qpFactory.createQualifyingProperties(qualifyingPropertiesType); } diff --git a/utils/src/test/java/at/gv/egiz/bku/utils/URLEncodingOutputStreamTest.java b/utils/src/test/java/at/gv/egiz/bku/utils/URLEncodingOutputStreamTest.java new file mode 100644 index 00000000..e92b9584 --- /dev/null +++ b/utils/src/test/java/at/gv/egiz/bku/utils/URLEncodingOutputStreamTest.java @@ -0,0 +1,147 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.utils; + +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; +import java.io.OutputStreamWriter; +import java.io.StringWriter; +import java.io.Writer; +import java.net.URLEncoder; +import java.nio.charset.Charset; + +import org.junit.BeforeClass; +import org.junit.Ignore; +import org.junit.Test; + +public class URLEncodingOutputStreamTest { + + private static String buf; + + private static Charset UTF_8 = Charset.forName("UTF-8"); + + @BeforeClass + public static void setUpClass() throws IOException { + + ClassLoader cl = URLEncodingOutputStreamTest.class.getClassLoader(); + InputStream is = cl.getResourceAsStream("BigRequest.xml"); + + assertNotNull(is); + + InputStreamReader reader = new InputStreamReader(is, UTF_8); + + StringBuilder sb = new StringBuilder(); + + char[] b = new char[512]; + for (int l; (l = reader.read(b)) != -1;) { + sb.append(b, 0, l); + } + + buf = sb.toString(); + + } + + @Test + public void testCompareResults() throws IOException { + + String out1; + String out2; + + // new + StringWriter writer = new StringWriter(); + URLEncodingOutputStream urlEnc = new URLEncodingOutputStream(writer); + OutputStreamWriter streamWriter = new OutputStreamWriter(urlEnc, UTF_8); + streamWriter.append(buf); + streamWriter.flush(); + out1 = writer.toString(); + + // URLEncoder + out2 = URLEncoder.encode(buf, UTF_8.name()); + + for (int i = 0; i < out1.length(); i++) { + if (out1.charAt(i) != out2.charAt(i)) { + System.out.println(i + ": " + out1.substring(i)); + System.out.println(i + ": " + out2.substring(i)); + } + } + + assertEquals(out1, out2); + + } + + @Ignore + @Test + public void testURLEncodingOutputStream() throws IOException { + + NullWriter writer = new NullWriter(); + + URLEncodingOutputStream urlEnc = new URLEncodingOutputStream(writer); + OutputStreamWriter streamWriter = new OutputStreamWriter(urlEnc, UTF_8); + + long t0, t1, dt = 0; + for (int run = 0; run < 1000; run++) { + t0 = System.currentTimeMillis(); + streamWriter.append(buf); + t1 = System.currentTimeMillis(); + if (run > 1) { + dt += t1 - t0; + } + } + System.out.println("Time " + dt + "ms"); + + } + + @Ignore + @Test + public void testURLEncodingNaive() throws IOException { + + String in = new String(buf); + + long t0, t1, dt = 0; + for (int run = 0; run < 1000; run++) { + t0 = System.currentTimeMillis(); + URLEncoder.encode(in, "UTF-8"); + t1 = System.currentTimeMillis(); + if (run > 1) { + dt += t1 - t0; + } + } + System.out.println("Time (naive) " + dt + "ms"); + + } + + public class NullWriter extends Writer { + + @Override + public void close() throws IOException { + } + + @Override + public void flush() throws IOException { + } + + @Override + public void write(char[] cbuf, int off, int len) throws IOException { + } + + } + +} diff --git a/utils/src/test/resources/BigRequest.xml b/utils/src/test/resources/BigRequest.xml new file mode 100644 index 00000000..90eb1eb8 --- /dev/null +++ b/utils/src/test/resources/BigRequest.xml @@ -0,0 +1,1060 @@ + + +SecureSignatureKeypair + + + TG9yZW0gaXBzdW0gZG9sb3Igc2l0IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2Np +bmcgZWxpdC4gTnVsbGFtIHZ1bHB1dGF0ZSwgcmlzdXMgaW1wZXJkaWV0IGNvbnNl +cXVhdCB2YXJpdXMsIHJpc3VzIGR1aSB0ZW1wdXMgbGVvLCBub24gbGFjaW5pYSBl +bmltIG51bmMgYSBzZW0uIERvbmVjIHBvcnRhLCBpcHN1bSB0aW5jaWR1bnQgdWx0 +cmljZXMgaW50ZXJkdW0sIGZlbGlzIGF1Z3VlIHNvZGFsZXMgYW50ZSwgdmVsIG9y +bmFyZSBsaWJlcm8gbnVsbGEgZXQgcHVydXMuIENyYXMgdGVtcHVzIHZhcml1cyBw +b3J0YS4gRG9uZWMgaWQgcHVydXMgdXQgdmVsaXQgYmliZW5kdW0gbHVjdHVzIGJs +YW5kaXQgc2l0IGFtZXQgbmVxdWUuIENsYXNzIGFwdGVudCB0YWNpdGkgc29jaW9z +cXUgYWQgbGl0b3JhIHRvcnF1ZW50IHBlciBjb251YmlhIG5vc3RyYSwgcGVyIGlu +Y2VwdG9zIGhpbWVuYWVvcy4gQ3JhcyBmYWNpbGlzaXMgdGVtcHVzIGZlcm1lbnR1 +bS4gRG9uZWMgZmVybWVudHVtIG1hc3NhIGV0IHNhcGllbiBwb3N1ZXJlIHZlbmVu +YXRpcy4gSW4gcXVpcyB1cm5hIG9yY2kuIER1aXMgYSBsaWJlcm8gb3JjaS4gTnVs +bGEgcG9ydHRpdG9yIGF1Z3VlIHZpdGFlIGxpZ3VsYSB0ZW1wb3Igc2VkIHJ1dHJ1 +bSBtaSBjdXJzdXMuIEFlbmVhbiBpYWN1bGlzIG5pc2kgYXQgaXBzdW0gY29uc2Vj +dGV0dXIgZWdldCB2YXJpdXMgbWFnbmEgc29sbGljaXR1ZGluLiBVdCBmYWNpbGlz +aXMgdGVsbHVzIGEgbmVxdWUgZWdlc3RhcyBwbGFjZXJhdC4gRG9uZWMgdG9ydG9y +IHZlbGl0LCB0aW5jaWR1bnQgYSBtb2xsaXMgY3Vyc3VzLCBsdWN0dXMgYWxpcXVh +bSBsaWJlcm8uIER1aXMgbm9uIHRlbGx1cyBwcmV0aXVtIHRlbGx1cyB2YXJpdXMg +ZWxlaWZlbmQgaW4gc2VkIHNlbS4gU3VzcGVuZGlzc2UgZmVybWVudHVtIHRlbGx1 +cyBpZCBmZWxpcyB0ZW1wdXMgdml2ZXJyYS4gRG9uZWMgcG9ydHRpdG9yIHRpbmNp +ZHVudCBtYXVyaXMgbmVjIGV1aXNtb2QuCgpQcmFlc2VudCB1bGxhbWNvcnBlciB0 +cmlzdGlxdWUgbG9yZW0sIGV0IHBsYWNlcmF0IG51bmMgZWxlbWVudHVtIHV0LiBN +b3JiaSBldCBhZGlwaXNjaW5nIHNlbS4gTmFtIHZlbCBuaWJoIGV1IGxlbyBjb25k +aW1lbnR1bSByaG9uY3VzIHF1aXMgc2VkIHVybmEuIFBoYXNlbGx1cyBpZCBqdXN0 +byB1dCBvcmNpIHZlc3RpYnVsdW0gc2NlbGVyaXNxdWUuIE5hbSBtb2xsaXMgdG9y +dG9yIHB1cnVzLiBQZWxsZW50ZXNxdWUgaWFjdWxpcyBzZW1wZXIgbWFsZXN1YWRh +LiBJbnRlZ2VyIGJsYW5kaXQgZmVsaXMgYXQgbG9yZW0gZXVpc21vZCB2ZW5lbmF0 +aXMuIE1hZWNlbmFzIG5lYyBlbGVpZmVuZCBsZW8uIERvbmVjIGxvYm9ydGlzLCBy +aXN1cyBuZWMgdGVtcHVzIHZvbHV0cGF0LCBudWxsYSBlbGl0IGx1Y3R1cyBhcmN1 +LCBhYyBwb3N1ZXJlIGxhY3VzIG1hc3NhIGluIG1pLiBNYWVjZW5hcyBzaXQgYW1l +dCBudW5jIG5lYyB0ZWxsdXMgZWdlc3RhcyB2ZXN0aWJ1bHVtIHZpdGFlIGV0IGVs +aXQuIE51bGxhbSBjb25zZWN0ZXR1ciBydXRydW0gdGVsbHVzIGFjIGFjY3Vtc2Fu +LiBDdXJhYml0dXIgZ3JhdmlkYSBhdWd1ZSBldCBtZXR1cyBjdXJzdXMgZWxlaWZl +bmQuIENyYXMgb2RpbyBhcmN1LCB0aW5jaWR1bnQgdXQgZWdlc3RhcyB2ZWwsIGdy +YXZpZGEgaW4gZXJvcy4gTnVuYyBldCBtYWxlc3VhZGEgcXVhbS4gTWF1cmlzIGFj +IHRlbGx1cyBhcmN1LgoKQ3JhcyBuaXNsIHNhcGllbiwgdGluY2lkdW50IGVnZXQg +ZWxlaWZlbmQgdmVsLCBwcmV0aXVtIGlkIGxlY3R1cy4gQWxpcXVhbSB0b3J0b3Ig +dXJuYSwgcG9zdWVyZSBpZCBydXRydW0gbHVjdHVzLCBhdWN0b3Igc2VkIGFudGUu +IFByb2luIGZlcm1lbnR1bSwgbmliaCBhIHZvbHV0cGF0IHZvbHV0cGF0LCBlcm9z +IGRvbG9yIHNjZWxlcmlzcXVlIG1hZ25hLCB0ZW1wdXMgc29sbGljaXR1ZGluIGxp +YmVybyBkb2xvciBydXRydW0gZXN0LiBNYXVyaXMgcXVpcyBqdXN0byBhcmN1LiBQ +cm9pbiB2ZWhpY3VsYSBhZGlwaXNjaW5nIGVyb3Mgbm9uIGNvbmRpbWVudHVtLiBO +dW5jIHN1c2NpcGl0LCBsZWN0dXMgZXUgaWFjdWxpcyBtb2xlc3RpZSwgbWkgZG9s +b3IgcG9ydGEgZG9sb3IsIGV1IHNhZ2l0dGlzIG1hc3NhIGlwc3VtIGluIG1pLiBO +dW5jIHNlbXBlciBzY2VsZXJpc3F1ZSBsb3JlbSwgYSBzb2RhbGVzIHRvcnRvciBw +b3J0dGl0b3IgaWQuIE51bGxhIG1hdHRpcywgdG9ydG9yIG5lYyBpYWN1bGlzIHBy +ZXRpdW0sIGVyYXQgbGFjdXMgdnVscHV0YXRlIGR1aSwgdnVscHV0YXRlIGZhY2ls +aXNpcyBkb2xvciB0dXJwaXMgdXQgZmVsaXMuIE1hZWNlbmFzIHZpdGFlIHNlbSBl +dCBuaWJoIHNhZ2l0dGlzIHRpbmNpZHVudCBxdWlzIGluIHRvcnRvci4gQWxpcXVh +bSBpZCBzb2RhbGVzIHJpc3VzLiBJbnRlZ2VyIGZhY2lsaXNpcywgc2FwaWVuIHV0 +IHNhZ2l0dGlzIGNvbnNlY3RldHVyLCBkaWFtIGxvcmVtIHZpdmVycmEgZG9sb3Is +IHF1aXMgY29tbW9kbyBuaWJoIGVyYXQgcXVpcyBtZXR1cy4gUHJvaW4gZGljdHVt +IHJpc3VzIG1hdXJpcy4gTnVuYyBldSB1cm5hIHNpdCBhbWV0IHZlbGl0IHBsYWNl +cmF0IGVsZWlmZW5kLiBBZW5lYW4gc2l0IGFtZXQgcHVydXMgbnVuYy4gUHJvaW4g +bm9uIG5lcXVlIGEgdGVsbHVzIG1hdHRpcyBlZ2VzdGFzIGF0IHV0IG51bmMuIERv +bmVjIG5vbiBhbnRlIHZpdGFlIG9yY2kgcGVsbGVudGVzcXVlIHNjZWxlcmlzcXVl +LiBNYWVjZW5hcyBhYyBpYWN1bGlzIGZlbGlzLiBVdCBhZGlwaXNjaW5nIHN1c2Np +cGl0IGRpYW0gdXQgcG9ydGEuIERvbmVjIHZlc3RpYnVsdW0gbGFjaW5pYSBtYWdu +YSwgaWQgcnV0cnVtIG5pc2kgdmVuZW5hdGlzIHNlZC4KCk51bGxhIHNhZ2l0dGlz +IHBoYXJldHJhIGFudGUgZXUgb3JuYXJlLiBBbGlxdWFtIGV1IGRvbG9yIHV0IHVy +bmEgY29uZGltZW50dW0gcnV0cnVtLiBJbnRlZ2VyIHN1c2NpcGl0LCB2ZWxpdCBu +ZWMgc29sbGljaXR1ZGluIGN1cnN1cywgbGVjdHVzIHF1YW0gc2NlbGVyaXNxdWUg +bWksIGlkIGF1Y3RvciBzYXBpZW4gdG9ydG9yIHNlZCB0ZWxsdXMuIERvbmVjIHRp +bmNpZHVudCB0aW5jaWR1bnQgbGVjdHVzLCBxdWlzIHNvZGFsZXMgcHVydXMgaW1w +ZXJkaWV0IGV0LiBOdWxsYSBmYWNpbGlzaS4gTnVsbGFtIGlhY3VsaXMgZWxlbWVu +dHVtIGZlbGlzLCBlZ2V0IG1hdHRpcyBkb2xvciB0cmlzdGlxdWUgYWMuIFNlZCBl +Z2V0IHNlbSBuZXF1ZS4gVXQgZmVybWVudHVtLCBtaSBxdWlzIHZvbHV0cGF0IHZl +bmVuYXRpcywgbGFjdXMgbmVxdWUgY29udmFsbGlzIGVzdCwgdml0YWUgc3VzY2lw +aXQgdHVycGlzIGFudGUgYXQgcmlzdXMuIE51bmMgZmVybWVudHVtLCBtYWduYSBx +dWlzIHZlbmVuYXRpcyBldWlzbW9kLCBlbGl0IHZlbGl0IGZlcm1lbnR1bSBqdXN0 +bywgYSBkaWN0dW0gbGlndWxhIGp1c3RvIGFjIGxvcmVtLiBTZWQgZWdldCB0b3J0 +b3IgbWFnbmEsIHZpdmVycmEgaW50ZXJkdW0gbGVvLiBRdWlzcXVlIGluIGxhY3Vz +IGV0IGxlY3R1cyBhZGlwaXNjaW5nIGNvbnNlY3RldHVyIGluIHF1aXMgZXN0LiBN +YXVyaXMgZXQgZG9sb3IgZXQgbmVxdWUgbW9sZXN0aWUgY29uc2VjdGV0dXIgZXVp +c21vZCBldSBlbGl0LiBOdWxsYSBmYWNpbGlzaS4gUHJvaW4gYWMgdmVsaXQgaXBz +dW0sIHV0IHRyaXN0aXF1ZSBtYWduYS4gVmVzdGlidWx1bSBwb3N1ZXJlIG1hbGVz +dWFkYSBuaXNsIHNpdCBhbWV0IGFsaXF1YW0uIFN1c3BlbmRpc3NlIHNlZCBpcHN1 +bSBpZCB0ZWxsdXMgcG9ydGEgcG9zdWVyZSBlZ2V0IHNpdCBhbWV0IHR1cnBpcy4g +TnVuYyBhYyBkb2xvciB2ZWwgdXJuYSBkYXBpYnVzIGZlcm1lbnR1bSBuZWMgdmVo +aWN1bGEgdXJuYS4gRnVzY2UgdGluY2lkdW50IG1ldHVzIGV1IGlwc3VtIG1hdHRp +cyB0cmlzdGlxdWUuIFNlZCBmYXVjaWJ1cyBmcmluZ2lsbGEgYWRpcGlzY2luZy4g +Q3JhcyBwaGFyZXRyYSwgYW50ZSBzZWQgYWNjdW1zYW4gcmhvbmN1cywgZWxpdCBk +b2xvciBsYWNpbmlhIG1hdXJpcywgYXQgbGFvcmVldCBsaWJlcm8gYXVndWUgYXQg +bmlzbC4KClByb2luIGEgbGVvIHV0IHRvcnRvciBwb3J0YSBsdWN0dXMuIFZlc3Rp +YnVsdW0gYW50ZSBpcHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3JjaSBsdWN0dXMg +ZXQgdWx0cmljZXMgcG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBVdCBzZWQgbnVuYyB2 +ZWwgbWV0dXMgc3VzY2lwaXQgY29uZ3VlIGF0IGEgZG9sb3IuIE51bmMgZXUgdG9y +dG9yIGxvcmVtLCBuZWMgY29uZ3VlIGxpYmVyby4gTW9yYmkgbGFvcmVldCBsZWN0 +dXMgbmlzbCwgdml0YWUgcmhvbmN1cyBlbGl0LiBTdXNwZW5kaXNzZSBldCBxdWFt +IHF1aXMgZHVpIGxhY2luaWEgc29kYWxlcyBuZWMgZXUgbGlndWxhLiBQZWxsZW50 +ZXNxdWUgbm9uIGlwc3VtIGxlbywgc2l0IGFtZXQgbW9sZXN0aWUgZHVpLiBTZWQg +YSBhdWd1ZSBlZ2V0IG1hdXJpcyBncmF2aWRhIG1hbGVzdWFkYSBldCBxdWlzIGlw +c3VtLiBBbGlxdWFtIGFjIG5pYmggbGlndWxhLCBpbiBwb3J0dGl0b3IgZWxpdC4g +TWF1cmlzIHR1cnBpcyBvcmNpLCBhY2N1bXNhbiBpbiBpbnRlcmR1bSBhdCwgZmFj +aWxpc2lzIHZpdGFlIHR1cnBpcy4gUXVpc3F1ZSBtYXR0aXMgcGVsbGVudGVzcXVl +IGVyb3MgdmVsIHZpdmVycmEuIFZlc3RpYnVsdW0gbGFvcmVldCBjb25ndWUgYWxp +cXVhbS4gRG9uZWMgcG9zdWVyZSBtYXVyaXMgbmVjIGxpYmVybyBvcm5hcmUgZXQg +ZWdlc3RhcyBhbnRlIHB1bHZpbmFyLiBDdXJhYml0dXIgYW50ZSBhbnRlLCBtb2xl +c3RpZSB1dCBiaWJlbmR1bSB2aXRhZSwgcnV0cnVtIHZlbCByaXN1cy4gRG9uZWMg +ZXQgbmVxdWUgcHVydXMsIHNpdCBhbWV0IGFkaXBpc2NpbmcgZmVsaXMuIFBlbGxl +bnRlc3F1ZSBkaWduaXNzaW0gdmVzdGlidWx1bSBzYXBpZW4gbmVjIGZyaW5naWxs +YS4gUHJvaW4gbmVjIHB1cnVzIGV0IGVzdCBldWlzbW9kIHBoYXJldHJhLiBQZWxs +ZW50ZXNxdWUgZGFwaWJ1cyBkYXBpYnVzIG1ldHVzIHZlbCBmYWNpbGlzaXMuIFZp +dmFtdXMgdmVsIGVsaXQgbnVuYy4KCkV0aWFtIGFjIGVuaW0gZWdldCBtYXVyaXMg +ZmF1Y2lidXMgZGFwaWJ1cy4gTW9yYmkgdml0YWUgbGVjdHVzIG5lcXVlLiBNYXVy +aXMgc2FwaWVuIG1ldHVzLCBzdXNjaXBpdCBzaXQgYW1ldCBlZ2VzdGFzIHZpdGFl +LCBwaGFyZXRyYSBhIG1hc3NhLiBVdCB2YXJpdXMsIHRvcnRvciBzZWQgZnJpbmdp +bGxhIHBsYWNlcmF0LCBuZXF1ZSBkaWFtIGNvbmd1ZSBudW5jLCBpZCBhbGlxdWV0 +IG5pc2kgcmlzdXMgdXQgdXJuYS4gVml2YW11cyBwbGFjZXJhdCBwb3J0YSBhcmN1 +IHZpdGFlIGFjY3Vtc2FuLiBNYXVyaXMgaGVuZHJlcml0LCBlbmltIHZpdGFlIGFs +aXF1YW0gcG9ydHRpdG9yLCBwdXJ1cyBuZXF1ZSBncmF2aWRhIG1hZ25hLCBub24g +cHJldGl1bSBuZXF1ZSBsZWN0dXMgc2l0IGFtZXQgdG9ydG9yLiBEdWlzIHN1c2Np +cGl0IG9ybmFyZSBvZGlvIHZpdGFlIHBoYXJldHJhLiBEb25lYyBlbGVpZmVuZCwg +ZHVpIG5vbiBncmF2aWRhIGNvbnZhbGxpcywgb2RpbyBhcmN1IGJsYW5kaXQgbWFn +bmEsIG5vbiBwb3J0YSBsZW8gbGliZXJvIHBvcnRhIG1hZ25hLiBEdWlzIGVzdCB1 +cm5hLCBsdWN0dXMgZXUgaW50ZXJkdW0gbmVjLCBpYWN1bGlzIG5lYyBlbGl0LiBD +dXJhYml0dXIgZmFjaWxpc2lzIHRlbXB1cyB0ZW1wdXMuIFNlZCBzZW0gdXJuYSwg +dml2ZXJyYSBldSBpbXBlcmRpZXQgc2l0IGFtZXQsIGludGVyZHVtIGV0IGp1c3Rv +LiBJbiBoYWMgaGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdC4gRG9uZWMgdGluY2lk +dW50IG1hc3NhIHV0IGR1aSBmZXJtZW50dW0gcG9zdWVyZSBldCBuZWMgdHVycGlz +LiBFdGlhbSBmZXJtZW50dW0gcG9ydGEgbWF1cmlzLiBTdXNwZW5kaXNzZSBsYWN1 +cyBsaWJlcm8sIHByZXRpdW0gaW4gZWdlc3RhcyB2ZWwsIHNhZ2l0dGlzIGV0IG1h +c3NhLiBOdWxsYSBhbGlxdWFtIGxhb3JlZXQgc2FwaWVuLCBhdCBwZWxsZW50ZXNx +dWUgZXJvcyB2ZW5lbmF0aXMgcXVpcy4gSW50ZWdlciBhY2N1bXNhbiwgbGFjdXMg +dXQgZGFwaWJ1cyBlZ2VzdGFzLCByaXN1cyBuaXNsIHNlbXBlciB0dXJwaXMsIHNp +dCBhbWV0IHZpdmVycmEgZmVsaXMgdHVycGlzIHNlZCB2ZWxpdC4KCkRvbmVjIHZl +aGljdWxhLCB0ZWxsdXMgcXVpcyBtb2xlc3RpZSBiaWJlbmR1bSwgYXVndWUgbmlz +bCB0ZW1wdXMgbG9yZW0sIHNpdCBhbWV0IGNvbmRpbWVudHVtIGp1c3RvIGF1Z3Vl +IHNpdCBhbWV0IGFudGUuIE51bGxhbSB0b3J0b3Igc2VtLCBtYXR0aXMgYWMgcG9y +dHRpdG9yIHZpdGFlLCBpYWN1bGlzIHNlZCBkdWkuIEN1bSBzb2NpaXMgbmF0b3F1 +ZSBwZW5hdGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJpZW50IG1vbnRlcywgbmFz +Y2V0dXIgcmlkaWN1bHVzIG11cy4gRXRpYW0gaW4gc2VtIGlwc3VtLiBJbiBldSBt +b2xlc3RpZSBtZXR1cy4gVml2YW11cyBsYW9yZWV0IGZhdWNpYnVzIG5pYmgsIGEg +c2VtcGVyIG5pYmggZnJpbmdpbGxhIHV0LiBNYWVjZW5hcyBsYW9yZWV0LCBwdXJ1 +cyBldSBzb2xsaWNpdHVkaW4gcGhhcmV0cmEsIGp1c3RvIHRlbGx1cyBjb21tb2Rv +IGF1Z3VlLCBpbiBmYXVjaWJ1cyBsZW8ganVzdG8gbmVjIG5pc2wuIE5hbSBldSBw +cmV0aXVtIGVzdC4gRnVzY2Ugc2l0IGFtZXQgcXVhbSBsb3JlbSwgdXQgc29kYWxl +cyB0ZWxsdXMuIE51bmMgZWxlbWVudHVtLCBzZW0gc2NlbGVyaXNxdWUgaWFjdWxp +cyBpbnRlcmR1bSwgZXJvcyBkdWkgb3JuYXJlIG9yY2ksIHNlZCBwbGFjZXJhdCBy +aXN1cyBlcmF0IGVnZXQgYXJjdS4gTW9yYmkgYWMgbWV0dXMgaWQgbGlndWxhIHBv +cnRhIGdyYXZpZGEuIE51bmMgY29udmFsbGlzIGRpYW0gaW4gbmlzaSBncmF2aWRh +IGFjIGNvbW1vZG8gbGFjdXMgZGlnbmlzc2ltLiBDdW0gc29jaWlzIG5hdG9xdWUg +cGVuYXRpYnVzIGV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250ZXMsIG5hc2Nl +dHVyIHJpZGljdWx1cyBtdXMuIEV0aWFtIHF1aXMgdmVsaXQgZXUgZmVsaXMgbHVj +dHVzIHBlbGxlbnRlc3F1ZSBub24gZWdlc3RhcyBuZXF1ZS4gTnVuYyBuaWJoIHRl +bGx1cywgcGxhY2VyYXQgbm9uIGZlcm1lbnR1bSBhdCwgb3JuYXJlIHF1aXMgZGlh +bS4gU3VzcGVuZGlzc2Ugc2l0IGFtZXQgcHVydXMgcXVpcyBkdWkgY29uc2VxdWF0 +IHByZXRpdW0uIEZ1c2NlIGV0IG1hZ25hIG5pc2ksIHZlbCB2ZXN0aWJ1bHVtIGVy +b3MuIEluIGZhdWNpYnVzLCBsYWN1cyBlZ2V0IGZhdWNpYnVzIGZldWdpYXQsIGxp +Z3VsYSBlbmltIHZlc3RpYnVsdW0gbG9yZW0sIGEgdml2ZXJyYSBsb3JlbSBlc3Qg +dml0YWUgcXVhbS4gTnVuYyBwdXJ1cyBuaXNsLCB2YXJpdXMgZXQgdGVtcG9yIHVs +dHJpY2llcywgaWFjdWxpcyBhIGxpYmVyby4gQ2xhc3MgYXB0ZW50IHRhY2l0aSBz +b2Npb3NxdSBhZCBsaXRvcmEgdG9ycXVlbnQgcGVyIGNvbnViaWEgbm9zdHJhLCBw +ZXIgaW5jZXB0b3MgaGltZW5hZW9zLgoKRnVzY2UgdmVsIGp1c3RvIHNpdCBhbWV0 +IHF1YW0gbWFsZXN1YWRhIG9ybmFyZSBzaXQgYW1ldCBldCBhbnRlLiBOdWxsYW0g +cmhvbmN1cyBwb3J0YSBzZW0gcXVpcyBtYWxlc3VhZGEuIENsYXNzIGFwdGVudCB0 +YWNpdGkgc29jaW9zcXUgYWQgbGl0b3JhIHRvcnF1ZW50IHBlciBjb251YmlhIG5v +c3RyYSwgcGVyIGluY2VwdG9zIGhpbWVuYWVvcy4gRG9uZWMgYW50ZSBvZGlvLCB0 +aW5jaWR1bnQgYWMgbW9sbGlzIGluLCB1bHRyaWNlcyBuZWMgZHVpLiBOdW5jIGN1 +cnN1cyBtYWduYSBuZWMgcHVydXMgZnJpbmdpbGxhIGEgbW9sZXN0aWUgcHVydXMg +bG9ib3J0aXMuIEZ1c2NlIHJ1dHJ1bSwgbG9yZW0gZWdldCB1bGxhbWNvcnBlciBm +cmluZ2lsbGEsIGR1aSBsaWd1bGEgc29sbGljaXR1ZGluIHJpc3VzLCB2aXRhZSBw +b3N1ZXJlIG5lcXVlIGZlbGlzIHZpdGFlIHF1YW0uIEN1cmFiaXR1ciBjb25kaW1l +bnR1bSBsaWJlcm8gYXQgb3JjaSBhdWN0b3IgZXUgY29tbW9kbyBsaWJlcm8gc29s +bGljaXR1ZGluLiBDcmFzIHNlZCBwdXJ1cyBtaSwgc2VkIGNvbnZhbGxpcyBuaWJo +LiBOdWxsYW0gYWMgbG9yZW0gYSBpcHN1bSBsYWNpbmlhIHVsbGFtY29ycGVyIGlk +IHF1aXMgdG9ydG9yLiBNb3JiaSBlbGVpZmVuZCwgbnVsbGEgdmVsIHZlbmVuYXRp +cyBjb25kaW1lbnR1bSwgbGVjdHVzIHRvcnRvciB2ZW5lbmF0aXMgcmlzdXMsIGEg +bHVjdHVzIGxhY3VzIGlwc3VtIHV0IHNhcGllbi4KCk1hdXJpcyBsYW9yZWV0IG51 +bmMgc2l0IGFtZXQgZW5pbSBkaWN0dW0gbG9ib3J0aXMuIE1hdXJpcyBydXRydW0s +IGVsaXQgdXQgbW9sZXN0aWUgb3JuYXJlLCB0b3J0b3IgZXJvcyB2YXJpdXMgbnVu +YywgdHJpc3RpcXVlIHBlbGxlbnRlc3F1ZSB0dXJwaXMgYXVndWUgaW4gYW50ZS4g +QWVuZWFuIGZlbGlzIGR1aSwgZnJpbmdpbGxhIGluIGFsaXF1YW0gYXQsIG9ybmFy +ZSB1dCBudWxsYS4gSW4gbWkgbnVuYywgc2VtcGVyIGluIGNvbmRpbWVudHVtIG5v +biwgY29uZ3VlIGFjIG1hdXJpcy4gQ3VyYWJpdHVyIGltcGVyZGlldCByaG9uY3Vz +IHNlbSwgbW9sZXN0aWUgYWRpcGlzY2luZyBpcHN1bSBzb2xsaWNpdHVkaW4gYS4g +Vml2YW11cyB1dCBpcHN1bSBxdWlzIHR1cnBpcyBhbGlxdWV0IHRpbmNpZHVudCBh +Y2N1bXNhbiBhYyBxdWFtLiBDdXJhYml0dXIgcG9ydHRpdG9yLCBtYXVyaXMgYWMg +bHVjdHVzIHZpdmVycmEsIHB1cnVzIGVzdCBhZGlwaXNjaW5nIHNhcGllbiwgc2l0 +IGFtZXQgYWxpcXVhbSBxdWFtIG51bGxhIGF0IGVyYXQuIFZpdmFtdXMgdGVtcHVz +LCBqdXN0byBhIHByZXRpdW0gZGljdHVtLCBpcHN1bSBudW5jIGxhb3JlZXQgdGVs +bHVzLCBuZWMgdGVtcHVzIHNlbSBuaXNpIGFjIHF1YW0uIFZpdmFtdXMgaW4gbWFz +c2EgZW5pbS4gUXVpc3F1ZSBuZWMgdG9ydG9yIHZpdGFlIG51bGxhIHVsdHJpY2Vz +IGNvbnZhbGxpcy4gTnVsbGFtIHRvcnRvciBtYXVyaXMsIGF1Y3RvciB2aXRhZSB0 +ZW1wb3IgZXQsIGF1Y3RvciBuZWMgc2FwaWVuLiBRdWlzcXVlIHVsbGFtY29ycGVy +IHZpdmVycmEgdmVuZW5hdGlzLiBNYWVjZW5hcyBxdWlzIGdyYXZpZGEgbWFzc2Eu +IEludGVnZXIgdml0YWUganVzdG8gbGVjdHVzLCBhYyBtYWxlc3VhZGEgcXVhbS4g +TWFlY2VuYXMgc2l0IGFtZXQgbmVxdWUgbnVsbGEsIG5lYyBpbXBlcmRpZXQgaXBz +dW0uIFNlZCB0ZW1wdXMgYmliZW5kdW0gc2FwaWVuLCBub24gZnJpbmdpbGxhIG51 +bmMgZWxlbWVudHVtIGV1LiBOdW5jIGF1Y3RvciBhbGlxdWV0IGxlbywgYmliZW5k +dW0gcHJldGl1bSBkaWFtIHBsYWNlcmF0IGFjLiBOYW0gaW4gZW5pbSBkdWkuIFNl +ZCBldCBuaWJoIG5vbiBudW5jIHBsYWNlcmF0IHBoYXJldHJhLiBTZWQgb2RpbyBs +ZW8sIGNvbmRpbWVudHVtIGV1IHN1c2NpcGl0IGV1LCBtb2xsaXMgZWdldCBuaXNp +LgoKUHJvaW4gb3JuYXJlLCBpcHN1bSB2aXRhZSBsYW9yZWV0IHZhcml1cywgbGFj +dXMgbGVvIHBoYXJldHJhIG1hdXJpcywgc2VkIGNvbnZhbGxpcyBsaWJlcm8gbWV0 +dXMgcmhvbmN1cyBvcmNpLiBNYXVyaXMgcnV0cnVtIGxlbyB2ZWwgYW50ZSBlZ2Vz +dGFzIGEgYWRpcGlzY2luZyBlc3QgdmVuZW5hdGlzLiBJbiBldSBtaSB1dCBlbGl0 +IHRyaXN0aXF1ZSB2ZWhpY3VsYS4gTnVuYyBwb3N1ZXJlLCBlbmltIHF1aXMgc3Vz +Y2lwaXQgYWNjdW1zYW4sIGVsaXQgbGVvIHNlbXBlciBudW5jLCBub24gbGFvcmVl +dCBhbnRlIG5pYmggc2l0IGFtZXQgbWF1cmlzLiBBbGlxdWFtIGFjIHF1YW0gcXVp +cyBuaXNsIHNvbGxpY2l0dWRpbiBtb2xlc3RpZSBpZCBhYyBudWxsYS4gSW50ZWdl +ciBldSBkb2xvciBpcHN1bS4gUGhhc2VsbHVzIGludGVyZHVtIHZlaGljdWxhIHNl +bXBlci4gU3VzcGVuZGlzc2UgbmVjIGFyY3UgYWMgZXN0IGlhY3VsaXMgdmVoaWN1 +bGEuIE1hZWNlbmFzIHNlbXBlciBsaWJlcm8gaWFjdWxpcyBsb3JlbSBmZXVnaWF0 +IGF1Y3Rvci4gQWxpcXVhbSBibGFuZGl0IHNlbXBlciBibGFuZGl0LiBVdCBlZ2Vz +dGFzIGVyb3Mgc2VkIG5pc2kgZGFwaWJ1cyBhIHNlbXBlciBtZXR1cyBkYXBpYnVz +LiBNb3JiaSB2dWxwdXRhdGUgbGFvcmVldCB2ZWxpdCwgZXUgYmliZW5kdW0gYXJj +dSBjb21tb2RvIG5vbi4gTWFlY2VuYXMgZmVsaXMgbnVuYywgdm9sdXRwYXQgaWQg +dmVzdGlidWx1bSB2aXRhZSwgdmVzdGlidWx1bSB2aXRhZSBhbnRlLgoKU2VkIG51 +bmMgaXBzdW0sIGF1Y3RvciB2ZWwgZmV1Z2lhdCBzaXQgYW1ldCwgaW50ZXJkdW0g +YXQgbGlndWxhLiBNYXVyaXMgcXVpcyBuaXNpIGVnZXQgbGVjdHVzIGdyYXZpZGEg +c2VtcGVyIGluIHF1aXMgZW5pbS4gTnVsbGEgYXVjdG9yIGVsZW1lbnR1bSBqdXN0 +bywgbm9uIGJpYmVuZHVtIGR1aSBmZXJtZW50dW0gYWMuIEZ1c2NlIGxvcmVtIGF1 +Z3VlLCBjb21tb2RvIG5vbiB0aW5jaWR1bnQgc2l0IGFtZXQsIGFjY3Vtc2FuIHNl +ZCBtZXR1cy4gTmFtIHNhcGllbiBlbmltLCBkaWduaXNzaW0gZXQgdmFyaXVzIGV1 +LCBsdWN0dXMgYXQgb3JjaS4gTnVsbGFtIGxpYmVybyBvcmNpLCBiaWJlbmR1bSBh +IGxhY2luaWEgYWMsIHZ1bHB1dGF0ZSBmYXVjaWJ1cyBtaS4gTW9yYmkgY29uZGlt +ZW50dW0gZmVybWVudHVtIGRpZ25pc3NpbS4gTG9yZW0gaXBzdW0gZG9sb3Igc2l0 +IGFtZXQsIGNvbnNlY3RldHVyIGFkaXBpc2NpbmcgZWxpdC4gUXVpc3F1ZSBldCBu +ZXF1ZSBlcmF0LCB1dCB2b2x1dHBhdCBsZW8uIFZlc3RpYnVsdW0gdmVsIGxpZ3Vs +YSBuZXF1ZS4gTnVuYyBwaGFyZXRyYSBsaWJlcm8gaW4gbWF1cmlzIGRhcGlidXMg +aW4gbGFvcmVldCBkdWkgbHVjdHVzLiBQaGFzZWxsdXMgdmVsaXQgbmlzaSwgZGlj +dHVtIGF0IHZvbHV0cGF0IG5lYywgaGVuZHJlcml0IGZhY2lsaXNpcyBlc3QuIFN1 +c3BlbmRpc3NlIG1hdXJpcyBwdXJ1cywgZGlnbmlzc2ltIHNpdCBhbWV0IHRpbmNp +ZHVudCBhYywgaWFjdWxpcyBpZCBzZW0uIER1aXMgcmlzdXMganVzdG8sIGZyaW5n +aWxsYSBhdCB2dWxwdXRhdGUgYXQsIGxvYm9ydGlzIG5vbiBhcmN1LiBBbGlxdWFt +IGVyYXQgdm9sdXRwYXQuCgpWaXZhbXVzIGxlY3R1cyBtaSwgdWxsYW1jb3JwZXIg +ZXQgZmV1Z2lhdCBzaXQgYW1ldCwgZ3JhdmlkYSBxdWlzIHZlbGl0LiBDcmFzIHRp +bmNpZHVudCBtZXR1cyByaXN1cywgZWdldCB0cmlzdGlxdWUgYXJjdS4gTnVuYyBl +Z2V0IGxlbyBhIGVsaXQgdGVtcG9yIHBvcnR0aXRvci4gQ3VtIHNvY2lpcyBuYXRv +cXVlIHBlbmF0aWJ1cyBldCBtYWduaXMgZGlzIHBhcnR1cmllbnQgbW9udGVzLCBu +YXNjZXR1ciByaWRpY3VsdXMgbXVzLiBQcmFlc2VudCB0ZW1wdXMgbnVuYyBlZ2V0 +IG5pYmggY29uc2VjdGV0dXIgYWMgY29udmFsbGlzIGVuaW0gc2FnaXR0aXMuIEFs +aXF1YW0gaXBzdW0gdXJuYSwgZmF1Y2lidXMgYWMgdHJpc3RpcXVlIHZlbCwgbGFv +cmVldCBhIGxlby4gUGhhc2VsbHVzIGNvbmRpbWVudHVtIGVuaW0gZWdldCBpcHN1 +bSB2b2x1dHBhdCB1dCBhY2N1bXNhbiBuaWJoIHBlbGxlbnRlc3F1ZS4gTnVsbGFt +IGxhb3JlZXQsIHRvcnRvciBpbiB1bGxhbWNvcnBlciBmcmluZ2lsbGEsIGR1aSBv +ZGlvIHNjZWxlcmlzcXVlIHB1cnVzLCB1dCBpYWN1bGlzIGVyYXQgcmlzdXMgYWMg +bnVsbGEuIEFsaXF1YW0gZWdlc3RhcyBsYWNpbmlhIGFsaXF1YW0uIE1hdXJpcyBi +bGFuZGl0LCB0b3J0b3IgcXVpcyBtb2xsaXMgcGVsbGVudGVzcXVlLCBudWxsYSBt +YWduYSB2ZXN0aWJ1bHVtIGVyYXQsIGV0IHRyaXN0aXF1ZSBsaWd1bGEgc2VtIGVn +ZXQgdGVsbHVzLiBWZXN0aWJ1bHVtIGZlbGlzIHRvcnRvciwgc2VtcGVyIGluIHN1 +c2NpcGl0IGVnZXQsIHRpbmNpZHVudCB2ZWwgdmVsaXQuCgpNYWVjZW5hcyBzZW0g +dGVsbHVzLCBiaWJlbmR1bSBhYyBjdXJzdXMgdXQsIGZldWdpYXQgdmVsIHRvcnRv +ci4gU2VkIHZlbmVuYXRpcyBmZWxpcyBhIGF1Z3VlIHByZXRpdW0gZXUgbGFvcmVl +dCBkdWkgbWF0dGlzLiBNYWVjZW5hcyByaG9uY3VzIHZlc3RpYnVsdW0gbWFnbmEg +ZWdldCBjb252YWxsaXMuIE51bGxhIGZhY2lsaXNpLiBGdXNjZSBpbnRlcmR1bSBk +aWN0dW0gbGVvIG5lYyBhZGlwaXNjaW5nLiBOdW5jIHZpdGFlIGxvcmVtIHF1YW0u +IEluIHVsdHJpY2llcyBzZW0gZXUgbGlndWxhIGVsZWlmZW5kIGluIHNhZ2l0dGlz +IGFyY3UgcnV0cnVtLiBOdWxsYW0gZGlhbSBqdXN0bywgZmVybWVudHVtIG5lYyBs +dWN0dXMgZXUsIGltcGVyZGlldCBuZWMgbGliZXJvLiBJbnRlZ2VyIGhlbmRyZXJp +dCB0ZW1wb3IgZGFwaWJ1cy4gU3VzcGVuZGlzc2UgcG90ZW50aS4gRG9uZWMgdXQg +YXJjdSBuZWMgbG9yZW0gbHVjdHVzIHZhcml1cyB2aXRhZSBhIG51bmMuIEZ1c2Nl +IGEgc2FwaWVuIGxhb3JlZXQgdGVsbHVzIGFkaXBpc2NpbmcgdmVzdGlidWx1bS4g +QWxpcXVhbSB2YXJpdXMgZGljdHVtIG1pIGVnZXQgZmV1Z2lhdC4gRXRpYW0gc2Vk +IGxlbyBldCBtYXVyaXMgZmV1Z2lhdCBldWlzbW9kLiBTdXNwZW5kaXNzZSBxdWlz +IG1hZ25hIG1hZ25hLCBhIHRpbmNpZHVudCBvcmNpLiBMb3JlbSBpcHN1bSBkb2xv +ciBzaXQgYW1ldCwgY29uc2VjdGV0dXIgYWRpcGlzY2luZyBlbGl0LiBEb25lYyBu +aXNpIHR1cnBpcywgYWxpcXVldCBldSBzb2xsaWNpdHVkaW4gdml0YWUsIGxhb3Jl +ZXQgbmVjIG5pc2kuIFZlc3RpYnVsdW0gdHJpc3RpcXVlLCB2ZWxpdCB2aXRhZSB1 +bGxhbWNvcnBlciBjb25kaW1lbnR1bSwgbGVjdHVzIG9yY2kgcG9ydHRpdG9yIGFy +Y3UsIGV1IHBsYWNlcmF0IGZlbGlzIHB1cnVzIG5lYyBvcmNpLiBOYW0gaXBzdW0g +YXVndWUsIHNjZWxlcmlzcXVlIGF0IGxhY2luaWEgc2l0IGFtZXQsIG1hdHRpcyBh +IGVyYXQuIFBoYXNlbGx1cyBhIG1hZ25hIHF1aXMgbGFjdXMgdmFyaXVzIHBsYWNl +cmF0LgoKUHJvaW4gb3JuYXJlIHZpdmVycmEgcGxhY2VyYXQuIFNlZCBpYWN1bGlz +IHVsdHJpY2VzIG1hZ25hLCBjb252YWxsaXMgYXVjdG9yIG1pIHRyaXN0aXF1ZSB2 +ZWwuIFBlbGxlbnRlc3F1ZSBhYyBuaXNpIHNpdCBhbWV0IG5pc2kgYWxpcXVhbSB0 +aW5jaWR1bnQgYWMgdXQgaXBzdW0uIFByYWVzZW50IGEgdGVsbHVzIG5vbiBudW5j +IGlhY3VsaXMgYWRpcGlzY2luZy4gUXVpc3F1ZSBmYWNpbGlzaXMganVzdG8gZWdl +dCBtZXR1cyBncmF2aWRhIHVsbGFtY29ycGVyLiBEb25lYyBzYWdpdHRpcywgdG9y +dG9yIGV1aXNtb2QgYWxpcXVhbSBpbnRlcmR1bSwgYXVndWUgYXVndWUgbGFvcmVl +dCBlbGl0LCBpbiBjb21tb2RvIHVybmEgbGFjdXMgdmVsIGVzdC4gVmVzdGlidWx1 +bSBkdWkgbmliaCwgdmFyaXVzIGEgaW50ZXJkdW0gYSwgcG9ydGEgdXQgbWV0dXMu +IFV0IGxlY3R1cyB1cm5hLCBwb3N1ZXJlIGluIGx1Y3R1cyBldCwgcnV0cnVtIGEg +ZXJhdC4gU3VzcGVuZGlzc2UgY3Vyc3VzLCB0b3J0b3Igdml0YWUgc2NlbGVyaXNx +dWUgdHJpc3RpcXVlLCBkb2xvciBlcmF0IGRpZ25pc3NpbSBsZWN0dXMsIG5lYyBz +b2RhbGVzIG1hdXJpcyB0ZWxsdXMgdmVsIHB1cnVzLiBEdWlzIGVsaXQgbWF1cmlz +LCBhY2N1bXNhbiB1dCBwb3N1ZXJlIHZ1bHB1dGF0ZSwgbWFsZXN1YWRhIGV0IGFu +dGUuIE1vcmJpIGJsYW5kaXQgbGFjdXMgYXQgbWF1cmlzIHNhZ2l0dGlzIHJ1dHJ1 +bS4gUGhhc2VsbHVzIGRvbG9yIG1hdXJpcywgY29uc2VxdWF0IHZlbCBmYXVjaWJ1 +cyB2ZWwsIHB1bHZpbmFyIG5lYyBhcmN1LiBOYW0gY29tbW9kbywgcHVydXMgdml0 +YWUgbW9sbGlzIHNjZWxlcmlzcXVlLCBzYXBpZW4gdHVycGlzIGJpYmVuZHVtIGFu +dGUsIGV1IGZhY2lsaXNpcyBpcHN1bSBpcHN1bSBuZWMgbmVxdWUuIENsYXNzIGFw +dGVudCB0YWNpdGkgc29jaW9zcXUgYWQgbGl0b3JhIHRvcnF1ZW50IHBlciBjb251 +YmlhIG5vc3RyYSwgcGVyIGluY2VwdG9zIGhpbWVuYWVvcy4gUGVsbGVudGVzcXVl +IGNvbnZhbGxpcyBkaWduaXNzaW0gbWFnbmEgc2l0IGFtZXQgdnVscHV0YXRlLiBT +ZWQgY29uZGltZW50dW0gdmVoaWN1bGEgbWF0dGlzLiBWaXZhbXVzIHRpbmNpZHVu +dCBmYWNpbGlzaXMgaXBzdW0sIGV0IHBvcnRhIHJpc3VzIHVsdHJpY2VzIHZpdGFl +LiBRdWlzcXVlIG5vbiBjb25zZXF1YXQgbmlzbC4gQ3VyYWJpdHVyIGp1c3RvIG51 +bGxhLCBiaWJlbmR1bSBpbiB2ZW5lbmF0aXMgZWdldCwgcG9zdWVyZSBlZ2V0IHNl +bS4KClBlbGxlbnRlc3F1ZSBzaXQgYW1ldCByaXN1cyB2ZWwgbGliZXJvIGV1aXNt +b2Qgc3VzY2lwaXQgdmVsIHNpdCBhbWV0IG1ldHVzLiBEb25lYyBncmF2aWRhLCBs +ZW8gcXVpcyBpbnRlcmR1bSBjb25ndWUsIHF1YW0gbGVjdHVzIHRyaXN0aXF1ZSBu +aXNpLCBldSB1bHRyaWNlcyBzZW0gdHVycGlzIHRpbmNpZHVudCBlc3QuIFByYWVz +ZW50IHB1bHZpbmFyIGNvbnZhbGxpcyB1cm5hIHZpdGFlIGlhY3VsaXMuIFV0IGNv +bnZhbGxpcyBwdWx2aW5hciBmYWNpbGlzaXMuIEN1bSBzb2NpaXMgbmF0b3F1ZSBw +ZW5hdGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJpZW50IG1vbnRlcywgbmFzY2V0 +dXIgcmlkaWN1bHVzIG11cy4gQWVuZWFuIGV0IGVyYXQgZG9sb3IsIGFjIHBvc3Vl +cmUgbWV0dXMuIFNlZCBjb25kaW1lbnR1bSBhZGlwaXNjaW5nIGlwc3VtLCBlZ2V0 +IHVsdHJpY2llcyBqdXN0byBmZXJtZW50dW0gc2l0IGFtZXQuIE5hbSBmZXJtZW50 +dW0gbGVvIHZpdGFlIGxlY3R1cyBtYXR0aXMgaW1wZXJkaWV0LiBFdGlhbSBkb2xv +ciBsYWN1cywgbWF0dGlzIGF0IHRlbXB1cyBldSwgY29uZ3VlIHZlbCB2ZWxpdC4g +UHJhZXNlbnQgYmxhbmRpdCB2aXZlcnJhIHJob25jdXMuIFBlbGxlbnRlc3F1ZSB2 +aXRhZSBsYWN1cyBsZW8uCgpRdWlzcXVlIGlkIGxvcmVtIHF1aXMgdHVycGlzIGx1 +Y3R1cyBjb25zZXF1YXQgaW4gc2l0IGFtZXQgZXN0LiBDdXJhYml0dXIgdHJpc3Rp +cXVlLCBhcmN1IGEgY3Vyc3VzIHZvbHV0cGF0LCBudWxsYSBlc3QgYXVjdG9yIHRl +bGx1cywgbmVjIGZhY2lsaXNpcyBuaWJoIGF1Z3VlIG5lYyBvcmNpLiBNYXVyaXMg +ZmV1Z2lhdCwgZXN0IGFjIGF1Y3RvciBldWlzbW9kLCBvZGlvIG5pYmggYWNjdW1z +YW4gbmVxdWUsIGluIGZlcm1lbnR1bSBvcmNpIG1hc3NhIHZpdGFlIGF1Z3VlLiBQ +ZWxsZW50ZXNxdWUgcXVpcyBtaSBhcmN1LCBub24gaW1wZXJkaWV0IGlwc3VtLiBO +dWxsYW0gZGFwaWJ1cyBoZW5kcmVyaXQgZmVsaXMsIGFjIHVsbGFtY29ycGVyIHRv +cnRvciBwaGFyZXRyYSBldC4gTnVsbGEgYWNjdW1zYW4sIGxhY3VzIHNlZCBlbGVt +ZW50dW0gaW50ZXJkdW0sIG1pIGFyY3UgdmVzdGlidWx1bSBuZXF1ZSwgZWdldCBm +YWNpbGlzaXMgZXJvcyBudW5jIGF0IGVsaXQuIFN1c3BlbmRpc3NlIGV1IG1hdXJp +cyBzdXNjaXBpdCBwdXJ1cyBkaWN0dW0gaWFjdWxpcy4gUHJhZXNlbnQgc2l0IGFt +ZXQgbnVuYyBuZWMgbGFjdXMgZmFjaWxpc2lzIHBvcnRhLiBNYXVyaXMgbnVuYyBp +cHN1bSwgc29sbGljaXR1ZGluIHNlZCBwb3N1ZXJlIGluLCBmZXJtZW50dW0gYWMg +dGVsbHVzLiBOdWxsYSBmcmluZ2lsbGEgc2NlbGVyaXNxdWUgZXJhdCBpZCBwbGFj +ZXJhdC4KCkludGVnZXIgZnJpbmdpbGxhIGZlcm1lbnR1bSB0dXJwaXMgZWdldCBs +YW9yZWV0LiBTdXNwZW5kaXNzZSBwb3N1ZXJlIGVzdCBhYyBlcm9zIGNvbnNlcXVh +dCBub24gZGlnbmlzc2ltIHB1cnVzIGFsaXF1ZXQuIE1hdXJpcyBwcmV0aXVtIHZl +bmVuYXRpcyBwdWx2aW5hci4gVXQgbmVxdWUgbWV0dXMsIGN1cnN1cyBpZCBkaWdu +aXNzaW0gc2l0IGFtZXQsIGNvbmRpbWVudHVtIGVnZXQgZXJvcy4gQWxpcXVhbSBl +cmF0IHZvbHV0cGF0LiBFdGlhbSBwb3J0YSBhbGlxdWFtIG5pc2ksIHNpdCBhbWV0 +IGNvbnNlY3RldHVyIHB1cnVzIGxvYm9ydGlzIG5lYy4gVmVzdGlidWx1bSB0aW5j +aWR1bnQgcGxhY2VyYXQgcXVhbSBhYyBjdXJzdXMuIFByYWVzZW50IGxhb3JlZXQg +ZXJvcyBub24gbmVxdWUgcmhvbmN1cyBhYyBoZW5kcmVyaXQgZHVpIHRlbXBvci4g +Q3JhcyBzb2RhbGVzIGVsaXQgdml0YWUgdXJuYSBpbnRlcmR1bSBhY2N1bXNhbi4g +TnVsbGFtIG5lYyBsYW9yZWV0IGFyY3UuIERvbmVjIGZyaW5naWxsYSBzY2VsZXJp +c3F1ZSByaXN1cywgbmVjIHNhZ2l0dGlzIG9kaW8gYWNjdW1zYW4gbm9uLiBRdWlz +cXVlIHJ1dHJ1bSBzb2RhbGVzIG9kaW8uIE1hdXJpcyBmYWNpbGlzaXMsIG5pYmgg +cXVpcyBlbGVpZmVuZCBzb2xsaWNpdHVkaW4sIGR1aSBvZGlvIGF1Y3RvciBvcmNp +LCBldSBwb3J0dGl0b3IgYXJjdSBudW5jIGFjIGxpZ3VsYS4gSW4gc2VkIG1pIG5l +cXVlLiBNYXVyaXMgZWdlc3RhcywgdGVsbHVzIHNlZCBldWlzbW9kIGVnZXN0YXMs +IGVyb3MgbGlndWxhIGdyYXZpZGEgcmlzdXMsIGF0IGFsaXF1YW0gbGVvIGxpZ3Vs +YSB1dCBvZGlvLiBBbGlxdWFtIHZlbCB2YXJpdXMgc2FwaWVuLiBFdGlhbSBldSBs +ZW8gZXJvcywgcXVpcyBjb25zZXF1YXQgbWkuIE51bGxhbSBzb2RhbGVzIHBlbGxl +bnRlc3F1ZSBvZGlvIG5vbiB0cmlzdGlxdWUuCgpBbGlxdWFtIGVyYXQgdm9sdXRw +YXQuIEFlbmVhbiBsYW9yZWV0LCBudW5jIGVnZXQgbW9sbGlzIGF1Y3RvciwgbWkg +bGlndWxhIGxvYm9ydGlzIGR1aSwgYSB1bHRyaWNpZXMgcXVhbSB2ZWxpdCB1dCBz +YXBpZW4uIFV0IHZlbCBpYWN1bGlzIG5pYmguIEV0aWFtIHV0IHJpc3VzIGR1aS4g +TWF1cmlzIGF0IGp1c3RvIGZlbGlzLiBNYXVyaXMgaWFjdWxpcyBiaWJlbmR1bSB2 +ZWxpdCBlZ2V0IGRhcGlidXMuIEFsaXF1YW0gZXJhdCB2b2x1dHBhdC4gTnVsbGEg +c2l0IGFtZXQgb3JjaSBhbnRlLCBhIGVnZXN0YXMgc2FwaWVuLiBNb3JiaSB1bGxh +bWNvcnBlciBsZWN0dXMgdmVsIG1hdXJpcyB2ZXN0aWJ1bHVtIG1hbGVzdWFkYS4g +Q3JhcyB2ZWwgbGVjdHVzIGlwc3VtLiBEdWlzIGVnZXN0YXMgdmVuZW5hdGlzIHBy +ZXRpdW0uIE1vcmJpIHNlZCB0b3J0b3IgZXUgb2RpbyBzdXNjaXBpdCBydXRydW0u +IFNlZCB1bHRyaWNlcyBtYXNzYSBmZXJtZW50dW0gbGFjdXMgdGVtcHVzIHBoYXJl +dHJhLiBJbiBldCBtYXVyaXMgcXVhbSwgaWQgZnJpbmdpbGxhIG1ldHVzLgoKQWVu +ZWFuIG5lYyB2ZWxpdCBkdWkuIE51bGxhbSBlZ2VzdGFzIG1pIGV1IGlwc3VtIHVs +dHJpY2VzIGVnZXQgdmVuZW5hdGlzIHZlbGl0IGxhY2luaWEuIFZpdmFtdXMgbmVj +IGxpZ3VsYSBzaXQgYW1ldCBqdXN0byBhZGlwaXNjaW5nIHZhcml1cyB1dCB1dCBw +dXJ1cy4gQWVuZWFuIGx1Y3R1cyBuaXNsIGVnZXQgbmlzbCB1bHRyaWNlcyBpbXBl +cmRpZXQuIFZpdmFtdXMgYSBuaWJoIGF0IGVsaXQgc29kYWxlcyBldWlzbW9kLiBB +ZW5lYW4gaGVuZHJlcml0IG5pc2kgdmVsIG1ldHVzIGNvbnZhbGxpcyB2dWxwdXRh +dGUuIE1vcmJpIHVybmEgdHVycGlzLCB0ZW1wb3IgYXQgcHVsdmluYXIgdmVsLCBj +b25zZWN0ZXR1ciBldSBtZXR1cy4gTmFtIGZyaW5naWxsYSBtYXVyaXMgc2VkIG9y +Y2kgcG9ydGEgYWMgbW9sbGlzIG51bGxhIGJsYW5kaXQuIEluIHVsdHJpY2llcyB2 +ZWxpdCBhdWN0b3IgYXJjdSBncmF2aWRhIGZlcm1lbnR1bS4gVXQgdmVsIG5lcXVl +IGV0IHZlbGl0IHByZXRpdW0gYmxhbmRpdCBldSBpbiBhbnRlLiBWZXN0aWJ1bHVt +IHV0IGR1aSBtYWduYS4gTmFtIGV0IGxhY3VzIGlwc3VtLCBzZWQgdGluY2lkdW50 +IHRlbGx1cy4gRG9uZWMgZWxlbWVudHVtIGVsZWlmZW5kIHRvcnRvciB1dCB2ZXN0 +aWJ1bHVtLgoKRXRpYW0gdm9sdXRwYXQgbWV0dXMgc2VkIGxvcmVtIGRhcGlidXMg +bGFjaW5pYS4gQ2xhc3MgYXB0ZW50IHRhY2l0aSBzb2Npb3NxdSBhZCBsaXRvcmEg +dG9ycXVlbnQgcGVyIGNvbnViaWEgbm9zdHJhLCBwZXIgaW5jZXB0b3MgaGltZW5h +ZW9zLiBWZXN0aWJ1bHVtIGEgYmxhbmRpdCBuaWJoLiBQaGFzZWxsdXMgZXQgbG9y +ZW0gdmVsIGVyb3MgaWFjdWxpcyB1bHRyaWNpZXMuIFNlZCBzaXQgYW1ldCBtYWdu +YSBzaXQgYW1ldCBlc3QgbW9sZXN0aWUgcHJldGl1bSBzZWQgbmVjIG9yY2kuIFN1 +c3BlbmRpc3NlIHBvdGVudGkuIE51bGxhIGNvbnZhbGxpcyBhbnRlIHZpdGFlIGRv +bG9yIGNvbnZhbGxpcyBub24gdmFyaXVzIG5lcXVlIHBlbGxlbnRlc3F1ZS4gQ3Jh +cyBldWlzbW9kIG1hc3NhIGEgZXJvcyBhbGlxdWFtIHVsdHJpY2VzLiBTZWQgdml0 +YWUgcHVydXMgdXQgbmlzaSBmYXVjaWJ1cyBmZXVnaWF0LiBQcmFlc2VudCBhIGxl +Y3R1cyBldCB2ZWxpdCBlZ2VzdGFzIHBoYXJldHJhIGV0IHNpdCBhbWV0IGRvbG9y +LiBEdWlzIHF1aXMgbGFjaW5pYSBvZGlvLiBTZWQgc2VkIGVuaW0gbGVvLiBEb25l +YyBwdWx2aW5hciBzb2xsaWNpdHVkaW4gbmVxdWUgdXQgZnJpbmdpbGxhLiBFdGlh +bSBtYWxlc3VhZGEgbmlzbCBkaWN0dW0gZXJhdCBkaWN0dW0gZGFwaWJ1cy4gRnVz +Y2UgZmFjaWxpc2lzLCBtaSB2ZWwgdmFyaXVzIG9ybmFyZSwgdG9ydG9yIG51bGxh +IG9ybmFyZSBlcm9zLCBhdCBldWlzbW9kIG5pYmggbmlzaSBldCBhdWd1ZS4gTWFl +Y2VuYXMgZWdldCBzYXBpZW4gbWkuIFNlZCBzZWQgbnVsbGEgbGVjdHVzLiBOdW5j +IGRpZ25pc3NpbSBsdWN0dXMgbGVjdHVzLCBhdCBhbGlxdWV0IGRvbG9yIHZlbmVu +YXRpcyBxdWlzLiBVdCBwdWx2aW5hciwgdG9ydG9yIHNpdCBhbWV0IHNjZWxlcmlz +cXVlIHBoYXJldHJhLCBmZWxpcyBsZW8gcHJldGl1bSBmZWxpcywgZXQgbWF0dGlz +IHNhcGllbiBtYXVyaXMgbWF0dGlzIG51bGxhLgoKU3VzcGVuZGlzc2UgcG90ZW50 +aS4gTnVuYyBxdWlzIHB1bHZpbmFyIHF1YW0uIER1aXMgZGFwaWJ1cyBiaWJlbmR1 +bSBmYWNpbGlzaXMuIE51bGxhbSBsb2JvcnRpcyBlcmF0IHNpdCBhbWV0IHF1YW0g +YWRpcGlzY2luZyBldSBtb2xlc3RpZSB0b3J0b3IgYWNjdW1zYW4uIFByYWVzZW50 +IHB1bHZpbmFyIGVuaW0gZXUganVzdG8gZGFwaWJ1cyBpbiB2aXZlcnJhIG1hdXJp +cyBjb21tb2RvLiBFdGlhbSBtb2xsaXMgY29uc2VxdWF0IHZlbGl0LCBub24gbW9s +ZXN0aWUgZXJvcyBjb25kaW1lbnR1bSBhYy4gRXRpYW0gdml0YWUgZXJhdCBuZWMg +ZWxpdCBjb25ndWUgY29uZGltZW50dW0gYSB1bGxhbWNvcnBlciB0dXJwaXMuIFZl +c3RpYnVsdW0gYW50ZSBpcHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3JjaSBsdWN0 +dXMgZXQgdWx0cmljZXMgcG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBWZXN0aWJ1bHVt +IHZpdGFlIGxvcmVtIGV0IGxlY3R1cyBjb252YWxsaXMgY29uc2VjdGV0dXIuIFN1 +c3BlbmRpc3NlIHNpdCBhbWV0IGZlbGlzIG5vbiBtZXR1cyBtYXR0aXMgbG9ib3J0 +aXMuIE1vcmJpIGV1IG51bGxhIHRvcnRvci4gTWFlY2VuYXMgaGVuZHJlcml0IG9y +Y2kgc2l0IGFtZXQgbGlndWxhIGludGVyZHVtIGV0IGlhY3VsaXMgbnVsbGEgcGxh +Y2VyYXQuIE5hbSBkaWN0dW0gbGFjdXMgYXQgYXJjdSByaG9uY3VzIGVsZWlmZW5k +LiBJbiBoYWMgaGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdC4KCkN1cmFiaXR1ciBh +YyB2ZW5lbmF0aXMgZHVpLiBDbGFzcyBhcHRlbnQgdGFjaXRpIHNvY2lvc3F1IGFk +IGxpdG9yYSB0b3JxdWVudCBwZXIgY29udWJpYSBub3N0cmEsIHBlciBpbmNlcHRv +cyBoaW1lbmFlb3MuIEludGVnZXIgYXVjdG9yIHBvcnRhIG5lcXVlIHZlbCBwZWxs +ZW50ZXNxdWUuIEFlbmVhbiBhYyBwdXJ1cyBxdWlzIHZlbGl0IGlhY3VsaXMgcG9y +dHRpdG9yIGluIGluIHNlbS4gRHVpcyB0aW5jaWR1bnQgcmlzdXMgaW4gcmlzdXMg +ZmF1Y2lidXMgYSBhbGlxdWFtIGRpYW0gYXVjdG9yLiBOdWxsYW0gc2VtIGF1Z3Vl +LCBhZGlwaXNjaW5nIHNlZCB0aW5jaWR1bnQgcXVpcywgbW9sZXN0aWUgc2VkIGxp +YmVyby4gVmVzdGlidWx1bSBjb21tb2RvIG9kaW8gdGVtcG9yIG51bGxhIG9ybmFy +ZSBwbGFjZXJhdC4gTW9yYmkgZG9sb3IgbWFzc2EsIGJpYmVuZHVtIGluIGVsZWlm +ZW5kIGlkLCBtb2xlc3RpZSB1dCBqdXN0by4gUXVpc3F1ZSB2YXJpdXMgbnVuYyBz +aXQgYW1ldCBuaXNsIGRhcGlidXMgZmFjaWxpc2lzLiBEb25lYyB1dCBlcmF0IG1p +LiBEdWlzIGVnZXQgY29uc2VjdGV0dXIgbWFnbmEuIE1hdXJpcyBlZ2VzdGFzIHNl +bXBlciBlZ2VzdGFzLiBTZWQgZXQganVzdG8gc2VkIG51bGxhIGJsYW5kaXQgYWNj +dW1zYW4gYXQgbm9uIGxlby4gSW4gZWdldCBlc3QgaXBzdW0uIE51bGxhIHRlbGx1 +cyBsaWd1bGEsIGFsaXF1ZXQgc2l0IGFtZXQgdnVscHV0YXRlIHZpdGFlLCBtb2xs +aXMgZXUgZXJhdC4KCkFlbmVhbiBhYyBhdWd1ZSBvZGlvLiBQcm9pbiBtb2xsaXMs +IGRvbG9yIHV0IGZldWdpYXQgc3VzY2lwaXQsIGR1aSBhbnRlIGNvbnNlY3RldHVy +IG9kaW8sIHZpdGFlIGNvbmRpbWVudHVtIHRlbGx1cyBudWxsYSBhYyBmZWxpcy4g +UGVsbGVudGVzcXVlIGVnZXN0YXMgdWx0cmljZXMgbnVuYywgZXUgc2FnaXR0aXMg +c2FwaWVuIGV1aXNtb2Qgdml0YWUuIEludGVnZXIgc29sbGljaXR1ZGluIGZldWdp +YXQgbGVvIG5lYyBjb25zZWN0ZXR1ci4gUHJhZXNlbnQgc2l0IGFtZXQgc2VtIGVy +YXQsIG5lYyB2b2x1dHBhdCBsYWN1cy4gRXRpYW0gYSBsYWN1cyBudWxsYSwgbm9u +IGludGVyZHVtIGVyYXQuIE1hZWNlbmFzIHF1aXMgZGljdHVtIGxlY3R1cy4gUGVs +bGVudGVzcXVlIGFjIGxpYmVybyB2ZWwgZWxpdCB0cmlzdGlxdWUgc2VtcGVyLiBR +dWlzcXVlIGV1IHN1c2NpcGl0IGR1aS4gSW4gaGFjIGhhYml0YXNzZSBwbGF0ZWEg +ZGljdHVtc3QuIENyYXMgZXUgcG9ydGEgcXVhbS4gQ3VyYWJpdHVyIHBoYXJldHJh +LCBmZWxpcyB1dCByaG9uY3VzIHRpbmNpZHVudCwgbnVsbGEgYXVndWUgcGxhY2Vy +YXQgc2FwaWVuLCBpZCB2ZXN0aWJ1bHVtIG5pc2wgbmVxdWUgYXQgZGlhbS4KClF1 +aXNxdWUgbGFvcmVldCBkYXBpYnVzIGx1Y3R1cy4gTW9yYmkgZXJhdCBvZGlvLCBt +YXR0aXMgc2l0IGFtZXQgdWx0cmljaWVzIGV1LCBpbnRlcmR1bSBldCBudWxsYS4g +TmFtIHZ1bHB1dGF0ZSwgbWV0dXMgbm9uIGVsZW1lbnR1bSBoZW5kcmVyaXQsIHVy +bmEgcHVydXMgcGhhcmV0cmEgZWxpdCwgdml0YWUgc29kYWxlcyBwdXJ1cyBsaWd1 +bGEgbm9uIHF1YW0uIEV0aWFtIGlkIGxpZ3VsYSB0aW5jaWR1bnQgbGVvIHBlbGxl +bnRlc3F1ZSBibGFuZGl0LiBVdCBhbnRlIHVybmEsIHZlc3RpYnVsdW0gc2VkIGVs +ZW1lbnR1bSBhYywgcGVsbGVudGVzcXVlIHNpdCBhbWV0IHRvcnRvci4gRnVzY2Ug +dmVuZW5hdGlzIGNvbW1vZG8gYW50ZSBhdCB0ZW1wb3IuIE51bGxhIGluIG9kaW8g +bGVjdHVzLiBEb25lYyBsYWNpbmlhIGRhcGlidXMgdmVoaWN1bGEuIFN1c3BlbmRp +c3NlIHNjZWxlcmlzcXVlIG9kaW8gdXQgbG9yZW0gZGlnbmlzc2ltIGlkIHByZXRp +dW0gdG9ydG9yIHN1c2NpcGl0LiBOdWxsYW0gZmVsaXMgYW50ZSwgZmVybWVudHVt +IGVnZXQgc29sbGljaXR1ZGluIHNpdCBhbWV0LCBjb21tb2RvIGF0IGVuaW0uIERv +bmVjIGFsaXF1ZXQgbWF1cmlzIGluIGVsaXQgYXVjdG9yIGF0IGNvbnZhbGxpcyBx +dWFtIHVsbGFtY29ycGVyLiBEdWlzIGVuaW0gbmliaCwgdnVscHV0YXRlIGluIGZh +Y2lsaXNpcyBpZCwgYWRpcGlzY2luZyBpbnRlcmR1bSBsYWN1cy4gQWVuZWFuIHNv +bGxpY2l0dWRpbiBjb25ndWUgY29uc2VjdGV0dXIuIFByYWVzZW50IGxvYm9ydGlz +IG5pc2wgZXQgbWV0dXMgZXVpc21vZCBjb25ndWUuIFN1c3BlbmRpc3NlIGlkIHRl +bXB1cyBpcHN1bS4KCkRvbmVjIGV1IGF1Y3RvciBzYXBpZW4uIEluIHBsYWNlcmF0 +IGF1Y3RvciBtYXNzYSB1dCBwbGFjZXJhdC4gVml2YW11cyBhdCB0dXJwaXMgZWxp +dC4gRG9uZWMgY29uZ3VlIHJob25jdXMgZXN0IGEgdml2ZXJyYS4gTnVuYyBub24g +b2RpbyBlbmltLiBDdW0gc29jaWlzIG5hdG9xdWUgcGVuYXRpYnVzIGV0IG1hZ25p +cyBkaXMgcGFydHVyaWVudCBtb250ZXMsIG5hc2NldHVyIHJpZGljdWx1cyBtdXMu +IE1hZWNlbmFzIHF1aXMgbWFzc2EgbGliZXJvLCBxdWlzIGVsZW1lbnR1bSBtYXVy +aXMuIFZlc3RpYnVsdW0gYW50ZSBpcHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3Jj +aSBsdWN0dXMgZXQgdWx0cmljZXMgcG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBWZXN0 +aWJ1bHVtIHZhcml1cyB2ZWxpdCBhIG9yY2kgZ3JhdmlkYSB1bHRyaWNpZXMgc2Vk +IHZlbCBsaWd1bGEuIFZlc3RpYnVsdW0gcHJldGl1bSB2ZWhpY3VsYSBhbGlxdWV0 +LiBTdXNwZW5kaXNzZSBhdWN0b3IgY29uZ3VlIG1hZ25hLCBhYyBjb252YWxsaXMg +ZGlhbSB1bGxhbWNvcnBlciB2ZWwuCgpBZW5lYW4gcGxhY2VyYXQgbW9sbGlzIGlw +c3VtLCBuZWMgdWxsYW1jb3JwZXIgcXVhbSBoZW5kcmVyaXQgZWdldC4gQWVuZWFu +IHNlZCBpcHN1bSBhIGFyY3UgbG9ib3J0aXMgdGluY2lkdW50LiBDbGFzcyBhcHRl +bnQgdGFjaXRpIHNvY2lvc3F1IGFkIGxpdG9yYSB0b3JxdWVudCBwZXIgY29udWJp +YSBub3N0cmEsIHBlciBpbmNlcHRvcyBoaW1lbmFlb3MuIEV0aWFtIGNvbnZhbGxp +cyB0b3J0b3Igc2FnaXR0aXMgbmlzbCBwb3J0YSBmZXJtZW50dW0uIFZpdmFtdXMg +YWNjdW1zYW4gbHVjdHVzIGNvbmd1ZS4gTWF1cmlzIGV0IGxlY3R1cyBsb3JlbS4g +TnVuYyBldCBudW5jIGV0IGF1Z3VlIGdyYXZpZGEgYmliZW5kdW0uIE51bGxhbSBz +dXNjaXBpdCBhcmN1IGV0IG1hdXJpcyBpYWN1bGlzIHZpdGFlIGNvbmd1ZSBuaXNs +IHRlbXB1cy4gQ2xhc3MgYXB0ZW50IHRhY2l0aSBzb2Npb3NxdSBhZCBsaXRvcmEg +dG9ycXVlbnQgcGVyIGNvbnViaWEgbm9zdHJhLCBwZXIgaW5jZXB0b3MgaGltZW5h +ZW9zLiBDcmFzIGRvbG9yIHRlbGx1cywgbHVjdHVzIHNlZCBpbXBlcmRpZXQgZXUs +IGFjY3Vtc2FuIG5lYyBsb3JlbS4gQ3JhcyBxdWlzIGlwc3VtIGFudGUuIFZlc3Rp +YnVsdW0gYW50ZSBpcHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3JjaSBsdWN0dXMg +ZXQgdWx0cmljZXMgcG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBRdWlzcXVlIHZpdGFl +IGRpYW0gYXVndWUsIGV1IHVsdHJpY2VzIGFyY3UuIFByYWVzZW50IGFudGUgdmVs +aXQsIHZlaGljdWxhIGVnZXQgY3Vyc3VzIGV0LCBjb25zZXF1YXQgc2l0IGFtZXQg +dG9ydG9yLiBNYWVjZW5hcyB1bHRyaWNlcyBsaWd1bGEgaW4gb2RpbyB2ZWhpY3Vs +YSB0aW5jaWR1bnQuIEFlbmVhbiB1bHRyaWNpZXMgaXBzdW0gdXQgc2VtIHZ1bHB1 +dGF0ZSB2aXRhZSBwdWx2aW5hciBkaWFtIGNvbnNlY3RldHVyLiBOYW0gdmVsIGVn +ZXN0YXMgZXJvcy4KClByb2luIHVybmEgbmliaCwgYWxpcXVldCBuZWMgc2FnaXR0 +aXMgYSwgY29uZ3VlIHNlZCBqdXN0by4gTWF1cmlzIHJpc3VzIG5lcXVlLCBibGFu +ZGl0IGN1cnN1cyBzZW1wZXIgZXUsIGZlcm1lbnR1bSBlZ2V0IHB1cnVzLiBDdXJh +Yml0dXIgaW4gbGFjdXMgYXVndWUsIHNpdCBhbWV0IGNvbmRpbWVudHVtIG1pLiBN +YXVyaXMgZXUgc2VtIGlwc3VtLCBpbiB1bHRyaWNlcyBtZXR1cy4gUXVpc3F1ZSBm +cmluZ2lsbGEgc2VtIGEgbmlzaSBjb21tb2RvIHZhcml1cy4gTnVuYyB1bHRyaWNl +cyBwbGFjZXJhdCBwbGFjZXJhdC4gVml2YW11cyBub24gbGVjdHVzIGRvbG9yLCBl +Z2V0IGhlbmRyZXJpdCBhdWd1ZS4gTmFtIHV0IG1hdHRpcyBwdXJ1cy4gSW50ZWdl +ciB2ZWwgdXJuYSBldCB0ZWxsdXMgbGFjaW5pYSBmYWNpbGlzaXMgcGVsbGVudGVz +cXVlIHV0IHRlbGx1cy4gRXRpYW0gbGFvcmVldCByaXN1cyBxdWlzIGVsaXQgZGlj +dHVtIGlkIHRyaXN0aXF1ZSBsZW8gc2VtcGVyLiBVdCBvcm5hcmUgbmlzbCBldSBu +aXNsIHVsbGFtY29ycGVyIGluIHNvbGxpY2l0dWRpbiBtYXVyaXMgZ3JhdmlkYS4g +RXRpYW0gaW4gdGluY2lkdW50IHZlbGl0LiBVdCB0ZW1wdXMgdHVycGlzIHZpdGFl +IHVybmEgc2FnaXR0aXMgdmVsIHBvcnRhIHNlbSB2b2x1dHBhdC4gRHVpcyBub24g +anVzdG8gbWV0dXMsIHRlbXBvciBmYXVjaWJ1cyBxdWFtLiBBbGlxdWFtIGluIGxh +Y3VzIG5lYyBtaSB2ZXN0aWJ1bHVtIGZyaW5naWxsYS4gUHJhZXNlbnQgdGVtcG9y +IGxlY3R1cyBhdCBtZXR1cyBwb3J0YSB1dCBjb25ndWUgZHVpIGZyaW5naWxsYS4K +Ck5hbSBhYyBsZWN0dXMgc2VtLCBhdCB2aXZlcnJhIHJpc3VzLiBDcmFzIHNpdCBh +bWV0IHNvZGFsZXMgbWFzc2EuIFF1aXNxdWUgY29uc2VjdGV0dXIgbGlndWxhIHBv +c3VlcmUgdHVycGlzIGV1aXNtb2QgaW50ZXJkdW0uIFV0IGV1IHRlbGx1cyBldSBt +YXNzYSB1bHRyaWNpZXMgYmliZW5kdW0gdml0YWUgaWQgbWV0dXMuIEN1cmFiaXR1 +ciBpbXBlcmRpZXQgY29uc2VxdWF0IHRpbmNpZHVudC4gVXQgZW5pbSBxdWFtLCBj +b25zZWN0ZXR1ciBhdCBwb3J0dGl0b3IgaW4sIHZhcml1cyBldSBtYWduYS4gTnVu +YyBhcmN1IGVsaXQsIHNvZGFsZXMgbm9uIGRhcGlidXMgdnVscHV0YXRlLCBsYWNp +bmlhIGlkIGZlbGlzLiBDdXJhYml0dXIgbHVjdHVzLCByaXN1cyBxdWlzIHZpdmVy +cmEgY29udmFsbGlzLCBtYXNzYSBqdXN0byB0ZW1wdXMgbGliZXJvLCB2aXRhZSBw +b3J0dGl0b3IgbGlndWxhIHZlbGl0IGEgdHVycGlzLiBOdW5jIHZpdmVycmEsIG1l +dHVzIGEgbWFsZXN1YWRhIGNvbnZhbGxpcywgbmVxdWUgYW50ZSBiaWJlbmR1bSBu +aXNsLCBlZ2V0IGltcGVyZGlldCBlbmltIGxlY3R1cyBldSBlbmltLiBQZWxsZW50 +ZXNxdWUgZW5pbSBuaXNsLCBhZGlwaXNjaW5nIGVnZXQgbW9sZXN0aWUgYXQsIGNv +bnNlY3RldHVyIGV1IG9yY2kuIFNlZCBwb3J0YSB1bGxhbWNvcnBlciBlc3QsIG5l +YyBkaWN0dW0gdHVycGlzIHNlbXBlciBzaXQgYW1ldC4KClF1aXNxdWUgcG9ydGEg +bWkgYWMgdmVsaXQgcmhvbmN1cyBhIHZlaGljdWxhIGxlbyBjb25zZXF1YXQuIE1v +cmJpIGxhb3JlZXQgbWF1cmlzIGVsaXQuIEZ1c2NlIHNlbXBlciByaXN1cyB2ZWwg +bGFjdXMgZWdlc3RhcyByaG9uY3VzLiBQZWxsZW50ZXNxdWUgdGluY2lkdW50IG51 +bGxhIGp1c3RvLCB2aXRhZSB2ZWhpY3VsYSBsaWJlcm8uIE1hdXJpcyBkYXBpYnVz +IGR1aSBpbiBtYWduYSB0cmlzdGlxdWUgc2l0IGFtZXQgZmFjaWxpc2lzIHJpc3Vz +IGxvYm9ydGlzLiBBZW5lYW4gc2l0IGFtZXQgZG9sb3Igdml0YWUgbG9yZW0gZXVp +c21vZCBjb252YWxsaXMuIE51bGxhbSBzaXQgYW1ldCBhZGlwaXNjaW5nIGp1c3Rv +LiBWaXZhbXVzIHZlc3RpYnVsdW0gb3JuYXJlIHN1c2NpcGl0LiBWZXN0aWJ1bHVt +IG1hbGVzdWFkYSB1bHRyaWNlcyB2ZWxpdCBub24gZmV1Z2lhdC4gVmVzdGlidWx1 +bSBhbnRlIGlwc3VtIHByaW1pcyBpbiBmYXVjaWJ1cyBvcmNpIGx1Y3R1cyBldCB1 +bHRyaWNlcyBwb3N1ZXJlIGN1YmlsaWEgQ3VyYWU7IE1hdXJpcyBhcmN1IGlwc3Vt +LCBjb21tb2RvIGluIGlhY3VsaXMgc2VkLCBjb25zZXF1YXQgdXQgYXVndWUuIEFs +aXF1YW0gbGliZXJvIG1hdXJpcywgYWxpcXVldCBhdCBjb25kaW1lbnR1bSBub24s +IGhlbmRyZXJpdCBuZWMgZXJhdC4gSW4gdXQgbWF1cmlzIGxvcmVtLiBWaXZhbXVz +IGVnZXQgbGlndWxhIGlkIG5pc2kgc29sbGljaXR1ZGluIHBsYWNlcmF0IGlkIG5l +YyB0ZWxsdXMuIE51bGxhIG5vbiBmYXVjaWJ1cyBsb3JlbS4gTnVsbGEgbm9uIG5p +YmggZXUgZW5pbSB2aXZlcnJhIGNvbnNlY3RldHVyLiBNb3JiaSBsaWJlcm8gbmlz +bCwgY29udmFsbGlzIGlkIGFsaXF1YW0gaWQsIHN1c2NpcGl0IGFjIGRpYW0uIENs +YXNzIGFwdGVudCB0YWNpdGkgc29jaW9zcXUgYWQgbGl0b3JhIHRvcnF1ZW50IHBl +ciBjb251YmlhIG5vc3RyYSwgcGVyIGluY2VwdG9zIGhpbWVuYWVvcy4gSW50ZWdl +ciBlZ2V0IGFudGUgc2FwaWVuLiBTZWQgbm9uIGF1Y3RvciBtYXNzYS4KCk1hZWNl +bmFzIHRpbmNpZHVudCBncmF2aWRhIGNvbnZhbGxpcy4gVmVzdGlidWx1bSBldCBp +YWN1bGlzIGxpYmVyby4gU2VkIHVybmEgb3JjaSwgY29udmFsbGlzIGluIGNvbnNl +cXVhdCBpZCwgdWx0cmljaWVzIHF1aXMgc2VtLiBFdGlhbSBhbGlxdWV0IHNhZ2l0 +dGlzIGltcGVyZGlldC4gTWF1cmlzIG5lYyBuZXF1ZSBxdWFtLiBNb3JiaSB0aW5j +aWR1bnQgbW9sbGlzIHZlbGl0IGVnZXQgdWx0cmljZXMuIERvbmVjIGF0IHR1cnBp +cyBtYWduYSwgZXUgcGxhY2VyYXQgZXJvcy4gUXVpc3F1ZSB0b3J0b3IgbmlzbCwg +dGluY2lkdW50IGV1IGltcGVyZGlldCBxdWlzLCBwb3N1ZXJlIG5lYyBlbGl0LiBD +dW0gc29jaWlzIG5hdG9xdWUgcGVuYXRpYnVzIGV0IG1hZ25pcyBkaXMgcGFydHVy +aWVudCBtb250ZXMsIG5hc2NldHVyIHJpZGljdWx1cyBtdXMuIFF1aXNxdWUgYWxp +cXVldCBsYW9yZWV0IGRpY3R1bS4KClF1aXNxdWUgdmVsIGJpYmVuZHVtIGxlby4g +RXRpYW0gZXQgbWF1cmlzIGxhY3VzLCBzZWQgc29sbGljaXR1ZGluIG5pc2kuIFF1 +aXNxdWUgaWQgcmlzdXMgaW4gbG9yZW0gbWF0dGlzIGRpY3R1bS4gU3VzcGVuZGlz +c2UgcG90ZW50aS4gRG9uZWMgbmVjIGp1c3RvIGFyY3UsIHV0IHBlbGxlbnRlc3F1 +ZSBzZW0uIFN1c3BlbmRpc3NlIHBvdGVudGkuIFBlbGxlbnRlc3F1ZSBlZ2V0IG5p +c2kgaWQgbmlzbCBsYWNpbmlhIGltcGVyZGlldC4gTmFtIGNvbnNlY3RldHVyIGZh +Y2lsaXNpcyBsZW8gbmVjIHRlbXBvci4gRHVpcyBmZXJtZW50dW0gbGFvcmVldCB0 +dXJwaXMgZXQgcHJldGl1bS4gQ2xhc3MgYXB0ZW50IHRhY2l0aSBzb2Npb3NxdSBh +ZCBsaXRvcmEgdG9ycXVlbnQgcGVyIGNvbnViaWEgbm9zdHJhLCBwZXIgaW5jZXB0 +b3MgaGltZW5hZW9zLiBBZW5lYW4gbGFvcmVldCBlc3Qgc2l0IGFtZXQgZWxpdCBm +ZXVnaWF0IGRhcGlidXMuIEV0aWFtIHRlbXB1cyBzdXNjaXBpdCB2ZWxpdCwgb3Ju +YXJlIGRhcGlidXMgaXBzdW0gcG9ydGEgbm9uLiBOdW5jIHV0IGRvbG9yIHV0IGR1 +aSBwb3J0YSBhY2N1bXNhbi4gSW50ZWdlciBkaWN0dW0sIHNlbSBub24gc3VzY2lw +aXQgc29sbGljaXR1ZGluLCB0b3J0b3IgZXJhdCBsYW9yZWV0IHRlbGx1cywgc2l0 +IGFtZXQgcHJldGl1bSBkb2xvciBtaSB1dCBpcHN1bS4gVml2YW11cyBhdWN0b3Ig +ZGlhbSBkaWN0dW0gc2FwaWVuIGZlcm1lbnR1bSBhZGlwaXNjaW5nLiBQaGFzZWxs +dXMgc2NlbGVyaXNxdWUgb2RpbyBxdWlzIG9yY2kgY3Vyc3VzIGV0IHRlbXBvciBz +ZW0gdGluY2lkdW50LiBJbiBoYWMgaGFiaXRhc3NlIHBsYXRlYSBkaWN0dW1zdC4g +QWVuZWFuIHNvZGFsZXMsIGVzdCBldCBtYXR0aXMgc29kYWxlcywgbG9yZW0gZGlh +bSBkYXBpYnVzIHF1YW0sIGFjIHByZXRpdW0gbGFjdXMgbGVjdHVzIGV1IHNhcGll +bi4gRG9uZWMgYWRpcGlzY2luZyBsb2JvcnRpcyBtaSBlZ2V0IHZlc3RpYnVsdW0u +CgpNYWVjZW5hcyBhdCBhbnRlIGVsaXQuIEluIHRlbXB1cyBydXRydW0gZXN0LCB2 +aXRhZSBlbGVtZW50dW0gbnVuYyBtb2xlc3RpZSBhYy4gQWxpcXVhbSB1dCBlbmlt +IGFyY3UsIG5lYyBzb2RhbGVzIG51bGxhLiBVdCBkaWduaXNzaW0gYWRpcGlzY2lu +ZyBvcm5hcmUuIER1aXMgZGljdHVtIGNvbW1vZG8gaXBzdW0sIGEgb3JuYXJlIHJp +c3VzIG1hbGVzdWFkYSBzZWQuIEV0aWFtIGlkIGFyY3UgbWF1cmlzLCBuZWMgcGhh +cmV0cmEgc2FwaWVuLiBMb3JlbSBpcHN1bSBkb2xvciBzaXQgYW1ldCwgY29uc2Vj +dGV0dXIgYWRpcGlzY2luZyBlbGl0LiBBZW5lYW4gcnV0cnVtIGxlY3R1cyBzZWQg +dHVycGlzIHBvcnR0aXRvciBoZW5kcmVyaXQuIEludGVnZXIgbWV0dXMgbGVvLCBs +dWN0dXMgYWMgbGFjaW5pYSBpbiwgZWxlaWZlbmQgZXQgbmVxdWUuIFBlbGxlbnRl +c3F1ZSBiaWJlbmR1bSBudWxsYSBzaXQgYW1ldCB0ZWxsdXMgZXVpc21vZCB2ZWwg +c2NlbGVyaXNxdWUgbWFnbmEgcnV0cnVtLiBBZW5lYW4gdWx0cmljZXMgY29udmFs +bGlzIG5pc2wsIGlkIG9ybmFyZSB0ZWxsdXMgYXVjdG9yIGV1LiBRdWlzcXVlIGxv +Ym9ydGlzIGF1Y3RvciBqdXN0bywgc2l0IGFtZXQgdGluY2lkdW50IGR1aSBsYWNp +bmlhIG5lYy4gTnVsbGFtIGNvbmd1ZSBudW5jIGF0IGZlbGlzIHBvcnR0aXRvciBy +dXRydW0gbm9uIGF0IGVuaW0uCgpVdCBjb252YWxsaXMgY29uZGltZW50dW0gbGFj +dXMgc2VkIGZhY2lsaXNpcy4gQWxpcXVhbSBwcmV0aXVtIGxpZ3VsYSBlZ2V0IG1h +Z25hIHBsYWNlcmF0IHZvbHV0cGF0LiBEb25lYyBub24gbG9yZW0gcGVsbGVudGVz +cXVlIGlwc3VtIGxvYm9ydGlzIHVsbGFtY29ycGVyLiBTdXNwZW5kaXNzZSB2b2x1 +dHBhdCBmZXJtZW50dW0gbWFsZXN1YWRhLiBQcmFlc2VudCBtb2xlc3RpZSBtYWxl +c3VhZGEgbG9yZW0sIHNpdCBhbWV0IGVsZWlmZW5kIG1hc3NhIGVsZWlmZW5kIG5l +Yy4gTnVsbGEgZmFjaWxpc2lzIHRpbmNpZHVudCBlcmF0LCBpbiBwb3J0dGl0b3Ig +ZXJvcyBzYWdpdHRpcyBpZC4gU2VkIGxvYm9ydGlzLCBsaWJlcm8gYXVjdG9yIGlu +dGVyZHVtIGhlbmRyZXJpdCwgZmVsaXMgcXVhbSB2ZXN0aWJ1bHVtIG5pYmgsIGVn +ZXQgaW1wZXJkaWV0IG1hZ25hIGxpZ3VsYSBhdCBudWxsYS4gQWxpcXVhbSBlcmF0 +IHZvbHV0cGF0LiBBbGlxdWFtIG5lYyBuaXNsIHZlbGl0LiBOdW5jIGRhcGlidXMg +ZGlnbmlzc2ltIG1hc3NhIGFjIGx1Y3R1cy4gTWF1cmlzIG5vbiBvZGlvIHB1cnVz +LiBEdWlzIGVyYXQgYW50ZSwgY29uc2VjdGV0dXIgcXVpcyBjb21tb2RvIGEsIGlh +Y3VsaXMgc2VkIGVzdC4gQ3VyYWJpdHVyIGp1c3RvIGp1c3RvLCBiaWJlbmR1bSBp +biBzZW1wZXIgdmVsLCBmYXVjaWJ1cyBpbiBuaWJoLiBFdGlhbSBtYWduYSBhcmN1 +LCBldWlzbW9kIGF0IHRpbmNpZHVudCBxdWlzLCBzb2xsaWNpdHVkaW4gZXQgbGVj +dHVzLiBOdWxsYW0gcHVydXMgbWV0dXMsIGZlcm1lbnR1bSBlZ2V0IHVsdHJpY2ll +cyBuZWMsIGNvbmd1ZSBhIG5pYmguIFBoYXNlbGx1cyBhIGxhY3VzIGlwc3VtLCBp +ZCBzb2xsaWNpdHVkaW4gdmVsaXQuCgpQaGFzZWxsdXMgbm9uIHZlbGl0IG9yY2ks +IGFjIGZldWdpYXQgbGFjdXMuIEN1cmFiaXR1ciBzZWQgc2FwaWVuIG1hZ25hLiBJ +biB2ZWwgcHVsdmluYXIgZmVsaXMuIE1hdXJpcyBxdWlzIGRpYW0gcXVpcyBtYXNz +YSB2YXJpdXMgdmFyaXVzLiBQcmFlc2VudCB1dCBhdWd1ZSBsZW8sIGV0IGZhY2ls +aXNpcyBtYXNzYS4gSW50ZWdlciBhdCB2ZWxpdCBvcmNpLCBuZWMgbW9sZXN0aWUg +ZXN0LiBNb3JiaSBwb3J0YSBibGFuZGl0IHR1cnBpcyBhdCBmcmluZ2lsbGEuIFNl +ZCBsYW9yZWV0IG9kaW8gdXQgZWxpdCBmZXJtZW50dW0gc2VkIGFjY3Vtc2FuIHRv +cnRvciB2b2x1dHBhdC4gVmVzdGlidWx1bSBhbnRlIGlwc3VtIHByaW1pcyBpbiBm +YXVjaWJ1cyBvcmNpIGx1Y3R1cyBldCB1bHRyaWNlcyBwb3N1ZXJlIGN1YmlsaWEg +Q3VyYWU7IEV0aWFtIGlkIG1hc3NhIHZpdGFlIGVyb3MgaWFjdWxpcyBmYWNpbGlz +aXMgc2VkIGFjIHNlbS4gRXRpYW0gdG9ydG9yIHF1YW0sIG1hbGVzdWFkYSBpbiBz +b2RhbGVzIGEsIHZ1bHB1dGF0ZSB0aW5jaWR1bnQgcXVhbS4gTnVsbGEgZmFjaWxp +c2kuIERvbmVjIGNvbmRpbWVudHVtIHZhcml1cyB1bHRyaWNlcy4gRnVzY2UgYmxh +bmRpdCwgdmVsaXQgdml0YWUgc2NlbGVyaXNxdWUgZXVpc21vZCwgbmliaCBudWxs +YSBpbnRlcmR1bSBhcmN1LCB2ZWwgdnVscHV0YXRlIGZlbGlzIGVzdCBpbiB0b3J0 +b3IuIFNlZCB1dCB1cm5hIGZlcm1lbnR1bSBkaWFtIGVsZWlmZW5kIGxvYm9ydGlz +LgoKQWxpcXVhbSBub24gbnVuYyBvZGlvLiBBbGlxdWFtIGlkIGRpYW0gdmVsIG1p +IHBvc3VlcmUgYXVjdG9yLiBQcmFlc2VudCB0ZW1wb3IgdGVsbHVzIHF1aXMgb2Rp +byB0aW5jaWR1bnQgcG9zdWVyZS4gSW50ZWdlciBhIG1hc3NhIHB1cnVzLCBhYyBn +cmF2aWRhIG1pLiBEb25lYyB2YXJpdXMgbmVxdWUgZXUgZXJvcyBzY2VsZXJpc3F1 +ZSBibGFuZGl0LiBNYWVjZW5hcyBjb25kaW1lbnR1bSB2b2x1dHBhdCBvZGlvIHBy +ZXRpdW0gY29udmFsbGlzLiBEdWlzIHBvc3VlcmUgdmVoaWN1bGEgdm9sdXRwYXQu +IFNlZCB0aW5jaWR1bnQgc2FwaWVuIGV1IGRpYW0gY3Vyc3VzIHZpdGFlIG9ybmFy +ZSBxdWFtIGFkaXBpc2NpbmcuIE5hbSBmYXVjaWJ1cyB0aW5jaWR1bnQgZWxlaWZl +bmQuIEFlbmVhbiBmYWNpbGlzaXMgY29uc2VxdWF0IHR1cnBpcywgYWMgbG9ib3J0 +aXMgdmVsaXQgZGljdHVtIHF1aXMuIE1hdXJpcyBpbXBlcmRpZXQgY29udmFsbGlz +IGxpZ3VsYSBtYXR0aXMgY29uZ3VlLiBOdWxsYW0gdWx0cmljaWVzIGNvbmd1ZSBs +YWN1cyBldCBwcmV0aXVtLiBQcmFlc2VudCBlcm9zIGFyY3UsIGxvYm9ydGlzIHV0 +IHBvcnR0aXRvciB1dCwgaW50ZXJkdW0gZXUgbGliZXJvLiBOYW0gbmVjIG9yY2kg +ZXJhdC4gQ3JhcyBoZW5kcmVyaXQgY29uc2VjdGV0dXIgbWFzc2EsIGlkIGxvYm9y +dGlzIGFyY3UgZXVpc21vZCBpZC4gU3VzcGVuZGlzc2UgcG90ZW50aS4gTnVsbGFt +IGVnZXN0YXMsIGVyb3MgYWMgc3VzY2lwaXQgbW9sZXN0aWUsIG5lcXVlIHRlbGx1 +cyBhZGlwaXNjaW5nIG1hdXJpcywgbm9uIGNvbW1vZG8gZmVsaXMgb2RpbyB1dCBz +ZW0uIE51bGxhbSBzYWdpdHRpcyBncmF2aWRhIHByZXRpdW0uIEZ1c2NlIHJ1dHJ1 +bSBjdXJzdXMgc2NlbGVyaXNxdWUuIFF1aXNxdWUgY29udmFsbGlzLCBkb2xvciBp +biBwdWx2aW5hciBhbGlxdWV0LCBzYXBpZW4gaXBzdW0gdGVtcG9yIGR1aSwgaWQg +dHJpc3RpcXVlIGVzdCBtYXVyaXMgYXVjdG9yIGp1c3RvLgoKQWVuZWFuIGFsaXF1 +ZXQgbWV0dXMgZXUgbWFnbmEgdHJpc3RpcXVlIGV1IGZlcm1lbnR1bSBtYWduYSB1 +bGxhbWNvcnBlci4gQWVuZWFuIHNjZWxlcmlzcXVlIGJsYW5kaXQgZWxlaWZlbmQu +IEludGVnZXIgYSBvcm5hcmUgb2Rpby4gTWFlY2VuYXMgZWxlaWZlbmQgaGVuZHJl +cml0IGFudGUgaWQgbW9sZXN0aWUuIE1hdXJpcyByaG9uY3VzIHBsYWNlcmF0IGFs +aXF1YW0uIFN1c3BlbmRpc3NlIGEgZWxpdCBkaWFtLCBldCBwaGFyZXRyYSBlc3Qu +IER1aXMgZWxlbWVudHVtIG9yY2kgZXUgYW50ZSBtYXR0aXMgYWMgY29uZ3VlIG5p +c2wgYWxpcXVldC4gSW50ZWdlciBzaXQgYW1ldCBkb2xvciBldCBtYXVyaXMgZWxl +aWZlbmQgbGFvcmVldC4gU2VkIGFsaXF1ZXQgcHJldGl1bSBudWxsYSwgaW4gZWxl +aWZlbmQgYXVndWUgcnV0cnVtIHF1aXMuIFF1aXNxdWUgZGFwaWJ1cyBuaXNsIHZp +dGFlIHRlbGx1cyBpbnRlcmR1bSBldSBibGFuZGl0IGFyY3UgY29uc2VxdWF0LiBF +dGlhbSBzZWQgcHVydXMgcmlzdXMuIEZ1c2NlIHR1cnBpcyBsaWJlcm8sIGFsaXF1 +YW0gbmVjIGxhY2luaWEgYXQsIGJsYW5kaXQgbmVjIG51bmMuIFByYWVzZW50IHZp +dmVycmEsIGxvcmVtIGFjIHBvcnR0aXRvciBtYWxlc3VhZGEsIGxvcmVtIHZlbGl0 +IHNvbGxpY2l0dWRpbiB2ZWxpdCwgc2l0IGFtZXQgdGluY2lkdW50IHVybmEgZHVp +IHZpdGFlIGxlby4KCkRvbmVjIHZpdGFlIGZlbGlzIHF1aXMgZW5pbSB2dWxwdXRh +dGUgcmhvbmN1cy4gUHJhZXNlbnQgZWxlbWVudHVtIHRyaXN0aXF1ZSBjb25ndWUu +IERvbmVjIHF1aXMgbWV0dXMgbmliaC4gTWFlY2VuYXMgYXJjdSBhbnRlLCBsYWNp +bmlhIGluIGRhcGlidXMgaWQsIGZlcm1lbnR1bSBzZWQgZXJhdC4gTW9yYmkgYWRp +cGlzY2luZyBncmF2aWRhIG1hZ25hLCB1dCBwb3N1ZXJlIG9kaW8gZmV1Z2lhdCB2 +aXRhZS4gU3VzcGVuZGlzc2UgcG9ydGEgbHVjdHVzIGxhb3JlZXQuIEFsaXF1YW0g +aW4gZXJhdCBzaXQgYW1ldCBvZGlvIHZlaGljdWxhIG9ybmFyZSBxdWlzIGF0IGR1 +aS4gU3VzcGVuZGlzc2Ugbm9uIGxvcmVtIHZpdGFlIGxpZ3VsYSBsdWN0dXMgY29u +c2VjdGV0dXIgYWMgaWQgcHVydXMuIE51bmMgdXQgbmlzaSBqdXN0by4gTnVsbGFt +IGVnZXQgc2FwaWVuIGNvbW1vZG8gZHVpIHN1c2NpcGl0IHBlbGxlbnRlc3F1ZS4g +Vml2YW11cyBzZW1wZXIgbWkgc2VkIGFyY3Ugc2VtcGVyIHZhcml1cy4gQ3JhcyBh +bGlxdWV0IHZlc3RpYnVsdW0gc2FwaWVuLCBhIGludGVyZHVtIG1pIHVsbGFtY29y +cGVyIHZlbC4gTW9yYmkgcHVydXMgZGlhbSwgb3JuYXJlIG5vbiB0ZW1wb3Igbm9u +LCBjb252YWxsaXMgbmVjIGVuaW0uIE51bGxhbSB0cmlzdGlxdWUgdnVscHV0YXRl +IGxlbyBuZWMgZmFjaWxpc2lzLiBQZWxsZW50ZXNxdWUgaGFiaXRhbnQgbW9yYmkg +dHJpc3RpcXVlIHNlbmVjdHVzIGV0IG5ldHVzIGV0IG1hbGVzdWFkYSBmYW1lcyBh +YyB0dXJwaXMgZWdlc3Rhcy4KCk1vcmJpIGltcGVyZGlldCB2ZWhpY3VsYSBjb25n +dWUuIE1hdXJpcyBxdWlzIG51bGxhIG9kaW8sIGEgZmF1Y2lidXMgdXJuYS4gTnVs +bGEgZXQgZXJvcyBkb2xvci4gRnVzY2UgYSBmYXVjaWJ1cyBpcHN1bS4gTWF1cmlz +IGZlcm1lbnR1bSBmZXVnaWF0IGRpZ25pc3NpbS4gVXQgYSBqdXN0byBlbGl0LCBu +b24gYXVjdG9yIHF1YW0uIFNlZCBsYWN1cyBhdWd1ZSwgcGxhY2VyYXQgYXQgYWxp +cXVhbSBub24sIG1hdHRpcyBpZCBtaS4gQWVuZWFuIGEgbGFvcmVldCBlcm9zLiBD +cmFzIHVsdHJpY2llcyBlbGl0IGluIG51bmMgc3VzY2lwaXQgaWQgc29sbGljaXR1 +ZGluIGVuaW0gY29uZGltZW50dW0uIFBoYXNlbGx1cyBkaWduaXNzaW0gbmlzaSBx +dWlzIGxlbyBpbnRlcmR1bSBwaGFyZXRyYS4gRG9uZWMgc2l0IGFtZXQgbGVvIGEg +ZHVpIHZpdmVycmEgbW9sZXN0aWUuIEN1cmFiaXR1ciBsb2JvcnRpcyBzYXBpZW4g +cXVpcyBuZXF1ZSBwdWx2aW5hciBhdCBmcmluZ2lsbGEgbmlzaSB2ZWhpY3VsYS4K +ClByYWVzZW50IG5vbiBwdXJ1cyB0ZWxsdXMuIEludGVnZXIgaWFjdWxpcyBkYXBp +YnVzIG5pc2wsIHRyaXN0aXF1ZSB2ZXN0aWJ1bHVtIG1pIG1hbGVzdWFkYSBzaXQg +YW1ldC4gU2VkIGxvYm9ydGlzIGhlbmRyZXJpdCBsb2JvcnRpcy4gUXVpc3F1ZSB0 +ZW1wb3IsIGFyY3UgYWMgdGVtcHVzIGF1Y3RvciwgbmVxdWUgcXVhbSBkaWN0dW0g +cXVhbSwgdml0YWUgZ3JhdmlkYSBsaWd1bGEgbmliaCBldSBhdWd1ZS4gQWVuZWFu +IGV1aXNtb2QgdGVtcG9yIGlwc3VtIGEgaGVuZHJlcml0LiBDcmFzIGRvbG9yIGxp +Z3VsYSwgZmF1Y2lidXMgYWMgaGVuZHJlcml0IGVnZXQsIGFsaXF1YW0gYSBuaXNs +LiBJbnRlZ2VyIG5lYyBjb25zZXF1YXQganVzdG8uIEludGVnZXIgcGhhcmV0cmEg +c2NlbGVyaXNxdWUgbGVvLiBBZW5lYW4gZXVpc21vZCB2ZWhpY3VsYSBhbnRlIG5v +biBwaGFyZXRyYS4gVmVzdGlidWx1bSBzb2xsaWNpdHVkaW4ganVzdG8gZXUgc2Vt +IGxhb3JlZXQgaW4gdGVtcHVzIG5lcXVlIGNvbW1vZG8uCgpVdCBpbiBhcmN1IGFu +dGUuIEN1cmFiaXR1ciB1bHRyaWNpZXMgdmVsaXQgZGlhbS4gQWxpcXVhbSB2ZWxp +dCBlcm9zLCB2b2x1dHBhdCBxdWlzIGN1cnN1cyBpZCwgdmVoaWN1bGEgYWMgdG9y +dG9yLiBOdWxsYSBwcmV0aXVtLCBlcmF0IGlkIGZhY2lsaXNpcyBibGFuZGl0LCBy +aXN1cyB0ZWxsdXMgYWxpcXVldCBvcmNpLCB2ZWwgY29uZGltZW50dW0gbmliaCBl +bGl0IHZpdGFlIGVsaXQuIFBoYXNlbGx1cyB1bGxhbWNvcnBlciBjb25zZWN0ZXR1 +ciBhbnRlIHNpdCBhbWV0IGx1Y3R1cy4gTnVsbGEgdXQgbnVsbGEgZWdldCBlcm9z +IGRpY3R1bSBwZWxsZW50ZXNxdWUgdmVsIHV0IG51bGxhLiBEb25lYyBsYW9yZWV0 +IHZpdmVycmEgbWFnbmEgdXQgaW50ZXJkdW0uIFZpdmFtdXMgcHVsdmluYXIgc2Fw +aWVuIGNvbnZhbGxpcyBtYWduYSBzb2RhbGVzIGVnZXQgZWdlc3RhcyBlc3QgaW1w +ZXJkaWV0LiBRdWlzcXVlIGZhY2lsaXNpcyBhbGlxdWFtIHNvZGFsZXMuIEV0aWFt +IGZlcm1lbnR1bSwgb2RpbyBhYyBzZW1wZXIgc2NlbGVyaXNxdWUsIHB1cnVzIGVu +aW0gaW1wZXJkaWV0IGF1Z3VlLCBzaXQgYW1ldCBkaWduaXNzaW0gc2FwaWVuIHRv +cnRvciBuZWMgbWF1cmlzLiBTdXNwZW5kaXNzZSBlbGVpZmVuZCBjb21tb2RvIG51 +bmMgcXVpcyBjb25zZWN0ZXR1ci4gRG9uZWMgZWdldCB0cmlzdGlxdWUgbGVvLgoK +U3VzcGVuZGlzc2Ugc29sbGljaXR1ZGluIHBoYXJldHJhIHNlbXBlci4gU2VkIGp1 +c3RvIGVzdCwgZmF1Y2lidXMgaWQgY3Vyc3VzIGEsIHBlbGxlbnRlc3F1ZSBpbiBt +aS4gTWF1cmlzIHNhZ2l0dGlzLCBpcHN1bSBjdXJzdXMgYmxhbmRpdCBpbXBlcmRp +ZXQsIGVzdCBlc3QgbHVjdHVzIHJpc3VzLCBxdWlzIGZlcm1lbnR1bSBsZW8gb3Jj +aSBhIG9kaW8uIE51bmMgc2l0IGFtZXQgdmVsaXQgaXBzdW0uIE5hbSBldWlzbW9k +IHB1bHZpbmFyIG1ldHVzLCBhYyBhZGlwaXNjaW5nIGR1aSB1bGxhbWNvcnBlciBh +LiBWZXN0aWJ1bHVtIGFudGUgaXBzdW0gcHJpbWlzIGluIGZhdWNpYnVzIG9yY2kg +bHVjdHVzIGV0IHVsdHJpY2VzIHBvc3VlcmUgY3ViaWxpYSBDdXJhZTsgU2VkIG1v +bGVzdGllIHRpbmNpZHVudCBkb2xvciwgc2VkIHByZXRpdW0gbWFnbmEgY29uc2Vj +dGV0dXIgdXQuIExvcmVtIGlwc3VtIGRvbG9yIHNpdCBhbWV0LCBjb25zZWN0ZXR1 +ciBhZGlwaXNjaW5nIGVsaXQuIEFsaXF1YW0gbGVjdHVzIGxpZ3VsYSwgaW50ZXJk +dW0gYXQgbG9ib3J0aXMgaWQsIGNvbnZhbGxpcyBzaXQgYW1ldCBzZW0uIFNlZCBl +Z2V0IG5lcXVlIGluIGFyY3UgdWx0cmljZXMgZmV1Z2lhdC4gUHJvaW4gdnVscHV0 +YXRlIGxlbyBlZ2V0IGVyb3MgZGFwaWJ1cyBhbGlxdWV0LiBGdXNjZSBmYWNpbGlz +aXMgY29uc2VxdWF0IGRpYW0sIHNlZCB2ZXN0aWJ1bHVtIG1pIHVsdHJpY2llcyBl +Z2V0LiBVdCBwb3N1ZXJlIGNvbmd1ZSBsaWJlcm8gc2l0IGFtZXQgZGlnbmlzc2lt +LiBQcm9pbiBxdWlzIGFyY3UgbGliZXJvLgoKVmVzdGlidWx1bSBhdCBhdWd1ZSBt +YXVyaXMuIEFsaXF1YW0gc2FnaXR0aXMgcG9ydGEgYW50ZSBpbiB2YXJpdXMuIFZl +c3RpYnVsdW0gbHVjdHVzIGlhY3VsaXMgYXJjdSBhIGludGVyZHVtLiBVdCB2YXJp +dXMgaGVuZHJlcml0IGxhY3VzIG5lYyBzYWdpdHRpcy4gU2VkIHV0IHJpc3VzIGFj +IGxlY3R1cyB1bHRyaWNpZXMgbW9sbGlzLiBOdW5jIGZldWdpYXQgc3VzY2lwaXQg +bnVuYyBxdWlzIGVsZW1lbnR1bS4gU3VzcGVuZGlzc2UgcG90ZW50aS4gRnVzY2Ug +bGFvcmVldCBlbGl0IGV1IG9kaW8gZnJpbmdpbGxhIHBlbGxlbnRlc3F1ZS4gRXRp +YW0gdml0YWUgYXJjdSBxdWlzIHF1YW0gc29kYWxlcyBmYWNpbGlzaXMgY29uc2Vx +dWF0IHV0IG9yY2kuIFBoYXNlbGx1cyB2aXRhZSBxdWFtIHF1aXMgbGVvIGNvbmd1 +ZSBpbnRlcmR1bSBzZWQgc3VzY2lwaXQgZXN0LiBNYWVjZW5hcyBjb25kaW1lbnR1 +bSwgbWFzc2EgZWdldCB0ZW1wb3IgcGhhcmV0cmEsIGVyYXQgbGVvIGxhY2luaWEg +b2Rpbywgc2l0IGFtZXQgZmV1Z2lhdCBtYXVyaXMgcmlzdXMgc2VkIHNhcGllbi4g +TW9yYmkgYXJjdSBsb3JlbSwgZGFwaWJ1cyBlZ2V0IHZlbmVuYXRpcyBzZWQsIHNl +bXBlciBlZ2V0IGVyb3MuIENyYXMgc2VtcGVyIHVsdHJpY2llcyBlcm9zIHZvbHV0 +cGF0IHZ1bHB1dGF0ZS4gTW9yYmkgYXQgbnVuYyBlZ2V0IG5pYmggZmV1Z2lhdCB0 +ZW1wdXMuCgpJbiBlZ2V0IGVsaXQgYSBkaWFtIHBsYWNlcmF0IHZvbHV0cGF0IHNl +ZCB0ZW1wdXMgZGlhbS4gTWFlY2VuYXMgdGVtcG9yIHNlbSBpZCBzZW0gdml2ZXJy +YSB2ZWwgZmVybWVudHVtIHJpc3VzIHBvcnR0aXRvci4gUHJvaW4gYSBtZXR1cyBt +ZXR1cy4gQWVuZWFuIHF1aXMgdGluY2lkdW50IG1hZ25hLiBEb25lYyBzaXQgYW1l +dCBwb3N1ZXJlIHJpc3VzLiBEb25lYyBlc3QganVzdG8sIGRhcGlidXMgaW4gc29s +bGljaXR1ZGluIGV1LCB2ZW5lbmF0aXMgc2l0IGFtZXQgZWxpdC4gQ2xhc3MgYXB0 +ZW50IHRhY2l0aSBzb2Npb3NxdSBhZCBsaXRvcmEgdG9ycXVlbnQgcGVyIGNvbnVi +aWEgbm9zdHJhLCBwZXIgaW5jZXB0b3MgaGltZW5hZW9zLiBDcmFzIGluIHR1cnBp +cyBuZWMgbnVuYyBmcmluZ2lsbGEgaWFjdWxpcy4gRXRpYW0gc3VzY2lwaXQgbmli +aCB2aXRhZSBsaWJlcm8gcGVsbGVudGVzcXVlIHZpdmVycmEuIENyYXMgaWQgbGVj +dHVzIHF1aXMgZW5pbSBvcm5hcmUgbW9sZXN0aWUgdml0YWUgdmVsIHRlbGx1cy4g +SW4gdmVzdGlidWx1bSB2dWxwdXRhdGUgdHVycGlzIGlkIHBvc3VlcmUuCgpOYW0g +ZXN0IGVyYXQsIHJob25jdXMgbm9uIGltcGVyZGlldCBpbiwgc2FnaXR0aXMgdml0 +YWUgaXBzdW0uIE51bGxhIHJ1dHJ1bSB0aW5jaWR1bnQgbGVjdHVzIGV0IGJsYW5k +aXQuIFV0IHNlZCBsaWd1bGEgbmlzbCwgbm9uIGRpY3R1bSBlcmF0LiBBZW5lYW4g +bG9yZW0gZW5pbSwgbW9sbGlzIHV0IHRpbmNpZHVudCBpZCwgY29tbW9kbyBzaXQg +YW1ldCBuaXNsLiBNYWVjZW5hcyBibGFuZGl0IHJob25jdXMgc2VtcGVyLiBGdXNj +ZSBhIG1hc3NhIG9yY2ksIGV0IHZlbmVuYXRpcyBhcmN1LiBNYXVyaXMgbW9sbGlz +IGR1aSBxdWlzIGZlbGlzIGJpYmVuZHVtIHBoYXJldHJhLiBDcmFzIHNlZCBpcHN1 +bSBtYXNzYSwgcG9ydHRpdG9yIHB1bHZpbmFyIG5pc2kuIExvcmVtIGlwc3VtIGRv +bG9yIHNpdCBhbWV0LCBjb25zZWN0ZXR1ciBhZGlwaXNjaW5nIGVsaXQuIFZpdmFt +dXMgY3Vyc3VzIGVsaXQgc2FnaXR0aXMgbGliZXJvIGhlbmRyZXJpdCB2ZXN0aWJ1 +bHVtLiBTZWQgcG9ydHRpdG9yLCB0b3J0b3IgdGluY2lkdW50IHBvcnR0aXRvciBz +ZW1wZXIsIGRpYW0gbWFnbmEgZWxlaWZlbmQgbnVuYywgc2VkIGNvbmRpbWVudHVt +IG5pYmggZXJhdCBxdWlzIG9kaW8uIERvbmVjIHBvc3VlcmUgdmVoaWN1bGEgcHVy +dXMsIGluIHB1bHZpbmFyIG9kaW8gaW50ZXJkdW0gZXUuIFZlc3RpYnVsdW0gZmFj +aWxpc2lzIHRpbmNpZHVudCBkYXBpYnVzLiBGdXNjZSBsdWN0dXMgbG9yZW0gZWdl +dCBxdWFtIGFjY3Vtc2FuIGluIG1hdHRpcyBuaWJoIHZvbHV0cGF0LiBOdWxsYW0g +ZXQgbGVvIGEgdXJuYSBwb3J0YSB2YXJpdXMgbm9uIHZpdGFlIGR1aS4gU2VkIGlu +dGVyZHVtLCBtZXR1cyBldSBydXRydW0gcGhhcmV0cmEsIG5pc2wgc2VtIHRlbXB1 +cyBqdXN0bywgdmFyaXVzIGNvbnZhbGxpcyBpcHN1bSBkaWFtIHV0IGxlY3R1cy4K +CkluIGhhYyBoYWJpdGFzc2UgcGxhdGVhIGRpY3R1bXN0LiBWZXN0aWJ1bHVtIGNv +bmd1ZSBzb2RhbGVzIG5pc2kgcXVpcyBvcm5hcmUuIEZ1c2NlIGN1cnN1cyBuaXNp +IGF0IHR1cnBpcyBjb25ndWUgaGVuZHJlcml0LiBWZXN0aWJ1bHVtIG5vbiBsYWN1 +cyB2ZWwgc2FwaWVuIHB1bHZpbmFyIHZlaGljdWxhIGF0IGluIGFudGUuIE51bGxh +IGZhY2lsaXNpLiBVdCB0cmlzdGlxdWUgdGluY2lkdW50IGVyYXQgaWQgbHVjdHVz +LiBDdXJhYml0dXIgcG9zdWVyZSBzb2RhbGVzIG5lcXVlIHF1aXMgdmFyaXVzLiBD +dXJhYml0dXIgY3Vyc3VzIGFjY3Vtc2FuIGlwc3VtLCB2ZWwgbHVjdHVzIGxpZ3Vs +YSBkYXBpYnVzIG5vbi4gQ3JhcyB2ZWhpY3VsYSBtYWduYSBpbiBsYWN1cyBvcm5h +cmUgZGFwaWJ1cy4gRG9uZWMgYWxpcXVldCBzb2xsaWNpdHVkaW4gbGFjdXMsIGV1 +IGlhY3VsaXMgZXJhdCBiaWJlbmR1bSBjb21tb2RvLiBEb25lYyBibGFuZGl0IGJp +YmVuZHVtIGZldWdpYXQuIFByYWVzZW50IGV1IGVzdCBqdXN0by4gUGVsbGVudGVz +cXVlIGF0IGVuaW0gc2VkIHNlbSB2aXZlcnJhIGNvbnZhbGxpcy4gTWFlY2VuYXMg +dmVuZW5hdGlzIG1ldHVzIHNhcGllbi4gU2VkIHBsYWNlcmF0IGZhY2lsaXNpcyBl +bGl0IG5lYyBtYWxlc3VhZGEuIEZ1c2NlIHNhcGllbiBlc3QsIGNvbnNlcXVhdCBh +IGNvbmd1ZSBlZ2V0LCBhY2N1bXNhbiBlZ2V0IGxvcmVtLiBTdXNwZW5kaXNzZSB0 +aW5jaWR1bnQgcHJldGl1bSBtYWduYSBlZ2V0IGRhcGlidXMuIEZ1c2NlIHZlbCBl +cm9zIGV0IGxvcmVtIGNvbnNlcXVhdCB0cmlzdGlxdWUgbmVjIGEgaXBzdW0uCgpQ +cm9pbiBxdWlzIGN1cnN1cyBhcmN1LiBNYWVjZW5hcyBlbGVpZmVuZCBsb3JlbSBp +ZCBuaXNsIHNjZWxlcmlzcXVlIHBsYWNlcmF0LiBGdXNjZSBpbXBlcmRpZXQgbG9y +ZW0gZXUgdXJuYSBkaWduaXNzaW0gZmVybWVudHVtLiBQZWxsZW50ZXNxdWUgbnVu +YyBuaXNsLCBpbXBlcmRpZXQgdXQgYWNjdW1zYW4gaWQsIGZlcm1lbnR1bSBub24g +bWF1cmlzLiBBZW5lYW4gZnJpbmdpbGxhIGxlY3R1cyB2aXRhZSB0dXJwaXMgZmVy +bWVudHVtIHZpdGFlIGZhY2lsaXNpcyBvZGlvIG1vbGxpcy4gQWVuZWFuIG5vbiBz +ZW0gZXQgZXJvcyBjb25ndWUgcG9ydGEgaWQgc2l0IGFtZXQgZGlhbS4gRG9uZWMg +ZnJpbmdpbGxhIGVyb3MgYXQgcXVhbSBpbXBlcmRpZXQgYXQgZ3JhdmlkYSB0b3J0 +b3IgdWxsYW1jb3JwZXIuIEZ1c2NlIGRvbG9yIHJpc3VzLCB2aXZlcnJhIGlkIGFs +aXF1ZXQgc2VkLCBkaWduaXNzaW0gcXVpcyBtYXVyaXMuIFF1aXNxdWUgYWMgbWV0 +dXMgaWQgcXVhbSBsb2JvcnRpcyB0cmlzdGlxdWUgYXQgdmVsIGVuaW0uIFBoYXNl +bGx1cyBpbiB0b3J0b3IgbWF1cmlzLiBTZWQgdGluY2lkdW50IGR1aSBub24gZXJv +cyBzb2xsaWNpdHVkaW4gdm9sdXRwYXQuIEN1cmFiaXR1ciB2aXZlcnJhIGVsZW1l +bnR1bSBhcmN1IGFjIHVsdHJpY2VzLiBOdWxsYSBmZWxpcyBsaWd1bGEsIGF1Y3Rv +ciBhdCBsYWNpbmlhIHNlZCwgdGluY2lkdW50IGF0IG1pLiBJbiB2ZWwgZWxpdCBv +cmNpLiBWZXN0aWJ1bHVtIGVyYXQgbmlzaSwgbW9sZXN0aWUgdmVsIGF1Y3RvciB2 +ZWwsIHNhZ2l0dGlzIGFjIGxlY3R1cy4gUGVsbGVudGVzcXVlIHVsdHJpY2llcyBj +b25kaW1lbnR1bSBudWxsYSBuZWMgZXVpc21vZC4KCkRvbmVjIGNvbnNlY3RldHVy +IHZlbmVuYXRpcyBzZW1wZXIuIFN1c3BlbmRpc3NlIHZlbCBkaWN0dW0gYXVndWUu +IFBlbGxlbnRlc3F1ZSBub24gbWF1cmlzIGp1c3RvLiBEb25lYyBhY2N1bXNhbiwg +bWV0dXMgdXQgcHJldGl1bSBtb2xlc3RpZSwgbGlndWxhIGp1c3RvIGx1Y3R1cyBv +cmNpLCBub24gdmFyaXVzIG1pIG5pYmggZXUganVzdG8uIFZlc3RpYnVsdW0gc2Vt +IHNlbSwgdGluY2lkdW50IGVnZXQgcG9ydGEgYSwgZmVybWVudHVtIGV0IHNhcGll +bi4gTnVsbGEgZmFjaWxpc2kuIFBlbGxlbnRlc3F1ZSBpbiB2ZXN0aWJ1bHVtIGFu +dGUuIE51bmMgaWFjdWxpcyBsaWd1bGEgbmVjIG9kaW8gc2FnaXR0aXMgbmVjIHBv +cnR0aXRvciBuaWJoIHNlbXBlci4gVXQgZWdldCBtZXR1cyBvcmNpLiBQcm9pbiBn +cmF2aWRhIG9yY2kgZGlnbmlzc2ltIGRpYW0gaWFjdWxpcyBhY2N1bXNhbi4gQWVu +ZWFuIGF1Z3VlIG9yY2ksIHBsYWNlcmF0IGV0IGNvbnZhbGxpcyBlZ2V0LCBzb2Rh +bGVzIHF1aXMgZGlhbS4gU2VkIHN1c2NpcGl0IG5pc2kgcXVpcyBsaWJlcm8gc29s +bGljaXR1ZGluIGV1IG1vbGxpcyBuZXF1ZSBtb2xlc3RpZS4gTWFlY2VuYXMgcHVy +dXMgbmlzbCwgY29uc2VjdGV0dXIgbm9uIHZlaGljdWxhIHNpdCBhbWV0LCB1bGxh +bWNvcnBlciBxdWlzIG5pYmguIFByYWVzZW50IHF1YW0gaXBzdW0sIG1vbGVzdGll +IGV1IHB1bHZpbmFyIGF0LCBpYWN1bGlzIGV1IHR1cnBpcy4gQ3JhcyBuZWMgZWxp +dCB1dCBsaWJlcm8gc3VzY2lwaXQgYWxpcXVldCBldCBuZWMgbGVjdHVzLiBWZXN0 +aWJ1bHVtIHB1cnVzIGF1Z3VlLCB0cmlzdGlxdWUgdml0YWUgY29udmFsbGlzIGF0 +LCB2ZWhpY3VsYSBub24gbWV0dXMuIEZ1c2NlIGx1Y3R1cyBjb25ndWUgbWksIHZl +bCBzYWdpdHRpcyBkb2xvciBtb2xsaXMgdmVsLiBQcmFlc2VudCBpbiBudW5jIGFj +Y3Vtc2FuIGxvcmVtIGxvYm9ydGlzIGlhY3VsaXMgdXQgdml0YWUgaXBzdW0uIFN1 +c3BlbmRpc3NlIHB1bHZpbmFyLCBudW5jIGFjIGFsaXF1ZXQgc2VtcGVyLCBsYWN1 +cyBsb3JlbSBldWlzbW9kIHB1cnVzLCB2ZWwgbW9sbGlzIG1ldHVzIHJpc3VzIG5l +YyBzYXBpZW4uCgpJbiB2ZW5lbmF0aXMgcG9zdWVyZSBzYXBpZW4sIHNpdCBhbWV0 +IGV1aXNtb2QgZG9sb3IgcGVsbGVudGVzcXVlIGV1LiBQcmFlc2VudCBsYW9yZWV0 +IGZlbGlzIHV0IG1ldHVzIHZlc3RpYnVsdW0gY29uZGltZW50dW0uIFV0IHNjZWxl +cmlzcXVlIGxlbyBhdWd1ZS4gU3VzcGVuZGlzc2Ugdml0YWUgZG9sb3IgcHVydXMs +IGlkIHJ1dHJ1bSBhbnRlLiBGdXNjZSBpbiB2ZWxpdCBhbnRlLCBhIHBlbGxlbnRl +c3F1ZSBtaS4gTWFlY2VuYXMgdmVsIHJpc3VzIGVnZXQgb3JjaSBmZXJtZW50dW0g +cHJldGl1bSBuZWMgdmVsIHNhcGllbi4gUGhhc2VsbHVzIGlwc3VtIG1hZ25hLCBi +aWJlbmR1bSBxdWlzIGZhdWNpYnVzIHZlbCwgcGxhY2VyYXQgaWQgbWFnbmEuIFZp +dmFtdXMgcXVhbSBkdWksIGNvbnNlY3RldHVyIHNlZCBwdWx2aW5hciBldSwgaW50 +ZXJkdW0gaWQgaXBzdW0uIENyYXMgbG9ib3J0aXMgZmFjaWxpc2lzIHJ1dHJ1bS4g +Q3VtIHNvY2lpcyBuYXRvcXVlIHBlbmF0aWJ1cyBldCBtYWduaXMgZGlzIHBhcnR1 +cmllbnQgbW9udGVzLCBuYXNjZXR1ciByaWRpY3VsdXMgbXVzLiBOYW0gdmVzdGli +dWx1bSBudW5jIHNlZCBqdXN0byBkaWduaXNzaW0gYWMgdGluY2lkdW50IHNhcGll +biBjb25ndWUuCgpQaGFzZWxsdXMgbm9uIGRpY3R1bSB0dXJwaXMuIFByb2luIGVn +ZXQgbWFzc2EgbGFjaW5pYSBsaWJlcm8gcnV0cnVtIHZlc3RpYnVsdW0uIE51bGxh +IGFsaXF1ZXQgbGliZXJvIGlkIHNhcGllbiBhbGlxdWFtIGZlcm1lbnR1bS4gVml2 +YW11cyBsZWN0dXMgaXBzdW0sIHBoYXJldHJhIHV0IGRhcGlidXMgdXQsIGFsaXF1 +YW0gYWMgbmVxdWUuIFZpdmFtdXMgZmF1Y2lidXMgbWkgcXVpcyBtYXVyaXMgcnV0 +cnVtIGFjIHBsYWNlcmF0IG5pc2kgc2NlbGVyaXNxdWUuIE1hdXJpcyBlbGl0IG9y +Y2ksIGFkaXBpc2NpbmcgZXUgY29uc2VxdWF0IGlkLCB2ZW5lbmF0aXMgaW4gbnVu +Yy4gQWVuZWFuIG5vbiBibGFuZGl0IGxpYmVyby4gU3VzcGVuZGlzc2UgaWQgYXVn +dWUgZHVpLiBRdWlzcXVlIG5lYyBvcmNpIHZlbCBvZGlvIG1hdHRpcyBncmF2aWRh +LiBWZXN0aWJ1bHVtIGFudGUgaXBzdW0gcHJpbWlzIGluIGZhdWNpYnVzIG9yY2kg +bHVjdHVzIGV0IHVsdHJpY2VzIHBvc3VlcmUgY3ViaWxpYSBDdXJhZTsgTWF1cmlz +IHZvbHV0cGF0IGR1aSB1dCBsYWN1cyBhZGlwaXNjaW5nIGJpYmVuZHVtLiBMb3Jl +bSBpcHN1bSBkb2xvciBzaXQgYW1ldCwgY29uc2VjdGV0dXIgYWRpcGlzY2luZyBl +bGl0LiBWaXZhbXVzIHZlbmVuYXRpcyBqdXN0byBldSBzYXBpZW4gZmVybWVudHVt +IGNvbmd1ZSBxdWlzIGluIG51bmMuIE51bGxhbSBsYWNpbmlhIGVyb3MgbG9yZW0s +IHV0IGFsaXF1YW0gb3JjaS4gUGhhc2VsbHVzIHN1c2NpcGl0LCBsYWN1cyBldCB0 +ZW1wb3Igc2VtcGVyLCBlc3QgbWF1cmlzIGNvbmd1ZSBtYXNzYSwgc2VkIHVsdHJp +Y2VzIG9yY2kgZGlhbSB2aXRhZSBpcHN1bS4KCk51bGxhIGZhY2lsaXNpLiBTZWQg +cG9zdWVyZSBmcmluZ2lsbGEgZmVsaXMsIGFjIHZlbmVuYXRpcyBkdWkgdnVscHV0 +YXRlIHV0LiBQcm9pbiBlbGVpZmVuZCB0ZW1wb3IgbW9sZXN0aWUuIE51bGxhIHRp +bmNpZHVudCBsZWN0dXMgdml0YWUgbmVxdWUgYmliZW5kdW0gcHJldGl1bS4gSW4g +bGliZXJvIG5pc2wsIHRyaXN0aXF1ZSBuZWMgYmliZW5kdW0gc2l0IGFtZXQsIHVs +bGFtY29ycGVyIG5lYyBlcmF0LiBTdXNwZW5kaXNzZSBpbnRlcmR1bSBwb3J0YSBv +cmNpLCBxdWlzIHZpdmVycmEgZXJhdCBhdWN0b3IgYXQuIER1aXMgYWMgZGlhbSBl +dCBsaWd1bGEgYmxhbmRpdCB0ZW1wb3IgbmVjIGV1IGxhY3VzLiBDdW0gc29jaWlz +IG5hdG9xdWUgcGVuYXRpYnVzIGV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250 +ZXMsIG5hc2NldHVyIHJpZGljdWx1cyBtdXMuIFByYWVzZW50IHBlbGxlbnRlc3F1 +ZSB2YXJpdXMgbnVsbGEgdmVsIGFsaXF1YW0uIEFsaXF1YW0gdXQgbGVjdHVzIG1h +dXJpcywgaWQgYWxpcXVldCBsYWN1cy4gSW50ZWdlciBzY2VsZXJpc3F1ZSBlbGVt +ZW50dW0gZHVpLCBldSBsYW9yZWV0IGF1Z3VlIGVsZW1lbnR1bSBzaXQgYW1ldC4g +VXQgdWxsYW1jb3JwZXIgdGVsbHVzIGNvbnZhbGxpcyBzYXBpZW4gdmVzdGlidWx1 +bSBub24gbGFvcmVldCBwdXJ1cyBhZGlwaXNjaW5nLiBOdW5jIG5lYyBxdWFtIG51 +bmMuIFZpdmFtdXMgdWx0cmljZXMgZmVybWVudHVtIG1hc3NhLCBzaXQgYW1ldCBz +Y2VsZXJpc3F1ZSBudW5jIGltcGVyZGlldCB1dC4KClZlc3RpYnVsdW0gYW50ZSBp +cHN1bSBwcmltaXMgaW4gZmF1Y2lidXMgb3JjaSBsdWN0dXMgZXQgdWx0cmljZXMg +cG9zdWVyZSBjdWJpbGlhIEN1cmFlOyBJbiBoYWMgaGFiaXRhc3NlIHBsYXRlYSBk +aWN0dW1zdC4gTnVsbGFtIHRpbmNpZHVudCBtb2xlc3RpZSBpcHN1bSB2ZWwgcmhv +bmN1cy4gSW50ZWdlciBlZ2V0IG51bmMgZXUgdGVsbHVzIHRpbmNpZHVudCBsYWNp +bmlhLiBJbnRlZ2VyIG5lYyBuaXNpIGVnZXQgYXVndWUgc2VtcGVyIHZhcml1cyBp +ZCBhYyBxdWFtLiBOYW0gdGluY2lkdW50LCB0ZWxsdXMgYWMgY29uZGltZW50dW0g +YWNjdW1zYW4sIGRvbG9yIGVyb3Mgdml2ZXJyYSBsZW8sIHBoYXJldHJhIHB1bHZp +bmFyIGxlY3R1cyBlcm9zIGluIG1pLiBEb25lYyBjb25zZXF1YXQsIHR1cnBpcyBp +ZCBjb252YWxsaXMgdm9sdXRwYXQsIGFudGUgc2VtIGVsZW1lbnR1bSBtYWduYSwg +cXVpcyB0ZW1wb3IgcmlzdXMgZGlhbSB2ZWwgdHVycGlzLiBNb3JiaSBhIG9yY2kg +b3JjaSwgZWdlc3RhcyBmZXVnaWF0IGxlY3R1cy4gTnVsbGEgbmVjIG5pYmggaWQg +YXVndWUgaW50ZXJkdW0gbW9sbGlzLiBTdXNwZW5kaXNzZSBwbGFjZXJhdCB0ZW1w +dXMgbnVuYyBhYyB2ZXN0aWJ1bHVtLiBEb25lYyBldCBtZXR1cyBkaWN0dW0gbGVv +IGJpYmVuZHVtIHVsdHJpY2VzIGluIG5lYyBsZWN0dXMuIFV0IHNlZCB2ZWxpdCBu +aWJoLCBzb2RhbGVzIHBvcnRhIG51bmMuIEluIGhhYyBoYWJpdGFzc2UgcGxhdGVh +IGRpY3R1bXN0LiBTZWQgZWxpdCB0b3J0b3IsIGFsaXF1ZXQgdmVsIHZvbHV0cGF0 +IGEsIHRpbmNpZHVudCBzZWQgc2FwaWVuLiBTdXNwZW5kaXNzZSBlZ2V0IGxpYmVy +byBsYWN1cy4gVml2YW11cyBhdWN0b3IgYW50ZSBub24gbmVxdWUgcG9ydHRpdG9y +IHV0IHByZXRpdW0gbmlzbCB0ZW1wdXMuIE51bGxhIHNvZGFsZXMgcmlzdXMgZXQg +ZXJhdCB2YXJpdXMgbGFvcmVldC4gTWFlY2VuYXMgbHVjdHVzIGxvYm9ydGlzIGxp +Z3VsYSBlZ2V0IGZlcm1lbnR1bS4KClZpdmFtdXMgY29udmFsbGlzIG5pYmggdml0 +YWUgdHVycGlzIGZldWdpYXQgdWx0cmljZXMuIFF1aXNxdWUgdml0YWUgYmxhbmRp +dCBtYXNzYS4gTWF1cmlzIGV1aXNtb2QgdXJuYSB1dCBuZXF1ZSBmZXJtZW50dW0g +dml0YWUgaW1wZXJkaWV0IG1hdXJpcyBldWlzbW9kLiBJbiBhIGR1aSB0ZWxsdXMs +IG5lYyBwb3N1ZXJlIGRvbG9yLiBBZW5lYW4gdWxsYW1jb3JwZXIgYXVndWUgaWQg +ZXJhdCBsYWNpbmlhIHB1bHZpbmFyLiBQZWxsZW50ZXNxdWUgYXQgbnVsbGEgdGVs +bHVzLiBOYW0gZWxlbWVudHVtIGlhY3VsaXMgcHVsdmluYXIuIFZpdmFtdXMgdG9y +dG9yIGxlY3R1cywgZ3JhdmlkYSB1dCBjb21tb2RvIGEsIHZpdmVycmEgdXQgb2Rp +by4gUGhhc2VsbHVzIGVsZW1lbnR1bSBibGFuZGl0IG9kaW8sIG5lYyBkYXBpYnVz +IGFudGUgbWFsZXN1YWRhIGEuIE1hZWNlbmFzIGltcGVyZGlldCwgZmVsaXMgYSBz +ZW1wZXIgZmFjaWxpc2lzLCBtYXNzYSBudWxsYSBhbGlxdWV0IHRvcnRvciwgZXQg +bWFsZXN1YWRhIG1hZ25hIGxlY3R1cyBhYyBwdXJ1cy4gQWVuZWFuIGF1Y3RvciB0 +ZWxsdXMgaWQganVzdG8gY29uZGltZW50dW0gdHJpc3RpcXVlLiBDcmFzIHZpdGFl +IHJ1dHJ1bSBhcmN1LiBNYXVyaXMgdGVtcHVzLCBtYWduYSBlZ2V0IHZhcml1cyBp +bnRlcmR1bSwgbmlzbCBqdXN0byBwb3J0YSBhdWd1ZSwgc2VkIHBvcnRhIG5pc2wg +cXVhbSBhIG5pYmguIE1hZWNlbmFzIHZpdGFlIHB1cnVzIGRpYW0uIFByYWVzZW50 +IGJpYmVuZHVtIG5pYmggZHVpLCBpbiB0aW5jaWR1bnQgbnVuYy4gRHVpcyB2aXRh +ZSBzZW0gYW50ZS4KCk1hdXJpcyBwb3N1ZXJlIGZlbGlzIGV0IHR1cnBpcyBzb2Rh +bGVzIGhlbmRyZXJpdCB1dCBpZCBudW5jLiBEb25lYyBsYW9yZWV0IG1hbGVzdWFk +YSBlcm9zLiBOYW0gcXVpcyBkaWFtIGFyY3UsIGV1IHRyaXN0aXF1ZSB0ZWxsdXMu +IFBlbGxlbnRlc3F1ZSBxdWlzIGVsaXQgbnVuYy4gQ3JhcyBsZW8gbG9yZW0sIG9y +bmFyZSBjb21tb2RvIG1vbGVzdGllIHNpdCBhbWV0LCBjb25zZXF1YXQgdmVsIGVz +dC4gSW4gaGFjIGhhYml0YXNzZSBwbGF0ZWEgZGljdHVtc3QuIENyYXMgcmlzdXMg +cXVhbSwgc3VzY2lwaXQgc2VtcGVyIGltcGVyZGlldCB1bHRyaWNlcywgdHJpc3Rp +cXVlIG5lYyBzYXBpZW4uIFBlbGxlbnRlc3F1ZSBjb25kaW1lbnR1bSwgdHVycGlz +IG5lYyBzb2RhbGVzIGNvbnNlY3RldHVyLCBkaWFtIHNlbSBiaWJlbmR1bSBkaWFt +LCB2aXRhZSBhbGlxdWV0IG1pIGFyY3UgYSBhcmN1LiBQaGFzZWxsdXMgaGVuZHJl +cml0LCBtYWduYSBxdWlzIGdyYXZpZGEgZmVybWVudHVtLCBtYWduYSBsZWN0dXMg +c2VtcGVyIG1hc3NhLCBzZWQgY29uZ3VlIHVybmEgbmliaCBhdCBudWxsYS4gQ3Jh +cyBzZWQgbmliaCBtaS4gTnVsbGEgdGVtcG9yIHByZXRpdW0gcG9ydGEuCgpVdCBp +ZCBqdXN0byB2aXRhZSB0dXJwaXMgY29udmFsbGlzIGNvbmd1ZS4gQ3VyYWJpdHVy +IG1hbGVzdWFkYSBwdXJ1cyBlZ2V0IGRpYW0gYXVjdG9yIGV0IHVsbGFtY29ycGVy +IHZlbGl0IG1hbGVzdWFkYS4gUGhhc2VsbHVzIHNjZWxlcmlzcXVlIGZlcm1lbnR1 +bSBsaWJlcm8uIE1vcmJpIGR1aSB0b3J0b3IsIGJsYW5kaXQgbWFsZXN1YWRhIGxv +Ym9ydGlzIHVsdHJpY2llcywgYmxhbmRpdCBldCBuaXNpLiBOdWxsYSBtYXR0aXMg +ZmFjaWxpc2lzIGxhY3VzLiBBbGlxdWFtIHNvZGFsZXMgZWxpdCBzaXQgYW1ldCBt +ZXR1cyB2ZW5lbmF0aXMgYSBjb21tb2RvIHF1YW0gYmliZW5kdW0uIFV0IG5vbiB0 +ZWxsdXMgdG9ydG9yLiBTZWQgc2VtcGVyLCBuaXNpIGluIHRlbXBvciB2ZXN0aWJ1 +bHVtLCBzZW0gbnVsbGEgZXVpc21vZCBhcmN1LCB1dCBzb2RhbGVzIGVzdCBudW5j +IGF0IHRlbGx1cy4gRG9uZWMgbm9uIG1ldHVzIG5vbiBkb2xvciBzY2VsZXJpc3F1 +ZSB2aXZlcnJhLiBQaGFzZWxsdXMgbmVjIG51bGxhIGp1c3RvLCB1dCBwb3J0dGl0 +b3IgbnVsbGEuIEZ1c2NlIGZldWdpYXQgZ3JhdmlkYSBzb2xsaWNpdHVkaW4uIFNl +ZCBpZCBoZW5kcmVyaXQgbWF1cmlzLiBEb25lYyBsZWN0dXMgdG9ydG9yLCBwb3J0 +YSBzaXQgYW1ldCBjb25kaW1lbnR1bSBzZWQsIHZhcml1cyBhIHZlbGl0LiBJbiBk +aWN0dW0gZG9sb3Igc2VkIGVzdCBkaWN0dW0gaW4gcnV0cnVtIG5lcXVlIHN1c2Np +cGl0LgoKTWFlY2VuYXMgaW1wZXJkaWV0IGNvbnZhbGxpcyB1bHRyaWNpZXMuIEN1 +bSBzb2NpaXMgbmF0b3F1ZSBwZW5hdGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJp +ZW50IG1vbnRlcywgbmFzY2V0dXIgcmlkaWN1bHVzIG11cy4gUGVsbGVudGVzcXVl +IG51bmMgdHVycGlzLCBpYWN1bGlzIHF1aXMgZWxlaWZlbmQgZXUsIHRpbmNpZHVu +dCB1dCBsYWN1cy4gQ3VyYWJpdHVyIHZpdGFlIHRlbGx1cyBuaWJoLiBQZWxsZW50 +ZXNxdWUgZWdldCBjb21tb2RvIG5pYmguIE51bGxhIGxhb3JlZXQsIGVyb3MgaWQg +aW1wZXJkaWV0IG1vbGxpcywgbmlzaSBlc3QgZWdlc3RhcyBmZWxpcywgZWdldCBs +dWN0dXMgZW5pbSBsYWN1cyB2aXRhZSBhcmN1LiBOdWxsYW0gaXBzdW0gZGlhbSwg +ZmF1Y2lidXMgZmV1Z2lhdCBjb21tb2RvIGV0LCB0ZW1wb3IgYWMgbGFjdXMuIERv +bmVjIHZlbCBlcmF0IG1hc3NhLCBhdCBwcmV0aXVtIGVzdC4gUGVsbGVudGVzcXVl +IGx1Y3R1cyBuaXNpIG51bGxhLCBhYyBhbGlxdWV0IGF1Z3VlLiBNYWVjZW5hcyBp +ZCBwaGFyZXRyYSBkb2xvci4gUHJvaW4gZGFwaWJ1cyBtYXR0aXMgY3Vyc3VzLiBN +b3JiaSBpbnRlcmR1bSwgZW5pbSBxdWlzIGZlcm1lbnR1bSBwbGFjZXJhdCwgbmlz +aSBtaSBjb25ndWUgc2VtLCBhIHRlbXBvciBuaXNsIG1hdXJpcyBpbiBzZW0uIElu +IGNvbmRpbWVudHVtLCBpcHN1bSBuZWMgdmVuZW5hdGlzIHZlbmVuYXRpcywgbnVs +bGEgZW5pbSBsYW9yZWV0IGFudGUsIG5lYyBoZW5kcmVyaXQgaXBzdW0gbGVjdHVz +IGVnZXQgcmlzdXMuIFBlbGxlbnRlc3F1ZSBlbmltIGxpYmVybywgdGluY2lkdW50 +IHZpdGFlIG1vbGVzdGllIHNpdCBhbWV0LCBncmF2aWRhIG5lYyBsYWN1cy4gRHVp +cyBhYyBzYXBpZW4gbGliZXJvLCBpbiBhbGlxdWV0IHF1YW0uIE1vcmJpIHRlbXBv +ciBsaWJlcm8gcXVpcyBlc3QgZ3JhdmlkYSBzZWQgZWdlc3RhcyBudWxsYSB2dWxw +dXRhdGUuCgpEb25lYyBsYWNpbmlhIG1pIGF0IHRlbGx1cyB2aXZlcnJhIGxvYm9y +dGlzLiBOdWxsYSBpbnRlcmR1bSwgdXJuYSB1dCBmYXVjaWJ1cyBzZW1wZXIsIGR1 +aSBsZWN0dXMgZnJpbmdpbGxhIGVyYXQsIHV0IGFsaXF1YW0gbmlzbCBpcHN1bSBh +dCBlcm9zLiBWaXZhbXVzIGNvbnZhbGxpcyBoZW5kcmVyaXQgYXJjdSBxdWlzIGNv +bmRpbWVudHVtLiBQcmFlc2VudCBhdCBmZXVnaWF0IHNhcGllbi4gUXVpc3F1ZSBu +b24gb3JjaSBhcmN1LiBQZWxsZW50ZXNxdWUgZWdldCBtaSBhcmN1LCBzaXQgYW1l +dCBsdWN0dXMgbnVuYy4gQ3VyYWJpdHVyIGxlY3R1cyBsZW8sIGNvbnNlcXVhdCBz +ZW1wZXIgaW1wZXJkaWV0IGV0LCBlbGVtZW50dW0gdml0YWUgZGlhbS4gUHJvaW4g +cHVydXMgbnVsbGEsIHB1bHZpbmFyIGlkIGltcGVyZGlldCBzZWQsIGZldWdpYXQg +YSBudWxsYS4gUHJvaW4gc3VzY2lwaXQgZWxpdCB2ZWwgYXJjdSB2ZW5lbmF0aXMg +c29kYWxlcy4gQ3JhcyBhY2N1bXNhbiBtYXNzYSBhYyBudWxsYSBwdWx2aW5hciBm +ZXVnaWF0IGV1IGF0IHRlbGx1cy4gUXVpc3F1ZSB2aXRhZSBlcmF0IG9yY2ksIG5v +biB0ZW1wb3IgZW5pbS4gRG9uZWMgb3JuYXJlIGxvYm9ydGlzIG1pIHZpdGFlIGNv +bnNlcXVhdC4gSW50ZWdlciB2aXZlcnJhLCB2ZWxpdCB2ZWwgcGVsbGVudGVzcXVl +IGFjY3Vtc2FuLCBhdWd1ZSBsaWd1bGEgYmxhbmRpdCBuaXNsLCBlZ2V0IGNvbmRp +bWVudHVtIG5lcXVlIGFyY3UgaW4gZXJhdC4gTmFtIHF1aXMgbG9yZW0gbG9yZW0s +IHZlbCBjdXJzdXMgcmlzdXMuIEluIG5lYyBudW5jIGRvbG9yLCBxdWlzIHBvcnR0 +aXRvciBuZXF1ZS4gTWFlY2VuYXMgdHVycGlzIG9kaW8sIGRpY3R1bSB2aXRhZSBj +b21tb2RvIHRpbmNpZHVudCwgYWxpcXVhbSB1dCBhdWd1ZS4gUGhhc2VsbHVzIGF0 +IGp1c3RvIGxhY3VzLiBQaGFzZWxsdXMgc2l0IGFtZXQgdXJuYSBhdCBhbnRlIHZh +cml1cyBwZWxsZW50ZXNxdWUuIFBlbGxlbnRlc3F1ZSBpbiBsaWJlcm8gYWMgdXJu +YSBmcmluZ2lsbGEgdGluY2lkdW50IHZpdGFlIHNlZCB2ZWxpdC4KCkRvbmVjIGFj +IHJpc3VzIHNhcGllbi4gTnVsbGEgZmFjaWxpc2kuIERvbmVjIGF0IHZlbGl0IG5v +biBudW5jIHRlbXB1cyBmZXJtZW50dW0uIEN1bSBzb2NpaXMgbmF0b3F1ZSBwZW5h +dGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJpZW50IG1vbnRlcywgbmFzY2V0dXIg +cmlkaWN1bHVzIG11cy4gRnVzY2UgaW50ZXJkdW0gYWxpcXVhbSBsb3JlbSwgaW4g +c2NlbGVyaXNxdWUgZW5pbSB0aW5jaWR1bnQgaWQuIFByYWVzZW50IHNvbGxpY2l0 +dWRpbiBkdWkgbmVjIGxhY3VzIGxhY2luaWEgcGxhY2VyYXQuIFV0IGVnZXQgbWF0 +dGlzIG1ldHVzLiBJbiB2ZWwgc2VtIHVybmEsIGV1IGNvbnZhbGxpcyB0dXJwaXMu +IER1aXMgaGVuZHJlcml0IGlwc3VtIHVybmEsIG5vbiBwZWxsZW50ZXNxdWUgb3Jj +aS4gVXQgZXN0IG1ldHVzLCBlbGVtZW50dW0gaW4gYmliZW5kdW0gaWQsIHZpdmVy +cmEgZGlnbmlzc2ltIHRlbGx1cy4gRHVpcyBpZCBlcmF0IGxpYmVyby4gVmVzdGli +dWx1bSBpbiBsaWJlcm8gbm9uIHNlbSB0aW5jaWR1bnQgZWxlbWVudHVtIHNlZCBl +dCBuaXNpLiBQaGFzZWxsdXMgbGVjdHVzIGVyYXQsIGVsZWlmZW5kIGlkIHNhZ2l0 +dGlzIHV0LCBmcmluZ2lsbGEgc2VkIHR1cnBpcy4gQWxpcXVhbSB2ZWwgZXJvcyBp +ZCBudW5jIHZlbmVuYXRpcyB1bGxhbWNvcnBlci4gQWxpcXVhbSB0cmlzdGlxdWUg +bWFzc2EgYSBtYXVyaXMgc2NlbGVyaXNxdWUgbm9uIGZhdWNpYnVzIG5lcXVlIHVs +dHJpY2llcy4KCkFsaXF1YW0gY29uc2VxdWF0IGx1Y3R1cyBlbGl0LCBpZCBtYWxl +c3VhZGEgZXJvcyBsb2JvcnRpcyB1dC4gTnVsbGFtIGEgaGVuZHJlcml0IGxpYmVy +by4gTWFlY2VuYXMgZXQgc2VtIGF0IGVyYXQgbWF0dGlzIGVsZWlmZW5kIHNlZCBz +aXQgYW1ldCBzZW0uIE51bGxhIGxvYm9ydGlzIG5pYmggYSBvcmNpIGVsZWlmZW5k +IHRlbXBvci4gUHJvaW4gbnVsbGEgZmVsaXMsIHZlbmVuYXRpcyBxdWlzIHVsdHJp +Y2llcyB2ZWwsIGFsaXF1ZXQgaW4gZG9sb3IuIFBoYXNlbGx1cyB0aW5jaWR1bnQg +ZG9sb3IgZmVybWVudHVtIG1hc3NhIGlhY3VsaXMgZGlnbmlzc2ltIHZlbCB1dCBk +dWkuIFByb2luIHRpbmNpZHVudCBzYWdpdHRpcyBzb2RhbGVzLiBQcm9pbiBtYXR0 +aXMgdmFyaXVzIGVuaW0sIGF0IGx1Y3R1cyBzZW0gaGVuZHJlcml0IGV1LiBVdCB2 +aXRhZSBncmF2aWRhIG9kaW8uIEFsaXF1YW0gZXJhdCB2b2x1dHBhdC4gTnVsbGEg +ZnJpbmdpbGxhIHBsYWNlcmF0IHZlbGl0LCBzZWQgYWxpcXVldCBudWxsYSBpbXBl +cmRpZXQgYS4gRG9uZWMgZWxlaWZlbmQgcHVsdmluYXIgb3JjaSwgaW4gcG9ydGEg +ZGlhbSBwb3N1ZXJlIGJpYmVuZHVtLiBQcm9pbiBlZ2VzdGFzIHBvcnR0aXRvciBh +bGlxdWFtLiBRdWlzcXVlIHNhcGllbiBmZWxpcywgaGVuZHJlcml0IGlkIGNvbmd1 +ZSBldSwgdGluY2lkdW50IHNlZCBlc3QuIFZpdmFtdXMgY3Vyc3VzIHByZXRpdW0g +ZXJhdCB1dCBmYXVjaWJ1cy4gSW50ZWdlciBsaWJlcm8gZWxpdCwgdmVuZW5hdGlz +IHZlbCBhbGlxdWV0IG5lYywgaW50ZXJkdW0gaW4gZW5pbS4gTmFtIGEgdmVsaXQg +anVzdG8sIHZpdGFlIGlhY3VsaXMgdHVycGlzLgoKVml2YW11cyBuaWJoIGxpZ3Vs +YSwgaW50ZXJkdW0gdmVzdGlidWx1bSB2ZW5lbmF0aXMgdml0YWUsIGZlcm1lbnR1 +bSBpbiBtYWduYS4gU3VzcGVuZGlzc2UgZHVpIGFyY3UsIGdyYXZpZGEgYWMgZWdl +c3RhcyBub24sIGNvbmd1ZSBub24gZGlhbS4gUGVsbGVudGVzcXVlIGhhYml0YW50 +IG1vcmJpIHRyaXN0aXF1ZSBzZW5lY3R1cyBldCBuZXR1cyBldCBtYWxlc3VhZGEg +ZmFtZXMgYWMgdHVycGlzIGVnZXN0YXMuIFBlbGxlbnRlc3F1ZSBwdWx2aW5hciBw +aGFyZXRyYSBsb3JlbSwgZXQgcG9zdWVyZSBzZW0gY29uZ3VlIHV0LiBTZWQgZWxl +bWVudHVtIGNvbnZhbGxpcyBkb2xvciBldSB2dWxwdXRhdGUuIEludGVnZXIgbmli +aCBqdXN0bywgcGVsbGVudGVzcXVlIGVnZXQgdWx0cmljaWVzIGF1Y3RvciwgZmVy +bWVudHVtIG5vbiBtaS4gUGVsbGVudGVzcXVlIGF0IG5lcXVlIGVzdC4gQ3VyYWJp +dHVyIHBlbGxlbnRlc3F1ZSBhcmN1IHNlZCBsYWN1cyBwbGFjZXJhdCBxdWlzIGRp +Z25pc3NpbSBvcmNpIHBsYWNlcmF0LiBOdWxsYW0gcGVsbGVudGVzcXVlIGxpYmVy +byBpZCBhbnRlIGRhcGlidXMgc2VkIGJpYmVuZHVtIG1ldHVzIHRyaXN0aXF1ZS4g +Vml2YW11cyBpZCBkdWkgcXVpcyBhcmN1IHVsdHJpY2VzIHZpdmVycmEuIFBlbGxl +bnRlc3F1ZSBhdWN0b3IgbmlzaSBzZWQgZXN0IGxhb3JlZXQgdml2ZXJyYS4gU3Vz +cGVuZGlzc2UgbGFjaW5pYSBsZWN0dXMgbWFzc2EuIEFsaXF1YW0gZXJhdCB2b2x1 +dHBhdC4KClF1aXNxdWUgdWxsYW1jb3JwZXIgYXVndWUgaW4ganVzdG8gdWx0cmlj +aWVzIHBvcnRhLiBTZWQgcXVpcyBhcmN1IGFjIGxvcmVtIGFjY3Vtc2FuIHBvc3Vl +cmUuIE1hdXJpcyBjb25zZXF1YXQsIGxpYmVybyBlZ2V0IGZldWdpYXQgbG9ib3J0 +aXMsIGlwc3VtIGZlbGlzIHZlc3RpYnVsdW0gdGVsbHVzLCB2ZWwgdWx0cmljZXMg +aXBzdW0gYXJjdSBldSBuaXNsLiBDdW0gc29jaWlzIG5hdG9xdWUgcGVuYXRpYnVz +IGV0IG1hZ25pcyBkaXMgcGFydHVyaWVudCBtb250ZXMsIG5hc2NldHVyIHJpZGlj +dWx1cyBtdXMuIEluIGhhYyBoYWJpdGFzc2UgcGxhdGVhIGRpY3R1bXN0LiBEdWlz +IHZpdmVycmEgdHVycGlzIHZlbCBlbGl0IGVsZWlmZW5kIGF0IHBvcnR0aXRvciB2 +ZWxpdCByaG9uY3VzLiBTZWQgYXQgZG9sb3IgcXVpcyBuaXNpIGNvbW1vZG8gcG9y +dHRpdG9yLiBNb3JiaSBsb3JlbSBvcmNpLCBjb21tb2RvIGEgbGFvcmVldCBuZWMs +IHZhcml1cyBhdCBsYWN1cy4gTWF1cmlzIHNlZCB2YXJpdXMgZW5pbS4gQWxpcXVh +bSBncmF2aWRhIGFkaXBpc2Npbmcgc2VtIG5vbiBzZW1wZXIuIFN1c3BlbmRpc3Nl +IGVnZXQgZ3JhdmlkYSBudW5jLgoKQ3JhcyB2ZXN0aWJ1bHVtIHRvcnRvciBuZWMg +bGlndWxhIG9ybmFyZSB0ZW1wb3IuIFV0IGlhY3VsaXMgbGlndWxhIGV0IGxlY3R1 +cyB0aW5jaWR1bnQgaWFjdWxpcy4gTWFlY2VuYXMgcHVsdmluYXIgdm9sdXRwYXQg +bGFjaW5pYS4gQ3VyYWJpdHVyIGhlbmRyZXJpdCBtYWxlc3VhZGEgbGVjdHVzLCBz +ZWQgbWFsZXN1YWRhIGVyb3MgZWdlc3RhcyBlZ2V0LiBBbGlxdWFtIGJpYmVuZHVt +IHZhcml1cyBvZGlvIHZhcml1cyBtYXR0aXMuIFByb2luIGFjIHJob25jdXMgYXJj +dS4gTnVsbGEgc3VzY2lwaXQgdG9ydG9yIGEgZXN0IHZpdmVycmEgdWxsYW1jb3Jw +ZXIuIEN1cmFiaXR1ciBldCBkdWkgZGlhbS4gU2VkIGF0IG5lcXVlIG5pc2wuIEN1 +cmFiaXR1ciBzYWdpdHRpcyBvcmNpIG5pc2wuIEN1bSBzb2NpaXMgbmF0b3F1ZSBw +ZW5hdGlidXMgZXQgbWFnbmlzIGRpcyBwYXJ0dXJpZW50IG1vbnRlcywgbmFzY2V0 +dXIgcmlkaWN1bHVzIG11cy4KCkNyYXMgZmVsaXMgbWV0dXMsIHZhcml1cyBzaXQg +YW1ldCBjb25zZXF1YXQgZWdldCwgc2VtcGVyIHZpdGFlIGxlby4gTWF1cmlzIHV0 +IG5pc2kgbGFjdXMsIGEgcHJldGl1bSBsYWN1cy4gRHVpcyBlZ2V0IGVzdCBuZWMg +ZG9sb3Igc29sbGljaXR1ZGluIGZlcm1lbnR1bS4gTWFlY2VuYXMgb3JuYXJlIGFk +aXBpc2NpbmcgZHVpLCB2aXRhZSBwZWxsZW50ZXNxdWUgbmlzbCBhbGlxdWFtIGEu +IFZpdmFtdXMgYXVjdG9yIGZyaW5naWxsYSBsaWd1bGEsIGlkIHRlbXBvciBqdXN0 +byBjb25ndWUgYS4gUHJhZXNlbnQgcXVpcyBsYW9yZWV0IGF1Z3VlLiBEb25lYyBp +ZCBvcmNpIHV0IG5pc2kgdml2ZXJyYSBjb21tb2RvLiBQZWxsZW50ZXNxdWUgZGlj +dHVtIHZhcml1cyBvcmNpIHZlbCBwaGFyZXRyYS4gTnVuYyBsaWJlcm8gbmlzbCBt +YXNzYSBudW5jLg== + + + + text/plain + + + + + \ No newline at end of file -- cgit v1.2.3 From 68941b57df2caeead67a5bede2ef5a635d07db32 Mon Sep 17 00:00:00 2001 From: mcentner Date: Wed, 11 Nov 2009 15:51:08 +0000 Subject: Added support for SHA-256 and partial support for e-card G3, BELPIC and Italian cards. git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@540 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4 --- .../at/gv/egiz/stal/util/JCEAlgorithmNames.java | 51 ---- .../java/at/gv/egiz/bku/conf/Configurator.java | 71 +++-- .../at/gv/egiz/bku/slcommands/impl/STALHelper.java | 26 +- .../impl/xsect/AlgorithmMethodFactoryImpl.java | 86 ++++-- .../bku/slcommands/impl/xsect/STALProvider.java | 6 +- .../egiz/bku/slcommands/impl/xsect/Signature.java | 23 +- .../slexceptions/SLExceptionMessages.properties | 2 +- .../slexceptions/SLExceptionMessages_en.properties | 2 +- smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java | 55 +++- smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java | 283 ++++++++++++++++++++ smcc/src/main/java/at/gv/egiz/smcc/ITCard.java | 297 +++++++++++++++++++++ .../src/main/java/at/gv/egiz/smcc/STARCOSCard.java | 192 +++++++++---- smcc/src/main/java/at/gv/egiz/smcc/SWCard.java | 8 +- .../main/java/at/gv/egiz/smcc/SignatureCard.java | 11 +- .../java/at/gv/egiz/smcc/SignatureCardFactory.java | 96 +++++-- .../java/at/gv/egiz/smcc/util/ISO7816Utils.java | 11 +- .../at/gv/egiz/smcc/BELPICCard.properties | 3 + .../resources/at/gv/egiz/smcc/ITCard.properties | 3 + smcc/src/test/java/at/gv/egiz/smcc/CardTest.java | 62 ++--- .../java/at/gv/egiz/smcc/acos/ACOSCardTest.java | 62 ++--- .../at/gv/egiz/smcc/starcos/STARCOSCardTest.java | 62 ++--- .../gv/egiz/bku/smccstal/SignRequestHandler.java | 21 +- .../java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java | 5 +- .../gv/egiz/xades/QualifyingPropertiesFactory.java | 15 +- 24 files changed, 1145 insertions(+), 308 deletions(-) delete mode 100644 STAL/src/main/java/at/gv/egiz/stal/util/JCEAlgorithmNames.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java create mode 100644 smcc/src/main/java/at/gv/egiz/smcc/ITCard.java create mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties create mode 100644 smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties (limited to 'bkucommon/src/main/resources') diff --git a/STAL/src/main/java/at/gv/egiz/stal/util/JCEAlgorithmNames.java b/STAL/src/main/java/at/gv/egiz/stal/util/JCEAlgorithmNames.java deleted file mode 100644 index c162eed4..00000000 --- a/STAL/src/main/java/at/gv/egiz/stal/util/JCEAlgorithmNames.java +++ /dev/null @@ -1,51 +0,0 @@ -/* -* Copyright 2008 Federal Chancellery Austria and -* Graz University of Technology -* -* Licensed under the Apache License, Version 2.0 (the "License"); -* you may not use this file except in compliance with the License. -* You may obtain a copy of the License at -* -* http://www.apache.org/licenses/LICENSE-2.0 -* -* Unless required by applicable law or agreed to in writing, software -* distributed under the License is distributed on an "AS IS" BASIS, -* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -* See the License for the specific language governing permissions and -* limitations under the License. -*/ -package at.gv.egiz.stal.util; - -import java.util.HashMap; -import java.util.Map; - -/** - * Maps XML Algorithms to JCE Hash names. - * - */ -public class JCEAlgorithmNames { - - private Map hashNameMap = new HashMap(); - - public static String[] JCE_HASH_NAMES = { "SHA-1" }; - - public static String[] SHA_1_ALGORITMS = { - "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1", - "http://www.w3.org/2000/09/xmldsig#rsa-sha1" }; - - private static JCEAlgorithmNames instance = new JCEAlgorithmNames(); - - private JCEAlgorithmNames() { - for (String alg : SHA_1_ALGORITMS) { - registerHash(alg, JCE_HASH_NAMES[0]); - } - } - - public static String getJCEHashName(String xmlAlgorithmURI) { - return instance.hashNameMap.get(xmlAlgorithmURI); - } - - public void registerHash(String xmlAlgorithmURI, String jceName) { - hashNameMap.put(xmlAlgorithmURI, jceName); - } -} diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java index 41c2512f..50f5d2b4 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/conf/Configurator.java @@ -166,31 +166,62 @@ public abstract class Configurator { protected void configureProviders() { log.debug("Registering security providers"); - Security.insertProviderAt(new IAIK(), 1); - Security.insertProviderAt(new ECCProvider(false), 2); + + IAIK iaikProvider = new IAIK(); + if (Security.getProvider(iaikProvider.getName()) == null) { + // register IAIK provider at first position + Security.insertProviderAt(iaikProvider, 1); + } else { + // IAIK provider already registered + log.info("Provider " + iaikProvider.getName() + " already registered."); + } + + ECCProvider eccProvider = new ECCProvider(false); + if (Security.getProvider(eccProvider.getName()) == null) { + // register ECC Provider at second position + Security.insertProviderAt(eccProvider, 2); + } else { + // ECC Provider already registered + log.info("Provider " + eccProvider.getName() + " already registered."); + } // registering STALProvider as delegation provider for XSECT STALProvider stalProvider = new STALProvider(); - Set services = stalProvider.getServices(); - StringBuilder sb = new StringBuilder(); - for (Service service : services) { - String algorithm = service.getType() + "." + service.getAlgorithm(); - XSecProvider.setDelegationProvider(algorithm, stalProvider.getName()); - sb.append("\n" + algorithm); + if (Security.getProvider(stalProvider.getName()) == null) { + // register STAL provider + Set services = stalProvider.getServices(); + StringBuilder sb = new StringBuilder(); + for (Service service : services) { + String algorithm = service.getType() + "." + service.getAlgorithm(); + XSecProvider.setDelegationProvider(algorithm, stalProvider.getName()); + sb.append("\n" + algorithm); + } + log + .debug("Registered STALProvider as XSecProvider delegation provider for the following services : " + + sb.toString()); + + Security.addProvider(stalProvider); + } else { + // STAL Provider already registered + log.info("Provider " + stalProvider.getName() + " already registered."); } - log - .debug("Registered STALProvider as XSecProvider delegation provider for the following services : " - + sb.toString()); - - Security.addProvider(stalProvider); - XSecProvider.addAsProvider(false); - sb = new StringBuilder(); - sb.append("Registered providers: "); - int i = 1; - for (Provider prov : Security.getProviders()) { - sb.append((i++) + ". : " + prov); + + if (Security.getProvider(XSecProvider.NAME) == null) { + // register XML Security provider + XSecProvider.addAsProvider(false); + } else { + log.info("Provider " + XSecProvider.NAME + " already registered."); + } + + if (log.isDebugEnabled()) { + StringBuilder sb = new StringBuilder(); + sb.append("Registered providers: "); + int i = 1; + for (Provider prov : Security.getProviders()) { + sb.append((i++) + ". : " + prov); + } + log.debug(sb.toString()); } - log.debug(sb.toString()); } protected void configViewer() { diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java index 0c7ce3f5..e903c608 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/STALHelper.java @@ -18,8 +18,15 @@ package at.gv.egiz.bku.slcommands.impl; import iaik.asn1.CodingException; import iaik.asn1.DerCoder; +import iaik.utils.Base64OutputStream; import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.io.StringWriter; import java.security.cert.CertificateException; import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; @@ -174,7 +181,24 @@ public class STALHelper { try { certificates.add((X509Certificate) certFactory.generateCertificate(new ByteArrayInputStream(cert))); } catch (CertificateException e) { - log.info("Failed to decode certificate.", e); + if (log.isDebugEnabled()) { + ByteArrayOutputStream certDump = new ByteArrayOutputStream(); + OutputStreamWriter writer = new OutputStreamWriter(certDump); + try { + writer.write("-----BEGIN CERTIFICATE-----\n"); + writer.flush(); + Base64OutputStream b64os = new Base64OutputStream(certDump); + b64os.write(cert); + b64os.flush(); + writer.write("\n-----END CERTIFICATE-----"); + writer.flush(); + } catch (IOException e1) { + log.info("Failed to decode certificate.", e); + } + log.debug("Failed to decode certificate.\n" + certDump.toString(), e); + } else { + log.info("Failed to decode certificate.", e); + } throw new SLCommandException(4000, SLExceptionMessages.EC4000_UNCLASSIFIED_INFOBOX_INVALID, new Object[] { "Certificates" }); diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java index 6b963465..061fe707 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/AlgorithmMethodFactoryImpl.java @@ -16,18 +16,23 @@ */ package at.gv.egiz.bku.slcommands.impl.xsect; -import iaik.xml.crypto.XmldsigMore; - -import java.security.InvalidAlgorithmParameterException; -import java.security.NoSuchAlgorithmException; -import java.security.cert.X509Certificate; - -import javax.xml.crypto.dsig.CanonicalizationMethod; -import javax.xml.crypto.dsig.DigestMethod; -import javax.xml.crypto.dsig.SignatureMethod; -import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; -import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; -import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; +import iaik.security.ecc.interfaces.ECDSAParams; +import iaik.xml.crypto.XmldsigMore; + +import java.security.InvalidAlgorithmParameterException; +import java.security.NoSuchAlgorithmException; +import java.security.PublicKey; +import java.security.cert.X509Certificate; +import java.security.interfaces.ECPublicKey; +import java.security.interfaces.RSAPublicKey; +import java.security.spec.ECParameterSpec; + +import javax.xml.crypto.dsig.CanonicalizationMethod; +import javax.xml.crypto.dsig.DigestMethod; +import javax.xml.crypto.dsig.SignatureMethod; +import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec; +import javax.xml.crypto.dsig.spec.DigestMethodParameterSpec; +import javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec; /** * An implementation of the AlgorithmMethod factory that uses the signing @@ -40,7 +45,12 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { /** * The signature algorithm URI. */ - private String signatureAlgorithmURI; + private String signatureAlgorithmURI; + + /** + * the digest algorithm URI. + */ + private String digestAlgorithmURI = DigestMethod.SHA1; /** * The algorithm parameters for the signature algorithm. @@ -51,23 +61,55 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { * Creates a new AlgrithmMethodFactory with the given * signingCertificate. * - * @param siginingCertificate + * @param signingCertificate * * @throws NoSuchAlgorithmException * if the public key algorithm of the given * signingCertificate is not supported */ - public AlgorithmMethodFactoryImpl(X509Certificate siginingCertificate) + public AlgorithmMethodFactoryImpl(X509Certificate signingCertificate) throws NoSuchAlgorithmException { - - String algorithm = siginingCertificate.getPublicKey().getAlgorithm(); + + PublicKey publicKey = signingCertificate.getPublicKey(); + String algorithm = publicKey.getAlgorithm(); if ("DSA".equals(algorithm)) { signatureAlgorithmURI = SignatureMethod.DSA_SHA1; - } else if ("RSA".equals(algorithm)) { - signatureAlgorithmURI = SignatureMethod.RSA_SHA1; - } else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) { - signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA1; + } else if ("RSA".equals(algorithm)) { + + int keyLength = 0; + if (publicKey instanceof RSAPublicKey) { + keyLength = ((RSAPublicKey) publicKey).getModulus().bitLength(); + } + + if (keyLength >= 2048) { + signatureAlgorithmURI = XmldsigMore.SIGNATURE_RSA_SHA256; + digestAlgorithmURI = DigestMethod.SHA256; + } else { + signatureAlgorithmURI = SignatureMethod.RSA_SHA1; + } + + } else if (("EC".equals(algorithm)) || ("ECDSA".equals(algorithm))) { + + int fieldSize = 0; + if (publicKey instanceof iaik.security.ecc.ecdsa.ECPublicKey) { + ECDSAParams params = ((iaik.security.ecc.ecdsa.ECPublicKey) publicKey).getParameter(); + fieldSize = params.getG().getCurve().getField().getSize().bitLength(); + } else if (publicKey instanceof ECPublicKey) { + ECParameterSpec params = ((ECPublicKey) publicKey).getParams(); + fieldSize = params.getCurve().getField().getFieldSize(); + } + + if (fieldSize < 256) { + signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA1; + } else if (fieldSize < 512) { + signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA256; + digestAlgorithmURI = DigestMethod.SHA256; + } else { + signatureAlgorithmURI = XmldsigMore.SIGNATURE_ECDSA_SHA512; + digestAlgorithmURI = DigestMethod.SHA512; + } + } else { throw new NoSuchAlgorithmException("Public key algorithm '" + algorithm + "' not supported."); @@ -104,7 +146,7 @@ public class AlgorithmMethodFactoryImpl implements AlgorithmMethodFactory { throws NoSuchAlgorithmException, InvalidAlgorithmParameterException { return signatureContext.getSignatureFactory().newDigestMethod( - DigestMethod.SHA1, (DigestMethodParameterSpec) null); + digestAlgorithmURI, (DigestMethodParameterSpec) null); } /* diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALProvider.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALProvider.java index 0ab30530..42c6a4c5 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALProvider.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/STALProvider.java @@ -49,7 +49,11 @@ public class STALProvider extends Provider { map.put("Signature." + SignatureMethod.RSA_SHA1, IMPL_PACKAGE_NAME + ".STALSignature"); map.put("Signature." + XmldsigMore.SIGNATURE_ECDSA_SHA1, - IMPL_PACKAGE_NAME + ".STALSignature"); + IMPL_PACKAGE_NAME + ".STALSignature"); + map.put("Signature." + XmldsigMore.SIGNATURE_RSA_SHA256, + IMPL_PACKAGE_NAME + ".STALSignature"); + map.put("Signature." + XmldsigMore.SIGNATURE_ECDSA_SHA256, + IMPL_PACKAGE_NAME + ".STALSignature"); AccessController.doPrivileged(new PrivilegedAction() { @Override diff --git a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java index 26ddb153..3cebb6a3 100644 --- a/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java +++ b/bkucommon/src/main/java/at/gv/egiz/bku/slcommands/impl/xsect/Signature.java @@ -628,9 +628,20 @@ public class Signature { String target = "#" + signatureId; + DigestMethod dm; + try { + dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get DigestMethod algorithm.", e); + throw new SLCommandException(4006); + } catch (InvalidAlgorithmParameterException e) { + log.error("Failed to get DigestMethod algorithm.", e); + throw new SLCommandException(4006); + } + JAXBElement qualifyingProperties; try { - qualifyingProperties = factory.createQualifyingProperties111(target, date, signingCertificates, idValue, dataObjectFormats); + qualifyingProperties = factory.createQualifyingProperties111(target, date, signingCertificates, idValue, dataObjectFormats, dm); } catch (QualifyingPropertiesException e) { log.error("Failed to create QualifyingProperties.", e); throw new SLCommandException(4000); @@ -665,7 +676,10 @@ public class Signature { String referenceURI = "#xmlns(xades=http://uri.etsi.org/01903/v1.1.1%23)%20xpointer(id('" + objectIdValue + "')/child::xades:QualifyingProperties/child::xades:SignedProperties)"; - DigestMethod dm; + + String referenceIdValue = ctx.getIdValueFactory().createIdValue("Reference"); + String referenceType = QualifyingPropertiesFactory.SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1; + try { dm = ctx.getAlgorithmMethodFactory().createDigestMethod(ctx); } catch (NoSuchAlgorithmException e) { @@ -675,10 +689,7 @@ public class Signature { log.error("Failed to get DigestMethod algorithm.", e); throw new SLCommandException(4006); } - - String referenceIdValue = ctx.getIdValueFactory().createIdValue("Reference"); - String referenceType = QualifyingPropertiesFactory.SIGNED_PROPERTIES_REFERENCE_TYPE_V1_1_1; - + Reference reference = ctx.getSignatureFactory().newReference(referenceURI, dm, null, referenceType, referenceIdValue); references.add(reference); diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties index db56184e..c5bfce18 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages.properties @@ -91,7 +91,7 @@ ec3002.invalid=XML-Struktur der Befehlsanfrage entspricht nicht dem Schema des S # 4xxx # -ec4000.infobox.invalid=Die Infobox '{0}' enthält ungültige Daten. +ec4000.infobox.invalid=Die Infobox {0} enthält ungültige Daten. ec4000.idlink.transfomation.failed=Die komprimierte Personenbindung konnte mit dem Stylesheet {0} nicht transformiert werden. ec4002.infobox.unknown=Unbekannter Infoboxbezeichner {0}. ec4003.not.resolved=Zu signierendes Datum kann nicht aufgelöst werden (URI={0}). diff --git a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties index 6c67ba87..a8bffdc6 100644 --- a/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties +++ b/bkucommon/src/main/resources/at/gv/egiz/bku/slexceptions/SLExceptionMessages_en.properties @@ -91,7 +91,7 @@ ec3002.invalid=XML structure of the command request does not comply with the Sec # 4xxx # -ec4000.infobox.invalid=The infobox '{0}' contains invalid content. +ec4000.infobox.invalid=The infobox {0} contains invalid content. ec4000.idlink.transfomation.failed=Failed to transform CompressedIdentityLink with Stylesheet {0}. ec4002.infobox.unknown=Unknown info box identifier {0}. ec4003.not.resolved=Data to be signed cannot be resolved from URI={0}. diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java index 414d4678..a63d4076 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/ACOSCard.java @@ -16,9 +16,13 @@ */ package at.gv.egiz.smcc; +import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; import java.security.AlgorithmParameters; import java.security.GeneralSecurityException; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.List; @@ -375,12 +379,46 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC @Override @Exclusive - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, - PINProvider provider) throws SignatureCardException, InterruptedException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { - if (hash.length != 20) { - throw new IllegalArgumentException("Hash value must be of length 20."); + ByteArrayOutputStream dst = new ByteArrayOutputStream(); + // key ID + dst.write(new byte[]{(byte) 0x84, (byte) 0x01, (byte) 0x88}); + // algorithm ID + dst.write(new byte[]{(byte) 0x80, (byte) 0x01}); + + MessageDigest md; + try { + if ("http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1".equals(alg)) { + dst.write((byte) 0x14); // SHA-1/ECC + md = MessageDigest.getInstance("SHA-1"); + } else if ("http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { + dst.write((byte) 0x12); // SHA-1 with padding according to PKCS#1 block type 01 + md = MessageDigest.getInstance("SHA-1"); + } else if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName) + && appVersion >= 2 + && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256".equals(alg)) { + dst.write((byte) 0x44); // SHA-256/ECC + md = MessageDigest.getInstance("SHA256"); + } else if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName) + && appVersion >= 2 + && "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256".equals(alg)) { + dst.write((byte) 0x41); // SHA-256 with padding according to PKCS#1 + md = MessageDigest.getInstance("SHA256"); + } else { + throw new SignatureCardException("Card does not support signature algorithm " + alg + "."); + } + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get MessageDigest.", e); + throw new SignatureCardException(e); } + + byte[] digest = new byte[md.getDigestLength()]; + for (int l; (l = input.read(digest)) != -1;) { + md.update(digest, 0, l); + } + digest = md.digest(); try { @@ -393,11 +431,11 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC // SELECT application execSELECT_AID(channel, AID_SIG); // MANAGE SECURITY ENVIRONMENT : SET DST - execMSE(channel, 0x41, 0xb6, DST_SIG); + execMSE(channel, 0x41, 0xb6, dst.toByteArray()); // VERIFY verifyPINLoop(channel, spec, provider); // PERFORM SECURITY OPERATION : HASH - execPSO_HASH(channel, hash); + execPSO_HASH(channel, digest); // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATRE return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); @@ -413,7 +451,7 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC while (true) { try { // INTERNAL AUTHENTICATE - return execINTERNAL_AUTHENTICATE(channel, hash); + return execINTERNAL_AUTHENTICATE(channel, digest); } catch (SecurityStatusNotSatisfiedException e) { verifyPINLoop(channel, spec, provider); } @@ -711,6 +749,9 @@ public class ACOSCard extends AbstractSignatureCard implements PINMgmtSignatureC ResponseAPDU resp = channel.transmit( new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); + if (resp.getSW() == 0x6982) { + throw new SecurityStatusNotSatisfiedException(); + } if (resp.getSW() != 0x9000) { throw new SignatureCardException( "PSO - COMPUTE DIGITAL SIGNATRE failed: SW=" diff --git a/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java new file mode 100644 index 00000000..15b47fb0 --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/BELPICCard.java @@ -0,0 +1,283 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + + +package at.gv.egiz.smcc; + +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.util.ISO7816Utils; +import at.gv.egiz.smcc.util.SMCCHelper; + +public class BELPICCard extends AbstractSignatureCard implements SignatureCard { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(BELPICCard.class); + + public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; + + public static final byte[] DF_BELPIC = new byte[] { (byte) 0xDF, + (byte) 0x00 }; + + public static final byte[] DF_ID = new byte[] { (byte) 0xDF, (byte) 0x01 }; + + public static final byte[] SIGN_CERT = new byte[] { (byte) 0x50, + (byte) 0x39 }; + +// public static final byte MSE_SET_ALGO_REF = (byte) 0x02; + +// public static final byte MSE_SET_PRIV_KEY_REF = (byte) 0x83; + + public static final int SIGNATURE_LENGTH = (int) 0x80; + + public static final byte KID = (byte) 0x01; + + public static final int READ_BUFFER_LENGTH = 256; + + public static final int PINSPEC_SS = 0; + + private static final PINSpec SS_PIN_SPEC = + new PINSpec(4, 12, "[0-9]", + "at/gv/egiz/smcc/BelpicCard", "sig.pin", KID, DF_BELPIC); + + /** + * Creates a new instance. + */ + public BELPICCard() { + super("at/gv/egiz/smcc/BelpicCard"); + pinSpecs.add(SS_PIN_SPEC); + } + + @Override + @Exclusive + public byte[] getCertificate(KeyboxName keyboxName) + throws SignatureCardException { + + if (keyboxName != KeyboxName.SECURE_SIGNATURE_KEYPAIR) { + throw new IllegalArgumentException("Keybox " + keyboxName + + " not supported"); + } + + try { + CardChannel channel = getCardChannel(); + // SELECT MF + execSELECT_FID(channel, MF); + // SELECT application + execSELECT_FID(channel, DF_BELPIC); + // SELECT file + execSELECT_FID(channel, SIGN_CERT); + // READ BINARY + byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, -1, (byte) 0x30); + if (certificate == null) { + throw new NotActivatedException(); + } + return certificate; + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } catch (CardException e) { + log.info("Failed to get certificate.", e); + throw new SignatureCardException(e); + } + + } + + @Override + @Exclusive + public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + throws SignatureCardException, InterruptedException { + + throw new IllegalArgumentException("Infobox '" + infobox + + "' not supported."); + } + + @Override + @Exclusive + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { + + if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { + throw new SignatureCardException("Card does not support key " + keyboxName + "."); + } + if (!"http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { + throw new SignatureCardException("Card does not support algorithm " + alg + "."); + } + + byte[] dst = new byte[] { (byte) 0x04, // number of following + // bytes + (byte) 0x80, // tag for algorithm reference + (byte) 0x02, // algorithm reference + (byte) 0x84, // tag for private key reference + (byte) 0x83 // private key reference + }; + + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get MessageDigest.", e); + throw new SignatureCardException(e); + } + // calculate message digest + byte[] digest = new byte[md.getDigestLength()]; + for (int l; (l = input.read(digest)) != -1;) { + md.update(digest, 0, l); + } + digest = md.digest(); + + try { + + CardChannel channel = getCardChannel(); + + // SELECT MF + execSELECT_FID(channel, MF); + // VERIFY + execMSE(channel, 0x41, 0xb6, dst); + // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE + verifyPINLoop(channel, SS_PIN_SPEC, provider); + // MANAGE SECURITY ENVIRONMENT : SET DST + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); + + } catch (CardException e) { + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); + } + + } + + public String toString() { + return "Belpic Card"; + } + + protected void verifyPINLoop(CardChannel channel, PINSpec spec, + PINProvider provider) throws LockedException, NotActivatedException, + SignatureCardException, InterruptedException, CardException { + + int retries = -1; //verifyPIN(channel, spec, null, -1); + do { + retries = verifyPIN(channel, spec, provider, retries); + } while (retries > 0); + } + + protected int verifyPIN(CardChannel channel, PINSpec pinSpec, + PINProvider provider, int retries) throws SignatureCardException, + LockedException, NotActivatedException, InterruptedException, + CardException { + + VerifyAPDUSpec apduSpec = new VerifyAPDUSpec( + new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID(), (byte) 0x08, + (byte) 0x20, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }, + 1, VerifyAPDUSpec.PIN_FORMAT_BCD, 7, 4, 4); + + ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); + + if (resp.getSW() == 0x9000) { + return -1; + } + if (resp.getSW() >> 4 == 0x63c) { + return 0x0f & resp.getSW(); + } + + switch (resp.getSW()) { + case 0x6983: + // authentication method blocked + throw new LockedException(); + case 0x6984: + // reference data not usable + throw new NotActivatedException(); + case 0x6985: + // conditions of use not satisfied + throw new NotActivatedException(); + + default: + String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW()); + log.info(msg); + throw new SignatureCardException(msg); + } + + } + + protected byte[] execSELECT_FID(CardChannel channel, byte[] fid) + throws SignatureCardException, CardException { + + ResponseAPDU resp = channel.transmit( + new CommandAPDU(0x00, 0xA4, 0x02, 0x0C, fid, 256)); + + if (resp.getSW() == 0x6A82) { + String msg = "File or application not found FID=" + + SMCCHelper.toString(fid) + " SW=" + + Integer.toHexString(resp.getSW()) + "."; + log.info(msg); + throw new FileNotFoundException(msg); + } else if (resp.getSW() != 0x9000) { + String msg = "Failed to select application FID=" + + SMCCHelper.toString(fid) + " SW=" + + Integer.toHexString(resp.getSW()) + "."; + log.error(msg); + throw new SignatureCardException(msg); + } else { + return resp.getBytes(); + } + + } + + protected void execMSE(CardChannel channel, int p1, int p2, byte[] data) + throws CardException, SignatureCardException { + ResponseAPDU resp = channel.transmit( + new CommandAPDU(0x00, 0x22, p1, p2, data, 256)); + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("MSE:SET failed: SW=" + + Integer.toHexString(resp.getSW())); + } + } + + protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, byte[] hash) + throws CardException, SignatureCardException { + ResponseAPDU resp; + resp = channel.transmit( + new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, hash, 256)); + if (resp.getSW() == 0x6982) { + throw new SecurityStatusNotSatisfiedException(); + } else if (resp.getSW() == 0x6983) { + throw new LockedException(); + } else if (resp.getSW() != 0x9000) { + throw new SignatureCardException( + "PSO: COMPUTE DIGITAL SIGNATRE failed: SW=" + + Integer.toHexString(resp.getSW())); + } else { + return resp.getData(); + } + } + + + + +} \ No newline at end of file diff --git a/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java new file mode 100644 index 00000000..831a1f9b --- /dev/null +++ b/smcc/src/main/java/at/gv/egiz/smcc/ITCard.java @@ -0,0 +1,297 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ + +package at.gv.egiz.smcc; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; + +import javax.smartcardio.CardChannel; +import javax.smartcardio.CardException; +import javax.smartcardio.CommandAPDU; +import javax.smartcardio.ResponseAPDU; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; + +import at.gv.egiz.smcc.util.ISO7816Utils; +import at.gv.egiz.smcc.util.SMCCHelper; + +public class ITCard extends AbstractSignatureCard { + + /** + * Logging facility. + */ + private static Log log = LogFactory.getLog(STARCOSCard.class); + + public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; + + public static final byte[] DF1 = new byte[] { (byte) 0x11, (byte) 0x00 }; + + public static final byte[] EF_C_Carta = new byte[] { (byte) 0x11, (byte) 0x01 }; + + private static final PINSpec SS_PIN_SPEC = + new PINSpec(5, 8, "[0-9]", + "at/gv/egiz/smcc/ITCard", "sig.pin", (byte) 0x10, + new byte[] { (byte) 0x11, (byte) 0x00 }); + + /** + * Creates a new instance. + */ + public ITCard() { + super("at/gv/egiz/smcc/ITCard"); + pinSpecs.add(SS_PIN_SPEC); + } + + @Override + @Exclusive + public byte[] getCertificate(KeyboxName keyboxName) + throws SignatureCardException, InterruptedException { + + if (keyboxName != KeyboxName.SECURE_SIGNATURE_KEYPAIR) { + throw new IllegalArgumentException("Keybox " + keyboxName + + " not supported"); + } + + try { + CardChannel channel = getCardChannel(); + // SELECT MF + execSELECT_FID(channel, MF); + // SELECT application + execSELECT_FID(channel, DF1); + // SELECT EF_C_Carta + byte[] fcx = execSELECT_FID(channel, EF_C_Carta); + int maxsize = ISO7816Utils.getLengthFromFCx(fcx); + // READ BINARY + byte[] certificate = ISO7816Utils.readTransparentFileTLV(channel, maxsize, (byte) 0x30); + if (certificate == null) { + throw new NotActivatedException(); + } + return certificate; + } catch (FileNotFoundException e) { + throw new NotActivatedException(); + } catch (CardException e) { + log.info("Failed to get certificate.", e); + throw new SignatureCardException(e); + } + + } + + @Override + @Exclusive + public byte[] getInfobox(String infobox, PINProvider provider, String domainId) + throws SignatureCardException, InterruptedException { + + throw new IllegalArgumentException("Infobox '" + infobox + + "' not supported."); + } + + @Override + @Exclusive + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, + InterruptedException, IOException { + + if (KeyboxName.SECURE_SIGNATURE_KEYPAIR != keyboxName) { + throw new SignatureCardException("Card does not support key " + keyboxName + "."); + } + if (!"http://www.w3.org/2000/09/xmldsig#rsa-sha1".equals(alg)) { + throw new SignatureCardException("Card does not support algorithm " + alg + "."); + } + + byte[] dst = new byte[] { + (byte) 0x83, // tag for algorithm reference + (byte) 0x01, // algorithm reference + (byte) 0x01 // private key reference + }; + + MessageDigest md; + try { + md = MessageDigest.getInstance("SHA-1"); + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get MessageDigest.", e); + throw new SignatureCardException(e); + } + // calculate message digest + byte[] digest = new byte[md.getDigestLength()]; + for (int l; (l = input.read(digest)) != -1;) { + md.update(digest, 0, l); + } + digest = md.digest(); + + try { + + CardChannel channel = getCardChannel(); + + // SELECT MF + execSELECT_FID(channel, MF); + // VERIFY + verifyPINLoop(channel, SS_PIN_SPEC, provider); + // MANAGE SECURITY ENVIRONMENT : RESTORE SE + execMSE(channel, 0xF3, 0x03, null); + // MANAGE SECURITY ENVIRONMENT : SET DST + execMSE(channel, 0xF1, 0xB8, dst); + // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); + + } catch (CardException e) { + log.warn(e); + throw new SignatureCardException("Failed to access card.", e); + } + + } + + protected void verifyPINLoop(CardChannel channel, PINSpec spec, + PINProvider provider) throws LockedException, NotActivatedException, + SignatureCardException, InterruptedException, CardException { + + int retries = -1; + do { + retries = verifyPIN(channel, spec, provider, retries); + } while (retries >= -1); + } + + protected int verifyPIN(CardChannel channel, PINSpec pinSpec, + PINProvider provider, int retries) throws SignatureCardException, + LockedException, NotActivatedException, InterruptedException, + CardException { + + VerifyAPDUSpec apduSpec = new VerifyAPDUSpec( + new byte[] { + (byte) 0x00, (byte) 0x20, (byte) 0x00, pinSpec.getKID(), (byte) 0x08, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff }, + 0, VerifyAPDUSpec.PIN_FORMAT_ASCII, 8); + + ResponseAPDU resp = reader.verify(channel, apduSpec, pinSpec, provider, retries); + + if (resp.getSW() == 0x9000) { + return -2; + } + if (resp.getSW() >> 4 == 0x63c) { + return 0x0f & resp.getSW(); + } + + switch (resp.getSW()) { + case 0x6300: + // incorrect PIN, number of retries not provided + return -1; + case 0x6983: + // authentication method blocked + throw new LockedException(); + case 0x6984: + // reference data not usable + throw new NotActivatedException(); + case 0x6985: + // conditions of use not satisfied + throw new NotActivatedException(); + + default: + String msg = "VERIFY failed. SW=" + Integer.toHexString(resp.getSW()); + log.info(msg); + throw new SignatureCardException(msg); + } + + } + + protected byte[] execSELECT_FID(CardChannel channel, byte[] fid) + throws SignatureCardException, CardException { + + ResponseAPDU resp = channel.transmit( + new CommandAPDU(0x00, 0xA4, 0x00, 0x00, fid, 256)); + + if (resp.getSW() == 0x6A82) { + String msg = "File or application not found FID=" + + SMCCHelper.toString(fid) + " SW=" + + Integer.toHexString(resp.getSW()) + "."; + log.info(msg); + throw new FileNotFoundException(msg); + } else if (resp.getSW() != 0x9000) { + String msg = "Failed to select application FID=" + + SMCCHelper.toString(fid) + " SW=" + + Integer.toHexString(resp.getSW()) + "."; + log.error(msg); + throw new SignatureCardException(msg); + } else { + return resp.getBytes(); + } + + } + + protected void execMSE(CardChannel channel, int p1, int p2, byte[] data) + throws CardException, SignatureCardException { + + ResponseAPDU resp; + if (data == null) { + resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2)); + } else { + resp = channel.transmit(new CommandAPDU(0x00, 0x22, p1, p2, data)); + } + + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("MSE:SET failed: SW=" + + Integer.toHexString(resp.getSW())); + } + } + + protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, + byte[] hash) throws CardException, SignatureCardException { + + byte[] oid = new byte[] { (byte) 0x30, (byte) 0x21, (byte) 0x30, + (byte) 0x09, (byte) 0x06, (byte) 0x05, (byte) 0x2b, + (byte) 0x0e, (byte) 0x03, (byte) 0x02, (byte) 0x1a, + (byte) 0x05, (byte) 0x00, (byte) 0x04, (byte) 0x14 }; + + ByteArrayOutputStream data = new ByteArrayOutputStream(); + + try { + // header + data.write(new byte[] { (byte) 0x00, (byte) 0x00, (byte) 0x01 }); + // padding + for (int i = 0, len = 125 - hash.length - oid.length; i < len; i++) { + data.write((byte) 0xFF); + } + data.write((byte) 0x00); + // oid + data.write(oid); + // hash + data.write(hash); + } catch (IOException e) { + throw new SignatureCardException(e); + } + + ResponseAPDU resp = channel + .transmit(new CommandAPDU(0x00, 0x2A, 0x80, 0x86, data.toByteArray(), 0x81)); + + + if (resp.getSW() == 0x6982) { + throw new SecurityStatusNotSatisfiedException(); + } else if (resp.getSW() == 0x6983) { + throw new LockedException(); + } else if (resp.getSW() != 0x9000) { + throw new SignatureCardException( + "PSO: COMPUTE DIGITAL SIGNATRE failed: SW=" + + Integer.toHexString(resp.getSW())); + } else { + return resp.getData(); + } +} + +} diff --git a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java index a0c2391d..01de8a77 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/STARCOSCard.java @@ -19,11 +19,16 @@ package at.gv.egiz.smcc; import java.io.ByteArrayOutputStream; import java.io.IOException; +import java.io.InputStream; +import java.security.MessageDigest; +import java.security.NoSuchAlgorithmException; import java.util.Arrays; import java.util.List; +import javax.smartcardio.Card; import javax.smartcardio.CardChannel; import javax.smartcardio.CardException; +import javax.smartcardio.CardTerminal; import javax.smartcardio.CommandAPDU; import javax.smartcardio.ResponseAPDU; @@ -41,6 +46,8 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu private static Log log = LogFactory.getLog(STARCOSCard.class); public static final byte[] MF = new byte[] { (byte) 0x3F, (byte) 0x00 }; + + public static final byte[] EF_VERSION = new byte[] { (byte) 0x00, (byte) 0x32 }; /** * Application ID SV-Personendaten. @@ -106,19 +113,6 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu public static final byte[] EF_C_X509_CA_CS_DS = new byte[] { (byte) 0xc6, (byte) 0x08 }; - public static final byte[] DST_SS = new byte[] { (byte) 0x84, (byte) 0x03, // tag - // , - // length - // ( - // key - // desc - // . - // ) - (byte) 0x80, (byte) 0x02, (byte) 0x00, // local, key ID, key version - (byte) 0x89, (byte) 0x03, // tag, length (algorithm ID) - (byte) 0x13, (byte) 0x35, (byte) 0x10 // ECDSA - }; - public static final byte KID_PIN_SS = (byte) 0x81; // Gewöhnliche Signatur (GS) @@ -133,19 +127,6 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu public static final byte[] EF_C_X509_CA_CS = new byte[] { (byte) 0x2f, (byte) 0x02 }; - public static final byte[] DST_GS = new byte[] { (byte) 0x84, (byte) 0x03, // tag - // , - // length - // ( - // key - // desc - // . - // ) - (byte) 0x80, (byte) 0x02, (byte) 0x00, // local, key ID, key version - (byte) 0x89, (byte) 0x03, // tag, length (algorithm ID) - (byte) 0x13, (byte) 0x35, (byte) 0x10 // ECDSA - }; - public static final byte KID_PIN_CARD = (byte) 0x01; private static final PINSpec CARD_PIN_SPEC = @@ -155,9 +136,11 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu private static final PINSpec SS_PIN_SPEC = new PINSpec(6, 12, "[0-9]", "at/gv/egiz/smcc/STARCOSCard", "sig.pin", KID_PIN_SS, AID_DF_SS); + + protected double version = 1.1; /** - * Creates an new instance. + * Creates a new instance. */ public STARCOSCard() { super("at/gv/egiz/smcc/STARCOSCard"); @@ -165,6 +148,35 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu pinSpecs.add(SS_PIN_SPEC); } + /* (non-Javadoc) + * @see at.gv.egiz.smcc.AbstractSignatureCard#init(javax.smartcardio.Card, javax.smartcardio.CardTerminal) + */ + @Override + public void init(Card card, CardTerminal cardTerminal) { + super.init(card, cardTerminal); + + // determine application version + CardChannel channel = getCardChannel(); + try { + // SELECT MF + execSELECT_MF(channel); + // SELECT EF_VERSION + execSELECT_FID(channel, EF_VERSION); + // READ BINARY + byte[] ver = ISO7816Utils.readRecord(channel, 1); + if (ver[0] == (byte) 0xa5 && ver[2] == (byte) 0x53) { + version = (0x0F & ver[4]) + (0xF0 & ver[5])/160.0 + (0x0F & ver[5])/100.0; + String generation = (version < 1.2) ? "<= G2" : "G3"; + log.info("e-card version=" + version + " (" + generation + ")"); + } + } catch (CardException e) { + log.warn(e); + } catch (SignatureCardException e) { + log.warn(e); + } + + } + @Override @Exclusive public byte[] getCertificate(KeyboxName keyboxName) @@ -281,19 +293,57 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu @Override @Exclusive - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, - PINProvider provider) throws SignatureCardException, InterruptedException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { - if (hash.length != 20) { - throw new IllegalArgumentException("Hash value must be of length 20."); + ByteArrayOutputStream dst = new ByteArrayOutputStream(); + byte[] ht = null; + + MessageDigest md = null; + try { + if (version < 1.2 && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha1".equals(alg)) { + // local key ID '02' version '00' + dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00}); + // algorithm ID ECDSA with SHA-1 + dst.write(new byte[] {(byte) 0x89, (byte) 0x03, (byte) 0x13, (byte) 0x35, (byte) 0x10}); + md = MessageDigest.getInstance("SHA-1"); + } else if (version >= 1.2 && "http://www.w3.org/2001/04/xmldsig-more#ecdsa-sha256".equals(alg)) { + // local key ID '02' version '00' + dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x02, (byte) 0x00}); + // portable algorithm reference + dst.write(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x04}); + // hash template + ht = new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x40}; + md = MessageDigest.getInstance("SHA256"); + } else if (version >= 1.2 && "http://www.w3.org/2001/04/xmldsig-more#rsa-sha256".equals(alg)) { + // local key ID '03' version '00' + dst.write(new byte[] {(byte) 0x84, (byte) 0x03, (byte) 0x80, (byte) 0x03, (byte) 0x00}); + // portable algorithm reference + dst.write(new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x02}); + // hash template + ht = new byte[] {(byte) 0x80, (byte) 0x01, (byte) 0x40}; + md = MessageDigest.getInstance("SHA256"); + } else { + throw new SignatureCardException("e-card versio " + version + " does not support signature algorithm " + alg + "."); + } + } catch (NoSuchAlgorithmException e) { + log.error("Failed to get MessageDigest.", e); + throw new SignatureCardException(e); } - + + // calculate message digest + byte[] digest = new byte[md.getDigestLength()]; + for (int l; (l = input.read(digest)) != -1;) { + md.update(digest, 0, l); + } + digest = md.digest(); + try { CardChannel channel = getCardChannel(); if (KeyboxName.SECURE_SIGNATURE_KEYPAIR.equals(keyboxName)) { - + PINSpec spec = SS_PIN_SPEC; // SELECT MF @@ -303,11 +353,21 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu // VERIFY verifyPINLoop(channel, spec, provider); // MANAGE SECURITY ENVIRONMENT : SET DST - execMSE(channel, 0x41, 0xb6, DST_SS); - // PERFORM SECURITY OPERATION : HASH - execPSO_HASH(channel, hash); - // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE - return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); + execMSE(channel, 0x41, 0xb6, dst.toByteArray()); + if (ht != null) { + // PERFORM SECURITY OPERATION : SET HT + execMSE(channel, 0x41, 0xaa, ht); + } + if (version < 1.2) { + // PERFORM SECURITY OPERATION : HASH + execPSO_HASH(channel, digest); + // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, null); + } else { + // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, digest); + } + } else if (KeyboxName.CERITIFIED_KEYPAIR.equals(keyboxName)) { @@ -316,14 +376,17 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu // SELECT application execSELECT_AID(channel, AID_DF_GS); // MANAGE SECURITY ENVIRONMENT : SET DST - execMSE(channel, 0x41, 0xb6, DST_GS); + execMSE(channel, 0x41, 0xb6, dst.toByteArray()); + if (ht != null) { + // PERFORM SECURITY OPERATION : SET HT + execMSE(channel, 0x41, 0xaa, ht); + } // PERFORM SECURITY OPERATION : HASH - execPSO_HASH(channel, hash); - + execPSO_HASH(channel, digest); while (true) { try { // PERFORM SECURITY OPERATION : COMPUTE DIGITAL SIGNATURE - return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel); + return execPSO_COMPUTE_DIGITAL_SIGNATURE(channel, null); } catch (SecurityStatusNotSatisfiedException e) { verifyPINLoop(channel, spec, provider); } @@ -682,7 +745,7 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu ResponseAPDU resp = channel.transmit( new CommandAPDU(0x00, 0x22, p1, p2, data)); if (resp.getSW() != 0x9000) { - throw new SignatureCardException("MSE:SET DST failed: SW=" + throw new SignatureCardException("MSE:SET failed: SW=" + Integer.toHexString(resp.getSW())); } } @@ -701,10 +764,47 @@ public class STARCOSCard extends AbstractSignatureCard implements PINMgmtSignatu } } - protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel) + protected void execPSO_HASH(CardChannel channel, InputStream input) + throws SignatureCardException, CardException { + ResponseAPDU resp; + int blockSize = 64; + byte[] b = new byte[blockSize]; + try { + ByteArrayOutputStream data = new ByteArrayOutputStream(); + // initialize + data.write((byte) 0x90); + data.write((byte) 0x00); + resp = channel.transmit( + new CommandAPDU(0x10, 0x2A, 0x90, 0xA0, data.toByteArray())); + data.reset(); + for (int l; (l = input.read(b)) != -1;) { + data.write((byte) 0x80); + data.write(l); + data.write(b, 0, l); + resp = channel.transmit( + new CommandAPDU((l == blockSize) ? 0x10 : 0x00, 0x2A, 0x90, 0xA0, data.toByteArray())); + if (resp.getSW() != 0x9000) { + throw new SignatureCardException("PSO:HASH failed: SW=" + + Integer.toHexString(resp.getSW())); + } + data.reset(); + } + } catch (IOException e) { + throw new SignatureCardException(e); + } + + } + + protected byte[] execPSO_COMPUTE_DIGITAL_SIGNATURE(CardChannel channel, byte[] hash) throws CardException, SignatureCardException { - ResponseAPDU resp = channel.transmit( - new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); + ResponseAPDU resp; + if (hash != null) { + resp = channel.transmit( + new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, hash, 256)); + } else { + resp = channel.transmit( + new CommandAPDU(0x00, 0x2A, 0x9E, 0x9A, 256)); + } if (resp.getSW() == 0x6982) { throw new SecurityStatusNotSatisfiedException(); } else if (resp.getSW() == 0x6983) { diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java index 279362c0..670704d5 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SWCard.java @@ -20,6 +20,7 @@ import java.io.ByteArrayOutputStream; import java.io.FileInputStream; import java.io.FileNotFoundException; import java.io.IOException; +import java.io.InputStream; import java.io.InputStreamReader; import java.nio.charset.Charset; import java.security.InvalidKeyException; @@ -308,7 +309,7 @@ public class SWCard implements SignatureCard { } @Override - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, PINProvider provider) throws SignatureCardException, InterruptedException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException { // KeyStore password char[] password = getPassword(keyboxName); @@ -363,7 +364,10 @@ public class SWCard implements SignatureCard { try { Signature signature = Signature.getInstance(algorithm); signature.initSign(privateKey); - signature.update(hash); + int l; + for (byte[] b = new byte[20]; (l = input.read(b)) != -1;) { + signature.update(b, 0, l); + } return signature.sign(); } catch (NoSuchAlgorithmException e) { String msg = "Algorithm + '" + algorithm + "' not supported for signing."; diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java index 1a163783..3d56f97b 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCard.java @@ -18,6 +18,9 @@ package at.gv.egiz.smcc; import at.gv.egiz.smcc.ccid.CCID; + +import java.io.IOException; +import java.io.InputStream; import java.util.Locale; import javax.smartcardio.Card; @@ -101,15 +104,17 @@ public interface SignatureCard { /** * - * @param hash + * @param input * @param keyboxName * @param provider + * @param alg TODO * @return * @throws at.gv.egiz.smcc.SignatureCardException * @throws java.lang.InterruptedException if applet is destroyed while in pin dialog + * @throws IOException */ - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, - PINProvider provider) throws SignatureCardException, InterruptedException; + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException, InterruptedException, IOException; public CCID getReader(); diff --git a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java index 26844473..47053f98 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/SignatureCardFactory.java @@ -170,21 +170,21 @@ public class SignatureCardFactory { }, "at.gv.egiz.smcc.STARCOSCard")); -// // e-card G3 -// supportedCards.add(new SupportedCard( -// // ATR (3b:dd:96:ff:81:b1:fe:45:1f:03:80:31:b0:52:02:03:64:04:1b:b4:22:81:05:18) -// new byte[] { -// (byte) 0x3b, (byte) 0xdd, (byte) 0x96, (byte) 0xff, (byte) 0x81, (byte) 0xb1, (byte) 0xfe, (byte) 0x45, -// (byte) 0x1f, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, -// (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 -// }, -// // mask ( -// new byte[] { -// (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, -// (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, -// (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 -// }, -// "at.gv.egiz.smcc.STARCOSCard")); + // e-card G3 + supportedCards.add(new SupportedCard( + // ATR (3b:dd:96:ff:81:b1:fe:45:1f:03:80:31:b0:52:02:03:64:04:1b:b4:22:81:05:18) + new byte[] { + (byte) 0x3b, (byte) 0xdd, (byte) 0x96, (byte) 0xff, (byte) 0x81, (byte) 0xb1, (byte) 0xfe, (byte) 0x45, + (byte) 0x1f, (byte) 0x03, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + }, + // mask ( + new byte[] { + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, + (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00 + }, + "at.gv.egiz.smcc.STARCOSCard")); // a-sign premium supportedCards.add(new SupportedCard( @@ -202,6 +202,72 @@ public class SignatureCardFactory { }, "at.gv.egiz.smcc.ACOSCard")); + // BELPIC + supportedCards.add(new SupportedCard( + // ATR (3b:98:13:40:0A:A5:03:01:01:01:AD:13:11) + new byte[] { (byte) 0x3b, (byte) 0x98, (byte) 0x13, + (byte) 0x40, (byte) 0x0a, (byte) 0xa5, (byte) 0x03, + (byte) 0x01, (byte) 0x01, (byte) 0x01, (byte) 0xad, + (byte) 0x13, (byte) 0x11 }, + // mask (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff) + new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff }, + "at.gv.egiz.smcc.BELPICCard")); + + // ITCards + supportedCards.add(new SupportedCard( + // ATR = + // [3b:ff:18:00:ff:81:31:fe:55:00:6b:02:09:02:00:01:11:01:43:4e:53:11:31:80:8e] + new byte[] { (byte) 0x3b, (byte) 0xff, (byte) 0x18, + (byte) 0x00, (byte) 0xff, (byte) 0x81, (byte) 0x31, + (byte) 0xfe, (byte) 0x55, (byte) 0x00, (byte) 0x6b, + (byte) 0x02, (byte) 0x09 /* + * , (byte) 0x02, (byte) 0x00, + * (byte) 0x01, (byte) 0x11, + * (byte) 0x01, (byte) 0x43, + * (byte) 0x4e, (byte) 0x53, + * (byte) 0x11, (byte) 0x31, + * (byte) 0x80, (byte) 0x8e + */ + }, + // mask (ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff) + new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff /* + * , (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff, + * (byte) 0xff, (byte) 0xff + */ + }, "at.gv.egiz.smcc.ITCard")); + supportedCards.add(new SupportedCard( + // ATR + // (3B:FF:18:00:FF:C1:0A:31:FE:55:00:6B:05:08:C8:05:01:01:01:43:4E:53:10:31:80:1C) + new byte[] { (byte) 0x3b, (byte) 0xff, (byte) 0x18, + (byte) 0x00, (byte) 0xFF, (byte) 0xC1, (byte) 0x0a, + (byte) 0x31, (byte) 0xfe, (byte) 0x55, (byte) 0x00, + (byte) 0x6B, (byte) 0x05, (byte) 0x08, (byte) 0xC8, + (byte) 0x05, (byte) 0x01, (byte) 0x01, (byte) 0x01, + (byte) 0x43, (byte) 0x4E, (byte) 0x53, (byte) 0x10, + (byte) 0x31, (byte) 0x80, (byte) 0x1C }, + // mask + // (ff:ff:ff:00:00:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:ff:00:00:00:00) + new byte[] { (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff, (byte) 0xff, + (byte) 0xff, (byte) 0xff, (byte) 0xff }, + "at.gv.egiz.smcc.ITCard")); + + + } /** diff --git a/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java b/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java index c5c7cbc9..fcd0b876 100644 --- a/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java +++ b/smcc/src/main/java/at/gv/egiz/smcc/util/ISO7816Utils.java @@ -103,6 +103,14 @@ public class ISO7816Utils { TransparentFileInputStream is = openTransparentFileInputStream(channel, maxSize); + + return readTransparentFileTLV(is, maxSize, expectedType); + + } + + public static byte[] readTransparentFileTLV(TransparentFileInputStream is, int maxSize, + byte expectedType) throws CardException, SignatureCardException { + try { @@ -170,7 +178,8 @@ public class ISO7816Utils { while (pos < (fcx[1] - 2)) { switch (fcx[pos]) { - case (byte) 0x80: { + case (byte) 0x80: + case (byte) 0x81: { len = 0xFF & fcx[pos + 2]; for (int i = 1; i < fcx[pos + 1]; i++) { len<<=8; diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties new file mode 100644 index 00000000..71267394 --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/BELPICCard.properties @@ -0,0 +1,3 @@ +#pin.name=PIN +sig.pin.name=PIN +sig.pin.length=4-12 \ No newline at end of file diff --git a/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties b/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties new file mode 100644 index 00000000..e0222a70 --- /dev/null +++ b/smcc/src/main/resources/at/gv/egiz/smcc/ITCard.properties @@ -0,0 +1,3 @@ +#pin.name=PIN +sig.pin.name=PIN +sig.pin.length=5-8 \ No newline at end of file diff --git a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java index 2a55357d..b3bd07ab 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/CardTest.java @@ -18,6 +18,8 @@ package at.gv.egiz.smcc; import static org.junit.Assert.*; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -178,13 +180,10 @@ public abstract class CardTest { @Test(expected = CancelledException.class) public void testSignSIGCancel() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -193,21 +192,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, pinProvider, + null); } @Test(expected = CancelledException.class) public void testSignDECCancel() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -216,21 +213,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } @Test(expected = InterruptedException.class) public void testSignSIGInterrrupted() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -239,21 +234,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = InterruptedException.class) public void testSignDECInterrrupted() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -262,21 +255,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } @Test(expected = CancelledException.class) public void testSignSIGConcurrent() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { final SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -294,21 +285,19 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = CancelledException.class) public void testSignDECConcurrent() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { final SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - PINProvider pinProvider = new PINProvider() { @Override public char[] providePIN(PINSpec spec, int retries) @@ -326,8 +315,9 @@ public abstract class CardTest { } }; - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java index 90bb039e..56d1e4b2 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/acos/ACOSCardTest.java @@ -21,6 +21,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -125,7 +127,7 @@ public abstract class ACOSCardTest extends CardTest { @Test public void testSignSIG() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { char[] pin = "123456".toCharArray(); @@ -134,11 +136,9 @@ public abstract class ACOSCardTest extends CardTest { ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG); appl.setPin(ACOSApplSIG.KID_PIN_SIG, pin); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - - byte[] signature = signatureCard.createSignature(hash, - KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin)); + byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), + KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); assertNotNull(signature); @@ -147,7 +147,7 @@ public abstract class ACOSCardTest extends CardTest { @Test public void testSignDEC() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { char[] pin = "1234".toCharArray(); @@ -156,11 +156,9 @@ public abstract class ACOSCardTest extends CardTest { ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC); appl.setPin(ACOSApplDEC.KID_PIN_DEC, pin); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - - byte[] signature = signatureCard.createSignature(hash, - KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin)); + byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), + KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); assertNotNull(signature); @@ -169,74 +167,66 @@ public abstract class ACOSCardTest extends CardTest { @Test(expected = LockedException.class) public void testSignSIGInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignDECInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignSIGBlockedPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); CardEmul card = (CardEmul) signatureCard.getCard(); ACOSApplSIG appl = (ACOSApplSIG) card.getApplication(ACOSAppl.AID_SIG); appl.setPin(ACOSApplSIG.KID_PIN_SIG, null); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignDECBlockedPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); CardEmul card = (CardEmul) signatureCard.getCard(); ACOSApplDEC appl = (ACOSApplDEC) card.getApplication(ACOSAppl.AID_DEC); appl.setPin(ACOSApplDEC.KID_PIN_DEC, null); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } diff --git a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java index 89e2ca65..b7dc9a0c 100644 --- a/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java +++ b/smcc/src/test/java/at/gv/egiz/smcc/starcos/STARCOSCardTest.java @@ -20,6 +20,8 @@ import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; +import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.UnsupportedEncodingException; import java.security.MessageDigest; import java.security.NoSuchAlgorithmException; @@ -147,7 +149,7 @@ public class STARCOSCardTest extends CardTest { @Test public void testSignSichereSignatur() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { char[] pin = "123456".toCharArray(); @@ -156,11 +158,9 @@ public class STARCOSCardTest extends CardTest { STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, pin); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - - byte[] signature = signatureCard.createSignature(hash, - KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin)); + byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), + KeyboxName.SECURE_SIGNATURE_KEYPAIR, new TestPINProvider(pin), null); assertNotNull(signature); @@ -169,7 +169,7 @@ public class STARCOSCardTest extends CardTest { @Test public void testSignGewoehnlicheSignatur() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { char[] pin = "1234".toCharArray(); @@ -178,11 +178,9 @@ public class STARCOSCardTest extends CardTest { STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, pin); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - - byte[] signature = signatureCard.createSignature(hash, - KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin)); + byte[] signature = signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), + KeyboxName.CERITIFIED_KEYPAIR, new TestPINProvider(pin), null); assertNotNull(signature); @@ -191,75 +189,67 @@ public class STARCOSCardTest extends CardTest { @Test(expected = LockedException.class) public void testSignSichereSignaturInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignGewoehnlicheSignaturInvalidPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("1234".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignSichereSignaturBlockedPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); CardEmul card = (CardEmul) signatureCard.getCard(); STARCOSApplSichereSignatur appl = (STARCOSApplSichereSignatur) card.getApplication(STARCOSApplSichereSignatur.AID_SichereSignatur); appl.setPin(STARCOSApplSichereSignatur.KID_PIN_SS, null); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("000000".toCharArray()); assertTrue(pinProvider.getProvided() <= 0); - signatureCard.createSignature(hash, KeyboxName.SECURE_SIGNATURE_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.SECURE_SIGNATURE_KEYPAIR, + pinProvider, null); } @Test(expected = LockedException.class) public void testSignGewoehnlicheSignaturBlockedPin() throws SignatureCardException, InterruptedException, CardNotSupportedException, - NoSuchAlgorithmException, UnsupportedEncodingException { + NoSuchAlgorithmException, IOException { SignatureCard signatureCard = createSignatureCard(); CardEmul card = (CardEmul) signatureCard.getCard(); STARCOSCardChannelEmul channel = (STARCOSCardChannelEmul) card.getBasicChannel(); channel.setPin(STARCOSCardChannelEmul.KID_PIN_Glob, null); - MessageDigest md = MessageDigest.getInstance("SHA-1"); - byte[] hash = md.digest("MOCCA".getBytes("ASCII")); - TestPINProvider pinProvider = new TestPINProvider("0000".toCharArray()); - signatureCard.createSignature(hash, KeyboxName.CERITIFIED_KEYPAIR, - pinProvider); + signatureCard.createSignature(new ByteArrayInputStream("MOCCA" + .getBytes("ASCII")), KeyboxName.CERITIFIED_KEYPAIR, + pinProvider, null); } diff --git a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java index 560f1373..58d7b305 100644 --- a/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java +++ b/smccSTAL/src/main/java/at/gv/egiz/bku/smccstal/SignRequestHandler.java @@ -18,9 +18,8 @@ package at.gv.egiz.bku.smccstal; import at.gv.egiz.bku.gui.BKUGUIFacade; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; import javax.xml.bind.JAXBContext; import javax.xml.bind.JAXBElement; @@ -44,7 +43,6 @@ import at.gv.egiz.stal.SignRequest; import at.gv.egiz.stal.SignResponse; import at.gv.egiz.stal.signedinfo.ObjectFactory; import at.gv.egiz.stal.signedinfo.SignedInfoType; -import at.gv.egiz.stal.util.JCEAlgorithmNames; public class SignRequestHandler extends AbstractRequestHandler { @@ -77,18 +75,11 @@ public class SignRequestHandler extends AbstractRequestHandler { JAXBElement si = (JAXBElement) unmarshaller.unmarshal(is); String signatureMethod = si.getValue().getSignatureMethod().getAlgorithm(); log.debug("Found signature method: " + signatureMethod); - String jceName = JCEAlgorithmNames.getJCEHashName(signatureMethod); - if (jceName == null) { - log.error("Hash algorithm not supported:"); - return new ErrorResponse(4006); - } - MessageDigest md = MessageDigest.getInstance(jceName); - md.update(signReq.getSignedInfo()); KeyboxName kb = SignatureCard.KeyboxName.getKeyboxName(signReq.getKeyIdentifier()); - byte[] resp = card.createSignature(md.digest(), kb, + byte[] resp = card.createSignature(new ByteArrayInputStream(signReq.getSignedInfo()), kb, new PINProviderFactory(card.getReader(), gui) - .getSignaturePINProvider(secureViewer, si.getValue())); + .getSignaturePINProvider(secureViewer, si.getValue()), signatureMethod); if (resp == null) { return new ErrorResponse(6001); } @@ -127,9 +118,9 @@ public class SignRequestHandler extends AbstractRequestHandler { } catch (JAXBException e) { log.error("Cannot unmarshall signed info", e); return new ErrorResponse(1000); - } catch (NoSuchAlgorithmException e) { - log.error(e); - return new ErrorResponse(1000); + } catch (IOException e) { + log.error("Error while creating signature: " + e); + return new ErrorResponse(4000); } } else { log.fatal("Got unexpected STAL request: " + request); diff --git a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java index 36880e68..16d3efa9 100644 --- a/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java +++ b/smccSTAL/src/test/java/at/gv/egiz/smcc/AbstractSMCCSTALTest.java @@ -1,5 +1,6 @@ package at.gv.egiz.smcc; +import java.io.InputStream; import java.util.ArrayList; import java.util.List; import java.util.Locale; @@ -37,8 +38,8 @@ public class AbstractSMCCSTALTest extends AbstractSMCCSTAL implements signatureCard = new SignatureCard() { @Override - public byte[] createSignature(byte[] hash, KeyboxName keyboxName, - PINProvider provider) throws SignatureCardException { + public byte[] createSignature(InputStream input, KeyboxName keyboxName, + PINProvider provider, String alg) throws SignatureCardException { // TODO Auto-generated method stub return null; } diff --git a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java index 82cba624..6f694b91 100644 --- a/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java +++ b/utils/src/main/java/at/gv/egiz/xades/QualifyingPropertiesFactory.java @@ -104,14 +104,14 @@ public class QualifyingPropertiesFactory { } - public DigestAlgAndValueType createDigestAlgAndValueType(X509Certificate certificate) throws QualifyingPropertiesException { + public DigestAlgAndValueType createDigestAlgAndValueType(X509Certificate certificate, DigestMethod dm) throws QualifyingPropertiesException { DigestMethodType digestMethodType = dsFactory.createDigestMethodType(); - digestMethodType.setAlgorithm(DigestMethod.SHA1); - + digestMethodType.setAlgorithm(dm.getAlgorithm()); + byte[] digest; try { - MessageDigest messageDigest = MessageDigest.getInstance("SHA-1"); + MessageDigest messageDigest = MessageDigest.getInstance(dm.getAlgorithm()); digest = messageDigest.digest(certificate.getEncoded()); } catch (CertificateEncodingException e) { throw new QualifyingPropertiesException(e); @@ -155,7 +155,10 @@ public class QualifyingPropertiesFactory { return dataObjectFormatType; } - public JAXBElement createQualifyingProperties111(String target, Date signingTime, List certificates, String idValue, List dataObjectFormats) throws QualifyingPropertiesException { + public JAXBElement createQualifyingProperties111( + String target, Date signingTime, List certificates, + String idValue, List dataObjectFormats, + DigestMethod digestMethod) throws QualifyingPropertiesException { GregorianCalendar gregorianCalendar = new GregorianCalendar(); gregorianCalendar.setTimeZone(TimeZone.getTimeZone("UTC")); @@ -175,7 +178,7 @@ public class QualifyingPropertiesFactory { for (X509Certificate certificate : certificates) { CertIDType certIDType = qpFactory.createCertIDType(); - certIDType.setCertDigest(createDigestAlgAndValueType(certificate)); + certIDType.setCertDigest(createDigestAlgAndValueType(certificate, digestMethod)); certIDType.setIssuerSerial(createX509IssuerSerialType(certificate)); certIDs.add(certIDType); -- cgit v1.2.3