# include "config.h"
#endif
+#define _GNU_SOURCE
+
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <pwd.h>
#include <errno.h>
#include <security/pam_appl.h>
+#include <syslog.h>
+#include <stdarg.h>
#include <polkit/polkit.h>
+static gchar *original_user_name = NULL;
+static gchar *command_line = NULL;
+static struct passwd *pw;
+
#ifndef HAVE_CLEARENV
extern char **environ;
/* ---------------------------------------------------------------------------------------------------- */
+static void
+log_message (gint level,
+ gboolean print_to_stderr,
+ const gchar *format,
+ ...)
+{
+ static gboolean is_log_open = FALSE;
+ va_list var_args;
+ gchar *s;
+ const gchar *cwd;
+ const gchar *tty;
+
+ if (!is_log_open)
+ {
+ openlog ("pkexec",
+ LOG_PID,
+ LOG_AUTHPRIV); /* security/authorization messages (private) */
+ is_log_open = TRUE;
+ }
+
+ va_start (var_args, format);
+ s = g_strdup_vprintf (format, var_args);
+ va_end (var_args);
+
+ cwd = get_current_dir_name ();
+ tty = ttyname (0);
+ if (tty == NULL)
+ tty = "unknown";
+
+ /* first complain to syslog */
+ syslog (level,
+ "%s: %s [USER=%s] [TTY=%s] [CWD=%s] [COMMAND=%s]",
+ original_user_name,
+ s,
+ pw->pw_name,
+ tty,
+ cwd,
+ command_line);
+
+ /* and then on stderr */
+ if (print_to_stderr)
+ g_printerr ("%s\n", s);
+
+ g_free (s);
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
static int
pam_conversation_function (int n,
const struct pam_message **msg,
/* check if it's in /etc/shells */
if (!is_valid_shell (value))
{
- g_printerr ("The value for environment variable SHELL is not included in the\n"
- "/etc/shells file. This incident will be reported. Bailing out.\n");
- /* TODO: syslog */
+ log_message (LOG_CRIT, TRUE,
+ "The value for the SHELL variable was not found the /etc/shells file.");
+ g_printerr ("\n"
+ "This incident has been reported.\n");
goto out;
}
}
strstr (value, "%") != NULL ||
strstr (value, "..") != NULL)
{
- g_printerr ("The value for environment variable %s contains suscipious content\n"
- "indicating an exploit. This incident will be reported. Bailing out.\n",
- key);
- /* TODO: syslog */
+ log_message (LOG_CRIT, TRUE,
+ "The value for environment variable %s contains suscipious content.",
+ key);
+ g_printerr ("\n"
+ "This incident has been reported.\n");
goto out;
}
PolkitDetails *details;
GError *error;
gchar *action_id;
- gchar *command_line;
gchar **exec_argv;
gchar *path;
struct passwd pwstruct;
- struct passwd *pw;
gchar pwbuf[8192];
gchar *s;
const gchar *environment_variables_to_save[] = {
goto out;
}
+ original_user_name = g_strdup (g_get_user_name ());
+
/* First process options and find the command-line to invoke. Avoid using fancy library routines
* that depend on environtment variables since we haven't cleared the environment just yet.
*/
command_line = g_strjoinv (" ", argv + n);
exec_argv = argv + n;
+ /* Look up information about the user we care about - yes, the return
+ * value of this function is a bit funky
+ */
+ rc = getpwnam_r (opt_user, &pwstruct, pwbuf, sizeof pwbuf, &pw);
+ if (rc == 0 && pw == NULL)
+ {
+ g_printerr ("User `%s' does not exist.\n", opt_user);
+ goto out;
+ }
+ else if (pw == NULL)
+ {
+ g_printerr ("Error getting information for user `%s': %s\n", opt_user, g_strerror (rc));
+ goto out;
+ }
+
/* now save the environment variables we care about */
saved_env = g_ptr_array_new ();
for (n = 0; environment_variables_to_save[n] != NULL; n++)
goto out;
}
- /* Look up information about the user we care about - yes, the return
- * value of this function is a bit funky
- */
- rc = getpwnam_r (opt_user, &pwstruct, pwbuf, sizeof pwbuf, &pw);
- if (rc == 0 && pw == NULL)
- {
- g_printerr ("User `%s' does not exist.\n", opt_user);
- goto out;
- }
- else if (pw == NULL)
- {
- g_printerr ("Error getting information for user `%s': %s\n", opt_user, g_strerror (rc));
- goto out;
- }
-
/* Initialize the GLib type system - this is needed to interact with the
* PolicyKit daemon
*/
}
else if (polkit_authorization_result_get_is_challenge (result))
{
- g_printerr ("Authorization requires authentication but no authentication agent was found.\n");
- /* TODO: syslog */
+ g_printerr ("Error executing command as another user: No authentication agent was found.\n");
goto out;
}
else
{
- g_printerr ("Not authorized.\n");
- /* TODO: syslog */
+ log_message (LOG_WARNING, TRUE,
+ "Error executing command as another user: Not authorized");
+ g_printerr ("\n"
+ "This incident has been reported.\n");
goto out;
}
goto out;
}
- /* TODO: syslog */
+ /* Log the fact that we're executing a command */
+ log_message (LOG_NOTICE, FALSE, "Executing command");
/* exec the program */
if (execv (path, exec_argv) != 0)
g_free (path);
g_free (command_line);
g_free (opt_user);
+ g_free (original_user_name);
return ret;
}