View | Details | Raw Unified | Return to bug 62863
Collapse All | Expand All

(-)a/src/core/org/apache/jmeter/util/SSLManager.java (-30 / +49 lines)
Lines 26-34 import java.net.HttpURLConnection; Link Here
26
import java.security.KeyStore;
26
import java.security.KeyStore;
27
import java.security.Provider;
27
import java.security.Provider;
28
import java.security.Security;
28
import java.security.Security;
29
import java.util.Arrays;
29
import java.util.Locale;
30
import java.util.Locale;
30
31
31
import javax.swing.JOptionPane;
32
import javax.swing.JOptionPane;
33
import javax.swing.JPasswordField;
32
34
33
import org.apache.jmeter.gui.GuiPackage;
35
import org.apache.jmeter.gui.GuiPackage;
34
import org.apache.jmeter.util.keystore.JmeterKeyStore;
36
import org.apache.jmeter.util.keystore.JmeterKeyStore;
Lines 122-153 public abstract class SSLManager { Link Here
122
                this.keyStore = null;
124
                this.keyStore = null;
123
                throw new IllegalArgumentException("Could not create keystore: "+e.getMessage(), e);
125
                throw new IllegalArgumentException("Could not create keystore: "+e.getMessage(), e);
124
            }
126
            }
125
127
            
126
            try {
128
           try {
127
                File initStore = new File(fileName);
129
              
128
130
              //The string 'NONE' is used for the keystore location when using PKCS11
129
                if (fileName.length() >0 && initStore.exists()) {
131
              //https://docs.oracle.com/javase/8/docs/technotes/guides/security/p11guide.html#JSSE
132
              if ("NONE".equalsIgnoreCase(fileName)) {
133
                 String password = getPassword();
134
                 if(password == null) {
135
                    throw new IllegalArgumentException("Password should not be null");
136
                 }
137
                 this.keyStore.load(null, getPassword());
138
              } else {
139
                 File initStore = new File(fileName);
140
                 if (fileName.length() > 0 && initStore.exists()) {
130
                    try (InputStream fis = new FileInputStream(initStore);
141
                    try (InputStream fis = new FileInputStream(initStore);
131
                            InputStream fileInputStream = new BufferedInputStream(fis)) {
142
                            InputStream fileInputStream = new BufferedInputStream(fis)) {
132
                        this.keyStore.load(fileInputStream, getPassword());
143
                       this.keyStore.load(fileInputStream, getPassword());
133
                        if (log.isInfoEnabled()) {
144
                       if (log.isInfoEnabled()) {
134
                            log.info(
145
                          log.info(
135
                                    "Total of {} aliases loaded OK from keystore",
146
                                  "Total of {} aliases loaded OK from keystore",
136
                                    keyStore.getAliasCount());
147
                                  keyStore.getAliasCount());
137
                        }
148
                       }
138
                    }
149
                    }
139
                } else {
150
                 } else {
140
                    log.warn("Keystore file not found, loading empty keystore");
151
                    log.warn("Keystore file not found, loading empty keystore");
141
                    this.defaultpw = ""; // Ensure not null
152
                    this.defaultpw = ""; // Ensure not null
142
                    this.keyStore.load(null, "");
153
                    this.keyStore.load(null, "");
143
                }
154
                 }
144
            } catch (Exception e) {
155
              }
145
                log.error("Problem loading keystore: {}", e.getMessage(), e);
156
           } catch (Exception e) {
146
            }
157
              log.error("Problem loading keystore: {}", e.getMessage(), e);
147
158
           }
148
            if (log.isDebugEnabled()) {
159
149
                log.debug("JmeterKeyStore type: {}", this.keyStore.getClass());
160
           if (log.isDebugEnabled()) {
150
            }
161
              log.debug("JmeterKeyStore type: {}", this.keyStore.getClass());
162
           }
151
        }
163
        }
152
164
153
        return this.keyStore;
165
        return this.keyStore;
