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

Collapse All | Expand All

(-)a/core.ui/src/org/netbeans/core/ui/options/general/GeneralOptionsModel.java (-3 / +1 lines)
 Lines 187-193    Link Here 
187
        return ProxySettings.getAuthenticationUsername ();
187
        return ProxySettings.getAuthenticationUsername ();
188
    }
188
    }
189
189
190
    //TODO: not used yet - store valu just in case if modified
191
    void setAuthenticationUsername (String username) {
190
    void setAuthenticationUsername (String username) {
192
        getProxyPreferences ().put (ProxySettings.PROXY_AUTHENTICATION_USERNAME, username);
191
        getProxyPreferences ().put (ProxySettings.PROXY_AUTHENTICATION_USERNAME, username);
193
    }
192
    }
 Lines 196-204    Link Here 
196
        return ProxySettings.getAuthenticationPassword ();
195
        return ProxySettings.getAuthenticationPassword ();
197
    }
196
    }
198
    
197
    
199
    //TODO: not used yet - store valu just in case if modified
200
    void setAuthenticationPassword(char [] password) {
198
    void setAuthenticationPassword(char [] password) {
201
        getProxyPreferences().put(ProxySettings.PROXY_AUTHENTICATION_PASSWORD, new String(password));
199
        ProxySettings.setAuthenticationPassword(password);
202
    }
200
    }
203
    
201
    
204
    // private helper methods ..................................................
202
    // private helper methods ..................................................
(-)a/hudson/nbproject/project.xml (+8 lines)
 Lines 51-56    Link Here 
51
                    </run-dependency>
51
                    </run-dependency>
52
                </dependency>
52
                </dependency>
53
                <dependency>
53
                <dependency>
54
                    <code-name-base>org.netbeans.modules.keyring</code-name-base>
55
                    <build-prerequisite/>
56
                    <compile-dependency/>
57
                    <run-dependency>
58
                        <specification-version>1.0</specification-version>
59
                    </run-dependency>
60
                </dependency>
61
                <dependency>
54
                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
62
                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
55
                    <build-prerequisite/>
63
                    <build-prerequisite/>
56
                    <compile-dependency/>
64
                    <compile-dependency/>
(-)a/hudson/src/org/netbeans/modules/hudson/ui/Bundle.properties (+3 lines)
 Lines 41-43    Link Here 
41
FormLogin.userLabel.text=&Username:
41
FormLogin.userLabel.text=&Username:
42
FormLogin.passLabel.text=&Password:
42
FormLogin.passLabel.text=&Password:
43
FormLogin.log_in=Log in to Hudson
43
FormLogin.log_in=Log in to Hudson
44
# {0} - server location
45
# {1} - user name
46
FormLogin.password_description=Password for {1} on {0}
(-)a/hudson/src/org/netbeans/modules/hudson/ui/FormLogin.java (+6 lines)
 Lines 42-47    Link Here 
42
import java.net.URL;
42
import java.net.URL;
43
import java.util.prefs.Preferences;
43
import java.util.prefs.Preferences;
44
import javax.swing.JPanel;
44
import javax.swing.JPanel;
45
import org.netbeans.api.keyring.Keyring;
45
import org.netbeans.modules.hudson.impl.HudsonManagerImpl;
46
import org.netbeans.modules.hudson.impl.HudsonManagerImpl;
46
import org.netbeans.modules.hudson.spi.PasswordAuthorizer;
47
import org.netbeans.modules.hudson.spi.PasswordAuthorizer;
47
import org.openide.DialogDescriptor;
48
import org.openide.DialogDescriptor;
 Lines 73-78    Link Here 
73
            String username = loginPrefs().get(server, null);
74
            String username = loginPrefs().get(server, null);
74
            if (username != null) {
75
            if (username != null) {
75
                panel.userField.setText(username);
76
                panel.userField.setText(username);
77
                char[] savedPassword = Keyring.read(server);
78
                if (savedPassword != null) {
79
                    panel.passField.setText(new String(savedPassword));
80
                }
76
            }
81
            }
77
            panel.locationField.setText(home.toString());
82
            panel.locationField.setText(home.toString());
78
            DialogDescriptor dd = new DialogDescriptor(panel, NbBundle.getMessage(FormLogin.class, "FormLogin.log_in"));
83
            DialogDescriptor dd = new DialogDescriptor(panel, NbBundle.getMessage(FormLogin.class, "FormLogin.log_in"));
 Lines 83-88    Link Here 
83
            loginPrefs().put(server, username);
88
            loginPrefs().put(server, username);
84
            String password = new String(panel.passField.getPassword());
89
            String password = new String(panel.passField.getPassword());
85
            panel.passField.setText("");
90
            panel.passField.setText("");
91
            Keyring.save(server, password.toCharArray(), NbBundle.getMessage(FormLogin.class, "FormLogin.password_description", home, username));
86
            return new String[] {username, password};
92
            return new String[] {username, password};
87
        }
93
        }
88
    }
94
    }
(-)a/kenai.ui/nbproject/project.xml (+8 lines)
 Lines 94-99    Link Here 
94
                    </run-dependency>
94
                    </run-dependency>
95
                </dependency>
95
                </dependency>
96
                <dependency>
96
                <dependency>
97
                    <code-name-base>org.netbeans.modules.keyring</code-name-base>
98
                    <build-prerequisite/>
99
                    <compile-dependency/>
100
                    <run-dependency>
101
                        <specification-version>1.0</specification-version>
102
                    </run-dependency>
103
                </dependency>
104
                <dependency>
97
                    <code-name-base>org.netbeans.modules.mercurial</code-name-base>
105
                    <code-name-base>org.netbeans.modules.mercurial</code-name-base>
98
                    <build-prerequisite/>
106
                    <build-prerequisite/>
99
                    <compile-dependency/>
107
                    <compile-dependency/>
(-)a/kenai.ui/src/org/netbeans/modules/kenai/ui/LoginPanel.form (-2 / +3 lines)
 Lines 34-40    Link Here 
34
          <Group type="102" alignment="0" attributes="0">
34
          <Group type="102" alignment="0" attributes="0">
35
              <Component id="lblKenaiLogoLeft" min="-2" max="-2" attributes="0"/>
35
              <Component id="lblKenaiLogoLeft" min="-2" max="-2" attributes="0"/>
36
              <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
36
              <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
37
              <Component id="lblKenaiLogoCenter" pref="196" max="32767" attributes="0"/>
37
              <Component id="lblKenaiLogoCenter" pref="202" max="32767" attributes="0"/>
38
              <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
38
              <EmptySpace min="-2" pref="0" max="-2" attributes="0"/>
39
              <Component id="lblKenaiLogoRight" min="-2" max="-2" attributes="0"/>
39
              <Component id="lblKenaiLogoRight" min="-2" max="-2" attributes="0"/>
40
          </Group>
40
          </Group>
 Lines 66-72    Link Here 
66
          </Group>
66
          </Group>
67
          <Group type="102" alignment="0" attributes="0">
67
          <Group type="102" alignment="0" attributes="0">
68
              <EmptySpace max="-2" attributes="0"/>
68
              <EmptySpace max="-2" attributes="0"/>
69
              <Component id="progressBar" pref="418" max="32767" attributes="0"/>
69
              <Component id="progressBar" pref="424" max="32767" attributes="0"/>
70
              <EmptySpace max="-2" attributes="0"/>
70
              <EmptySpace max="-2" attributes="0"/>
71
          </Group>
71
          </Group>
72
      </Group>
72
      </Group>
 Lines 164-169    Link Here 
164
    </Component>
164
    </Component>
165
    <Component class="javax.swing.JCheckBox" name="chkRememberMe">
165
    <Component class="javax.swing.JCheckBox" name="chkRememberMe">
166
      <Properties>
166
      <Properties>
167
        <Property name="selected" type="boolean" value="true"/>
167
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
168
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
168
          <ResourceString bundle="org/netbeans/modules/kenai/ui/Bundle.properties" key="LoginPanel.chkRememberMe.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
169
          <ResourceString bundle="org/netbeans/modules/kenai/ui/Bundle.properties" key="LoginPanel.chkRememberMe.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
169
        </Property>
170
        </Property>
(-)a/kenai.ui/src/org/netbeans/modules/kenai/ui/LoginPanel.java (-2 / +3 lines)
 Lines 200-205    Link Here 
200
        lblPassword.setLabelFor(password);
200
        lblPassword.setLabelFor(password);
201
        org.openide.awt.Mnemonics.setLocalizedText(lblPassword, org.openide.util.NbBundle.getMessage(LoginPanel.class, "LoginPanel.lblPassword.text")); // NOI18N
201
        org.openide.awt.Mnemonics.setLocalizedText(lblPassword, org.openide.util.NbBundle.getMessage(LoginPanel.class, "LoginPanel.lblPassword.text")); // NOI18N
202
202
203
        chkRememberMe.setSelected(true);
203
        org.openide.awt.Mnemonics.setLocalizedText(chkRememberMe, org.openide.util.NbBundle.getMessage(LoginPanel.class, "LoginPanel.chkRememberMe.text")); // NOI18N
204
        org.openide.awt.Mnemonics.setLocalizedText(chkRememberMe, org.openide.util.NbBundle.getMessage(LoginPanel.class, "LoginPanel.chkRememberMe.text")); // NOI18N
204
        chkRememberMe.setToolTipText(org.openide.util.NbBundle.getMessage(LoginPanel.class, "LoginPanel.chkRememberMe.toolTipText")); // NOI18N
205
        chkRememberMe.setToolTipText(org.openide.util.NbBundle.getMessage(LoginPanel.class, "LoginPanel.chkRememberMe.toolTipText")); // NOI18N
