Zrtp Gui and event modifications. (Issue #463)

cusax-fix
Yana Stamcheva 17 years ago
parent 220ec09d41
commit ea303ffd2d

@ -119,10 +119,16 @@ service.gui.buttons.EDIT_TOOLBAR_BUTTON=resources/images/impl/gui/buttons/editTo
service.gui.buttons.EDIT_TOOLBAR_BUTTON_PRESSED=resources/images/impl/gui/buttons/editToolbarButtonPressed.png
service.gui.buttons.DIAL_BUTTON=resources/images/impl/gui/buttons/dialButton.png
service.gui.buttons.HOLD_BUTTON=resources/images/impl/gui/buttons/holdButton.png
service.gui.buttons.HOLD_BUTTON_FULL_SCREEN=resources/images/impl/gui/buttons/holdButtonFullScreen.png
service.gui.buttons.MUTE_BUTTON=resources/images/impl/gui/buttons/muteButton.png
service.gui.buttons.MUTE_BUTTON_FULL_SCREEN=resources/images/impl/gui/buttons/muteButtonFullScreen.png
service.gui.buttons.TRANSFER_CALL_BUTTON=resources/images/impl/gui/buttons/transferCallButton.png
service.gui.buttons.SECURE_BUTTON_ON=resources/images/impl/gui/buttons/secureOn.png
service.gui.buttons.SECURE_BUTTON_OFF=resources/images/impl/gui/buttons/secureOff.png
service.gui.buttons.SECURE_VIDEO_ON=resources/images/impl/gui/buttons/secureVideoOn.png
service.gui.buttons.SECURE_VIDEO_OFF=resources/images/impl/gui/buttons/secureVideoOff.png
service.gui.buttons.SECURE_AUDIO_ON=resources/images/impl/gui/buttons/secureAudioOn.png
service.gui.buttons.SECURE_AUDIO_OFF=resources/images/impl/gui/buttons/secureAudioOff.png
service.gui.buttons.ENCR_VERIFIED=resources/images/impl/gui/buttons/encrypted_verified.png
service.gui.buttons.ENCR=resources/images/impl/gui/buttons/encrypted.png
service.gui.buttons.ENCR_DISABLED=resources/images/impl/gui/buttons/encrypted_disabled.png

Binary file not shown.

Before

Width:  |  Height:  |  Size: 693 B

After

Width:  |  Height:  |  Size: 389 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 839 B

After

Width:  |  Height:  |  Size: 543 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 287 B

After

Width:  |  Height:  |  Size: 848 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 695 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 962 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 736 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 781 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 579 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 585 B

@ -675,6 +675,10 @@ impl.media.security.WARNING_NO_RS_MATCH=<html>No retained shared secret availabl
impl.media.security.WARNING_NO_EXPECTED_RS_MATCH=<html>An expected retained shared secret is missing.<br/><b>SAS verification is required</b><br/>If SAS codes do not match then hangup and try again</html>
impl.media.security.SEVERE_GENERIC_MSG=<html>A severe security problem was detected.<br/><b>Your call is not secure</b><br/>Error code: {0}</html>
impl.media.security.ZRTP_GENERIC_MSG=<html>A severe ZRTP problem was detected.<br/><b>Your call is not secure</b><br/>Error code: {0}</html>
impl.media.security.INTERNAL_PROTOCOL_ERROR=<html>Internal protocol error occurred.<br/><b>Your call is not secure</b><br/>Error code: {0}</html>
impl.media.security.CHECKSUM_MISMATCH=<html>Internal ZRTP packet checksum mismatch.<br/>If you see this message often this may mean a denial-of-service attack!</html>
impl.media.security.RETRY_RATE_EXCEEDED=<html>Too much retries during security negotiation. This may mean that the other party has internet connection problems.<br/><b>Your call is not secure</b><br/>Error code: {0}</html>
impl.media.security.DATA_SEND_FAILED=<html>Failed to send encryption data. Internet data connection or peer is down.<br/><b>Your call is not secure</b><br/>Error code: {0}</html>
impl.media.security.SECURITY_OFF=Call encryption support off
impl.media.security.SECURITY_ON=Call encryption support on
#impl.media.security.ENGINE_INIT_FAILURE=Securing engine initialization failure

@ -545,7 +545,8 @@ public OperationSetWebContactInfo getWebContactInfoOpSet(
OperationSet opSet
= protocolProvider.getOperationSet(OperationSetWebContactInfo.class);
return (opSet instanceof OperationSetWebContactInfo) ? (OperationSetWebContactInfo) opSet
return (opSet instanceof OperationSetWebContactInfo)
? (OperationSetWebContactInfo) opSet
: null;
}
@ -563,7 +564,8 @@ public OperationSetBasicTelephony getTelephonyOpSet(
OperationSet opSet
= protocolProvider.getOperationSet(OperationSetBasicTelephony.class);
return (opSet instanceof OperationSetBasicTelephony) ? (OperationSetBasicTelephony) opSet
return (opSet instanceof OperationSetBasicTelephony)
? (OperationSetBasicTelephony) opSet
: null;
}

@ -28,7 +28,9 @@
*/
public class CallPanel
extends TransparentPanel
implements CallChangeListener, CallParticipantListener, SecurityGUIListener
implements CallChangeListener,
CallParticipantListener,
CallParticipantSecurityListener
{
private final TransparentPanel mainPanel = new TransparentPanel();
@ -248,19 +250,49 @@ public void participantImageChanged(CallParticipantChangeEvent evt)
{
}
public void securityStatusChanged(SecurityGUIEvent securityEvent)
public void securityOn(CallParticipantSecurityOnEvent securityEvent)
{
CallParticipant part = (CallParticipant)securityEvent.getSource();
CallParticipantPanel panel = getParticipantPanel(part);
CallParticipant participant = (CallParticipant)securityEvent.getSource();
if (securityEvent.getEventID() == SecurityGUIEvent.SECURITY_ENABLED)
CallParticipantPanel participantPanel = getParticipantPanel(participant);
participantPanel.setStateIcon(
new ImageIcon(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_ON)));
participantPanel.setEncryptionCipher(securityEvent.getCipher());
if (securityEvent.getSessionType()
.equals(CallParticipantSecurityOnEvent.AUDIO_SESSION))
{
participantPanel.setAudioSecurityOn(true);
}
else if (securityEvent.getSessionType()
.equals(CallParticipantSecurityOnEvent.VIDEO_SESSION))
{
panel.changeSecureCallButton(true);
participantPanel.setVideoSecurityOn(true);
}
if (securityEvent.getProvider() == SecurityGUIEvent.ZRTP)
participantPanel.createSecurityPanel(securityEvent);
}
public void securityOff(CallParticipantSecurityOffEvent securityEvent)
{
CallParticipant participant = (CallParticipant)securityEvent.getSource();
CallParticipantPanel participantPanel = getParticipantPanel(participant);
participantPanel.setStateIcon(
new ImageIcon(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF)));
if (securityEvent.getSessionType()
.equals(CallParticipantSecurityOnEvent.AUDIO_SESSION))
{
participantPanel.setAudioSecurityOn(false);
}
else if (securityEvent.getSessionType()
.equals(CallParticipantSecurityOnEvent.VIDEO_SESSION))
{
panel.changeZrtpPanel((SecurityGUIEventZrtp) securityEvent);
participantPanel.setVideoSecurityOn(false);
}
}
@ -285,7 +317,6 @@ private void setCall(Call call, String callType)
this.call = call;
this.call.addCallChangeListener(this);
this.call.addSecurityGUIListener("zrtp", this);
// Remove all previously added participant panels, because they do not
// correspond to real participants.
@ -299,6 +330,7 @@ private void setCall(Call call, String callType)
CallParticipant participant = participants.next();
participant.addCallParticipantListener(this);
participant.addCallParticipantSecurityListener(this);
this.addCallParticipant(participant, callType);
}
@ -387,4 +419,13 @@ public CallParticipantPanel getParticipantPanel(CallParticipant participant)
}
return null;
}
public void securityMessageRecieved(
CallParticipantSecurityMessageEvent event)
{
NotificationManager.fireNotification(
NotificationManager.WARNING_MESSAGE,
"Security error",
event.getI18nMessage());
}
}

