41
42
def __init__(self, content=None):
42
43
if content is None:
44
45
gpg_signing_key=amy@example.com
46
gpg_signing_command=false'''
46
47
super(FakeConfig, self).__init__(content)
50
class TestCommandLine(tests.TestCase):
53
super(TestCommandLine, self).setUp()
54
self.my_gpg = gpg.GPGStrategy(FakeConfig())
56
def test_signing_command_line(self):
57
self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
58
self.my_gpg._command_line())
60
def test_signing_command_line_from_default(self):
61
# Using 'default' for gpg_signing_key will use the mail part of 'email'
62
my_gpg = gpg.GPGStrategy(FakeConfig('''
63
email=Amy <amy@example.com>
64
gpg_signing_key=default
65
gpg_signing_command=false'''))
66
self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
67
my_gpg._command_line())
69
def test_signing_command_line_from_email(self):
70
# Not setting gpg_signing_key will use the mail part of 'email'
71
my_gpg = gpg.GPGStrategy(FakeConfig('''
72
email=Amy <amy@example.com>
73
gpg_signing_command=false'''))
74
self.assertEqual(['false', '--clearsign', '-u', 'amy@example.com'],
75
my_gpg._command_line())
77
def test_checks_return_code(self):
78
# This test needs a unix like platform - one with 'false' to run.
79
# if you have one, please make this work :)
80
self.assertRaises(errors.SigningFailed, self.my_gpg.sign, 'content')
82
def assertProduces(self, content):
83
# This needs a 'cat' command or similar to work.
84
if sys.platform == 'win32':
85
# Windows doesn't come with cat, and we don't require it
86
# so lets try using python instead.
87
# But stupid windows and line-ending conversions.
88
# It is too much work to make sys.stdout be in binary mode.
89
# http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/65443
90
self.my_gpg._command_line = lambda:[sys.executable, '-c',
91
'import sys; sys.stdout.write(sys.stdin.read())']
92
new_content = content.replace('\n', '\r\n')
94
self.assertEqual(new_content, self.my_gpg.sign(content))
96
self.my_gpg._command_line = lambda:['cat', '-']
97
self.assertEqual(content, self.my_gpg.sign(content))
99
def test_returns_output(self):
100
content = "some content\nwith newlines\n"
101
self.assertProduces(content)
103
def test_clears_progress(self):
104
content = "some content\nwith newlines\n"
105
old_clear_term = ui.ui_factory.clear_term
106
clear_term_called = []
109
clear_term_called.append(True)
110
ui.ui_factory.clear_term = clear_term
112
self.assertProduces(content)
114
ui.ui_factory.clear_term = old_clear_term
115
self.assertEqual([True], clear_term_called)
117
def test_aborts_on_unicode(self):
118
"""You can't sign Unicode text; it must be encoded first."""
119
self.assertRaises(errors.BzrBadParameterUnicode,
120
self.assertProduces, u'foo')
49
123
class TestVerify(TestCase):
51
125
def import_keys(self):
53
context = gpg.Context()
127
context = gpgme.Context()
55
key = gpg.Data(b"""-----BEGIN PGP PUBLIC KEY BLOCK-----
129
key = BytesIO(b"""-----BEGIN PGP PUBLIC KEY BLOCK-----
56
130
Version: GnuPG v1.4.11 (GNU/Linux)
58
132
mQENBE343IgBCADwzPW7kmKb2bjB+UU+1ER/ABMZspvtoZMPusUw7bk6coXHF/0W
190
264
-----END PGP PUBLIC KEY BLOCK-----
192
context.op_import(key)
193
context.op_import(secret_key)
194
context.op_import(revoked_key)
195
context.op_import(expired_key)
267
context.import_(secret_key)
268
context.import_(revoked_key)
269
context.import_(expired_key)
197
271
def test_verify_untrusted_but_accepted(self):
198
# untrusted by gpg but listed as acceptable_keys by user
199
self.requireFeature(features.gpg)
272
#untrusted by gpg but listed as acceptable_keys by user
273
self.requireFeature(features.gpgme)
200
274
self.import_keys()
202
content = b"""-----BEGIN PGP SIGNED MESSAGE-----
276
content = """-----BEGIN PGP SIGNED MESSAGE-----
205
279
bazaar-ng testament short form 1
218
292
-----END PGP SIGNATURE-----
220
plain = b"""bazaar-ng testament short form 1
294
plain = """bazaar-ng testament short form 1
221
295
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
222
296
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
224
298
my_gpg = gpg.GPGStrategy(FakeConfig())
225
299
my_gpg.set_acceptable_keys("bazaar@example.com")
226
self.assertEqual((gpg.SIGNATURE_VALID, None, plain),
227
my_gpg.verify(content))
300
self.assertEqual((gpg.SIGNATURE_VALID, None), my_gpg.verify(content,
229
303
def test_verify_unacceptable_key(self):
230
self.requireFeature(features.gpg)
304
self.requireFeature(features.gpgme)
231
305
self.import_keys()
233
content = b"""-----BEGIN PGP SIGNED MESSAGE-----
307
content = """-----BEGIN PGP SIGNED MESSAGE-----
236
310
bazaar-ng testament short form 1
249
323
-----END PGP SIGNATURE-----
251
plain = b"""bazaar-ng testament short form 1
325
plain = """bazaar-ng testament short form 1
252
326
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
253
327
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
255
329
my_gpg = gpg.GPGStrategy(FakeConfig())
256
330
my_gpg.set_acceptable_keys("foo@example.com")
257
self.assertEqual((gpg.SIGNATURE_KEY_MISSING, u'E3080E45', plain),
258
my_gpg.verify(content))
331
self.assertEqual((gpg.SIGNATURE_KEY_MISSING, u'E3080E45'),
332
my_gpg.verify(content, plain))
260
334
def test_verify_valid_but_untrusted(self):
261
self.requireFeature(features.gpg)
264
content = b"""-----BEGIN PGP SIGNED MESSAGE-----
267
bazaar-ng testament short form 1
268
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
269
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
270
-----BEGIN PGP SIGNATURE-----
271
Version: GnuPG v1.4.11 (GNU/Linux)
273
iQEcBAEBAgAGBQJN+ekFAAoJEIdoGx7jCA5FGtEH/i+XxJRvqU6wdBtLVrGBMAGk
274
FZ5VP+KyXYtymSbgSstj/vM12NeMIeFs3xGnNnYuX1MIcY6We5TKtCH0epY6ym5+
275
6g2Q2QpQ5/sT2d0mWzR0K4uVngmxVQaXTdk5PdZ40O7ULeDLW6CxzxMHyUL1rsIx
276
7UBUTBh1O/1n3ZfD99hUkm3hVcnsN90uTKH59zV9NWwArU0cug60+5eDKJhSJDbG
277
rIwlqbFAjDZ7L/48e+IaYIJwBZFzMBpJKdCxzALLtauMf+KK8hGiL2hrRbWm7ty6
278
NgxfkMYOB4rDPdSstT35N+5uBG3n/UzjxHssi0svMfVETYYX40y57dm2eZQXFp8=
280
-----END PGP SIGNATURE-----
282
plain = b"""bazaar-ng testament short form 1
283
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
284
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
286
my_gpg = gpg.GPGStrategy(FakeConfig())
287
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None,
288
plain), my_gpg.verify(content))
335
self.requireFeature(features.gpgme)
338
content = """-----BEGIN PGP SIGNED MESSAGE-----
341
bazaar-ng testament short form 1
342
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
343
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
344
-----BEGIN PGP SIGNATURE-----
345
Version: GnuPG v1.4.11 (GNU/Linux)
347
iQEcBAEBAgAGBQJN+ekFAAoJEIdoGx7jCA5FGtEH/i+XxJRvqU6wdBtLVrGBMAGk
348
FZ5VP+KyXYtymSbgSstj/vM12NeMIeFs3xGnNnYuX1MIcY6We5TKtCH0epY6ym5+
349
6g2Q2QpQ5/sT2d0mWzR0K4uVngmxVQaXTdk5PdZ40O7ULeDLW6CxzxMHyUL1rsIx
350
7UBUTBh1O/1n3ZfD99hUkm3hVcnsN90uTKH59zV9NWwArU0cug60+5eDKJhSJDbG
351
rIwlqbFAjDZ7L/48e+IaYIJwBZFzMBpJKdCxzALLtauMf+KK8hGiL2hrRbWm7ty6
352
NgxfkMYOB4rDPdSstT35N+5uBG3n/UzjxHssi0svMfVETYYX40y57dm2eZQXFp8=
354
-----END PGP SIGNATURE-----
356
plain = """bazaar-ng testament short form 1
357
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
358
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
360
my_gpg = gpg.GPGStrategy(FakeConfig())
361
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None), my_gpg.verify(content,
364
def test_verify_bad_testament(self):
365
self.requireFeature(features.gpgme)
368
content = """-----BEGIN PGP SIGNED MESSAGE-----
371
bazaar-ng testament short form 1
372
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
373
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
374
-----BEGIN PGP SIGNATURE-----
375
Version: GnuPG v1.4.11 (GNU/Linux)
377
iQEcBAEBAgAGBQJN+ekFAAoJEIdoGx7jCA5FGtEH/i+XxJRvqU6wdBtLVrGBMAGk
378
FZ5VP+KyXYtymSbgSstj/vM12NeMIeFs3xGnNnYuX1MIcY6We5TKtCH0epY6ym5+
379
6g2Q2QpQ5/sT2d0mWzR0K4uVngmxVQaXTdk5PdZ40O7ULeDLW6CxzxMHyUL1rsIx
380
7UBUTBh1O/1n3ZfD99hUkm3hVcnsN90uTKH59zV9NWwArU0cug60+5eDKJhSJDbG
381
rIwlqbFAjDZ7L/48e+IaYIJwBZFzMBpJKdCxzALLtauMf+KK8hGiL2hrRbWm7ty6
382
NgxfkMYOB4rDPdSstT35N+5uBG3n/UzjxHssi0svMfVETYYX40y57dm2eZQXFp8=
384
-----END PGP SIGNATURE-----
386
plain = """bazaar-ng testament short form 1
387
revision-id: doctor@example.com-20110527185938-hluafawphszb8dl1
388
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
390
my_gpg = gpg.GPGStrategy(FakeConfig())
391
my_gpg.set_acceptable_keys("bazaar@example.com")
392
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None), my_gpg.verify(content,
290
396
def test_verify_revoked_signature(self):
291
self.requireFeature(features.gpg)
397
self.requireFeature(features.gpgme)
292
398
self.import_keys()
294
content = b"""-----BEGIN PGP SIGNED MESSAGE-----
400
content = """-----BEGIN PGP SIGNED MESSAGE-----
329
435
-----END PGP SIGNATURE-----
331
plain = b"""bazaar-ng testament short form 1
437
plain = """bazaar-ng testament short form 1
332
438
revision-id: amy@example.com-20110527185938-hluafawphszb8dl1
333
439
sha1: 6411f9bdf6571200357140c9ce7c0f50106ac9a4
335
441
my_gpg = gpg.GPGStrategy(FakeConfig())
336
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None, plain),
337
my_gpg.verify(content))
442
self.assertEqual((gpg.SIGNATURE_NOT_VALID, None),
443
my_gpg.verify(content, plain))
339
445
def test_verify_expired_but_valid(self):
340
self.requireFeature(features.gpg)
446
self.requireFeature(features.gpgme)
341
447
self.import_keys()
342
content = b"""-----BEGIN PGP SIGNED MESSAGE-----
448
content = """-----BEGIN PGP SIGNED MESSAGE-----
345
451
bazaar-ng testament short form 1
346
452
revision-id: test@example.com-20110801100657-f1dr1nompeex723z
347
453
sha1: 59ab434be4c2d5d646dee84f514aa09e1b72feeb
348
454
-----BEGIN PGP SIGNATURE-----
349
455
Version: GnuPG v1.4.10 (GNU/Linux)
351
457
iJwEAQECAAYFAk42esUACgkQHOJve0+NFRPc5wP7BoZkzBU8JaHMLv/LmqLr0sUz
352
458
zuE51ofZZ19L7KVtQWsOi4jFy0fi4A5TFwO8u9SOfoREGvkw292Uty9subSouK5/
353
459
mFmDOYPQ+O83zWgYZsBmMJWYDZ+X9I6XXZSbPtV/7XyTjaxtl5uRnDVJjg+AzKvD
356
462
-----END PGP SIGNATURE-----
464
plain = """bazaar-ng testament short form 1
465
revision-id: test@example.com-20110801100657-f1dr1nompeex723z
466
sha1: 59ab434be4c2d5d646dee84f514aa09e1b72feeb
358
468
my_gpg = gpg.GPGStrategy(FakeConfig())
359
self.assertEqual((gpg.SIGNATURE_EXPIRED, u'4F8D1513', None),
360
my_gpg.verify(content))
469
self.assertEqual((gpg.SIGNATURE_EXPIRED, u'4F8D1513'),
470
my_gpg.verify(content, plain))
362
472
def test_verify_unknown_key(self):
363
self.requireFeature(features.gpg)
473
self.requireFeature(features.gpgme)
364
474
self.import_keys()
365
content = b"""-----BEGIN PGP SIGNED MESSAGE-----
475
content = """-----BEGIN PGP SIGNED MESSAGE-----
391
502
[u'B5DEED5FCB15DAE6ECEF919587681B1EE3080E45'])
393
504
def test_set_acceptable_keys_from_config(self):
394
self.requireFeature(features.gpg)
505
self.requireFeature(features.gpgme)
395
506
self.import_keys()
396
507
my_gpg = gpg.GPGStrategy(FakeConfig(
397
b'acceptable_keys=bazaar@example.com'))
508
'acceptable_keys=bazaar@example.com'))
398
509
my_gpg.set_acceptable_keys(None)
399
510
self.assertEqual(my_gpg.acceptable_keys,
400
511
[u'B5DEED5FCB15DAE6ECEF919587681B1EE3080E45'])
402
513
def test_set_acceptable_keys_unknown(self):
403
self.requireFeature(features.gpg)
514
self.requireFeature(features.gpgme)
404
515
my_gpg = gpg.GPGStrategy(FakeConfig())
408
518
self.notes.append(args[0] % args[1:])
409
519
self.overrideAttr(trace, 'note', note)
410
520
my_gpg.set_acceptable_keys("unknown")
411
521
self.assertEqual(my_gpg.acceptable_keys, [])
412
522
self.assertEqual(self.notes,
413
['No GnuPG key results for pattern: unknown'])
523
['No GnuPG key results for pattern: unknown'])
416
526
class TestDisabled(TestCase):
418
528
def test_sign(self):
419
self.assertRaises(gpg.SigningFailed,
420
gpg.DisabledGPGStrategy(None).sign, b'content', gpg.MODE_CLEAR)
529
self.assertRaises(errors.SigningFailed,
530
gpg.DisabledGPGStrategy(None).sign, 'content')
422
532
def test_verify(self):
423
self.assertRaises(gpg.SignatureVerificationFailed,
424
gpg.DisabledGPGStrategy(None).verify, b'content')
533
self.assertRaises(errors.SignatureVerificationFailed,
534
gpg.DisabledGPGStrategy(None).verify, 'content',