View | Details | Raw Unified | Return to bug 230242 | Differences between
and this patch

Collapse All | Expand All

(-)fragment.xml (+4 lines)
Lines 7-13 Link Here
7
         point="org.eclipse.equinox.security.secureStorage">
7
         point="org.eclipse.equinox.security.secureStorage">
8
      <provider
8
      <provider
9
            class="org.eclipse.equinox.internal.security.win32.WinCrypto"
9
            class="org.eclipse.equinox.internal.security.win32.WinCrypto"
10
            description="%providerDescription"
10
            priority="5">
11
            priority="5">
12
         <hint
13
               value="AutomaticPasswordGeneration">
14
         </hint>
11
      </provider>
15
      </provider>
12
   </extension>
16
   </extension>
13
17
(-)fragment.properties (+1 lines)
Lines 11-13 Link Here
11
fragmentName = Windows Data Protection services integration
11
fragmentName = Windows Data Protection services integration
12
providerName = Eclipse.org
12
providerName = Eclipse.org
13
windowsModuleName = Windows Integration
13
windowsModuleName = Windows Integration
14
providerDescription = The provider uses Windows APIs to encrypt a randomly generated \'master\' password in a way specific to the login credentials. Users who can log into the Windows account can access contents of the secure storage.
(-)fragment.properties (+1 lines)
Lines 11-13 Link Here
11
fragmentName = OS X Keystore service integration
11
fragmentName = OS X Keystore service integration
12
providerName = Eclipse.org
12
providerName = Eclipse.org
13
macModuleName = OS X Keystore Integration
13
macModuleName = OS X Keystore Integration
14
providerDescription = The provider uses the operating system\'s keyring to store a randomly generated user-specific \'master\' password. Users who can log into the operating system account can access contents of the secure storage.
(-)fragment.xml (+4 lines)
Lines 7-13 Link Here
7
         point="org.eclipse.equinox.security.secureStorage">
7
         point="org.eclipse.equinox.security.secureStorage">
8
      <provider
8
      <provider
9
            class="org.eclipse.equinox.internal.security.osx.OSXProvider"
9
            class="org.eclipse.equinox.internal.security.osx.OSXProvider"
10
            description="%providerDescription"
10
            priority="5">
11
            priority="5">
12
         <hint
13
               value="AutomaticPasswordGeneration">
14
         </hint>
11
      </provider>
15
      </provider>
12
   </extension>
16
   </extension>
13
</fragment>
17
</fragment>
(-)src/org/eclipse/equinox/internal/security/storage/friends/InternalExchangeUtils.java (-1 / +3 lines)
Lines 27-32 Link Here
27
 */
27
 */
28
public class InternalExchangeUtils {
28
public class InternalExchangeUtils {
29
29
30
	static public final String HINT_PASSWORD_AUTOGEN = "AutomaticPasswordGeneration"; //$NON-NLS-1$
31
30
	static private final String JUNIT_APPS1 = "org.eclipse.pde.junit.runtime."; //$NON-NLS-1$
32
	static private final String JUNIT_APPS1 = "org.eclipse.pde.junit.runtime."; //$NON-NLS-1$
31
	static private final String JUNIT_APPS2 = "org.eclipse.test."; //$NON-NLS-1$
33
	static private final String JUNIT_APPS2 = "org.eclipse.test."; //$NON-NLS-1$
32
34
Lines 52-58 Link Here
52
		List result = new ArrayList(availableModules.size());
54
		List result = new ArrayList(availableModules.size());
53
		for (Iterator i = availableModules.iterator(); i.hasNext();) {
55
		for (Iterator i = availableModules.iterator(); i.hasNext();) {
54
			ExtStorageModule module = (ExtStorageModule) i.next();
56
			ExtStorageModule module = (ExtStorageModule) i.next();
55
			result.add(new PasswordProviderDescription(module.name, module.moduleID, module.priority));
57
			result.add(new PasswordProviderDescription(module.name, module.moduleID, module.priority, module.description, module.hints));
56
		}
58
		}
57
		return result;
59
		return result;
58
	}
60
	}
(-)src/org/eclipse/equinox/internal/security/storage/friends/PasswordProviderDescription.java (-1 / +25 lines)
Lines 10-28 Link Here
10
 *******************************************************************************/
