forked from pool/ca-certificates
OBS-URL: https://build.opensuse.org/package/show/Base:System/ca-certificates?expand=0&rev=18
241 lines
6.5 KiB
Java
241 lines
6.5 KiB
Java
/*
|
|
* Import system SSL certificates to java keystore
|
|
* Copyright (C) 2010 SUSE LINUX Products GmbH
|
|
*
|
|
* Author: Ludwig Nussel
|
|
*
|
|
* This program is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU General Public License
|
|
* version 2 as published by the Free Software Foundation.
|
|
*
|
|
* 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
*/
|
|
|
|
import java.security.KeyStore;
|
|
import java.io.File;
|
|
import java.io.FileInputStream;
|
|
import java.io.FileOutputStream;
|
|
import java.io.BufferedInputStream;
|
|
import java.io.FilenameFilter;
|
|
import java.util.HashSet;
|
|
import java.util.Enumeration;
|
|
import java.util.Iterator;
|
|
|
|
import java.security.cert.CertificateFactory;
|
|
import java.security.cert.X509Certificate;
|
|
|
|
public class keystore
|
|
{
|
|
static HashSet<String> blacklist;
|
|
|
|
public static void usage() {
|
|
System.err.println("Usage: java keystore -keystore <keystore_file> -cadir <directory> [-storepass <password>|-f|-v]");
|
|
System.err.println("");
|
|
System.err.println(" -keystore <keystore_file>\tname of final keystore (required)");
|
|
System.err.println(" -cadir <directory>\t\tdirectory contains certificates (required)");
|
|
System.err.println(" -storepass <password>\tthe password");
|
|
System.err.println(" -f\t\t\t\tfresh existing keystore");
|
|
System.err.println(" -v\t\t\t\tbe verbose");
|
|
System.err.println(" -h/--help\t\t\tshow this help");
|
|
}
|
|
|
|
public static void main(String[] args)
|
|
throws java.security.KeyStoreException,
|
|
java.security.NoSuchAlgorithmException,
|
|
java.security.cert.CertificateException,
|
|
java.io.IOException
|
|
{
|
|
char[] password = null;
|
|
String ksfilename = null;
|
|
String cadirname = null;
|
|
boolean verbose = false;
|
|
boolean fresh = false;
|
|
|
|
if (args.length == 0) {
|
|
usage();
|
|
System.exit(1);
|
|
}
|
|
|
|
|
|
if (!System.getProperty("java.vendor").equals("Free Software Foundation, Inc.")) {
|
|
password = "changeit".toCharArray();
|
|
}
|
|
|
|
for (int i = 0; i < args.length; ++i) {
|
|
if (args[i].equals("-keystore")) {
|
|
ksfilename = args[++i];
|
|
} else if (args[i].equals("-cadir")) {
|
|
cadirname = args[++i];
|
|
} else if (args[i].equals("-storepass")) {
|
|
password = args[++i].toCharArray();
|
|
} else if (args[i].equals("-v")) {
|
|
verbose = true;
|
|
} else if (args[i].equals("-f")) {
|
|
fresh = true;
|
|
} else if (args[i].equals("-h") || args[i].equals("--help")) {
|
|
usage();
|
|
System.exit(1);
|
|
} else {
|
|
System.err.println("invalid argument: " + args[i]);
|
|
System.err.println("type -h/--help for help");
|
|
System.exit(1);
|
|
}
|
|
}
|
|
|
|
if (ksfilename == null) {
|
|
System.err.println("must specify -keystore");
|
|
return;
|
|
}
|
|
|
|
if (cadirname == null) {
|
|
System.err.println("must specify -cadir");
|
|
return;
|
|
}
|
|
|
|
File cadir = new File(cadirname);
|
|
if (!cadir.isDirectory()) {
|
|
System.err.println("cadir is not a directory");
|
|
return;
|
|
}
|
|
|
|
blacklist = new HashSet<String>();
|
|
// XXX: make a file
|
|
// blacklist.add("foo");
|
|
|
|
String certs[] = cadir.list(new FilenameFilter(){
|
|
public boolean accept(File dir, String name)
|
|
{
|
|
if (!name.endsWith(".pem")) {
|
|
return false;
|
|
}
|
|
if (blacklist.contains(name)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
});
|
|
|
|
KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());
|
|
|
|
FileInputStream storein = null;
|
|
try {
|
|
File f = new File(ksfilename);
|
|
if (!fresh && f.exists()) {
|
|
storein = new FileInputStream(ksfilename);
|
|
}
|
|
ks.load(storein, password);
|
|
} finally {
|
|
if (storein != null) {
|
|
storein.close();
|
|
}
|
|
}
|
|
|
|
HashSet<String> known = new HashSet<String>();
|
|
for (Enumeration<String> a = ks.aliases(); a.hasMoreElements();) {
|
|
known.add(a.nextElement());
|
|
}
|
|
|
|
CertificateFactory cf = CertificateFactory.getInstance("X509");
|
|
int added = 0;
|
|
int removed = 0;
|
|
|
|
for (int i = 0; i < certs.length; ++i) {
|
|
BufferedInputStream f;
|
|
try {
|
|
f = new BufferedInputStream(new FileInputStream(cadirname+"/"+certs[i]));
|
|
} catch (java.io.FileNotFoundException ex) {
|
|
System.err.println("skipping " + certs[i] + ": file not found");
|
|
continue;
|
|
}
|
|
String marker = "-----BEGIN CERTIFICATE-----";
|
|
boolean found = false;
|
|
|
|
f.mark(80);
|
|
String line;
|
|
String alias = null;
|
|
// we need to parse and skip the "header"
|
|
while((line = readline(f)) != null) {
|
|
if (line.equals(marker)) {
|
|
f.reset();
|
|
found = true;
|
|
break;
|
|
} else if (line.startsWith("# alias=")) {
|
|
// FIXME: somehow UTF-8 encoding must be enforced here
|
|
alias = line.substring(8);
|
|
}
|
|
f.mark(80);
|
|
}
|
|
if (found) {
|
|
if (alias == null) {
|
|
alias = certs[i].substring(0, certs[i].length()-4); // without .pem
|
|
}
|
|
alias = alias.toLowerCase();
|
|
try {
|
|
X509Certificate cert = (X509Certificate)cf.generateCertificate(f);
|
|
if (known.contains(alias)) {
|
|
if (verbose)
|
|
System.out.println("already known: " + alias);
|
|
known.remove(alias);
|
|
} else {
|
|
if (verbose)
|
|
System.out.println("adding " + alias);
|
|
ks.setCertificateEntry(alias, cert);
|
|
++added;
|
|
}
|
|
} catch (java.security.cert.CertificateException ex) {
|
|
System.err.println("imporing " + certs[i] + " failed: " + ex.getCause());
|
|
}
|
|
} else {
|
|
System.out.println("skipping file with unrecognized format: " + certs[i]);
|
|
}
|
|
}
|
|
|
|
if (!known.isEmpty()) {
|
|
for (Iterator<String> it = known.iterator(); it.hasNext();) {
|
|
String alias = it.next();
|
|
if (verbose)
|
|
System.out.println("removing " + alias);
|
|
ks.deleteEntry(alias);
|
|
++removed;
|
|
}
|
|
}
|
|
|
|
if (added != 0 || removed != 0) {
|
|
FileOutputStream storeout = new FileOutputStream(ksfilename);
|
|
ks.store(storeout, password);
|
|
storeout.close();
|
|
}
|
|
|
|
System.out.println(added + " added, " + removed + " removed.");
|
|
}
|
|
|
|
public static String readline(BufferedInputStream in)
|
|
throws java.io.IOException
|
|
{
|
|
StringBuffer buf = new StringBuffer(80);
|
|
int c = in.read();
|
|
while(c != -1 && c != '\n' && c != '\r') {
|
|
buf.append((char)c);
|
|
c = in.read();
|
|
}
|
|
if (c == '\r') {
|
|
in.mark(1);
|
|
c = in.read();
|
|
if (c != '\n')
|
|
in.reset();
|
|
}
|
|
if (buf.length() == 0)
|
|
return null;
|
|
|
|
return buf.toString();
|
|
}
|
|
}
|