Re: svn commit: r1187840 - in /jakarta/jmeter/trunk: bin/ src/core/org/apache/jmeter/util/ src/core/org/apache/jmeter/util/keystore/ xdocs/

sebb <[email protected]> Sun, 23 Oct 2011 12:01:36 +0100
Newsgroups gmane.comp.jakarta.cactus.devel
Message-ID <CAOGo0VbDtA+89ude9RaeROFAB0HOOHMJA210jQc9kuor-5JJAQ@mail.gmail.com>
On 23 October 2011 11:53, Philippe Mouawad <[email protected]> wro=
te:
> I looked in a bit more detail,
> static is needed

Not if one moves the field to the WrappedX509KeyManager class, which
is what I will do.

> I think AtomicInteger won't do it because we need to increment and %
> aliasCount in the same time, don't know if we can do that =A0so maybe jus=
t a
> custom lock for this static field would do it.

> On Sun, Oct 23, 2011 at 12:49 PM, sebb <[email protected]> wrote:
>
>> On 23 October 2011 11:38, Philippe Mouawad <[email protected]>
>> wrote:
>> > Hello,
>> > Regarding this last commit, =A0I think there is an issue in last_user
>> either
>> > being static or being synchronized on this.
>> >
>> > In my opinion, as it seems JsseSSLManager is a singleton, last_user
>> should
>> > be instance variable.
>> > If it's not the case, then synchronized block in getNextIndex should b=
e
>> on
>> > JsseSSLManager.class or field should use AtomicInteger .
>>
>> Good catch indeed!
>>
>> I originally was going to use AtomicInteger, but would still have had
>> to protect the wrap-around code.
>>
>> I'll fix it shortly.
>>
>> > Regards
>> > Philippe
>> >
>> > On Sun, Oct 23, 2011 at 3:50 AM, <[email protected]> wrote:
>> >
>> >> Author: sebb
>> >> Date: Sun Oct 23 01:50:55 2011
>> >> New Revision: 1187840
>> >>
>> >> URL: http://svn.apache.org/viewvc?rev=3D1187840&view=3Drev
>> >> Log:
>> >> Bug 52033 - Allowing multiple certificates (JKS)
>> >>
>> >> Modified:
>> >> =A0 =A0jakarta/jmeter/trunk/bin/jmeter.properties
>> >>
>> =A0jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/JsseSSLManager.j=
ava
>> >> =A0 =A0jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/SSLManage=
r.java
>> >>
>> >>
>> =A0jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/keystore/Default=
KeyStore.java
>> >>
>> >>
>> =A0jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/keystore/JmeterK=
eyStore.java
>> >> =A0 =A0jakarta/jmeter/trunk/xdocs/changes.xml
>> >>
>> >> Modified: jakarta/jmeter/trunk/bin/jmeter.properties
>> >> URL:
>> >>
>> http://svn.apache.org/viewvc/jakarta/jmeter/trunk/bin/jmeter.properties?=
rev=3D1187840&r1=3D1187839&r2=3D1187840&view=3Ddiff
>> >>
>> >>
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
>> >> --- jakarta/jmeter/trunk/bin/jmeter.properties (original)
>> >> +++ jakarta/jmeter/trunk/bin/jmeter.properties Sun Oct 23 01:50:55 20=
11
>> >> @@ -78,6 +78,11 @@ xml.parser=3Dorg.apache.xerces.parsers.SAX
>> >> =A0# set the value to 'false' to reset the SSL context each iteration
>> >> =A0#https.use.cached.ssl.context=3Dtrue
>> >>
>> >> +# Start and end index to be used with keystores with many entries
>> >> +# The default is to use entry 0, i.e. the first
>> >> +#https.keyStoreStartIndex=3D0
>> >> +#https.keyStoreEndIndex=3D0
>> >> +
>> >>
>> >>
>> =A0#--------------------------------------------------------------------=
-------
>> >> =A0# Look and Feel configuration
>> >>
>> >>
>> =A0#--------------------------------------------------------------------=
-------
>> >>
>> >> Modified:
>> >> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/JsseSSLManager.j=
ava
>> >> URL:
>> >>
>> http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jm=
eter/util/JsseSSLManager.java?rev=3D1187840&r1=3D1187839&r2=3D1187840&view=
=3Ddiff
>> >>
>> >>
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
>> >> ---
>> >> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/JsseSSLManager.j=
ava
>> >> (original)
>> >> +++
>> >> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/JsseSSLManager.j=
ava
>> Sun
>> >> Oct 23 01:50:55 2011
>> >> @@ -70,6 +70,9 @@ public class JsseSSLManager extends SSLM
>> >>
>> >> =A0 =A0 private static final int cps;
>> >>
>> >> + =A0 =A0//@GuardedBy("this")
>> >> + =A0 =A0private static int =A0last_user;
>> >> +
>> >> =A0 =A0 static {
>> >> =A0 =A0 =A0 =A0 log.info("Using default SSL protocol: "+DEFAULT_SSL_P=
ROTOCOL);
>> >> =A0 =A0 =A0 =A0 log.info("SSL session context: "+(SHARED_SESSION_CONT=
EXT ?
>> >> "shared" : "per-thread"));
>> >> @@ -314,8 +317,12 @@ public class JsseSSLManager extends SSLM
>> >> =A0 =A0 =A0 =A0 =A0*/
>> >> =A0 =A0 =A0 =A0 public String[] getClientAliases(String keyType, Prin=
cipal[]
>> >> issuers) {
>> >> =A0 =A0 =A0 =A0 =A0 =A0 log.debug("WrappedX509Manager: getClientAlias=
es: ");
>> >> - =A0 =A0 =A0 =A0 =A0 =A0log.debug(this.store.getAlias());
>> >> - =A0 =A0 =A0 =A0 =A0 =A0return new String[] { this.store.getAlias() =
};
>> >> + =A0 =A0 =A0 =A0 =A0 =A0int count =3D this.store.getAliasCount();
>> >> + =A0 =A0 =A0 =A0 =A0 =A0String[] aliases =3D new String[count];
>> >> + =A0 =A0 =A0 =A0 =A0 =A0for(int i =3D 0; i < aliases.length; i++) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0aliases[i] =3D this.store.getAlias(i=
);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 return aliases;
>> >> =A0 =A0 =A0 =A0 }
>> >>
>> >> =A0 =A0 =A0 =A0 /**
>> >> @@ -343,7 +350,7 @@ public class JsseSSLManager extends SSLM
>> >> =A0 =A0 =A0 =A0 =A0*/
>> >> =A0 =A0 =A0 =A0 public X509Certificate[] getCertificateChain(String a=
lias) {
>> >> =A0 =A0 =A0 =A0 =A0 =A0 log.debug("WrappedX509Manager: getCertificate=
Chain(" + alias
>> +
>> >> ")");
>> >> - =A0 =A0 =A0 =A0 =A0 =A0return this.store.getCertificateChain();
>> >> + =A0 =A0 =A0 =A0 =A0 =A0return this.store.getCertificateChain(alias)=
;
>> >> =A0 =A0 =A0 =A0 }
>> >>
>> >> =A0 =A0 =A0 =A0 /**
>> >> @@ -354,8 +361,9 @@ public class JsseSSLManager extends SSLM
>> >> =A0 =A0 =A0 =A0 =A0* @return The PrivateKey value
>> >> =A0 =A0 =A0 =A0 =A0*/
>> >> =A0 =A0 =A0 =A0 public PrivateKey getPrivateKey(String alias) {
>> >> - =A0 =A0 =A0 =A0 =A0 =A0log.debug("WrappedX509Manager: getPrivateKey=
: " +
>> >> this.store.getPrivateKey());
>> >> - =A0 =A0 =A0 =A0 =A0 =A0return this.store.getPrivateKey();
>> >> + =A0 =A0 =A0 =A0 =A0 =A0PrivateKey privateKey =3D this.store.getPriv=
ateKey(alias);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0log.debug("WrappedX509Manager: getPrivateKey=
: " +
>> privateKey);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0return privateKey;
>> >> =A0 =A0 =A0 =A0 }
>> >>
>> >> =A0 =A0 =A0 =A0 /**
>> >> @@ -372,14 +380,28 @@ public class JsseSSLManager extends SSLM
>> >> =A0 =A0 =A0 =A0 =A0* @see javax.net.ssl.X509KeyManager#chooseClientAl=
ias(String[],
>> >> Principal[], Socket)
>> >> =A0 =A0 =A0 =A0 =A0*/
>> >> =A0 =A0 =A0 =A0 public String chooseClientAlias(String[] keyType, Pri=
ncipal[]
>> >> issuers, Socket socket) {
>> >> - =A0 =A0 =A0 =A0 =A0 =A0String alias =3D this.store.getAlias();
>> >> - =A0 =A0 =A0 =A0 =A0 =A0log.debug("ClientAlias: " + alias);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0log.debug("keyType: " + keyType[0]);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0int aliasCount =3D this.store.getAliasCount(=
);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0String alias =3D
>> this.store.getAlias(getNextIndex(aliasCount));
>> >> =A0 =A0 =A0 =A0 =A0 =A0 if (alias =3D=3D null || alias.length() =3D=
=3D 0) {
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 log.debug("ClientAlias not found.");
>> >> =A0 =A0 =A0 =A0 =A0 =A0 }
>> >> =A0 =A0 =A0 =A0 =A0 =A0 return alias;
>> >> =A0 =A0 =A0 =A0 }
>> >>
>> >> + =A0 =A0 =A0 =A0private int getNextIndex(int aliasCount) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0if (aliasCount =3D=3D 1) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return 0;
>> >> + =A0 =A0 =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0 =A0 =A0synchronized(this) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0last_user ++;
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (last_user >=3D aliasCount) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0last_user =3D 0;
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return last_user;
>> >> + =A0 =A0 =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0}
>> >> +
>> >> =A0 =A0 =A0 =A0 /**
>> >> =A0 =A0 =A0 =A0 =A0* Choose the server alias for the SSLServerSockets=
. This are
>> not
>> >> used
>> >> =A0 =A0 =A0 =A0 =A0* in JMeter.
>> >>
>> >> Modified:
>> >> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/SSLManager.java
>> >> URL:
>> >>
>> http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jm=
eter/util/SSLManager.java?rev=3D1187840&r1=3D1187839&r2=3D1187840&view=3Ddi=
ff
>> >>
>> >>
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
>> >> --- jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/SSLManager.j=
ava
>> >> (original)
>> >> +++ jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/SSLManager.j=
ava
>> >> Sun Oct 23 01:50:55 2011
>> >> @@ -64,7 +64,7 @@ public abstract class SSLManager {
>> >> =A0 =A0 private static final Provider sslProvider =3D null;
>> >>
>> >> =A0 =A0 /** Cache the KeyStore instance */
>> >> - =A0 =A0private JmeterKeyStore keyStore;
>> >> + =A0 =A0private volatile JmeterKeyStore keyStore;
>> >>
>> >> =A0 =A0 /** Cache the TrustStore instance - null if no truststore nam=
e was
>> >> provided */
>> >> =A0 =A0 private KeyStore trustStore =3D null;
>> >> @@ -126,7 +126,9 @@ public abstract class SSLManager {
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (initStore.exists()) {
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 fileInputStream =3D new FileI=
nputStream(initStore);
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 this.keyStore.load(fileInputS=
tream, getPassword());
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0log.info("Keystore loaded OK=
 from file, found
>> alias:
>> >> "+keyStore.getAlias());
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (log.isInfoEnabled()) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0log.info("Total of "=
 +
>> keyStore.getAliasCount() +
>> >> " aliases loaded OK from keystore");
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 } else {
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 log.warn("Keystore file not f=
ound, loading empty
>> >> keystore");
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 this.defaultpw =3D ""; // Ens=
ure not null
>> >>
>> >> Modified:
>> >>
>> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/keystore/DefaultKey=
Store.java
>> >> URL:
>> >>
>> http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jm=
eter/util/keystore/DefaultKeyStore.java?rev=3D1187840&r1=3D1187839&r2=3D118=
7840&view=3Ddiff
>> >>
>> >>
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
>> >> ---
>> >>
>> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/keystore/DefaultKey=
Store.java
>> >> (original)
>> >> +++
>> >>
>> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/keystore/DefaultKey=
Store.java
>> >> Sun Oct 23 01:50:55 2011
>> >> @@ -23,21 +23,35 @@ import java.security.KeyStore;
>> >> =A0import java.security.PrivateKey;
>> >> =A0import java.security.cert.Certificate;
>> >> =A0import java.security.cert.X509Certificate;
>> >> +import java.util.ArrayList;
>> >> =A0import java.util.Enumeration;
>> >>
>> >> +import org.apache.jmeter.util.JMeterUtils;
>> >> +
>> >> =A0/**
>> >> =A0* Use this Keystore to wrap the normal KeyStore implementation.
>> >> =A0*
>> >> =A0*/
>> >> =A0public class DefaultKeyStore extends JmeterKeyStore {
>> >> - =A0 =A0private X509Certificate[] certChain;
>> >> + =A0 =A0private X509Certificate[][] certChains;
>> >>
>> >> - =A0 =A0private PrivateKey key;
>> >> + =A0 =A0private PrivateKey[] keys;
>> >>
>> >> - =A0 =A0private String alias;
>> >> + =A0 =A0private String[] names;
>> >>
>> >> =A0 =A0 private final KeyStore store;
>> >>
>> >> + =A0 =A0private static final String KEY_STORE_START_INDEX =3D
>> >> "https.keyStoreStartIndex"; // $NON-NLS-1$
>> >> + =A0 =A0private static final String KEY_STORE_END_INDEX =A0 =3D
>> >> "https.keyStoreEndIndex"; // $NON-NLS-1$
>> >> +
>> >> + =A0 =A0private static final int startIndex;
>> >> + =A0 =A0private static final int endIndex;
>> >> +
>> >> + =A0 =A0static {
>> >> + =A0 =A0 =A0 =A0startIndex =3D JMeterUtils.getPropDefault(KEY_STORE_=
START_INDEX,
>> 0);
>> >> + =A0 =A0 =A0 =A0endIndex =3D JMeterUtils.getPropDefault(KEY_STORE_EN=
D_INDEX, 0);
>> >> + =A0 =A0}
>> >> +
>> >> =A0 =A0 public DefaultKeyStore(String type) throws Exception {
>> >> =A0 =A0 =A0 =A0 this.store =3D KeyStore.getInstance(type);
>> >> =A0 =A0 }
>> >> @@ -46,54 +60,96 @@ public class DefaultKeyStore extends Jme
>> >> =A0 =A0 @Override
>> >> =A0 =A0 public void load(InputStream is, String pword) throws Excepti=
on {
>> >> =A0 =A0 =A0 =A0 store.load(is, pword.toCharArray());
>> >> - =A0 =A0 =A0 =A0PrivateKey _key =3D null;
>> >> - =A0 =A0 =A0 =A0X509Certificate[] _certChain =3D null;
>> >>
>> >> - =A0 =A0 =A0 =A0if (null !=3D is){ // No point checking an empty key=
store
>> >> + =A0 =A0 =A0 =A0ArrayList<String> v_names =3D new ArrayList<String>(=
);
>> >> + =A0 =A0 =A0 =A0ArrayList<PrivateKey> v_keys =3D new ArrayList<Priva=
teKey>();
>> >> + =A0 =A0 =A0 =A0ArrayList<X509Certificate[]> v_certChains =3D new
>> >> ArrayList<X509Certificate[]>();
>> >>
>> >> + =A0 =A0 =A0 =A0if (null !=3D is){ // No point checking an empty key=
store
>> >> + =A0 =A0 =A0 =A0 =A0 =A0PrivateKey _key =3D null;
>> >> + =A0 =A0 =A0 =A0 =A0 =A0int index =3D 0;
>> >> =A0 =A0 =A0 =A0 =A0 =A0 Enumeration<String> aliases =3D store.aliases=
();
>> >> =A0 =A0 =A0 =A0 =A0 =A0 while (aliases.hasMoreElements()) {
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0this.alias =3D aliases.nextElement()=
;
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0String alias =3D aliases.nextElement=
();
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 if (store.isKeyEntry(alias)) {
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_key =3D (PrivateKey) store.=
getKey(alias,
>> >> pword.toCharArray());
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Certificate[] chain =3D
>> >> store.getCertificateChain(alias);
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_certChain =3D new X509Certi=
ficate[chain.length];
>> >> -
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0for (int i =3D 0; i < chain.=
length; i++) {
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_certChain[i] =3D (X=
509Certificate) chain[i];
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if ((index >=3D startIndex &=
& index <=3D endIndex)) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0_key =3D (PrivateKey=
) store.getKey(alias,
>> >> pword.toCharArray());
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (null =3D=3D _key=
) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0throw new Ex=
ception("No key found for
>> alias: "
>> >> + alias); // Should not happen
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0Certificate[] chain =
=3D
>> >> store.getCertificateChain(alias);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0if (null =3D=3D chai=
n) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0throw new Ex=
ception("No certificate chain
>> >> found for alias: " + alias);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0v_names.add(alias);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0v_keys.add(_key);
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0v_certChains.add((X5=
09Certificate[]) chain);
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> >> -
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0break;
>> >> =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0 }
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0index++;
>> >> =A0 =A0 =A0 =A0 =A0 =A0 }
>> >>
>> >> =A0 =A0 =A0 =A0 =A0 =A0 if (null =3D=3D _key) {
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0throw new Exception("No key found");
>> >> - =A0 =A0 =A0 =A0 =A0 =A0}
>> >> - =A0 =A0 =A0 =A0 =A0 =A0if (null =3D=3D _certChain) {
>> >> - =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0throw new Exception("No certificate =
chain found");
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0throw new Exception("No key(s) found=
");
>> >> =A0 =A0 =A0 =A0 =A0 =A0 }
>> >> =A0 =A0 =A0 =A0 }
>> >>
>> >> - =A0 =A0 =A0 =A0this.key =3D _key;
>> >> - =A0 =A0 =A0 =A0this.certChain =3D _certChain;
>> >> + =A0 =A0 =A0 =A0/*
>> >> + =A0 =A0 =A0 =A0 * Note: if is =3D=3D null, the arrays will be empty
>> >> + =A0 =A0 =A0 =A0 */
>> >> + =A0 =A0 =A0 =A0int v_size =3D v_names.size();
>> >> +
>> >> + =A0 =A0 =A0 =A0this.names =3D new String[v_size];
>> >> + =A0 =A0 =A0 =A0this.names =3D v_names.toArray(names);
>> >> +
>> >> + =A0 =A0 =A0 =A0this.keys =3D new PrivateKey[v_size];
>> >> + =A0 =A0 =A0 =A0this.keys =3D v_keys.toArray(keys);
>> >> +
>> >> + =A0 =A0 =A0 =A0this.certChains =3D new X509Certificate[v_size][];
>> >> + =A0 =A0 =A0 =A0this.certChains =3D v_certChains.toArray(certChains)=
;
>> >> =A0 =A0 }
>> >>
>> >> - =A0 =A0/** {@inheritDoc} */
>> >> =A0 =A0 @Override
>> >> - =A0 =A0public final X509Certificate[] getCertificateChain() {
>> >> - =A0 =A0 =A0 =A0return this.certChain;
>> >> + =A0 =A0public final X509Certificate[] getCertificateChain(String al=
ias) {
>> >> + =A0 =A0 =A0 =A0int entry =3D findAlias(alias);
>> >> + =A0 =A0 =A0 =A0if (entry >=3D0) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0return this.certChains[entry];
>> >> + =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0return null;
>> >> =A0 =A0 }
>> >>
>> >> - =A0 =A0/** {@inheritDoc} */
>> >> =A0 =A0 @Override
>> >> - =A0 =A0public final PrivateKey getPrivateKey() {
>> >> - =A0 =A0 =A0 =A0return this.key;
>> >> + =A0 =A0public final PrivateKey getPrivateKey(String alias) {
>> >> + =A0 =A0 =A0 =A0int entry =3D findAlias(alias);
>> >> + =A0 =A0 =A0 =A0if (entry >=3D0) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0return this.keys[entry];
>> >> + =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0return null;
>> >> =A0 =A0 }
>> >>
>> >> - =A0 =A0/** {@inheritDoc} */
>> >> =A0 =A0 @Override
>> >> - =A0 =A0public final String getAlias() {
>> >> - =A0 =A0 =A0 =A0return this.alias;
>> >> + =A0 =A0public final String getAlias(int index) {
>> >> + =A0 =A0 =A0 =A0int length =3D this.names.length;
>> >> + =A0 =A0 =A0 =A0if (length =3D=3D 0 && index =3D=3D 0) { // i.e. is =
=3D=3D null
>> >> + =A0 =A0 =A0 =A0 =A0 =A0return null;
>> >> + =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0if (index >=3D length || index < 0) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0throw new ArrayIndexOutOfBoundsException(ind=
ex);
>> >> + =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0return this.names[index];
>> >> + =A0 =A0}
>> >> +
>> >> + =A0 =A0@Override
>> >> + =A0 =A0public int getAliasCount() {
>> >> + =A0 =A0 =A0 =A0return this.names.length;
>> >> + =A0 =A0}
>> >> +
>> >> + =A0 =A0private int findAlias(String alias) {
>> >> + =A0 =A0 =A0 =A0for(int i =3D 0; i < names.length; i++) {
>> >> + =A0 =A0 =A0 =A0 =A0 =A0if (alias.equals(names[i])){
>> >> + =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0return i;
>> >> + =A0 =A0 =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0}
>> >> + =A0 =A0 =A0 =A0return -1;
>> >> =A0 =A0 }
>> >> =A0}
>> >>
>> >> Modified:
>> >>
>> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/keystore/JmeterKeyS=
tore.java
>> >> URL:
>> >>
>> http://svn.apache.org/viewvc/jakarta/jmeter/trunk/src/core/org/apache/jm=
eter/util/keystore/JmeterKeyStore.java?rev=3D1187840&r1=3D1187839&r2=3D1187=
840&view=3Ddiff
>> >>
>> >>
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
>> >> ---
>> >>
>> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/keystore/JmeterKeyS=
tore.java
>> >> (original)
>> >> +++
>> >>
>> jakarta/jmeter/trunk/src/core/org/apache/jmeter/util/keystore/JmeterKeyS=
tore.java
>> >> Sun Oct 23 01:50:55 2011
>> >> @@ -34,16 +34,18 @@ public abstract class JmeterKeyStore {
>> >> =A0 =A0 public abstract void load(InputStream is, String password) th=
rows
>> >> Exception;
>> >>
>> >> =A0 =A0 /**
>> >> - =A0 =A0 * Get the ordered certificate chain.
>> >> + =A0 =A0 * Get the ordered certificate chain for a specific alias.
>> >> =A0 =A0 =A0*/
>> >> - =A0 =A0public abstract X509Certificate[] getCertificateChain();
>> >> + =A0 =A0public abstract X509Certificate[] getCertificateChain(String
>> alias);
>> >>
>> >> - =A0 =A0public abstract String getAlias();
>> >> + =A0 =A0public abstract int getAliasCount();
>> >> +
>> >> + =A0 =A0public abstract String getAlias(int index);
>> >>
>> >> =A0 =A0 /**
>> >> - =A0 =A0 * Return the private Key
>> >> + =A0 =A0 * Return the private Key for a specific alias
>> >> =A0 =A0 =A0*/
>> >> - =A0 =A0public abstract PrivateKey getPrivateKey();
>> >> + =A0 =A0public abstract PrivateKey getPrivateKey(String alias);
>> >>
>> >> =A0 =A0 public static final JmeterKeyStore getInstance(String type) t=
hrows
>> >> Exception {
>> >> =A0 =A0 =A0 =A0 // JAVA 1.4 now handles all keystore types, so just u=
se default
>> >>
>> >> Modified: jakarta/jmeter/trunk/xdocs/changes.xml
>> >> URL:
>> >>
>> http://svn.apache.org/viewvc/jakarta/jmeter/trunk/xdocs/changes.xml?rev=
=3D1187840&r1=3D1187839&r2=3D1187840&view=3Ddiff
>> >>
>> >>
>> =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D
>> >> --- jakarta/jmeter/trunk/xdocs/changes.xml (original)
>> >> +++ jakarta/jmeter/trunk/xdocs/changes.xml Sun Oct 23 01:50:55 2011
>> >> @@ -137,6 +137,7 @@ Mirror server now uses default port 8081
>> >> =A0<h3>HTTP Samplers</h3>
>> >> =A0<ul>
>> >> =A0<li>Bug 51981 - Better support for file: protocol in HTTP sampler<=
/li>
>> >> +<li>Bug 52033 - Allowing multiple certificates (JKS)</li>
>> >> =A0</ul>
>> >>
>> >> =A0<h3>Other samplers</h3>
>> >>
>> >>
>> >>
>> >> ---------------------------------------------------------------------
>> >> To unsubscribe, e-mail: [email protected]
>> >> For additional commands, e-mail: [email protected]=
g
>> >>
>> >>
>> >
>> >
>> > --
>> > Cordialement.
>> > Philippe Mouawad.
>> >
>>
>> ---------------------------------------------------------------------
>> To unsubscribe, e-mail: [email protected]
>> For additional commands, e-mail: [email protected]
>>
>>
>
>
> --
> Cordialement.
> Philippe Mouawad.
>