From ea303ffd2d970a3ec0a9bffb83ad90ab2012b676 Mon Sep 17 00:00:00 2001 From: Yana Stamcheva Date: Sun, 15 Feb 2009 09:49:15 +0000 Subject: [PATCH] Zrtp Gui and event modifications. (Issue #463) --- resources/images/images.properties | 6 + .../images/impl/gui/buttons/encrypted.png | Bin 693 -> 389 bytes .../impl/gui/buttons/encrypted_verified.png | Bin 839 -> 543 bytes .../impl/gui/buttons/exitFullScreen.png | Bin 287 -> 848 bytes .../impl/gui/buttons/holdButtonFullScreen.png | Bin 0 -> 695 bytes .../impl/gui/buttons/muteButtonFullScreen.png | Bin 0 -> 962 bytes .../impl/gui/buttons/secureAudioOff.png | Bin 0 -> 736 bytes .../images/impl/gui/buttons/secureAudioOn.png | Bin 0 -> 781 bytes .../impl/gui/buttons/secureVideoOff.png | Bin 0 -> 579 bytes .../images/impl/gui/buttons/secureVideoOn.png | Bin 0 -> 585 bytes resources/languages/resources.properties | 4 + .../communicator/impl/gui/main/MainFrame.java | 6 +- .../impl/gui/main/call/CallPanel.java | 59 ++- .../gui/main/call/CallParticipantPanel.java | 199 ++++++---- .../impl/gui/main/call/HoldButton.java | 16 + ...ureButton.java => SecureVerifyButton.java} | 4 +- .../impl/gui/main/call/SecurityPanel.java | 144 ++++++++ .../gui/main/call/SecurityStatusLabel.java | 86 +++++ .../impl/gui/main/call/ZrtpPanel.java | 258 ------------- .../gui/main/contactlist/ContactList.java | 8 +- .../gui/main/contactlist/ContactListPane.java | 1 - .../ExtendedTooltip.java} | 38 +- .../impl/gui/utils/ImageLoader.java | 36 ++ .../impl/gui/utils/NotificationManager.java | 4 +- .../impl/media/CallSessionImpl.java | 76 ++-- .../media/transform/TransformManager.java | 34 +- .../impl/media/transform/zrtp/SCCallback.java | 341 ------------------ .../transform/zrtp/SecurityEventManager.java | 333 +++++++++++++++++ .../transform/zrtp/ZRTPTransformEngine.java | 239 ++++++------ .../media/transform/zrtp/ZrtpRawPacket.java | 2 +- .../protocol/sip/CallParticipantSipImpl.java | 6 +- .../protocol/AbstractCallParticipant.java | 197 ++++++++++ .../communicator/service/protocol/Call.java | 38 +- .../service/protocol/CallParticipant.java | 17 + .../CallParticipantSecurityListener.java | 53 +++ .../CallParticipantSecurityMessageEvent.java | 168 +++++++++ .../CallParticipantSecurityOffEvent.java | 47 +++ .../event/CallParticipantSecurityOnEvent.java | 109 ++++++ .../CallParticipantSecurityStatusEvent.java | 38 ++ .../protocol/event/SecurityGUIEvent.java | 75 ---- .../protocol/event/SecurityGUIEventZrtp.java | 54 --- .../protocol/event/SecurityGUIListener.java | 31 -- 42 files changed, 1675 insertions(+), 1052 deletions(-) create mode 100644 resources/images/impl/gui/buttons/holdButtonFullScreen.png create mode 100644 resources/images/impl/gui/buttons/muteButtonFullScreen.png create mode 100644 resources/images/impl/gui/buttons/secureAudioOff.png create mode 100644 resources/images/impl/gui/buttons/secureAudioOn.png create mode 100644 resources/images/impl/gui/buttons/secureVideoOff.png create mode 100644 resources/images/impl/gui/buttons/secureVideoOn.png rename src/net/java/sip/communicator/impl/gui/main/call/{SecureButton.java => SecureVerifyButton.java} (96%) create mode 100755 src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java create mode 100644 src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java delete mode 100755 src/net/java/sip/communicator/impl/gui/main/call/ZrtpPanel.java rename src/net/java/sip/communicator/impl/gui/{main/contactlist/MetaContactTooltip.java => utils/ExtendedTooltip.java} (76%) delete mode 100644 src/net/java/sip/communicator/impl/media/transform/zrtp/SCCallback.java create mode 100644 src/net/java/sip/communicator/impl/media/transform/zrtp/SecurityEventManager.java create mode 100755 src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityListener.java create mode 100644 src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityMessageEvent.java create mode 100644 src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityOffEvent.java create mode 100755 src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityOnEvent.java create mode 100644 src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityStatusEvent.java delete mode 100755 src/net/java/sip/communicator/service/protocol/event/SecurityGUIEvent.java delete mode 100755 src/net/java/sip/communicator/service/protocol/event/SecurityGUIEventZrtp.java delete mode 100755 src/net/java/sip/communicator/service/protocol/event/SecurityGUIListener.java diff --git a/resources/images/images.properties b/resources/images/images.properties index 4e2869d44..f4fd97e3e 100644 --- a/resources/images/images.properties +++ b/resources/images/images.properties @@ -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 diff --git a/resources/images/impl/gui/buttons/encrypted.png b/resources/images/impl/gui/buttons/encrypted.png index cd638f0fdf534b5245e87b7839e716771985793f..5164f461cb53d713833a1dfa60f523e7f4b4c854 100755 GIT binary patch literal 389 zcmeAS@N?(olHy`uVBq!ia0vp^Vj#@H1|*Mc$*~4fjKx9jP7LeL$-D$|*pj^6T^Rm@ z;DWu&Cj&(|3p^r=fvWz1Fyr)2hA%)t_7YEDSN5AsJOXM=KUlq<1LasfT^vI!PQSfs z@73%m!1`hSqN$6fCWy`!6lpd2$ddF_(B;jZhPACt+cyaQDduG5=3lU&j5%qdTePS8 ztu+b<^?wQ}hQ=AcId}W`o7sue4Y|~+RF#wX+;1E!dbt0ARQt@Ib{h&@ObXiFSf9$y zp84}fc+n>JgUemN@cxcCu2uH2i#5jONXgqSO)^1D8HR~+NnX7qVk-cf1Q zd*$6uY5N{+(}`}5*cg$tyFK)+US4kh|JIdVe}4*vD?M7#^f~!p&e~_LNA%9I?Kms` z&FJ%<`J(L1Q6_=szI@$b*|PNPMAQ5whvq7lSe3S{Zxh(J%J}&4r@c2;&bk=?Lc_w4t-!`g4F$mjI@`F>vChv#YGuQ4<8BHq;%z1`UvyVKs@ zdI3O|)!jltnk^P9&oY@?Qggkxc`-fxv?Cggq*JM(hohqdiDa^yGiN&J>+6n%LV>G? zhb3<+b#rZLX+iu0q|>vW*4EJE`1qyifq}lZ?d?5dWo5nm<;$+Bs*1P2|7qi;M4{tE%=0P*zu49!OI8?(pznG?9o+ zl}g920U5wk2ZYdk!C>HAFz97tV<(@_OHZ=dd*8Czdq+Z4vs+vH`?@X&1bpX&(A>r@ zpeQPap(BJKpD!Jorny!>o104)WLeQPt%|PeD2nR7n=4&Dy%|CD`h~QI-z@ktBlEqP zks-Hm{=4M2ejehf=Ka_EKE+>x1keJomK~h%hg;KD{QP+2R3vmPl|?)xZ#4hVk%$bn z$D(2Nr&9HmcUBCcJ|4dR`JE4-AaNr#d1a!#rwAMYP8h4W?BKn|32?TA(*B>H@+EH;P=K39Ij$HbQv+0dfm(Wx35CJcaGlZsNfI=8Eo- bfgHdu-ML%nzxwyp00000NkvXXu0mjfmhe{N diff --git a/resources/images/impl/gui/buttons/encrypted_verified.png b/resources/images/impl/gui/buttons/encrypted_verified.png index 2b9d3c75ccfd8fed299446aa6fe5ccae225062ed..d5ba1638e8b2f3e01fb939a63aade3d40f3a5e36 100755 GIT binary patch delta 527 zcmV+q0`UFE2A>2jiBL{Q4GJ0x0000DNk~Le0000M0000M2nGNE0K~LxI{*Lx0drDE zLIAGL9O;oE9Df1)0005}0hfsY^Z)<=2XskIMF-ge3=ky>-Sd$a0004>Nkl%sxIwhB8418{iz5ri=JzxjO0R!Lza4jM$o+lQOUEl}s z8#q+e2U|V?`~+5k&#L;}>%^bTcyAX4P}Kp@HkXHsSg~Qo=NVQ#+iE>~{3a~B@atyW z7Likznt#6*ta&;-5y=4;Zo3Ht0vLutx7(#&uLDeh6IH#MXGPx1`~7~R(I^0+P>5Qs zMmC!z91dHD%X{&7-@3?TGITl};_*0zLV;v5Nwr#~QmMH1%<}jjdc7XOV31<5NGg@0 z)oM{Hl@@<1L}Y5`+U+*6Sd7VJLOPvhIQ;*KP*_#pJS%?LiAJLVK(pC&6m{zH+lfdd z@)0<&a{YdvL?S`CTxK*HISF5m$K%_1R>S}UICi_E7Q6yCz?rH(z5hav_yh7PbfT>8 R)93&I002ovPDHLkV1j27-Vy)+ delta 826 zcmV-A1I7HG1jhy;iBL{Q4GJ0x0000DNk~Le0000G0000G2nGNE03Y-JVUaEze+v@; z01FcV0GgZ_00007bV*G`2iOZ75G*M;1HEPd00PuWL_t(I%XQLEXcSi*!13?y?9Bej zxPNMN>z_6Li47Q(fRUxpfI?%@qZAK9Xp2P9gQqM)Kynd#*^5;WX`zrJ7K#Twq=kau z#ngissWCAnAvBuoF0(tE9cSLof6UHK58G^(hQ8B#yx;r$e*E4qz<<`wn?I#?>_~jo z-JQG~kH0XUA^l}@KF^z@_?b8}1f)YKo7mSx`n%$F|%*L1yl zWnkb)BArfNs8rS;0R}*D0}#Rvg~Q7Ja9Cn?cBxn_>i6>btAFS7SIa`w^Kak2d*?U; zMG5T}!fq#S1Ey)=x(-4Je~QJ*dZW>p*|@uNCs#5I)3)t8j^kjOR=aO)>C=zrRK#vs z=qt#LQfU16gWcoD``dvJ-s`gWp+K-+lt0hBO5Fz?AOJ9vKQb&wV>vH%Xh_|rM%MMJ zNJWg<&L1iZwLhLrM6C~IJyczqc7^rrz}TDLLjWb6)7f*M4aawBe?Xb0-;4$W(ZNn& zpWi@t3iK*+q_(i@)bn2!UjQv&O>5#=3sBPlxI16s(&27osnw$Qmc!Hy1Ax)77~UJ5 zHBH^@!K&utRxMC$0F+6ITO(_HlS(pK)=}?A0T>w#z?TnO6`3;+_}-8#tk|6-$O3@E$cHo^74 zky>v$=K#0ak{ploXH9<2tN?KFR0T{2>K@b^U^l?=w$6d@qwNfF-{au{mH43wLASY? z+4Z2&LLJI0V*zY;GPWe$-+DDvFBofIgrB$jLBy z3H)suCc`<=LJJ z2f#HEk>V_nbH-ULN+i?OZUr_GrLxEmA|lxppiCSP5jr|MxnEO*vM4kV2rw}=#*E8l zF2KxzNA>kQZfM~1>?{Gl-;#i`@^W4}ovbV`v%9-%BEZCfTLlG#LLuJv_gf+dsHm*u zO>ZwZ9S;0~fQbMT2XtMJ1z8qg7)JbQ_P=Qj=(>&uD5c2F%_STTrzMWX8E2%12&Nn& zLaL!_T2!S74{K|A*3yDfDrJ1W!@=vG9z^7v11X28I>P`>i;@}!PZ}G!VYl;fc$nkk zq*IlW(o#CQx;QyGiN^zoVVF8#UIPgZ#OmQ*bu~FQ8}9}N;&Hc&ig?xCjUhsCZ||QD zTqp(FSq&r#`04X8JvEgS=W)CFvak@HQPVP*0$q=%z%UH9JRaT;4iXFo&)GUXIf>uz zr?##xUMDg4%u|p~03b@?cDwnuw8YWT5vl(9y12-W*NZ5XvMC}-o#K*`=$>E! z;ZTSfmy2*XoF)ZnE+q4FbIi}pSt3s&NHf1!J?AqG5v2~Z$bTqGWS!_0IUCpVbuAK! z@L_0Z9C&)g0w!Lxw>QN)BPZ~Ht8LAkkkFid8X39L=Crk~?N4)>i1E?UOKs1anwyg@ a62AdRP0MD`PMxv<00003ks+CmJLf=~=K*e15Pu(NWZwbG?a z14X(Lx(ya8-MB9(beV0zRgpqnx-R|$DnX(oG_fusiE$$|UqW2iOfzAEFPh1m-Fx@F zIfrxa%-m~rIvsj(BOVtZ0ZcGjG=co*Qt4Okrqva2b75f?$N&$3$q|!x(E#26>5qj% z*%feWX=xUC4_pa|xE~c@`9m&O761{+jFFskt_+Z}ZaaAaADaD}Uzp#TF1wALPSfaKyLg+c*< zYw@@z7Mq*Hw6=^K@H?ZFa`$c9HoD{cY?B)BJEN3x_id#-F>AmbUjhH>fNk3s4p^2q zXj$PpFzAl2fRQ-xKQ$0Y3WgD2VwK-3HM$g-2=H@2DOZ?p3IhKQgkA$ZA0jL08UU!( zYRt^cxa%Lanw#g|9}__FEq7^1^&NJQ&qi2O~_B6002ovPDHLkV1izVEa?CM literal 0 HcmV?d00001 diff --git a/resources/images/impl/gui/buttons/muteButtonFullScreen.png b/resources/images/impl/gui/buttons/muteButtonFullScreen.png new file mode 100644 index 0000000000000000000000000000000000000000..c4014d15af3b55e844b36c76dd3d5d0275949650 GIT binary patch literal 962 zcmV;z13mnSP)*mnUtyXiE3sqiRs|FTS*$MR0ptGISbXI}ku>1h zzTFLU0JT8&DvKvE2V4W1M#ABVWdon?-024X0`k^K_-#xAr30g*6AC~n)saSVUTJjz z^^&NyWI}5l+yJK>Vr~BW!8XhF@eqb`8XU7 z!iIqm0*AxFm%$((7Zh;$;zh3_JkH?d*NqJP0k`LAF>@0r|57XM##`u#b1VSOClmG}J_;-35!!SO`@s9e= zRu4p@QO>ltbG)^c?yFY`)zy)Fzp$u?RQkzs4>)6?BeAQ(hSiKc1T z<$@Hyg2hCFUvAyP=l651r-v^B0W?iZPXaaj_K`>=_`J53pKsoz((C2M_3Py3=2G9# zKu=c}i;Ihv`81^zcB*LGHe7jm=(>)-riR~c-=@5xg0NxmS$X+#5;n?SZ2!D`Nx_ya z+#4Nbm&Ze;*UPVceS8%P(bwB+`xtB=L0@k#$C{h@unx-AqG!3gYJ2S)Y{r%+Rp`UIOaUY~b?2Lx<{002h>0pa061ONa48FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H10$oW&K~y-6m6ShBQ$ZZZKlgfll*JkmHKk3I^hX?ftKtgn21Qr-%AZ`psE&*w~05&mnAR)nXu#c2yf%;qS z{r-LKo4a>EWv%6ZOhm2%Pk{_@6L@WmdGD`N&45M31s(%0fPPeQkN~u6R z9)EKpSVV3EUx2&*-00{iD=RBxvsqH96xnPRpv_u)pp?4a5G*1}MD74{z!^U@5D1XT zWSE|wW@BT6rKKf$dwT)e0IaoVYn;nkL=r$AcmSLSlppAs)|y~2NVQr8pjxfc(a}Mz z4-1kF5p%8rQ-2;R5yYG3=Iu2Ha6B! zc|M<~QmHUAGebBW1_;+KFBFYNLqL}Ud~ej8NF)xwM@B~I>+7RXC>+L;$t1;Mk=4~z zfZa$W(gN(2N~JyEKm#v<0w4|L0X;oEIF3Uql{&7ZqP1?Z)^64O9c_$R0J=n^6F3Ll z04B@ja?tC_<#Ob5xg(@fsZ{U&3Ba~y;T3;3>{nzt7{ Sg5;L~0000WdP)002h>0pa061ONa48FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H10*XmQK~y-6m6SbbQ&ALvzx&?HOPdB2;~ybXV{Bed51k4Pym15be4z)c{llzQin6Gs6{DQ#c~cn!m$ z2>bv(`~?bd7Ptii9}m07Hb2#4d7=hXirZMy}i8%A=usB zWoc=Nd_Iq5)i2Y?$Vem9iAJMApt7;CQ33WW;05pokbZDD9QM8og#we4lbEK-%E}6% zP>4_{)NpTGmKD@mZ@PNPQc8UWx}}sCfs?>>>iZt3)oLC%l}b@46bJ@`UdK)T-==BW zLWnI_|K&XprPMmG4t$eRZULWGS672dDWt6bOh-qDS4eB^-4tNkFbtde^9Gn{IV+@; z_kj082-(@$=^a=@%H=YpQmLUnu2!o#+qPdTrJlhdL&zOIFM%oC2h&25#bWVmS6A0i zu~__gD7dM>8DJE63M72)5^&Bx-HrtI73l*W0XKlFz_e0o#vk_wq`S}|FrpDW00000 LNkvXXu0mjf8gEFj literal 0 HcmV?d00001 diff --git a/resources/images/impl/gui/buttons/secureVideoOff.png b/resources/images/impl/gui/buttons/secureVideoOff.png new file mode 100644 index 0000000000000000000000000000000000000000..546aaad315fa7095895fba51401f4aeb7b243876 GIT binary patch literal 579 zcmV-J0=)f+P)3ZN00004b3#c}2nYxW zdh($8FWQhbW?9;ba!ELWdL_~cP?peYja~^ zaAhuUa%Y?FJQ@H10l-N_K~y-6wUjZ78c`6(f4ebC#C1tP3(=@y2NHs$5y2vekivWb ziD@LMECPb2%~k1aQ>50yORDR%un`XKOFV^u5D^KBScC;-Q`{-KnmdbRs(Ca2_v6p- z=4r0$A|g@XBk&yXb9=bJ47gBAUHna?S(fz>xB{Nu0rbWiXegz=cpD-T(18!9KtrJr zwOWm8wTj>G2e=2EiO2&Fv;q9|0WVIm*X?$(Z5zWd$Y!(D>vez#kOeM9#01WPm%!Wy zn0G-Fi3G`Hl5)9BG#aJX>k$Y9a2yA~5Rn4#6?k@YWv-v%HWrI9o6T?>hsk7uuIq%u z;Z3^+eA|HnxV~c`%d$wP)7!I%5DW$}O_Rl9;g!Dz?t6;|;Cwz$r_(v=yx;FrC=_V5 zTG+O|DIY)q4n~p5WVU&;*`!n|F&GR0h(sd9<8j*UHmlWYBm2Si)4ScVrfJ(em&;)o z2B}o)X#XY}z+2!I@MssjH?;A1yv-|>${u04Tr!4mbmz!1d;R0zPk4 zx~@|!7O^aA@Ai7VW;h%&8jW_#b0Ddd`VAl=Dd0Qs_@A$|i1>i_+W-25{s5kBg4w?@ RUF!e<002ovPDHLkV1m2m{7nD= literal 0 HcmV?d00001 diff --git a/resources/images/impl/gui/buttons/secureVideoOn.png b/resources/images/impl/gui/buttons/secureVideoOn.png new file mode 100644 index 0000000000000000000000000000000000000000..489784b0addfc69cf15935a804d8a439e5b543c6 GIT binary patch literal 585 zcmV-P0=E5$P)3ZN00004b3#c}2nYxW zdxtkB|(~MK3|u z5-$-VZAaNl|3Y~0v}^;h2N{V@fe;v7x_J4Z@DhX;?7@Q!VuxK#$Jx5n?=<}0=X>CL znVHCHwL(O$1J8lmz!mTL6EN1YNXR?DwPV=YL#xcOS|31FpMAya7{$+0Uv=Ha1}rcBW>GeFc>hMP66om z`}n?3xm*szp8zL7ZmV0x!brm~Fin$uKELUF-$&Q=F#JB}``$^!vaEN2vo1=d60YkK zjqb6G$733eMwmR9FMF%7ZF?i_^?I~gEk>ge0EI$ literal 0 HcmV?d00001 diff --git a/resources/languages/resources.properties b/resources/languages/resources.properties index f6426c96b..b3cef5787 100644 --- a/resources/languages/resources.properties +++ b/resources/languages/resources.properties @@ -675,6 +675,10 @@ impl.media.security.WARNING_NO_RS_MATCH=No retained shared secret availabl impl.media.security.WARNING_NO_EXPECTED_RS_MATCH=An expected retained shared secret is missing.
SAS verification is required
If SAS codes do not match then hangup and try again impl.media.security.SEVERE_GENERIC_MSG=A severe security problem was detected.
Your call is not secure
Error code: {0} impl.media.security.ZRTP_GENERIC_MSG=A severe ZRTP problem was detected.
Your call is not secure
Error code: {0} +impl.media.security.INTERNAL_PROTOCOL_ERROR=Internal protocol error occurred.
Your call is not secure
Error code: {0} +impl.media.security.CHECKSUM_MISMATCH=Internal ZRTP packet checksum mismatch.
If you see this message often this may mean a denial-of-service attack! +impl.media.security.RETRY_RATE_EXCEEDED=Too much retries during security negotiation. This may mean that the other party has internet connection problems.
Your call is not secure
Error code: {0} +impl.media.security.DATA_SEND_FAILED=Failed to send encryption data. Internet data connection or peer is down.
Your call is not secure
Error code: {0} 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 diff --git a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java index 37e9d0a54..d9f57c7bb 100755 --- a/src/net/java/sip/communicator/impl/gui/main/MainFrame.java +++ b/src/net/java/sip/communicator/impl/gui/main/MainFrame.java @@ -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; } diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java index 19dd05b0d..fa6473375 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallPanel.java @@ -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()); + } } diff --git a/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java index 07e9c47ad..34c4977a4 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/CallParticipantPanel.java @@ -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 Window 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 CallParticipantPanel 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 Component representing a UI means to secure - * the Call of the associated callParticipant or - * null if secure call is unsupported. - * - * @return a new Component representing the UI means to secure - * the Call of callParticipant or - * null 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 true if the audio security is on, otherwise - + * false. + */ + public boolean isAudioSecurityOn() + { + return isAudioSecurityOn; } + /** + * Indicates if the video security is turned on or off. + * + * @return true if the video security is on, otherwise - + * false. + */ + 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)); diff --git a/src/net/java/sip/communicator/impl/gui/main/call/HoldButton.java b/src/net/java/sip/communicator/impl/gui/main/call/HoldButton.java index 7524e3808..65faf324e 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/HoldButton.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/HoldButton.java @@ -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 * CallParticipant on/off hold. diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecureButton.java b/src/net/java/sip/communicator/impl/gui/main/call/SecureVerifyButton.java similarity index 96% rename from src/net/java/sip/communicator/impl/gui/main/call/SecureButton.java rename to src/net/java/sip/communicator/impl/gui/main/call/SecureVerifyButton.java index ef94fd885..61b044e3c 100644 --- a/src/net/java/sip/communicator/impl/gui/main/call/SecureButton.java +++ b/src/net/java/sip/communicator/impl/gui/main/call/SecureVerifyButton.java @@ -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)); diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java new file mode 100755 index 000000000..485654c65 --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/call/SecurityPanel.java @@ -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(); + } +} diff --git a/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java b/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java new file mode 100644 index 000000000..7c3d9af31 --- /dev/null +++ b/src/net/java/sip/communicator/impl/gui/main/call/SecurityStatusLabel.java @@ -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; + } +} \ No newline at end of file diff --git a/src/net/java/sip/communicator/impl/gui/main/call/ZrtpPanel.java b/src/net/java/sip/communicator/impl/gui/main/call/ZrtpPanel.java deleted file mode 100755 index b9540dd25..000000000 --- a/src/net/java/sip/communicator/impl/gui/main/call/ZrtpPanel.java +++ /dev/null @@ -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 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 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 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 - * - */ - 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); - } - } -} diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java index 54c473716..0bbb013ce 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactList.java @@ -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); } /** diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPane.java b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPane.java index f172857b0..b4eeb3775 100755 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPane.java +++ b/src/net/java/sip/communicator/impl/gui/main/contactlist/ContactListPane.java @@ -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 diff --git a/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactTooltip.java b/src/net/java/sip/communicator/impl/gui/utils/ExtendedTooltip.java similarity index 76% rename from src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactTooltip.java rename to src/net/java/sip/communicator/impl/gui/utils/ExtendedTooltip.java index c12227c7a..64385c08d 100644 --- a/src/net/java/sip/communicator/impl/gui/main/contactlist/MetaContactTooltip.java +++ b/src/net/java/sip/communicator/impl/gui/utils/ExtendedTooltip.java @@ -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 MetaContactTooltip. */ - 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; diff --git a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java index b401bed46..efe167345 100644 --- a/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java +++ b/src/net/java/sip/communicator/impl/gui/utils/ImageLoader.java @@ -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. */ diff --git a/src/net/java/sip/communicator/impl/gui/utils/NotificationManager.java b/src/net/java/sip/communicator/impl/gui/utils/NotificationManager.java index 3d2a02732..2316e8d01 100644 --- a/src/net/java/sip/communicator/impl/gui/utils/NotificationManager.java +++ b/src/net/java/sip/communicator/impl/gui/utils/NotificationManager.java @@ -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 diff --git a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java index e0efb722a..4e572e0df 100644 --- a/src/net/java/sip/communicator/impl/media/CallSessionImpl.java +++ b/src/net/java/sip/communicator/impl/media/CallSessionImpl.java @@ -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++; diff --git a/src/net/java/sip/communicator/impl/media/transform/TransformManager.java b/src/net/java/sip/communicator/impl/media/transform/TransformManager.java index ada557939..09c8760df 100755 --- a/src/net/java/sip/communicator/impl/media/transform/TransformManager.java +++ b/src/net/java/sip/communicator/impl/media/transform/TransformManager.java @@ -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; } } diff --git a/src/net/java/sip/communicator/impl/media/transform/zrtp/SCCallback.java b/src/net/java/sip/communicator/impl/media/transform/zrtp/SCCallback.java deleted file mode 100644 index dd0e52333..000000000 --- a/src/net/java/sip/communicator/impl/media/transform/zrtp/SCCallback.java +++ /dev/null @@ -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 - * showMessage() 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 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 state = new HashMap(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 state = new HashMap(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"); - } -} diff --git a/src/net/java/sip/communicator/impl/media/transform/zrtp/SecurityEventManager.java b/src/net/java/sip/communicator/impl/media/transform/zrtp/SecurityEventManager.java new file mode 100644 index 000000000..dd1a6eaa8 --- /dev/null +++ b/src/net/java/sip/communicator/impl/media/transform/zrtp/SecurityEventManager.java @@ -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 + * showMessage() 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 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."); + } + +} diff --git a/src/net/java/sip/communicator/impl/media/transform/zrtp/ZRTPTransformEngine.java b/src/net/java/sip/communicator/impl/media/transform/zrtp/ZRTPTransformEngine.java index db2498331..b1654bf8f 100644 --- a/src/net/java/sip/communicator/impl/media/transform/zrtp/ZRTPTransformEngine.java +++ b/src/net/java/sip/communicator/impl/media/transform/zrtp/ZRTPTransformEngine.java @@ -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 ZRTPCTransformer. + * * @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); } } diff --git a/src/net/java/sip/communicator/impl/media/transform/zrtp/ZrtpRawPacket.java b/src/net/java/sip/communicator/impl/media/transform/zrtp/ZrtpRawPacket.java index 947c87868..88a4e222a 100644 --- a/src/net/java/sip/communicator/impl/media/transform/zrtp/ZrtpRawPacket.java +++ b/src/net/java/sip/communicator/impl/media/transform/zrtp/ZrtpRawPacket.java @@ -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; } /** diff --git a/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java b/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java index 598267412..cb8009c59 100644 --- a/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java +++ b/src/net/java/sip/communicator/impl/protocol/sip/CallParticipantSipImpl.java @@ -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); } /** diff --git a/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java b/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java index 2b5e9af7b..d165cf17d 100644 --- a/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java +++ b/src/net/java/sip/communicator/service/protocol/AbstractCallParticipant.java @@ -31,6 +31,14 @@ public abstract class AbstractCallParticipant protected final List callParticipantListeners = new ArrayList(); + /** + * All the CallParticipantSecurityListener-s registered with this + * CallParticipant. + */ + protected final List + callParticipantSecurityListeners + = new ArrayList(); + /** * The state of the call participant. */ @@ -66,6 +74,38 @@ public void removeCallParticipantListener(CallParticipantListener listener) } } + /** + * Registers the listener 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 CallParticipantChangeEvent using this call * participant as source, setting it to be of type eventType and @@ -140,6 +180,121 @@ protected void fireCallParticipantChangeEvent(String eventType, } } + /** + * Constructs a CallParticipantSecurityStatusEvent using this call + * participant as source, setting it to be of type eventType and + * the corresponding oldValue and newValue, + * + * @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 listeners = null; + synchronized (callParticipantSecurityListeners) + { + listeners = new ArrayList( + callParticipantSecurityListeners).iterator(); + } + + while (listeners.hasNext()) + { + CallParticipantSecurityListener listener + = (CallParticipantSecurityListener) listeners.next(); + + listener.securityOn(evt); + } + } + + /** + * Constructs a CallParticipantSecurityStatusEvent using this call + * participant as source, setting it to be of type eventType and + * the corresponding oldValue and newValue, + * + * @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 listeners = null; + synchronized (callParticipantSecurityListeners) + { + listeners = new ArrayList( + callParticipantSecurityListeners).iterator(); + } + + while (listeners.hasNext()) + { + CallParticipantSecurityListener listener + = (CallParticipantSecurityListener) listeners.next(); + + listener.securityOff(event); + } + } + + /** + * Constructs a CallParticipantSecurityStatusEvent using this call + * participant as source, setting it to be of type eventType and + * the corresponding oldValue and newValue, + * + * @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 listeners = null; + synchronized (callParticipantSecurityListeners) + { + listeners = new ArrayList( + callParticipantSecurityListeners).iterator(); + } + + while (listeners.hasNext()) + { + CallParticipantSecurityListener listener + = (CallParticipantSecurityListener) listeners.next(); + + listener.securityMessageRecieved(evt); + } + } + /** * Returns a string representation of the participant in the form of *
@@ -252,4 +407,46 @@ public boolean isMute() { return false; } + + /** + * Sets the security status for this call participant. + * + * @param isSecurityOn true to indicate that the security is + * turned on and false - 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); + } } diff --git a/src/net/java/sip/communicator/service/protocol/Call.java b/src/net/java/sip/communicator/service/protocol/Call.java index 3cf2ae8f9..bc0428173 100644 --- a/src/net/java/sip/communicator/service/protocol/Call.java +++ b/src/net/java/sip/communicator/service/protocol/Call.java @@ -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 securityGUIListeners; + private Hashtable 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(); - - 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 * diff --git a/src/net/java/sip/communicator/service/protocol/CallParticipant.java b/src/net/java/sip/communicator/service/protocol/CallParticipant.java index 6a077e516..98ab18ddd 100644 --- a/src/net/java/sip/communicator/service/protocol/CallParticipant.java +++ b/src/net/java/sip/communicator/service/protocol/CallParticipant.java @@ -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 CallParticipant transitioned * into a state (likely {@link CallParticipantState#CONNECTED}) marking the diff --git a/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityListener.java b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityListener.java new file mode 100755 index 000000000..fa1f6a7ac --- /dev/null +++ b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityListener.java @@ -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); +} diff --git a/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityMessageEvent.java b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityMessageEvent.java new file mode 100644 index 000000000..7e81508d7 --- /dev/null +++ b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityMessageEvent.java @@ -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 CallParticipantSecurityFailedEvent 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 CallParticipantSecurityFailedEvent 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; + } +} diff --git a/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityOffEvent.java b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityOffEvent.java new file mode 100644 index 000000000..198e5c45e --- /dev/null +++ b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityOffEvent.java @@ -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 CallParticipantSecurityAuthenticationEvent 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; + } +} diff --git a/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityOnEvent.java b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityOnEvent.java new file mode 100755 index 000000000..9db113b5b --- /dev/null +++ b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityOnEvent.java @@ -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 CallParticipantSecurityOnEvent 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 CallParticipant for which this event occurred. + * + * @return the CallParticipant 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 true if the security string was already verified + * and false - otherwise. + * + * @return true if the security string was already verified + * and false - otherwise. + */ + public boolean isSecurityVerified() + { + return isVerified; + } +} diff --git a/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityStatusEvent.java b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityStatusEvent.java new file mode 100644 index 000000000..d380e32fe --- /dev/null +++ b/src/net/java/sip/communicator/service/protocol/event/CallParticipantSecurityStatusEvent.java @@ -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); + } +} diff --git a/src/net/java/sip/communicator/service/protocol/event/SecurityGUIEvent.java b/src/net/java/sip/communicator/service/protocol/event/SecurityGUIEvent.java deleted file mode 100755 index 933d2bfcc..000000000 --- a/src/net/java/sip/communicator/service/protocol/event/SecurityGUIEvent.java +++ /dev/null @@ -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; - } -} diff --git a/src/net/java/sip/communicator/service/protocol/event/SecurityGUIEventZrtp.java b/src/net/java/sip/communicator/service/protocol/event/SecurityGUIEventZrtp.java deleted file mode 100755 index 90edc38f4..000000000 --- a/src/net/java/sip/communicator/service/protocol/event/SecurityGUIEventZrtp.java +++ /dev/null @@ -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 states; - - public SecurityGUIEventZrtp(CallParticipant part, - HashMap states) { - super(part, SecurityGUIEvent.ZRTP, SecurityGUIEvent.STATUS_CHANGE); - this.states = states; - } - - /** - * @return the states - */ - public HashMap getStates() { - return states; - } - -} diff --git a/src/net/java/sip/communicator/service/protocol/event/SecurityGUIListener.java b/src/net/java/sip/communicator/service/protocol/event/SecurityGUIListener.java deleted file mode 100755 index 16f1c2527..000000000 --- a/src/net/java/sip/communicator/service/protocol/event/SecurityGUIListener.java +++ /dev/null @@ -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); -}