Adds SSLCertificateVerifier to the Java API.
The native API supports setting an SSLCertificateVerifier that can be used
to provide a custom certificate verifier for incoming SSL certificates. This
change provides this functionality to the Java API so that a Java implementation
can also be provided. It is expected this will only be used in specialized
circumstances and most users will not hit this code path.
Bug: webrtc:9541
Change-Id: Id3c75b8f288333b53edc2959bac533e3ec614978
Reviewed-on: https://webrtc-review.googlesource.com/89500
Commit-Queue: Benjamin Wright <benwright@webrtc.org>
Reviewed-by: Sami Kalliomäki <sakal@webrtc.org>
Cr-Commit-Position: refs/heads/master@{#24057}
diff --git a/sdk/android/BUILD.gn b/sdk/android/BUILD.gn
index e6ad0da..fb08dd1 100644
--- a/sdk/android/BUILD.gn
+++ b/sdk/android/BUILD.gn
@@ -492,6 +492,7 @@
"api/org/webrtc/RtpReceiver.java",
"api/org/webrtc/RtpSender.java",
"api/org/webrtc/RtpTransceiver.java",
+ "api/org/webrtc/SSLCertificateVerifier.java",
"api/org/webrtc/SdpObserver.java",
"api/org/webrtc/SessionDescription.java",
"api/org/webrtc/StatsObserver.java",
@@ -578,6 +579,8 @@
"src/jni/pc/sdpobserver.h",
"src/jni/pc/sessiondescription.cc",
"src/jni/pc/sessiondescription.h",
+ "src/jni/pc/sslcertificateverifierwrapper.cc",
+ "src/jni/pc/sslcertificateverifierwrapper.h",
"src/jni/pc/statsobserver.cc",
"src/jni/pc/statsobserver.h",
"src/jni/pc/turncustomizer.cc",
@@ -990,6 +993,7 @@
"api/org/webrtc/RtpReceiver.java",
"api/org/webrtc/RtpSender.java",
"api/org/webrtc/RtpTransceiver.java",
+ "api/org/webrtc/SSLCertificateVerifier.java",
"api/org/webrtc/SdpObserver.java",
"api/org/webrtc/SessionDescription.java",
"api/org/webrtc/StatsObserver.java",
diff --git a/sdk/android/api/org/webrtc/PeerConnectionDependencies.java b/sdk/android/api/org/webrtc/PeerConnectionDependencies.java
index 8ecf0ff..fd765b1 100644
--- a/sdk/android/api/org/webrtc/PeerConnectionDependencies.java
+++ b/sdk/android/api/org/webrtc/PeerConnectionDependencies.java
@@ -20,18 +20,27 @@
*/
public final class PeerConnectionDependencies {
// Mandatory dependencies.
- private PeerConnection.Observer observer;
+ private final PeerConnection.Observer observer;
+
+ // Optional fields.
+ private final SSLCertificateVerifier sslCertificateVerifier;
public static class Builder {
private PeerConnection.Observer observer;
+ private SSLCertificateVerifier sslCertificateVerifier;
private Builder(PeerConnection.Observer observer) {
this.observer = observer;
}
+ public Builder setSSLCertificateVerifier(SSLCertificateVerifier sslCertificateVerifier) {
+ this.sslCertificateVerifier = sslCertificateVerifier;
+ return this;
+ }
+
// Observer is a required dependency and so is forced in the construction of the object.
public PeerConnectionDependencies createPeerConnectionDependencies() {
- return new PeerConnectionDependencies(observer);
+ return new PeerConnectionDependencies(observer, sslCertificateVerifier);
}
}
@@ -43,7 +52,14 @@
return observer;
}
- private PeerConnectionDependencies(PeerConnection.Observer observer) {
+ @Nullable
+ SSLCertificateVerifier getSSLCertificateVerifier() {
+ return sslCertificateVerifier;
+ }
+
+ private PeerConnectionDependencies(
+ PeerConnection.Observer observer, SSLCertificateVerifier sslCertificateVerifier) {
this.observer = observer;
+ this.sslCertificateVerifier = sslCertificateVerifier;
}
}
diff --git a/sdk/android/api/org/webrtc/PeerConnectionFactory.java b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
index e4e881f..3a76d7c 100644
--- a/sdk/android/api/org/webrtc/PeerConnectionFactory.java
+++ b/sdk/android/api/org/webrtc/PeerConnectionFactory.java
@@ -329,6 +329,25 @@
}
/**
+ * Internal helper function to pass the parameters down into the native JNI bridge.
+ */
+ @Nullable
+ PeerConnection createPeerConnectionInternal(PeerConnection.RTCConfiguration rtcConfig,
+ MediaConstraints constraints, PeerConnection.Observer observer,
+ SSLCertificateVerifier sslCertificateVerifier) {
+ long nativeObserver = PeerConnection.createNativePeerConnectionObserver(observer);
+ if (nativeObserver == 0) {
+ return null;
+ }
+ long nativePeerConnection = nativeCreatePeerConnection(
+ nativeFactory, rtcConfig, constraints, nativeObserver, sslCertificateVerifier);
+ if (nativePeerConnection == 0) {
+ return null;
+ }
+ return new PeerConnection(nativePeerConnection);
+ }
+
+ /**
* Deprecated. PeerConnection constraints are deprecated. Supply values in rtcConfig struct
* instead and use the method without constraints in the signature.
*/
@@ -336,16 +355,8 @@
@Deprecated
public PeerConnection createPeerConnection(PeerConnection.RTCConfiguration rtcConfig,
MediaConstraints constraints, PeerConnection.Observer observer) {
- long nativeObserver = PeerConnection.createNativePeerConnectionObserver(observer);
- if (nativeObserver == 0) {
- return null;
- }
- long nativePeerConnection =
- nativeCreatePeerConnection(nativeFactory, rtcConfig, constraints, nativeObserver);
- if (nativePeerConnection == 0) {
- return null;
- }
- return new PeerConnection(nativePeerConnection);
+ return createPeerConnectionInternal(
+ rtcConfig, constraints, observer, /* sslCertificateVerifier= */ null);
}
/**
@@ -376,7 +387,8 @@
@Nullable
public PeerConnection createPeerConnection(
PeerConnection.RTCConfiguration rtcConfig, PeerConnectionDependencies dependencies) {
- return createPeerConnection(rtcConfig, null /* constraints */, dependencies.getObserver());
+ return createPeerConnectionInternal(rtcConfig, null /* constraints */,
+ dependencies.getObserver(), dependencies.getSSLCertificateVerifier());
}
public MediaStream createLocalMediaStream(String label) {
@@ -514,7 +526,8 @@
VideoDecoderFactory decoderFactory, long nativeAudioProcessor,
long nativeFecControllerFactory);
private static native long nativeCreatePeerConnection(long factory,
- PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver);
+ PeerConnection.RTCConfiguration rtcConfig, MediaConstraints constraints, long nativeObserver,
+ SSLCertificateVerifier sslCertificateVerifier);
private static native long nativeCreateLocalMediaStream(long factory, String label);
private static native long nativeCreateVideoSource(long factory, boolean is_screencast);
private static native long nativeCreateVideoTrack(
diff --git a/sdk/android/api/org/webrtc/SSLCertificateVerifier.java b/sdk/android/api/org/webrtc/SSLCertificateVerifier.java
new file mode 100644
index 0000000..461cd3b
--- /dev/null
+++ b/sdk/android/api/org/webrtc/SSLCertificateVerifier.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+package org.webrtc;
+
+/**
+ * The SSLCertificateVerifier interface allows API users to provide custom
+ * logic to verify certificates.
+ */
+public interface SSLCertificateVerifier {
+ /**
+ * Implementations of verify allow applications to provide custom logic for
+ * verifying certificates. This is not required by default and should be used
+ * with care.
+ *
+ * @param certificate A byte array containing a DER encoded X509 certificate.
+ * @return True if the certificate is verified and trusted else false.
+ */
+ @CalledByNative boolean verify(byte[] certificate);
+}
diff --git a/sdk/android/src/jni/pc/peerconnectionfactory.cc b/sdk/android/src/jni/pc/peerconnectionfactory.cc
index 889593e..ba1be38 100644
--- a/sdk/android/src/jni/pc/peerconnectionfactory.cc
+++ b/sdk/android/src/jni/pc/peerconnectionfactory.cc
@@ -34,6 +34,7 @@
#include "sdk/android/src/jni/pc/media.h"
#include "sdk/android/src/jni/pc/ownedfactoryandthreads.h"
#include "sdk/android/src/jni/pc/peerconnection.h"
+#include "sdk/android/src/jni/pc/sslcertificateverifierwrapper.h"
#include "sdk/android/src/jni/pc/video.h"
#include "system_wrappers/include/field_trial.h"
// Adding 'nogncheck' to disable the gn include headers check.
@@ -374,7 +375,8 @@
jlong factory,
const JavaParamRef<jobject>& j_rtc_config,
const JavaParamRef<jobject>& j_constraints,
- jlong observer_p) {
+ jlong observer_p,
+ const JavaParamRef<jobject>& j_sslCertificateVerifier) {
rtc::scoped_refptr<PeerConnectionFactoryInterface> f(
reinterpret_cast<PeerConnectionFactoryInterface*>(
factoryFromJava(factory)));
@@ -404,8 +406,17 @@
constraints = JavaToNativeMediaConstraints(jni, j_constraints);
CopyConstraintsIntoRtcConfiguration(constraints.get(), &rtc_config);
}
- rtc::scoped_refptr<PeerConnectionInterface> pc(
- f->CreatePeerConnection(rtc_config, nullptr, nullptr, observer.get()));
+
+ PeerConnectionDependencies peer_connection_dependencies(observer.get());
+ if (!j_sslCertificateVerifier.is_null()) {
+ peer_connection_dependencies.tls_cert_verifier =
+ absl::make_unique<SSLCertificateVerifierWrapper>(
+ jni, j_sslCertificateVerifier);
+ }
+
+ rtc::scoped_refptr<PeerConnectionInterface> pc(f->CreatePeerConnection(
+ rtc_config, std::move(peer_connection_dependencies)));
+
return jlongFromPointer(
new OwnedPeerConnection(pc, std::move(observer), std::move(constraints)));
}
diff --git a/sdk/android/src/jni/pc/sslcertificateverifierwrapper.cc b/sdk/android/src/jni/pc/sslcertificateverifierwrapper.cc
new file mode 100644
index 0000000..2ff9a46
--- /dev/null
+++ b/sdk/android/src/jni/pc/sslcertificateverifierwrapper.cc
@@ -0,0 +1,44 @@
+/*
+ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#include "sdk/android/src/jni/pc/sslcertificateverifierwrapper.h"
+#include "sdk/android/generated_peerconnection_jni/jni/SSLCertificateVerifier_jni.h"
+#include "sdk/android/native_api/jni/class_loader.h"
+#include "sdk/android/native_api/jni/java_types.h"
+
+namespace webrtc {
+namespace jni {
+
+SSLCertificateVerifierWrapper::SSLCertificateVerifierWrapper(
+ JNIEnv* jni,
+ const JavaRef<jobject>& ssl_certificate_verifier)
+ : ssl_certificate_verifier_(jni, ssl_certificate_verifier) {}
+
+SSLCertificateVerifierWrapper::~SSLCertificateVerifierWrapper() = default;
+
+bool SSLCertificateVerifierWrapper::Verify(
+ const rtc::SSLCertificate& certificate) {
+ JNIEnv* jni = AttachCurrentThreadIfNeeded();
+
+ // Serialize the der encoding of the cert into a jbyteArray
+ rtc::Buffer cert_der_buffer;
+ certificate.ToDER(&cert_der_buffer);
+ ScopedJavaLocalRef<jbyteArray> jni_buffer(
+ jni, jni->NewByteArray(cert_der_buffer.size()));
+ jni->SetByteArrayRegion(
+ jni_buffer.obj(), 0, cert_der_buffer.size(),
+ reinterpret_cast<const jbyte*>(cert_der_buffer.data()));
+
+ return Java_SSLCertificateVerifier_verify(jni, ssl_certificate_verifier_,
+ jni_buffer);
+}
+
+} // namespace jni
+} // namespace webrtc
diff --git a/sdk/android/src/jni/pc/sslcertificateverifierwrapper.h b/sdk/android/src/jni/pc/sslcertificateverifierwrapper.h
new file mode 100644
index 0000000..719fa44
--- /dev/null
+++ b/sdk/android/src/jni/pc/sslcertificateverifierwrapper.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright 2018 The WebRTC project authors. All Rights Reserved.
+ *
+ * Use of this source code is governed by a BSD-style license
+ * that can be found in the LICENSE file in the root of the source
+ * tree. An additional intellectual property rights grant can be found
+ * in the file PATENTS. All contributing project authors may
+ * be found in the AUTHORS file in the root of the source tree.
+ */
+
+#ifndef SDK_ANDROID_SRC_JNI_PC_SSLCERTIFICATEVERIFIERWRAPPER_H_
+#define SDK_ANDROID_SRC_JNI_PC_SSLCERTIFICATEVERIFIERWRAPPER_H_
+
+#include <jni.h>
+#include <vector>
+
+#include "rtc_base/sslcertificate.h"
+#include "sdk/android/src/jni/jni_helpers.h"
+
+namespace webrtc {
+namespace jni {
+
+// Wrapper for Java SSLCertifiacteVerifier class. Delegates method calls through
+// JNI and wraps the encoder inside SSLCertificateVerifierWrapper.
+class SSLCertificateVerifierWrapper : public rtc::SSLCertificateVerifier {
+ public:
+ SSLCertificateVerifierWrapper(
+ JNIEnv* jni,
+ const JavaRef<jobject>& ssl_certificate_verifier);
+ ~SSLCertificateVerifierWrapper() override;
+
+ bool Verify(const rtc::SSLCertificate& certificate) override;
+
+ private:
+ const ScopedJavaGlobalRef<jobject> ssl_certificate_verifier_;
+};
+
+} // namespace jni
+} // namespace webrtc
+
+#endif // SDK_ANDROID_SRC_JNI_PC_SSLCERTIFICATEVERIFIERWRAPPER_H_