diff options
author | Bojan Suzic <bojan.suzic@iaik.tugraz.at> | 2014-11-03 13:05:12 +0100 |
---|---|---|
committer | Bojan Suzic <bojan.suzic@iaik.tugraz.at> | 2014-11-03 13:05:12 +0100 |
commit | c2819264cface1a6f11cfe692429a0e93804794f (patch) | |
tree | 710858de5e3d9883d36213b041e5baff25d1da29 /spss/server | |
parent | 22a66cdf1b5f7916422034f3338e680202ddc31b (diff) | |
parent | 2886006ba2ca141377e66a330df5fc52797c2755 (diff) | |
download | moa-id-spss-c2819264cface1a6f11cfe692429a0e93804794f.tar.gz moa-id-spss-c2819264cface1a6f11cfe692429a0e93804794f.tar.bz2 moa-id-spss-c2819264cface1a6f11cfe692429a0e93804794f.zip |
merging
Diffstat (limited to 'spss/server')
-rw-r--r-- | spss/server/history.txt | 11 | ||||
-rw-r--r-- | spss/server/readme.update.txt | 69 | ||||
-rw-r--r-- | spss/server/serverlib/.gitignore | 1 | ||||
-rw-r--r-- | spss/server/serverlib/pom.xml | 25 | ||||
-rw-r--r-- | spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java | 178 | ||||
-rw-r--r-- | spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java | 3 | ||||
-rw-r--r-- | spss/server/serverws/.gitignore | 2 | ||||
-rw-r--r-- | spss/server/serverws/pom.xml | 2 | ||||
-rw-r--r-- | spss/server/serverws/resources/wsdl/MOA-SPSS-2.0.0.wsdl (renamed from spss/server/serverws/resources/wsdl/MOA-SPSS-1.5.2.wsdl) | 0 | ||||
-rw-r--r-- | spss/server/serverws/resources/wsdl/MOA-SPSS-2.0.0.xsd (renamed from spss/server/serverws/resources/wsdl/MOA-SPSS-1.5.2.xsd) | 0 | ||||
-rw-r--r-- | spss/server/serverws/src/main/webapp/WEB-INF/server-config.wsdd | 4 | ||||
-rw-r--r-- | spss/server/serverws/src/main/webapp/WEB-INF/web.xml | 14 | ||||
-rw-r--r-- | spss/server/tools/.gitignore | 1 |
13 files changed, 230 insertions, 80 deletions
diff --git a/spss/server/history.txt b/spss/server/history.txt index 2dbd62760..9fbfd6a7d 100644 --- a/spss/server/history.txt +++ b/spss/server/history.txt @@ -1,4 +1,15 @@ ############## +2.0.3 +############## +- Neues Endpunkt zum Auslesen des Zertifikats einer Schlüsselgruppe hinzugefügt +- Libraries aktuallisert + > javax.xml.bind.jaxb-api 2.2.12 + > xerces.xercesImpl 2.11.0 + > xalan 2.7.2 + > serializer 2.7.2 + + +############## 2.0.2 ############## - Libraries aktuallisert diff --git a/spss/server/readme.update.txt b/spss/server/readme.update.txt index 144abc5bc..3ebf15565 100644 --- a/spss/server/readme.update.txt +++ b/spss/server/readme.update.txt @@ -1,5 +1,5 @@ ------------------------------------------------------------------------------- - Update einer bestehenden MOA-SPSS-Installation auf Version 2.0.2 + Update einer bestehenden MOA-SPSS-Installation auf Version 2.0.3 ------------------------------------------------------------------------------- Es gibt zwei Moeglichkeiten (im Folgenden als "Update Variante A" und "Update Variante B" bezeichnet), das Update von MOA-SPSS auf Version @@ -23,12 +23,9 @@ Update Variante A 1.) Erstellen Sie eine Sicherungskopie des kompletten Tomcat-Verzeichnisses Ihrer MOA-SPSS-Installation. -2.) Erstellen Sie eine Sicherungskopie aller "iaik*.jar"-Dateien im Verzeichnis - JAVA_HOME\jre\lib\ext, und loeschen Sie diese Dateien danach. +2.) Fuehren Sie eine Neuinstallation gemaess Handbuch durch. -3.) Fuehren Sie eine Neuinstallation gemaess Handbuch durch. - -4.) Kopieren Sie etwaige Konfigurationsdateien, Trust-Profile und Key-Stores, +3.) Kopieren Sie etwaige Konfigurationsdateien, Trust-Profile und Key-Stores, die Sie aus Ihrer alten Installation beibehalten moechten, aus Ihrer Sicherungskopie in die entsprechenden Verzeichnisse der neuen Installation. @@ -36,7 +33,7 @@ Update Variante A Update Variante B, Punkt 9 beschrieben vor, um Ihre alten Trustprofile auf einen aktuellen Stand zu bringen. -5.) Nur wenn alte Installation aelter als Version 1.3.0: +4.) Nur wenn alte Installation aelter als Version 1.3.0: Falls Sie Ihre alte MOA-SP Konfigurationsdatei weiterverwenden wollen: Seit dem Wechsel auf Version 1.3.1 verwendet MOA SP ein neues Format fuer die XML-Konfigurationsdatei. Sie muessen die Konfigurationsdatei fuer MOA-SP aus @@ -51,9 +48,9 @@ Update Variante B 1.) Erstellen Sie eine Sicherungskopie des kompletten Tomcat-Verzeichnisses Ihrer MOA-SPSS-Installation. -2.) Entpacken Sie die Datei "moa-spss-2.0.2.zip" in das Verzeichnis MOA_SPSS_INST. +2.) Entpacken Sie die Datei "moa-spss-2.0.3.zip" in das Verzeichnis MOA_SPSS_INST. -3.) Erstellen Sie eine Sicherungskopie aller "iaik*.jar"-Dateien im Verzeichnis +3.) Erstellen Sie eine Sicherungskopie aller "*.jar"-Dateien im Verzeichnis JAVA_HOME\jre\lib\ext und loeschen Sie diese Dateien danach. 4.) Kopieren Sie alle Dateien aus dem Verzeichnis MOA_SPSS_INST\ext in das @@ -71,58 +68,8 @@ Update Variante B MOA_SPSS_INST\moa-spss.war. 8.) Loeschen Sie das Verzeichnis CATALINA_HOME\work. - -9.) Update der Trust-Profile. - Wenn Sie Ihre alten Trust-Profile durch die neuen ersetzen wollen, dann gehen - Sie vor, wie in Punkt a). Wenn Sie Ihre eigenen Trust-Profile beibehalten wollen, - dann gehen Sie vor, wie in Punkt b). - - a) Gehen Sie wie folgt vor, um die Trust-Profile auszutauschen: - - 1) Loeschen Sie das Verzeichnis CATALINA_HOME\conf\moa-spss\trustProfiles. - 2) Kopieren Sie das Verzeichnis MOA_SPSS_INST\conf\moa-spss\trustProfiles - in das Verzeichnis CATALINA_HOME\conf\moa-spss. - - b) Falls Sie Ihre alten Trust-Profile beibehalten wollen, gehen Sie wie folgt vor, - um die Profile auf den aktuellen Stand zu bringen: - - 1) Loeschen Sie die Datei "C=AT,O=Hauptverband oesterr. Sozialvers.,CN=CRL-Signer.der" - aus jedem Trustprofil, in dem sie enthalten ist. (Je nachdem welche Version Sie - ursprünglich verwendet haben kann diese Datei auch in keinem Trustprofile vorhanden sein) - - 2) Loeschen Sie die Datei "OCSP Responder 02-20051027-20101027.der" aus jedem - Trustprofil, in dem sie enthalten ist. (Je nachdem welche Version Sie - ursprünglich verwendet haben kann diese Datei auch in keinem Trustprofile vorhanden sein) - - 3) Ergaenzen Sie ihre Trustprofile durch alle Zertifikate aus den entsprechenden Profilen - im Verzeichnis MOA_SPSS_INST\conf\moa-spss\trustProfiles, die nicht in Ihren - Profilen enthalten sind. Am einfachsten ist es, wenn Sie den Inhalt der einzelnen Profile - aus der Distribution (MOA_SPSS_INST\conf\moa-spss\trustProfiles) in die entsprechenden - Profile Ihrer Installation (CATALINA_HOME\conf\moa-spss\trustProfiles) kopieren und - dabei die vorhandenen gleichnamigen Zertifikate �berschreiben), also z.B: - - Kopieren des Inhalts von - MOA_SPSS_INST\conf\moa-spss\trustProfiles\certifiedSignature - nach - CATALINA_HOME\conf\moa-spss\trustProfiles\certifiedSignature - usw. - -10.) Update des Cert-Stores. - a) Kopieren Sie den Inhalt des Verzeichnisses MOA_SPSS_INST\conf\moa-spss\certstore - in das Verzeichnis CATALINA_HOME\conf\moa-spss\certstore. Wenn Sie gefragt werden, ob Sie - vorhandene Dateien oder Unterverzeichnisse ueberschreiben sollen, dann bejahen Sie das. - - b) Falls vorhanden, loeschen Sie die Datei "890A4C8282E95EBB398685D9501486EF213941B5" aus dem - Verzeichnis CATALINA_HOME\conf\moa-spss\certstore\10F17BDACD8DEAA1E8F23FBEAE7B3EC3D9773D1D. - - c) Falls die Datei "E7340D1FB627D8917A9C0D23F21515C441BF1214" noch nicht im Verzeichnis - CATALINA_HOME\conf\moa-spss\certstore\10F17BDACD8DEAA1E8F23FBEAE7B3EC3D9773D1D - enthalten ist, dann kopieren Sie diese Datei aus dem Verzeichnis - MOA_ID_INST_AUTH\conf\moa-spss\certstore\10F17BDACD8DEAA1E8F23FBEAE7B3EC3D9773D1D - in das Verzeichnis - CATALINA_HOME\conf\moa-spss\certstore\10F17BDACD8DEAA1E8F23FBEAE7B3EC3D9773D1D. - -11.) Nur wenn alte Installation aelter als Version 1.3.0: + +9.) Nur wenn alte Installation aelter als Version 1.3.0: Mit dem Wechsel auf Version 1.3.0 verwendet MOA SP ein neues Format fuer die XML-Konfigurationsdatei. Sie muessen die Konfigurationsdatei fuer MOA-SP aus Ihrer alten Installation auf das neue Format konvertieren. Details dazu diff --git a/spss/server/serverlib/.gitignore b/spss/server/serverlib/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/spss/server/serverlib/.gitignore @@ -0,0 +1 @@ +/target diff --git a/spss/server/serverlib/pom.xml b/spss/server/serverlib/pom.xml index 7ecdef3b5..da78d3dc1 100644 --- a/spss/server/serverlib/pom.xml +++ b/spss/server/serverlib/pom.xml @@ -160,18 +160,19 @@ </exclusion>
</exclusions>
</dependency>
-
- <dependency>
- <groupId>iaik</groupId>
- <artifactId>iaik_xsect_eval</artifactId>
- <version>1.1709142</version>
- </dependency>
- <dependency>
- <groupId>org.xerial</groupId>
- <artifactId>sqlite-jdbc</artifactId>
- <version>3.7.8-SNAPSHOT</version>
- </dependency>
-
+
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-impl</artifactId>
+ <version>2.2.11</version>
+ </dependency>
+
+ <dependency>
+ <groupId>com.sun.xml.bind</groupId>
+ <artifactId>jaxb-core</artifactId>
+ <version>2.2.11</version>
+ </dependency>
+
<!-- <dependency>
<groupId>iaik</groupId>
<artifactId>iaik_util</artifactId>
diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java new file mode 100644 index 000000000..c8a0f68bf --- /dev/null +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/server/service/CertificateProviderServlet.java @@ -0,0 +1,178 @@ +package at.gv.egovernment.moa.spss.server.service; + +import iaik.server.modules.keys.KeyEntryID; +import iaik.server.modules.keys.KeyModule; +import iaik.server.modules.keys.KeyModuleFactory; + +import java.io.IOException; +import java.math.BigInteger; +import java.security.Principal; +import java.security.cert.Certificate; +import java.security.cert.X509Certificate; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; +import java.util.List; +import java.util.Set; + +import javax.servlet.ServletException; +import javax.servlet.http.HttpServlet; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; + +import at.gv.egovernment.moa.logging.Logger; +import at.gv.egovernment.moa.spss.server.config.ConfigurationException; +import at.gv.egovernment.moa.spss.server.config.ConfigurationProvider; +import at.gv.egovernment.moa.spss.server.config.KeyGroupEntry; +import at.gv.egovernment.moa.spss.server.logging.TransactionId; +import at.gv.egovernment.moa.spss.server.transaction.TransactionIDGenerator; + +/** + * + * @author Andreas Fitzek + * @version $Id$ + */ +public class CertificateProviderServlet extends HttpServlet { + + /** + * + */ + private static final long serialVersionUID = -6907582473072190122L; + + /** The property name for accessing the X509 client certificate chain. */ + private static final String X509_CERTIFICATE_PROPERTY = "javax.servlet.request.X509Certificate"; + + public static final String PARAM_KEYID = "id"; + + /** + * Build the set of <code>KeyEntryID</code>s available to the given + * <code>keyGroupID</code>. + * + * @param keyGroupID + * The keygroup ID for which the available keys should be + * returned. + * @return The <code>Set</code> of <code>KeyEntryID</code>s identifying the + * available keys. + * @throws ConfigurationException + */ + private Set buildKeySet(String keyGroupID, X509Certificate cert, KeyModule module) + throws ConfigurationException { + ConfigurationProvider config = ConfigurationProvider.getInstance(); + Set keyGroupEntries; + + // get the KeyGroup entries from the configuration + if (cert != null) { + Principal issuer = cert.getIssuerDN(); + BigInteger serialNumber = cert.getSerialNumber(); + + keyGroupEntries = config.getKeyGroupEntries(issuer, serialNumber, + keyGroupID); + } else { + keyGroupEntries = config.getKeyGroupEntries(null, null, keyGroupID); + } + + // map the KeyGroup entries to a set of KeyEntryIDs + if (keyGroupEntries == null) { + return null; + } else if (keyGroupEntries.size() == 0) { + return Collections.EMPTY_SET; + } else { + + Set keyEntryIDs = module.getPrivateKeyEntryIDs(); + Set keySet = new HashSet(); + Iterator iter; + + // filter out the keys that do not exist in the IAIK configuration + // by walking through the key entries and checking if the exist in + // the + // keyGroupEntries + for (iter = keyEntryIDs.iterator(); iter.hasNext();) { + KeyEntryID entryID = (KeyEntryID) iter.next(); + KeyGroupEntry entry = new KeyGroupEntry(entryID.getModuleID(), + entryID.getCertificateIssuer(), + entryID.getCertificateSerialNumber()); + if (keyGroupEntries.contains(entry)) { + keySet.add(entryID); + } + } + return keySet; + } + } + + private X509Certificate getClientCertificate(HttpServletRequest request) { + X509Certificate[] clientCert = (X509Certificate[]) request + .getAttribute(X509_CERTIFICATE_PROPERTY); + if(clientCert != null) { + return clientCert[0]; + } + return null; + } + + public void doGet(HttpServletRequest request, HttpServletResponse response) + throws ServletException, IOException { + try { + X509Certificate cert = getClientCertificate(request); + String keyId = request.getParameter(PARAM_KEYID); + + if(keyId == null) { + Logger.warn(PARAM_KEYID + " not provided in Request. Returning: " + HttpServletResponse.SC_BAD_REQUEST); + response.sendError(HttpServletResponse.SC_BAD_REQUEST); + return; + } + + String transactionId = TransactionIDGenerator.nextID(); + + KeyModule module = KeyModuleFactory.getInstance(new TransactionId( + transactionId)); + + Set keySet = buildKeySet(keyId, cert, module); + + if(keySet == null || keySet.isEmpty()) { + Logger.warn("No keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } + + + if(keySet.size() != 1) { + Logger.warn("Too many keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_CONFLICT); + return; + } + + Iterator iter; + + // filter out the keys that do not exist in the IAIK configuration + // by walking through the key entries and checking if the exist in + // the + // keyGroupEntries + for (iter = keySet.iterator(); iter.hasNext();) { + KeyEntryID entryID = (KeyEntryID) iter.next(); + + List certChain = module.getPrivateKeyEntry(entryID).getCertificateChain(); + + if(certChain != null && !certChain.isEmpty()) { + Logger.trace("Returning Certificate!"); + Certificate keyCert = ((Certificate)certChain.get(0)); + byte[] certData = keyCert.getEncoded(); + response.setStatus(HttpServletResponse.SC_OK); + response.setContentType("application/pkix-cert"); + response.setHeader("Content-disposition","attachment; filename=\"" + keyId + ".cer\""); + response.getOutputStream().write(certData); + response.getOutputStream().close(); + return; + } + + break; + } + + // No Certificate could be found! + Logger.warn("Failed to find keys available for Key Identifier " + keyId + " and given authentication."); + response.sendError(HttpServletResponse.SC_NOT_FOUND); + return; + } catch(Throwable e) { + Logger.error("Unhandled Exception when providing certificate", e); + response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR); + } + } +} diff --git a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java index 492d10eda..f8e8f608b 100644 --- a/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java +++ b/spss/server/serverlib/src/main/java/at/gv/egovernment/moa/spss/tsl/utils/TSLImportFromFileContext.java @@ -726,7 +726,8 @@ public class TSLImportFromFileContext extends iaik.xml.crypto.tsl.TSLImportFromF } else if (e.getMessage().startsWith("cvc-datatype-valid.1.2.1: '") && e.getMessage().endsWith("' is not a valid value for 'NCName'.")){
- if (expectedTerritory_ == Countries.CY || expectedTerritory_ == Countries.LV){
+ if (expectedTerritory_ == Countries.CY || expectedTerritory_ == Countries.LV ||
+ expectedTerritory_ == Countries.HR || expectedTerritory_ == Countries.NL){
return new AttributeValueFixup("","Id","(.+)","x$1",e, this);
}
} else if (e.getMessage().startsWith("cvc-complex-type.2.3: Element '") && e.getMessage().endsWith("' cannot have character [children], because the type's content type is element-only.")) {
diff --git a/spss/server/serverws/.gitignore b/spss/server/serverws/.gitignore new file mode 100644 index 000000000..4dc009173 --- /dev/null +++ b/spss/server/serverws/.gitignore @@ -0,0 +1,2 @@ +/target +/bin diff --git a/spss/server/serverws/pom.xml b/spss/server/serverws/pom.xml index 79a16cbb5..bbfb3c443 100644 --- a/spss/server/serverws/pom.xml +++ b/spss/server/serverws/pom.xml @@ -50,7 +50,7 @@ <webResources> <resource> <directory>${basedir}/resources/wsdl</directory> - <targetPath>resources/schemas</targetPath> + <targetPath>WEB-INF/classes/resources/schemas</targetPath> <includes> <include>*.xsd</include> <include>*.wsdl</include> diff --git a/spss/server/serverws/resources/wsdl/MOA-SPSS-1.5.2.wsdl b/spss/server/serverws/resources/wsdl/MOA-SPSS-2.0.0.wsdl index 4f9deee38..4f9deee38 100644 --- a/spss/server/serverws/resources/wsdl/MOA-SPSS-1.5.2.wsdl +++ b/spss/server/serverws/resources/wsdl/MOA-SPSS-2.0.0.wsdl diff --git a/spss/server/serverws/resources/wsdl/MOA-SPSS-1.5.2.xsd b/spss/server/serverws/resources/wsdl/MOA-SPSS-2.0.0.xsd index cc0a7c882..cc0a7c882 100644 --- a/spss/server/serverws/resources/wsdl/MOA-SPSS-1.5.2.xsd +++ b/spss/server/serverws/resources/wsdl/MOA-SPSS-2.0.0.xsd diff --git a/spss/server/serverws/src/main/webapp/WEB-INF/server-config.wsdd b/spss/server/serverws/src/main/webapp/WEB-INF/server-config.wsdd index 9ff243e5c..43e748734 100644 --- a/spss/server/serverws/src/main/webapp/WEB-INF/server-config.wsdd +++ b/spss/server/serverws/src/main/webapp/WEB-INF/server-config.wsdd @@ -16,7 +16,7 @@ <namespace>http://reference.e-government.gv.at/namespace/moa/20020822#</namespace>
<parameter name="allowedMethods" value="CreateCMSSignatureRequest CreateXMLSignatureRequest"/>
<parameter name="className" value="at.gv.egovernment.moa.spss.server.service.SignatureCreationService"/>
- <wsdlFile>webapps/moa-spss/resources/schemas/MOA-SPSS-2.0.0.wsdl</wsdlFile>
+ <wsdlFile>/resources/schemas/MOA-SPSS-2.0.0.wsdl</wsdlFile>
<requestFlow>
<handler type="MOAHandler"/>
@@ -30,7 +30,7 @@ <namespace>http://reference.e-government.gv.at/namespace/moa/20020822#</namespace>
<parameter name="allowedMethods" value="VerifyCMSSignatureRequest VerifyXMLSignatureRequest"/>
<parameter name="className" value="at.gv.egovernment.moa.spss.server.service.SignatureVerificationService"/>
- <wsdlFile>webapps/moa-spss/resources/schemas/MOA-SPSS-2.0.0.wsdl</wsdlFile>
+ <wsdlFile>/resources/schemas/MOA-SPSS-2.0.0.wsdl</wsdlFile>
<requestFlow>
<handler type="MOAHandler"/>
</requestFlow>
diff --git a/spss/server/serverws/src/main/webapp/WEB-INF/web.xml b/spss/server/serverws/src/main/webapp/WEB-INF/web.xml index b68ee850e..5de9f1d9c 100644 --- a/spss/server/serverws/src/main/webapp/WEB-INF/web.xml +++ b/spss/server/serverws/src/main/webapp/WEB-INF/web.xml @@ -10,9 +10,7 @@ <servlet> <servlet-name>ConfigurationServlet</servlet-name> <display-name>MOA Configuration Servlet</display-name> - <servlet-class> - at.gv.egovernment.moa.spss.server.service.ConfigurationServlet - </servlet-class> + <servlet-class>at.gv.egovernment.moa.spss.server.service.ConfigurationServlet</servlet-class> <load-on-startup>0</load-on-startup> </servlet> <servlet> @@ -22,6 +20,12 @@ org.apache.axis.transport.http.AxisServlet </servlet-class> </servlet> + <servlet> + <servlet-name>CertificateProviderServlet</servlet-name> + <display-name>MOA Certificate Provider Servlet</display-name> + <servlet-class>at.gv.egovernment.moa.spss.server.service.CertificateProviderServlet</servlet-class> + <load-on-startup>0</load-on-startup> + </servlet> <servlet-mapping> <servlet-name>AxisServlet</servlet-name> <url-pattern>/services/*</url-pattern> @@ -30,6 +34,10 @@ <servlet-name>ConfigurationServlet</servlet-name> <url-pattern>/ConfigurationUpdate</url-pattern> </servlet-mapping> + <servlet-mapping> + <servlet-name>CertificateProviderServlet</servlet-name> + <url-pattern>/Certificate</url-pattern> + </servlet-mapping> <security-constraint> <web-resource-collection> diff --git a/spss/server/tools/.gitignore b/spss/server/tools/.gitignore new file mode 100644 index 000000000..ea8c4bf7f --- /dev/null +++ b/spss/server/tools/.gitignore @@ -0,0 +1 @@ +/target |