blob: de17a3293b1dc1fd767f36eedf8289cc66fb3698 [file] [log] [blame]
Stepan Salenikovichbe87d2c2016-01-25 14:14:34 -05001/*
2 * Copyright (C) 2015-2016 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
112 delete priv->qmodel_key_exchange;
113
114 G_OBJECT_CLASS(account_security_tab_parent_class)->finalize(object);
115}
116
117static void
118account_security_tab_init(AccountSecurityTab *view)
119{
120 gtk_widget_init_template(GTK_WIDGET(view));
121}
122
123static void
124account_security_tab_class_init(AccountSecurityTabClass *klass)
125{
126 G_OBJECT_CLASS(klass)->dispose = account_security_tab_dispose;
127 G_OBJECT_CLASS(klass)->finalize = account_security_tab_finalize;
128
129 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
130 "/cx/ring/RingGnome/accountsecuritytab.ui");
131
aviau7e3c3f92016-12-12 15:10:46 -0500132 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, frame_srtp);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400133 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_use_srtp);
134 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, box_key_exchange);
135 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, combobox_key_exchange);
136 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_srtp_fallback);
137 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_use_tls);
138 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, grid_tls_settings_0);
139 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_ca_list);
140 /* TODO: add when implemented
141 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, button_view_ca);
142 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, button_view_certificate);
143 */
144 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_certificate);
145 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_private_key);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400146 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, label_private_key_password);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400147 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, entry_password);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400148 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, label_password_matches);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400149 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, grid_tls_settings_1);
150 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, combobox_tls_protocol_method);
151 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, entry_tls_server_name);
152 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, adjustment_tls_timeout);
153 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, buttonbox_cipher_list);
154 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, radiobutton_use_default_ciphers);
155 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, radiobutton_custom_ciphers);
156 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, revealer_cipher_list);
157 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, treeview_cipher_list);
158 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_verify_certs_server);
159 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_verify_certs_client);
160 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_require_incoming_tls_certs);
161}
162
163static void
164use_srtp_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
165{
166 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
167 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
168
169 gboolean use_srtp = gtk_toggle_button_get_active(toggle_button);
170
171 priv->account->setSrtpEnabled(use_srtp);
172 priv->account->keyExchangeModel()->enableSRTP(use_srtp);
173
174 /* the other options are not relevant if SRTP is not active */
175 gtk_widget_set_sensitive(priv->box_key_exchange, priv->account->isSrtpEnabled());
176 gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback, priv->account->isSrtpEnabled());
177}
178
179static void
180use_rtp_fallback_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
181{
182 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
183 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
184
185 gboolean use_rtp_fallback = gtk_toggle_button_get_active(toggle_button);
186
187 priv->account->setSrtpRtpFallback(use_rtp_fallback);
188}
189
190static void
191use_tls_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
192{
193 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
194 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
195
196 gboolean use_tls = gtk_toggle_button_get_active(toggle_button);
197
198 priv->account->setTlsEnabled(use_tls);
199
200 /* disable the other tls options if no tls */
201 gtk_widget_set_sensitive(priv->grid_tls_settings_0, priv->account->isTlsEnabled());
202 gtk_widget_set_sensitive(priv->grid_tls_settings_1, priv->account->isTlsEnabled());
203 gtk_widget_set_sensitive(priv->buttonbox_cipher_list, priv->account->isTlsEnabled());
204 gtk_widget_set_sensitive(priv->treeview_cipher_list, priv->account->isTlsEnabled());
205 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server, priv->account->isTlsEnabled());
206 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client, priv->account->isTlsEnabled());
207 gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs, priv->account->isTlsEnabled());
208}
209
210static void
211tls_server_name_changed(GtkEntry *entry, AccountSecurityTab *self)
212{
213 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
214 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
215
216 priv->account->setTlsServerName(gtk_entry_get_text(entry));
217}
218
219static void
220tls_timeout_changed(GtkAdjustment *adjustment, AccountSecurityTab *self)
221{
222 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
223 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
224
225 int timeout = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
226 priv->account->setTlsNegotiationTimeoutSec(timeout);
227}
228
229static void
230use_default_ciphers_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
231{
232 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
233 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
234
235 gboolean use_default_ciphers = gtk_toggle_button_get_active(toggle_button);
236
237 priv->account->cipherModel()->setUseDefault(use_default_ciphers);
238
239 /* hide the cipher list if we're using the default ones */
240 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list), !use_default_ciphers);
241}
242
243static void
244cipher_enable_toggled(GtkCellRendererToggle *renderer, gchar *path, AccountSecurityTab *self)
245{
246 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
247 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
248
249 /* we want to set it to the opposite of the current value */
250 gboolean toggle = !gtk_cell_renderer_toggle_get_active(renderer);
251
252 /* get iter which was clicked */
253 GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
254 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_cipher_list));
255 GtkTreeIter iter;
256 gtk_tree_model_get_iter(model, &iter, tree_path);
257
258 /* get qmodelindex from iter and set the model data */
259 QModelIndex idx = gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), &iter);
260 if (idx.isValid())
261 priv->account->cipherModel()->setData(idx, toggle ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
262}
263
264static void
265render_check_state(G_GNUC_UNUSED GtkCellLayout *cell_layout,
266 GtkCellRenderer *cell,
267 GtkTreeModel *model,
268 GtkTreeIter *iter,
269 G_GNUC_UNUSED gpointer data)
270{
271 QModelIndex idx;
272 if (GTK_IS_Q_TREE_MODEL(model))
273 idx = gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), iter);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400274
275 gboolean checked = FALSE;
276
277 if (idx.isValid()) {
278 checked = idx.data(Qt::CheckStateRole).value<int>() == Qt::Checked ? TRUE : FALSE;
279 }
280
281 g_object_set(G_OBJECT(cell), "active", checked, NULL);
282}
283
284static void
285verify_certs_server_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
286{
287 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
288 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
289
290 gboolean verify_certs = gtk_toggle_button_get_active(toggle_button);
291
292 priv->account->setTlsVerifyServer(verify_certs);
293}
294
295static void
296verify_certs_client_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
297{
298 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
299 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
300
301 gboolean verify_certs = gtk_toggle_button_get_active(toggle_button);
302
303 priv->account->setTlsVerifyClient(verify_certs);
304}
305
306static void
307require_incoming_certs_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
308{
309 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
310 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
311
312 gboolean require = gtk_toggle_button_get_active(toggle_button);
313
314 priv->account->setTlsRequireClientCertificate(require);
315}
316
317static void
318ca_cert_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
319{
320 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
321 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
322
323 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400324
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400325 priv->account->setTlsCaListCertificate(filename);
326 g_free(filename);
327}
328
329static void
330user_cert_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
331{
332 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
333 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
334
335 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400336
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400337 priv->account->setTlsCertificate(filename);
338 g_free(filename);
339}
340
341static void
342private_key_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
343{
344 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
345 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
346
347 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400348
349 priv->account->setTlsPrivateKey(filename);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400350 g_free(filename);
351}
352
353static void
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400354private_key_password_changed(GtkEntry *entry, AccountSecurityTab *self)
355{
356 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
357 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
358
359 priv->account->setTlsPassword(gtk_entry_get_text(entry));
360}
361
362static void
363check_tlspassword_valid(AccountSecurityTab *self)
364{
365 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
366 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
367
368 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
369 if (priv->user_cert->privateKeyMatch() == Certificate::CheckValues::PASSED) {
370 gtk_label_set_markup(
371 GTK_LABEL(priv->label_password_matches),
372 "<span fgcolor=\"green\">&#x2713;</span>"
373 );
374 } else {
375 gtk_label_set_markup(
376 GTK_LABEL(priv->label_password_matches),
377 "<span fgcolor=\"red\">&#x2717;</span>"
378 );
379 }
380 } else {
381 gtk_label_set_text(GTK_LABEL(priv->label_password_matches), "");
382 }
383}
384
385static void
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400386build_tab_view(AccountSecurityTab *self)
387{
388 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
389 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
390
aviau7e3c3f92016-12-12 15:10:46 -0500391 gboolean is_ring_account = priv->account->protocol() == Account::Protocol::RING;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400392
393 /* SRTP */
394 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp),
395 priv->account->isSrtpEnabled());
396 /* disable options if SRTP is off or if its a RING account */
aviau7e3c3f92016-12-12 15:10:46 -0500397 gtk_widget_set_sensitive(priv->checkbutton_use_srtp, !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400398 gtk_widget_set_sensitive(priv->box_key_exchange,
aviau7e3c3f92016-12-12 15:10:46 -0500399 priv->account->isSrtpEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400400 gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback,
aviau7e3c3f92016-12-12 15:10:46 -0500401 priv->account->isSrtpEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400402 g_signal_connect(priv->checkbutton_use_srtp, "toggled", G_CALLBACK(use_srtp_toggled), self);
403
404 /* encryption key exchange type */
405 priv->key_exchange_selection = gtk_combo_box_set_qmodel(
406 GTK_COMBO_BOX(priv->combobox_key_exchange),
407 (QAbstractItemModel *)priv->account->keyExchangeModel(),
408 priv->account->keyExchangeModel()->selectionModel());
409
410 /* SRTP fallback */
411 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback),
412 priv->account->isSrtpRtpFallback());
413 g_signal_connect(priv->checkbutton_srtp_fallback, "toggled", G_CALLBACK(use_rtp_fallback_toggled), self);
414
415 /* use TLS */
416 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls),
417 priv->account->isTlsEnabled());
418
aviau7e3c3f92016-12-12 15:10:46 -0500419 /* disable certain options if TLS is off */
420 gtk_widget_set_sensitive(priv->checkbutton_use_tls, !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400421 gtk_widget_set_sensitive(priv->grid_tls_settings_0,
422 priv->account->isTlsEnabled());
423 gtk_widget_set_sensitive(priv->grid_tls_settings_1,
aviau7e3c3f92016-12-12 15:10:46 -0500424 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400425 gtk_widget_set_sensitive(priv->buttonbox_cipher_list,
aviau7e3c3f92016-12-12 15:10:46 -0500426 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400427 gtk_widget_set_sensitive(priv->treeview_cipher_list,
aviau7e3c3f92016-12-12 15:10:46 -0500428 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400429 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server,
aviau7e3c3f92016-12-12 15:10:46 -0500430 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400431 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client,
aviau7e3c3f92016-12-12 15:10:46 -0500432 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400433 gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs,
aviau7e3c3f92016-12-12 15:10:46 -0500434 priv->account->isTlsEnabled() && !is_ring_account);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400435 g_signal_connect(priv->checkbutton_use_tls, "toggled", G_CALLBACK(use_tls_toggled), self);
436
aviau7e3c3f92016-12-12 15:10:46 -0500437 /* hide everything that is not relevant to Ring accounts */
438 if (is_ring_account)
439 {
440 gtk_widget_hide(priv->frame_srtp);
441 gtk_widget_hide(priv->grid_tls_settings_1);
442 gtk_widget_hide(priv->checkbutton_verify_certs_server);
443 gtk_widget_hide(priv->checkbutton_verify_certs_client);
444 gtk_widget_hide(priv->checkbutton_require_incoming_tls_certs);
445 gtk_widget_hide(priv->buttonbox_cipher_list);
446 }
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400447 /* CA certificate */
448 Certificate *ca_cert = priv->account->tlsCaListCertificate();
449 if (ca_cert) {
450 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400451 ca_cert->path().toUtf8().constData());
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400452 }
453 g_signal_connect(priv->filechooserbutton_ca_list, "file-set", G_CALLBACK(ca_cert_file_set), self);
454
455 /* user certificate */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400456 if ( (priv->user_cert = priv->account->tlsCertificate()) ) {
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400457 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400458 priv->user_cert->path().toUtf8().constData()
459 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400460 }
Stepan Salenikovichd890ad72015-05-20 10:17:48 -0400461 g_signal_connect(priv->filechooserbutton_certificate, "file-set", G_CALLBACK(user_cert_file_set), self);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400462
463 /* private key */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400464 if (!priv->account->tlsPrivateKey().isEmpty()) {
465 gtk_file_chooser_set_filename(
466 GTK_FILE_CHOOSER(priv->filechooserbutton_private_key),
467 priv->account->tlsPrivateKey().toUtf8().constData()
468 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400469 }
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400470
Stepan Salenikovichd890ad72015-05-20 10:17:48 -0400471 g_signal_connect(priv->filechooserbutton_private_key, "file-set", G_CALLBACK(private_key_file_set), self);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400472
473 /* password */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400474 check_tlspassword_valid(self);
475 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
476 gtk_entry_set_text(
477 GTK_ENTRY(priv->entry_password),
478 priv->account->tlsPassword().toUtf8().constData()
479 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400480 gtk_widget_set_sensitive(priv->entry_password, TRUE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400481 gtk_widget_set_sensitive(priv->label_private_key_password, TRUE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400482 } else {
483 /* private key not chosen, or password not required, so disactivate the entry */
484 gtk_widget_set_sensitive(priv->entry_password, FALSE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400485 gtk_widget_set_sensitive(priv->label_private_key_password, FALSE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400486 }
487
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400488 g_signal_connect(priv->entry_password, "changed", G_CALLBACK(private_key_password_changed), self);
489
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400490 /* TLS protocol method */
491 priv->tls_method_selection = gtk_combo_box_set_qmodel(GTK_COMBO_BOX(priv->combobox_tls_protocol_method),
492 (QAbstractItemModel *)priv->account->tlsMethodModel(),
493 priv->account->tlsMethodModel()->selectionModel());
494
495 /* outgoing TLS server */
496 gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name),
497 priv->account->tlsServerName().toUtf8().constData());
498 g_signal_connect(priv->entry_tls_server_name, "changed", G_CALLBACK(tls_server_name_changed), self);
499
500
501 /* TLS nego timeout */
502 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout),
503 priv->account->tlsNegotiationTimeoutSec());
504 g_signal_connect(priv->adjustment_tls_timeout, "value-changed", G_CALLBACK(tls_timeout_changed), self);
505
506 /* cipher default or custom */
507 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers),
508 priv->account->cipherModel()->useDefault());
509 /* hide the cipher list if we're using the default ones */
510 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list),
511 !priv->account->cipherModel()->useDefault());
512 g_signal_connect(priv->radiobutton_use_default_ciphers,
513 "toggled", G_CALLBACK(use_default_ciphers_toggled), self);
514
515 /* cipher list */
516 GtkQTreeModel *cipher_model = gtk_q_tree_model_new(
517 (QAbstractItemModel *)priv->account->cipherModel(),
518 2,
aviau9bbb19b2016-05-16 15:53:44 -0400519 0, Qt::CheckStateRole, G_TYPE_BOOLEAN,
520 0, Qt::DisplayRole, G_TYPE_STRING);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400521 gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_cipher_list),
522 GTK_TREE_MODEL(cipher_model));
523 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(priv->treeview_cipher_list),
524 FALSE);
525
526 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
527 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
528 "Enabled", renderer, NULL);
529 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column);
530
531 /* we have to use a custom data function here because Qt::Checked and Qt::Unchecked
532 * are not the same as true/false as there is an intermediate state */
533 gtk_tree_view_column_set_cell_data_func(column,
534 renderer,
535 (GtkTreeCellDataFunc)render_check_state,
536 NULL, NULL);
537
538 g_signal_connect(renderer, "toggled", G_CALLBACK(cipher_enable_toggled), self);
539
540 renderer = gtk_cell_renderer_text_new();
541 column = gtk_tree_view_column_new_with_attributes("Cipher", renderer, "text", 1, NULL);
542 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column);
543
544 /* server certs */
545 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server),
546 priv->account->isTlsVerifyServer());
Stepan Salenikovich226df012015-07-08 16:09:39 -0400547 g_signal_connect(priv->checkbutton_verify_certs_server,
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400548 "toggled", G_CALLBACK(verify_certs_server_toggled), self);
549
550 /* client certs */
551 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client),
552 priv->account->isTlsVerifyClient());
553 g_signal_connect(priv->checkbutton_verify_certs_client,
554 "toggled", G_CALLBACK(verify_certs_client_toggled), self);
555
556 /* incoming certs */
557 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs),
558 priv->account->isTlsRequireClientCertificate());
559 g_signal_connect(priv->checkbutton_require_incoming_tls_certs,
560 "toggled", G_CALLBACK(require_incoming_certs_toggled), self);
561
562 /* update account UI if model is updated */
563 priv->account_updated = QObject::connect(
564 priv->account,
565 &Account::changed,
566 [=] () {
567 /* SRTP */
568 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp),
569 priv->account->isSrtpEnabled());
570
571 /* SRTP fallback */
572 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback),
573 priv->account->isSrtpRtpFallback());
574 /* use TLS */
575 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls),
576 priv->account->isTlsEnabled());
577
578 /* CA certificate */
579 Certificate *ca_cert = priv->account->tlsCaListCertificate();
580 if (ca_cert) {
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400581 gtk_file_chooser_set_filename(
582 GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list),
583 ca_cert->path().toUtf8().constData()
584 );
585 } else {
586 /* make sure nothing is selected */
587 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400588 }
589
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400590
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400591 /* user certificate */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400592 QObject::disconnect(priv->cert_changed);
593 if ( (priv->user_cert = priv->account->tlsCertificate()) ) {
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400594 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400595 priv->user_cert->path().toUtf8().constData()
596 );
597 } else {
598 /* make sure nothing is selected */
599 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400600 }
601
602 /* private key */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400603 if (!priv->account->tlsPrivateKey().isEmpty()) {
604 gtk_file_chooser_set_filename(
605 GTK_FILE_CHOOSER(priv->filechooserbutton_private_key),
606 priv->account->tlsPrivateKey().toUtf8().constData()
607 );
608 } else {
609 /* make sure nothing is selected */
610 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_private_key));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400611 }
612
613 /* password */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400614 check_tlspassword_valid(self);
615 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
616 gtk_entry_set_text(
617 GTK_ENTRY(priv->entry_password),
618 priv->account->tlsPassword().toUtf8().constData()
619 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400620 gtk_widget_set_sensitive(priv->entry_password, TRUE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400621 gtk_widget_set_sensitive(priv->label_private_key_password, TRUE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400622 } else {
623 /* private key not chosen, or password not required, so disactivate the entry */
624 gtk_widget_set_sensitive(priv->entry_password, FALSE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400625 gtk_widget_set_sensitive(priv->label_private_key_password, FALSE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400626 }
627
628 /* outgoing TLS server */
629 gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name),
630 priv->account->tlsServerName().toUtf8().constData());
631
632 /* TLS nego timeout */
633 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout),
634 priv->account->tlsNegotiationTimeoutSec());
635
636 /* cipher default or custom */
637 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers),
638 priv->account->cipherModel()->useDefault());
639
640 /* server certs */
641 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server),
642 priv->account->isTlsVerifyServer());
643
644 /* client certs */
645 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client),
646 priv->account->isTlsVerifyClient());
647
648 /* incoming certs */
649 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs),
650 priv->account->isTlsRequireClientCertificate());
651 }
652 );
653}
654
655GtkWidget *
656account_security_tab_new(Account *account)
657{
658 g_return_val_if_fail(account != NULL, NULL);
659
660 gpointer view = g_object_new(ACCOUNT_SECURITY_TAB_TYPE, NULL);
661
662 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(view);
663 priv->account = account;
664
665 build_tab_view(ACCOUNT_SECURITY_TAB(view));
666
667 return (GtkWidget *)view;
668}