20
20
# import system imports here
23
from bzrlib import errors, ui
24
import bzrlib.gpg as gpg
25
from bzrlib.tests import TestCase
26
from bzrlib.tests import features
28
class FakeConfig(object):
30
def gpg_signing_command(self):
33
def acceptable_keys(self):
37
class TestCommandLine(TestCase):
31
from bzrlib.tests import (
37
class FakeConfig(config.MemoryStack):
39
def __init__(self, content=None):
42
gpg_signing_key=amy@example.com
43
gpg_signing_command=false'''
44
super(FakeConfig, self).__init__(content)
47
class TestCommandLine(tests.TestCase):
50
super(TestCommandLine, self).setUp()
51
self.my_gpg = gpg.GPGStrategy(FakeConfig())
39
53
def test_signing_command_line(self):
40
my_gpg = gpg.GPGStrategy(FakeConfig())
41
self.assertEqual(['false', '--clearsign'],
54
self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
55
self.my_gpg._command_line())
57
def test_signing_command_line_from_default(self):
58
# Using 'default' for gpg_signing_key will use the mail part of 'email'
59
my_gpg = gpg.GPGStrategy(FakeConfig('''
60
email=Amy <amy@example.com>
61
gpg_signing_key=default
62
gpg_signing_command=false'''))
63
self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
64
my_gpg._command_line())
66
def test_signing_command_line_from_email(self):
67
# Not setting gpg_signing_key will use the mail part of 'email'
68
my_gpg = gpg.GPGStrategy(FakeConfig('''
69
email=Amy <amy@example.com>
70
gpg_signing_command=false'''))
71
self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
42
72
my_gpg._command_line())
44
74
def test_checks_return_code(self):
45
75
# This test needs a unix like platform - one with 'false' to run.
46
76
# if you have one, please make this work :)
47
my_gpg = gpg.GPGStrategy(FakeConfig())
48
self.assertRaises(errors.SigningFailed, my_gpg.sign, 'content')
77
self.assertRaises(errors.SigningFailed, self.my_gpg.sign, 'content')
50
79
def assertProduces(self, content):
51
80
# This needs a 'cat' command or similar to work.
52
my_gpg = gpg.GPGStrategy(FakeConfig())
53
81
if sys.platform == 'win32':
54
82
# Windows doesn't come with cat, and we don't require it
55
83
# so lets try using python instead.
56
84
# But stupid windows and line-ending conversions.
57
85
# It is too much work to make sys.stdout be in binary mode.
58
86
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65443
59
my_gpg._command_line = lambda:[sys.executable, '-c',
87
self.my_gpg._command_line = lambda:[sys.executable, '-c',
60
88
'import sys; sys.stdout.write(sys.stdin.read())']
61
89
new_content = content.replace('\n', '\r\n')
63
self.assertEqual(new_content, my_gpg.sign(content))
91
self.assertEqual(new_content, self.my_gpg.sign(content))
65
my_gpg._command_line = lambda:['cat', '-']
66
self.assertEqual(content, my_gpg.sign(content))
93
self.my_gpg._command_line = lambda:['cat', '-']
94
self.assertEqual(content, self.my_gpg.sign(content))
68
96
def test_returns_output(self):
69
97
content = "some content\nwith newlines\n"
184
215
-----END PGP PRIVATE KEY BLOCK-----
218
revoked_key = StringIO("""-----BEGIN PGP PUBLIC KEY BLOCK-----
219
Version: GnuPG v1.4.11 (GNU/Linux)
221
mI0ETjlW5gEEAOb/6P+TVM59E897wRtatxys2BhsHCXM4T7xjIiANfDwejDdifqh
222
tluTfSJLLxPembtrrEjux1C0AJgc+f0MIfsc3Pr3eFJzKB2ot/1IVG1/1KnA0zt3
223
W2xPT3lRib27WJ9Fag+dMtQaIzgJ7/n2DFxsFZ33FD2kxrEXB2exGg6FABEBAAGI
224
pgQgAQIAEAUCTjlXkAkdAHJldm9rZWQACgkQjs6dvEpb0cQPHAP/Wi9rbx0e+1Sf
225
ziGgyVdr3m3A6uvze5oXKVgFRbGRUYSH4/I8GW0W9x4TcRg9h+YaQ8NUdADr9kNE
226
tKAljLqYA5qdqSfYuaij1M++Xj+KUZ359R74sHuQqwnRy1XXQNfRs/QpXA7vLdds
227
rjg+pbWuXO92TZJUdnqtWW+VEyZBsPy0G3Rlc3Qga2V5IDx0ZXN0QGV4YW1wbGUu
228
Y29tPoi4BBMBAgAiBQJOOVbmAhsDBgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAK
229
CRCOzp28SlvRxNWzA/42WVmI0b+6mF/imEOlY1TiyvrcpK250rkSDsCtL4lOwy7G
230
antZhpgNfnXRd/ySfsS3EB6dpOWgOSxGRvWQhA+vxBT9BYNk49qd3JIrSaSWpR12
231
rET8qO1rEQQFWsw03CxTGujxGlmEO+a1yguRXp2UWaY7FngcQmD+8q7BUIVm7riN
232
BE45VuYBBADTEH2jHTjNCc5CMOhea6EJTrkx3upcEqB2oyhWeSWJiBGOxlcddsjo
233
3J3/EmBB8kK1hM9TidD3SG64x1N287lg8ELJBlKv+pQVyxohGJ1u/THgpTDMMQcL
234
luG5rAHQGSfyzKTiOnaTyBYg3M/nzgUOU9dKEFB0EA3tjUXFOT+r3wARAQABiJ8E
235
GAECAAkFAk45VuYCGwwACgkQjs6dvEpb0cRSLQP/fzCWX2lXwlwWiVF8BOPF7o9z
236
icHErc7/X17RGb4qj1kVf+UkRdUWJrbEVh4h6MncBIuA70WsYogiw+Kz/0LCtQAR
237
YUJsPy/EL++OKPH1aFasOdTxwkTka85+RdYqhP1+z/aYLFMWq6mRFI+o6x2k5mGi
240
-----END PGP PUBLIC KEY BLOCK-----
243
expired_key = StringIO("""-----BEGIN PGP PUBLIC KEY BLOCK-----
244
Version: GnuPG v1.4.11 (GNU/Linux)
246
mI0ETjZ6PAEEALkR4GcFQidCCxV7pgQwQd5MZua0YO2l92fVqHX+PhnZ6egCLKdD
247
2bWlMUd6MLPF3FlRL7BBAxvW/DazkBOp7ljsnpMpptEzY49Uem1irYLYiVb9zK96
248
0sQZzFxFkfEYetQEXC68mIck8tbySOX5NAOw++3jFm3J7dsU1R3XtYzRABEBAAG0
249
G3Rlc3Qga2V5IDx0ZXN0QGV4YW1wbGUuY29tPoi+BBMBAgAoBQJONno8AhsDBQkA
250
AVGABgsJCAcDAgYVCAIJCgsEFgIDAQIeAQIXgAAKCRAc4m97T40VEz+DA/9PBphG
251
Yp9cHVaHSfTUKGTGgIbvRe60sFNpDCYZeAGDrygOMuI8MNzbVpwefRBFHVPx7jWd
252
rrYMsLkcsNUS9D0baU+0D/qp7JVg7ZSQtG0O6IG4eTZhibteY1fu0+unlXmg9NHx
253
5VvhwzBiJDYji00M2p/CZEMiYFUuy76CsxUpN7iNBE42ejwBBACkv2/mX7IPQg0C
254
A3KSrJsJv+sdvKm4b4xuI4OwagwTIVz4KlTqV4IBrVjSBfwyMXucXz0bTW85qjgA
255
+n67td8vyjYYZUEz1uY9lSquQQDnAN0txL3cLHZXWiWOkmzZVddQtlflK2a/J9o0
256
QkHPVUm+hc4l64dIzStrNl2S66fAvQARAQABiKUEGAECAA8FAk42ejwCGwwFCQAB
257
UYAACgkQHOJve0+NFROEYQP/epg+o8iBs31hkSERyZjrRR66LpywezWj30Rn/3mX
258
Fzi9HkF4xLemWOzdNt9C5PYrOep85PQg8haEjknxVjZFS0ikT1h3OWk/TF1ZrLVm
259
WzyX8DaHQEjKpLJJjXcAbTiZBNMk0QaVC9RvIeHpCf3n3DC49DdjsPJRMKOn8KDi
262
-----END PGP PUBLIC KEY BLOCK-----
187
264
context.import_(key)
188
265
context.import_(secret_key)
266
context.import_(revoked_key)
267
context.import_(expired_key)
190
def test_verify_valid(self):
269
def test_verify_untrusted_but_accepted(self):
270
#untrusted by gpg but listed as acceptable_keys by user
191
271
self.requireFeature(features.gpgme)
192
272
self.import_keys()
194
274
content = """-----BEGIN PGP SIGNED MESSAGE-----
218
298
self.assertEqual((gpg.SIGNATURE_VALID, None), my_gpg.verify(content,
301
def test_verify_unacceptable_key(self):
302
self.requireFeature(features.gpgme)
305
content = """-----BEGIN PGP SIGNED MESSAGE-----
308
bazaar-ng testament short form 1
309
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
310
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
311
-----BEGIN PGP SIGNATURE-----
312
Version: GnuPG v1.4.11 (GNU/Linux)
314
iQEcBAEBAgAGBQJN+ekFAAoJEIdoGx7jCA5FGtEH/i+XxJRvqU6wdBtLVrGBMAGk
315
FZ5VP+KyXYtymSbgSstj/vM12NeMIeFs3xGnNnYuX1MIcY6We5TKtCH0epY6ym5+
316
6g2Q2QpQ5/sT2d0mWzR0K4uVngmxVQaXTdk5PdZ40O7ULeDLW6CxzxMHyUL1rsIx
317
7UBUTBh1O/1n3ZfD99hUkm3hVcnsN90uTKH59zV9NWwArU0cug60+5eDKJhSJDbG
318
rIwlqbFAjDZ7L/48e+IaYIJwBZFzMBpJKdCxzALLtauMf+KK8hGiL2hrRbWm7ty6
319
NgxfkMYOB4rDPdSstT35N+5uBG3n/UzjxHssi0svMfVETYYX40y57dm2eZQXFp8=
321
-----END PGP SIGNATURE-----
323
plain = """bazaar-ng testament short form 1
324
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
325
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
327
my_gpg = gpg.GPGStrategy(FakeConfig())
328
my_gpg.set_acceptable_keys("foo@example.com")
329
self.assertEqual((gpg.SIGNATURE_KEY_MISSING, u'E3080E45'),
330
my_gpg.verify(content, plain))
332
def test_verify_valid_but_untrusted(self):
333
self.requireFeature(features.gpgme)
336
content = """-----BEGIN PGP SIGNED MESSAGE-----
339
bazaar-ng testament short form 1
340
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
341
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
342
-----BEGIN PGP SIGNATURE-----
343
Version: GnuPG v1.4.11 (GNU/Linux)
345
iQEcBAEBAgAGBQJN+ekFAAoJEIdoGx7jCA5FGtEH/i+XxJRvqU6wdBtLVrGBMAGk
346
FZ5VP+KyXYtymSbgSstj/vM12NeMIeFs3xGnNnYuX1MIcY6We5TKtCH0epY6ym5+
347
6g2Q2QpQ5/sT2d0mWzR0K4uVngmxVQaXTdk5PdZ40O7ULeDLW6CxzxMHyUL1rsIx
348
7UBUTBh1O/1n3ZfD99hUkm3hVcnsN90uTKH59zV9NWwArU0cug60+5eDKJhSJDbG
349
rIwlqbFAjDZ7L/48e+IaYIJwBZFzMBpJKdCxzALLtauMf+KK8hGiL2hrRbWm7ty6
350
NgxfkMYOB4rDPdSstT35N+5uBG3n/UzjxHssi0svMfVETYYX40y57dm2eZQXFp8=
352
-----END PGP SIGNATURE-----
354
plain = """bazaar-ng testament short form 1
355
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
356
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
358
my_gpg = gpg.GPGStrategy(FakeConfig())
359
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None), my_gpg.verify(content,
221
362
def test_verify_bad_testament(self):
222
363
self.requireFeature(features.gpgme)
223
364
self.import_keys()
225
366
content = """-----BEGIN PGP SIGNED MESSAGE-----
249
390
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None), my_gpg.verify(content,
394
def test_verify_revoked_signature(self):
395
self.requireFeature(features.gpgme)
398
content = """-----BEGIN PGP SIGNED MESSAGE-----
402
-----BEGIN PGP SIGNATURE-----
403
Version: GnuPG v1.4.11 (GNU/Linux)
405
iJwEAQECAAYFAk45V18ACgkQjs6dvEpb0cSIZQP/eOGTXGPlrNwvDkcX2d8O///I
406
ecB4sUIUEpv1XAk1MkNu58lsjjK72lRaLusEGqd7HwrFmpxVeVs0oWLg23PNPCFs
407
yJBID9ma+VxFVPtkEFnrc1R72sBJLfBcTxMkwVTC8eeznjdtn+cg+aLkxbPdrGnr
410
-----END PGP SIGNATURE-----
413
my_gpg = gpg.GPGStrategy(FakeConfig())
414
my_gpg.set_acceptable_keys("test@example.com")
415
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None), my_gpg.verify(content,
252
418
def test_verify_invalid(self):
253
419
self.requireFeature(features.gpgme)
254
421
content = """-----BEGIN PGP SIGNED MESSAGE-----
273
440
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None),
274
441
my_gpg.verify(content, plain))
443
def test_verify_expired_but_valid(self):
444
self.requireFeature(features.gpgme)
446
content = """-----BEGIN PGP SIGNED MESSAGE-----
449
bazaar-ng testament short form 1
450
revision-id: test@example.com-20110801100657-f1dr1nompeex723z
451
sha1: 59ab434be4c2d5d646dee84f514aa09e1b72feeb
452
-----BEGIN PGP SIGNATURE-----
453
Version: GnuPG v1.4.10 (GNU/Linux)
455
iJwEAQECAAYFAk42esUACgkQHOJve0+NFRPc5wP7BoZkzBU8JaHMLv/LmqLr0sUz
456
zuE51ofZZ19L7KVtQWsOi4jFy0fi4A5TFwO8u9SOfoREGvkw292Uty9subSouK5/
457
mFmDOYPQ+O83zWgYZsBmMJWYDZ+X9I6XXZSbPtV/7XyTjaxtl5uRnDVJjg+AzKvD
460
-----END PGP SIGNATURE-----
462
plain = """bazaar-ng testament short form 1
463
revision-id: test@example.com-20110801100657-f1dr1nompeex723z
464
sha1: 59ab434be4c2d5d646dee84f514aa09e1b72feeb
466
my_gpg = gpg.GPGStrategy(FakeConfig())
467
self.assertEqual((gpg.SIGNATURE_EXPIRED, u'4F8D1513'),
468
my_gpg.verify(content, plain))
470
def test_verify_unknown_key(self):
471
self.requireFeature(features.gpgme)
473
content = """-----BEGIN PGP SIGNED MESSAGE-----
477
-----BEGIN PGP SIGNATURE-----
478
Version: GnuPG v1.4.11 (GNU/Linux)
480
iQEcBAEBAgAGBQJOORKwAAoJENf6AkFdUeVvJDYH/1Cz+AJn1Jvy5n64o+0fZ5Ow
481
Y7UQb4QQTIOV7jI7n4hv/yBzuHrtImFzYvQl/o2Ezzi8B8L5gZtQy+xCUF+Q8iWs
482
gytZ5JUtSze7hDZo1NUl4etjoRGYqRfrUcvE2LkVH2dFbDGyyQfVmoeSHa5akuuP
483
QZmyg2F983rACVIpGvsqTH6RcBdvE9vx68lugeKQA8ArDn39/74FBFipFzrXSPij
484
eKFpl+yZmIb3g6HkPIC8o4j/tMvc37xF1OG5sBu8FT0+FC+VgY7vAblneDftAbyP
485
sIODx4WcfJtjLG/qkRYqJ4gDHo0eMpTJSk2CWebajdm4b+JBrM1F9mgKuZFLruE=
487
-----END PGP SIGNATURE-----
490
my_gpg = gpg.GPGStrategy(FakeConfig())
491
self.assertEqual((gpg.SIGNATURE_KEY_MISSING, u'5D51E56F'),
492
my_gpg.verify(content, plain))
276
494
def test_set_acceptable_keys(self):
277
495
self.requireFeature(features.gpgme)
278
496
self.import_keys()
281
499
self.assertEqual(my_gpg.acceptable_keys,
282
500
[u'B5DEED5FCB15DAE6ECEF919587681B1EE3080E45'])
502
def test_set_acceptable_keys_from_config(self):
503
self.requireFeature(features.gpgme)
505
my_gpg = gpg.GPGStrategy(FakeConfig(
506
'acceptable_keys=bazaar@example.com'))
507
my_gpg.set_acceptable_keys(None)
508
self.assertEqual(my_gpg.acceptable_keys,
509
[u'B5DEED5FCB15DAE6ECEF919587681B1EE3080E45'])
284
511
def test_set_acceptable_keys_unknown(self):
285
512
self.requireFeature(features.gpgme)
286
513
my_gpg = gpg.GPGStrategy(FakeConfig())
516
self.notes.append(args[0] % args[1:])
517
self.overrideAttr(trace, 'note', note)
287
518
my_gpg.set_acceptable_keys("unknown")
288
519
self.assertEqual(my_gpg.acceptable_keys, [])
520
self.assertEqual(self.notes,
521
['No GnuPG key results for pattern: unknown'])
291
524
class TestDisabled(TestCase):