File: wotsap.py

package info (click to toggle)
pius 3.0.0-8
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 432 kB
  • sloc: python: 2,963; perl: 178; makefile: 2; sh: 1
file content (130 lines) | stat: -rw-r--r-- 4,486 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
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
# WIP: wotsap parser
import json
import os


# TODO: since the wotsap website is all fubar'd, I've hacked it up to read
# /tmp/report. You can generate this with 'wotsap >/tmp/report'
class PgpReport:
    """Class for retrieving and processing wotsap reports."""

    kURL = "http://webware.lysator.liu.se/jc/wotsap/wots/latest/keystatistics/"
    kDATAFILE = ".gpg_report"
    kSIGNED = "SIGNED"
    kNOT_SIGNED = "NOTSIGNED"

    def __init__(self, keyid, clear_data, keyring=None):
        self.keyid = keyid
        self.need_upload = []
        self.need_to_sign = []
        self.might_need_to_sign = []
        self.need_sigs_from = []
        self.sign_data = {}
        self.datafile = "%s/%s" % (os.path.expanduser("~"), self.kDATAFILE)
        self.keys = []
        if keyring:
            self.keys = self._get_keyring_keyids(keyring)

        self._get_wotsap_report()
        if clear_data:
            self.clear_datafile()
        else:
            self._read_datafile()

    def get_need_to_sign(self):
        """Accessor for need_to_sign."""
        return self.need_to_sign

    def get_need_upload(self):
        """Accessor for need_upload."""
        return self.need_upload

    def clear_datafile(self):
        os.remove(self.datafile)

    def _read_datafile(self):
        """Read our data file."""
        if not os.path.exists(self.datafile):
            return
        f = open(self.datafile, "r")
        d = ""
        for l in f:
            d += l
        self.sign_data = json.read(d)
        f.close()

    def _write_datafile(self):
        """Write our data file."""
        f = open(self.datafile, "w")
        f.write(json.write(self.sign_data))
        f.close()

    def _get_wotsap_report(self):
        """Get wotsap report for a key."""
        # url = '%s0x%s.txt' % (self.kURL, self.keyid)
        # report = urllib2.urlopen(url)
        # self._parse_wotsap_report(report)
        # report.close()
        f = open("/tmp/report", "r")
        self._parse_wotsap_report(f)
        f.close()

    def _parse_wotsap_report(self, report):
        """Parse the wotsap report."""
        for line in report:
            if line.startswith("This key is signed by, excluding"):
                line = report.next()
                while not line.startswith("Total:"):
                    self.might_need_to_sign.append(line.strip().split()[1])
                    line = report.next()

            if line.startswith("Keys signed by this key, excluding"):
                line = report.next()
                while not line.startswith("Total:"):
                    self.need_sigs_from.append(line.strip().split()[1])
                    line = report.next()

    def check_for_upload_needed(self):
        """Walk through keys without our sig and determine their status."""
        copy = []
        copy.extend(self.might_need_to_sign)
        for keyid in copy:
            if self.keys and keyid not in self.keys:
                continue
            if keyid in self.sign_data:
                if self.sign_data[keyid] == self.kSIGNED:
                    self.need_upload.append(keyid)
                    self.might_need_to_sign.remove(keyid)
                else:
                    self.need_to_sign.append(keyid)
                    self.might_need_to_sign.remove(keyid)
            else:
                signed = ""
                while signed not in ("y", "Y", "n", "N", "yes", "no"):
                    signed = input("Have you signed key %s? " % keyid)

                if signed in ("y", "Y", "yes"):
                    self.sign_data[keyid] = self.kSIGNED
                    self.need_upload.append(keyid)
                    self.might_need_to_sign.remove(keyid)
                else:
                    self.sign_data[keyid] = self.kNOT_SIGNED
                    self.need_to_sign.append(keyid)
                    self.might_need_to_sign.remove(keyid)
        if not self.keys:
            assert not self.might_need_to_sign
        self._write_datafile()

    def _get_keyring_keyids(self, keyring):
        """Get all the keyids off of a keyring."""
        keys = []
        gpg = os.popen(
            "gpg --fixed-list-mode --with-colons --no-default-keyring"
            " --keyring %r --fingerprint" % keyring
        )
        for line in gpg:
            if not line.startswith("fpr"):
                continue
            keys.append("0x%s" % line.split(":")[9][-8:])
        gpg.close()
        return keys