10
 *******************************************************************************/
11
package org.eclipse.equinox.internal.security.storage.friends;
11
package org.eclipse.equinox.internal.security.storage.friends;
12
12
13
import java.util.Iterator;
14
import java.util.List;
15
13
/**
16
/**
14
 * This class is used to pass description of a password provider module.
17
 * This class is used to pass description of a password provider module.
15
 */
18
 */
16
public class PasswordProviderDescription {
19
public class PasswordProviderDescription {
17
20
21
	static final private String EMPTY_STRING = ""; //$NON-NLS-1$
22
18
	private int priority;
23
	private int priority;
19
	private String id;
24
	private String id;
20
	private String name;
25
	private String name;
26
	private String description;
27
	private List hints;
21
28
22
	public PasswordProviderDescription(String name, String id, int priority) {
29
	public PasswordProviderDescription(String name, String id, int priority, String description, List hints) {
23
		this.id = id;
30
		this.id = id;
24
		this.name = name;
31
		this.name = name;
25
		this.priority = priority;
32
		this.priority = priority;
33
		this.description = description;
34
		this.hints = hints;
26
	}
35
	}
27
36
28
	public int getPriority() {
37
	public int getPriority() {
Lines 33-38 Link Here
33
		return id;
42
		return id;
34
	}
43
	}
35
44
45
	public String getDescription() {
46
		return (description == null) ? EMPTY_STRING : description;
47
	}
48
49
	public boolean hasHint(String hint) {
50
		if (hints == null)
51
			return false;
52
		for (Iterator i = hints.iterator(); i.hasNext();) {
53
			String candidate = (String) i.next();
54
			if (hint.equalsIgnoreCase(candidate))
55
				return true;
56
		}
57
		return false;
58
	}
59
36
	public String getName() {
60
	public String getName() {
37
		if (name == null || name.length() == 0)
61
		if (name == null || name.length() == 0)
38
			return id;
62
			return id;
(-)schema/secureStorage.exsd (-1 / +31 lines)
Lines 44-49 Link Here
44
44
45
   <element name="provider">
45
   <element name="provider">
46
      <complexType>
46
      <complexType>
47
         <sequence>
48
            <element ref="hint" minOccurs="0" maxOccurs="unbounded"/>
49
         </sequence>
47
         <attribute name="class" type="string" use="required">
50
         <attribute name="class" type="string" use="required">
48
            <annotation>
51
            <annotation>
49
               <documentation>
52
               <documentation>
Lines 61-66 Link Here
61
               </documentation>
64
               </documentation>
62
            </annotation>
65
            </annotation>
63
         </attribute>
66
         </attribute>
67
         <attribute name="description" type="string">
68
            <annotation>
69
               <documentation>
70
                  Optional text describing to the user functionality of this password provider.
71
               </documentation>
72
               <appinfo>
73
                  <meta.attribute translatable="true"/>
74
               </appinfo>
75
            </annotation>
76
         </attribute>
77
      </complexType>
78
   </element>
79
80
   <element name="hint">
81
      <complexType>
82
         <attribute name="value" use="required">
83
            <annotation>
84
               <documentation>
85
                  To help secure storage optimize workflows, providers that acquire master passwords without input from the user the should specify &lt;tt&gt;AutomaticPasswordGeneration&lt;/tt&gt; hint.
86
               </documentation>
87
            </annotation>
88
            <simpleType>
89
               <restriction base="string">
90
                  <enumeration value="AutomaticPasswordGeneration">
91
                  </enumeration>
92
               </restriction>
93
            </simpleType>
94
         </attribute>
64
      </complexType>
95
      </complexType>
65
   </element>
96
   </element>
66
97
Lines 100-106 Link Here
100
      <documentation>
131
      <documentation>
101
         &lt;p&gt;The &lt;code&gt;org.eclipse.equinox.security.ui&lt;/code&gt; bundle supplies default password provider that prompts user to enter the password.&lt;/p&gt;
132
         &lt;p&gt;The &lt;code&gt;org.eclipse.equinox.security.ui&lt;/code&gt; bundle supplies default password provider that prompts user to enter the password.&lt;/p&gt;
102
&lt;p&gt;The &lt;code&gt;org.eclipse.equinox.security.win32.x86&lt;/code&gt; fragment provides Windows OS integration.&lt;/p&gt;
133
&lt;p&gt;The &lt;code&gt;org.eclipse.equinox.security.win32.x86&lt;/code&gt; fragment provides Windows OS integration.&lt;/p&gt;
103
104
      </documentation>
134
      </documentation>
105
   </annotation>
135
   </annotation>
106
136
(-)src/org/eclipse/equinox/internal/security/storage/PasswordProviderSelector.java (-2 / +23 lines)
Lines 32-38 Link Here
32
	final private static String EXTENSION_POINT = "org.eclipse.equinox.security.secureStorage"; //$NON-NLS-1$
32
	final private static String EXTENSION_POINT = "org.eclipse.equinox.security.secureStorage"; //$NON-NLS-1$
33
	final private static String STORAGE_MODULE = "provider";//$NON-NLS-1$
33
	final private static String STORAGE_MODULE = "provider";//$NON-NLS-1$
34
	final private static String MODULE_PRIORITY = "priority";//$NON-NLS-1$
34
	final private static String MODULE_PRIORITY = "priority";//$NON-NLS-1$
35
	final private static String MODULE_DESCRIPTION = "description";//$NON-NLS-1$
35
	final private static String CLASS_NAME = "class";//$NON-NLS-1$
36
	final private static String CLASS_NAME = "class";//$NON-NLS-1$
37
	final private static String HINTS_NAME = "hint";//$NON-NLS-1$
38
	final private static String HINT_VALUE = "value";//$NON-NLS-1$
36
39
37
	private Map modules = new HashMap(5); // cache of modules found
40
	private Map modules = new HashMap(5); // cache of modules found
38
41
Lines 41-53 Link Here
41
		public IConfigurationElement element;
44
		public IConfigurationElement element;
42
		public int priority;
45
		public int priority;
43
		public String name;
46
		public String name;
47
		public String description;
48
		public List hints;
44
49
45
		public ExtStorageModule(String id, IConfigurationElement element, int priority, String name) {
50
		public ExtStorageModule(String id, IConfigurationElement element, int priority, String name, String description, List hints) {
46
			super();
51
			super();
47
			this.element = element;
52
			this.element = element;
48
			this.moduleID = id;
53
			this.moduleID = id;
49
			this.priority = priority;
54
			this.priority = priority;
50
			this.name = name;
55
			this.name = name;
56
			this.description = description;
57
			this.hints = hints;
51
		}
58
		}
52
	}
59
	}
53
60
Lines 107-113 Link Here
107
					priority = 10;
114
					priority = 10;
108
			}
115
			}
