-
Lyubomir Marinov authoredLyubomir Marinov authored
ZrtpControlImpl.java 10.21 KiB
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package org.jitsi.impl.neomedia;
import gnu.java.zrtp.*;
import gnu.java.zrtp.utils.*;
import java.util.*;
import org.jitsi.impl.neomedia.transform.zrtp.*;
import org.jitsi.service.neomedia.*;
import org.jitsi.service.neomedia.event.*;
/**
* Controls zrtp in the MediaStream.
*
* @author Damian Minkov
*/
public class ZrtpControlImpl
implements ZrtpControl
{
/**
* The listener interested in security events about zrtp.
*/
private SrtpListener zrtpListener = null;
/**
* Additional info codes for and data to support ZRTP4J.
* These could be added to the library. However they are specific for this
* implementation, needing them for various GUI changes.
*/
public static enum ZRTPCustomInfoCodes
{
ZRTPNotEnabledByUser,
ZRTPDisabledByCallEnd,
ZRTPEngineInitFailure,
ZRTPEnabledByDefault
}
/**
* The zrtp engine control by this ZrtpControl.
*/
private ZRTPTransformEngine zrtpEngine = null;
/**
* This is the connector, required to send ZRTP packets
* via the DatagramSocket.
*/
private AbstractRTPConnector zrtpConnector = null;
/**
* Whether current is master session.
*/
private boolean masterSession = false;
/**
* Creates the control.
*/
ZrtpControlImpl()
{
}
/**
* Cleans up the current zrtp control and its engine.
*/
public void cleanup()
{
if(zrtpEngine != null)
{
zrtpEngine.stopZrtp();
zrtpEngine.cleanup();
}
zrtpEngine = null;
zrtpConnector = null;
}
/**
* Sets a <tt>ZrtpListener</tt> that will listen for zrtp security events.
*
* @param zrtpListener the <tt>ZrtpListener</tt> to set
*/
public void setSrtpListener(SrtpListener zrtpListener)
{
this.zrtpListener = zrtpListener;
}
/**
* Returns the <tt>ZrtpListener</tt> which listens for security events.
*
* @return the <tt>ZrtpListener</tt> which listens for security events
*/
public SrtpListener getSrtpListener()
{
return this.zrtpListener;
}
/**
* Method for getting the default secure status value for communication
*
* @return the default enabled/disabled status value for secure
* communication
*/
public boolean getSecureCommunicationStatus()
{
return
(zrtpEngine != null) && zrtpEngine.getSecureCommunicationStatus();
}
/**
* Sets the SAS verification
*
* @param verified the new SAS verification status
*/
public void setSASVerification(boolean verified)
{
ZRTPTransformEngine engine = getTransformEngine();
if (verified)
engine.SASVerified();
else
engine.resetSASVerified();
}
/**
* Returns the zrtp engine currently used by this stream.
* @return the zrtp engine
*/
public ZRTPTransformEngine getTransformEngine()
{
if(zrtpEngine == null)
{
zrtpEngine = new ZRTPTransformEngine();
// NOTE: set paranoid mode before initializing
// zrtpEngine.setParanoidMode(paranoidMode);
zrtpEngine.initialize(
"GNUZRTP4J.zid",
false,
ZrtpConfigureUtils.getZrtpConfiguration());
zrtpEngine.setUserCallback(new SecurityEventManager(this));
}
return zrtpEngine;
}
/**
* When in multistream mode, enables the master session.
* @param masterSession whether current control, controls the master session.
*/
public void setMasterSession(boolean masterSession)
{
// by default its not master, change only if set to be master
// sometimes (jingle) streams are re-initing and
// we must reuse old value (true) event that false is submitted
if(masterSession)
this.masterSession = masterSession;
}
/**
* Starts and enables zrtp in the stream holding this control.
* @param mediaType the media type of the stream this control controls.
*/
public void start(MediaType mediaType)
{
boolean zrtpAutoStart;
// ZRTP engine initialization
ZRTPTransformEngine engine = getTransformEngine();
// Create security user callback for each peer.
SecurityEventManager securityEventManager = engine.getUserCallback();
// Decide if this will become the ZRTP Master session:
// - Statement: audio media session will be started before video
// media session
// - if no other audio session was started before then this will
// become
// ZRTP Master session
// - only the ZRTP master sessions start in "auto-sensing" mode
// to immediately catch ZRTP communication from other client
// - after the master session has completed its key negotiation
// it will start other media sessions (see SCCallback)
if (masterSession)
{
zrtpAutoStart = true;
securityEventManager.setDHSession(true);
// we know that audio is considered as master for zrtp
securityEventManager.setSessionType(
mediaType.equals(MediaType.AUDIO) ?
SecurityEventManager.AUDIO_SESSION
: SecurityEventManager.VIDEO_SESSION
);
}
else
{
// check whether video was not already started
// it may happen when using multistreams, audio has inited
// and started video
// initially engine has value enableZrtp = false
zrtpAutoStart = zrtpEngine.isEnableZrtp();
securityEventManager.setSessionType(
mediaType.equals(MediaType.AUDIO) ?
SecurityEventManager.AUDIO_SESSION
: SecurityEventManager.VIDEO_SESSION);
}
engine.setConnector(zrtpConnector);
securityEventManager.setSrtpListener(zrtpListener);
// tells the engine whether to autostart(enable)
// zrtp communication, if false it just passes packets without
// transformation
engine.setEnableZrtp(zrtpAutoStart);
engine.sendInfo(
ZrtpCodes.MessageSeverity.Info,
EnumSet.of(
ZRTPCustomInfoCodes.ZRTPEnabledByDefault));
}
/**
* Start multi-stream ZRTP sessions.
*
* After the ZRTP Master (DH) session reached secure state the SCCallback
* calls this method to start the multi-stream ZRTP sessions.
*
* enable auto-start mode (auto-sensing) to the engine.
* @param master master SRTP data
*/
public void setMultistream(SrtpControl master)
{
if(master == null || master == this)
return;
if(!(master instanceof ZrtpControlImpl))
throw new IllegalArgumentException("master is no ZRTP control");
ZRTPTransformEngine engine = getTransformEngine();
engine.setMultiStrParams(((ZrtpControlImpl) master)
.getTransformEngine().getMultiStrParams());
engine.setEnableZrtp(true);
}
/**
* Return the zrtp hello hash String.
*
* @return String the zrtp hello hash.
*/
public String getHelloHash()
{
return getTransformEngine().getHelloHash();
}
/**
* Get the ZRTP Hello Hash data - separate strings.
*
* @return String array containing the version string at offset 0, the Hello
* hash value as hex-digits at offset 1. Hello hash is available
* immediately after class instantiation. Returns <code>null</code>
* if ZRTP is not available.
*/
public String[] getHelloHashSep()
{
return getTransformEngine().getHelloHashSep();
}
/**
* Sets the <tt>RTPConnector</tt> which is to use or uses this ZRTP engine.
*
* @param connector the <tt>RTPConnector</tt> which is to use or uses this
* ZRTP engine
*/
public void setConnector(AbstractRTPConnector connector)
{
zrtpConnector = connector;
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.neomedia.ZrtpControl#getSecurityString
* ()
*/
public String getSecurityString()
{
return getTransformEngine().getUserCallback().getSecurityString();
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.neomedia.ZrtpControl#getCiperString
* ()
*/
public String getCipherString()
{
return getTransformEngine().getUserCallback().getCipherString();
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.neomedia.ZrtpControl#isSecurityVerified
* ()
*/
public boolean isSecurityVerified()
{
return getTransformEngine().getUserCallback().isSecurityVerified();
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.neomedia.ZrtpControl#getPeerZid
* ()
*/
public byte[] getPeerZid()
{
return getTransformEngine().getPeerZid();
}
/*
* (non-Javadoc)
*
* @see
* net.java.sip.communicator.service.neomedia.ZrtpControl#getPeerZidString
* ()
*/
public String getPeerZidString()
{
byte[] zid = getPeerZid();
String s = new String(ZrtpUtils.bytesToHexString(zid, zid.length));
return s;
}
/**
* Returns false, ZRTP exchanges is keys over the media path.
*
* @return false
*/
public boolean requiresSecureSignalingTransport()
{
return false;
}
/**
* Returns the timeout value that will we will wait
* and fire timeout secure event if call is not secured.
* The value is in milliseconds.
* @return the timeout value that will we will wait
* and fire timeout secure event if call is not secured.
*/
public long getTimeoutValue()
{
// this is the default value as mentioned in rfc6189
// we will later grab this setting from zrtp
return 3750;
}
}