Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable Windows Key Store Access #820

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,9 @@
import net.sourceforge.jnlp.runtime.JNLPRuntime;
import net.sourceforge.jnlp.security.CertificateUtils;
import net.sourceforge.jnlp.security.KeyStores;
import net.sourceforge.jnlp.security.KeyStores.KeyStoreWrap;
import net.sourceforge.jnlp.security.KeyStores.KeyStoreWindows;
import net.sourceforge.jnlp.security.KeyStores.KeyStoreWithPath;
import net.sourceforge.jnlp.security.KeyStores.Level;
import net.sourceforge.jnlp.security.SecurityUtil;
import net.sourceforge.jnlp.util.RestrictedFileUtils;
Expand Down Expand Up @@ -111,7 +114,7 @@ public class CertificatePane extends JPanel {
};

JTabbedPane tabbedPane;
JTextField certPath = new JTextField();
JTextField certLocation = new JTextField();
private final JTable userTable;
private final JTable systemTable;
private JComboBox<CertificateType> certificateTypeCombo;
Expand All @@ -120,6 +123,7 @@ public class CertificatePane extends JPanel {

/** JComponents that should be disabled for system store */
private final List<JComponent> disableForSystem;
private final List<JComponent> disableForWindowsStores;

private Window parent;
private JComponent defaultFocusComponent = null;
Expand All @@ -128,7 +132,7 @@ public class CertificatePane extends JPanel {
* The Current KeyStore. Only one table/tab is visible for interaction to
* the user. This KeyStore corresponds to that.
*/
private KeyStores.KeyStoreWithPath keyStore = null;
private KeyStoreWrap keyStoreWrap = null;

public CertificatePane(Window parent) {
super();
Expand All @@ -139,6 +143,7 @@ public CertificatePane(Window parent) {
systemTable = new JTable(null);
systemTable.setAutoCreateRowSorter(true);
disableForSystem = new ArrayList<>();
disableForWindowsStores = new ArrayList<>();

addComponents();

Expand All @@ -157,7 +162,7 @@ public CertificatePane(Window parent) {
*/
private void initializeKeyStore() {
try {
keyStore = KeyStores.getKeyStore(currentKeyStoreLevel, currentKeyStoreType);
keyStoreWrap = KeyStores.getWrapContainer(currentKeyStoreLevel, currentKeyStoreType).getWrap();
} catch (Exception e) {
LOG.error(IcedTeaWebConstants.DEFAULT_ERROR_MESSAGE, e);
}
Expand Down Expand Up @@ -224,24 +229,24 @@ private void addComponents() {
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);
button.setSize(maxWidth, button.getSize().height);
// import and remove buttons
if (i == 0 || i == 2) {
disableForSystem.add(button);
disableForSystem.add(button);
disableForWindowsStores.add(button);
}
buttonPanel.add(button);
}

tablePanel.add(tabbedPane, BorderLayout.CENTER);
JPanel buttonPanelWrapper = new JPanel(new BorderLayout());
certPath.setEditable(false);
buttonPanelWrapper.add(certPath, BorderLayout.CENTER);
certLocation.setEditable(false);
buttonPanelWrapper.add(certLocation, BorderLayout.CENTER);
buttonPanelWrapper.add(buttonPanel, BorderLayout.EAST);
tablePanel.add(buttonPanelWrapper, BorderLayout.SOUTH);
main.add(certificateTypePanel, BorderLayout.NORTH);
Expand Down Expand Up @@ -277,9 +282,9 @@ private void readKeyStore() {
try {

//Get all of the X509Certificates and put them into an ArrayList
aliases = keyStore.getKs().aliases();
aliases = keyStoreWrap.getKs().aliases();
while (aliases.hasMoreElements()) {
Certificate c = keyStore.getKs().getCertificate(aliases.nextElement());
Certificate c = keyStoreWrap.getKs().getCertificate(aliases.nextElement());
if (c instanceof X509Certificate) {
certs.add((X509Certificate) c);
}
Expand Down Expand Up @@ -308,15 +313,40 @@ private void repopulateTables() {
initializeKeyStore();
readKeyStore();
try {
File src = new File(keyStore.getPath());
File resolved = src.getCanonicalFile();
if (resolved.equals(src)) {
certPath.setText(keyStore.getPath());
LOG.info(keyStore.getPath());
} else {
certPath.setText(keyStore.getPath() + " -> " + resolved.getCanonicalPath());
LOG.info("{} -> {}", keyStore.getPath(), resolved.getCanonicalPath());
}

KeyStores.Family keyStoreFamily = keyStoreWrap.getFamily();

switch(keyStoreFamily) {

case JKS:
KeyStoreWithPath keyStorePath = (KeyStoreWithPath)keyStoreWrap;

File src = new File(keyStorePath.getPath());
File resolved = src.getCanonicalFile();
if (resolved.equals(src)) {
certLocation.setText(keyStorePath.getPath());
LOG.info(keyStorePath.getPath());
} else {
certLocation.setText(keyStorePath.getPath() + " -> " + resolved.getCanonicalPath());
LOG.info("{} -> {}", keyStorePath.getPath(), resolved.getCanonicalPath());
}

if(currentKeyStoreLevel == Level.USER) {
for (JComponent component : disableForSystem) {
component.setEnabled(true);
}
}
case WINDOWS:
KeyStoreWindows keyStoreWin = (KeyStoreWindows)keyStoreWrap;

certLocation.setText(keyStoreWin.getStoreType().getDescription());

for (JComponent component : disableForWindowsStores) {
component.setEnabled(false);
}

LOG.info(keyStoreWin.getStoreType().getDescription());
}
} catch (Exception ex) {
LOG.error(IcedTeaWebConstants.DEFAULT_ERROR_MESSAGE, ex);
}
Expand Down Expand Up @@ -380,6 +410,7 @@ public void actionPerformed(ActionEvent e) {
* or vice versa). Changes the currentKeyStore Enables or disables buttons.
*/
private class TabChangeListener implements ChangeListener {

@Override
public void stateChanged(ChangeEvent e) {
JTabbedPane source = (JTabbedPane) e.getSource();
Expand All @@ -388,7 +419,8 @@ public void stateChanged(ChangeEvent e) {
currentKeyStoreLevel = Level.USER;
for (JComponent component : disableForSystem) {
component.setEnabled(true);
}
}

break;
case 1:
currentKeyStoreLevel = Level.SYSTEM;
Expand All @@ -410,11 +442,11 @@ public void actionPerformed(ActionEvent e) {
int returnVal = chooser.showOpenDialog(parent);
if (returnVal == JFileChooser.APPROVE_OPTION) {
try {
KeyStore ks = keyStore.getKs();
KeyStore ks = keyStoreWrap.getKs();
if (currentKeyStoreType == KeyStores.Type.CLIENT_CERTS) {
char[] password = getPassword(R("CVImportPasswordMessage"));
if (password != null) {
final KeyStore caks = KeyStores.getKeyStore(currentKeyStoreLevel, KeyStores.Type.CA_CERTS).getKs();
final KeyStore caks = KeyStores.getWrapContainer(currentKeyStoreLevel, KeyStores.Type.CA_CERTS).getWrap().getKs();
final int caksSize = caks.size();
CertificateUtils.addPKCS12ToKeyStore(chooser.getSelectedFile(), ks, password, caks);
if (caks.size() > caksSize) {
Expand Down Expand Up @@ -475,16 +507,16 @@ public void actionPerformed(ActionEvent e) {
JFileChooser chooser = new JFileChooser();
int returnVal = chooser.showSaveDialog(parent);
if (returnVal == JFileChooser.APPROVE_OPTION) {
String alias = keyStore.getKs().getCertificateAlias(certs
String alias = keyStoreWrap.getKs().getCertificateAlias(certs
.get(selectedRow));
if (alias != null) {
if (currentKeyStoreType == KeyStores.Type.CLIENT_CERTS) {
char[] password = getPassword(R("CVExportPasswordMessage"));
if (password != null) {
CertificateUtils.dumpPKCS12(alias, chooser.getSelectedFile(), keyStore.getKs(), password);
CertificateUtils.dumpPKCS12(alias, chooser.getSelectedFile(), keyStoreWrap.getKs(), password);
}
} else {
Certificate c = keyStore.getKs().getCertificate(alias);
Certificate c = keyStoreWrap.getKs().getCertificate(alias);
PrintStream ps = new PrintStream(chooser.getSelectedFile().getAbsolutePath());
CertificateUtils.dump(c, ps);
}
Expand Down Expand Up @@ -516,20 +548,20 @@ public void actionPerformed(ActionEvent e) {
int selectedRow = table.getSelectedRow();

if (selectedRow != -1) {
String alias = keyStore.getKs().getCertificateAlias(certs.get(selectedRow));
String alias = keyStoreWrap.getKs().getCertificateAlias(certs.get(selectedRow));
if (alias != null) {

int i = JOptionPane.showConfirmDialog(parent,
R("CVRemoveConfirmMessage"),
R("CVRemoveConfirmTitle"),
JOptionPane.YES_NO_OPTION);
if (i == 0) {
keyStore.getKs().deleteEntry(alias);
keyStoreWrap.getKs().deleteEntry(alias);
File keyStoreFile = KeyStores.getKeyStoreLocation(currentKeyStoreLevel, currentKeyStoreType).getFile();
if (!keyStoreFile.isFile()) {
RestrictedFileUtils.createRestrictedFile(keyStoreFile);
}
SecurityUtil.storeKeyStore(keyStore.getKs(), keyStoreFile);
SecurityUtil.storeKeyStore(keyStoreWrap.getKs(), keyStoreFile);
}
}
repopulateTables();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,7 @@ public void actionPerformed(ActionEvent e) {

public void saveCert() {
try {
KeyStore ks = KeyStores.getKeyStore(Level.USER, Type.CERTS).getKs();
KeyStore ks = KeyStores.getWrapContainer(Level.USER, Type.CERTS).getWrap().getKs();
X509Certificate c = (X509Certificate) parent.getCertVerifier().getPublisher(null);
CertificateUtils.addToKeyStore(c, ks);
File keyStoreFile = KeyStores.getKeyStoreLocation(Level.USER, Type.CERTS).getFile();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,15 @@ public interface ConfigurationConstants {
String KEY_SECURITY_EXPIRED_WARNING = "deployment.security.expired.warning";

String KEY_SECURITY_JSSE_HOSTMISMATCH_WARNING = "deployment.security.jsse.hostmismatch.warning";


/**
* Properties to manage to access Windows key stores
*/
String KEY_SECURITY_USE_ROOTCA_STORE_TYPE_WINDOWS_ROOT = "deployment.security.use.rootca.store.type.windowsRoot";

String KEY_SECURITY_USE_ROOTCA_STORE_TYPE_WINDOWS_MY = "deployment.security.use.rootca.store.type.windowsMy";


/**
* Boolean. Only show security prompts to user if true
Expand Down
15 changes: 15 additions & 0 deletions core/src/main/java/net/sourceforge/jnlp/config/Defaults.java
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,21 @@ public class Defaults {
ValidatorFactory.createFilePathValidator()
),

/*
* Windows certificates key stores
*/
Setting.createDefault(
ConfigurationConstants.KEY_SECURITY_USE_ROOTCA_STORE_TYPE_WINDOWS_ROOT,
String.valueOf(false),
ValidatorFactory.createBooleanValidator()
),
Setting.createDefault(
ConfigurationConstants.KEY_SECURITY_USE_ROOTCA_STORE_TYPE_WINDOWS_MY,
String.valueOf(false),
ValidatorFactory.createBooleanValidator()
),


/*
* security access and control
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -272,7 +272,7 @@ public static void initialize() throws IllegalStateException {
try {
SSLSocketFactory sslSocketFactory;
SSLContext context = SSLContext.getInstance("SSL");
KeyStore ks = KeyStores.getKeyStore(KeyStores.Level.USER, KeyStores.Type.CLIENT_CERTS).getKs();
KeyStore ks = KeyStores.getWrapContainer(KeyStores.Level.USER, KeyStores.Type.CLIENT_CERTS).getWrap().getKs();
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
SecurityUtil.initKeyManagerFactory(kmf, ks);
TrustManager[] trust = new TrustManager[] { getSSLSocketTrustManager() };
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -126,7 +126,7 @@ public static void addPKCS12ToKeyStore(File file, KeyStore ks, char[] password,
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
KeyStore keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(bis, password);
KeyStore systemCa = KeyStores.getKeyStore(KeyStores.Level.SYSTEM, KeyStores.Type.CA_CERTS).getKs();
KeyStore systemCa = KeyStores.getWrapContainer(KeyStores.Level.SYSTEM, KeyStores.Type.CA_CERTS).getWrap().getKs();

Enumeration<String> aliasList = keyStore.aliases();

Expand Down Expand Up @@ -182,7 +182,7 @@ public static boolean inKeyStores(X509Certificate c, List<KeyStore> keyStores) {
// Verify against this entry
final String alias = aliases.nextElement();
if (c.equals(keyStore.getCertificate(alias))) {
LOG.debug("{} found in cacerts ({})", c.getSubjectX500Principal().getName(), KeyStores.getPathToKeystore(keyStore));
LOG.debug("{} found in cacerts ({})", c.getSubjectX500Principal().getName(), KeyStores.getLocationToKeystore(keyStore));
return true;
} // else continue
}
Expand Down
Loading