gnunet-svn
[Top][All Lists]
Advanced

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

[taler-anastasis-gtk] branch master updated: force user to enter TOTP co


From: gnunet
Subject: [taler-anastasis-gtk] branch master updated: force user to enter TOTP code once before proceeding during backup
Date: Wed, 29 Sep 2021 23:32:09 +0200

This is an automated email from the git hooks/post-receive script.

grothoff pushed a commit to branch master
in repository anastasis-gtk.

The following commit(s) were added to refs/heads/master by this push:
     new ba92d27  force user to enter TOTP code once before proceeding during 
backup
ba92d27 is described below

commit ba92d27e5901f5063439914fbce99543cce74238
Author: Christian Grothoff <christian@grothoff.org>
AuthorDate: Wed Sep 29 23:32:06 2021 +0200

    force user to enter TOTP code once before proceeding during backup
---
 contrib/anastasis_gtk_auth_add_totp.glade         |  53 +++++++-
 src/anastasis/Makefile.am                         |   1 +
 src/anastasis/anastasis-gtk_handle-method-totp.c  | 156 +++++++++++++++++++---
 src/anastasis/anastasis-gtk_handle-method-video.c |  70 +++-------
 4 files changed, 210 insertions(+), 70 deletions(-)

diff --git a/contrib/anastasis_gtk_auth_add_totp.glade 
b/contrib/anastasis_gtk_auth_add_totp.glade
index 0809bcc..1d1ce64 100644
--- a/contrib/anastasis_gtk_auth_add_totp.glade
+++ b/contrib/anastasis_gtk_auth_add_totp.glade
@@ -1,5 +1,5 @@
 <?xml version="1.0" encoding="UTF-8"?>
-<!-- Generated with glade 3.38.2
+<!-- Generated with glade 3.38.2 
 
 Copyright (C) 2019-2021 Anastasis SARL
 
@@ -60,7 +60,7 @@ Author: Belen Pena, Christian Grothoff, Dennis Neufeld
               <object class="GtkButton" 
id="anastasis_gtk_b_totp_dialog_btn_ok">
                 <property name="label">gtk-ok</property>
                 <property name="visible">True</property>
-                <property name="sensitive">True</property>
+                <property name="sensitive">False</property>
                 <property name="can-focus">False</property>
                 <property name="can-default">True</property>
                 <property name="has-default">True</property>
@@ -93,8 +93,7 @@ Author: Belen Pena, Christian Grothoff, Dennis Neufeld
                 <property name="can-focus">False</property>
                 <property name="label" translatable="yes">For TOTP 
authentication, you need to set a name for the TOTP secret.
 Then, you must scan the generated QR code with your TOTP App to
-import the TOTP secret it into your TOTP App.
-&lt;b&gt;Make sure to scan the QR code before closing this 
dialog!&lt;/b&gt;</property>
+import the TOTP secret it into your TOTP App.</property>
                 <property name="use-markup">True</property>
               </object>
               <packing>
@@ -173,6 +172,52 @@ import the TOTP secret it into your TOTP App.
                 <property name="expand">False</property>
                 <property name="fill">False</property>
                 <property name="padding">5</property>
+                <property name="position">1</property>
+              </packing>
+            </child>
+            <child>
+              <object class="GtkBox">
+                <property name="visible">True</property>
+                <property name="can-focus">False</property>
+                <property name="orientation">vertical</property>
+                <child>
+                  <object class="GtkLabel">
+                    <property name="visible">True</property>
+                    <property name="can-focus">False</property>
+                    <property name="halign">start</property>
+                    <property name="label" translatable="yes">Confirm that 
your TOTP App works by entering the current code here:</property>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="padding">5</property>
+                    <property name="position">0</property>
+                  </packing>
+                </child>
+                <child>
+                  <object class="GtkEntry" id="totp_entry">
+                    <property name="visible">True</property>
+                    <property name="can-focus">True</property>
+                    <property name="tooltip-text" translatable="yes">Enter the 
8-digit TOTP code. Valid for 30s.</property>
+                    <property name="max-length">9</property>
+                    <property name="activates-default">True</property>
+                    <property name="max-width-chars">9</property>
+                    <property 
name="primary-icon-stock">gtk-dialog-question</property>
+                    <property name="placeholder-text" 
translatable="yes">00000000</property>
+                    <property name="input-purpose">number</property>
+                    <signal name="changed" handler="totp_entry_changed_cb" 
swapped="no"/>
+                  </object>
+                  <packing>
+                    <property name="expand">False</property>
+                    <property name="fill">True</property>
+                    <property name="padding">5</property>
+                    <property name="position">1</property>
+                  </packing>
+                </child>
+              </object>
+              <packing>
+                <property name="expand">False</property>
+                <property name="fill">True</property>
                 <property name="position">2</property>
               </packing>
             </child>
