offlineimap/contrib/store-pw-with-gpg/gpg-pw.py

100 lines
2.8 KiB
Python

#!/usr/bin/python
# Originally taken from: http://stevelosh.com/blog/2012/10/the-homely-mutt/
# by Steve Losh
# Modified by Lorenzo Grespan on Jan, 2014
import re
import subprocess
from sys import argv
import logging
from os.path import expanduser
import unittest
import os
import sys
logging.basicConfig(level=logging.INFO)
DEFAULT_PASSWORDS_FILE = os.path.join(
os.path.expanduser('~/Mail'),
'passwords.gpg')
def get_keychain_pass(account=None, server=None):
'''Mac OSX keychain password extraction'''
params = {
'security': '/usr/bin/security',
'command': 'find-internet-password',
'account': account,
'server': server,
'keychain': expanduser('~') + '/Library/Keychains/login.keychain',
}
command = ("%(security)s -v %(command)s"
" -g -a %(account)s -s %(server)s %(keychain)s" % params)
output = subprocess.check_output(
command, shell=True, stderr=subprocess.STDOUT)
outtext = [l for l in output.splitlines()
if l.startswith('password: ')][0]
return find_password(outtext)
def find_password(text):
'''Helper method for osx password extraction'''
# a non-capturing group
r = re.match(r'password: (?:0x[A-F0-9]+ )?"(.*)"', text)
if r:
return r.group(1)
else:
logging.warn("Not found")
return None
def get_gpg_pass(account, storage):
'''GPG method'''
command = ("gpg", "-d", storage)
# get attention
print '\a' # BEL
output = subprocess.check_output(command)
# p = subprocess.Popen(command, stdout=subprocess.PIPE)
# output, err = p.communicate()
for line in output.split('\n'):
r = re.match(r'{} ([a-zA-Z0-9]+)'.format(account), line)
if r:
return r.group(1)
return None
def get_pass(account=None, server=None, passwd_file=None):
'''Main method'''
if not passwd_file:
storage = DEFAULT_PASSWORDS_FILE
else:
storage = os.path.join(
os.path.expanduser('~/Mail'),
passwd_file)
if os.path.exists('/usr/bin/security'):
return get_keychain_pass(account, server)
if os.path.exists(storage):
logging.info("Using {}".format(storage))
return get_gpg_pass(account, storage)
else:
logging.warn("No password file found")
sys.exit(1)
return None
# test with: python -m unittest <this module name>
# really basic tests.. nothing to see. move along
class Tester(unittest.TestCase):
def testMatchSimple(self):
text = 'password: "exampleonetimepass "'
self.assertTrue(find_password(text))
def testMatchComplex(self):
text = r'password: 0x74676D62646D736B646970766C66696B0A "anotherexamplepass\012"'
self.assertTrue(find_password(text))
if __name__ == "__main__":
print get_pass(argv[1], argv[2], argv[3])