anastasis-gtk_handle-method-sms.c (6417B)
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 /** 22 * @file src/anastasis/anastasis-gtk_handle-method-sms.c 23 * @brief Handle dialogs for security sms 24 * @author Christian Grothoff 25 */ 26 #include <gnunet/gnunet_util_lib.h> 27 #include "anastasis_gtk_util.h" 28 #include "anastasis-gtk_action.h" 29 #include "anastasis-gtk_helper.h" 30 #include "anastasis-gtk_handle-identity-changed.h" 31 #include <jansson.h> 32 33 34 /** 35 * Return obfuscated variant of a phone number. 36 * 37 * @param number input address 38 * @return obfuscated version, NULL on errors 39 */ 40 static char * 41 mask_number (const char *number) 42 { 43 char *at; 44 size_t nlen; 45 char *result; 46 47 result = GNUNET_strdup (number); 48 at = strchr (result, '+'); 49 if ( (NULL != at) && 50 (result != at) ) 51 { 52 GNUNET_break (0); 53 GNUNET_free (result); 54 return NULL; 55 } 56 nlen = strlen (number); 57 if (NULL != at) 58 { 59 if (strlen (at) < 3) 60 { 61 GNUNET_break (0); 62 GNUNET_free (result); 63 return NULL; 64 } 65 at += 3; 66 nlen -= 3; 67 } 68 else 69 { 70 at = result; 71 } 72 switch (nlen) 73 { 74 case 0: 75 GNUNET_break (0); 76 GNUNET_free (result); 77 return NULL; 78 case 1: 79 at[0] = '?'; 80 break; 81 case 2: 82 case 3: 83 case 4: 84 at[0] = '?'; 85 at[1] = '?'; 86 break; 87 default: 88 for (unsigned int i = 1; i<nlen - 3; i++) 89 at[i] = '?'; 90 break; 91 } 92 93 /* shorten multiple consecutive "?" to "*" */ 94 { 95 bool star = false; 96 bool qmark = false; 97 size_t woff = 0; 98 99 for (unsigned int i = 0; i<strlen (result); i++) 100 { 101 result[woff++] = result[i]; 102 if ('?' == result[i]) 103 { 104 if (star) 105 { 106 /* more than two "??" in a row */ 107 woff--; 108 continue; 109 } 110 if (qmark) 111 { 112 /* two "??", combine to "*" */ 113 result[--woff - 1] = '*'; 114 star = true; 115 continue; 116 } 117 /* first qmark */ 118 qmark = true; 119 } 120 else 121 { 122 star = false; 123 qmark = false; 124 } 125 } 126 result[woff] = '\0'; 127 } 128 return result; 129 } 130 131 132 /** 133 * Function called from the security-sms dialog upon completion. 134 * 135 * @param dialog the pseudonym selection dialog 136 * @param response_id response code from the dialog 137 * @param user_data the builder of the dialog 138 */ 139 void 140 anastasis_gtk_b_sms_dialog_response_cb (GtkDialog *dialog, 141 gint response_id, 142 gpointer user_data) 143 { 144 GtkBuilder *builder = GTK_BUILDER (user_data); 145 GtkEntry *q; 146 const char *qs; 147 json_t *args; 148 char *mn; 149 char *ins; 150 151 if (GTK_RESPONSE_OK != response_id) 152 { 153 gtk_widget_destroy (GTK_WIDGET (dialog)); 154 g_object_unref (G_OBJECT (builder)); 155 return; 156 } 157 q = GTK_ENTRY (gtk_builder_get_object (builder, 158 "anastasis_gtk_b_sms_dialog_phonenumber_entry")); 159 qs = gtk_entry_get_text (q); 160 mn = mask_number (qs); 161 GNUNET_asprintf (&ins, 162 _ ("phone number %s"), 163 mn); 164 GNUNET_free (mn); 165 args = json_pack ("{ s:{s:s, s:o, s:s}}", 166 "authentication_method", 167 "type", 168 "sms", 169 "challenge", 170 GNUNET_JSON_from_data (qs, 171 strlen (qs)), 172 "instructions", 173 ins); 174 GNUNET_free (ins); 175 gtk_widget_destroy (GTK_WIDGET (dialog)); 176 g_object_unref (G_OBJECT (builder)); 177 AG_freeze (); 178 AG_ra = ANASTASIS_redux_action (AG_redux_state, 179 "add_authentication", 180 args, 181 &AG_action_cb, 182 NULL); 183 json_decref (args); 184 } 185 186 187 void 188 anastasis_gtk_b_sms_dialog_phonenumber_entry_changed_cb (GtkEntry *entry, 189 gpointer user_data) 190 { 191 GtkBuilder *builder = GTK_BUILDER (user_data); 192 GtkEntry *q; 193 const char *qs; 194 regex_t regex; 195 int regex_result; 196 const char *regexp = "^\\+[0-9]+$"; 197 198 regex_result = regcomp (®ex, 199 regexp, 200 REG_EXTENDED); 201 if (0 < regex_result) 202 { 203 GNUNET_break (0); 204 return; 205 } 206 q = GTK_ENTRY (gtk_builder_get_object (builder, 207 "anastasis_gtk_b_sms_dialog_phonenumber_entry")); 208 qs = gtk_entry_get_text (q); 209 regex_result = regexec (®ex, 210 qs, 211 0, 212 NULL, 213 0); 214 regfree (®ex); 215 gtk_widget_set_sensitive ( 216 GTK_WIDGET (gtk_builder_get_object (builder, 217 "anastasis_gtk_b_sms_dialog_btn_ok")), 218 0 == regex_result); 219 } 220 221 222 /** 223 * Callback invoked if the the "secure sms"-button is clicked. 224 * 225 * @param object 226 * @param user_data unused 227 */ 228 void 229 anastasis_gtk_btn_add_auth_sms_clicked_cb (GObject *object, 230 gpointer user_data) 231 { 232 GtkWidget *ad; 233 GtkBuilder *builder; 234 235 builder = ANASTASIS_GTK_get_new_builder ( 236 ANASTASIS_GTK_project_data (), 237 "anastasis_gtk_auth_add_sms.glade", 238 NULL); 239 if (NULL == builder) 240 { 241 GNUNET_break (0); 242 return; 243 } 244 ad = GTK_WIDGET (gtk_builder_get_object (builder, 245 "anastasis_gtk_b_sms_dialog")); 246 { 247 GtkWidget *toplevel; 248 249 toplevel = gtk_widget_get_toplevel (GTK_WIDGET (object)); 250 gtk_window_set_transient_for (GTK_WINDOW (ad), 251 GTK_WINDOW (toplevel)); 252 gtk_window_present (GTK_WINDOW (ad)); 253 } 254 }