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__ */