blob: e3a23f0d7fbfe0bdfcd76e87523aa30d7f5cf01d [file] [log] [blame]
Stepan Salenikovichbe87d2c2016-01-25 14:14:34 -05001/*
Guillaume Roguez2a6150d2017-07-19 18:24:47 -04002 * Copyright (C) 2015-2017 Savoir-faire Linux Inc.
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -04003 * Author: Stepan Salenikovich <stepan.salenikovich@savoirfairelinux.com>
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 3 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040018 */
19
20#include "accountsecuritytab.h"
21
22#include <gtk/gtk.h>
23#include <account.h>
24#include "models/activeitemproxymodel.h"
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040025#include "models/gtkqtreemodel.h"
26#include "utils/models.h"
27#include <certificate.h>
28#include <ciphermodel.h>
29#include <QtCore/QItemSelectionModel>
30
31struct _AccountSecurityTab
32{
33 GtkBox parent;
34};
35
36struct _AccountSecurityTabClass
37{
38 GtkBoxClass parent_class;
39};
40
41typedef struct _AccountSecurityTabPrivate AccountSecurityTabPrivate;
42
43struct _AccountSecurityTabPrivate
44{
45 Account *account;
aviau7e3c3f92016-12-12 15:10:46 -050046 GtkWidget *frame_srtp;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040047 GtkWidget *checkbutton_use_srtp;
48 GtkWidget *box_key_exchange;
49 GtkWidget *combobox_key_exchange;
50 GtkWidget *checkbutton_srtp_fallback;
51 GtkWidget *checkbutton_use_tls;
52 GtkWidget *grid_tls_settings_0;
53 GtkWidget *filechooserbutton_ca_list;
54 /* TODO: add when implemented
55 GtkWidget *button_view_ca;
56 GtkWidget *button_view_certificate;
57 */
58 GtkWidget *filechooserbutton_certificate;
59 GtkWidget *filechooserbutton_private_key;
Stepan Salenikovich6242ff12015-08-14 15:20:03 -040060 GtkWidget *label_private_key_password;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040061 GtkWidget *entry_password;
Stepan Salenikovich6242ff12015-08-14 15:20:03 -040062 GtkWidget *label_password_matches;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040063 GtkWidget *grid_tls_settings_1;
64 GtkWidget *combobox_tls_protocol_method;
65 GtkWidget *entry_tls_server_name;
66 GtkWidget *adjustment_tls_timeout;
67 GtkWidget *buttonbox_cipher_list;
68 GtkWidget *radiobutton_use_default_ciphers;
69 GtkWidget *radiobutton_custom_ciphers;
70 GtkWidget *revealer_cipher_list;
71 GtkWidget *treeview_cipher_list;
72 GtkWidget *checkbutton_verify_certs_server;
73 GtkWidget *checkbutton_verify_certs_client;
74 GtkWidget *checkbutton_require_incoming_tls_certs;
75
76 QMetaObject::Connection account_updated;
77 QMetaObject::Connection key_exchange_selection;
78 QMetaObject::Connection tls_method_selection;
Stepan Salenikovich6242ff12015-08-14 15:20:03 -040079 QMetaObject::Connection cert_changed;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040080
81 ActiveItemProxyModel *qmodel_key_exchange;
Stepan Salenikovich6242ff12015-08-14 15:20:03 -040082
83 Certificate *user_cert;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040084};
85
86G_DEFINE_TYPE_WITH_PRIVATE(AccountSecurityTab, account_security_tab, GTK_TYPE_BOX);
87
88#define ACCOUNT_SECURITY_TAB_GET_PRIVATE(obj) \
89 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_SECURITY_TAB_TYPE, \
90 AccountSecurityTabPrivate))
91
92static void
93account_security_tab_dispose(GObject *object)
94{
95 AccountSecurityTab *view = ACCOUNT_SECURITY_TAB(object);
96 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(view);
97
98 QObject::disconnect(priv->account_updated);
99 QObject::disconnect(priv->key_exchange_selection);
100 QObject::disconnect(priv->tls_method_selection);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400101 QObject::disconnect(priv->cert_changed);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400102
103 G_OBJECT_CLASS(account_security_tab_parent_class)->dispose(object);
104}
105
106static void
107account_security_tab_finalize(GObject *object)
108{
109 AccountSecurityTab *view = ACCOUNT_SECURITY_TAB(object);
110 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(view);
111
Nicolas Jagerfad674f2017-10-19 11:35:36 -0400112 if (priv->qmodel_key_exchange) {
113 delete priv->qmodel_key_exchange;
114 priv->qmodel_key_exchange = nullptr;
115 }
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400116
117 G_OBJECT_CLASS(account_security_tab_parent_class)->finalize(object);
118}
119
120static void
121account_security_tab_init(AccountSecurityTab *view)
122{
123 gtk_widget_init_template(GTK_WIDGET(view));
124}
125
126static void
127account_security_tab_class_init(AccountSecurityTabClass *klass)
128{
129 G_OBJECT_CLASS(klass)->dispose = account_security_tab_dispose;
130 G_OBJECT_CLASS(klass)->finalize = account_security_tab_finalize;
131
132 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
133 "/cx/ring/RingGnome/accountsecuritytab.ui");
134
aviau7e3c3f92016-12-12 15:10:46 -0500135 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, frame_srtp);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400136 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_use_srtp);
137 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, box_key_exchange);
138 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, combobox_key_exchange);
139 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_srtp_fallback);
140 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_use_tls);
141 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, grid_tls_settings_0);
142 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_ca_list);
143 /* TODO: add when implemented
144 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, button_view_ca);
145 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, button_view_certificate);
146 */
147 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_certificate);
148 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_private_key);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400149 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, label_private_key_password);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400150 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, entry_password);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400151 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, label_password_matches);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400152 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, grid_tls_settings_1);
153 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, combobox_tls_protocol_method);
154 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, entry_tls_server_name);
155 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, adjustment_tls_timeout);
156 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, buttonbox_cipher_list);
157 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, radiobutton_use_default_ciphers);
158 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, radiobutton_custom_ciphers);
159 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, revealer_cipher_list);
160 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, treeview_cipher_list);
161 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_verify_certs_server);
162 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_verify_certs_client);
163 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_require_incoming_tls_certs);
164}
165
166static void
167use_srtp_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
168{
169 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
170 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
171
172 gboolean use_srtp = gtk_toggle_button_get_active(toggle_button);
173
174 priv->account->setSrtpEnabled(use_srtp);
175 priv->account->keyExchangeModel()->enableSRTP(use_srtp);
176
177 /* the other options are not relevant if SRTP is not active */
178 gtk_widget_set_sensitive(priv->box_key_exchange, priv->account->isSrtpEnabled());
179 gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback, priv->account->isSrtpEnabled());
180}
181
182static void
183use_rtp_fallback_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
184{
185 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
186 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
187
188 gboolean use_rtp_fallback = gtk_toggle_button_get_active(toggle_button);
189
190 priv->account->setSrtpRtpFallback(use_rtp_fallback);
191}
192
193static void
194use_tls_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
195{
196 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
197 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
198
199 gboolean use_tls = gtk_toggle_button_get_active(toggle_button);
200
201 priv->account->setTlsEnabled(use_tls);
202
203 /* disable the other tls options if no tls */
204 gtk_widget_set_sensitive(priv->grid_tls_settings_0, priv->account->isTlsEnabled());
205 gtk_widget_set_sensitive(priv->grid_tls_settings_1, priv->account->isTlsEnabled());
206 gtk_widget_set_sensitive(priv->buttonbox_cipher_list, priv->account->isTlsEnabled());
207 gtk_widget_set_sensitive(priv->treeview_cipher_list, priv->account->isTlsEnabled());
208 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server, priv->account->isTlsEnabled());
209 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client, priv->account->isTlsEnabled());
210 gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs, priv->account->isTlsEnabled());
211}
212
213static void
214tls_server_name_changed(GtkEntry *entry, AccountSecurityTab *self)
215{
216 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
217 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
218
219 priv->account->setTlsServerName(gtk_entry_get_text(entry));
220}
221
222static void
223tls_timeout_changed(GtkAdjustment *adjustment, AccountSecurityTab *self)
224{
225 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
226 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
227
228 int timeout = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
229 priv->account->setTlsNegotiationTimeoutSec(timeout);
230}
231
232static void
233use_default_ciphers_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
234{
235 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
236 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
237
238 gboolean use_default_ciphers = gtk_toggle_button_get_active(toggle_button);
239
240 priv->account->cipherModel()->setUseDefault(use_default_ciphers);
241
242 /* hide the cipher list if we're using the default ones */
243 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list), !use_default_ciphers);
244}
245
246static void
247cipher_enable_toggled(GtkCellRendererToggle *renderer, gchar *path, AccountSecurityTab *self)
248{
249 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
250 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
251
252 /* we want to set it to the opposite of the current value */
253 gboolean toggle = !gtk_cell_renderer_toggle_get_active(renderer);
254
255 /* get iter which was clicked */
256 GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
257 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_cipher_list));
258 GtkTreeIter iter;
259 gtk_tree_model_get_iter(model, &iter, tree_path);
260
261 /* get qmodelindex from iter and set the model data */
262 QModelIndex idx = gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), &iter);
263 if (idx.isValid())
264 priv->account->cipherModel()->setData(idx, toggle ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
265}
266
267static void
268render_check_state(G_GNUC_UNUSED GtkCellLayout *cell_layout,
269 GtkCellRenderer *cell,
270 GtkTreeModel *model,
271 GtkTreeIter *iter,
272 G_GNUC_UNUSED gpointer data)
273{
274 QModelIndex idx;
275 if (GTK_IS_Q_TREE_MODEL(model))
276 idx = gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), iter);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400277
278 gboolean checked = FALSE;
279
280 if (idx.isValid()) {
281 checked = idx.data(Qt::CheckStateRole).value<int>() == Qt::Checked ? TRUE : FALSE;
282 }
283
284 g_object_set(G_OBJECT(cell), "active", checked, NULL);
285}
286
287static void
288verify_certs_server_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
289{
290 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
291 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
292
293 gboolean verify_certs = gtk_toggle_button_get_active(toggle_button);
294
295 priv->account->setTlsVerifyServer(verify_certs);
296}
297
298static void
299verify_certs_client_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
300{
301 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
302 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
303
304 gboolean verify_certs = gtk_toggle_button_get_active(toggle_button);
305
306 priv->account->setTlsVerifyClient(verify_certs);
307}
308
309static void
310require_incoming_certs_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
311{
312 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
313 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
314
315 gboolean require = gtk_toggle_button_get_active(toggle_button);
316
317 priv->account->setTlsRequireClientCertificate(require);
318}
319
320static void
321ca_cert_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
322{
323 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
324 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
325
326 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400327
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400328 priv->account->setTlsCaListCertificate(filename);
329 g_free(filename);
330}
331
332static void
333user_cert_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
334{
335 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
336 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
337
338 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400339
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400340 priv->account->setTlsCertificate(filename);
341 g_free(filename);
342}
343
344static void
345private_key_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
346{
347 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
348 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
349
350 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400351
352 priv->account->setTlsPrivateKey(filename);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400353 g_free(filename);
354}
355
356static void
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400357private_key_password_changed(GtkEntry *entry, AccountSecurityTab *self)
358{
359 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
360 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
361
362 priv->account->setTlsPassword(gtk_entry_get_text(entry));
363}
364
365static void
366check_tlspassword_valid(AccountSecurityTab *self)
367{
368 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
369 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
370
371 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
372 if (priv->user_cert->privateKeyMatch() == Certificate::CheckValues::PASSED) {
373 gtk_label_set_markup(
374 GTK_LABEL(priv->label_password_matches),
375 "<span fgcolor=\"green\">&#x2713;</span>"
376 );
377 } else {
378 gtk_label_set_markup(
379 GTK_LABEL(priv->label_password_matches),
380 "<span fgcolor=\"red\">&#x2717;</span>"
381 );
382 }
383 } else {
384 gtk_label_set_text(GTK_LABEL(priv->label_password_matches), "");
385 }
386}
387
388static void
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400389build_tab_view(AccountSecurityTab *self)
390{
391 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
392 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
393
aviau7e3c3f92016-12-12 15:10:46 -0500394 gboolean is_ring_account = priv->account->protocol() == Account::Protocol::RING;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400395
396 /* SRTP */
397 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp),
398 priv->account->isSrtpEnabled());
399 /* disable options if SRTP is off or if its a RING account */
aviau7e3c3f92016-12-12 15:10:46 -0500400 gtk_widget_set_sensitive(priv->checkbutton_use_srtp, !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400401 gtk_widget_set_sensitive(priv->box_key_exchange,
aviau7e3c3f92016-12-12 15:10:46 -0500402 priv->account->isSrtpEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400403 gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback,
aviau7e3c3f92016-12-12 15:10:46 -0500404 priv->account->isSrtpEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400405 g_signal_connect(priv->checkbutton_use_srtp, "toggled", G_CALLBACK(use_srtp_toggled), self);
406
407 /* encryption key exchange type */
Stepan Salenikovich4c31b212017-04-26 13:45:12 -0400408 priv->key_exchange_selection = gtk_combo_box_set_qmodel_text(
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400409 GTK_COMBO_BOX(priv->combobox_key_exchange),
410 (QAbstractItemModel *)priv->account->keyExchangeModel(),
411 priv->account->keyExchangeModel()->selectionModel());
412
413 /* SRTP fallback */
414 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback),
415 priv->account->isSrtpRtpFallback());
416 g_signal_connect(priv->checkbutton_srtp_fallback, "toggled", G_CALLBACK(use_rtp_fallback_toggled), self);
417
418 /* use TLS */
419 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls),
420 priv->account->isTlsEnabled());
421
aviau7e3c3f92016-12-12 15:10:46 -0500422 /* disable certain options if TLS is off */
423 gtk_widget_set_sensitive(priv->checkbutton_use_tls, !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400424 gtk_widget_set_sensitive(priv->grid_tls_settings_0,
425 priv->account->isTlsEnabled());
426 gtk_widget_set_sensitive(priv->grid_tls_settings_1,
aviau7e3c3f92016-12-12 15:10:46 -0500427 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400428 gtk_widget_set_sensitive(priv->buttonbox_cipher_list,
aviau7e3c3f92016-12-12 15:10:46 -0500429 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400430 gtk_widget_set_sensitive(priv->treeview_cipher_list,
aviau7e3c3f92016-12-12 15:10:46 -0500431 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400432 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server,
aviau7e3c3f92016-12-12 15:10:46 -0500433 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400434 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client,
aviau7e3c3f92016-12-12 15:10:46 -0500435 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400436 gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs,
aviau7e3c3f92016-12-12 15:10:46 -0500437 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400438 g_signal_connect(priv->checkbutton_use_tls, "toggled", G_CALLBACK(use_tls_toggled), self);
439
aviau7e3c3f92016-12-12 15:10:46 -0500440 /* hide everything that is not relevant to Ring accounts */
441 if (is_ring_account)
442 {
443 gtk_widget_hide(priv->frame_srtp);
444 gtk_widget_hide(priv->grid_tls_settings_1);
445 gtk_widget_hide(priv->checkbutton_verify_certs_server);
446 gtk_widget_hide(priv->checkbutton_verify_certs_client);
447 gtk_widget_hide(priv->checkbutton_require_incoming_tls_certs);
448 gtk_widget_hide(priv->buttonbox_cipher_list);
449 }
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400450 /* CA certificate */
451 Certificate *ca_cert = priv->account->tlsCaListCertificate();
452 if (ca_cert) {
453 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400454 ca_cert->path().toUtf8().constData());
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400455 }
456 g_signal_connect(priv->filechooserbutton_ca_list, "file-set", G_CALLBACK(ca_cert_file_set), self);
457
458 /* user certificate */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400459 if ( (priv->user_cert = priv->account->tlsCertificate()) ) {
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400460 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400461 priv->user_cert->path().toUtf8().constData()
462 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400463 }
Stepan Salenikovichd890ad72015-05-20 10:17:48 -0400464 g_signal_connect(priv->filechooserbutton_certificate, "file-set", G_CALLBACK(user_cert_file_set), self);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400465
466 /* private key */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400467 if (!priv->account->tlsPrivateKey().isEmpty()) {
468 gtk_file_chooser_set_filename(
469 GTK_FILE_CHOOSER(priv->filechooserbutton_private_key),
470 priv->account->tlsPrivateKey().toUtf8().constData()
471 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400472 }
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400473
Stepan Salenikovichd890ad72015-05-20 10:17:48 -0400474 g_signal_connect(priv->filechooserbutton_private_key, "file-set", G_CALLBACK(private_key_file_set), self);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400475
476 /* password */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400477 check_tlspassword_valid(self);
478 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
479 gtk_entry_set_text(
480 GTK_ENTRY(priv->entry_password),
481 priv->account->tlsPassword().toUtf8().constData()
482 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400483 gtk_widget_set_sensitive(priv->entry_password, TRUE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400484 gtk_widget_set_sensitive(priv->label_private_key_password, TRUE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400485 } else {
486 /* private key not chosen, or password not required, so disactivate the entry */
487 gtk_widget_set_sensitive(priv->entry_password, FALSE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400488 gtk_widget_set_sensitive(priv->label_private_key_password, FALSE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400489 }
490
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400491 g_signal_connect(priv->entry_password, "changed", G_CALLBACK(private_key_password_changed), self);
492
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400493 /* TLS protocol method */
Stepan Salenikovich4c31b212017-04-26 13:45:12 -0400494 priv->tls_method_selection = gtk_combo_box_set_qmodel_text(GTK_COMBO_BOX(priv->combobox_tls_protocol_method),
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400495 (QAbstractItemModel *)priv->account->tlsMethodModel(),
496 priv->account->tlsMethodModel()->selectionModel());
497
498 /* outgoing TLS server */
499 gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name),
500 priv->account->tlsServerName().toUtf8().constData());
501 g_signal_connect(priv->entry_tls_server_name, "changed", G_CALLBACK(tls_server_name_changed), self);
502
503
504 /* TLS nego timeout */
505 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout),
506 priv->account->tlsNegotiationTimeoutSec());
507 g_signal_connect(priv->adjustment_tls_timeout, "value-changed", G_CALLBACK(tls_timeout_changed), self);
508
509 /* cipher default or custom */
510 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers),
511 priv->account->cipherModel()->useDefault());
512 /* hide the cipher list if we're using the default ones */
513 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list),
514 !priv->account->cipherModel()->useDefault());
515 g_signal_connect(priv->radiobutton_use_default_ciphers,
516 "toggled", G_CALLBACK(use_default_ciphers_toggled), self);
517
518 /* cipher list */
519 GtkQTreeModel *cipher_model = gtk_q_tree_model_new(
520 (QAbstractItemModel *)priv->account->cipherModel(),
521 2,
aviau9bbb19b2016-05-16 15:53:44 -0400522 0, Qt::CheckStateRole, G_TYPE_BOOLEAN,
523 0, Qt::DisplayRole, G_TYPE_STRING);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400524 gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_cipher_list),
525 GTK_TREE_MODEL(cipher_model));
526 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(priv->treeview_cipher_list),
527 FALSE);
528
529 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
530 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
531 "Enabled", renderer, NULL);
532 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column);
533
534 /* we have to use a custom data function here because Qt::Checked and Qt::Unchecked
535 * are not the same as true/false as there is an intermediate state */
536 gtk_tree_view_column_set_cell_data_func(column,
537 renderer,
538 (GtkTreeCellDataFunc)render_check_state,
539 NULL, NULL);
540
541 g_signal_connect(renderer, "toggled", G_CALLBACK(cipher_enable_toggled), self);
542
543 renderer = gtk_cell_renderer_text_new();
544 column = gtk_tree_view_column_new_with_attributes("Cipher", renderer, "text", 1, NULL);
545 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column);
546
547 /* server certs */
548 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server),
549 priv->account->isTlsVerifyServer());
Stepan Salenikovich226df012015-07-08 16:09:39 -0400550 g_signal_connect(priv->checkbutton_verify_certs_server,
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400551 "toggled", G_CALLBACK(verify_certs_server_toggled), self);
552
553 /* client certs */
554 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client),
555 priv->account->isTlsVerifyClient());
556 g_signal_connect(priv->checkbutton_verify_certs_client,
557 "toggled", G_CALLBACK(verify_certs_client_toggled), self);
558
559 /* incoming certs */
560 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs),
561 priv->account->isTlsRequireClientCertificate());
562 g_signal_connect(priv->checkbutton_require_incoming_tls_certs,
563 "toggled", G_CALLBACK(require_incoming_certs_toggled), self);
564
565 /* update account UI if model is updated */
566 priv->account_updated = QObject::connect(
567 priv->account,
568 &Account::changed,
569 [=] () {
570 /* SRTP */
571 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp),
572 priv->account->isSrtpEnabled());
573
574 /* SRTP fallback */
575 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback),
576 priv->account->isSrtpRtpFallback());
577 /* use TLS */
578 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls),
579 priv->account->isTlsEnabled());
580
581 /* CA certificate */
582 Certificate *ca_cert = priv->account->tlsCaListCertificate();
583 if (ca_cert) {
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400584 gtk_file_chooser_set_filename(
585 GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list),
586 ca_cert->path().toUtf8().constData()
587 );
588 } else {
589 /* make sure nothing is selected */
590 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400591 }
592
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400593
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400594 /* user certificate */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400595 QObject::disconnect(priv->cert_changed);
596 if ( (priv->user_cert = priv->account->tlsCertificate()) ) {
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400597 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400598 priv->user_cert->path().toUtf8().constData()
599 );
600 } else {
601 /* make sure nothing is selected */
602 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400603 }
604
605 /* private key */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400606 if (!priv->account->tlsPrivateKey().isEmpty()) {
607 gtk_file_chooser_set_filename(
608 GTK_FILE_CHOOSER(priv->filechooserbutton_private_key),
609 priv->account->tlsPrivateKey().toUtf8().constData()
610 );
611 } else {
612 /* make sure nothing is selected */
613 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_private_key));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400614 }
615
616 /* password */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400617 check_tlspassword_valid(self);
618 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
619 gtk_entry_set_text(
620 GTK_ENTRY(priv->entry_password),
621 priv->account->tlsPassword().toUtf8().constData()
622 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400623 gtk_widget_set_sensitive(priv->entry_password, TRUE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400624 gtk_widget_set_sensitive(priv->label_private_key_password, TRUE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400625 } else {
626 /* private key not chosen, or password not required, so disactivate the entry */
627 gtk_widget_set_sensitive(priv->entry_password, FALSE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400628 gtk_widget_set_sensitive(priv->label_private_key_password, FALSE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400629 }
630
631 /* outgoing TLS server */
632 gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name),
633 priv->account->tlsServerName().toUtf8().constData());
634
635 /* TLS nego timeout */
636 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout),
637 priv->account->tlsNegotiationTimeoutSec());
638
639 /* cipher default or custom */
640 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers),
641 priv->account->cipherModel()->useDefault());
642
643 /* server certs */
644 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server),
645 priv->account->isTlsVerifyServer());
646
647 /* client certs */
648 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client),
649 priv->account->isTlsVerifyClient());
650
651 /* incoming certs */
652 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs),
653 priv->account->isTlsRequireClientCertificate());
654 }
655 );
656}
657
658GtkWidget *
659account_security_tab_new(Account *account)
660{
661 g_return_val_if_fail(account != NULL, NULL);
662
663 gpointer view = g_object_new(ACCOUNT_SECURITY_TAB_TYPE, NULL);
664
665 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(view);
666 priv->account = account;
667
668 build_tab_view(ACCOUNT_SECURITY_TAB(view));
669
670 return (GtkWidget *)view;
671}