205
        chkRememberMe.addActionListener(new java.awt.event.ActionListener() {
206
        chkRememberMe.addActionListener(new java.awt.event.ActionListener() {
 Lines 237-243    Link Here 
237
            .add(layout.createSequentialGroup()
238
            .add(layout.createSequentialGroup()
238
                .add(lblKenaiLogoLeft)
239
                .add(lblKenaiLogoLeft)
239
                .add(0, 0, 0)
240
                .add(0, 0, 0)
240
                .add(lblKenaiLogoCenter, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 196, Short.MAX_VALUE)
241
                .add(lblKenaiLogoCenter, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 202, Short.MAX_VALUE)
241
                .add(0, 0, 0)
242
                .add(0, 0, 0)
242
                .add(lblKenaiLogoRight))
243
                .add(lblKenaiLogoRight))
243
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
244
            .add(org.jdesktop.layout.GroupLayout.TRAILING, layout.createSequentialGroup()
 Lines 262-268    Link Here 
262
                .addContainerGap())
263
                .addContainerGap())
263
            .add(layout.createSequentialGroup()
264
            .add(layout.createSequentialGroup()
264
                .addContainerGap()
265
                .addContainerGap()
265
                .add(progressBar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 418, Short.MAX_VALUE)
266
                .add(progressBar, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 424, Short.MAX_VALUE)
266
                .addContainerGap())
267
                .addContainerGap())
267
        );
268
        );
268
        layout.setVerticalGroup(
269
        layout.setVerticalGroup(
(-)a/kenai.ui/src/org/netbeans/modules/kenai/ui/spi/Bundle.properties (+39 lines)
Line 0    Link Here 
1
# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
2
#
3
# Copyright 2009 Sun Microsystems, Inc. All rights reserved.
4
#
5
# The contents of this file are subject to the terms of either the GNU
6
# General Public License Version 2 only ("GPL") or the Common
7
# Development and Distribution License("CDDL") (collectively, the
8
# "License"). You may not use this file except in compliance with the
9
# License. You can obtain a copy of the License at
10
# http://www.netbeans.org/cddl-gplv2.html
11
# or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
12
# specific language governing permissions and limitations under the
13
# License.  When distributing the software, include this License Header
14
# Notice in each file and include the License file at
15
# nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
16
# particular file as subject to the "Classpath" exception as provided
17
# by Sun in the GPL Version 2 section of the License file that
18
# accompanied this code. If applicable, add the following below the
19
# License Header, with the fields enclosed by brackets [] replaced by
20
# your own identifying information:
21
# "Portions Copyrighted [year] [name of copyright owner]"
22
#
23
# If you wish your version of this file to be governed by only the CDDL
24
# or only the GPL Version 2, indicate your decision by adding
25
# "[Contributor] elects to include this software in this distribution
26
# under the [CDDL or GPL Version 2] license." If you do not indicate a
27
# single choice of license, a recipient has the option to distribute
28
# your version of this file under either the CDDL, the GPL Version 2 or
29
# to extend the choice of license to its licensees as provided above.
30
# However, if you add GPL Version 2 code and therefore, elected the GPL
31
# Version 2 license, then the option applies only if the new code is
32
# made subject to such option by the copyright holder.
33
#
34
# Contributor(s):
35
#
36
# Portions Copyrighted 2009 Sun Microsystems, Inc.
37
38
# {0} - kenai.com or similar
39
UIUtils.password_keyring_description=Password for {0}
(-)a/kenai.ui/src/org/netbeans/modules/kenai/ui/spi/Scrambler.java (-69 / +1 lines)
 Lines 45-61    Link Here 
45
45
46
import java.io.ByteArrayOutputStream;
46
import java.io.ByteArrayOutputStream;
47
47
48
/**
48
@Deprecated
49
 * Scrambles text (the password) using the standard scheme described in the
50
 * CVS protocol version 1.10. This encoding is trivial and should not be
51
 * used for security, but rather as a mechanism for avoiding inadvertant
52
 * compromise.
53
 * @author  Robert Greig, Tomas Stupka
54
 */
55
class Scrambler {
49
class Scrambler {
56
50
57
    private static final char [] characters = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/".toCharArray(); // NOI18N
58
59
    /**
51
    /**
60
     * The mapping array
52
     * The mapping array
61
     */
53
     */
 Lines 313-333    Link Here 
313
        return instance;
305
        return instance;
314
    }
306
    }
315
307
316
    /**
317
     * Scramble text, turning it into a String of scrambled data
318
     * @return a String of scrambled data
319
     */
320
    public String scramble(String text) {
321
        StringBuffer buf = new StringBuffer("A"); //NOI18N
322
323
        if (text != null) {
324
            for (int i = 0; i < text.length(); ++i) {
325
                buf.append(scramble(text.charAt(i)));
326
            }
327
        }        
328
        return new String(encode(buf.toString().getBytes()));
329
    }
330
    
331
    public String descramble(String scrambledText) {        
308
    public String descramble(String scrambledText) {        
332
        StringBuffer buf = new StringBuffer(); 
309
        StringBuffer buf = new StringBuffer(); 
333
        if (scrambledText != null) {            
310
        if (scrambledText != null) {            
 Lines 348-398    Link Here 
348
    private byte[] decode(String str) {        
325
    private byte[] decode(String str) {        
349
        return decode64(str);
326
        return decode64(str);
350
    }
327
    }
351
    
352
    private byte[] encode(byte[] encode) {        
353
        return encode64(encode).getBytes();
354
    }
355
356
    private static String encode64(byte [] data) {
357
        return encode64(data, false);
358
    }
359
360
    private static String encode64(byte [] data, boolean useNewlines) {
361
        int length = data.length;
362
        StringBuffer sb = new StringBuffer(data.length * 3 / 2);
363
364
        int end = length - 3;
365
        int i = 0;
366
        int lineCount = 0;
367
368
        while (i <= end) {
369
            int d = ((((int) data[i]) & 0xFF) << 16) | ((((int) data[i + 1]) & 0xFF) << 8) | (((int) data[i + 2]) & 0xFF);
370
            sb.append(characters[(d >> 18) & 0x3F]);
371
            sb.append(characters[(d >> 12) & 0x3F]);
372
            sb.append(characters[(d >> 6) & 0x3F]);
373
            sb.append(characters[d & 0x3F]);
374
            i += 3;
375
376
            if (useNewlines && lineCount++ >= 14) {
377
                lineCount = 0;
378
                sb.append(System.getProperty("line.separator"));
379
            }
380
        }
381
382
        if (i == length - 2) {
383
            int d = ((((int) data[i]) & 0xFF) << 16) | ((((int) data[i + 1]) & 0xFF) << 8);
384
            sb.append(characters[(d >> 18) & 0x3F]);
385
            sb.append(characters[(d >> 12) & 0x3F]);
386
            sb.append(characters[(d >> 6) & 0x3F]);
387
            sb.append("="); // NOI18N
388
        } else if (i == length - 1) {
389
            int d = (((int) data[i]) & 0xFF) << 16;
390
            sb.append(characters[(d >> 18) & 0x3F]);
391
            sb.append(characters[(d >> 12) & 0x3F]);
392
            sb.append("=="); // NOI18N
393
        }
394
        return sb.toString();
395
    }
396
328
397
    private static byte [] decode64(String s) {
329
    private static byte [] decode64(String s) {
398
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
330
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
(-)a/kenai.ui/src/org/netbeans/modules/kenai/ui/spi/UIUtils.java (-7 / +35 lines)
 Lines 57-62    Link Here 
57
import javax.swing.JLabel;
57
import javax.swing.JLabel;
58
import javax.swing.JRootPane;
58
import javax.swing.JRootPane;
59
import javax.swing.SwingUtilities;
59
import javax.swing.SwingUtilities;
60
import org.netbeans.api.keyring.Keyring;
60
import org.netbeans.modules.kenai.api.Kenai;
61
import org.netbeans.modules.kenai.api.Kenai;
61
import org.netbeans.modules.kenai.api.KenaiException;
62
import org.netbeans.modules.kenai.api.KenaiException;
62
import org.netbeans.modules.kenai.api.KenaiUser;
63
import org.netbeans.modules.kenai.api.KenaiUser;
 Lines 125-135    Link Here 
125
        if (uname==null) {
126
        if (uname==null) {
126
            return false;
127
            return false;
127
        }
128
        }
128
        String password=preferences.get(getPrefName(KENAI_PASSWORD_PREF), null); // NOI18N
129
        PresenceIndicator.getDefault().init();
129
        PresenceIndicator.getDefault().init();
130
        try {
130
        try {
131
            KenaiConnection.getDefault();
131
            KenaiConnection.getDefault();
132
            Kenai.getDefault().login(uname, Scrambler.getInstance().descramble(password).toCharArray(), force?true:Boolean.parseBoolean(preferences.get(getPrefName(ONLINE_STATUS_PREF), String.valueOf(Utilities.isChatSupported()))));
132
            char[] password = loadPassword(preferences);
133
            if (password == null) {
134
                return false;
135
            }
136
            Kenai.getDefault().login(uname, password,
137
                    force ? true : Boolean.parseBoolean(preferences.get(getPrefName(ONLINE_STATUS_PREF), String.valueOf(Utilities.isChatSupported()))));
133
        } catch (KenaiException ex) {
138
        } catch (KenaiException ex) {
134
            return false;
139
            return false;
135
        }
140
        }
 Lines 137-142    Link Here 
137
    }
142
    }
138
143
139
    /**
144
    /**
145
     * Loads password from the keyring. For settings compatibility,
146
     * can also interpret and upgrade old insecure storage.
147
     */
148
    @SuppressWarnings("deprecation")
149
    private static char[] loadPassword(Preferences preferences) {
150
        String passwordPref = getPrefName(KENAI_PASSWORD_PREF);
151
        String scrambledPassword = preferences.get(passwordPref, null); // NOI18N
152
        char[] newPassword = Keyring.read(passwordPref);
153
        if (scrambledPassword != null) {
154
            preferences.remove(passwordPref);
155
            if (newPassword == null) {
156
                return Scrambler.getInstance().descramble(scrambledPassword).toCharArray();
157
            }
158
        }
159
        return newPassword;
160
    }
161
162
    /**
140
     * Invokes login dialog
163
     * Invokes login dialog
141
     * @return true, if user was succesfully logged in
164
     * @return true, if user was succesfully logged in
142
     */
165
     */
 Lines 186-198    Link Here 
186
                                }
209
                                }
187
                            }
210
                            }
188
                        });
211
                        });
212
                        String passwordPref = getPrefName(KENAI_PASSWORD_PREF);
189
                        if (loginPanel.isStorePassword()) {
213
                        if (loginPanel.isStorePassword()) {
190
                            preferences.put(getPrefName(KENAI_USERNAME_PREF), loginPanel.getUsername()); // NOI18N
214
                            preferences.put(getPrefName(KENAI_USERNAME_PREF), loginPanel.getUsername()); // NOI18N
191
                            preferences.put(getPrefName(KENAI_PASSWORD_PREF), Scrambler.getInstance().scramble(new String(loginPanel.getPassword()))); // NOI18N
215
                            Keyring.save(passwordPref, loginPanel.getPassword(),
216
                                    NbBundle.getMessage(UIUtils.class, "UIUtils.password_keyring_description", Kenai.getDefault().getUrl().getHost()));
192
                        } else {
217
                        } else {
193
                            preferences.remove(getPrefName(KENAI_USERNAME_PREF)); // NOI18N
218
                            preferences.remove(getPrefName(KENAI_USERNAME_PREF)); // NOI18N
194
                            preferences.remove(getPrefName(KENAI_PASSWORD_PREF)); // NOI18N
219
                            Keyring.delete(passwordPref);
195
                        }
220
                        }
221
                        preferences.remove(passwordPref);