109
			String name = extensions[i].getLabel();
116
			String name = extensions[i].getLabel();
110
			allAvailableModules.add(new ExtStorageModule(moduleID, element, priority, name));
117
118
			String description = element.getAttribute(MODULE_DESCRIPTION);
119
120
			List suppliedHints = null;
121
			IConfigurationElement[] hints = element.getChildren(HINTS_NAME);
122
			if (hints.length != 0) {
123
				suppliedHints = new ArrayList(hints.length);
124
				for (int j = 0; j < hints.length; j++) {
125
					String hint = hints[j].getAttribute(HINT_VALUE);
126
					if (hint != null)
127
						suppliedHints.add(hint);
128
				}
129
			}
130
131
			allAvailableModules.add(new ExtStorageModule(moduleID, element, priority, name, description, suppliedHints));
111
		}
132
		}
112
133
113
		Collections.sort(allAvailableModules, new Comparator() {
134
		Collections.sort(allAvailableModules, new Comparator() {
(-)plugin.xml (+1 lines)
Lines 63-68 Link Here
63
         point="org.eclipse.equinox.security.secureStorage">
63
         point="org.eclipse.equinox.security.secureStorage">
64
      <provider
64
      <provider
65
            class="org.eclipse.equinox.internal.security.ui.storage.DefaultPasswordProvider"
65
            class="org.eclipse.equinox.internal.security.ui.storage.DefaultPasswordProvider"
66
            description="%providerDescription"
66
            priority="2">
67
            priority="2">
67
      </provider>
68
      </provider>
68
   </extension>
69
   </extension>
(-)plugin.properties (+1 lines)
Lines 19-21 Link Here
19
certificateFileDescription = Import certificates into the platform.
19
certificateFileDescription = Import certificates into the platform.
20
storage = Secure Storage
20
storage = Secure Storage
21
uiPasswordProviderName = UI Prompt
21
uiPasswordProviderName = UI Prompt
22
providerDescription = The provider brings up a secure storage login dialog for the user to input the \'master\' password. This provider does not persist \'master\' password in any way but relies on the user to input it.
(-)src/org/eclipse/equinox/internal/security/ui/nls/SecUIMessages.java (+2 lines)
Lines 70-75 Link Here
70
	public static String passwordCacheGroup;
70
	public static String passwordCacheGroup;
71
	public static String providerGroup;
71
	public static String providerGroup;
72
	public static String passwordCacheNote;
72
	public static String passwordCacheNote;
73
	public static String providerDetails;
73
74
74
	// secure storage view
75
	// secure storage view
75
	public static String generalTitle;
76
	public static String generalTitle;
Lines 145-150 Link Here
145
	public static String wizardSwitchError;
146
	public static String wizardSwitchError;
146
	public static String wizardDoneTitle;
147
	public static String wizardDoneTitle;
147
	public static String wizardDone;
148
	public static String wizardDone;
149
	public static String passwordChangeDone;
148
150
149
	// challenge-response dialog
151
	// challenge-response dialog
150
	public static String pswdRecoveryOptionTitle;
152
	public static String pswdRecoveryOptionTitle;
(-)src/org/eclipse/equinox/internal/security/ui/nls/messages.properties (+2 lines)
Lines 64-69 Link Here
64
exportButton = &Export...
64
exportButton = &Export...
65
locationButton = S&torage location:
65
locationButton = S&torage location:
66
providerDescription = Providers supply \'master\' passwords used to encrypt information. The enabled provider with the highest priority is chosen. A provider can be disabled by un-checking it from this list.
66
providerDescription = Providers supply \'master\' passwords used to encrypt information. The enabled provider with the highest priority is chosen. A provider can be disabled by un-checking it from this list.
67
providerDetails = Details:
67
68
68
## Secure storage view
69
## Secure storage view
69
generalTitle = Secure Storage
70
generalTitle = Secure Storage
Lines 139-144 Link Here
139
wizardSwitchError = An error occurred while creating new password. See error log for details. 
140
wizardSwitchError = An error occurred while creating new password. See error log for details. 
140
wizardDoneTitle = Complete
141
wizardDoneTitle = Complete
141
wizardDone = Password change complete.
142
wizardDone = Password change complete.
143
passwordChangeDone = The \'master\' password has been successfully changed for the provider \"{0}\".
142
144
143
## challenge-response dialog
145
## challenge-response dialog
144
pswdRecoveryOptionTitle = Secure Storage
146
pswdRecoveryOptionTitle = Secure Storage
(-)src/org/eclipse/equinox/internal/security/ui/storage/TabPassword.java (-6 / +74 lines)
Lines 18-26 Link Here
18
import org.eclipse.equinox.internal.security.ui.nls.SecUIMessages;
18
import org.eclipse.equinox.internal.security.ui.nls.SecUIMessages;
19
import org.eclipse.equinox.security.storage.ISecurePreferences;
19
import org.eclipse.equinox.security.storage.ISecurePreferences;
20
import org.eclipse.equinox.security.storage.SecurePreferencesFactory;
20
import org.eclipse.equinox.security.storage.SecurePreferencesFactory;
21
import org.eclipse.jface.dialogs.MessageDialog;
21
import org.eclipse.jface.layout.*;
22
import org.eclipse.jface.layout.*;
22
import org.eclipse.jface.viewers.ColumnWeightData;
23
import org.eclipse.jface.viewers.ColumnWeightData;
23
import org.eclipse.jface.viewers.TableLayout;
24
import org.eclipse.jface.viewers.TableLayout;
25
import org.eclipse.osgi.util.NLS;
24
import org.eclipse.swt.SWT;
26
import org.eclipse.swt.SWT;
25
import org.eclipse.swt.events.*;
27
import org.eclipse.swt.events.*;
26
import org.eclipse.swt.layout.GridData;
28
import org.eclipse.swt.layout.GridData;
Lines 40-45 Link Here
40
	protected Button buttonChangePassword;
42
	protected Button buttonChangePassword;
41
	protected Button buttonRecoverPassword;
43
	protected Button buttonRecoverPassword;
42
44
45
	protected Text detailsText;
46
43
	protected boolean providerModified = false;
47
	protected boolean providerModified = false;
44
48
45
	public TabPassword(TabFolder folder, int index, final Shell shell) {
49
	public TabPassword(TabFolder folder, int index, final Shell shell) {
Lines 107-112 Link Here
107
				if ((e.detail & SWT.CHECK) != 0)
111
				if ((e.detail & SWT.CHECK) != 0)
108
					providerModified = true;
112
					providerModified = true;
109
				enableButtons();
113
				enableButtons();
114
				updateDescription();
110
			}
115
			}
111
		});
116
		});
