nma-file-cert-chooser.c 14 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
/* NetworkManager Applet -- allow user control over networking
 *
 * Dan Williams <dcbw@redhat.com>
 * Lubomir Rintel <lkundrak@v3.sk>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the
 * Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
 * Boston, MA 02110-1301 USA.
 *
 * Copyright (C) 2015,2017 Red Hat, Inc.
 */

#include "nm-default.h"
25 26
#include "nma-cert-chooser-private.h"
#include "utils.h"
27 28 29 30 31 32
#ifdef LIBNM_BUILD
#include "nma-ui-utils.h"
#else
#include "nm-ui-utils.h"
#endif

33
#define NMA_FILE_CERT_CHOOSER_GET_PRIVATE(self) (&(_NM_GET_PRIVATE (self, NMACertChooser, NMA_IS_CERT_CHOOSER)->_sub.file))
34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205

static void
set_key_password (NMACertChooser *cert_chooser, const gchar *password)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	g_return_if_fail (priv->key_password != NULL);
	gtk_entry_set_text (GTK_ENTRY (priv->key_password), password);
}

static const gchar *
get_key_password (NMACertChooser *cert_chooser)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	g_return_val_if_fail (priv->key_password != NULL, NULL);
	return gtk_entry_get_text (GTK_ENTRY (priv->key_password));
}

static void
set_key_uri (NMACertChooser *cert_chooser, const gchar *uri)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	if (uri)
		gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (priv->key_button), uri);
}

static gchar *
get_key_uri (NMACertChooser *cert_chooser)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	return gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (priv->key_button));
}

static void
set_cert_uri (NMACertChooser *cert_chooser, const gchar *uri)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	if (uri)
		gtk_file_chooser_set_uri (GTK_FILE_CHOOSER (priv->cert_button), uri);
}

static gchar *
get_cert_uri (NMACertChooser *cert_chooser)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	return gtk_file_chooser_get_uri (GTK_FILE_CHOOSER (priv->cert_button));
}

static void
add_to_size_group (NMACertChooser *cert_chooser, GtkSizeGroup *group)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	gtk_size_group_add_widget (group, priv->cert_button_label);
	gtk_size_group_add_widget (group, priv->key_button_label);
	gtk_size_group_add_widget (group, priv->key_password_label);
}

static gboolean
validate (NMACertChooser *cert_chooser, GError **error)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);
	GError *local = NULL;
	char *tmp;

	tmp = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (priv->cert_button));
	if (tmp) {
		g_free (tmp);
	} else {
		g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("No certificate set"));
		return FALSE;
	}

	g_signal_emit_by_name (cert_chooser, "cert-validate", &local);
	if (local) {
		widget_set_error (priv->cert_button);
		g_propagate_error (error, local);
		return FALSE;
	} else {
		widget_unset_error (priv->cert_button);
	}

	if (gtk_widget_get_visible (priv->key_button)) {
		tmp = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (priv->key_button));
		if (tmp) {
			g_free (tmp);
		} else {
			g_set_error_literal (error, NMA_ERROR, NMA_ERROR_GENERIC, _("No key set"));
			return FALSE;
		}

		g_signal_emit_by_name (cert_chooser, "key-validate", &local);
		if (local) {
			widget_set_error (priv->key_button);
			g_propagate_error (error, local);
			return FALSE;
		} else {
			widget_unset_error (priv->key_button);
		}

		g_signal_emit_by_name (cert_chooser, "key-password-validate", &local);
		if (local) {
			widget_set_error (priv->key_password);
			g_propagate_error (error, local);
			return FALSE;
		} else {
			widget_unset_error (priv->key_password);
		}
	}

	return TRUE;
}

static void
setup_key_password_storage (NMACertChooser *cert_chooser,
                            NMSettingSecretFlags initial_flags,
                            NMSetting *setting,
                            const char *password_flags_name,
                            gboolean with_not_required,
                            gboolean ask_mode)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	nma_utils_setup_password_storage (priv->key_password,
	                                  initial_flags,
	                                  setting,
	                                  password_flags_name,
	                                  with_not_required,
	                                  ask_mode);
}

static void
update_key_password_storage (NMACertChooser *cert_chooser,
                             NMSettingSecretFlags secret_flags,
                             NMSetting *setting,
                             const char *password_flags_name)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	nma_utils_update_password_storage (priv->key_password,
	                                   secret_flags,
	                                   setting,
	                                   password_flags_name);
}


static NMSettingSecretFlags
get_key_password_flags (NMACertChooser *cert_chooser)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	return nma_utils_menu_to_secret_flags (priv->key_password);
}

static void
reset_filter (GtkWidget *widget, GParamSpec *spec, gpointer user_data)
{
	if (!gtk_file_chooser_get_filter (GTK_FILE_CHOOSER (widget))) {
		g_signal_handlers_block_by_func (widget, reset_filter, user_data);
		gtk_file_chooser_set_filter (GTK_FILE_CHOOSER (widget), GTK_FILE_FILTER (user_data));
		g_signal_handlers_unblock_by_func (widget, reset_filter, user_data);
	}
}

