GPG is now optional

This commit is contained in:
Yann Leboulanger 2004-10-16 09:37:32 +00:00
parent c4f47e9de6
commit 2e6c33719c
3 changed files with 171 additions and 159 deletions

View file

@ -22,8 +22,6 @@ import sys, os, time, string, logging
import common.hub, common.optparser import common.hub, common.optparser
import common.jabber import common.jabber
import socket, select, pickle import socket, select, pickle
import GnuPGInterface
from common import i18n from common import i18n
_ = i18n._ _ = i18n._
@ -48,158 +46,164 @@ def XMLunescape(txt):
txt = txt.replace("&", "&") txt = txt.replace("&", "&")
return txt return txt
class MyGnuPG(GnuPGInterface.GnuPG): USE_GPG = 1
def __init__(self): try:
GnuPGInterface.GnuPG.__init__(self) import GnuPGInterface
self.setup_my_options() except:
USE_GPG = 0
else:
class MyGnuPG(GnuPGInterface.GnuPG):
def __init__(self):
GnuPGInterface.GnuPG.__init__(self)
self.setup_my_options()
def setup_my_options(self): def setup_my_options(self):
self.options.armor = 1 self.options.armor = 1
self.options.meta_interactive = 0 self.options.meta_interactive = 0
self.options.extra_args.append('--no-secmem-warning') self.options.extra_args.append('--no-secmem-warning')
def _read_response(self, child_stdout): def _read_response(self, child_stdout):
# Internal method: reads all the output from GPG, taking notice # Internal method: reads all the output from GPG, taking notice
# only of lines that begin with the magic [GNUPG:] prefix. # only of lines that begin with the magic [GNUPG:] prefix.
# (See doc/DETAILS in the GPG distribution for info on GPG's # (See doc/DETAILS in the GPG distribution for info on GPG's
# output when --status-fd is specified.) # output when --status-fd is specified.)
# #
# Returns a dictionary, mapping GPG's keywords to the arguments # Returns a dictionary, mapping GPG's keywords to the arguments
# for that keyword. # for that keyword.
resp = {} resp = {}
while 1: while 1:
line = child_stdout.readline() line = child_stdout.readline()
if line == "": break if line == "": break
line = string.rstrip( line ) line = string.rstrip( line )
if line[0:9] == '[GNUPG:] ': if line[0:9] == '[GNUPG:] ':
# Chop off the prefix # Chop off the prefix
line = line[9:] line = line[9:]
L = string.split(line, None, 1) L = string.split(line, None, 1)
keyword = L[0] keyword = L[0]
if len(L) > 1: if len(L) > 1:
resp[ keyword ] = L[1] resp[ keyword ] = L[1]
else: else:
resp[ keyword ] = "" resp[ keyword ] = ""
return resp return resp
def encrypt(self, string, recipients): def encrypt(self, string, recipients):
self.options.recipients = recipients # a list! self.options.recipients = recipients # a list!
proc = self.run(['--encrypt'], create_fhs=['stdin', 'stdout']) proc = self.run(['--encrypt'], create_fhs=['stdin', 'stdout'])
proc.handles['stdin'].write(string) proc.handles['stdin'].write(string)
proc.handles['stdin'].close() proc.handles['stdin'].close()
output = proc.handles['stdout'].read() output = proc.handles['stdout'].read()
proc.handles['stdout'].close() proc.handles['stdout'].close()
try: proc.wait() try: proc.wait()
except IOError: pass except IOError: pass
return self.stripHeaderFooter(output)
def decrypt(self, string, keyID):
proc = self.run(['--decrypt', '-q', '-u %s'%keyID], create_fhs=['stdin', 'stdout', 'status'])
enc = self.addHeaderFooter(string, 'MESSAGE')
proc.handles['stdin'].write(enc)
proc.handles['stdin'].close()
output = proc.handles['stdout'].read()
proc.handles['stdout'].close()
resp = proc.handles['status'].read()
proc.handles['status'].close()
try: proc.wait()
except IOError: pass
return output
def sign(self, string, keyID):
proc = self.run(['-b', '-u %s'%keyID], create_fhs=['stdin', 'stdout', 'status', 'stderr'])
proc.handles['stdin'].write(string)
proc.handles['stdin'].close()
output = proc.handles['stdout'].read()
proc.handles['stdout'].close()
proc.handles['stderr'].close()
stat = proc.handles['status']
resp = self._read_response(stat)
proc.handles['status'].close()
try: proc.wait()
except IOError: pass
if resp.has_key('BAD_PASSPHRASE'):
return 'BAD_PASSPHRASE'
elif resp.has_key('GOOD_PASSPHRASE'):
return self.stripHeaderFooter(output) return self.stripHeaderFooter(output)
def verify(self, str, sign): def decrypt(self, string, keyID):
file = open('gpg_data', 'w+r') proc = self.run(['--decrypt', '-q', '-u %s'%keyID], create_fhs=['stdin', 'stdout', 'status'])
try: os.remove('gpg_data') enc = self.addHeaderFooter(string, 'MESSAGE')
except: pass proc.handles['stdin'].write(enc)
fd = file.fileno() proc.handles['stdin'].close()
file.write(str)
file.seek(0)
proc = self.run(['--verify', '--enable-special-filenames', '-', '-&%s'%fd], create_fhs=['stdin', 'status', 'stderr']) output = proc.handles['stdout'].read()
proc.handles['stdout'].close()
file.close resp = proc.handles['status'].read()
sign = self.addHeaderFooter(sign, 'SIGNATURE') proc.handles['status'].close()
proc.handles['stdin'].write(sign)
proc.handles['stdin'].close()
proc.handles['stderr'].close()
stat = proc.handles['status'] try: proc.wait()
resp = self._read_response(stat) except IOError: pass
proc.handles['status'].close() return output
def sign(self, string, keyID):
proc = self.run(['-b', '-u %s'%keyID], create_fhs=['stdin', 'stdout', 'status', 'stderr'])
proc.handles['stdin'].write(string)
proc.handles['stdin'].close()
try: proc.wait() output = proc.handles['stdout'].read()
except IOError: pass proc.handles['stdout'].close()
proc.handles['stderr'].close()
keyid = '' stat = proc.handles['status']
if resp.has_key('GOODSIG'): resp = self._read_response(stat)
keyid = string.split(resp['GOODSIG'])[0] proc.handles['status'].close()
return keyid
def get_secret_keys(self): try: proc.wait()
proc = self.run(['--with-colons', '--list-secret-keys'], \ except IOError: pass
create_fhs=['stdout']) if resp.has_key('BAD_PASSPHRASE'):
output = proc.handles['stdout'].read() return 'BAD_PASSPHRASE'
proc.handles['stdout'].close() elif resp.has_key('GOOD_PASSPHRASE'):
return self.stripHeaderFooter(output)
keys = {} def verify(self, str, sign):
lines = string.split(output, '\n') file = open('gpg_data', 'w+r')
for line in lines: try: os.remove('gpg_data')
sline = string.split(line, ':') except: pass
if sline[0] == 'sec': fd = file.fileno()
keys[sline[4][8:]] = sline[9] file.write(str)
return keys file.seek(0)
try: proc.wait()
except IOError: pass proc = self.run(['--verify', '--enable-special-filenames', '-', '-&%s'%fd], create_fhs=['stdin', 'status', 'stderr'])
def stripHeaderFooter(self, data): file.close
"""Remove header and footer from data""" sign = self.addHeaderFooter(sign, 'SIGNATURE')
lines = string.split(data, '\n') proc.handles['stdin'].write(sign)
while lines[0] != '': proc.handles['stdin'].close()
lines.remove(lines[0]) proc.handles['stderr'].close()
while lines[0] == '':
lines.remove(lines[0])
i = 0
for line in lines:
if line:
if line[0] == '-': break
i = i+1
line = string.join(lines[0:i], '\n')
return line
def addHeaderFooter(self, data, type): stat = proc.handles['status']
"""Add header and footer from data""" resp = self._read_response(stat)
out = "-----BEGIN PGP %s-----\n" % type proc.handles['status'].close()
out = out + "Version: PGP\n"
out = out + "\n" try: proc.wait()
out = out + data + "\n" except IOError: pass
out = out + "-----END PGP %s-----\n" % type
return out keyid = ''
if resp.has_key('GOODSIG'):
keyid = string.split(resp['GOODSIG'])[0]
return keyid
def get_secret_keys(self):
proc = self.run(['--with-colons', '--list-secret-keys'], \
create_fhs=['stdout'])
output = proc.handles['stdout'].read()
proc.handles['stdout'].close()
keys = {}
lines = string.split(output, '\n')
for line in lines:
sline = string.split(line, ':')
if sline[0] == 'sec':
keys[sline[4][8:]] = sline[9]
return keys
try: proc.wait()
except IOError: pass
def stripHeaderFooter(self, data):
"""Remove header and footer from data"""
lines = string.split(data, '\n')
while lines[0] != '':
lines.remove(lines[0])
while lines[0] == '':
lines.remove(lines[0])
i = 0
for line in lines:
if line:
if line[0] == '-': break
i = i+1
line = string.join(lines[0:i], '\n')
return line
def addHeaderFooter(self, data, type):
"""Add header and footer from data"""
out = "-----BEGIN PGP %s-----\n" % type
out = out + "Version: PGP\n"
out = out + "\n"
out = out + data + "\n"
out = out + "-----END PGP %s-----\n" % type
return out
class GajimCore: class GajimCore:
"""Core""" """Core"""
@ -220,11 +224,13 @@ class GajimCore:
#connexions {con: name, ...} #connexions {con: name, ...}
self.connexions = {} self.connexions = {}
self.gpg = {} self.gpg = {}
self.gpg_common = MyGnuPG() if USE_GPG:
self.gpg_common = MyGnuPG()
for a in self.accounts: for a in self.accounts:
self.connected[a] = 0 #0:offline, 1:online, 2:away, self.connected[a] = 0 #0:offline, 1:online, 2:away,
#3:xa, 4:dnd, 5:invisible #3:xa, 4:dnd, 5:invisible
self.gpg[a] = MyGnuPG() if USE_GPG:
self.gpg[a] = MyGnuPG()
self.myVCardID = [] self.myVCardID = []
self.loadPlugins(self.cfgParser.tab['Core']['modules']) self.loadPlugins(self.cfgParser.tab['Core']['modules'])
else: else:
@ -344,7 +350,7 @@ class GajimCore:
if xtag.getNamespace() == common.jabber.NS_XENCRYPTED: if xtag.getNamespace() == common.jabber.NS_XENCRYPTED:
encTag = xtag encTag = xtag
break break
if encTag: if encTag and USE_GPG:
#decrypt #decrypt
encmsg = encTag.getData() encmsg = encTag.getData()
keyID = '' keyID = ''
@ -382,7 +388,7 @@ class GajimCore:
if xtag.getNamespace() == common.jabber.NS_XSIGNED: if xtag.getNamespace() == common.jabber.NS_XSIGNED:
sigTag = xtag sigTag = xtag
break break
if sigTag: if sigTag and USE_GPG:
#verify #verify
sigmsg = sigTag.getData() sigmsg = sigTag.getData()
keyID = self.gpg[self.connexions[con]].verify(status, sigmsg) keyID = self.gpg[self.connexions[con]].verify(status, sigmsg)
@ -523,9 +529,8 @@ class GajimCore:
self.hub.sendPlugin('WARNING', None, _("Couldn't connect to %s : %s") \ self.hub.sendPlugin('WARNING', None, _("Couldn't connect to %s : %s") \
% (hostname, e)) % (hostname, e))
return 0 return 0
except: # except:
sys.exc_info()[1][0] # print sys.exc_info()[1]
sys.exc_info()[1][1]
else: else:
log.debug("Connected to server") log.debug("Connected to server")
@ -567,7 +572,7 @@ class GajimCore:
def request_infos(self, account, con, jid): def request_infos(self, account, con, jid):
identities, features = con.discoverInfo(jid) identities, features = con.discoverInfo(jid)
if not identities: if not identities:
identities, features, items = con.browseAgent(jid) identities, features, items = con.browseAgents(jid)
else: else:
items = con.discoverItems(jid) items = con.discoverItems(jid)
self.hub.sendPlugin('AGENT_INFO', account, (jid, identities, features, items)) self.hub.sendPlugin('AGENT_INFO', account, (jid, identities, features, items))
@ -619,11 +624,12 @@ class GajimCore:
for item in ev[2][2].keys(): for item in ev[2][2].keys():
if not config.has_key(item): if not config.has_key(item):
config[item] = ev[2][2][item] config[item] = ev[2][2][item]
self.hub.sendPlugin('CONFIG', None, (ev[2][0], config))
else: else:
self.cfgParser.tab[ev[2][1]] = ev[2][2] config = ev[2][2]
self.cfgParser.tab[ev[2][1]] = config
self.cfgParser.writeCfgFile() self.cfgParser.writeCfgFile()
self.hub.sendPlugin('CONFIG', None, (ev[2][0], ev[2][2])) config['usegpg'] = USE_GPG
self.hub.sendPlugin('CONFIG', None, (ev[2][0], config))
#('CONFIG', account, (section, config)) #('CONFIG', account, (section, config))
elif ev[0] == 'CONFIG': elif ev[0] == 'CONFIG':
if ev[2][0] == 'accounts': if ev[2][0] == 'accounts':
@ -642,7 +648,7 @@ class GajimCore:
self.cfgParser.tab[a] = ev[2][1][a] self.cfgParser.tab[a] = ev[2][1][a]
if not a in self.connected.keys(): if not a in self.connected.keys():
self.connected[a] = 0 self.connected[a] = 0
if not self.gpg.has_key(a): if not self.gpg.has_key(a) and USE_GPG:
self.gpg[a] = MyGnuPG() self.gpg[a] = MyGnuPG()
else: else:
self.cfgParser.tab[ev[2][0]] = ev[2][1] self.cfgParser.tab[ev[2][0]] = ev[2][1]
@ -658,7 +664,7 @@ class GajimCore:
keyID = '' keyID = ''
if self.cfgParser.tab[ev[1]].has_key("keyid"): if self.cfgParser.tab[ev[1]].has_key("keyid"):
keyID = self.cfgParser.tab[ev[1]]["keyid"] keyID = self.cfgParser.tab[ev[1]]["keyid"]
if keyID: if keyID and USE_GPG:
signed = self.gpg[ev[1]].sign(msg, keyID) signed = self.gpg[ev[1]].sign(msg, keyID)
if signed == 'BAD_PASSPHRASE': if signed == 'BAD_PASSPHRASE':
signed = '' signed = ''
@ -709,7 +715,7 @@ class GajimCore:
elif ev[0] == 'MSG': elif ev[0] == 'MSG':
msgtxt = ev[2][1] msgtxt = ev[2][1]
msgenc = '' msgenc = ''
if ev[2][2]: if ev[2][2] and USE_GPG:
#encrypt #encrypt
msgenc = self.gpg[ev[1]].encrypt(ev[2][1], [ev[2][2]]) msgenc = self.gpg[ev[1]].encrypt(ev[2][1], [ev[2][2]])
if msgenc: msgtxt = '[this message is encrypted]' if msgenc: msgtxt = '[this message is encrypted]'
@ -766,7 +772,6 @@ class GajimCore:
groups=ev[2][2]) groups=ev[2][2])
#('REQ_AGENTS', account, ()) #('REQ_AGENTS', account, ())
elif ev[0] == 'REQ_AGENTS': elif ev[0] == 'REQ_AGENTS':
# agents = con.requestAgents()
#do we need that ? #do we need that ?
#con.discoverInfo('jabber.lagaule.org') #con.discoverInfo('jabber.lagaule.org')
agents = con.discoverItems('jabber.lagaule.org') agents = con.discoverItems('jabber.lagaule.org')
@ -810,8 +815,9 @@ class GajimCore:
elif ev[0] == 'ACC_CHG': elif ev[0] == 'ACC_CHG':
self.connected[ev[2]] = self.connected[ev[1]] self.connected[ev[2]] = self.connected[ev[1]]
del self.connected[ev[1]] del self.connected[ev[1]]
self.gpg[ev[2]] = self.gpg[ev[1]] if USE_GPG:
del self.gpg[ev[1]] self.gpg[ev[2]] = self.gpg[ev[1]]
del self.gpg[ev[1]]
if con: if con:
self.connexions[con] = ev[2] self.connexions[con] = ev[2]
#('ASK_VCARD', account, jid) #('ASK_VCARD', account, jid)
@ -891,10 +897,12 @@ class GajimCore:
'available', show=ev[2][2], status = ev[2][3])) 'available', show=ev[2][2], status = ev[2][3]))
#('PASSPHRASE', account, passphrase) #('PASSPHRASE', account, passphrase)
elif ev[0] == 'PASSPHRASE': elif ev[0] == 'PASSPHRASE':
self.gpg[ev[1]].passphrase = ev[2] if USE_GPG:
self.gpg[ev[1]].passphrase = ev[2]
elif ev[0] == 'GPG_SECRETE_KEYS': elif ev[0] == 'GPG_SECRETE_KEYS':
keys = self.gpg_common.get_secret_keys() if USE_GPG:
self.hub.sendPlugin('GPG_SECRETE_KEYS', ev[1], keys) keys = self.gpg_common.get_secret_keys()
self.hub.sendPlugin('GPG_SECRETE_KEYS', ev[1], keys)
else: else:
log.debug(_("Unknown Command %s") % ev[0]) log.debug(_("Unknown Command %s") % ev[0])
if self.mode == 'server': if self.mode == 'server':

