aboutsummaryrefslogtreecommitdiff
blob: bd4a6ef5709f3413e4fcc4b6dcaabd3cee622c53 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
#
#-*- coding:utf-8 -*-

"""
    Gentoo-Keys - gkeygen/actions.py

    Primary API interface module
    @copyright: 2014 by Pavlos Ratis <dastergon@gentoo.org>
    @license: GNU GPL2, see COPYING for details
"""

import gpgme
import os
import re
import shutil
import sys

from collections import OrderedDict

if sys.version_info[0] >= 3:
    from urllib.request import urlopen
    py_input = input
    _unicode = str
else:
    from urllib2 import urlopen
    py_input = raw_input
    _unicode = unicode

from gkeys.fileops import ensure_dirs
from gkeys import log


Action_Map = OrderedDict([
    ('gen-key', {
        'func': 'genkey',
        'options': ['spec', 'dest'],
        'desc': '''Generate a gpg key using a spec file''',
        'long_desc': '''Generate a gpg key using a spec file''',
        'example': '''$ gkeys-gen gen-key

    GPG key creator
        Spec file..: glep-63-recommended
        Homepage...: https://wiki.gentoo.org/wiki/GLEP:63

Give your Full Name: Foo Barr
Give your Email: foo@barr.net

Review:
 Full Name: Foo Barr
 Email: foo@barr.net

Continue?[y/n]: y

* Creating gpg folder at /home/brian/gkeys-user/gpghome

    * Creating gpg.conf file at /home/brian/gkeys-user/gpghome


    ____________________
    < Generating GPG key >
     --------------------
            \   ^__^
             \  (oo)\_______
                (__)\       )\/
                    ||----w |
                    ||     ||

    * Give the password for the key. (Pick a strong one)
        Please surf the internet, type on your keyboard, etc.
        This helps the random number generator work effectively

    Your new GLEP 63 based OpenPGP key has been created in /home/brian/gkeys-user/gpghome


        GPG key info:
            Full Name: Foo Barr,
            Email: foo@barr.net,
            Fingerprint: CF8F369903999538F79287497AD8F5FEF19A7A69


    In order to use your new key, place the new gpghome to your ~/.gnupg folder by running the following command:
        mv /home/brian/gkeys-user/gpghome ~/.gnupg
    Important: If you have another old key in ~/.gnupg please make sure you backup it up first.

    Please read the FAQ for post-generation steps that are available in:
    https://wiki.gentoo.org/wiki/Project:Gentoo-keys/Generating_GLEP_63_based_OpenPGP_keys
''',
        }),
    ('list-specs', {
        'func': 'list_specs',
        'options': [],
        'desc': '''List spec file definitions (spec names) found in the config''',
        'long_desc': '''List spec file definitions (spec names) found in the config.
    The default-spec setting when the pkg was installed is set to glep-63-recommended.''',
        'example': '''$ gkeys-gen list-specs

 Gkey task results:
    Specs defined: glep-63,  default-spec,  glep-63-recommended
''',
        }),
])

Available_Actions = ['gen-key', 'list-specs']

LARRY = """
    ____________________
    < Generating GPG key >
     --------------------
            \   ^__^
             \  (oo)\_______
                (__)\       )\/
                    ||----w |
                    ||     ||"""

GPG_INFO_STRING = """
        GPG key info:
            Full Name: %s,
            Email: %s,
            Fingerprint: %s
                        """