@ -14,7 +14,6 @@
import javax.swing.Timer;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.protocol.*;
@ -36,7 +35,7 @@ public class CallParticipantPanel
private static final Logger logger =
Logger.getLogger(CallParticipantPanel.class);
private final JLabel stateLabel = new JLabel("Unknown", JLabel.CENTER);
private final SecurityStatusLabel securityStatusLabel;
private final JLabel timeLabel = new JLabel("00:00:00", JLabel.CENTER);
@ -63,6 +62,12 @@ public class CallParticipantPanel
private Component localVideo;
private boolean isAudioSecurityOn = false;
private boolean isVideoSecurityOn = false;
private String encryptionCipher;
/**
* The current <code>Window</code> being displayed in full-screen. Because
* the AWT API with respect to the full-screen support doesn't seem
@ -71,9 +76,8 @@ public class CallParticipantPanel
*/
private Window fullScreenWindow;
private SecureButton secureButton;
private ParticipantStatusPanel statusPanel;
private ZrtpPanel zrtpPanel = null;
private SecurityPanel securityPanel = null;
/**
* Creates a <tt>CallParticipantPanel</tt> for the given call participant.
@ -85,6 +89,12 @@ public CallParticipantPanel(CallParticipant callParticipant)
this.callParticipant = callParticipant;
this.participantName = callParticipant.getDisplayName();
this.securityStatusLabel = new SecurityStatusLabel(
this,
"Unknown",
new ImageIcon(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF)),
JLabel.CENTER);
// Initialize the date to 0
// Need to use Calendar because new Date(0) returns a date where the
// hour is initialized to 1.
@ -105,6 +115,7 @@ public CallParticipantPanel(CallParticipant callParticipant)
{
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
constraints.gridy = 0;
constraints.weightx = 0;
add(nameBar, constraints);
@ -121,7 +132,7 @@ public CallParticipantPanel(CallParticipant callParticipant)
constraints.fill = GridBagConstraints.BOTH;
constraints.gridx = 0;
constraints.gridy = GridBagConstraints.RELATIVE;
constraints.gridy = 1;
constraints.weightx = 1;
constraints.weighty = 1;
@ -131,6 +142,7 @@ public CallParticipantPanel(CallParticipant callParticipant)
{
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
constraints.gridy = 3;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.insets = new Insets(5, 0, 0, 0);
@ -147,10 +159,10 @@ public CallParticipantPanel(CallParticipant callParticipant)
private Component createButtonBar( boolean heavyweight,
Component[] buttons)
{
Container buttonBar =
heavyweight ? new Container() : new TransparentPanel();
Container buttonBar
= heavyweight ? new Container() : new TransparentPanel();
buttonBar.setLayout(new FlowLayout(FlowLayout.CENTER, 0, 3));
buttonBar.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
for (int buttonIndex = 0; buttonIndex < buttons.length; buttonIndex++)
{
@ -254,29 +266,20 @@ private Component createNameBar()
private Component createStatusBar()
{
// stateLabel
stateLabel.setForeground(Color.WHITE);
stateLabel.setText(callParticipant.getState().getStateString());
// secureLabel
// Component secureLabel = createSecureCallLabel();
// zrtpPanel = createZrtpPanel();
securityStatusLabel.setForeground(Color.WHITE);
securityStatusLabel.setText(callParticipant.getState().getStateString());
statusPanel = new ParticipantStatusPanel(new GridLayout(1, 0, 5, 5));
timeLabel.setForeground(Color.WHITE);
statusPanel.add(timeLabel);
statusPanel.add(stateLabel);
// if (secureLabel != null)
// namePanel.add(secureLabel);
// if (zrtpPanel != null)
// namePanel.add(zrtpPanel);
statusPanel.add(securityStatusLabel);
Component[] buttons =
new Component[]
{
createTransferCallButton(),
createSecureCallButton(),
createEnterFullScreenButton()
};
@ -312,60 +315,38 @@ private Component createTransferCallButton()
return null;
}
/**
* Creates a new <code>Component</code> representing a UI means to secure
* the <code>Call</code> of the associated <code>callParticipant</code> or
* <tt>null</tt> if secure call is unsupported.
*
* @return a new <code>Component</code> representing the UI means to secure
* the <code>Call</code> of <code>callParticipant</code> or
* <tt>null</tt> if secure call is unsupported
*/
private Component createSecureCallButton()
public void createSecurityPanel(
CallParticipantSecurityOnEvent event)
{
Call call = callParticipant.getCall();
if (call != null)
{
OperationSetSecureTelephony secure =
(OperationSetSecureTelephony) call.getProtocolProvider()
.getOperationSet(OperationSetSecureTelephony.class);
OperationSetSecureTelephony secure
= (OperationSetSecureTelephony) call
.getProtocolProvider().getOperationSet(
OperationSetSecureTelephony.class);
if (secure != null)
{
secureButton = new SecureButton(callParticipant);
if (securityPanel == null)
{
securityPanel = new SecurityPanel(callParticipant);
secureButton.setToolTipText(
GuiActivator.getResources().getI18NString(
"impl.media.security.TOGGLE_ON_SECURITY"));
GridBagConstraints constraints = new GridBagConstraints();
return secureButton;
}
}
return null;
}
constraints.fill = GridBagConstraints.NONE;
constraints.gridx = 0;
constraints.gridy = 2;
constraints.weightx = 0;
constraints.weighty = 0;
constraints.insets = new Insets(5, 0, 0, 0);
public void changeSecureCallButton(boolean isEnabled)
{
secureButton.updateSecureButton(isEnabled);
}
this.add(securityPanel, constraints);
}
public void changeZrtpPanel(SecurityGUIEventZrtp securityEvent)
{
Call call = callParticipant.getCall();
securityPanel.refreshStates(event);
if (call != null) {
OperationSetSecureTelephony secure = (OperationSetSecureTelephony) call
.getProtocolProvider().getOperationSet(
OperationSetSecureTelephony.class);
if (secure != null) {
if (zrtpPanel == null) {
zrtpPanel = new ZrtpPanel();
zrtpPanel.setName("zrtpPanel");
zrtpPanel.addComponentsToPane();
statusPanel.add(zrtpPanel);
}
zrtpPanel.refreshStates(securityEvent);
this.revalidate();
}
}
@ -620,10 +601,96 @@ public void run()
*/
public void setState(String state, Icon icon)
{
this.stateLabel.setText(state);
this.stateLabel.setIcon(icon);
this.securityStatusLabel.setText(state);
this.securityStatusLabel.setIcon(icon);
}
/**
* Sets the state string.
*
* @param stateString the state string
*/
public void setStateString(String stateString)
{
this.securityStatusLabel.setText(stateString);
}
/**
* Sets the states icon.
*
* @param icon the state icon
*/
public void setStateIcon(Icon icon)
{
this.securityStatusLabel.setIcon(icon);
}
/**
* Sets the audio security on or off.
*
* @param isAudioSecurityOn indicates if the audio security is turned on or
* off.
*/
public void setAudioSecurityOn(boolean isAudioSecurityOn)
{
this.isAudioSecurityOn = isAudioSecurityOn;
}
/**
* Sets the video security on or off.
*
* @param isVideoSecurityOn indicates if the video security is turned on or
* off.
*/
public void setVideoSecurityOn(boolean isVideoSecurityOn)
{
this.isVideoSecurityOn = isVideoSecurityOn;
}
/**
* Indicates if the audio security is turned on or off.
*
* @return <code>true</code> if the audio security is on, otherwise -
* <code>false</code>.
*/
public boolean isAudioSecurityOn()
{
return isAudioSecurityOn;
}
/**
* Indicates if the video security is turned on or off.
*
* @return <code>true</code> if the video security is on, otherwise -
* <code>false</code>.
*/
public boolean isVideoSecurityOn()
{
return isVideoSecurityOn;
}
/**
* Returns the cipher used for the encryption of the current call.
*
* @return the cipher used for the encryption of the current call.
*/
public String getEncryptionCipher()
{
return encryptionCipher;
}
/**
* Sets the cipher used for the encryption of the current call.
*
* @param encryptionCipher the cipher used for the encryption of the
* current call.
*/
public void setEncryptionCipher(String encryptionCipher)
{
this.encryptionCipher = encryptionCipher;
}
/**
* Starts the timer that counts call duration.
*/
@ -766,7 +833,7 @@ private Component createFullScreenButtonBar()
{
Component[] buttons =
new Component[]
{ new HoldButton(callParticipant.getCall()),
{ new HoldButton(callParticipant.getCall(), true),
new MuteButton(callParticipant.getCall()),
createExitFullScreenButton() };
@ -907,9 +974,9 @@ private static class ParticipantStatusPanel
* the instances of the class, there're no fields so the default
* serialization routine will work.
*/
private static final long serialVersionUID = 0L;
private static final long serialVersionUID = 0L;
public ParticipantStatusPanel(LayoutManager layout)
public ParticipantStatusPanel(LayoutManager layout)
{
super(layout);
this.setBorder(BorderFactory.createEmptyBorder(0, 5, 0, 5));

@ -44,6 +44,22 @@ public HoldButton(Call call)
"service.gui.HOLD_BUTTON_TOOL_TIP"));
}
public HoldButton(Call call, boolean isFullScreenMode)
{
this(call);
if (isFullScreenMode)
{
this.setBgImage(
ImageLoader.getImage(ImageLoader.HOLD_BUTTON_FULL_SCREEN));
this.setBgRolloverImage(
ImageLoader.getImage(ImageLoader.HOLD_BUTTON_FULL_SCREEN));
this.setPressedImage(
ImageLoader.getImage(ImageLoader.HOLD_BUTTON_FULL_SCREEN));
this.setIconImage(null);
}
}
/**
* Represents the model of a toggle button that puts an associated
* <tt>CallParticipant</tt> on/off hold.

@ -19,13 +19,13 @@
* @author Emanuel Onica
*/
@SuppressWarnings("serial")
public class SecureButton
public class SecureVerifyButton
extends SIPCommButton
implements ActionListener
{
private final CallParticipant callParticipant;
public SecureButton(CallParticipant callParticipant)
public SecureVerifyButton(CallParticipant callParticipant)
{
super(ImageLoader.getImage(ImageLoader.SECURE_BUTTON_OFF));

@ -0,0 +1,144 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.customcontrols.*;
import net.java.sip.communicator.impl.gui.main.call.CallParticipantPanel.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.notification.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.swing.*;
public class SecurityPanel
extends TransparentPanel
{
private CallParticipant participant;
private Image iconEncr;
private Image iconEncrVerified;
private boolean sasVerified = false;
private NotificationService notificationService = null;
private static final String ZRTP_SECURE_NOTIFICATION
= "ZrtpSecureNotification";
private static final String ZRTP_ALERT_NOTIFICATION
= "ZrtpAlertNotification";
private SIPCommButton sasVerificationButton
= new SIPCommButton(iconEncr);
private JLabel securityStringLabel = new JLabel();
public SecurityPanel(CallParticipant participant)
{
this.participant = participant;
this.setLayout(new GridLayout(1, 0, 5, 5));
this.setBorder(
BorderFactory.createTitledBorder("Compare with partner"));
iconEncrVerified =
ImageLoader.getImage(ImageLoader.ENCR_VERIFIED);
iconEncr = ImageLoader.getImage(ImageLoader.ENCR);
notificationService = GuiActivator.getNotificationService();
if(notificationService != null)
{
notificationService.registerDefaultNotificationForEvent(
ZRTP_SECURE_NOTIFICATION,
NotificationService.ACTION_SOUND,
SoundProperties.ZRTP_SECURE,
null);
notificationService.registerDefaultNotificationForEvent(
ZRTP_ALERT_NOTIFICATION,
NotificationService.ACTION_SOUND,
SoundProperties.ZRTP_ALERT,
null);
}
this.addComponentsToPane();
}
private void addComponentsToPane()
{
this.add(sasVerificationButton);
this.add(securityStringLabel);
// Action to trigger SAS verification
sasVerificationButton.addActionListener(new ActionListener()
{
public void actionPerformed(ActionEvent e)
{
boolean sucess = false;
Call call = participant.getCall();
if (call != null)
{
OperationSetSecureTelephony secure
= (OperationSetSecureTelephony) call
.getProtocolProvider().getOperationSet(
OperationSetSecureTelephony.class);
if (secure != null)
{
sucess = secure.setSasVerified( participant,
!sasVerified);
}
if (sucess)
{
if (sasVerified)
{
sasVerified = false;
sasVerificationButton.setImage(iconEncr);
}
else
{
sasVerified = true;
sasVerificationButton.setImage(iconEncrVerified);
}
}
}
}
});
}
public void refreshStates(CallParticipantSecurityOnEvent event)
{
String securityString = event.getSecurityString();
if (securityString != null)
{
securityStringLabel.setText(securityString);
if (event.isSecurityVerified())
{
sasVerificationButton.setImage(iconEncrVerified);
}
}
sasVerificationButton.setImage(iconEncr);
notificationService.fireNotification(ZRTP_SECURE_NOTIFICATION);
revalidate();
repaint();
}
}

@ -0,0 +1,86 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.utils.*;
/**
*
* @author Yana Stamcheva
*/
public class SecurityStatusLabel extends JLabel
{
private final CallParticipantPanel callParticipantPanel;
public SecurityStatusLabel( CallParticipantPanel callParticipantPanel,
String text,
Icon icon,
int alignment)
{
super(text, icon, alignment);
this.callParticipantPanel = callParticipantPanel;
this.setToolTipText("Test");
}
/**
* Create tooltip.
*/
public JToolTip createToolTip()
{
ExtendedTooltip tip = new ExtendedTooltip();
tip.setTitle("Security status");
ImageIcon audioStatusIcon;
String audioStatusString;
if (callParticipantPanel.isAudioSecurityOn())
{
audioStatusIcon = new ImageIcon(
ImageLoader.getImage(ImageLoader.SECURE_AUDIO_ON));
audioStatusString = "Audio security on.";
}
else
{
audioStatusIcon = new ImageIcon(
ImageLoader.getImage(ImageLoader.SECURE_AUDIO_OFF));
audioStatusString = "Audio security off.";
}
ImageIcon videoStatusIcon;
String videoStatusString;
if (callParticipantPanel.isVideoSecurityOn())
{
videoStatusIcon = new ImageIcon(
ImageLoader.getImage(ImageLoader.SECURE_VIDEO_ON));
videoStatusString = "Video security on.";
}
else
{
videoStatusIcon = new ImageIcon(
ImageLoader.getImage(ImageLoader.SECURE_VIDEO_OFF));
videoStatusString = "Video security off.";
}
String cipher = "Cipher: " + callParticipantPanel.getEncryptionCipher();
tip.addLine(audioStatusIcon,
audioStatusString);
tip.addLine(videoStatusIcon,
videoStatusString);
tip.addLine(null, cipher);
tip.setComponent(this);
return tip;
}
}

@ -1,258 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.call;
import java.awt.*;
import java.awt.event.*;
import java.util.*;
import javax.swing.*;
import net.java.sip.communicator.impl.gui.*;
import net.java.sip.communicator.impl.gui.utils.*;
import net.java.sip.communicator.service.gui.*;
import net.java.sip.communicator.service.notification.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.swing.*;
public class ZrtpPanel extends TransparentPanel {
/**
* Default.
*/
private static final long serialVersionUID = 1L;
private static final String ZRTP_SECURE = "ZrtpSecure";
private static final String ZRTP_ALERT = "ZrtpAlert";
private CallParticipant participant;
private JButton secButton;
private JLabel sasLabel;
private JLabel secMethod;
private JLabel sessionType;
private JButton secButtonV;
private JLabel sasLabelV;
private JLabel secMethodV;
private JLabel sessionTypeV;
private ImageIcon iconEncr;
private ImageIcon iconEncrVerified;
private ImageIcon iconEncrDisabled;
private boolean sasVerified = false;
private NotificationService notificationService = null;
public ZrtpPanel() {
iconEncrVerified = new ImageIcon(
ImageLoader.getImage(ImageLoader.ENCR_VERIFIED));
iconEncr = new ImageIcon(ImageLoader.getImage(ImageLoader.ENCR));
iconEncrDisabled = new ImageIcon(
ImageLoader.getImage(ImageLoader.ENCR_DISABLED));
setLayout(new GridLayout(0, 4, 10, 3));
secButton = new JButton("");
sasLabel = new JLabel("", JLabel.CENTER);
secMethod = new JLabel("None", JLabel.CENTER);
sessionType = new JLabel("", JLabel.CENTER);
secButtonV = new JButton(iconEncrDisabled);
sasLabelV = new JLabel("", JLabel.CENTER);
secMethodV = new JLabel("None", JLabel.CENTER);
sessionTypeV = new JLabel("", JLabel.CENTER);
setPreferredSize(new Dimension(350, 80));
notificationService = GuiActivator.getNotificationService();
if(notificationService != null) {
notificationService.registerDefaultNotificationForEvent(
ZRTP_SECURE,
NotificationService.ACTION_SOUND,
SoundProperties.ZRTP_SECURE,
null);
notificationService.registerDefaultNotificationForEvent(
ZRTP_ALERT,
NotificationService.ACTION_SOUND,
SoundProperties.ZRTP_ALERT,
null);
}
}
public void addComponentsToPane() {
add(new JLabel("Session", JLabel.CENTER));
add(new JLabel("SAS", JLabel.CENTER));
add(new JLabel("Status", JLabel.CENTER));
add(new JLabel("Method", JLabel.CENTER));
add(sessionType);
add(sasLabel);
add(secButton);
secButton.setEnabled(false);
add(secMethod);
add(sessionTypeV);
add(sasLabelV);
add(secButtonV);
add(secMethodV);
// Action to trigger SAS verification
secButton.addActionListener(new ActionListener() {
public void actionPerformed(ActionEvent e) {
boolean sucess = false;
Call call = participant.getCall();
if (call != null) {
OperationSetSecureTelephony secure = (OperationSetSecureTelephony) call
.getProtocolProvider().getOperationSet(
OperationSetSecureTelephony.class);
if (secure != null) {
sucess = secure.setSasVerified(participant,
!sasVerified);
}
if (sucess) {
if (sasVerified) {
sasVerified = false;
secButton.setIcon(iconEncr);
// secButton.setText("Sec");
} else {
sasVerified = true;
secButton.setIcon(iconEncrVerified);
// secButton.setText("Ver");
}
}
}
}
});
revalidate();
setVisible(true);
}
public void refreshStates(SecurityGUIEventZrtp securityEvent) {
HashMap<String, Object> state = securityEvent.getStates();
if (SecurityGUIEventZrtp.AUDIO.equals((String)state.get(SecurityGUIEventZrtp.SESSION_TYPE))) {
refreshStatesAudio(securityEvent);
}
if (SecurityGUIEventZrtp.VIDEO.equals((String)state.get(SecurityGUIEventZrtp.SESSION_TYPE))) {
refreshStatesVideo(securityEvent);
}
if (SecurityGUIEventZrtp.MSG_WARN.equals((String)state.get(SecurityGUIEventZrtp.SESSION_TYPE))) {
String text = (String)state.get(SecurityGUIEventZrtp.MSG_TEXT);
DisplayPopupMessage popup = new DisplayPopupMessage("ZRTP Security Warning", text);
popup.start();
}
revalidate();
}
private void refreshStatesAudio(SecurityGUIEventZrtp securityEvent) {
HashMap<String, Object> state = securityEvent.getStates();
sessionType.setText("Audio");
String sas = (String)state.get(SecurityGUIEventZrtp.SAS);
if (sas != null) {
// if SAS is provided then this event was sent by the ZRTP master (DH mode)
// store this participant for action calls via SecureTelephony operations
participant = (CallParticipant)securityEvent.getSource();
sasLabel.setText(sas);
Boolean verified = (Boolean)state.get(SecurityGUIEventZrtp.SAS_VERIFY);
if (verified.booleanValue()) {
secButton.setIcon(iconEncrVerified);
secButton.setEnabled(true);
sasVerified = true;
}
else {
sasVerified = false;
}
}
Boolean secure = (Boolean)state.get(SecurityGUIEventZrtp.SECURITY_CHANGE);
if (secure != null) {
if (secure.booleanValue()) {
secButton.setIcon(iconEncr);
secButton.setEnabled(true);
secMethod.setText((String)state.get(SecurityGUIEventZrtp.CIPHER));
notificationService.fireNotification(ZRTP_SECURE);
}
else {
secButton.setIcon(iconEncrDisabled);
secButton.setEnabled(false);
secMethod.setText("");
sasLabel.setText("");
}
}
}
private void refreshStatesVideo(SecurityGUIEventZrtp securityEvent) {
HashMap<String, Object> state = securityEvent.getStates();
sessionTypeV.setText("Video");
String sas = (String)state.get(SecurityGUIEventZrtp.SAS);
if (sas != null) {
// if SAS is provided then this event was sent by the ZRTP master (DH mode)
// store this participant for action calls via SecureTelephony operations
participant = (CallParticipant)securityEvent.getSource();
sasLabelV.setText(sas);
Boolean verified = (Boolean)state.get(SecurityGUIEventZrtp.SAS_VERIFY);
if (verified.booleanValue()) {
secButtonV.setIcon(iconEncrVerified);
}
}
Boolean secure = (Boolean)state.get(SecurityGUIEventZrtp.SECURITY_CHANGE);
if (secure != null) {
if (secure.booleanValue()) {
secButtonV.setIcon(iconEncr);
secMethodV.setText((String)state.get(SecurityGUIEventZrtp.CIPHER));
}
else {
secButtonV.setIcon(iconEncrDisabled);
secMethodV.setText("");
sasLabelV.setText("");
}
}
}
/**
* This small thread display messages that are relevant to the end user.
* Use an own thread not to block ZRTP processing.
*
* @author Werner Dittmann <Werner.Dittmann@t-online.de>
*
*/
private class DisplayPopupMessage extends Thread {
private final PopupDialog popupDialog;
private final String message;
private final String title;
DisplayPopupMessage(String title, String message) {
this.title = title;
this.message = message;
UIService uiService = GuiActivator.getUIService();
// Obtain the current UI implementation PopupDialog
popupDialog = uiService.getPopupDialog();
}
public void run() {
popupDialog.showMessagePopupDialog(message, title, PopupDialog.INFORMATION_MESSAGE);
}
}
}

@ -1602,7 +1602,7 @@ public JToolTip createToolTip()
Object element = listModel.getElementAt(index);
MetaContactTooltip tip = new MetaContactTooltip();
ExtendedTooltip tip = new ExtendedTooltip();
if (element instanceof MetaContact)
{
MetaContact metaContact = (MetaContact) element;
@ -1627,7 +1627,7 @@ public JToolTip createToolTip()
String contactAddress = protocolContact.getAddress();
String statusMessage = protocolContact.getStatusMessage();
tip.addProtocolContact(new ImageIcon(protocolStatusIcon),
tip.addLine(new ImageIcon(protocolStatusIcon),
contactAddress);
}
}
@ -1696,6 +1696,8 @@ public void addActiveContact(MetaContact metaContact)
if(!activeContacts.contains(metaContact))
this.activeContacts.add(metaContact);
}
this.refreshContact(metaContact);
}
/**
@ -1714,6 +1716,8 @@ public void removeActiveContact(MetaContact metaContact)
GuiActivator.getSystrayService().setSystrayIcon(
SystrayService.SC_IMG_TYPE);
}
this.refreshContact(metaContact);
}
/**

@ -321,7 +321,6 @@ public void messageReceived(MessageReceivedEvent evt)
// Show an envelope on the sender contact in the contact list and
// in the systray.
contactList.addActiveContact(metaContact);
contactList.refreshContact(metaContact);
// Obtain the corresponding chat panel.
final ChatPanel chatPanel

@ -4,7 +4,7 @@
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.gui.main.contactlist;
package net.java.sip.communicator.impl.gui.utils;
import java.awt.*;
@ -18,7 +18,7 @@
*
* @author Yana Stamcheva
*/
public class MetaContactTooltip
public class ExtendedTooltip
extends JToolTip
{
private static final int textRowHeight = 25;
@ -27,7 +27,7 @@ public class MetaContactTooltip
private final JLabel titleLabel = new JLabel();
private final JPanel protocolContactsPanel = new JPanel();
private final JPanel linesPanel = new JPanel();
private int textWidth;
@ -36,7 +36,7 @@ public class MetaContactTooltip
/**
* Created a <tt>MetaContactTooltip</tt>.
*/
public MetaContactTooltip()
public ExtendedTooltip()
{
this.setUI(new ImageToolTipUI());
@ -47,7 +47,7 @@ public MetaContactTooltip()
mainPanel.setOpaque(false);
centerPanel.setOpaque(false);
protocolContactsPanel.setOpaque(false);
linesPanel.setOpaque(false);
mainPanel.add(imageLabel, BorderLayout.WEST);
mainPanel.add(centerPanel, BorderLayout.CENTER);
@ -55,10 +55,10 @@ public MetaContactTooltip()
titleLabel.setFont(titleLabel.getFont().deriveFont(Font.BOLD));
centerPanel.add(titleLabel, BorderLayout.NORTH);
centerPanel.add(protocolContactsPanel, BorderLayout.CENTER);
centerPanel.add(linesPanel, BorderLayout.CENTER);
protocolContactsPanel.setLayout(
new BoxLayout(protocolContactsPanel, BoxLayout.Y_AXIS));
linesPanel.setLayout(
new BoxLayout(linesPanel, BoxLayout.Y_AXIS));
this.add(mainPanel);
}
@ -97,19 +97,23 @@ public void setTitle(String titleText)
* @param protocolContactIcon The icon for the protocol contact to add.
* @param protocolContactName The name of the protocol contact to add.
*/
public void addProtocolContact( ImageIcon protocolContactIcon,
String protocolContactName)
public void addLine(ImageIcon icon,
String text)
{
JLabel protocolContactLabel = new JLabel( protocolContactName,
protocolContactIcon,
JLabel.CENTER);
JLabel lineLabel = new JLabel( text,
icon,
JLabel.CENTER);
protocolContactsPanel.add(protocolContactLabel);
linesPanel.add(lineLabel);
int iconWidth = 0;
if (icon != null)
iconWidth = icon.getIconWidth();
int stringWidth
= GuiUtils.getStringWidth(protocolContactLabel, protocolContactName)
+ protocolContactIcon.getIconWidth()
+ protocolContactLabel.getIconTextGap();
= GuiUtils.getStringWidth(lineLabel, text)
+ iconWidth
+ lineLabel.getIconTextGap();
if (textWidth < stringWidth)
textWidth = stringWidth;

@ -377,6 +377,12 @@ public class ImageLoader {
public static final ImageID HOLD_BUTTON
= new ImageID("service.gui.buttons.HOLD_BUTTON");
/**
* A hold button icon for the full screen mode.
*/
public static final ImageID HOLD_BUTTON_FULL_SCREEN
= new ImageID("service.gui.buttons.HOLD_BUTTON_FULL_SCREEN");
/**
* The icon shown when the status of the call is "On hold".
*/
@ -395,6 +401,12 @@ public class ImageLoader {
public static final ImageID MUTE_BUTTON
= new ImageID("service.gui.buttons.MUTE_BUTTON");
/**
* A mute button icon for the full screen mode.
*/
public static final ImageID MUTE_BUTTON_FULL_SCREEN
= new ImageID("service.gui.buttons.MUTE_BUTTON_FULL_SCREEN");
/**
* A call-transfer button icon. The icon shown in the CallParticipant panel.
*/
@ -413,6 +425,30 @@ public class ImageLoader {
public static final ImageID SECURE_BUTTON_OFF =
new ImageID("service.gui.buttons.SECURE_BUTTON_OFF");
/**
* The secure button on icon. The icon shown in the CallParticipant panel.
*/
public static final ImageID SECURE_AUDIO_ON =
new ImageID("service.gui.buttons.SECURE_AUDIO_ON");
/**
* The secure button off icon. The icon shown in the CallParticipant panel.
*/
public static final ImageID SECURE_AUDIO_OFF =
new ImageID("service.gui.buttons.SECURE_AUDIO_OFF");
/**
* The secure button on icon. The icon shown in the CallParticipant panel.
*/
public static final ImageID SECURE_VIDEO_ON =
new ImageID("service.gui.buttons.SECURE_VIDEO_ON");
/**
* The secure button off icon. The icon shown in the CallParticipant panel.
*/
public static final ImageID SECURE_VIDEO_OFF =
new ImageID("service.gui.buttons.SECURE_VIDEO_OFF");
/**
* The security button: encryted and SAS verified, encrypted only, security off.
*/

@ -22,7 +22,9 @@ public class NotificationManager
public static final String BUSY_CALL = "BusyCall";
public static final String PROACTIVE_NOTIFICATION = "ProactiveNotification";
public static final String WARNING_MESSAGE = "WarningMessage";
public static void registerGuiNotifications()
{
NotificationService notificationService

@ -201,6 +201,16 @@ public class CallSessionImpl
*/
private static final byte ON_HOLD_REMOTELY = 1 << 2;
/**
* Indicates an audio session type.
*/
public static final String AUDIO_SESSION = "AUDIO_SESSION";
/**
* Indicates a video session type.
*/
public static final String VIDEO_SESSION = "VIDEO_SESSION";
/**
* The flags which determine whether this side of the call has put the other
* on hold and whether the other side of the call has put this on hold.
@ -2106,37 +2116,51 @@ private void initializeRtpManager(RTPManager rtpManager,
// The connector is created based also on the crypto services
// The crypto provider solution should be queried somehow
// or taken from a resources file
TransformConnector transConnector = TransformManager.createZRTPConnector(
TransformConnector transConnector
= TransformManager.createZRTPConnector(
bindAddress, this);
rtpManager.initialize(transConnector);
this.transConnectors.put(rtpManager, transConnector);
SCCallback callback = new SCCallback(this);
// Create security user callback for each participant.
SecurityEventManager securityEventManager
= new SecurityEventManager(this);
boolean zrtpAutoStart = false;
// 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
// - 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 (rtpManager.equals(audioRtpManager)) {
if (zrtpDHSession == null) {
// - 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 (rtpManager.equals(audioRtpManager))
{
if (zrtpDHSession == null)
{
zrtpDHSession = transConnector;
zrtpAutoStart = true;
callback.setDHSession(true);
securityEventManager.setDHSession(true);
}
callback.setType(SecurityGUIEventZrtp.AUDIO);
securityEventManager.setSessionType(AUDIO_SESSION);
}
else if (rtpManager.equals(videoRtpManager)) {
callback.setType(SecurityGUIEventZrtp.VIDEO);
else if (rtpManager.equals(videoRtpManager))
{
securityEventManager.setSessionType(VIDEO_SESSION);
}
// ZRTP engine initialization
ZRTPTransformEngine engine
= (ZRTPTransformEngine)transConnector.getEngine();
engine.setUserCallback(callback);
= (ZRTPTransformEngine) transConnector.getEngine();
engine.setUserCallback(securityEventManager);
// Case 1: user toggled secure communication prior to the call
// call is encrypted by default due to the option set in
@ -2145,16 +2169,16 @@ else if (rtpManager.equals(videoRtpManager)) {
{
if (engine.initialize("GNUZRTP4J.zid", zrtpAutoStart))
{
usingZRTP = true;
engine.sendInfo(
ZrtpCodes.MessageSeverity.Info,
EnumSet.of(
usingZRTP = true;
engine.sendInfo(
ZrtpCodes.MessageSeverity.Info,
EnumSet.of(
ZRTPCustomInfoCodes.ZRTPEnabledByDefault));
}
else
{
engine.sendInfo(ZrtpCodes.MessageSeverity.Info,
EnumSet.of(ZRTPCustomInfoCodes.ZRTPEngineInitFailure));
engine.sendInfo(ZrtpCodes.MessageSeverity.Info,
EnumSet.of(ZRTPCustomInfoCodes.ZRTPEngineInitFailure));
}
}
// Case 2: user will toggle secure communication during the call
@ -2938,7 +2962,7 @@ private void zrtpChangeStatus(RTPManager manager, SecureEvent event)
public int startZrtpMultiStreams()
{
ZRTPTransformEngine engine
= (ZRTPTransformEngine)zrtpDHSession.getEngine();
= (ZRTPTransformEngine) zrtpDHSession.getEngine();
int counter = 0;
byte[] multiStreamData = engine.getMultiStrParams();
@ -2948,11 +2972,11 @@ public int startZrtpMultiStreams()
while (tcs.hasMoreElements())
{
TransformConnector tc = tcs.nextElement();
if (tc.equals(zrtpDHSession))
{
continue;
}
engine = (ZRTPTransformEngine)tc.getEngine();
engine = (ZRTPTransformEngine) tc.getEngine();
engine.setMultiStrParams(multiStreamData);
engine.setEnableZrtp(true);
counter++;

@ -12,6 +12,7 @@
import net.java.sip.communicator.impl.media.transform.srtp.*;
import net.java.sip.communicator.impl.media.transform.zrtp.*;
import net.java.sip.communicator.service.media.*;
import net.java.sip.communicator.util.*;
/**
* TransformManager class encapsulate the logic of creating different kinds of
@ -22,8 +23,10 @@
* @author Emanuel Onica (eonica@info.uaic.ro)
*/
public class TransformManager
{
{
private static final Logger logger
= Logger.getLogger(TransformManager.class);
/**
* Create a SRTP TransformConnector, which will provide SRTP encryption /
* decryption functionality, using algorithms defined in RFC3711.
@ -34,17 +37,17 @@ public class TransformManager
* @param srtpPolicy SRTP policy for this SRTP session
* @param srtcpPolicy SRTCP policy for this SRTP session
* @param cryptoProvider the cryptography services provider selection string
* should be obtained from a resource file or by querying
* should be obtained from a resource file or by querying
* @return the TransformConnector used for SRTP encyption/decryption
* @throws InvalidSessionAddressException if the local RTP session address
* is invalid
*/
public static TransformConnector createSRTPConnector(SessionAddress addr,
byte[] masterKey,
byte[] masterSalt,
byte[] masterKey,
byte[] masterSalt,
SRTPPolicy srtpPolicy,
SRTPPolicy srtcpPolicy)
throws InvalidSessionAddressException
throws InvalidSessionAddressException
{
SRTPTransformEngine engine = null;
@ -63,7 +66,7 @@ public static TransformConnector createSRTPConnector(SessionAddress addr,
*
* @param addr local RTP session listen address
* @param cryptoProvider the cryptography services provider selection string
* should be obtained from a resource file or by querying
* should be obtained from a resource file or by querying
* @return the TransformConnector used for SRTP encyption/decryption
* @throws InvalidSessionAddressException
*/
@ -72,22 +75,20 @@ public static TransformConnector createZRTPConnector(SessionAddress addr,
throws InvalidSessionAddressException
{
//for adding multistream support the engine should be instantiated
//once as a static variable of this class and passed to every ZRTP
//connector as a parameter
//once as a static variable of this class and passed to every ZRTP
//connector as a parameter
ZRTPTransformEngine engine = new ZRTPTransformEngine();
TransformConnector connector = null;
connector = new ZrtpTransformConnector(addr, engine);
TransformConnector connector = new ZrtpTransformConnector(addr, engine);
//for adding multistream support this method should be replaced with
//an addConnector, which should add the connector to an internal engine
//connector array; supporting multistream mode by the engine implies
//the proper management of this connector array - practically every
//stream has it's own connector
engine.setConnector(connector);
return connector;
engine.setConnector(connector);
return connector;
}
/**
@ -106,6 +107,7 @@ public static TransformConnector createDummyConnector(SessionAddress addr)
{
DummyTransformEngine engine = new DummyTransformEngine();
TransformConnector connector = new TransformConnector(addr, engine);
return connector;
}
}

@ -1,341 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.media.transform.zrtp;
import java.util.*;
import net.java.sip.communicator.impl.media.CallSessionImpl;
import net.java.sip.communicator.impl.media.MediaActivator;
import net.java.sip.communicator.service.media.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.util.Logger;
import net.java.sip.communicator.service.protocol.event.*;
import gnu.java.zrtp.*;
/**
* The user callback class for ZRTP4J.
*
* This class constructs and sends events to the ZRTP GUI implementation. The
* <code>showMessage()<code> function implements a specific check to start
* associated ZRTP multi-stream sessions.
*
* Coordinate this callback class with the associated GUI implementation class
* net.java.sip.communicator.impl.gui.main.call.ZrtpPanel
*
* @see net.java.sip.communicator.impl.gui.main.call.ZrtpPanel
*
* @author Emanuel Onica
* @author Werner Dittmann
*
*/
public class SCCallback extends ZrtpUserCallback {
private static final Logger logger = Logger.getLogger(SCCallback.class);
public static final String WARNING_NO_RS_MATCH = MediaActivator
.getResources().getI18NString(
"impl.media.security.WARNING_NO_RS_MATCH");
public static final String WARNING_NO_EXPECTED_RS_MATCH = MediaActivator
.getResources().getI18NString(
"impl.media.security.WARNING_NO_EXPECTED_RS_MATCH");
private CallSession callSession = null;
private SecurityGUIListener guiListener = null;
private CallParticipant participant;
/*
* Is this a ZRTP DH (Master) session?
*/
private boolean dhSession = false;
/*
* Type of session. See class SecurityGUIEventZrtp which types are
* supported.
*/
private String sessionType = null;
/*
* Remember the cipher name
*/
private String cipherName = null;
/*
* Remember the SAS
*/
private String sasData = null;
/*
* Remember SAS verification state
*/
private boolean sasVerification = false;
/**
* The class constructor.
*/
public SCCallback(CallSession callSession) {
this.callSession = callSession;
guiListener = callSession.getCall().getSecurityGUIListener("zrtp");
Iterator<CallParticipant> participants = callSession.getCall()
.getCallParticipants();
if (participants.hasNext())
participant = participants.next();
}
public void init() {
SecurityGUIEvent evt = new SecurityGUIEvent(participant,
SecurityGUIEvent.NONE, SecurityGUIEvent.SECURITY_ENABLED);
if (logger.isInfoEnabled())
logger.info(sessionType + ": initialize SCCallback");
fireStateChangedEvent(evt);
}
private void fireStateChangedEvent(SecurityGUIEvent evt) {
if (guiListener != null) {
guiListener.securityStatusChanged(evt);
} else {
guiListener = callSession.getCall().getSecurityGUIListener("zrtp");
if (guiListener != null) {
guiListener.securityStatusChanged(evt);
}
}
}
/**
* Set the type of this session.
*
* @param type
*/
public void setType(String type) {
sessionType = type;
}
/**
* Set the DH session flag.
*
* @param yesNo
*/
public void setDHSession(boolean yesNo) {
dhSession = yesNo;
}
/*
* The following methods implement the ZrtpUserCallback interface
*/
/*
* (non-Javadoc)
*
* @see gnu.java.zrtp.ZrtpUserCallback#secureOn(java.lang.String)
*/
public void secureOn(String cipher) {
if (logger.isInfoEnabled())
logger.info(sessionType + ": cipher enabled: " + cipher);
cipherName = cipher;
}
/*
* (non-Javadoc)
*
* @see gnu.java.zrtp.ZrtpUserCallback#showSAS(java.lang.String, boolean)
*/
public void showSAS(String sas, boolean verified) {
if (logger.isInfoEnabled())
logger.info(sessionType + ": SAS is: " + sas);
sasData = sas;
sasVerification = verified;
}
/*
* (non-Javadoc)
*
* @see gnu.java.zrtp.ZrtpUserCallback#showMessage(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity, java.util.EnumSet)
*/
public void showMessage(ZrtpCodes.MessageSeverity sev, EnumSet<?> subCode) {
int multiStreams = 0;
HashMap<String, Object> state = new HashMap<String, Object>(5);
boolean fireEvent = false;
Iterator<?> ii = subCode.iterator();
Object msgCode = ii.next();
if (sev == ZrtpCodes.MessageSeverity.Info) {
if (msgCode instanceof ZrtpCodes.InfoCodes) {
ZrtpCodes.InfoCodes inf = (ZrtpCodes.InfoCodes) msgCode;
// If the ZRTP Master session (DH mode) signals "security on"
// then start multi-stream sessions.
// Signal SAS to GUI only if this is a DH mode session.
// Multi-stream session don't have own SAS data
if (inf == ZrtpCodes.InfoCodes.InfoSecureStateOn) {
if (dhSession) {
multiStreams = ((CallSessionImpl) callSession)
.startZrtpMultiStreams();
state.put(SecurityGUIEventZrtp.SAS, sasData);
if (sasVerification) {
state.put(SecurityGUIEventZrtp.SAS_VERIFY,
Boolean.TRUE);
} else {
state.put(SecurityGUIEventZrtp.SAS_VERIFY,
Boolean.FALSE);
}
}
state.put(SecurityGUIEventZrtp.SESSION_TYPE, sessionType);
state.put(SecurityGUIEventZrtp.SECURITY_CHANGE,
Boolean.TRUE);
state.put(SecurityGUIEventZrtp.CIPHER, cipherName);
fireEvent = true;
}
if (inf == ZrtpCodes.InfoCodes.InfoHelloReceived) {
state.put(SecurityGUIEventZrtp.SESSION_TYPE,
SecurityGUIEventZrtp.MSG_INFO);
fireEvent = true;
}
}
}
/*
* Warning codes usually do not affect encryption or security. Onl
* in few cases inform the user and ask to verify SAS
*/
if (sev == ZrtpCodes.MessageSeverity.Warning) {
if (msgCode instanceof ZrtpCodes.WarningCodes) {
ZrtpCodes.WarningCodes warn = (ZrtpCodes.WarningCodes) msgCode;
if (warn == ZrtpCodes.WarningCodes.WarningNoRSMatch) {
state.put(SecurityGUIEventZrtp.SESSION_TYPE,
SecurityGUIEventZrtp.MSG_WARN);
state.put(SecurityGUIEventZrtp.MSG_TEXT,
WARNING_NO_RS_MATCH);
fireEvent = true;
}
if (warn == ZrtpCodes.WarningCodes.WarningNoExpectedRSMatch) {
state.put(SecurityGUIEventZrtp.SESSION_TYPE,
SecurityGUIEventZrtp.MSG_WARN);
state.put(SecurityGUIEventZrtp.MSG_TEXT,
WARNING_NO_EXPECTED_RS_MATCH);
fireEvent = true;
}
}
}
/*
* Severe or ZRTP error codes always signal that security cannot be established.
* Inform the user about this.
*/
if (sev == ZrtpCodes.MessageSeverity.Severe) {
String[] param = new String[1];
param[0] = msgCode.toString();
String msg = MediaActivator
.getResources().getI18NString(
"impl.media.security.SEVERE_GENERIC_MSG", param);
state.put(SecurityGUIEventZrtp.SESSION_TYPE,
SecurityGUIEventZrtp.MSG_SEVERE);
state.put(SecurityGUIEventZrtp.MSG_TEXT, msg);
fireEvent = true;
}
if (sev == ZrtpCodes.MessageSeverity.ZrtpError) {
String[] param = new String[1];
param[0] = msgCode.toString();
String msg = MediaActivator
.getResources().getI18NString(
"impl.media.security.ZRTP_GENERIC_MSG", param);
state.put(SecurityGUIEventZrtp.SESSION_TYPE,
SecurityGUIEventZrtp.MSG_ZRTP);
state.put(SecurityGUIEventZrtp.MSG_TEXT, msg);
fireEvent = true;
}
if (fireEvent) {
SecurityGUIEventZrtp evt = new SecurityGUIEventZrtp(participant,
state);
fireStateChangedEvent(evt);
}
if (logger.isInfoEnabled()) {
logger.info(sessionType + ": " + "ZRTP message: severity: " + sev
+ ", sub code: " + msgCode + ", DH session: " + dhSession
+ ", multi: " + multiStreams);
}
}
/*
* (non-Javadoc)
*
* @see gnu.java.zrtp.ZrtpUserCallback#zrtpNegotiationFailed(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity, java.util.EnumSet)
*/
public void zrtpNegotiationFailed(ZrtpCodes.MessageSeverity severity,
EnumSet<?> subCode) {
Iterator<?> ii = subCode.iterator();
Object msgCode = ii.next();
if (logger.isInfoEnabled())
logger.warn(sessionType
+ ": ZRTP key negotiation failed, sub code: " + msgCode);
}
/*
* (non-Javadoc)
*
* @see gnu.java.zrtp.ZrtpUserCallback#secureOff()
*/
public void secureOff() {
if (logger.isInfoEnabled())
logger.info(sessionType + ": Security off");
HashMap<String, Object> state = new HashMap<String, Object>(2);
state
.put(SecurityGUIEventZrtp.SESSION_TYPE,
SecurityGUIEventZrtp.AUDIO);
state.put(SecurityGUIEventZrtp.SECURITY_CHANGE, Boolean.FALSE);
SecurityGUIEventZrtp evt = new SecurityGUIEventZrtp(participant, state);
fireStateChangedEvent(evt);
}
/*
* (non-Javadoc)
*
* @see gnu.java.zrtp.ZrtpUserCallback#zrtpNotSuppOther()
*/
public void zrtpNotSuppOther() {
if (logger.isInfoEnabled())
logger
.info(sessionType
+ ": Other party does not support ZRTP key negotiation protocol, no secure calls possible");
}
/*
* (non-Javadoc)
*
* @see gnu.java.zrtp.ZrtpUserCallback#confirmGoClear()
*/
public void confirmGoClear() {
if (logger.isInfoEnabled())
logger.info(sessionType + ": GoClear confirmation requested");
}
}

@ -0,0 +1,333 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.impl.media.transform.zrtp;
import gnu.java.zrtp.*;
import java.util.*;
import net.java.sip.communicator.impl.media.*;
import net.java.sip.communicator.service.media.*;
import net.java.sip.communicator.service.protocol.*;
import net.java.sip.communicator.service.protocol.event.*;
import net.java.sip.communicator.util.*;
/**
* The user callback class for ZRTP4J.
*
* This class constructs and sends events to the ZRTP GUI implementation. The
* <code>showMessage()<code> function implements a specific check to start
* associated ZRTP multi-stream sessions.
*
* Coordinate this callback class with the associated GUI implementation class
* net.java.sip.communicator.impl.gui.main.call.ZrtpPanel
*
* @see net.java.sip.communicator.impl.gui.main.call.SecurityPanel
*
* @author Emanuel Onica
* @author Werner Dittmann
* @author Yana Stamcheva
*
*/
public class SecurityEventManager extends ZrtpUserCallback
{
private static final Logger logger
= Logger.getLogger(SecurityEventManager.class);
public static final String WARNING_NO_RS_MATCH = MediaActivator
.getResources().getI18NString(
"impl.media.security.WARNING_NO_RS_MATCH");
public static final String WARNING_NO_EXPECTED_RS_MATCH = MediaActivator
.getResources().getI18NString(
"impl.media.security.WARNING_NO_EXPECTED_RS_MATCH");
private CallParticipant callParticipant;
private CallSession callSession;
/**
* Is this a ZRTP DH (Master) session?
*/
private boolean isDHSession = false;
/**
* Type of session
*/
private String sessionType;
/**
* SAS string.
*/
private String sas;
/**
* Cipher.
*/
private String cipher;
/**
* Indicates if the SAS has already been verified in a previous session.
*/
private boolean isSasVerified;
/**
* The class constructor.
*/
public SecurityEventManager(CallSession callSession)
{
this.callSession = callSession;
// At this moment we're supporting a security call between only two
// participants. In the future the call participant would be passed
// as a parameter to the SecurityEventManager.
Iterator<CallParticipant> callParticipants
= callSession.getCall().getCallParticipants();
while (callParticipants.hasNext())
{
this.callParticipant = callParticipants.next();
}
}
/**
* Set the type of this session.
*
* @param type the session type. The session type could be either
* CallSessionImpl.AUDIO_SESSION or CallSessionImpl.VIDEO_SESSION.
*/
public void setSessionType(String type)
{
if (type.equals(CallSessionImpl.AUDIO_SESSION))
sessionType = CallParticipantSecurityStatusEvent.AUDIO_SESSION;
else if (type.equals(CallSessionImpl.VIDEO_SESSION))
sessionType = CallParticipantSecurityStatusEvent.VIDEO_SESSION;
}
/**
* Set the DH session flag.
*
* @param isDHSession the DH session flag.
*/
public void setDHSession(boolean isDHSession)
{
this.isDHSession = isDHSession;
}
/*
* The following methods implement the ZrtpUserCallback interface
*/
/**
* Reports the security algorithm that the ZRTP protocol negotiated.
*
* @see gnu.java.zrtp.ZrtpUserCallback#secureOn(java.lang.String)
*/
public void secureOn(String cipher)
{
if (logger.isInfoEnabled())
logger.info(sessionType + ": cipher enabled: " + cipher);
this.cipher = cipher;
}
/**
* ZRTP computes the SAS string after nearly all the negotiation
* and computations are done internally.
*
* @see gnu.java.zrtp.ZrtpUserCallback#showSAS(java.lang.String, boolean)
*/
public void showSAS(String sas, boolean isVerified)
{
if (logger.isInfoEnabled())
logger.info(sessionType + ": SAS is: " + sas);
this.sas = sas;
this.isSasVerified = isVerified;
}
/**
* @see gnu.java.zrtp.ZrtpUserCallback#showMessage(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity, java.util.EnumSet)
*/
public void showMessage(ZrtpCodes.MessageSeverity sev,
EnumSet<?> subCode)
{
int multiStreams = 0;
Iterator<?> ii = subCode.iterator();
Object msgCode = ii.next();
String messageType = null;
String message = null;
String i18nMessage = null;
if (msgCode instanceof ZrtpCodes.InfoCodes)
{
ZrtpCodes.InfoCodes inf = (ZrtpCodes.InfoCodes) msgCode;
// If the ZRTP Master session (DH mode) signals "security on"
// then start multi-stream sessions.
// Signal SAS to GUI only if this is a DH mode session.
// Multi-stream session don't have own SAS data
if (inf == ZrtpCodes.InfoCodes.InfoSecureStateOn)
{
if (isDHSession)
{
multiStreams = ((CallSessionImpl) callSession)
.startZrtpMultiStreams();
((AbstractCallParticipant) callParticipant)
.setSecurityOn( true,
sessionType,
cipher,
sas,
isSasVerified);
}
}
}
else if (msgCode instanceof ZrtpCodes.WarningCodes)
{
// Warning codes usually do not affect encryption or security. Only
// in few cases inform the user and ask to verify SAS.
ZrtpCodes.WarningCodes warn = (ZrtpCodes.WarningCodes) msgCode;
if (warn == ZrtpCodes.WarningCodes.WarningNoRSMatch)
{
messageType = CallParticipantSecurityMessageEvent
.SECURITY_AUTHENTICATION_REQUIRED;
message = "No retained shared secret available.";
i18nMessage = WARNING_NO_RS_MATCH;
}
else if (warn == ZrtpCodes.WarningCodes.WarningNoExpectedRSMatch)
{
messageType = CallParticipantSecurityMessageEvent
.RETAINED_SECURITY_AUTHENTICATION_FAILED;
message = "An expected retained shared secret is missing.";
i18nMessage = WARNING_NO_EXPECTED_RS_MATCH;
}
else if (warn == ZrtpCodes.WarningCodes.WarningCRCmismatch)
{
messageType = CallParticipantSecurityMessageEvent
.CHECKSUM_MISMATCH;
message = "Internal ZRTP packet checksum mismatch.";
i18nMessage = MediaActivator.getResources().getI18NString(
"impl.media.security.CHECKSUM_MISMATCH");
}
}
else if (msgCode instanceof ZrtpCodes.SevereCodes)
{
ZrtpCodes.SevereCodes severe = (ZrtpCodes.SevereCodes) msgCode;
if (severe == ZrtpCodes.SevereCodes.SevereCannotSend)
{
messageType = CallParticipantSecurityMessageEvent
.DATA_SEND_FAILED;
message = "Failed to send data."
+ "Internet data connection or peer is down.";
i18nMessage = MediaActivator.getResources().getI18NString(
"impl.media.security.DATA_SEND_FAILED",
new String[]{msgCode.toString()});
}
else if (severe == ZrtpCodes.SevereCodes.SevereTooMuchRetries)
{
messageType = CallParticipantSecurityMessageEvent
.RETRY_RATE_EXCEEDED;
message = "Too much retries during ZRTP negotiation.";
i18nMessage = MediaActivator.getResources().getI18NString(
"impl.media.security.RETRY_RATE_EXCEEDED",
new String[]{msgCode.toString()});
}
else if (severe == ZrtpCodes.SevereCodes.SevereProtocolError)
{
messageType = CallParticipantSecurityMessageEvent
.INTERNAL_PROTOCOL_ERROR;
message = "Internal protocol error occured.";
i18nMessage = MediaActivator.getResources().getI18NString(
"impl.media.security.INTERNAL_PROTOCOL_ERROR",
new String[]{msgCode.toString()});
}
else
{
messageType = CallParticipantSecurityMessageEvent.GENERAL_ERROR;
message = "General error has occurred.";
i18nMessage = MediaActivator.getResources().getI18NString(
"impl.media.security.ZRTP_GENERIC_MSG",
new String[]{msgCode.toString()});
}
}
else if (msgCode instanceof ZrtpCodes.ZrtpErrorCodes)
{
messageType = CallParticipantSecurityMessageEvent.NOT_COMPATIBLE;
message = "Indicates compatibility problems like for example:"
+ "unsupported protocol version, unsupported hash type,"
+ "cypher type, SAS scheme, etc.";
i18nMessage = MediaActivator.getResources().getI18NString(
"impl.media.security.ZRTP_GENERIC_MSG",
new String[]{msgCode.toString()});
}
if (messageType != null)
((AbstractCallParticipant) callParticipant)
.setSecurityMessage(messageType, message, i18nMessage);
if (logger.isInfoEnabled())
{
logger.info(sessionType + ": " + "ZRTP message: severity: " + sev
+ ", sub code: " + msgCode + ", DH session: " + isDHSession
+ ", multi: " + multiStreams);
}
}
/**
* @see gnu.java.zrtp.ZrtpUserCallback#zrtpNegotiationFailed(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity, java.util.EnumSet)
*/
public void zrtpNegotiationFailed( ZrtpCodes.MessageSeverity severity,
EnumSet<?> subCode)
{
Iterator<?> ii = subCode.iterator();
Object msgCode = ii.next();
if (logger.isInfoEnabled())
logger.info(sessionType
+ ": ZRTP key negotiation failed, sub code: " + msgCode);
}
/**
* @see gnu.java.zrtp.ZrtpUserCallback#secureOff()
*/
public void secureOff()
{
if (logger.isInfoEnabled())
logger.info(sessionType + ": Security off");
((AbstractCallParticipant) callParticipant)
.setSecurityOff(sessionType);
}
/**
* @see gnu.java.zrtp.ZrtpUserCallback#zrtpNotSuppOther()
*/
public void zrtpNotSuppOther()
{
if (logger.isInfoEnabled())
logger.info(sessionType
+ ": Other party does not support ZRTP key negotiation protocol,"
+ " no secure calls possible.");
}
/**
* @see gnu.java.zrtp.ZrtpUserCallback#confirmGoClear()
*/
public void confirmGoClear()
{
if (logger.isInfoEnabled())
logger.info(sessionType + ": GoClear confirmation requested.");
}
}

@ -15,11 +15,11 @@
import net.java.sip.communicator.impl.media.transform.*;
import net.java.sip.communicator.impl.media.transform.srtp.*;
import net.java.sip.communicator.service.fileaccess.*;
import net.java.sip.communicator.util.*;
import java.io.*;
import java.util.EnumSet;
/**
* JMF extension/connector to support GNU ZRTP4J.
*
@ -146,9 +146,10 @@
*
*/
public class ZRTPTransformEngine
implements TransformEngine, PacketTransformer, ZrtpCallback
implements TransformEngine,
PacketTransformer,
ZrtpCallback
{
/**
* Very simple Timeout provider class.
*
@ -160,7 +161,6 @@ public class ZRTPTransformEngine
*/
class TimeoutProvider extends Thread
{
public TimeoutProvider(String name)
{
super(name);
@ -250,7 +250,12 @@ public void run()
}
}
// each ZRTP packet has a fixed header of 12 bytes
private static final Logger logger
= Logger.getLogger(ZRTPTransformEngine.class);
/**
* Each ZRTP packet has a fixed header of 12 bytes.
*/
protected static final int ZRTP_PACKET_HEADER = 12;
/**
@ -272,7 +277,7 @@ public void run()
/**
* User callback class.
*/
private SCCallback userCallback = null;
private SecurityEventManager securityEventManager = null;
/**
* The ZRTP engine.
@ -327,12 +332,12 @@ public void run()
*/
public ZRTPTransformEngine()
{
senderZrtpSeqNo = 1; // should be a random number
senderZrtpSeqNo = 1; // should be a random number
}
/*
* (non-Javadoc)
*
/**
* Returns an instance of <tt>ZRTPCTransformer</tt>.
*
* @see net.java.sip.communicator.impl.media.transform.
* TransformEngine#getRTCPTransformer()
*/
@ -341,9 +346,9 @@ public PacketTransformer getRTCPTransformer()
return new ZRTPCTransformer(this);
}
/*
* (non-Javadoc)
*
/**
* Returns this RTPTransformer.
*
* @see net.java.sip.communicator.impl.media.transform.
* TransformEngine#getRTPTransformer()
*/
@ -392,8 +397,10 @@ public synchronized boolean initialize(String zidFilename,
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
logger.warn("Failed to create the zid file.");
if (logger.isDebugEnabled())
logger.debug("Failed to create the zid file.", e);
}
String zidFilePath = null;
@ -404,8 +411,9 @@ public synchronized boolean initialize(String zidFilename,
}
catch (SecurityException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
if (logger.isDebugEnabled())
logger.debug(
"Failed to obtain the absolute path of the zid file.", e);
}
ZidFile zf = ZidFile.getInstance();
@ -429,6 +437,7 @@ public synchronized boolean initialize(String zidFilename,
return false;
}
}
zrtpEngine = new ZRtp(zf.getZid(), this, clientIdString);
if (timeoutProvider == null)
@ -437,17 +446,18 @@ public synchronized boolean initialize(String zidFilename,
timeoutProvider.setDaemon(true);
timeoutProvider.start();
}
userCallback.init();
enableZrtp = autoEnable;
return true;
}
/**
* Start the ZRTP stack immediately, not autosensing mode.
*
*/
public void startZrtp() {
if (zrtpEngine != null) {
public void startZrtp()
{
if (zrtpEngine != null)
{
zrtpEngine.startZrtpEngine();
started = true;
}
@ -455,10 +465,11 @@ public void startZrtp() {
/**
* Stop ZRTP engine.
*
*/
public void stopZrtp() {
if (zrtpEngine != null) {
public void stopZrtp()
{
if (zrtpEngine != null)
{
zrtpEngine.stopZrtp();
zrtpEngine = null;
started = false;
@ -468,20 +479,21 @@ public void stopZrtp() {
/**
* Cleanup function for any remaining timers
*/
public void cleanup() {
if (timeoutProvider != null) {
public void cleanup()
{
if (timeoutProvider != null)
{
timeoutProvider.stopRun();
timeoutProvider = null;
}
}
/* (non-Javadoc)
* @see net.java.sip.communicator.impl.media.transform.PacketTransformer#
* transform(net.java.sip.communicator.impl.media.transform.RawPacket)
*/
/*
/**
* The data output stream calls this method to transform outgoing
* packets.
*
* @see net.java.sip.communicator.impl.media.transform.PacketTransformer#
* transform(net.java.sip.communicator.impl.media.transform.RawPacket)
*/
public RawPacket transform(RawPacket pkt)
{
@ -507,33 +519,30 @@ public RawPacket transform(RawPacket pkt)
return null;
*/
/*
* ZRTP needs the SSRC of the sending stream.
*/
// ZRTP needs the SSRC of the sending stream.
if (enableZrtp && ownSSRC == 0)
{
ownSSRC = zPkt.getSSRC();
}
/*
* If SRTP is active then srtpTransformer is set, use it.
*/
// If SRTP is active then srtpTransformer is set, use it.
sendPacketCount++;
if (srtpOutTransformer == null)
{
return pkt;
}
return srtpOutTransformer.transform(pkt);
}
/* (non-Javadoc)
/**
* The input data stream calls this method to transform
* incoming packets.
*
* @see net.java.sip.communicator.impl.media.transform.PacketTransformer#
* reverseTransform(
* net.java.sip.communicator.impl.media.transform.RawPacket)
*/
/*
* The input data stream calls this method to transfrom
* incoming packets.
*/
public RawPacket reverseTransform(RawPacket pkt)
{
ZrtpRawPacket zPkt = new ZrtpRawPacket(pkt);
@ -572,7 +581,7 @@ public RawPacket reverseTransform(RawPacket pkt)
{
if (!zPkt.checkCrc())
{
userCallback.showMessage(ZrtpCodes.MessageSeverity.Warning,
securityEventManager.showMessage(ZrtpCodes.MessageSeverity.Warning,
EnumSet.of(ZrtpCodes.WarningCodes.WarningCRCmismatch));
return null;
}
@ -588,7 +597,7 @@ public RawPacket reverseTransform(RawPacket pkt)
}
/**
* The callback method required by the ZRTP implementation
* The callback method required by the ZRTP implementation.
* First allocate space to hold the complete ZRTP packet, copy
* the message part in its place, the initalize the header, counter,
* SSRC and crc.
@ -598,7 +607,6 @@ public RawPacket reverseTransform(RawPacket pkt)
*/
public boolean sendDataZRTP(byte[] data)
{
int totalLength = ZRTP_PACKET_HEADER + data.length;
byte[] tmp = new byte[totalLength];
System.arraycopy(data, 0, tmp, ZRTP_PACKET_HEADER, data.length);
@ -612,20 +620,24 @@ public boolean sendDataZRTP(byte[] data)
try
{
zrtpConnector.getDataOutputStream().write(packet.getBuffer(),
packet.getOffset(), packet.getLength());
zrtpConnector.getDataOutputStream().write( packet.getBuffer(),
packet.getOffset(),
packet.getLength());
}
catch (IOException e)
{
// TODO Auto-generated catch block
e.printStackTrace();
logger.warn("Failed to send ZRTP data.");
if (logger.isDebugEnabled())
logger.debug("Failed to send ZRTP data.", e);
return false;
}
return true;
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#srtpSecretsReady(
* gnu.java.zrtp.ZrtpSrtpSecrets,
* gnu.java.zrtp.ZrtpCallback.EnableSecurity)
@ -633,12 +645,11 @@ public boolean sendDataZRTP(byte[] data)
public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets,
EnableSecurity part)
{
SRTPPolicy srtpPolicy = null;
if (part == EnableSecurity.ForSender)
{
// To encrypt packets: intiator uses initiator keys,
// To encrypt packets: initiator uses initiator keys,
// responder uses responder keys
// Create a "half baked" crypto context first and store it. This is
// the main crypto context for the sending part of the connection.
@ -651,9 +662,11 @@ public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets,
secrets.getSrtpAuthTagLen() / 8,// auth tag length
secrets.getInitSaltLen() / 8 // salt length
);
SRTPTransformEngine engine = new SRTPTransformEngine(secrets
.getKeyInitiator(), secrets.getSaltInitiator(),
srtpPolicy, srtpPolicy);
srtpOutTransformer = engine.getRTPTransformer();
}
else
@ -672,9 +685,10 @@ public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets,
srtpOutTransformer = engine.getRTPTransformer();
}
}
if (part == EnableSecurity.ForReceiver)
{
// To decrypt packets: intiator uses responder keys,
// To decrypt packets: initiator uses responder keys,
// responder initiator keys
// See comment above.
if (secrets.getRole() == Role.Initiator)
@ -711,25 +725,26 @@ public boolean srtpSecretsReady(ZrtpSrtpSecrets secrets,
return true;
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#srtpSecretsOn(java.lang.String,
* java.lang.String, boolean)
*/
public void srtpSecretsOn(String c, String s, boolean verified)
{
if (userCallback != null)
if (securityEventManager != null)
{
userCallback.secureOn(c);
securityEventManager.secureOn(c);
}
if (userCallback != null && s != null)
if (securityEventManager != null && s != null)
{
userCallback.showSAS(s, verified);
securityEventManager.showSAS(s, verified);
}
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#srtpSecretsOff(
* gnu.java.zrtp.ZrtpCallback.EnableSecurity)
*/
@ -739,18 +754,20 @@ public void srtpSecretsOff(EnableSecurity part)
{
srtpOutTransformer = null;
}
if (part == EnableSecurity.ForReceiver)
{
srtpInTransformer = null;
}
if (userCallback != null)
if (securityEventManager != null)
{
userCallback.secureOff();
securityEventManager.secureOff();
}
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#activateTimer(int)
*/
public int activateTimer(int time)
@ -759,11 +776,12 @@ public int activateTimer(int time)
{
timeoutProvider.requestTimeout(time, this);
}
return 1;
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#cancelTimer()
*/
public int cancelTimer()
@ -781,27 +799,28 @@ public int cancelTimer()
*/
public void handleTimeout()
{
if (zrtpEngine != null) {
if (zrtpEngine != null)
{
zrtpEngine.processTimeout();
}
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#sendInfo(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity,
* java.util.EnumSet)
*/
public void sendInfo(ZrtpCodes.MessageSeverity severity, EnumSet<?> subCode)
{
if (userCallback != null)
if (securityEventManager != null)
{
userCallback.showMessage(severity, subCode);
securityEventManager.showMessage(severity, subCode);
}
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#zrtpNegotiationFailed(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity,
* java.util.EnumSet)
@ -809,14 +828,14 @@ public void sendInfo(ZrtpCodes.MessageSeverity severity, EnumSet<?> subCode)
public void zrtpNegotiationFailed(ZrtpCodes.MessageSeverity severity,
EnumSet<?> subCode)
{
if (userCallback != null)
if (securityEventManager != null)
{
userCallback.zrtpNegotiationFailed(severity, subCode);
securityEventManager.zrtpNegotiationFailed(severity, subCode);
}
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#goClearProcedureFailed(
* gnu.java.zrtp.ZrtpCodes.MessageSeverity,
* java.util.EnumSet, boolean)
@ -832,69 +851,68 @@ public void goClearProcedureFailed(ZrtpCodes.MessageSeverity severity,
// }
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#zrtpNotSuppOther()
*/
public void zrtpNotSuppOther()
{
if (userCallback != null)
if (securityEventManager != null)
{
userCallback.zrtpNotSuppOther();
securityEventManager.zrtpNotSuppOther();
}
}
/*
* (non-Javadoc)
/**
* @see gnu.java.zrtp.ZrtpCallback#zrtpAskEnrollment(java.lang.String)
*/
public void zrtpAskEnrollment(String info)
{
if (userCallback != null)
if (securityEventManager != null)
{
userCallback.zrtpAskEnrollment(info);
securityEventManager.zrtpAskEnrollment(info);
}
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#zrtpInformEnrollment(java.lang.String)
*/
public void zrtpInformEnrollment(String info)
{
if (userCallback != null)
if (securityEventManager != null)
{
userCallback.zrtpInformEnrollment(info);
securityEventManager.zrtpInformEnrollment(info);
}
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#signSAS(java.lang.String)
*/
public void signSAS(String sas)
{
if (userCallback != null)
if (securityEventManager != null)
{
userCallback.signSAS(sas);
securityEventManager.signSAS(sas);
}
}
/*
* (non-Javadoc)
/**
*
* @see gnu.java.zrtp.ZrtpCallback#checkSASSignature(java.lang.String)
*/
public boolean checkSASSignature(String sas)
{
return ((userCallback != null)
? userCallback.checkSASSignature(sas)
return ((securityEventManager != null)
? securityEventManager.checkSASSignature(sas)
: false);
}
/**
* Sets the enableZrtp flag
* Sets the enableZrtp flag.
*
* @param onOff The value for the enableZrtp flag
* @param onOff The value for the enableZrtp flag.
*/
public void setEnableZrtp(boolean onOff)
{
@ -902,9 +920,9 @@ public void setEnableZrtp(boolean onOff)
}
/**
* Returns the enableZrtp flag
* Returns the enableZrtp flag.
*
* @return the enableZrtp flag
* @return the enableZrtp flag.
*/
public boolean isEnableZrtp()
{
@ -1093,7 +1111,7 @@ public void setPBXEnrollment(boolean yesNo)
*/
public void handleGoClear()
{
userCallback.confirmGoClear();
securityEventManager.confirmGoClear();
}
/**
@ -1113,9 +1131,9 @@ public void setConnector(TransformConnector connector)
*
* @param ub The user callback class
*/
public void setUserCallback(SCCallback ub)
public void setUserCallback(SecurityEventManager ub)
{
userCallback = ub;
securityEventManager = ub;
}
/**
@ -1142,11 +1160,11 @@ public void stopStreaming(boolean stop)
*
* @return the user callback
*/
public SCCallback getUserCallback()
public SecurityEventManager getUserCallback()
{
return userCallback;
return securityEventManager;
}
/**
* Get other party's ZID (ZRTP Identifier) data
*
@ -1160,7 +1178,8 @@ public SCCallback getUserCallback()
*
* @return the ZID data as byte array.
*/
public byte[] getZid() {
public byte[] getZid()
{
return ((zrtpEngine != null) ? zrtpEngine.getZid() : null);
}
}

@ -127,7 +127,7 @@ protected void setSeqNum(short seq)
{
int at = 2;
buffer[offset + at++] = (byte)(seq>>8);
buffer[offset + at] = (byte)seq;
buffer[offset + at] = (byte)seq;
}
/**

@ -360,9 +360,9 @@ public void setTransportAddress(InetSocketAddress transportAddress)
this.fireCallParticipantChangeEvent(
CallParticipantChangeEvent
.CALL_PARTICIPANT_TRANSPORT_ADDRESS_CHANGE
, oldTransportAddress
, transportAddress);
.CALL_PARTICIPANT_TRANSPORT_ADDRESS_CHANGE,
oldTransportAddress,
transportAddress);
}
/**

@ -31,6 +31,14 @@ public abstract class AbstractCallParticipant
protected final List<CallParticipantListener> callParticipantListeners
= new ArrayList<CallParticipantListener>();
/**
* All the CallParticipantSecurityListener-s registered with this
* CallParticipant.
*/
protected final List<CallParticipantSecurityListener>
callParticipantSecurityListeners
= new ArrayList<CallParticipantSecurityListener>();
/**
* The state of the call participant.
*/
@ -66,6 +74,38 @@ public void removeCallParticipantListener(CallParticipantListener listener)
}
}
/**
* Registers the <tt>listener</tt> to the list of listeners that would be
* receiving CallParticipantSecurityEvents
*
* @param listener a listener instance to register with this participant.
*/
public void addCallParticipantSecurityListener(
CallParticipantSecurityListener listener)
{
synchronized(callParticipantSecurityListeners)
{
if (!callParticipantSecurityListeners.contains(listener))
callParticipantSecurityListeners.add(listener);
}
}
/**
* Unregisters the specified listener.
*
* @param listener the listener to unregister.
*/
public void removeCallParticipantSecurityListener(
CallParticipantSecurityListener listener)
{
if (listener == null)
return;
synchronized(callParticipantSecurityListeners)
{
callParticipantSecurityListeners.remove(listener);
}
}
/**
* Constructs a <tt>CallParticipantChangeEvent</tt> using this call
* participant as source, setting it to be of type <tt>eventType</tt> and
@ -140,6 +180,121 @@ protected void fireCallParticipantChangeEvent(String eventType,
}
}
/**
* Constructs a <tt>CallParticipantSecurityStatusEvent</tt> using this call
* participant as source, setting it to be of type <tt>eventType</tt> and
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
*
* @param sessionType the type of the session - audio or video
* @param eventID the identifier of the event
*/
protected void fireCallParticipantSecurityOnEvent(
String sessionType,
String cipher,
String securityString,
boolean isVerified)
{
CallParticipantSecurityOnEvent evt
= new CallParticipantSecurityOnEvent( this,
sessionType,
cipher,
securityString,
isVerified);
logger.debug("Dispatching a CallParticipantSecurityStatusEvent event to "
+ callParticipantSecurityListeners.size()
+" listeners. event is: " + evt.toString());
Iterator<CallParticipantSecurityListener> listeners = null;
synchronized (callParticipantSecurityListeners)
{
listeners = new ArrayList<CallParticipantSecurityListener>(
callParticipantSecurityListeners).iterator();
}
while (listeners.hasNext())
{
CallParticipantSecurityListener listener
= (CallParticipantSecurityListener) listeners.next();
listener.securityOn(evt);
}
}
/**
* Constructs a <tt>CallParticipantSecurityStatusEvent</tt> using this call
* participant as source, setting it to be of type <tt>eventType</tt> and
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
*
* @param sessionType the type of the session - audio or video
* @param eventID the identifier of the event
*/
protected void fireCallParticipantSecurityOffEvent(String sessionType)
{
CallParticipantSecurityOffEvent event
= new CallParticipantSecurityOffEvent( this,
sessionType);
logger.debug(
"Dispatching a CallParticipantSecurityAuthenticationEvent event to "
+ callParticipantSecurityListeners.size()
+" listeners. event is: " + event.toString());
Iterator<CallParticipantSecurityListener> listeners = null;
synchronized (callParticipantSecurityListeners)
{
listeners = new ArrayList<CallParticipantSecurityListener>(
callParticipantSecurityListeners).iterator();
}
while (listeners.hasNext())
{
CallParticipantSecurityListener listener
= (CallParticipantSecurityListener) listeners.next();
listener.securityOff(event);
}
}
/**
* Constructs a <tt>CallParticipantSecurityStatusEvent</tt> using this call
* participant as source, setting it to be of type <tt>eventType</tt> and
* the corresponding <tt>oldValue</tt> and <tt>newValue</tt>,
*
* @param sessionType the type of the session - audio or video
* @param eventID the identifier of the event
*/
protected void fireCallParticipantSecurityMessageEvent(
String messageType,
String message,
String i18nMessage)
{
CallParticipantSecurityMessageEvent evt
= new CallParticipantSecurityMessageEvent( this,
messageType,
message,
i18nMessage);
logger.debug("Dispatching a CallParticipantSecurityFailedEvent event to "
+ callParticipantSecurityListeners.size()
+" listeners. event is: " + evt.toString());
Iterator<CallParticipantSecurityListener> listeners = null;
synchronized (callParticipantSecurityListeners)
{
listeners = new ArrayList<CallParticipantSecurityListener>(
callParticipantSecurityListeners).iterator();
}
while (listeners.hasNext())
{
CallParticipantSecurityListener listener
= (CallParticipantSecurityListener) listeners.next();
listener.securityMessageRecieved(evt);
}
}
/**
* Returns a string representation of the participant in the form of
* <br/>
@ -252,4 +407,46 @@ public boolean isMute()
{
return false;
}
/**
* Sets the security status for this call participant.
*
* @param isSecurityOn <code>true</code> to indicate that the security is
* turned on and <code>false</code> - otherwise.
* @param sessionType the type of the call session - audio or video.
*/
public void setSecurityOn( boolean isSecurityOn,
String sessionType,
String cipher,
String securityString,
boolean isVerified)
{
if (isSecurityOn)
fireCallParticipantSecurityOnEvent(
sessionType,
cipher,
securityString,
isVerified);
}
public void setSecurityOff(String sessionType)
{
fireCallParticipantSecurityOffEvent(sessionType);
}
/**
* Sets the security message associated with a failure/warning or
* information coming from the encryption protocol.
*
* @param messageType the type of the message.
* @param message the message
*/
public void setSecurityMessage( String messageType,
String message,
String i18nMessage)
{
fireCallParticipantSecurityMessageEvent(messageType,
message,
i18nMessage);
}
}

@ -47,7 +47,7 @@ public abstract class Call
* be needed inside specific layers of the call securing, depending on the
* securing algorithm used
*/
private Hashtable<Object, SecurityGUIListener> securityGUIListeners;
private Hashtable<Object, CallParticipantSecurityListener> securityGUIListeners;
/**
* If this flag is set to true according to the account properties
@ -262,42 +262,6 @@ protected void fireCallChangeEvent( String type,
*/
public abstract CallState getCallState();
/**
* This method is used to add references to various GUI components related to
* securing the call that might be used in different way in by various securing
* algorithms, and consequently might be needed for particular usage at the layers
* where the specified algorithms operate
*
* @param key a key used by a securing algorithm implementation
* to identify the GUI item needed
* @param the GUI listener
*/
public void addSecurityGUIListener(Object key, SecurityGUIListener value)
{
if (securityGUIListeners == null)
securityGUIListeners = new Hashtable<Object, SecurityGUIListener>();
securityGUIListeners.put(key, value);
}
/**
* This method is used to obtain the reference to various GUI components related to
* securing the call that might be used in different way in by various securing
* algorithms, and consequently might be needed for particular usage at the layers
* where the specified algorithms operate
*
* @param key a key used by a securing algorithm implementation
* to identify the GUI item needed
* @return the GUI listener
*/
public SecurityGUIListener getSecurityGUIListener(Object key)
{
if (securityGUIListeners == null)
return null;
else
return securityGUIListeners.get(key);
}
/**
* Returns the default call encryption flag
*

@ -87,6 +87,23 @@ public interface CallParticipant
*/
public void removeCallParticipantListener(CallParticipantListener listener);
/**
* Allows the user interface to register a listener interested in security
* status changes.
*
* @param listener a listener instance to register with this participant
*/
public void addCallParticipantSecurityListener(
CallParticipantSecurityListener listener);
/**
* Unregisters the specified listener.
*
* @param listener the listener to unregister
*/
public void removeCallParticipantSecurityListener(
CallParticipantSecurityListener listener);
/**
* Gets the time at which this <code>CallParticipant</code> transitioned
* into a state (likely {@link CallParticipantState#CONNECTED}) marking the

@ -0,0 +1,53 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import java.util.EventListener;
/**
* CallParticipantSecurityListener interface extends EventListener. This is the
* listener interface used to handle an event related with a change in security
* status.
*
* The change in security status is triggered at the protocol level, which
* signal security state changes to the GUI. This modifies the current security
* status indicator for the call sessions.
*
* @author Werner Dittmann
* @author Yana Stamcheva
*/
public interface CallParticipantSecurityListener extends EventListener
{
/**
* The handler for the security event received. The security event
* represents an indication of change in the security status.
*
* @param securityEvent
* the security event received
*/
public void securityOn(
CallParticipantSecurityOnEvent securityEvent);
/**
* The handler for the security event received. The security event
* represents an indication of change in the security status.
*
* @param securityEvent
* the security event received
*/
public void securityOff(
CallParticipantSecurityOffEvent securityEvent);
/**
* The handler of the security message event.
*
* @param event the security message event.
*/
public void securityMessageRecieved(
CallParticipantSecurityMessageEvent event);
}

@ -0,0 +1,168 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import java.util.*;
import net.java.sip.communicator.service.protocol.*;
/**
* The <tt>CallParticipantSecurityFailedEvent</tt> is triggered whenever
* a problem has occurred during call security process.
*
* @author Yana Stamcheva
*/
public class CallParticipantSecurityMessageEvent
extends EventObject
{
/**
* Indicates that no retained shared secrets are available. The user shall
* must verify security strings with the other party.
*/
public static final String SECURITY_AUTHENTICATION_REQUIRED
= "SecurityAuthenticationRequired";
/**
* Indicates that shared secrets retained during previous sessions did not
* offer valid identifiers. This can happen if the other party uses another
* client software or lost its stored shared secrets. In rare case this
* could also signal a Man-In-The-Middle (MITM) attack. Therefore the user
* shall must verify the SAS with the other party to prove the correct
* exchange ZRTP data.
*/
public static final String RETAINED_SECURITY_AUTHENTICATION_FAILED
= "RetainedSecurityAuthenticationFailed";
/**
* Indicates an internal encryption packet checksum mismatch. In other words
* the packet was dropped. If this happens often this may indicate a bad
* connection that corrupts data during transmission. In rare cases and if
* it happens regularly this could also signal a denial-of-serice attack.
*/
public static final String CHECKSUM_MISMATCH = "CheckSumMismatch";
/**
* Indicates dropping packet because SRTP authentication failed. This may
* happen if the data was corrupted during transmission or during the very
* first packets after switching to secure mode. In rare cases and if this
* happens later during a secure session this could also signal a
* denial-of-serice attack.
*/
public static final String AUTHENTICATION_FAILED = "AuthenticationFailed";
/**
* Indicates dropping packet because SRTP replay check failed. A duplicate
* SRTP packet was detected. This may happen if the data was corrupted
* during transmission. In rare cases and if this happens later during a
* secure session this could also signal a denial-of-serice attack.
*/
public static final String REPLAY_CHECK_FAILED = "ReplayCheckFailed";
/**
* Indicates too much retries during security negotiation. This may happen
* if the other party stops to proceed the handshake. Usually if Internet
* connection is lost or the peer has some problems.
*/
public static final String RETRY_RATE_EXCEEDED = "RetryRateExceeded";
/**
* Indicates that data cannot be send. Internet data connection or peer is
* down.
*/
public static final String DATA_SEND_FAILED = "DataSendFailed";
/**
* Indicates that an internal protocol error occurred. Usually some sort of
* software problem.
*/
public static final String INTERNAL_PROTOCOL_ERROR = "InternalProtocolError";
/**
* Indicates compatibility problems like for example: unsupported protocol
* version, unsupported hash type, cypher type, SAS scheme, etc.
*/
public static final String NOT_COMPATIBLE = "NotCompatible";
/**
* Indicates that the other party doesn't support the encryption algorithm
* we're using or encryption at all.
*/
public static final String NOT_SUPPORTED = "NotSupported";
/**
* Indicates that a general error has occurred.
*/
public static final String GENERAL_ERROR = "GeneralError";
/**
* One of the event types defined in this class.
*/
private String eventType;
/**
* The message associated with this event.
*/
private String eventMessage;
/**
* The internationalized message associated with this event.
*/
private String eventI18nMessage;
/**
* Creates a <tt>CallParticipantSecurityFailedEvent</tt> by specifying the
* call participant, event type and message associated with this event.
*
* @param callParticipant the call participant implied in this event.
* @param eventType the type of the event. One of the constants defined in
* this class.
* @param eventMessage the message associated with this event.
* @param i18nMessage the internationalized message associated with this
* event that could be shown to the user.
*/
public CallParticipantSecurityMessageEvent( CallParticipant callParticipant,
String eventType,
String eventMessage,
String i18nMessage)
{
super(callParticipant);
this.eventType = eventType;
this.eventMessage = eventMessage;
this.eventI18nMessage = i18nMessage;
}
/**
* Returns the type of this event.
*
* @return the type of this event.
*/
public String getType()
{
return eventType;
}
/**
* Returns the message associated with this event.
*
* @return the message associated with this event.
*/
public String getMessage()
{
return eventMessage;
}
/**
* Returns the internationalized message associated with this event.
*
* @return the internationalized message associated with this event.
*/
public String getI18nMessage()
{
return eventI18nMessage;
}
}

@ -0,0 +1,47 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import net.java.sip.communicator.service.protocol.*;
/**
* The <tt>CallParticipantSecurityAuthenticationEvent</tt> is triggered whenever
* a the security strings are received in a secure call.
*
* @author Yana Stamcheva
*/
public class CallParticipantSecurityOffEvent
extends CallParticipantSecurityStatusEvent
{
private final String sessionType;
/**
* The event constructor.
*
* @param callParticipant
* the call participant associated with this event
* @param sessionType
* the type of the session: audio or video
*/
public CallParticipantSecurityOffEvent( CallParticipant callParticipant,
String sessionType)
{
super(callParticipant);
this.sessionType = sessionType;
}
/**
* Returns the type of the session, either AUDIO_SESSION or VIDEO_SESSION.
*
* @return the type of the session, either AUDIO_SESSION or VIDEO_SESSION.
*/
public String getSessionType()
{
return sessionType;
}
}

@ -0,0 +1,109 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import net.java.sip.communicator.service.protocol.*;
/**
* The <tt>CallParticipantSecurityOnEvent</tt> is triggered whenever a
* communication with a given participant is going secure.
*
* @author Werner Dittmann
* @author Yana Stamcheva
*/
public class CallParticipantSecurityOnEvent
extends CallParticipantSecurityStatusEvent
{
private final String sessionType;
private String securityString;
private boolean isVerified;
private String cipher;
/**
* The event constructor
*
* @param callParticipant
* the call participant associated with this event
* @param sessionType
* the type of the session, either AUDIO_SESSION or VIDEO_SESSION
* @param cipher
* the cipher used for the encryption
* @param securityString
* the security string (SAS)
* @param isVerified
* indicates if the security string has already been verified
*/
public CallParticipantSecurityOnEvent(
CallParticipant callParticipant,
String sessionType,
String cipher,
String securityString,
boolean isVerified)
{
super(callParticipant);
this.sessionType = sessionType;
this.cipher = cipher;
this.securityString = securityString;
this.isVerified = isVerified;
}
/**
* Returns the <tt>CallParticipant</tt> for which this event occurred.
*
* @return the <tt>CallParticipant</tt> for which this event occurred.
*/
public CallParticipant getCallParticipant()
{
return (CallParticipant) getSource();
}
/**
* Returns the type of the session, either AUDIO_SESSION or VIDEO_SESSION.
*
* @return the type of the session, either AUDIO_SESSION or VIDEO_SESSION.
*/
public String getSessionType()
{
return sessionType;
}
/**
* Returns the cipher used for the encryption.
*
* @return the cipher used for the encryption.
*/
public String getCipher()
{
return cipher;
}
/**
* Returns the security string.
*
* @return the security string.
*/
public String getSecurityString()
{
return securityString;
}
/**
* Returns <code>true</code> if the security string was already verified
* and <code>false</code> - otherwise.
*
* @return <code>true</code> if the security string was already verified
* and <code>false</code> - otherwise.
*/
public boolean isSecurityVerified()
{
return isVerified;
}
}

@ -0,0 +1,38 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import java.util.*;
/**
* Parent class for SecurityOn and SecurityOff events.
*
* @author Yana Stamcheva
*/
public abstract class CallParticipantSecurityStatusEvent
extends EventObject
{
/**
* Constant value defining that security is enabled.
*/
public static final String AUDIO_SESSION = "AUDIO_SESSION";
/**
* Constant value defining that security is disabled.
*/
public static final String VIDEO_SESSION = "VIDEO_SESSION";
/**
* Constructor required by the EventObject.
*
* @param source the source object for this event.
*/
public CallParticipantSecurityStatusEvent(Object source)
{
super(source);
}
}

@ -1,75 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import java.util.EventObject;
import net.java.sip.communicator.service.protocol.CallParticipant;
public class SecurityGUIEvent extends EventObject {
/**
* Default
*/
private static final long serialVersionUID = 1L;
/**
* Constant value defining that security status changed.
*/
public static final int STATUS_CHANGE = 1;
/**
* Constant value defining that security is enabled.
*/
public static final int SECURITY_ENABLED = 2;
/**
* The actual event value
*/
private final int eventID;
/**
* Constant value defining the key share provider .
*/
public static final int NONE = 0;
public static final int ZRTP = 1;
private final int provider;
/**
* The event constructor
*
* @param callSession
* the event source - the call session for which this event
* applies
* @param eventID
* the change value - going secure or stopping secure
* communication
*/
public SecurityGUIEvent(CallParticipant part,
int prov, int eventID) {
super(part);
this.eventID = eventID;
this.provider = prov;
}
/**
* @return the eventID
*/
public int getEventID() {
return eventID;
}
/**
* @return the provider
*/
public int getProvider() {
return provider;
}
}

@ -1,54 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import java.util.HashMap;
import net.java.sip.communicator.service.protocol.CallParticipant;
public class SecurityGUIEventZrtp extends SecurityGUIEvent {
/**
* Default
*/
private static final long serialVersionUID = 1L;
/**
* ZRTP security state change actions
*/
public final static String CIPHER = "cipherName";
public final static String SECURITY_CHANGE = "secure";
public final static String SAS = "sas";
public final static String SAS_VERIFY = "sasVerify";
public final static String SESSION_TYPE = "type";
public final static String AUDIO = "Audio";
public final static String VIDEO = "Video";
public final static String MSG_INFO = "Info";
public final static String MSG_WARN = "Warn";
public final static String MSG_SEVERE = "Severe";
public final static String MSG_ZRTP = "Zrtp";
public final static String MSG_TEXT = "Msg";
private final HashMap<String, Object> states;
public SecurityGUIEventZrtp(CallParticipant part,
HashMap<String, Object> states) {
super(part, SecurityGUIEvent.ZRTP, SecurityGUIEvent.STATUS_CHANGE);
this.states = states;
}
/**
* @return the states
*/
public HashMap<String, Object> getStates() {
return states;
}
}

@ -1,31 +0,0 @@
/*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client.
*
* Distributable under LGPL license.
* See terms of license at gnu.org.
*/
package net.java.sip.communicator.service.protocol.event;
import java.util.EventListener;
/**
* SecureEventListener interface extends EventListener This is the listener
* interface used to handle an event related with a change in security status.
*
* The change in security status is triggered at the protocol level, which
* signal security state changes to the GUI. This modifies the current security
* status indicator for the call sessions.
*
*/
public interface SecurityGUIListener extends EventListener {
/**
* The handler for the security event received. The security event represents an
* indication of change in the security status.
*
* @param securityEvent
* the securityEvent received
*/
public void securityStatusChanged(SecurityGUIEvent securityEvent);
}
Loading…
Cancel
Save