[network-manager-applet/lr/pkcs11: 13/17] libnma: add PKCS#11 login dialog



commit 72eab7c9a9da7ab6eb55bfa7e3f866529cec5b41
Author: Lubomir Rintel <lkundrak v3 sk>
Date:   Fri Feb 24 18:13:28 2017 +0100

    libnma: add PKCS#11 login dialog
    
    Unlock a PKCS#11 with a PIN. Will be useful for PKCS#11 certificate
    chooser.

 Makefile.am                                 |   15 ++-
 po/POTFILES.in                              |    2 +
 src/libnma/nma-pkcs11-token-login-dialog.c  |  250 +++++++++++++++++++++++++++
 src/libnma/nma-pkcs11-token-login-dialog.h  |   57 ++++++
 src/libnma/nma-pkcs11-token-login-dialog.ui |  111 ++++++++++++
 src/libnma/nma.gresource.xml                |    1 +
 6 files changed, 434 insertions(+), 2 deletions(-)
---
diff --git a/Makefile.am b/Makefile.am
index 4c5895e..b693d6b 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -499,6 +499,14 @@ libnma_c_real = \
 libnma_h_priv_real = \
        src/libnma/nma-file-cert-chooser.h
 
+if WITH_GCR
+libnma_h_priv_real += \
+       src/libnma/nma-pkcs11-token-login-dialog.h
+
+libnma_c_real += \
+       src/libnma/nma-pkcs11-token-login-dialog.c
+endif
+
 src_libnma_libnmadir = $(includedir)/libnma
 
 src_libnma_libnma_HEADERS = \
@@ -566,6 +574,7 @@ EXTRA_DIST += \
        src/libnma/libnma.pc.in \
        src/libnma/libnma.ver \
        src/libnma/wifi.ui \
+       src/libnma/nma-pkcs11-token-login-dialog.ui \
        src/libnma/nma.gresource.xml
 
 ###############################################################################
