anastasis-gtk

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

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


      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 "anastasis-gtk_rows.h"
     36 #include <jansson.h>
     37 
     38 
     39 /**
     40  * The user selected the 'forward' button. Move on with the
     41  * country selection.
     42  */
     43 static void
     44 forward_country_selecting (void)
     45 {
     46   AGRow *row;
     47   json_t *arguments;
     48 
     49   row = AG_selected_row ("anastasis_gtk_country_selection");
     50   if (NULL == row)
     51   {
     52     GNUNET_break (0);
     53     return;
     54   }
     55   arguments = GNUNET_JSON_PACK (
     56     GNUNET_JSON_pack_string ("country",
     57                              AG_row_string (row,
     58                                             "name")),
     59     GNUNET_JSON_pack_string ("country_code",
     60                              AG_row_string (row,
     61                                             "code")));
     62   AG_freeze ();
     63   AG_ra = ANASTASIS_redux_action (AG_redux_state,
     64                                   "select_country",
     65                                   arguments,
     66                                   &AG_action_cb,
     67                                   NULL);
     68   json_decref (arguments);
     69 }
     70 
     71 
     72 /**
     73  * The user has entered their personal attributes and
     74  * confirmed they are correct. Move to the next state.
     75  * Note that #AG_freeze() was already called.
     76  */
     77 static void
     78 confirm_attributes (void)
     79 {
     80   json_t *args;
     81 
     82   args = AG_collect_attributes (false);
     83   GNUNET_assert (NULL != args);
     84   AG_ra = ANASTASIS_redux_action (AG_redux_state,
     85                                   "enter_user_attributes",
     86                                   args,
     87                                   &AG_action_cb,
     88                                   NULL);
     89   json_decref (args);
     90 }
     91 
     92 
     93 /**
     94  * Function called with the result of asking the user
     95  * if they are sure about the personal details they
     96  * entered.
     97  *
     98  * @param the dialog
     99  * @param response_id must be GTK_RESPONSE_OK to proceed
    100  * @param user_data the builder
    101  */
    102 void
    103 anastasis_gtk_user_sure_dialog_response_cb (
    104   GtkDialog *dialog,
    105   gint response_id,
    106   gpointer user_data)
    107 {
    108   GtkBuilder *builder = user_data;
    109 
    110   gtk_window_destroy (GTK_WINDOW (dialog));
    111   g_object_unref (G_OBJECT (builder));
    112   if (GTK_RESPONSE_OK != response_id)
    113   {
    114     AG_thaw ();
    115     return;
    116   }
    117   confirm_attributes ();
    118 }
    119 
    120 
    121 /**
    122  * Launch dialog to question certainty of user providing
    123  * personal details during backup.
    124  */
    125 static void
    126 question_certainty (void)
    127 {
    128   GtkBuilder *builder;
    129   GtkDialog *ad;
    130 
    131   builder = ANASTASIS_GTK_get_new_builder (
    132     ANASTASIS_GTK_project_data (),
    133     "anastasis_gtk_user_sure.ui",
    134     NULL);
    135   if (NULL == builder)
    136   {
    137     GNUNET_break (0);
    138     return;
    139   }
    140   ad = GTK_DIALOG (gtk_builder_get_object (builder,
    141                                            "anastasis_gtk_user_sure_dialog"));
    142   if (NULL == ad)
    143   {
    144     GNUNET_break (0);
    145     g_object_unref (G_OBJECT (builder));
    146     return;
    147   }
    148   /* show dialog */
    149   {
    150     GtkRoot *toplevel;
    151     GtkWidget *widget;
    152 
    153 #if ! HAVE_HPDF_H
    154     gtk_widget_set_visible (GTK_WIDGET (
    155         gtk_builder_get_object (
    156           builder,
    157           "anastasis_gtk_print_details_button")),
    158                            FALSE);
    159 #endif
    160     widget = GTK_WIDGET (GCG_get_main_window_object (
    161                            "anastasis_gtk_auth_button_grid"));
    162     toplevel = gtk_widget_get_root (widget);
    163     gtk_window_set_transient_for (GTK_WINDOW (ad),
    164                                   GTK_WINDOW (toplevel));
    165     gtk_window_present (GTK_WINDOW (ad));
    166   }
    167 }
    168 
    169 
    170 /**
    171  * The user clicked the 'next' button in the dialog where they enter
    172  * their personal attributes. If we are in the backup process, make
    173  * them first confirm that the attributes are correct and well-known
    174  * to them. Otherwise, simply directly proceed.
    175  */
    176 void
    177 AG_forward_user_attributes_collecting (void)
    178 {
    179   bool in_backup;
    180 
    181   AG_freeze ();
    182   in_backup = (NULL != json_object_get (AG_redux_state,
    183                                         "backup_state"));
    184   if (in_backup)
    185     question_certainty ();
    186   else
    187     confirm_attributes ();
    188 }
    189 
    190 
    191 /**
    192  * Function called with the result of questioning the user
    193  * if they really want to proceed with less than three
    194  * authentication factors.
    195  *
    196  * @param source the dialog
    197  * @param res the result of the user's choice, button 1 to proceed
    198  * @param user_data unused
    199  */
    200 static void
    201 confirm_multifactor_response_cb (GObject *source,
    202                                  GAsyncResult *res,
    203                                  gpointer user_data)
    204 {
    205   (void) user_data;
    206   if (1 !=
    207       gtk_alert_dialog_choose_finish (GTK_ALERT_DIALOG (source),
    208                                       res,
    209                                       NULL))
    210   {
    211     AG_thaw ();
    212     return;
    213   }
    214   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    215                                   "next",
    216                                   NULL,
    217                                   &AG_action_cb,
    218                                   NULL);
    219 }
    220 
    221 
    222 /**
    223  * Function called with the result of telling the
    224  * user that they cannot use 1-FA.
    225  *
    226  * @param source the dialog
    227  * @param res the result of the user's choice, unused
    228  * @param user_data unused
    229  */
    230 static void
    231 deny_singlefactor_response_cb (GObject *source,
    232                                GAsyncResult *res,
    233                                gpointer user_data)
    234 {
    235   (void) user_data;
    236   (void) gtk_alert_dialog_choose_finish (GTK_ALERT_DIALOG (source),
    237                                          res,
    238                                          NULL);
    239   AG_thaw ();
    240 }
    241 
    242 
    243 /**
    244  * Return the main window, to be used as the parent of our dialogs.
    245  *
    246  * @return the main window
    247  */
    248 static GtkWindow *
    249 main_window (void)
    250 {
    251   GtkWidget *widget;
    252 
    253   widget = GTK_WIDGET (GCG_get_main_window_object (
    254                          "anastasis_gtk_auth_button_grid"));
    255   return GTK_WINDOW (gtk_widget_get_root (widget));
    256 }
    257 
    258 
    259 /**
    260  * Launch dialog to question sanity of user providing
    261  * too few authentication methods.
    262  */
    263 static void
    264 question_sanity (void)
    265 {
    266   GtkAlertDialog *ad;
    267   const char *buttons[] = {
    268     _ ("_Back"),
    269     _ ("_Next"),
    270     NULL
    271   };
    272 
    273   ad = gtk_alert_dialog_new (
    274     "%s",
    275     _ (
    276       "To keep your secret secure, we recommend you specify at least three authentication options before proceeding."));
    277   gtk_alert_dialog_set_detail (
    278     ad,
    279     _ ("Select \"back\" to add additional authentication options."));
    280   gtk_alert_dialog_set_buttons (ad,
    281                                 buttons);
    282   gtk_alert_dialog_set_cancel_button (ad,
    283                                       0);
    284   gtk_alert_dialog_set_default_button (ad,
    285                                        1);
    286   gtk_alert_dialog_choose (ad,
    287                            main_window (),
    288                            NULL,
    289                            &confirm_multifactor_response_cb,
    290                            NULL);
    291   g_object_unref (ad);
    292 }
    293 
    294 
    295 /**
    296  * Launch dialog to deny 1-FA setups.
    297  */
    298 static void
    299 refuse_insanity (void)
    300 {
    301   GtkAlertDialog *ad;
    302   const char *buttons[] = {
    303     _ ("_Back"),
    304     NULL
    305   };
    306 
    307   ad = gtk_alert_dialog_new (
    308     "%s",
    309     _ (
    310       "To keep your secret secure, we require at least two authentication options, and recommend you specify at least three authentication options before proceeding."));
    311   gtk_alert_dialog_set_detail (
    312     ad,
    313     _ ("Select \"back\" to add additional authentication options."));
    314   gtk_alert_dialog_set_buttons (ad,
    315                                 buttons);
    316   gtk_alert_dialog_set_cancel_button (ad,
    317                                       0);
    318   gtk_alert_dialog_set_default_button (ad,
    319                                        0);
    320   gtk_alert_dialog_choose (ad,
    321                            main_window (),
    322                            NULL,
    323                            &deny_singlefactor_response_cb,
    324                            NULL);
    325   g_object_unref (ad);
    326 }
    327 
    328 
    329 /**
    330  * The user has clicked 'next' in the 'authentications_editing' state.
    331  * Check if the number of authentication methods configured is above
    332  * a threshold. If no, warn before allowing to proceed.
    333  */
    334 static void
    335 forward_authentications_editing (void)
    336 {
    337   json_t *methods;
    338 
    339   AG_freeze ();
    340   methods = json_object_get (AG_redux_state,
    341                              "authentication_methods");
    342   if (json_array_size (methods) < 2)
    343   {
    344     refuse_insanity ();
    345     return;
    346   }
    347   if (json_array_size (methods) < 3)
    348   {
    349     question_sanity ();
    350     return;
    351   }
    352   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    353                                   "next",
    354                                   NULL,
    355                                   &AG_action_cb,
    356                                   NULL);
    357 }
    358 
    359 
    360 /**
    361  * The user has pressed 'next' in POLICIES_EDITING state.
    362  * Proceed to secret editing.
    363  */
    364 static void
    365 forward_policies_reviewing (void)
    366 {
    367   AG_freeze ();
    368   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    369                                   "next",
    370                                   NULL,
    371                                   &AG_action_cb,
    372                                   NULL);
    373 }
    374 
    375 
    376 static void
    377 forward_secret_editing (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 /**
    389  * The user has pressed 'next' after selecting a secret to recover.
    390  */
    391 static void
    392 forward_secret_selecting (void)
    393 {
    394   AGRow *row;
    395   json_t *args;
    396 
    397   AG_freeze ();
    398   AG_stop_long_action ();
    399   row = AG_selected_row ("anastasis_gtk_secret_selection_treeselection");
    400   if (NULL == row)
    401   {
    402     GNUNET_break (0);
    403     AG_insensitive ("anastasis_gtk_main_window_forward_button");
    404     return;
    405   }
    406   args = GNUNET_JSON_PACK (
    407     GNUNET_JSON_pack_array_incref ("providers",
    408                                    AG_row_json (row,
    409                                                 "providers")),
    410     GNUNET_JSON_pack_uint64 ("attribute_mask",
    411                              AG_row_uint (row,
    412                                           "attribute_mask")),
    413     GNUNET_JSON_pack_string ("secret_name",
    414                              AG_row_string (row,
    415                                             "secret_name")));
    416   GNUNET_log (GNUNET_ERROR_TYPE_INFO,
    417               "Proceeding with policy version %u at provider %s\n",
    418               (unsigned int) AG_row_uint (row,
    419                                           "version"),
    420               AG_row_string (row,
    421                              "provider_url"));
    422   if (NULL != AG_pd)
    423   {
    424     ANASTASIS_policy_discovery_stop (AG_pd);
    425     AG_pd = NULL;
    426   }
    427   AG_ra = ANASTASIS_redux_action (AG_redux_state,
    428                                   "select_version",
    429                                   args,
    430                                   &AG_action_cb,
    431                                   NULL);
    432   json_decref (args);
    433 }
    434 
    435 
    436 /**
    437  * Callback invoked if the the "forward"-button is clicked.
    438  *
    439  * @param object
    440  * @param user_data unused
    441  */
    442 void
    443 anastasis_gtk_main_window_forward_clicked (GObject *object,
    444                                            gpointer user_data)
    445 {
    446   struct DispatchItem actions[] = {
    447     { .state = "COUNTRY_SELECTING",
    448       .action = &forward_country_selecting },
    449     { .state = "USER_ATTRIBUTES_COLLECTING",
    450       .action = &AG_forward_user_attributes_collecting },
    451     { .state = "AUTHENTICATIONS_EDITING",
    452       .action = &forward_authentications_editing },
    453     { .state = "POLICIES_REVIEWING",
    454       .action = &forward_policies_reviewing },
    455     { .state = "SECRET_EDITING",
    456       .action = &forward_secret_editing },
    457     { .state = "SECRET_SELECTING",
    458       .action = &forward_secret_selecting },
    459     { .state = NULL,
    460       .action = NULL }
    461   };
    462 
    463   AG_insensitive ("anastasis_gtk_main_window_forward_button");
    464   AG_dispatch (actions);
    465 }