1#!/usr/bin/env python3
2# -*- coding: utf-8 -*-
3
4from __future__ import absolute_import, division, unicode_literals
5
6import gpg
7import os.path
8import subprocess
9import sys
10
11from groups import group_lists
12
13# Copyright (C) 2018 Ben McGinnes <ben@gnupg.org>
14#
15# This program is free software; you can redistribute it and/or modify it under
16# the terms of the GNU General Public License as published by the Free Software
17# Foundation; either version 2 of the License, or (at your option) any later
18# version.
19#
20# This program is free software; you can redistribute it and/or modify it under
21# the terms of the GNU Lesser General Public License as published by the Free
22# Software Foundation; either version 2.1 of the License, or (at your option)
23# any later version.
24#
25# This program is distributed in the hope that it will be useful, but WITHOUT
26# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
27# FOR A PARTICULAR PURPOSE.  See the GNU General Public License and the GNU
28# Lesser General Public License for more details.
29#
30# You should have received a copy of the GNU General Public License and the GNU
31# Lesser General Public along with this program; if not, see
32# <https://www.gnu.org/licenses/>.
33
34print("""
35This script applies a local signature or certification to every key in a group.
36
37Usage: local-sign-group.py <group name> [signing keyid] [gnupg homedir]
38""")
39
40c = gpg.Context(armor=True)
41mkfpr = None
42defkey_fpr = None
43enckey_fpr = None
44to_certify = []
45
46if len(sys.argv) >= 4:
47    clique = sys.argv[1]
48    sigkey = sys.argv[2]
49    homedir = sys.argv[3]
50elif len(sys.argv) == 3:
51    clique = sys.argv[1]
52    sigkey = sys.argv[2]
53    homedir = input("Enter the GPG configuration directory path (optional): ")
54elif len(sys.argv) == 2:
55    clique = sys.argv[1]
56    sigkey = input("Enter the key ID to sign with (conditionally optional): ")
57    homedir = input("Enter the GPG configuration directory path (optional): ")
58else:
59    clique = input("Enter the group matching the key(s) to locally sign: ")
60    sigkey = input("Enter the key ID to sign with (conditionally optional): ")
61    homedir = input("Enter the GPG configuration directory path (optional): ")
62
63if len(homedir) == 0:
64    homedir = None
65elif homedir.startswith("~"):
66    userdir = os.path.expanduser(homedir)
67    if os.path.exists(userdir) is True:
68        homedir = os.path.realpath(userdir)
69    else:
70        homedir = None
71else:
72    homedir = os.path.realpath(homedir)
73
74if homedir is not None and os.path.exists(homedir) is False:
75    homedir = None
76elif homedir is not None and os.path.exists(homedir) is True:
77    if os.path.isdir(homedir) is False:
78        homedir = None
79    else:
80        pass
81
82if homedir is not None:
83    c.home_dir = homedir
84else:
85    pass
86
87if len(sigkey) == 0:
88    sigkey = None
89else:
90    pass
91
92if sys.platform == "win32":
93    gpgconfcmd = "gpgconf.exe --list-options gpg"
94else:
95    gpgconfcmd = "gpgconf --list-options gpg"
96
97try:
98    lines = subprocess.getoutput(gpgconfcmd).splitlines()
99except:
100    process = subprocess.Popen(gpgconfcmd.split(), stdout=subprocess.PIPE)
101    procom = process.communicate()
102    if sys.version_info[0] == 2:
103        lines = procom[0].splitlines()
104    else:
105        lines = procom[0].decode().splitlines()
106
107for i in range(len(lines)):
108    if lines[i].startswith("default-key") is True:
109        dline = lines[i]
110    elif lines[i].startswith("encrypt-to") is True:
111        eline = lines[i]
112    else:
113        pass
114
115defkey_fpr = dline.split(":")[-1].replace('"', '').split(',')[0].upper()
116enckey_fpr = eline.split(":")[-1].replace('"', '').split(',')[0].upper()
117
118try:
119    dkey = c.keylist(pattern=defkey_fpr, secret=True)
120    dk = list(dkey)
121except Exception as de:
122    print(de)
123    dk = None
124    print("No valid default key.")
125
126try:
127    ekey = c.keylist(pattern=defkey_fpr, secret=True)
128    ek = list(ekey)
129except Exception as ee:
130    print(ee)
131    ek = None
132    print("No valid always encrypt to key.")
133
134if sigkey is not None:
135    mykey = c.keylist(pattern=sigkey, secret=True)
136    mk = list(mykey)
137    mkfpr = mk[0].fpr.upper()
138    c.signers = mk
139else:
140    if dk is None and ek is not None:
141        c.signers = ek
142    else:
143        pass
144
145for group in group_lists:
146    if group[0] == clique:
147        for logrus in group[1]:
148            khole = c.keylist(pattern=logrus)
149            k = list(khole)
150            to_certify.append(k[0].fpr.upper())
151    else:
152        pass
153
154if mkfpr is not None:
155    if to_certify.count(mkfpr) > 0:
156        for n in range(to_certify.count(mkfpr)):
157            to_certify.remove(mkfpr)
158    else:
159        pass
160else:
161    pass
162
163if defkey_fpr is not None:
164    if to_certify.count(defkey_fpr) > 0:
165        for n in range(to_certify.count(defkey_fpr)):
166            to_certify.remove(defkey_fpr)
167    else:
168        pass
169else:
170    pass
171
172if enckey_fpr is not None:
173    if to_certify.count(enckey_fpr) > 0:
174        for n in range(to_certify.count(enckey_fpr)):
175            to_certify.remove(enckey_fpr)
176    else:
177        pass
178else:
179    pass
180
181for fpr in to_certify:
182    key = c.get_key(fpr)
183    c.key_sign(key, uids=None, expires_in=False, local=True)
184