Commit 382d68ff authored by Andre Heinecke's avatar Andre Heinecke Committed by Marek Kašík

Use secrets service for cups auth_info

    When a printer requires auth_info (e.g. a printer connected
    over the samba protocol) it is now possible to save the
    credentials necessary for printing if a secrets service
    is available over dbus.
    The auth_info is then stored / loaded from the default
    collection of that secrets service.
    If no such service is available the user is not shown
    the option to remember the password and the behavior
    remains the same as before.

    https://bugzilla.gnome.org/show_bug.cgi?id=674264
parent d5dae5b5
...@@ -124,7 +124,6 @@ VOID:UINT,STRING,UINT ...@@ -124,7 +124,6 @@ VOID:UINT,STRING,UINT
VOID:UINT,UINT VOID:UINT,UINT
VOID:VOID VOID:VOID
OBJECT:OBJECT,INT,INT OBJECT:OBJECT,INT,INT
VOID:POINTER,POINTER,POINTER,POINTER,STRING
VOID:OBJECT,STRING,POINTER,POINTER VOID:OBJECT,STRING,POINTER,POINTER
INT:INT INT:INT
VOID:POINTER,STRING,INT VOID:POINTER,STRING,INT
......
...@@ -47,6 +47,7 @@ struct _GtkPrintBackendPrivate ...@@ -47,6 +47,7 @@ struct _GtkPrintBackendPrivate
GtkPrintBackendStatus status; GtkPrintBackendStatus status;
char **auth_info_required; char **auth_info_required;
char **auth_info; char **auth_info;
gboolean store_auth_info;
}; };
enum { enum {
...@@ -360,7 +361,8 @@ static void request_password (GtkPrintBack ...@@ -360,7 +361,8 @@ static void request_password (GtkPrintBack
gpointer auth_info_default, gpointer auth_info_default,
gpointer auth_info_display, gpointer auth_info_display,
gpointer auth_info_visible, gpointer auth_info_visible,
const gchar *prompt); const gchar *prompt,
gboolean can_store_auth_info);
static void static void
gtk_print_backend_class_init (GtkPrintBackendClass *class) gtk_print_backend_class_init (GtkPrintBackendClass *class)
...@@ -437,9 +439,9 @@ gtk_print_backend_class_init (GtkPrintBackendClass *class) ...@@ -437,9 +439,9 @@ gtk_print_backend_class_init (GtkPrintBackendClass *class)
G_TYPE_FROM_CLASS (class), G_TYPE_FROM_CLASS (class),
G_SIGNAL_RUN_LAST, G_SIGNAL_RUN_LAST,
G_STRUCT_OFFSET (GtkPrintBackendClass, request_password), G_STRUCT_OFFSET (GtkPrintBackendClass, request_password),
NULL, NULL, NULL, NULL, NULL,
_gtk_marshal_VOID__POINTER_POINTER_POINTER_POINTER_STRING, G_TYPE_NONE, 6, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER,
G_TYPE_NONE, 5, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_POINTER, G_TYPE_STRING); G_TYPE_POINTER, G_TYPE_STRING, G_TYPE_BOOLEAN);
} }
static void static void
...@@ -666,12 +668,24 @@ gtk_print_backend_print_stream (GtkPrintBackend *backend, ...@@ -666,12 +668,24 @@ gtk_print_backend_print_stream (GtkPrintBackend *backend,
void void
gtk_print_backend_set_password (GtkPrintBackend *backend, gtk_print_backend_set_password (GtkPrintBackend *backend,
gchar **auth_info_required, gchar **auth_info_required,
gchar **auth_info) gchar **auth_info,
gboolean store_auth_info)
{ {
g_return_if_fail (GTK_IS_PRINT_BACKEND (backend)); g_return_if_fail (GTK_IS_PRINT_BACKEND (backend));
if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password) if (GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password)
GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend, auth_info_required, auth_info); GTK_PRINT_BACKEND_GET_CLASS (backend)->set_password (backend,
auth_info_required,
auth_info,
store_auth_info);
}
static void
store_auth_info_toggled (GtkCheckButton *chkbtn,
gpointer user_data)
{
gboolean *data = (gboolean *) user_data;
*data = gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (chkbtn));
} }
static void static void
...@@ -698,9 +712,9 @@ password_dialog_response (GtkWidget *dialog, ...@@ -698,9 +712,9 @@ password_dialog_response (GtkWidget *dialog,
gint i; gint i;
if (response_id == GTK_RESPONSE_OK) if (response_id == GTK_RESPONSE_OK)
gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info); gtk_print_backend_set_password (backend, priv->auth_info_required, priv->auth_info, priv->store_auth_info);
else else
gtk_print_backend_set_password (backend, priv->auth_info_required, NULL); gtk_print_backend_set_password (backend, priv->auth_info_required, NULL, FALSE);
for (i = 0; i < g_strv_length (priv->auth_info_required); i++) for (i = 0; i < g_strv_length (priv->auth_info_required); i++)
if (priv->auth_info[i] != NULL) if (priv->auth_info[i] != NULL)
...@@ -725,10 +739,11 @@ request_password (GtkPrintBackend *backend, ...@@ -725,10 +739,11 @@ request_password (GtkPrintBackend *backend,
gpointer auth_info_default, gpointer auth_info_default,
gpointer auth_info_display, gpointer auth_info_display,
gpointer auth_info_visible, gpointer auth_info_visible,
const gchar *prompt) const gchar *prompt,
gboolean can_store_auth_info)
{ {
GtkPrintBackendPrivate *priv = backend->priv; GtkPrintBackendPrivate *priv = backend->priv;
GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry; GtkWidget *dialog, *box, *main_box, *label, *icon, *vbox, *entry, *chkbtn;
GtkWidget *focus = NULL; GtkWidget *focus = NULL;
GtkWidget *content_area; GtkWidget *content_area;
gchar *markup; gchar *markup;
...@@ -742,6 +757,7 @@ request_password (GtkPrintBackend *backend, ...@@ -742,6 +757,7 @@ request_password (GtkPrintBackend *backend,
priv->auth_info_required = g_strdupv (ai_required); priv->auth_info_required = g_strdupv (ai_required);
length = g_strv_length (ai_required); length = g_strv_length (ai_required);
priv->auth_info = g_new0 (gchar *, length); priv->auth_info = g_new0 (gchar *, length);
priv->store_auth_info = FALSE;
dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL, dialog = gtk_dialog_new_with_buttons ( _("Authentication"), NULL, GTK_DIALOG_MODAL,
_("_Cancel"), GTK_RESPONSE_CANCEL, _("_Cancel"), GTK_RESPONSE_CANCEL,
...@@ -812,6 +828,16 @@ request_password (GtkPrintBackend *backend, ...@@ -812,6 +828,16 @@ request_password (GtkPrintBackend *backend,
} }
} }
if (can_store_auth_info)
{
chkbtn = gtk_check_button_new_with_mnemonic (_("_Remember password"));
gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (chkbtn), FALSE);
gtk_box_pack_start (GTK_BOX (vbox), chkbtn, FALSE, FALSE, 6);
g_signal_connect (chkbtn, "toggled",
G_CALLBACK (store_auth_info_toggled),
&(priv->store_auth_info));
}
if (focus != NULL) if (focus != NULL)
{ {
gtk_widget_grab_focus (focus); gtk_widget_grab_focus (focus);
......
...@@ -124,12 +124,14 @@ struct _GtkPrintBackendClass ...@@ -124,12 +124,14 @@ struct _GtkPrintBackendClass
gpointer auth_info_default, gpointer auth_info_default,
gpointer auth_info_display, gpointer auth_info_display,
gpointer auth_info_visible, gpointer auth_info_visible,
const gchar *prompt); const gchar *prompt,
gboolean can_store_auth_info);
/* not a signal */ /* not a signal */
void (*set_password) (GtkPrintBackend *backend, void (*set_password) (GtkPrintBackend *backend,
gchar **auth_info_required, gchar **auth_info_required,
gchar **auth_info); gchar **auth_info,
gboolean store_auth_info);
/* Padding for future expansion */ /* Padding for future expansion */
void (*_gtk_reserved1) (void); void (*_gtk_reserved1) (void);
...@@ -162,7 +164,8 @@ void gtk_print_backend_destroy (GtkPrintBackend *pri ...@@ -162,7 +164,8 @@ void gtk_print_backend_destroy (GtkPrintBackend *pri
GDK_AVAILABLE_IN_ALL GDK_AVAILABLE_IN_ALL
void gtk_print_backend_set_password (GtkPrintBackend *backend, void gtk_print_backend_set_password (GtkPrintBackend *backend,
gchar **auth_info_required, gchar **auth_info_required,
gchar **auth_info); gchar **auth_info,
gboolean can_store_auth_info);
/* Backend-only functions for GtkPrintBackend */ /* Backend-only functions for GtkPrintBackend */
......
...@@ -29,12 +29,14 @@ backend_LTLIBRARIES = libprintbackend-cups.la ...@@ -29,12 +29,14 @@ backend_LTLIBRARIES = libprintbackend-cups.la
libprintbackend_cups_la_SOURCES = \ libprintbackend_cups_la_SOURCES = \
gtkprintbackendcups.c \ gtkprintbackendcups.c \
gtkprintercups.c \ gtkprintercups.c \
gtkcupsutils.c gtkcupsutils.c \
gtkcupssecretsutils.c
noinst_HEADERS = \ noinst_HEADERS = \
gtkprintbackendcups.h \ gtkprintbackendcups.h \
gtkprintercups.h \ gtkprintercups.h \
gtkcupsutils.h gtkcupsutils.h \
gtkcupssecretsutils.h
libprintbackend_cups_la_LDFLAGS = -avoid-version -module $(no_undefined) libprintbackend_cups_la_LDFLAGS = -avoid-version -module $(no_undefined)
libprintbackend_cups_la_LIBADD = $(LDADDS) $(CUPS_LIBS) libprintbackend_cups_la_LIBADD = $(LDADDS) $(CUPS_LIBS)
......
This diff is collapsed.
/* gtkcupssecretsutils.h: Helper to use a secrets service for printer passwords
* Copyright (C) 2014 Intevation GmbH
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __GTK_SECRETS_UTILS_H__
#define __GTK_SECRETS_UTILS_H__
#include <glib.h>
#include "gtkcupsutils.h"
G_BEGIN_DECLS
void gtk_cups_secrets_service_query_task (gpointer source_object,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
const gchar *printer_uri,
gchar **auth_info_required);
guint gtk_cups_secrets_service_watch (GBusNameAppearedCallback appeared,
GBusNameVanishedCallback vanished,
gpointer user_data);
void gtk_cups_secrets_service_store (gchar **auth_info,
gchar **auth_info_labels,
const gchar *printer_uri);
G_END_DECLS
#endif /* __GTK_SECRETS_UTILS_H__ */
...@@ -54,6 +54,7 @@ ...@@ -54,6 +54,7 @@
#include "gtkprintercups.h" #include "gtkprintercups.h"
#include "gtkcupsutils.h" #include "gtkcupsutils.h"
#include "gtkcupssecretsutils.h"
#ifdef HAVE_COLORD #ifdef HAVE_COLORD
#include <colord.h> #include <colord.h>
...@@ -153,6 +154,9 @@ struct _GtkPrintBackendCups ...@@ -153,6 +154,9 @@ struct _GtkPrintBackendCups
gchar *avahi_service_browser_paths[2]; gchar *avahi_service_browser_paths[2];
GCancellable *avahi_cancellable; GCancellable *avahi_cancellable;
#endif #endif
gboolean secrets_service_available;
guint secrets_service_watch_id;
GCancellable *secrets_service_cancellable;
}; };
static GObjectClass *backend_parent_class; static GObjectClass *backend_parent_class;
...@@ -213,16 +217,26 @@ static cairo_surface_t * cups_printer_create_cairo_surface (GtkPrinter ...@@ -213,16 +217,26 @@ static cairo_surface_t * cups_printer_create_cairo_surface (GtkPrinter
static void gtk_print_backend_cups_set_password (GtkPrintBackend *backend, static void gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
gchar **auth_info_required, gchar **auth_info_required,
gchar **auth_info); gchar **auth_info,
gboolean store_auth_info);
void overwrite_and_free (gpointer data); void overwrite_and_free (gpointer data);
static gboolean is_address_local (const gchar *address); static gboolean is_address_local (const gchar *address);
static gboolean request_auth_info (gpointer data); static gboolean request_auth_info (gpointer data);
static void lookup_auth_info (gpointer data);
#ifdef HAVE_CUPS_API_1_6 #ifdef HAVE_CUPS_API_1_6
static void avahi_request_printer_list (GtkPrintBackendCups *cups_backend); static void avahi_request_printer_list (GtkPrintBackendCups *cups_backend);
#endif #endif
static void secrets_service_appeared_cb (GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
gpointer user_data);
static void secrets_service_vanished_cb (GDBusConnection *connection,
const gchar *name,
gpointer user_data);
static void static void
gtk_print_backend_cups_register_type (GTypeModule *module) gtk_print_backend_cups_register_type (GTypeModule *module)
{ {
...@@ -780,6 +794,13 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups) ...@@ -780,6 +794,13 @@ gtk_print_backend_cups_init (GtkPrintBackendCups *backend_cups)
#endif #endif
cups_get_local_default_printer (backend_cups); cups_get_local_default_printer (backend_cups);
backend_cups->secrets_service_available = FALSE;
backend_cups->secrets_service_cancellable = g_cancellable_new ();
backend_cups->secrets_service_watch_id =
gtk_cups_secrets_service_watch (secrets_service_appeared_cb,
secrets_service_vanished_cb,
backend_cups);
} }
static void static void
...@@ -815,6 +836,12 @@ gtk_print_backend_cups_finalize (GObject *object) ...@@ -815,6 +836,12 @@ gtk_print_backend_cups_finalize (GObject *object)
g_clear_object (&backend_cups->dbus_connection); g_clear_object (&backend_cups->dbus_connection);
#endif #endif
g_clear_object (&backend_cups->secrets_service_cancellable);
if (backend_cups->secrets_service_watch_id != 0)
{
g_bus_unwatch_name (backend_cups->secrets_service_watch_id);
}
backend_parent_class->finalize (object); backend_parent_class->finalize (object);
} }
...@@ -895,7 +922,8 @@ is_address_local (const gchar *address) ...@@ -895,7 +922,8 @@ is_address_local (const gchar *address)
static void static void
gtk_print_backend_cups_set_password (GtkPrintBackend *backend, gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
gchar **auth_info_required, gchar **auth_info_required,
gchar **auth_info) gchar **auth_info,
gboolean store_auth_info)
{ {
GtkPrintBackendCups *cups_backend = GTK_PRINT_BACKEND_CUPS (backend); GtkPrintBackendCups *cups_backend = GTK_PRINT_BACKEND_CUPS (backend);
GList *l; GList *l;
...@@ -924,7 +952,7 @@ gtk_print_backend_cups_set_password (GtkPrintBackend *backend, ...@@ -924,7 +952,7 @@ gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
gchar *key = g_strconcat (username, "@", hostname, NULL); gchar *key = g_strconcat (username, "@", hostname, NULL);
g_hash_table_insert (cups_backend->auth, key, g_strdup (password)); g_hash_table_insert (cups_backend->auth, key, g_strdup (password));
GTK_NOTE (PRINTING, GTK_NOTE (PRINTING,
g_print ("CUPS backend: storing password for %s\n", key)); g_print ("CUPS backend: caching password for %s\n", key));
} }
g_free (cups_backend->username); g_free (cups_backend->username);
...@@ -947,6 +975,17 @@ gtk_print_backend_cups_set_password (GtkPrintBackend *backend, ...@@ -947,6 +975,17 @@ gtk_print_backend_cups_set_password (GtkPrintBackend *backend,
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
dispatch->request->auth_info[i] = g_strdup (auth_info[i]); dispatch->request->auth_info[i] = g_strdup (auth_info[i]);
} }
/* Save the password if the user requested it */
if (password != NULL && store_auth_info)
{
const gchar *printer_uri =
gtk_cups_request_ipp_get_string (dispatch->request,
IPP_TAG_URI,
"printer-uri");
gtk_cups_secrets_service_store (auth_info, auth_info_required,
printer_uri);
}
dispatch->backend->authentication_lock = FALSE; dispatch->backend->authentication_lock = FALSE;
dispatch->request->need_auth_info = FALSE; dispatch->request->need_auth_info = FALSE;
} }
...@@ -1074,7 +1113,9 @@ request_password (gpointer data) ...@@ -1074,7 +1113,9 @@ request_password (gpointer data)
g_free (printer_name); g_free (printer_name);
g_signal_emit_by_name (dispatch->backend, "request-password", g_signal_emit_by_name (dispatch->backend, "request-password",
auth_info_required, auth_info_default, auth_info_display, auth_info_visible, prompt); auth_info_required, auth_info_default,
auth_info_display, auth_info_visible, prompt,
FALSE); /* Cups password is only cached not stored. */
g_free (prompt); g_free (prompt);
} }
...@@ -1178,6 +1219,98 @@ check_auth_info (gpointer user_data) ...@@ -1178,6 +1219,98 @@ check_auth_info (gpointer user_data)
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
} }
static void
lookup_auth_info_cb (GObject *source_object,
GAsyncResult *res,
gpointer user_data)
{
GTask *task;
GtkPrintCupsDispatchWatch *dispatch;
gchar **auth_info;
GError *error = NULL;
gint i;
task = (GTask *) res;
dispatch = user_data;
auth_info = g_task_propagate_pointer (task, &error);
if (auth_info == NULL)
{
if (error != NULL)
{
GTK_NOTE (PRINTING,
g_print ("Failed to look up auth info: %s\n", error->message));
g_error_free (error);
}
else
{
/* Error note should have been shown by the function causing this */
GTK_NOTE (PRINTING, g_print ("Failed to look up auth info.\n"));
}
dispatch->backend->authentication_lock = FALSE;
g_object_unref (task);
request_auth_info (dispatch);
return;
}
gtk_print_backend_cups_set_password (GTK_PRINT_BACKEND (dispatch->backend),
dispatch->request->auth_info_required, auth_info,
FALSE);
for (i = 0; auth_info[i] != NULL; i++)
{
overwrite_and_free (auth_info[i]);
auth_info[i] = NULL;
}
g_clear_pointer (auth_info, g_free);
g_object_unref (task);
}
static void
lookup_auth_info (gpointer user_data)
{
GtkPrintCupsDispatchWatch *dispatch;
gsize length,
i;
gboolean need_secret_auth_info = FALSE;
const gchar *printer_uri;
dispatch = user_data;
if (dispatch->backend->authentication_lock)
return;
length = g_strv_length (dispatch->request->auth_info_required);
for (i = 0; i < length; i++)
{
if (g_strcmp0 (dispatch->request->auth_info_required[i], "password") == 0)
{
need_secret_auth_info = TRUE;
break;
}
}
g_idle_add (check_auth_info, user_data);
if (dispatch->backend->secrets_service_available && need_secret_auth_info)
{
dispatch->backend->authentication_lock = TRUE;
printer_uri = gtk_cups_request_ipp_get_string (dispatch->request,
IPP_TAG_URI,
"printer-uri");
gtk_cups_secrets_service_query_task (dispatch->backend,
dispatch->backend->secrets_service_cancellable,
lookup_auth_info_cb,
dispatch,
printer_uri,
dispatch->request->auth_info_required);
return;
}
request_auth_info (user_data);
}
static gboolean static gboolean
request_auth_info (gpointer user_data) request_auth_info (gpointer user_data)
{ {
...@@ -1254,7 +1387,8 @@ request_auth_info (gpointer user_data) ...@@ -1254,7 +1387,8 @@ request_auth_info (gpointer user_data)
auth_info_default, auth_info_default,
auth_info_display, auth_info_display,
auth_info_visible, auth_info_visible,
prompt); prompt,
dispatch->backend->secrets_service_available);
for (i = 0; i < length; i++) for (i = 0; i < length; i++)
{ {
...@@ -1267,8 +1401,6 @@ request_auth_info (gpointer user_data) ...@@ -1267,8 +1401,6 @@ request_auth_info (gpointer user_data)
g_free (printer_name); g_free (printer_name);
g_free (prompt); g_free (prompt);
g_idle_add (check_auth_info, user_data);
return FALSE; return FALSE;
} }
...@@ -1469,7 +1601,7 @@ cups_request_execute (GtkPrintBackendCups *print_backend, ...@@ -1469,7 +1601,7 @@ cups_request_execute (GtkPrintBackendCups *print_backend,
{ {
dispatch->callback = callback; dispatch->callback = callback;
dispatch->callback_data = user_data; dispatch->callback_data = user_data;
request_auth_info (dispatch); lookup_auth_info (dispatch);
} }
else else
{ {
...@@ -5924,3 +6056,24 @@ cups_printer_get_capabilities (GtkPrinter *printer) ...@@ -5924,3 +6056,24 @@ cups_printer_get_capabilities (GtkPrinter *printer)
return capabilities; return capabilities;
} }
static void
secrets_service_appeared_cb (GDBusConnection *connection,
const gchar *name,
const gchar *name_owner,
gpointer user_data)
{
GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
backend->secrets_service_available = TRUE;
}
static void
secrets_service_vanished_cb (GDBusConnection *connection,
const gchar *name,
gpointer user_data)
{
GtkPrintBackendCups *backend = GTK_PRINT_BACKEND_CUPS (user_data);
backend->secrets_service_available = FALSE;
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment