Added Daniel Carrera's GPG key to the hints database.
[zeroinstall.git] / zeroinstall / 0launch-gui / trust_box.py
blobf2240529f263e03db889de4a82a0ca278223b255
1 # -*- coding: utf-8 -*-
3 import gtk
4 from zeroinstall.injector.model import SafeException
5 from zeroinstall.injector import gpg, trust
6 from zeroinstall.injector.iface_cache import iface_cache
8 import gui
9 import dialog, help_box
11 def pretty_fp(fp):
12 s = fp[0:4]
13 for x in range(4, len(fp), 4):
14 s += ' ' + fp[x:x + 4]
15 return s
17 class TrustBox(dialog.Dialog):
18 interface = None
19 sigs = None
20 iface_xml = None
21 valid_sigs = None
23 def __init__(self, interface, sigs, iface_xml):
24 dialog.Dialog.__init__(self)
26 def destroy(box):
27 global _queue
28 assert _queue[0] is self
29 del _queue[0]
30 # Remove any queued boxes that are no longer required
31 def still_untrusted(box):
32 for sig in box.valid_sigs:
33 if trust.trust_db.is_trusted(sig.fingerprint):
34 return False
35 return True
36 if _queue:
37 next = _queue[0]
38 if still_untrusted(next):
39 next.show()
40 else:
41 next.trust_keys([])
42 next.destroy() # Will trigger this again...
43 self.connect('destroy', destroy)
45 def left(text):
46 label = gtk.Label(text)
47 label.set_alignment(0, 0.5)
48 label.set_selectable(True)
49 return label
51 self.interface = interface
52 self.sigs = sigs
53 self.iface_xml = iface_xml
55 self.set_title('Confirm trust')
57 vbox = gtk.VBox(False, 4)
58 vbox.set_border_width(4)
59 self.vbox.pack_start(vbox, True, True, 0)
61 label = left('Checking: ' + interface.uri + '\n\n'
62 'Please confirm that you trust '
63 'these keys to sign software updates:')
64 vbox.pack_start(label, False, True, 0)
66 notebook = gtk.Notebook()
67 vbox.pack_start(notebook, True, True, 0)
69 self.add_button(gtk.STOCK_HELP, gtk.RESPONSE_HELP)
70 self.add_button(gtk.STOCK_CANCEL, gtk.RESPONSE_CANCEL)
71 self.add_button(gtk.STOCK_ADD, gtk.RESPONSE_OK)
72 self.set_default_response(gtk.RESPONSE_OK)
74 self.valid_sigs = [s for s in sigs if isinstance(s, gpg.ValidSig)]
75 if not self.valid_sigs:
76 raise SafeException('No valid signatures found')
78 trust_checkbox = {} # Sig -> CheckButton
79 def ok_sensitive():
80 trust_any = False
81 for toggle in trust_checkbox.values():
82 if toggle.get_active():
83 trust_any = True
84 break
85 self.set_response_sensitive(gtk.RESPONSE_OK, trust_any)
86 for sig in self.valid_sigs:
87 if hasattr(sig, 'get_details'):
88 name = '<unknown>'
89 details = sig.get_details()
90 for item in details:
91 if item[0] in ('pub', 'uid') and \
92 len(item) > 9:
93 name = item[9]
94 break
95 else:
96 name = None
97 page = gtk.VBox(False, 4)
98 page.set_border_width(8)
99 page.pack_start(left('Fingerprint: ' + pretty_fp(sig.fingerprint)), False, True, 0)
100 if name is not None:
101 page.pack_start(left('Claimed identity: ' + name), False, True, 0)
103 frame = gtk.Frame('Unreliable hints database says')
104 frame.set_border_width(4)
105 hint = left(hints.get(sig.fingerprint, 'Warning: Nothing known about this key!'))
106 hint.set_line_wrap(True)
107 hint.set_padding(4, 4)
108 frame.add(hint)
109 page.pack_start(frame, True, True, 0)
111 trust_checkbox[sig] = gtk.CheckButton('_Trust this key')
112 page.pack_start(trust_checkbox[sig], False, True, 0)
113 trust_checkbox[sig].connect('toggled', lambda t: ok_sensitive())
115 notebook.append_page(page, gtk.Label(name or 'Signature'))
117 ok_sensitive()
118 self.vbox.show_all()
120 def response(box, resp):
121 if resp == gtk.RESPONSE_HELP:
122 trust_help.display()
123 return
124 if resp == gtk.RESPONSE_OK:
125 self.trust_keys([sig for sig in trust_checkbox if trust_checkbox[sig].get_active()])
126 self.destroy()
127 self.connect('response', response)
129 def trust_keys(self, sigs):
130 try:
131 for sig in sigs:
132 trust.trust_db.trust_key(sig.fingerprint)
134 if hasattr(gui.policy, 'process_pending'):
135 # 0launch >= 0.25
136 gui.policy.process_pending()
137 else:
138 # Problem: calls recalculate(), which may trigger re-downloading interfaces
139 # we are currently waiting to confirm!
140 if not iface_cache.update_interface_if_trusted(self.interface, self.sigs,
141 self.iface_xml):
142 raise Exception('Bug: still not trusted!!')
143 except Exception, ex:
144 dialog.alert(None, ex)
145 if not isinstance(ex, SafeException):
146 raise
148 _queue = []
149 def confirm_trust(interface, sigs, iface_xml):
150 _queue.append(TrustBox(interface, sigs, iface_xml))
151 if len(_queue) == 1:
152 _queue[0].show()
154 trust_help = help_box.HelpBox("Trust Help",
155 ('Overview', """
156 When you run a program, it typically has access to all your files and can generally do \
157 anything that you're allowed to do (delete files, send emails, etc). So it's important \
158 to make sure that you don't run anything malicious."""),
160 ('Digital signatures', """
161 Each software author creates a 'key-pair'; a 'public key' and a 'private key'. Without going \
162 into the maths, only something encrypted with the private key will decrypt with the public key.
164 So, when a programmer releases some software, they encrypt it with their private key (which no-one \
165 else has). When you download it, the injector checks that it decrypts using their public key, thus \
166 proving that it came from them and hasn't been tampered with."""),
168 ('Trust', """
169 After the injector has checked that the software hasn't been modified since it was signed with \
170 the private key, you still have the following problems:
172 1. Does the public key you have really belong to the author?
173 2. Even if the software really did come from that person, do you trust them?"""),
175 ('Key fingerprints', """
176 To confirm (1), you should compare the public key you have with the genuine one. To make this \
177 easier, the injector displays a 'fingerprint' for the key. Look in mailing list postings or some \
178 other source to check that the fingerprint is right (a different key will have a different \
179 fingerprint).
181 You're trying to protect against the situation where an attacker breaks into a web site \
182 and puts up malicious software, signed with the attacker's private key, and puts up the \
183 attacker's public key too. If you've downloaded this software before, you \
184 should be suspicious that you're being asked to confirm another key!"""),
186 ('Reputation', """
187 In general, most problems seem to come from malicous and otherwise-unknown people \
188 replacing software with modified versions, or creating new programs intended only to \
189 cause damage. So, check your programs are signed by a key with a good reputation!"""))
191 hints = {
192 '1DC295D11A3F910DA49D3839AA1A7812B40B0B6E' :
193 'Ken Hayber has been writing ROX applications since 2003. This key '
194 'was announced on the rox-users list on 5 Jun 2005.',
196 '4338D5420E0BAEB6B2E73530B66A4F24AB8B4B65' :
197 'Thomas Formella is experimenting with packaging programs for 0launch. This key '
198 'was announced on 11 Sep 2005 on the zero-install mailing list.',
200 '92429807C9853C0744A68B9AAE07828059A53CC1' :
201 'Thomas Leonard created Zero Install and ROX. This key is used to sign updates to the '
202 'injector; you should accept it.',
204 '0597A2AFB6B372ACB97AC6E433B938C2E9D8826D' :
205 'Stephen Watson is a project admin for the ROX desktop, and has been involved with the '
206 'project since 2000. This key has been used for signing software since the 23 Jul 2005 '
207 'announcement on the zero-install mailing list.',
209 'F0A0CA2A8D8FCC123F5EC04CD8D59DC384AE988E' :
210 'Piero Ottuzzi is experimenting with packaging programs for 0launch. This key has been '
211 'known since a 16 Mar 2005 post to the zero-install mailing list. It was first used to '
212 'sign software in an announcement posted on 9 Aug 2005.',
214 'FC71DC3364367CE82F91472DDF32928893D894E9' :
215 'Niklas Höglund is experimenting with using Zero Install on the Nokia 770. This key has '
216 'been known since the announcement of 4 Apr 2006 on the zero-install mailing list.',
218 'B93AAE76C40A3222425A04FA0BDA706F2C21E592' :
219 'Ilja Honkonen is experimenting with packaging software for Zero Install. This key '
220 'was announced on 2006-04-21 on the zero-install mailing list.',
222 '5D3D90FB4E6FE10C7F76E94DEE6BC26DBFDE8022' :
223 'Dennis Tomas leads the rox4debian packaging effort. This key has been known since '
224 'an email forwarded to the rox-devel list on 2006-05-28.',
226 '2E2B4E59CAC8D874CD2759D34B1095AF2E992B19' :
227 'Lennon Cook creates the FreeBSD-x86 binaries for various ROX applications. '
228 'This key was announced in a Jun 17, 2006 post to the rox-devel mailing list.',
230 '7722DC5085B903FF176CCAA9695BA303C9839ABC' :
231 'Lennon Cook creates the FreeBSD-x86 binaries for various ROX applications. '
232 'This key was announced in an Oct 5, 2006 post to the rox-users mailing list.',
234 '617794D7C3DFE0FFF572065C0529FDB71FB13910' :
235 'This low-security key is used to sign Zero Install interfaces which have been '
236 "automatically generated by a script. Typically, the upstream software didn't "
237 "come with a signature, so it's impossible to know if the code is actually OK. "
238 "However, there is still some benefit: if the archive is modified after the "
239 "script has signed it then any further changes will be detected, so this isn't "
240 "completely pointless.",
242 '5E665D0ECCCF1215F725BD2FA7421904E3D1B654' :
243 'Daniel Carrera works on the OpenDocument viewer from opendocumentfellowship.org. '
244 'This key was confirmed in a zero-install mailing list post on 2007-01-09.',