summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authormathieui <mathieui@mathieui.net>2012-03-08 22:39:30 +0100
committermathieui <mathieui@mathieui.net>2012-03-08 22:39:30 +0100
commit9d42ebdf2e5d770ca66a0b7f95adbe36bfd7083e (patch)
tree9146fcf67fa626191c36b49e4a7a94065d470f7e /src
parent13a269d6b211d571486d223bba71bd4230c82838 (diff)
downloadpoezio-9d42ebdf2e5d770ca66a0b7f95adbe36bfd7083e.tar.gz
poezio-9d42ebdf2e5d770ca66a0b7f95adbe36bfd7083e.tar.bz2
poezio-9d42ebdf2e5d770ca66a0b7f95adbe36bfd7083e.tar.xz
poezio-9d42ebdf2e5d770ca66a0b7f95adbe36bfd7083e.zip
Validate the SSL cert using the TOFU (Trust On First Use) model
Diffstat (limited to 'src')
-rw-r--r--src/core.py51
-rw-r--r--src/windows.py42
2 files changed, 89 insertions, 4 deletions
diff --git a/src/core.py b/src/core.py
index 8a4fc7de..91bd0372 100644
--- a/src/core.py
+++ b/src/core.py
@@ -11,14 +11,12 @@ import os
import sys
import time
import curses
-import threading
-import traceback
+import ssl
+from hashlib import sha1
from datetime import datetime
from xml.etree import cElementTree as ET
-from inspect import getargspec
-
import common
import theming
import logging
@@ -94,6 +92,7 @@ class Core(object):
self.events = events.EventHandler()
self.xmpp = singleton.Singleton(connection.Connection)
self.xmpp.core = self
+ self.paused = False
self.remote_fifo = None
# a unique buffer used to store global informations
# that are displayed in almost all tabs, in an
@@ -202,6 +201,7 @@ class Core(object):
self.xmpp.add_event_handler("chatstate_gone", self.on_chatstate_gone)
self.xmpp.add_event_handler("chatstate_inactive", self.on_chatstate_inactive)
self.xmpp.add_event_handler("attention", self.on_attention)
+ self.xmpp.add_event_handler("ssl_cert", self.validate_ssl)
self.all_stanzas = Callback('custom matcher', connection.MatchAll(None), self.incoming_stanza)
self.xmpp.register_handler(self.all_stanzas)
@@ -218,6 +218,44 @@ class Core(object):
for plugin in plugins.split():
self.plugin_manager.load(plugin)
+ def validate_ssl(self, pem):
+ """
+ Check the server certificate using the sleekxmpp ssl_cert event
+ """
+ if config.get('ignore_certificate', 'false').lower() == 'true':
+ return
+ cert = config.get('certificate', '')
+ der = ssl.PEM_cert_to_DER_cert(pem)
+ found_cert = sha1(der).hexdigest()
+ if cert:
+ if found_cert == cert:
+ log.debug('Cert %s OK', found_cert)
+ return
+ else:
+ saved_input = self.current_tab().input
+ log.debug('\nWARNING: CERTIFICATE CHANGED old: %s, new: %s\n', cert, found_cert)
+ input = windows.YesNoInput(text="WARNING! Certificate hash changed to %s. Accept? (y/n)" % found_cert)
+ self.current_tab().input = input
+ input.resize(1, self.current_tab().width, self.current_tab().height-1, 0)
+ input.refresh()
+ self.doupdate()
+ self.paused = True
+ while input.value is None:
+ pass
+ self.current_tab().input = saved_input
+ self.paused = False
+ if input.value:
+ self.information('Setting new certificate: old: %s, new: %s' % (cert, found_cert), 'Info')
+ log.debug('Setting certificate to %s', found_cert)
+ config.set_and_save('certificate', found_cert)
+ else:
+ self.information('You refused to validate the certificate. You are now disconnected', 'Info')
+ self.xmpp.disconnect()
+ else:
+ log.debug('First time. Setting certificate to %s', found_cert)
+ config.set_and_save('certificate', found_cert)
+
+
def start(self):
"""
Init curses, create the first tab, etc
@@ -965,8 +1003,13 @@ class Core(object):
return '\n'
return key
while self.running:
+ if self.paused: continue
char_list = [common.replace_key_with_bound(key)\
for key in self.read_keyboard()]
+ if self.paused:
+ self.current_tab().input.do_command(char_list[0])
+ self.current_tab().input.prompt()
+ continue
# Special case for M-x where x is a number
if len(char_list) == 1:
char = char_list[0]
diff --git a/src/windows.py b/src/windows.py
index 5b48f052..50cad4c6 100644
--- a/src/windows.py
+++ b/src/windows.py
@@ -806,6 +806,48 @@ class HelpText(Win):
def do_command(self, key, raw=False):
return False
+class YesNoInput(Win):
+ """
+ A Window just displaying a Yes/No input
+ Used to ask a confirmation
+ """
+ def __init__(self, text=''):
+ Win.__init__(self)
+ self.key_func = {
+ 'y' : self.on_yes,
+ 'n' : self.on_no,
+ }
+ self.txt = text
+ self.value = None
+
+ def on_yes(self):
+ self.value = True
+
+ def on_no(self):
+ self.value = False
+
+ def refresh(self, txt=None):
+ log.debug('Refresh: %s',self.__class__.__name__)
+ if txt:
+ self.txt = txt
+ with g_lock:
+ self._win.erase()
+ self.addstr(0, 0, self.txt[:self.width-1], to_curses_attr(get_theme().COLOR_INFORMATION_BAR))
+ self.finish_line(get_theme().COLOR_INFORMATION_BAR)
+ self._refresh()
+
+ def do_command(self, key, raw=False):
+ if key.lower() in self.key_func:
+ self.key_func[key]()
+
+ def prompt(self):
+ """Monopolizes the input while waiting for a recognized keypress"""
+ cl = []
+ while self.value is None:
+ if len(cl) == 1 and cl[0] in self.key_func:
+ self.key_func[cl[0]]()
+ cl = self.core.read_keyboard()
+
class Input(Win):
"""
The simplest Input possible, provides just a way to edit a single line