summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/com/isode/stroke/client/ClientSession.java20
-rw-r--r--src/com/isode/stroke/session/BasicSessionStream.java14
-rw-r--r--src/com/isode/stroke/session/SessionStream.java8
-rw-r--r--src/com/isode/stroke/streamstack/TLSLayer.java8
-rw-r--r--src/com/isode/stroke/tls/CertificateTrustChecker.java8
-rw-r--r--src/com/isode/stroke/tls/TLSContext.java13
-rw-r--r--src/com/isode/stroke/tls/java/JSSEContext.java24
7 files changed, 69 insertions, 26 deletions
diff --git a/src/com/isode/stroke/client/ClientSession.java b/src/com/isode/stroke/client/ClientSession.java
index f6082b7..c0caeb6 100644
--- a/src/com/isode/stroke/client/ClientSession.java
+++ b/src/com/isode/stroke/client/ClientSession.java
@@ -1,9 +1,9 @@
/*
- * Copyright (c) 2010-2012 Isode Limited, London, England.
+ * Copyright (c) 2010-2014 Isode Limited, London, England.
* All rights reserved.
*/
/*
- * Copyright (c) 2010-2011 Remko Tronçon.
+ * Copyright (c) 2010-2014 Remko Tronçon.
* All rights reserved.
*/
package com.isode.stroke.client;
@@ -48,6 +48,8 @@ import com.isode.stroke.tls.Certificate;
import com.isode.stroke.tls.CertificateTrustChecker;
import com.isode.stroke.tls.CertificateVerificationError;
import com.isode.stroke.tls.ServerIdentityVerifier;
+
+import java.util.List;
import java.util.UUID;
public class ClientSession {
@@ -513,24 +515,26 @@ public class ClientSession {
if (!checkState(State.Encrypting)) {
return;
}
- final Certificate certificate = stream.getPeerCertificate();
+ final List<Certificate> certificateChain = stream.getPeerCertificateChain();
+ final Certificate peerCertificate =
+ (certificateChain == null || certificateChain.isEmpty() ? null : certificateChain.get(0));
final CertificateVerificationError verificationError = stream.getPeerCertificateVerificationError();
if (verificationError != null) {
- checkTrustOrFinish(certificate, verificationError);
+ checkTrustOrFinish(certificateChain, verificationError);
}
else {
final ServerIdentityVerifier identityVerifier = new ServerIdentityVerifier(localJID);
- if (identityVerifier.certificateVerifies(certificate)) {
+ if (identityVerifier.certificateVerifies(peerCertificate)) {
continueAfterTLSEncrypted();
}
else {
- checkTrustOrFinish(certificate, new CertificateVerificationError(CertificateVerificationError.Type.InvalidServerIdentity));
+ checkTrustOrFinish(certificateChain, new CertificateVerificationError(CertificateVerificationError.Type.InvalidServerIdentity));
}
}
}
- private void checkTrustOrFinish(final Certificate certificate, final CertificateVerificationError error) {
- if (certificateTrustChecker != null && certificateTrustChecker.isCertificateTrusted(certificate)) {
+ private void checkTrustOrFinish(final List<Certificate> certificateChain, final CertificateVerificationError error) {
+ if (certificateTrustChecker != null && certificateTrustChecker.isCertificateTrusted(certificateChain)) {
continueAfterTLSEncrypted();
}
else {
diff --git a/src/com/isode/stroke/session/BasicSessionStream.java b/src/com/isode/stroke/session/BasicSessionStream.java
index dbe13f7..f1e7bf1 100644
--- a/src/com/isode/stroke/session/BasicSessionStream.java
+++ b/src/com/isode/stroke/session/BasicSessionStream.java
@@ -1,17 +1,18 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2014 Remko Tronçon
* All rights reserved. */
/*
- * Copyright (c) 2010-2012, Isode Limited, London, England.
+ * Copyright (c) 2010-2014, Isode Limited, London, England.
* All rights reserved.
*/
package com.isode.stroke.session;
+import java.util.List;
+
import com.isode.stroke.base.ByteArray;
import com.isode.stroke.elements.Element;
import com.isode.stroke.elements.ProtocolHeader;
import com.isode.stroke.elements.StreamType;
-import com.isode.stroke.eventloop.EventLoop;
import com.isode.stroke.network.Connection;
import com.isode.stroke.network.TimerFactory;
import com.isode.stroke.parser.PayloadParserFactoryCollection;
@@ -23,10 +24,10 @@ import com.isode.stroke.streamstack.ConnectionLayer;
import com.isode.stroke.streamstack.StreamStack;
import com.isode.stroke.streamstack.TLSLayer;
import com.isode.stroke.streamstack.WhitespacePingLayer;
-import com.isode.stroke.tls.TLSContextFactory;
import com.isode.stroke.streamstack.XMPPLayer;
import com.isode.stroke.tls.Certificate;
import com.isode.stroke.tls.CertificateVerificationError;
+import com.isode.stroke.tls.TLSContextFactory;
public class BasicSessionStream extends SessionStream {
@@ -156,6 +157,11 @@ public class BasicSessionStream extends SessionStream {
return tlsLayer != null;
}
+ @Override
+ public List<Certificate> getPeerCertificateChain() {
+ return tlsLayer.getPeerCertificateChain();
+ }
+ @Override
public Certificate getPeerCertificate() {
return tlsLayer.getPeerCertificate();
}
diff --git a/src/com/isode/stroke/session/SessionStream.java b/src/com/isode/stroke/session/SessionStream.java
index 5dbb0fc..2b9932b 100644
--- a/src/com/isode/stroke/session/SessionStream.java
+++ b/src/com/isode/stroke/session/SessionStream.java
@@ -1,13 +1,15 @@
/*
- * Copyright (c) 2010 Remko Tronçon
+ * Copyright (c) 2010-2014 Remko Tronçon
* All rights reserved.
*/
/*
- * Copyright (c) 2010-2012, Isode Limited, London, England.
+ * Copyright (c) 2010-2014, Isode Limited, London, England.
* All rights reserved.
*/
package com.isode.stroke.session;
+import java.util.List;
+
import com.isode.stroke.base.ByteArray;
import com.isode.stroke.elements.Element;
import com.isode.stroke.elements.ProtocolHeader;
@@ -16,7 +18,6 @@ import com.isode.stroke.signals.Signal1;
import com.isode.stroke.tls.Certificate;
import com.isode.stroke.tls.CertificateVerificationError;
import com.isode.stroke.tls.CertificateWithKey;
-import com.isode.stroke.tls.PKCS12Certificate;
public abstract class SessionStream {
@@ -69,6 +70,7 @@ public abstract class SessionStream {
return certificate != null && !certificate.isNull();
}
+ public abstract List<Certificate> getPeerCertificateChain();
public abstract Certificate getPeerCertificate();
public abstract CertificateVerificationError getPeerCertificateVerificationError();
diff --git a/src/com/isode/stroke/streamstack/TLSLayer.java b/src/com/isode/stroke/streamstack/TLSLayer.java
index 1f213fc..70bcd1a 100644
--- a/src/com/isode/stroke/streamstack/TLSLayer.java
+++ b/src/com/isode/stroke/streamstack/TLSLayer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2010-2012, Isode Limited, London, England.
+ * Copyright (c) 2010-2014, Isode Limited, London, England.
* All rights reserved.
*/
/*
@@ -9,6 +9,8 @@
package com.isode.stroke.streamstack;
+import java.util.List;
+
import com.isode.stroke.base.ByteArray;
import com.isode.stroke.signals.Signal;
import com.isode.stroke.signals.Slot1;
@@ -54,6 +56,10 @@ public class TLSLayer extends StreamLayer {
return context.setClientCertificate(certificate);
}
+ public List<Certificate> getPeerCertificateChain() {
+ return context.getPeerCertificateChain();
+ }
+
public Certificate getPeerCertificate() {
return context.getPeerCertificate();
}
diff --git a/src/com/isode/stroke/tls/CertificateTrustChecker.java b/src/com/isode/stroke/tls/CertificateTrustChecker.java
index 2fcf3c0..7f4753b 100644
--- a/src/com/isode/stroke/tls/CertificateTrustChecker.java
+++ b/src/com/isode/stroke/tls/CertificateTrustChecker.java
@@ -4,11 +4,14 @@
* See Documentation/Licenses/GPLv3.txt for more information.
*/
/*
- * Copyright (c) 2011, Isode Limited, London, England.
+ * Copyright (c) 2011-2014, Isode Limited, London, England.
* All rights reserved.
*/
package com.isode.stroke.tls;
+import java.util.List;
+
+
/**
* A class to implement a check for certificate trust.
*/
@@ -19,5 +22,6 @@ public interface CertificateTrustChecker {
* trusted. This usually happens when a certificate's validation
* fails, to check whether to proceed with the connection or not.
*/
- boolean isCertificateTrusted(Certificate certificate);
+ public boolean isCertificateTrusted(List<Certificate> chain);
+
}
diff --git a/src/com/isode/stroke/tls/TLSContext.java b/src/com/isode/stroke/tls/TLSContext.java
index ec39a3b..738c8b6 100644
--- a/src/com/isode/stroke/tls/TLSContext.java
+++ b/src/com/isode/stroke/tls/TLSContext.java
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2011-2012, Isode Limited, London, England.
+ * Copyright (c) 2011-2014, Isode Limited, London, England.
* All rights reserved.
*/
/*
@@ -9,6 +9,8 @@
package com.isode.stroke.tls;
+import java.util.List;
+
import com.isode.stroke.base.ByteArray;
import com.isode.stroke.signals.Signal;
import com.isode.stroke.signals.Signal1;
@@ -22,7 +24,16 @@ public abstract class TLSContext {
public abstract void handleDataFromNetwork(ByteArray data);
public abstract void handleDataFromApplication(ByteArray data);
+ /**
+ * The peer certificate, as presented by the remote entity
+ * @return the peer certificate, which may be null
+ */
public abstract Certificate getPeerCertificate();
+ /**
+ * The peer's certificate chain, as presented by the remote entity
+ * @return the peer certificate chain, which may be null.
+ */
+ public abstract List<Certificate> getPeerCertificateChain();
public abstract CertificateVerificationError getPeerCertificateVerificationError();
public abstract ByteArray getFinishMessage();
diff --git a/src/com/isode/stroke/tls/java/JSSEContext.java b/src/com/isode/stroke/tls/java/JSSEContext.java
index 2928498..13904e8 100644
--- a/src/com/isode/stroke/tls/java/JSSEContext.java
+++ b/src/com/isode/stroke/tls/java/JSSEContext.java
@@ -1,4 +1,4 @@
-/* Copyright (c) 2012-2013, Isode Limited, London, England.
+/* Copyright (c) 2012-2014, Isode Limited, London, England.
* All rights reserved.
*
* Acquisition and use of this software and related materials for any
@@ -26,7 +26,9 @@ import java.security.cert.CertificateException;
import java.security.cert.CertificateExpiredException;
import java.security.cert.CertificateNotYetValidException;
import java.security.cert.X509Certificate;
+import java.util.ArrayList;
import java.util.HashSet;
+import java.util.List;
import java.util.Set;
import java.util.Vector;
import java.util.logging.Level;
@@ -627,8 +629,10 @@ public class JSSEContext extends TLSContext {
if (certs == null || certs.length == 0) {
return;
}
-
- peerCertificate = new JavaCertificate(certs[0]);
+ peerCertificateChain = new ArrayList<Certificate>(certs.length);
+ for (X509Certificate x509:certs) {
+ peerCertificateChain.add(new JavaCertificate(x509));
+ }
/* Swiften uses SSL_get_verify_result() for this, and the documentation
* for that says it "while the verification of a certificate can fail
@@ -1052,10 +1056,16 @@ public class JSSEContext extends TLSContext {
}
-
+ @Override
+ public List<Certificate> getPeerCertificateChain() {
+ return peerCertificateChain;
+ }
@Override
public Certificate getPeerCertificate() {
- return peerCertificate;
+ if (peerCertificateChain == null || peerCertificateChain.isEmpty()) {
+ return null;
+ }
+ return (peerCertificateChain.get(0));
}
@Override
@@ -1161,9 +1171,9 @@ public class JSSEContext extends TLSContext {
private Object recvMutex = new Object();
/**
- * The server certificate as obtained from the TLS handshake
+ * The server certificate chain as obtained from the TLS handshake
*/
- private JavaCertificate peerCertificate = null;
+ private List<Certificate> peerCertificateChain = null;
/**
* The CertificateVerificationError derived from the peerCertificate. This