Author: ebourg-guest Date: 2014-03-24 10:31:35 +0000 (Mon, 24 Mar 2014) New Revision: 17922
Added: trunk/ca-certificates-java/pom.xml trunk/ca-certificates-java/src/ trunk/ca-certificates-java/src/main/ trunk/ca-certificates-java/src/main/java/ trunk/ca-certificates-java/src/main/java/org/ trunk/ca-certificates-java/src/main/java/org/debian/ trunk/ca-certificates-java/src/main/java/org/debian/security/ trunk/ca-certificates-java/src/main/java/org/debian/security/Exceptions.java trunk/ca-certificates-java/src/main/java/org/debian/security/UpdateCertificates.java trunk/ca-certificates-java/src/test/ trunk/ca-certificates-java/src/test/java/ trunk/ca-certificates-java/src/test/java/org/ trunk/ca-certificates-java/src/test/java/org/debian/ trunk/ca-certificates-java/src/test/java/org/debian/security/ trunk/ca-certificates-java/src/test/java/org/debian/security/UpdateCertificatesTest.java Removed: trunk/ca-certificates-java/Exceptions.java trunk/ca-certificates-java/UpdateCertificates.java trunk/ca-certificates-java/UpdateCertificatesTest.java Modified: trunk/ca-certificates-java/ trunk/ca-certificates-java/debian/changelog trunk/ca-certificates-java/debian/rules Log: Mavenized the project Property changes on: trunk/ca-certificates-java ___________________________________________________________________ Modified: svn:ignore - bin .classpath .project + *.iml .classpath .project bin target Deleted: trunk/ca-certificates-java/Exceptions.java =================================================================== --- trunk/ca-certificates-java/Exceptions.java 2014-03-24 09:39:49 UTC (rev 17921) +++ trunk/ca-certificates-java/Exceptions.java 2014-03-24 10:31:35 UTC (rev 17922) @@ -1,61 +0,0 @@ -/* - * Copyright (C) 2012 Damien Raude-Morvan <[email protected]> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -/** - * Custom exceptions used by {@link UpdateCertificates} - * - * @author Damien Raude-Morvan <[email protected]> - */ -public class Exceptions { - - /** - * Data send in stdin is invalid (neither "+" or "-" command). - */ - public static class UnknownInput extends Exception { - private static final long serialVersionUID = 5698253678856993527L; - public UnknownInput(final String message) { - super(message); - } - - } - - /** - * Unable to save keystore to provided location. - */ - public static class UnableToSaveKeystore extends Exception { - private static final long serialVersionUID = 3632154306237688490L; - public UnableToSaveKeystore(final String message, final Exception e) { - super(message, e); - } - - } - - /** - * Unable to open keystore from provided location (might be an invalid password - * or IO error). - */ - public static class InvalidKeystorePassword extends Exception { - private static final long serialVersionUID = 7004201816889107694L; - public InvalidKeystorePassword(final String message, final Exception e) { - super(message, e); - } - - } - -} Deleted: trunk/ca-certificates-java/UpdateCertificates.java =================================================================== --- trunk/ca-certificates-java/UpdateCertificates.java 2014-03-24 09:39:49 UTC (rev 17921) +++ trunk/ca-certificates-java/UpdateCertificates.java 2014-03-24 10:31:35 UTC (rev 17922) @@ -1,223 +0,0 @@ -/* - * Copyright (C) 2011 Torsten Werner <[email protected]> - * Copyright (C) 2012 Damien Raude-Morvan <[email protected]> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -import java.io.BufferedReader; -import java.io.File; -import java.io.FileInputStream; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStreamReader; -import java.io.Reader; -import java.security.GeneralSecurityException; -import java.security.KeyStore; -import java.security.KeyStoreException; -import java.security.cert.Certificate; -import java.security.cert.CertificateFactory; - -/** - * This code is a re-implementation of the idea from Ludwig Nussel found in - * https://github.com/openSUSE/ca-certificates/blob/41917f5a/keystore.java - * for the Debian operating system. It updates the global JVM keystore. - * - * @author Torsten Werner - * @author Damien Raude-Morvan - */ -public class UpdateCertificates { - - private char[] password = null; - - private String ksFilename = null; - - private KeyStore ks = null; - - private CertificateFactory certFactory = null; - - public static void main(String[] args) throws IOException, GeneralSecurityException { - String passwordString = "changeit"; - if (args.length == 2 && args[0].equals("-storepass")) { - passwordString = args[1]; - } - else if (args.length > 0) { - System.err.println("Usage: java UpdateCertificates [-storepass <password>]"); - System.exit(1); - } - - try { - UpdateCertificates uc = new UpdateCertificates(passwordString, "/etc/ssl/certs/java/cacerts"); - // Force reading of inputstream in UTF-8 - uc.processChanges(new InputStreamReader(System.in, "UTF8")); - uc.writeKeyStore(); - } catch (Exceptions.InvalidKeystorePassword e) { - e.printStackTrace(System.err); - System.exit(1); - } catch (Exceptions.UnableToSaveKeystore e) { - e.printStackTrace(System.err); - System.exit(1); - } - } - - public UpdateCertificates(final String passwordString, final String keystoreFile) throws IOException, GeneralSecurityException, Exceptions.InvalidKeystorePassword { - this.password = passwordString.toCharArray(); - this.ksFilename = keystoreFile; - this.ks = openKeyStore(); - this.certFactory = CertificateFactory.getInstance("X.509"); - } - - /** - * Try to open a existing keystore or create an new one. - */ - private KeyStore openKeyStore() throws GeneralSecurityException, IOException, Exceptions.InvalidKeystorePassword { - KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); - File certInputFile = new File(this.ksFilename); - FileInputStream certInputStream = null; - if (certInputFile.canRead()) { - certInputStream = new FileInputStream(certInputFile); - } - try { - ks.load(certInputStream, this.password); - } - catch (IOException e) { - throw new Exceptions.InvalidKeystorePassword("Cannot open Java keystore. Is the password correct?", e); - } - if (certInputStream != null) { - certInputStream.close(); - } - return ks; - } - - /** - * Until reader EOF, try to read changes and send each to {@link #parseLine(String)}. - */ - protected void processChanges(final Reader reader) - throws IOException, GeneralSecurityException { - String line; - BufferedReader bufferedStdinReader = new BufferedReader(reader); - while((line = bufferedStdinReader.readLine()) != null) { - try { - parseLine(line); - } catch (Exceptions.UnknownInput e) { - System.err.println("Unknown input: " + line); - // Keep processing for others lines - } - } - } - - /** - * Parse given line to choose between {@link #addAlias(String, Certificate)} - * or {@link #deleteAlias(String)}. - */ - protected void parseLine(final String line) - throws GeneralSecurityException, IOException, Exceptions.UnknownInput { - assert this.ks != null; - - String path = line.substring(1); - String filename = path.substring(path.lastIndexOf("/") + 1); - String alias = "debian:" + filename; - if(line.startsWith("+")) { - Certificate cert = loadCertificate(path); - if (cert == null) { - return; - } - addAlias(alias, cert); - } - else if (line.startsWith("-")) { - deleteAlias(alias); - // Remove old non-prefixed aliases, too. This code should be - // removed after the release of Wheezy. - deleteAlias(filename); - } - else { - throw new Exceptions.UnknownInput(line); - } - } - - /** - * Delete cert in keystore at given alias. - */ - private void deleteAlias(final String alias) throws GeneralSecurityException { - assert this.ks != null; - - if (contains(alias)) { - System.out.println("Removing " + alias); - this.ks.deleteEntry(alias); - } - } - - /** - * Add or replace existing cert in keystore with given alias. - */ - private void addAlias(final String alias, final Certificate cert) - throws KeyStoreException { - assert this.ks != null; - - if(contains(alias)) { - System.out.println("Replacing " + alias); - this.ks.deleteEntry(alias); - } - else { - System.out.println("Adding " + alias); - } - this.ks.setCertificateEntry(alias, cert); - } - - /** - * Returns true when alias exist in keystore. - */ - protected boolean contains(String alias) throws KeyStoreException { - assert this.ks != null; - - return this.ks.containsAlias(alias); - } - - /** - * Try to load a certificate instance from given path. - */ - private Certificate loadCertificate(final String path) { - assert this.certFactory != null; - - Certificate cert = null; - try { - FileInputStream certFile = new FileInputStream(path); - cert = this.certFactory.generateCertificate(certFile); - certFile.close(); - } - catch (Exception e) { - System.err.println("Warning: there was a problem reading the certificate file " + - path + ". Message:\n " + e.getMessage()); - } - return cert; - } - - /** - * Write actual keystore content to disk. - */ - protected void writeKeyStore() throws GeneralSecurityException, Exceptions.UnableToSaveKeystore { - assert this.ks != null; - - try { - FileOutputStream certOutputFile = new FileOutputStream(this.ksFilename); - this.ks.store(certOutputFile, this.password); - certOutputFile.close(); - } - catch (IOException e) { - throw new Exceptions.UnableToSaveKeystore("There was a problem saving the new Java keystore.", e); - } - } -} Deleted: trunk/ca-certificates-java/UpdateCertificatesTest.java =================================================================== --- trunk/ca-certificates-java/UpdateCertificatesTest.java 2014-03-24 09:39:49 UTC (rev 17921) +++ trunk/ca-certificates-java/UpdateCertificatesTest.java 2014-03-24 10:31:35 UTC (rev 17922) @@ -1,221 +0,0 @@ -/* - * Copyright (C) 2012 Damien Raude-Morvan <[email protected]> - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License along - * with this program; if not, write to the Free Software Foundation, Inc., - * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. - * - */ - -import java.io.File; -import java.io.IOException; -import java.security.GeneralSecurityException; - -import junit.framework.Assert; - -import org.junit.Before; -import org.junit.Test; - -/** - * Tests for {@link UpdateCertificates}. - * - * @author Damien Raude-Morvan - */ -public class UpdateCertificatesTest { - - private static final String ALIAS_CACERT = "debian:spi-cacert-2008.crt"; - private static final String INVALID_CACERT = "x/usr/share/ca-certificates/spi-inc.org/spi-cacert-2008.crt"; - private static final String REMOVE_CACERT = "-/usr/share/ca-certificates/spi-inc.org/spi-cacert-2008.crt"; - private static final String ADD_CACERT = "+/usr/share/ca-certificates/spi-inc.org/spi-cacert-2008.crt"; - - private String ksFilename = null; - private String ksPassword = null; - - @Before - public void start() { - this.ksFilename = "./tests-cacerts"; - this.ksPassword = "changeit"; - // Delete any previous file - File keystore = new File(this.ksFilename); - keystore.delete(); - } - - /** - * Test a simple open then write without any modification. - */ - @Test - public void testNoop() throws IOException, GeneralSecurityException, - Exceptions.InvalidKeystorePassword, Exceptions.UnableToSaveKeystore { - UpdateCertificates uc = new UpdateCertificates(this.ksPassword, - this.ksFilename); - uc.writeKeyStore(); - } - - /** - * Test a to open a keystore and write without any modification - * and then try to open it again with wrong password : will throw a - * InvalidKeystorePassword - */ - @Test - public void testWriteThenOpenWrongPwd() throws IOException, - GeneralSecurityException, Exceptions.UnableToSaveKeystore { - try { - UpdateCertificates uc = new UpdateCertificates(this.ksPassword, - this.ksFilename); - uc.writeKeyStore(); - } catch (Exceptions.InvalidKeystorePassword e) { - Assert.fail(); - } - - try { - UpdateCertificates uc = new UpdateCertificates("wrongpassword", - this.ksFilename); - Assert.fail(); - uc.writeKeyStore(); - } catch (Exceptions.InvalidKeystorePassword e) { - Assert.assertEquals( - "Cannot open Java keystore. Is the password correct?", - e.getMessage()); - } - } - - /** - * Test a to open a keystore then remove its backing File (and replace it - * with a directory with the same name) and try to write in to disk : - * will throw an UnableToSaveKeystore - */ - @Test - public void testDeleteThenWrite() throws IOException, - GeneralSecurityException, Exceptions.InvalidKeystorePassword { - try { - UpdateCertificates uc = new UpdateCertificates(this.ksPassword, - this.ksFilename); - - // Replace actual file by a directory ! - File keystore = new File(this.ksFilename); - keystore.delete(); - keystore.mkdir(); - - // Will fail with some IOException - uc.writeKeyStore(); - Assert.fail(); - } catch (Exceptions.UnableToSaveKeystore e) { - Assert.assertEquals( - "There was a problem saving the new Java keystore.", - e.getMessage()); - } - } - - /** - * Try to send an invalid command ("x") in parseLine : throw UnknownInput - */ - @Test - public void testWrongCommand() throws IOException, - GeneralSecurityException, Exceptions.InvalidKeystorePassword { - UpdateCertificates uc = new UpdateCertificates(this.ksPassword, - this.ksFilename); - try { - uc.parseLine(INVALID_CACERT); - Assert.fail(); - } catch (Exceptions.UnknownInput e) { - Assert.assertEquals(INVALID_CACERT, e.getMessage()); - } - } - - /** - * Test to insert a valid certificate and then check if it's really in KS. - */ - @Test - public void testAdd() throws IOException, GeneralSecurityException, - Exceptions.UnknownInput, Exceptions.InvalidKeystorePassword, - Exceptions.UnableToSaveKeystore { - UpdateCertificates uc = new UpdateCertificates(this.ksPassword, - this.ksFilename); - uc.parseLine(ADD_CACERT); - uc.writeKeyStore(); - - Assert.assertEquals(true, uc.contains(ALIAS_CACERT)); - } - - /** - * Test to insert a invalide certificate : no exception, but check there - * is no alias created with that name - */ - @Test - public void testAddInvalidCert() throws IOException, - GeneralSecurityException, Exceptions.UnknownInput, - Exceptions.InvalidKeystorePassword, Exceptions.UnableToSaveKeystore { - UpdateCertificates uc = new UpdateCertificates(this.ksPassword, - this.ksFilename); - uc.parseLine("+/usr/share/ca-certificates/null.crt"); - uc.writeKeyStore(); - - Assert.assertEquals(false, uc.contains("debian:null.crt")); - } - - /** - * Try to add same certificate multiple time : we replace it and - * there is only one alias. - */ - @Test - public void testReplace() throws IOException, GeneralSecurityException, - Exceptions.UnknownInput, Exceptions.InvalidKeystorePassword, - Exceptions.UnableToSaveKeystore { - UpdateCertificates uc = new UpdateCertificates(this.ksPassword, - this.ksFilename); - uc.parseLine(ADD_CACERT); - uc.parseLine(ADD_CACERT); - uc.writeKeyStore(); - - Assert.assertEquals(true, uc.contains(ALIAS_CACERT)); - } - - /** - * Try to remove a non-existant certificate : it's a no-op. - */ - @Test - public void testRemove() throws IOException, GeneralSecurityException, - Exceptions.UnknownInput, Exceptions.InvalidKeystorePassword, - Exceptions.UnableToSaveKeystore { - UpdateCertificates uc = new UpdateCertificates(this.ksPassword, - this.ksFilename); - uc.parseLine(REMOVE_CACERT); - uc.writeKeyStore(); - - // We start with empty KS, so it shouldn't do anything - Assert.assertEquals(false, uc.contains(ALIAS_CACERT)); - } - - /** - * Try to add cert, write to disk, then open keystore again and remove. - */ - @Test - public void testAddThenRemove() throws IOException, - GeneralSecurityException, Exceptions.UnknownInput, - Exceptions.InvalidKeystorePassword, Exceptions.UnableToSaveKeystore { - UpdateCertificates ucAdd = new UpdateCertificates(this.ksPassword, - this.ksFilename); - ucAdd.parseLine(ADD_CACERT); - ucAdd.writeKeyStore(); - - Assert.assertEquals(true, ucAdd.contains(ALIAS_CACERT)); - - UpdateCertificates ucRemove = new UpdateCertificates(this.ksPassword, - this.ksFilename); - ucRemove.parseLine(REMOVE_CACERT); - ucRemove.writeKeyStore(); - - Assert.assertEquals(false, ucRemove.contains(ALIAS_CACERT)); - } - -} Modified: trunk/ca-certificates-java/debian/changelog =================================================================== --- trunk/ca-certificates-java/debian/changelog 2014-03-24 09:39:49 UTC (rev 17921) +++ trunk/ca-certificates-java/debian/changelog 2014-03-24 10:31:35 UTC (rev 17922) @@ -5,6 +5,7 @@ certificate from the ca-certificates package (Closes: #741755) * Limit the memory used by java to 64M when updating the certificates (Closes: 576453) + * Mavenized the project * d/control: Standards-Version updated to 3.9.5 (no changes) * Switch to debhelper level 9 Modified: trunk/ca-certificates-java/debian/rules =================================================================== --- trunk/ca-certificates-java/debian/rules 2014-03-24 09:39:49 UTC (rev 17921) +++ trunk/ca-certificates-java/debian/rules 2014-03-24 10:31:35 UTC (rev 17922) @@ -16,7 +16,7 @@ JAVA_HOME := /usr/lib/jvm/default-java export JAVA_HOME -OPTS := --no-javadoc --main=UpdateCertificates --javacopts="-source 1.6 -target 1.6" +OPTS := --no-javadoc --main=org.debian.security.UpdateCertificates --javacopts="-source 1.6 -target 1.6" CLASSPATH := /usr/share/java/junit4.jar export CLASSPATH @@ -33,7 +33,7 @@ ifeq ($(do_junit),yes) $(JAVA_HOME)/bin/java -cp /usr/share/java/junit4.jar:./ca-certificates-java.jar \ org.junit.runner.JUnitCore \ - UpdateCertificatesTest + org.debian.security.UpdateCertificatesTest endif touch $@ Added: trunk/ca-certificates-java/pom.xml =================================================================== --- trunk/ca-certificates-java/pom.xml (rev 0) +++ trunk/ca-certificates-java/pom.xml 2014-03-24 10:31:35 UTC (rev 17922) @@ -0,0 +1,33 @@ +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" + xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd"> + <modelVersion>4.0.0</modelVersion> + + <groupId>org.debian</groupId> + <artifactId>ca-certificates-java</artifactId> + <version>20130815</version> + <packaging>jar</packaging> + <name>ca-certificates-java</name> + <description>Common CA certificates</description> + + <dependencies> + <dependency> + <groupId>junit</groupId> + <artifactId>junit</artifactId> + <version>4.11</version> + <scope>test</scope> + </dependency> + </dependencies> + + <build> + <plugins> + <plugin> + <artifactId>maven-compiler-plugin</artifactId> + <version>2.1</version> + <configuration> + <source>1.6</source> + <target>1.6</target> + </configuration> + </plugin> + </plugins> + </build> +</project> Property changes on: trunk/ca-certificates-java/pom.xml ___________________________________________________________________ Added: svn:keywords + Date Author Id Revision HeadURL Added: svn:eol-style + native Copied: trunk/ca-certificates-java/src/main/java/org/debian/security/Exceptions.java (from rev 17921, trunk/ca-certificates-java/Exceptions.java) =================================================================== --- trunk/ca-certificates-java/src/main/java/org/debian/security/Exceptions.java (rev 0) +++ trunk/ca-certificates-java/src/main/java/org/debian/security/Exceptions.java 2014-03-24 10:31:35 UTC (rev 17922) @@ -0,0 +1,63 @@ +/* + * Copyright (C) 2012 Damien Raude-Morvan <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package org.debian.security; + +/** + * Custom exceptions used by {@link UpdateCertificates} + * + * @author Damien Raude-Morvan <[email protected]> + */ +public class Exceptions { + + /** + * Data send in stdin is invalid (neither "+" or "-" command). + */ + public static class UnknownInput extends Exception { + private static final long serialVersionUID = 5698253678856993527L; + public UnknownInput(final String message) { + super(message); + } + + } + + /** + * Unable to save keystore to provided location. + */ + public static class UnableToSaveKeystore extends Exception { + private static final long serialVersionUID = 3632154306237688490L; + public UnableToSaveKeystore(final String message, final Exception e) { + super(message, e); + } + + } + + /** + * Unable to open keystore from provided location (might be an invalid password + * or IO error). + */ + public static class InvalidKeystorePassword extends Exception { + private static final long serialVersionUID = 7004201816889107694L; + public InvalidKeystorePassword(final String message, final Exception e) { + super(message, e); + } + + } + +} Copied: trunk/ca-certificates-java/src/main/java/org/debian/security/UpdateCertificates.java (from rev 17921, trunk/ca-certificates-java/UpdateCertificates.java) =================================================================== --- trunk/ca-certificates-java/src/main/java/org/debian/security/UpdateCertificates.java (rev 0) +++ trunk/ca-certificates-java/src/main/java/org/debian/security/UpdateCertificates.java 2014-03-24 10:31:35 UTC (rev 17922) @@ -0,0 +1,225 @@ +/* + * Copyright (C) 2011 Torsten Werner <[email protected]> + * Copyright (C) 2012 Damien Raude-Morvan <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package org.debian.security; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStreamReader; +import java.io.Reader; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; + +/** + * This code is a re-implementation of the idea from Ludwig Nussel found in + * https://github.com/openSUSE/ca-certificates/blob/41917f5a/keystore.java + * for the Debian operating system. It updates the global JVM keystore. + * + * @author Torsten Werner + * @author Damien Raude-Morvan + */ +public class UpdateCertificates { + + private char[] password = null; + + private String ksFilename = null; + + private KeyStore ks = null; + + private CertificateFactory certFactory = null; + + public static void main(String[] args) throws IOException, GeneralSecurityException { + String passwordString = "changeit"; + if (args.length == 2 && args[0].equals("-storepass")) { + passwordString = args[1]; + } + else if (args.length > 0) { + System.err.println("Usage: java UpdateCertificates [-storepass <password>]"); + System.exit(1); + } + + try { + UpdateCertificates uc = new UpdateCertificates(passwordString, "/etc/ssl/certs/java/cacerts"); + // Force reading of inputstream in UTF-8 + uc.processChanges(new InputStreamReader(System.in, "UTF8")); + uc.writeKeyStore(); + } catch (Exceptions.InvalidKeystorePassword e) { + e.printStackTrace(System.err); + System.exit(1); + } catch (Exceptions.UnableToSaveKeystore e) { + e.printStackTrace(System.err); + System.exit(1); + } + } + + public UpdateCertificates(final String passwordString, final String keystoreFile) throws IOException, GeneralSecurityException, Exceptions.InvalidKeystorePassword { + this.password = passwordString.toCharArray(); + this.ksFilename = keystoreFile; + this.ks = openKeyStore(); + this.certFactory = CertificateFactory.getInstance("X.509"); + } + + /** + * Try to open a existing keystore or create an new one. + */ + private KeyStore openKeyStore() throws GeneralSecurityException, IOException, Exceptions.InvalidKeystorePassword { + KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType()); + File certInputFile = new File(this.ksFilename); + FileInputStream certInputStream = null; + if (certInputFile.canRead()) { + certInputStream = new FileInputStream(certInputFile); + } + try { + ks.load(certInputStream, this.password); + } + catch (IOException e) { + throw new Exceptions.InvalidKeystorePassword("Cannot open Java keystore. Is the password correct?", e); + } + if (certInputStream != null) { + certInputStream.close(); + } + return ks; + } + + /** + * Until reader EOF, try to read changes and send each to {@link #parseLine(String)}. + */ + protected void processChanges(final Reader reader) + throws IOException, GeneralSecurityException { + String line; + BufferedReader bufferedStdinReader = new BufferedReader(reader); + while((line = bufferedStdinReader.readLine()) != null) { + try { + parseLine(line); + } catch (Exceptions.UnknownInput e) { + System.err.println("Unknown input: " + line); + // Keep processing for others lines + } + } + } + + /** + * Parse given line to choose between {@link #addAlias(String, Certificate)} + * or {@link #deleteAlias(String)}. + */ + protected void parseLine(final String line) + throws GeneralSecurityException, IOException, Exceptions.UnknownInput { + assert this.ks != null; + + String path = line.substring(1); + String filename = path.substring(path.lastIndexOf("/") + 1); + String alias = "debian:" + filename; + if(line.startsWith("+")) { + Certificate cert = loadCertificate(path); + if (cert == null) { + return; + } + addAlias(alias, cert); + } + else if (line.startsWith("-")) { + deleteAlias(alias); + // Remove old non-prefixed aliases, too. This code should be + // removed after the release of Wheezy. + deleteAlias(filename); + } + else { + throw new Exceptions.UnknownInput(line); + } + } + + /** + * Delete cert in keystore at given alias. + */ + private void deleteAlias(final String alias) throws GeneralSecurityException { + assert this.ks != null; + + if (contains(alias)) { + System.out.println("Removing " + alias); + this.ks.deleteEntry(alias); + } + } + + /** + * Add or replace existing cert in keystore with given alias. + */ + private void addAlias(final String alias, final Certificate cert) + throws KeyStoreException { + assert this.ks != null; + + if(contains(alias)) { + System.out.println("Replacing " + alias); + this.ks.deleteEntry(alias); + } + else { + System.out.println("Adding " + alias); + } + this.ks.setCertificateEntry(alias, cert); + } + + /** + * Returns true when alias exist in keystore. + */ + protected boolean contains(String alias) throws KeyStoreException { + assert this.ks != null; + + return this.ks.containsAlias(alias); + } + + /** + * Try to load a certificate instance from given path. + */ + private Certificate loadCertificate(final String path) { + assert this.certFactory != null; + + Certificate cert = null; + try { + FileInputStream certFile = new FileInputStream(path); + cert = this.certFactory.generateCertificate(certFile); + certFile.close(); + } + catch (Exception e) { + System.err.println("Warning: there was a problem reading the certificate file " + + path + ". Message:\n " + e.getMessage()); + } + return cert; + } + + /** + * Write actual keystore content to disk. + */ + protected void writeKeyStore() throws GeneralSecurityException, Exceptions.UnableToSaveKeystore { + assert this.ks != null; + + try { + FileOutputStream certOutputFile = new FileOutputStream(this.ksFilename); + this.ks.store(certOutputFile, this.password); + certOutputFile.close(); + } + catch (IOException e) { + throw new Exceptions.UnableToSaveKeystore("There was a problem saving the new Java keystore.", e); + } + } +} Copied: trunk/ca-certificates-java/src/test/java/org/debian/security/UpdateCertificatesTest.java (from rev 17921, trunk/ca-certificates-java/UpdateCertificatesTest.java) =================================================================== --- trunk/ca-certificates-java/src/test/java/org/debian/security/UpdateCertificatesTest.java (rev 0) +++ trunk/ca-certificates-java/src/test/java/org/debian/security/UpdateCertificatesTest.java 2014-03-24 10:31:35 UTC (rev 17922) @@ -0,0 +1,223 @@ +/* + * Copyright (C) 2012 Damien Raude-Morvan <[email protected]> + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. + * + */ + +package org.debian.security; + +import java.io.File; +import java.io.IOException; +import java.security.GeneralSecurityException; + +import junit.framework.Assert; + +import org.junit.Before; +import org.junit.Test; + +/** + * Tests for {@link UpdateCertificates}. + * + * @author Damien Raude-Morvan + */ +public class UpdateCertificatesTest { + + private static final String ALIAS_CACERT = "debian:spi-cacert-2008.crt"; + private static final String INVALID_CACERT = "x/usr/share/ca-certificates/spi-inc.org/spi-cacert-2008.crt"; + private static final String REMOVE_CACERT = "-/usr/share/ca-certificates/spi-inc.org/spi-cacert-2008.crt"; + private static final String ADD_CACERT = "+/usr/share/ca-certificates/spi-inc.org/spi-cacert-2008.crt"; + + private String ksFilename = null; + private String ksPassword = null; + + @Before + public void start() { + this.ksFilename = "./tests-cacerts"; + this.ksPassword = "changeit"; + // Delete any previous file + File keystore = new File(this.ksFilename); + keystore.delete(); + } + + /** + * Test a simple open then write without any modification. + */ + @Test + public void testNoop() throws IOException, GeneralSecurityException, + Exceptions.InvalidKeystorePassword, Exceptions.UnableToSaveKeystore { + UpdateCertificates uc = new UpdateCertificates(this.ksPassword, + this.ksFilename); + uc.writeKeyStore(); + } + + /** + * Test a to open a keystore and write without any modification + * and then try to open it again with wrong password : will throw a + * InvalidKeystorePassword + */ + @Test + public void testWriteThenOpenWrongPwd() throws IOException, + GeneralSecurityException, Exceptions.UnableToSaveKeystore { + try { + UpdateCertificates uc = new UpdateCertificates(this.ksPassword, + this.ksFilename); + uc.writeKeyStore(); + } catch (Exceptions.InvalidKeystorePassword e) { + Assert.fail(); + } + + try { + UpdateCertificates uc = new UpdateCertificates("wrongpassword", + this.ksFilename); + Assert.fail(); + uc.writeKeyStore(); + } catch (Exceptions.InvalidKeystorePassword e) { + Assert.assertEquals( + "Cannot open Java keystore. Is the password correct?", + e.getMessage()); + } + } + + /** + * Test a to open a keystore then remove its backing File (and replace it + * with a directory with the same name) and try to write in to disk : + * will throw an UnableToSaveKeystore + */ + @Test + public void testDeleteThenWrite() throws IOException, + GeneralSecurityException, Exceptions.InvalidKeystorePassword { + try { + UpdateCertificates uc = new UpdateCertificates(this.ksPassword, + this.ksFilename); + + // Replace actual file by a directory ! + File keystore = new File(this.ksFilename); + keystore.delete(); + keystore.mkdir(); + + // Will fail with some IOException + uc.writeKeyStore(); + Assert.fail(); + } catch (Exceptions.UnableToSaveKeystore e) { + Assert.assertEquals( + "There was a problem saving the new Java keystore.", + e.getMessage()); + } + } + + /** + * Try to send an invalid command ("x") in parseLine : throw UnknownInput + */ + @Test + public void testWrongCommand() throws IOException, + GeneralSecurityException, Exceptions.InvalidKeystorePassword { + UpdateCertificates uc = new UpdateCertificates(this.ksPassword, + this.ksFilename); + try { + uc.parseLine(INVALID_CACERT); + Assert.fail(); + } catch (Exceptions.UnknownInput e) { + Assert.assertEquals(INVALID_CACERT, e.getMessage()); + } + } + + /** + * Test to insert a valid certificate and then check if it's really in KS. + */ + @Test + public void testAdd() throws IOException, GeneralSecurityException, + Exceptions.UnknownInput, Exceptions.InvalidKeystorePassword, + Exceptions.UnableToSaveKeystore { + UpdateCertificates uc = new UpdateCertificates(this.ksPassword, + this.ksFilename); + uc.parseLine(ADD_CACERT); + uc.writeKeyStore(); + + Assert.assertEquals(true, uc.contains(ALIAS_CACERT)); + } + + /** + * Test to insert a invalide certificate : no exception, but check there + * is no alias created with that name + */ + @Test + public void testAddInvalidCert() throws IOException, + GeneralSecurityException, Exceptions.UnknownInput, + Exceptions.InvalidKeystorePassword, Exceptions.UnableToSaveKeystore { + UpdateCertificates uc = new UpdateCertificates(this.ksPassword, + this.ksFilename); + uc.parseLine("+/usr/share/ca-certificates/null.crt"); + uc.writeKeyStore(); + + Assert.assertEquals(false, uc.contains("debian:null.crt")); + } + + /** + * Try to add same certificate multiple time : we replace it and + * there is only one alias. + */ + @Test + public void testReplace() throws IOException, GeneralSecurityException, + Exceptions.UnknownInput, Exceptions.InvalidKeystorePassword, + Exceptions.UnableToSaveKeystore { + UpdateCertificates uc = new UpdateCertificates(this.ksPassword, + this.ksFilename); + uc.parseLine(ADD_CACERT); + uc.parseLine(ADD_CACERT); + uc.writeKeyStore(); + + Assert.assertEquals(true, uc.contains(ALIAS_CACERT)); + } + + /** + * Try to remove a non-existant certificate : it's a no-op. + */ + @Test + public void testRemove() throws IOException, GeneralSecurityException, + Exceptions.UnknownInput, Exceptions.InvalidKeystorePassword, + Exceptions.UnableToSaveKeystore { + UpdateCertificates uc = new UpdateCertificates(this.ksPassword, + this.ksFilename); + uc.parseLine(REMOVE_CACERT); + uc.writeKeyStore(); + + // We start with empty KS, so it shouldn't do anything + Assert.assertEquals(false, uc.contains(ALIAS_CACERT)); + } + + /** + * Try to add cert, write to disk, then open keystore again and remove. + */ + @Test + public void testAddThenRemove() throws IOException, + GeneralSecurityException, Exceptions.UnknownInput, + Exceptions.InvalidKeystorePassword, Exceptions.UnableToSaveKeystore { + UpdateCertificates ucAdd = new UpdateCertificates(this.ksPassword, + this.ksFilename); + ucAdd.parseLine(ADD_CACERT); + ucAdd.writeKeyStore(); + + Assert.assertEquals(true, ucAdd.contains(ALIAS_CACERT)); + + UpdateCertificates ucRemove = new UpdateCertificates(this.ksPassword, + this.ksFilename); + ucRemove.parseLine(REMOVE_CACERT); + ucRemove.writeKeyStore(); + + Assert.assertEquals(false, ucRemove.contains(ALIAS_CACERT)); + } + +} _______________________________________________ pkg-java-commits mailing list [email protected] http://lists.alioth.debian.org/cgi-bin/mailman/listinfo/pkg-java-commits

