blob: 028ae7749cdc22262afb5245932f666ccc428829 [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"
25#include "models/gtkqsortfiltertreemodel.h"
26#include "models/gtkqtreemodel.h"
27#include "utils/models.h"
28#include <certificate.h>
29#include <ciphermodel.h>
30#include <QtCore/QItemSelectionModel>
31
32struct _AccountSecurityTab
33{
34 GtkBox parent;
35};
36
37struct _AccountSecurityTabClass
38{
39 GtkBoxClass parent_class;
40};
41
42typedef struct _AccountSecurityTabPrivate AccountSecurityTabPrivate;
43
44struct _AccountSecurityTabPrivate
45{
46 Account *account;
47 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
132 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_use_srtp);
133 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, box_key_exchange);
134 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, combobox_key_exchange);
135 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_srtp_fallback);
136 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_use_tls);
137 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, grid_tls_settings_0);
138 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_ca_list);
139 /* TODO: add when implemented
140 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, button_view_ca);
141 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, button_view_certificate);
142 */
143 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_certificate);
144 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_private_key);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400145 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, label_private_key_password);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400146 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, entry_password);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400147 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, label_password_matches);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400148 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, grid_tls_settings_1);
149 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, combobox_tls_protocol_method);
150 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, entry_tls_server_name);
151 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, adjustment_tls_timeout);
152 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, buttonbox_cipher_list);
153 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, radiobutton_use_default_ciphers);
154 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, radiobutton_custom_ciphers);
155 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, revealer_cipher_list);
156 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, treeview_cipher_list);
157 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_verify_certs_server);
158 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_verify_certs_client);
159 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_require_incoming_tls_certs);
160}
161
162static void
163use_srtp_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
164{
165 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
166 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
167
168 gboolean use_srtp = gtk_toggle_button_get_active(toggle_button);
169
170 priv->account->setSrtpEnabled(use_srtp);
171 priv->account->keyExchangeModel()->enableSRTP(use_srtp);
172
173 /* the other options are not relevant if SRTP is not active */
174 gtk_widget_set_sensitive(priv->box_key_exchange, priv->account->isSrtpEnabled());
175 gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback, priv->account->isSrtpEnabled());
176}
177
178static void
179use_rtp_fallback_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
180{
181 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
182 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
183
184 gboolean use_rtp_fallback = gtk_toggle_button_get_active(toggle_button);
185
186 priv->account->setSrtpRtpFallback(use_rtp_fallback);
187}
188
189static void
190use_tls_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
191{
192 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
193 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
194
195 gboolean use_tls = gtk_toggle_button_get_active(toggle_button);
196
197 priv->account->setTlsEnabled(use_tls);
198
199 /* disable the other tls options if no tls */
200 gtk_widget_set_sensitive(priv->grid_tls_settings_0, priv->account->isTlsEnabled());
201 gtk_widget_set_sensitive(priv->grid_tls_settings_1, priv->account->isTlsEnabled());
202 gtk_widget_set_sensitive(priv->buttonbox_cipher_list, priv->account->isTlsEnabled());
203 gtk_widget_set_sensitive(priv->treeview_cipher_list, priv->account->isTlsEnabled());
204 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server, priv->account->isTlsEnabled());
205 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client, priv->account->isTlsEnabled());
206 gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs, priv->account->isTlsEnabled());
207}
208
209static void
210tls_server_name_changed(GtkEntry *entry, AccountSecurityTab *self)
211{
212 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
213 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
214
215 priv->account->setTlsServerName(gtk_entry_get_text(entry));
216}
217
218static void
219tls_timeout_changed(GtkAdjustment *adjustment, AccountSecurityTab *self)
220{
221 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
222 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
223
224 int timeout = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
225 priv->account->setTlsNegotiationTimeoutSec(timeout);
226}
227
228static void
229use_default_ciphers_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
230{
231 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
232 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
233
234 gboolean use_default_ciphers = gtk_toggle_button_get_active(toggle_button);
235
236 priv->account->cipherModel()->setUseDefault(use_default_ciphers);
237
238 /* hide the cipher list if we're using the default ones */
239 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list), !use_default_ciphers);
240}
241
242static void
243cipher_enable_toggled(GtkCellRendererToggle *renderer, gchar *path, AccountSecurityTab *self)
244{
245 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
246 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
247
248 /* we want to set it to the opposite of the current value */
249 gboolean toggle = !gtk_cell_renderer_toggle_get_active(renderer);
250
251 /* get iter which was clicked */
252 GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
253 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_cipher_list));
254 GtkTreeIter iter;
255 gtk_tree_model_get_iter(model, &iter, tree_path);
256
257 /* get qmodelindex from iter and set the model data */
258 QModelIndex idx = gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), &iter);
259 if (idx.isValid())
260 priv->account->cipherModel()->setData(idx, toggle ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
261}
262
263static void
264render_check_state(G_GNUC_UNUSED GtkCellLayout *cell_layout,
265 GtkCellRenderer *cell,
266 GtkTreeModel *model,
267 GtkTreeIter *iter,
268 G_GNUC_UNUSED gpointer data)
269{
270 QModelIndex idx;
271 if (GTK_IS_Q_TREE_MODEL(model))
272 idx = gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), iter);
273 else if (GTK_IS_Q_SORT_FILTER_TREE_MODEL(model))
274 idx = gtk_q_sort_filter_tree_model_get_source_idx(GTK_Q_SORT_FILTER_TREE_MODEL(model), iter);
275
276 gboolean checked = FALSE;
277
278 if (idx.isValid()) {
279 checked = idx.data(Qt::CheckStateRole).value<int>() == Qt::Checked ? TRUE : FALSE;
280 }
281
282 g_object_set(G_OBJECT(cell), "active", checked, NULL);
283}
284
285static void
286verify_certs_server_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
287{
288 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
289 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
290
291 gboolean verify_certs = gtk_toggle_button_get_active(toggle_button);
292
293 priv->account->setTlsVerifyServer(verify_certs);
294}
295
296static void
297verify_certs_client_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
298{
299 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
300 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
301
302 gboolean verify_certs = gtk_toggle_button_get_active(toggle_button);
303
304 priv->account->setTlsVerifyClient(verify_certs);
305}
306
307static void
308require_incoming_certs_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
309{
310 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
311 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
312
313 gboolean require = gtk_toggle_button_get_active(toggle_button);
314
315 priv->account->setTlsRequireClientCertificate(require);
316}
317
318static void
319ca_cert_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
320{
321 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
322 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
323
324 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400325
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400326 priv->account->setTlsCaListCertificate(filename);
327 g_free(filename);
328}
329
330static void
331user_cert_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
332{
333 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
334 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
335
336 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400337
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400338 priv->account->setTlsCertificate(filename);
339 g_free(filename);
340}
341
342static void
343private_key_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
344{
345 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
346 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
347
348 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400349
350 priv->account->setTlsPrivateKey(filename);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400351 g_free(filename);
352}
353
354static void
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400355private_key_password_changed(GtkEntry *entry, AccountSecurityTab *self)
356{
357 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
358 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
359
360 priv->account->setTlsPassword(gtk_entry_get_text(entry));
361}
362
363static void
364check_tlspassword_valid(AccountSecurityTab *self)
365{
366 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
367 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
368
369 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
370 if (priv->user_cert->privateKeyMatch() == Certificate::CheckValues::PASSED) {
371 gtk_label_set_markup(
372 GTK_LABEL(priv->label_password_matches),
373 "<span fgcolor=\"green\">&#x2713;</span>"
374 );
375 } else {
376 gtk_label_set_markup(
377 GTK_LABEL(priv->label_password_matches),
378 "<span fgcolor=\"red\">&#x2717;</span>"
379 );
380 }
381 } else {
382 gtk_label_set_text(GTK_LABEL(priv->label_password_matches), "");
383 }
384}
385
386static void
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400387build_tab_view(AccountSecurityTab *self)
388{
389 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
390 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
391
392 gboolean not_ring = priv->account->protocol() != Account::Protocol::RING;
393
394 /* SRTP */
395 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp),
396 priv->account->isSrtpEnabled());
397 /* disable options if SRTP is off or if its a RING account */
398 gtk_widget_set_sensitive(priv->checkbutton_use_srtp, not_ring);
399 gtk_widget_set_sensitive(priv->box_key_exchange,
400 priv->account->isSrtpEnabled() && not_ring);
401 gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback,
402 priv->account->isSrtpEnabled() && not_ring);
403 g_signal_connect(priv->checkbutton_use_srtp, "toggled", G_CALLBACK(use_srtp_toggled), self);
404
405 /* encryption key exchange type */
406 priv->key_exchange_selection = gtk_combo_box_set_qmodel(
407 GTK_COMBO_BOX(priv->combobox_key_exchange),
408 (QAbstractItemModel *)priv->account->keyExchangeModel(),
409 priv->account->keyExchangeModel()->selectionModel());
410
411 /* SRTP fallback */
412 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback),
413 priv->account->isSrtpRtpFallback());
414 g_signal_connect(priv->checkbutton_srtp_fallback, "toggled", G_CALLBACK(use_rtp_fallback_toggled), self);
415
416 /* use TLS */
417 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls),
418 priv->account->isTlsEnabled());
419
420 /* disable certain options if TLS is off, or if its a RING account*/
421 gtk_widget_set_sensitive(priv->checkbutton_use_tls, not_ring);
422 gtk_widget_set_sensitive(priv->grid_tls_settings_0,
423 priv->account->isTlsEnabled());
424 gtk_widget_set_sensitive(priv->grid_tls_settings_1,
425 priv->account->isTlsEnabled() && not_ring);
426 gtk_widget_set_sensitive(priv->buttonbox_cipher_list,
427 priv->account->isTlsEnabled() && not_ring);
428 gtk_widget_set_sensitive(priv->treeview_cipher_list,
429 priv->account->isTlsEnabled() && not_ring);
430 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server,
431 priv->account->isTlsEnabled() && not_ring);
432 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client,
433 priv->account->isTlsEnabled() && not_ring);
434 gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs,
435 priv->account->isTlsEnabled() && not_ring);
436 g_signal_connect(priv->checkbutton_use_tls, "toggled", G_CALLBACK(use_tls_toggled), self);
437
438 /* CA certificate */
439 Certificate *ca_cert = priv->account->tlsCaListCertificate();
440 if (ca_cert) {
441 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400442 ca_cert->path().toUtf8().constData());
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400443 }
444 g_signal_connect(priv->filechooserbutton_ca_list, "file-set", G_CALLBACK(ca_cert_file_set), self);
445
446 /* user certificate */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400447 if ( (priv->user_cert = priv->account->tlsCertificate()) ) {
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400448 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400449 priv->user_cert->path().toUtf8().constData()
450 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400451 }
Stepan Salenikovichd890ad72015-05-20 10:17:48 -0400452 g_signal_connect(priv->filechooserbutton_certificate, "file-set", G_CALLBACK(user_cert_file_set), self);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400453
454 /* private key */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400455 if (!priv->account->tlsPrivateKey().isEmpty()) {
456 gtk_file_chooser_set_filename(
457 GTK_FILE_CHOOSER(priv->filechooserbutton_private_key),
458 priv->account->tlsPrivateKey().toUtf8().constData()
459 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400460 }
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400461
Stepan Salenikovichd890ad72015-05-20 10:17:48 -0400462 g_signal_connect(priv->filechooserbutton_private_key, "file-set", G_CALLBACK(private_key_file_set), self);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400463
464 /* password */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400465 check_tlspassword_valid(self);
466 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
467 gtk_entry_set_text(
468 GTK_ENTRY(priv->entry_password),
469 priv->account->tlsPassword().toUtf8().constData()
470 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400471 gtk_widget_set_sensitive(priv->entry_password, TRUE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400472 gtk_widget_set_sensitive(priv->label_private_key_password, TRUE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400473 } else {
474 /* private key not chosen, or password not required, so disactivate the entry */
475 gtk_widget_set_sensitive(priv->entry_password, FALSE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400476 gtk_widget_set_sensitive(priv->label_private_key_password, FALSE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400477 }
478
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400479 g_signal_connect(priv->entry_password, "changed", G_CALLBACK(private_key_password_changed), self);
480
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400481 /* TLS protocol method */
482 priv->tls_method_selection = gtk_combo_box_set_qmodel(GTK_COMBO_BOX(priv->combobox_tls_protocol_method),
483 (QAbstractItemModel *)priv->account->tlsMethodModel(),
484 priv->account->tlsMethodModel()->selectionModel());
485
486 /* outgoing TLS server */
487 gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name),
488 priv->account->tlsServerName().toUtf8().constData());
489 g_signal_connect(priv->entry_tls_server_name, "changed", G_CALLBACK(tls_server_name_changed), self);
490
491
492 /* TLS nego timeout */
493 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout),
494 priv->account->tlsNegotiationTimeoutSec());
495 g_signal_connect(priv->adjustment_tls_timeout, "value-changed", G_CALLBACK(tls_timeout_changed), self);
496
497 /* cipher default or custom */
498 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers),
499 priv->account->cipherModel()->useDefault());
500 /* hide the cipher list if we're using the default ones */
501 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list),
502 !priv->account->cipherModel()->useDefault());
503 g_signal_connect(priv->radiobutton_use_default_ciphers,
504 "toggled", G_CALLBACK(use_default_ciphers_toggled), self);
505
506 /* cipher list */
507 GtkQTreeModel *cipher_model = gtk_q_tree_model_new(
508 (QAbstractItemModel *)priv->account->cipherModel(),
509 2,
510 Qt::CheckStateRole, G_TYPE_BOOLEAN,
511 Qt::DisplayRole, G_TYPE_STRING);
512 gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_cipher_list),
513 GTK_TREE_MODEL(cipher_model));
514 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(priv->treeview_cipher_list),
515 FALSE);
516
517 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
518 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
519 "Enabled", renderer, NULL);
520 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column);
521
522 /* we have to use a custom data function here because Qt::Checked and Qt::Unchecked
523 * are not the same as true/false as there is an intermediate state */
524 gtk_tree_view_column_set_cell_data_func(column,
525 renderer,
526 (GtkTreeCellDataFunc)render_check_state,
527 NULL, NULL);
528
529 g_signal_connect(renderer, "toggled", G_CALLBACK(cipher_enable_toggled), self);
530
531 renderer = gtk_cell_renderer_text_new();
532 column = gtk_tree_view_column_new_with_attributes("Cipher", renderer, "text", 1, NULL);
533 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column);
534
535 /* server certs */
536 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server),
537 priv->account->isTlsVerifyServer());
Stepan Salenikovich226df012015-07-08 16:09:39 -0400538 g_signal_connect(priv->checkbutton_verify_certs_server,
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400539 "toggled", G_CALLBACK(verify_certs_server_toggled), self);
540
541 /* client certs */
542 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client),
543 priv->account->isTlsVerifyClient());
544 g_signal_connect(priv->checkbutton_verify_certs_client,
545 "toggled", G_CALLBACK(verify_certs_client_toggled), self);
546
547 /* incoming certs */
548 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs),
549 priv->account->isTlsRequireClientCertificate());
550 g_signal_connect(priv->checkbutton_require_incoming_tls_certs,
551 "toggled", G_CALLBACK(require_incoming_certs_toggled), self);
552
553 /* update account UI if model is updated */
554 priv->account_updated = QObject::connect(
555 priv->account,
556 &Account::changed,
557 [=] () {
558 /* SRTP */
559 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp),
560 priv->account->isSrtpEnabled());
561
562 /* SRTP fallback */
563 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback),
564 priv->account->isSrtpRtpFallback());
565 /* use TLS */
566 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls),
567 priv->account->isTlsEnabled());
568
569 /* CA certificate */
570 Certificate *ca_cert = priv->account->tlsCaListCertificate();
571 if (ca_cert) {
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400572 gtk_file_chooser_set_filename(
573 GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list),
574 ca_cert->path().toUtf8().constData()
575 );
576 } else {
577 /* make sure nothing is selected */
578 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400579 }
580
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400581
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400582 /* user certificate */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400583 QObject::disconnect(priv->cert_changed);
584 if ( (priv->user_cert = priv->account->tlsCertificate()) ) {
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400585 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400586 priv->user_cert->path().toUtf8().constData()
587 );
588 } else {
589 /* make sure nothing is selected */
590 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400591 }
592
593 /* private key */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400594 if (!priv->account->tlsPrivateKey().isEmpty()) {
595 gtk_file_chooser_set_filename(
596 GTK_FILE_CHOOSER(priv->filechooserbutton_private_key),
597 priv->account->tlsPrivateKey().toUtf8().constData()
598 );
599 } else {
600 /* make sure nothing is selected */
601 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_private_key));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400602 }
603
604 /* password */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400605 check_tlspassword_valid(self);
606 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
607 gtk_entry_set_text(
608 GTK_ENTRY(priv->entry_password),
609 priv->account->tlsPassword().toUtf8().constData()
610 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400611 gtk_widget_set_sensitive(priv->entry_password, TRUE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400612 gtk_widget_set_sensitive(priv->label_private_key_password, TRUE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400613 } else {
614 /* private key not chosen, or password not required, so disactivate the entry */
615 gtk_widget_set_sensitive(priv->entry_password, FALSE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400616 gtk_widget_set_sensitive(priv->label_private_key_password, FALSE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400617 }
618
619 /* outgoing TLS server */
620 gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name),
621 priv->account->tlsServerName().toUtf8().constData());
622
623 /* TLS nego timeout */
624 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout),
625 priv->account->tlsNegotiationTimeoutSec());
626
627 /* cipher default or custom */
628 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers),
629 priv->account->cipherModel()->useDefault());
630
631 /* server certs */
632 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server),
633 priv->account->isTlsVerifyServer());
634
635 /* client certs */
636 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client),
637 priv->account->isTlsVerifyClient());
638
639 /* incoming certs */
640 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs),
641 priv->account->isTlsRequireClientCertificate());
642 }
643 );
644}
645
646GtkWidget *
647account_security_tab_new(Account *account)
648{
649 g_return_val_if_fail(account != NULL, NULL);
650
651 gpointer view = g_object_new(ACCOUNT_SECURITY_TAB_TYPE, NULL);
652
653 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(view);
654 priv->account = account;
655
656 build_tab_view(ACCOUNT_SECURITY_TAB(view));
657
658 return (GtkWidget *)view;
659}