diff -urp cups-pk-helper-0.0.3.orig/src/cups.c cups-pk-helper-0.0.3/src/cups.c
--- cups-pk-helper-0.0.3.orig/src/cups.c	2008-11-21 00:04:28.000000000 -0600
+++ cups-pk-helper-0.0.3/src/cups.c	2020-05-13 16:10:11.629062916 -0500
@@ -21,19 +21,23 @@
  *
  */
 
+#include <config.h>
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <unistd.h>
+#define __USE_GNU 1
 #include <fcntl.h>
+#undef __USE_GNU
 #include <errno.h>
 #include <ctype.h>
+#include <grp.h>
+#include <pwd.h>
 #include <sys/wait.h>
 #include <sys/types.h>
 #include <sys/stat.h>
 #include <sys/ioctl.h>
 
-#include <config.h>
-
 #include <glib.h>
 #include <glib/gstdio.h>
 #include <glib/gi18n.h>
@@ -45,6 +49,12 @@
 
 #include "cups.h"
 
+/* This is 0.1 second */
+#define RECONNECT_DELAY        100000
+/* We try to reconnect during 3 seconds. It's still a fairly long time even for
+ * restarting cups, so it should be fine */
+#define MAX_RECONNECT_ATTEMPTS 30
+
 /*
      getPrinters
      getDests
@@ -174,6 +184,25 @@ cph_cups_init (CphCups *cups)
         cups->priv->internal_status = NULL;
 }
 
+static gboolean
+cph_cups_reconnect (CphCups *cups)
+{
+        int return_value = -1;
+        int i;
+
+        for (i = 0; i < MAX_RECONNECT_ATTEMPTS; i++) {
+                return_value = httpReconnect (cups->priv->connection);
+                if (return_value == 0)
+                        break;
+                g_usleep (RECONNECT_DELAY);
+        }
+
+        if (return_value == 0)
+                return TRUE;
+        else
+                return FALSE;
+}
+
 static void
 cph_cups_finalize (GObject *object)
 {
@@ -356,6 +385,84 @@ _CPH_CUPS_IS_VALID (filename, "filename"
  * Helpers
  ******************************************************/
 
+static gboolean
+_cph_cups_set_effective_id (unsigned int   sender_uid,
+                            int           *saved_ngroups,
+                            gid_t        **saved_groups)
+{
+        struct passwd *password_entry;
+        int            ngroups;
+        gid_t         *groups;
+
+        /* avoid g_assert() because we don't want to crash here */
+        if (saved_ngroups == NULL || saved_groups == NULL) {
+                g_critical ("Internal error: cannot save supplementary groups.");
+                return FALSE;
+        }
+
+        *saved_ngroups = -1;
+        *saved_groups = NULL;
+
+        ngroups = getgroups (0, NULL);
+        if (ngroups < 0)
+                return FALSE;
+
+        groups = g_new (gid_t, ngroups);
+        if (groups == NULL && ngroups > 0)
+                return FALSE;
+
+        if (getgroups (ngroups, groups) < 0) {
+                g_free (groups);
+
+                return FALSE;
+        }
+
+        password_entry = getpwuid ((uid_t) sender_uid);
+
+        if (password_entry == NULL ||
+            setegid (password_entry->pw_gid) != 0) {
+                g_free (groups);
+
+                return FALSE;
+        }
+
+        if (initgroups (password_entry->pw_name,
+                        password_entry->pw_gid) != 0) {
+                if (getgid () != getegid ())
+                        setegid (getgid ());
+
+                g_free (groups);
+
+                return FALSE;
+        }
+
+
+        if (seteuid (sender_uid) != 0) {
+                if (getgid () != getegid ())
+                        setegid (getgid ());
+
+                setgroups (ngroups, groups);
+                g_free (groups);
+
+                return FALSE;
+        }
+
+        *saved_ngroups = ngroups;
+        *saved_groups = groups;
+
+        return TRUE;
+}
+
+static void
+_cph_cups_reset_effective_id (int    saved_ngroups,
+                              gid_t *saved_groups)
+{
+        seteuid (getuid ());
+        setegid (getgid ());
+        if (saved_ngroups >= 0)
+                setgroups (saved_ngroups, saved_groups);
+}
+
 static void
 _cph_cups_add_printer_uri (ipp_t      *request,
                            const char *name)
@@ -394,6 +501,21 @@ _cph_cups_set_internal_status (CphCups
 }
 
 static void
