From 74b747a0268ec9ba27783f3bebd9897089b5a898 Mon Sep 17 00:00:00 2001
From: Lyubomir Marinov <lyubomir.marinov@jitsi.org>
Date: Thu, 20 Nov 2014 10:15:36 +0200
Subject: [PATCH] Adds a boolean ConfigurationService/System property
 org.jitsi.impl.neomedia.transform.dtls.DtlsPacketTransformer.dropUnencryptedPkts
 which indicates whether sent/received unencrypted packets are to be dropped.

---
 .../transform/dtls/DatagramTransportImpl.java |   5 +
 .../transform/dtls/DtlsControlImpl.java       |  98 +++----
 .../transform/dtls/DtlsPacketTransformer.java | 272 ++++++++++--------
 .../transform/dtls/DtlsTransformEngine.java   |  74 ++---
 .../transform/dtls/TlsClientImpl.java         |   3 +
 5 files changed, 254 insertions(+), 198 deletions(-)

diff --git a/src/org/jitsi/impl/neomedia/transform/dtls/DatagramTransportImpl.java b/src/org/jitsi/impl/neomedia/transform/dtls/DatagramTransportImpl.java
index 502ba13b..71976ea2 100644
--- a/src/org/jitsi/impl/neomedia/transform/dtls/DatagramTransportImpl.java
+++ b/src/org/jitsi/impl/neomedia/transform/dtls/DatagramTransportImpl.java
@@ -151,6 +151,7 @@ private void breakOutOfDTLSReliableHandshakeReceiveMessage(Throwable cause)
     /**
      * {@inheritDoc}
      */
