Package common :: Module passwords
[hide private]
[frames] | no frames]

Source Code for Module common.passwords

  1  # -*- coding:utf-8 -*- 
  2  ## src/common/passwords.py 
  3  ## 
  4  ## Copyright (C) 2006 Gustavo J. A. M. Carneiro <gjcarneiro AT gmail.com> 
  5  ##                    Nikos Kouremenos <kourem AT gmail.com> 
  6  ## Copyright (C) 2006-2010 Yann Leboulanger <asterix AT lagaule.org> 
  7  ## Copyright (C) 2007 Jean-Marie Traissard <jim AT lapin.org> 
  8  ##                    Julien Pivotto <roidelapluie AT gmail.com> 
  9  ## Copyright (C) 2008 Stephan Erb <steve-e AT h3c.de> 
 10  ## Copyright (c) 2009 Thorsten Glaser <t.glaser AT tarent.de> 
 11  ## 
 12  ## This file is part of Gajim. 
 13  ## 
 14  ## Gajim is free software; you can redistribute it and/or modify 
 15  ## it under the terms of the GNU General Public License as published 
 16  ## by the Free Software Foundation; version 3 only. 
 17  ## 
 18  ## Gajim is distributed in the hope that it will be useful, 
 19  ## but WITHOUT ANY WARRANTY; without even the implied warranty of 
 20  ## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 
 21  ## GNU General Public License for more details. 
 22  ## 
 23  ## You should have received a copy of the GNU General Public License 
 24  ## along with Gajim. If not, see <http://www.gnu.org/licenses/>. 
 25  ## 
 26   
 27  __all__ = ['get_password', 'save_password'] 
 28   
 29  import warnings 
 30  from common import gajim 
 31  from common import kwalletbinding 
 32   
 33  USER_HAS_GNOMEKEYRING = False 
 34  USER_USES_GNOMEKEYRING = False 
 35  USER_HAS_KWALLETCLI = False 
 36  gnomekeyring = None 
 37   
