Mercurial > hg > release > icedtea6-1.3
changeset 751:5284b488b3ed cacao
2008-03-06 Joshua Sumali <jsumali@redhat.com>
* Makefile.am: Added new 'extra' targets. These new targets build the
sources in the extra/ directory to build about.jar, which is the new
sample jnlp application for javaws.
* Makefile.in: Regenerated.
* generated/sun/awt/X11/generator/sizer.32: Regenerated.
* rt/net/sourceforge/jnlp/resources/Manifest.mf: Fix boot class typo.
* rt/net/sourceforge/jnlp/resources/Messages.properties: Improved command
line options.
* rt/net/sourceforge/jnlp/runtime/Boot.java: Changed command line
behaviour. Sample application now only runs if the -about flag is passed.
* rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Remove call to
printStackTrace.
* rt/net/sourceforge/jnlp/security/CertsInfoPane.java: Rearranged methods
and relaxed visibility in some fields/methods for SingleCertInfoPane
class.
* rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Added
single certificate dialog showing.
* rt/net/sourceforge/jnlp/tools/KeyTool.java: Moved KeyStore retrieving to
new SecurityUtil class.
* extra/net/sourceforge/jnlp/about/HTMLPanel.java: New File.
* extra/net/sourceforge/jnlp/about/Main.java: Likewise.
* extra/net/sourceforge/jnlp/about/resources/about.html: Likewise.
* extra/net/sourceforge/jnlp/about/resources/applications.html: Likewise.
* extra/net/sourceforge/jnlp/about/resources/jamIcon.jpg: Likewise.
* extra/net/sourceforge/jnlp/about/resources/notes.html: Likewise.
* rt/net/sourceforge/jnlp/resources/about.jnlp: Likewise.
* rt/net/sourceforge/jnlp/security/SecurityUtil.java: Likewise.
* rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java: Likewise.
* rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java: Likewise.
* rt/net/sourceforge/jnlp/security/viewer/CertificateViewer.java:
Likewise.
line wrap: on
line diff
--- a/ChangeLog Wed Mar 05 08:37:23 2008 -0500 +++ b/ChangeLog Thu Mar 06 09:46:38 2008 -0500 @@ -1,3 +1,37 @@ +2008-03-06 Joshua Sumali <jsumali@redhat.com> + + * Makefile.am: Added new 'extra' targets. These new targets build the + sources in the extra/ directory to build about.jar, which is the new + sample jnlp application for javaws. + * Makefile.in: Regenerated. + * generated/sun/awt/X11/generator/sizer.32: Regenerated. + * rt/net/sourceforge/jnlp/resources/Manifest.mf: Fix boot class typo. + * rt/net/sourceforge/jnlp/resources/Messages.properties: Improved command + line options. + * rt/net/sourceforge/jnlp/runtime/Boot.java: Changed command line + behaviour. Sample application now only runs if the -about flag is passed. + * rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java: Remove call to + printStackTrace. + * rt/net/sourceforge/jnlp/security/CertsInfoPane.java: Rearranged methods + and relaxed visibility in some fields/methods for SingleCertInfoPane + class. + * rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java: Added + single certificate dialog showing. + * rt/net/sourceforge/jnlp/tools/KeyTool.java: Moved KeyStore retrieving to + new SecurityUtil class. + * extra/net/sourceforge/jnlp/about/HTMLPanel.java: New File. + * extra/net/sourceforge/jnlp/about/Main.java: Likewise. + * extra/net/sourceforge/jnlp/about/resources/about.html: Likewise. + * extra/net/sourceforge/jnlp/about/resources/applications.html: Likewise. + * extra/net/sourceforge/jnlp/about/resources/jamIcon.jpg: Likewise. + * extra/net/sourceforge/jnlp/about/resources/notes.html: Likewise. + * rt/net/sourceforge/jnlp/resources/about.jnlp: Likewise. + * rt/net/sourceforge/jnlp/security/SecurityUtil.java: Likewise. + * rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java: Likewise. + * rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java: Likewise. + * rt/net/sourceforge/jnlp/security/viewer/CertificateViewer.java: + Likewise. + 2008-03-05 Gary Benson <gbenson@redhat.com> * contrib/templater/README: Updated URL.
--- a/Makefile.am Wed Mar 05 08:37:23 2008 -0500 +++ b/Makefile.am Thu Mar 06 09:46:38 2008 -0500 @@ -16,9 +16,11 @@ distclean-local: clean-copy rm -rf stamps rm -f rt-source-files.txt \ - hotspot-tools-source-files.txt + hotspot-tools-source-files.txt \ + extra-source-files.txt rm -rf bootstrap rm -rf lib + rm -rf extra-lib rm -rf openjdk-ecj rm -rf openjdk rm -rf hotspot-tools @@ -34,7 +36,7 @@ clean-icedtea icedtea-against-icedtea clean-icedtea-ecj clean-plugs \ clean-tools-jar clean-shared-objects \ clean-copy clean-hotspot-tools clean-rt clean-gcjwebplugin \ - hotspot hotspot-helper + hotspot hotspot-helper clean-extra EXTRA_DIST = rt generated $(ICEDTEA_PATCHES) $(ICEDTEA_ECJ_PATCH) \ gcjwebplugin.cc patches/icedtea-speed.patch tools-copy contrib ports \ @@ -498,7 +500,8 @@ # you change it in the icedtea-debug target as well. icedtea: stamps/bootstrap-directory-symlink.stamp \ stamps/hotspot-tools.stamp stamps/plugs.stamp \ - stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so + stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so \ + extra-lib/about.jar $(MAKE) \ $(ICEDTEA_ENV) \ -C openjdk/control/make/ @@ -509,15 +512,18 @@ cp -pPRf gcjwebplugin.so \ $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \ fi - cp rt/net/sourceforge/jnlp/resources/default.jnlp \ + cp rt/net/sourceforge/jnlp/resources/about.jnlp \ + extra-lib/about.jar \ $(BUILD_OUTPUT_DIR)/j2re-image/lib - cp rt/net/sourceforge/jnlp/resources/default.jnlp \ + cp rt/net/sourceforge/jnlp/resources/about.jnlp \ + extra-lib/about.jar \ $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib @echo "IcedTea is served:" $(BUILD_OUTPUT_DIR) icedtea-debug: stamps/bootstrap-directory-symlink.stamp \ stamps/hotspot-tools.stamp stamps/plugs.stamp \ - stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so + stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so \ + extra-lib/about.jar $(MAKE) \ $(ICEDTEA_ENV) \ -C openjdk/control/make \ @@ -530,8 +536,10 @@ $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \ fi cp rt/net/sourceforge/jnlp/resources/default.jnlp \ + extra-lib/about.jar \ $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib cp rt/net/sourceforge/jnlp/resources/default.jnlp \ + extra-lib/about.jar \ $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib @echo "IcedTea (debug build) is served:" \ $(BUILD_OUTPUT_DIR)-debug @@ -789,6 +797,42 @@ cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar bootstrap/ecj/jre/lib/rt.jar; \ fi +# extras -- used to create about.jar for javaws. +extra-source-files.txt: + find extra -name '*.java' | sort > $@ + +stamps/extra-class-files.stamp: extra-source-files.txt \ + bootstrap/jdk1.7.0/jre/lib/rt-closed.jar + mkdir -p extra-lib + if ! test -f stamps/icedtea-ecj.stamp ; \ + then \ + $(JAVAC) $(MEMORY_LIMIT) -g -d extra-lib -bootclasspath '' -source 1.6 \ + -sourcepath extra -cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \ + @extra-source-files.txt ; \ + else \ + $(ICEDTEA_BOOT_DIR)/bin/javac $(MEMORY_LIMIT) -g -d extra-lib \ + -bootclasspath '' -source 1.6 \ + -sourcepath extra -cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \ + @extra-source-files.txt ; \ + fi + cp -r extra/net/sourceforge/jnlp/about/resources \ + extra-lib/net/sourceforge/jnlp/about + mkdir -p stamps + touch $@ + +clean-extra: + rm -rf extra-lib + rm -f stamps/extra-class-files.stamp + rm -f extra-source-files.txt + +extra-lib/about.jar: stamps/extra-class-files.stamp + if ! test -f stamps/icedtea-ecj.stamp ; \ + then \ + $(JAR) cf $@ -C extra-lib net ; \ + else \ + $(ICEDTEA_BOOT_DIR)/bin/jar cf $@ -C extra-lib net ; \ + fi + # gcjwebplugin.so. gcjwebplugin.so: gcjwebplugin.cc if test "$(ENABLE_PLUGIN)" == "yes" ; \
--- a/Makefile.in Wed Mar 05 08:37:23 2008 -0500 +++ b/Makefile.in Thu Mar 06 09:46:38 2008 -0500 @@ -655,9 +655,11 @@ distclean-local: clean-copy rm -rf stamps rm -f rt-source-files.txt \ - hotspot-tools-source-files.txt + hotspot-tools-source-files.txt \ + extra-source-files.txt rm -rf bootstrap rm -rf lib + rm -rf extra-lib rm -rf openjdk-ecj rm -rf openjdk rm -rf hotspot-tools @@ -673,7 +675,7 @@ clean-icedtea icedtea-against-icedtea clean-icedtea-ecj clean-plugs \ clean-tools-jar clean-shared-objects \ clean-copy clean-hotspot-tools clean-rt clean-gcjwebplugin \ - hotspot hotspot-helper + hotspot hotspot-helper clean-extra env: @echo 'unset JAVA_HOME' @@ -922,7 +924,8 @@ # you change it in the icedtea-debug target as well. icedtea: stamps/bootstrap-directory-symlink.stamp \ stamps/hotspot-tools.stamp stamps/plugs.stamp \ - stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so + stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so \ + extra-lib/about.jar $(MAKE) \ $(ICEDTEA_ENV) \ -C openjdk/ j2se_only @@ -933,15 +936,18 @@ cp -pPRf gcjwebplugin.so \ $(BUILD_OUTPUT_DIR)/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \ fi - cp rt/net/sourceforge/jnlp/resources/default.jnlp \ + cp rt/net/sourceforge/jnlp/resources/about.jnlp \ + extra-lib/about.jar \ $(BUILD_OUTPUT_DIR)/j2re-image/lib - cp rt/net/sourceforge/jnlp/resources/default.jnlp \ + cp rt/net/sourceforge/jnlp/resources/about.jnlp \ + extra-lib/about.jar \ $(BUILD_OUTPUT_DIR)/j2sdk-image/jre/lib @echo "IcedTea is served:" $(BUILD_OUTPUT_DIR) icedtea-debug: stamps/bootstrap-directory-symlink.stamp \ stamps/hotspot-tools.stamp stamps/plugs.stamp \ - stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so + stamps/ports.stamp stamps/patch.stamp gcjwebplugin.so \ + extra-lib/about.jar $(MAKE) \ $(ICEDTEA_ENV) \ -C openjdk/ \ @@ -954,8 +960,10 @@ $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib/$(INSTALL_ARCH_DIR) ; \ fi cp rt/net/sourceforge/jnlp/resources/default.jnlp \ + extra-lib/about.jar \ $(BUILD_OUTPUT_DIR)-debug/j2re-image/lib cp rt/net/sourceforge/jnlp/resources/default.jnlp \ + extra-lib/about.jar \ $(BUILD_OUTPUT_DIR)-debug/j2sdk-image/jre/lib @echo "IcedTea (debug build) is served:" \ $(BUILD_OUTPUT_DIR)-debug @@ -1183,6 +1191,42 @@ cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar bootstrap/ecj/jre/lib/rt.jar; \ fi +# extras -- used to create about.jar for javaws. +extra-source-files.txt: + find extra -name '*.java' | sort > $@ + +stamps/extra-class-files.stamp: extra-source-files.txt \ + bootstrap/jdk1.7.0/jre/lib/rt-closed.jar + mkdir -p extra-lib + if ! test -f stamps/icedtea-ecj.stamp ; \ + then \ + $(JAVAC) $(MEMORY_LIMIT) -g -d extra-lib -bootclasspath '' -source 1.6 \ + -sourcepath extra -cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \ + @extra-source-files.txt ; \ + else \ + $(ICEDTEA_BOOT_DIR)/bin/javac $(MEMORY_LIMIT) -g -d extra-lib \ + -bootclasspath '' -source 1.6 \ + -sourcepath extra -cp bootstrap/jdk1.7.0/jre/lib/rt-closed.jar \ + @extra-source-files.txt ; \ + fi + cp -r extra/net/sourceforge/jnlp/about/resources \ + extra-lib/net/sourceforge/jnlp/about + mkdir -p stamps + touch $@ + +clean-extra: + rm -rf extra-lib + rm -f stamps/extra-class-files.stamp + rm -f extra-source-files.txt + +extra-lib/about.jar: stamps/extra-class-files.stamp + if ! test -f stamps/icedtea-ecj.stamp ; \ + then \ + $(JAR) cf $@ -C extra-lib net ; \ + else \ + $(ICEDTEA_BOOT_DIR)/bin/jar cf $@ -C extra-lib net ; \ + fi + # gcjwebplugin.so. gcjwebplugin.so: gcjwebplugin.cc if test "$(ENABLE_PLUGIN)" == "yes" ; \
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/net/sourceforge/jnlp/about/HTMLPanel.java Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,59 @@ +/* HTMLPanel.java + Copyright (C) 2008 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package net.sourceforge.jnlp.about; + +import java.awt.BorderLayout; +import java.io.IOException; +import java.net.URL; + +import javax.swing.JPanel; +import javax.swing.JScrollPane; +import javax.swing.JEditorPane; + +public class HTMLPanel extends JPanel { + + JEditorPane pane; + + public HTMLPanel(URL url) throws IOException { + super(new BorderLayout()); + pane = new JEditorPane(url); + pane.setEditable(false); + JScrollPane scroller = new JScrollPane(pane); + add(scroller, BorderLayout.CENTER); + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/net/sourceforge/jnlp/about/Main.java Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,135 @@ +/* Main.java + Copyright (C) 2008 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package net.sourceforge.jnlp.about; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.Toolkit; +import java.io.IOException; +import java.net.URL; + +import javax.swing.JFrame; +import javax.swing.JPanel; +import javax.swing.JTabbedPane; +import javax.swing.UIManager; +import javax.swing.event.HyperlinkEvent; +import javax.swing.event.HyperlinkListener; + +import net.sourceforge.jnlp.Launcher; +import net.sourceforge.jnlp.runtime.JNLPRuntime; + +public class Main extends JPanel implements HyperlinkListener { + + private final String notes = "/net/sourceforge/jnlp/about/resources/notes.html"; + private final String apps = "/net/sourceforge/jnlp/about/resources/applications.html"; + private final String about = "/net/sourceforge/jnlp/about/resources/about.html"; + JTabbedPane tabbedPane; + + public Main() throws IOException { + super(new BorderLayout()); + + HTMLPanel notesPanel = new HTMLPanel(getClass().getResource(notes)); + HTMLPanel appsPanel = new HTMLPanel(getClass().getResource(apps)); + HTMLPanel aboutPanel = new HTMLPanel(getClass().getResource(about)); + + appsPanel.pane.addHyperlinkListener(this); + + tabbedPane = new JTabbedPane(); + + tabbedPane.add("About NetX", aboutPanel); + tabbedPane.add("Applications", appsPanel); + tabbedPane.add("Notes", notesPanel); + + tabbedPane.setPreferredSize(new Dimension(550,410)); + add(tabbedPane, BorderLayout.CENTER); + } + + private static void createAndShowGUI() { + JNLPRuntime.setExitClass(Main.class); + + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + } + + JFrame frame = new JFrame("About NetX"); + frame.setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE); + Main demo = null; + try { + demo = new Main(); + } catch (Exception e) { + e.printStackTrace(); + System.exit(1); + } + demo.setOpaque(true); + frame.setContentPane(demo); + frame.pack(); + centerDialog(frame); + frame.setVisible(true); + } + + private static void centerDialog(JFrame frame) { + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension dialogSize = frame.getSize(); + + frame.setLocation((screen.width - dialogSize.width)/2, + (screen.height - dialogSize.height)/2); + } + + public static void main(String[] args) { + javax.swing.SwingUtilities.invokeLater(new Runnable() { + public void run() { + createAndShowGUI(); + } + }); + } + + public void hyperlinkUpdate(HyperlinkEvent e) { + if (e.getEventType() == HyperlinkEvent.EventType.ACTIVATED) { + URL url = e.getURL(); + + Launcher launcher = new Launcher( + JNLPRuntime.getDefaultLaunchHandler()); + try { + launcher.launchBackground(url); + } catch (Exception ex) { + ex.printStackTrace(); + } + } + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/net/sourceforge/jnlp/about/resources/about.html Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,28 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + <head> + <title> + </title> + </head> + <body> + <b>NetX</b> is a high-quality JNLP client that executes + network-based applications. + <br>NetX downloads code over the + network, caches it, and runs it in a secure sandbox + environment (unless signed). + <br><br><big><b> + Features of NetX: + </b></big> + <ul> + <li><b>Modular: </b>Easily add JNLP capabilities to an application.</li> + <li><b>Small Size: </b>Loads from a ~130K JAR file.</li> + <li><b>Saves Memory: </b>Launch programs in a shared JVM.</li> + <li><b>Fast startup:</b> Runs applications from a cache for fast starting. </li> + <li><b>Security:</b> Run any application in a sandbox or log its activities.</li> + <li><b>Auto-Update:</b> Applications can auto-update without special code.</li> + <li><b>Network Deployment:</b> Deploy to the internet, not with installers. </li> + <li><b>Open Source:</b> GNU Lesser General Public License.</li> + </ul> + </body> +</html> +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/net/sourceforge/jnlp/about/resources/applications.html Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,36 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> +<head> +<title>Applications</title> +</head> +<body> + +<big><b>Sample Applications:</b></big><br> +<b> <a href="http://www.jGoodies.com/download/jdiskreport/jdiskreport.jnlp">jDiskReport</a> -</b> http://www.jGoodies.com/download/jdiskreport/jdiskreport.jnlp<br> +<b> <a href="http://www.jgoodies.com/download/jpathreport/jpathreport.jnlp">jPathReport</a> -</b> http://www.jgoodies.com/download/jpathreport/jpathreport.jnlp<br> +<b> <a href="http://www.L2FProd.com/software/skinlf/jnlp/demo.php">Skin L2F Demo</a> -</b> http://www.L2FProd.com/software/skinlf/jnlp/demo.php<br> +<b> <a href="http://www.glub.com/products/secureftp/secureftp.jnlp">Secure FTP</a> -</b> http://www.glub.com/products/secureftp/secureftp.jnlp<br> +<b> <a href="http://www.jext.org/apps/jext.jnlp">Jext</a> -</b> http://www.jext.org/apps/jext.jnlp<br> +<b> <a href="http://www.javazoom.net/jlgui/jws/jlgui.jnlp">Java Music Player</a> -</b> http://www.javazoom.net/jlgui/jws/jlgui.jnlp<br> +<br> +<big><b>Apps using netx:</b></big><br> +<b> <a href="http://jnlp.sourceforge.net/netx/start/start.jnlp">Java Start Button</a> -</b> http://jnlp.sourceforge.net/netx/start/start.jnlp<br> +<br> +<big><b>Sun Demos:</b></big><br> +<b> <a href="http://java.sun.com/products/javawebstart/apps/swingset2.jnlp">SwingSet2</a> -</b> http://java.sun.com/products/javawebstart/apps/swingset2.jnlp<br> +<b> <a href="http://java.sun.com/products/javawebstart/apps/notepad.jnlp">Notepad</a> -</b> http://java.sun.com/products/javawebstart/apps/notepad.jnlp<br> +<b> <a href="http://java.sun.com/products/javawebstart/apps/draw.jnlp">Draw</a> -</b> http://java.sun.com/products/javawebstart/apps/draw.jnlp<br> +<b> <a href="http://java.sun.com/products/javawebstart/apps/mg.jnlp">Military Game</a> -</b> http://java.sun.com/products/javawebstart/apps/mg.jnlp<br> +<br> +<big><b>Tests:</b></big><br> + <a href="http://www.acm.vt.edu/~jmaxwell/security/SecurityTest.jnlp">Security Test</a><br> + <a href="http://www.acm.vt.edu/~jmaxwell/security/SecurityTestSigned.jnlp">Security Test (signed)</a><br> + <a href="http://www.acm.vt.edu/~jmaxwell/security/StrictTest.jnlp">Security Test (signed; fail strict JNLP)</a><br> + <a href="http://www.acm.vt.edu/~jmaxwell/security/PermissionList.jnlp">Permission Test</a><br> + <a href="http://www.acm.vt.edu/~jmaxwell/security/PermissionListSigned.jnlp">Permission Test (signed)</a> +<table cellpadding="0" cellspacing="0" border="0"> + <tbody><tr><td valign="Top" nowrap="true" bgcolor="#ffffff" width="500"><br> + </td></tr></tbody> +</table> +</body> +</html>
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/extra/net/sourceforge/jnlp/about/resources/notes.html Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,82 @@ +<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> +<html> + <head> + <title>Release Notes</title> + </head> + <body> + <br> + <table cellpadding="2" cellspacing="2" border="0" width="100%"> + <tbody> + <tr> + <td valign="Top" width="15"></td> + <td valign="Top" width="100%"> + <table cellpadding="0" cellspacing="0" border="0" align="Center"> + <tbody> + <tr> + <td valign="Middle" align="Center" nowrap="true"><div align="Center"> + <img src="jamIcon.jpg" alt="Jam Icon" width="87" height="84" align="Center"> + </div> + </td> + </tr> + <tr> + <td valign="Middle" nowrap="true" align="Justify"> + <div align="Center"> + <big><b>Jon A. Maxwell</b></big><br> + developer<br> + <big><b>Joshua Sumali</b></big><br> + developer + </div> + </td> + </tr> + </tbody> + </table> + </td> + </tr> + </tbody> + </table> +<br> +<big><b>Release Notes</b></big> +<br> +<table cellpadding="0" cellspacing="0" border="0"> + <tbody> + <tr> + <td valign="Top" width="15"><br></td> + + + <td valign="Top"> + NetX on IcedTea: Security Support + <ul> + <li> Full signed application support </li> + <li> User trusted certificates support </li> + <li> Some JNLP API Services implemented </li> + <li> Improved unsigned application sandboxing with JNLP API </li> + </ul> + </td> + </tr> + <tr> + <td valign="Top" width="15"><br></td> + <td valign="Top"> + Version 0.5: Refines multi-app capabilities + native code support + <ul> + <li> Released under LGPL. </li> + <li> Separate event queue, look and feel, etc for each application. </li> + <li> Native code support. </li> + <li> Supports headless mode. </li> + <li> Internationalized messages. </li> + <li> Uses NanoXML parser. </li> + <li> Minor changes listed on project web site... </li> + </ul> + + </td> + </tr> + </tbody> +</table> +<b>Please visit the SourceForge site + <a href="http://jnlp.sourceforge.net/netx/index.html"> + http://jnlp.sourceforge.net/netx/index.html + </a> + and the IcedTea site + <a href="http://iced-tea.org">http://iced-tea.org</a> + for more information.</b><br> +</body> +</html>
--- a/rt/net/sourceforge/jnlp/resources/Manifest.mf Wed Mar 05 08:37:23 2008 -0500 +++ b/rt/net/sourceforge/jnlp/resources/Manifest.mf Thu Mar 06 09:46:38 2008 -0500 @@ -2,5 +2,5 @@ Created-By: jnlp.sourceforge.net Specification-Title: netx JNLP client Sealed: true -Main-Class: net.sourceforge.jnlp.netx.jnlp.runtime.Boot13 +Main-Class: net.sourceforge.jnlp.runtime.Boot13
--- a/rt/net/sourceforge/jnlp/resources/Messages.properties Wed Mar 05 08:37:23 2008 -0500 +++ b/rt/net/sourceforge/jnlp/resources/Messages.properties Thu Mar 06 09:46:38 2008 -0500 @@ -105,7 +105,8 @@ RExitNoApp=Can not exit the JVM because the current application cannot be determined. # Boot options, message should be shorter than this ----------------> -BOUsage=Usage: java -jar netx.jar [-options] -jnlp location +BOUsage=javaws [-run-options] <jnlp file> +BOUsage2=javaws [-control-options] BOBasedir = Directory where the cache is kept. BOJnlp = Location of JNLP file to launch (url or file). BOArg = Adds an application argument before launching. @@ -114,11 +115,12 @@ BOUpdate = Update check if seconds since last checked. BOLicense = Display the GPL license and exit. BOVerbose = Enable verbose output. -BOAbout = Streamed from the internet. +BOAbout = Shows a sample application. BONosecurity= Disables the secure runtime environment. BONoupdate = Disables checking for updates. BOHeadless = Disables download window, other UIs. BOStrict = Enables strict checking of JNLP file format. +BOViewer = Shows the trusted certificate viewer. BOHelp = Print this message and exit. # Cache
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/net/sourceforge/jnlp/resources/about.jnlp Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<jnlp spec="1.0" href="about.jnlp" codebase="."> + <information> + <title>About window for NetX</title> + <vendor>NetX</vendor> + <homepage href="http://jnlp.sourceforge.net/netx/"/> + <description>Displays information about NetX</description> + <offline/> + </information> + <resources> + <j2se version="1.4+"/> + <jar href="about.jar"/> + </resources> + <security> + <all-permissions/> + </security> + <application-desc main-class="net.sourceforge.jnlp.about.Main"> + </application-desc> +</jnlp> +
--- a/rt/net/sourceforge/jnlp/runtime/Boot.java Wed Mar 05 08:37:23 2008 -0500 +++ b/rt/net/sourceforge/jnlp/runtime/Boot.java Thu Mar 06 09:46:38 2008 -0500 @@ -25,6 +25,7 @@ import net.sourceforge.jnlp.*; import net.sourceforge.jnlp.cache.*; import net.sourceforge.jnlp.runtime.*; +import net.sourceforge.jnlp.security.viewer.CertificateViewer; import net.sourceforge.jnlp.services.*; import net.sourceforge.jnlp.util.*; @@ -51,8 +52,8 @@ private static final String version = "0.5"; /** the JNLP file to open to display the network-based about window */ - private static final String aboutFile = - "http://jnlp.sourceforge.net/netx/about/netx"+version+".jnlp"; + private static final String aboutFile = + System.getProperty("java.home") + "/lib/about.jnlp"; /** the text to display before launching the about link */ private static final String aboutMessage = "" @@ -80,16 +81,21 @@ + "\n"; private static final String helpMessage = "\n" - + R("BOUsage")+"\n" + + "Usage: " + R("BOUsage")+"\n" + + " " + R("BOUsage2")+"\n" + + "\n" + + "control-options:"+"\n" + + " -about "+R("BOAbout")+"\n" + + " -viewer "+R("BOViewer")+"\n" + + "\n" + + "run-options:"+"\n" + " -basedir dir "+R("BOBasedir")+"\n" - + " -jnlp location "+R("BOJnlp")+"\n" + " -arg arg "+R("BOArg")+"\n" + " -param name=value "+R("BOParam")+"\n" + " -property name=value "+R("BOProperty")+"\n" + " -update seconds "+R("BOUpdate")+"\n" + " -license "+R("BOLicense")+"\n" + " -verbose "+R("BOVerbose")+"\n" - + " -about "+R("BOAbout")+"\n" + " -nosecurity "+R("BONosecurity")+"\n" + " -noupdate "+R("BONoupdate")+"\n" + " -headless "+R("BOHeadless")+"\n" @@ -106,6 +112,18 @@ */ public static void main(String[] argsIn) { args = argsIn; + + if (null != getOption("-viewer")) { + + try { + CertificateViewer.main(null); + System.exit(0); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + + } if (null != getOption("-license")) { System.out.println(miniLicense); @@ -131,8 +149,6 @@ if (null != getOption("-headless")) JNLPRuntime.setHeadless(true); - if (null != getOption("-verify")) - JNLPRuntime.setVerify(true); if (null != getOption("-noupdate")) JNLPRuntime.setDefaultUpdatePolicy(UpdatePolicy.NEVER); @@ -174,14 +190,16 @@ System.exit(1); } - private static String getDefaultFile() { + /** + * Returns the about.jnlp file in {java.home}/lib or null if this file + * does not exist. + */ + private static String getAboutFile() { - String defaultJnlpFile = System.getProperty("java.home") - + "/lib/default.jnlp"; - if (new File(defaultJnlpFile).exists()) - return defaultJnlpFile; - - return null; + if (new File(aboutFile).exists()) + return aboutFile; + else + return null; } /** @@ -189,28 +207,37 @@ * specified. */ private static JNLPFile getFile() throws ParseException, MalformedURLException, IOException { - String location = getOption("-jnlp"); - + + String location = getJNLPFile(); + // override -jnlp with aboutFile - if (null != getOption("-about")) - location = aboutFile; + if (getOption("-about") != null) { + location = getAboutFile(); + if (location == null) + fatalError("Unable to find about.jnlp in {java.home}/lib/"); + } else { + location = getJNLPFile(); + } - // still null, use default - if (location == null) - location = getDefaultFile(); - - if (location == null) - fatalError(R("BNeedsFile")+helpMessage); - + if (location == null) { + System.out.println(helpMessage); + System.exit(1); + } + if (JNLPRuntime.isDebug()) System.out.println(R("BFileLoc")+": "+location); URL url = null; - if (new File(location).exists()) - url = new File(location).toURL(); // Why use file.getCanonicalFile? - else - url = new URL(ServiceUtil.getBasicService().getCodeBase(), location); + try { + if (new File(location).exists()) + url = new File(location).toURL(); // Why use file.getCanonicalFile? + else + url = new URL(ServiceUtil.getBasicService().getCodeBase(), location); + } catch (Exception e) { + fatalError("Invalid jnlp file " + location); + } + boolean strict = (null != getOption("-strict")); JNLPFile file = new JNLPFile(url, strict); @@ -292,6 +319,35 @@ } /** + * Gets the JNLP file from the command line arguments, or exists upon error. + */ + private static String getJNLPFile() { + + if (args.length == 0) { + System.out.println(helpMessage); + System.exit(0); + } else if (args.length == 1) { + + String lastArg = args[args.length - 1]; + if (lastArg.endsWith(".jnlp")) { + return args[args.length - 1]; + } else + return null; + } else { + String lastArg = args[args.length - 1]; + String secondLastArg = args[args.length - 2]; + + if (doubleArgs.indexOf(secondLastArg) == -1) { + return lastArg; + } else { + System.out.println(helpMessage); + System.exit(0); + } + } + return null; + } + + /** * Return value of the first occurence of the specified * option, or null if the option is not present. If the * option is a flag (0-parameter) and is present then the
--- a/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java Wed Mar 05 08:37:23 2008 -0500 +++ b/rt/net/sourceforge/jnlp/runtime/JNLPRuntime.java Thu Mar 06 09:46:38 2008 -0500 @@ -442,7 +442,6 @@ resources = ResourceBundle.getBundle("net.sourceforge.jnlp.resources.Messages"); } catch (Exception ex) { - ex.printStackTrace(); throw new IllegalStateException("Missing resource bundle in netx.jar:net/sourceforge/jnlp/resource/Messages.properties"); } }
--- a/rt/net/sourceforge/jnlp/security/CertsInfoPane.java Wed Mar 05 08:37:23 2008 -0500 +++ b/rt/net/sourceforge/jnlp/security/CertsInfoPane.java Thu Mar 06 09:46:38 2008 -0500 @@ -67,14 +67,14 @@ private ArrayList<CertPath> certs; private JList list; - private JTree tree; + protected JTree tree; private JTable table; private JTextArea output; private ListSelectionModel listSelectionModel; private ListSelectionModel tableSelectionModel; - private String[] certNames; + protected String[] certNames; private String[] columnNames = { "Field", "Value" }; - private ArrayList<String[][]> certsData; + protected ArrayList<String[][]> certsData; public CertsInfoPane(JComponent x) { super(x); @@ -83,7 +83,7 @@ /** * Builds the JTree out of CertPaths. */ - private void buildTree() { + void buildTree() { //for now, we're only going to display the first signer, even though //jars can be signed by multiple people. CertPath firstPath = certs.get(0); @@ -118,59 +118,69 @@ } /** - * Constructs the GUI components of this UI + * Fills in certsNames, certsData with data from the certificates. */ - protected void installComponents() { + protected void populateTable() { certs = ((SecurityWarningDialog)optionPane).getJarSigner().getCerts(); - buildTree(); certNames = new String[certs.get(0).getCertificates().size()]; certsData = new ArrayList<String[][]>(); for (int i = 0; i < certs.get(0).getCertificates().size(); i++) { X509Certificate c = (X509Certificate) certs.get(0).getCertificates().get(i); - - String version = ""+c.getVersion(); - String serialNumber = c.getSerialNumber().toString(); - String signatureAlg = c.getSigAlgName(); - String issuer = c.getIssuerX500Principal().toString(); - String validity = new CertificateValidity(c.getNotBefore(), - c.getNotAfter()).toString(); - String subject = c.getSubjectX500Principal().toString(); - - //convert our signature into a nice human-readable form. - HexDumpEncoder encoder = new HexDumpEncoder(); - String signature = encoder.encodeBuffer(c.getSignature()); - - String md5Hash = ""; - String sha1Hash = ""; - try { - MessageDigest digest = MessageDigest.getInstance("MD5"); - digest.update(c.getEncoded()); - md5Hash = makeFingerprint(digest.digest()); - - digest = MessageDigest.getInstance("SHA-1"); - digest.update(c.getEncoded()); - sha1Hash = makeFingerprint(digest.digest()); - } catch (Exception e) { - //fail quietly - } - - String[][] cert = { {"Version", version}, - {"Serial", serialNumber}, - {"Signature Algorithm", signatureAlg}, - {"Issuer", issuer}, - {"Validity", validity}, - {"Subject", subject}, - {"Signature", signature}, - {"MD5 Fingerprint", md5Hash}, - {"SHA1 Fingerprint", sha1Hash} - }; - certsData.add(cert); + certsData.add(parseCert(c)); certNames[i] = getCN(c.getSubjectX500Principal().getName()) + " (" + getCN(c.getIssuerX500Principal().getName()) + ")"; } + } + + protected String[][] parseCert(X509Certificate c) { + + String version = ""+c.getVersion(); + String serialNumber = c.getSerialNumber().toString(); + String signatureAlg = c.getSigAlgName(); + String issuer = c.getIssuerX500Principal().toString(); + String validity = new CertificateValidity(c.getNotBefore(), + c.getNotAfter()).toString(); + String subject = c.getSubjectX500Principal().toString(); + //convert our signature into a nice human-readable form. + HexDumpEncoder encoder = new HexDumpEncoder(); + String signature = encoder.encodeBuffer(c.getSignature()); + + String md5Hash = ""; + String sha1Hash = ""; + try { + MessageDigest digest = MessageDigest.getInstance("MD5"); + digest.update(c.getEncoded()); + md5Hash = makeFingerprint(digest.digest()); + + digest = MessageDigest.getInstance("SHA-1"); + digest.update(c.getEncoded()); + sha1Hash = makeFingerprint(digest.digest()); + } catch (Exception e) { + //fail quietly + } + + String[][] cert = { {"Version", version}, + {"Serial", serialNumber}, + {"Signature Algorithm", signatureAlg}, + {"Issuer", issuer}, + {"Validity", validity}, + {"Subject", subject}, + {"Signature", signature}, + {"MD5 Fingerprint", md5Hash}, + {"SHA1 Fingerprint", sha1Hash} + }; + return cert; + } + + /** + * Constructs the GUI components of this UI + */ + protected void installComponents() { + buildTree(); + populateTable(); /** //List of Certs list = new JList(certNames); @@ -227,7 +237,7 @@ /** * Extracts the CN field from a Certificate principal string. */ - private String getCN(String principal) { + protected String getCN(String principal) { int start = principal.indexOf("CN="); int end = principal.indexOf(",", start); @@ -276,7 +286,7 @@ /** * Updates the JTable when the JTree selection has changed. */ - private class TreeSelectionHandler implements TreeSelectionListener { + protected class TreeSelectionHandler implements TreeSelectionListener { public void valueChanged(TreeSelectionEvent e) { DefaultMutableTreeNode node = (DefaultMutableTreeNode) tree.getLastSelectedPathComponent();
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/net/sourceforge/jnlp/security/SecurityUtil.java Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,200 @@ +/* SecurityUtil.java + Copyright (C) 2008 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package net.sourceforge.jnlp.security; + +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.security.KeyStore; + +public class SecurityUtil { + + private static String homeDir = null; + private static final String certDir = "/.netx/security/"; + private static final String certFile = "trusted.certs"; + private static final char[] password = "changeit".toCharArray(); + + public static String getTrustedCertsFilename() throws Exception{ + + homeDir = System.getProperty("user.home"); + + if (homeDir == null) { + throw new Exception("Could not access home directory"); + } else { + return homeDir + certDir + certFile; + } + } + + public static char[] getTrustedCertsPassword() { + return password; + } + + public static String getCN(String principal) { + int start = principal.indexOf("CN="); + int end = principal.indexOf(",", start); + + if (end == -1) { + end = principal.length(); + } + + if (start >= 0) + return principal.substring(start+3, end); + else + return principal; + } + + /** + * Checks the user's home directory to see if the trusted.certs file exists. + * If it does not exist, it tries to create an empty keystore. + * @return true if the trusted.certs file exists or a new trusted.certs + * was created successfully, otherwise false. + */ + public static boolean checkTrustedCertsFile() throws Exception { + + File certFile = new File(getTrustedCertsFilename()); + + //file does not exist + if (!certFile.isFile()) { + File dir = new File(homeDir+certDir); + boolean madeDir = false; + if (!dir.isDirectory()) { + madeDir = dir.mkdirs(); + } + + //made directory, or directory exists + if (madeDir || dir.isDirectory()) { + KeyStore ks = KeyStore.getInstance("JKS"); + ks.load(null, password); + FileOutputStream fos = new FileOutputStream(certFile); + ks.store(fos, password); + fos.close(); + return true; + } else { + return false; + } + } else { + return true; + } + } + + /** + * Returns the keystore associated with the user's trusted.certs file, + * or null otherwise. + */ + public static KeyStore getUserKeyStore() throws Exception { + + KeyStore ks = null; + FileInputStream fis = null; + + if (checkTrustedCertsFile()) { + + try { + File file = new File(getTrustedCertsFilename()); + if (file.exists()) { + fis = new FileInputStream(file); + ks = KeyStore.getInstance("JKS"); + ks.load(fis, password); + } + } catch (Exception e) { + e.printStackTrace(); + throw e; + } finally { + if (fis != null) + fis.close(); + } + } + return ks; + } + + /** + * Returns the keystore associated with the JDK cacerts file, + * or null otherwise. + */ + public static KeyStore getCacertsKeyStore() throws Exception { + + KeyStore caks = null; + FileInputStream fis = null; + + try { + File file = new File(System.getProperty("java.home") + + "/lib/security/cacerts"); + if (file.exists()) { + fis = new FileInputStream(file); + caks = KeyStore.getInstance("JKS"); + caks.load(fis, null); + } + } catch (Exception e) { + caks = null; + } finally { + if (fis != null) + fis.close(); + } + + return caks; + } + + /** + * Returns the keystore associated with the system certs file, + * or null otherwise. + */ + public static KeyStore getSystemCertStore() throws Exception { + + KeyStore caks = null; + FileInputStream fis = null; + + try { + File file = new File(System.getProperty("javax.net.ssl.trustStore")); + String type = System.getProperty("javax.net.ssl.trustStoreType"); + //String provider = "SUN"; + char[] password = System.getProperty( + "javax.net.ssl.trustStorePassword").toCharArray(); + if (file.exists()) { + fis = new FileInputStream(file); + caks = KeyStore.getInstance(type); + caks.load(fis, password); + } + } catch (Exception e) { + caks = null; + } finally { + if (fis != null) + fis.close(); + } + + return caks; + } +}
--- a/rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java Wed Mar 05 08:37:23 2008 -0500 +++ b/rt/net/sourceforge/jnlp/security/SecurityWarningDialog.java Thu Mar 06 09:46:38 2008 -0500 @@ -44,10 +44,12 @@ import javax.swing.*; import java.awt.event.*; import javax.swing.plaf.OptionPaneUI; + import java.beans.PropertyChangeListener; import java.beans.PropertyChangeEvent; import java.util.ArrayList; import java.security.cert.CertPath; +import java.security.cert.X509Certificate; /** * Provides methods for showing security warning dialogs @@ -62,6 +64,7 @@ CERT_WARNING, MORE_INFO, CERT_INFO, + SINGLE_CERT_INFO, ACCESS_WARNING, APPLET_WARNING } @@ -89,6 +92,8 @@ private JarSigner jarSigner; + private X509Certificate cert; + /** Whether or not this object has been fully initialized */ private boolean initialized = false; @@ -112,6 +117,17 @@ updateUI(); } + //for displaying a single certificate + public SecurityWarningDialog(DialogType dialogType, X509Certificate c) { + this.dialogType = dialogType; + this.accessType = null; + this.file = null; + this.jarSigner = null; + this.cert = c; + initialized = true; + updateUI(); + } + /** * Returns if this dialog has been fully initialized yet. * @return true if this dialog has been initialized, and false otherwise. @@ -224,6 +240,24 @@ dialog.dispose(); } + /** + * Displays a single certificate's information. + * + * @param c + * @param optionPane + */ + public static void showSingleCertInfoDialog(X509Certificate c, + JOptionPane parent) { + + SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.SINGLE_CERT_INFO, c); + JDialog dialog = swd.createDialog(); + dialog.setLocationRelativeTo(parent); + swd.selectInitialValue(); + dialog.setResizable(true); + dialog.setVisible(true); + dialog.dispose(); + } + public static int showAppletWarning() { SecurityWarningDialog swd = new SecurityWarningDialog(DialogType.APPLET_WARNING, null, null, null); @@ -320,6 +354,10 @@ public JarSigner getJarSigner() { return jarSigner; } + + public X509Certificate getCert() { + return cert; + } /** * Updates the UI using SecurityWarningOptionPane, instead of the @@ -333,6 +371,8 @@ setUI((OptionPaneUI) new MoreInfoPane(this)); else if (dialogType == DialogType.CERT_INFO) setUI((OptionPaneUI) new CertsInfoPane(this)); + else if (dialogType == DialogType.SINGLE_CERT_INFO) + setUI((OptionPaneUI) new SingleCertInfoPane(this)); else if (dialogType == DialogType.ACCESS_WARNING) setUI((OptionPaneUI) new AccessWarningPane(this)); else if (dialogType == DialogType.APPLET_WARNING)
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/net/sourceforge/jnlp/security/SingleCertInfoPane.java Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,77 @@ +/* SingleCertInfoPane.java + Copyright (C) 2008 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package net.sourceforge.jnlp.security; + +import java.security.cert.X509Certificate; +import java.util.ArrayList; + +import javax.swing.JComponent; +import javax.swing.JTree; +import javax.swing.tree.DefaultMutableTreeNode; +import javax.swing.tree.TreeSelectionModel; + +public class SingleCertInfoPane extends CertsInfoPane { + + public SingleCertInfoPane(JComponent x) { + super(x); + } + + protected void buildTree() { + X509Certificate cert = ((SecurityWarningDialog)optionPane).getCert(); + String subjectString = + getCN(cert.getSubjectX500Principal().getName()); + String issuerString = + getCN(cert.getIssuerX500Principal().getName()); + + DefaultMutableTreeNode top = new DefaultMutableTreeNode(subjectString + + " (" + issuerString + ")"); + + tree = new JTree(top); + tree.getSelectionModel().setSelectionMode(TreeSelectionModel.SINGLE_TREE_SELECTION); + tree.addTreeSelectionListener(new TreeSelectionHandler()); + } + + protected void populateTable() { + X509Certificate c = ((SecurityWarningDialog)optionPane).getCert(); + certNames = new String[1]; + certsData = new ArrayList<String[][]>(); + certsData.add(parseCert(c)); + certNames[0] = getCN(c.getSubjectX500Principal().getName()) + + " (" + getCN(c.getIssuerX500Principal().getName()) + ")"; + } +}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/net/sourceforge/jnlp/security/viewer/CertificatePane.java Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,358 @@ +/* CertificatePane.java + Copyright (C) 2008 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package net.sourceforge.jnlp.security.viewer; + +import java.awt.BorderLayout; +import java.awt.Dimension; +import java.awt.FlowLayout; +import java.awt.event.ActionEvent; +import java.awt.event.ActionListener; +import java.awt.event.KeyEvent; +import java.io.File; +import java.io.FileInputStream; +import java.io.FileOutputStream; +import java.io.PrintStream; +import java.security.KeyStore; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; + + +import javax.swing.BorderFactory; +import javax.swing.JButton; +import javax.swing.JComponent; +import javax.swing.JFileChooser; +import javax.swing.JOptionPane; +import javax.swing.JPanel; +import javax.swing.JRootPane; +import javax.swing.JTabbedPane; +import javax.swing.JTable; +import javax.swing.ListSelectionModel; +import javax.swing.SwingUtilities; +import javax.swing.UIManager; +import javax.swing.plaf.OptionPaneUI; +import javax.swing.table.DefaultTableModel; +import javax.swing.JScrollPane; + +import net.sourceforge.jnlp.runtime.JNLPRuntime; +import net.sourceforge.jnlp.security.SecurityUtil; +import net.sourceforge.jnlp.security.SecurityWarningDialog; +import net.sourceforge.jnlp.security.SecurityDialogUI; +import net.sourceforge.jnlp.tools.KeyTool; + +//import java.security.KeyStoreException; +//import java.security.NoSuchAlgorithmException; +//import java.security.cert.CertificateException; +//import java.io.FileNotFoundException; +//import java.io.IOException; + + +// note: We might want to extend OptionPaneUI instead +public class CertificatePane extends SecurityDialogUI { + + /** + * The certificates stored in the user's trusted.certs file. + */ + private ArrayList<X509Certificate> certs = null; + + /** + * "Issued To" and "Issued By" string pairs for certs. + */ + private String[][] issuedToAndBy = null; + private final String[] columnNames = { "Issued To", "Issued By" }; + + private JTable table; + + /** + * The KeyStore associated with the user's trusted.certs file. + */ + private KeyStore keyStore = null; + + public CertificatePane(JComponent x) { + super(x); + initializeKeyStore(); + } + + /** + * Reads the user's trusted.cacerts keystore. + */ + private void initializeKeyStore() { + try { + keyStore = SecurityUtil.getUserKeyStore(); + } catch (Exception e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Installs the user interface for the SecurityWarningDialog. + */ + public void installUI(JComponent c) { + + //Only install the UI when type and file in SecurityWarningDialog + //have been set. + if (((CertificateViewer)c).isInitialized()) { + setSystemLookAndFeel(); + optionPane = (JOptionPane)c; + optionPane.setLayout(new BorderLayout()); + installComponents(); + installListeners(); + } + } + + private void setSystemLookAndFeel() { + try { + UIManager.setLookAndFeel(UIManager.getSystemLookAndFeelClassName()); + } catch (Exception e) { + //don't worry if we can't. + } + } + + //create the GUI here. + protected void installComponents() { + readKeyStore(); + + JPanel main = new JPanel(new BorderLayout()); + + JPanel tablePanel = new JPanel(new BorderLayout()); + + //Table + DefaultTableModel tableModel + = new DefaultTableModel(issuedToAndBy, columnNames); + table = new JTable(tableModel); + table.getTableHeader().setReorderingAllowed(false); + table.setFillsViewportHeight(true); + JScrollPane tablePane = new JScrollPane(table); + tablePane.setPreferredSize(new Dimension(500,200)); + tablePane.setSize(new Dimension(500,200)); + tablePane.setBorder(BorderFactory.createEmptyBorder(10,10,10,10)); + + JTabbedPane tabbedPane = new JTabbedPane(); + tabbedPane.addTab("User", tablePane); + JPanel buttonPanel = new JPanel(new FlowLayout()); + + String[] buttonNames = {"Import", "Export", "Remove", "Details"}; + char[] buttonMnemonics = { KeyEvent.VK_I, + KeyEvent.VK_E, + KeyEvent.VK_M, + KeyEvent.VK_D}; + ActionListener[] listeners = { new ImportButtonListener(), + new ExportButtonListener(), + new RemoveButtonListener(), + new DetailsButtonListener() }; + JButton button; + + //get the max width + int maxWidth = 0; + for (int i = 0; i < buttonNames.length; i++) { + button = new JButton(buttonNames[i]); + maxWidth = Math.max(maxWidth, button.getMinimumSize().width); + } + + for (int i = 0; i < buttonNames.length; i++) { + button = new JButton(buttonNames[i]); + button.setMnemonic(buttonMnemonics[i]); + button.addActionListener(listeners[i]); + button.setSize(maxWidth, button.getSize().height); + buttonPanel.add(button); + } + + tablePanel.add(tabbedPane, BorderLayout.CENTER); + tablePanel.add(buttonPanel, BorderLayout.SOUTH); + + JPanel closePanel = new JPanel(new BorderLayout()); + closePanel.setBorder(BorderFactory.createEmptyBorder(7,7,7,7)); + JButton closeButton = new JButton("Close"); + closeButton.addActionListener(createButtonActionListener(0)); + closePanel.add(closeButton, BorderLayout.EAST); + + main.add(tablePanel, BorderLayout.CENTER); + main.add(closePanel, BorderLayout.SOUTH); + + optionPane.add(main); + + } + + /** + * Read in the optionPane's keystore to issuedToAndBy. + */ + private void readKeyStore() { + + Enumeration<String> aliases = null; + certs = new ArrayList<X509Certificate>(); + try { + + //Get all of the X509Certificates and put them into an ArrayList + aliases = keyStore.aliases(); + while (aliases.hasMoreElements()) { + Certificate c = keyStore.getCertificate(aliases.nextElement()); + if (c instanceof X509Certificate) + certs.add((X509Certificate)c); + } + + //get the publisher and root information + issuedToAndBy = new String[certs.size()][2]; + for (int i = 0; i < certs.size(); i++) { + X509Certificate c = certs.get(i); + issuedToAndBy[i][0] = + SecurityUtil.getCN(c.getSubjectX500Principal().getName()); + issuedToAndBy[i][1] = + SecurityUtil.getCN(c.getIssuerX500Principal().getName()); + } + } catch (Exception e) { + //TODO + } + } + + /** + * Re-reads the certs file and repopulates the JTable. This is typically + * called after a certificate was deleted from the keystore. + */ + private void repopulateTable() { + initializeKeyStore(); + readKeyStore(); + DefaultTableModel tableModel + = new DefaultTableModel(issuedToAndBy, columnNames); + + table.setModel(tableModel); + optionPane.repaint(); + } + + private class ImportButtonListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + + JFileChooser chooser = new JFileChooser(); + int returnVal = chooser.showOpenDialog(optionPane); + if(returnVal == JFileChooser.APPROVE_OPTION) { + try { + KeyTool kt = new KeyTool(); + kt.importCert(chooser.getSelectedFile()); + repopulateTable(); + } catch (Exception ex) { + // TODO: handle exception + ex.printStackTrace(); + } + } + } + } + + private class ExportButtonListener implements ActionListener { + public void actionPerformed(ActionEvent e) { + //For now, let's just export in -rfc mode as keytool does. + //we'll write to a file the exported certificate. + + + try { + int selectedRow = table.getSelectedRow(); + if (selectedRow != -1) { + JFileChooser chooser = new JFileChooser(); + int returnVal = chooser.showOpenDialog(optionPane); + if(returnVal == JFileChooser.APPROVE_OPTION) { + String alias = keyStore.getCertificateAlias(certs + .get(selectedRow)); + if (alias != null) { + Certificate c = keyStore.getCertificate(alias); + PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath()); + KeyTool.dumpCert(c, ps); + repopulateTable(); + } + } + } + } catch (Exception ex) { + // TODO + ex.printStackTrace(); + } + } + } + + private class RemoveButtonListener implements ActionListener { + + /** + * Removes a certificate from the keyStore and writes changes to disk. + */ + public void actionPerformed(ActionEvent e) { + + try { + int selectedRow = table.getSelectedRow(); + + if (selectedRow != -1){ + String alias = keyStore.getCertificateAlias(certs.get(selectedRow)); + if (alias != null) { + + int i = JOptionPane.showConfirmDialog(optionPane, + "Are you sure you want to remove the selected certificate?", + "Confirmation - Remove Certificate?", + JOptionPane.YES_NO_OPTION); + if (i == 0) { + keyStore.deleteEntry(alias); + FileOutputStream fos = new FileOutputStream( + SecurityUtil.getTrustedCertsFilename()); + keyStore.store(fos, SecurityUtil.getTrustedCertsPassword()); + fos.close(); + } + } + repopulateTable(); + } + } catch (Exception ex) { + // TODO + ex.printStackTrace(); + } + + } + } + + private class DetailsButtonListener implements ActionListener { + + /** + * Shows the details of a trusted certificate. + */ + public void actionPerformed(ActionEvent e) { + + int selectedRow = table.getSelectedRow(); + if (selectedRow != -1 && selectedRow >= 0) { + X509Certificate c = certs.get(selectedRow); + SecurityWarningDialog.showSingleCertInfoDialog(c, optionPane); + } + } + } + +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rt/net/sourceforge/jnlp/security/viewer/CertificateViewer.java Thu Mar 06 09:46:38 2008 -0500 @@ -0,0 +1,148 @@ +/* CertificateViewer.java + Copyright (C) 2008 Red Hat, Inc. + +This file is part of IcedTea. + +IcedTea is free software; you can redistribute it and/or +modify it under the terms of the GNU General Public License as published by +the Free Software Foundation, version 2. + +IcedTea is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +General Public License for more details. + +You should have received a copy of the GNU General Public License +along with IcedTea; see the file COPYING. If not, write to +the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA +02110-1301 USA. + +Linking this library statically or dynamically with other modules is +making a combined work based on this library. Thus, the terms and +conditions of the GNU General Public License cover the whole +combination. + +As a special exception, the copyright holders of this library give you +permission to link this library with independent modules to produce an +executable, regardless of the license terms of these independent +modules, and to copy and distribute the resulting executable under +terms of your choice, provided that you also meet, for each linked +independent module, the terms and conditions of the license of that +module. An independent module is a module which is not derived from +or based on this library. If you modify this library, you may extend +this exception to your version of the library, but you are not +obligated to do so. If you do not wish to do so, delete this +exception statement from your version. +*/ + +package net.sourceforge.jnlp.security.viewer; + +import java.awt.BorderLayout; +import java.awt.Container; +import java.awt.Dimension; +import java.awt.Frame; +import java.awt.Toolkit; +import java.awt.event.ComponentAdapter; +import java.awt.event.ComponentEvent; +import java.awt.event.WindowAdapter; +import java.awt.event.WindowEvent; +import java.beans.PropertyChangeEvent; +import java.beans.PropertyChangeListener; + +import javax.swing.JDialog; +import javax.swing.JOptionPane; +import javax.swing.plaf.OptionPaneUI; + +public class CertificateViewer extends JOptionPane { + + private boolean initialized = false; + + public CertificateViewer() throws Exception { + + initialized = true; + updateUI(); + } + + public boolean isInitialized(){ + return initialized; + } + + public void updateUI() { + setUI((OptionPaneUI) new CertificatePane(this)); + } + + private static void centerDialog(JDialog dialog) { + Dimension screen = Toolkit.getDefaultToolkit().getScreenSize(); + Dimension dialogSize = dialog.getSize(); + + dialog.setLocation((screen.width - dialogSize.width)/2, + (screen.height - dialogSize.height)/2); + } + + //Modified from javax.swing.JOptionPane + private JDialog createDialog() { + String dialogTitle = "Certificates"; + final JDialog dialog = new JDialog((Frame)null, dialogTitle, true); + + Container contentPane = dialog.getContentPane(); + contentPane.setLayout(new BorderLayout()); + contentPane.add(this, BorderLayout.CENTER); + dialog.pack(); + + WindowAdapter adapter = new WindowAdapter() { + private boolean gotFocus = false; + public void windowClosing(WindowEvent we) { + setValue(null); + } + public void windowGainedFocus(WindowEvent we) { + // Once window gets focus, set initial focus + if (!gotFocus) { + selectInitialValue(); + gotFocus = true; + } + } + }; + dialog.addWindowListener(adapter); + dialog.addWindowFocusListener(adapter); + + dialog.addComponentListener(new ComponentAdapter() { + public void componentShown(ComponentEvent ce) { + // reset value to ensure closing works properly + setValue(JOptionPane.UNINITIALIZED_VALUE); + } + }); + + addPropertyChangeListener( new PropertyChangeListener() { + public void propertyChange(PropertyChangeEvent event) { + // Let the defaultCloseOperation handle the closing + // if the user closed the window without selecting a button + // (newValue = null in that case). Otherwise, close the dialog. + if (dialog.isVisible() && + event.getSource() == CertificateViewer.this && + (event.getPropertyName().equals(VALUE_PROPERTY) || + event.getPropertyName().equals(INPUT_VALUE_PROPERTY)) && + event.getNewValue() != null && + event.getNewValue() != JOptionPane.UNINITIALIZED_VALUE) { + dialog.setVisible(false); + } + } + }); + + return dialog; + } + + public static void showCertificateViewer() throws Exception { + CertificateViewer cv = new CertificateViewer(); + JDialog dialog = cv.createDialog(); + cv.selectInitialValue(); + dialog.setResizable(true); + centerDialog(dialog); + dialog.setVisible(true); + dialog.dispose(); + } + + public static void main(String[] args) throws Exception { + CertificateViewer.showCertificateViewer(); + } +} +
--- a/rt/net/sourceforge/jnlp/tools/KeyTool.java Wed Mar 05 08:37:23 2008 -0500 +++ b/rt/net/sourceforge/jnlp/tools/KeyTool.java Thu Mar 06 09:46:38 2008 -0500 @@ -25,14 +25,19 @@ package net.sourceforge.jnlp.tools; +import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; +import java.io.IOException; +import java.io.InputStream; import java.io.PrintStream; import java.security.KeyStore; import java.security.MessageDigest; import java.security.PublicKey; import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.CertificateFactory; import java.security.cert.X509Certificate; import java.security.Principal; import java.util.Enumeration; @@ -40,6 +45,11 @@ import java.util.Hashtable; import java.util.Vector; +import net.sourceforge.jnlp.security.SecurityUtil; + +import sun.misc.BASE64Encoder; +import sun.security.provider.X509Factory; + /** * This tool manages the user's trusted certificates * @@ -54,13 +64,9 @@ private KeyStore cacerts = null; // System ca-bundle.crt private KeyStore systemcerts = null; - private String homeDir = null; - private final String certPath = "/.netx/security/"; - private final String certFile = "trusted.certs"; - private String fullCertPath = null; - //private CertificateFactory cf = null; + + private String fullCertPath = SecurityUtil.getTrustedCertsFilename(); - private FileInputStream fis = null; private FileOutputStream fos = null; /** @@ -68,6 +74,11 @@ */ private boolean trustcacerts = true; + /** + * Whether we print certificates in rfc, base64 encoding. + */ + private boolean rfc = true; + private final char[] password = "changeit".toCharArray(); /** @@ -78,13 +89,36 @@ public KeyTool() throws Exception { // Initialize all the keystores. - usercerts = getUserKeyStore(); - cacerts = getCacertsKeyStore(); - systemcerts = getSystemCertStore(); + usercerts = SecurityUtil.getUserKeyStore(); + cacerts = SecurityUtil.getCacertsKeyStore(); + systemcerts = SecurityUtil.getSystemCertStore(); } /** - * Add's a trusted certificate to the user's keystore. + * Adds a trusted certificate to the user's keystore. + * @return true if the add was successful, false otherwise. + */ + public boolean importCert(File file) throws Exception { + + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file)); + CertificateFactory cf = CertificateFactory.getInstance("X509"); + X509Certificate cert = null; + + if (bis.available() >= 1) { + try { + cert = (X509Certificate)cf.generateCertificate(bis); + } catch (ClassCastException cce) { + throw new Exception("Input file is not an X509 Certificate"); + } catch (CertificateException ce) { + throw new Exception("Input file is not an X509 Certificate"); + } + } + + return importCert((Certificate)cert); + } + + /** + * Adds a trusted certificate to the user's keystore. * @return true if the add was successful, false otherwise. */ public boolean importCert(Certificate cert) throws Exception { @@ -112,41 +146,6 @@ } /** - * Checks the user's home directory to see if the trusted.certs file exists. - * If it does not exist, it tries to create an empty keystore. - * @return true if the trusted.certs file exists or a new trusted.certs - * was created successfully, otherwise false. - */ - private boolean checkFiles() throws Exception { - - File certFile = new File(fullCertPath); - - if (!certFile.isFile()) { //file does not exist - File certDir = new File(homeDir+certPath); - boolean madeDir = false; - if (!certDir.isDirectory()) { //directory does not exist - madeDir = (new File(homeDir+certPath)).mkdirs(); - } - - // If we successfully made the directory, - // or the directory already exists (but the file does - // not), then create the keystore. - if (madeDir || certDir.isDirectory()) { - usercerts = KeyStore.getInstance("JKS"); - usercerts.load(null, password); - fos = new FileOutputStream(certFile); - usercerts.store(fos, password); - fos.close(); - return true; - } else { - return false; - } - } else { //cert file already exists - return true; - } - } - - /** * Prints all keystore entries. */ private void doPrintEntries(PrintStream out) throws Exception { @@ -283,81 +282,6 @@ return cert.getSubjectDN().equals(cert.getIssuerDN()); } - /** - * Returns the keystore associated with the users - * trusted.certs file, or null otherwise. - */ - private KeyStore getUserKeyStore() throws Exception { - - homeDir = System.getProperty("user.home"); - fullCertPath = homeDir + certPath + certFile; - KeyStore ks = KeyStore.getInstance("JKS"); - - if (ks != null && checkFiles()) { - fis = new FileInputStream(fullCertPath); - ks.load(fis, password); - if (fis != null) - fis.close(); - } - return ks; - } - - /** - * Returns the keystore associated with the JDK cacerts file, - * or null otherwise. - */ - private KeyStore getCacertsKeyStore() throws Exception { - - KeyStore caks = null; - FileInputStream fis = null; - - try { - String sep = File.separator; - File file = new File(System.getProperty("java.home") + sep - + "lib" + sep + "security" + sep - + "cacerts"); - caks = null; - fis = new FileInputStream(file); - caks = KeyStore.getInstance("JKS"); - caks.load(fis, null); - } catch (Exception e) { - caks = null; - } finally { - if (fis != null) - fis.close(); - } - - return caks; - } - - /** - * Returns the keystore associated with the system certs file, - * or null otherwise. - */ - private KeyStore getSystemCertStore() throws Exception { - - KeyStore caks = null; - FileInputStream fis = null; - - try { - String file = System.getProperty("javax.net.ssl.trustStore"); - String type = System.getProperty("javax.net.ssl.trustStoreType"); - String provider = "SUN"; - char[] password = System.getProperty( - "javax.net.ssl.trustStorePassword").toCharArray(); - caks = KeyStore.getInstance(type); - fis = new FileInputStream(file); - caks.load(fis, password); - } catch (Exception e) { - caks = null; - } finally { - if (fis != null) - fis.close(); - } - - return caks; - } - /** * Checks if a given certificate is part of the user's cacerts * keystore. @@ -428,7 +352,7 @@ keystorecerts2Hashtable(usercerts, certs); } if (trustcacerts) { //if we're trusting the cacerts - KeyStore caks = getCacertsKeyStore(); + KeyStore caks = SecurityUtil.getCacertsKeyStore(); if (caks!=null && caks.size()>0) { if (certs == null) { certs = new Hashtable<Principal, Vector<Certificate>>(11); @@ -534,6 +458,20 @@ return false; } + public static void dumpCert(Certificate cert, PrintStream out) + throws IOException, CertificateException { + + boolean printRfc = true; + if (printRfc) { + BASE64Encoder encoder = new BASE64Encoder(); + out.println(X509Factory.BEGIN_CERT); + encoder.encodeBuffer(cert.getEncoded(), out); + out.println(X509Factory.END_CERT); + } else { + out.write(cert.getEncoded()); // binary + } + } + public static void main(String[] args) throws Exception { KeyTool kt = new KeyTool(); kt.doPrintEntries(System.out);