[rs-commit] r35 - in /redwax-signtext/trunk/src/linux: crypto.c crypto.h main.c message.c signtext.c signtext.h

rs-commit at redwax.eu rs-commit at redwax.eu
Mon Sep 5 12:50:21 CEST 2022


Author: minfrin at redwax.eu
Date: Mon Sep  5 12:50:20 2022
New Revision: 35

Log:
Have the UI respond to the pinpad type / pin params for each certificate.

Modified:
    redwax-signtext/trunk/src/linux/crypto.c
    redwax-signtext/trunk/src/linux/crypto.h
    redwax-signtext/trunk/src/linux/main.c
    redwax-signtext/trunk/src/linux/message.c
    redwax-signtext/trunk/src/linux/signtext.c
    redwax-signtext/trunk/src/linux/signtext.h

Modified: redwax-signtext/trunk/src/linux/crypto.c
==============================================================================
--- redwax-signtext/trunk/src/linux/crypto.c	(original)
+++ redwax-signtext/trunk/src/linux/crypto.c	Mon Sep  5 12:50:20 2022
@@ -29,7 +29,7 @@
   GckAttributes *attrs;
   gulong category;
   gboolean is_ca;
-
+return TRUE;
   if (!GCR_IS_PKCS11_CERTIFICATE(obj)) {
     return FALSE;
   }
@@ -88,36 +88,103 @@
   gck_slot_info_free(info);
 }
 