@@ -863,11 +872,13 @@ CFILE_GLOB = $(top_srcdir)/src/libnma/*.c
 IGNORE_HFILES = \
        nma-resources.h \
        nma-version.h \
-       nma-file-cert-chooser.h
+       nma-file-cert-chooser.h \
+       nma-pkcs11-token-login-dialog.h
 
 mkdb_ignore_c_files = \
        nma-resources.c \
-       nma-file-cert-chooser.c
+       nma-file-cert-chooser.c \
+       nma-pkcs11-token-login-dialog.c
 
 MKDB_OPTIONS = --ignore-files "$(IGNORE_HFILES) $(mkdb_ignore_c_files)"
 
diff --git a/po/POTFILES.in b/po/POTFILES.in
index 983b3ef..a735f38 100644
--- a/po/POTFILES.in
+++ b/po/POTFILES.in
@@ -78,6 +78,8 @@ src/ethernet-dialog.c
 src/libnma/nma-file-cert-chooser.c
 src/libnma/nma-mobile-providers.c
 src/libnma/nma-mobile-wizard.c
+src/libnma/nma-pkcs11-token-login-dialog.c
+[type: gettext/glade]src/libnma/nma-pkcs11-token-login-dialog.ui
 src/libnma/nma-ui-utils.c
 src/libnma/nma-vpn-password-dialog.c
 src/libnma/nma-wifi-dialog.c
diff --git a/src/libnma/nma-pkcs11-token-login-dialog.c b/src/libnma/nma-pkcs11-token-login-dialog.c
new file mode 100644
index 0000000..963e710
--- /dev/null
+++ b/src/libnma/nma-pkcs11-token-login-dialog.c
@@ -0,0 +1,250 @@
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Lubomir Rintel <lkundrak v3 sk>
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2016,2017 Red Hat, Inc.
+ */
+
+#include "nm-default.h"
+#include "nma-pkcs11-token-login-dialog.h"
+
+#include <gck/gck.h>
+
+/**
+ * SECTION:nma-pkcs11-token-login-dialog
+ * @title: NMAPkcs11TokenLoginDialog
+ * @short_description: The PKCS\#11 PIN Dialog
+ * @see_also: #GcrObjectChooserDialog
+ *
+ * #NMAPkcs11TokenLoginDialog asks for the PKCS\#11 login PIN.
+ * It enforces the PIN constrains (maximum & minimum length).
+ *
+ * Used by the #GcrObjectChooserDialog when the #GcrTokensSidebar indicates
+ * that the user requested the token to be logged in.
+ */
+
+struct _NMAPkcs11TokenLoginDialogPrivate
+{
+       GckSlot *slot;
+       GckTokenInfo *info;
+
+       GtkEntry *pin_entry;
+       GtkCheckButton *remember;
+};
+
+G_DEFINE_TYPE_WITH_CODE (NMAPkcs11TokenLoginDialog, nma_pkcs11_token_login_dialog, GTK_TYPE_DIALOG,
+                         G_ADD_PRIVATE (NMAPkcs11TokenLoginDialog));
+
+enum
+{
+       PROP_0,
+       PROP_TOKEN_SLOT,
+};
+
+/**
+ * nma_pkcs11_token_login_dialog_get_pin_value:
+ * @self: The #NMAPkcs11TokenLoginDialog
+ *
+ * Returns: the entered PIN
+ */
+
+const guchar *
+nma_pkcs11_token_login_dialog_get_pin_value (NMAPkcs11TokenLoginDialog *self)
+{
+       NMAPkcs11TokenLoginDialogPrivate *priv = self->priv;
+       GtkEntryBuffer *buffer = gtk_entry_get_buffer (priv->pin_entry);
+
+       return (guchar *) gtk_entry_buffer_get_text (buffer);
+}
+
+/**
+ * nma_pkcs11_token_login_dialog_get_pin_length:
+ * @self: The #NMAPkcs11TokenLoginDialog
+ *
+ * Returns: the PIN length
+ */
+
+gulong
+nma_pkcs11_token_login_dialog_get_pin_length (NMAPkcs11TokenLoginDialog *self)
+{
+       NMAPkcs11TokenLoginDialogPrivate *priv = self->priv;
+       GtkEntryBuffer *buffer = gtk_entry_get_buffer (priv->pin_entry);
+
+       return gtk_entry_buffer_get_bytes (buffer);
+}
+
+/**
+ * nma_pkcs11_token_login_dialog_get_remember_pin:
+ * @self: The #NMAPkcs11TokenLoginDialog
+ *
+ * Returns: %TRUE if the "Remember PIN" checkbox was checked
+ */
+
+gboolean
+nma_pkcs11_token_login_dialog_get_remember_pin (NMAPkcs11TokenLoginDialog *self)
+{
+       NMAPkcs11TokenLoginDialogPrivate *priv = self->priv;
+
+       return gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (priv->remember));
+}
+
+static void
+get_property (GObject *object, guint prop_id, GValue *value, GParamSpec *pspec)
+{
+       NMAPkcs11TokenLoginDialog *self = NMA_PKCS11_TOKEN_LOGIN_DIALOG (object);
+       NMAPkcs11TokenLoginDialogPrivate *priv = self->priv;
+
+       switch (prop_id) {
+       case PROP_TOKEN_SLOT:
+               if (priv->slot)
+                       g_value_set_object (value, priv->slot);
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static gboolean
+can_activate (NMAPkcs11TokenLoginDialog *self)
+{
+       NMAPkcs11TokenLoginDialogPrivate *priv = self->priv;
+       GtkEntryBuffer *buffer = gtk_entry_get_buffer (priv->pin_entry);
+       guint len = gtk_entry_buffer_get_length (buffer);
+
+       return len <= priv->info->max_pin_len && len >= priv->info->min_pin_len;
+}
+
+static void
+set_slot (NMAPkcs11TokenLoginDialog *self, GckSlot *slot)
+{
+       NMAPkcs11TokenLoginDialogPrivate *priv = self->priv;
+       gchar *title;
+
+       g_clear_object (&priv->slot);
+       if (priv->info)
+               gck_token_info_free (priv->info);
+
+       priv->slot = slot;
+       priv->info = gck_slot_get_token_info (slot);
+       g_return_if_fail (priv->info);
+
+       title = g_strdup_printf (_("Enter %s PIN"), priv->info->label);
+       gtk_window_set_title (GTK_WINDOW (self), title);
+       g_free (title);
+
+       gtk_entry_set_max_length (priv->pin_entry, priv->info->max_pin_len);
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (self), GTK_RESPONSE_ACCEPT,
+                                          can_activate (self));
+}
+
+
+static void
+set_property (GObject *object, guint prop_id, const GValue *value, GParamSpec *pspec)
+{
+       NMAPkcs11TokenLoginDialog *self = NMA_PKCS11_TOKEN_LOGIN_DIALOG (object);
+
+       switch (prop_id) {
+       case PROP_TOKEN_SLOT:
+               set_slot (self, g_value_dup_object (value));
+               break;
+       default:
+               G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+       }
+}
+
+static void
+finalize (GObject *object)
+{
+       NMAPkcs11TokenLoginDialog *self = NMA_PKCS11_TOKEN_LOGIN_DIALOG (object);
+       NMAPkcs11TokenLoginDialogPrivate *priv = self->priv;
+
+       g_clear_object (&priv->slot);
+       if (priv->info) {
+               gck_token_info_free (priv->info);
+               priv->info = NULL;
+       }
+
+       G_OBJECT_CLASS (nma_pkcs11_token_login_dialog_parent_class)->finalize (object);
+}
+
+static void
+pin_changed (GtkEditable *editable, gpointer user_data)
+{
+       gtk_dialog_set_response_sensitive (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT,
+                                          can_activate (NMA_PKCS11_TOKEN_LOGIN_DIALOG (user_data)));
+}
+
+
+static void
+pin_activate (GtkEditable *editable, gpointer user_data)
+{
+       if (can_activate (NMA_PKCS11_TOKEN_LOGIN_DIALOG (user_data)))
+               gtk_dialog_response (GTK_DIALOG (user_data), GTK_RESPONSE_ACCEPT);
+}
+
+static void
+nma_pkcs11_token_login_dialog_class_init (NMAPkcs11TokenLoginDialogClass *klass)
+{
+       GObjectClass *object_class = G_OBJECT_CLASS (klass);
+       GtkWidgetClass *widget_class = GTK_WIDGET_CLASS (klass);
+
+       object_class->get_property = get_property;
+       object_class->set_property = set_property;
+       object_class->finalize = finalize;
+
+       /**
+        * NMAPkcs11TokenLoginDialog::token-slot:
+        *
+        * Slot that contains the pin for which the dialog requests
+        * the PIN.
+        */
+       g_object_class_install_property (object_class, PROP_TOKEN_SLOT,
+               g_param_spec_object ("token-slot", "Slot", "Slot containing the Token",
+                                    GCK_TYPE_SLOT, G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
+
+       gtk_widget_class_set_template_from_resource (widget_class, 
"/org/freedesktop/network-manager-applet/nma-pkcs11-token-login-dialog.ui");
+       gtk_widget_class_bind_template_child_private (widget_class, NMAPkcs11TokenLoginDialog, pin_entry);
+       gtk_widget_class_bind_template_child_private (widget_class, NMAPkcs11TokenLoginDialog, remember);
+       gtk_widget_class_bind_template_callback (widget_class, pin_changed);
+       gtk_widget_class_bind_template_callback (widget_class, pin_activate);
+}
+
+static void
+nma_pkcs11_token_login_dialog_init (NMAPkcs11TokenLoginDialog *self)
+{
+       self->priv = nma_pkcs11_token_login_dialog_get_instance_private (self);
+
+       gtk_widget_init_template (GTK_WIDGET (self));
+}
+
+/**
+ * nma_pkcs11_token_login_dialog_new:
+ * @slot: Slot that contains the pin for which the dialog requests the PIN
+ *
+ * Creates the new PKCS\#11 login dialog.
+ *
+ * Returns: the newly created #NMAPkcs11TokenLoginDialog
+ */
+GtkWidget *
+nma_pkcs11_token_login_dialog_new (GckSlot *slot)
+{
+       return GTK_WIDGET (g_object_new (NMA_TYPE_PKCS11_TOKEN_LOGIN_DIALOG,
+                          "use-header-bar", TRUE,
+                          "token-slot", slot,
+                          NULL));
+}
diff --git a/src/libnma/nma-pkcs11-token-login-dialog.h b/src/libnma/nma-pkcs11-token-login-dialog.h
new file mode 100644
index 0000000..9cc83d4
--- /dev/null
+++ b/src/libnma/nma-pkcs11-token-login-dialog.h
@@ -0,0 +1,57 @@
+/* NetworkManager Applet -- allow user control over networking
+ *
+ * Lubomir Rintel <lkundrak v3 sk>
+ *
+ * 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, write to the
+ * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301 USA.
+ *
+ * Copyright (C) 2017 Red Hat, Inc.
+ */
+
+#ifndef __NMA_PKCS11_TOKEN_LOGIN_DIALOG_H__
+#define __NMA_PKCS11_TOKEN_LOGIN_DIALOG_H__
+
+#include <gtk/gtk.h>
+#include <gck/gck.h>
+
+typedef struct _NMAPkcs11TokenLoginDialogPrivate NMAPkcs11TokenLoginDialogPrivate;
+
+typedef struct {
+        GtkDialog parent;
+        NMAPkcs11TokenLoginDialogPrivate *priv;
+} NMAPkcs11TokenLoginDialog;
+
+typedef struct {
+        GtkDialog parent;
+} NMAPkcs11TokenLoginDialogClass;
+
+#define NMA_TYPE_PKCS11_TOKEN_LOGIN_DIALOG            (nma_pkcs11_token_login_dialog_get_type ())
+#define NMA_PKCS11_TOKEN_LOGIN_DIALOG(obj)            (G_TYPE_CHECK_INSTANCE_CAST ((obj), 
NMA_TYPE_PKCS11_TOKEN_LOGIN_DIALOG, NMAPkcs11TokenLoginDialog))
+#define NMA_PKCS11_TOKEN_LOGIN_DIALOG_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST ((klass), 
NMA_TYPE_PKCS11_TOKEN_LOGIN_DIALOG, NMAPkcs11TokenLoginDialogClass))
+#define NMA_IS_PKCS11_TOKEN_LOGIN_DIALOG(obj)         (G_TYPE_CHECK_INSTANCE_TYPE ((obj), 
NMA_TYPE_PKCS11_TOKEN_LOGIN_DIALOG))
+#define NMA_IS_PKCS11_TOKEN_LOGIN_DIALOG_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), 
NMA_TYPE_PKCS11_TOKEN_LOGIN_DIALOG))
+#define NMA_PKCS11_TOKEN_LOGIN_DIALOG_GET_CLASS(obj)  (G_TYPE_INSTANCE_GET_CLASS ((obj), 
NMA_TYPE_PKCS11_TOKEN_LOGIN_DIALOG, NMAPkcs11TokenLoginDialogClass))
+
+GType nma_pkcs11_token_login_dialog_get_type (void);
+
+GtkWidget *nma_pkcs11_token_login_dialog_new (GckSlot *slot);
+
+const guchar *nma_pkcs11_token_login_dialog_get_pin_value (NMAPkcs11TokenLoginDialog *self);
+
+gulong nma_pkcs11_token_login_dialog_get_pin_length (NMAPkcs11TokenLoginDialog *self);
+
+gboolean nma_pkcs11_token_login_dialog_get_remember_pin (NMAPkcs11TokenLoginDialog *self);
+
+#endif /* __NMA_PKCS11_TOKEN_LOGIN_DIALOG_H__ */
diff --git a/src/libnma/nma-pkcs11-token-login-dialog.ui b/src/libnma/nma-pkcs11-token-login-dialog.ui
new file mode 100644
index 0000000..fc9784b
--- /dev/null
+++ b/src/libnma/nma-pkcs11-token-login-dialog.ui
@@ -0,0 +1,111 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- Generated with glade 3.20.0 -->
+<interface>
+  <requires lib="gtk+" version="3.20"/>
+  <template class="NMAPkcs11TokenLoginDialog" parent="GtkDialog">
+    <property name="can_focus">False</property>
+    <property name="type_hint">dialog</property>
+    <child internal-child="vbox">
+      <object class="GtkBox">
+        <property name="can_focus">False</property>
+        <property name="orientation">vertical</property>
+        <property name="spacing">2</property>
+        <child internal-child="action_area">
+          <object class="GtkButtonBox">
+            <property name="can_focus">False</property>
+            <property name="layout_style">end</property>
+            <child>
+              <object class="GtkButton" id="cancel">
+                <property name="label" translatable="yes">_Cancel</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="pack_type">end</property>
+                <property name="position">0</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkButton" id="login">
+                <property name="label" translatable="yes">_Login</property>
+                <property name="visible">True</property>
+                <property name="can_focus">False</property>
+                <property name="can_default">True</property>
+                <property name="receives_default">False</property>
+                <property name="use_underline">True</property>
+              </object>
+              <packing>
+                <property name="expand">True</property>
+                <property name="fill">True</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">False</property>
+            <property name="position">0</property>
+          </packing>
+        </child>
+        <child>
+          <object class="GtkBox">
+            <property name="visible">True</property>
+            <property name="can_focus">False</property>
+            <property name="margin_left">12</property>
+            <property name="margin_right">12</property>
+            <property name="margin_top">12</property>
+            <property name="margin_bottom">12</property>
+            <property name="orientation">vertical</property>
+            <child>
+              <object class="GtkEntry" id="pin_entry">
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="visibility">False</property>
+                <property name="input_purpose">password</property>
+                <signal name="activate" handler="pin_activate" swapped="no"/>
+                <signal name="changed" handler="pin_changed" swapped="no"/>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">6</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkCheckButton" id="remember">
+                <property name="label" translatable="yes">_Remember PIN</property>
+                <property name="visible">True</property>
+                <property name="can_focus">True</property>
+                <property name="receives_default">False</property>
+                <property name="halign">start</property>
+                <property name="use_underline">True</property>
+                <property name="draw_indicator">True</property>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
+                <property name="padding">6</property>
+                <property name="position">2</property>
+              </packing>
+            </child>
+          </object>
+          <packing>
+            <property name="expand">False</property>
+            <property name="fill">True</property>
+            <property name="position">1</property>
+          </packing>
+        </child>
+      </object>
+    </child>
+    <action-widgets>
+      <action-widget response="-6">cancel</action-widget>
+      <action-widget response="-3">login</action-widget>
+    </action-widgets>
+  </template>
+</interface>
diff --git a/src/libnma/nma.gresource.xml b/src/libnma/nma.gresource.xml
index a8a181e..a9133e4 100644
--- a/src/libnma/nma.gresource.xml
+++ b/src/libnma/nma.gresource.xml
@@ -2,5 +2,6 @@
 <gresources>
        <gresource prefix="/org/freedesktop/network-manager-applet">
                <file preprocess="xml-stripblanks">wifi.ui</file>
+               <file preprocess="xml-stripblanks">nma-pkcs11-token-login-dialog.ui</file>
        </gresource>
 </gresources>


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]