/*
* Jitsi, the OpenSource Java VoIP and Instant Messaging client.
*
* Copyright @ 2015 Atlassian Pty Ltd
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package net.java.sip.communicator.service.protocol;
import net.java.sip.communicator.util.*;
import org.jitsi.service.neomedia.*;
import java.io.*;
import java.util.*;
/**
* The <tt>SecurityAccountRegistration</tt> is used to determine security
* options for different registration protocol (Jabber, SIP). Useful to the
* SecurityPanel.
*
* @author Vincent Lucas
* @author Pawel Domas
* @author Lyubomir Marinov
*/
public abstract class SecurityAccountRegistration
implements Serializable
{
/**
* The encryption protocols managed by this SecurityPanel.
*/
public static final List<String> ENCRYPTION_PROTOCOLS
= Collections.unmodifiableList(
Arrays.asList(
SrtpControlType.ZRTP.toString(),
SrtpControlType.SDES.toString(),
SrtpControlType.DTLS_SRTP.toString()));
/**
* Enables support to encrypt calls.
*/
private boolean defaultEncryption = true;
/**
* Enables ZRTP encryption.
*/
private boolean sipZrtpAttribute = true;
/**
* Tells if SDES is enabled for this account.
*/
private boolean sdesEnabled = false;
/**
* The list of cipher suites enabled for SDES.
*/
private String sdesCipherSuites = null;
/**
* The map between encryption protocols and their priority order.
*/
private Map<String, Integer> encryptionProtocols;
/**
* The map between encryption protocols and their status (enabled or
* disabled).
*/
private Map<String, Boolean> encryptionProtocolStatus;
/**
* Initializes the security account registration properties with the default
* values.
*/
public SecurityAccountRegistration()
{
// Sets the default values.
encryptionProtocols = new HashMap<String, Integer>(1);
encryptionProtocols.put("ZRTP", 0);
encryptionProtocolStatus = new HashMap<String, Boolean>(1);
encryptionProtocolStatus.put("ZRTP", true);
sdesCipherSuites
= UtilActivator.getResources().getSettingsString(
SDesControl.SDES_CIPHER_SUITES);
}
/**
* 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 or to Jabber/IQ
*
* @return include the ZRTP attribute to SIP/SDP or to Jabber/IQ
*/
public boolean isSipZrtpAttribute()
{
return sipZrtpAttribute;
}
/**
* Sets ZRTP attribute support
*
* @param sipZrtpAttribute include the ZRTP attribute to SIP/SDP or to
* Jabber/IQ
*/
public void setSipZrtpAttribute(boolean sipZrtpAttribute)
{
this.sipZrtpAttribute = sipZrtpAttribute;
}
/**
* Tells if SDES is enabled for this account.
*
* @return True if SDES is enabled. False, otherwise.
*/
public boolean isSDesEnabled()
{
return sdesEnabled;
}
/**
* Enables or disables SDES for this 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 cipherSuites The list of cipher suites enabled for SDES.
* Null if no cipher suite is enabled.
*/
public void setSDesCipherSuites(String cipherSuites)
{
this.sdesCipherSuites = cipherSuites;
}
/**
* Sets the method used for RTP/SAVP indication.
*/
public abstract void setSavpOption(int savpOption);
/**
* Returns the method used for RTP/SAVP indication.
* @return the method used for RTP/SAVP indication.
*/
public abstract int getSavpOption();
/**
* Returns the map between the encryption protocols and their priority
* order.
*
* @return The map between the encryption protocols and their priority
* order.
*/
public Map<String, Integer> getEncryptionProtocols()
{
return encryptionProtocols;
}
/**
* Sets the map between the encryption protocols and their priority order.
*
* @param encryptionProtocols The map between the encryption protocols and
* their priority order.
*/
public void setEncryptionProtocols(
Map<String, Integer> encryptionProtocols)
{
this.encryptionProtocols = encryptionProtocols;
}
/**
* Returns the map between the encryption protocols and their status.
*
* @return The map between the encryption protocols and their status.
*/
public Map<String, Boolean> getEncryptionProtocolStatus()
{
return encryptionProtocolStatus;
}
/**
* Sets the map between the encryption protocols and their status.
*
* @param encryptionProtocolStatus The map between the encryption protocols
* and their status.
*/
public void setEncryptionProtocolStatus(
Map<String, Boolean> encryptionProtocolStatus)
{
this.encryptionProtocolStatus = encryptionProtocolStatus;
}
/**
* Adds the ordered encryption protocol names to the property list given in
* parameter.
*
* @param properties The property list to fill in.
*/
private void addEncryptionProtocolsToProperties(
Map<String, String> properties)
{
for (Map.Entry<String, Integer> e : getEncryptionProtocols().entrySet())
{
properties.put(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL
+ "."
+ e.getKey(),
e.getValue().toString());
}
}
/**
* Adds the encryption protocol status to the property list given in
* parameter.
*
* @param properties The property list to fill in.
*/
private void addEncryptionProtocolStatusToProperties(
Map<String, String> properties)
{
for (Map.Entry<String,Boolean> e
: getEncryptionProtocolStatus().entrySet())
{
properties.put(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL_STATUS
+ "."
+ e.getKey(),
e.getValue().toString());
}
}
/**
* Stores security properties held by this registration object into given
* properties map.
* @param propertiesMap the map that will be used for storing security
* properties held by this object.
*/
public void storeProperties(Map<String, String> propertiesMap)
{
propertiesMap.put(ProtocolProviderFactory.DEFAULT_ENCRYPTION,
Boolean.toString(isDefaultEncryption()));
// Sets the ordered list of encryption protocols.
addEncryptionProtocolsToProperties(propertiesMap);
// Sets the list of encryption protocol status.
addEncryptionProtocolStatusToProperties(propertiesMap);
propertiesMap.put(ProtocolProviderFactory.DEFAULT_SIPZRTP_ATTRIBUTE,
Boolean.toString(isSipZrtpAttribute()));
propertiesMap.put(ProtocolProviderFactory.SAVP_OPTION,
Integer.toString(getSavpOption()));
propertiesMap.put(ProtocolProviderFactory.SDES_CIPHER_SUITES,
getSDesCipherSuites());
}
/**
* Loads security properties from the account with the given identifier.
* @param accountID the account identifier.
*/
public void loadAccount(AccountID accountID)
{
setDefaultEncryption(
accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.DEFAULT_ENCRYPTION,
true));
encryptionProtocols = new HashMap<String, Integer>();
encryptionProtocolStatus = new HashMap<String, Boolean>();
Map<String,Integer> srcEncryptionProtocols
= accountID.getIntegerPropertiesByPrefix(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL,
true);
Map<String,Boolean> srcEncryptionProtocolStatus
= accountID.getBooleanPropertiesByPrefix(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL_STATUS,
true,
false);
// Load stored values.
int prefixeLength
= ProtocolProviderFactory.ENCRYPTION_PROTOCOL.length() + 1;
for (Map.Entry<String,Integer> e : srcEncryptionProtocols.entrySet())
{
String name = e.getKey().substring(prefixeLength);
if (isExistingEncryptionProtocol(name))
{
// Copy the priority
encryptionProtocols.put(name, e.getValue());
// Extract the status
boolean enabled
= srcEncryptionProtocolStatus.get(
ProtocolProviderFactory.ENCRYPTION_PROTOCOL_STATUS
+ "."
+ name);
encryptionProtocolStatus.put(name, enabled);
}
}
setSipZrtpAttribute(
accountID.getAccountPropertyBoolean(
ProtocolProviderFactory.DEFAULT_SIPZRTP_ATTRIBUTE,
true));
setSavpOption(
accountID.getAccountPropertyInt(
ProtocolProviderFactory.SAVP_OPTION,
ProtocolProviderFactory.SAVP_OFF));
setSDesCipherSuites(
accountID.getAccountPropertyString(
ProtocolProviderFactory.SDES_CIPHER_SUITES));
}
/**
* Loads the list of enabled and disabled encryption protocols with their
* priority into array of <tt>String</tt> and array of <tt>Boolean</tt>.
* The protocols are positioned in the array by the priority and the
* <tt>Boolean</tt> array holds the enabled flag on the corresponding index.
*
* @param encryptionProtocols The map of encryption protocols with their
* priority available for this account.
* @param encryptionProtocolStatus The map of encryption protocol statuses.
* @return <tt>Object[]</tt> array holding:<br/>
* - at [0] <tt>String[]</tt> the list of extracted protocol names<br/>
* - at [1] <tt>boolean[]</tt> the list of of protocol status flags
*/
public static Object[] loadEncryptionProtocols(
Map<String, Integer> encryptionProtocols,
Map<String, Boolean> encryptionProtocolStatus)
{
int nbEncryptionProtocols = ENCRYPTION_PROTOCOLS.size();
String[] encryptions = new String[nbEncryptionProtocols];
boolean[] selectedEncryptions = new boolean[nbEncryptionProtocols];
// Load stored values.
for (Map.Entry<String,Integer> e : encryptionProtocols.entrySet())
{
int index = e.getValue();
// If the property is set.
if (index != -1)
{
String name = e.getKey();
if (isExistingEncryptionProtocol(name))
{
encryptions[index] = name;
selectedEncryptions[index]
= encryptionProtocolStatus.get(name);
}
}
}
// Load default values.
int j = 0;
for (String encryptionProtocol : ENCRYPTION_PROTOCOLS)
{
// Specify a default value only if there is no specific value set.
if(!encryptionProtocols.containsKey(encryptionProtocol))
{
boolean set = false;
// Search for the first empty element.
while(j < encryptions.length && !set)
{
if(encryptions[j] == null)
{
encryptions[j] = encryptionProtocol;
// By default only ZRTP is set to true.
selectedEncryptions[j]
= encryptionProtocol.equals("ZRTP");
set = true;
}
++j;
}
}
}
return new Object[] { encryptions, selectedEncryptions};
}
/**
* Checks if a specific <tt>protocol</tt> is on the list of supported
* (encryption) protocols.
*
* @param protocol the protocol name
* @return <tt>true</tt> if <tt>protocol</tt> is supported; <tt>false</tt>,
* otherwise
*/
private static boolean isExistingEncryptionProtocol(String protocol)
{
return ENCRYPTION_PROTOCOLS.contains(protocol);
}
}