File: gpg-pw.py

package info (click to toggle)
offlineimap3 0.0~git20210225.1e7ef9e%2Bdfsg-4
  • links: PTS, VCS
  • area: main
  • in suites: bullseye
  • size: 1,328 kB
  • sloc: python: 7,974; sh: 548; makefile: 81
file content (99 lines) | stat: -rw-r--r-- 2,886 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
#!/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]))