View file

@ -423,8 +423,11 @@ class accountPreference_Window:
if infos.has_key('proxyport'): if infos.has_key('proxyport'):
self.xml.get_widget("entry_proxyport").set_text(str(\ self.xml.get_widget("entry_proxyport").set_text(str(\
infos['proxyport'])) infos['proxyport']))
if infos.has_key('keyid'): if not infos.has_key('usegpg'):
if infos['keyid']: self.xml.get_widget('gpg_key_label').set_text('GPG is not usable on this computer')
self.xml.get_widget('gpg_choose_key_button').set_sensitive(False)
if infos.has_key('keyid') and infos.has_key('usegpg'):
if infos['keyid'] and infos['usegpg']:
self.xml.get_widget('gpg_key_label').set_text(infos['keyid']) self.xml.get_widget('gpg_key_label').set_text(infos['keyid'])
if infos.has_key('keyname'): if infos.has_key('keyname'):
self.xml.get_widget('gpg_name_label').set_text(infos['keyname']) self.xml.get_widget('gpg_name_label').set_text(infos['keyname'])

View file

@ -1355,7 +1355,8 @@ class roster_Window:
save_gpg_pass = self.plugin.accounts[account]["savegpgpass"] save_gpg_pass = self.plugin.accounts[account]["savegpgpass"]
if self.plugin.accounts[account].has_key("keyid"): if self.plugin.accounts[account].has_key("keyid"):
keyid = self.plugin.accounts[account]["keyid"] keyid = self.plugin.accounts[account]["keyid"]
if keyid and not self.plugin.connected[account]: if keyid and not self.plugin.connected[account] and \
self.plugin.config['usegpg']:
if save_gpg_pass: if save_gpg_pass:
passphrase = self.plugin.accounts[account]['gpgpass'] passphrase = self.plugin.accounts[account]['gpgpass']
else: else: