1#!/usr/bin/env python
2
3# Copyright (C) 2016 g10 Code GmbH
4#
5# This file is part of GPGME.
6#
7# GPGME is free software; you can redistribute it and/or modify it
8# under the terms of the GNU General Public License as published by
9# the Free Software Foundation; either version 2 of the License, or
10# (at your option) any later version.
11#
12# GPGME is distributed in the hope that it will be useful, but WITHOUT
13# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
14# or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General
15# Public License for more details.
16#
17# You should have received a copy of the GNU Lesser General Public
18# License along with this program; if not, see <https://www.gnu.org/licenses/>.
19
20from __future__ import absolute_import, print_function, unicode_literals
21
22import gpg
23import support
24
25del absolute_import, print_function, unicode_literals
26
27support.assert_gpg_version((2, 1, 14))
28
29
30# Check expration of keys.  This test assumes three subkeys of which
31# 2 are expired; it is used with the "Whisky" test key.  It has
32# already been checked that these 3 subkeys are available.
33def check_whisky(name, key):
34    sub1 = key.subkeys[2]
35    sub2 = key.subkeys[3]
36
37    assert sub1.expired and sub2.expired, \
38        "Subkey of `{}' not flagged as expired".format(name)
39    assert sub1.expires == 1129636886 and sub2.expires == 1129636939, \
40        "Subkey of `{}' has wrong expiration date".format(name)
41
42
43keys = [
44    [
45        "A0FF4590BB6122EDEF6E3C542D727CC768697734", "6AE6D7EE46A871F8",
46        [["Alfa Test", "demo key", "alfa@example.net"],
47         ["Alpha Test", "demo key", "alpha@example.net"],
48         ["Alice", "demo key", ""]], 1
49    ],
50    [
51        "D695676BDCEDCC2CDD6152BCFE180B1DA9E3B0B2", "5381EA4EE29BA37F",
52        [["Bob", "demo key", ""],
53         ["Bravo Test", "demo key", "bravo@example.net"]], 1
54    ],
55    [
56        "61EE841A2A27EB983B3B3C26413F4AF31AFDAB6C", "E71E72ACBC43DA60",
57        [["Charlie Test", "demo key", "charlie@example.net"]], 1
58    ],
59    [
60        "6560C59C43D031C54D7C588EEBA9F240EB9DC9E6", "06F22880B0C45424",
61        [["Delta Test", "demo key", "delta@example.net"]], 1
62    ],
63    [
64        "3531152DE293E26A07F504BC318C1FAEFAEF6D1B", "B5C79E1A7272144D",
65        [["Echelon", "demo key",
66          ""], ["Echo Test", "demo key", "echo@example.net"],
67         ["Eve", "demo key", ""]], 1
68    ],
69    [
70        "56D33268F7FE693FBB594762D4BF57F37372E243", "0A32EE79EE45198E",
71        [["Foxtrot Test", "demo key", "foxtrot@example.net"]], 1
72    ],
73    [
74        "C9C07DCC6621B9FB8D071B1D168410A48FC282E6", "247491CC9DCAD354",
75        [["Golf Test", "demo key", "golf@example.net"]], 1
76    ],
77    [
78        "9E91CBB11E4D4135583EF90513DB965534C6E3F1", "76E26537D622AD0A",
79        [["Hotel Test", "demo key", "hotel@example.net"]], 1
80    ],
81    [
82        "CD538D6CC9FB3D745ECDA5201FE8FC6F04259677", "C1C8EFDE61F76C73",
83        [["India Test", "demo key", "india@example.net"]], 1
84    ],
85    [
86        "F8F1EDC73995AB739AD54B380C820C71D2699313", "BD0B108735F8F136",
87        [["Juliet Test", "demo key", "juliet@example.net"]], 1
88    ],
89    [
90        "3FD11083779196C2ECDD9594AD1B0FAD43C2D0C7", "86CBB34A9AF64D02",
91        [["Kilo Test", "demo key", "kilo@example.net"]], 1
92    ],
93    [
94        "1DDD28CEF714F5B03B8C246937CAB51FB79103F8", "0363B449FE56350C",
95        [["Lima Test", "demo key", "lima@example.net"]], 1
96    ],
97    [
98        "2686AA191A278013992C72EBBE794852BE5CF886", "5F600A834F31EAE8",
99        [["Mallory", "demo key", ""],
100         ["Mike Test", "demo key", "mike@example.net"]], 1
101    ],
102    [
103        "5AB9D6D7BAA1C95B3BAA3D9425B00FD430CEC684", "4C1D63308B70E472",
104        [["November Test", "demo key", "november@example.net"]], 1
105    ],
106    [
107        "43929E89F8F79381678CAE515F6356BA6D9732AC", "FF0785712681619F",
108        [["Oscar Test", "demo key", "oscar@example.net"]], 1
109    ],
110    [
111        "6FAA9C201E5E26DCBAEC39FD5D15E01D3FF13206", "2764E18263330D9C",
112        [["Papa test", "demo key", "papa@example.net"]], 1
113    ],
114    [
115        "A7969DA1C3297AA96D49843F1C67EC133C661C84", "6CDCFC44A029ACF4",
116        [["Quebec Test", "demo key", "quebec@example.net"]], 1
117    ],
118    [
119        "38FBE1E4BF6A5E1242C8F6A13BDBEDB1777FBED3", "9FAB805A11D102EA",
120        [["Romeo Test", "demo key", "romeo@example.net"]], 1
121    ],
122    [
123        "045B2334ADD69FC221076841A5E67F7FA3AE3EA1", "93B88B0F0F1B50B4",
124        [["Sierra Test", "demo key", "sierra@example.net"]], 1
125    ],
126    [
127        "ECAC774F4EEEB0620767044A58CB9A4C85A81F38", "97B60E01101C0402",
128        [["Tango Test", "demo key", "tango@example.net"]], 1
129    ],
130    [
131        "0DBCAD3F08843B9557C6C4D4A94C0F75653244D6", "93079B915522BDB9",
132        [["Uniform Test", "demo key", "uniform@example.net"]], 1
133    ],
134    [
135        "E8143C489C8D41124DC40D0B47AF4B6961F04784", "04071FB807287134",
136        [["Victor Test", "demo key", "victor@example.org"]], 1
137    ],
138    [
139        "E8D6C90B683B0982BD557A99DEF0F7B8EC67DBDE", "D7FBB421FD6E27F6",
140        [["Whisky Test", "demo key", "whisky@example.net"]], 3, check_whisky
141    ],
142    [
143        "04C1DF62EFA0EBB00519B06A8979A6C5567FB34A", "5CC6F87F41E408BE",
144        [["XRay Test", "demo key", "xray@example.net"]], 1
145    ],
146    [
147        "ED9B316F78644A58D042655A9EEF34CD4B11B25F", "5ADFD255F7B080AD",
148        [["Yankee Test", "demo key", "yankee@example.net"]], 1
149    ],
150    [
151        "23FD347A419429BACCD5E72D6BC4778054ACD246", "EF9DC276A172C881",
152        [["Zulu Test", "demo key", "zulu@example.net"]], 1
153    ],
154]
155
156
157def check_global(key, uids, n_subkeys):
158    assert not key.revoked, "Key unexpectedly revoked"
159    assert not key.expired, "Key unexpectedly expired"
160    assert not key.disabled, "Key unexpectedly disabled"
161    assert not key.invalid, "Key unexpectedly invalid"
162    assert key.can_sign, "Key unexpectedly unusable for signing"
163    assert key.can_certify, "Key unexpectedly unusable for certifications"
164    assert not key.secret, "Key unexpectedly secret"
165    assert not key.protocol != gpg.constants.protocol.OpenPGP, \
166        "Key has unexpected protocol: {}".format(key.protocol)
167    assert not key.issuer_serial, \
168        "Key unexpectedly carries issuer serial: {}".format(key.issuer_serial)
169    assert not key.issuer_name, \
170        "Key unexpectedly carries issuer name: {}".format(key.issuer_name)
171    assert not key.chain_id, \
172        "Key unexpectedly carries chain ID: {}".format(key.chain_id)
173    assert key.owner_trust == gpg.constants.validity.UNKNOWN, \
174        "Key has unexpected owner trust: {}".format(key.owner_trust)
175    assert len(key.subkeys) - 1 == n_subkeys, \
176        "Key `{}' has unexpected number of subkeys".format(uids[0][0])
177
178
179def check_subkey(fpr, which, subkey):
180    assert not subkey.revoked, which + " key unexpectedly revoked"
181    assert not subkey.expired, which + " key unexpectedly expired"
182    assert not subkey.disabled, which + " key unexpectedly disabled"
183    assert not subkey.invalid, which + " key unexpectedly invalid"
184
185    if which == "Primary":
186        assert not subkey.can_encrypt, \
187            which + " key unexpectedly usable for encryption"
188        assert subkey.can_sign, \
189            which + " key unexpectedly unusable for signing"
190        assert subkey.can_certify, \
191            which + " key unexpectedly unusable for certifications"
192    else:
193        assert subkey.can_encrypt, \
194            which + " key unexpectedly unusable for encryption"
195        assert not subkey.can_sign, \
196            which + " key unexpectedly usable for signing"
197        assert not subkey.can_certify, \
198            which + " key unexpectedly usable for certifications"
199
200    assert not subkey.secret, which + " key unexpectedly secret"
201    assert not subkey.is_cardkey, "Public key marked as card key"
202    assert not subkey.card_number, "Public key with card number set"
203    assert not subkey.pubkey_algo != \
204        (gpg.constants.pk.DSA if which == "Primary"
205         else gpg.constants.pk.ELG_E), \
206         which + " key has unexpected public key algo: {}".format(subkey.
207                                                                  pubkey_algo)
208    assert subkey.length == 1024, \
209        which + " key has unexpected length: {}".format(subkey.length)
210    assert fpr.endswith(subkey.keyid), \
211        which + " key has unexpected key ID: {}".format(subkey.keyid)
212    assert which == "Secondary" or subkey.fpr == fpr, \
213        which + " key has unexpected fingerprint: {}".format(subkey.fpr)
214    assert not subkey.expires, \
215        which + " key unexpectedly expires: {}".format(subkey.expires)
216
217
218def check_uid(which, ref, uid):
219    assert not uid.revoked, which + " user ID unexpectedly revoked"
220    assert not uid.invalid, which + " user ID unexpectedly invalid"
221    assert uid.validity == gpg.constants.validity.UNKNOWN, \
222        which + " user ID has unexpected validity: {}".format(uid.validity)
223    assert not uid.signatures, which + " user ID unexpectedly signed"
224    assert uid.name == ref[0], \
225        "Unexpected name in {} user ID: {!r}".format(which.lower(), uid.name)
226    assert uid.comment == ref[1], \
227        "Unexpected comment in {} user ID: {!r}".format(which.lower(),
228                                                        uid.comment)
229    assert uid.email == ref[2], \
230        "Unexpected email in {} user ID: {!r}".format(which.lower(), uid.email)
231
232
233# Export all the data from our keyring...
234key_data = gpg.Data()
235with gpg.Context() as c:
236    c.op_export_keys([c.get_key(k[0]) for k in keys], 0, key_data)
237
238# ... rewind the tape...
239key_data.rewind()
240
241# ... and feed it into a keylist in an empty context.
242with support.EphemeralContext() as c:
243    for i, key in enumerate(c.keylist(source=key_data)):
244        try:
245            if len(keys[i]) == 4:
246                fpr, sec_keyid, uids, n_subkeys = keys[i]
247                misc_check = None
248            else:
249                fpr, sec_keyid, uids, n_subkeys, misc_check = keys[i]
250        except IndexError:
251            # There are more keys.  We don't check for that.
252            break
253
254        # Global key flags.
255        check_global(key, uids, n_subkeys)
256        check_subkey(fpr, "Primary", key.subkeys[0])
257        check_subkey(sec_keyid, "Secondary", key.subkeys[1])
258
259        assert len(key.uids) == len(uids)
260        check_uid("First", uids[0], key.uids[0])
261        if len(key.uids) > 1:
262            check_uid("Second", uids[1], key.uids[1])
263        if len(key.uids) > 2:
264            check_uid("Third", uids[2], key.uids[2])
265
266        if misc_check:
267            misc_check(uids[0][0], key)
268
269    assert len(list(c.keylist())) == 0, "Keys were imported"
270