112
		GridDataFactory.defaultsFor(providerTable).span(1, 2).applyTo(providerTable);
117
		GridDataFactory.defaultsFor(providerTable).span(1, 2).applyTo(providerTable);
Lines 121-130 Link Here
121
			}
126
			}
122
127
123
			public void widgetSelected(SelectionEvent e) {
128
			public void widgetSelected(SelectionEvent e) {
129
				PasswordProviderDescription selectedModule = getSelectedModule();
130
				if (selectedModule == null)
131
					return;
124
				String moduleID = getSelectedModuleID();
132
				String moduleID = getSelectedModuleID();
125
				ISecurePreferences rootNode = SecurePreferencesFactory.getDefault();
133
				ISecurePreferences rootNode = SecurePreferencesFactory.getDefault();
126
				ChangePasswordWizardDialog dialog = new ChangePasswordWizardDialog(shell, rootNode, moduleID);
134
				if (selectedModule.hasHint(InternalExchangeUtils.HINT_PASSWORD_AUTOGEN)) {
127
				dialog.open();
135
					// do replacement behind the scene without showing the wizard
136
					changePassword(rootNode, moduleID, selectedModule.getName(), shell);
137
				} else {
138
					// show the wizard to provide separate "old" and "new" password entries
139
					ChangePasswordWizardDialog dialog = new ChangePasswordWizardDialog(shell, rootNode, moduleID);
140
					dialog.open();
141
				}
128
				enableLogout();
142
				enableLogout();
129
			}
143
			}