196
                    } else {
222
                    } else {
197
                        loginPanel.putClientProperty("cancel", "true"); // NOI18N
223
                        loginPanel.putClientProperty("cancel", "true"); // NOI18N
198
                        JDialog parent = (JDialog) loginPanel.getRootPane().getParent();
224
                        JDialog parent = (JDialog) loginPanel.getRootPane().getParent();
 Lines 205-214    Link Here 
205
        Dialog d = DialogDisplayer.getDefault().createDialog(login);
231
        Dialog d = DialogDisplayer.getDefault().createDialog(login);
206
232
207
        String uname=preferences.get(getPrefName(KENAI_USERNAME_PREF), null); // NOI18N
233
        String uname=preferences.get(getPrefName(KENAI_USERNAME_PREF), null); // NOI18N
208
        String password=preferences.get(getPrefName(KENAI_PASSWORD_PREF), null); // NOI18N
234
        if (uname != null) {
209
        if (uname!=null && password!=null) {
210
            loginPanel.setUsername(uname);
235
            loginPanel.setUsername(uname);
211
            loginPanel.setPassword(Scrambler.getInstance().descramble(password).toCharArray());
236
            char[] password = loadPassword(preferences);
237
            if (password != null) {
238
                loginPanel.setPassword(password);
239
            }
212
        }
240
        }
213
        d.pack();
241
        d.pack();
214
        d.setResizable(false);
242
        d.setResizable(false);
(-)a/kenai.ui/test/unit/src/org/netbeans/modules/kenai/ui/spi/UIUtilsTest.java (-80 lines)
 Lines 1-80    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.kenai.ui.spi;
41
42
import java.util.prefs.Preferences;
43
import org.junit.AfterClass;
44
import org.junit.BeforeClass;
45
import org.junit.Test;
46
import org.openide.util.NbPreferences;
47
import static org.junit.Assert.*;
48
49
/**
50
 *
51
 * @author Jan Becicka
52
 */
53
public class UIUtilsTest {
54
55
    public UIUtilsTest() {
56
    }
57
58
    @BeforeClass
59
    public static void setUpClass() throws Exception {
60
    }
61
62
    @AfterClass
63
    public static void tearDownClass() throws Exception {
64
    }
65
66
    /**
67
     * Test of showLogin method, of class UIUtils.
68
     */
69
    @Test
70
    public void testEncodeDecode() {
71
        String testpass = "pswd";
72
        String scram = Scrambler.getInstance().scramble(testpass);
73
        Preferences preferences=NbPreferences.forModule(UIUtils.class);
74
        preferences.put("kenai.test.password", scram);
75
        String newp=preferences.get("kenai.test.password", null);
76
        String r = Scrambler.getInstance().descramble(newp);
77
        assertEquals(testpass, r);
78
        // TODO review the generated test code and remove the default call to fail.
79
    }
80
}
(-)a/keyring/build.xml (+14 lines)
Line 0    Link Here 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project basedir="." default="netbeans" name="keyring">
3
    <import file="../nbbuild/templates/projectized.xml"/>
4
    <target name="debug" depends="netbeans">
5
        <input addproperty="nonative" defaultvalue="false" validargs="true,false" message="Suppress native keyrings?"/>
6
        <ant dir="../nbbuild" target="tryme-debug">
7
            <property name="tryme.args" value="
8
                -J-Dnetbeans.full.hack=true
9
                -J-Dorg.netbeans.modules.keyring.level=FINER
10
                -J-Dnetbeans.keyring.no.native=${nonative}
11
            "/>
12
        </ant>
13
    </target>
14
</project>
(-)a/keyring/manifest.mf (+5 lines)
Line 0    Link Here 
1
Manifest-Version: 1.0
2
OpenIDE-Module: org.netbeans.modules.keyring
3
OpenIDE-Module-Localizing-Bundle: org/netbeans/modules/keyring/Bundle.properties
4
OpenIDE-Module-Specification-Version: 1.0
5
(-)a/keyring/nbproject/project.properties (+4 lines)
Line 0    Link Here 
1
is.autoload=true
2
javac.source=1.5
3
javac.compilerargs=-Xlint -Xlint:-serial
4
tryme.args=-J-Dnetbeans.full.hack=true -J-Dorg.netbeans.modules.keyring.level=0
(-)a/keyring/nbproject/project.xml (+71 lines)
Line 0    Link Here 
1
<?xml version="1.0" encoding="UTF-8"?>
2
<project xmlns="http://www.netbeans.org/ns/project/1">
3
    <type>org.netbeans.modules.apisupport.project</type>
4
    <configuration>
5
        <data xmlns="http://www.netbeans.org/ns/nb-module-project/3">
6
            <code-name-base>org.netbeans.modules.keyring</code-name-base>
7
            <module-dependencies>
8
                <dependency>
9
                    <code-name-base>org.jdesktop.layout</code-name-base>
10
                    <build-prerequisite/>
11
                    <compile-dependency/>
12
                    <run-dependency>
13
                        <release-version>1</release-version>
14
                        <specification-version>1.9</specification-version>
15
                    </run-dependency>
16
                </dependency>
17
                <dependency>
18
                    <code-name-base>org.netbeans.libs.jna</code-name-base>
19
                    <build-prerequisite/>
20
                    <compile-dependency/>
21
                    <run-dependency>
22
                        <release-version>1</release-version>
23
                        <specification-version>1.4</specification-version>
24
                    </run-dependency>
25
                </dependency>
26
                <dependency>
27
                    <code-name-base>org.openide.awt</code-name-base>
28
                    <build-prerequisite/>
29
                    <compile-dependency/>
30
                    <run-dependency>
31
                        <specification-version>7.16</specification-version>
32
                    </run-dependency>
33
                </dependency>
34
                <dependency>
35
                    <code-name-base>org.openide.dialogs</code-name-base>
36
                    <build-prerequisite/>
37
                    <compile-dependency/>
38
                    <run-dependency>
39
                        <specification-version>7.13</specification-version>
40
                    </run-dependency>
41
                </dependency>
42
                <dependency>
43
                    <code-name-base>org.openide.util</code-name-base>
44
                    <build-prerequisite/>
45
                    <compile-dependency/>
46
                    <run-dependency>
47
                        <specification-version>7.29</specification-version>
48
                    </run-dependency>
49
                </dependency>
50
            </module-dependencies>
51
            <test-dependencies>
52
                <test-type>
53
                    <name>unit</name>
54
                    <test-dependency>
55
                        <code-name-base>org.netbeans.libs.junit4</code-name-base>
56
                        <compile-dependency/>
57
                    </test-dependency>
58
                    <test-dependency>
59
                        <code-name-base>org.netbeans.modules.nbjunit</code-name-base>
60
                        <recursive/>
61
                        <compile-dependency/>
62
                    </test-dependency>
63
                </test-type>
64
            </test-dependencies>
65
            <public-packages>
66
                <package>org.netbeans.api.keyring</package>
67
                <package>org.netbeans.spi.keyring</package>
68
            </public-packages>
69
        </data>
70
    </configuration>
71
</project>
(-)a/keyring/src/org/netbeans/api/keyring/Keyring.java (+125 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.api.keyring;
41
42
import java.util.Arrays;
43
import java.util.logging.Level;
44
import java.util.logging.Logger;
45
import org.netbeans.spi.keyring.KeyringProvider;
46
import org.openide.util.Lookup;
47
import org.openide.util.Parameters;
48
49
/**
50
 * Client class for working with stored keys (such as passwords).
51
 * <p>The key identifier should be unique for the whole application,
52
 * so qualify it with any prefixes as needed.
53
 * <p>Avoid calling methods on this class from the event dispatch thread,
54
 * as some provider implementations may need to block while displaying a dialog
55
 * (e.g. prompting for a master password to access the keyring).
56
 */
57
public class Keyring {
58
59
    private Keyring() {}
60
61
    private static KeyringProvider PROVIDER;
62
    private static KeyringProvider provider() {
63
        if (PROVIDER == null) {
64
            for (KeyringProvider p : Lookup.getDefault().lookupAll(KeyringProvider.class)) {
65
                if (p.enabled()) {
66
                    PROVIDER = p;
67
                    break;
68
                }
69
            }
70
            if (PROVIDER == null) {
71
                PROVIDER = new DummyKeyringProvider();
72
            }
73
            Logger.getLogger("org.netbeans.modules.keyring").log(Level.FINE, "Using provider: {0}", PROVIDER);
74
        }
75
        return PROVIDER;
76
    }
77
78
    /**
79
     * Reads a key from the ring.
80
     * @param key the identifier of the key
81
     * @return its value if found (you may null out its elements), else null if not present
82
     */
83
    public static synchronized char[] read(String key) {
84
        Parameters.notNull("key", key);
85
        return provider().read(key);
86
    }
87
88
    /**
89
     * Saves a key to the ring.
90
     * If it could not be saved, does nothing.
91
     * If the key already existed, overwrites the password.
92
     * @param key a key identifier
93
     * @param password the password or other sensitive information associated with the key
94
     *                 (its contents will be nulled out by end of call)
95
     * @param description a user-visible description of the key (may be null)
96
     */
97
    public static synchronized void save(String key, char[] password, String description) {
98
        Parameters.notNull("key", key);
99
        Parameters.notNull("password", password);
100
        provider().save(key, password, description);
101
        Arrays.fill(password, (char) 0);
102
    }
103
104
    /**
105
     * Deletes a key from the ring.
106
     * If the key was not in the ring to begin with, does nothing.
107
     * @param key a key identifier
108
     */
109
    public static synchronized void delete(String key) {
110
        Parameters.notNull("key", key);
111
        provider().delete(key);
112
    }
113
114
    private static class DummyKeyringProvider implements KeyringProvider {
115
        public boolean enabled() {
116
            return true;
117
        }
118
        public char[] read(String key) {
119
            return null;
120
        }
121
        public void save(String key, char[] password, String description) {}
122
        public void delete(String key) {}
123
    }
124
125
}
(-)a/keyring/src/org/netbeans/modules/keyring/Bundle.properties (+1 lines)
Line 0    Link Here 
1
OpenIDE-Module-Name=Keyring API
(-)a/keyring/src/org/netbeans/modules/keyring/Utils.java (+69 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring;
41
42
import java.util.prefs.Preferences;
43
44
public class Utils {
45
46
    private Utils() {}
47
48
    public static byte[] chars2Bytes(char[] chars) {
49
        byte[] bytes = new byte[chars.length * 2];
50
        for (int i = 0; i < chars.length; i++) {
51
            bytes[i * 2] = (byte) (chars[i] / 256);
52
            bytes[i * 2 + 1] = (byte) (chars[i] % 256);
53
        }
54
        return bytes;
55
    }
56
57
    public static char[] bytes2Chars(byte[] bytes) {
58
        char[] result = new char[bytes.length / 2];
59
        for (int i = 0; i < result.length; i++) {
60
            result[i] = (char) (((int) bytes[i * 2]) * 256 + (int) bytes[i * 2 + 1]);
61
        }
62
        return result;
63
    }
64
65
    public static void goMinusR(Preferences p) {
66
        // XXX try to set $userdir/config/${p.absolutePath()}.properties to -rw-------
67
    }
68
69
}
(-)a/keyring/src/org/netbeans/modules/keyring/fallback/Bundle.properties (+4 lines)
Line 0    Link Here 
1
MasterPasswordPanel.masterPasswordLabel.text=Master &Password:
2
MasterPasswordPanel.setNewBox.text=&Change...
3
MasterPasswordPanel.newLabel1.text=&New Master Password:
4
MasterPasswordPanel.newLabel2.text=&Retype:
(-)a/keyring/src/org/netbeans/modules/keyring/fallback/FallbackProvider.java (+173 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.fallback;
41
42
import java.util.HashMap;
43
import java.util.Map;
44
import java.util.UUID;
45
import java.util.concurrent.Callable;
46
import java.util.logging.Level;
47
import java.util.logging.Logger;
48
import java.util.prefs.Preferences;
49
import org.netbeans.modules.keyring.Utils;
50
import org.netbeans.modules.keyring.spi.EncryptionProvider;
51
import org.netbeans.spi.keyring.KeyringProvider;
52
import org.openide.util.Lookup;
53
import org.openide.util.NbPreferences;
54
import org.openide.util.lookup.ServiceProvider;
55
56
/**
57
 * Platform-independent keyring provider using a master password and the user directory.
58
 */
59
@ServiceProvider(service=KeyringProvider.class, position=1000)
60
public class FallbackProvider implements KeyringProvider, Callable<Void> {
61
62
    private static final Logger LOG = Logger.getLogger(FallbackProvider.class.getName());
63
    private static final String DESCRIPTION = ".description";
64
    private static final String SAMPLE_KEY = "__sample__";
65
66
    private EncryptionProvider encryption;
67
 
68
    public boolean enabled() {
69
        for (EncryptionProvider p : Lookup.getDefault().lookupAll(EncryptionProvider.class)) {
70
            if (p.enabled()) {
71
                encryption = p;
72
                LOG.log(Level.FINE, "Using provider: {0}", p);
73
                Preferences prefs = prefs();
74
                Utils.goMinusR(prefs);
75
                p.encryptionChangingCallback(this);
76
                if (!testSampleKey(prefs)) {
77
                    continue;
78
                }
79
                return true;
80
            }
81
        }
82
        LOG.fine("No provider");
83
        return false;
84
    }
85
    
86
    private boolean testSampleKey(Preferences prefs) {
87
        byte[] ciphertext = prefs().getByteArray(SAMPLE_KEY, null);
88
        if (ciphertext == null) {
89
            save(SAMPLE_KEY, (SAMPLE_KEY + UUID.randomUUID()).toCharArray(), "Sample value ensuring that decryption is working."); // XXX I18N
90
            LOG.fine("saved sample key");
91
            return true;
92
        } else {
93
            while (true) {
94
                try {
95
                    if (new String(encryption.decrypt(ciphertext)).startsWith(SAMPLE_KEY)) {
96
                        LOG.fine("succeeded in decrypting sample key");
97
                        return true;
98
                    } else {
99
                        LOG.fine("wrong result decrypting sample key");
100
                    }
101
                } catch (Exception x) {
102
                    LOG.log(Level.FINE, "failed to decrypt sample key", x);
103
                }
104
                if (!encryption.decryptionFailed()) {
105
                    LOG.fine("sample key decryption failed and are not retrying");
106
                    return false;
107
                }
108
                LOG.fine("will retry decryption of sample key");
109
            }
110
        }
111
    }
112
113
    private Preferences prefs() {
114
        return NbPreferences.forModule(FallbackProvider.class).node(encryption.id());
115
    }
116
117
    public char[] read(String key) {
118
        byte[] ciphertext = prefs().getByteArray(key, null);
119
        if (ciphertext == null) {
120
            return null;
121
        }
122
        try {
123
            return encryption.decrypt(ciphertext);
124
        } catch (Exception x) {
125
            LOG.log(Level.FINE, "failed to decrypt password for " + key, x);
126
        }
127
        return null;
128
    }
129
130
    public void save(String key, char[] password, String description) {
131
        Preferences prefs = prefs();
132
        try {
133
            prefs.putByteArray(key, encryption.encrypt(password));
134
        } catch (Exception x) {
135
            LOG.log(Level.FINE, "failed to encrypt password for " + key, x);
136
            return;
137
        }
138
        if (description != null) {
139
            // Preferences interface gives no access to *.properties comments, so:
140
            prefs.put(key + DESCRIPTION, description);
141
        }
142
    }
143
144
    public void delete(String key) {
145
        Preferences prefs = prefs();
146
        prefs.remove(key);
147
        prefs.remove(key + DESCRIPTION);
148
    }
149
150
    public Void call() throws Exception { // encryption changing
151
        LOG.fine("encryption changing");
152
        Map<String,char[]> saved = new HashMap<String,char[]>();
153
        Preferences prefs = prefs();
154
        for (String k : prefs.keys()) {
155
            if (k.endsWith(DESCRIPTION)) {
156
                continue;
157
            }
158
            byte[] ciphertext = prefs.getByteArray(k, null);
159
            if (ciphertext == null) {
160
                continue;
161
            }
162
            saved.put(k, encryption.decrypt(ciphertext));
163
        }
164
        LOG.log(Level.FINE, "reencrypting keys: {0}", saved.keySet());
165
        encryption.encryptionChanged();
166
        for (Map.Entry<String,char[]> entry : saved.entrySet()) {
167
            prefs.putByteArray(entry.getKey(), encryption.encrypt(entry.getValue()));
168
        }
169
        LOG.fine("encryption changing finished");
170
        return null;
171
    }
172
173
}
(-)a/keyring/src/org/netbeans/modules/keyring/fallback/MasterPasswordEncryption.java (+217 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.fallback;
41
42
import java.security.Key;
43
import java.security.spec.AlgorithmParameterSpec;
44
import java.security.spec.KeySpec;
45
import java.util.Arrays;
46
import java.util.UUID;
47
import java.util.concurrent.Callable;
48
import java.util.concurrent.atomic.AtomicBoolean;
49
import java.util.logging.Level;
50
import java.util.logging.Logger;
51
import java.util.prefs.Preferences;
52
import javax.crypto.Cipher;
53
import javax.crypto.SecretKeyFactory;
54
import javax.crypto.spec.PBEKeySpec;
55
import javax.crypto.spec.PBEParameterSpec;
56
import org.netbeans.modules.keyring.Utils;
57
import org.netbeans.modules.keyring.spi.EncryptionProvider;
58
import org.openide.util.NbPreferences;
59
import org.openide.util.lookup.ServiceProvider;
60
61
/**
62
 * Encrypts data using a master password which the user must enter for each NetBeans session.
63
 */
64
@ServiceProvider(service=EncryptionProvider.class, position=1000)
65
public class MasterPasswordEncryption implements EncryptionProvider {
66
67
    private static final Logger LOG = Logger.getLogger(MasterPasswordEncryption.class.getName());
68
    private static final String ENCRYPTION_ALGORITHM = "PBEWithSHA1AndDESede"; // NOI18N
69
    private static SecretKeyFactory KEY_FACTORY;
70
    private static AlgorithmParameterSpec PARAM_SPEC;
71
72
    private Cipher encrypt, decrypt;
73
    private boolean unlocked;
74
    private Callable<Void> encryptionChanging;
75
    private char[] newMasterPassword;
76
77
    public boolean enabled() {
78
        try {
79
            KEY_FACTORY = SecretKeyFactory.getInstance(ENCRYPTION_ALGORITHM);
80
            encrypt = Cipher.getInstance(ENCRYPTION_ALGORITHM);
81
            decrypt = Cipher.getInstance(ENCRYPTION_ALGORITHM);
82
            Preferences prefs = NbPreferences.forModule(MasterPasswordEncryption.class);
83
            Utils.goMinusR(prefs);
84
            String saltKey = "salt"; // NOI18N
85
            byte[] salt = prefs.getByteArray(saltKey, null);
86
            if (salt == null) {
87
                salt = UUID.randomUUID().toString().getBytes();
88
                prefs.putByteArray(saltKey, salt);
89
            }
90
            PARAM_SPEC = new PBEParameterSpec(salt, 20);
91
            return true;
92
        } catch (Exception x) {
93
            LOG.log(Level.INFO, "Cannot initialize security using " + ENCRYPTION_ALGORITHM, x);
94
            return false;
95
        }
96
    }
97
98
    public String id() {
99
        return "general"; // NOI18N
100
    }
101
102
    public byte[] encrypt(char[] cleartext) throws Exception {
103
        if (!unlockIfNecessary()) {
104
            throw new Exception("cannot unlock");
105
        }
106
        try {
107
            return doEncrypt(cleartext);
108
        } catch (Exception x) {
109
            unlocked = false; // reset
110
            throw x;
111
        }
112
    }
113
114
    public char[] decrypt(byte[] ciphertext) throws Exception {
115
        AtomicBoolean callEncryptionChanging = new AtomicBoolean();
116
        if (!unlockIfNecessary(callEncryptionChanging)) {
117
            throw new Exception("cannot unlock");
118
        }
119
        try {
120
            return doDecrypt(ciphertext);
121
        } catch (Exception x) {
122
            unlocked = false; // reset
123
            throw x;
124
        } finally {
125
            if (callEncryptionChanging.get()) {
126
                try {
127
                    encryptionChanging.call();
128
                } catch (Exception x) {
129
                    LOG.log(Level.FINE, "failed to change encryption", x);
130
                }
131
            }
132
        }
133
    }
134
135
    private boolean unlockIfNecessary() {
136
        AtomicBoolean callEncryptionChanging = new AtomicBoolean();
137
        boolean result = unlockIfNecessary(callEncryptionChanging);
138
        if (callEncryptionChanging.get()) {
139
            try {
140
                encryptionChanging.call();
141
            } catch (Exception x) {
142
                LOG.log(Level.FINE, "failed to change encryption", x);
143
            }
144
        }
145
        return result;
146
    }
147
    private boolean unlockIfNecessary(AtomicBoolean callEncryptionChanging) {
148
        if (unlocked) {
149
            return true;
150
        }
151
        char[][] passwords = new MasterPasswordPanel().display();
152
        if (passwords == null) {
153
            LOG.fine("cancelled master password dialog");
154
            return false;
155
        }
156
        try {
157
            unlock(passwords[0]);
158
            Arrays.fill(passwords[0], '\0');
159
            if (passwords.length == 2) {
160
                newMasterPassword = passwords[1];
161
                LOG.fine("will set new master password");
162
                callEncryptionChanging.set(true);
163
            }
164
            return true;
165
        } catch (Exception x) {
166
            LOG.log(Level.FINE, "failed to initialize ciphers", x);
167
            return false;
168
        }
169
    }
170
171
    void unlock(char[] masterPassword) throws Exception {
172
        LOG.fine("switching to new master password");
173
        KeySpec keySpec = new PBEKeySpec(masterPassword);
174
        Key key = KEY_FACTORY.generateSecret(keySpec);
175
        encrypt.init(Cipher.ENCRYPT_MODE, key, PARAM_SPEC);
176
        decrypt.init(Cipher.DECRYPT_MODE, key, PARAM_SPEC);
177
        unlocked = true;
178
    }
179
180
    byte[] doEncrypt(char[] cleartext) throws Exception {
181
        assert unlocked;
182
        byte[] cleartextB = Utils.chars2Bytes(cleartext);
183
        byte[] result = encrypt.doFinal(cleartextB);
184
        Arrays.fill(cleartextB, (byte) 0);
185
        return result;
186
    }
187
188
    char[] doDecrypt(byte[] ciphertext) throws Exception {
189
        assert unlocked;
190
        byte[] result = decrypt.doFinal(ciphertext);
191
        char[] cleartext = Utils.bytes2Chars(result);
192
        Arrays.fill(result, (byte) 0);
193
        return cleartext;
194
    }
195
196
    public boolean decryptionFailed() {
197
        unlocked = false;
198
        return unlockIfNecessary();
199
    }
200
201
    public void encryptionChangingCallback(Callable<Void> callback) {
202
        encryptionChanging = callback;
203
    }
204
205
    public void encryptionChanged() {
206
        assert newMasterPassword != null;
207
        LOG.fine("encryption changed");
208
        try {
209
            unlock(newMasterPassword);
210
        } catch (Exception x) {
211
            LOG.log(Level.FINE, "failed to initialize ciphers", x);
212
        }
213
        Arrays.fill(newMasterPassword, '\0');
214
        newMasterPassword = null;
215
    }
216
217
}
(-)a/keyring/src/org/netbeans/modules/keyring/fallback/MasterPasswordPanel.form (+119 lines)
Line 0    Link Here 
1
<?xml version="1.0" encoding="UTF-8" ?>
2
3
<Form version="1.5" maxVersion="1.7" type="org.netbeans.modules.form.forminfo.JPanelFormInfo">
4
  <AuxValues>
5
    <AuxValue name="FormSettings_autoResourcing" type="java.lang.Integer" value="1"/>
6
    <AuxValue name="FormSettings_autoSetComponentName" type="java.lang.Boolean" value="false"/>
7
    <AuxValue name="FormSettings_generateFQN" type="java.lang.Boolean" value="true"/>
8
    <AuxValue name="FormSettings_generateMnemonicsCode" type="java.lang.Boolean" value="true"/>
9
    <AuxValue name="FormSettings_i18nAutoMode" type="java.lang.Boolean" value="true"/>
10
    <AuxValue name="FormSettings_layoutCodeTarget" type="java.lang.Integer" value="2"/>
11
    <AuxValue name="FormSettings_listenerGenerationStyle" type="java.lang.Integer" value="0"/>
12
    <AuxValue name="FormSettings_variablesLocal" type="java.lang.Boolean" value="false"/>
13
    <AuxValue name="FormSettings_variablesModifier" type="java.lang.Integer" value="2"/>
14
  </AuxValues>
15
16
  <Layout>
17
    <DimensionLayout dim="0">
18
      <Group type="103" groupAlignment="0" attributes="0">
19
          <Group type="102" attributes="0">
20
              <EmptySpace max="-2" attributes="0"/>
21
              <Group type="103" groupAlignment="0" attributes="0">
22
                  <Group type="102" attributes="0">
23
                      <Group type="103" groupAlignment="0" attributes="0">
24
                          <Component id="newLabel1" alignment="0" min="-2" max="-2" attributes="0"/>
25
                          <Component id="newLabel2" alignment="0" min="-2" max="-2" attributes="0"/>
26
                          <Component id="masterPasswordLabel" alignment="0" min="-2" max="-2" attributes="0"/>
27
                      </Group>
28
                      <EmptySpace max="-2" attributes="0"/>
29
                      <Group type="103" groupAlignment="0" attributes="0">
30
                          <Component id="masterPasswordField" alignment="0" pref="224" max="32767" attributes="0"/>
31
                          <Component id="newField2" pref="224" max="32767" attributes="0"/>
32
                          <Component id="newField1" alignment="0" pref="224" max="32767" attributes="0"/>
33
                      </Group>
34
                  </Group>
35
                  <Component id="setNewBox" alignment="0" min="-2" max="-2" attributes="0"/>
36
              </Group>
37
              <EmptySpace max="-2" attributes="0"/>
38
          </Group>
39
      </Group>
40
    </DimensionLayout>
41
    <DimensionLayout dim="1">
42
      <Group type="103" groupAlignment="0" attributes="0">
43
          <Group type="102" alignment="0" attributes="0">
44
              <EmptySpace max="-2" attributes="0"/>
45
              <Group type="103" groupAlignment="3" attributes="0">
46
                  <Component id="masterPasswordLabel" alignment="3" min="-2" max="-2" attributes="0"/>
47
                  <Component id="masterPasswordField" alignment="3" min="-2" max="-2" attributes="0"/>
48
              </Group>
49
              <EmptySpace type="separate" max="-2" attributes="0"/>
50
              <Component id="setNewBox" min="-2" max="-2" attributes="0"/>
51
              <EmptySpace max="-2" attributes="0"/>
52
              <Group type="103" groupAlignment="3" attributes="0">
53
                  <Component id="newLabel1" alignment="3" min="-2" max="-2" attributes="0"/>
54
                  <Component id="newField1" alignment="3" min="-2" max="-2" attributes="0"/>
55
              </Group>
56
              <EmptySpace max="-2" attributes="0"/>
57
              <Group type="103" groupAlignment="3" attributes="0">
58
                  <Component id="newLabel2" alignment="3" min="-2" max="-2" attributes="0"/>
59
                  <Component id="newField2" alignment="3" min="-2" max="-2" attributes="0"/>
60
              </Group>
61
              <EmptySpace max="32767" attributes="0"/>
62
          </Group>
63
      </Group>
64
    </DimensionLayout>
65
  </Layout>
66
  <SubComponents>
67
    <Component class="javax.swing.JLabel" name="masterPasswordLabel">
68
      <Properties>
69
        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
70
          <ComponentRef name="masterPasswordField"/>
71
        </Property>
72
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
73
          <ResourceString bundle="org/netbeans/modules/keyring/fallback/Bundle.properties" key="MasterPasswordPanel.masterPasswordLabel.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
74
        </Property>
75
      </Properties>
76
    </Component>
77
    <Component class="javax.swing.JPasswordField" name="masterPasswordField">
78
    </Component>
79
    <Component class="javax.swing.JCheckBox" name="setNewBox">
80
      <Properties>
81
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
82
          <ResourceString bundle="org/netbeans/modules/keyring/fallback/Bundle.properties" key="MasterPasswordPanel.setNewBox.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
83
        </Property>
84
      </Properties>
85
    </Component>
86
    <Component class="javax.swing.JLabel" name="newLabel1">
87
      <Properties>
88
        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
89
          <ComponentRef name="newField1"/>
90
        </Property>
91
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
92
          <ResourceString bundle="org/netbeans/modules/keyring/fallback/Bundle.properties" key="MasterPasswordPanel.newLabel1.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
93
        </Property>
94
        <Property name="enabled" type="boolean" value="false"/>
95
      </Properties>
96
    </Component>
97
    <Component class="javax.swing.JPasswordField" name="newField1">
98
      <Properties>
99
        <Property name="enabled" type="boolean" value="false"/>
100
      </Properties>
101
    </Component>
102
    <Component class="javax.swing.JLabel" name="newLabel2">
103
      <Properties>
104
        <Property name="labelFor" type="java.awt.Component" editor="org.netbeans.modules.form.ComponentChooserEditor">
105
          <ComponentRef name="newField2"/>
106
        </Property>
107
        <Property name="text" type="java.lang.String" editor="org.netbeans.modules.i18n.form.FormI18nStringEditor">
108
          <ResourceString bundle="org/netbeans/modules/keyring/fallback/Bundle.properties" key="MasterPasswordPanel.newLabel2.text" replaceFormat="org.openide.util.NbBundle.getMessage({sourceFileName}.class, &quot;{key}&quot;)"/>
109
        </Property>
110
        <Property name="enabled" type="boolean" value="false"/>
111
      </Properties>
112
    </Component>
113
    <Component class="javax.swing.JPasswordField" name="newField2">
114
      <Properties>
115
        <Property name="enabled" type="boolean" value="false"/>
116
      </Properties>
117
    </Component>
118
  </SubComponents>
119
</Form>
(-)a/keyring/src/org/netbeans/modules/keyring/fallback/MasterPasswordPanel.java (+202 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.fallback;
41
42
import java.awt.event.ActionEvent;
43
import java.awt.event.ActionListener;
44
import java.util.Arrays;
45
import javax.swing.JButton;
46
import javax.swing.JPanel;
47
import javax.swing.event.DocumentEvent;
48
import javax.swing.event.DocumentListener;
49
import org.openide.DialogDisplayer;
50
import org.openide.NotificationLineSupport;
51
import org.openide.NotifyDescriptor;
52
53
class MasterPasswordPanel extends JPanel {
54
55
    public MasterPasswordPanel() {
56
        initComponents();
57
    }
58
59
    /**
60
     * Shows this dialog.
61
     * @return master password, and if selected, new master password; or null if cancelled
62
     */
63
    public char[][] display() {
64
        // XXX I18N
65
        final JButton ok = new JButton("OK");
66
        ok.setDefaultCapable(true);
67
        NotifyDescriptor d = new NotifyDescriptor(this, "Enter Master Password", NotifyDescriptor.OK_CANCEL_OPTION, NotifyDescriptor.PLAIN_MESSAGE,
68
                new Object[] {ok, NotifyDescriptor.CANCEL_OPTION}, ok);
69
        final NotificationLineSupport notification = d.createNotificationLineSupport();
70
        final Runnable update = new Runnable() {
71
            public void run() {
72
                if (masterPasswordField.getPassword().length == 0) {
73
                    notification.setInformationMessage("Enter password");
74
                    ok.setEnabled(false);
75
                    return;
76
                }
77
                boolean changing = setNewBox.isSelected();
78
                newLabel1.setEnabled(changing);
79
                newField1.setEnabled(changing);
80
                newLabel2.setEnabled(changing);
81
                newField2.setEnabled(changing);
82
                if (changing) {
83
                    if (newField1.getPassword().length == 0) {
84
                        notification.setInformationMessage("Enter new password");
85
                        ok.setEnabled(false);
86
                        return;
87
                    }
88
                    if (!Arrays.equals(newField1.getPassword(), newField2.getPassword())) {
89
                        notification.setInformationMessage("New passwords do not match");
90
                        ok.setEnabled(false);
91
                        return;
92
                    }
93
                }
94
                notification.clearMessages();
95
                ok.setEnabled(true);
96
            }
97
        };
98
        DocumentListener listener = new DocumentListener() {
99
            public void insertUpdate(DocumentEvent e) {
100
                update.run();
101
            }
102
            public void removeUpdate(DocumentEvent e) {
103
                update.run();
104
            }
105
            public void changedUpdate(DocumentEvent e) {}
106
        };
107
        update.run();
108
        masterPasswordField.getDocument().addDocumentListener(listener);
109
        newField1.getDocument().addDocumentListener(listener);
110
        newField2.getDocument().addDocumentListener(listener);
111
        setNewBox.addActionListener(new ActionListener() {
112
            public void actionPerformed(ActionEvent e) {
113
                update.run();
114
            }
115
        });
116
        if (DialogDisplayer.getDefault().notify(d) != ok) {
117
            return null;
118
        }
119
        char[] masterPassword = masterPasswordField.getPassword();
120
        return setNewBox.isSelected() ? new char[][] {masterPassword, newField1.getPassword()} : new char[][] {masterPassword};
121
    }
122
123
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
124
    private void initComponents() {
125
126
        masterPasswordLabel = new javax.swing.JLabel();
127
        masterPasswordField = new javax.swing.JPasswordField();
128
        setNewBox = new javax.swing.JCheckBox();
129
        newLabel1 = new javax.swing.JLabel();
130
        newField1 = new javax.swing.JPasswordField();
131
        newLabel2 = new javax.swing.JLabel();
132
        newField2 = new javax.swing.JPasswordField();
133
134
        masterPasswordLabel.setLabelFor(masterPasswordField);
135
        org.openide.awt.Mnemonics.setLocalizedText(masterPasswordLabel, org.openide.util.NbBundle.getMessage(MasterPasswordPanel.class, "MasterPasswordPanel.masterPasswordLabel.text")); // NOI18N
136
137
        org.openide.awt.Mnemonics.setLocalizedText(setNewBox, org.openide.util.NbBundle.getMessage(MasterPasswordPanel.class, "MasterPasswordPanel.setNewBox.text")); // NOI18N
138
139
        newLabel1.setLabelFor(newField1);
140
        org.openide.awt.Mnemonics.setLocalizedText(newLabel1, org.openide.util.NbBundle.getMessage(MasterPasswordPanel.class, "MasterPasswordPanel.newLabel1.text")); // NOI18N
141
        newLabel1.setEnabled(false);
142
143
        newField1.setEnabled(false);
144
145
        newLabel2.setLabelFor(newField2);
146
        org.openide.awt.Mnemonics.setLocalizedText(newLabel2, org.openide.util.NbBundle.getMessage(MasterPasswordPanel.class, "MasterPasswordPanel.newLabel2.text")); // NOI18N
147
        newLabel2.setEnabled(false);
148
149
        newField2.setEnabled(false);
150
151
        org.jdesktop.layout.GroupLayout layout = new org.jdesktop.layout.GroupLayout(this);
152
        this.setLayout(layout);
153
        layout.setHorizontalGroup(
154
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
155
            .add(layout.createSequentialGroup()
156
                .addContainerGap()
157
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
158
                    .add(layout.createSequentialGroup()
159
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
160
                            .add(newLabel1)
161
                            .add(newLabel2)
162
                            .add(masterPasswordLabel))
163
                        .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
164
                        .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
165
                            .add(masterPasswordField, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 224, Short.MAX_VALUE)
166
                            .add(newField2, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 224, Short.MAX_VALUE)
167
                            .add(newField1, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, 224, Short.MAX_VALUE)))
168
                    .add(setNewBox))
169
                .addContainerGap())
170
        );
171
        layout.setVerticalGroup(
172
            layout.createParallelGroup(org.jdesktop.layout.GroupLayout.LEADING)
173
            .add(layout.createSequentialGroup()
174
                .addContainerGap()
175
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
176
                    .add(masterPasswordLabel)
177
                    .add(masterPasswordField, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
178
                .add(18, 18, 18)
179
                .add(setNewBox)
180
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
181
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
182
                    .add(newLabel1)
183
                    .add(newField1, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
184
                .addPreferredGap(org.jdesktop.layout.LayoutStyle.RELATED)
185
                .add(layout.createParallelGroup(org.jdesktop.layout.GroupLayout.BASELINE)
186
                    .add(newLabel2)
187
                    .add(newField2, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE, org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, org.jdesktop.layout.GroupLayout.PREFERRED_SIZE))
188
                .addContainerGap(org.jdesktop.layout.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))
189
        );
190
    }// </editor-fold>//GEN-END:initComponents
191
192
    // Variables declaration - do not modify//GEN-BEGIN:variables
193
    private javax.swing.JPasswordField masterPasswordField;
194
    private javax.swing.JLabel masterPasswordLabel;
195
    private javax.swing.JPasswordField newField1;
196
    private javax.swing.JPasswordField newField2;
197
    private javax.swing.JLabel newLabel1;
198
    private javax.swing.JLabel newLabel2;
199
    private javax.swing.JCheckBox setNewBox;
200
    // End of variables declaration//GEN-END:variables
201
202
}
(-)a/keyring/src/org/netbeans/modules/keyring/gnome/GnomeKeyringLibrary.java (+80 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.gnome;
41
42
import com.sun.jna.Library;
43
import com.sun.jna.Native;
44
import com.sun.jna.Structure;
45
46
/**
47
 * @see <a href="http://library.gnome.org/devel/gnome-keyring/stable/">gnome-keyring API Reference</a>
48
 */
49
public interface GnomeKeyringLibrary extends Library {
50
51
    GnomeKeyringLibrary LIBRARY = (GnomeKeyringLibrary) Native.loadLibrary("gnome-keyring", GnomeKeyringLibrary.class);
52
53
    boolean gnome_keyring_is_available();
54
55
    int gnome_keyring_store_password_sync(GnomeKeyringPasswordSchema schema,
56
                                                         String keyring,
57
                                                         String display_name,
58
                                                         String password,
59
                                                         String... attrs);
60
61
    int gnome_keyring_find_password_sync(GnomeKeyringPasswordSchema schema,
62
                                         String[] password,
63
                                         String... attrs);
64
65
    int gnome_keyring_delete_password_sync(GnomeKeyringPasswordSchema schema,
66
                                           String... attrs);
67
68
    void g_set_application_name(String name);
69
70
    class GnomeKeyringPasswordSchema extends Structure {
71
        public int item_type;
72
        public GnomeKeyringPasswordSchemaAttribute[] attributes = new GnomeKeyringPasswordSchemaAttribute[32];
73
    }
74
75
    class GnomeKeyringPasswordSchemaAttribute extends Structure {
76
        public String name;
77
        public int type;
78
    }
79
80
}
(-)a/keyring/src/org/netbeans/modules/keyring/gnome/GnomeProvider.java (+131 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.gnome;
41
42
import java.text.MessageFormat;
43
import java.util.MissingResourceException;
44
import java.util.logging.Level;
45
import java.util.logging.Logger;
46
import static org.netbeans.modules.keyring.gnome.GnomeKeyringLibrary.*;
47
import org.netbeans.spi.keyring.KeyringProvider;
48
import org.openide.util.NbBundle;
49
import org.openide.util.lookup.ServiceProvider;
50
51
@ServiceProvider(service=KeyringProvider.class, position=100)
52
public class GnomeProvider implements KeyringProvider {
53
54
    private static final Logger LOG = Logger.getLogger(GnomeProvider.class.getName());
55
    private static final String KEY = "key"; // NOI18N
56
57
    private static GnomeKeyringPasswordSchema SCHEMA;
58
59
    public boolean enabled() {
60
        if (Boolean.getBoolean("netbeans.keyring.no.native")) {
61
            LOG.fine("native keyring integration disabled");
62
            return false;
63
        }
64
        if (System.getenv("GNOME_KEYRING_PID") == null) { // NOI18N
65
            // XXX is this going to be set on all Gnome platforms?
66
            LOG.fine("GNOME_KEYRING_PID not set");
67
            return false;
68
        }
69
        String appName;
70
        try {
71
            appName = MessageFormat.format(
72
                    NbBundle.getBundle("org.netbeans.core.windows.view.ui.Bundle").getString("CTL_MainWindow_Title_No_Project"),
73
                    System.getProperty("netbeans.buildnumber"));
74
        } catch (MissingResourceException x) {
75
            appName = "NetBeans"; // NOI18N
76
        }
77
        try {
78
            // Need to do this somewhere, or we get warnings on console.
79
            // Also used by confirmation dialogs to give the app access to the login keyring.
80
            LIBRARY.g_set_application_name(appName);
81
            if (!LIBRARY.gnome_keyring_is_available()) {
82
                return false;
83
            }
84
            SCHEMA = new GnomeKeyringPasswordSchema();
85
            SCHEMA.item_type = 0; // GNOME_KEYRING_ITEM_GENERIC_SECRET
86
            SCHEMA.attributes[0] = new GnomeKeyringPasswordSchemaAttribute();
87
            SCHEMA.attributes[0].name = KEY;
88
            SCHEMA.attributes[0].type = 0; // GNOME_KEYRING_ATTRIBUTE_TYPE_STRING
89
            SCHEMA.attributes[1] = null;
90
            return true;
91
        } catch (Throwable t) {
92
            LOG.log(Level.FINE, null, t);
93
            return false;
94
        }
95
    }
96
97
    public char[] read(String key) {
98
        // XXX try to use the char[] directly; not sure how to do this with JNA
99
        String[] password = {null};
100
        error(GnomeKeyringLibrary.LIBRARY.gnome_keyring_find_password_sync(SCHEMA, password, KEY, key));
101
        return password[0] != null ? password[0].toCharArray() : null;
102
    }
103
104
    public void save(String key, char[] password, String description) {
105
        error(GnomeKeyringLibrary.LIBRARY.gnome_keyring_store_password_sync(
106
                SCHEMA, null, description != null ? description : key, new String(password), KEY, key));
107
    }
108
109
    public void delete(String key) {
110
        error(GnomeKeyringLibrary.LIBRARY.gnome_keyring_delete_password_sync(SCHEMA, KEY, key));
111
    }
112
113
    private static String[] ERRORS = {
114
        "OK", // NOI18N
115
        "DENIED", // NOI18N
116
        "NO_KEYRING_DAEMON", // NOI18N
117
        "ALREADY_UNLOCKED", // NOI18N
118
        "NO_SUCH_KEYRING", // NOI18N
119
        "BAD_ARGUMENTS", // NOI18N
120
        "IO_ERROR", // NOI18N
121
        "CANCELLED", // NOI18N
122
        "KEYRING_ALREADY_EXISTS", // NOI18N
123
        "NO_MATCH", // NOI18N
124
    };
125
    private static void error(int code) {
126
        if (code != 0 && code != 9) {
127
            LOG.warning("gnome-keyring error: " + ERRORS[code]);
128
        }
129
    }
130
131
}
(-)a/keyring/src/org/netbeans/modules/keyring/mac/MacProvider.java (+119 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.mac;
41
42
import com.sun.jna.Pointer;
43
import java.io.UnsupportedEncodingException;
44
import java.util.logging.Level;
45
import java.util.logging.Logger;
46
import org.netbeans.spi.keyring.KeyringProvider;
47
import org.openide.util.Utilities;
48
import org.openide.util.lookup.ServiceProvider;
49
50
@ServiceProvider(service=KeyringProvider.class, position=200)
51
public class MacProvider implements KeyringProvider {
52
53
    private static final Logger LOG = Logger.getLogger(MacProvider.class.getName());
54
55
    public boolean enabled() {
56
        if (Boolean.getBoolean("netbeans.keyring.no.native")) {
57
            LOG.fine("native keyring integration disabled");
58
            return false;
59
        }
60
        return Utilities.isMac();
61
    }
62
63
    public char[] read(String key) {
64
        try {
65
            byte[] serviceName = key.getBytes("UTF-8");
66
            byte[] accountName = "NetBeans".getBytes("UTF-8");
67
            int[] dataLength = new int[1];
68
            Pointer[] data = new Pointer[1];
69
            error("find", SecurityLibrary.LIBRARY.SecKeychainFindGenericPassword(null, serviceName.length, serviceName,
70
                    accountName.length, accountName, dataLength, data, null));
71
            if (data[0] == null) {
72
                return null;
73
            }
74
            byte[] value = data[0].getByteArray(0, dataLength[0]); // XXX ought to call SecKeychainItemFreeContent
75
            return new String(value, "UTF-8").toCharArray();
76
        } catch (UnsupportedEncodingException x) {
77
            LOG.log(Level.WARNING, null, x);
78
            return null;
79
        }
80
    }
81
82
    public void save(String key, char[] password, String description) {
83
        delete(key); // XXX supposed to use SecKeychainItemModifyContent instead, but this seems like too much work
84
        try {
85
            byte[] serviceName = key.getBytes("UTF-8");
86
            byte[] accountName = "NetBeans".getBytes("UTF-8");
87
            // Keychain Access seems to expect UTF-8, so do not use Utils.chars2Bytes:
88
            byte[] data = new String(password).getBytes("UTF-8");
89
            error("save", SecurityLibrary.LIBRARY.SecKeychainAddGenericPassword(null, serviceName.length, serviceName,
90
                    accountName.length, accountName, data.length, data, null));
91
        } catch (UnsupportedEncodingException x) {
92
            LOG.log(Level.WARNING, null, x);
93
        }
94
        // XXX use description somehow... better to use SecItemAdd with kSecAttrDescription
95
    }
96
97
    public void delete(String key) {
98
        try {
99
            byte[] serviceName = key.getBytes("UTF-8");
100
            byte[] accountName = "NetBeans".getBytes("UTF-8");
101
            Pointer[] itemRef = new Pointer[1];
102
            error("find (for delete)", SecurityLibrary.LIBRARY.SecKeychainFindGenericPassword(null, serviceName.length, serviceName,
103
                    accountName.length, accountName, null, null, itemRef));
104
            if (itemRef[0] != null) {
105
                error("delete", SecurityLibrary.LIBRARY.SecKeychainItemDelete(itemRef[0]));
106
            }
107
        } catch (UnsupportedEncodingException x) {
108
            LOG.log(Level.WARNING, null, x);
109
        }
110
    }
111
112
    private static void error(String msg, int code) {
113
        if (code != 0 && code != /* errSecItemNotFound, always returned from find it seems */-25300) {
114
            // XXX translate, but SecCopyErrorMessageString returns weird CFStringRef
115
            LOG.warning(msg + ": " + code);
116
        }
117
    }
118
119
}
(-)a/keyring/src/org/netbeans/modules/keyring/mac/SecurityLibrary.java (+79 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.mac;
41
42
import com.sun.jna.Library;
43
import com.sun.jna.Native;
44
import com.sun.jna.Pointer;
45
46
/**
47
 * @see <a href="http://developer.apple.com/mac/library/DOCUMENTATION/Security/Reference/keychainservices/Reference/reference.html">Security Framework Reference</a>
48
 */
49
public interface SecurityLibrary extends Library {
50
51
    SecurityLibrary LIBRARY = (SecurityLibrary) Native.loadLibrary("Security", SecurityLibrary.class);
52
53
    int SecKeychainAddGenericPassword(
54
            Pointer keychain,
55
            int serviceNameLength,
56
            byte[] serviceName,
57
            int accountNameLength,
58
            byte[] accountName,
59
            int passwordLength,
60
            byte[] passwordData,
61
            Pointer itemRef
62
            );
63
64
    int SecKeychainFindGenericPassword(
65
            Pointer keychainOrArray,
66
            int serviceNameLength,
67
            byte[] serviceName,
68
            int accountNameLength,
69
            byte[] accountName,
70
            int[] passwordLength,
71
            Pointer[] passwordData,
72
            Pointer[] itemRef
73
            );
74
75
    int SecKeychainItemDelete(
76
            Pointer itemRef
77
            );
78
79
}
(-)a/keyring/src/org/netbeans/modules/keyring/spi/EncryptionProvider.java (+116 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.spi;
41
42
import java.util.concurrent.Callable;
43
import org.netbeans.spi.keyring.KeyringProvider;
44
45
/**
46
 * A weaker version of {@link KeyringProvider} which can only encrypt passwords securely.
47
 * Rather than managing the complete storage of the keyring, a NetBeans-specific keyring
48
 * is used, but this provider can encrypt the sensitive contents.
49
 * The encryption is assumed to be symmetric but the encryption key should be secured.
50
 * If the NetBeans {@link KeyringProvider} is used, the first encryption provider to be found
51
 * in global lookup which claims to be enabled will be used;
52
 * a standard implementation exists (at position 1000) which uses a simple master password.
53
 */
54
public interface EncryptionProvider {
55
56
    /**
57
     * Check whether this provider can be used in the current JVM session.
58
     * If integrating a native library, this should attempt to load it.
59
     * This method will be called at most once per JVM session,
60
     * prior to any other methods in this interface being called.
61
     * @return true if this provider should be used, false if not
62
     */
63
    boolean enabled();
64
65
    /**
66
     * Define a unique ID for this encryption provider, so that if the same userdir
67
     * is reused on machines of different architecture the encrypted passwords will not conflict.
68
     * @return an arbitrary ID specific to the algorithm
69
     */
70
    String id();
71
72
    /**
73
     * Encrypt a password or other sensitive data so that only the current user can decrypt it.
74
     * @param cleartext some data (may be nulled out after this call)
75
     * @return encrypted data
76
     * @throws Exception if anything goes wrong
77
     */
78
    byte[] encrypt(char[] cleartext) throws Exception;
79
80
    /**
81
     * Decrypt a password or other sensitive data.
82
     * @param ciphertext encrypted data
83
     * @return cleartext (may be nulled out after this call)
84
     * @throws Exception if anything goes wrong
85
     */
86
    char[] decrypt(byte[] ciphertext) throws Exception;
87
88
    /**
89
     * Called if {@link #decrypt} produced incorrect results on a sample key.
90
     * The provider can react by prompting again for a master password, for example.
91
     * <p>Implementations which do not support dynamic changes to the encryption
92
     * key or method should return false from this method.
93
     * @return true if an attempt was made to correct the encryption, false if nothing has changed
94
     */
95
    boolean decryptionFailed();
96
97
    /**
98
     * Offers a callback in case the encryption needs to change.
99
     * For example, this may be employed if the user asks to change a master password.
100
     * During the callback, the provider will be asked to decrypt existing secrets
101
     * using the old encryption key; then {@link #encryptionChanged}
102
     * will be called; finally the secrets will be reencrypted using the new encryption key.
103
     * <p>Implementations which do not support dynamic changes to the encryption
104
     * key or method may ignore this method.
105
     * @param callback a callback which the provider may store and later call
106
     */
107
    void encryptionChangingCallback(Callable<Void> callback);
108
109
    /**
110
     * See {@link #encryptionChangingCallback} for description.
111
     * <p>Implementations which do not support dynamic changes to the encryption
112
     * key or method may ignore this method.
113
     */
114
    void encryptionChanged();
115
116
}
(-)a/keyring/src/org/netbeans/modules/keyring/win32/Win32Protect.java (+165 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.win32;
41
42
import com.sun.jna.Memory;
43
import com.sun.jna.Native;
44
import com.sun.jna.Pointer;
45
import com.sun.jna.Structure;
46
import com.sun.jna.WString;
47
import com.sun.jna.win32.StdCallLibrary;
48
import java.util.Arrays;
49
import java.util.concurrent.Callable;
50
import java.util.logging.Level;
51
import java.util.logging.Logger;
52
import org.netbeans.modules.keyring.Utils;
53
import org.netbeans.modules.keyring.spi.EncryptionProvider;
54
import org.openide.util.lookup.ServiceProvider;
55
56
/**
57
 * Data protection utility for Microsoft Windows.
58
 * XXX org.tmatesoft.svn.core.internal.util.jna.SVNWinCrypt is a possibly more robust implementation
59
 * (though it seems to set CRYPTPROTECT_UI_FORBIDDEN which we do not necessarily want).
60
 */
61
@ServiceProvider(service=EncryptionProvider.class, position=100)
62
public class Win32Protect implements EncryptionProvider {
63
64
    private static final Logger LOG = Logger.getLogger(Win32Protect.class.getName());
65
    
66
    public boolean enabled() {
67
        if (Boolean.getBoolean("netbeans.keyring.no.native")) {
68
            LOG.fine("native keyring integration disabled");
69
            return false;
70
        }
71
        try {
72
            if (CryptLib.INSTANCE == null) {
73
                LOG.fine("loadLibrary -> null");
74
                return false;
75
            }
76
            return true;
77
        } catch (Throwable t) {
78
            LOG.log(Level.FINE, null, t);
79
            return false;
80
        }
81
    }
82
83
    public String id() {
84
        return "win32"; // NOI18N
85
    }
86
87
    public byte[] encrypt(char[] cleartext) throws Exception {
88
        byte[] cleartextB = Utils.chars2Bytes(cleartext);
89
        CryptIntegerBlob input = new CryptIntegerBlob();
90
        input.store(cleartextB);
91
        Arrays.fill(cleartextB, (byte) 0);
92
        CryptIntegerBlob output = new CryptIntegerBlob();
93
        if (!CryptLib.INSTANCE.CryptProtectData(input, null, null, null, null, 0, output)) {
94
            throw new Exception("CryptProtectData failed");
95
        }
96
        input.zero();
97
        return output.load();
98
    }
99
100
    public char[] decrypt(byte[] ciphertext) throws Exception {
101
        CryptIntegerBlob input = new CryptIntegerBlob();
102
        input.store(ciphertext);
103
        CryptIntegerBlob output = new CryptIntegerBlob();
104
        if (!CryptLib.INSTANCE.CryptUnprotectData(input, null, null, null, null, 0, output)) {
105
            throw new Exception("CryptUnprotectData failed");
106
        }
107
        byte[] result = output.load();
108
        // XXX gives CCE because not a Memory: output.zero();
109
        char[] cleartext = Utils.bytes2Chars(result);
110
        Arrays.fill(result, (byte) 0);
111
        return cleartext;
112
    }
113
114
    public boolean decryptionFailed() {
115
        return false; // not much to do about it
116
    }
117
118
    public void encryptionChangingCallback(Callable<Void> callback) {}
119
120
    public void encryptionChanged() {
121
        assert false;
122
    }
123
124
    public interface CryptLib extends StdCallLibrary {
125
        CryptLib INSTANCE = (CryptLib) Native.loadLibrary("Crypt32", CryptLib.class); // NOI18N
126
        /** @see <a href="http://msdn.microsoft.com/en-us/library/aa380261(VS.85,printer).aspx">Reference</a> */
127
        boolean CryptProtectData(
128
                CryptIntegerBlob pDataIn,
129
                WString szDataDescr,
130
                CryptIntegerBlob pOptionalEntropy,
131
                Pointer pvReserved,
132
                Pointer pPromptStruct,
133
                int dwFlags,
134
                CryptIntegerBlob pDataOut
135
        )/* throws LastErrorException*/;
136
        /** @see <a href="http://msdn.microsoft.com/en-us/library/aa380882(VS.85,printer).aspx">Reference</a> */
137
        boolean CryptUnprotectData(
138
                CryptIntegerBlob pDataIn,
139
                WString[] ppszDataDescr,
140
                CryptIntegerBlob pOptionalEntropy,
141
                Pointer pvReserved,
142
                Pointer pPromptStruct,
143
                int dwFlags,
144
                CryptIntegerBlob pDataOut
145
        )/* throws LastErrorException*/;
146
    }
147
    
148
    public static class CryptIntegerBlob extends Structure {
149
        public int cbData;
150
        public /*byte[]*/Pointer pbData;
151
        byte[] load() {
152
            return pbData.getByteArray(0, cbData);
153
            // XXX how to free pbData? [Kernel32]LocalFree?
154
        }
155
        void store(byte[] data) {
156
            cbData = data.length;
157
            pbData = new Memory(data.length);
158
            pbData.write(0, data, 0, cbData);
159
        }
160
        void zero() {
161
            ((Memory) pbData).clear();
162
        }
163
    }
164
165
}
(-)a/keyring/src/org/netbeans/spi/keyring/KeyringProvider.java (+88 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.spi.keyring;
41
42
/**
43
 * Provider for a keyring.
44
 * Should be registered in global lookup.
45
 * Providers will be searched in the order in which they are encountered
46
 * until one which is {@link #enabled} is found.
47
 * There is a default platform-independent implementation at position 1000
48
 * which should always be enabled.
49
 * <p>All SPI calls are made from one thread at a time, so providers need not be synchronized.
50
 */
51
public interface KeyringProvider {
52
53
    /**
54
     * Check whether this provider can be used in the current JVM session.
55
     * If integrating a native keyring, this should attempt to load related
56
     * libraries and check whether they can be found.
57
     * This method will be called at most once per JVM session,
58
     * prior to any other methods in this interface being called.
59
     * @return true if this provider should be used, false if not
60
     */
61
    boolean enabled();
62
63
    /**
64
     * Read a key from the ring.
65
     * @param key the identifier of the key
66
     * @return its value if found (elements may be later nulled out), else null if not present
67
     */
68
    char[] read(String key);
69
70
    /**
71
     * Save a key to the ring.
72
     * If it could not be saved, do nothing.
73
     * If the key already existed, overwrite the password.
74
     * @param key a key identifier
75
     * @param password the password or other sensitive information associated with the key
76
     *                 (elements will be later nulled out)
77
     * @param description a user-visible description of the key (may be null)
78
     */
79
    void save(String key, char[] password, String description);
80
81
    /**
82
     * Delete a key from the ring.
83
     * If the key was not in the ring to begin with, do nothing.
84
     * @param key a key identifier
85
     */
86
    void delete(String key);
87
88
}
(-)a/keyring/test/unit/src/org/netbeans/modules/keyring/KeyringProviderTestBase.java (+78 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring;
41
42
import java.util.UUID;
43
import org.netbeans.junit.NbTestCase;
44
import org.netbeans.spi.keyring.KeyringProvider;
45
46
public abstract class KeyringProviderTestBase extends NbTestCase {
47
48
    protected KeyringProviderTestBase(String n) {
49
        super(n);
50
    }
51
52
    protected abstract KeyringProvider createProvider();
53
54
    public void testStorage() throws Exception {
55
        KeyringProvider p = createProvider();
56
        if (!p.enabled()) {
57
            System.err.println(p + "disabled on " + System.getProperty("os.name") + ", skipping");
58
            return;
59
        }
60
        doTestStorage(p, "something", "secret stuff " + UUID.randomUUID(), null);
61
        doTestStorage(p, "more", "secret stuff", "a description here");
62
        doTestStorage(p, "klíč", "hezky česky", "můj heslo");
63
        doTestStorage(p, "klā′vē ər", "ॐ", "κρυπτός");
64
    }
65
    private void doTestStorage(KeyringProvider p, String key, String password, String description) throws Exception {
66
        key = "KeyringProviderTestBase." + key; // avoid interfering with anything real
67
        assertEquals(null, p.read(key));
68
        try {
69
            p.save(key, password.toCharArray(), description);
70
            char[] loaded = p.read(key);
71
            assertEquals(password, loaded != null ? new String(loaded) : null);
72
        } finally {
73
            p.delete(key);
74
            assertEquals(null, p.read(key));
75
        }
76
    }
77
78
}
(-)a/keyring/test/unit/src/org/netbeans/modules/keyring/fallback/MasterPasswordEncryptionTest.java (+78 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.fallback;
41
42
import org.netbeans.junit.NbTestCase;
43
44
public class MasterPasswordEncryptionTest extends NbTestCase {
45
46
    public MasterPasswordEncryptionTest(String n) {
47
        super(n);
48
    }
49
50
    public void testEncryption() throws Exception {
51
        doTestEncryption("Top Secret!", "my password");
52
        doTestEncryption("some extra secret pass phrase", "something pretty long here for whatever reason...");
53
        // Only ASCII is apparently supported for master passwords:
54
        doTestEncryption("muj heslo", "hezky česky");
55
        doTestEncryption("muj heslo", "ॐ");
56
    }
57
    private void doTestEncryption(String masterPassword, String password) throws Exception {
58
        MasterPasswordEncryption p = new MasterPasswordEncryption();
59
        assertTrue(p.enabled());
60
        p.unlock(masterPassword.toCharArray());
61
        assertEquals(password, new String(p.decrypt(p.encrypt(password.toCharArray()))));
62
    }
63
64
    public void testWrongPassword() throws Exception {
65
        MasterPasswordEncryption p = new MasterPasswordEncryption();
66
        assertTrue(p.enabled());
67
        p.unlock("first password".toCharArray());
68
        byte[] ciphertext = p.encrypt("secret".toCharArray());
69
        p.unlock("second password".toCharArray());
70
        try {
71
            p.decrypt(ciphertext);
72
            fail("should not be able to decrypt with incorrect password");
73
        } catch (Exception x) {
74
            // expected: "BadPaddingException: Given final block not properly padded"
75
        }
76
    }
77
78
}
(-)a/keyring/test/unit/src/org/netbeans/modules/keyring/gnome/GnomeProviderTest.java (+55 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.gnome;
41
42
import org.netbeans.modules.keyring.KeyringProviderTestBase;
43
import org.netbeans.spi.keyring.KeyringProvider;
44
45
public class GnomeProviderTest extends KeyringProviderTestBase {
46
47
    public GnomeProviderTest(String n) {
48
        super(n);
49
    }
50
51
    protected KeyringProvider createProvider() {
52
        return new GnomeProvider();
53
    }
54
55
}
(-)a/keyring/test/unit/src/org/netbeans/modules/keyring/mac/MacProviderTest.java (+55 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.mac;
41
42
import org.netbeans.modules.keyring.KeyringProviderTestBase;
43
import org.netbeans.spi.keyring.KeyringProvider;
44
45
public class MacProviderTest extends KeyringProviderTestBase {
46
47
    public MacProviderTest(String n) {
48
        super(n);
49
    }
50
51
    protected KeyringProvider createProvider() {
52
        return new MacProvider();
53
    }
54
55
}
(-)a/keyring/test/unit/src/org/netbeans/modules/keyring/win32/Win32ProtectTest.java (+67 lines)
Line 0    Link Here 
1
/*
2
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
3
 *
4
 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
5
 *
6
 * The contents of this file are subject to the terms of either the GNU
7
 * General Public License Version 2 only ("GPL") or the Common
8
 * Development and Distribution License("CDDL") (collectively, the
9
 * "License"). You may not use this file except in compliance with the
10
 * License. You can obtain a copy of the License at
11
 * http://www.netbeans.org/cddl-gplv2.html
12
 * or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
 * specific language governing permissions and limitations under the
14
 * License.  When distributing the software, include this License Header
15
 * Notice in each file and include the License file at
16
 * nbbuild/licenses/CDDL-GPL-2-CP.  Sun designates this
17
 * particular file as subject to the "Classpath" exception as provided
18
 * by Sun in the GPL Version 2 section of the License file that
19
 * accompanied this code. If applicable, add the following below the
20
 * License Header, with the fields enclosed by brackets [] replaced by
21
 * your own identifying information:
22
 * "Portions Copyrighted [year] [name of copyright owner]"
23
 *
24
 * If you wish your version of this file to be governed by only the CDDL
25
 * or only the GPL Version 2, indicate your decision by adding
26
 * "[Contributor] elects to include this software in this distribution
27
 * under the [CDDL or GPL Version 2] license." If you do not indicate a
28
 * single choice of license, a recipient has the option to distribute
29
 * your version of this file under either the CDDL, the GPL Version 2 or
30
 * to extend the choice of license to its licensees as provided above.
31
 * However, if you add GPL Version 2 code and therefore, elected the GPL
32
 * Version 2 license, then the option applies only if the new code is
33
 * made subject to such option by the copyright holder.
34
 *
35
 * Contributor(s):
36
 *
37
 * Portions Copyrighted 2009 Sun Microsystems, Inc.
38
 */
39
40
package org.netbeans.modules.keyring.win32;
41
42
import org.netbeans.junit.NbTestCase;
43
44
public class Win32ProtectTest extends NbTestCase {
45
46
    public Win32ProtectTest(String n) {
47
        super(n);
48
    }
49
50
    public void testEncryption() throws Exception {
51
        Win32Protect p = new Win32Protect();
52
        if (!p.enabled()) {
53
            System.err.println("Skipping Win32ProtectTest on " + System.getProperty("os.name"));
54
            return;
55
        }
56
        doTestEncryption(p, "my password");
57
        doTestEncryption(p, "something pretty long here for whatever reason...");
58
        doTestEncryption(p, "hezky česky");
59
        doTestEncryption(p, "ॐ");
60
    }
61
    private void doTestEncryption(Win32Protect p, String password) throws Exception {
62
        byte[] ciphertext = p.encrypt(password.toCharArray());
63
        //System.err.println(password + " -> " + Arrays.toString(ciphertext));
64
        assertEquals(password, new String(p.decrypt(ciphertext)));
65
    }
66
67
}
(-)a/libs.jna/nbproject/project.xml (+1 lines)
 Lines 53-58    Link Here 
53
                <friend>org.netbeans.core.nativeaccess</friend>
53
                <friend>org.netbeans.core.nativeaccess</friend>
54
                <friend>org.netbeans.modules.dlight.nativeexecution</friend>
54
                <friend>org.netbeans.modules.dlight.nativeexecution</friend>
55
                <friend>org.netbeans.modules.extexecution.destroy</friend>
55
                <friend>org.netbeans.modules.extexecution.destroy</friend>
56
                <friend>org.netbeans.modules.keyring</friend>
56
                <friend>org.netbeans.modules.maven.killer</friend>
57
                <friend>org.netbeans.modules.maven.killer</friend>
57
                <friend>org.netbeans.modules.python.qshell</friend>
58
                <friend>org.netbeans.modules.python.qshell</friend>
58
                <package>com.sun.jna</package>
59
                <package>com.sun.jna</package>
(-)a/nbbuild/cluster.properties (+1 lines)
 Lines 207-212    Link Here 
207
        editor.mimelookup.impl,\
207
        editor.mimelookup.impl,\
208
        favorites,\
208
        favorites,\
209
        javahelp,\
209
        javahelp,\
210
        keyring,\
210
        libs.jna,\
211
        libs.jna,\
211
        libs.jsr223,\
212
        libs.jsr223,\
212
        libs.junit4,\
213
        libs.junit4,\
(-)a/o.n.core/nbproject/project.xml (+8 lines)
 Lines 74-79    Link Here 
74
                    </run-dependency>
74
                    </run-dependency>
75
                </dependency>
75
                </dependency>
76
                <dependency>
76
                <dependency>
77
                    <code-name-base>org.netbeans.modules.keyring</code-name-base>
78
                    <build-prerequisite/>
79
                    <compile-dependency/>
80
                    <run-dependency>
81
                        <specification-version>1.0</specification-version>
82
                    </run-dependency>
83
                </dependency>
84
                <dependency>
77
                    <code-name-base>org.netbeans.swing.plaf</code-name-base>
85
                    <code-name-base>org.netbeans.swing.plaf</code-name-base>
78
                    <build-prerequisite/>
86
                    <build-prerequisite/>
79
                    <compile-dependency/>
87
                    <compile-dependency/>
(-)a/o.n.core/src/org/netbeans/core/Bundle.properties (+4 lines)
 Lines 179-183    Link Here 
179
# NbAuthenticatorPanel
179
# NbAuthenticatorPanel
180
NbAuthenticatorPanel.userNameLbl.text=&User Name:
180
NbAuthenticatorPanel.userNameLbl.text=&User Name:
181
NbAuthenticatorPanel.passwordLbl.text=&Password:
181
NbAuthenticatorPanel.passwordLbl.text=&Password:
182
# {0} - realm (domain name?)
183
NbAuthenticatorPanel.password.description=Password for {0}
184
185
ProxySettings.password.description=Proxy password
182
186
183
Title_WebBrowser=Web Browser
187
Title_WebBrowser=Web Browser
(-)a/o.n.core/src/org/netbeans/core/NbAuthenticatorPanel.java (-2 / +23 lines)
 Lines 38-43    Link Here 
38
 */
38
 */
39
package org.netbeans.core;
39
package org.netbeans.core;
40
40
41
import java.util.prefs.Preferences;
42
import org.netbeans.api.keyring.Keyring;
43
import org.openide.util.NbBundle;
44
import org.openide.util.NbPreferences;
45
41
/**
46
/**
42
 *
47
 *
43
 * @author  lukas
48
 * @author  lukas
 Lines 45-55    Link Here 
45
final class NbAuthenticatorPanel extends javax.swing.JPanel {
50
final class NbAuthenticatorPanel extends javax.swing.JPanel {
46
51
47
    private String realmName;
52
    private String realmName;
53
    private final Preferences prefs;
54
    private final String keyringKey;
48
55
49
    /** Creates new form AuthenticatorPanel */
56
    /** Creates new form AuthenticatorPanel */
50
    public NbAuthenticatorPanel(String realmName) {
57
    public NbAuthenticatorPanel(String realmName) {
51
        this.realmName = realmName;
58
        this.realmName = realmName;
52
        initComponents();
59
        initComponents();
60
        prefs = NbPreferences.forModule(NbAuthenticatorPanel.class).node("authentication"); // NOI18N
61
        keyringKey = "authentication." + realmName; // NOI18N
62
        String username = prefs.get(realmName, null);
63
        if (username != null) {
64
            userName.setText(username);
65
            char[] pwd = Keyring.read(keyringKey);
66
            if (pwd != null) {
67
                password.setText(new String(pwd));
68
            }
69
        }
53
    }
70
    }
54
71
55
    /** This method is called from within the constructor to
72
    /** This method is called from within the constructor to
 Lines 117-126    Link Here 
117
    // End of variables declaration//GEN-END:variables
134
    // End of variables declaration//GEN-END:variables
118
135
119
    public char[] getPassword() {
136
    public char[] getPassword() {
120
        return password.getPassword();
137
        Keyring.save(keyringKey, password.getPassword(),
138
                NbBundle.getMessage(NbAuthenticatorPanel.class, "NbAuthenticatorPanel.password.description", realmName));
139
        return password.getPassword(); // call getPassword again, since previous return value nulled out
121
    }
140
    }
122
141
123
    public String getUserName() {
142
    public String getUserName() {
124
        return userName.getText();
143
        String username = userName.getText();
144
        prefs.put(realmName, username);
145
        return username;
125
    }
146
    }
126
}
147
}
(-)a/o.n.core/src/org/netbeans/core/ProxySettings.java (-2 / +16 lines)
 Lines 49-54    Link Here 
49
import java.util.StringTokenizer;
49
import java.util.StringTokenizer;
50
import java.util.prefs.PreferenceChangeListener;
50
import java.util.prefs.PreferenceChangeListener;
51
import java.util.prefs.Preferences;
51
import java.util.prefs.Preferences;
52
import org.netbeans.api.keyring.Keyring;
53
import org.openide.util.NbBundle;
52
import org.openide.util.NbPreferences;
54
import org.openide.util.NbPreferences;
53
import org.openide.util.Utilities;
55
import org.openide.util.Utilities;
54
56
 Lines 148-156    Link Here 
148
    }
150
    }
149
    
151
    
150
    public static char[] getAuthenticationPassword () {
152
    public static char[] getAuthenticationPassword () {
151
        return getPreferences ().get (PROXY_AUTHENTICATION_PASSWORD, "").toCharArray ();
153
        String old = getPreferences().get(PROXY_AUTHENTICATION_PASSWORD, null);
154
        if (old != null) {
155
            getPreferences().remove(PROXY_AUTHENTICATION_PASSWORD);
156
            setAuthenticationPassword(old.toCharArray());
157
        }
158
        char[] pwd = Keyring.read(PROXY_AUTHENTICATION_PASSWORD);
159
        return pwd != null ? pwd : new char[0];
152
    }
160
    }
153
    
161
    
162
    public static void setAuthenticationPassword(char[] password) {
163
        Keyring.save(ProxySettings.PROXY_AUTHENTICATION_PASSWORD, password,
164
                // XXX consider including getHttpHost and/or getHttpsHost
165
                NbBundle.getMessage(ProxySettings.class, "ProxySettings.password.description"));
166
    }
167
154
    static void addPreferenceChangeListener (PreferenceChangeListener l) {
168
    static void addPreferenceChangeListener (PreferenceChangeListener l) {
155
        getPreferences ().addPreferenceChangeListener (l);
169
        getPreferences ().addPreferenceChangeListener (l);
156
    }
170
    }
 Lines 158-164    Link Here 
158
    static void removePreferenceChangeListener (PreferenceChangeListener l) {
172
    static void removePreferenceChangeListener (PreferenceChangeListener l) {
159
        getPreferences ().removePreferenceChangeListener (l);
173
        getPreferences ().removePreferenceChangeListener (l);
160
    }
174
    }
161
    
175
162
    static class SystemProxySettings extends ProxySettings {
176
    static class SystemProxySettings extends ProxySettings {
163
        
177
        
164
        public static String getHttpHost () {
178
        public static String getHttpHost () {
(-)a/uihandler/nbproject/project.xml (+8 lines)
 Lines 73-78    Link Here 
73
                    </run-dependency>
73
                    </run-dependency>
74
                </dependency>
74
                </dependency>
75
                <dependency>
75
                <dependency>
76
                    <code-name-base>org.netbeans.modules.keyring</code-name-base>
77
                    <build-prerequisite/>
78
                    <compile-dependency/>
79
                    <run-dependency>
80
                        <specification-version>1.0</specification-version>
81
                    </run-dependency>
82
                </dependency>
83
                <dependency>
76
                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
84
                    <code-name-base>org.netbeans.modules.options.api</code-name-base>
77
                    <build-prerequisite/>
85
                    <build-prerequisite/>
78
                    <compile-dependency/>
86
                    <compile-dependency/>
(-)a/uihandler/src/org/netbeans/modules/exceptions/Bundle.properties (+2 lines)
 Lines 49-51    Link Here 
49
submit a bug at <a href="http://www.netbeans.org/issues/enter_bug.cgi">\
49
submit a bug at <a href="http://www.netbeans.org/issues/enter_bug.cgi">\
50
http://www.netbeans.org/issues/enter_bug.cgi</a> against logger, please.
50
http://www.netbeans.org/issues/enter_bug.cgi</a> against logger, please.
51
LoadingMessage=Loading 
51
LoadingMessage=Loading 
52
53
ExceptionsSettings.password.description=Exception reporter login
(-)a/uihandler/src/org/netbeans/modules/exceptions/ExceptionsSettings.java (-2 / +12 lines)
 Lines 42-47    Link Here 
42
package org.netbeans.modules.exceptions;
42
package org.netbeans.modules.exceptions;
43
43
44
import java.util.prefs.Preferences;
44
import java.util.prefs.Preferences;
45
import org.netbeans.api.keyring.Keyring;
46
import org.openide.util.NbBundle;
45
import org.openide.util.NbPreferences;
47
import org.openide.util.NbPreferences;
46
48
47
/**
49
/**
 Lines 52-57    Link Here 
52
    
54
    
53
    private static final String userProp = "UserName";       // NOI18N
55
    private static final String userProp = "UserName";       // NOI18N
54
    private static final String passwdProp = "Passwd";
56
    private static final String passwdProp = "Passwd";
57
    private static final String passwdKey = "exceptionreporter"; // NOI18N
55
    private static final String guestProp = "Guest";
58
    private static final String guestProp = "Guest";
56
    private static final String rememberProp = "RememberPasswd";
59
    private static final String rememberProp = "RememberPasswd";
57
60
 Lines 73-83    Link Here 
73
    }
76
    }
74
        
77
        
75
    public String getPasswd() {
78
    public String getPasswd() {
76
        return prefs().get(passwdProp, "");
79
        String old = prefs().get(passwdProp, null);
80
        if (old != null) {
81
            setPasswd(old);
82
            prefs().remove(passwdProp);
83
        }
84
        char[] pwd = Keyring.read(passwdKey);
85
        return pwd != null ? new String(pwd) : "";
77
    }
86
    }
78
87
79
    public void setPasswd(String passwd) {
88
    public void setPasswd(String passwd) {
80
        prefs().put(passwdProp, passwd);
89
        Keyring.save(passwdKey, passwd.toCharArray(),
90
                NbBundle.getMessage(ExceptionsSettings.class, "ExceptionsSettings.password.description"));
81
    }
91
    }
82
    
92
    
83
    public boolean isGuest() {
93
    public boolean isGuest() {

Return to bug 173413
By use of this website, you agree to the NetBeans Policies and Terms of Use. © 2012, Oracle Corporation and/or its affiliates. Sponsored by Oracle logo