From 6fb96a7f8b2f4b0c488e340628a5b8f49382f9c2 Mon Sep 17 00:00:00 2001 From: John Ferlan Date: Tue, 9 Feb 2016 10:09:44 -0500 Subject: [PATCH] util: Introduce API's for Polkit text authentication Introduce virPolkitAgentCreate and virPolkitAgentDestroy virPolkitAgentCreate will run the polkit pkttyagent image as an asynchronous command in order to handle the local agent authentication via stdin/stdout. The code makes use of the pkttyagent --notify-fd mechanism to let it know when the agent is successfully registered. virPolkitAgentDestroy will close the command effectively reaping our child process --- src/libvirt_private.syms | 2 + src/util/virpolkit.c | 90 +++++++++++++++++++++++++++++++++++++++- src/util/virpolkit.h | 9 ++++ 3 files changed, 100 insertions(+), 1 deletion(-) diff --git a/src/libvirt_private.syms b/src/libvirt_private.syms index 4b40612198..4c53bf42a0 100644 --- a/src/libvirt_private.syms +++ b/src/libvirt_private.syms @@ -2032,6 +2032,8 @@ virPidFileWritePath; # util/virpolkit.h +virPolkitAgentCreate; +virPolkitAgentDestroy; virPolkitCheckAuth; diff --git a/src/util/virpolkit.c b/src/util/virpolkit.c index df707f1a2d..3bb60a5aa3 100644 --- a/src/util/virpolkit.c +++ b/src/util/virpolkit.c @@ -20,6 +20,7 @@ */ #include +#include #if WITH_POLKIT0 # include @@ -27,19 +28,24 @@ #endif #include "virpolkit.h" -#include "vircommand.h" #include "virerror.h" #include "virlog.h" #include "virstring.h" #include "virprocess.h" #include "viralloc.h" #include "virdbus.h" +#include "virfile.h" #define VIR_FROM_THIS VIR_FROM_POLKIT VIR_LOG_INIT("util.polkit"); #if WITH_POLKIT1 + +struct _virPolkitAgent { + virCommandPtr cmd; +}; + /* * virPolkitCheckAuth: * @actionid: permission to check @@ -136,6 +142,74 @@ int virPolkitCheckAuth(const char *actionid, } +/* virPolkitAgentDestroy: + * @cmd: Pointer to the virCommandPtr created during virPolkitAgentCreate + * + * Destroy resources used by Polkit Agent + */ +void +virPolkitAgentDestroy(virPolkitAgentPtr agent) +{ + if (!agent) + return; + + virCommandFree(agent->cmd); + VIR_FREE(agent); +} + +/* virPolkitAgentCreate: + * + * Allocate and setup a polkit agent + * + * Returns a virCommandPtr on success and NULL on failure + */ +virPolkitAgentPtr +virPolkitAgentCreate(void) +{ + virPolkitAgentPtr agent; + virCommandPtr cmd = virCommandNewArgList(PKTTYAGENT, "--process", NULL); + int pipe_fd[2] = {-1, -1}; + struct pollfd pollfd; + int outfd = STDOUT_FILENO; + int errfd = STDERR_FILENO; + + if (!isatty(STDIN_FILENO)) + goto error; + + if (pipe2(pipe_fd, 0) < 0) + goto error; + + if (VIR_ALLOC(agent) < 0) + goto error; + agent->cmd = cmd; + + virCommandAddArgFormat(cmd, "%lld", (long long int) getpid()); + virCommandAddArg(cmd, "--notify-fd"); + virCommandAddArgFormat(cmd, "%d", pipe_fd[1]); + virCommandAddArg(cmd, "--fallback"); + virCommandSetInputFD(cmd, STDIN_FILENO); + virCommandSetOutputFD(cmd, &outfd); + virCommandSetErrorFD(cmd, &errfd); + virCommandPassFD(cmd, pipe_fd[1], VIR_COMMAND_PASS_FD_CLOSE_PARENT); + if (virCommandRunAsync(cmd, NULL) < 0) + goto error; + + pollfd.fd = pipe_fd[0]; + pollfd.events = POLLHUP; + + if (poll(&pollfd, 1, -1) < 0) + goto error; + + return agent; + + error: + VIR_FORCE_CLOSE(pipe_fd[0]); + VIR_FORCE_CLOSE(pipe_fd[1]); + virPolkitAgentDestroy(agent); + return NULL; +} + + #elif WITH_POLKIT0 int virPolkitCheckAuth(const char *actionid, pid_t pid, @@ -254,4 +328,18 @@ int virPolkitCheckAuth(const char *actionid ATTRIBUTE_UNUSED, } +void +virPolkitAgentDestroy(virCommandPtr cmd ATTRIBUTE_UNUSED) +{ + return; /* do nothing */ +} + + +virCommandPtr +virPolkitAgentCreate(void) +{ + virReportError(VIR_ERR_AUTH_FAILED, "%s", + _("polkit text authentication agent unavailable")); + return NULL; +} #endif /* WITH_POLKIT1 */ diff --git a/src/util/virpolkit.h b/src/util/virpolkit.h index 36122d04ed..14ff0730d3 100644 --- a/src/util/virpolkit.h +++ b/src/util/virpolkit.h @@ -23,6 +23,9 @@ # define __VIR_POLKIT_H__ # include "internal.h" +# include "vircommand.h" + +# define PKTTYAGENT "/usr/bin/pkttyagent" int virPolkitCheckAuth(const char *actionid, pid_t pid, @@ -31,4 +34,10 @@ int virPolkitCheckAuth(const char *actionid, const char **details, bool allowInteraction); +typedef struct _virPolkitAgent virPolkitAgent; +typedef virPolkitAgent *virPolkitAgentPtr; + +void virPolkitAgentDestroy(virPolkitAgentPtr cmd); +virPolkitAgentPtr virPolkitAgentCreate(void); + #endif /* __VIR_POLKIT_H__ */