Lines 157-163 public abstract class SSLManager { Link Here
157
     * The password can be defined as a property; this dialogue is provided to allow it
169
     * The password can be defined as a property; this dialogue is provided to allow it
158
     * to be entered at run-time.
170
     * to be entered at run-time.
159
     *
171
     *
160
     * However, this does not gain much, as the dialogue does not (yet) support hidden input ...
161
     *
172
     *
162
    */
173
    */
163
    private String getPassword() {
174
    private String getPassword() {
Lines 166-181 public abstract class SSLManager { Link Here
166
            final GuiPackage guiInstance = GuiPackage.getInstance();
177
            final GuiPackage guiInstance = GuiPackage.getInstance();
167
            if (guiInstance != null) {
178
            if (guiInstance != null) {
168
                synchronized (this) { // TODO is sync really needed?
179
                synchronized (this) { // TODO is sync really needed?
169
                    this.defaultpw = JOptionPane.showInputDialog(
180
                  JPasswordField pwf = new JPasswordField(64);
170
                            guiInstance.getMainFrame(),
181
                  pwf.setEchoChar('*');
171
                            JMeterUtils.getResString("ssl_pass_prompt"),  // $NON-NLS-1$
182
                  int choice = JOptionPane.showConfirmDialog(
172
                            JMeterUtils.getResString("ssl_pass_title"),  // $NON-NLS-1$
183
                          guiInstance.getMainFrame(),
173
                            JOptionPane.QUESTION_MESSAGE);
184
                          pwf,
174
                    System.setProperty(KEY_STORE_PASSWORD, this.defaultpw);
185
                          JMeterUtils.getResString("ssl_pass_prompt"),
175
                    password = this.defaultpw;
186
                          JOptionPane.OK_CANCEL_OPTION,
176
                }
187
                          JOptionPane.PLAIN_MESSAGE);
188
                  if (choice == JOptionPane.OK_OPTION) {
189
                     char[] pwchars = pwf.getPassword();
190
                     this.defaultpw = new String(pwchars);
191
                     Arrays.fill(pwchars, '*');
192
                  }
193
                  System.setProperty(KEY_STORE_PASSWORD, this.defaultpw);
194
                  password = this.defaultpw;
195
               }
177
            } else {
196
            } else {
178
                log.warn("No password provided, and no GUI present so cannot prompt");
197
               log.warn("No password provided, and no GUI present so cannot prompt");
179
            }
198
            }
180
        }
199
        }
181
        return password;
200
        return password;
(-)a/src/core/org/apache/jmeter/util/keystore/JmeterKeyStore.java (-38 / +36 lines)
Lines 115-163 public final class JmeterKeyStore { Link Here
115
            throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, UnrecoverableKeyException {
115
            throws NoSuchAlgorithmException, CertificateException, IOException, KeyStoreException, UnrecoverableKeyException {
116
        char[] pw = pword==null ? null : pword.toCharArray();
116
        char[] pw = pword==null ? null : pword.toCharArray();
117
        store.load(is, pw);
117
        store.load(is, pw);
118
    
118
119
        List<String> aliasesList = new ArrayList<>();
119
        List<String> aliasesList = new ArrayList<>();
120
        this.privateKeyByAlias = new HashMap<>();
120
        this.privateKeyByAlias = new HashMap<>();
121
        this.certsByAlias = new HashMap<>();
121
        this.certsByAlias = new HashMap<>();
122
122
123
        if (null != is){ // No point checking an empty keystore
123
       PrivateKey privateKey = null;
124
            PrivateKey privateKey = null;
124
       int index = 0;
125
            int index = 0;
125
       Enumeration<String> aliases = store.aliases();
126
            Enumeration<String> aliases = store.aliases();
126
       while (aliases.hasMoreElements()) {
127
            while (aliases.hasMoreElements()) {
127
          String alias = aliases.nextElement();
128
                String alias = aliases.nextElement();
128
          if (store.isKeyEntry(alias)) {
129
                if (store.isKeyEntry(alias)) {
129
             if (index >= startIndex && (endIndex == -1 || index <= endIndex)) {
130
                    if (index >= startIndex && (endIndex== -1 || index <= endIndex)) {
130
                privateKey = (PrivateKey) store.getKey(alias, pw);
131
                        privateKey = (PrivateKey) store.getKey(alias, pw);
131
                if (null == privateKey) {
132
                        if (null == privateKey) {
132
                   throw new IOException("No key found for alias: " + alias); // Should not happen
133
                            throw new IOException("No key found for alias: " + alias); // Should not happen
134
                        }
135
                        Certificate[] chain = store.getCertificateChain(alias);
136
                        if (null == chain) {
137
                            throw new IOException("No certificate chain found for alias: " + alias);
138
                        }
139
                        aliasesList.add(alias);
140
                        X509Certificate[] x509certs = new X509Certificate[chain.length];
141
                        for (int i = 0; i < x509certs.length; i++) {
142
                            x509certs[i] = (X509Certificate)chain[i];
143
                        }
144
145
                        privateKeyByAlias.put(alias, privateKey);
146
                        certsByAlias.put(alias, x509certs);
147
                    }
148
                    index++;
149
                }
133
                }
150
            }
134
                Certificate[] chain = store.getCertificateChain(alias);
151
    
135
                if (null == chain) {
152
            if (null == privateKey) {
136
                   throw new IOException("No certificate chain found for alias: " + alias);
153
                throw new IOException("No key(s) found");
137
                }
154
            }
138
                aliasesList.add(alias);
155
            if (endIndex != -1 && index <= endIndex-startIndex && log.isWarnEnabled()) {
139
                X509Certificate[] x509certs = new X509Certificate[chain.length];
156
                log.warn("Did not find as much aliases as configured in indexes Start={}, end={}, found={}",
140
                for (int i = 0; i < x509certs.length; i++) {
157
                        startIndex, endIndex, certsByAlias.size());
141
                   x509certs[i] = (X509Certificate) chain[i];
158
            }
142
                }
159
        }
143
160
    
144
                privateKeyByAlias.put(alias, privateKey);
145
                certsByAlias.put(alias, x509certs);
146
             }
147
             index++;
148
          }
149
       }
150
151
       if (null == privateKey) {
152
          throw new IOException("No key(s) found");
153
       }
154
       if (endIndex != -1 && index <= endIndex - startIndex && log.isWarnEnabled()) {
155
          log.warn("Did not find as much aliases as configured in indexes Start={}, end={}, found={}",
156
                  startIndex, endIndex, certsByAlias.size());
157
       }
158
161
        /*
159
        /*
162
         * Note: if is == null, the arrays will be empty
160
         * Note: if is == null, the arrays will be empty
163
         */
161
         */

Return to bug 62863