-static void
-crypto_slots_done (GObject *source_object,
-                   GAsyncResult *res,
-                   gpointer user_data)
-{
-  SignTextData *signtext = user_data;
+static gboolean
+crypto_slots_do (
+  gpointer user_data
+);
+
+static void
+crypto_slot_do (gpointer user_data);
+
+static void
+crypto_slot_done (GObject *source_object,
+                  GAsyncResult *res,
+                  gpointer user_data)
+{
+  SignTextToken *signtext_token = user_data;
+  SignTextData *signtext = signtext_token->signtext;
   GList *incoming, *current, *l;
   GError *gerror = NULL;
 
   g_printerr("crypto_slots_done\n");
 
-  current = gcr_collection_get_objects(signtext->certificates);
-
   incoming = gck_enumerator_next_finish(GCK_ENUMERATOR(source_object), res, &gerror);
 
-  for (l = current; l; l = g_list_next (l)) {
-    if (!g_list_find(incoming, l->data)) {
-      gcr_simple_collection_remove(GCR_SIMPLE_COLLECTION(signtext->certificates), l->data);
-      g_object_unref(l->data);
-    }
-  }
-
   for (l = incoming; l; l = g_list_next (l)) {
-    if (!g_list_find(current, l->data)) {
+    if (!gcr_collection_contains(signtext->incoming, l->data)) {
       g_object_ref(l->data);
-      gcr_simple_collection_add(GCR_SIMPLE_COLLECTION(signtext->certificates), l->data);
+      g_object_set_data_full(l->data, "token-info",
+                             gck_token_info_copy(signtext_token->token_info),
+                             (GDestroyNotify)gck_token_info_free);
+      gcr_simple_collection_add(GCR_SIMPLE_COLLECTION(signtext->incoming), l->data);
     }
   }
 
   gck_list_unref_free(incoming);
+
+  if (signtext_token->next) {
+    g_idle_add((GSourceFunc)crypto_slot_do, signtext_token->next);
+  }
+  else {
+
+    incoming = gcr_collection_get_objects(signtext->incoming);
+
+    for (l = incoming; l; l = g_list_next (l)) {
+     if (!gcr_collection_contains(signtext->certificates, l->data)) {
+        g_object_ref(l->data);
+        gcr_simple_collection_add(GCR_SIMPLE_COLLECTION(signtext->certificates), l->data);
+      }
+    }
+
+    current = gcr_collection_get_objects(signtext->certificates);
+
+    for (l = current; l; l = g_list_next (l)) {
+      if (!gcr_collection_contains(signtext->incoming, l->data)) {
+        gcr_simple_collection_remove(GCR_SIMPLE_COLLECTION(signtext->certificates), l->data);
+        g_object_unref(l->data);
+      }
+    }
+
+    g_object_unref(signtext->incoming);
+    signtext->incoming = gcr_simple_collection_new();
+
+    g_timeout_add_seconds(2, crypto_slots_do, signtext_token->signtext);
+  }
+
+  signtext_token_free(signtext_token);
+}
+
+static void
+crypto_slot_do (gpointer user_data)
+{
+  SignTextToken *signtext_token = user_data;
+
+  /*
+   * The minumum you must request to get a certificate back that will display in a dropdown
+   * is CKA_VALUE, CKA_CLASS, CKA_CERTIFICATE_TYPE. Any less than that and you get nothing.
+   *
+   * CKA_CERTIFICATE_CATEGORY tells us if the certificate is a user certificate, or an
+   * intermediate/root.
+   */
+  static const gulong CERTIFICATE_ATTRS[] = {CKA_VALUE, CKA_ID, CKA_LABEL, CKA_CLASS, CKA_CERTIFICATE_TYPE, CKA_CERTIFICATE_CATEGORY, CKA_MODIFIABLE};
+
+  GckEnumerator *cenum;
+
+  GckBuilder builder = GCK_BUILDER_INIT;
+
+  /*
+   * Search for all certificates on a token (ie not in a session).
+   */
+  gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
+  gck_builder_add_ulong(&builder, CKA_CLASS, CKO_CERTIFICATE);
+
+  signtext_token->token_info = gck_slot_get_token_info (signtext_token->slot);
+
+  cenum = gck_slot_enumerate_objects(signtext_token->slot, gck_builder_end (&builder), GCK_SESSION_READ_ONLY);
+
+  gck_enumerator_set_object_type_full(cenum, GCR_TYPE_PKCS11_CERTIFICATE, CERTIFICATE_ATTRS, G_N_ELEMENTS (CERTIFICATE_ATTRS));
+
+  gck_enumerator_next_async(cenum, -1, signtext_token->signtext->cancellable, crypto_slot_done, signtext_token);
 
 }
 
@@ -127,7 +194,7 @@
 )
 {
   SignTextData *signtext = user_data;
-  GList *slots;
+  GList *slots, *l;
 
   guint slots_len = 0;
 
@@ -137,46 +204,46 @@
 
   if (slots_len != signtext->slots_len) {
 
+    SignTextToken *signtext_token = NULL, *st;
+
     g_printerr("crypto_slots_do: %d/%d\n", slots_len, signtext->slots_len);
 
-    /*
-     * The minumum you must request to get a certificate back that will display in a dropdown
-     * is CKA_VALUE, CKA_CLASS, CKA_CERTIFICATE_TYPE. Any less than that and you get nothing.
-     *
-     * CKA_CERTIFICATE_CATEGORY tells us if the certificate is a user certificate, or an
-     * intermediate/root.
-     */
-    static const gulong CERTIFICATE_ATTRS[] = {CKA_VALUE, CKA_ID, CKA_LABEL, CKA_CLASS, CKA_CERTIFICATE_TYPE, CKA_CERTIFICATE_CATEGORY, CKA_MODIFIABLE};
-
-    GckEnumerator *cenum;
-
-    GckBuilder builder = GCK_BUILDER_INIT;
-
-    /*
-     * Search for all certificates on a token (ie not in a session).
-     */
-    gck_builder_add_boolean (&builder, CKA_TOKEN, TRUE);
-    gck_builder_add_ulong(&builder, CKA_CLASS, CKO_CERTIFICATE);
-
-    cenum = gck_modules_enumerate_objects(signtext->modules, gck_builder_end (&builder), GCK_SESSION_READ_ONLY);
-
-    gck_enumerator_set_object_type_full(cenum, GCR_TYPE_PKCS11_CERTIFICATE, CERTIFICATE_ATTRS, G_N_ELEMENTS (CERTIFICATE_ATTRS));
-
-    gck_enumerator_next_async(cenum, -1, signtext->cancellable, crypto_slots_done, signtext);
+    for (l = slots; l; l = g_list_next (l)) {
+
+      GckSlot *slot = GCK_SLOT(l->data);
+
+      st = signtext_token_new();
+
+      st->signtext = signtext;
+      st->slot = slot;
+      //st->token_info = gck_slot_get_token_info (slot);
+      //st->certificates = gcr_simple_collection_new();
+      st->next = signtext_token;
+
+      signtext_token = st;
+
+    }
+
+    g_idle_add((GSourceFunc)crypto_slot_do, signtext_token);
 
     signtext->slots_len = slots_len;
 
-  }
-
-  gck_list_unref_free(slots);
-
-  return TRUE;
+    return FALSE;
+  }
+
+  else {
+    gck_list_unref_free(slots);
+  }
+
+  g_timeout_add_seconds(2, crypto_slots_do, signtext);
+
+  return FALSE;
 }
 
 static void
 crypto_slots_start(SignTextData *signtext)
 {
-  g_timeout_add_seconds(2, crypto_slots_do, signtext);
+  crypto_slots_do(signtext);
 }
 
 static void