130
		});
144
		});
Lines 153-158 Link Here
153
		setButtonSize(buttonRecoverPassword);
167
		setButtonSize(buttonRecoverPassword);
154
168
155
		enableButtons();
169
		enableButtons();
170
171
		Label descriptionLabel = new Label(providersComp, SWT.NONE);
172
		descriptionLabel.setLayoutData(new GridData(SWT.FILL, SWT.CENTER, false, false, 2, 1));
173
		descriptionLabel.setText(SecUIMessages.providerDetails);
174
175
		detailsText = new Text(providersComp, SWT.MULTI | SWT.LEAD | SWT.BORDER | SWT.READ_ONLY | SWT.WRAP);
176
		detailsText.setBackground(detailsText.getDisplay().getSystemColor(SWT.COLOR_LIST_BACKGROUND));
177
		gridData = new GridData(SWT.FILL, SWT.FILL, false, false, 1, 1);
178
		gridData.widthHint = 300;
179
		gridData.heightHint = 65;
180
		detailsText.setLayoutData(gridData);
181
		updateDescription();
182
156
		GridLayoutFactory.fillDefaults().margins(LayoutConstants.getSpacing()).generateLayout(page);
183
		GridLayoutFactory.fillDefaults().margins(LayoutConstants.getSpacing()).generateLayout(page);
157
	}
184
	}
158
185
Lines 169-175 Link Here
169
			PasswordProviderDescription module = (PasswordProviderDescription) i.next();
196
			PasswordProviderDescription module = (PasswordProviderDescription) i.next();
170
			TableItem item = new TableItem(providerTable, SWT.NONE);
197
			TableItem item = new TableItem(providerTable, SWT.NONE);