+_cph_cups_set_internal_status_from_http (CphCups       *cups,
+                                         http_status_t  status)
+{
+        if (cups->priv->internal_status)
+                g_free (cups->priv->internal_status);
+
+        /* Only 2xx answers are okay */
+        if (status < HTTP_OK ||
+            status >= HTTP_MULTIPLE_CHOICES)
+                cups->priv->internal_status = g_strdup (httpStatus (status));
+        else
+                cups->priv->internal_status = NULL;
+}
+
+static void
 _cph_cups_set_error_from_reply (CphCups *cups,
                                 ipp_t   *reply)
 {
@@ -797,10 +919,18 @@ cph_cups_is_printer_local (CphCups    *c
 }
 
 gboolean
-cph_cups_file_get (CphCups    *cups,
-                   const char *resource,
-                   const char *filename)
-{
+cph_cups_file_get (CphCups      *cups,
+                   const char   *resource,
+                   const char   *filename,
+                   unsigned int  sender_uid)
+{
+        int           saved_ngroups = -1;
+        gid_t        *saved_groups = NULL;
+        http_status_t status;
+        int           fd;
+        struct stat   file_stat;
+        char         *error;
+
         g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
 
         if (!_cph_cups_is_resource_valid (cups, resource))
@@ -808,20 +938,88 @@ cph_cups_file_get (CphCups    *cups,
         if (!_cph_cups_is_filename_valid (cups, filename))
                 return FALSE;
 
+        if (!_cph_cups_set_effective_id (sender_uid,
+                                         &saved_ngroups, &saved_groups)) {
+                error = g_strdup_printf ("Cannot check if \"%s\" is "
+                                         "writable: %s",
+                                         filename, strerror (errno));
+                _cph_cups_set_internal_status (cups, error);
+                g_free (error);
+
+                return FALSE;
+        }
+
+        fd = open (filename, O_WRONLY | O_NOFOLLOW | O_TRUNC);
+
+        _cph_cups_reset_effective_id (saved_ngroups, saved_groups);
+        g_free (saved_groups);
+
+        if (fd < 0) {
+                error = g_strdup_printf ("Cannot open \"%s\": %s",
+                                         filename, strerror (errno));
+                _cph_cups_set_internal_status (cups, error);
+                g_free (error);
+
+                return FALSE;
+        }
+
+
+        if (fstat (fd, &file_stat) != 0) {
+                error = g_strdup_printf ("Cannot write to \"%s\": %s",
+                                         filename, strerror (errno));
+                _cph_cups_set_internal_status (cups, error);
+                g_free (error);
+
+                close (fd);
+
+                return FALSE;
+        }
+
+        if (!S_ISREG (file_stat.st_mode)) {
+                /* hrm, this looks suspicious... we won't help */
+                error = g_strdup_printf ("File \"%s\" is not a regular file.",
+                                         filename);
+                _cph_cups_set_internal_status (cups, error);
+                g_free (error);
+
+                close (fd);
+
+                return FALSE;
+        }
+
         /* reset the internal status: we'll use the cups status */
         _cph_cups_set_internal_status (cups, NULL);
 
-        cups->priv->last_status = cupsGetFile (cups->priv->connection,
-                                               resource, filename);
+        status = cupsGetFd (cups->priv->connection, resource, fd);
 
-        return cups->priv->last_status == HTTP_OK;
+        /* FIXME: There's a bug where the cups connection can fail with EPIPE.
+         * We're working around it here until it's fixed in cups. */
+        if (status != HTTP_OK) {
+                if (cph_cups_reconnect (cups))
+                        status = cupsGetFd (cups->priv->connection,
+                                            resource, fd);
+        }
+
+        close (fd);
+
+        _cph_cups_set_internal_status_from_http (cups, status);
+
+        return (status == HTTP_OK);
 }
 
 gboolean
-cph_cups_file_put (CphCups    *cups,
-                   const char *resource,
-                   const char *filename)
-{
+cph_cups_file_put (CphCups      *cups,
+                   const char   *resource,
+                   const char   *filename,
+                   unsigned int  sender_uid)
+{
+        int           saved_ngroups = -1;
+        gid_t        *saved_groups = NULL;
+        http_status_t status;
+        int           fd;
+        struct stat   file_stat;
+        char         *error;
+
         g_return_val_if_fail (CPH_IS_CUPS (cups), FALSE);
 
         if (!_cph_cups_is_resource_valid (cups, resource))
@@ -829,14 +1027,68 @@ cph_cups_file_put (CphCups    *cups,
         if (!_cph_cups_is_filename_valid (cups, filename))
                 return FALSE;
 
+        if (!_cph_cups_set_effective_id (sender_uid,
+                                         &saved_ngroups, &saved_groups)) {
+                error = g_strdup_printf ("Cannot check if \"%s\" is "
+                                         "readable: %s",
+                                         filename, strerror (errno));
+                _cph_cups_set_internal_status (cups, error);
+                g_free (error);
+
+                return FALSE;
+        }
+
+        fd = open (filename, O_RDONLY);
+
+        _cph_cups_reset_effective_id (saved_ngroups, saved_groups);
+        g_free (saved_groups);
+
+        if (fd < 0) {
+                error = g_strdup_printf ("Cannot open \"%s\": %s",
+                                         filename, strerror (errno));
+                _cph_cups_set_internal_status (cups, error);
+                g_free (error);
+
+                return FALSE;
+        }
+
+        if (fstat (fd, &file_stat) != 0) {
+                error = g_strdup_printf ("Cannot read \"%s\": %s",
+                                         filename, strerror (errno));
+                _cph_cups_set_internal_status (cups, error);
+                g_free (error);
+
+                close (fd);
+
+                return FALSE;
+        }
+
+        if (!S_ISREG (file_stat.st_mode)) {
+                /* hrm, this looks suspicious... we won't help */
+                error = g_strdup_printf ("File \"%s\" is not a regular file.",
+                                         filename);
+                _cph_cups_set_internal_status (cups, error);
+                g_free (error);
+
+                close (fd);
+
+                return FALSE;
+        }
+
         /* reset the internal status: we'll use the cups status */
         _cph_cups_set_internal_status (cups, NULL);
 
-        cups->priv->last_status = cupsPutFile (cups->priv->connection,
-                                               resource, filename);
+        status = cupsPutFd (cups->priv->connection, resource, fd);
+
+        close (fd);
+
+        _cph_cups_set_internal_status_from_http (cups, status);
+
+        /* CUPS is being restarted, so we need to reconnect */
+        cph_cups_reconnect (cups);
 
-        return (cups->priv->last_status == HTTP_OK ||
-                cups->priv->last_status == HTTP_CREATED);
+        return (status == HTTP_OK ||
+                status == HTTP_CREATED);
 }
 
 gboolean
diff -urp cups-pk-helper-0.0.3.orig/src/cups.h cups-pk-helper-0.0.3/src/cups.h
--- cups-pk-helper-0.0.3.orig/src/cups.h	2008-11-20 18:50:42.000000000 -0600
+++ cups-pk-helper-0.0.3/src/cups.h	2020-05-11 15:37:22.558323832 -0500
@@ -60,13 +60,15 @@ gboolean cph_cups_is_class (CphCups    *
 char *cph_cups_printer_get_uri (CphCups    *cups,
                                 const char *printer_name);
 
-gboolean cph_cups_file_get (CphCups    *cups,
-                            const char *resource,
-                            const char *filename);
+gboolean cph_cups_file_get (CphCups      *cups,
+                            const char   *resource,
+                            const char   *filename,
+                            unsigned int  sender_uid);
 
-gboolean cph_cups_file_put (CphCups    *cups,
-                            const char *resource,
-                            const char *filename);
+gboolean cph_cups_file_put (CphCups      *cups,
+                            const char   *resource,
+                            const char   *filename,
+                            unsigned int  sender_uid);
 
 gboolean cph_cups_printer_add (CphCups    *cups,
                                const char *printer_name,
diff -urp cups-pk-helper-0.0.3.orig/src/cups-pk-helper-mechanism.c cups-pk-helper-0.0.3/src/cups-pk-helper-mechanism.c
--- cups-pk-helper-0.0.3.orig/src/cups-pk-helper-mechanism.c	2008-11-21 00:28:20.000000000 -0600
+++ cups-pk-helper-0.0.3/src/cups-pk-helper-mechanism.c	2020-05-11 15:37:22.558323832 -0500
@@ -123,6 +123,7 @@ struct CphMechanismPrivate
         DBusGConnection *system_bus_connection;
         PolKitContext   *pol_ctx;
         CphCups         *cups;
+        DBusGProxy      *dbus_proxy;
 };
 
 static GObject *cph_mechanism_constructor (GType                  type,
@@ -178,6 +179,7 @@ cph_mechanism_init (CphMechanism *mechan
         mechanism->priv = CPH_MECHANISM_GET_PRIVATE (mechanism);
 
         mechanism->priv->cups = NULL;
+	mechanism->priv->dbus_proxy = NULL;
 }
 
 static void
@@ -194,6 +196,10 @@ cph_mechanism_finalize (GObject *object)
                 g_object_unref (mechanism->priv->cups);
         mechanism->priv->cups = NULL;
 
+	if (mechanism->priv->dbus_proxy != NULL)
+                g_object_unref (mechanism->priv->dbus_proxy);
+        mechanism->priv->dbus_proxy = NULL;
+
         G_OBJECT_CLASS (cph_mechanism_parent_class)->finalize (object);
 }
 
@@ -499,6 +505,62 @@ _cph_mechanism_return_error_and_value (C
         dbus_g_method_return (context, error, value);
 }
 
+static gboolean
+_cph_mechanism_ensure_dbus_proxy (CphMechanism *mechanism)
+{
+	if (mechanism->priv->dbus_proxy != NULL)
+		return TRUE;
+
+	mechanism->priv->dbus_proxy = dbus_g_proxy_new_for_name (mechanism->priv->system_bus_connection,
+								 "org.freedesktop.DBus",
+								 "/org/freedesktop/DBus",
+								 "org.freedesktop.DBus");
+	if (mechanism->priv->dbus_proxy == NULL) {
+		g_warning ("Could not get proxy to dbus service user");
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
+static gboolean
+_cph_mechanism_get_sender_uid (CphMechanism          *mechanism,
+                               DBusGMethodInvocation *context,
+                               unsigned int          *sender_uid)
+{
+        GError           *error;
+        const char       *sender;
+	gboolean          ret;
+
+        *sender_uid = 0;
+
+        if (!_cph_mechanism_ensure_dbus_proxy (mechanism))
+		return FALSE;
+
+        sender = dbus_g_method_get_sender (context);
+
+	error = NULL;
+	ret = dbus_g_proxy_call (mechanism->priv->dbus_proxy,
+				 "GetConnectionUnixUser",
+				 &error,
+				 G_TYPE_STRING, &sender,
+				 G_TYPE_INVALID,
+				 G_TYPE_UINT, sender_uid,
+				 G_TYPE_INVALID);
+
+	if (!ret) {
+		if (error)
+                        g_warning ("Could not get unix user: %s", error->message);
+                else
+                        g_warning ("Could not get unix user");
+
+		g_error_free (error);
+		return FALSE;
+	}
+
+	return TRUE;
+}
+
 /* exported methods */
 
 gboolean
@@ -507,14 +569,27 @@ cph_mechanism_file_get (CphMechanism
                         const char            *filename,
                         DBusGMethodInvocation *context)
 {
-        gboolean ret;
+	unsigned int sender_uid;
+        gboolean     ret;
 
         reset_killtimer (mechanism);
 
+        if (!_cph_mechanism_get_sender_uid (mechanism, context, &sender_uid)) {
+                GError *error;
+
+                error = g_error_new (CPH_MECHANISM_ERROR,
+                                     CPH_MECHANISM_ERROR_GENERAL,
+                                     "Cannot determine sender UID");
+		dbus_g_method_return_error (context, error);
+                g_error_free (error);
+
+                return TRUE;
+        }
+
         if (!_check_polkit_for_action (mechanism, context, "server-settings"))
                 return FALSE;
 
-        ret = cph_cups_file_get (mechanism->priv->cups, resource, filename);
+        ret = cph_cups_file_get (mechanism->priv->cups, resource, filename, sender_uid);
         _cph_mechanism_return_error (mechanism, context, !ret);
 
         return TRUE;
@@ -526,14 +601,27 @@ cph_mechanism_file_put (CphMechanism
                         const char            *filename,
                         DBusGMethodInvocation *context)
 {
+	unsigned int sender_uid;
         gboolean ret;
 
         reset_killtimer (mechanism);
 
+        if (!_cph_mechanism_get_sender_uid (mechanism, context, &sender_uid)) {
+                GError *error;
+
+                error = g_error_new (CPH_MECHANISM_ERROR,
+                                     CPH_MECHANISM_ERROR_GENERAL,
+                                     "Cannot determine sender UID");
+		dbus_g_method_return_error (context, error);
+                g_error_free (error);
+
+                return TRUE;
+        }
+
         if (!_check_polkit_for_action (mechanism, context, "server-settings"))
                 return FALSE;
 
-        ret = cph_cups_file_put (mechanism->priv->cups, resource, filename);
+        ret = cph_cups_file_put (mechanism->priv->cups, resource, filename, sender_uid);
         _cph_mechanism_return_error (mechanism, context, !ret);
 
         /* TODO: this is a workaround for bnc#447422
