1
2
3
4
5 from gozerbot.config import config
6 from gozerbot.datadir import datadir
7 from gozerbot.generic import gozerpopen, rlog
8 import os
9 import re
10 import tempfile
11
14
17
20
22 ''' Wrapper for the GNU Privacy Guard. '''
23
24 re_verify = re.compile('^\[GNUPG:\] VALIDSIG ([0-9A-F]+)', re.I | re.M)
25 re_import = re.compile('^\[GNUPG:\] IMPORT_OK \d ([0-9A-F]+)', re.I | re.M)
26 re_pubkey = re.compile('^\[GNUPG:\] NO_PUBKEY ([0-9A-F]+)', re.I | re.M)
27
29 self.homedir = os.path.join(datadir, 'pgp')
30 if not os.path.exists(self.homedir):
31 rlog(5, 'pgp', 'creating directory %s' % self.homedir)
32 os.mkdir(self.homedir)
33 if hasattr(config, 'pgpkeyserver'):
34 self.keyserver = config.pgpkeyserver
35 else:
36 self.keyserver = 'pgp.mit.edu'
37
38 os.chmod(self.homedir, 0700)
39 rlog(5, 'pgp', 'will be using public key server %s' % self.keyserver)
40
42 (data, returncode) = self._gpg('--fingerprint', keyid)
43 return returncode == 0
44
46 tmp = self._tmp(data)
47 (data, returncode) = self._gpg('--import', tmp)
48 os.unlink(tmp)
49 test_import = self.re_import.search(data)
50 if test_import:
51 fingerprint = test_import.group(1)
52 return fingerprint
53 return None
54
56 (data, returncode) = self._gpg('--keyserver ', self.keyserver, \
57 '--recv-keys', fingerprint)
58 if returncode == 256:
59 raise NoGPGException()
60 return returncode == 0
61
63 if len(data) < 8:
64 return False
65 (_, returncode) = self._gpg('--yes', '--delete-keys', data)
66 if returncode == 256:
67 raise NoGPGException()
68 return returncode == 0
69
71 tmp = self._tmp(data)
72 (data, returncode) = self._gpg('--verify', tmp)
73 os.unlink(tmp)
74 if returncode == 256:
75 raise NoGPGException()
76 if returncode not in (None, 0, 512):
77 return False
78 test_pubkey = self.re_pubkey.search(data)
79 if test_pubkey:
80 raise PgpNoPubkeyException(test_pubkey.group(1))
81 test_verify = self.re_verify.search(data)
82 if test_verify:
83 return test_verify.group(1)
84
86 tmp1 = self._tmp(data)
87 tmp2 = self._tmp(signature)
88 (data, returncode) = self._gpg('--verify', tmp2, tmp1)
89 os.unlink(tmp2)
90 os.unlink(tmp1)
91 if returncode == 256:
92 raise NoGPGException()
93 if returncode not in (None, 0, 512):
94 return False
95 test_pubkey = self.re_pubkey.search(data)
96 if test_pubkey:
97 raise PgpNoPubkeyException(test_pubkey.group(1))
98 test_verify = self.re_verify.search(data)
99 if test_verify:
100 return test_verify.group(1)
101 return None
102
103 - def _gpg(self, *extra):
104 cmnd = ['gpg', '--homedir', self.homedir, '--batch', '--status-fd', '1']
105 cmnd += list(extra)
106 rlog(0, 'pgp', 'executing: %s' % ' '.join(cmnd))
107 try:
108 proces = gozerpopen(cmnd, [])
109 except OSError, ex:
110 raise NoGPGException
111 except Exception, ex:
112 rlog(0, 'pgp', 'error running "%s": %s' % (cmnd, str(ex)))
113 raise
114 data = proces.fromchild.read()
115 returncode = proces.close()
116 rlog(0, 'pgp', 'return code: %s, data: %s' % (returncode, data))
117 return (data, returncode)
118
119 - def _tmp(self, data):
120 fdid, tmp = tempfile.mkstemp()
121 fd = os.fdopen(fdid, 'w')
122 fd.write(data)
123 fd.close()
124 return tmp
125
126
127 gozerbot_pgp_keys = {
128
129 '5290D844CF600B6CA6AFF8952D6D437CC5C9C2B2': '''
130 -----BEGIN PGP PUBLIC KEY BLOCK-----
131
132 mQGiBEZM0ZURBADomT07whLs4n/ml84aIl8Ch6ShngfaaOS12ZrBQVQ/VSh7zPOx
133 IzfhSmwDJAWLZOnnM5zAqWPuNSJa3hQzY/M+X7vv3/p7kkB54/5U6LW+8ODENnMe
134 yPJhbI7phlfeE+STK9hytC3W5+OSrQknXkwYm1bGOur0iiU4Nr16ePE19wCg4KIc
135 ecqxm1U2CRtVC6G3qrZpscMD/0loPcv6Yw7Sx+3UwgAFaOJNE73P+h87wz29WkKs
136 h8Sx/l+Zf2NW/cMUwR0OOQQpzXKtZ8mF/CuPY4YITThKEGh680dUecuGBk5k3LeE
137 ZuLCFagEwZDWqXq/rR7+v8KCaxHpsaoU9P9p3Z7mruvaTYFp+yNfIYAklYoVI2iO
138 pB9PA/94xF3Vsdm3rqT6MUCVbBLKRRNHh7RDiFhQb0GfoWQiae0ZdJO2zWKCprKc
139 cboswKVs0SEUAD30izAaMlfR/p/LrFDHYwr5bBm38xhRMgFxrqdV+5o1+bdYNGA6
140 dJc6XgDWhDHpErCDibGAugNfVCDPhTE1eKbQQXST1KHnhyOcWbQeQmFydCBUaGF0
141 ZSA8YmFydEBnb3plcmJvdC5vcmc+iGAEExECACAFAkZM0ZUCGwMGCwkIBwMCBBUC
142 CAMEFgIDAQIeAQIXgAAKCRAtbUN8xcnCslzoAKCq7QqTlT10I6WcDZddY9GqcKxp
143 VQCaAgX1r9e39X79HR3NxTU6EHgm1hm5Ag0ERkzRnxAIALEuEASs9rpQNcpn6+UJ
144 M43J6vu9qYPl6T4ljsTdsi11Lr7r2ltFmvu/RqA9R4M4QwS/JZjm71R3Ci0eJSnR
145 AlkhejYHn5TKJ5rzRO6EUL0Jd/Rwgk/9qivIyfKAW3A1To2JgRUP9WI19MKYu6e9
146 K5h3KNi/1FfpeOFptB9mHyXBO2rHR9gaN6Wu9uz+eOGlZCyhNRx1jlmVcKAudT2g
147 qg/8NsuiEmv9Wf/CMgYawyenqx8S7cYC5EvHEscIOI/8zma0/1JqD8vllbSh64Ih
148 fsaW3twx/2gAIgtxRSIW7RQuYhs+zBT2C+Sg91rEgGcXjaw+OW2OZJ4kq1Qba82V
149 UOcAAwUH/21DRtgKgAX6xk97l+6ItP19HrcmydxNh299BboSKJDh5RcO1H4xOYyx
150 8NCDLhluGNzqeKPbBeW60F3qpkoQMGD7XsVpfKFu4Umn2qtrZAlg6qucgF0476IO
151 rhvKskAbNMBlocKzxiT+Ruomkt0Bwa3S1owXlMFwImA8coiWCQ8QnbpvjsYW9OH4
152 AgznK5uXKWgMxlZ9SffU0IHXipl3TENXiIdSwUUc2gV5emV/ROFhASNl7YYxZhY6
153 ng8YRku3MXM2jN1S/gNX1hvcq20oFjucKx7YkkV1k23FKF6XK776bmD0hYiSH1e0
154 uSAlBPAgC5HPqMpFhfyeFnDW0N90DR6ISQQYEQIACQUCRkzRnwIbDAAKCRAtbUN8
155 xcnCsoVMAJ472BdMgh+eUJp0+rGCeQhLELJVlQCcCV1zrNw9yoxIGJYnMZZSn4V5
156 Yf8=
157 =UxRq
158 -----END PGP PUBLIC KEY BLOCK-----
159 ''',
160
161 'D561C5D7CD86CB3CCA1AB5512A22EC17F9EBC3D8': '''
162 -----BEGIN PGP PUBLIC KEY BLOCK-----
163
164 mQGiBEZMjOARBACYqwLsv7AMOEHL4wspu0DVXwzVm3U3AU2LivHaJjj66zTd16K4
165 1QQ8CjdWVjMLOSH9tvj0Z7wbdyeQEjAxykgIgIUvQ0zuHgzqVsbpW//W/Noc1Z3K
166 MIEPBQIDdWM7Ln9+1jZAWIKU6oPU6F9Qt2/8o2NDc0w8O73NKgn/NGWtqwCglitS
167 SvUvpP3HZZ8aYwqjk51j0V8D/ilgVNkb/7FumD2yF1R48bJmbRaFu58Hu2IplRr0
168 cGHZ1ijCR8fWeMPGY3CakEOjxQa9IkNtoce/PGTgbIl+TLwXSdiiyu5xkEIt2HHm
169 F3lzLw2o6T59g2w22KpLeXMO02+LcNdsV/BOrhLiO7E/cDB7wBfd/BG3zNC9C2ln
170 cmL4BACL5SEaOE4BCRrOfWdDDUF9iiXGxpCErdxlwId9eFM5OMe48ZmB7oGY52dY
171 rzGK54bqkVxRf5MOcUy3IjulZcy/LcOmm+agNnbQPVTuWNfty8+pSs6cPnF2bBUN
172 xf+UEZnQRlUHokHBy20DMjV3v8jXMBtZxlB24EmMDE21nAofZrQxdGVobWF6ZS5j
173 b20gKGdvemVycGx1Z3MpIDxnb3plcnBsdWdzQHRlaG1hemUuY29tPohgBBMRAgAg
174 BQJGTIzgAhsDBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQKiLsF/nrw9gngQCf
175 esACa4M8ZjvMul8xad4oIUHkMTYAn0+bZBN8ip10/5qIR/CdDvwSL56b
176 =RTHp
177 -----END PGP PUBLIC KEY BLOCK-----
178 ''',
179
180 'B2FF7E64254524AC21EF9B76FF52B757C5181C13': '''
181 -----BEGIN PGP PUBLIC KEY BLOCK-----
182 Version: GnuPG v1.4.6 (GNU/Linux)
183
184 mQGiBEjE3rURBACHzP3dPU2E8t62zZ+nzksHsmaV4ooJPoysEWWpG9SdC2MGuwQ7
185 cnhCWmhxee6VbZ+KbC+pIEpEXeFPK3yaOkO09A1/CKuFTwndDR6Xzy4c/7WauYxq
186 hmn5Q/eODoKYseRoGY65u/rpK1/8OlNxjQltr1Ysgw+GHfjkJK2pWNz3wwCgnVZK
187 p6TYgb9EHLSjqmXekaOMV5kD/iH10PJXj3V+ToZKrsumP3dxha2TICtWMAo6LHa0
188 Qwwkjag93Ji+5yyVM/9UrYzJlqLUapTDit4gmeRm+3Abz6zcOcemowIbNhl/AK8F
189 04JaLTr3uOkkBaVRaIYWWPU8pmq9qT2vcPXxYVE87IBURp9XyvEZrhI/DPCtvXsJ
190 ZB+3A/0UVOo5anIiejqxk99VB61wYD2jN5SUD/VctrhIJYs0PnNBbD3rKcFwURLy
191 WB2cBRXPHoFBOm8h1nWxG/vCMvJoLSI9oU7/AV7j0v6uLSrO0EP8AreQONJi0J29
192 mIjIvdCn/f7pmYXJIL+xo+B1H2yd8uCUT66R+byqTlaISOZGe7Q6QmFzIHZhbiBP
193 b3N0dmVlbiAoR296ZXJib3QgUGx1Z2lucykgPHYub29zdHZlZW5AZ21haWwuY29t
194 PohgBBMRAgAgBQJIxN61AhsjBgsJCAcDAgQVAggDBBYCAwECHgECF4AACgkQ/1K3
195 V8UYHBOjywCfUZUZL034A5FL5Dv6jW+ul5FVee8An29ig3yylumzZclKGqnnRn0S
196 eb72uQENBEjE3rcQBAC22r4DBZNX6F9LDwtEXLnRpDwP1lf9e5gvD9NMD++zvEfq
197 Ezu/1WCg2hgPSJEDlX0sCnCeqyIonl5/3UjPfug9ZtZDOPjZAl2BDIAptwhZoNSd
198 ypuC4xOyLog7CXpTO0xHQAG7RhBncU9ieenZQQzTV81nFuWe5Icy1espbAi8xwAD
199 BQP6AhoaTKoNv6/JbHrDAigC0mcS7KabeumkRnOCHcZVdPYumto3E63SHZtAXFxI
200 ldkoCOhYfuj/3nosydJcSX0EF2rZMr9p0Mc/N+I341DVagi2OlLRYsqqrBbPm37j
201 BQNEDl/OUHI17ckd45OqiZ2RYiZlbXBrInFyFNhxElTBeQeISQQYEQIACQUCSMTe
202 twIbDAAKCRD/UrdXxRgcE7s4AJ9UzkvCP/tiwzoqe5nQSBqMZAwfUACfS+KCdWq0
203 92kg/7BDhzoD5a25BkI=
204 =+OEG
205 -----END PGP PUBLIC KEY BLOCK-----
206 '''}
207
208
209 pgp = Pgp()
210 for keyid, keydata in gozerbot_pgp_keys.iteritems():
211 try:
212 if not pgp.exists(keyid):
213 pgp.imports(keydata)
214 except NoGPGException:
215 rlog(10, 'pgp', 'no pgp installed')
216 break
217