# HG changeset patch
# User Cole Robinson <crobinso@redhat.com>
# Date 1241723712 14400
# Node ID 5d6dc8af58b592b00035f28334ab1284ae1a0f21
# Parent bec888f2890f7eff9c7d05c46a5059172497dba4
Allow PolicyKit and SASL authentication.
Use openAuth when opening the initial connection: allows PolicyKit and
SASA username/password auth.
diff -r bec888f2890f -r 5d6dc8af58b5 virtinst/cli.py
--- a/virtinst/cli.py Tue May 26 12:43:46 2009 -0400
+++ b/virtinst/cli.py Thu May 07 15:15:12 2009 -0400
@@ -145,6 +145,7 @@
print _("Exiting at user request.")
sys.exit(0)
+# Connection opening helper functions
def getConnection(connect):
if not User.current().has_priv(User.PRIV_CREATE_DOMAIN, connect):
fail(_("Must be root to create Xen guests"))
@@ -152,7 +153,105 @@
fail(_("Could not find usable default libvirt connection."))
logging.debug("Using libvirt URI '%s'" % connect)
- return libvirt.open(connect)
+ return open_connection(connect)
+
+def open_connection(uri):
+ open_flags = 0
+ valid_auth_options = [libvirt.VIR_CRED_AUTHNAME,
+ libvirt.VIR_CRED_PASSPHRASE,
+ libvirt.VIR_CRED_EXTERNAL]
+ authcb = do_creds
+ authcb_data = None
+
+ return libvirt.openAuth(uri, [valid_auth_options, authcb, authcb_data],
+ open_flags)
+
+def do_creds(creds, cbdata):
+ try:
+ return _do_creds(creds, cbdata)
+ except:
+ _util.log_exception("Error in creds callback.")
+ raise
+
+def _do_creds(creds, cbdata_ignore):
+
+ if (len(creds) == 1 and
+ creds[0][0] == libvirt.VIR_CRED_EXTERNAL and
+ creds[0][2] == "PolicyKit"):
+ return _do_creds_polkit(creds[0][1])
+
+ for cred in creds:
+ if cred[0] == libvirt.VIR_CRED_EXTERNAL:
+ return -1
+
+ return _do_creds_authname(creds)
+
+# PolicyKit auth
+def _do_creds_polkit(action):
+ if os.getuid() == 0:
+ logging.debug("Skipping policykit check as root")
+ return 0 # Success
+ logging.debug("Doing policykit for %s" % action)
+
+ import subprocess
+ import commands
+
+ bin_path = "/usr/bin/polkit-auth"
+
+ if not os.path.exists(bin_path):
+ logging.debug("%s not present, skipping polkit auth." % bin_path)
+ return 0
+
+ cmdstr = "%s %s" % (bin_path, "--explicit")
+ output = commands.getstatusoutput(cmdstr)
+ if output[1].count(action):
+ logging.debug("User already authorized for %s." % action)
+ # Hide spurious output from polkit-auth
+ popen_stdout = subprocess.PIPE
+ popen_stderr = subprocess.PIPE
+ else:
+ popen_stdout = None
+ popen_stderr = None
+
+ # Force polkit prompting to be text mode. Not strictly required, but
+ # launching a dialog is overkill.
+ env = os.environ.copy()
+ env["POLKIT_AUTH_FORCE_TEXT"] = "set"
+
+ cmd = [bin_path, "--obtain", action]
+ proc = subprocess.Popen(cmd, env=env, stdout=popen_stdout,
+ stderr=popen_stderr)
+ out, err = proc.communicate()
+
+ if out and popen_stdout:
+ logging.debug("polkit-auth stdout: %s" % out)
+ if err and popen_stderr:
+ logging.debug("polkit-auth stderr: %s" % err)
+
+ return 0
+
+# SASL username/pass auth
+def _do_creds_authname(creds):
+ retindex = 4
+
+ for cred in creds:
+ credtype, prompt, ignore, ignore, ignore = cred
+ prompt += ": "
+
+ res = cred[retindex]
+ if credtype == libvirt.VIR_CRED_AUTHNAME:
+ res = raw_input(prompt)
+ elif credtype == libvirt.VIR_CRED_PASSPHRASE:
+ import getpass
+ res = getpass.getpass(prompt)
+ else:
+ logging.debug("Unknown auth type in creds callback: %d" %
+ credtype)
+ return -1
+
+ cred[retindex] = res
+
+ return 0
#
# Prompting