@@ -232,4 +299,78 @@
   gck_modules_initialize_registered_async(signtext->cancellable, (GAsyncReadyCallback)crypto_init_done, signtext);
 }
 
-
+void crypto_selector_changed(GcrComboSelector *selector,
+                             gpointer user_data)
+{
+  GObject *selected;
+  SignTextInstance *instance = user_data;
+
+  g_printerr("crypto_selector_changed\n");
+
+  selected = gcr_combo_selector_get_selected(selector);
+
+  if (selected && GCR_IS_PKCS11_CERTIFICATE(selected)) {
+
+    GcrPkcs11Certificate *certificate = GCR_PKCS11_CERTIFICATE(selected);
+
+    GckTokenInfo *token_info = g_object_get_data(G_OBJECT (certificate), "token-info");
+
+    if (token_info) {
+  g_printerr("crypto_selector_changed: token\n");
+
+      gtk_entry_set_max_length(instance->pin, token_info->max_pin_len);
+
+      if (token_info->flags & CKF_PROTECTED_AUTHENTICATION_PATH) {
+        gtk_entry_set_icon_from_icon_name(instance->pin, GTK_ENTRY_ICON_PRIMARY, "accessories-calculator-symbolic");
+        gtk_widget_set_sensitive(GTK_WIDGET(instance->pin), FALSE);
+        gtk_entry_set_placeholder_text(GTK_ENTRY(instance->pin), "Use pinpad to enter PIN");
+        gtk_entry_set_text(GTK_ENTRY(instance->pin), "");
+      }
+      else {
+        gtk_entry_set_icon_from_icon_name(instance->pin, GTK_ENTRY_ICON_PRIMARY, "dialog-password-symbolic");
+        gtk_widget_set_sensitive(GTK_WIDGET(instance->pin), TRUE);
+        gtk_entry_set_placeholder_text(GTK_ENTRY(instance->pin), "Enter your PIN");
+        gtk_entry_set_text(GTK_ENTRY(instance->pin), "");
+      }
+
+      if (!(token_info->flags & CKF_USER_PIN_INITIALIZED)) {
+        gtk_entry_set_icon_from_icon_name(instance->pin, GTK_ENTRY_ICON_PRIMARY, "dialog-error-symbolic");
+        gtk_widget_set_sensitive(GTK_WIDGET(instance->pin), FALSE);   
+        gtk_entry_set_placeholder_text(GTK_ENTRY(instance->pin), "PIN is not initialised");
+      }
+      else if (token_info->flags & CKF_USER_PIN_LOCKED) {
+        gtk_entry_set_icon_from_icon_name(instance->pin, GTK_ENTRY_ICON_PRIMARY, "dialog-error-symbolic");
+        gtk_widget_set_sensitive(GTK_WIDGET(instance->pin), FALSE);
+        gtk_entry_set_placeholder_text(GTK_ENTRY(instance->pin), "PIN is locked");
+      }
+      else if (token_info->flags & CKF_USER_PIN_TO_BE_CHANGED) {
+        gtk_entry_set_icon_from_icon_name(instance->pin, GTK_ENTRY_ICON_PRIMARY, "dialog-unavailable-symbolic");
+        gtk_widget_set_sensitive(GTK_WIDGET(instance->pin), FALSE);   
+        gtk_entry_set_placeholder_text(GTK_ENTRY(instance->pin), "PIN must be changed before use");
+      }
+      else if (token_info->flags & CKF_USER_PIN_FINAL_TRY) {
+        gtk_entry_set_icon_from_icon_name(instance->pin, GTK_ENTRY_ICON_PRIMARY, "dialog-warning-symbolic");
+        gtk_widget_set_sensitive(GTK_WIDGET(instance->pin), TRUE); 
+        gtk_entry_set_placeholder_text(GTK_ENTRY(instance->pin), "Final try on PIN");
+      }
+      else if (token_info->flags & CKF_USER_PIN_COUNT_LOW) {
+        gtk_entry_set_icon_from_icon_name(instance->pin, GTK_ENTRY_ICON_PRIMARY, "dialog-warning-symbolic");
+        gtk_widget_set_sensitive(GTK_WIDGET(instance->pin), TRUE); 
+        gtk_entry_set_placeholder_text(GTK_ENTRY(instance->pin), "PIN retries are low");
+      }
+
+    }
+  }
+
+}
+
+void
+crypto_instance_start(SignTextInstance *instance, GcrCollection *certificates)
+{
+
+  instance->selector = gcr_combo_selector_new(certificates);
+
+  g_signal_connect(instance->selector, "changed", (GCallback)crypto_selector_changed, instance);
+
+}
+