diff --git a/src/anastasis/Makefile.am b/src/anastasis/Makefile.am
index 4e409ab..b27a8af 100644
--- a/src/anastasis/Makefile.am
+++ b/src/anastasis/Makefile.am
@@ -74,6 +74,7 @@ anastasis_gtk_LDADD = \
   -lgnunetcurl \
   -lgnunetjson \
   -ljansson \
+  -lgcrypt \
   -lmicrohttpd \
   -lmagic \
   $(INTLLIBS)
diff --git a/src/anastasis/anastasis-gtk_handle-method-totp.c 
b/src/anastasis/anastasis-gtk_handle-method-totp.c
index 34cdbc4..b85e6d4 100644
--- a/src/anastasis/anastasis-gtk_handle-method-totp.c
+++ b/src/anastasis/anastasis-gtk_handle-method-totp.c
@@ -29,12 +29,98 @@
 #include "anastasis-gtk_helper.h"
 #include "anastasis-gtk_handle-identity-changed.h"
 #include <jansson.h>
+#include <gcrypt.h>
 
+/**
+ * How long is a TOTP code valid?
+ */
+#define TOTP_VALIDITY_PERIOD GNUNET_TIME_relative_multiply ( \
+    GNUNET_TIME_UNIT_SECONDS, 30)
+
+/**
+ * Range of time we allow (plus-minus).
+ */
+#define TIME_INTERVAL_RANGE 2
+
+/**
+ * How long is the shared secret in bytes?
+ */
+#define SECRET_LEN 32
 
 /**
  * Random secret used in the current dialog.
  */
