diff options
Diffstat (limited to 'BKUWebStart/src/main/java/at')
9 files changed, 2079 insertions, 0 deletions
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..37638510 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Configurator.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 iaik.asn1.CodingException; +import iaik.utils.StreamCopier; + +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.URL; +import java.security.GeneralSecurityException; +import java.security.KeyStore; +import java.util.Enumeration; +import java.util.Iterator; +import java.util.UUID; +import java.util.jar.Attributes; +import java.util.jar.Manifest; +import java.util.zip.ZipEntry; +import java.util.zip.ZipFile; +import java.util.zip.ZipOutputStream; + +import org.apache.log4j.PropertyConfigurator; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * + * @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.2.11-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 Logger log = LoggerFactory.getLogger(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, MIN_CONFIG_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); + } + // re-configure logging + // TODO: move to appropriate place + String log4jconfig = configDir.getPath() + File.separatorChar + "log4j.properties"; + log.debug("Reconfiguring logging with " + log4jconfig); + PropertyConfigurator.configureAndWatch(log4jconfig); + } + + /** + * 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 (updateRequired(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.trace("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; + } + + /** + * if unknown old, update in any case + * if known old and unknown min, don't update + * @param oldVersion + * @param minVersion + * @return + */ + protected static boolean updateRequired(String oldVersion, String minVersion) { + log.debug("comparing " + oldVersion + " to " + minVersion); + if (oldVersion != null && !UNKOWN_VERSION.equals(oldVersion)) { + if (minVersion != null && !UNKOWN_VERSION.equals(minVersion)) { + int fromInd = 0; + int nextIndOld, nextIndMin; + int xOld, xMin; + + // assume dots '.' appear in major version only (not after "-SNAPSHOT") + while ((nextIndOld = oldVersion.indexOf('.', fromInd)) > 0) { + nextIndMin = minVersion.indexOf('.', fromInd); + if (nextIndMin < 0) { + log.debug("installed version newer than minimum required (newer minor version)"); + } + xOld = Integer.valueOf(oldVersion.substring(fromInd, nextIndOld)); + xMin = Integer.valueOf(minVersion.substring(fromInd, nextIndMin)); + if (xMin > xOld) { + log.debug("update required"); + return true; + } else if (xMin < xOld) { + log.debug("installed version newer than minimum required"); + return false; + } + fromInd = nextIndOld + 1; + } + + // compare last digit of major + boolean preRelease = true; + int majorEndOld = oldVersion.indexOf("-SNAPSHOT"); + if (majorEndOld < 0) { + preRelease = false; + majorEndOld = oldVersion.indexOf('-'); // 1.0.10-r439 + if (majorEndOld < 0) { + majorEndOld = oldVersion.length(); + } + } + + boolean releaseRequired = false; + int majorEndMin = minVersion.indexOf("-SNAPSHOT"); + if (majorEndMin < 0) { + releaseRequired = true; + majorEndMin = minVersion.indexOf('-'); + if (majorEndMin < 0) { + majorEndMin = minVersion.length(); + } + } + + xOld = Integer.valueOf(oldVersion.substring(fromInd, majorEndOld)); + boolean hasMoreDigitsMin = true; + nextIndMin = minVersion.indexOf('.', fromInd); + if (nextIndMin < 0) { + hasMoreDigitsMin = false; + nextIndMin = majorEndMin; + } + xMin = Integer.valueOf(minVersion.substring(fromInd, nextIndMin)); + if (xMin > xOld) { + log.debug("update required"); + return true; + } else if (xMin < xOld) { + log.debug("installed version newer than minimum required"); + return false; + } else if (hasMoreDigitsMin) { // xMin == xOld + log.debug("update required (newer minor version required)"); + return true; + } else if (preRelease && releaseRequired) { + log.debug("pre-release installed but release required"); + return true; + } else { + log.debug("exact match, no updated required"); + return false; + } + } + log.debug("unknown minimum version, do not update"); + return false; + } + log.debug("no 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)); + new StreamCopier(entryIS, zip).copyStream(); + 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)); + new StreamCopier(is, os).copyStream(); + 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.trace("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); + new StreamCopier(Configurator.class.getClassLoader().getResourceAsStream(entry), bos).copyStream(); + 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(); + new StreamCopier(zipFile.getInputStream(entry), + new FileOutputStream(eF)).copyStream(); + } + 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)) { + log.error("failed to make " + passwdFile + " owner readable only (certain file-systems do not support owner's permissions)"); + } + 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 new file mode 100644 index 00000000..4d1fe658 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Container.java @@ -0,0 +1,264 @@ +package at.gv.egiz.bku.webstart;
+
+import iaik.utils.StreamCopier;
+
+import java.awt.AWTPermission;
+import java.io.BufferedInputStream;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+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.AllPermission;
+import java.security.KeyStore;
+import java.security.Permissions;
+import java.security.SecurityPermission;
+import java.security.cert.Certificate;
+import java.util.PropertyPermission;
+import javax.smartcardio.CardPermission;
+import org.mortbay.jetty.Connector;
+import org.mortbay.jetty.Server;
+import org.mortbay.jetty.nio.SelectChannelConnector;
+import org.mortbay.jetty.security.SslSocketConnector;
+import org.mortbay.jetty.webapp.WebAppContext;
+import org.mortbay.thread.QueuedThreadPool;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Container {
+
+ public static final String HTTP_PORT_PROPERTY = "mocca.http.port";
+ public static final String HTTPS_PORT_PROPERTY = "mocca.http.port";
+ private static Logger log = LoggerFactory.getLogger(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;
+ private WebAppContext webapp;
+ private Certificate caCertificate;
+
+ public void init() throws IOException {
+// System.setProperty("DEBUG", "true");
+ server = new Server();
+ QueuedThreadPool qtp = new QueuedThreadPool();
+ qtp.setMaxThreads(5);
+ qtp.setMinThreads(2);
+ qtp.setLowThreads(0);
+ server.setThreadPool(qtp);
+ server.setStopAtShutdown(true);
+ server.setGracefulShutdown(3000);
+
+ SelectChannelConnector connector = new SelectChannelConnector();
+ connector.setPort(Integer.getInteger(HTTP_PORT_PROPERTY, 3495).intValue());
+ connector.setAcceptors(1);
+ connector.setConfidentialPort(Integer.getInteger(HTTPS_PORT_PROPERTY, 3496).intValue());
+ connector.setHost("127.0.0.1");
+
+ SslSocketConnector sslConnector = new SslSocketConnector();
+ 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") + "/" + 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());
+ String passwd = readPassword(new File(configDir, Configurator.PASSWD_FILE));
+ sslConnector.setPassword(passwd);
+ sslConnector.setKeyPassword(passwd);
+
+ //avoid jetty's ClassCastException: iaik.security.ecc.ecdsa.ECPublicKey cannot be cast to java.security.interfaces.ECPublicKey
+ String[] RFC4492CipherSuites = new String[]{
+ "TLS_ECDH_ECDSA_WITH_NULL_SHA",
+ "TLS_ECDH_ECDSA_WITH_RC4_128_SHA",
+ "TLS_ECDH_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "TLS_ECDH_ECDSA_WITH_AES_128_CBC_SHA",
+ "TLS_ECDH_ECDSA_WITH_AES_256_CBC_SHA",
+ "TLS_ECDHE_ECDSA_WITH_NULL_SHA",
+ "TLS_ECDHE_ECDSA_WITH_RC4_128_SHA",
+ "TLS_ECDHE_ECDSA_WITH_3DES_EDE_CBC_SHA",
+ "TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA",
+ "TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA",
+ "TLS_ECDH_RSA_WITH_NULL_SHA",
+ "TLS_ECDH_RSA_WITH_RC4_128_SHA",
+ "TLS_ECDH_RSA_WITH_3DES_EDE_CBC_SHA",
+ "TLS_ECDH_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_ECDH_RSA_WITH_AES_256_CBC_SHA",
+ "TLS_ECDHE_RSA_WITH_NULL_SHA",
+ "TLS_ECDHE_RSA_WITH_RC4_128_SHA",
+ "TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA",
+ "TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA",
+ "TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA",
+ "TLS_ECDH_anon_WITH_NULL_SHA",
+ "TLS_ECDH_anon_WITH_RC4_128_SHA",
+ "TLS_ECDH_anon_WITH_3DES_EDE_CBC_SHA",
+ "TLS_ECDH_anon_WITH_AES_128_CBC_SHA",
+ "TLS_ECDH_anon_WITH_AES_256_CBC_SHA"
+ };
+
+ sslConnector.setExcludeCipherSuites(RFC4492CipherSuites);
+
+ server.setConnectors(new Connector[]{connector, sslConnector});
+
+ webapp = new WebAppContext();
+ webapp.setLogUrlOnStart(true);
+ webapp.setContextPath("/");
+ webapp.setExtractWAR(true);
+ webapp.setParentLoaderPriority(false);
+
+ webapp.setWar(copyWebapp(webapp.getTempDirectory()));
+ webapp.setPermissions(getPermissions(webapp.getTempDirectory()));
+
+ server.setHandler(webapp);
+ server.setGracefulShutdown(1000 * 3);
+
+ loadCACertificate(keystoreFile, passwd.toCharArray());
+ }
+
+ /**
+ * @return The first valid (not empty, no comment) line of the passwd file
+ * @throws IOException
+ */
+ protected static String readPassword(File passwdFile) throws IOException {
+ if (passwdFile.exists() && passwdFile.canRead()) {
+ BufferedReader passwdReader = null;
+ try {
+ passwdReader = new BufferedReader(new FileReader(passwdFile));
+ String passwd;
+ while ((passwd = passwdReader.readLine().trim()) != null) {
+ if (passwd.length() > 0 && !passwd.startsWith("#")) {
+ return passwd;
+ }
+ }
+ } catch (IOException ex) {
+ log.error("failed to read password from " + passwdFile, ex);
+ throw ex;
+ } finally {
+ try {
+ passwdReader.close();
+ } catch (IOException ex) {
+ }
+ }
+ }
+ throw new IOException(passwdFile + " not readable");
+ }
+
+ private String copyWebapp(File webappDir) throws IOException {
+ File webapp = new File(webappDir, "BKULocal.war");
+ log.debug("copying BKULocal classpath resource to " + webapp);
+ InputStream is = getClass().getClassLoader().getResourceAsStream("BKULocal.war");
+ OutputStream os = new BufferedOutputStream(new FileOutputStream(webapp));
+ new StreamCopier(is, os).copyStream();
+ os.close();
+ return webapp.getPath();
+ }
+
+ private Permissions getPermissions(File webappDir) {
+ Permissions perms = new Permissions();
+ perms.add(new AllPermission());
+
+
+ if (false) {
+
+ // jetty-webstart (spring?)
+ perms.add(new RuntimePermission("getClassLoader"));
+
+ // standard permissions
+ perms.add(new PropertyPermission("*", "read,write"));
+ 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"));
+ perms.add(new FilePermission(new File(System.getProperty("user.home") + "/.mocca/certs/-").getAbsolutePath(), "read, write,delete"));
+
+ //TODO
+// log.trace("granting file read/write permission to MOCCA local");
+// perms.add(new FilePermission("<<ALL FILES>>", "read, write"));
+
+ }
+ return perms;
+ }
+
+ public void start() throws Exception {
+ server.start();
+ // webapp.getBaseResource()
+ File caCertFile = new File(webapp.getTempDirectory(), "webapp/ca.crt");
+ BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(caCertFile));
+ bos.write(caCertificate.getEncoded());
+ bos.flush();
+ bos.close();
+ }
+
+ public boolean isRunning() {
+ return server.isRunning();
+ }
+
+ public void stop() throws Exception {
+ server.stop();
+ }
+
+ public void destroy() {
+ server.destroy();
+ }
+
+ public void join() throws InterruptedException {
+ server.join();
+ }
+
+ private void loadCACertificate(File keystoreFile, char[] passwd) {
+ try {
+ if (log.isTraceEnabled()) {
+ log.trace("local ca certificate from " + keystoreFile);
+ }
+ BufferedInputStream bis = new BufferedInputStream(new FileInputStream(keystoreFile));
+ KeyStore sslKeyStore = KeyStore.getInstance("JKS");
+ sslKeyStore.load(bis, passwd);
+ Certificate[] sslChain = sslKeyStore.getCertificateChain(TLSServerCA.MOCCA_TLS_SERVER_ALIAS);
+ caCertificate = sslChain[sslChain.length - 1];
+ bis.close();
+ } catch (Exception ex) {
+ log.error("Failed to load local ca certificate", ex);
+ log.warn("automated web certificate installation will not be available");
+ }
+ }
+}
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..ef7edef1 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/Launcher.java @@ -0,0 +1,391 @@ +package at.gv.egiz.bku.webstart;
+
+import at.gv.egiz.bku.webstart.gui.AboutDialog;
+import at.gv.egiz.bku.webstart.gui.BKUControllerInterface;
+import at.gv.egiz.bku.webstart.gui.PINManagementInvoker;
+import iaik.asn1.CodingException;
+import java.io.IOException;
+import java.net.URISyntaxException;
+import java.util.Locale;
+import java.util.ResourceBundle;
+
+import javax.jnlp.UnavailableServiceException;
+
+import com.sun.javaws.security.JavaWebStartSecurity;
+import java.awt.AWTException;
+import java.awt.Desktop;
+import java.awt.Image;
+import java.awt.MenuItem;
+import java.awt.PopupMenu;
+import java.awt.SplashScreen;
+import java.awt.SystemTray;
+import java.awt.TrayIcon;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.WindowAdapter;
+import java.net.BindException;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.text.MessageFormat;
+import java.util.jar.Attributes;
+import java.util.jar.Manifest;
+import javax.imageio.ImageIO;
+import javax.jnlp.BasicService;
+import javax.jnlp.ServiceManager;
+import javax.swing.JFrame;
+import org.mortbay.util.MultiException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class Launcher implements BKUControllerInterface, ActionListener {
+ public static final String HELP_COMMAND = "help";
+
+ public static final String WEBAPP_RESOURCE = "BKULocal.war";
+ public static final String CERTIFICATES_RESOURCE = "BKUCertificates.jar";
+ public static final String WEBAPP_FILE = "BKULocal.war";
+ /** no leading slash for messages, but for image */
+ public static final String MESSAGES_RESOURCE = "at/gv/egiz/bku/webstart/messages";
+ public static final String TRAYICON_RESOURCE = "/at/gv/egiz/bku/webstart/chip";
+ /** resource bundle messages */
+ public static final String CAPTION_DEFAULT = "tray.caption.default";
+ public static final String CAPTION_ERROR = "tray.caption.error";
+ public static final String MESSAGE_START = "tray.message.start";
+ public static final String MESSAGE_START_OFFLINE = "tray.message.start.offline";
+ public static final String MESSAGE_CONFIG = "tray.message.config";
+ public static final String MESSAGE_CERTS = "tray.message.certs";
+ public static final String MESSAGE_FINISHED = "tray.message.finished";
+ public static final String MESSAGE_SHUTDOWN = "tray.message.shutdown";
+ public static final String ERROR_START = "tray.error.start";
+ public static final String ERROR_CONFIG = "tray.error.config";
+ public static final String ERROR_BIND = "tray.error.bind";
+ public static final String ERROR_PIN = "tray.error.pin.connect";
+ public static final String ERROR_OPEN_URL = "tray.error.open.url";
+ public static final String LABEL_SHUTDOWN = "tray.label.shutdown";
+ public static final String LABEL_PIN = "tray.label.pin";
+ public static final String LABEL_HELP = "tray.label.help";
+ public static final String LABEL_ABOUT = "tray.label.about";
+ public static final String TOOLTIP_DEFAULT = "tray.tooltip.default";
+
+ /** action commands for tray menu */
+ public static final String SHUTDOWN_COMMAND = "shutdown";
+ public static final String PIN_COMMAND = "pin";
+ public static final String ABOUT_COMMAND = "about";
+
+ private static Logger log = LoggerFactory.getLogger(Launcher.class);
+
+
+ /** local bku uri */
+ public static final URL HTTP_SECURITY_LAYER_URL;
+ public static final URL HTTPS_SECURITY_LAYER_URL;
+ public static final URL INSTALL_CERT_URL;
+ public static final URL PIN_MANAGEMENT_URL;
+ public static final URL HELP_URL;
+ static {
+ URL http = null;
+ URL https = null;
+ URL pin = null;
+ URL cert = null;
+ URL help = null;
+ try {
+ http = new URL("http://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3495).intValue());
+ https = new URL("https://localhost:" + Integer.getInteger(Container.HTTPS_PORT_PROPERTY, 3496).intValue());
+ pin = new URL(http, "/PINManagement");
+ cert = new URL(http, "/installCertificate");
+ help = new URL(http, "/help");
+ } catch (MalformedURLException ex) {
+ log.error("Failed to create URL.", ex);
+ } finally {
+ HTTP_SECURITY_LAYER_URL = http;
+ HTTPS_SECURITY_LAYER_URL = https;
+ PIN_MANAGEMENT_URL = pin;
+ INSTALL_CERT_URL = cert;
+ HELP_URL = help;
+ }
+ }
+ 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 TrayIcon trayIcon;
+ private ResourceBundle messages;
+ private AboutDialog aboutDialog;
+
+
+ public Launcher() {
+ log.info("Initializing Launcher");
+ if (log.isTraceEnabled()) {
+ SecurityManager sm = System.getSecurityManager();
+ if (sm instanceof JavaWebStartSecurity) {
+ System.setSecurityManager(new LogSecurityManager((JavaWebStartSecurity) sm));
+ }
+ }
+ messages = ResourceBundle.getBundle(MESSAGES_RESOURCE, Locale.getDefault());
+ trayIcon = initTrayIcon();
+ }
+
+ public void launch() throws Exception {
+ initStart();
+ try {
+ initConfig();
+ } catch (Exception ex) {
+ log.error("Failed to initialize configuration", ex);
+ trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
+ messages.getString(ERROR_CONFIG), TrayIcon.MessageType.ERROR);
+ throw ex;
+ }
+ try {
+ startServer();
+ initFinished();
+ } catch (BindException ex) {
+ log.error("Failed to launch server, " + ex.getMessage(), ex);
+ trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
+ messages.getString(ERROR_BIND), TrayIcon.MessageType.ERROR);
+ throw ex;
+ } catch (MultiException ex) {
+ log.error("Failed to launch server, " + ex.getMessage(), ex);
+ if (ex.getThrowable(0) instanceof BindException) {
+ trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
+ messages.getString(ERROR_BIND), TrayIcon.MessageType.ERROR);
+ } else {
+ trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
+ messages.getString(ERROR_START), TrayIcon.MessageType.ERROR);
+ }
+ throw ex;
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ log.error("Failed to launch server, " + ex.getMessage(), ex);
+ trayIcon.displayMessage(messages.getString(CAPTION_ERROR),
+ messages.getString(ERROR_START), TrayIcon.MessageType.ERROR);
+ throw ex;
+ }
+ }
+
+ private void browse(URL url) throws IOException, URISyntaxException {
+ // 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)) {
+ desktop.browse(url.toURI());
+ return;
+ }
+ }
+ throw new IOException("current platform does not support Java Desktop API");
+ }
+
+ private TrayIcon initTrayIcon() {
+ if (SystemTray.isSupported()) {
+ try {
+ // get the SystemTray instance
+ SystemTray tray = SystemTray.getSystemTray();
+ log.debug("TrayIcon size: " + tray.getTrayIconSize());
+
+ String iconResource;
+ if (tray.getTrayIconSize().height < 17) {
+ iconResource = TRAYICON_RESOURCE + "16.png";
+ } else if (tray.getTrayIconSize().height < 25) {
+ iconResource = TRAYICON_RESOURCE + "24.png";
+ } else if (tray.getTrayIconSize().height < 33) {
+ iconResource = TRAYICON_RESOURCE + "32.png";
+ } else {
+ iconResource = TRAYICON_RESOURCE + "48.png";
+ }
+ Image image = ImageIO.read(getClass().getResourceAsStream(iconResource));
+
+ PopupMenu popup = new PopupMenu();
+
+ MenuItem helpItem = new MenuItem(messages.getString(LABEL_HELP));
+ helpItem.addActionListener(this);
+ helpItem.setActionCommand(HELP_COMMAND);
+ popup.add(helpItem);
+
+ MenuItem pinItem = new MenuItem(messages.getString(LABEL_PIN));
+ pinItem.addActionListener(this);
+ pinItem.setActionCommand(PIN_COMMAND);
+ popup.add(pinItem);
+
+ MenuItem shutdownItem = new MenuItem(messages.getString(LABEL_SHUTDOWN));
+ shutdownItem.addActionListener(this);
+ shutdownItem.setActionCommand(SHUTDOWN_COMMAND);
+ popup.add(shutdownItem);
+
+ popup.addSeparator();
+
+ MenuItem aboutItem = new MenuItem(messages.getString(LABEL_ABOUT));
+ aboutItem.setActionCommand(ABOUT_COMMAND);
+ aboutItem.addActionListener(this);
+ popup.add(aboutItem);
+
+ TrayIcon ti = new TrayIcon(image, messages.getString(TOOLTIP_DEFAULT), popup);
+ ti.addActionListener(this);
+ tray.add(ti);
+ return ti;
+ } catch (AWTException ex) {
+ log.error("Failed to init tray icon", ex);
+ } catch (IOException ex) {
+ log.error("Failed to load tray icon image", ex);
+ }
+ } else {
+ log.error("No system tray support");
+ }
+ return null;
+ }
+
+ private void initStart() {
+ try {
+ trayIcon.displayMessage(messages.getString(CAPTION_DEFAULT),
+ messages.getString(MESSAGE_START), TrayIcon.MessageType.INFO);
+ basicService = (BasicService) ServiceManager.lookup("javax.jnlp.BasicService");
+ if (basicService.isOffline()) {
+ log.info("launching MOCCA Web Start offline");
+ trayIcon.displayMessage(messages.getString(CAPTION_DEFAULT),
+ messages.getString(MESSAGE_START_OFFLINE), TrayIcon.MessageType.INFO);
+ } else {
+ log.info("launching MOCCA Web Start online");
+ }
+ } catch (UnavailableServiceException ex) {
+ log.info("Failed to obtain JNLP service: " + ex.getMessage());
+ }
+ }
+
+ private void initConfig() throws IOException, CodingException, GeneralSecurityException {
+ trayIcon.displayMessage(messages.getString(CAPTION_DEFAULT),
+ messages.getString(MESSAGE_CONFIG), TrayIcon.MessageType.INFO);
+ config = new Configurator();
+ config.ensureConfiguration();
+ trayIcon.displayMessage(messages.getString(CAPTION_DEFAULT),
+ messages.getString(MESSAGE_CERTS), TrayIcon.MessageType.INFO);
+ config.ensureCertificates();
+ }
+
+ private void startServer() throws Exception {
+ log.info("init servlet container and MOCCA webapp");
+// trayIcon.displayMessage(messages.getString(CAPTION_DEFAULT),
+// messages.getString(MESSAGE_START), TrayIcon.MessageType.INFO);
+ server = new Container();
+ server.init();
+ server.start();
+ }
+
+ private void initFinished() {
+ try {
+ trayIcon.displayMessage(messages.getString(CAPTION_DEFAULT),
+ messages.getString(MESSAGE_FINISHED), TrayIcon.MessageType.INFO);
+ // 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()) {
+ try {
+ browse(HTTP_SECURITY_LAYER_URL);
+ } catch (Exception ex) {
+ log.error("failed to open system browser, install TLS certificate manually: " + HTTPS_SECURITY_LAYER_URL, ex);
+ }
+ }
+ 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");
+ trayIcon.displayMessage(messages.getString(CAPTION_DEFAULT),
+ messages.getString(MESSAGE_SHUTDOWN), TrayIcon.MessageType.INFO);
+ 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);
+ }
+
+ /**
+ * Listen for TrayMenu actions (display error messages on trayIcon)
+ * @param e
+ */
+ @Override
+ public void actionPerformed(ActionEvent e) {
+ if (SHUTDOWN_COMMAND.equals(e.getActionCommand())) {
+ log.debug("shutdown requested via tray menu");
+ this.shutDown();
+ } else if (ABOUT_COMMAND.equals(e.getActionCommand())) {
+ log.debug("about dialog requested via tray menu");
+ if (aboutDialog == null) {
+ aboutDialog = new AboutDialog(new JFrame(), true, version);
+ aboutDialog.addWindowListener(new WindowAdapter() {
+
+ @Override
+ public void windowClosing(java.awt.event.WindowEvent e) {
+ aboutDialog.setVisible(false);
+ }
+ });
+ }
+ aboutDialog.setLocationByPlatform(true);
+ aboutDialog.setVisible(true);
+ } else if (PIN_COMMAND.equals(e.getActionCommand())) {
+ log.debug("pin management dialog requested via tray menu");
+
+ new Thread(new PINManagementInvoker(trayIcon, messages)).start();
+ } else if (HELP_COMMAND.equals(e.getActionCommand())) {
+ log.debug("help page requested via tray menu");
+ try {
+ browse(HELP_URL);
+ } catch (Exception ex) {
+ log.error("Failed to open " + HELP_URL, ex);
+ String msg = MessageFormat.format(messages.getString(ERROR_OPEN_URL), HELP_URL);
+ trayIcon.displayMessage(messages.getString(CAPTION_ERROR), msg, TrayIcon.MessageType.ERROR);
+ }
+ } else {
+ log.error("unknown tray menu command: " + e.getActionCommand());
+ }
+ }
+
+ public static void main(String[] args) throws InterruptedException, IOException {
+ try {
+ Launcher launcher = new Launcher();
+ launcher.launch();
+ } catch (Exception ex) {
+ ex.printStackTrace();
+ log.debug("Caught exception " + ex.getMessage(), ex);
+ log.info("waiting to shutdown...");
+ Thread.sleep(5000);
+ log.info("exit");
+ 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..d589812e --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/LogSecurityManager.java @@ -0,0 +1,443 @@ +/* + * 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.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * 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 Logger log = LoggerFactory.getLogger(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; + } + } + + @SuppressWarnings("deprecation") + @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(); +// } + @SuppressWarnings("deprecation") + @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/TLSServerCA.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java new file mode 100644 index 00000000..745042f8 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/TLSServerCA.java @@ -0,0 +1,142 @@ +package at.gv.egiz.bku.webstart;
+
+import iaik.asn1.CodingException;
+import iaik.asn1.ObjectID;
+import iaik.asn1.structures.AlgorithmID;
+import iaik.asn1.structures.GeneralName;
+import iaik.asn1.structures.GeneralNames;
+import iaik.asn1.structures.Name;
+import iaik.x509.X509Certificate;
+import iaik.x509.extensions.AuthorityKeyIdentifier;
+import iaik.x509.extensions.BasicConstraints;
+import iaik.x509.extensions.ExtendedKeyUsage;
+import iaik.x509.extensions.KeyUsage;
+
+import iaik.x509.extensions.SubjectAltName;
+import iaik.x509.extensions.SubjectKeyIdentifier;
+import java.io.IOException;
+import java.math.BigInteger;
+import java.security.GeneralSecurityException;
+import java.security.KeyPair;
+import java.security.KeyPairGenerator;
+import java.security.KeyStore;
+import java.security.NoSuchAlgorithmException;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.Random;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+
+public class TLSServerCA {
+ public static final int CA_VALIDITY_Y = 3;
+ public static final String MOCCA_TLS_SERVER_ALIAS = "server";
+ public static final int SERVER_VALIDITY_Y = 3;
+ private final static Logger log = LoggerFactory.getLogger(TLSServerCA.class);
+
+ private KeyPair caKeyPair;
+ private X509Certificate caCert;
+
+ private KeyPair serverKeyPair;
+ private X509Certificate serverCert;
+
+ private KeyPair generateKeyPair() throws NoSuchAlgorithmException {
+ KeyPairGenerator gen = KeyPairGenerator.getInstance("RSA");
+ gen.initialize(2048);
+ return gen.generateKeyPair();
+ }
+
+ private void generateCACert() throws GeneralSecurityException, CodingException {
+ log.debug("generating MOCCA CA certificate");
+ Name subject = new Name();
+ subject.addRDN(ObjectID.country, "AT");
+ subject.addRDN(ObjectID.organization, "MOCCA");
+ subject.addRDN(ObjectID.organizationalUnit, "MOCCA TLS Server CA");
+
+ caKeyPair = generateKeyPair();
+ caCert = new X509Certificate();
+ caCert.setSerialNumber(new BigInteger(20, new Random()));
+ caCert.setSubjectDN(subject);
+ caCert.setPublicKey(caKeyPair.getPublic());
+ caCert.setIssuerDN(subject);
+
+ caCert.addExtension(new SubjectKeyIdentifier(caKeyPair.getPublic()));
+
+ BasicConstraints bc = new BasicConstraints(true);
+ bc.setCritical(true);
+ caCert.addExtension(bc);
+ KeyUsage ku = new KeyUsage(KeyUsage.keyCertSign | KeyUsage.cRLSign
+ | KeyUsage.digitalSignature);
+ ku.setCritical(true);
+ caCert.addExtension(ku);
+
+ GregorianCalendar date = new GregorianCalendar();
+ date.add(Calendar.HOUR_OF_DAY, -1);
+ caCert.setValidNotBefore(date.getTime());
+ date.add(Calendar.YEAR, CA_VALIDITY_Y);
+ caCert.setValidNotAfter(date.getTime());
+ caCert.sign(AlgorithmID.sha1WithRSAEncryption, caKeyPair.getPrivate());
+
+ log.debug("successfully generated MOCCA TLS Server CA certificate " + caCert.getSubjectDN());
+ }
+
+ private void generateServerCert() throws GeneralSecurityException, CodingException {
+ log.debug("generating MOCCA server certificate");
+ Name subject = new Name();
+ subject.addRDN(ObjectID.country, "AT");
+ subject.addRDN(ObjectID.organization, "MOCCA");
+ subject.addRDN(ObjectID.organizationalUnit, "MOCCA TLS Server");
+ subject.addRDN(ObjectID.commonName, "localhost");
+ subject.addRDN(ObjectID.commonName, "127.0.0.1");
+
+ serverKeyPair = generateKeyPair();
+ serverCert = new X509Certificate();
+ serverCert.setSerialNumber(new BigInteger(20, new Random()));
+ serverCert.setSubjectDN(subject);
+ serverCert.setPublicKey(serverKeyPair.getPublic());
+ serverCert.setIssuerDN(caCert.getSubjectDN());
+
+ serverCert.addExtension(new SubjectKeyIdentifier(serverKeyPair.getPublic()));
+ byte[] aki = new SubjectKeyIdentifier(caCert.getPublicKey()).get();
+ serverCert.addExtension(new AuthorityKeyIdentifier(aki));
+
+ serverCert.addExtension(new ExtendedKeyUsage(ExtendedKeyUsage.serverAuth));
+
+ GeneralNames altNames = new GeneralNames();
+ altNames.addName(new GeneralName(GeneralName.dNSName, "localhost"));
+ altNames.addName(new GeneralName(GeneralName.dNSName, "127.0.0.1"));
+ altNames.addName(new GeneralName(GeneralName.iPAddress, "127.0.0.1"));
+ serverCert.addExtension(new SubjectAltName(altNames));
+
+ serverCert.addExtension(new BasicConstraints(false));
+ serverCert.addExtension(new KeyUsage(KeyUsage.keyEncipherment
+ | KeyUsage.digitalSignature));
+
+ GregorianCalendar date = new GregorianCalendar();
+ date.add(Calendar.HOUR_OF_DAY, -1);
+ serverCert.setValidNotBefore(date.getTime());
+ date.add(Calendar.YEAR,SERVER_VALIDITY_Y);
+ date.add(Calendar.HOUR_OF_DAY, -1);
+ serverCert.setValidNotAfter(date.getTime());
+ serverCert.sign(AlgorithmID.sha1WithRSAEncryption, caKeyPair.getPrivate());
+
+ log.debug("successfully generated MOCCA TLS Server certificate " + serverCert.getSubjectDN());
+ caKeyPair = null;
+ }
+
+ public KeyStore generateKeyStore(char[] password) throws GeneralSecurityException, IOException, CodingException {
+// try {
+ generateCACert();
+ generateServerCert();
+ KeyStore ks = KeyStore.getInstance("JKS");
+ ks.load(null, null);
+ ks.setKeyEntry(MOCCA_TLS_SERVER_ALIAS, serverKeyPair.getPrivate(), password, new X509Certificate[]{serverCert, caCert});
+ return ks;
+// } catch (Exception e) {
+// log.error("Cannot generate certificate", e);
+// }
+// return null;
+ }
+
+}
diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.form b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.form new file mode 100644 index 00000000..548893a7 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.form @@ -0,0 +1,139 @@ +<?xml version="1.0" encoding="UTF-8" ?> + +<Form version="1.3" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JDialogFormInfo"> + <Properties> + <Property name="defaultCloseOperation" type="int" value="2"/> + <Property name="title" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/gv/egiz/bku/webstart/messages.properties" key="about.frame.title" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/> + </Property> + </Properties> + <SyntheticProperties> + <SyntheticProperty name="formSizePolicy" type="int" value="1"/> + </SyntheticProperties> + <AuxValues> + <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/> + <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="1"/> + <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/> + <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/> + <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/> + </AuxValues> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jPanel1" alignment="1" max="32767" attributes="0"/> + <Component id="jPanel3" alignment="1" max="32767" attributes="0"/> + </Group> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jPanel1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + <Component id="jPanel3" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Container class="javax.swing.JPanel" name="jPanel1"> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <Component id="jLabel1" min="-2" max="-2" attributes="0"/> + <EmptySpace type="unrelated" max="-2" attributes="0"/> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jLabel3" min="-2" max="-2" attributes="0"/> + <Component id="jLabel2" min="-2" max="-2" attributes="0"/> + </Group> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Component id="jLabel1" min="-2" max="-2" attributes="0"/> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jLabel3" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + <Component id="jLabel2" min="-2" max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JLabel" name="jLabel1"> + <Properties> + <Property name="icon" type="javax.swing.Icon" editor="org.netbeans.modules.form.editors2.IconEditor"> + <Image iconType="3" name="/at/gv/egiz/bku/webstart/chiperling96.png"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel2"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.form.RADConnectionPropertyEditor"> + <Connection code="getVersionText(bundle)" type="code"/> + </Property> + </Properties> + </Component> + <Component class="javax.swing.JLabel" name="jLabel3"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/gv/egiz/bku/webstart/messages.properties" key="about.title" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/> + </Property> + </Properties> + </Component> + </SubComponents> + </Container> + <Container class="javax.swing.JPanel" name="jPanel3"> + + <Layout> + <DimensionLayout dim="0"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="1" attributes="0"> + <EmptySpace pref="163" max="32767" attributes="0"/> + <Component id="jButton1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="-2" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + <DimensionLayout dim="1"> + <Group type="103" groupAlignment="0" attributes="0"> + <Group type="102" alignment="0" attributes="0"> + <EmptySpace max="-2" attributes="0"/> + <Component id="jButton1" min="-2" max="-2" attributes="0"/> + <EmptySpace max="32767" attributes="0"/> + </Group> + </Group> + </DimensionLayout> + </Layout> + <SubComponents> + <Component class="javax.swing.JButton" name="jButton1"> + <Properties> + <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor"> + <ResourceString bundle="at/gv/egiz/bku/webstart/messages.properties" key="button.close" replaceFormat="java.util.ResourceBundle.getBundle("{bundleNameSlashes}").getString("{key}")"/> + </Property> + </Properties> + <Events> + <EventHandler event="actionPerformed" listener="java.awt.event.ActionListener" parameters="java.awt.event.ActionEvent" handler="jButton1ActionPerformed"/> + </Events> + </Component> + </SubComponents> + </Container> + </SubComponents> +</Form> diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java new file mode 100644 index 00000000..ba2c007d --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/AboutDialog.java @@ -0,0 +1,165 @@ +/* + * To change this template, choose Tools | Templates + * and open the template in the editor. + */ + +/* + * AboutDialog.java + * + * Created on 18.08.2009, 11:54:44 + */ + +package at.gv.egiz.bku.webstart.gui; + +import java.text.MessageFormat; +import java.util.ResourceBundle; + +/** + * + * @author clemens + */ +public class AboutDialog extends javax.swing.JDialog { + + /** + * + */ + private static final long serialVersionUID = 1L; + + /** Creates new form AboutDialog */ + public AboutDialog(java.awt.Frame parent, boolean modal, String version) { + super(parent, modal); + this.version = version; + initComponents(); + } + + /** This method is called from within the constructor to + * initialize the form. + * WARNING: Do NOT modify this code. The content of this method is + * always regenerated by the Form Editor. + */ + // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents + private void initComponents() { + + jPanel1 = new javax.swing.JPanel(); + jLabel1 = new javax.swing.JLabel(); + jLabel2 = new javax.swing.JLabel(); + jLabel3 = new javax.swing.JLabel(); + jPanel3 = new javax.swing.JPanel(); + jButton1 = new javax.swing.JButton(); + + setDefaultCloseOperation(javax.swing.WindowConstants.DISPOSE_ON_CLOSE); + java.util.ResourceBundle bundle = java.util.ResourceBundle.getBundle("at/gv/egiz/bku/webstart/messages"); // NOI18N + setTitle(bundle.getString("about.frame.title")); // NOI18N + + jLabel1.setIcon(new javax.swing.ImageIcon(getClass().getResource("/at/gv/egiz/bku/webstart/chiperling96.png"))); // NOI18N + + jLabel2.setText(getVersionText(bundle)); + + jLabel3.setText(bundle.getString("about.title")); // NOI18N + + javax.swing.GroupLayout jPanel1Layout = new javax.swing.GroupLayout(jPanel1); + jPanel1.setLayout(jPanel1Layout); + jPanel1Layout.setHorizontalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel1Layout.createSequentialGroup() + .addComponent(jLabel1) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.UNRELATED) + .addGroup(jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel3) + .addComponent(jLabel2)) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + jPanel1Layout.setVerticalGroup( + jPanel1Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jLabel1) + .addGroup(jPanel1Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jLabel3) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED) + .addComponent(jLabel2)) + ); + + jButton1.setText(bundle.getString("button.close")); // NOI18N + jButton1.addActionListener(new java.awt.event.ActionListener() { + public void actionPerformed(java.awt.event.ActionEvent evt) { + jButton1ActionPerformed(evt); + } + }); + + javax.swing.GroupLayout jPanel3Layout = new javax.swing.GroupLayout(jPanel3); + jPanel3.setLayout(jPanel3Layout); + jPanel3Layout.setHorizontalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(javax.swing.GroupLayout.Alignment.TRAILING, jPanel3Layout.createSequentialGroup() + .addContainerGap(163, Short.MAX_VALUE) + .addComponent(jButton1) + .addContainerGap()) + ); + jPanel3Layout.setVerticalGroup( + jPanel3Layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(jPanel3Layout.createSequentialGroup() + .addContainerGap() + .addComponent(jButton1) + .addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + ); + + javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane()); + getContentPane().setLayout(layout); + layout.setHorizontalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addComponent(jPanel1, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel3, javax.swing.GroupLayout.Alignment.TRAILING, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE)) + .addContainerGap()) + ); + layout.setVerticalGroup( + layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING) + .addGroup(layout.createSequentialGroup() + .addContainerGap() + .addComponent(jPanel1, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addPreferredGap(javax.swing.LayoutStyle.ComponentPlacement.RELATED, javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE) + .addComponent(jPanel3, javax.swing.GroupLayout.PREFERRED_SIZE, javax.swing.GroupLayout.DEFAULT_SIZE, javax.swing.GroupLayout.PREFERRED_SIZE) + .addContainerGap()) + ); + + pack(); + }// </editor-fold>//GEN-END:initComponents + + private String getVersionText(ResourceBundle bundle) { + return MessageFormat.format(bundle.getString("about.version"), version); + } + private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_jButton1ActionPerformed + // TODO add your handling code here: + setVisible(false); + }//GEN-LAST:event_jButton1ActionPerformed + + /** + * @param args the command line arguments + */ + public static void main(String args[]) { + java.awt.EventQueue.invokeLater(new Runnable() { + public void run() { + AboutDialog dialog = new AboutDialog(new javax.swing.JFrame(), true, "1.2.3"); + dialog.addWindowListener(new java.awt.event.WindowAdapter() { + public void windowClosing(java.awt.event.WindowEvent e) { + System.exit(0); + } + }); + dialog.setVisible(true); + } + }); + } + + // Variables declaration - do not modify//GEN-BEGIN:variables + private javax.swing.JButton jButton1; + private javax.swing.JLabel jLabel1; + private javax.swing.JLabel jLabel2; + private javax.swing.JLabel jLabel3; + private javax.swing.JPanel jPanel1; + private javax.swing.JPanel jPanel3; + // End of variables declaration//GEN-END:variables + + private String version; +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/BKUControllerInterface.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/BKUControllerInterface.java new file mode 100644 index 00000000..886b55f7 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/BKUControllerInterface.java @@ -0,0 +1,23 @@ +/* +* Copyright 2008 Federal Chancellery Austria and +* Graz University of Technology +* +* Licensed under the Apache License, Version 2.0 (the "License"); +* you may not use this file except in compliance with the License. +* You may obtain a copy of the License at +* +* http://www.apache.org/licenses/LICENSE-2.0 +* +* Unless required by applicable law or agreed to in writing, software +* distributed under the License is distributed on an "AS IS" BASIS, +* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +* See the License for the specific language governing permissions and +* limitations under the License. +*/ +package at.gv.egiz.bku.webstart.gui; + +public interface BKUControllerInterface { + + public void shutDown(); + +} diff --git a/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java new file mode 100644 index 00000000..1f14d751 --- /dev/null +++ b/BKUWebStart/src/main/java/at/gv/egiz/bku/webstart/gui/PINManagementInvoker.java @@ -0,0 +1,72 @@ +/* + * 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.gui; + +import at.gv.egiz.bku.webstart.Launcher; +import java.awt.TrayIcon; +import java.io.IOException; +import java.net.HttpURLConnection; +import java.util.ResourceBundle; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * GUI is painted using SwingUtilities.invokeLater, but TrayIcon ActionListener Thread (== webstart thread) joined Jetty Thread + * + * @author Clemens Orthacker <clemens.orthacker@iaik.tugraz.at> + */ +public class PINManagementInvoker implements Runnable { + + private static final Logger log = LoggerFactory.getLogger(PINManagementInvoker.class); + + TrayIcon trayIcon; + ResourceBundle messages; + + public PINManagementInvoker(TrayIcon trayIcon, ResourceBundle messages) { + this.trayIcon = trayIcon; + this.messages = messages; + } + + @Override + public void run() { + HttpURLConnection connection = null; + try { + log.debug("Connecting to: " + Launcher.PIN_MANAGEMENT_URL); + + connection = (HttpURLConnection) Launcher.PIN_MANAGEMENT_URL.openConnection(); + + connection.setRequestMethod("GET"); + connection.setReadTimeout(0); + connection.connect(); + + if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) { + log.debug("pin management dialog returned"); + } else { + log.error("unexpected response from pin management: " + connection.getResponseMessage()); + } + } catch (IOException ex) { + log.error("Failed to connect to PIN Management", ex); + trayIcon.displayMessage(messages.getString(Launcher.CAPTION_ERROR), + messages.getString(Launcher.ERROR_PIN), TrayIcon.MessageType.ERROR); + } finally { + if (connection != null) { + connection.disconnect(); + } + } + } +} |