summaryrefslogtreecommitdiff
path: root/BKUWebStart/src/main/java/at
diff options
context:
space:
mode:
authorclemenso <clemenso@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4>2009-08-13 09:19:28 +0000
committerclemenso <clemenso@8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4>2009-08-13 09:19:28 +0000
commit79016a7b2f9d89e52e991b0abdfc73ad24e60979 (patch)
tree96c5a625181af1f4d8da241eb53281bf22bbbda1 /BKUWebStart/src/main/java/at
parentec680d62e3e2564d0854b2d34827d7d61f84b709 (diff)
downloadmocca-79016a7b2f9d89e52e991b0abdfc73ad24e60979.tar.gz
mocca-79016a7b2f9d89e52e991b0abdfc73ad24e60979.tar.bz2
mocca-79016a7b2f9d89e52e991b0abdfc73ad24e60979.zip
[#433] update BKU Web Start CertStore
WebStart configuration refactored git-svn-id: https://joinup.ec.europa.eu/svn/mocca/trunk@423 8a26b1a7-26f0-462f-b9ef-d0e30c41f5a4
Diffstat (limited to 'BKUWebStart/src/main/java/at')
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/BKULauncher.java418
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java418
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java75
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java230
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java440
-rw-r--r--BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/ui/TrayIconDialog.java2
6 files changed, 1151 insertions, 432 deletions
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/BKULauncher.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/BKULauncher.java
deleted file mode 100644
index abc0b8ee..00000000
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/BKULauncher.java
+++ /dev/null
@@ -1,418 +0,0 @@
-package at.gv.egiz.bku.webstart;
-
-import iaik.asn1.CodingException;
-import java.io.File;
-import java.io.FileNotFoundException;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.io.OutputStream;
-import java.net.MalformedURLException;
-import java.security.KeyStore;
-import java.security.KeyStoreException;
-import java.security.NoSuchAlgorithmException;
-import java.security.cert.CertificateException;
-import java.util.Enumeration;
-import java.util.Locale;
-import java.util.MissingResourceException;
-import java.util.ResourceBundle;
-import java.util.logging.Level;
-import java.util.logging.Logger;
-import java.util.zip.ZipEntry;
-import java.util.zip.ZipFile;
-
-//import org.apache.commons.cli.CommandLine;
-//import org.apache.commons.cli.CommandLineParser;
-//import org.apache.commons.cli.HelpFormatter;
-//import org.apache.commons.cli.Options;
-//import org.apache.commons.cli.ParseException;
-//import org.apache.commons.cli.PosixParser;
-import org.apache.commons.logging.Log;
-import org.apache.commons.logging.LogFactory;
-
-import at.gv.egiz.bku.webstart.ui.BKUControllerInterface;
-import at.gv.egiz.bku.webstart.ui.TrayIconDialog;
-import at.gv.egiz.bku.utils.StreamUtil;
-import java.awt.Desktop;
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
-import java.io.BufferedWriter;
-import java.io.FileInputStream;
-import java.io.FileReader;
-import java.io.FileWriter;
-import java.net.BindException;
-import java.net.URI;
-import java.net.URL;
-import java.security.GeneralSecurityException;
-import java.util.UUID;
-import java.util.jar.Attributes;
-import java.util.jar.Manifest;
-import java.util.zip.ZipOutputStream;
-import org.mortbay.util.MultiException;
-
-public class BKULauncher implements BKUControllerInterface {
-
- /** configurations with less than this (major) version will be backuped and updated */
- public static final String MIN_CONFIG_VERSION = "1.0.3";
- public static final String CONFIG_DIR = ".mocca/conf/";
- public static final String CONF_TEMPLATE_FILE = "configuration.zip";
- public static final String CONF_TEMPLATE_RESOURCE = "at/gv/egiz/bku/webstart/conf/configuration.zip";
- public static final String WEBAPP_RESOURCE = "BKULocal.war";
- public static final String WEBAPP_FILE = "BKULocal.war";
- public static final String KEYSTORE_FILE = "keystore.ks";
- public static final String MESSAGES_RESOURCE = "at/gv/egiz/bku/webstart/ui/UIMessages";
- public static final String PASSWD_FILE = ".secret";
- /** resource bundle messages */
- public static final String GREETING_CAPTION = "Greetings.Caption";
- public static final String GREETING_MESSAGE = "Greetings.Message";
- public static final String STARTUP_CAPTION = "Startup.Caption";
- public static final String ERROR_CAPTION = "Error.Caption";
- public static final String STARTUP_MESSAGE = "Startup.Message";
- public static final String ERROR_STARTUP_MESSAGE = "Error.Startup.Message";
- public static final String ERROR_CONF_MESSAGE = "Error.Conf.Message";
- public static final String ERROR_BIND_MESSAGE = "Error.Bind.Message";
- public static final String VERSION_FILE = ".version";
- private static Log log = LogFactory.getLog(BKULauncher.class);
- private ResourceBundle resourceBundle = null;
- private Container server;
-
- private void createConfig(File configDir, File versionFile, String version) throws IOException, CertificateException, GeneralSecurityException, KeyStoreException, FileNotFoundException, NoSuchAlgorithmException {
- log.debug("creating config directory: " + configDir);
- configDir.mkdirs();
- InputStream is = getClass().getClassLoader().getResourceAsStream(CONF_TEMPLATE_RESOURCE);
- OutputStream os = new FileOutputStream(new File(configDir, CONF_TEMPLATE_FILE));
- StreamUtil.copyStream(is, os);
- os.close();
- File confTemplateFile = new File(configDir, CONF_TEMPLATE_FILE);
- unzip(confTemplateFile);
- confTemplateFile.delete();
- writeVersionFile(versionFile, version);
- }
-
- private void createCertificates(File configDir) throws IOException, GeneralSecurityException, CodingException {
- char[] password = UUID.randomUUID().toString().toCharArray();
- File passwdFile = new File(configDir, PASSWD_FILE);
- FileWriter passwdWriter = new FileWriter(passwdFile);
- passwdWriter.write(password);
- passwdWriter.close();
- if (!passwdFile.setReadable(true, true)) {
- passwdFile.delete();
- throw new IOException("failed to make " + passwdFile + " owner readable only, deleting file");
- }
- TLSServerCA ca = new TLSServerCA();
- KeyStore ks = ca.generateKeyStore(password);
- FileOutputStream fos = new FileOutputStream(new File(configDir, KEYSTORE_FILE));
- ks.store(fos, password);
- fos.close();
- }
-
- private String getFileVersion(File versionFile) throws FileNotFoundException, IOException {
- //TODO no file?
- if (versionFile.exists() && versionFile.canRead()) {
- BufferedReader versionReader = new BufferedReader(new FileReader(versionFile));
- String versionString = null;
- while ((versionString = versionReader.readLine().trim()) != null) {
- if (versionString.length() > 0 && !versionString.startsWith("#")) {
- log.debug("found existing configuration version " + versionString);
- break;
- }
- }
- return versionString;
- }
- return null;
- }
-
- private String getManifestVersion() throws MalformedURLException, IOException {
- String bkuWebStartJar = BKULauncher.class.getProtectionDomain().getCodeSource().getLocation().toString();
- URL manifestURL = new URL("jar:" + bkuWebStartJar + "!/META-INF/MANIFEST.MF");
- String version = null;
- if (manifestURL != null) {
- Manifest manifest = new Manifest(manifestURL.openStream());
- if (log.isTraceEnabled()) {
- log.trace("read version information from " + manifestURL);
- }
- Attributes atts = manifest.getMainAttributes();
- if (atts != null) {
- version = atts.getValue("Implementation-Build");
- }
- }
- if (version == null) {
- version = "UNKNOWN";
- }
- log.debug("config version: " + version);
- return version;
- }
-
- /**
- * change the
- * @param oldVersion
- * @param newVersion
- * @return
- */
- private boolean updateRequired(String oldVersion, String newVersion) {
- if (oldVersion != null) {
- log.debug("comparing " + oldVersion + " to " + MIN_CONFIG_VERSION);
-
- int majorEnd = oldVersion.indexOf('-');
- String oldMajor = (majorEnd < 0) ? oldVersion : oldVersion.substring(0, majorEnd);
-
- int compare = oldMajor.compareTo(MIN_CONFIG_VERSION);
- if (compare < 0 ||
- // SNAPSHOT versions are pre-releases (update if release required)
- (compare == 0 && oldVersion.startsWith("-SNAPSHOT", majorEnd))) {
- return true;
- } else {
- return false;
- }
- }
- log.debug("no old version, update required");
- return true;
- }
-
- private boolean updateRequiredStrict(String oldVersion, String newVersion) {
- String[] oldV = oldVersion.split("-");
- String[] newV = newVersion.split("-");
- log.debug("comparing " + oldV[0] + " to " + newV[0]);
- if (oldV[0].compareTo(newV[0]) < 0) {
- log.debug("update required");
- return true;
- } else {
- log.debug("comparing " + oldV[oldV.length - 1] + " to " + newV[newV.length - 1]);
- if (oldV[oldV.length - 1].compareTo(newV[newV.length - 1]) < 0) {
- log.debug("update required");
- return true;
- } else {
- log.debug("no update required");
- return false;
- }
- }
- }
-
- private void writeVersionFile(File versionFile, String version) throws IOException {
- BufferedWriter versionWriter = new BufferedWriter(new FileWriter(versionFile));
- versionWriter.write("# MOCCA Web Start configuration version\n");
- versionWriter.write("# DO NOT MODIFY THIS FILE\n\n");
- versionWriter.write(version);
- versionWriter.close();
- }
-
-// private SplashScreen splash = SplashScreen.getSplashScreen();
- private void startUpServer() throws Exception {
- log.info("init servlet container and MOCCA webapp");
- server = new Container();
- // XmlConfiguration xcfg = new XmlConfiguration(getClass().getClassLoader()
- // .getResourceAsStream("at/gv/egiz/bku/local/app/jetty.xml"));
- // xcfg.configure(server);
- server.init();
- server.start();
- }
-
- private void initTrayIcon() {
- log.debug("init MOCCA tray icon");
- Locale loc = Locale.getDefault();
- try {
- resourceBundle = ResourceBundle.getBundle(
- MESSAGES_RESOURCE, loc);
- } catch (MissingResourceException mx) {
- resourceBundle = ResourceBundle.getBundle(
- MESSAGES_RESOURCE, Locale.ENGLISH);
- }
- TrayIconDialog.getInstance().init(resourceBundle);
- TrayIconDialog.getInstance().setShutdownHook(this);
-// TrayIconDialog.getInstance().displayInfo(GREETING_CAPTION, GREETING_MESSAGE);
- }
-
- private void initStart() {
- }
-
- private void initFinished(boolean installCert) {
- try {
-// if (splash != null) {
-// try {
-// splash.close();
-// } catch (IllegalStateException ex) {
-// log.warn("Failed to close splash screen: " + ex.getMessage());
-// }
-// }
-
- if (installCert) {
- log.debug("trying install MOCCA certificate on system browser");
- if (Desktop.isDesktopSupported()) {
- Desktop desktop = Desktop.getDesktop();
- if (desktop.isSupported(Desktop.Action.BROWSE)) {
- try {
- desktop.browse(new URI("https://localhost:" +
- Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3496).intValue()));
- } catch (Exception ex) {
- log.error("failed to open system browser, install MOCCA certificate manually", ex);
- }
- } else {
- log.error("failed to open system browser, install MOCCA certificate manually");
- }
- } else {
- log.error("failed to open system browser, install MOCCA certificate manually");
- }
- }
-
- log.info("init completed, joining server");
- server.join();
- } catch (InterruptedException e) {
- log.warn("failed to join MOCCA server: " + e.getMessage(), e);
- }
- }
-
- private void unzip(File zipfile) throws IOException {
- File dir = zipfile.getParentFile();
- ZipFile zipFile = new ZipFile(zipfile);
- Enumeration<? extends ZipEntry> entries = zipFile.entries();
- while (entries.hasMoreElements()) {
- ZipEntry entry = entries.nextElement();
- File eF = new File(dir, entry.getName());
- if (entry.isDirectory()) {
- eF.mkdirs();
- continue;
- }
- File f = new File(eF.getParent());
- f.mkdirs();
- StreamUtil.copyStream(zipFile.getInputStream(entry),
- new FileOutputStream(eF));
- }
- zipFile.close();
- }
-
- /**
- * @param args
- */
- public static void main(String[] args) throws InterruptedException {
-
- if (log.isDebugEnabled()) {
- //System.setProperty("DEBUG", "true");
- System.setProperty("VERBOSE", "true");
- System.setProperty("javax.net.debug", "ssl,handshake");
- }
-
-// log.warn("***** DISABLING SECURITY MANAGER *******");
- System.setSecurityManager(null);
-
- BKULauncher launcher = new BKULauncher();
- launcher.initStart();
-
- boolean installCert = false;
-
- launcher.initTrayIcon();
- TrayIconDialog.getInstance().displayInfo(STARTUP_CAPTION, STARTUP_MESSAGE);
-
- try {
- File configDir = new File(System.getProperty("user.home") + '/' + CONFIG_DIR);
- installCert = launcher.ensureConfig(configDir);
- } catch (Exception ex) {
- log.fatal("Failed to init MOCCA configuration, exiting", ex);
- TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_CONF_MESSAGE);
- Thread.sleep(5000);
- System.exit(-1000);
- }
-
- try {
- launcher.startUpServer();
- TrayIconDialog.getInstance().displayInfo(GREETING_CAPTION, GREETING_MESSAGE);
- launcher.initFinished(installCert);
- } catch (BindException ex) {
- log.fatal("Failed to launch MOCCA, " + ex.getMessage(), ex);
- TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_BIND_MESSAGE);
- Thread.sleep(5000);
- System.exit(-1000);
- } catch (MultiException ex) {
- log.fatal("Failed to launch MOCCA, " + ex.getMessage(), ex);
- if (ex.getThrowable(0) instanceof BindException) {
- TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_BIND_MESSAGE);
- } else {
- TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_STARTUP_MESSAGE);
- }
- Thread.sleep(5000);
- System.exit(-1000);
- } catch (Exception e) {
- log.fatal("Failed to launch MOCCA, " + e.getMessage(), e);
- TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_STARTUP_MESSAGE);
- Thread.sleep(5000);
- System.exit(-1000);
- }
-
- }
-
- private void backupAndDelete(File dir, URI relativeTo, ZipOutputStream zip) throws IOException {
- if (dir.isDirectory()) {
- File[] subDirs = dir.listFiles();
- for (File subDir : subDirs) {
- backupAndDelete(subDir, relativeTo, zip);
- subDir.delete();
- }
- } else {
- URI relativePath = relativeTo.relativize(dir.toURI());
- ZipEntry entry = new ZipEntry(relativePath.toString());
- zip.putNextEntry(entry);
- BufferedInputStream entryIS = new BufferedInputStream(new FileInputStream(dir));
- StreamUtil.copyStream(entryIS, zip);
- entryIS.close();
- zip.closeEntry();
- dir.delete();
- }
- }
-
- /**
- * Checks whether the config directory already exists and creates it otherwise.
- * @param configDir the config directory to be created
- * @return true if a new MOCCA cert was created (and needs to be installed in the browser)
- */
- private boolean ensureConfig(File configDir) throws IOException, GeneralSecurityException, CodingException {
- log.debug("config directory: " + configDir);
- String manifestVersion = getManifestVersion();
- File versionFile = new File(configDir, VERSION_FILE);
-
- if (configDir.exists()) {
- if (configDir.isFile()) {
- log.error("invalid config directory: " + configDir);
- throw new IOException("invalid config directory: " + configDir);
- } else {
- String fileVersion = getFileVersion(versionFile);
- if (updateRequired(fileVersion, manifestVersion)) {
- if (fileVersion == null) {
- fileVersion = "unknown";
- }
- log.info("updating configuration from " + fileVersion + " to " + manifestVersion);
- File moccaDir = configDir.getParentFile();
- File zipFile = new File(moccaDir, "conf-" + fileVersion + ".zip");
- ZipOutputStream zipOS = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
- backupAndDelete(configDir, moccaDir.toURI(), zipOS);
- zipOS.close();
- createConfig(configDir, versionFile, manifestVersion);
- createCertificates(configDir);
- return true;
- }
- }
- } else {
- createConfig(configDir, versionFile, manifestVersion);
- createCertificates(configDir);
- return true;
- }
- return false;
- }
-
- public void shutDown() {
- log.info("Shutting down server");
- if ((server != null) && (server.isRunning())) {
- try {
- if (server.isRunning()) {
- server.stop();
- }
- } catch (Exception e) {
- log.debug(e.toString());
- } finally {
- if (server.isRunning()) {
- server.destroy();
- }
- }
- }
- System.exit(0);
- }
-}
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
new file mode 100644
index 00000000..ab1746ed
--- /dev/null
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.java
@@ -0,0 +1,418 @@
+/*
+ * 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.webstart;
+
+import at.gv.egiz.bku.utils.StreamUtil;
+import iaik.asn1.CodingException;
+import iaik.xml.crypto.utils.Utils;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.KeyStore;
+import java.util.Enumeration;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+import java.util.UUID;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+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.eclipse.jdt.core.dom.ThisExpression;
+
+/**
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class Configurator {
+
+ /**
+ * MOCCA configuration
+ * configurations with less than this (major) version will be backuped and updated
+ * allowed: MAJOR[.MINOR[.X[-SNAPSHOT]]]
+ */
+ public static final String MIN_CONFIG_VERSION = "1.0.9-SNAPSHOT";
+ public static final String CONFIG_DIR = ".mocca/conf/";
+ public static final String CERTS_DIR = ".mocca/certs/";
+ public static final String VERSION_FILE = ".version";
+ public static final String UNKOWN_VERSION = "unknown";
+ public static final String CONF_TEMPLATE_FILE = "conf-tmp.zip";
+ public static final String CONF_TEMPLATE_RESOURCE = "at/gv/egiz/bku/webstart/conf/conf.zip";
+ public static final String CERTIFICATES_PKG = "at/gv/egiz/bku/certs";
+
+ /**
+ * MOCCA TLS certificate
+ */
+ public static final String KEYSTORE_FILE = "keystore.ks";
+ public static final String PASSWD_FILE = ".secret";
+
+ private static final Log log = LogFactory.getLog(Configurator.class);
+
+ /** currently installed configuration version */
+ private String version;
+ private String certsVersion;
+ /** whether a new MOCCA TLS cert was created during initialization */
+ private boolean certRenewed = false;
+
+ /**
+ * Checks whether the config directory already exists and creates it otherwise.
+ * @param configDir the config directory to be created
+ * @throws IOException config/certificate creation failed
+ * @throws GeneralSecurityException if MOCCA TLS certificate could not be created
+ * @throws CodingException if MOCCA TLS certificate could not be created
+ */
+ public void ensureConfiguration() throws IOException, CodingException, GeneralSecurityException {
+ File configDir = new File(System.getProperty("user.home") + '/' + CONFIG_DIR);
+ if (configDir.exists()) {
+ if (configDir.isFile()) {
+ log.error("invalid config directory: " + configDir);
+ throw new IOException("invalid config directory: " + configDir);
+ } else {
+ version = readVersion(new File(configDir, VERSION_FILE));
+ if (log.isDebugEnabled()) {
+ log.debug("config directory " + configDir + ", version " + version);
+ }
+ if (updateRequired(version)) {
+ File moccaDir = configDir.getParentFile();
+ File zipFile = new File(moccaDir, "conf-" + version + ".zip");
+ ZipOutputStream zipOS = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
+ log.info("backup configuration to " + zipFile);
+ backupAndDelete(configDir, moccaDir.toURI(), zipOS);
+ zipOS.close();
+ initConfig(configDir);
+ }
+ }
+ } else {
+ initConfig(configDir);
+ }
+ }
+
+ /**
+ * To be replaced by TSLs in IAIK-PKI
+ * @throws IOException
+ */
+ public void ensureCertificates() throws IOException {
+ File certsDir = new File(System.getProperty("user.home") + '/' + CERTS_DIR);
+ if (certsDir.exists()) {
+ if (certsDir.isFile()) {
+ log.error("invalid certificate store directory: " + certsDir);
+ throw new IOException("invalid config directory: " + certsDir);
+ } else {
+ certsVersion = readVersion(new File(certsDir, VERSION_FILE));
+ if (log.isDebugEnabled()) {
+ log.debug("certificate-store directory " + certsDir + ", version " + certsVersion);
+ }
+ String newCertsVersion = getCertificatesVersion();
+ if (updateRequiredStrict(certsVersion, newCertsVersion)) {
+ File moccaDir = certsDir.getParentFile();
+ File zipFile = new File(moccaDir, "certs-" + certsVersion + ".zip");
+ ZipOutputStream zipOS = new ZipOutputStream(new BufferedOutputStream(new FileOutputStream(zipFile)));
+ log.info("backup certificates to " + zipFile);
+ backupAndDelete(certsDir, moccaDir.toURI(), zipOS);
+ zipOS.close();
+
+ createCerts(certsDir, newCertsVersion);
+ certsVersion = newCertsVersion;
+ }
+ }
+ } else {
+ String newCertsVersion = getCertificatesVersion();
+ createCerts(certsDir, newCertsVersion);
+ certsVersion = newCertsVersion;
+ }
+ }
+
+ /**
+ *
+ * @return whether a new MOCCA TLS certificate has been created during initialization
+ */
+ public boolean isCertRenewed() {
+ return certRenewed;
+ }
+
+ /**
+ * @return The first valid (not empty, no comment) line of the version file or
+ * "unknown" if version file cannot be read or does not contain such a line.
+ */
+ protected static String readVersion(File versionFile) {
+ if (versionFile.exists() && versionFile.canRead()) {
+ BufferedReader versionReader = null;
+ try {
+ versionReader = new BufferedReader(new FileReader(versionFile));
+ String version;
+ while ((version = versionReader.readLine().trim()) != null) {
+ if (version.length() > 0 && !version.startsWith("#")) {
+ log.debug("configuration version from " + versionFile + ": " + version);
+ return version;
+ }
+ }
+ } catch (IOException ex) {
+ log.error("failed to read configuration version from " + versionFile, ex);
+ } finally {
+ try {
+ versionReader.close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+ log.debug("unknown configuration version");
+ return UNKOWN_VERSION;
+ }
+
+ /**
+ * Temporary workaround, replace with TSLs in IAIK-PKI.
+ * Retrieves version from BKUCertificates.jar Manifest file.
+ * The (remote) resource URL will be handled by the JNLP loader,
+ * and the resource retrieved from the cache.
+ *
+ * @return
+ * @throws IOException
+ */
+ private static String getCertificatesVersion() throws IOException {
+ String certsResourceVersion = null;
+ URL certsURL = Configurator.class.getClassLoader().getResource(CERTIFICATES_PKG);
+ if (certsURL != null) {
+ StringBuilder url = new StringBuilder(certsURL.toExternalForm());
+ url = url.replace(url.length() - CERTIFICATES_PKG.length(), url.length(), "META-INF/MANIFEST.MF");
+ log.trace("retrieve certificates resource version from " + url);
+ certsURL = new URL(url.toString());
+ Manifest certsManifest = new Manifest(certsURL.openStream());
+ Attributes atts = certsManifest.getMainAttributes();
+ if (atts != null) {
+ certsResourceVersion = atts.getValue("Implementation-Version");
+ log.debug("certs resource version: " + certsResourceVersion);
+ }
+ } else {
+ log.error("Failed to retrieve certificates resource " + CERTIFICATES_PKG);
+ throw new IOException("Failed to retrieve certificates resource " + CERTIFICATES_PKG);
+ }
+ return certsResourceVersion;
+ }
+
+ protected static boolean updateRequired(String oldVersion) {
+ log.debug("comparing " + oldVersion + " to " + MIN_CONFIG_VERSION);
+ if (oldVersion != null && !UNKOWN_VERSION.equals(oldVersion)) {
+
+ int majorEnd = oldVersion.indexOf('-');
+ String oldMajor = (majorEnd < 0) ? oldVersion : oldVersion.substring(0, majorEnd);
+
+ String minMajor = MIN_CONFIG_VERSION;
+ boolean releaseRequired = true;
+ if (MIN_CONFIG_VERSION.endsWith("-SNAPSHOT")) {
+ releaseRequired = false;
+ minMajor = minMajor.substring(0, minMajor.length() - 9);
+ }
+
+ int compare = oldMajor.compareTo(minMajor);
+ if (compare < 0 ||
+ // SNAPSHOT versions are pre-releases (update if release required)
+ (compare == 0 && releaseRequired && oldVersion.startsWith("-SNAPSHOT", majorEnd))) {
+ log.debug("configuration update required");
+ return true;
+ } else {
+ log.debug("configuration up to date");
+ return false;
+ }
+ }
+ log.debug("no old version, configuration update required");
+ return true;
+ }
+
+ /**
+ * if unknown old, update in any case
+ * if known old and unknown new, don't update
+ * @param oldVersion
+ * @param newVersion
+ * @return
+ */
+ private boolean updateRequiredStrict(String oldVersion, String newVersion) {
+ log.debug("comparing " + oldVersion + " to " + newVersion);
+ if (oldVersion != null && !UNKOWN_VERSION.equals(oldVersion)) {
+ if (newVersion != null && !UNKOWN_VERSION.equals(newVersion)) {
+ String[] oldV = oldVersion.split("-");
+ String[] newV = newVersion.split("-");
+ log.trace("comparing " + oldV[0] + " to " + newV[0]);
+ if (oldV[0].compareTo(newV[0]) < 0) {
+ log.debug("update required");
+ return true;
+ } else {
+ log.trace("comparing " + oldV[oldV.length - 1] + " to " + newV[newV.length - 1]);
+ if (oldV[oldV.length - 1].compareTo(newV[newV.length - 1]) < 0) {
+ log.debug("update required");
+ return true;
+ } else {
+ log.debug("no update required");
+ return false;
+ }
+ }
+ }
+ log.debug("unknown new version, do not update");
+ return true;
+ }
+ log.debug("unknown old version, update required");
+ return true;
+ }
+
+ protected static void backupAndDelete(File dir, URI relativeTo, ZipOutputStream zip) throws IOException {
+ if (dir.isDirectory()) {
+ File[] subDirs = dir.listFiles();
+ for (File subDir : subDirs) {
+ backupAndDelete(subDir, relativeTo, zip);
+ subDir.delete();
+ }
+ } else {
+ URI relativePath = relativeTo.relativize(dir.toURI());
+ ZipEntry entry = new ZipEntry(relativePath.toString());
+ zip.putNextEntry(entry);
+ BufferedInputStream entryIS = new BufferedInputStream(new FileInputStream(dir));
+ StreamUtil.copyStream(entryIS, zip);
+ entryIS.close();
+ zip.closeEntry();
+ dir.delete();
+ }
+ }
+
+ /**
+ * set up a new MOCCA local configuration
+ * (not to be called directly, call ensureConfiguration())
+ * @throws IOException config/certificate creation failed
+ * @throws GeneralSecurityException if MOCCA TLS certificate could not be created
+ * @throws CodingException if MOCCA TLS certificate could not be created
+ */
+ protected void initConfig(File configDir) throws IOException, GeneralSecurityException, CodingException {
+ createConfig(configDir, Launcher.version);
+ version = Launcher.version;
+ createKeyStore(configDir);
+ certRenewed = true;
+ }
+
+ private static void createConfig(File configDir, String version) throws IOException {
+ if (log.isDebugEnabled()) {
+ log.debug("creating configuration version " + Launcher.version + " in " + configDir );
+ }
+ configDir.mkdirs();
+ 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);
+ os.close();
+ unzip(confTemplateFile, configDir);
+ confTemplateFile.delete();
+ writeVersionFile(new File(configDir, VERSION_FILE), version);
+ }
+
+ /**
+ * set up a new MOCCA local certStore
+ * @throws IOException config/certificate creation failed
+ * @throws GeneralSecurityException if MOCCA TLS certificate could not be created
+ * @throws CodingException if MOCCA TLS certificate could not be created
+ */
+ private static void createCerts(File certsDir, String certsVersion) throws IOException {
+ if (log.isDebugEnabled()) {
+ log.debug("creating certificate-store " + certsDir + ", version " + certsVersion);
+ }
+ URL certsURL = Configurator.class.getClassLoader().getResource(CERTIFICATES_PKG);
+ if (certsURL != null) {
+ StringBuilder url = new StringBuilder(certsURL.toExternalForm());
+ url = url.replace(url.length() - CERTIFICATES_PKG.length(), url.length(), "META-INF/MANIFEST.MF");
+ log.debug("retrieve certificate resource names from " + url);
+ certsURL = new URL(url.toString());
+ Manifest certsManifest = new Manifest(certsURL.openStream());
+ certsDir.mkdirs();
+ Iterator<String> entries = certsManifest.getEntries().keySet().iterator();
+ while (entries.hasNext()) {
+ String entry = entries.next();
+ if (entry.startsWith(CERTIFICATES_PKG)) {
+ String f = entry.substring(CERTIFICATES_PKG.length()); // "/trustStore/..."
+ 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);
+ bos.close();
+ } else {
+ log.trace("ignore " + entry);
+ }
+ }
+ writeVersionFile(new File(certsDir, VERSION_FILE), certsVersion);
+ } else {
+ log.error("Failed to retrieve certificates resource " + CERTIFICATES_PKG);
+ throw new IOException("Failed to retrieve certificates resource " + CERTIFICATES_PKG);
+ }
+ }
+
+ private static void unzip(File zipfile, File toDir) throws IOException {
+ ZipFile zipFile = new ZipFile(zipfile);
+ Enumeration<? extends ZipEntry> entries = zipFile.entries();
+ while (entries.hasMoreElements()) {
+ ZipEntry entry = entries.nextElement();
+ File eF = new File(toDir, entry.getName());
+ if (entry.isDirectory()) {
+ eF.mkdirs();
+ continue;
+ }
+ File f = new File(eF.getParent());
+ f.mkdirs();
+ StreamUtil.copyStream(zipFile.getInputStream(entry),
+ new FileOutputStream(eF));
+ }
+ zipFile.close();
+ }
+
+ private static void writeVersionFile(File versionFile, String version) throws IOException {
+ BufferedWriter versionWriter = new BufferedWriter(new FileWriter(versionFile));
+ versionWriter.write("# MOCCA Web Start configuration version\n");
+ versionWriter.write("# DO NOT MODIFY THIS FILE\n\n");
+ versionWriter.write(version);
+ versionWriter.close();
+ }
+
+ private static void createKeyStore(File configDir) throws IOException, GeneralSecurityException, CodingException {
+ char[] password = UUID.randomUUID().toString().toCharArray();
+ File passwdFile = new File(configDir, PASSWD_FILE);
+ FileWriter passwdWriter = new FileWriter(passwdFile);
+ passwdWriter.write(password);
+ passwdWriter.close();
+ if (!passwdFile.setReadable(false, false) || !passwdFile.setReadable(true, true)) {
+ passwdFile.delete();
+ throw new IOException("failed to make " + passwdFile + " owner readable only, deleting file");
+ }
+ TLSServerCA ca = new TLSServerCA();
+ KeyStore ks = ca.generateKeyStore(password);
+ File ksFile = new File(configDir, KEYSTORE_FILE);
+ FileOutputStream fos = new FileOutputStream(ksFile);
+ ks.store(fos, password);
+ fos.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 89044486..4df90ab2 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,22 +1,28 @@
package at.gv.egiz.bku.webstart;
import at.gv.egiz.bku.utils.StreamUtil;
+import java.awt.AWTPermission;
import java.io.BufferedOutputStream;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
+import java.io.FilePermission;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
+import java.lang.reflect.ReflectPermission;
+import java.net.NetPermission;
+import java.net.SocketPermission;
+import java.security.Permissions;
+import java.security.SecurityPermission;
+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.Handler;
import org.mortbay.jetty.Server;
-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.WebAppContext;
@@ -28,12 +34,18 @@ public class Container {
public static final String HTTPS_PORT_PROPERTY = "mocca.http.port";
private static Log log = LogFactory.getLog(Container.class);
+ static {
+ if (log.isDebugEnabled()) {
+ //Jetty log INFO and WARN, include ignored exceptions
+ //jetty logging may be further restricted by setting level in log4j.properties
+ System.setProperty("VERBOSE", "true");
+ //do not set Jetty DEBUG logging, produces loads of output
+ //System.setProperty("DEBUG", "true");
+ }
+ }
private Server server;
- public Container() {
- }
-
public void init() throws IOException {
// System.setProperty("DEBUG", "true");
server = new Server();
@@ -55,15 +67,15 @@ public class Container {
sslConnector.setPort(Integer.getInteger(HTTPS_PORT_PROPERTY, 3496).intValue());
sslConnector.setAcceptors(1);
sslConnector.setHost("127.0.0.1");
- File configDir = new File(System.getProperty("user.home") + "/" + BKULauncher.CONFIG_DIR);
- File keystoreFile = new File(configDir, BKULauncher.KEYSTORE_FILE);
+ File configDir = new File(System.getProperty("user.home") + "/" + Configurator.CONFIG_DIR);
+ File keystoreFile = new File(configDir, Configurator.KEYSTORE_FILE);
if (!keystoreFile.canRead()) {
log.error("MOCCA keystore file not readable: " + keystoreFile.getAbsolutePath());
throw new FileNotFoundException("MOCCA keystore file not readable: " + keystoreFile.getAbsolutePath());
}
log.debug("loading MOCCA keystore from " + keystoreFile.getAbsolutePath());
sslConnector.setKeystore(keystoreFile.getAbsolutePath());
- File passwdFile = new File(configDir, BKULauncher.PASSWD_FILE);
+ File passwdFile = new File(configDir, Configurator.PASSWD_FILE);
BufferedReader reader = new BufferedReader(new FileReader(passwdFile));
String pwd;
while ((pwd = reader.readLine()) != null) {
@@ -107,7 +119,6 @@ public class Container {
sslConnector.setExcludeCipherSuites(RFC4492CipherSuites);
-
server.setConnectors(new Connector[] { connector, sslConnector });
WebAppContext webapp = new WebAppContext();
@@ -116,13 +127,13 @@ public class Container {
webapp.setExtractWAR(true);
webapp.setParentLoaderPriority(false);
- webapp.setWar(copyWebapp(webapp.getTempDirectory())); //getClass().getClassLoader().getResource("BKULocalWar/").toString());
-
+ webapp.setWar(copyWebapp(webapp.getTempDirectory()));
+ webapp.setPermissions(getPermissions(webapp.getTempDirectory()));
+
server.setHandler(webapp);
server.setGracefulShutdown(1000*3);
}
-
private String copyWebapp(File webappDir) throws IOException {
File webapp = new File(webappDir, "BKULocal.war");
log.debug("copying BKULocal classpath resource to " + webapp);
@@ -133,6 +144,44 @@ public class Container {
return webapp.getPath();
}
+ private Permissions getPermissions(File webappDir) {
+ Permissions perms = new Permissions();
+
+ // jetty-webstart (spring?)
+ perms.add(new RuntimePermission("getClassLoader"));
+
+ // standard permissions
+ perms.add(new PropertyPermission("*", "read"));
+ perms.add(new RuntimePermission("accessDeclaredMembers"));
+ perms.add(new RuntimePermission("accessClassInPackage.*"));
+ perms.add(new RuntimePermission("defineClassInPackage.*"));
+ perms.add(new RuntimePermission("setFactory"));
+ perms.add(new RuntimePermission("getProtectionDomain"));
+ perms.add(new RuntimePermission("modifyThread"));
+ perms.add(new RuntimePermission("modifyThreadGroup"));
+ perms.add(new RuntimePermission("setFactory"));
+ perms.add(new ReflectPermission("suppressAccessChecks"));
+
+ // MOCCA specific
+ perms.add(new SocketPermission("*", "connect,resolve"));
+ perms.add(new NetPermission("specifyStreamHandler"));
+ perms.add(new SecurityPermission("insertProvider.*"));
+ perms.add(new SecurityPermission("putProviderProperty.*"));
+ perms.add(new SecurityPermission("removeProvider.*"));
+ perms.add(new CardPermission("*", "*"));
+ perms.add(new AWTPermission("*"));
+
+ perms.add(new FilePermission(webappDir.getAbsolutePath() + "/-", "read"));
+ perms.add(new FilePermission(new File(System.getProperty("java.home") + "/lib/xalan.properties").getAbsolutePath(), "read"));
+ perms.add(new FilePermission(new File(System.getProperty("java.home") + "/lib/xerces.properties").getAbsolutePath(), "read"));
+ perms.add(new FilePermission(new File(System.getProperty("user.home")).getAbsolutePath(), "read, write"));
+ perms.add(new FilePermission(new File(System.getProperty("user.home") + "/-").getAbsolutePath(), "read, write"));
+ perms.add(new FilePermission(new File(System.getProperty("user.home") + "/.mocca/logs/*").getAbsolutePath(), "read, write,delete"));
+
+
+ return perms;
+ }
+
public void start() throws Exception {
server.start();
}
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
new file mode 100644
index 00000000..f7be7b65
--- /dev/null
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java
@@ -0,0 +1,230 @@
+package at.gv.egiz.bku.webstart;
+
+import iaik.asn1.CodingException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Locale;
+import java.util.MissingResourceException;
+import java.util.ResourceBundle;
+
+import javax.jnlp.UnavailableServiceException;
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+
+import at.gv.egiz.bku.webstart.ui.BKUControllerInterface;
+import at.gv.egiz.bku.webstart.ui.TrayIconDialog;
+import com.sun.javaws.security.JavaWebStartSecurity;
+import java.awt.Desktop;
+import java.awt.SplashScreen;
+import java.net.BindException;
+import java.net.URI;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import javax.jnlp.BasicService;
+import javax.jnlp.ServiceManager;
+import org.mortbay.util.MultiException;
+
+public class Launcher implements BKUControllerInterface {
+
+ public static final String WEBAPP_RESOURCE = "BKULocal.war";
+ public static final String CERTIFICATES_RESOURCE = "BKUCertificates.jar";
+ public static final String WEBAPP_FILE = "BKULocal.war";
+ public static final String MESSAGES_RESOURCE = "at/gv/egiz/bku/webstart/ui/UIMessages";
+ /** resource bundle messages */
+ public static final String GREETING_CAPTION = "Greetings.Caption";
+ public static final String GREETING_MESSAGE = "Greetings.Message";
+ public static final String CONFIG_CAPTION = "Config.Caption";
+ public static final String CONFIG_MESSAGE = "Config.Message";
+ public static final String STARTUP_CAPTION = "Startup.Caption";
+ public static final String STARTUP_MESSAGE = "Startup.Message";
+ public static final String ERROR_CAPTION = "Error.Caption";
+ public static final String ERROR_STARTUP_MESSAGE = "Error.Startup.Message";
+ public static final String ERROR_CONF_MESSAGE = "Error.Conf.Message";
+ public static final String ERROR_BIND_MESSAGE = "Error.Bind.Message";
+ public static final URI HTTPS_SECURITY_LAYER_URI;
+ private static Log log = LogFactory.getLog(Launcher.class);
+
+ static {
+ URI tmp = null;
+ try {
+ tmp = new URI("https://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3496).intValue());
+ } catch (URISyntaxException ex) {
+ log.error(ex);
+ } finally {
+ HTTPS_SECURITY_LAYER_URI = tmp;
+ }
+ }
+
+ public static final String version;
+ static {
+ String tmp = Configurator.UNKOWN_VERSION;
+ try {
+ String bkuWebStartJar = Launcher.class.getProtectionDomain().getCodeSource().getLocation().toString();
+ URL manifestURL = new URL("jar:" + bkuWebStartJar + "!/META-INF/MANIFEST.MF");
+ if (log.isTraceEnabled()) {
+ log.trace("read version information from " + manifestURL);
+ }
+ Manifest manifest = new Manifest(manifestURL.openStream());
+ Attributes atts = manifest.getMainAttributes();
+ if (atts != null) {
+ tmp = atts.getValue("Implementation-Build");
+ }
+ } catch (IOException ex) {
+ log.error("failed to read version", ex);
+ } finally {
+ version = tmp;
+ log.info("BKU Web Start " + version);
+ }
+ }
+
+ private Configurator config;
+ private Container server;
+ private BasicService basicService;
+
+ private void initStart() {
+ try {
+ basicService = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService");
+ if (basicService.isOffline()) {
+ log.info("launching MOCCA Web Start offline");
+ } else {
+ log.info("launching MOCCA Web Start online");
+ }
+ } catch (UnavailableServiceException ex) {
+ log.info("Failed to obtain JNLP service: " + ex.getMessage());
+ }
+ }
+
+ private void initTrayIcon() {
+ log.debug("init MOCCA tray icon");
+ Locale loc = Locale.getDefault();
+ ResourceBundle resourceBundle;
+ try {
+ resourceBundle = ResourceBundle.getBundle(
+ MESSAGES_RESOURCE, loc);
+ } catch (MissingResourceException mx) {
+ resourceBundle = ResourceBundle.getBundle(
+ MESSAGES_RESOURCE, Locale.ENGLISH);
+ }
+ TrayIconDialog.getInstance().init(resourceBundle);
+ TrayIconDialog.getInstance().setShutdownHook(this);
+// TrayIconDialog.getInstance().displayInfo(GREETING_CAPTION, GREETING_MESSAGE);
+ }
+
+ private void initConfig() throws IOException, CodingException, GeneralSecurityException {
+ config = new Configurator();
+ config.ensureConfiguration();
+ config.ensureCertificates();
+ }
+
+ private void startServer() throws Exception {
+ log.info("init servlet container and MOCCA webapp");
+ server = new Container();
+ server.init();
+ server.start();
+ }
+
+ private void initFinished() {
+ try {
+ // standalone (non-webstart) version has splashscreen
+ if (SplashScreen.getSplashScreen() != null) {
+ try {
+ SplashScreen.getSplashScreen().close();
+ } catch (IllegalStateException ex) {
+ log.warn("Failed to close splash screen: " + ex.getMessage());
+ }
+ }
+ if (config.isCertRenewed()) {
+ // don't use basicService.showDocument(), which causes a java ssl warning dialog
+ if (Desktop.isDesktopSupported()) {
+ Desktop desktop = Desktop.getDesktop();
+ if (desktop.isSupported(Desktop.Action.BROWSE)) {
+ try {
+ desktop.browse(HTTPS_SECURITY_LAYER_URI);
+ } catch (Exception ex) {
+ log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URI, ex);
+ }
+ } else {
+ log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URI);
+ }
+ } else {
+ log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URI);
+ }
+ }
+ log.info("BKU successfully started");
+ server.join();
+ } catch (InterruptedException e) {
+ log.warn("failed to join server: " + e.getMessage(), e);
+ }
+ }
+
+ @Override
+ public void shutDown() {
+ log.info("Shutting down server");
+ if ((server != null) && (server.isRunning())) {
+ try {
+ if (server.isRunning()) {
+ server.stop();
+ }
+ } catch (Exception e) {
+ log.debug(e.toString());
+ } finally {
+ if (server.isRunning()) {
+ server.destroy();
+ }
+ }
+ }
+ System.exit(0);
+ }
+
+ public static void main(String[] args) throws InterruptedException, IOException {
+
+ if (log.isTraceEnabled()) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm instanceof JavaWebStartSecurity) {
+ System.setSecurityManager(new LogSecurityManager((JavaWebStartSecurity) sm));
+ }
+ }
+
+ Launcher launcher = new Launcher();
+ launcher.initStart();
+ launcher.initTrayIcon(); //keep reference? BKULauncher not garbage collected after main()
+
+ try {
+ TrayIconDialog.getInstance().displayInfo(CONFIG_CAPTION, CONFIG_MESSAGE);
+ launcher.initConfig();
+ } catch (Exception ex) {
+ log.fatal("Failed to initialize configuration", ex);
+ TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_CONF_MESSAGE);
+ Thread.sleep(5000);
+ System.exit(-1000);
+ }
+
+ try {
+ TrayIconDialog.getInstance().displayInfo(STARTUP_CAPTION, STARTUP_MESSAGE);
+ launcher.startServer();
+ TrayIconDialog.getInstance().displayInfo(GREETING_CAPTION, GREETING_MESSAGE);
+ launcher.initFinished();
+ } catch (BindException ex) {
+ log.fatal("Failed to launch server, " + ex.getMessage(), ex);
+ TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_BIND_MESSAGE);
+ Thread.sleep(5000);
+ System.exit(-1000);
+ } catch (MultiException ex) {
+ log.fatal("Failed to launch server, " + ex.getMessage(), ex);
+ if (ex.getThrowable(0) instanceof BindException) {
+ TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_BIND_MESSAGE);
+ } else {
+ TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_STARTUP_MESSAGE);
+ }
+ Thread.sleep(5000);
+ System.exit(-1000);
+ } catch (Exception e) {
+ log.fatal("Failed to launch server, " + e.getMessage(), e);
+ TrayIconDialog.getInstance().displayError(ERROR_CAPTION, ERROR_STARTUP_MESSAGE);
+ Thread.sleep(5000);
+ System.exit(-1000);
+ }
+ }
+}
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
new file mode 100644
index 00000000..99fd403b
--- /dev/null
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java
@@ -0,0 +1,440 @@
+/*
+ * 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.webstart;
+
+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;
+
+/**
+ * JVM argument -Djava.security.debug=access,failure
+ * (passed as attribute to java element in jnlp) is ignored.
+ *
+ * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at>
+ */
+public class LogSecurityManager extends SecurityManager {
+
+ protected static final Log log = LogFactory.getLog(LogSecurityManager.class);
+ JavaWebStartSecurity sm;
+
+ public LogSecurityManager(JavaWebStartSecurity sm) {
+ this.sm = sm;
+// AppPolicy policy = AppPolicy.getInstance();
+// SecurityManager sm = System.getSecurityManager();
+ }
+
+ @Override
+ public void checkAccept(String host, int port) {
+ try {
+ sm.checkAccept(host, port);
+ } catch (SecurityException ex) {
+ log.warn("checkAccept(" + host + ", " + port + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkAccess(Thread g) {
+ try {
+ sm.checkAccess(g);
+ } catch (SecurityException ex) {
+ log.warn("checkAccess(" + g + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkAccess(ThreadGroup g) {
+ try {
+ sm.checkAccess(g);
+ } catch (SecurityException ex) {
+ log.warn("checkAccess(" + g + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+
+ }
+
+ @Override
+ public void checkAwtEventQueueAccess() {
+ try {
+ sm.checkAwtEventQueueAccess();
+ } catch (SecurityException ex) {
+ log.warn("checkAwtEventQAccess():" + ex.getMessage(), ex);
+ throw ex;
+ }
+
+ }
+
+ @Override
+ public void checkConnect(String host, int port) {
+ try {
+ sm.checkConnect(host, port);
+ } catch (SecurityException ex) {
+ log.warn("checkConnect(" + host + ", " + port + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkConnect(String host, int port, Object context) {
+ try {
+ sm.checkConnect(host, port, context);
+ } catch (SecurityException ex) {
+ log.warn("checkConnect(" + host + ", " + port + ", " + context + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkCreateClassLoader() {
+ try {
+ sm.checkCreateClassLoader();
+ } catch (SecurityException ex) {
+ log.warn("checkCreateClassLoader(): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkDelete(String file) {
+ try {
+ sm.checkDelete(file);
+ } catch (SecurityException ex) {
+ log.warn("checkDelete(" + file + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkExec(String cmd) {
+ try {
+ sm.checkExec(cmd);
+ } catch (SecurityException ex) {
+ log.warn("checkExec(" + cmd + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkExit(int status) {
+ try {
+ sm.checkExit(status);
+ } catch (SecurityException ex) {
+ log.warn("checkExit(" + status + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkLink(String lib) {
+ try {
+ sm.checkLink(lib);
+ } catch (SecurityException ex) {
+ log.warn("checkLink(" + lib + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkListen(int port) {
+ try {
+ sm.checkListen(port);
+ } catch (SecurityException ex) {
+ log.warn("checkListen(" + port + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkMemberAccess(Class<?> clazz, int which) {
+ try {
+ sm.checkMemberAccess(clazz, which);
+ } catch (SecurityException ex) {
+ log.warn("checkMemberAccess(" + clazz + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkMulticast(InetAddress maddr) {
+ try {
+ sm.checkMulticast(maddr);
+ } catch (SecurityException ex) {
+ log.warn("checkMulticast(" + maddr + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkMulticast(InetAddress maddr, byte ttl) {
+ try {
+ sm.checkMulticast(maddr,ttl);
+ } catch (SecurityException ex) {
+ log.warn("checkMulticast(" + maddr + "," + ttl + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkPackageAccess(String pkg) {
+ try {
+ sm.checkPackageAccess(pkg);
+ } catch (SecurityException ex) {
+ log.warn("checkPackageAccess(" + pkg + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkPackageDefinition(String pkg) {
+ try {
+ sm.checkPackageDefinition(pkg);
+ } catch (SecurityException ex) {
+ log.warn("checkPackageDefinition(" + pkg + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkPermission(Permission perm) {
+ try {
+ sm.checkPermission(perm);
+ } catch (SecurityException ex) {
+ log.warn("checkPermission(" + perm.toString() + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkPermission(Permission perm, Object context) {
+ try {
+ sm.checkPermission(perm, context);
+ } catch (SecurityException ex) {
+ log.warn("checkPermission(" + perm.toString() + ", ctx): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkPrintJobAccess() {
+ try {
+ sm.checkPrintJobAccess();
+ } catch (SecurityException ex) {
+ log.info("checkPrintJobAccess(): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ /**
+ * allowed
+ */
+ @Override
+ public void checkPropertiesAccess() {
+ try {
+ sm.checkPropertiesAccess();
+ } catch (SecurityException ex) {
+ log.info("checkPropertiesAccess(): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ /**
+ * access to all properties allowed
+ * @param key
+ */
+ @Override
+ public void checkPropertyAccess(String key) {
+ try {
+ sm.checkPropertyAccess(key);
+ } catch (SecurityException ex) {
+ log.info("checkPropertyAccess(" + key + "): " + ex.getMessage());
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkRead(FileDescriptor fd) {
+ try {
+ sm.checkRead(fd);
+ } catch (SecurityException ex) {
+ log.warn("checkRead(" + fd + ") " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkRead(String file) {
+ try {
+ sm.checkRead(file);
+ } catch (SecurityException ex) {
+ log.warn("checkRead(" + file + ") " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkRead(String file, Object context) {
+ try {
+ sm.checkRead(file, context);
+ } catch (SecurityException ex) {
+ log.warn("checkRead(" + file + ") " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkSecurityAccess(String target) {
+ try {
+ sm.checkSecurityAccess(target);
+ } catch (SecurityException ex) {
+ log.info("checkSecurityAccess(" + target + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public void checkSetFactory() {
+ log.info("checkSetFactory() ");
+ try {
+ sm.checkSetFactory();
+ } catch (SecurityException ex) {
+ log.warn("checkSetFactroy(): " + ex.getMessage(), ex);
+ throw ex;
+ }
+
+ }
+
+ @Override
+ public void checkSystemClipboardAccess() {
+ try {
+ sm.checkSystemClipboardAccess();
+ } catch (SecurityException ex) {
+ log.info("checkSystemClipboardAccess(): " + ex.getMessage(), ex);
+ throw ex;
+ }
+ }
+
+ @Override
+ public boolean checkTopLevelWindow(Object window) {
+ log.info("checkTopLevelWindow(Object window)");
+ try {
+ return sm.checkTopLevelWindow(window);
+ } catch (SecurityException ex) {
+ log.warn("checkTopLevelWindow(" + window + "): " + ex.getMessage(), ex);
+ throw ex;
+ }
+
+ }
+
+ @Override
+ public void checkWrite(FileDescriptor fd) {
+ try {
+ sm.checkWrite(fd);
+ } catch (SecurityException ex) {
+ log.info("checkWrite(" + fd + "): " + ex.getMessage(), ex);
+ }
+ }
+
+ @Override
+ public void checkWrite(String file) {
+ try {
+ sm.checkWrite(file);
+ } catch (SecurityException ex) {
+ log.info("checkWrite(" + file + "): " + ex.getMessage(), ex);
+ }
+ }
+
+// @Override
+// protected int classDepth(String name) {
+// log.info("classDepth(String name)"); return this.classDepth(name);
+// }
+//
+// @Override
+// protected int classLoaderDepth() {
+// log.info("classLoaderDepth"); return sm.classLoaderDepth();
+// }
+//
+// @Override
+// protected Object clone() throws CloneNotSupportedException {
+// log.info("clone"); return sm.clone();
+// }
+//
+// @Override
+// protected ClassLoader currentClassLoader() {
+// log.info("currentClassLoader"); return sm.currentClassLoader();
+// }
+//
+// @Override
+// protected Class<?> currentLoadedClass() {
+// log.info("currentLoadedClass"); return sm.currentLoadedClass();
+// }
+ @Override
+ public boolean equals(Object obj) {
+ log.info("equals");
+ return sm.equals(obj);
+ }
+
+// @Override
+// protected void finalize() throws Throwable {
+// log.info("finalize"); sm.finalize();
+// }
+// @Override
+// protected Class[] getClassContext() {
+// log.info("getClassContext"); return sm.getClassContext();
+// }
+ @Override
+ public boolean getInCheck() {
+ log.info("getInCheck");
+ return sm.getInCheck();
+ }
+
+ @Override
+ public Object getSecurityContext() {
+ log.info("getSecurityContext");
+ return sm.getSecurityContext();
+ }
+
+ @Override
+ public ThreadGroup getThreadGroup() {
+ log.info("getThreadGroup");
+ return sm.getThreadGroup();
+ }
+
+ @Override
+ public int hashCode() {
+ log.info("hashCode");
+ return sm.hashCode();
+ }
+
+// @Override
+// protected boolean inClass(String name) {
+// log.info("inClass"); return sm.inClass(name);
+// }
+//
+// @Override
+// protected boolean inClassLoader() {
+// log.info(""); return sm.inClassLoader();
+// }
+ @Override
+ public String toString() {
+ log.info("toString");
+ return sm.toString();
+ }
+}
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/ui/TrayIconDialog.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/ui/TrayIconDialog.java
index 9990b2a0..fb7c40dd 100644
--- a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/ui/TrayIconDialog.java
+++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/ui/TrayIconDialog.java
@@ -36,7 +36,7 @@ import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
public class TrayIconDialog implements TrayIconDialogInterface {
- public static final String TRAYICON_RESOURCE = "at/gv/egiz/bku/webstart/ui/trayicon.png";
+ public static final String TRAYICON_RESOURCE = "at/gv/egiz/bku/webstart/ui/trayicon_32.png";
public static final String TRAYMENU_SHUTDOWN = "TrayMenu.Shutdown";
public static final String TRAYMENU_TOOLTIP = "TrayMenu.Tooltip";