Switched keyring code to use gnomekeyring module. Disable keyring support if not available
This commit is contained in:
parent
ce35ed2b2d
commit
7a52fabd80
2
README
2
README
|
@ -31,7 +31,7 @@ please report any success to the mailing lists
|
|||
libvirt-python >= 0.1.1
|
||||
dbus-python >= 0.61
|
||||
gnome-keyring >= 0.4.9
|
||||
python-ctypes >= 0.9.9.6
|
||||
gnome-python-desktop >= 2.15.4
|
||||
libxml2-python >= 2.6.23
|
||||
vte >= 0.12.2
|
||||
|
||||
|
|
|
@ -166,16 +166,17 @@ class vmmConfig:
|
|||
def get_secret_name(self, vm):
|
||||
return "vm-console-" + vm.get_uuid()
|
||||
|
||||
def has_keyring(self):
|
||||
if self.keyring == None:
|
||||
self.keyring = vmmKeyring()
|
||||
return self.keyring.is_available()
|
||||
|
||||
def clear_console_password(self, vm):
|
||||
id = self.conf.get_int(self.conf_dir + "/console/passwords/" + vm.get_uuid())
|
||||
|
||||
if id != None:
|
||||
if self.keyring == None:
|
||||
try:
|
||||
self.keyring = vmmKeyring()
|
||||
except:
|
||||
print _("Unable to access keyring")
|
||||
return
|
||||
if not(self.has_keyring()):
|
||||
return
|
||||
|
||||
self.keyring.clear_secret(id)
|
||||
self.conf.unset(self.conf_dir + "/console/passwords/" + vm.get_uuid())
|
||||
|
@ -183,27 +184,27 @@ class vmmConfig:
|
|||
def get_console_password(self, vm):
|
||||
id = self.conf.get_int(self.conf_dir + "/console/passwords/" + vm.get_uuid())
|
||||
|
||||
if id != None:
|
||||
if self.keyring == None:
|
||||
try:
|
||||
self.keyring = vmmKeyring()
|
||||
except:
|
||||
print _("Unable to access keyring")
|
||||
return ""
|
||||
if id != None and id != 0:
|
||||
if not(self.has_keyring()):
|
||||
return ""
|
||||
|
||||
secret = self.keyring.get_secret(id)
|
||||
if secret != None and secret.get_name() == self.get_secret_name(vm):
|
||||
# XXX validate attributes
|
||||
if not(secret.has_attribute("hvuri")):
|
||||
return ""
|
||||
if secret.get_attribute("hvuri") != vm.get_connection().get_uri():
|
||||
return ""
|
||||
if not(secret.has_attribute("uuid")):
|
||||
return ""
|
||||
if secret.get_attribute("uuid") != vm.get_uuid():
|
||||
return ""
|
||||
|
||||
return secret.get_secret()
|
||||
return ""
|
||||
|
||||
def set_console_password(self, vm, password):
|
||||
if self.keyring == None:
|
||||
try:
|
||||
self.keyring = vmmKeyring()
|
||||
except:
|
||||
print _("Unable to access keyring")
|
||||
return
|
||||
if not(self.has_keyring()):
|
||||
return
|
||||
|
||||
# Nb, we don't bother to check if there is an existing
|
||||
# secret, because gnome-keyring auto-replaces an existing
|
||||
|
|
|
@ -172,10 +172,14 @@ class vmmConsole(gobject.GObject):
|
|||
def activate_auth_page(self):
|
||||
pw = self.config.get_console_password(self.vm)
|
||||
self.window.get_widget("console-auth-password").set_text(pw)
|
||||
if pw != None and pw != "":
|
||||
self.window.get_widget("console-auth-remember").set_active(True)
|
||||
if self.config.has_keyring():
|
||||
self.window.get_widget("console-auth-remember").set_sensitive(True)
|
||||
if pw != None and pw != "":
|
||||
self.window.get_widget("console-auth-remember").set_active(True)
|
||||
else:
|
||||
self.window.get_widget("console-auth-remember").set_active(False)
|
||||
else:
|
||||
self.window.get_widget("console-auth-remember").set_active(False)
|
||||
self.window.get_widget("console-auth-remember").set_sensitive(False)
|
||||
self.window.get_widget("console-pages").set_current_page(2)
|
||||
|
||||
def activate_viewer_page(self):
|
||||
|
@ -226,11 +230,9 @@ class vmmConsole(gobject.GObject):
|
|||
self.window.get_widget("menu-vm-run").set_sensitive(False)
|
||||
|
||||
if vm.is_serial_console_tty_accessible():
|
||||
print "Access"
|
||||
self.window.get_widget("control-terminal").set_sensitive(True)
|
||||
self.window.get_widget("menu-vm-terminal").set_sensitive(True)
|
||||
else:
|
||||
print "Denied"
|
||||
self.window.get_widget("control-terminal").set_sensitive(False)
|
||||
self.window.get_widget("menu-vm-terminal").set_sensitive(False)
|
||||
|
||||
|
|
|
@ -16,214 +16,50 @@
|
|||
# along with this program; if not, write to the Free Software
|
||||
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
|
||||
#
|
||||
#
|
||||
# There is no python binding for keyring in FC5 so we use
|
||||
# ctypes to do the magic. This code is scary, but works
|
||||
# pretty well...so far
|
||||
#
|
||||
# XXX audit this code for memory leaks. The gnome-keyring API
|
||||
# docs are non-existant so i've no clue what bits are the callers
|
||||
# responsibility to free() :-(
|
||||
|
||||
import gtk
|
||||
|
||||
from ctypes import *
|
||||
import gobject
|
||||
|
||||
from virtManager.secret import *
|
||||
|
||||
class vmmKeyring:
|
||||
# Map to GnomeKeyringAttribute struct
|
||||
# XXX lame that we have 32 & 64 bit variant
|
||||
# need to get the Union stuff working for the
|
||||
# 'value' field which should solve the padding
|
||||
# problems automagically
|
||||
class Attribute64(Structure):
|
||||
_fields_ =[('name', c_char_p),
|
||||
('type', c_int),
|
||||
('pad', c_int),
|
||||
('value', c_char_p)]
|
||||
class Attribute32(Structure):
|
||||
_fields_ =[('name', c_char_p),
|
||||
('type', c_int),
|
||||
('value', c_char_p)]
|
||||
import sys
|
||||
|
||||
# Hack to map to GArray struct in glib
|
||||
class GArray(Structure):
|
||||
_fields_ = [('data', c_char_p),
|
||||
('len', c_uint)]
|
||||
haveKeyring = False
|
||||
try:
|
||||
import gnomekeyring
|
||||
haveKeyring = True
|
||||
except:
|
||||
print "No support for gnome-keyring"
|
||||
pass
|
||||
|
||||
class vmmKeyring:
|
||||
|
||||
def __init__(self):
|
||||
# Load the two libs we need to play with
|
||||
self.glib = cdll.LoadLibrary("libglib-2.0.so")
|
||||
self.krlib = cdll.LoadLibrary("libgnome-keyring.so")
|
||||
if haveKeyring:
|
||||
self.keyring = gnomekeyring.get_default_keyring_sync()
|
||||
else:
|
||||
self.keyring = None
|
||||
|
||||
# Declare the callback type
|
||||
cbtype = CFUNCTYPE(c_void_p, c_int, c_char_p, c_void_p)
|
||||
self.cb = cbtype(self._get_default_keyring_complete)
|
||||
|
||||
# This gets filled out by callback with keyring name
|
||||
self.keyring = None
|
||||
# Used by callback to store secret info
|
||||
self.secrets = {}
|
||||
|
||||
# Get the keyring name
|
||||
f = self.krlib.gnome_keyring_get_default_keyring(self.cb, None, None)
|
||||
# Block until complete
|
||||
# XXX lame - blocks whole UI
|
||||
gtk.main()
|
||||
|
||||
# User might have denied access
|
||||
def is_available(self):
|
||||
if self.keyring == None:
|
||||
raise "Cannot access default keyring"
|
||||
|
||||
return False
|
||||
return True
|
||||
|
||||
def add_secret(self, secret):
|
||||
# We need to store the attributes in an array
|
||||
g_array_new = self.glib.g_array_new
|
||||
g_array_new.restype = c_void_p
|
||||
|
||||
# XXX remove this lame 32/64 bit fork
|
||||
if sizeof(c_void_p) == 4:
|
||||
attrs = g_array_new(c_int(0), c_int(0), sizeof(c_char_p) + sizeof(c_int) + sizeof(c_char_p))
|
||||
else:
|
||||
attrs = g_array_new(c_int(0), c_int(0), sizeof(c_char_p) + sizeof(c_int) + sizeof(c_int) + sizeof(c_char_p))
|
||||
|
||||
# Key a hold of them so they not immediately garbage collected
|
||||
saveAttrs = {}
|
||||
for key in secret.list_attributes():
|
||||
# Add all attributes to array
|
||||
a = None
|
||||
# XXX remove this lame 32/64 bit fork
|
||||
if sizeof(c_void_p) == 4:
|
||||
a = vmmKeyring.Attribute32(name= c_char_p(key),
|
||||
type= c_int(0),
|
||||
value= c_char_p(str(secret.get_attribute(key))))
|
||||
else:
|
||||
a = vmmKeyring.Attribute64(name= c_char_p(key),
|
||||
type= c_int(0),
|
||||
pad= c_int(0),
|
||||
value= c_char_p(str(secret.get_attribute(key))))
|
||||
saveAttrs[key] = a
|
||||
self.glib.g_array_append_vals(attrs, byref(a), 1)
|
||||
|
||||
# Declare callback type
|
||||
cbaddtype = CFUNCTYPE(c_void_p, c_int, c_int, POINTER(c_int))
|
||||
self.cbadd = cbaddtype(self._add_secret_complete)
|
||||
|
||||
# Fetch handle to our function
|
||||
creator = self.krlib.gnome_keyring_item_create
|
||||
creator.restype = c_void_p
|
||||
# Callback will populate id of the secret in this
|
||||
id = c_int(-1)
|
||||
|
||||
# Now add the secret
|
||||
creator(None, c_int(0), c_char_p(secret.get_name()), attrs, c_char_p(secret.get_secret()), c_int(1), self.cbadd, pointer(id), None)
|
||||
# Block until compelte
|
||||
gtk.main()
|
||||
|
||||
# Release attributes no longer neede
|
||||
self.glib.g_array_free(attrs)
|
||||
|
||||
return id.value
|
||||
id = gnomekeyring.item_create_sync(self.keyring,
|
||||
gnomekeyring.ITEM_GENERIC_SECRET,
|
||||
secret.get_name(),
|
||||
secret.get_attributes(),
|
||||
secret.get_secret(),
|
||||
True)
|
||||
|
||||
return id
|
||||
|
||||
def get_secret(self, id):
|
||||
# Declare the callback type
|
||||
cbgetinfotype = CFUNCTYPE(c_void_p, c_int, c_void_p, POINTER(c_int))
|
||||
self.cbgetinfo = cbgetinfotype(self._get_item_info_complete)
|
||||
item = gnomekeyring.item_get_info_sync(self.keyring, id)
|
||||
|
||||
# Fetch the method we want to call
|
||||
getinfo = self.krlib.gnome_keyring_item_get_info
|
||||
getinfo.restype = c_void_p
|
||||
attrs = gnomekeyring.item_get_attributes_sync(self.keyring, id)
|
||||
|
||||
# We need this in callback
|
||||
i = c_int(id)
|
||||
|
||||
# Fetch the basic info
|
||||
p = getinfo(c_char_p(self.keyring), c_int(id), self.cbgetinfo, pointer(i), None)
|
||||
# Block until done
|
||||
gtk.main()
|
||||
if self.secrets.has_key(id):
|
||||
# Declare callback type
|
||||
cbgetattrstype = CFUNCTYPE(c_void_p, c_int, POINTER(vmmKeyring.GArray), POINTER(c_int))
|
||||
self.cbgetattrs = cbgetattrstype(self._get_item_attrs_complete)
|
||||
|
||||
# Declare function we wnt to call to get attributes
|
||||
getattrs = self.krlib.gnome_keyring_item_get_attributes
|
||||
getattrs.restype = c_void_p
|
||||
|
||||
# Fetch the attrs
|
||||
getattrs(c_char_p(self.keyring), c_int(id), self.cbgetattrs, pointer(i), None)
|
||||
# Block until done
|
||||
gtk.main()
|
||||
|
||||
secret = self.secrets[id]
|
||||
del self.secrets[id]
|
||||
return secret
|
||||
else:
|
||||
return None
|
||||
return vmmSecret(item.get_display_name(), item.get_secret(), attrs)
|
||||
|
||||
|
||||
def clear_secret(self, id):
|
||||
# Declare the callback type
|
||||
cbdeletetype = CFUNCTYPE(c_void_p, c_int, c_void_p)
|
||||
self.cbdelete = cbdeletetype(self._delete_item_complete)
|
||||
gnomekeyring.item_delete_sync(self.keyring, id)
|
||||
|
||||
# Fetch the method we want to call
|
||||
getinfo = self.krlib.gnome_keyring_item_delete
|
||||
getinfo.restype = c_void_p
|
||||
|
||||
# Fetch the basic info
|
||||
p = getinfo(c_char_p(self.keyring), c_int(id), self.cbdelete, None, None)
|
||||
# Block until done
|
||||
gtk.main()
|
||||
|
||||
def _get_default_keyring_complete(self, status, name, data):
|
||||
if status != 0:
|
||||
self.keyring = None
|
||||
gtk.main_quit()
|
||||
return
|
||||
# Save name of default keyring somewhere safe
|
||||
if name == None:
|
||||
name = ""
|
||||
self.keyring = name
|
||||
gtk.main_quit()
|
||||
|
||||
def _add_secret_complete(self, status, id, data):
|
||||
if status != 0:
|
||||
data.contents.value = -1
|
||||
gtk.main_quit()
|
||||
return
|
||||
data.contents.value = id
|
||||
gtk.main_quit()
|
||||
|
||||
def _delete_item_complete(self, status, data):
|
||||
gtk.main_quit()
|
||||
|
||||
def _get_item_info_complete(self, status, info, data=None):
|
||||
if status != 0:
|
||||
gtk.main_quit()
|
||||
return
|
||||
|
||||
getname = self.krlib.gnome_keyring_item_info_get_display_name
|
||||
getname.restype = c_char_p
|
||||
|
||||
getsecret = self.krlib.gnome_keyring_item_info_get_secret
|
||||
getsecret.restype = c_char_p
|
||||
|
||||
name = getname(info)
|
||||
secret = getsecret(info)
|
||||
|
||||
self.secrets[data.contents.value] = vmmSecret(name, secret)
|
||||
|
||||
gtk.main_quit()
|
||||
|
||||
def _get_item_attrs_complete(self, status, attrs, data=None):
|
||||
if status != 0:
|
||||
gtk.main_quit()
|
||||
return
|
||||
|
||||
# XXX @#%$&(#%@ glib has a macro for accessing
|
||||
# elements in array which can obviously can't use
|
||||
# from python. Figure out nasty pointer magic here...
|
||||
|
||||
gtk.main_quit()
|
||||
|
|
|
@ -35,6 +35,12 @@ class vmmSecret:
|
|||
def get_name(self):
|
||||
return self.name
|
||||
|
||||
def get_attributes(self):
|
||||
return self.attributes
|
||||
|
||||
def has_attribute(self, key):
|
||||
return self.attributes.has_key(key)
|
||||
|
||||
def add_attribute(self, key, value):
|
||||
if type(value) != str:
|
||||
value = str(value)
|
||||
|
|
|
@ -28,7 +28,7 @@ Requires: dbus-python >= 0.61
|
|||
# We use 'ctypes' so don't need the 'gnome-keyring-python' bits
|
||||
Requires: gnome-keyring >= 0.4.9
|
||||
# Minimum we've tested with
|
||||
Requires: python-ctypes >= 0.9.9.6
|
||||
Requires: gnome-python-gnomekeyring >= 2.15.4
|
||||
# Minimum we've tested with
|
||||
Requires: libxml2-python >= 2.6.23
|
||||
|
||||
|
|
Loading…
Reference in New Issue