class Actions(object):

    def __init__(self, config, output=None, logger=None):
        self.config = config
        self.output = output
        self.logger = logger

    def configure_config_file(self,args, gpghome):
        '''Creates the config file'''
        newgpgconfpath = os.path.join(gpghome, 'gpg.conf')
        defaultpath = '/usr/share/gnupg/gpg-conf.skel'
        file_exists = False
        while not file_exists:
            skelconfpath = py_input("Path of default gpg configuration file to use (default: %s) " %defaultpath)
            if len(skelconfpath) <= 0:
                skelconfpath = defaultpath
            file_exists = os.path.exists(skelconfpath)
        shutil.copy(skelconfpath, newgpgconfpath)
        with open(newgpgconfpath, 'a') as conf:
            for line in urlopen(self.config.get_key('gpg-urls', args.spec)):
                conf.write(_unicode(line.decode('utf-8'))) 


    def genkey(self, args):
        '''Generate a gpg key using a spec file'''
        messages = []
        if not args.destination:
            gpghome = self.config.get_key('gkeys-gen', 'gpg-home')
        else:
            if os.path.exists(args.destination):
                gpghome = os.path.join(args.destination, 'gpghome')
            else:
                messages.extend(['', "Aborting... %s path does not exist." % args.destination])
                return (False, messages)
        self.logger.debug("MAIN: _action_genkey; setting gpghome destination: %s" % gpghome)
        self.logger.debug("MAIN: _action_genkey; args= %s" % str(args))
        if not args.spec:
            args.spec = self.config.get_key('spec', 'default-spec')
        key_params = self.get_input(args)
        ack = None
        while ack not in ["y", "yes", "n", "no"]:
            ack = py_input("Continue?[y/n]: ").lower()
        if ack in ["n", "no"]:
            messages.extend(['', "\nKey generation aborted."])
            return (False, messages)
        elif ack in ["y", "yes"]:
            # Set the environment to custom gpg directory
            os.environ['GNUPGHOME'] = gpghome
            gpghome_full_path = os.path.abspath(gpghome)
            self.logger.info("MAIN: _action_genkey; create custom gpg directory: %s" % gpghome_full_path)
            self.output(["\n* Creating gpg folder at %s" % gpghome_full_path])
            ensure_dirs(gpghome)
            # Copy default gpg-conf.skel and append glep63 requirements
            self.configure_config_file(args, gpghome)
            # Key generation
            ctx = gpgme.Context()
            self.logger.info("MAIN: _action_genkey: Generating GPG key...")
            self.output([LARRY])
            self.output(["* Give the password for the key. (Pick a strong one)",
                "    Please surf the internet, type on your keyboard, etc. ",
                "    This helps the random number generator work effectively"])
            try:
                result = ctx.genkey(key_params)
            except gpgme.GpgmeError as e:
                self.logger.debug("MAIN: _action_genkey: GpgmeError: %s" % str(e))
                self.logger.debug("MAIN: _action_genkey: Aborting... Gpgme errored out.")
                messages.extend(['', "Aborting... Gpgme reported an error.\n",
                    "    GpgmeError: %s\n" % str(e),
                    "    See the log file for details: %s" % log.logname])
                return (False, messages)
            key = ctx.get_key(result.fpr, True)
            self.logger.debug("MAIN: _action_genkey: Generated key: %s - %s"
                              % (key.uids[0].uid, key.subkeys[0].fpr))
            self.output(["Your new GLEP 63 based OpenPGP key has been created in %s" % gpghome_full_path])
            self.output([GPG_INFO_STRING % (key.uids[0].name, key.uids[0].email,
                               key.subkeys[0].fpr)])
            self.output(["In order to use your new key, place the new gpghome to your ~/.gnupg folder by running the following command:",
                        "    mv %s ~/.gnupg" % gpghome_full_path,
                        "Important: If you have another old key in ~/.gnupg please make sure you backup it up first.\n",
                        "Please read the FAQ for post-generation steps that are available in:",
                        "https://wiki.gentoo.org/wiki/Project:Gentoo-keys/Generating_GLEP_63_based_OpenPGP_keys"])
            return (True, messages)


    def get_input(self, args):
        '''Interactive user input'''
        self.output(['', "GPG key creator",
            "    Spec file..: %s" % args.spec,
            "    Homepage...: %s"
            % self.config.get_key('spec-homepage', args.spec),
            ])
        name = py_input("Give your Full Name: ")
        email = py_input("Give your Email: ")
        while not re.match(r'[\w.-]+@[\w.-]+', email):
            self.output(["\nBad email input. Try again."])
            email = py_input("Give your Email: ")
        print("\nReview:\n Full Name: %s\n Email: %s\n" % (name, email))
        url = self.config.get_key('spec-urls', args.spec)
        key_properties = urlopen(url).read()
        return _unicode(key_properties.decode('utf-8')).format(name, email)


    def list_specs(self, args):
        '''List seed file definitions found in the config'''
        specs = list(self.config.get_key('spec'))
        return (True, {"Specs defined: %s\n"
            % (",  ".join(specs)): True})