-static char totp[32];
+static char totp_key[SECRET_LEN];
+
+
+/**
+ * Compute TOTP code at current time with offset
+ * @a time_off for the @a key.
+ *
+ * @param time_off offset to apply when computing the code
+ * @return TOTP code at this time
+ */
+static uint64_t
+compute_totp (int time_off)
+{
+  struct GNUNET_TIME_Absolute now;
+  time_t t;
+  uint64_t ctr;
+  uint8_t hmac[20]; /* SHA1: 20 bytes */
+
+  now = GNUNET_TIME_absolute_get ();
+  (void) GNUNET_TIME_round_abs (&now);
+  while (time_off < 0)
+  {
+    now = GNUNET_TIME_absolute_subtract (now,
+                                         TOTP_VALIDITY_PERIOD);
+    time_off++;
+  }
+  while (time_off > 0)
+  {
+    now = GNUNET_TIME_absolute_add (now,
+                                    TOTP_VALIDITY_PERIOD);
+    time_off--;
+  }
+  t = now.abs_value_us / GNUNET_TIME_UNIT_SECONDS.rel_value_us;
+  ctr = GNUNET_htonll (t / 30LLU);
+
+  {
+    gcry_md_hd_t md;
+    const unsigned char *mc;
+
+    GNUNET_assert (GPG_ERR_NO_ERROR ==
+                   gcry_md_open (&md,
+                                 GCRY_MD_SHA1,
+                                 GCRY_MD_FLAG_HMAC));
+    gcry_md_setkey (md,
+                    totp_key,
+                    sizeof (totp_key));
+    gcry_md_write (md,
+                   &ctr,
+                   sizeof (ctr));
+    mc = gcry_md_read (md,
+                       GCRY_MD_SHA1);
+    GNUNET_assert (NULL != mc);
+    memcpy (hmac,
+            mc,
+            sizeof (hmac));
+    gcry_md_close (md);
+  }
+
+  {
+    uint32_t code = 0;
+    int offset;
+
+    offset = hmac[sizeof (hmac) - 1] & 0x0f;
+    for (int count = 0; count < 4; count++)
+      code |= hmac[offset + 3 - count] << (8 * count);
+    code &= 0x7fffffff;
+    /* always use 8 digits (maximum) */
+    code = code % 100000000;
+    return code;
+  }
+}
 
 
 /**
@@ -100,20 +186,20 @@ refresh_totp (GtkBuilder *builder)
   const char *name;
   char *u_name;
   char *uri;
-  char base_sec[sizeof (totp) * 2];
+  char base_sec[sizeof (totp_key) * 2];
   GdkPixbuf *pb;
   GtkImage *img;
 
   gtk_widget_set_sensitive (
     GTK_WIDGET (gtk_builder_get_object (builder,
                                         "anastasis_gtk_b_totp_dialog_btn_ok")),
-    false);
+    FALSE);
   q = GTK_ENTRY (gtk_builder_get_object (builder,
                                          
"anastasis_gtk_b_totp_dialog_name_entry"));
   name = gtk_entry_get_text (q);
   u_name = TALER_urlencode (name);
-  base32enc (totp,
-             sizeof (totp),
+  base32enc (totp_key,
+             sizeof (totp_key),
              base_sec);
   GNUNET_asprintf (&uri,
                    "otpauth://totp/%s?digits=8&secret=%s",
@@ -130,10 +216,6 @@ refresh_totp (GtkBuilder *builder)
     gtk_image_set_from_pixbuf (img,
                                pb);
     g_object_unref (pb);
-    gtk_widget_set_sensitive (
-      GTK_WIDGET (gtk_builder_get_object (builder,
-                                          
"anastasis_gtk_b_totp_dialog_btn_ok")),
-      true);
   }
 }
 
@@ -169,15 +251,15 @@ anastasis_gtk_b_totp_dialog_response_cb (GtkDialog 
*dialog,
                     "type",
                     "totp",
                     "challenge",
-                    GNUNET_JSON_from_data (totp,
-                                           sizeof (totp)),
+                    GNUNET_JSON_from_data (totp_key,
+                                           sizeof (totp_key)),
                     "instructions",
                     name);
   gtk_widget_destroy (GTK_WIDGET (dialog));
   g_object_unref (G_OBJECT (builder));
-  memset (totp,
+  memset (totp_key,
           0,
-          sizeof (totp));
+          sizeof (totp_key));
   AG_freeze ();
   AG_ra = ANASTASIS_redux_action (AG_redux_state,
                                   "add_authentication",
@@ -188,12 +270,56 @@ anastasis_gtk_b_totp_dialog_response_cb (GtkDialog 
*dialog,
 }
 
 
+void
+totp_entry_changed_cb (GtkEntry *entry,
+                       gpointer user_data)
+{
+  GtkBuilder *builder = GTK_BUILDER (user_data);
+  GtkWidget *but;
+  GtkEntry *q;
+  const char *code;
+  unsigned int val;
+  char dummy;
+  bool found = false;
+
+  q = GTK_ENTRY (gtk_builder_get_object (builder,
+                                         "totp_entry"));
+  code = gtk_entry_get_text (q);
+  if (1 != sscanf (code,
+                   "%u%c",
+                   &val,
+                   &dummy))
+    return;
+  for (int i = -TIME_INTERVAL_RANGE;
+       i <= TIME_INTERVAL_RANGE;
+       i++)
+  {
+    if (val == compute_totp (i))
+    {
+      found = true;
+      break;
+    }
+  }
+  if (! found)
+    return;
+  but = GTK_WIDGET (gtk_builder_get_object (builder,
+                                            
"anastasis_gtk_b_totp_dialog_btn_ok"));
+  gtk_widget_set_sensitive (but,
+                            TRUE);
+}
+
+
 void
 anastasis_gtk_b_totp_dialog_name_entry_changed_cb (GtkEntry *entry,
                                                    gpointer user_data)
 {
   GtkBuilder *builder = GTK_BUILDER (user_data);
+  GtkEntry *e;
 
+  /* clear code user already entered, if any */
+  e = GTK_ENTRY (gtk_builder_get_object (builder,
+                                         "totp_entry"));
+  gtk_entry_set_text (e, "");
   refresh_totp (builder);
 }
 
@@ -212,8 +338,8 @@ anastasis_gtk_btn_add_auth_totp_clicked_cb (GObject *object,
   GtkBuilder *builder;
 
   GNUNET_CRYPTO_random_block (GNUNET_CRYPTO_QUALITY_NONCE,
-                              totp,
-                              sizeof (totp));
+                              totp_key,
+                              sizeof (totp_key));
   builder = GNUNET_GTK_get_new_builder ("anastasis_gtk_auth_add_totp.glade",
                                         NULL);
   if (NULL == builder)
diff --git a/src/anastasis/anastasis-gtk_handle-method-video.c 
b/src/anastasis/anastasis-gtk_handle-method-video.c
index 64841b8..a0a6053 100644
--- a/src/anastasis/anastasis-gtk_handle-method-video.c
+++ b/src/anastasis/anastasis-gtk_handle-method-video.c
@@ -19,9 +19,11 @@
 */
 
 /**
- * @file src/anastasis/anastasis-gtk_handle-method-question.c
- * @brief Handle dialogs for security question
+ * @file src/anastasis/anastasis-gtk_handle-method-video.c
+ * @brief Handle dialogs for video authentication
  * @author Christian Grothoff
+ *
+ * FIXME: This implementation is far from complete.
  */
 #include <gnunet/platform.h>
 #include <gnunet/gnunet_util_lib.h>
@@ -39,15 +41,11 @@
  * @param user_data the builder of the dialog
  */
 void
