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