38 -class PasswordStorage(object):
39 - def get_password(self, account_name):
40 raise NotImplementedError
41 - def save_password(self, account_name, password):
42 raise NotImplementedError
43 44
45 -class SimplePasswordStorage(PasswordStorage):
46 - def get_password(self, account_name):
47 passwd = gajim.config.get_per('accounts', account_name, 'password') 48 if passwd and (passwd.startswith('gnomekeyring:') or \ 49 passwd == '<kwallet>'): 50 # this is not a real password, it's either a gnome 51 # keyring token or stored in the KDE wallet 52 return None 53 else: 54 return passwd
55
56 - def save_password(self, account_name, password):
57 gajim.config.set_per('accounts', account_name, 'password', password) 58 if account_name in gajim.connections: 59 gajim.connections[account_name].password = password
60 61
62 -class GnomePasswordStorage(PasswordStorage):
63 - def __init__(self):
64 self.keyring = gnomekeyring.get_default_keyring_sync() 65 if self.keyring is None: 66 self.keyring = 'default' 67 try: 68 gnomekeyring.create_sync(self.keyring, None) 69 except gnomekeyring.AlreadyExistsError: 70 pass
71
72 - def get_password(self, account_name):
73 conf = gajim.config.get_per('accounts', account_name, 'password') 74 if conf is None or conf == '<kwallet>': 75 return None 76 if not conf.startswith('gnomekeyring:'): 77 password = conf 78 ## migrate the password over to keyring 79 try: 80 self.save_password(account_name, password, update=False) 81 except gnomekeyring.NoKeyringDaemonError: 82 ## no keyring daemon: in the future, stop using it 83 set_storage(SimplePasswordStorage()) 84 return password 85 try: 86 server = gajim.config.get_per('accounts', account_name, 'hostname') 87 user = gajim.config.get_per('accounts', account_name, 'name') 88 attributes1 = dict(server=str(server), user=str(user), protocol='xmpp') 89 attributes2 = dict(account_name=str(account_name), gajim=1) 90 try: 91 items = gnomekeyring.find_items_sync( 92 gnomekeyring.ITEM_NETWORK_PASSWORD, attributes1) 93 except gnomekeyring.Error: 94 try: 95 items = gnomekeyring.find_items_sync( 96 gnomekeyring.ITEM_GENERIC_SECRET, attributes2) 97 if items: 98 # We found an old item, move it to new way of storing 99 password = items[0].secret 100 self.save_password(account_name, password) 101 gnomekeyring.item_delete_sync(items[0].keyring, 102 int(items[0].item_id)) 103 except gnomekeyring.Error: 104 items = [] 105 if len(items) > 1: 106 warnings.warn("multiple gnome keyring items found for account %s;" 107 " trying to use the first one..." 108 % account_name) 109 if items: 110 return items[0].secret 111 else: 112 return None 113 except gnomekeyring.DeniedError: 114 return None 115 except gnomekeyring.NoKeyringDaemonError: 116 ## no keyring daemon: in the future, stop using it 117 set_storage(SimplePasswordStorage()) 118 return None
119
120 - def save_password(self, account_name, password, update=True):
121 server = gajim.config.get_per('accounts', account_name, 'hostname') 122 user = gajim.config.get_per('accounts', account_name, 'name') 123 display_name = _('XMPP account %s@%s') % (user, server) 124 attributes1 = dict(server=str(server), user=str(user), protocol='xmpp') 125 if password is None: 126 password = str() 127 try: 128 auth_token = gnomekeyring.item_create_sync( 129 self.keyring, gnomekeyring.ITEM_NETWORK_PASSWORD, 130 display_name, attributes1, password, update) 131 except gnomekeyring.DeniedError: 132 set_storage(SimplePasswordStorage()) 133 storage.save_password(account_name, password) 134 return 135 gajim.config.set_per('accounts', account_name, 'password', 136 'gnomekeyring:') 137 if account_name in gajim.connections: 138 gajim.connections[account_name].password = password
139
140 -class KWalletPasswordStorage(PasswordStorage):
141 - def get_password(self, account_name):
142 pw = gajim.config.get_per('accounts', account_name, 'password') 143 if not pw or pw.startswith('gnomekeyring:'): 144 # unset, empty or not ours 145 return None 146 if pw != '<kwallet>': 147 # migrate the password 148 if kwalletbinding.kwallet_put('gajim', account_name, pw): 149 gajim.config.set_per('accounts', account_name, 'password', 150 '<kwallet>') 151 else: 152 # stop using the KDE Wallet 153 set_storage(SimplePasswordStorage()) 154 return pw 155 pw = kwalletbinding.kwallet_get('gajim', account_name) 156 if pw is None: 157 # stop using the KDE Wallet 158 set_storage(SimplePasswordStorage()) 159 if not pw: 160 # False, None, or the empty string 161 return None 162 return pw
163
164 - def save_password(self, account_name, password):
165 if not kwalletbinding.kwallet_put('gajim', account_name, password): 166 # stop using the KDE Wallet 167 set_storage(SimplePasswordStorage()) 168 storage.save_password(account_name, password) 169 return 170 pwtoken = '<kwallet>' 171 if not password: 172 # no sense in looking up the empty string in the KWallet 173 pwtoken = '' 174 gajim.config.set_per('accounts', account_name, 'password', pwtoken) 175 if account_name in gajim.connections: 176 gajim.connections[account_name].password = password
177 178 179 storage = None
180 -def get_storage():
181 global storage 182 if storage is None: # None is only in first time get_storage is called 183 if gajim.config.get('use_gnomekeyring'): 184 global gnomekeyring 185 try: 186 import gnomekeyring 187 except ImportError: 188 pass 189 else: 190 global USER_HAS_GNOMEKEYRING 191 global USER_USES_GNOMEKEYRING 192 USER_HAS_GNOMEKEYRING = True 193 if gnomekeyring.is_available(): 194 USER_USES_GNOMEKEYRING = True 195 else: 196 USER_USES_GNOMEKEYRING = False 197 if USER_USES_GNOMEKEYRING: 198 try: 199 storage = GnomePasswordStorage() 200 except (gnomekeyring.NoKeyringDaemonError, gnomekeyring.DeniedError): 201 storage = None 202 if storage is None: 203 if gajim.config.get('use_kwalletcli'): 204 global USER_HAS_KWALLETCLI 205 if kwalletbinding.kwallet_available(): 206 USER_HAS_KWALLETCLI = True 207 if USER_HAS_KWALLETCLI: 208 storage = KWalletPasswordStorage() 209 if storage is None: 210 storage = SimplePasswordStorage() 211 return storage
212
213 -def set_storage(storage_):
214 global storage 215 storage = storage_
216 217
218 -def get_password(account_name):
219 return get_storage().get_password(account_name)
220
221 -def save_password(account_name, password):
222 return get_storage().save_password(account_name, password)
223