Changeset 9861

Show
Ignore:
Timestamp:
06/29/08 06:39:29 (3 months ago)
Author:
bct
Message:

make esession authentication warning less obtrusive

Location:
trunk
Files:
1 added
7 modified

Legend:

Unmodified
Added
Removed
  • trunk/data/glade/message_window.glade

    r9653 r9861  
    112112                        <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> 
    113113                        <child> 
    114                           <widget class="GtkImage" id="lock_image"> 
    115                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> 
    116                             <property name="no_show_all">True</property> 
    117                             <property name="stock">gtk-dialog-authentication</property> 
    118                             <property name="icon_size">1</property> 
    119                           </widget> 
     114                                                                                                        <widget class="GtkButton" id="authentication_button"> 
     115                                                                                                                <property name="no_show_all">True</property> 
     116                                                                                                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> 
     117                                                                                                                <property name="relief">GTK_RELIEF_NONE</property> 
     118                                                                                                                <property name="focus_on_click">False</property> 
     119                                                                                                                <property name="response_id">0</property> 
     120                                                                                                                <child> 
     121                                                                                                                        <widget class="GtkImage" id="lock_image"> 
     122                                                                                                                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK</property> 
     123                                                                                                                                <property name="stock">gtk-dialog-authentication</property> 
     124                                                                                                                                <property name="icon_size">1</property> 
     125                                                                                                                        </widget> 
     126                                                                                                                </child> 
     127                                                                                                        </widget> 
    120128                          <packing> 
    121129                            <property name="expand">False</property> 
  • trunk/src/chat_control.py

    r9811 r9861  
    10571057                        gajim.config.get('hide_chat_banner')) 
    10581058 
     1059                self.authentication_button = self.xml.get_widget('authentication_button') 
     1060                id = self.authentication_button.connect('clicked', self._on_authentication_button_clicked) 
     1061                self.handlers[id] = self.authentication_button 
     1062 
    10591063                # Add lock image to show chat encryption 
    10601064                self.lock_image = self.xml.get_widget('lock_image') 
     
    11161120                self.handlers[id] = widget 
    11171121 
    1118                 self.session = session 
     1122                if not session: 
     1123                        session = gajim.connections[self.account].find_controlless_session(self.contact.jid) 
     1124                        self.session = session 
     1125 
    11191126                if session: 
    11201127                        session.control = self 
    1121  
    1122                 # Enable ecryption if needed 
     1128                        self.session = session 
     1129 
     1130                        if session.enable_encryption: 
     1131                                self.print_esession_details() 
     1132 
     1133                # Enable encryption if needed 
    11231134                e2e_is_active = hasattr(self, 'session') and self.session and self.session.enable_encryption 
    11241135                self.gpg_is_active = False 
     
    11351146                                self.session.loggable = gajim.config.get('log_encrypted_sessions') 
    11361147                        self._show_lock_image(self.gpg_is_active, 'GPG', self.gpg_is_active, self.session and \ 
    1137                                         self.session.is_loggable()) 
     1148                                        self.session.is_loggable(), self.session and self.session.verified_identity) 
    11381149 
    11391150                self.status_tooltip = gtk.Tooltips() 
     
    13661377 
    13671378                self._show_lock_image(self.gpg_is_active, 'GPG', self.gpg_is_active, self.session and \ 
    1368                                 self.session.is_loggable()) 
     1379                                self.session.is_loggable(), self.session and self.session.verified_identity) 
    13691380 
    13701381        def _show_lock_image(self, visible, enc_type = '', enc_enabled = False, chat_logged = False, authenticated = False): 
     
    13741385                logged_string = chat_logged and 'will' or 'will NOT' 
    13751386 
    1376                 if enc_type == 'OTR': 
    1377                         authenticated_string = authenticated \ 
    1378                                 and ' and authenticated' \ 
    1379                                 or ' and NOT authenticated' 
    1380                 else: 
    1381                         authenticated_string = '' 
    1382  
    1383                 tooltip = '%s Encryption %s active%s.\n' \ 
     1387                if authenticated: 
     1388                        authenticated_string = ' and authenticated' 
     1389                        self.lock_image.set_from_stock('gtk-dialog-authentication', 1) 
     1390                else: 
     1391                        authenticated_string = ' and NOT authenticated' 
     1392                        self.lock_image.set_from_stock('gtk-dialog-warning', 1) 
     1393 
     1394                tooltip = '%s encryption %s active%s.\n' \ 
    13841395                        'Your chat session %s be logged.' % \ 
    1385                         (enc_type, status_string, authenticated_string,  
     1396                        (enc_type, status_string, authenticated_string, 
    13861397                        logged_string) 
    13871398 
    1388                 self.lock_tooltip.set_tip(self.lock_image, tooltip) 
    1389                 self.widget_set_visible(self.lock_image, not visible) 
     1399                self.lock_tooltip.set_tip(self.authentication_button, tooltip) 
     1400                self.widget_set_visible(self.authentication_button, not visible) 
    13901401                self.lock_image.set_sensitive(enc_enabled) 
     1402 
     1403        def _on_authentication_button_clicked(self, widget): 
     1404                if self.session and self.session.enable_encryption: 
     1405                        dialogs.ESessionInfoWindow(self.session) 
    13911406 
    13921407        def _process_command(self, message): 
     
    15891604 
    15901605                        ChatControlBase.print_conversation_line(self, msg, 'status', '', None) 
     1606 
     1607                        if not self.session.verified_identity: 
     1608                                ChatControlBase.print_conversation_line(self, 'SAS not verified', 'status', '', None) 
    15911609                else: 
    15921610                        msg = _('E2E encryption disabled') 
    15931611                        ChatControlBase.print_conversation_line(self, msg, 'status', '', None) 
     1612 
    15941613                self._show_lock_image(e2e_is_active, 'E2E', e2e_is_active, self.session and \ 
    1595                                 self.session.is_loggable()) 
     1614                                self.session.is_loggable(), self.session and self.session.verified_identity) 
    15961615 
    15971616        def print_conversation(self, text, frm='', tim=None, encrypted=False, 
  • trunk/src/common/stanza_session.py

    r9802 r9861  
    184184                self._kc_o = None 
    185185 
     186                # has the remote contact's identity ever been verified? 
     187                self.verified_identity = False 
     188 
    186189        # keep the encrypter updated with my latest cipher key 
    187190        def set_kc_s(self, value): 
     
    339342 
    340343                if i_o == 'a' and self.sas_algs == 'sas28x5': 
    341                         # XXX not necessary if there's a verified retained secret 
     344                        # we don't need to calculate this if there's a verified retained secret 
     345                        # (but we do anyways) 
    342346                        self.sas = crypto.sas_28x5(m_o, self.form_s) 
    343347 
     
    845849                        self.control.print_esession_details() 
    846850 
    847         # calculate and store the new retained secret 
    848         # prompt the user to check the remote party's identity (if necessary) 
    849         def do_retained_secret(self, k, srs): 
     851        def do_retained_secret(self, k, old_srs): 
     852                '''calculate the new retained secret. determine if the user needs to check the remote party's identity. set up callbacks for when the identity has been verified.''' 
     853 
    850854                new_srs = self.hmac(k, 'New Retained Secret') 
     855                self.srs = new_srs 
     856 
    851857                account = self.conn.name 
    852858                bjid = self.jid.getStripped() 
    853859 
    854                 if srs: 
    855                         if secrets.secrets().srs_verified(account, bjid, srs): 
    856                                 secrets.secrets().replace_srs(account, bjid, srs, new_srs, True) 
     860                self.verified_identity = False 
     861 
     862                if old_srs: 
     863                        if secrets.secrets().srs_verified(account, bjid, old_srs): 
     864                                # already had a stored secret verified by the user. 
     865                                secrets.secrets().replace_srs(account, bjid, old_srs, new_srs, True) 
     866                                # continue without warning. 
     867                                self.verified_identity = True 
    857868                        else: 
    858                                 def _cb(verified): 
    859                                         secrets.secrets().replace_srs(account, bjid, srs, new_srs, verified) 
    860  
    861                                 self.check_identity(_cb) 
    862                 else: 
    863                         def _cb(verified): 
    864                                 secrets.secrets().save_new_srs(account, bjid, new_srs, verified) 
    865  
    866                         self.check_identity(_cb) 
     869                                # had a secret, but it wasn't verified. 
     870                                secrets.secrets().replace_srs(account, bjid, old_srs, new_srs, False) 
     871                else: 
     872                        # we don't even have an SRS 
     873                        secrets.secrets().save_new_srs(account, bjid, new_srs, False) 
     874 
     875        def _verified_srs_cb(self): 
     876                secrets.secrets().replace_srs(self.conn.name, self.jid.getStripped(), self.srs, self.srs, True) 
    867877 
    868878        def make_dhfield(self, modp_options, sigmai): 
  • trunk/src/dialogs.py

    r9857 r9861  
    37813781                self.dataform_widget.show_all() 
    37823782                self.vbox.pack_start(self.dataform_widget) 
    3783          
     3783 
    37843784        def on_ok(self): 
    37853785                form = self.dataform_widget.data_form 
     
    37893789                        self.df_response_ok(form) 
    37903790                self.destroy() 
     3791 
     3792class ESessionInfoWindow: 
     3793        '''Class for displaying information about a XEP-0116 encrypted session''' 
     3794        def __init__(self, session): 
     3795                self.session = session 
     3796 
     3797                self.xml = gtkgui_helpers.get_glade('esession_info_window.glade') 
     3798                self.xml.signal_autoconnect(self) 
     3799 
     3800                self.update_info() 
     3801 
     3802                self.window = self.xml.get_widget('esession_info_window') 
     3803                self.window.show_all() 
     3804 
     3805        def update_info(self): 
     3806                labeltext = _('''Your chat session with %s is encrypted.\n\nSAS is: %s''') % (self.session.jid, self.session.sas) 
     3807 
     3808                if self.session.verified_identity: 
     3809                        labeltext += '\n\n' + _('''You have already verified this contact's identity.''') 
     3810                        w = self.xml.get_widget('verification_info') 
     3811                        w.set_no_show_all(True) 
     3812                        w.hide() 
     3813 
     3814                self.xml.get_widget('info_display').set_text(labeltext) 
     3815 
     3816        def on_close_button_clicked(self, widget): 
     3817                self.window.destroy() 
     3818 
     3819        def on_verify_now_button_clicked(self, widget): 
     3820                pritext = _('''Have you verified the remote contact's identity?''') 
     3821                sectext = _('''To prevent a man-in-the-middle attack, you should speak to this person directly (in person or on the phone) and verify that they see the same SAS as you.\n\nThis session's SAS: %s''') % self.session.sas 
     3822                sectext += '\n\n' + _('Did you talk to the remote contact and verify the SAS?') 
     3823 
     3824                dialog = YesNoDialog(pritext, sectext) 
     3825 
     3826                if dialog.get_response() == gtk.RESPONSE_YES: 
     3827                        self.session._verified_srs_cb() 
     3828                        self.session.verified_identity = True 
     3829                        self.update_info() 
  • trunk/src/negotiation.py

    r9115 r9861  
    1414        elif features['logging'] == 'mustnot': 
    1515                return _('- messages will not be logged') 
    16  
    17 def show_sas_dialog(session, jid, sas, on_success): 
    18         def success_cb(checked): 
    19                 on_success(checked) 
    20  
    21         def failure_cb(): 
    22                 session.reject_negotiation() 
    23  
    24         dialogs.ConfirmationDialogCheck(_('''OK to continue with negotiation?'''), 
    25                 _('''You've begun an encrypted session with %s, but it can't be guaranteed that you're talking directly to the person you think you are. 
    26  
    27 You should speak with them directly (in person or on the phone) and confirm that their Short Authentication String is identical to this one: %s 
    28  
    29 Would you like to continue with the encrypted session?''') % (jid, sas), 
    30  
    31                 _('Yes, I verified the Short Authentication String'), 
    32                 on_response_ok=success_cb, on_response_cancel=failure_cb, is_modal=False) 
    3316 
    3417class FeatureNegotiationWindow: 
     
    6851 
    6952        def on_cancel_button_clicked(self, widget): 
    70                 # XXX determine whether to reveal presence 
    71  
    7253                rejection = xmpp.Message(self.jid) 
    7354                rejection.setThread(self.session.thread_id) 
     
    8162                feature.addChild(node=x) 
    8263 
    83                 # XXX optional <body/> 
    84  
    8564                gajim.connections[self.account].send_stanza(rejection) 
    8665 
  • trunk/src/secrets.py

    r8873 r9861  
    137137        def srs_verified(self, account, jid, srs): 
    138138                return self.find_srs(account, jid, srs)[1] 
    139                  
     139 
    140140        def replace_srs(self, account, jid, old_secret, new_secret, verified): 
    141141                our_secrets = self.srs[account][jid] 
  • trunk/src/session.py

    r9846 r9861  
    335335        # ---- ESessions stuff --- 
    336336 
    337         def check_identity(self, on_success): 
    338                 negotiation.show_sas_dialog(self, self.jid, self.sas, on_success) 
    339  
    340337        def handle_negotiation(self, form): 
    341338                if form.getField('accept') and not form['accept'] in ('1', 'true'):