Modified: redwax-signtext/trunk/src/linux/crypto.h
==============================================================================
--- redwax-signtext/trunk/src/linux/crypto.h	(original)
+++ redwax-signtext/trunk/src/linux/crypto.h	Mon Sep  5 12:50:20 2022
@@ -28,6 +28,8 @@
 GcrCollection *
 crypto_filter(GcrCollection *certificates);
 
+void
+crypto_instance_start(SignTextInstance *instance, GcrCollection *certificates);
 
 #endif
 

Modified: redwax-signtext/trunk/src/linux/main.c
==============================================================================
--- redwax-signtext/trunk/src/linux/main.c	(original)
+++ redwax-signtext/trunk/src/linux/main.c	Mon Sep  5 12:50:20 2022
@@ -39,8 +39,6 @@
   g_printerr ("activate\n");
 
   signtext->cancellable = g_cancellable_new();
-
-  signtext->certificates = gcr_simple_collection_new();
 
   signtext->stack = GTK_STACK(gtk_stack_new ());
   gtk_widget_show (GTK_WIDGET(signtext->stack));

Modified: redwax-signtext/trunk/src/linux/message.c
==============================================================================
--- redwax-signtext/trunk/src/linux/message.c	(original)
+++ redwax-signtext/trunk/src/linux/message.c	Mon Sep  5 12:50:20 2022
@@ -151,15 +151,17 @@
     else if (json_node_get_node_type(request) == JSON_NODE_OBJECT) {
 
         GcrCollection *certificates = crypto_filter(signtext->certificates);
+
+        crypto_instance_start(instance, certificates);
  
-        instance->selector = gcr_combo_selector_new(certificates);
-
 #ifdef HAVE_GTK_BOX_APPEND
   	gtk_box_append (instance->box, GTK_WIDGET(instance->textview));
         gtk_box_append (instance->box, GTK_WIDGET(instance->selector));
+        gtk_box_append (instance->box, GTK_WIDGET(instance->pin));
 #else
         gtk_box_pack_start (instance->box, GTK_WIDGET(instance->textview), TRUE, TRUE, 0);
         gtk_box_pack_start (instance->box, GTK_WIDGET(instance->selector), FALSE, FALSE, 0);
+        gtk_box_pack_start (instance->box, GTK_WIDGET(instance->pin), FALSE, FALSE, 0);
 #endif
 
         gtk_stack_add_titled(signtext->stack, GTK_WIDGET (instance->box), instance->uuid, g_uri_get_host(instance->uri));

Modified: redwax-signtext/trunk/src/linux/signtext.c
==============================================================================
--- redwax-signtext/trunk/src/linux/signtext.c	(original)
+++ redwax-signtext/trunk/src/linux/signtext.c	Mon Sep  5 12:50:20 2022
@@ -33,16 +33,36 @@
 
   memset(signtext, 0, sizeof(SignTextData));
 
+  signtext->incoming = gcr_simple_collection_new();
+  signtext->certificates = gcr_simple_collection_new();
+
   return signtext;
 }
 
 void signtext_data_free(SignTextData *data)
 {
   if (data) {
+    if (data->incoming) g_object_unref(data->incoming);
     if (data->certificates) g_object_unref(data->certificates);
     if (data->modules) gck_list_unref_free(data->modules);
+    if (data->slots) gck_list_unref_free(data->slots);
   }
   g_free(data);
+}
+
+SignTextToken *signtext_token_new()
+{
+  SignTextToken *token = g_new (SignTextToken, 1);
+
+  memset(token, 0, sizeof(SignTextToken));
+
+  return token;
+}
+
+void signtext_token_free(SignTextToken *signtext_token)
+{
+  if (signtext_token->token_info) gck_token_info_free(signtext_token->token_info);
+  g_free(signtext_token);
 }
 
 SignTextInstance *signtext_instance_new(gint64 id, const gchar *uuid, GUri *uri)
