trust_box.py :  » Installer » Zero-Install » zeroinstall-injector-0.47 » zeroinstall » gtkui » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » Installer » Zero Install 
Zero Install » zeroinstall injector 0.47 » zeroinstall » gtkui » trust_box.py
"""
A dialog box for confirming GPG keys.
"""

# Copyright (C) 2009, Thomas Leonard
# -*- coding: utf-8 -*-
# See the README file for details, or visit http://0install.net.
from zeroinstall import _

import gtk
from zeroinstall.injector.model import SafeException
from zeroinstall.injector import gpg,trust
from zeroinstall.support import tasks
from zeroinstall.gtkui import help_box,gtkutils

def frame(page, title, content, expand = False):
  frame = gtk.Frame()
  label = gtk.Label()
  label.set_markup('<b>%s</b>' % title)
  frame.set_label_widget(label)
  frame.set_shadow_type(gtk.SHADOW_NONE)
  if type(content) in (str, unicode):
    content = gtk.Label(content)
    content.set_alignment(0, 0.5)
    content.set_selectable(True)
  frame.add(content)
  if hasattr(content, 'set_padding'):
    content.set_padding(8, 4)
  else:
    content.set_border_width(8)
  page.pack_start(frame, expand, True, 0)

def pretty_fp(fp):
  s = fp[0:4]
  for x in range(4, len(fp), 4):
    s += ' ' + fp[x:x + 4]
  return s

def left(text):
  label = gtk.Label(text)
  label.set_alignment(0, 0.5)
  label.set_selectable(True)
  return label

def make_hints_area(closed, key_info_fetcher):
  def text(parent):
    text = ""
    for node in parent.childNodes:
      if node.nodeType == node.TEXT_NODE:
        text = text + node.data
    return text

  hints = gtk.VBox(False, 4)

  shown = set()
  def add_hints():
    infos = set(key_info_fetcher.info) - shown
    for info in infos:
      hints.add(make_hint(info.getAttribute("vote"), text(info)))
      shown.add(info)

    if not(key_info_fetcher.blocker or shown):
      hints.add(make_hint("bad", _('Warning: Nothing known about this key!')))

  if key_info_fetcher.blocker:
    status = left(key_info_fetcher.status)
    hints.add(status)

    @tasks.async
    def update_when_ready():
      while key_info_fetcher.blocker:
        yield key_info_fetcher.blocker, closed
        if closed.happened:
          # The dialog box was closed. Stop updating.
          return
        add_hints()
      status.destroy()
    update_when_ready()
  else:
    add_hints()

  hints.show()
  return hints

def make_hint(vote, hint_text):
  hint_icon = gtk.Image()
  if vote == "good":
    hint_icon.set_from_stock(gtk.STOCK_YES, gtk.ICON_SIZE_BUTTON)
  else:
    hint_icon.set_from_stock(gtk.STOCK_DIALOG_WARNING, gtk.ICON_SIZE_BUTTON)
  hint = left(hint_text)
  hint.set_line_wrap(True)
  hint_hbox = gtk.HBox(False, 4)
  hint_hbox.pack_start(hint_icon, False, True, 0)
  hint_hbox.pack_start(hint, True, True, 0)
  hint_icon.set_alignment(0, 0)
  hint_hbox.show_all()
  return hint_hbox

