gpg-pw.py 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. #!/usr/bin/python
  2. # Originally taken from: http://stevelosh.com/blog/2012/10/the-homely-mutt/
  3. # by Steve Losh
  4. # Modified by Lorenzo Grespan on Jan, 2014
  5. import re
  6. import subprocess
  7. from sys import argv
  8. import logging
  9. from os.path import expanduser
  10. import unittest
  11. import os
  12. import sys
  13. logging.basicConfig(level=logging.INFO)
  14. DEFAULT_PASSWORDS_FILE = os.path.join(
  15. os.path.expanduser('~/Mail'),
  16. 'passwords.gpg')
  17. def get_keychain_pass(account=None, server=None):
  18. '''Mac OSX keychain password extraction'''
  19. params = {
  20. 'security': '/usr/bin/security',
  21. 'command': 'find-internet-password',
  22. 'account': account,
  23. 'server': server,
  24. 'keychain': expanduser('~') + '/Library/Keychains/login.keychain',
  25. }
  26. command = ("%(security)s -v %(command)s"
  27. " -g -a %(account)s -s %(server)s %(keychain)s" % params)
  28. output = subprocess.check_output(
  29. command, shell=True, stderr=subprocess.STDOUT)
  30. outtext = [l for l in output.splitlines()
  31. if l.startswith('password: ')][0]
  32. return find_password(outtext)
  33. def find_password(text):
  34. '''Helper method for osx password extraction'''
  35. # a non-capturing group
  36. r = re.match(r'password: (?:0x[A-F0-9]+ )?"(.*)"', text)
  37. if r:
  38. return r.group(1)
  39. else:
  40. logging.warn("Not found")
  41. return None
  42. def get_gpg_pass(account, storage):
  43. '''GPG method'''
  44. command = ("gpg", "-d", storage)
  45. # get attention
  46. print('\a') # BEL
  47. output = subprocess.check_output(command)
  48. # p = subprocess.Popen(command, stdout=subprocess.PIPE)
  49. # output, err = p.communicate()
  50. for line in output.split('\n'):
  51. r = re.match(r'{} ([a-zA-Z0-9]+)'.format(account), line)
  52. if r:
  53. return r.group(1)
  54. return None
  55. def get_pass(account=None, server=None, passwd_file=None):
  56. '''Main method'''
  57. if not passwd_file:
  58. storage = DEFAULT_PASSWORDS_FILE
  59. else:
  60. storage = os.path.join(
  61. os.path.expanduser('~/Mail'),
  62. passwd_file)
  63. if os.path.exists('/usr/bin/security'):
  64. return get_keychain_pass(account, server)
  65. if os.path.exists(storage):
  66. logging.info("Using {}".format(storage))
  67. return get_gpg_pass(account, storage)
  68. else:
  69. logging.warn("No password file found")
  70. sys.exit(1)
  71. return None
  72. # test with: python -m unittest <this module name>
  73. # really basic tests.. nothing to see. move along
  74. class Tester(unittest.TestCase):
  75. def testMatchSimple(self):
  76. text = 'password: "exampleonetimepass "'
  77. self.assertTrue(find_password(text))
  78. def testMatchComplex(self):
  79. text = r'password: 0x74676D62646D736B646970766C66696B0A "anotherexamplepass\012"'
  80. self.assertTrue(find_password(text))
  81. if __name__ == "__main__":
  82. print(get_pass(argv[1], argv[2], argv[3]))