pgpius-commit Mailing List for PGP Individual UID Signer (Page 2)
Brought to you by:
jaymzh
You can subscribe to this list here.
| 2009 |
Jan
|
Feb
(12) |
Mar
(4) |
Apr
(3) |
May
|
Jun
|
Jul
|
Aug
|
Sep
(4) |
Oct
|
Nov
|
Dec
|
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 2010 |
Jan
|
Feb
(5) |
Mar
(8) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
(3) |
Oct
|
Nov
|
Dec
|
| 2011 |
Jan
|
Feb
|
Mar
(10) |
Apr
(1) |
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2012 |
Jan
(3) |
Feb
|
Mar
|
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
| 2013 |
Jan
|
Feb
|
Mar
(2) |
Apr
|
May
|
Jun
|
Jul
|
Aug
|
Sep
|
Oct
|
Nov
|
Dec
|
|
From: Phil D. <ja...@us...> - 2010-03-01 20:28:28
|
Update of /cvsroot/pgpius/pius In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv5304 Modified Files: Changelog pius Log Message: - Stop QP-encoding the key, as it prevents people from manually doing gpg -d <encrypted_file> | gpg --import since the decrypted payload is a MIME message with QP-encoding. They need to use an intelligent MTA, or mime_dump, and this is confusing some users. See the note in the code, but since this is armored in encrypted output, it should be safe. - QP-encode the body... especially since we claim it's QP - Remove the signed, but unencrypted files (potential security hole fixed here) - Add a note to the emails that PIUS generated them, for clarity. Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.24 retrieving revision 1.25 diff -u -d -r1.24 -r1.25 --- pius 1 Mar 2010 15:06:22 -0000 1.24 +++ pius 1 Mar 2010 20:28:20 -0000 1.25 @@ -75,6 +75,8 @@ If you have any questions, let me know. + +Generated by PIUS (http://www.phildev.net/pius/). ''' DEFAULT_NON_MIME_EMAIL_TEXT = '''Hello, @@ -98,6 +100,8 @@ If you have any questions, let me know. + +Generated by PIUS (http://www.phildev.net/pius/). ''' def debug(line): @@ -816,6 +820,8 @@ # add a newline to all the sys.stdout.write()s print '' + os.unlink(self._outfile_path(uids[index]['file'])) + if self.verbose: self.print_filenames(uids) @@ -919,17 +925,30 @@ textpart = MIMEBase.MIMEBase('text', 'plain', charset="ISO-8859-1") textpart.add_header('Content-Transfer-Encoding', 'quoted-printable') textpart.__delitem__('MIME-Version') - textpart.set_payload(self._get_email_body(keyid, email)) + textpart.set_payload(quopriMIME.encode(self._get_email_body(keyid, email))) encrypted_body.attach(textpart) # The second part of the signed body filepath = self._outfile_path(filename) - attached_sig = MIMEBase.MIMEBase('text', 'plain', name='%s' % filename) - attached_sig.add_header('Content-Transfer-Encoding', 'quoted-printable') + attached_sig = MIMEBase.MIMEBase('application', 'pgp-keys', name='%s' % filename) attached_sig.add_header('Content-Disposition', 'inline', filename='%s' % filename) attached_sig.__delitem__('MIME-Version') - attached_sig.set_payload(quopriMIME.encode(open(filepath, 'r').read())) + # + # We USED to make this quoted-printable, but people with non-PGP-aware MUAs + # were decrypting the body manually, and then trying to import the resulting + # MIME message which was QP-encoded... so if there was an equals-sign in the + # message, it would actually be an '=3D' and thus fail the import. + # + # RFC2015 strongly suggests using QP for any signed data to prevent MTAs + # from messing with it... however, since this gets encrypted, this data is + # never available for an MTA to mess with, so this ... should be safe, and + # allows both methods of decrypting and importing the key. + # + # Side-note, if we ever turn to QP, be sure to use quopriMIME.encode to + # encode the payload. + # + attached_sig.set_payload(open(filepath, 'r').read()) encrypted_body.attach(attached_sig) encrypted_body.__delitem__('MIME-Version') Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- Changelog 27 Feb 2010 16:03:05 -0000 1.12 +++ Changelog 1 Mar 2010 20:28:20 -0000 1.13 @@ -2,6 +2,15 @@ Released: ph...@ip... - When signing all keys on a keyring, sort them first. +- Stop QP-encoding the key, as it prevents people from manually doing + gpg -d <encrypted_file> | gpg --import + since the decrypted payload is a MIME message with QP-encoding. They need to + use an intelligent MTA, or mime_dump, and this is confusing some users. See + the note in the code, but since this is armored in encrypted output, it + should be safe. +- QP-encode the body... especially since we claim it's QP +- Remove the signed, but unencrypted files (potential security hole fixed here) +- Add a note to the emails that PIUS generated them, for clarity. 2.0.5 Released: 02/27/10 |
|
From: Phil D. <ja...@us...> - 2010-03-01 15:06:42
|
Update of /cvsroot/pgpius/pius In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv30562 Modified Files: pius Log Message: sort sanely. Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.23 retrieving revision 1.24 diff -u -d -r1.23 -r1.24 --- pius 27 Feb 2010 16:03:05 -0000 1.23 +++ pius 1 Mar 2010 15:06:22 -0000 1.24 @@ -239,12 +239,7 @@ gpg.close() # sort the list - keylist = key_map.keys() - keylist.sort() - keyids = [] - for name in keylist: - keyids.append(key_map[name]) - + keyids = [ i[1] for i in sorted(key_map.items())] return keyids def check_fingerprint(self, key): |
|
From: Phil D. <ja...@us...> - 2010-02-27 16:03:13
|
Update of /cvsroot/pgpius/pius In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv5757 Modified Files: Changelog pius Log Message: - When signing all keys on a keyring, sort them first. Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.22 retrieving revision 1.23 diff -u -d -r1.22 -r1.23 --- pius 27 Feb 2010 11:17:09 -0000 1.22 +++ pius 27 Feb 2010 16:03:05 -0000 1.23 @@ -34,7 +34,7 @@ import subprocess import sys -VERSION = '2.0.5' +VERSION = '2.0.5+CVS' DEBUG_ON = False MODE_INTERACTIVE = 0 @@ -225,17 +225,26 @@ debug(cmd) gpg = os.popen(cmd, 'r') pub_re = re.compile('^pub:') - keyids = [] + key_map = {} for line in gpg.readlines(): if not pub_re.search(line): continue - uid = line.split(':')[4] + lineparts = line.split(':') + name = lineparts[9] + uid = lineparts[4] # get the shirt version uid = uid[8:16] debug('Got id %s' % uid) - keyids.append(uid) + key_map[name] = uid gpg.close() + # sort the list + keylist = key_map.keys() + keylist.sort() + keyids = [] + for name in keylist: + keyids.append(key_map[name]) + return keyids def check_fingerprint(self, key): Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- Changelog 27 Feb 2010 11:17:09 -0000 1.11 +++ Changelog 27 Feb 2010 16:03:05 -0000 1.12 @@ -1,3 +1,8 @@ +2.0.5+CVS +Released: +ph...@ip... +- When signing all keys on a keyring, sort them first. + 2.0.5 Released: 02/27/10 ph...@ip... |
|
From: Phil D. <ja...@us...> - 2010-02-27 11:17:17
|
Update of /cvsroot/pgpius/pius In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv3546 Modified Files: Changelog pius pius.spec Log Message: version bump. Index: pius.spec =================================================================== RCS file: /cvsroot/pgpius/pius/pius.spec,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- pius.spec 12 Feb 2010 23:04:08 -0000 1.6 +++ pius.spec 27 Feb 2010 11:17:09 -0000 1.7 @@ -2,7 +2,7 @@ # $Id$ %define name pius -%define version 2.0.4 +%define version 2.0.5 %define release 1 Name: %{name} Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.21 retrieving revision 1.22 diff -u -d -r1.21 -r1.22 --- pius 27 Feb 2010 11:07:09 -0000 1.21 +++ pius 27 Feb 2010 11:17:09 -0000 1.22 @@ -34,7 +34,7 @@ import subprocess import sys -VERSION = '2.0.4' +VERSION = '2.0.5' DEBUG_ON = False MODE_INTERACTIVE = 0 Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- Changelog 12 Feb 2010 23:04:08 -0000 1.10 +++ Changelog 27 Feb 2010 11:17:09 -0000 1.11 @@ -1,3 +1,13 @@ +2.0.5 +Released: 02/27/10 +ph...@ip... +- Encode keys for quoted-printable before sending them that way. + (closes #2960095) +- Prompt for a sign-level rather than 'y' or 'n', allowing for different levels + per key. (closes #2960103) +- Remove help text that claimed a local mail server is required for mailing off + keys - this hasn't been true for a while (thanks to kcb...@gm...) + 2.0.4 Released: 02/13/10 ma...@ma... |
|
From: Phil D. <ja...@us...> - 2010-02-27 11:07:17
|
Update of /cvsroot/pgpius/pius In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv2437 Modified Files: pius Log Message: - Prompt for a sign-level rather than 'y' or 'n', allowing for different levels per key. Fixes issue 2960103. Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.20 retrieving revision 1.21 diff -u -d -r1.20 -r1.21 --- pius 27 Feb 2010 10:45:12 -0000 1.20 +++ pius 27 Feb 2010 11:07:09 -0000 1.21 @@ -174,7 +174,7 @@ GPG_SIG_CREATED = '[GNUPG:] SIG_CREATED' def __init__(self, signer, mode, keyring, gpg_path, tmpdir, outdir, - encrypt_outfiles, sign_level, mail, verbose, mail_text, + encrypt_outfiles, mail, verbose, mail_text, mail_override, mail_host, mail_port, mail_no_pgp_mime, mail_user, mail_tls): self.mode = mode @@ -184,7 +184,6 @@ self.tmpdir = tmpdir self.outdir = outdir self.encrypt_outfiles = encrypt_outfiles - self.sign_level = sign_level self.mail = mail self.mail_text = mail_text self.mail_override = mail_override @@ -257,10 +256,17 @@ print 'WARNING: Keyid %s not valid, skipping.' % key return False - ans = raw_input('Have you verified this user/key? (y/N/q) ') + ans = 'y' + while ans == 'y': + ans = raw_input('\nHave you verified this user/key, and if so, what level' + '\ndo you want to sign at? (0/1/2/3/N/q) [default: N] ') + if ans == 'y': + print ('\n"Yes" is no longer a valid answer, please specify a level to' + ' sign at.') + print - if ans in ('y', 'Y', 'yes', 'Yes', 'YES'): - return True + if ans in ('0', '1', '2', '3'): + return ans elif ans in ('q', 'Q'): print 'Dying at user request' sys.exit(1) @@ -557,11 +563,11 @@ # reason it's still here is because agent support is flaky and some people # may not like us storing their passphrase in memory. # - def sign_uid_expect(self, key, index): + def sign_uid_expect(self, key, index, level): '''Sign a UID, using the expect stuff. Interactive mode.''' cmd = ('%s --no-default-keyring --keyring %s --default-cert-level %s' ' --no-ask-cert-level --edit-key %s' - % (self.gpg, self.tmp_keyring, self.sign_level, key)) + % (self.gpg, self.tmp_keyring, level, key)) debug(cmd) gpg = pexpect.spawn(cmd) gpg.setecho(False) @@ -603,7 +609,7 @@ line = fd.readline().strip() debug('got line %s' % line) - def sign_uid(self, key, index): + def sign_uid(self, key, index, level): '''Sign a single UID of a key. This can use either cached passpharse or gpg-agent.''' @@ -615,7 +621,7 @@ cmd = ('%s %s %s %s -u %s %s --default-cert-level %s --no-ask-cert-level' ' --edit-key %s' % (self.gpg, self.gpg_quiet_opts, self.gpg_fd_opts, keyring, - self.signer, agent, self.sign_level, key)) + self.signer, agent, level, key)) debug(cmd) gpg = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, @@ -732,7 +738,7 @@ if uids[index]['status'] != 'r' and uids[index]['result']: print ' %(id)s: %(enc_file)s' % uids[index] - def sign_all_uids(self, key): + def sign_all_uids(self, key, level): '''The main function that signs all the UIDs on a given key.''' uids = self.get_uids(key) print ' There are %s UIDs on this key to sign' % (len(uids) - 1) @@ -752,7 +758,7 @@ # Sign the key... if self.mode in (MODE_CACHE_PASSPHRASE, MODE_AGENT): try: - res = self.sign_uid(key, index) + res = self.sign_uid(key, index, level) except AgentError: print '\ngpg-agent problems, bailing out!' sys.exit(1) @@ -764,7 +770,7 @@ # No need to say anything else sys.exit(1) else: - res = self.sign_uid_expect(key, index) + res = self.sign_uid_expect(key, index, level) if not res: uids[index]['result'] = False continue @@ -1137,8 +1143,7 @@ tmp_dir=DEFAULT_TMP_DIR, keyring=DEFAULT_KEYRING, mail_host=DEFAULT_MAIL_HOST, - mail_port=DEFAULT_MAIL_PORT, - sign_level=3) + mail_port=DEFAULT_MAIL_PORT) parser.add_option('-a', '--use-agent', action='store_const', const=MODE_AGENT, dest='mode', help='Use pgp-agent instead of letting gpg prompt the' @@ -1166,9 +1171,6 @@ ' into the default keyring. Ignored if -r is not' ' specified, or if it\'s the same as the default' ' keyring.') - parser.add_option('-l', '--signature-level', dest='sign_level', - metavar='LEVEL', nargs=1, type='int', - help='The level to sign keys at (0-3). [default: %default]') parser.add_option('-m', '--mail', dest='mail', metavar='EMAIL', nargs=1, type='email', help='Email the encrypted, signed keys to the' @@ -1267,11 +1269,11 @@ signer = uids_signer(options.signer, options.mode, options.keyring, options.gpg_path, options.tmp_dir, options.out_dir, - options.encrypt_outfiles, options.sign_level, - options.mail, options.verbose, options.mail_text, - options.mail_override, options.mail_host, - options.mail_port, options.mail_no_pgp_mime, - options.mail_user, options.mail_tls) + options.encrypt_outfiles, options.mail, options.verbose, + options.mail_text, options.mail_override, + options.mail_host, options.mail_port, + options.mail_no_pgp_mime, options.mail_user, + options.mail_tls) if options.all_keys: key_list = signer.get_all_keyids() @@ -1308,10 +1310,11 @@ # The actual signing for key in key_list: - if not signer.check_fingerprint(key): + retval = signer.check_fingerprint(key) + if retval == False: continue print 'Signing all UIDs on key %s' % key - signer.sign_all_uids(key) + signer.sign_all_uids(key, retval) print '' # If the user asked, import the keys |
|
From: Phil D. <ja...@us...> - 2010-02-27 10:45:20
|
Update of /cvsroot/pgpius/pius In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv32282 Modified Files: pius Log Message: - We need to encode keys for quoted-printable before sending them that way. Fixes issue 2960095. - Fixes 2 >80 lines - Fixes inaccurate help text Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.19 retrieving revision 1.20 diff -u -d -r1.19 -r1.20 --- pius 12 Feb 2010 23:04:08 -0000 1.19 +++ pius 27 Feb 2010 10:45:12 -0000 1.20 @@ -22,6 +22,7 @@ from email import MIMEBase from email import MIMEMultipart from email import MIMEText +from email import quopriMIME from email.Utils import formatdate from copy import copy from optparse import OptionParser, Option, OptionValueError @@ -662,9 +663,10 @@ # Unfortunately PGP doesn't give us anything parsable in this case. It # just gives us another prompt. We give the most likely problem. Best we # can do. - print (' ERROR: GnuPG won\'t let us sign, this probably means it can\'t' - ' find a secret key, which most likely means that the keyring you' - ' are using doesn\'t have _your_ _public_ key on it.') + print (' ERROR: GnuPG won\'t let us sign, this probably means it' + ' can\'t find a secret key, which most likely means that the' + ' keyring you are using doesn\'t have _your_ _public_ key on' + ' it.') gpg.stdin.write('quit\n') raise NoSelfKeyError elif uids_signer.GPG_CONFIRM in line: @@ -917,7 +919,7 @@ attached_sig.add_header('Content-Disposition', 'inline', filename='%s' % filename) attached_sig.__delitem__('MIME-Version') - attached_sig.set_payload(open(filepath, 'r').read()) + attached_sig.set_payload(quopriMIME.encode(open(filepath, 'r').read())) encrypted_body.attach(attached_sig) encrypted_body.__delitem__('MIME-Version') @@ -1166,12 +1168,12 @@ ' keyring.') parser.add_option('-l', '--signature-level', dest='sign_level', metavar='LEVEL', nargs=1, type='int', - help='The level to sign keys at (0-3).') + help='The level to sign keys at (0-3). [default: %default]') parser.add_option('-m', '--mail', dest='mail', metavar='EMAIL', nargs=1, type='email', help='Email the encrypted, signed keys to the' ' respective email addresses. EMAIL is the address' - ' to send from. Requires local mailserver.') + ' to send from. See also -H and -p.') parser.add_option('-M', '--mail-text', dest='mail_text', metavar='FILE', nargs=1, type='not_another_opt', help='Use the text in FILE as the body of email when' |
|
From: Phil D. <ja...@us...> - 2010-02-12 23:04:16
|
Update of /cvsroot/pgpius/pius In directory sfp-cvsdas-2.v30.ch3.sourceforge.com:/tmp/cvs-serv23582 Modified Files: COPYING Changelog pius pius.spec Log Message: - Release 2.0.4 Index: pius.spec =================================================================== RCS file: /cvsroot/pgpius/pius/pius.spec,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- pius.spec 26 Apr 2009 14:15:59 -0000 1.5 +++ pius.spec 12 Feb 2010 23:04:08 -0000 1.6 @@ -2,7 +2,7 @@ # $Id$ %define name pius -%define version 2.0.3 +%define version 2.0.4 %define release 1 Name: %{name} Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.18 retrieving revision 1.19 diff -u -d -r1.18 -r1.19 --- pius 8 Sep 2009 19:02:38 -0000 1.18 +++ pius 12 Feb 2010 23:04:08 -0000 1.19 @@ -5,7 +5,7 @@ # vim:shiftwidth=2:tabstop=2:expandtab:textwidth=80:softtabstop=2:ai: # -# Copyright (c) 2008 - 2009 Phil Dibowitz (ph...@ip...) +# Copyright (c) 2008 - 2010 Phil Dibowitz (ph...@ip...) # # This program is free software; you can redistribute it and/or # modify it under the terms of the GNU General Public License as @@ -33,7 +33,7 @@ import subprocess import sys -VERSION = '2.0.3' +VERSION = '2.0.4' DEBUG_ON = False MODE_INTERACTIVE = 0 Index: COPYING =================================================================== RCS file: /cvsroot/pgpius/pius/COPYING,v retrieving revision 1.1 retrieving revision 1.2 diff -u -d -r1.1 -r1.2 --- COPYING 6 Feb 2009 23:38:11 -0000 1.1 +++ COPYING 12 Feb 2010 23:04:08 -0000 1.2 @@ -1,4 +1,4 @@ - Copyright (C) 2007 Phil Dibowitz (ph...@ip...) + Copyright (C) 2007-2010 Phil Dibowitz <ph...@ip...> This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- Changelog 3 Sep 2009 19:01:51 -0000 1.9 +++ Changelog 12 Feb 2010 23:04:08 -0000 1.10 @@ -1,10 +1,16 @@ -CVS +2.0.4 +Released: 02/13/10 ma...@ma... - Make pius respect the GNUPGHOME environment variable ph...@ip... - Add support for a config file. Based heavily on a patch by ma...@ma... - Fix default GNUPGHOME to use $HOME rather than ~/ +2.0.3 +Released: 04/26/09 +- Fix typo in exception name +- Add newline between keys + 2.0.2 Released: 04/22/09 ph...@ip... |
|
From: Phil D. <ja...@us...> - 2009-09-08 19:02:47
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv28450 Modified Files: pius Log Message: Fix comment, thanks to ma...@ma... Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.17 retrieving revision 1.18 diff -u -d -r1.17 -r1.18 --- pius 3 Sep 2009 19:06:35 -0000 1.17 +++ pius 8 Sep 2009 19:02:38 -0000 1.18 @@ -1220,7 +1220,7 @@ parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='Be more verbose.') - # Check for extra options in the GnuPG homedirectory. + # Check for extra options in the ~/.pius file opts_file = os.path.join(HOME, '.pius') all_opts = [] sep = re.compile(r'(?:\s*=\s*|\s*:\s*\s+)') |
|
From: Phil D. <ja...@us...> - 2009-09-03 19:06:44
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv30170 Modified Files: pius Log Message: Add useful comment Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.16 retrieving revision 1.17 diff -u -d -r1.16 -r1.17 --- pius 3 Sep 2009 19:01:51 -0000 1.16 +++ pius 3 Sep 2009 19:06:35 -0000 1.17 @@ -1236,6 +1236,9 @@ except IOError: # File doesn't exist or is broken pass + # Note that by putting this at the end we allow the command line to override + # options specified in the config file, BUT if any options conflict, the first + # wins, so the config file wins. Meh. all_opts.extend(sys.argv[1:]) (options, args) = parser.parse_args(all_opts) |
|
From: Phil D. <ja...@us...> - 2009-09-03 19:02:03
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv29726 Modified Files: Changelog README pius Log Message: Add the ability to have options in a config file, ~/.pius. Based heavily on a patch by Matt Brown <ma...@ma...>, with modifications to * change the file name * not require "--" in the file * have much more flexible parsing In addition, I've fixed the previous patch but grabbing $HOME from the environment ra ther than using ~/ which doesn't work in open() Signed-off-by: Phil Dibowitz <ph...@ip...> Index: README =================================================================== RCS file: /cvsroot/pgpius/pius/README,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- README 22 Mar 2009 11:35:26 -0000 1.3 +++ README 3 Sep 2009 19:01:51 -0000 1.4 @@ -120,6 +120,19 @@ <ph...@ip...>. +CONFIG FILE + +You can specify options you'd like to always use in a ~/.pius file. The format +of this file is option=value. The "=value" part is obviously not required for +options that don't have a value. An example might be: + + mai...@sa... + tmp-dir=/home/you/pius/tmp + +Pius will except both '=', ':', or whitespace as a separator, and will handle +extra whitespace around any separator. + + Phil Dibowitz ph...@ip... Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.15 retrieving revision 1.16 diff -u -d -r1.15 -r1.16 --- pius 3 Sep 2009 18:29:56 -0000 1.15 +++ pius 3 Sep 2009 19:01:51 -0000 1.16 @@ -40,7 +40,8 @@ MODE_CACHE_PASSPHRASE = 1 MODE_AGENT = 2 -GNUPGHOME = os.environ.get('GNUPGHOME', '~/.gnupg') +HOME = os.environ.get('HOME') +GNUPGHOME = os.environ.get('GNUPGHOME', os.path.join(HOME, '.gnupg')) DEFAULT_GPG_PATH = '/usr/bin/gpg' DEFAULT_KEYRING = os.path.join(GNUPGHOME, 'pubring.gpg') DEFAULT_TMP_DIR = '/tmp/pius_tmp' @@ -1219,7 +1220,24 @@ parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='Be more verbose.') - (options, args) = parser.parse_args() + # Check for extra options in the GnuPG homedirectory. + opts_file = os.path.join(HOME, '.pius') + all_opts = [] + sep = re.compile(r'(?:\s*=\s*|\s*:\s*\s+)') + try: + fp = open(opts_file, 'r') + for line in fp: + parts = sep.split(line.strip()) + if not parts[0].startswith('--'): + parts[0] = '--%s' % parts[0] + if parser.has_option(parts[0]): + all_opts.extend(parts) + fp.close() + except IOError: + # File doesn't exist or is broken + pass + all_opts.extend(sys.argv[1:]) + (options, args) = parser.parse_args(all_opts) print 'Welcome to PIUS, the PGP Individual UID Signer.\n' Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- Changelog 3 Sep 2009 18:29:56 -0000 1.8 +++ Changelog 3 Sep 2009 19:01:51 -0000 1.9 @@ -1,6 +1,9 @@ CVS ma...@ma... - Make pius respect the GNUPGHOME environment variable +ph...@ip... +- Add support for a config file. Based heavily on a patch by ma...@ma... +- Fix default GNUPGHOME to use $HOME rather than ~/ 2.0.2 Released: 04/22/09 |
|
From: Phil D. <ja...@us...> - 2009-09-03 18:30:11
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv26483 Modified Files: Changelog pius Log Message: From: Matt Brown <ma...@ma...> This patch makes pius respect GNUPGHOME Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.14 retrieving revision 1.15 diff -u -d -r1.14 -r1.15 --- pius 26 Apr 2009 14:15:59 -0000 1.14 +++ pius 3 Sep 2009 18:29:56 -0000 1.15 @@ -40,8 +40,9 @@ MODE_CACHE_PASSPHRASE = 1 MODE_AGENT = 2 +GNUPGHOME = os.environ.get('GNUPGHOME', '~/.gnupg') DEFAULT_GPG_PATH = '/usr/bin/gpg' -DEFAULT_KEYRING = '~/.gnupg/pubring.gpg' +DEFAULT_KEYRING = os.path.join(GNUPGHOME, 'pubring.gpg') DEFAULT_TMP_DIR = '/tmp/pius_tmp' DEFAULT_OUT_DIR = '/tmp/pius_out' DEFAULT_MAIL_HOST = 'localhost' Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.7 retrieving revision 1.8 diff -u -d -r1.7 -r1.8 --- Changelog 22 Apr 2009 14:18:13 -0000 1.7 +++ Changelog 3 Sep 2009 18:29:56 -0000 1.8 @@ -1,3 +1,7 @@ +CVS +ma...@ma... +- Make pius respect the GNUPGHOME environment variable + 2.0.2 Released: 04/22/09 ph...@ip... |
|
From: Phil D. <ja...@us...> - 2009-04-26 14:16:12
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv3091 Modified Files: pius pius.spec Log Message: - Fix typo in exception name - Add newline between keys - bump version Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius.spec =================================================================== RCS file: /cvsroot/pgpius/pius/pius.spec,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- pius.spec 22 Apr 2009 14:18:13 -0000 1.4 +++ pius.spec 26 Apr 2009 14:15:59 -0000 1.5 @@ -2,7 +2,7 @@ # $Id$ %define name pius -%define version 2.0.2 +%define version 2.0.3 %define release 1 Name: %{name} Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.13 retrieving revision 1.14 diff -u -d -r1.13 -r1.14 --- pius 22 Apr 2009 14:18:13 -0000 1.13 +++ pius 26 Apr 2009 14:15:59 -0000 1.14 @@ -33,7 +33,7 @@ import subprocess import sys -VERSION = '2.0.2' +VERSION = '2.0.3' DEBUG_ON = False MODE_INTERACTIVE = 0 @@ -934,7 +934,7 @@ try: self.encrypt_and_sign_file(tmpfile, signed_tmpfile, keyid) except EncryptionKeyError: - raise EncyptionKeyError + raise EncryptionKeyError # Create the version part of the PGP/Mime encryption pgp_ver = MIMEBase.MIMEBase('application', 'pgp-encrypted') @@ -1288,6 +1288,7 @@ continue print 'Signing all UIDs on key %s' % key signer.sign_all_uids(key) + print '' # If the user asked, import the keys if options.import_keyring: |
|
From: Phil D. <ja...@us...> - 2009-04-22 14:18:19
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv10678 Modified Files: Changelog pius pius.spec Log Message: Releasing 2.0.2. Index: pius.spec =================================================================== RCS file: /cvsroot/pgpius/pius/pius.spec,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- pius.spec 22 Mar 2009 12:32:44 -0000 1.3 +++ pius.spec 22 Apr 2009 14:18:13 -0000 1.4 @@ -2,7 +2,7 @@ # $Id$ %define name pius -%define version 2.0.1 +%define version 2.0.2 %define release 1 Name: %{name} Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.12 retrieving revision 1.13 diff -u -d -r1.12 -r1.13 --- pius 21 Apr 2009 16:05:52 -0000 1.12 +++ pius 22 Apr 2009 14:18:13 -0000 1.13 @@ -33,7 +33,7 @@ import subprocess import sys -VERSION = '2.0.1' +VERSION = '2.0.2' DEBUG_ON = False MODE_INTERACTIVE = 0 Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.6 retrieving revision 1.7 diff -u -d -r1.6 -r1.7 --- Changelog 21 Apr 2009 16:05:52 -0000 1.6 +++ Changelog 22 Apr 2009 14:18:13 -0000 1.7 @@ -1,5 +1,5 @@ -CVS -Released: +2.0.2 +Released: 04/22/09 ph...@ip... - Catch the case where a users' public key isn't on the keyring and report it to the user instead of just failing (reported by phil.pennock at spodhuis.org) |
|
From: Phil D. <ja...@us...> - 2009-04-21 16:06:03
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv9462 Modified Files: Changelog pius Log Message: - Catch the case when the key we're signing doesn't have an encryption subkey but we're doing PGP/Mime Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.11 retrieving revision 1.12 diff -u -d -r1.11 -r1.12 --- pius 22 Mar 2009 13:44:59 -0000 1.11 +++ pius 21 Apr 2009 16:05:52 -0000 1.12 @@ -931,7 +931,10 @@ tfile = open(tmpfile, 'w') tfile.write(dos_body) tfile.close() - self.encrypt_and_sign_file(tmpfile, signed_tmpfile, keyid) + try: + self.encrypt_and_sign_file(tmpfile, signed_tmpfile, keyid) + except EncryptionKeyError: + raise EncyptionKeyError # Create the version part of the PGP/Mime encryption pgp_ver = MIMEBase.MIMEBase('application', 'pgp-encrypted') @@ -973,11 +976,16 @@ def send_mail(self, email, keyid, uid_data): '''Send the encrypted uid off to the user.''' - if self.mail_no_pgp_mime: - msg = self._generate_non_pgp_mime_email(email, keyid, - uid_data['enc_file']) - else: - msg = self._generate_pgp_mime_email(email, keyid, uid_data['file']) + try: + if self.mail_no_pgp_mime: + msg = self._generate_non_pgp_mime_email(email, keyid, + uid_data['enc_file']) + else: + msg = self._generate_pgp_mime_email(email, keyid, uid_data['file']) + except EncryptionKeyError: + msg = ('Failed to generate the email to the user. This is most' + ' likely due to the user having no encryption subkey.') + raise MailSendError, msg # We don't duplicate the header logic in the sub functions, we # do that here Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.5 retrieving revision 1.6 diff -u -d -r1.5 -r1.6 --- Changelog 22 Mar 2009 13:44:59 -0000 1.5 +++ Changelog 21 Apr 2009 16:05:52 -0000 1.6 @@ -8,6 +8,8 @@ - Specify the key to sign with incase there are two private keys and both of them happen to be on the public ring as well. (reported by phil.pennock at spodhuis.org) +- Catch the case when the key we're signing doesn't have an encryption subkey + but we're doing PGP/Mime 2.0.1 Released: 02/28/09 |
|
From: Phil D. <ja...@us...> - 2009-03-22 13:46:35
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv15174 Modified Files: Changelog pius Log Message: pius: - Specify the key to sign with incase there are two private keys and both of them happen to be on the public ring as well. (reported by phil.pennock at spodhuis.org) Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.10 retrieving revision 1.11 diff -u -d -r1.10 -r1.11 --- pius 22 Mar 2009 12:32:44 -0000 1.10 +++ pius 22 Mar 2009 13:44:59 -0000 1.11 @@ -607,11 +607,12 @@ agent = '' if self.mode == MODE_AGENT: agent = '--use-agent' + keyring = '--no-default-keyring --keyring %s' % self.tmp_keyring # Note that if passphrase-fd is different from command-fd, nothing works. - cmd = ('%s %s %s --no-default-keyring --keyring %s %s' - ' --default-cert-level %s --no-ask-cert-level --edit-key %s' % - (self.gpg, self.gpg_quiet_opts, self.gpg_fd_opts, self.tmp_keyring, - agent, self.sign_level, key)) + cmd = ('%s %s %s %s -u %s %s --default-cert-level %s --no-ask-cert-level' + ' --edit-key %s' % + (self.gpg, self.gpg_quiet_opts, self.gpg_fd_opts, keyring, + self.signer, agent, self.sign_level, key)) debug(cmd) gpg = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, @@ -822,9 +823,9 @@ if self.mode == MODE_AGENT: agent = '--use-agent' keyring = '--no-default-keyring --keyring %s' % self.tmp_keyring - cmd = ('%s %s %s %s %s --always-trust -aes -r %s -r %s --output %s %s' % - (self.gpg, self.gpg_quiet_opts, self.gpg_fd_opts, keyring, - agent, keyid, self.signer, outfile, infile)) + cmd = ('%s %s %s %s %s --always-trust -u %s -aes -r %s -r %s --output %s %s' + % (self.gpg, self.gpg_quiet_opts, self.gpg_fd_opts, keyring, + agent, self.signer, keyid, self.signer, outfile, infile)) debug(cmd) gpg = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.4 retrieving revision 1.5 diff -u -d -r1.4 -r1.5 --- Changelog 22 Mar 2009 12:34:30 -0000 1.4 +++ Changelog 22 Mar 2009 13:44:59 -0000 1.5 @@ -2,8 +2,12 @@ Released: ph...@ip... - Catch the case where a users' public key isn't on the keyring and report it - to the user instead of just failing -- Handle expired subkeys on the _signers'_ key + to the user instead of just failing (reported by phil.pennock at spodhuis.org) +- Handle expired subkeys on the _signers'_ key (reported by phil.pennock at + spodhuis.org) +- Specify the key to sign with incase there are two private keys and both of + them happen to be on the public ring as well. (reported by phil.pennock at + spodhuis.org) 2.0.1 Released: 02/28/09 |
|
From: Phil D. <ja...@us...> - 2009-03-22 12:34:39
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv16272 Modified Files: Changelog Log Message: add changelog entries Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.3 retrieving revision 1.4 diff -u -d -r1.3 -r1.4 --- Changelog 22 Mar 2009 11:35:26 -0000 1.3 +++ Changelog 22 Mar 2009 12:34:30 -0000 1.4 @@ -1,3 +1,10 @@ +CVS +Released: +ph...@ip... +- Catch the case where a users' public key isn't on the keyring and report it + to the user instead of just failing +- Handle expired subkeys on the _signers'_ key + 2.0.1 Released: 02/28/09 ph...@ip... |
|
From: Phil D. <ja...@us...> - 2009-03-22 12:33:00
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv9788 Modified Files: pius pius.spec Log Message: pius: - Catch the case where a users' public key isn't on the keyring and report it to the user instead of just failing - Handle expired subkeys on the _signers'_ key pius.spec: - Catch up the version numbers here All of the above problems reported by phil.pennock at spodhuis.org Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius.spec =================================================================== RCS file: /cvsroot/pgpius/pius/pius.spec,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- pius.spec 22 Mar 2009 11:35:26 -0000 1.2 +++ pius.spec 22 Mar 2009 12:32:44 -0000 1.3 @@ -2,7 +2,7 @@ # $Id$ %define name pius -%define version 2.0.0 +%define version 2.0.1 %define release 1 Name: %{name} Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.9 retrieving revision 1.10 diff -u -d -r1.9 -r1.10 --- pius 22 Mar 2009 11:35:26 -0000 1.9 +++ pius 22 Mar 2009 12:32:44 -0000 1.10 @@ -123,6 +123,12 @@ pass +class NoSelfKeyError(Exception): + '''An exception for when the user didn't include their own public key in the + keyring.''' + pass + + class EncryptionKeyError(Exception): '''An exception for when a key can't encrypt (no encryption subkey).''' pass @@ -636,18 +642,36 @@ gpg.stdin.write('sign\n') self.gpg_wait_for_string(gpg.stdout, uids_signer.GPG_ACK) - # Either we already signed this, or we can proceed - line = gpg.stdout.readline() - debug('Got %s' % line) - if uids_signer.GPG_ALREADY_SIGNED in line: - print ' UID already signed' - gpg.stdin.write('quit\n') - return False - elif not uids_signer.GPG_CONFIRM in line: - print ' ERROR: GnuPG reported an unknown error' - gpg.stdin.write('quit\n') - return False - # else its uids_signer.GPG_CONFIRM... + while True: + debug('Waiting for response') + line = gpg.stdout.readline() + debug('Got %s' % line) + if uids_signer.GPG_ALREADY_SIGNED in line: + print ' UID already signed' + gpg.stdin.write('quit\n') + return False + elif (uids_signer.GPG_KEY_EXP in line or + uids_signer.GPG_SIG_EXP in line): + # The user has an expired signing or encryption key, keep going + debug('Got GPG_KEY/SIG_EXP') + continue + elif uids_signer.GPG_PROMPT in line: + # Unfortunately PGP doesn't give us anything parsable in this case. It + # just gives us another prompt. We give the most likely problem. Best we + # can do. + print (' ERROR: GnuPG won\'t let us sign, this probably means it can\'t' + ' find a secret key, which most likely means that the keyring you' + ' are using doesn\'t have _your_ _public_ key on it.') + gpg.stdin.write('quit\n') + raise NoSelfKeyError + elif uids_signer.GPG_CONFIRM in line: + # This is what we want + break + else: + print ' ERROR: GnuPG reported an unknown error' + gpg.stdin.write('quit\n') + # Don't raise an exception, it's not probably just this UID... + return False debug('Confirming signing') gpg.stdin.write('Y\n') @@ -731,6 +755,9 @@ print ('\nThe passphrase that worked a moment ago now doesn\'t work.' ' I\'m bailing out!') sys.exit(1) + except NoSelfKeyError: + # No need to say anything else + sys.exit(1) else: res = self.sign_uid_expect(key, index) if not res: |
|
From: Phil D. <ja...@us...> - 2009-03-22 11:35:38
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv24816 Modified Files: Changelog README pius Added Files: pius.spec Log Message: Merging 2x back to HEAD Index: README =================================================================== RCS file: /cvsroot/pgpius/pius/README,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- README 7 Feb 2009 00:52:20 -0000 1.2 +++ README 22 Mar 2009 11:35:26 -0000 1.3 @@ -1,10 +1,11 @@ PIUS: The PGP Individual UID Signer + INTRODUCTION PIUS started life as a group of bad shell scripts I had thrown together through the years after going to various PGP keysigning parties. These scripts -automated various bits and pieces of signing various keys and UIDs, but feel +automated various bits and pieces of signing various keys and UIDs, but fell short of actually making it a mostly painless process. Finally I decided to sit down and combine all these shell scripts into a single @@ -18,10 +19,10 @@ The original version heavily used the pexpect module for various reasons: (1) I wanted to be able to let the user enter the passphrase directly into gpg for security reasons, (2) Using the --{command,passphrase,status}-fd options turned -not to be not that well documented and not work the way the documentation +not to be not that well documented and not work the way the documentation suggested. -This method quickly showed itself to be very fragile. So, Imanaged to bend gpg +This method quickly showed itself to be very fragile. So, I managed to bend gpg to my will without using pexpect, and the only thing left that uses pexpect is the 'interactive' mode, which will probably one day go away if gpg-agent becomes reliable enough. @@ -29,50 +30,70 @@ USAGE -The simplest use form is - $ pius -e -s <your_keyid> <keyid> +The simplest (but least useful) use form is + $ pius -s <your_keyid> <keyid> This will sign all UIDs on <keyid>, and export one copy of the for each UID with only that UID signed. These keys are exported into a file in /tmp named <keyid>__<id>.asc, where id is usually an email address if we can extract one, -otherwise some other piece of the UID. The '-e' flag is what turns on the -encryption of the outfiles, and the '-s' flag denotes the "signing" keyid. This -default mode uses the pexpect mode to drop you into gpg at the right time so -you can enter your passphrase directly into it. This means in this mode you -will be prompted once for every UID on every key you sign. This mode will go -away eventually. +otherwise some other piece of the UID. The '-s' flag denotes the "signing" +keyid. -There are two other modes which you can enter by using -p or -a. The -p option -causes PIUS to prompt for your passpharse at startup and feed it to gpg when -needed. The passphrase is only stored in memory, but since we don't require -root (or setuid) we don't lock memory. This may raise security issues if there -are untrusted individuals on the system (but for single user desktops shouldn't -be an issue). The -a mode will attempt to use gpg-agent. This is the most -secure and convenient method, but sometimes gpg-agent can be flaky. +Note this default mode will prompt for your passphrase and cache it for the life +of the execution so that it can provide it to GnuPG. There are other options, +please see the SECURITY IMPLICATIONS section below. After a keysigning party you probably have a party keyring provided by the organizer and want to sign most of the keys on it. In this case, don't specify -the all the keyids to sign. You probably also want to automatically send off -emails with the encrypted signatures to all of the UIDs that you verify. In -that case you want: - $ pius -A -e -m <your_email> -r </path/to/keyring.gpg> -s <your_keyid> +the all the keyids to sign and instead probably want something more like: + $ pius -A -r </path/to/keyring.gpg> -m <your_email> -s <your_keyid> The -r flag specifies a keyring to use, and the -A flag says to sign all keyids on that keyring. Since you are prompted to verify each fingerprint, you can say -no to any people on the ring you were unable to verify. The -e flag says to -encrypt the exported keyfile and the -m flag says to email it using the -provided address as the From. +no to any people on the ring you were unable to verify. The -p flag, as +previously mentioned, will catch your passphrase. -m will cause pius to email +out the keys to the respective email addresses from <your_email>. There are a variety of other options that you may want: * customize the tmpdir and outdir directories (-t and -o respectively) + * encrypt the outfiles to <filename>_ENCRYPTED.asc (-e) * select the signing level (-l) - * import the unsigned keys to the default keyring (-i) + * import the unsigned keys to the default keyring (-I) * verbose mode (-v) + * customize mail hostname and port (-H and -P respectively) + * customize the email message (-M) + * don't use PGP/Mime in the email (-O, implies -e) + * specify a SMTPAUTH or STARTTLS for SMTP (-u and -S) And more! See the '-h' option for more. -A NOTE ON SENDING EMAILS +SECURITY IMPLICATIONS + +The default mode for pius, starting in 2.0.0 is 'cache_passphrase' mode. This +means that pius will ask you for your passphrase at startup, verify this +passphrase is correct, and then feed it GnuPG everytime it needs it. The +passphrase is stored in memory and only for the life of the execution of pius. +For most users this should be relatively safe. However, it is worth noting that +if you are on a machine whose system administrators you don't trust, there is a +small danger of them reading this memory while pius is running. + +There are two alternatives for people not comfortable with this. The first is to +use the agent mode. By specifying -a, pius will ask gpg to get the passphrase +from an gpg-agent. You will need to have your gpg-agent setup and running. +However, gpg-agent can be rather flaky, so we recommend you pre-seed by doing +something that requires your private keys so it can cache your keys before you +run pius. + +Finally we have 'interactive mode' which can be entered using -i. This will use +pexpect to handle most of the signing interactions and then drop you into the +'gpg --edit-key' shell whenever gpg needs a passphrase. Using this you can enter +your passphrase directly into gpg. This mode has two main disadvantages. The +first is that the pexpect code is quite fragile, and the second is that you'll +have to type your passphrase for every key-UID combination. + + +SENDING EMAILS When PIUS emails out keys it BCC's you, so you will get a copy of every email sent out. If you would like to see what is going to be sent and not have it @@ -83,8 +104,24 @@ option to forcefully override the TO in the envelope of the email. When doing this *only* the address specified as an argument to -n will get the email. +If you want to see the email sent when not using PGP/Mime then try: + $ pius -T -O + +If you want to customize this message you can do so with the -M option. Note +that you may use python's named variable interpolation syntax here to have pius +fill in email (the email in the UID, i.e. the recipient), keyid (of the key that +was signed), and signer (the keyid used to sign, i.e. your keyid). For example, +you can simply include "%(keyid)s" (without the quotes) to get the keyid. + + LICENSE PIUS is released under the GNU Public License v2 and is Copyright Phil Dibowitz <ph...@ip...>. + +Phil Dibowitz +ph...@ip... + + +# vim:shiftwidth=2:tabstop=2:expandtab:textwidth=80:softtabstop=2:ai: --- NEW FILE: pius.spec --- # Sample spec file. # $Id: pius.spec,v 1.2 2009/03/22 11:35:26 jaymzh Exp $ %define name pius %define version 2.0.0 %define release 1 Name: %{name} Summary: A tool for signing and email all UIDs on a set of PGP keys. Version: %{version} Release: %{release} Group: Utilities License: GPLv2 URL: http://www.phildev.net/pius/ BuildRoot: %{_tmppath}/%{name}-buildroot Requires: python %description The PGP Individual UID Signer (PIUS) is a tool for individually signing all of the UIDs on a set of keys and encrypt-emailing each one to it's respective email address. This drastically reduces the time and errors involved in signing keys after a keysigning party. %prep rm -rf $RPM_BUILD_ROOT %setup %install make install PREFIX=$RPM_BUILD_ROOT/usr %clean rm -rf $RPM_BUILD_ROOT %files %defattr(755, root, bin, 755) /usr/bin/%{name} %doc README COPYING Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.8 retrieving revision 1.9 diff -u -d -r1.8 -r1.9 --- pius 6 Feb 2009 23:38:11 -0000 1.8 +++ pius 22 Mar 2009 11:35:26 -0000 1.9 @@ -1,4 +1,6 @@ #!/usr/bin/python +"""A utility to sign all UIDs on a list of PGP keys and PGP/Mime encrypt-email +them to the respective emails.""" # vim:shiftwidth=2:tabstop=2:expandtab:textwidth=80:softtabstop=2:ai: @@ -9,6 +11,10 @@ # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, version 2. # +# Note that we only import pexpect if -i is specified. In order to do this [...1130 lines suppressed...] + if not signer.check_fingerprint(key): continue print 'Signing all UIDs on key %s' % key - p.sign_all_uids(key) + signer.sign_all_uids(key) - p.cleanup() + # If the user asked, import the keys + if options.import_keyring: + if ((not options.keyring) or (options.keyring == DEFAULT_KEYRING)): + print ('WARNING: Ignoring -i: Either -r wasn\'t specified, or it was' + ' the same as the default keyring.') + else: + signer.import_unsigned_keys() -main() + signer.cleanup() + +if __name__ == '__main__': + main() Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.2 retrieving revision 1.3 diff -u -d -r1.2 -r1.3 --- Changelog 7 Feb 2009 00:52:20 -0000 1.2 +++ Changelog 22 Mar 2009 11:35:26 -0000 1.3 @@ -1,3 +1,29 @@ +2.0.1 +Released: 02/28/09 +ph...@ip... +- Fix bug where pius would occasionally report a good key as bad + +2.0.0 +Released: 02/07/09 +ph...@ip... +- Add support for PGP/Mime, make it default +- Significant improvement to error checking and handling of gpg calls +- Minimize keys in import +- Better input checking +- Various code cleanups +- Support named interpolation in email templates +- Use proper extension for our tmp keyring +- Change default tmp/out directories to something more sane +- Fix handling of mode (-p, -i, -a) +- Make cache_passphrase mode default +- Add prompt about sending email if user didn't specify +- Move import of keyring to end +- Only import pexpect if we need it +- Add support for STARTTLS and SMTPAUTH when sending email +- Guard main() in an if __name__ == '__main__' to allow pydoc to work on pius +- Added a spec file +- Add notes to the README on how to write custom emails + 1.7 Released: 02/06/09 ph...@ip... |
|
From: Phil D. <ja...@us...> - 2009-02-28 20:50:00
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv16809 Modified Files: Tag: pius_2_x_branch Changelog pius Log Message: I can reproduce this outside of pius, but some interaction between python and subprocess and gpg gets confused after the first key in pius2 and thinks that gpg --fingerprint exits with 2 even when running that same command works otherwise. Adding the quiet options to that commandline seems to solve the problem. pius: - Add quiet options to --fingerprint command line - Bump version Changelog: - Add 2.0.1 data Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.7.2.6 retrieving revision 1.7.2.7 diff -u -d -r1.7.2.6 -r1.7.2.7 --- pius 7 Feb 2009 23:05:43 -0000 1.7.2.6 +++ pius 28 Feb 2009 20:49:55 -0000 1.7.2.7 @@ -33,7 +33,7 @@ import subprocess import sys -VERSION = '2.0.0' +VERSION = '2.0.1' DEBUG_ON = False MODE_INTERACTIVE = 0 @@ -232,8 +232,8 @@ def check_fingerprint(self, key): '''Prompt the user to see if they have verified this fingerprint.''' - cmd = ('%s --no-default-keyring --keyring %s --fingerprint %s' - % (self.gpg, self.keyring, key)) + cmd = ('%s %s --no-default-keyring --keyring %s --fingerprint %s' + % (self.gpg, self.gpg_quiet_opts, self.keyring, key)) # Note we attach stderr to a pipe so it won't print errors to the terminal # which it does even if stderr=None debug(cmd) Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.1.2.7 retrieving revision 1.1.2.8 diff -u -d -r1.1.2.7 -r1.1.2.8 --- Changelog 7 Feb 2009 23:23:59 -0000 1.1.2.7 +++ Changelog 28 Feb 2009 20:49:54 -0000 1.1.2.8 @@ -1,3 +1,8 @@ +2.0.1 +Released: 02/28/09 +ph...@ip... +- Fix bug where pius would occasionally report a good key as bad + 2.0.0 Released: 02/07/09 ph...@ip... |
|
From: Phil D. <ja...@us...> - 2009-02-07 23:24:04
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv32354 Modified Files: Tag: pius_2_x_branch Changelog README Log Message: A few final things for 2.0.0 README: - Explain how to write custom emails Changelog: - List the above Signed-off-by: Phil Dibowitz <ph...@ip...> Index: README =================================================================== RCS file: /cvsroot/pgpius/pius/README,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -d -r1.1.2.3 -r1.1.2.4 --- README 7 Feb 2009 23:12:13 -0000 1.1.2.3 +++ README 7 Feb 2009 23:23:59 -0000 1.1.2.4 @@ -93,7 +93,7 @@ have to type your passphrase for every key-UID combination. -A NOTE ON SENDING EMAILS +SENDING EMAILS When PIUS emails out keys it BCC's you, so you will get a copy of every email sent out. If you would like to see what is going to be sent and not have it @@ -107,6 +107,12 @@ If you want to see the email sent when not using PGP/Mime then try: $ pius -T -O +If you want to customize this message you can do so with the -M option. Note +that you may use python's named variable interpolation syntax here to have pius +fill in email (the email in the UID, i.e. the recipient), keyid (of the key that +was signed), and signer (the keyid used to sign, i.e. your keyid). For example, +you can simply include "%(keyid)s" (without the quotes) to get the keyid. + LICENSE Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.1.2.6 retrieving revision 1.1.2.7 diff -u -d -r1.1.2.6 -r1.1.2.7 --- Changelog 7 Feb 2009 23:05:42 -0000 1.1.2.6 +++ Changelog 7 Feb 2009 23:23:59 -0000 1.1.2.7 @@ -17,6 +17,7 @@ - Add support for STARTTLS and SMTPAUTH when sending email - Guard main() in an if __name__ == '__main__' to allow pydoc to work on pius - Added a spec file +- Add notes to the README on how to write custom emails 1.7 Released: 02/06/09 |
|
From: Phil D. <ja...@us...> - 2009-02-07 23:12:17
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv26312 Modified Files: Tag: pius_2_x_branch README Log Message: README: - A few final fixes to the REAMDE for 2.0.0 The LAST commit message got lost and should have been: This is 2.0.0! pius - Remove BETA from version Changelog - note the spec file pius.spec - Add spec file Signed-off-by: Phil Dibowitz <ph...@ip...> Index: README =================================================================== RCS file: /cvsroot/pgpius/pius/README,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -d -r1.1.2.2 -r1.1.2.3 --- README 7 Feb 2009 00:49:10 -0000 1.1.2.2 +++ README 7 Feb 2009 23:12:13 -0000 1.1.2.3 @@ -63,6 +63,7 @@ * customize mail hostname and port (-H and -P respectively) * customize the email message (-M) * don't use PGP/Mime in the email (-O, implies -e) + * specify a SMTPAUTH or STARTTLS for SMTP (-u and -S) And more! See the '-h' option for more. @@ -103,6 +104,9 @@ option to forcefully override the TO in the envelope of the email. When doing this *only* the address specified as an argument to -n will get the email. +If you want to see the email sent when not using PGP/Mime then try: + $ pius -T -O + LICENSE |
|
From: Phil D. <ja...@us...> - 2009-02-07 23:05:47
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv23912 Modified Files: Tag: pius_2_x_branch Changelog pius Added Files: Tag: pius_2_x_branch pius.spec Log Message: --- NEW FILE: pius.spec --- # Sample spec file. # $Id: pius.spec,v 1.1.2.1 2009/02/07 23:05:43 jaymzh Exp $ %define name pius %define version 2.0.0 %define release 1 Name: %{name} Summary: A tool for signing and email all UIDs on a set of PGP keys. Version: %{version} Release: %{release} Group: Utilities License: GPLv2 URL: http://www.phildev.net/pius/ BuildRoot: %{_tmppath}/%{name}-buildroot Requires: python %description The PGP Individual UID Signer (PIUS) is a tool for individually signing all of the UIDs on a set of keys and encrypt-emailing each one to it's respective email address. This drastically reduces the time and errors involved in signing keys after a keysigning party. %prep rm -rf $RPM_BUILD_ROOT %setup %install make install PREFIX=$RPM_BUILD_ROOT/usr %clean rm -rf $RPM_BUILD_ROOT %files %defattr(755, root, bin, 755) /usr/bin/%{name} %doc README COPYING Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.7.2.5 retrieving revision 1.7.2.6 diff -u -d -r1.7.2.5 -r1.7.2.6 --- pius 7 Feb 2009 22:54:22 -0000 1.7.2.5 +++ pius 7 Feb 2009 23:05:43 -0000 1.7.2.6 @@ -33,7 +33,7 @@ import subprocess import sys -VERSION = '2.0.0-BETA' +VERSION = '2.0.0' DEBUG_ON = False MODE_INTERACTIVE = 0 Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.1.2.5 retrieving revision 1.1.2.6 diff -u -d -r1.1.2.5 -r1.1.2.6 --- Changelog 7 Feb 2009 22:54:22 -0000 1.1.2.5 +++ Changelog 7 Feb 2009 23:05:42 -0000 1.1.2.6 @@ -1,5 +1,5 @@ 2.0.0 -Released: +Released: 02/07/09 ph...@ip... - Add support for PGP/Mime, make it default - Significant improvement to error checking and handling of gpg calls @@ -16,6 +16,7 @@ - Only import pexpect if we need it - Add support for STARTTLS and SMTPAUTH when sending email - Guard main() in an if __name__ == '__main__' to allow pydoc to work on pius +- Added a spec file 1.7 Released: 02/06/09 |
|
From: Phil D. <ja...@us...> - 2009-02-07 22:54:26
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv17572 Modified Files: Tag: pius_2_x_branch Changelog pius Log Message: - Guard main() in an if __name__ == '__main__' to allow pydoc to work on pius - Fix some > 80 lines - Add a comment about lint. Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.7.2.4 retrieving revision 1.7.2.5 diff -u -d -r1.7.2.4 -r1.7.2.5 --- pius 7 Feb 2009 22:35:53 -0000 1.7.2.4 +++ pius 7 Feb 2009 22:54:22 -0000 1.7.2.5 @@ -11,6 +11,10 @@ # modify it under the terms of the GNU General Public License as # published by the Free Software Foundation, version 2. # +# Note that we only import pexpect if -i is specified. In order to do this +# in a relatively clean way (if you just import it it will only be local), we +# use a trick that pylint will complain about. I'm quite alright with that. +# # TODO: # - Offer ability to "pick up where we left off" # @@ -258,6 +262,7 @@ self.mail_pass = getpass.getpass('Please enter your mail server password: ') def verify_mail_pass(self): + '''Verify the password we got works for SMTPAUTH.''' smtp = smtplib.SMTP(self.mail_host, self.mail_port) # NOTE WELL: SECURITY IMPORTANT NOTE! # In python 2.6 if you attempt to starttls() and the server doesn't @@ -961,8 +966,9 @@ if self.mail_tls: # NOTE WELL: SECURITY IMPORTANT NOTE! # In python 2.6 if you attempt to starttls() and the server doesn't - # understand an exception is raised. However before that, it just carried on - # and one could attempt to auth over a plain-text session. This is BAD! + # understand an exception is raised. However before that, it just + # carried on # and one could attempt to auth over a plain-text session. + # This is BAD! # # So, in order be secure on older pythons we ehlo() and then check the # response before attempting startls. @@ -1231,8 +1237,8 @@ signer.get_mail_pass() try: if not signer.verify_mail_pass(): - print ('Sorry, cannot authenticate to %s as %s with that passwword, try' - ' again.' % (signer.mail_host, signer.mail_user)) + print ('Sorry, cannot authenticate to %s as %s with that passwword,' + ' try again.' % (signer.mail_host, signer.mail_user)) else: break except MailSendError, msg: @@ -1257,4 +1263,5 @@ signer.cleanup() -main() +if __name__ == '__main__': + main() Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.1.2.4 retrieving revision 1.1.2.5 diff -u -d -r1.1.2.4 -r1.1.2.5 --- Changelog 7 Feb 2009 22:35:53 -0000 1.1.2.4 +++ Changelog 7 Feb 2009 22:54:22 -0000 1.1.2.5 @@ -15,9 +15,10 @@ - Move import of keyring to end - Only import pexpect if we need it - Add support for STARTTLS and SMTPAUTH when sending email +- Guard main() in an if __name__ == '__main__' to allow pydoc to work on pius 1.7 -Released: +Released: 02/06/09 ph...@ip... - Adjust regex for email address to be much less restrictive |
|
From: Phil D. <ja...@us...> - 2009-02-07 22:35:57
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv5948 Modified Files: Tag: pius_2_x_branch Changelog pius Log Message: - Add support for STARTTLS and SMTPAUTH when sending email - Some various lint fixes - A code cleanups Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.7.2.3 retrieving revision 1.7.2.4 diff -u -d -r1.7.2.3 -r1.7.2.4 --- pius 7 Feb 2009 12:35:14 -0000 1.7.2.3 +++ pius 7 Feb 2009 22:35:53 -0000 1.7.2.4 @@ -1,4 +1,6 @@ #!/usr/bin/python +"""A utility to sign all UIDs on a list of PGP keys and PGP/Mime encrypt-email +them to the respective emails.""" # vim:shiftwidth=2:tabstop=2:expandtab:textwidth=80:softtabstop=2:ai: @@ -11,7 +13,6 @@ # # TODO: # - Offer ability to "pick up where we left off" -# - Add TLS/auth support to SMTP # from email import MIMEBase @@ -27,10 +28,9 @@ import socket import subprocess import sys -import time VERSION = '2.0.0-BETA' -debug_on = False +DEBUG_ON = False MODE_INTERACTIVE = 0 MODE_CACHE_PASSPHRASE = 1 @@ -95,7 +95,7 @@ def debug(line): '''Print a line, if debug is on, preceeded with DEBUG:.''' - if debug_on: + if DEBUG_ON: print 'DEBUG:', line def print_default_email(no_mime): @@ -113,26 +113,32 @@ '''An exception for when Agent sucks.''' pass + class PassphraseError(Exception): '''An exception for when a 'good' cached passphrase didn't work.''' pass + class EncryptionKeyError(Exception): '''An exception for when a key can't encrypt (no encryption subkey).''' pass + class EncryptionUnknownError(Exception): '''An exception for NOT the above. Should never happen.''' pass + class GpgUnknownError(Exception): '''An exception for NOT the above. Should never happen.''' pass + class MailSendError(Exception): '''An exception for for NOT the above. Should never happen.''' pass + class uids_signer(object): '''Main class for signing UIDs.''' @@ -156,11 +162,11 @@ def __init__(self, signer, mode, keyring, gpg_path, tmpdir, outdir, encrypt_outfiles, sign_level, mail, verbose, mail_text, - override_email, mail_host, mail_port, no_pgp_mime): + mail_override, mail_host, mail_port, mail_no_pgp_mime, mail_user, + mail_tls): self.mode = mode self.signer = signer self.keyring = keyring - self.passphrase_confirmed = False self.gpg = gpg_path self.tmpdir = tmpdir self.outdir = outdir @@ -168,30 +174,36 @@ self.sign_level = sign_level self.mail = mail self.mail_text = mail_text - self.verbose = verbose - self.override_email = override_email + self.mail_override = mail_override self.mail_host = mail_host self.mail_port = mail_port - self.no_pgp_mime = no_pgp_mime + self.mail_no_pgp_mime = mail_no_pgp_mime + self.mail_tls = mail_tls + self.mail_user = mail_user + self.mail_pass = '' + self.verbose = verbose + self.passphrase = '' self.tmp_keyring = '%s/%s' % (self.tmpdir, uids_signer.TMP_KEYRING_FILE) self.gpg_quiet_opts = '-q --no-tty --no-auto-check-trustdb --batch' self.gpg_fd_opts = '--command-fd 0 --passphrase-fd 0 --status-fd 1' - def _outfile_path(self, file): - return '%s/%s' % (self.outdir, file) + def _outfile_path(self, ofile): + '''Internal function to take a filename and put it in self.outdir.''' + return '%s/%s' % (self.outdir, ofile) - def _tmpfile_path(self, file): - return '%s/%s' % (self.tmpdir, file) + def _tmpfile_path(self, tfile): + '''Internal function to take a filename and put it in self.tmpdir.''' + return '%s/%s' % (self.tmpdir, tfile) def cleanup(self): '''Cleanup all our temp files.''' self._clean_files([self.tmp_keyring, ('%s~' % self.tmp_keyring)]) - def _clean_files(self, list): + def _clean_files(self, flist): '''Delete a list of files.''' - for file in list: - if os.path.exists(file): - os.unlink(file) + for cfile in flist: + if os.path.exists(cfile): + os.unlink(cfile) def get_all_keyids(self): '''Given a keyring, get all the KeyIDs from it.''' @@ -205,11 +217,11 @@ for line in gpg.readlines(): if not pub_re.search(line): continue - id = line.split(':')[4] + uid = line.split(':')[4] # get the shirt version - id = id[8:16] - debug('Got id %s' % id) - keyids.append(id) + uid = uid[8:16] + debug('Got id %s' % uid) + keyids.append(uid) gpg.close() return keyids @@ -232,15 +244,46 @@ print 'WARNING: Keyid %s not valid, skipping.' % key return False - a = raw_input('Have you verified this user/key? (y/N/q) ') + ans = raw_input('Have you verified this user/key? (y/N/q) ') print - if a in ('y', 'Y', 'yes', 'Yes', 'YES'): - return True; - elif a in ('q', 'Q'): + if ans in ('y', 'Y', 'yes', 'Yes', 'YES'): + return True + elif ans in ('q', 'Q'): print 'Dying at user request' sys.exit(1) return False + def get_mail_pass(self): + '''Prompt the user for their passphrase.''' + self.mail_pass = getpass.getpass('Please enter your mail server password: ') + + def verify_mail_pass(self): + smtp = smtplib.SMTP(self.mail_host, self.mail_port) + # NOTE WELL: SECURITY IMPORTANT NOTE! + # In python 2.6 if you attempt to starttls() and the server doesn't + # understand an exception is raised. However before that, it just carried on + # and one could attempt to auth over a plain-text session. This is BAD! + # + # So, in order be secure on older pythons we ehlo() and then check the + # response before attempting startls. + try: + smtp.ehlo() + if not smtp.has_extn('STARTTLS'): + # Emulate 2.6 behavior + raise smtplib.SMTPException('Server does not support STARTTLS') + smtp.starttls() + # must ehlo after startls + smtp.ehlo() + smtp.login(self.mail_user, self.mail_pass) + except smtplib.SMTPAuthenticationError: + return False + except smtplib.SMTPException, msg: + raise MailSendError, msg + finally: + smtp.quit() + + return True + def get_passphrase(self): '''Prompt the user for their passphrase.''' self.passphrase = getpass.getpass('Please enter your PGP passphrase: ') @@ -290,7 +333,6 @@ tfile.close() self._clean_files([filename, filename_enc, filename_dec]) if line == magic_string: - self.passphrase_confirmed = True return True debug('File does not contain magic string') return False @@ -330,9 +372,9 @@ continue status = fields[1] - id = fields[9] + uid = fields[9] - debug('Got UID %s with status %s' % (id, status)) + debug('Got UID %s with status %s' % (uid, status)) # If we can we capture an email address is saved for # emailing off signed keys (not yet implemented), and @@ -342,22 +384,22 @@ # id and blank out the email. # # For the normal case (have email), we'll be storing each email twice - # but that's OK since it means that email is *always* a vlaid email or + # but that's OK since it means that email is *always* a valid email or # None and id is *always* a valid identifier - m = re.search('.* <(.*)>', id) - if m: - email = m.group(1) + match = re.search('.* <(.*)>', uid) + if match: + email = match.group(1) debug('got email %s' % email) filename = re.sub('@', '_at_', email) filename = '%s__%s' % (key, filename) - id = email + uid = email else: # but if it doesn't have an email, do the right thing email = None debug('no email') - id = re.sub(' ', '_', id) - id = re.sub('\'', '', id) - filename = '%s__%s' % (key, id) + uid = re.sub(' ', '_', uid) + uid = re.sub('\'', '', uid) + filename = '%s__%s' % (key, uid) if filename in unique_files: debug('Filename is a duplicate') @@ -379,7 +421,7 @@ unique_files.append(filename) filename += '.asc' uids.append({'email': email, 'file': filename, 'status': status, - 'id': id}) + 'id': uid}) debug('quitting') # sometimes it wants a save here. I don't know why. We can quit and check @@ -401,7 +443,7 @@ '''Encrypt the file we exported the signed UID to.''' (base, ext) = os.path.splitext(filename) path = self._outfile_path(filename) - enc_file = '%s_ENCRYPTED.asc' % base + enc_file = '%s_ENCRYPTED%s' % (base, ext) enc_path = self._outfile_path(enc_file) if os.path.exists(enc_path): os.unlink(enc_path) @@ -524,10 +566,10 @@ gpg.expect(re.compile('Really sign.*')) debug('Confirming signing') gpg.sendline('y') - '''Tell the user how to get out of this, and then drop them into the gpg - shell.''' - print ' Passing you to gpg for passprhase.' - print ' Hit ^] after succesfully typing in your passphrase' + # Tell the user how to get out of this, and then drop them into the gpg + # shell. + print '\n\nPassing you to gpg for passphrase.' + print 'Hit ^] after succesfully typing in your passphrase' gpg.interact() # When we return, we have a Command> prompt that w can't # 'expect'... or at least if the user did it right @@ -721,9 +763,8 @@ continue self.send_mail(uids[index]['email'], key, uids[index]) sys.stdout.write(', mailed') - except MailSendError: - print '\nFailed to connect to mail server (%s:%s)' % (self.mail_host, - self.mail_port) + except MailSendError, msg: + print '\nFailed to send mail: %s' % (msg) # add a newline to all the sys.stdout.write()s print '' @@ -741,7 +782,7 @@ (self.gpg, self.gpg_quiet_opts, self.keyring)) self._run_and_check_status(cmd) - def encrypt_and_sign_file(self, input, output, keyid): + def encrypt_and_sign_file(self, infile, outfile, keyid): '''Encrypt and sign a file. Used for PGP/Mime email generation.''' @@ -751,7 +792,7 @@ keyring = '--no-default-keyring --keyring %s' % self.tmp_keyring cmd = ('%s %s %s %s %s --always-trust -aes -r %s -r %s --output %s %s' % (self.gpg, self.gpg_quiet_opts, self.gpg_fd_opts, keyring, - agent, keyid, self.signer, output, input)) + agent, keyid, self.signer, outfile, infile)) debug(cmd) gpg = subprocess.Popen(cmd, shell=True, stdin=subprocess.PIPE, @@ -809,12 +850,12 @@ if self.mail_text: return open(self.mail_text, 'r').read() % interpolation_dict else: - if self.no_pgp_mime: + if self.mail_no_pgp_mime: return DEFAULT_NON_MIME_EMAIL_TEXT % interpolation_dict else: return DEFAULT_MIME_EMAIL_TEXT % interpolation_dict - def generate_pgp_mime_email(self, email, keyid, filename): + def _generate_pgp_mime_email(self, email, keyid, filename): '''Generates the PGP/Mime body. The message headers MUST be added by the caller.''' @@ -881,7 +922,7 @@ self._clean_files([tmpfile, signed_tmpfile]) return msg - def generate_non_pgp_mime_email(self, email, keyid, filename): + def _generate_non_pgp_mime_email(self, email, keyid, filename): '''Send the encrypted uid off to the user.''' msg = MIMEMultipart.MIMEMultipart() msg.epilogue = '' @@ -899,16 +940,17 @@ def send_mail(self, email, keyid, uid_data): '''Send the encrypted uid off to the user.''' - if self.no_pgp_mime: - msg = self.generate_non_pgp_mime_email(email, keyid, uid_data['enc_file']) + if self.mail_no_pgp_mime: + msg = self._generate_non_pgp_mime_email(email, keyid, + uid_data['enc_file']) else: - msg = self.generate_pgp_mime_email(email, keyid, uid_data['file']) + msg = self._generate_pgp_mime_email(email, keyid, uid_data['file']) # We don't duplicate the header logic in the sub functions, we # do that here msg['From'] = self.mail - if self.override_email: - msg['To'] = self.override_email + if self.mail_override: + msg['To'] = self.mail_override else: msg['To'] = email msg['Date'] = formatdate(localtime=True) @@ -916,14 +958,34 @@ try: smtp = smtplib.SMTP(self.mail_host, self.mail_port) - if self.override_email: - env_to = self.override_email + if self.mail_tls: + # NOTE WELL: SECURITY IMPORTANT NOTE! + # In python 2.6 if you attempt to starttls() and the server doesn't + # understand an exception is raised. However before that, it just carried on + # and one could attempt to auth over a plain-text session. This is BAD! + # + # So, in order be secure on older pythons we ehlo() and then check the + # response before attempting startls. + smtp.ehlo() + if not smtp.has_extn('STARTTLS'): + # Emulate 2.6 behavior + raise smtplib.SMTPException('Server does not support STARTTLS') + smtp.starttls() + # must re-ehlo after STARTTLS + smtp.ehlo() + # Don't want to send auth information unless we're TLS'd + if self.mail_user: + smtp.login(self.mail_user, self.mail_pass) + if self.mail_override: + env_to = self.mail_override else: # BCC the user... env_to = [email, self.mail] smtp.sendmail(self.mail, env_to, msg.as_string()) smtp.quit() + except smtplib.SMTPException, msg: + raise MailSendError, msg except socket.error, msg: raise MailSendError, msg @@ -935,27 +997,32 @@ # required argument. This is an ugly hack around that. # def check_not_another_opt(option, opt, value): - m = re.search('^\-', value) - if m: + '''Ensure argument to an option isn't another option.''' + match = re.search('^\-', value) + if match: raise OptionValueError('Option %s: Value %s looks like another option' ' instead of the required argument' % (opt, value)) return value def check_email(option, opt, value): - m = re.match('.+@.+\..+', value) - if not m: + '''Ensure argument seems like an email address.''' + match = re.match('.+@.+\..+', value) + if not match: raise OptionValueError('Option %s: Value %s does not appear like a well' ' formed email address' % (opt, value)) return value def check_keyid(option, opt, value): - m = re.match('[0-9a-fA-Fx]', value) - if not m: + '''Ensure argument seems like a keyid.''' + match = re.match('[0-9a-fA-Fx]', value) + if not match: raise OptionValueError('Option %s: Value %s does not appear to be a KeyID' % (opt, value)) return value + class MyOption(Option): + '''Our own option class.''' TYPES = Option.TYPES + ('not_another_opt', 'email', 'keyid') TYPE_CHECKER = copy(Option.TYPE_CHECKER) TYPE_CHECKER.update({'not_another_opt': check_not_another_opt, @@ -965,11 +1032,12 @@ def check_options(parser, options, args): - global debug_on + '''Given the parsed options, sanity check them.''' + global DEBUG_ON if options.debug == True: print 'Setting debug' - debug_on = True; + DEBUG_ON = True if not options.signer: parser.error('You must specify a keyid to sign with.') @@ -983,7 +1051,7 @@ if not args: parser.error('Keyid required') elif not options.keyring: - parser.error('The -A options requires the -r option') + parser.error('The -A options requires the -r option') if options.mode == MODE_INTERACTIVE: try: @@ -993,21 +1061,26 @@ parser.error('You chose interactive mode but do not have the pexpect' ' module installed.') - if options.mail and options.no_pgp_mime and not options.encrypt_outfiles: + if options.mail and options.mail_no_pgp_mime and not options.encrypt_outfiles: print 'NOTE: -O and -m are present, turning on -e' options.encrypt_outfiles = True + if options.mail_user and not options.mail_tls: + print 'NOTE: -u is present, turning on -S.' + options.mail_tls = True + if options.mail_text and not options.mail: parser.error('ERROR: -M requires -m') - for dir in (options.tmp_dir, options.out_dir): - if os.path.exists(dir) and not os.path.isdir(dir): + for mydir in (options.tmp_dir, options.out_dir): + if os.path.exists(mydir) and not os.path.isdir(mydir): parser.error('%s exists but isn\'t a directory. It must not exist or be\n' - 'a directory.' % dir) - if not os.path.exists(dir): - os.mkdir(dir, 0700) + 'a directory.' % mydir) + if not os.path.exists(mydir): + os.mkdir(mydir, 0700) def main(): + """Main.""" usage = ('%prog [options] -s <signer_keyid> <keyid> [<keyid> ...]\n' ' %prog [options] -A -r <keyring_path> -s <signer_keyid>') parser = OptionParser(usage=usage, version='%%prog %s' % VERSION, @@ -1019,7 +1092,7 @@ keyring=DEFAULT_KEYRING, mail_host=DEFAULT_MAIL_HOST, mail_port=DEFAULT_MAIL_PORT, - sign_level='3') + sign_level=3) parser.add_option('-a', '--use-agent', action='store_const', const=MODE_AGENT, dest='mode', help='Use pgp-agent instead of letting gpg prompt the' @@ -1034,8 +1107,9 @@ help='Encrypt output files with respective keys.') parser.add_option('-d', '--debug', action='store_true', dest='debug', help='Enable debugging output.') - parser.add_option('-H', '--mail_host', dest='mail_host', metavar='HOSTNAME', - nargs=1, help='Hostname of SMTP server. [default: %default]') + parser.add_option('-H', '--mail-host', dest='mail_host', metavar='HOSTNAME', + nargs=1, type='not_another_opt', + help='Hostname of SMTP server. [default: %default]') parser.add_option('-i', '--interactive', action='store_const', const=MODE_INTERACTIVE, dest='mode', help='Use the pexpect' ' module for signing and drop to the gpg shell for' @@ -1060,7 +1134,7 @@ ' sending out emails instead of the default text.' ' To see the default text use' ' --print-default-email. Requires -m.') - parser.add_option('-n', '--override-email', dest='override_email', + parser.add_option('-n', '--override-email', dest='mail_override', metavar='EMAIL', nargs=1, type='email', help='Rather than send to the user, send to this address.' ' Mostly useful for debugging.') @@ -1068,14 +1142,14 @@ nargs=1, type='not_another_opt', help='Directory to put signed keys in. [default: %default]') parser.add_option('-O', '--no-pgp-mime', action='store_true', - dest='no_pgp_mime', + dest='mail_no_pgp_mime', help='Do not use PGP/Mime when sending email.') - parser.add_option('-p', '--cache_passphrase', action='store_const', + parser.add_option('-p', '--cache-passphrase', action='store_const', const=MODE_CACHE_PASSPHRASE, dest='mode', help='Cache private key passphrase in memory and provide' ' it to gpg instead of letting gpg prompt the user' ' for every UID. [default: true]') - parser.add_option('-P', '--mail_port', dest='mail_port', metavar='PORT', + parser.add_option('-P', '--mail-port', dest='mail_port', metavar='PORT', nargs=1, type='int', help='Port of SMTP server. [default: %default]') parser.add_option('-r', '--keyring', dest='keyring', metavar='KEYRING', @@ -1086,12 +1160,19 @@ parser.add_option('-s', '--signer', dest='signer', nargs=1, type='keyid', help='The keyid to sign with (required).') + parser.add_option('-S', '--mail-tls', action='store_true', dest='mail_tls', + help='Use STARTTLS when talking to the SMTP server.') parser.add_option('-t', '--tmp-dir', dest='tmp_dir', nargs=1, type='not_another_opt', help='Directory to put temporary stuff in. [default:' ' %default]') parser.add_option('-T', '--print-default-email', dest='print_default_email', action='store_true', help='Print the default email.') + parser.add_option('-u', '--mail-user', dest='mail_user', metavar='USER', + type='not_another_opt', nargs=1, + help='Authenticate to the SMTP server, and use username' + ' USER. You will be prompted for the password. Implies' + ' -S.') parser.add_option('-v', '--verbose', dest='verbose', action='store_true', help='Be more verbose.') @@ -1101,7 +1182,7 @@ # The easy thing first... if options.print_default_email: - print_default_email(options.no_pgp_mime) + print_default_email(options.mail_no_pgp_mime) sys.exit(0) # Check input to make sure users want sane things @@ -1118,35 +1199,53 @@ options.mail = ans print - p = uids_signer(options.signer, options.mode, options.keyring, - options.gpg_path, options.tmp_dir, options.out_dir, - options.encrypt_outfiles, options.sign_level, options.mail, - options.verbose, options.mail_text, options.override_email, - options.mail_host, options.mail_port, options.no_pgp_mime) + signer = uids_signer(options.signer, options.mode, options.keyring, + options.gpg_path, options.tmp_dir, options.out_dir, + options.encrypt_outfiles, options.sign_level, + options.mail, options.verbose, options.mail_text, + options.mail_override, options.mail_host, + options.mail_port, options.mail_no_pgp_mime, + options.mail_user, options.mail_tls) if options.all_keys: - list = p.get_all_keyids() - if len(list) == 0: + key_list = signer.get_all_keyids() + if len(key_list) == 0: print "Failed to find keys on this keyring\n" sys.exit(1) if args: - list.extend(args) + key_list.extend(args) else: - list = args + key_list = args if options.mode == MODE_CACHE_PASSPHRASE: print ('NOTE: See the README about security implications.') - while not p.passphrase_confirmed: - p.get_passphrase() - if not p.verify_passphrase(): + while True: + signer.get_passphrase() + if not signer.verify_passphrase(): print 'Sorry, cannot unlock the key with that passphrase, try again.' + else: + break + + if options.mail_user: + while True: + signer.get_mail_pass() + try: + if not signer.verify_mail_pass(): + print ('Sorry, cannot authenticate to %s as %s with that passwword, try' + ' again.' % (signer.mail_host, signer.mail_user)) + else: + break + except MailSendError, msg: + print ('There was a problem talking to the mail server (%s): %s' + % (signer.mail_host, msg)) + sys.exit(1) # The actual signing - for key in list: - if not p.check_fingerprint(key): + for key in key_list: + if not signer.check_fingerprint(key): continue print 'Signing all UIDs on key %s' % key - p.sign_all_uids(key) + signer.sign_all_uids(key) # If the user asked, import the keys if options.import_keyring: @@ -1154,8 +1253,8 @@ print ('WARNING: Ignoring -i: Either -r wasn\'t specified, or it was' ' the same as the default keyring.') else: - p.import_unsigned_keys() + signer.import_unsigned_keys() - p.cleanup() + signer.cleanup() main() Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.1.2.3 retrieving revision 1.1.2.4 diff -u -d -r1.1.2.3 -r1.1.2.4 --- Changelog 7 Feb 2009 12:35:14 -0000 1.1.2.3 +++ Changelog 7 Feb 2009 22:35:53 -0000 1.1.2.4 @@ -14,6 +14,7 @@ - Add prompt about sending email if user didn't specify - Move import of keyring to end - Only import pexpect if we need it +- Add support for STARTTLS and SMTPAUTH when sending email 1.7 Released: |
|
From: Phil D. <ja...@us...> - 2009-02-07 12:35:20
|
Update of /cvsroot/pgpius/pius In directory ddv4jf1.ch3.sourceforge.com:/tmp/cvs-serv28901 Modified Files: Tag: pius_2_x_branch pius Changelog Log Message: pius: - Don't import pexpect if we don't need it. Signed-off-by: Phil Dibowitz <ph...@ip...> Index: pius =================================================================== RCS file: /cvsroot/pgpius/pius/pius,v retrieving revision 1.7.2.2 retrieving revision 1.7.2.3 diff -u -d -r1.7.2.2 -r1.7.2.3 --- pius 7 Feb 2009 00:49:10 -0000 1.7.2.2 +++ pius 7 Feb 2009 12:35:14 -0000 1.7.2.3 @@ -22,7 +22,6 @@ from optparse import OptionParser, Option, OptionValueError import getpass import os -import pexpect import re import smtplib import socket @@ -496,16 +495,6 @@ self.tmp_keyring, path)) self._run_and_check_status(cmd) - def sign_with_interact(self, gpg): - '''Tell the user how to get out of this, and then drop them into the gpg - shell.''' - print ' Passing you to gpg for passprhase.' - print ' Hit ^] after succesfully typing in your passphrase' - gpg.interact() - # When we return, we have a Command> prompt that w can't - # 'expect'... or at least if the user did it right - print '' - # # NOTE: # This is a sucky hack. I may just completely delete it one day. The only @@ -535,11 +524,16 @@ gpg.expect(re.compile('Really sign.*')) debug('Confirming signing') gpg.sendline('y') - self.sign_with_interact(gpg) + '''Tell the user how to get out of this, and then drop them into the gpg + shell.''' + print ' Passing you to gpg for passprhase.' + print ' Hit ^] after succesfully typing in your passphrase' + gpg.interact() + # When we return, we have a Command> prompt that w can't + # 'expect'... or at least if the user did it right + print '' # Unselect this UID debug('unselecting uid') - #gpg.sendline(str(index)) - #gpg.expect('Command> ') debug('Saving key') gpg.sendline('save') #gpg.close() @@ -991,6 +985,14 @@ elif not options.keyring: parser.error('The -A options requires the -r option') + if options.mode == MODE_INTERACTIVE: + try: + global pexpect + import pexpect + except ImportError: + parser.error('You chose interactive mode but do not have the pexpect' + ' module installed.') + if options.mail and options.no_pgp_mime and not options.encrypt_outfiles: print 'NOTE: -O and -m are present, turning on -e' options.encrypt_outfiles = True Index: Changelog =================================================================== RCS file: /cvsroot/pgpius/pius/Changelog,v retrieving revision 1.1.2.2 retrieving revision 1.1.2.3 diff -u -d -r1.1.2.2 -r1.1.2.3 --- Changelog 7 Feb 2009 00:49:10 -0000 1.1.2.2 +++ Changelog 7 Feb 2009 12:35:14 -0000 1.1.2.3 @@ -13,6 +13,7 @@ - Make cache_passphrase mode default - Add prompt about sending email if user didn't specify - Move import of keyring to end +- Only import pexpect if we need it 1.7 Released: |