class TrustBox(gtk.Dialog):
  """Display a dialog box asking the user to confirm that one of the
  keys is trusted for this domain.
  """
  parent = None
  closed = None

  def __init__(self, pending, valid_sigs, parent):
    """@since: 0.42"""
    assert valid_sigs

    gtk.Dialog.__init__(self)
    self.set_has_separator(False)
    self.set_position(gtk.WIN_POS_CENTER)
    self.set_transient_for(parent)

    self.closed = tasks.Blocker(_("confirming keys with user"))

    domain = trust.domain_from_url(pending.url)
    assert domain

    def destroy(box):
      self.closed.trigger()

    self.connect('destroy', destroy)

    self.set_title(_('Confirm trust'))

    vbox = gtk.VBox(False, 4)
    vbox.set_border_width(4)
    self.vbox.pack_start(vbox, True, True, 0)

    notebook = gtk.Notebook()

    if len(valid_sigs) == 1:
      notebook.set_show_tabs(False)

    label = left(_('Checking: %s') % pending.url)
    label.set_padding(4, 4)
    vbox.pack_start(label, False, True, 0)

    currently_trusted_keys = trust.trust_db.get_keys_for_domain(domain)
    if currently_trusted_keys:
      keys = [gpg.load_key(fingerprint) for fingerprint in currently_trusted_keys]
      descriptions = [_("%(key_name)s\n(fingerprint: %(key_fingerprint)s)") % {'key_name': key.name, 'key_fingerprint': pretty_fp(key.fingerprint)}
          for key in keys]
    else:
      descriptions = [_('None')]
    frame(vbox, _('Keys already approved for "%s"') % domain, '\n'.join(descriptions))

    label = left(ngettext('This key signed the feed:', 'These keys signed the feed:', len(valid_sigs)))

    label.set_padding(4, 4)
    vbox.pack_start(label, False, True, 0)

    vbox.pack_start(notebook, True, True, 0)

    self.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP)
    self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
    self.add_button(gtk.STOCK_ADD, gtk.RESPONSE_OK)
    self.set_default_response(gtk.RESPONSE_OK)

    trust_checkbox = {}  # Sig -> CheckButton
    def ok_sensitive():
      trust_any = False
      for toggle in trust_checkbox.values():
        if toggle.get_active():
          trust_any = True
          break
      self.set_response_sensitive(gtk.RESPONSE_OK, trust_any)

    for sig in valid_sigs:
      if hasattr(sig, 'get_details'):
        name = '<unknown>'
        details = sig.get_details()
        for item in details:
          if item[0] == 'uid' and len(item) > 9:
            name = item[9]
            break
      else:
        name = None
      page = gtk.VBox(False, 4)
      page.set_border_width(8)

      frame(page, _('Fingerprint'), pretty_fp(sig.fingerprint))

      if name is not None:
        frame(page, _('Claimed identity'), name)

      frame(page, _('Unreliable hints database says'), make_hints_area(self.closed, valid_sigs[sig]))

      already_trusted = trust.trust_db.get_trust_domains(sig.fingerprint)
      if already_trusted:
        frame(page, _('You already trust this key for these domains'),
          '\n'.join(already_trusted))

      trust_checkbox[sig] = gtk.CheckButton(_('_Trust this key'))
      page.pack_start(trust_checkbox[sig], False, True, 0)
      trust_checkbox[sig].connect('toggled', lambda t: ok_sensitive())

      notebook.append_page(page, gtk.Label(name or 'Signature'))

    ok_sensitive()
    self.vbox.show_all()

    def response(box, resp):
      if resp == gtk.RESPONSE_HELP:
        trust_help.display()
        return
      if resp == gtk.RESPONSE_OK:
        self.trust_keys([sig for sig in trust_checkbox if trust_checkbox[sig].get_active()], domain)
      self.destroy()
    self.connect('response', response)
  
  def trust_keys(self, agreed_sigs, domain):
    assert domain
    try:
      for sig in agreed_sigs:
        trust.trust_db.trust_key(sig.fingerprint, domain)

      trust.trust_db.notify()
    except Exception, ex:
      gtkutils.show_message_box(self, str(ex), gtk.MESSAGE_ERROR)
      if not isinstance(ex, SafeException):
        raise

trust_help = help_box.HelpBox(_("Trust Help"),
(_('Overview'), '\n' +
_("""When you run a program, it typically has access to all your files and can generally do \
anything that you're allowed to do (delete files, send emails, etc). So it's important \
to make sure that you don't run anything malicious.""")),

(_('Digital signatures'), '\n' +
_("""Each software author creates a 'key-pair'; a 'public key' and a 'private key'. Without going \
into the maths, only something encrypted with the private key will decrypt with the public key.

So, when a programmer releases some software, they encrypt it with their private key (which no-one \
else has). When you download it, the injector checks that it decrypts using their public key, thus \
proving that it came from them and hasn't been tampered with.""")),

(_('Trust'), '\n' +
_("""After the injector has checked that the software hasn't been modified since it was signed with \
the private key, you still have the following problems:

1. Does the public key you have really belong to the author?
2. Even if the software really did come from that person, do you trust them?""")),

(_('Key fingerprints'), '\n' +
_("""To confirm (1), you should compare the public key you have with the genuine one. To make this \
easier, the injector displays a 'fingerprint' for the key. Look in mailing list postings or some \
other source to check that the fingerprint is right (a different key will have a different \
fingerprint).

You're trying to protect against the situation where an attacker breaks into a web site \
and puts up malicious software, signed with the attacker's private key, and puts up the \
attacker's public key too. If you've downloaded this software before, you \
should be suspicious that you're being asked to confirm another key!""")),

(_('Reputation'), '\n' +
_("""In general, most problems seem to come from malicous and otherwise-unknown people \
replacing software with modified versions, or creating new programs intended only to \
cause damage. So, check your programs are signed by a key with a good reputation!""")))
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.