#!/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 # 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])