### Eclipse Workspace Patch 1.0 #P org.tigris.subversion.subclipse.ui Index: src/org/tigris/subversion/subclipse/ui/authentication/SSLClientCertificatesMSCapi.java =================================================================== --- src/org/tigris/subversion/subclipse/ui/authentication/SSLClientCertificatesMSCapi.java (revision 0) +++ src/org/tigris/subversion/subclipse/ui/authentication/SSLClientCertificatesMSCapi.java (revision 0) @@ -0,0 +1,98 @@ +package org.tigris.subversion.subclipse.ui.authentication; + +import java.io.IOException; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.Provider; +import java.security.Security; +import java.security.cert.Certificate; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.util.ArrayList; +import java.util.Enumeration; +import java.util.List; + +import org.eclipse.jface.viewers.LabelProvider; +import org.eclipse.swt.widgets.Shell; +import org.eclipse.ui.dialogs.ListDialog; +import org.tigris.subversion.subclipse.ui.util.ListContentProvider; + +public class SSLClientCertificatesMSCapi extends ListDialog { + protected String alias; + + /** + * + * @param parent + * @param url : the url from which we want to get the root url + */ + public SSLClientCertificatesMSCapi(Shell parent, String realm) { + super(parent); + // List list = new ArrayList(); + List list = new ArrayList(); + Provider pmscapi = Security.getProvider("SunMSCAPI"); + Provider pjacapi = Security.getProvider("CAPI"); + try { + KeyStore keyStore = null; + //use JACAPI + if (pmscapi != null) { + keyStore = KeyStore.getInstance("Windows-MY",pmscapi); + pmscapi.setProperty("Signature.SHA1withRSA","sun.security.mscapi.RSASignature$SHA1"); + } else if (pjacapi != null) { + keyStore = KeyStore.getInstance("CAPI"); + } + if (keyStore != null) { + keyStore.load(null, null); + //for (Enumeration aliasEnumeration = keyStore.aliases();aliasEnumeration.hasMoreElements();) { + for (Enumeration aliasEnumeration = keyStore.aliases();aliasEnumeration.hasMoreElements();) { + String alias = (String) aliasEnumeration.nextElement(); + String issuer = ""; + Certificate cert = keyStore.getCertificate(alias); + if (cert instanceof X509Certificate) { + issuer = ((X509Certificate) cert).getIssuerDN().getName(); + } + list.add(new String[]{alias,issuer}); + //keyStore.getCertificate(alias) + } + } + } catch (KeyStoreException e) { + e.printStackTrace(); + } catch (NoSuchAlgorithmException e) { + e.printStackTrace(); + } catch (CertificateException e) { + e.printStackTrace(); + } catch (IOException e) { + e.printStackTrace(); + } + setTitle("Select Certificate Alias"); //$NON-NLS-1$ + setAddCancelButton(true); + LabelProvider lp = new LabelProvider(){ + public String getText(Object element) { + if (element == null) { + return ""; + } else if (element instanceof String[] && ((String[]) element).length > 1) { + return ((String[]) element)[0] + " | issued by: " + ((String[]) element)[1]; + } else { + return element.toString(); + } + } + }; + setLabelProvider(lp); + setMessage("select the right certificate alias"); //$NON-NLS-1$ + setContentProvider(new ListContentProvider()); + setInput(list); + } + + + public String getAlias() { + if (getResult() != null && getResult().length>0) { + Object result = getResult()[0]; + if (result instanceof String[]) { + this.alias = ((String[]) result)[0]; + } else { + this.alias = (String) result; + } + } + return alias; + } +} Index: src/org/tigris/subversion/subclipse/ui/authentication/SSLClientCertificate.java =================================================================== --- src/org/tigris/subversion/subclipse/ui/authentication/SSLClientCertificate.java (revision 4649) +++ src/org/tigris/subversion/subclipse/ui/authentication/SSLClientCertificate.java (working copy) @@ -10,13 +10,17 @@ ******************************************************************************/ package org.tigris.subversion.subclipse.ui.authentication; +import java.security.Provider; +import java.security.Security; import java.util.Properties; -import org.eclipse.jface.dialogs.TrayDialog; +import org.eclipse.core.runtime.Platform; import org.eclipse.jface.dialogs.IDialogConstants; +import org.eclipse.jface.dialogs.TrayDialog; import org.eclipse.swt.SWT; import org.eclipse.swt.events.SelectionAdapter; import org.eclipse.swt.events.SelectionEvent; +import org.eclipse.swt.events.SelectionListener; import org.eclipse.swt.layout.GridData; import org.eclipse.swt.layout.GridLayout; import org.eclipse.swt.widgets.Button; @@ -27,6 +31,7 @@ import org.eclipse.swt.widgets.Label; import org.eclipse.swt.widgets.Shell; import org.eclipse.swt.widgets.Text; +import org.tigris.subversion.subclipse.core.SVNProviderPlugin; import org.tigris.subversion.subclipse.ui.Policy; import org.tigris.subversion.subclipse.ui.SVNUIPlugin; @@ -36,13 +41,18 @@ private String passphrase; private boolean save; private boolean maySave; + private boolean msCapi; + private Button mscapiButton; private Combo keyFileCombo; private Text passphraseText; + private Text aliasText; private Button browseButton; private Button saveButton; private Button okButton; + private Button aliasButton; + private String alias; private String[] keyFiles = new String[0]; - + private static int WIDTH = 300; public SSLClientCertificate(Shell parentShell, String realm, boolean maySave) { @@ -51,7 +61,7 @@ this.maySave = maySave; keyFiles = SVNUIPlugin.getPlugin().getRepositoryManager().getKeyFilesManager().getPreviousKeyFiles(); } - + protected Control createDialogArea(Composite parent) { Composite rtnGroup = (Composite)super.createDialogArea(parent); getShell().setText(Policy.bind("SSLPromptDialog.title")); //$NON-NLS-1$ @@ -60,7 +70,7 @@ rtnGroup.setLayout(layout); rtnGroup.setLayoutData( new GridData(GridData.HORIZONTAL_ALIGN_BEGINNING)); - + Label realmLabel = new Label(rtnGroup, SWT.NONE); realmLabel.setText(Policy.bind("PasswordPromptDialog.repository")); //$NON-NLS-1$ Text realmText = new Text(rtnGroup, SWT.BORDER); @@ -69,10 +79,73 @@ realmText.setLayoutData(gd); realmText.setEditable(false); realmText.setText(realm); - + boolean mscapiSupport = false; + Provider pjacapi = Security.getProvider("CAPI"); + Provider pmscapi = Security.getProvider("SunMSCAPI"); + String svnClientText = ""; + if (SVNProviderPlugin.getPlugin() != null && SVNProviderPlugin.getPlugin().getSVNClientManager() != null) { + svnClientText = SVNProviderPlugin.getPlugin().getSVNClientManager().getSvnClientInterface(); + } + // ms capi is only suported for windows and for provider SunMSCAPI and JACAPI from keyon + // further ms capi is only supported from svnkit as client! + if (Platform.OS_WIN32 != null && !"".equals(Platform.OS_WIN32) && (pjacapi != null || pmscapi != null) && "svnkit".equals(svnClientText) ) { + mscapiSupport = true; + mscapiButton = new Button(rtnGroup, SWT.CHECK); + mscapiButton.setText("Get Certificate from Windows store (MSCAPI)");//Policy.bind("SSHPromptDialog.save")); //$NON-NLS-1$ + gd = new GridData(); + gd.horizontalSpan = 2; + mscapiButton.setLayoutData(gd); + SelectionListener mscapiSelectionListener = new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + if (mscapiButton.getSelection()) { + keyFileCombo.setEnabled(false); + browseButton.setEnabled(false); + passphraseText.setEnabled(false); + aliasButton.setEnabled(true); + } else { + keyFileCombo.setEnabled(true); + browseButton.setEnabled(true); + passphraseText.setEnabled(true); + aliasButton.setEnabled(false); + aliasText.setText(""); + } + } + }; + mscapiButton.addSelectionListener(mscapiSelectionListener); + Label aliasLabel = new Label(rtnGroup, SWT.NONE); + aliasLabel.setText("Alias:"); //$NON-NLS-1$ + + Composite ailiasSelectGroup = new Composite(rtnGroup, SWT.NONE); + GridLayout aliasLayout = new GridLayout(); + aliasLayout.numColumns = 2; + aliasLayout.marginWidth = 0; + aliasLayout.marginHeight = 0; + ailiasSelectGroup.setLayout(aliasLayout); + + gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL); + ailiasSelectGroup.setLayoutData(gd); + aliasText = new Text(ailiasSelectGroup, SWT.BORDER); + gd = new GridData(); + gd.widthHint = WIDTH; + aliasText.setLayoutData(gd); + aliasText.setEnabled(false); + aliasButton = new Button(ailiasSelectGroup, SWT.PUSH); + aliasButton.setText("Select alias"); //$NON-NLS-1$ + SelectionListener msCapiCertificateSelectionListener = new SelectionAdapter() { + public void widgetSelected(SelectionEvent e) { + SSLClientCertificatesMSCapi dialog = new SSLClientCertificatesMSCapi(SVNUIPlugin.getStandardDisplay().getActiveShell(), realm); + if (dialog.open() == SSLClientCertificatesMSCapi.OK) { + aliasText.setText(dialog.getAlias()); + } + } + }; + aliasButton.addSelectionListener(msCapiCertificateSelectionListener); + aliasButton.setEnabled(false); + } + Label keyFileLabel = new Label (rtnGroup, SWT.NONE); keyFileLabel.setText(Policy.bind("SSLPromptDialog.certificate")); //$NON-NLS-1$ - + Composite keyFileGroup = new Composite(rtnGroup, SWT.NONE); GridLayout keyFileLayout = new GridLayout(); keyFileLayout.numColumns = 2; @@ -81,17 +154,44 @@ keyFileGroup.setLayout(keyFileLayout); gd = new GridData(GridData.GRAB_HORIZONTAL | GridData.HORIZONTAL_ALIGN_FILL); keyFileGroup.setLayoutData(gd); - + keyFileCombo = new Combo(keyFileGroup, SWT.BORDER); gd = new GridData(); gd.widthHint = WIDTH; keyFileCombo.setLayoutData(gd); keyFileCombo.setEnabled(true); - if (keyFiles != null && keyFiles.length > 0) { - for (int i = 0; i < keyFiles.length; i++) keyFileCombo.add(keyFiles[i]); - keyFileCombo.setText(keyFiles[0]); + boolean msCapiPreselected = false; + if (mscapiSupport) { + if (keyFiles != null && keyFiles.length > 0) { + if (keyFiles[0] != null && keyFiles[0].startsWith("MSCAPI")) { + msCapiPreselected = true; + keyFileCombo.setEnabled(false); + aliasButton.setEnabled(true); + mscapiButton.setSelection(true); + if (keyFiles[0].split(";").length > 1) { + aliasText.setText(keyFiles[0].split(";")[1]); + } + } + boolean textset = false; + for (int i = 0; i < keyFiles.length; i++) { + if (keyFiles[i] != null && keyFiles[i].startsWith("MSCAPI")) { + continue; + } + if (!textset) { + keyFileCombo.setText(keyFiles[i]); + textset = true; + } + keyFileCombo.add(keyFiles[i]); + } + } + } else { + /* origin */ + if (keyFiles != null && keyFiles.length > 0) { + for (int i = 0; i < keyFiles.length; i++) keyFileCombo.add(keyFiles[i]); + keyFileCombo.setText(keyFiles[0]); + } } - + browseButton = new Button(keyFileGroup, SWT.PUSH); browseButton.setText(Policy.bind("SSHPromptDialog.browse")); //$NON-NLS-1$ browseButton.addSelectionListener(new SelectionAdapter() { @@ -104,8 +204,8 @@ if (returnFile != null) keyFileCombo.setText(returnFile); } }); - browseButton.setEnabled(true); - + browseButton.setEnabled(!msCapiPreselected); + Label passphraseLabel = new Label(rtnGroup, SWT.NONE); passphraseLabel.setText(Policy.bind("SSHPromptDialog.passphrase")); //$NON-NLS-1$ passphraseText = new Text(rtnGroup, SWT.BORDER); @@ -113,8 +213,8 @@ gd.widthHint = WIDTH; passphraseText.setEchoChar('*'); passphraseText.setLayoutData(gd); - passphraseText.setEnabled(true); - + passphraseText.setEnabled(!msCapiPreselected); + if (maySave) { saveButton = new Button(rtnGroup, SWT.CHECK); saveButton.setText(Policy.bind("SSHPromptDialog.save")); //$NON-NLS-1$ @@ -124,7 +224,7 @@ } return rtnGroup; } - + public Button createButton(Composite parent, int id, String label, boolean isDefault) { Button button = super.createButton(parent, id, label, isDefault); if (id == IDialogConstants.OK_ID) { @@ -135,21 +235,37 @@ } protected void okPressed() { - certificate = keyFileCombo.getText().trim(); passphrase = passphraseText.getText().trim(); - if (maySave) save = saveButton.getSelection(); + alias = aliasText.getText().trim(); + if (Platform.OS_WIN32 != null && !"".equals(Platform.OS_WIN32)) { + msCapi = mscapiButton.getSelection(); + } + if (msCapi) { + certificate = "MSCAPI"+(alias != null && !"".equals(alias)?";"+alias:""); + } else { + certificate = keyFileCombo.getText().trim(); + } if (certificate.length() > 0) SVNUIPlugin.getPlugin().getRepositoryManager().getKeyFilesManager().addKeyFile(certificate); + if (maySave) save = saveButton.getSelection(); super.okPressed(); } public boolean isSave() { return save; } - + public String getKeyFile() { return certificate; } - + public String getPassphrase() { return passphrase; } + + public boolean isMSCapi() { + return msCapi; + } + + public String getAlias() { + return alias; + } } Index: src/org/tigris/subversion/subclipse/ui/authentication/SVNPromptUserPassword.java =================================================================== --- src/org/tigris/subversion/subclipse/ui/authentication/SVNPromptUserPassword.java (revision 4649) +++ src/org/tigris/subversion/subclipse/ui/authentication/SVNPromptUserPassword.java (working copy) @@ -35,6 +35,7 @@ private int sshPort; private String keyFile; private String passPhrase; + private boolean useMSCapi; public SVNPromptUserPassword() { super(); @@ -54,9 +55,9 @@ MessageDialog.QUESTION, new String[] {IDialogConstants.YES_LABEL, IDialogConstants.NO_LABEL}, defaultButton); - yesNoAnswer = (dialog.open() == 0); + yesNoAnswer = (dialog.open() == 0); } - }); + }); return yesNoAnswer; } @@ -87,9 +88,9 @@ break; default: trust = TrustSSLServerDialog.REJECT; - } + } } - }); + }); return trust; } @@ -107,9 +108,9 @@ password = dialog.getPassword(); allowedSave = dialog.isSave(); rtnCode = true; - } + } } - }); + }); return rtnCode; } @@ -126,9 +127,9 @@ username = dialog.getUsername(); allowedSave = dialog.isSave(); rtnCode = true; - } + } } - }); + }); return rtnCode; } @@ -148,9 +149,9 @@ if (dialog.open() == QuestionDialog.OK) { allowedSave = dialog.isSave(); answer = dialog.getAnswer(); - } + } } - }); + }); return answer; } @@ -185,9 +186,9 @@ passPhrase = dialog.getPassphrase(); allowedSave = dialog.isSave(); rtnCode = true; - } + } } - }); + }); return rtnCode; } public String getSSLClientCertPassword() { @@ -196,6 +197,9 @@ public String getSSLClientCertPath() { return keyFile; } + public boolean useMSCapi() { + return useMSCapi; + } public boolean promptSSL(String promptRealm, boolean promptMaySave) { rtnCode = false; realm = promptRealm; @@ -206,12 +210,14 @@ realm, maySave); if (dialog.open() == PasswordPromptDialog.OK) { keyFile = dialog.getKeyFile(); - passPhrase = dialog.getPassphrase(); + useMSCapi = dialog.isMSCapi(); + passPhrase = dialog.getPassphrase(); allowedSave = dialog.isSave(); rtnCode = true; - } + + } } - }); + }); return rtnCode; } }