static void
cert_changed_cb (GtkFileChooserButton *file_chooser_button, gpointer user_data)
{
206
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (NMA_CERT_CHOOSER (user_data));
207 208 209 210 211 212 213 214 215 216 217

	if (gtk_widget_get_visible (priv->key_button)) {
		gtk_widget_set_sensitive (priv->key_button, TRUE);
		gtk_widget_set_sensitive (priv->key_button_label, TRUE);
	}
	g_signal_emit_by_name (user_data, "changed");
}

static void
key_changed_cb (GtkFileChooserButton *file_chooser_button, gpointer user_data)
{
218
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (NMA_CERT_CHOOSER (user_data));
219 220 221 222 223 224 225 226 227 228 229 230 231 232 233

	gtk_widget_set_sensitive (priv->key_password, TRUE);
	gtk_widget_set_sensitive (priv->key_password_label, TRUE);
	g_signal_emit_by_name (user_data, "changed");
}

static void
key_password_changed_cb (GtkEntry *entry, gpointer user_data)
{
	g_signal_emit_by_name (user_data, "changed");
}

static void
show_toggled_cb (GtkCheckButton *button, gpointer user_data)
{
234
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (NMA_CERT_CHOOSER (user_data));
235 236 237 238 239 240 241 242 243 244 245 246 247 248 249

	gtk_entry_set_visibility (GTK_ENTRY (priv->key_password),
	                          gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (button)));
}

static void
set_title (NMACertChooser *cert_chooser, const gchar *title)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);
	gchar *text;

	text = g_strdup_printf (_("Choose a key for %s Certificate"), title);
	gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (priv->key_button), text);
	g_free (text);

250
	text = g_strdup_printf (_("%s private _key"), title);
251 252 253
	gtk_label_set_text_with_mnemonic (GTK_LABEL (priv->key_button_label), text);
	g_free (text);

254
	text = g_strdup_printf (_("%s key _password"), title);
255 256 257 258 259 260 261
	gtk_label_set_text_with_mnemonic (GTK_LABEL (priv->key_password_label), text);
	g_free (text);

	text = g_strdup_printf (_("Choose %s Certificate"), title);
	gtk_file_chooser_button_set_title (GTK_FILE_CHOOSER_BUTTON (priv->cert_button), text);
	g_free (text);

262
	text = g_strdup_printf (_("%s _certificate"), title);
263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288
	gtk_label_set_text_with_mnemonic (GTK_LABEL (priv->cert_button_label), text);
	g_free (text);
}

static void
set_flags (NMACertChooser *cert_chooser, NMACertChooserFlags flags)
{
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);

	if (flags & NMA_CERT_CHOOSER_FLAG_CERT) {
		gtk_widget_hide (priv->key_button);
		gtk_widget_hide (priv->key_button_label);
		gtk_widget_hide (priv->key_password);
		gtk_widget_hide (priv->key_password_label);
		gtk_widget_hide (priv->show_password);
	}

	if (flags & NMA_CERT_CHOOSER_FLAG_PASSWORDS) {
		gtk_widget_hide (priv->cert_button);
		gtk_widget_hide (priv->cert_button_label);
		gtk_widget_hide (priv->key_button);
		gtk_widget_hide (priv->key_button_label);
	}
}

static void
289
init (NMACertChooser *cert_chooser)
290
{
291
	NMAFileCertChooserPrivate *priv = NMA_FILE_CERT_CHOOSER_GET_PRIVATE (cert_chooser);
292 293
	GtkFileFilter *filter;

294 295
	gtk_grid_insert_column (GTK_GRID (cert_chooser), 2);
	gtk_grid_set_row_spacing (GTK_GRID (cert_chooser), 6);
296
	gtk_grid_set_column_spacing (GTK_GRID (cert_chooser), 6);
297 298

	/* The key chooser */
299
	gtk_grid_insert_row (GTK_GRID (cert_chooser), 0);
300 301 302 303 304 305

	priv->key_button = g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
	                                  "action", GTK_FILE_CHOOSER_ACTION_OPEN,
	                                  "filter", utils_key_filter (),
	                                  "local-only", TRUE,
	                                  NULL);
306
	gtk_grid_attach (GTK_GRID (cert_chooser), priv->key_button, 1, 0, 1, 1);
307 308 309
	gtk_widget_set_hexpand (priv->key_button, TRUE);
	gtk_widget_set_sensitive (priv->key_button, FALSE);
	gtk_widget_show (priv->key_button);
310
	gtk_widget_set_no_show_all (priv->key_button, TRUE);
311

312 313
	g_signal_connect (priv->key_button, "selection-changed",
	                  G_CALLBACK (key_changed_cb), cert_chooser);
314 315

	priv->key_button_label = gtk_label_new (NULL);
316
	g_object_set (priv->key_button_label, "xalign", (gfloat) 1, NULL);
317
	gtk_label_set_mnemonic_widget (GTK_LABEL (priv->key_button_label), priv->key_button);
