| 1 | # -*- coding:utf-8 -*- |
|---|
| 2 | ## src/secrets.py |
|---|
| 3 | ## |
|---|
| 4 | ## Copyright (C) 2007-2008 Brendan Taylor <whateley AT gmail.com> |
|---|
| 5 | ## Copyright (C) 2008 Jonathan Schleifer <js-gajim AT webkeks.org> |
|---|
| 6 | ## |
|---|
| 7 | ## This file is part of Gajim. |
|---|
| 8 | ## |
|---|
| 9 | ## Gajim is free software; you can redistribute it and/or modify |
|---|
| 10 | ## it under the terms of the GNU General Public License as published |
|---|
| 11 | ## by the Free Software Foundation; version 3 only. |
|---|
| 12 | ## |
|---|
| 13 | ## Gajim is distributed in the hope that it will be useful, |
|---|
| 14 | ## but WITHOUT ANY WARRANTY; without even the implied warranty of |
|---|
| 15 | ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
|---|
| 16 | ## GNU General Public License for more details. |
|---|
| 17 | ## |
|---|
| 18 | ## You should have received a copy of the GNU General Public License |
|---|
| 19 | ## along with Gajim. If not, see <http://www.gnu.org/licenses/>. |
|---|
| 20 | ## |
|---|
| 21 | |
|---|
| 22 | from common.configpaths import gajimpaths |
|---|
| 23 | |
|---|
| 24 | from common import crypto |
|---|
| 25 | from common import exceptions |
|---|
| 26 | |
|---|
| 27 | import os |
|---|
| 28 | import pickle |
|---|
| 29 | |
|---|
| 30 | secrets_filename = gajimpaths['SECRETS_FILE'] |
|---|
| 31 | secrets_cache = None |
|---|
| 32 | |
|---|
| 33 | class Secrets: |
|---|
| 34 | def __init__(self, filename): |
|---|
| 35 | self.filename = filename |
|---|
| 36 | self.srs = {} |
|---|
| 37 | self.pubkeys = {} |
|---|
| 38 | self.privkeys = {} |
|---|
| 39 | |
|---|
| 40 | def cancel(self): |
|---|
| 41 | raise exceptions.Cancelled |
|---|
| 42 | |
|---|
| 43 | def save(self): |
|---|
| 44 | pickle.dumps(self) |
|---|
| 45 | |
|---|
| 46 | f = open(secrets_filename, 'w') |
|---|
| 47 | f.write(pickle.dumps(self)) |
|---|
| 48 | f.close() |
|---|
| 49 | |
|---|
| 50 | def retained_secrets(self, account, bare_jid): |
|---|
| 51 | try: |
|---|
| 52 | return self.srs[account][bare_jid] |
|---|
| 53 | except KeyError: |
|---|
| 54 | return [] |
|---|
| 55 | |
|---|
| 56 | # retained secrets are stored as a tuple of the secret and whether the user |
|---|
| 57 | # has verified it |
|---|
| 58 | def save_new_srs(self, account, jid, secret, verified): |
|---|
| 59 | if not account in self.srs: |
|---|
| 60 | self.srs[account] = {} |
|---|
| 61 | |
|---|
| 62 | if not jid in self.srs[account]: |
|---|
| 63 | self.srs[account][jid] = [] |
|---|
| 64 | |
|---|
| 65 | self.srs[account][jid].append((secret, verified)) |
|---|
| 66 | |
|---|
| 67 | self.save() |
|---|
| 68 | |
|---|
| 69 | def find_srs(self, account, jid, srs): |
|---|
| 70 | our_secrets = self.srs[account][jid] |
|---|
| 71 | return filter(lambda (x,y): x == srs, our_secrets)[0] |
|---|
| 72 | |
|---|
| 73 | # has the user verified this retained secret? |
|---|
| 74 | def srs_verified(self, account, jid, srs): |
|---|
| 75 | return self.find_srs(account, jid, srs)[1] |
|---|
| 76 | |
|---|
| 77 | def replace_srs(self, account, jid, old_secret, new_secret, verified): |
|---|
| 78 | our_secrets = self.srs[account][jid] |
|---|
| 79 | |
|---|
| 80 | idx = our_secrets.index(self.find_srs(account, jid, old_secret)) |
|---|
| 81 | |
|---|
| 82 | our_secrets[idx] = (new_secret, verified) |
|---|
| 83 | |
|---|
| 84 | self.save() |
|---|
| 85 | |
|---|
| 86 | # the public key associated with 'account' |
|---|
| 87 | def my_pubkey(self, account): |
|---|
| 88 | try: |
|---|
| 89 | pk = self.privkeys[account] |
|---|
| 90 | except KeyError: |
|---|
| 91 | pk = Crypto.PublicKey.RSA.generate(384, crypto.random_bytes) |
|---|
| 92 | |
|---|
| 93 | self.privkeys[account] = pk |
|---|
| 94 | self.save() |
|---|
| 95 | |
|---|
| 96 | return pk |
|---|
| 97 | |
|---|
| 98 | def load_secrets(filename): |
|---|
| 99 | f = open(filename, 'r') |
|---|
| 100 | |
|---|
| 101 | try: |
|---|
| 102 | secrets = pickle.loads(f.read()) |
|---|
| 103 | except KeyError: |
|---|
| 104 | f.close() |
|---|
| 105 | secrets = Secrets(filename) |
|---|
| 106 | |
|---|
| 107 | return secrets |
|---|
| 108 | |
|---|
| 109 | def secrets(): |
|---|
| 110 | global secrets_cache |
|---|
| 111 | |
|---|
| 112 | if secrets_cache: |
|---|
| 113 | return secrets_cache |
|---|
| 114 | |
|---|
| 115 | if os.path.exists(secrets_filename): |
|---|
| 116 | secrets_cache = load_secrets(secrets_filename) |
|---|
| 117 | else: |
|---|
| 118 | secrets_cache = Secrets(secrets_filename) |
|---|
| 119 | |
|---|
| 120 | return secrets_cache |
|---|
| 121 | |
|---|
| 122 | # vim: se ts=3: |
|---|