+    @Override
     public void close()
         throws IOException
     {
@@ -224,6 +225,7 @@ private void flush()
     /**
      * {@inheritDoc}
      */
+    @Override
     public int getReceiveLimit()
         throws IOException
     {
@@ -239,6 +241,7 @@ public int getReceiveLimit()
     /**
      * {@inheritDoc}
      */
+    @Override
     public int getSendLimit()
         throws IOException
     {
@@ -316,6 +319,7 @@ void queueReceive(byte[] buf, int off, int len)
     /**
      * {@inheritDoc}
      */
+    @Override
     public int receive(byte[] buf, int off, int len, int waitMillis)
         throws IOException
     {
@@ -453,6 +457,7 @@ public int receive(byte[] buf, int off, int len, int waitMillis)
     /**
      * {@inheritDoc}
      */
+    @Override
     public void send(byte[] buf, int off, int len)
         throws IOException
     {
diff --git a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsControlImpl.java b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsControlImpl.java
index c9cc03b4..2214e237 100644
--- a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsControlImpl.java
+++ b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsControlImpl.java
@@ -405,11 +405,6 @@ private static String toHex(byte[] fingerprint)
      */
     private final String localFingerprint;
 
-    /**
-     * Whether rtcp-mux is in use.
-     */
-    private boolean rtcpmux = false;
-
     /**
      * The hash function of {@link #localFingerprint} (which is the same as the
      * digest algorithm of the signature algorithm of {@link #certificate} in
@@ -422,6 +417,11 @@ private static String toHex(byte[] fingerprint)
      */
     private Map<String,String> remoteFingerprints;
 
+    /**
+     * Whether rtcp-mux is in use.
+     */
+    private boolean rtcpmux = false;
+
     /**
      * The value of the <tt>setup</tt> SDP attribute defined by RFC 4145
      * &quot;TCP-Based Media Transport in the Session Description Protocol
@@ -474,22 +474,6 @@ public DtlsControlImpl(boolean disableSRTP)
                     localFingerprintHashFunction);
     }
 
-    /**
-     * Prepares this <tt>DtlsControlImpl</tt> for garbage collection.
-     */
-    private void doCleanup()
-    {
-        super.cleanup(null);
-
-        setConnector(null);
-
-        synchronized (this)
-        {
-            disposed = true;
-            notifyAll();
-        }
-    }
-
     /**
      * {@inheritDoc}
      */
@@ -521,6 +505,22 @@ protected DtlsTransformEngine createTransformEngine()
         return transformEngine;
     }
 
+    /**
+     * Prepares this <tt>DtlsControlImpl</tt> for garbage collection.
+     */
+    private void doCleanup()
+    {
+        super.cleanup(null);
+
+        setConnector(null);
+
+        synchronized (this)
+        {
+            disposed = true;
+            notifyAll();
+        }
+    }
+
     /**
      * Gets the certificate with which the local endpoint represented by this
      * instance authenticates its ends of DTLS sessions.
@@ -582,6 +582,18 @@ boolean isSrtpDisabled()
         return disableSRTP;
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void registerUser(Object user)
+    {
+        synchronized (users)
+        {
+            users.add(user);
+        }
+    }
+
     /**
      * {@inheritDoc}
      *
@@ -627,6 +639,22 @@ public void setRemoteFingerprints(Map<String,String> remoteFingerprints)
         }
     }
 
+    /**
+     * {@inheritDoc}
+     */
+    @Override
+    public void setRtcpmux(boolean rtcpmux)
+    {
+        if (this.rtcpmux != rtcpmux)
+        {
+            this.rtcpmux = rtcpmux;
+            DtlsTransformEngine transformEngine = this.transformEngine;
+
+            if (transformEngine != null)
+                transformEngine.setRtcpmux(rtcpmux);
+        }
+    }
+
     /**
      * {@inheritDoc}
      */
@@ -789,32 +817,4 @@ boolean verifyAndValidateCertificate(
         }
         return b;
     }
-
-    /**
-     * {@inheritDoc}
-     */
-    public void setRtcpmux(boolean rtcpmux)
-    {
-        if (this.rtcpmux != rtcpmux)
-        {
-            this.rtcpmux = rtcpmux;
-            DtlsTransformEngine transformEngine = this.transformEngine;
-
-            if (transformEngine != null)
-                transformEngine.setRtcpmux(rtcpmux);
-        }
-    }
-
-    /**
-     * {@inheritDoc}
-     */
-    @Override
-    public void registerUser(Object user)
-    {
-        synchronized (users)
-        {
-            users.add(user);
-        }
-    }
-
 }
diff --git a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsPacketTransformer.java b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsPacketTransformer.java
index 9d7ab0c5..ed9cf9e2 100644
--- a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsPacketTransformer.java
+++ b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsPacketTransformer.java
@@ -14,6 +14,8 @@
 import org.jitsi.impl.neomedia.*;
 import org.jitsi.impl.neomedia.transform.*;
 import org.jitsi.impl.neomedia.transform.srtp.*;
+import org.jitsi.service.configuration.*;
+import org.jitsi.service.libjitsi.*;
 import org.jitsi.service.neomedia.*;
 import org.jitsi.util.*;
 
@@ -26,6 +28,8 @@
 public class DtlsPacketTransformer
     extends SinglePacketTransformer
 {
+    private static final long CONNECT_RETRY_INTERVAL = 500;
+
     /**
      * The maximum number of times that
      * {@link #runInConnectThread(DTLSProtocol, TlsPeer, DatagramTransport)} is
@@ -36,7 +40,23 @@ public class DtlsPacketTransformer
      */
     private static final int CONNECT_TRIES = 3;
 
-    private static final long CONNECT_RETRY_INTERVAL = 500;
+    /**
+     * The indicator which determines whether unencrypted packets sent or
+     * received through <tt>DtlsPacketTransformer</tt> are to be dropped. The
+     * default value is <tt>false</tt>.
+     *
+     * @see #DROP_UNENCRYPTED_PKTS_PNAME
+     */
+    private static final boolean DROP_UNENCRYPTED_PKTS;
+
+    /**
+     * The name of the <tt>ConfigurationService</tt> and/or <tt>System</tt>
+     * property which indicates whether unencrypted packets sent or received
+     * through <tt>DtlsPacketTransformer</tt> are to be dropped. The default
+     * value is <tt>false</tt>.
+     */
+    private static final String DROP_UNENCRYPTED_PKTS_PNAME
+        = DtlsPacketTransformer.class.getName() + ".dropUnencryptedPkts";
 
     /**
      * The length of the header of a DTLS record.
@@ -56,6 +76,28 @@ public class DtlsPacketTransformer
     private static final Logger logger
         = Logger.getLogger(DtlsPacketTransformer.class);
 
+    static
+    {
+        ConfigurationService cfg = LibJitsi.getConfigurationService();
+        boolean dropUnencryptedPkts = false;
+
+        if (cfg == null)
+        {
+            String s = System.getProperty(DROP_UNENCRYPTED_PKTS_PNAME);
+
+            if (s != null)
+                dropUnencryptedPkts = Boolean.parseBoolean(s);
+        }
+        else
+        {
+            dropUnencryptedPkts
+                = cfg.getBoolean(
+                        DROP_UNENCRYPTED_PKTS_PNAME,
+                        dropUnencryptedPkts);
+        }
+        DROP_UNENCRYPTED_PKTS = dropUnencryptedPkts;
+    }
+
     /**
      * Determines whether a specific array of <tt>byte</tt>s appears to contain
      * a DTLS record.
@@ -123,14 +165,14 @@ public static boolean isDtlsRecord(byte[] buf, int off, int len)
     private final int componentID;
 
     /**
-     * The background <tt>Thread</tt> which initializes {@link #dtlsTransport}.
+     * The <tt>RTPConnector</tt> which uses this <tt>PacketTransformer</tt>.
      */
-    private Thread connectThread;
+    private AbstractRTPConnector connector;
 
     /**
-     * The <tt>RTPConnector</tt> which uses this <tt>PacketTransformer</tt>.
+     * The background <tt>Thread</tt> which initializes {@link #dtlsTransport}.
      */
-    private AbstractRTPConnector connector;
+    private Thread connectThread;
 
     /**
      * The <tt>DatagramTransport</tt> implementation which adapts
@@ -152,9 +194,13 @@ public static boolean isDtlsRecord(byte[] buf, int off, int len)
     private MediaType mediaType;
 
     /**
-     * The <tt>SRTPTransformer</tt> to be used by this instance.
+     * Whether rtcp-mux is in use.
+     *
+     * If enabled, and this is the transformer for RTCP, it will not establish
+     * a DTLS session on its own, but rather wait for the RTP transformer to
+     * do so, and reuse it to initialize the SRTP transformer.
      */
-    private SinglePacketTransformer srtpTransformer;
+    private boolean rtcpmux = false;
 
     /**
      * The value of the <tt>setup</tt> SDP attribute defined by RFC 4145
@@ -164,6 +210,11 @@ public static boolean isDtlsRecord(byte[] buf, int off, int len)
      */
     private DtlsControl.Setup setup;
 
+    /**
+     * The <tt>SRTPTransformer</tt> to be used by this instance.
+     */
+    private SinglePacketTransformer srtpTransformer;
+
     /**
      * The indicator which determines whether the <tt>TlsPeer</tt> employed by
      * this <tt>PacketTransformer</tt> has raised an
@@ -177,15 +228,6 @@ public static boolean isDtlsRecord(byte[] buf, int off, int len)
      */
     private final DtlsTransformEngine transformEngine;
 
-    /**
-     * Whether rtcp-mux is in use.
-     *
-     * If enabled, and this is the transformer for RTCP, it will not establish
-     * a DTLS session on its own, but rather wait for the RTP transformer to
-     * do so, and reuse it to initialize the SRTP transformer.
-     */
-    private boolean rtcpmux = false;
-
     /**
      * Initializes a new <tt>DtlsPacketTransformer</tt> instance.
      *
@@ -205,6 +247,7 @@ public DtlsPacketTransformer(
     /**
      * {@inheritDoc}
      */
+    @Override
     public synchronized void close()
     {
         /*
@@ -375,6 +418,41 @@ private boolean handleRunInConnectThreadException(
         return false;
     }
 
+    /**
+     * Tries to initialize {@link #srtpTransformer} by using the
+     * <tt>DtlsPacketTransformer</tt> for RTP.
+     *
+     * @return the (possibly updated) value of {@link #srtpTransformer}.
+     */
+    private SinglePacketTransformer initializeSRTCPTransformerFromRtp()
+    {
+        if (srtpTransformer != null)
+            return srtpTransformer; //already initialized
+
+        DtlsPacketTransformer rtpDtlsPacketTransformer
+            = (DtlsPacketTransformer) getTransformEngine().getRTPTransformer();
+
+        PacketTransformer rtpSrtpTransformer
+            = rtpDtlsPacketTransformer.srtpTransformer;
+
+        if (rtpSrtpTransformer != null
+                && rtpSrtpTransformer instanceof SRTPTransformer)
+        {
+            synchronized (this)
+            {
+                if (srtpTransformer == null) //previous check was not synchronized
+                {
+                    DtlsPacketTransformer.this.srtpTransformer
+                        = new SRTCPTransformer(
+                            (SRTPTransformer) rtpSrtpTransformer);
+                }
+                return srtpTransformer;
+            }
+        }
+
+        return srtpTransformer;
+    }
+
     /**
      * Initializes a new <tt>SRTPTransformer</tt> instance with a specific
      * (negotiated) <tt>SRTPProtectionProfile</tt> and the keying material
@@ -579,6 +657,7 @@ void notifyAlertRaised(
     /**
      * {@inheritDoc}
      */
+    @Override
     public RawPacket reverseTransform(RawPacket pkt)
     {
         byte[] buf = pkt.getBuffer();
@@ -590,8 +669,9 @@ public RawPacket reverseTransform(RawPacket pkt)
             if (rtcpmux && Component.RTCP == componentID)
             {
                 // This should never happen.
-                logger.warn("Dropping a DTLS record, because it was received"
-                            + " on the RTCP channel while rtcpmux is in use.");
+                logger.warn(
+                        "Dropping a DTLS record, because it was received on the"
+                            + " RTCP channel while rtcpmux is in use.");
                 return null;
             }
 
@@ -693,9 +773,7 @@ else if (delta < 0)
         }
         else if (transformEngine.isSrtpDisabled())
         {
-            /**
-             * In pure DTLS mode only DTLS records pass through.
-             */
+            // In pure DTLS mode only DTLS records pass through.
             pkt = null;
         }
         else
@@ -717,6 +795,8 @@ else if (transformEngine.isSrtpDisabled())
 
             if (srtpTransformer != null)
                 pkt = srtpTransformer.reverseTransform(pkt);
+            else if (DROP_UNENCRYPTED_PKTS)
+                pkt = null;
         }
         return pkt;
     }
@@ -841,6 +921,53 @@ else if (dtlsProtocol instanceof DTLSServerProtocol)
             srtpTransformer.close();
     }
 
+    /**
+     * Sends the data contained in a specific byte array as application data
+     * through the DTLS connection of this <tt>DtlsPacketTransformer</tt>.
+     *
+     * @param buf the byte array containing data to send.
+     * @param off the offset in <tt>buf</tt> where the data begins.
+     * @param len the length of data to send.
+     */
+    public void sendApplicationData(byte[] buf, int off, int len)
+    {
+        DTLSTransport dtlsTransport = this.dtlsTransport;
+        Exception exception = null;
+
+        if (dtlsTransport != null)
+        {
+            try
+            {
+                dtlsTransport.send(buf, off, len);
+            }
+            catch (IOException ioe)
+            {
+                exception = ioe;
+            }
+        }
+        else
+        {
+            exception = new NullPointerException("dtlsTransport");
+        }
+
+        if (exception != null)
+        {
+            /*
+             * SrtpControl.start(MediaType) starts its associated
+             * TransformEngine. We will use that mediaType to signal the
+             * normal stop then as well i.e. we will ignore exception
+             * after the procedure to stop this PacketTransformer has
+             * begun.
+             */
+            if ((mediaType != null) && !tlsPeerHasRaisedCloseNotifyWarning)
+            {
+                logger.error(
+                        "Failed to send application data over DTLS transport: ",
+                        exception);
+            }
+        }
+    }
+
     /**
      * Sets the <tt>RTPConnector</tt> which is to use or uses this
      * <tt>PacketTransformer</tt>.
@@ -883,6 +1010,15 @@ synchronized void setMediaType(MediaType mediaType)
         }
     }
 
+    /**
+     * Enables/disables rtcp-mux.
+     * @param rtcpmux whether to enable or disable.
+     */
+    void setRtcpmux(boolean rtcpmux)
+    {
+        this.rtcpmux = rtcpmux;
+    }
+
     /**
      * Sets the DTLS protocol according to which this
      * <tt>DtlsPacketTransformer</tt> is to act either as a DTLS server or a
@@ -1054,6 +1190,7 @@ private synchronized void stop()
     /**
      * {@inheritDoc}
      */
+    @Override
     public RawPacket transform(RawPacket pkt)
     {
         byte[] buf = pkt.getBuffer();
@@ -1088,6 +1225,8 @@ public RawPacket transform(RawPacket pkt)
 
             if (srtpTransformer != null)
                 pkt = srtpTransformer.transform(pkt);
+            else if (DROP_UNENCRYPTED_PKTS)
+                pkt = null;
         }
         /* Pure DTLS mode */
         else
@@ -1128,95 +1267,4 @@ public RawPacket transform(RawPacket pkt)
         }
         return pkt;
     }
-
-    /**
-     * Sends the data contained in a specific byte array as application data
-     * through the DTLS connection of this <tt>DtlsPacketTransformer</tt>.
-     *
-     * @param buf the byte array containing data to send.
-     * @param off the offset in <tt>buf</tt> where the data begins.
-     * @param len the length of data to send.
-     */
-    public void sendApplicationData(byte[] buf, int off, int len)
-    {
-        DTLSTransport dtlsTransport = this.dtlsTransport;
-        Exception exception = null;
-
-        if (dtlsTransport != null)
-        {
-            try
-            {
-                dtlsTransport.send(buf, off, len);
-            }
-            catch (IOException ioe)
-            {
-                exception = ioe;
-            }
-        }
-        else
-        {
-            exception = new NullPointerException("dtlsTransport");
-        }
-
-        if (exception != null)
-        {
-            /*
-             * SrtpControl.start(MediaType) starts its associated
-             * TransformEngine. We will use that mediaType to signal the
-             * normal stop then as well i.e. we will ignore exception
-             * after the procedure to stop this PacketTransformer has
-             * begun.
-             */
-            if ((mediaType != null) && !tlsPeerHasRaisedCloseNotifyWarning)
-            {
-                logger.error(
-                        "Failed to send application data over DTLS transport: ",
-                        exception);
-            }
-        }
-    }
-
-    /**
-     * Enables/disables rtcp-mux.
-     * @param rtcpmux whether to enable or disable.
-     */
-    void setRtcpmux(boolean rtcpmux)
-    {
-        this.rtcpmux = rtcpmux;
-    }
-
-    /**
-     * Tries to initialize {@link #srtpTransformer} by using the
-     * <tt>DtlsPacketTransformer</tt> for RTP.
-     *
-     * @return the (possibly updated) value of {@link #srtpTransformer}.
-     */
-    private SinglePacketTransformer initializeSRTCPTransformerFromRtp()
-    {
-        if (srtpTransformer != null)
-            return srtpTransformer; //already initialized
-
-        DtlsPacketTransformer rtpDtlsPacketTransformer
-            = (DtlsPacketTransformer) getTransformEngine().getRTPTransformer();
-
-        PacketTransformer rtpSrtpTransformer
-            = rtpDtlsPacketTransformer.srtpTransformer;
-
-        if (rtpSrtpTransformer != null
-                && rtpSrtpTransformer instanceof SRTPTransformer)
-        {
-            synchronized (this)
-            {
-                if (srtpTransformer == null) //previous check was not synchronized
-                {
-                    DtlsPacketTransformer.this.srtpTransformer
-                        = new SRTCPTransformer(
-                            (SRTPTransformer) rtpSrtpTransformer);
-                }
-                return srtpTransformer;
-            }
-        }
-
-        return srtpTransformer;
-    }
 }
diff --git a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsTransformEngine.java b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsTransformEngine.java
index bf4af747..094c51ad 100644
--- a/src/org/jitsi/impl/neomedia/transform/dtls/DtlsTransformEngine.java
+++ b/src/org/jitsi/impl/neomedia/transform/dtls/DtlsTransformEngine.java
@@ -32,15 +32,6 @@ public class DtlsTransformEngine
      */
     private boolean disposed = false;
 
-    /**
-     * Whether rtcp-mux is in use.
-     *
-     * When enabled, the <tt>DtlsPacketTransformer</tt> will, instead of
-     * establishing a DTLS session, wait for the transformer for RTP to
-     * establish one, and reuse it to initialize its SRTP transformer.
-     */
-    private boolean rtcpmux = false;
-
     /**
      * The <tt>DtlsControl</tt> which has initialized this instance.
      */
@@ -59,6 +50,15 @@ public class DtlsTransformEngine
     private final DtlsPacketTransformer[] packetTransformers
         = new DtlsPacketTransformer[2];
 
+    /**
+     * Whether rtcp-mux is in use.
+     *
+     * When enabled, the <tt>DtlsPacketTransformer</tt> will, instead of
+     * establishing a DTLS session, wait for the transformer for RTP to
+     * establish one, and reuse it to initialize its SRTP transformer.
+     */
+    private boolean rtcpmux = false;
+
     /**
      * The value of the <tt>setup</tt> SDP attribute defined by RFC 4145
      * &quot;TCP-Based Media Transport in the Session Description Protocol
@@ -174,6 +174,16 @@ public PacketTransformer getRTPTransformer()
         return getPacketTransformer(Component.RTP);
     }
 
+    /**
+     * Indicates if SRTP extensions should be disabled which means we are
+     * currently working in pure DTLS mode.
+     * @return <tt>true</tt> if SRTP extensions should be disabled.
+     */
+    boolean isSrtpDisabled()
+    {
+        return dtlsControl.isSrtpDisabled();
+    }
+
     /**
      * Sets the <tt>RTPConnector</tt> which is to use or uses this
      * <tt>TransformEngine</tt>.
@@ -216,6 +226,24 @@ private void setMediaType(MediaType mediaType)
         }
     }
 
+    /**
+     * Enables/disables rtcp-mux.
+     * @param rtcpmux whether to enable or disable.
+     */
+    void setRtcpmux(boolean rtcpmux)
+    {
+        if (this.rtcpmux != rtcpmux)
+        {
+            this.rtcpmux = rtcpmux;
+
+            for (DtlsPacketTransformer packetTransformer : packetTransformers)
+            {
+                if (packetTransformer != null)
+                    packetTransformer.setRtcpmux(rtcpmux);
+            }
+        }
+    }
+
     /**
      * Sets the DTLS protocol according to which this
      * <tt>DtlsTransformEngine</tt> is to act either as a DTLS server or a DTLS
@@ -249,32 +277,4 @@ void start(MediaType mediaType)
     {
         setMediaType(mediaType);
     }
-
-    /**
-     * Indicates if SRTP extensions should be disabled which means we are
-     * currently working in pure DTLS mode.
-     * @return <tt>true</tt> if SRTP extensions should be disabled.
-     */
-    boolean isSrtpDisabled()
-    {
-        return dtlsControl.isSrtpDisabled();
-    }
-
-    /**
-     * Enables/disables rtcp-mux.
-     * @param rtcpmux whether to enable or disable.
-     */
-    void setRtcpmux(boolean rtcpmux)
-    {
-        if (this.rtcpmux != rtcpmux)
-        {
-            this.rtcpmux = rtcpmux;
-
-            for (DtlsPacketTransformer packetTransformer : packetTransformers)
-            {
-                if (packetTransformer != null)
-                    packetTransformer.setRtcpmux(rtcpmux);
-            }
-        }
-    }
 }
diff --git a/src/org/jitsi/impl/neomedia/transform/dtls/TlsClientImpl.java b/src/org/jitsi/impl/neomedia/transform/dtls/TlsClientImpl.java
index e03e4a90..ace9a33d 100644
--- a/src/org/jitsi/impl/neomedia/transform/dtls/TlsClientImpl.java
+++ b/src/org/jitsi/impl/neomedia/transform/dtls/TlsClientImpl.java
@@ -62,6 +62,7 @@ public TlsClientImpl(DtlsPacketTransformer packetTransformer)
     /**
      * {@inheritDoc}
      */
+    @Override
     public synchronized TlsAuthentication getAuthentication()
         throws IOException
     {
@@ -303,6 +304,7 @@ private class TlsAuthenticationImpl
         /**
          * {@inheritDoc}
          */
+        @Override
         public TlsCredentials getClientCredentials(
                 CertificateRequest certificateRequest)
             throws IOException
@@ -330,6 +332,7 @@ public TlsCredentials getClientCredentials(
         /**
          * {@inheritDoc}
          */
+        @Override
         public void notifyServerCertificate(Certificate serverCertificate)
             throws IOException
         {
-- 
GitLab