-anastasis_gtk_b_question_dialog_response_cb (GtkDialog *dialog,
-                                             gint response_id,
-                                             gpointer user_data)
+anastasis_gtk_b_video_dialog_response_cb (GtkDialog *dialog,
+                                          gint response_id,
+                                          gpointer user_data)
 {
   GtkBuilder *builder = GTK_BUILDER (user_data);
-  GtkEntry *q;
-  GtkEntry *a;
-  const char *qs;
-  const char *as;
   json_t *args;
 
   if (GTK_RESPONSE_OK != response_id)
@@ -56,19 +54,13 @@ anastasis_gtk_b_question_dialog_response_cb (GtkDialog 
*dialog,
     g_object_unref (G_OBJECT (builder));
     return;
   }
-  q = GTK_ENTRY (gtk_builder_get_object (builder,
-                                         
"anastasis_gtk_b_question_dialog_question_entry"));
-  qs = gtk_entry_get_text (q);
-  a = GTK_ENTRY (gtk_builder_get_object (builder,
-                                         
"anastasis_gtk_b_question_dialog_answer_entry"));
-  as = gtk_entry_get_text (a);
   args = json_pack ("{ s:{s:s, s:o, s:s}}",
                     "authentication_method",
                     "type",
-                    "question",
+                    "video",
                     "challenge",
-                    GNUNET_JSON_from_data (as,
-                                           strlen (as)),
+                    GNUNET_JSON_from_data ("DATA",
+                                           strlen ("DATA")),
                     "instructions",
                     qs);
   gtk_widget_destroy (GTK_WIDGET (dialog));
@@ -86,40 +78,16 @@ anastasis_gtk_b_question_dialog_response_cb (GtkDialog 
*dialog,
 static void
 update_sensitivity (GtkBuilder *builder)
 {
-  GtkEntry *q;
-  GtkEntry *a;
-  const char *qs;
-  const char *as;
-
-  q = GTK_ENTRY (gtk_builder_get_object (builder,
-                                         
"anastasis_gtk_b_question_dialog_question_entry"));
-  qs = gtk_entry_get_text (q);
-  a = GTK_ENTRY (gtk_builder_get_object (builder,
-                                         
"anastasis_gtk_b_question_dialog_answer_entry"));
-  as = gtk_entry_get_text (a);
   gtk_widget_set_sensitive (
     GTK_WIDGET (gtk_builder_get_object (builder,
-                                        
"anastasis_gtk_b_question_dialog_btn_ok")),
-    ( (NULL != qs) &&
-      (0 < strlen (qs)) &&
-      (NULL != as) &&
-      (0 < strlen (as)) ));
+                                        
"anastasis_gtk_b_video_dialog_btn_ok")),
+    FALSE);
 }
 
 
 void
-anastasis_gtk_b_question_dialog_question_entry_changed_cb (GtkEntry *entry,
-                                                           gpointer user_data)
-{
-  GtkBuilder *builder = GTK_BUILDER (user_data);
-
-  update_sensitivity (builder);
-}
-
-
-void
-anastasis_gtk_b_question_dialog_answer_entry_changed_cb (GtkEntry *entry,
-                                                         gpointer user_data)
+anastasis_gtk_b_video_dialog_video_entry_changed_cb (GtkEntry *entry,
+                                                     gpointer user_data)
 {
   GtkBuilder *builder = GTK_BUILDER (user_data);
 
@@ -128,19 +96,19 @@ anastasis_gtk_b_question_dialog_answer_entry_changed_cb 
(GtkEntry *entry,
 
 
 /**
- * Callback invoked if the the "secure question"-button is clicked.
+ * Callback invoked if the the "secure video"-button is clicked.
  *
  * @param object
  * @param user_data unused
  */
 void
-anastasis_gtk_btn_add_auth_question_clicked_cb (GObject *object,
-                                                gpointer user_data)
+anastasis_gtk_btn_add_auth_video_clicked_cb (GObject *object,
+                                             gpointer user_data)
 {
   GtkWidget *ad;
   GtkBuilder *builder;
 
-  builder = GNUNET_GTK_get_new_builder 
("anastasis_gtk_auth_add_question.glade",
+  builder = GNUNET_GTK_get_new_builder ("anastasis_gtk_auth_add_video.glade",
                                         NULL);
   if (NULL == builder)
   {
@@ -148,7 +116,7 @@ anastasis_gtk_btn_add_auth_question_clicked_cb (GObject 
*object,
     return;
   }
   ad = GTK_WIDGET (gtk_builder_get_object (builder,
-                                           "anastasis_gtk_b_question_dialog"));
+                                           "anastasis_gtk_b_video_dialog"));
   {
     GtkWidget *toplevel;
 

-- 
To stop receiving notification emails like this one, please contact
gnunet@gnunet.org.



reply via email to

[Prev in Thread] Current Thread [Next in Thread]