anastasis-gtk

Demonstrator GUI for Anastasis
Log | Files | Refs | README | LICENSE

anastasis-gtk_handle-main-window-forward-clicked.c (13134B)


      1 /*
      2      This file is part of anastasis-gtk.
      3      Copyright (C) 2020, 2021 Anastasis SARL
      4 
      5      Anastasis is free software; you can redistribute it and/or modify
      6      it under the terms of the GNU General Public License as published
      7      by the Free Software Foundation; either version 3, or (at your
      8      option) any later version.
      9 
     10      Anastasis is distributed in the hope that it will be useful, but
     11      WITHOUT ANY WARRANTY; without even the implied warranty of
     12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
     13      General Public License for more details.
     14 
     15      You should have received a copy of the GNU General Public License
     16      along with Anastasis; see the file COPYING.  If not, write to the
     17      Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
     18      Boston, MA 02110-1301, USA.
     19 */
     20 /**
     21  * @file src/anastasis/anastasis-gtk_handle-main-window-forward-clicked.c
     22  * @brief
     23  * @author Christian Grothoff
     24  * @author Dennis Neufeld
     25  */
     26 #include "anastasis_gtk_config.h"
     27 #define HAVE_USED_CONFIG_H 1
     28 
     29 #include <gnunet/gnunet_util_lib.h>
     30 #include "anastasis_gtk_util.h"
     31 #include "anastasis-gtk_action.h"
     32 #include "anastasis-gtk_attributes.h"
     33 #include "anastasis-gtk_dispatch.h"
     34 #include "anastasis-gtk_helper.h"
     35 #include <jansson.h>
     36 
     37 
     38 /**
     39  * The user selected the 'forward' button. Move on with the
     40  * country selection.
     41  */
     42 static void
     43 forward_country_selecting (void)
     44 {
     45   GtkTreeIter iter;
     46   GtkTreeView *tv;
     47   GtkTreeModel *model;
     48   GtkTreeSelection *sel;
     49   gchar *country_name;
     50   gchar *country_code;
     51   json_t *arguments;
     52 
     53   tv = GTK_TREE_VIEW (GCG_get_main_window_object (
     54                         "anastasis_gtk_country_treeview"));
     55   sel = gtk_tree_view_get_selection (tv);
     56   if (! gtk_tree_selection_get_selected (sel,
     57                                          &model,
     58                                          &iter))
     59   {
     60     GNUNET_break (0);
     61     return;
     62   }
     63   gtk_tree_model_get (model,
     64                       &iter,
     65                       AG_CCMC_COUNTRY_NAME, &country_name,
     66                       AG_CCMC_COUNTRY_CODE, &country_code,
     67                       -1);
     68   arguments = GNUNET_JSON_PACK (
     69     GNUNET_JSON_pack_string ("country",
     70                              country_name),
     71     GNUNET_JSON_pack_string ("country_code",
     72                              country_code));
     73   g_free (country_name);
     74   g_free (country_code);
     75   AG_freeze ();
     76   AG_ra = ANASTASIS_redux_action (AG_redux_state,
     77                                   "select_country",
     78                                   arguments,
     79                                   &AG_action_cb,
     80                                   NULL);
     81   json_decref (arguments);
     82 }
     83 
     84 
     85 /**
     86  * The user has entered their personal attributes and
     87  * confirmed they are correct. Move to the next state.
     88  * Note that #AG_freeze() was already called.
     89  */
     90 static void
     91 confirm_attributes (void)
     92 {
     93   json_t *args;
     94 
     95   args = AG_collect_attributes (false);
     96   GNUNET_assert (NULL != args);
     97   AG_ra = ANASTASIS_redux_action (AG_redux_state,
     98                                   "enter_user_attributes",
     99                                   args,
    100                                   &AG_action_cb,
    101                                   NULL);
    102   json_decref (args);
    103 }
    104 
    105 
    106 /**
    107  * Function called with the result of asking the user
    108  * if they are sure about the personal details they
    109  * entered.
    110  *
    111  * @param the dialog
    112  * @param response_id must be GTK_RESPONSE_OK to proceed
    113  * @param user_data the builder
    114  */
    115 void
    116 anastasis_gtk_user_sure_dialog_response_cb (
    117   GtkDialog *dialog,
    118   gint response_id,
    119   gpointer user_data)
    120 {
    121   GtkBuilder *builder = user_data;
    122 
    123   gtk_widget_destroy (GTK_WIDGET (dialog));
    124   g_object_unref (G_OBJECT (builder));
    125   if (GTK_RESPONSE_OK != response_id)
    126   {
    127     AG_thaw ();
    128     return;
    129   }
    130   confirm_attributes ();
    131 }
    132 
    133 
    134 /**
    135  * Launch dialog to question certainty of user providing
    136  * personal details during backup.
    137  */
    138 static void
    139 question_certainty (void)
    140 {
    141   GtkBuilder *builder;
    142   GtkDialog *ad;
    143 
    144   builder = ANASTASIS_GTK_get_new_builder (
    145     ANASTASIS_GTK_project_data (),
    146     "anastasis_gtk_user_sure.glade",
    147     NULL);
    148   if (NULL == builder)
    149   {
    150     GNUNET_break (0);
    151     return;
    152   }
    153   ad = GTK_DIALOG (gtk_builder_get_object (builder,
    154                                            "anastasis_gtk_user_sure_dialog"));
    155   if (NULL == ad)
    156   {
    157     GNUNET_break (0);
    158     g_object_unref (G_OBJECT (builder));
    159     return;
    160   }
    161   /* show dialog */
    162   {
    163     GtkWidget *toplevel;
    164     GtkWidget *widget;
    165 
    166 #if ! HAVE_HPDF_H
    167     gtk_widget_hide (
    168       GTK_WIDGET (
    169         gtk_builder_get_object (
    170           builder,
    171           "anastasis_gtk_print_details_button")));
    172 #endif
    173     widget = GTK_WIDGET (GCG_get_main_window_object (
    174                            "anastasis_gtk_auth_button_grid"));
    175     toplevel = gtk_widget_get_toplevel (widget);
    176     gtk_window_set_transient_for (GTK_WINDOW (ad),
    177                                   GTK_WINDOW (toplevel));
    178     gtk_window_present (GTK_WINDOW (ad));
    179   }
    180 }
    181 
    182 
    183 /**
    184  * The user clicked the 'next' button in the dialog where they enter
    185  * their personal attributes. If we are in the backup process, make
    186  * them first confirm that the attributes are correct and well-known
    187  * to them. Otherwise, simply directly proceed.
    188  */
    189 void
    190 AG_forward_user_attributes_collecting (void)
    191 {
    192   bool in_backup;
    193 
    194   AG_freeze ();
    195   in_backup = (NULL != json_object_get (AG_redux_state,
    196                                         "backup_state"));
    197   if (in_backup)
    198     question_certainty ();
    199   else
    200     confirm_attributes ();
    201 }
    202 
    203 
    204 /**
    205  * Function called with the result of questioning the user
    206  * if they really want to proceed with less than three
    207  * authentication factors.
    208  *
    209  * @param the dialog
    210  * @param response_id must be GTK_RESPONSE_OK to proceed
    211  * @param user_data the builder
    212  */
    213 void
    214 anastasis_gtk_confirm_multifactor_dialog_response_cb (
    215   GtkDialog *dialog,
    216   gint response_id,
    217   gpointer user_data)
    218 {
    219   GtkBuilder *builder = user_data;
    220 
    221   gtk_widget_destroy (GTK_WIDGET (dialog));
    222   g_object_unref (G_OBJECT (builder));
    223   if (GTK_RESPONSE_OK != response_id)
    224   {
    225     AG_thaw ();
    226     return;
    227   }
    228   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    229                                   "next",
    230                                   NULL,
    231                                   &AG_action_cb,
    232                                   NULL);
    233 }
    234 
    235 
    236 /**
    237  * Function called with the result of telling the
    238  * user that they cannot use 1-FA.
    239  *
    240  * @param the dialog
    241  * @param response_id must be GTK_RESPONSE_OK to proceed
    242  * @param user_data the builder
    243  */
    244 void
    245 anastasis_gtk_deny_singlefactor_dialog_response_cb (
    246   GtkDialog *dialog,
    247   gint response_id,
    248   gpointer user_data)
    249 {
    250   GtkBuilder *builder = user_data;
    251 
    252   gtk_widget_destroy (GTK_WIDGET (dialog));
    253   g_object_unref (G_OBJECT (builder));
    254   AG_thaw ();
    255 }
    256 
    257 
    258 /**
    259  * Launch dialog to question sanity of user providing
    260  * too few authentication methods.
    261  */
    262 static void
    263 question_sanity (void)
    264 {
    265   GtkBuilder *builder;
    266   GtkDialog *ad;
    267 
    268   builder = ANASTASIS_GTK_get_new_builder (
    269     ANASTASIS_GTK_project_data (),
    270     "anastasis_gtk_warn_multifactor.glade",
    271     NULL);
    272   if (NULL == builder)
    273   {
    274     GNUNET_break (0);
    275     return;
    276   }
    277   ad = GTK_DIALOG (gtk_builder_get_object (builder,
    278                                            "anastasis_gtk_confirm_multifactor_dialog"));
    279   if (NULL == ad)
    280   {
    281     GNUNET_break (0);
    282     g_object_unref (G_OBJECT (builder));
    283     return;
    284   }
    285   /* show dialog */
    286   {
    287     GtkWidget *toplevel;
    288     GtkWidget *widget;
    289 
    290     widget = GTK_WIDGET (GCG_get_main_window_object (
    291                            "anastasis_gtk_auth_button_grid"));
    292     toplevel = gtk_widget_get_toplevel (widget);
    293     gtk_window_set_transient_for (GTK_WINDOW (ad),
    294                                   GTK_WINDOW (toplevel));
    295     gtk_window_present (GTK_WINDOW (ad));
    296   }
    297 }
    298 
    299 
    300 /**
    301  * Launch dialog to deny 1-FA setups.
    302  */
    303 static void
    304 refuse_insanity (void)
    305 {
    306   GtkBuilder *builder;
    307   GtkDialog *ad;
    308 
    309   builder = ANASTASIS_GTK_get_new_builder (
    310     ANASTASIS_GTK_project_data (),
    311     "anastasis_gtk_deny_singlefactor.glade",
    312     NULL);
    313   if (NULL == builder)
    314   {
    315     GNUNET_break (0);
    316     return;
    317   }
    318   ad = GTK_DIALOG (gtk_builder_get_object (builder,
    319                                            "anastasis_gtk_deny_singlefactor_dialog"));
    320   if (NULL == ad)
    321   {
    322     GNUNET_break (0);
    323     g_object_unref (G_OBJECT (builder));
    324     return;
    325   }
    326   /* show dialog */
    327   {
    328     GtkWidget *toplevel;
    329     GtkWidget *widget;
    330 
    331     widget = GTK_WIDGET (GCG_get_main_window_object (
    332                            "anastasis_gtk_auth_button_grid"));
    333     toplevel = gtk_widget_get_toplevel (widget);
    334     gtk_window_set_transient_for (GTK_WINDOW (ad),
    335                                   GTK_WINDOW (toplevel));
    336     gtk_window_present (GTK_WINDOW (ad));
    337   }
    338 }
    339 
    340 
    341 /**
    342  * The user has clicked 'next' in the 'authentications_editing' state.
    343  * Check if the number of authentication methods configured is above
    344  * a threshold. If no, warn before allowing to proceed.
    345  */
    346 static void
    347 forward_authentications_editing (void)
    348 {
    349   json_t *methods;
    350 
    351   AG_freeze ();
    352   methods = json_object_get (AG_redux_state,
    353                              "authentication_methods");
    354   if (json_array_size (methods) < 2)
    355   {
    356     refuse_insanity ();
    357     return;
    358   }
    359   if (json_array_size (methods) < 3)
    360   {
    361     question_sanity ();
    362     return;
    363   }
    364   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    365                                   "next",
    366                                   NULL,
    367                                   &AG_action_cb,
    368                                   NULL);
    369 }
    370 
    371 
    372 /**
    373  * The user has pressed 'next' in POLICIES_EDITING state.
    374  * Proceed to secret editing.
    375  */
    376 static void
    377 forward_policies_reviewing (void)
    378 {
    379   AG_freeze ();
    380   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    381                                   "next",
    382                                   NULL,
    383                                   &AG_action_cb,
    384                                   NULL);
    385 }
    386 
    387 
    388 static void
    389 forward_secret_editing (void)
    390 {
    391   AG_freeze ();
    392   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    393                                   "next",
    394                                   NULL,
    395                                   &AG_action_cb,
    396                                   NULL);
    397 }
    398 
    399 
    400 /**
    401  * The user has pressed 'next' after selecting a secret to recover.
    402  */
    403 static void
    404 forward_secret_selecting (void)
    405 {
    406   GtkTreeSelection *selection;
    407   GtkTreeModel *model;
    408   GtkTreeIter iter;
    409   json_t *args;
    410   gchar *provider_url;
    411   gchar *secret_name;
    412   gint version;
    413   gint mask;
    414   const json_t *providers;
    415 
    416   AG_freeze ();
    417   AG_stop_long_action ();
    418   selection = GTK_TREE_SELECTION (
    419     GCG_get_main_window_object (
    420       "anastasis_gtk_secret_selection_treeselection"));
    421 
    422   if (! gtk_tree_selection_get_selected (selection,
    423                                          &model,
    424                                          &iter))
    425   {
    426     GNUNET_break (0);
    427     AG_insensitive ("anastasis_gtk_main_window_forward_button");
    428     return;
    429   }
    430   gtk_tree_model_get (model,
    431                       &iter,
    432                       AG_SSMC_PROVIDER_URL, &provider_url,
    433                       AG_SSMC_POLICY_VERSION, &version,
    434                       AG_SSMC_ATTRIBUTE_MASK, &mask,
    435                       AG_SSMC_SECRET_NAME, &secret_name,
    436                       AG_SSMC_POLICY_PROVIDER_JSON, &providers,
    437                       -1);
    438   args = GNUNET_JSON_PACK (
    439     GNUNET_JSON_pack_array_incref ("providers",
    440                                    (json_t *) providers),
    441     GNUNET_JSON_pack_uint64 ("attribute_mask",
    442                              mask),
    443     GNUNET_JSON_pack_string ("secret_name",
    444                              secret_name));
    445   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    446               "Proceeding with policy version %u at provider %s\n",
    447               (unsigned int) version,
    448               provider_url);
    449   g_free (provider_url);
    450   g_free (secret_name);
    451   if (NULL != AG_pd)
    452   {
    453     ANASTASIS_policy_discovery_stop (AG_pd);
    454     AG_pd = NULL;
    455   }
    456   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    457                                   "select_version",
    458                                   args,
    459                                   &AG_action_cb,
    460                                   NULL);
    461   json_decref (args);
    462 }
    463 
    464 
    465 /**
    466  * Callback invoked if the the "forward"-button is clicked.
    467  *
    468  * @param object
    469  * @param user_data unused
    470  */
    471 void
    472 anastasis_gtk_main_window_forward_clicked (GObject *object,
    473                                            gpointer user_data)
    474 {
    475   struct DispatchItem actions[] = {
    476     { .state = "COUNTRY_SELECTING",
    477       .action = &forward_country_selecting },
    478     { .state = "USER_ATTRIBUTES_COLLECTING",
    479       .action = &AG_forward_user_attributes_collecting },
    480     { .state = "AUTHENTICATIONS_EDITING",
    481       .action = &forward_authentications_editing },
    482     { .state = "POLICIES_REVIEWING",
    483       .action = &forward_policies_reviewing },
    484     { .state = "SECRET_EDITING",
    485       .action = &forward_secret_editing },
    486     { .state = "SECRET_SELECTING",
    487       .action = &forward_secret_selecting },
    488     { .state = NULL,
    489       .action = NULL }
    490   };
    491 
    492   AG_insensitive ("anastasis_gtk_main_window_forward_button");
    493   AG_dispatch (actions);
    494 }