171
			item.setText(new String[] {module.getName(), Integer.toString(module.getPriority())});
198
			item.setText(new String[] {module.getName(), Integer.toString(module.getPriority())});
172
			item.setData(module.getId());
199
			item.setData(module);
173
			if (disabledModules == null)
200
			if (disabledModules == null)
174
				item.setChecked(true);
201
				item.setChecked(true);
175
			else
202
			else
Lines 180-194 Link Here
180
		layout.addColumnData(new ColumnWeightData(5));
207
		layout.addColumnData(new ColumnWeightData(5));
181
		layout.addColumnData(new ColumnWeightData(1));
208
		layout.addColumnData(new ColumnWeightData(1));
182
		providerTable.setLayout(layout);
209
		providerTable.setLayout(layout);
210
211
		if (providerTable.getItemCount() > 0)
212
			providerTable.select(0);
183
	}
213
	}
184
214
185
	protected String getSelectedModuleID() {
215
	protected PasswordProviderDescription getSelectedModule() {
186
		if (providerTable == null)
216
		if (providerTable == null)
187
			return null;
217
			return null;
188
		TableItem[] items = providerTable.getSelection();
218
		TableItem[] items = providerTable.getSelection();
189
		if (items.length == 0)
219
		if (items.length == 0)
190
			return null;
220
			return null;
191
		return (String) items[0].getData();
221
		return ((PasswordProviderDescription) items[0].getData());
222
	}
223
224
	protected String getSelectedModuleID() {
225
		PasswordProviderDescription selectedModule = getSelectedModule();
226
		if (selectedModule == null)
227
			return null;
228
		return selectedModule.getId();
192
	}
229
	}
193
230
194
	protected void enableButtons() {
231
	protected void enableButtons() {
Lines 246-252 Link Here
246
				tmp.append(',');
283
				tmp.append(',');
247
			else
284
			else
248
				first = false;
285
				first = false;
249
			tmp.append((String) items[i].getData());
286
			tmp.append(((PasswordProviderDescription) items[i].getData()).getId());
250
		}
287
		}
251
288
252
		IEclipsePreferences node = new ConfigurationScope().getNode(PREFERENCES_PLUGIN);
289
		IEclipsePreferences node = new ConfigurationScope().getNode(PREFERENCES_PLUGIN);
Lines 276-279 Link Here
276
		GridDataFactory.defaultsFor(button).align(SWT.FILL, SWT.BEGINNING).grab(false, false).applyTo(button);
313
		GridDataFactory.defaultsFor(button).align(SWT.FILL, SWT.BEGINNING).grab(false, false).applyTo(button);
277
	}
314
	}
278
315
316
	protected boolean changePassword(ISecurePreferences node, String moduleID, String name, Shell shell) {
317
		ReEncrypter reEncrypter = new ReEncrypter(node, moduleID);
318
		if (!reEncrypter.decrypt()) {
319
			MessageBox messageBox = new MessageBox(shell, SWT.YES | SWT.NO | SWT.ICON_WARNING);
320
			messageBox.setText(SecUIMessages.changePasswordWizardTitle);
321
			messageBox.setMessage(SecUIMessages.wizardDecodeWarning);
322
			if (messageBox.open() == SWT.YES)
323
				return false;
324
		}
325
326
		if (!reEncrypter.switchToNewPassword()) {
327
			MessageBox messageBox = new MessageBox(shell, SWT.OK | SWT.ICON_ERROR);
328
			messageBox.setText(SecUIMessages.changePasswordWizardTitle);
329
			messageBox.setMessage(SecUIMessages.wizardSwitchError);
330
			messageBox.open();
331
			return false;
332
		}
333
		reEncrypter.encrypt();
334
335
		// all good
336
		String msg = NLS.bind(SecUIMessages.passwordChangeDone, name);
337
		MessageDialog.openInformation(StorageUtils.getShell(), SecUIMessages.generalDialogTitle, msg);
338
		return true;
339
	}
340
341
	protected void updateDescription() {
342
		PasswordProviderDescription selectedModule = getSelectedModule();
343
		if (selectedModule != null && detailsText != null)
344
			detailsText.setText(selectedModule.getDescription());
345
	}
346
279
}
347
}

Return to bug 230242