Switched keyring code to use gnomekeyring module. Disable keyring support if not available

This commit is contained in:
berrange@dhcp-5-251.virt.boston.redhat.com 2006-08-15 16:07:17 -04:00
parent ce35ed2b2d
commit 7a52fabd80
6 changed files with 66 additions and 221 deletions

2
README
View File

@ -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

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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)

View File

@ -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