Adds SDES for XMPP. Works with Jingle and GTalk (only for gmail web app, doesn not work on "talk" for android).

cusax-fix
Vincent Lucas 13 years ago
parent c1366b5d7f
commit a45b6e0940

@ -1019,7 +1019,7 @@ plugin.sipaccregwizz.DTMF_INBAND=Inband
plugin.sipaccregwizz.REGISTER=REGISTER
plugin.sipaccregwizz.OVERRIDE_SERVER_DEFAULT_OPTIONS=Override server default options
plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION=Enable support to encrypt calls
plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Indicate support of ZRTP in SIP data
plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE=Indicate support of ZRTP in signalling protocol
plugin.sipaccregwizz.AUTH_NAME=Authorization name
plugin.sipaccregwizz.DISPLAY_NAME=Display name
plugin.sipaccregwizz.EXISTING_ACCOUNT=Existing SIP account

@ -6,7 +6,20 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;
import ch.imvs.sdes4j.srtp.*;
import java.util.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.jingle.*;
import net.java.sip.communicator.impl.protocol.jabber.jinglesdp.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.media.*;
import net.java.sip.communicator.util.*;
import org.jitsi.impl.neomedia.transform.sdes.*;
import org.jitsi.service.neomedia.*;
import org.jivesoftware.smack.packet.*;
/**
* An implementation of the <tt>CallPeerMediaHandler</tt> abstract class for the
@ -18,6 +31,13 @@ public abstract class AbstractCallPeerMediaHandlerJabberGTalkImpl
<T extends AbstractCallPeerJabberGTalkImpl<?,?>>
extends CallPeerMediaHandler<T>
{
/**
* The <tt>Logger</tt> used by the <tt>CallPeerMediaHandlerJabberImpl</tt>
* class and its instances for logging output.
*/
private static final Logger logger
= Logger.getLogger(AbstractCallPeerMediaHandlerJabberGTalkImpl.class);
/**
* Indicates if the <tt>CallPeer</tt> will support </tt>inputevt</tt>
* extension (i.e. will be able to be remote-controlled).
@ -56,4 +76,438 @@ public void setLocalInputEvtAware(boolean enable)
{
localInputEvtAware = enable;
}
/**
* Detects and adds ZRTP available encryption method present in the
* description given in parameter.
*
* @param isInitiator True if the local call instance is the initiator of
* the call. False otherwise.
* @param description The DESCRIPTION element of the JINGLE element which
* contains the PAYLOAD-TYPE and (more important here) the ENCRYPTION.
* @param mediaType The type of media (AUDIO or VIDEO).
*/
protected void addZRTPAdvertisedEncryptions(
boolean isInitiator,
RtpDescriptionPacketExtension description,
MediaType mediaType)
{
// Conforming to XEP-0167 schema there is 0 or 1 ENCRYPTION element for
// a given DESCRIPTION.
EncryptionPacketExtension encryptionPacketExtension
= description.getFirstChildOfType(
EncryptionPacketExtension.class);
if(encryptionPacketExtension != null)
{
AccountID accountID
= getPeer().getProtocolProvider().getAccountID();
// ZRTP
ZrtpHashPacketExtension zrtpHashPacketExtension =
encryptionPacketExtension.getFirstChildOfType(
ZrtpHashPacketExtension.class);
if(zrtpHashPacketExtension != null
&& zrtpHashPacketExtension.getValue() != null
&& accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.DEFAULT_ENCRYPTION,
true)
&& getPeer().getCall().isSipZrtpAttribute())
{
addAdvertisedEncryptionMethod(SrtpControlType.ZRTP);
}
}
}
/**
* Detects and adds SDES available encryption method present in the
* description given in parameter.
*
* @param isInitiator True if the local call instance is the initiator of
* the call. False otherwise.
* @param description The DESCRIPTION element of the JINGLE element which
* contains the PAYLOAD-TYPE and (more important here) the ENCRYPTION.
* @param mediaType The type of media (AUDIO or VIDEO).
*/
protected void addSDESAdvertisedEncryptions(
boolean isInitiator,
RtpDescriptionPacketExtension description,
MediaType mediaType)
{
// Conforming to XEP-0167 schema there is 0 or 1 ENCRYPTION element for
// a given DESCRIPTION.
EncryptionPacketExtension encryptionPacketExtension
= description.getFirstChildOfType(
EncryptionPacketExtension.class);
if(encryptionPacketExtension != null)
{
AccountID accountID
= getPeer().getProtocolProvider().getAccountID();
// SDES
if(accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.SDES_ENABLED,
false)
&& accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.DEFAULT_ENCRYPTION,
true))
{
Map<MediaTypeSrtpControl, SrtpControl> srtpControls
= getSrtpControls();
MediaTypeSrtpControl key
= new MediaTypeSrtpControl(mediaType, SrtpControlType.SDES);
SrtpControl control = srtpControls.get(key);
if(control == null)
{
control
= JabberActivator.getMediaService().createSDesControl();
srtpControls.put(key, control);
}
SDesControl tmpSDesControl = (SDesControl) control;
SrtpCryptoAttribute selectedSdes = selectSdesCryptoSuite(
isInitiator,
tmpSDesControl,
encryptionPacketExtension);
if(selectedSdes != null)
{
//found an SDES answer, remove all other controls
Iterator<Map.Entry<MediaTypeSrtpControl, SrtpControl>> iter
= srtpControls.entrySet().iterator();
while (iter.hasNext())
{
Map.Entry<MediaTypeSrtpControl, SrtpControl> entry
= iter.next();
MediaTypeSrtpControl mtsc = entry.getKey();
if ((mtsc.mediaType == mediaType)
&& (mtsc.srtpControlType != SrtpControlType.SDES))
{
entry.getValue().cleanup();
iter.remove();
}
}
addAdvertisedEncryptionMethod(SrtpControlType.SDES);
}
else
{
control.cleanup();
srtpControls.remove(key);
}
}
}
// If we were initiating the encryption, and the remote peer does not
// manage it, then we must remove the unusable SDES srtpControl.
else if(isInitiator)
{
AccountID accountID
= getPeer().getProtocolProvider().getAccountID();
// SDES
if(accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.SDES_ENABLED,
false)
&& accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.DEFAULT_ENCRYPTION,
true))
{
Map<MediaTypeSrtpControl, SrtpControl> srtpControls
= getSrtpControls();
MediaTypeSrtpControl key
= new MediaTypeSrtpControl(mediaType, SrtpControlType.SDES);
SrtpControl control = srtpControls.get(key);
if(control != null)
{
control.cleanup();
srtpControls.remove(key);
}
}
}
}
/**
* Returns the selected SDES crypto suite selected.
*
* @param isInitiator True if the local call instance is the initiator of
* the call. False otherwise.
* @param sDesControl The SDES based SRTP MediaStream encryption
* control.
* @param encryptionPacketExtension The ENCRYPTION element received from the
* remote peer. This may contain the SDES crypto suites available for the
* remote peer.
*
* @return The selected SDES crypto suite supported by both the local and
* the remote peer. Or null, if there is no crypto suite supported by both
* of the peers.
*/
protected SrtpCryptoAttribute selectSdesCryptoSuite(
boolean isInitiator,
SDesControl sDesControl,
EncryptionPacketExtension encryptionPacketExtension)
{
List<CryptoPacketExtension> cryptoPacketExtensions =
encryptionPacketExtension.getCryptoList();
Vector<SrtpCryptoAttribute> peerAttributes
= new Vector<SrtpCryptoAttribute>(cryptoPacketExtensions.size());
for(int i = 0; i < cryptoPacketExtensions.size(); ++i)
{
peerAttributes.add(
cryptoPacketExtensions.get(i).toSrtpCryptoAttribute());
}
if(peerAttributes == null)
{
return null;
}
if(isInitiator)
{
return sDesControl.initiatorSelectAttribute(peerAttributes);
}
else
{
return sDesControl.responderSelectAttribute(peerAttributes);
}
}
/**
* Returns if the remote peer supports ZRTP.
*
* @param encryptionPacketExtension The ENCRYPTION element received from
* the remote peer. This may contain the ZRTP acket element for the remote
* peer.
*
* @return True if the remote peer supports ZRTP. False, otherwise.
*/
protected boolean isRemoteZrtpCapable(
EncryptionPacketExtension encryptionPacketExtension)
{
List<? extends PacketExtension> packetExtensions =
encryptionPacketExtension.getChildExtensions();
for(int i = 0; i < packetExtensions.size(); ++i)
{
if(packetExtensions.get(i) instanceof ZrtpHashPacketExtension)
{
return true;
}
}
return false;
}
/**
* Sets ZRTP element to the ENCRYPTION element of the DESCRIPTION for a
* given media.
*
* @param mediaType The type of media we are modifying the DESCRIPTION to
* integrate the ENCRYPTION element.
* @param description The element containing the media DESCRIPTION and its
* encryption.
* @param remoteDescription The element containing the media DESCRIPTION and
* its encryption for the remote peer. Null, if the local peer is the
* initiator of the call.
*
* @return True if the ZRTP element has been added to encryption. False,
* otherwise.
*/
protected boolean setZrtpEncryptionToDescription(
MediaType mediaType,
RtpDescriptionPacketExtension description,
RtpDescriptionPacketExtension remoteDescription)
{
boolean isRemoteZrtpCapable = (remoteDescription == null);
if(remoteDescription != null)
{
// Conforming to XEP-0167 schema there is 0 or 1 ENCRYPTION
// element for a given DESCRIPTION.
EncryptionPacketExtension remoteEncryption
= remoteDescription.getFirstChildOfType(
EncryptionPacketExtension.class);
if(remoteEncryption != null
&& isRemoteZrtpCapable(remoteEncryption))
{
isRemoteZrtpCapable = true;
}
}
if(getPeer().getProtocolProvider().getAccountID()
.getAccountPropertyBoolean(
ProtocolProviderFactory.DEFAULT_ENCRYPTION,
true)
&& getPeer().getCall().isSipZrtpAttribute()
&& isRemoteZrtpCapable)
{
Map<MediaTypeSrtpControl, SrtpControl> srtpControls
= getSrtpControls();
MediaTypeSrtpControl key
= new MediaTypeSrtpControl(mediaType, SrtpControlType.ZRTP);
SrtpControl control = srtpControls.get(key);
if(control == null)
{
control = JabberActivator.getMediaService().createZrtpControl();
srtpControls.put(key, control);
}
String helloHash[] = ((ZrtpControl)control).getHelloHashSep();
if(helloHash != null && helloHash[1].length() > 0)
{
ZrtpHashPacketExtension hash = new ZrtpHashPacketExtension();
hash.setVersion(helloHash[0]);
hash.setValue(helloHash[1]);
EncryptionPacketExtension encryption
= description.getFirstChildOfType(
EncryptionPacketExtension.class);
if(encryption == null)
{
encryption = new EncryptionPacketExtension();
description.addChildExtension(encryption);
}
encryption.addChildExtension(hash);
return true;
}
}
return false;
}
/**
* Sets SDES element(s) to the ENCRYPTION element of the DESCRIPTION for a
* given media.
*
* @param mediaType The type of media we are modifying the DESCRIPTION to
* integrate the ENCRYPTION element.
* @param description The element containing the media DESCRIPTION and its
* encryption.
* @param remoteDescription The element containing the media DESCRIPTION and
* its encryption for the remote peer. Null, if the local peer is the
* initiator of the call.
*
* @return True if the crypto element has been added to encryption. False,
* otherwise.
*/
protected boolean setSDesEncryptionToDescription(
MediaType mediaType,
RtpDescriptionPacketExtension localDescription,
RtpDescriptionPacketExtension remoteDescription)
{
AccountID accountID = getPeer().getProtocolProvider().getAccountID();
// check if SDES and encryption is enabled at all
if(accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.SDES_ENABLED,
false)
&& accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.DEFAULT_ENCRYPTION,
true))
{
// get or create the control
Map<MediaTypeSrtpControl, SrtpControl> srtpControls
= getSrtpControls();
MediaTypeSrtpControl key
= new MediaTypeSrtpControl(mediaType, SrtpControlType.SDES);
SrtpControl control = srtpControls.get(key);
if (control == null)
{
control = JabberActivator.getMediaService().createSDesControl();
srtpControls.put(key, control);
}
// set the enabled ciphers suites
SDesControl sdcontrol = (SDesControl) control;
String ciphers
= accountID.getAccountPropertyString(
ProtocolProviderFactory.SDES_CIPHER_SUITES);
if (ciphers == null)
{
ciphers =
JabberActivator.getResources().getSettingsString(
SDesControl.SDES_CIPHER_SUITES);
}
sdcontrol.setEnabledCiphers(Arrays.asList(ciphers.split(",")));
// act as initiator
if (remoteDescription == null)
{
EncryptionPacketExtension localEncryption
= localDescription.getFirstChildOfType(
EncryptionPacketExtension.class);
if(localEncryption == null)
{
localEncryption = new EncryptionPacketExtension();
localDescription.addChildExtension(localEncryption);
}
for(SrtpCryptoAttribute ca:
sdcontrol.getInitiatorCryptoAttributes())
{
CryptoPacketExtension crypto
= new CryptoPacketExtension(ca);
localEncryption.addChildExtension(crypto);
}
return true;
}
// act as responder
else
{
// Conforming to XEP-0167 schema there is 0 or 1 ENCRYPTION
// element for a given DESCRIPTION.
EncryptionPacketExtension remoteEncryption
= remoteDescription.getFirstChildOfType(
EncryptionPacketExtension.class);
if(remoteEncryption != null)
{
SrtpCryptoAttribute selectedSdes = selectSdesCryptoSuite(
false,
sdcontrol,
remoteEncryption);
if(selectedSdes != null)
{
EncryptionPacketExtension localEncryption
= localDescription.getFirstChildOfType(
EncryptionPacketExtension.class);
if(localEncryption == null)
{
localEncryption = new EncryptionPacketExtension();
localDescription.addChildExtension(localEncryption);
}
CryptoPacketExtension crypto
= new CryptoPacketExtension(selectedSdes);
localEncryption.addChildExtension(crypto);
return true;
}
else
{
// none of the offered suites match, destroy the sdes
// control
sdcontrol.cleanup();
srtpControls.remove(key);
logger.warn(
"Received unsupported sdes crypto attribute");
}
}
else
{
// peer doesn't offer any SDES attribute, destroy the sdes
// control
sdcontrol.cleanup();
srtpControls.remove(key);
}
}
}
return false;
}
}