@@ -63,6 +83,10 @@
   gtk_text_view_set_cursor_visible(instance->textview, FALSE);
   gtk_text_view_set_wrap_mode(instance->textview, GTK_WRAP_WORD_CHAR);
 
+  instance->pin_buffer = gcr_secure_entry_buffer_new();
+  instance->pin = GTK_ENTRY(gtk_entry_new_with_buffer(instance->pin_buffer));
+  gtk_entry_set_visibility(GTK_ENTRY(instance->pin), FALSE);
+  gtk_entry_set_icon_from_icon_name(instance->pin, GTK_ENTRY_ICON_PRIMARY, "dialog-password-symbolic");
   return instance;
 }
 
@@ -73,6 +97,7 @@
     if (instance->uri) g_uri_unref(instance->uri);
     if (instance->textview) g_object_unref(instance->textview);
     if (instance->buffer) g_object_unref(instance->buffer);
+    if (instance->pin) g_object_unref(instance->pin);
   }
   g_free(instance);
 }

Modified: redwax-signtext/trunk/src/linux/signtext.h
==============================================================================
--- redwax-signtext/trunk/src/linux/signtext.h	(original)
+++ redwax-signtext/trunk/src/linux/signtext.h	Mon Sep  5 12:50:20 2022
@@ -51,9 +51,20 @@
   GtkStackSwitcher *switcher;
   GtkStack *stack;
   GList *modules;
+  GList *slots;
+  GcrCollection *incoming;
   GcrCollection *certificates;
   guint slots_len;
 } SignTextData;
+
+typedef struct SignTextToken SignTextToken;
+
+struct SignTextToken {
+  SignTextData *signtext;
+  GckSlot *slot;
+  GckTokenInfo *token_info;
+  SignTextToken *next;
+};
 
 typedef struct SignTextInstance {
   GUri *uri;
@@ -64,10 +75,15 @@
   GtkTextBuffer *buffer;
   GtkTextView *textview;
   GcrComboSelector *selector;
+  GtkEntryBuffer *pin_buffer;
+  GtkEntry *pin;
 } SignTextInstance;
 
 SignTextData *signtext_data_new();
 void signtext_data_free(SignTextData *data);
+
+SignTextToken *signtext_token_new();
+void signtext_token_free(SignTextToken *data);
 
 SignTextInstance *signtext_instance_new(gint64 id, const gchar *uuid, GUri *uri);
 void signtext_instance_free(SignTextInstance *instance);



More information about the rs-commit mailing list