318
	gtk_grid_attach (GTK_GRID (cert_chooser), priv->key_button_label, 0, 0, 1, 1);
319 320
	gtk_widget_set_sensitive (priv->key_button_label, FALSE);
	gtk_widget_show (priv->key_button_label);
321
	gtk_widget_set_no_show_all (priv->key_button_label, TRUE);
322 323

	/* The key password entry */
324
	gtk_grid_insert_row (GTK_GRID (cert_chooser), 1);
325 326 327

	priv->key_password = gtk_entry_new ();
	gtk_entry_set_visibility (GTK_ENTRY (priv->key_password), FALSE);
328
	gtk_grid_attach (GTK_GRID (cert_chooser), priv->key_password, 1, 1, 1, 1);
329 330 331
	gtk_widget_set_hexpand (priv->key_password, TRUE);
	gtk_widget_set_sensitive (priv->key_password, FALSE);
	gtk_widget_show (priv->key_password);
332
	gtk_widget_set_no_show_all (priv->key_password, TRUE);
333

334 335
	g_signal_connect (priv->key_password, "changed",
	                  G_CALLBACK (key_password_changed_cb), cert_chooser);
336 337

	priv->key_password_label = gtk_label_new (NULL);
338
	g_object_set (priv->key_password_label, "xalign", (gfloat) 1, NULL);
339
	gtk_label_set_mnemonic_widget (GTK_LABEL (priv->key_password_label), priv->key_password);
340
	gtk_grid_attach (GTK_GRID (cert_chooser), priv->key_password_label, 0, 1, 1, 1);
341 342
	gtk_widget_set_sensitive (priv->key_password_label, FALSE);
	gtk_widget_show (priv->key_password_label);
343
	gtk_widget_set_no_show_all (priv->key_password_label, TRUE);
344 345

	/* Show password */
346
	gtk_grid_insert_row (GTK_GRID (cert_chooser), 2);
347
	priv->show_password = gtk_check_button_new_with_mnemonic ("Sho_w password");
348
	gtk_grid_attach (GTK_GRID (cert_chooser), priv->show_password, 1, 2, 1, 1);
349
	gtk_widget_show (priv->show_password);
350
	gtk_widget_set_no_show_all (priv->show_password, TRUE);
351
	g_signal_connect (priv->show_password, "toggled",
352
	                  G_CALLBACK (show_toggled_cb), cert_chooser);
353 354

	/* The certificate chooser */
355
	gtk_grid_insert_row (GTK_GRID (cert_chooser), 0);
356 357 358 359 360 361 362

	filter = utils_cert_filter ();
	priv->cert_button = g_object_new (GTK_TYPE_FILE_CHOOSER_BUTTON,
	                                  "action", GTK_FILE_CHOOSER_ACTION_OPEN,
	                                  "filter", filter,
	                                  "local-only", TRUE,
	                                  NULL);
363
	gtk_grid_attach (GTK_GRID (cert_chooser), priv->cert_button, 1, 0, 1, 1);
364 365
	gtk_widget_set_hexpand (priv->cert_button, TRUE);
	gtk_widget_show (priv->cert_button);
366
	gtk_widget_set_no_show_all (priv->cert_button, TRUE);
367 368 369 370 371 372 373 374 375 376

	/* For some reason, GTK+ calls set_current_filter (..., NULL) from
	 * gtkfilechooserdefault.c::show_and_select_files_finished_loading() on our
	 * dialog; so force-reset the filter to what we want it to be whenever
	 * it gets cleared.
	 */
	g_signal_connect (priv->cert_button, "notify::filter",
	                  G_CALLBACK (reset_filter), filter);

	g_signal_connect (priv->cert_button, "selection-changed",
377
	                  G_CALLBACK (cert_changed_cb), cert_chooser);
378 379

	priv->cert_button_label = gtk_label_new (NULL);
380
	g_object_set (priv->cert_button_label, "xalign", (gfloat) 1, NULL);
381
	gtk_label_set_mnemonic_widget (GTK_LABEL (priv->cert_button_label), priv->cert_button);
382
	gtk_grid_attach (GTK_GRID (cert_chooser), priv->cert_button_label, 0, 0, 1, 1);
383
	gtk_widget_show (priv->cert_button_label);
384
	gtk_widget_set_no_show_all (priv->cert_button_label, TRUE);
385
}
386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406

const NMACertChooserVtable nma_cert_chooser_vtable_file = {
	.init = init,

	.set_title = set_title,
	.set_flags = set_flags,

	.set_cert_uri = set_cert_uri,
	.get_cert_uri = get_cert_uri,
	.set_key_uri = set_key_uri,
	.get_key_uri = get_key_uri,
	.set_key_password = set_key_password,
	.get_key_password = get_key_password,

	.add_to_size_group = add_to_size_group,
	.validate = validate,

	.setup_key_password_storage = setup_key_password_storage,
	.update_key_password_storage = update_key_password_storage,
	.get_key_password_flags = get_key_password_flags,
};