@ -54,12 +54,9 @@ public class CallPeerMediaHandlerGTalkImpl
= new LinkedHashMap<String, List<PayloadTypePacketExtension> >();
/**
* The current description of the streams that the remote side has with us.
* We use {@link LinkedHashMap}s to make sure that we preserve
* the order of the individual content extensions.
* The remote DESCRIPTION.
*/
private Map<String, List<PayloadTypePacketExtension> > remoteContentMap
= new LinkedHashMap<String, List<PayloadTypePacketExtension> >();
private RtpDescriptionPacketExtension remoteDescription = null;
/**
* The <tt>TransportManager</tt> implementation handling our address
@ -125,6 +122,8 @@ public void processOffer(RtpDescriptionPacketExtension offer)
throws OperationFailedException,
IllegalArgumentException
{
this.remoteDescription = offer;
List<PayloadTypePacketExtension> payloadTypes = offer.getPayloadTypes();
boolean atLeastOneValidDescription = false;
List<PayloadTypePacketExtension> answer =
@ -149,21 +148,6 @@ else if(ext.getNamespace().equals(
}
}
EncryptionPacketExtension encryptionPacketExtension
= offer.getFirstChildOfType(EncryptionPacketExtension.class);
if(encryptionPacketExtension != null)
{
ZrtpHashPacketExtension zrtpHashPacketExtension =
encryptionPacketExtension.getFirstChildOfType(
ZrtpHashPacketExtension.class);
if(zrtpHashPacketExtension != null
&& zrtpHashPacketExtension.getValue() != null)
{
addAdvertisedEncryptionMethod(SrtpControlType.ZRTP);
}
}
for(MediaType mediaType : MediaType.values())
{
if(!(isAudio && mediaType == MediaType.AUDIO) &&
@ -172,8 +156,6 @@ else if(ext.getNamespace().equals(
continue;
}
remoteContentMap.put(mediaType.toString(), payloadTypes);
MediaDevice dev = getDefaultDevice(mediaType);
MediaDirection devDirection
@ -321,6 +303,31 @@ public RtpDescriptionPacketExtension generateSessionAccept(
}
}
// ZRTP
boolean isZRTPAddedToDescription = setZrtpEncryptionToDescription(
mediaType,
description,
remoteDescription);
if(isZRTPAddedToDescription)
{
addZRTPAdvertisedEncryptions(
false,
remoteDescription,
mediaType);
}
else
{
// SDES
addSDESAdvertisedEncryptions(
false,
remoteDescription,
mediaType);
setSDesEncryptionToDescription(
mediaType,
description,
remoteDescription);
}
initStream(mediaName, connector, dev, format, target,
direction, rtpExtensions, masterStream);
}
@ -349,21 +356,6 @@ public void processAnswer(RtpDescriptionPacketExtension answer)
{
List<PayloadTypePacketExtension> lst = answer.getPayloadTypes();
EncryptionPacketExtension encryptionPacketExtension
= answer.getFirstChildOfType(EncryptionPacketExtension.class);
if(encryptionPacketExtension != null)
{
ZrtpHashPacketExtension zrtpHashPacketExtension =
encryptionPacketExtension.getFirstChildOfType(
ZrtpHashPacketExtension.class);
if(zrtpHashPacketExtension != null
&& zrtpHashPacketExtension.getValue() != null)
{
addAdvertisedEncryptionMethod(SrtpControlType.ZRTP);
}
}
boolean masterStreamSet = true;
for(MediaType mediaType : MediaType.values())
{
@ -386,6 +378,9 @@ public void processAnswer(RtpDescriptionPacketExtension answer)
if(format == null)
continue;
addZRTPAdvertisedEncryptions(true, answer, mediaType);
addSDESAdvertisedEncryptions(true, answer, mediaType);
// stream connector
StreamConnector connector
= transportManager.getStreamConnector(mediaType);
@ -528,6 +523,23 @@ public RtpDescriptionPacketExtension createDescription()
mediaDescs.add(ext);
}
}
if(mediaType == MediaType.AUDIO || isVideo)
{
//SDES
// It is important to set SDES before ZRTP in order to make
// GTALK application able to work with SDES.
setSDesEncryptionToDescription(
mediaType,
description,
null);
//ZRTP
setZrtpEncryptionToDescription(
mediaType,
description,
null);
}
}
}

@ -6,6 +6,8 @@
*/
package net.java.sip.communicator.impl.protocol.jabber;
import ch.imvs.sdes4j.srtp.*;
import java.lang.reflect.*;
import java.util.*;
@ -346,38 +348,26 @@ public void processOffer(List<ContentPacketExtension> offer)
getDynamicPayloadTypes(),
getRtpExtensionsRegistry());
RtpDescriptionPacketExtension localDescription =
JingleUtils.getRtpDescription(ourContent);
// ZRTP
if(getPeer().getCall().isSipZrtpAttribute())
boolean isZRTPAddedToDescription = setZrtpEncryptionToDescription(
mediaType,
localDescription,
description);
if(isZRTPAddedToDescription)
{
Map<MediaTypeSrtpControl, SrtpControl> srtpControls
= getSrtpControls();
MediaTypeSrtpControl key
= new MediaTypeSrtpControl(mediaType, SrtpControlType.ZRTP);
SrtpControl control = srtpControls.get(key);
if(control == null)
{
control
= JabberActivator.getMediaService().createZrtpControl();
srtpControls.put(key, control);
}
String helloHash[] = ((ZrtpControl)control).getHelloHashSep();
if(helloHash != null && helloHash[1].length() > 0)
{
EncryptionPacketExtension encryption = new
EncryptionPacketExtension();
ZrtpHashPacketExtension hash
= new ZrtpHashPacketExtension();
hash.setVersion(helloHash[0]);
hash.setValue(helloHash[1]);
encryption.addChildExtension(hash);
RtpDescriptionPacketExtension rtpDescription =
JingleUtils.getRtpDescription(ourContent);
rtpDescription.setEncryption(encryption);
}
addZRTPAdvertisedEncryptions(false, description, mediaType);
}
else
{
// SDES
addSDESAdvertisedEncryptions(false, description, mediaType);
setSDesEncryptionToDescription(
mediaType,
localDescription,
description);
}
// got an content which have inputevt, it means that peer requests
@ -392,22 +382,6 @@ public void processOffer(List<ContentPacketExtension> offer)
localContentMap.put(content.getName(), ourContent);
atLeastOneValidDescription = true;
EncryptionPacketExtension encryptionPacketExtension
= description.getFirstChildOfType(
EncryptionPacketExtension.class);
if(encryptionPacketExtension != null)
{
ZrtpHashPacketExtension zrtpHashPacketExtension =
encryptionPacketExtension.getFirstChildOfType(
ZrtpHashPacketExtension.class);
if(zrtpHashPacketExtension != null
&& zrtpHashPacketExtension.getValue() != null)
{
addAdvertisedEncryptionMethod(SrtpControlType.ZRTP);
}
}
}
if (!atLeastOneValidDescription)
@ -627,42 +601,22 @@ private ContentPacketExtension createContent(MediaDevice dev)
receiveQualityPreset), direction,
dev.getSupportedExtensions());
//ZRTP
if(getPeer().getCall().isSipZrtpAttribute())
{
Map<MediaTypeSrtpControl, SrtpControl> srtpControls
= getSrtpControls();
MediaTypeSrtpControl key
= new MediaTypeSrtpControl(
dev.getMediaType(),
SrtpControlType.ZRTP);
SrtpControl control = srtpControls.get(key);
if(control == null)
{
control
= JabberActivator.getMediaService().createZrtpControl();
srtpControls.put(key, control);
}
String helloHash[] = ((ZrtpControl)control).getHelloHashSep();
RtpDescriptionPacketExtension description =
JingleUtils.getRtpDescription(content);
if(helloHash != null && helloHash[1].length() > 0)
{
EncryptionPacketExtension encryption = new
EncryptionPacketExtension();
ZrtpHashPacketExtension hash
= new ZrtpHashPacketExtension();
//SDES
// It is important to set SDES before ZRTP in order to make GTALK
// application able to work with SDES.
setSDesEncryptionToDescription(
dev.getMediaType(),
description,
null);
hash.setVersion(helloHash[0]);
hash.setValue(helloHash[1]);
encryption.addChildExtension(hash);
RtpDescriptionPacketExtension description =
JingleUtils.getRtpDescription(content);
description.setEncryption(encryption);
}
}
//ZRTP
setZrtpEncryptionToDescription(
dev.getMediaType(),
description,
null);
return content;
}
@ -790,49 +744,26 @@ public List<ContentPacketExtension> createContentList()
direction,
dev.getSupportedExtensions());
//ZRTP
if(getPeer().getCall().isSipZrtpAttribute())
{
Map<MediaTypeSrtpControl, SrtpControl> srtpControls
= getSrtpControls();
MediaTypeSrtpControl key
= new MediaTypeSrtpControl(
mediaType,
SrtpControlType.ZRTP);
SrtpControl control = srtpControls.get(key);
if(control == null)
{
control
= JabberActivator.getMediaService()
.createZrtpControl();
srtpControls.put(key, control);
}
RtpDescriptionPacketExtension description =
JingleUtils.getRtpDescription(content);
String helloHash[] =
((ZrtpControl) control).getHelloHashSep();
//SDES
// It is important to set SDES before ZRTP in order to make
// GTALK application able to work with SDES.
setSDesEncryptionToDescription(
mediaType,
description,
null);
if(helloHash != null && helloHash[1].length() > 0)
{
EncryptionPacketExtension encryption = new
EncryptionPacketExtension();
ZrtpHashPacketExtension hash
= new ZrtpHashPacketExtension();
hash.setVersion(helloHash[0]);
hash.setValue(helloHash[1]);
encryption.addChildExtension(hash);
RtpDescriptionPacketExtension description =
JingleUtils.getRtpDescription(content);
description.setEncryption(encryption);
}
}
//ZRTP
setZrtpEncryptionToDescription(
mediaType,
description,
null);
/* we request a desktop sharing session so add the inputevt
* extension in the "video" content
*/
RtpDescriptionPacketExtension description
= JingleUtils.getRtpDescription(content);
if(description.getMedia().equals(MediaType.VIDEO.toString())
&& getLocalInputEvtAware())
{
@ -1105,6 +1036,9 @@ private void processContent(ContentPacketExtension content, boolean modify,
OperationFailedException.ILLEGAL_ARGUMENT, null, logger);
}
addZRTPAdvertisedEncryptions(true, description, mediaType);
addSDESAdvertisedEncryptions(true, description, mediaType);
StreamConnector connector
= transportManager.getStreamConnector(mediaType);
@ -1175,21 +1109,6 @@ private void processContent(ContentPacketExtension content, boolean modify,
}
}
EncryptionPacketExtension encryptionPacketExtension
= description.getFirstChildOfType(EncryptionPacketExtension.class);
if(encryptionPacketExtension != null)
{
ZrtpHashPacketExtension zrtpHashPacketExtension =
encryptionPacketExtension.getFirstChildOfType(
ZrtpHashPacketExtension.class);
if(zrtpHashPacketExtension != null
&& zrtpHashPacketExtension.getValue() != null)
{
addAdvertisedEncryptionMethod(SrtpControlType.ZRTP);
}
}
// create the corresponding stream...
initStream(content.getName(), connector, dev,
supportedFormats.get(0), target, direction, rtpExtensions,

@ -38,6 +38,7 @@ public class OperationSetBasicTelephonyJabberImpl
implements RegistrationStateChangeListener,
PacketListener,
PacketFilter,
OperationSetSecureSDesTelephony,
OperationSetSecureZrtpTelephony,
OperationSetAdvancedTelephony<ProtocolProviderServiceJabberImpl>
{
@ -401,8 +402,8 @@ else if(priority == bestPriority && jabberStatus != null)
}
}
}
else if (protocolProvider.isGTalkTesting() /* test GTALK property */
/* see if peer supports Google Talk voice */
else if (protocolProvider.isGTalkTesting() // test GTALK property
// see if peer supports Google Talk voice
&& (hasGtalkCaps || alwaysCallGtalk))
{
if(priority > bestPriority)

@ -1710,6 +1710,9 @@ protected void initialize(String screenname,
addSupportedOperationSet(
OperationSetSecureZrtpTelephony.class,
basicTelephony);
addSupportedOperationSet(
OperationSetSecureSDesTelephony.class,
basicTelephony);
// initialize video telephony OperationSet
addSupportedOperationSet(

@ -6,6 +6,8 @@
*/
package net.java.sip.communicator.impl.protocol.jabber.extensions.jingle;
import ch.imvs.sdes4j.srtp.*;
import net.java.sip.communicator.impl.protocol.jabber.extensions.*;
/**
@ -13,10 +15,23 @@
* used during a jingle session.
*
* @author Emil Ivov
* @author Vincent Lucas
*/
public class CryptoPacketExtension
extends AbstractPacketExtension
{
/**
* The name of the "crypto" element.
*/
public static final String ELEMENT_NAME = "crypto";
/**
* The namespace for the "crypto" element.
* It it set to "not null" only for Gtalk SDES support (may be set to null
* once gtalk supports jingle).
*/
public static final String NAMESPACE = "urn:xmpp:jingle:apps:rtp:1";
/**
* The name of the 'crypto-suite' argument.
*/
@ -43,7 +58,67 @@ public class CryptoPacketExtension
*/
public CryptoPacketExtension()
{
super(null, "crypto");
super(NAMESPACE, ELEMENT_NAME);
}
/**
* Creates a new {@link CryptoPacketExtension} instance with the proper
* element name and namespace and initialises it with the parameters
* contained by the cryptoAttribute.
*
* @param cryptoAttribute The cryptoAttribute containing the crypto-suite,
* key-params, session-params and key information.
*/
public CryptoPacketExtension(SrtpCryptoAttribute cryptoAttribute)
{
this();
initialize(cryptoAttribute);
}
/**
* Initialises it with the parameters contained by the cryptoAttribute.
*
* @param cryptoAttribute The cryptoAttribute containing the crypto-suite,
* key-params, session-params and key information.
*/
private void initialize(SrtpCryptoAttribute cryptoAttribute)
{
// Encode the tag element.
this.setTag(Integer.toString(cryptoAttribute.getTag()));
// Encode the crypto-suite element.
this.setCryptoSuite(cryptoAttribute.getCryptoSuite().encode());
// Encode the key-params element.
StringBuffer keyParamsString = new StringBuffer();
SrtpKeyParam[] keyParams = cryptoAttribute.getKeyParams();
for(int i = 0; i < keyParams.length; ++i)
{
keyParamsString.append(keyParams[i].encode());
if (i < keyParams.length - 1)
{
keyParamsString.append(';');
}
}
this.setKeyParams(keyParamsString.toString());
// Encode the session-params element (optional).
SrtpSessionParam[] sessionParams = cryptoAttribute.getSessionParams();
if (sessionParams != null)
{
StringBuffer sessionParamsString = new StringBuffer();
for(int i = 0; i < sessionParams.length; ++i)
{
sessionParamsString.append(
sessionParams[i].encode());
if (i < sessionParams.length - 1)
{
sessionParamsString.append(' ');
}
}
this.setSessionParams(sessionParamsString.toString());
}
}
/**
@ -69,6 +144,23 @@ public String getCryptoSuite()
return getAttributeAsString(CRYPTO_SUITE_ATTR_NAME);
}
/**
* Returns if the current crypto suite equals the one given in parameter.
*
* @param cryptoSuite a <tt>String</tt> that describes the encryption and
* authentication algorithms.
*
* @return True if the current crypto suite equals the one given in
* parameter. False, otherwise.
*/
public boolean equalsCryptoSuite(String cryptoSuite)
{
String currentCryptoSuite = this.getCryptoSuite();
return CryptoPacketExtension.equalsStrings(
currentCryptoSuite,
cryptoSuite);
}
/**
* Sets the value of the <tt>key-params</tt> attribute that provides one or
* more sets of keying material for the crypto-suite in question).
@ -87,11 +179,28 @@ public void setKeyParams(String keyParams)
* @return a <tt>String</tt> that provides one or more sets of keying
* material for the crypto-suite in question).
*/
public String getKeyPaams()
public String getKeyParams()
{
return getAttributeAsString(KEY_PARAMS_ATTR_NAME);
}
/**
* Returns if the current key params equals the one given in parameter.
*
* @param keyParams a <tt>String</tt> that provides one or more sets of
* keying material for the crypto-suite in question.
*
* @return True if the current key params equals the one given in
* parameter. False, otherwise.
*/
public boolean equalsKeyParams(String keyParams)
{
String currentKeyParams = this.getKeyParams();
return CryptoPacketExtension.equalsStrings(
currentKeyParams,
keyParams);
}
/**
* Sets the value of the <tt>session-params</tt> attribute that provides
* transport-specific parameters for SRTP negotiation.
@ -110,11 +219,28 @@ public void setSessionParams(String sessionParams)
* @return a <tt>String</tt> that provides transport-specific parameters
* for SRTP negotiation.
*/
public String getSessionPaams()
public String getSessionParams()
{
return getAttributeAsString(SESSION_PARAMS_ATTR_NAME);
}
/**
* Returns if the current session params equals the one given in parameter.
*
* @param sessionParams a <tt>String</tt> that provides transport-specific
* parameters for SRTP negotiation.
*
* @return True if the current session params equals the one given in
* parameter. False, otherwise.
*/
public boolean equalsSessionParams(String sessionParams)
{
String currentSessionParams = this.getSessionParams();
return CryptoPacketExtension.equalsStrings(
currentSessionParams,
sessionParams);
}
/**
* Sets the value of the <tt>tag</tt> attribute: a decimal number used as
* an identifier for a particular crypto element.
@ -137,4 +263,110 @@ public String getTag()
{
return getAttributeAsString(TAG_ATTR_NAME);
}
/**
* Returns if the current tag equals the one given in parameter.
*
* @param tag a <tt>String</tt> containing a decimal number used as an
* identifier for a particular crypto element.
*
* @return True if the current tag equals the one given in parameter. False,
* otherwise.
*/
public boolean equalsTag(String tag)
{
String currentTag = this.getTag();
return CryptoPacketExtension.equalsStrings(
currentTag,
tag);
}
/**
* Returns a SrtpCryptoAttribute corresponding to this
* CryptoPAcketExtension.
*
* @return A SrtpCryptoAttribute corresponding to this
* CryptoPAcketExtension.
*/
public SrtpCryptoAttribute toSrtpCryptoAttribute()
{
// Decode the tag element.
int tag = Integer.parseInt(this.getTag());
// Decode the crypto-suite element.
SrtpCryptoSuite cryptoSuite
= new SrtpCryptoSuite(this.getCryptoSuite());
// Decode the key-params element.
String[] stringKeyParams = this.getKeyParams().split(";");
SrtpKeyParam[] keyParams = new SrtpKeyParam[stringKeyParams.length];
for(int i = 0; i < stringKeyParams.length; ++i)
{
keyParams[i] = new SrtpKeyParam(stringKeyParams[i]);
}
// Decode the session-params element (optional).
String tmpStringSessionParams = this.getSessionParams();
SrtpSessionParam[] sessionParams = null;
if(tmpStringSessionParams != null)
{
String[] stringSessionParams = tmpStringSessionParams.split(" ");
sessionParams = new SrtpSessionParam[stringSessionParams.length];
for(int i = 0; i < stringSessionParams.length; ++i)
{
sessionParams[i]
= SrtpSessionParam.create(stringSessionParams[i]);
}
}
// Creaates the new SrtpCryptoAttribute.
return new SrtpCryptoAttribute(
tag,
cryptoSuite,
keyParams,
sessionParams);
}
/**
* Returns if the first String equals the second one.
*
* @param string1 A String to be compared with the second one.
* @param string2 A String to be compared with the fisrt one.
*
* @return True if both strings are null, or if they represent the same
* sequane of characters. False, otherwise.
*/
private static boolean equalsStrings(String string1, String string2)
{
return (
((string1 == null) && (string2 == null))
|| string1.equals(string2)
);
}
/**
* Returns if the current CryptoPacketExtension equals the one given in
* parameter.
*
* @param obj an object which might be an instance of CryptoPacketExtension.
*
* @return True if the object in parameter is a CryptoPAcketExtension with
* all fields (crypto-suite, key-params, session-params and tag)
* corresponding to the current one. False, otherwsise.
*/
public boolean equals(Object obj)
{
if(obj instanceof CryptoPacketExtension)
{
CryptoPacketExtension crypto = (CryptoPacketExtension) obj;
return (
crypto.equalsCryptoSuite(this.getCryptoSuite())
&& crypto.equalsKeyParams(this.getKeyParams())
&& crypto.equalsSessionParams(this.getSessionParams())
&& crypto.equalsTag(this.getTag())
);
}
return false;
}
}

@ -23,8 +23,10 @@ public class EncryptionPacketExtension
{
/**
* The namespace of the "encryption" element.
* It it set to "not null" only for Gtalk SDES support (may be set to null
* once gtalk supports jingle).
*/
public static final String NAMESPACE = null;
public static final String NAMESPACE = "urn:xmpp:jingle:apps:rtp:1";
/**
* The name of the "encryption" element.
@ -58,7 +60,10 @@ public EncryptionPacketExtension()
*/
public void addCrypto(CryptoPacketExtension crypto)
{
cryptoList.add(crypto);
if(!cryptoList.contains(crypto))
{
cryptoList.add(crypto);
}
}
/**
@ -111,8 +116,27 @@ public List<? extends PacketExtension> getChildExtensions()
{
List<PacketExtension> ret = new ArrayList<PacketExtension>();
ret.addAll(getCryptoList());
ret.addAll(super.getChildExtensions());
return ret;
}
/**
* Adds the specified <tt>childExtension</tt> to the list of extensions
* registered with this packet.
* <p/>
* Overriding extensions may need to override this method if they would like
* to have anything more elaborate than just a list of extensions (e.g.
* casting separate instances to more specific.
*
* @param childExtension the extension we'd like to add here.
*/
public void addChildExtension(PacketExtension childExtension)
{
super.addChildExtension(childExtension);
if(childExtension instanceof CryptoPacketExtension)
{
this.addCrypto(((CryptoPacketExtension) childExtension));
}
}
}

@ -72,6 +72,13 @@ public JingleIQProvider()
new DefaultPacketExtensionProvider
<ZrtpHashPacketExtension>(ZrtpHashPacketExtension.class));
//<crypto/> provider
providerManager.addExtensionProvider(
CryptoPacketExtension.ELEMENT_NAME,
RtpDescriptionPacketExtension.NAMESPACE,
new DefaultPacketExtensionProvider
<CryptoPacketExtension>(CryptoPacketExtension.class));
//ice-udp transport
providerManager.addExtensionProvider(
IceUdpTransportPacketExtension.ELEMENT_NAME,

@ -4,7 +4,8 @@ Bundle-Description: An Jabber implementation of the Protocol Provider Service.
Bundle-Vendor: jitsi.org
Bundle-Version: 0.0.1
System-Bundle: yes
Import-Package: javax.net,
Import-Package: ch.imvs.sdes4j.srtp,
javax.net,
javax.net.ssl,
javax.security.auth.callback,
javax.security.sasl,

@ -6,6 +6,8 @@
*/
package net.java.sip.communicator.impl.protocol.sip;
import ch.imvs.sdes4j.srtp.*;
import java.net.*;
import java.util.*;
@ -586,8 +588,10 @@ private Vector<MediaDescription> createMediaDescriptionsForAnswer(
mutuallySupportedFormats, connector,
direction, rtpExtensions);
if(!updateMediaDescriptionForSDes(mediaType, md, mediaDescription))
updateMediaDescriptionForZrtp(mediaType, md);
if(!updateMediaDescriptionForZrtp(mediaType, md))
{
updateMediaDescriptionForSDes(mediaType, md, mediaDescription);
}
// create the corresponding stream...
MediaFormat fmt = findMediaFormat(remoteFormats,
@ -640,8 +644,10 @@ private Vector<MediaDescription> createMediaDescriptionsForAnswer(
*
* @param mediaType the media type.
* @param md the description to be updated.
*
* @return True if ZRTP is added tp the media description. False, otherwise.
*/
private void updateMediaDescriptionForZrtp(
private boolean updateMediaDescriptionForZrtp(
MediaType mediaType, MediaDescription md)
{
MediaAwareCallPeer<?, ?, ?> peer = getPeer();
@ -670,13 +676,17 @@ private void updateMediaDescriptionForZrtp(
String helloHash = zcontrol.getHelloHash();
if(helloHash != null && helloHash.length() > 0)
{
md.setAttribute(SdpUtils.ZRTP_HASH_ATTR, helloHash);
return true;
}
}
catch (SdpException ex)
{
logger.error("Cannot add zrtp-hash to sdp", ex);
}
}
return false;
}
/**
@ -685,6 +695,8 @@ private void updateMediaDescriptionForZrtp(
* @param mediaType the media type.
* @param localMd the description of the local peer.
* @param remoteMd the description of the remote peer.
*
* @return True if SDES is added tp the media description. False, otherwise.
*/
private boolean updateMediaDescriptionForSDes(
MediaType mediaType,
@ -736,64 +748,37 @@ private boolean updateMediaDescriptionForSDes(
@SuppressWarnings("unchecked")
Vector<Attribute> atts = localMd.getAttributes(true);
for (String ca : sdcontrol.getInitiatorCryptoAttributes())
atts.add(SdpUtils.createAttribute("crypto", ca));
for(SrtpCryptoAttribute ca:
sdcontrol.getInitiatorCryptoAttributes())
atts.add(SdpUtils.createAttribute("crypto", ca.encode()));
return true;
}
// act as responder
else
{
@SuppressWarnings("unchecked")
Vector<Attribute> atts = remoteMd.getAttributes(true);
List<String> peerAttributes = new LinkedList<String>();
SrtpCryptoAttribute localAttr
= selectSdesCryptoSuite(false, sdcontrol, remoteMd);
for (Attribute a : atts)
if (localAttr != null)
{
try
{
if (a.getName().equals("crypto"))
peerAttributes.add(a.getValue());
}
catch (SdpParseException e)
{
logger.error("received an uparsable sdp attribute", e);
}
}
if (peerAttributes.size() > 0)
{
String localAttr
= sdcontrol.responderSelectAttribute(peerAttributes);
if (localAttr != null)
{
try
{
localMd.setAttribute("crypto", localAttr);
return true;
}
catch (SdpException e)
{
logger.error("unable to add crypto to answer", e);
}
localMd.setAttribute("crypto", localAttr.encode());
return true;
}
else
catch (SdpException e)
{
// none of the offered suites match, destroy the sdes
// control
sdcontrol.cleanup();
srtpControls.remove(key);
logger.warn(
"Received unsupported sdes crypto attribute "
+ peerAttributes);
logger.error("unable to add crypto to answer", e);
}
}
else
{
// peer doesn't offer any SDES attribute, destroy the sdes
// none of the offered suites match, destroy the sdes
// control
sdcontrol.cleanup();
srtpControls.remove(key);
logger.warn("Received unsupported sdes crypto attribute.");
}
return false;
}
@ -874,8 +859,6 @@ private synchronized void processAnswer(SessionDescription answer)
this.setCallInfoURL(SdpUtils.getCallInfoURL(answer));
boolean masterStreamSet = false;
boolean hasZrtp = false;
boolean hasSdes = false;
List<MediaType> seenMediaTypes = new ArrayList<MediaType>();
for (MediaDescription mediaDescription : remoteDescriptions)
{
@ -979,33 +962,14 @@ private synchronized void processAnswer(SessionDescription answer)
if(scontrol != null)
{
List<String> peerAttributes = new LinkedList<String>();
@SuppressWarnings("unchecked")
Vector<Attribute> attrs = mediaDescription.getAttributes(true);
for (Attribute a : attrs)
{
try
{
if (a.getName().equals("crypto"))
{
peerAttributes.add(a.getValue());
}
}
catch (SdpParseException e)
{
logger.error("received an unparsable sdp attribute", e);
}
}
if(!((SDesControl) scontrol).initiatorSelectAttribute(
peerAttributes))
if(selectSdesCryptoSuite(
true,
(SDesControl) scontrol,
mediaDescription) == null)
{
scontrol.cleanup();
srtpControls.remove(key);
if(peerAttributes.size() > 0)
logger
.warn("Received unsupported sdes crypto attribute: "
+ peerAttributes);
logger.warn("Received unsupported sdes crypto attribute.");
}
else
{
@ -1028,7 +992,7 @@ private synchronized void processAnswer(SessionDescription answer)
}
}
hasSdes = true;
addAdvertisedEncryptionMethod(SrtpControlType.SDES);
}
}
@ -1053,8 +1017,11 @@ private synchronized void processAnswer(SessionDescription answer)
try
{
hasZrtp = mediaDescription.getAttribute(
SdpUtils.ZRTP_HASH_ATTR) != null;
if(mediaDescription.getAttribute(SdpUtils.ZRTP_HASH_ATTR)
!= null)
{
addAdvertisedEncryptionMethod(SrtpControlType.ZRTP);
}
}
catch (SdpParseException e)
{
@ -1065,11 +1032,6 @@ private synchronized void processAnswer(SessionDescription answer)
initStream(connector, dev, supportedFormats.get(0), target,
direction, rtpExtensions, masterStream);
}
if(hasSdes)
addAdvertisedEncryptionMethod(SrtpControlType.SDES);
if(hasZrtp)
addAdvertisedEncryptionMethod(SrtpControlType.ZRTP);
}
/**
@ -1239,4 +1201,56 @@ public void setSupportQualityControls(boolean value)
{
this.supportQualityControls = value;
}
/**
* Returns the selected crypto suite selected.
*
* @param isInitiator True if the local call instance is the initiator of
* the call. False otherwise.
* @param sDesControl The SDES based SRTP MediaStream encryption control.
* @param encryptionPacketExtension The ENCRYPTION element received from the
* remote peer. This contains the SDES crypto suites available for the
* remote peer.
*
* @return The selected SDES crypto suite supported by both the local and
* the remote peer. Or null, if there is no crypto suite supported by both
* of the peers.
*/
protected SrtpCryptoAttribute selectSdesCryptoSuite(
boolean isInitiator,
SDesControl sDesControl,
MediaDescription mediaDescription)
{
@SuppressWarnings("unchecked")
Vector<Attribute> attrs = mediaDescription.getAttributes(true);
Vector<SrtpCryptoAttribute> peerAttributes
= new Vector<SrtpCryptoAttribute>(attrs.size());
Attribute a;
for(int i = 0; i < attrs.size(); ++i)
{
try
{
a = attrs.get(i);
if (a.getName().equals("crypto"))
{
peerAttributes.add(
SrtpCryptoAttribute.create(a.getValue()));
}
}
catch (SdpParseException e)
{
logger.error("received an unparsable sdp attribute", e);
}
}
if(isInitiator)
{
return sDesControl.initiatorSelectAttribute(peerAttributes);
}
else
{
return sDesControl.responderSelectAttribute(peerAttributes);
}
}
}

@ -4,7 +4,8 @@ Bundle-Description: A bundle that implements the Protocol Provider package over
Bundle-Vendor: jitsi.org
Bundle-Version: 0.0.1
System-Bundle: yes
Import-Package: javax.net,
Import-Package: ch.imvs.sdes4j.srtp,
javax.net,
javax.net.ssl,
javax.security.auth.x500,
javax.xml.datatype,

@ -8,6 +8,7 @@
import java.util.*;
import net.java.sip.communicator.plugin.sipaccregwizz.*;
import net.java.sip.communicator.service.protocol.*;
/**
@ -17,6 +18,7 @@
* @author Yana Stamcheva
*/
public class JabberAccountRegistration
implements SecurityAccountRegistration
{
/**
* The default value of server port for jabber accounts.
@ -199,6 +201,26 @@ public class JabberAccountRegistration
*/
private String dtmfMethod = null;
/**
* Enables support to encrypt calls.
*/
private boolean defaultEncryption = true;
/**
* Enqbles ZRTP encryption.
*/
private boolean sipZrtpAttribute = true;
/**
* Tells if SDES is enabled for this Jabber account.
*/
private boolean sdesEnabled = false;
/**
* The list of cipher suites enabledfor SDES.
*/
private String sdesCipherSuites = null;
/**
* Returns the password of the jabber registration account.
* @return the password of the jabber registration account.
@ -816,4 +838,95 @@ public void setDefaultDTMFMethod(String defaultDTMFMethod)
{
this.defaultDTMFMethod = defaultDTMFMethod;
}
/**
* Tells if SDES is enabled for this Jabber account.
*
* @return True if SDES is enabled. False, otherwise.
*/
public boolean isSDesEnabled()
{
return sdesEnabled;
}
/**
* Enables or disables SDES for this Jabber account.
*
* @param sdesEnabled True to enable SDES. False, otherwise.
*/
public void setSDesEnabled(boolean sdesEnabled)
{
this.sdesEnabled = sdesEnabled;
}
/**
* Returns the list of cipher suites enabled for SDES.
*
* @return The list of cipher suites enabled for SDES. Null if no cipher
* suite is enabled.
*/
public String getSDesCipherSuites()
{
return sdesCipherSuites;
}
/**
* Sets the list of cipher suites enabled for SDES.
*
* @param The list of cipher suites enabled for SDES. Null if no cipher
* suite is enabled.
*/
public void setSDesCipherSuites(String cipherSuites)
{
this.sdesCipherSuites = cipherSuites;
}
/**
* If default call encryption is enabled
*
* @return If default call encryption is enabled
*/
public boolean isDefaultEncryption()
{
return defaultEncryption;
}
/**
* Sets default call encryption
*
* @param defaultEncryption if we want to set call encryption on as default
*/
public void setDefaultEncryption(boolean defaultEncryption)
{
this.defaultEncryption = defaultEncryption;
}
/**
* Check if to include the ZRTP attribute to SIP/SDP
*
* @return include the ZRTP attribute to SIP/SDP
*/
public boolean isSipZrtpAttribute()
{
return sipZrtpAttribute;
}
/**
* Sets SIP ZRTP attribute support
*
* @param sipZrtpAttribute include the ZRTP attribute to SIP/SDP
*/
public void setSipZrtpAttribute(boolean sipZrtpAttribute)
{
this.sipZrtpAttribute = sipZrtpAttribute;
}
/**
* Sets the method used for RTP/SAVP indication.
*/
public void setSavpOption(int savpOption)
{
// SAVP option is not useful for XMPP account.
// Thereby, do nothing.
}
}

@ -1,3 +1,8 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license. See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.jabberaccregwizz;
import java.awt.*;
@ -6,6 +11,7 @@
import javax.swing.*;
import net.java.sip.communicator.plugin.sipaccregwizz.*;
import net.java.sip.communicator.service.credentialsstorage.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.swing.*;
@ -27,6 +33,8 @@ public class JabberAccountRegistrationForm
private final ConnectionPanel connectionPanel;
private final SecurityPanel securityPanel;
private final IceConfigPanel iceConfigPanel;
private final TelephonyConfigPanel telephonyConfigPanel;
@ -57,6 +65,8 @@ public JabberAccountRegistrationForm(JabberAccountRegistrationWizard wizard)
connectionPanel = new ConnectionPanel(this);
securityPanel = new SecurityPanel(this.getRegistration(), false);
iceConfigPanel = new IceConfigPanel();
telephonyConfigPanel = new TelephonyConfigPanel();
@ -87,6 +97,10 @@ void init()
tabbedPane.addTab(Resources.getString("service.gui.CONNECTION"),
connectionPanel);
if (securityPanel.getParent() != tabbedPane)
tabbedPane.addTab(Resources.getString("service.gui.SECURITY"),
securityPanel);
if (iceConfigPanel.getParent() != tabbedPane)
tabbedPane.addTab(Resources.getString("service.gui.ICE"),
iceConfigPanel);
@ -287,6 +301,8 @@ public boolean commitPage(JabberAccountRegistration registration)
registration.setDTMFMethod(connectionPanel.getDTMFMethod());
securityPanel.commitPanel(registration);
registration.setUseIce(iceConfigPanel.isUseIce());
registration.setUseGoogleIce(iceConfigPanel.isUseGoogleIce());
registration.setAutoDiscoverStun(iceConfigPanel.isAutoDiscoverStun());
@ -403,6 +419,8 @@ public void loadAccount(AccountID accountID)
connectionPanel.setDTMFMethod(
accountID.getAccountPropertyString("DTMF_METHOD"));
securityPanel.loadAccount(accountID);
String useIce =
accountProperties.get(ProtocolProviderFactory.IS_USE_ICE);
boolean isUseIce = Boolean.parseBoolean(

@ -440,6 +440,18 @@ protected ProtocolProviderService installAccount(
accountProperties.put("DTMF_METHOD",
registration.getDefaultDTMFMethod());
accountProperties.put(ProtocolProviderFactory.DEFAULT_ENCRYPTION,
Boolean.toString(registration.isDefaultEncryption()));
accountProperties.put(ProtocolProviderFactory.DEFAULT_SIPZRTP_ATTRIBUTE,
Boolean.toString(registration.isSipZrtpAttribute()));
accountProperties.put(ProtocolProviderFactory.SDES_ENABLED,
Boolean.toString(registration.isSDesEnabled()));
accountProperties.put(ProtocolProviderFactory.SDES_CIPHER_SUITES,
registration.getSDesCipherSuites());
if (isModification())
{

@ -22,6 +22,7 @@ Import-Package: org.osgi.framework,
org.jitsi.util,
net.java.sip.communicator.util,
net.java.sip.communicator.util.swing,
net.java.sip.communicator.plugin.sipaccregwizz,
javax.naming,
javax.naming.directory,
javax.xml.parsers,

@ -13,6 +13,7 @@
* @author Grigorii Balutsel
*/
public class SIPAccountRegistration
implements SecurityAccountRegistration
{
public static String DEFAULT_PORT = "5060";
@ -68,14 +69,26 @@ public class SIPAccountRegistration
private boolean forceP2PMode = false;
/**
* Enables support to encrypt calls.
*/
private boolean defaultEncryption = true;
/**
* Enqbles ZRTP encryption.
*/
private boolean sipZrtpAttribute = true;
/**
* Tells if SDES is enabled for this SIP account.
*/
private boolean sdesEnabled = false;
private int savpOption = 0;
/**
* The list of cipher suites enabled for SDES.
*/
private String sdesCipherSuites = null;
private String pollingPeriod = DEFAULT_POLL_PERIOD;
@ -596,31 +609,61 @@ public void setSipZrtpAttribute(boolean sipZrtpAttribute)
this.sipZrtpAttribute = sipZrtpAttribute;
}
/**
* Tells if SDES is enabled for this SIP account.
*
* @return True if SDES is enabled. False, otherwise.
*/
public boolean isSDesEnabled()
{
return sdesEnabled;
}
/**
* Enables or disables SDES for this SIP account.
*
* @param sdesEnabled True to enable SDES. False, otherwise.
*/
public void setSDesEnabled(boolean sdesEnabled)
{
this.sdesEnabled = sdesEnabled;
}
/**
* Returns the list of cipher suites enabled for SDES.
*
* @return The list of cipher suites enabled for SDES. Null if no cipher
* suite is enabled.
*/
public String getSDesCipherSuites()
{
return sdesCipherSuites;
}
/**
* Sets the list of cipher suites enabled for SDES.
*
* @param The list of cipher suites enabled for SDES. Null if no cipher
* suite is enabled.
*/
public void setSDesCipherSuites(String cipherSuites)
{
this.sdesCipherSuites = cipherSuites;
}
/**
* Gets the method used for RTP/SAVP indication.
*
* @return The method used for RTP/SAVP indication.
*/
public int getSavpOption()
{
return savpOption;
}
/**
* Sets the method used for RTP/SAVP indication.
*/
public void setSavpOption(int savpOption)
{
this.savpOption = savpOption;

@ -53,7 +53,7 @@ public SIPAccountRegistrationForm(SIPAccountRegistrationWizard wizard)
accountPanel = new AccountPanel(this);
connectionPanel = new ConnectionPanel(this);
securityPanel = new SecurityPanel(this);
securityPanel = new SecurityPanel(this.getRegistration(), true);
presencePanel = new PresencePanel(this);
}

@ -0,0 +1,79 @@
/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license. See terms of license at gnu.org.
*/
package net.java.sip.communicator.plugin.sipaccregwizz;
/**
* The <tt>SecurityAccountRegistration</tt> is used to determine security
* options for different registration protocol (Jabber, SIP). Useful fot the
* SecurityPanel.
*
* @author Vincent Lucas
*/
public interface SecurityAccountRegistration
{
/**
* If default call encryption is enabled
*
* @return If default call encryption is enabled
*/
public boolean isDefaultEncryption();
/**
* Sets default call encryption
*
* @param defaultEncryption if we want to set call encryption on as default
*/
public void setDefaultEncryption(boolean defaultEncryption);
/**
* Check if to include the ZRTP attribute to SIP/SDP
*
* @return include the ZRTP attribute to SIP/SDP
*/
public boolean isSipZrtpAttribute();
/**
* Sets SIP ZRTP attribute support
*
* @param sipZrtpAttribute include the ZRTP attribute to SIP/SDP
*/
public void setSipZrtpAttribute(boolean sipZrtpAttribute);
/**
* Tells if SDES is enabled for this SIP account.
*
* @return True if SDES is enabled. False, otherwise.
*/
public boolean isSDesEnabled();
/**
* Enables or disables SDES for this SIP account.
*
* @param sdesEnabled True to enable SDES. False, otherwise.
*/
public void setSDesEnabled(boolean sdesEnabled);
/**
* Returns the list of cipher suites enabled for SDES.
*
* @return The list of cipher suites enabled for SDES. Null if no cipher
* suite is enabled.
*/
public String getSDesCipherSuites();
/**
* Sets the list of cipher suites enabled for SDES.
*
* @param The list of cipher suites enabled for SDES. Null if no cipher
* suite is enabled.
*/
public void setSDesCipherSuites(String cipherSuites);
/**
* Sets the method used for RTP/SAVP indication.
*/
public void setSavpOption(int savpOption);
}

@ -30,7 +30,7 @@ public class SecurityPanel
*/
private static final long serialVersionUID = 0L;
private final SIPAccountRegistrationForm regform;
private final SecurityAccountRegistration regform;
private JPanel pnlAdvancedSettings;
private JCheckBox enableDefaultEncryption;
@ -41,6 +41,12 @@ public class SecurityPanel
private CipherTableModel cipherModel;
private JLabel cmdExpandAdvancedSettings;
/**
* Boolean used to display or not the SAVP options (only useful for SIP, not
* for XMPP).
*/
private boolean displaySavpOtions;
private static class SavpOption
{
int option;
@ -170,18 +176,32 @@ String getEnabledCiphers()
}
}
if(sb.length() == 0)
return null;
String result = sb.substring(0, sb.length()-1);
return (defaultCiphers == null
|| defaultCiphers.equals(result)) ? null : result;
{
return sb.toString();
}
else
{
return sb.substring(0, sb.length()-1);
}
}
}
public SecurityPanel(SIPAccountRegistrationForm regform)
/**
* Initiates a panel to configure the security (ZRTP and SDES) for SIP or
* XMPP protocols.
*
* @param regform The registration form of the account to configure.
* @param displaySavpOptions Boolean used to display or not the SAVP options
* (only useful for SIP, not for XMPP).
*/
public SecurityPanel(
SecurityAccountRegistration regform,
boolean displaySavpOptions)
{
super(new BorderLayout(10, 10));
this.regform = regform;
this.displaySavpOtions = displaySavpOptions;
initComponents();
}
@ -202,7 +222,7 @@ private void initComponents()
//general encryption option
enableDefaultEncryption = new SIPCommCheckBox(Resources
.getString("plugin.sipaccregwizz.ENABLE_DEFAULT_ENCRYPTION"),
regform.getRegistration().isDefaultEncryption());
regform.isDefaultEncryption());
enableDefaultEncryption.addActionListener(this);
mainPanel.add(enableDefaultEncryption, c);
@ -262,7 +282,7 @@ public void mouseClicked(MouseEvent e)
//ZRTP
enableSipZrtpAttribute = new SIPCommCheckBox(Resources
.getString("plugin.sipaccregwizz.ENABLE_SIPZRTP_ATTRIBUTE"),
regform.getRegistration().isSipZrtpAttribute());
regform.isSipZrtpAttribute());
c.gridy++;
pnlAdvancedSettings.add(enableSipZrtpAttribute, c);
@ -272,10 +292,16 @@ public void mouseClicked(MouseEvent e)
lblSavpOption.setText(
Resources.getString("plugin.sipaccregwizz.SAVP_OPTION"));
c.gridy++;
pnlAdvancedSettings.add(lblSavpOption, c);
if(this.displaySavpOtions)
{
pnlAdvancedSettings.add(lblSavpOption, c);
}
c.gridx = 2;
c.weightx = 1;
pnlAdvancedSettings.add(new JSeparator(), c);
if(this.displaySavpOtions)
{
pnlAdvancedSettings.add(new JSeparator(), c);
}
cboSavpOption = new JComboBox(new SavpOption[]{
new SavpOption(0),
new SavpOption(1),
@ -285,12 +311,15 @@ public void mouseClicked(MouseEvent e)
c.gridy++;
c.insets = new Insets(0, 20, 0, 0);
c.weightx = 0;
pnlAdvancedSettings.add(cboSavpOption, c);
if(this.displaySavpOtions)
{
pnlAdvancedSettings.add(cboSavpOption, c);
}
//SDES
enableSDesAttribute = new SIPCommCheckBox(Resources
.getString("plugin.sipaccregwizz.ENABLE_SDES_ATTRIBUTE"),
regform.getRegistration().isSDesEnabled());
regform.isSDesEnabled());
enableSDesAttribute.addActionListener(this);
c.gridy++;
c.gridwidth = 1;
@ -310,8 +339,7 @@ public void mouseClicked(MouseEvent e)
.getString("plugin.sipaccregwizz.CIPHER_SUITES"));
pnlAdvancedSettings.add(lblCipherInfo, c);
cipherModel = new CipherTableModel(regform.getRegistration()
.getSDesCipherSuites());
cipherModel = new CipherTableModel(regform.getSDesCipherSuites());
tabCiphers = new JTable(cipherModel);
tabCiphers.setShowGrid(false);
tabCiphers.setTableHeader(null);
@ -331,7 +359,7 @@ public void mouseClicked(MouseEvent e)
* @param registration the SIPAccountRegistration
* @return
*/
boolean commitPanel(SIPAccountRegistration registration)
public boolean commitPanel(SecurityAccountRegistration registration)
{
registration.setDefaultEncryption(enableDefaultEncryption.isSelected());
registration.setSipZrtpAttribute(enableSipZrtpAttribute.isSelected());
@ -346,7 +374,7 @@ boolean commitPanel(SIPAccountRegistration registration)
* Loads the account with the given identifier.
* @param accountID the account identifier
*/
void loadAccount(AccountID accountID)
public void loadAccount(AccountID accountID)
{
enableDefaultEncryption.setSelected(
accountID.getAccountPropertyBoolean(

@ -256,14 +256,12 @@ public void run()
&& answerWithVideo
&& opSetVideoTelephony != null)
{
System.out.println("CHENZO: VIDEO");
opSetVideoTelephony.answerVideoCallPeer(peer);
}
// Else sends only audio to the repote peer (the remote peer is
// still able to send us its video stream).
else if(opSetBasicTelephony != null)
{
System.out.println("CHENZO: AUDIO");
opSetBasicTelephony.answerCallPeer(peer);
}
}

Loading…
Cancel
Save