blob: 052710745d2a594e511589af9a1234362aa2ec46 [file] [log] [blame]
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -04001 /*
2 * Copyright (C) 2015 Savoir-Faire Linux Inc.
3 * 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.
18 *
19 * Additional permission under GNU GPL version 3 section 7:
20 *
21 * If you modify this program, or any covered work, by linking or
22 * combining it with the OpenSSL project's OpenSSL library (or a
23 * modified version of that library), containing parts covered by the
24 * terms of the OpenSSL or SSLeay licenses, Savoir-Faire Linux Inc.
25 * grants you additional permission to convey the resulting work.
26 * Corresponding Source for a non-source form of such a combination
27 * shall include the source code for the parts of OpenSSL used as well
28 * as that of the covered work.
29 */
30
31#include "accountsecuritytab.h"
32
33#include <gtk/gtk.h>
34#include <account.h>
35#include "models/activeitemproxymodel.h"
36#include "models/gtkqsortfiltertreemodel.h"
37#include "models/gtkqtreemodel.h"
38#include "utils/models.h"
39#include <certificate.h>
40#include <ciphermodel.h>
41#include <QtCore/QItemSelectionModel>
42
43struct _AccountSecurityTab
44{
45 GtkBox parent;
46};
47
48struct _AccountSecurityTabClass
49{
50 GtkBoxClass parent_class;
51};
52
53typedef struct _AccountSecurityTabPrivate AccountSecurityTabPrivate;
54
55struct _AccountSecurityTabPrivate
56{
57 Account *account;
58 GtkWidget *checkbutton_use_srtp;
59 GtkWidget *box_key_exchange;
60 GtkWidget *combobox_key_exchange;
61 GtkWidget *checkbutton_srtp_fallback;
62 GtkWidget *checkbutton_use_tls;
63 GtkWidget *grid_tls_settings_0;
64 GtkWidget *filechooserbutton_ca_list;
65 /* TODO: add when implemented
66 GtkWidget *button_view_ca;
67 GtkWidget *button_view_certificate;
68 */
69 GtkWidget *filechooserbutton_certificate;
70 GtkWidget *filechooserbutton_private_key;
Stepan Salenikovich6242ff12015-08-14 15:20:03 -040071 GtkWidget *label_private_key_password;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040072 GtkWidget *entry_password;
Stepan Salenikovich6242ff12015-08-14 15:20:03 -040073 GtkWidget *label_password_matches;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040074 GtkWidget *grid_tls_settings_1;
75 GtkWidget *combobox_tls_protocol_method;
76 GtkWidget *entry_tls_server_name;
77 GtkWidget *adjustment_tls_timeout;
78 GtkWidget *buttonbox_cipher_list;
79 GtkWidget *radiobutton_use_default_ciphers;
80 GtkWidget *radiobutton_custom_ciphers;
81 GtkWidget *revealer_cipher_list;
82 GtkWidget *treeview_cipher_list;
83 GtkWidget *checkbutton_verify_certs_server;
84 GtkWidget *checkbutton_verify_certs_client;
85 GtkWidget *checkbutton_require_incoming_tls_certs;
86
87 QMetaObject::Connection account_updated;
88 QMetaObject::Connection key_exchange_selection;
89 QMetaObject::Connection tls_method_selection;
Stepan Salenikovich6242ff12015-08-14 15:20:03 -040090 QMetaObject::Connection cert_changed;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040091
92 ActiveItemProxyModel *qmodel_key_exchange;
Stepan Salenikovich6242ff12015-08-14 15:20:03 -040093
94 Certificate *user_cert;
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -040095};
96
97G_DEFINE_TYPE_WITH_PRIVATE(AccountSecurityTab, account_security_tab, GTK_TYPE_BOX);
98
99#define ACCOUNT_SECURITY_TAB_GET_PRIVATE(obj) \
100 (G_TYPE_INSTANCE_GET_PRIVATE ((obj), ACCOUNT_SECURITY_TAB_TYPE, \
101 AccountSecurityTabPrivate))
102
103static void
104account_security_tab_dispose(GObject *object)
105{
106 AccountSecurityTab *view = ACCOUNT_SECURITY_TAB(object);
107 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(view);
108
109 QObject::disconnect(priv->account_updated);
110 QObject::disconnect(priv->key_exchange_selection);
111 QObject::disconnect(priv->tls_method_selection);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400112 QObject::disconnect(priv->cert_changed);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400113
114 G_OBJECT_CLASS(account_security_tab_parent_class)->dispose(object);
115}
116
117static void
118account_security_tab_finalize(GObject *object)
119{
120 AccountSecurityTab *view = ACCOUNT_SECURITY_TAB(object);
121 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(view);
122
123 delete priv->qmodel_key_exchange;
124
125 G_OBJECT_CLASS(account_security_tab_parent_class)->finalize(object);
126}
127
128static void
129account_security_tab_init(AccountSecurityTab *view)
130{
131 gtk_widget_init_template(GTK_WIDGET(view));
132}
133
134static void
135account_security_tab_class_init(AccountSecurityTabClass *klass)
136{
137 G_OBJECT_CLASS(klass)->dispose = account_security_tab_dispose;
138 G_OBJECT_CLASS(klass)->finalize = account_security_tab_finalize;
139
140 gtk_widget_class_set_template_from_resource(GTK_WIDGET_CLASS (klass),
141 "/cx/ring/RingGnome/accountsecuritytab.ui");
142
143 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_use_srtp);
144 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, box_key_exchange);
145 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, combobox_key_exchange);
146 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_srtp_fallback);
147 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_use_tls);
148 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, grid_tls_settings_0);
149 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_ca_list);
150 /* TODO: add when implemented
151 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, button_view_ca);
152 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, button_view_certificate);
153 */
154 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_certificate);
155 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, filechooserbutton_private_key);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400156 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, label_private_key_password);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400157 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, entry_password);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400158 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, label_password_matches);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400159 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, grid_tls_settings_1);
160 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, combobox_tls_protocol_method);
161 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, entry_tls_server_name);
162 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, adjustment_tls_timeout);
163 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, buttonbox_cipher_list);
164 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, radiobutton_use_default_ciphers);
165 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, radiobutton_custom_ciphers);
166 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, revealer_cipher_list);
167 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, treeview_cipher_list);
168 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_verify_certs_server);
169 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_verify_certs_client);
170 gtk_widget_class_bind_template_child_private(GTK_WIDGET_CLASS (klass), AccountSecurityTab, checkbutton_require_incoming_tls_certs);
171}
172
173static void
174use_srtp_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
175{
176 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
177 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
178
179 gboolean use_srtp = gtk_toggle_button_get_active(toggle_button);
180
181 priv->account->setSrtpEnabled(use_srtp);
182 priv->account->keyExchangeModel()->enableSRTP(use_srtp);
183
184 /* the other options are not relevant if SRTP is not active */
185 gtk_widget_set_sensitive(priv->box_key_exchange, priv->account->isSrtpEnabled());
186 gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback, priv->account->isSrtpEnabled());
187}
188
189static void
190use_rtp_fallback_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_rtp_fallback = gtk_toggle_button_get_active(toggle_button);
196
197 priv->account->setSrtpRtpFallback(use_rtp_fallback);
198}
199
200static void
201use_tls_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
202{
203 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
204 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
205
206 gboolean use_tls = gtk_toggle_button_get_active(toggle_button);
207
208 priv->account->setTlsEnabled(use_tls);
209
210 /* disable the other tls options if no tls */
211 gtk_widget_set_sensitive(priv->grid_tls_settings_0, priv->account->isTlsEnabled());
212 gtk_widget_set_sensitive(priv->grid_tls_settings_1, priv->account->isTlsEnabled());
213 gtk_widget_set_sensitive(priv->buttonbox_cipher_list, priv->account->isTlsEnabled());
214 gtk_widget_set_sensitive(priv->treeview_cipher_list, priv->account->isTlsEnabled());
215 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server, priv->account->isTlsEnabled());
216 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client, priv->account->isTlsEnabled());
217 gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs, priv->account->isTlsEnabled());
218}
219
220static void
221tls_server_name_changed(GtkEntry *entry, AccountSecurityTab *self)
222{
223 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
224 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
225
226 priv->account->setTlsServerName(gtk_entry_get_text(entry));
227}
228
229static void
230tls_timeout_changed(GtkAdjustment *adjustment, AccountSecurityTab *self)
231{
232 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
233 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
234
235 int timeout = (int)gtk_adjustment_get_value(GTK_ADJUSTMENT(adjustment));
236 priv->account->setTlsNegotiationTimeoutSec(timeout);
237}
238
239static void
240use_default_ciphers_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
241{
242 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
243 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
244
245 gboolean use_default_ciphers = gtk_toggle_button_get_active(toggle_button);
246
247 priv->account->cipherModel()->setUseDefault(use_default_ciphers);
248
249 /* hide the cipher list if we're using the default ones */
250 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list), !use_default_ciphers);
251}
252
253static void
254cipher_enable_toggled(GtkCellRendererToggle *renderer, gchar *path, AccountSecurityTab *self)
255{
256 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
257 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
258
259 /* we want to set it to the opposite of the current value */
260 gboolean toggle = !gtk_cell_renderer_toggle_get_active(renderer);
261
262 /* get iter which was clicked */
263 GtkTreePath *tree_path = gtk_tree_path_new_from_string(path);
264 GtkTreeModel *model = gtk_tree_view_get_model(GTK_TREE_VIEW(priv->treeview_cipher_list));
265 GtkTreeIter iter;
266 gtk_tree_model_get_iter(model, &iter, tree_path);
267
268 /* get qmodelindex from iter and set the model data */
269 QModelIndex idx = gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), &iter);
270 if (idx.isValid())
271 priv->account->cipherModel()->setData(idx, toggle ? Qt::Checked : Qt::Unchecked, Qt::CheckStateRole);
272}
273
274static void
275render_check_state(G_GNUC_UNUSED GtkCellLayout *cell_layout,
276 GtkCellRenderer *cell,
277 GtkTreeModel *model,
278 GtkTreeIter *iter,
279 G_GNUC_UNUSED gpointer data)
280{
281 QModelIndex idx;
282 if (GTK_IS_Q_TREE_MODEL(model))
283 idx = gtk_q_tree_model_get_source_idx(GTK_Q_TREE_MODEL(model), iter);
284 else if (GTK_IS_Q_SORT_FILTER_TREE_MODEL(model))
285 idx = gtk_q_sort_filter_tree_model_get_source_idx(GTK_Q_SORT_FILTER_TREE_MODEL(model), iter);
286
287 gboolean checked = FALSE;
288
289 if (idx.isValid()) {
290 checked = idx.data(Qt::CheckStateRole).value<int>() == Qt::Checked ? TRUE : FALSE;
291 }
292
293 g_object_set(G_OBJECT(cell), "active", checked, NULL);
294}
295
296static void
297verify_certs_server_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->setTlsVerifyServer(verify_certs);
305}
306
307static void
308verify_certs_client_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 verify_certs = gtk_toggle_button_get_active(toggle_button);
314
315 priv->account->setTlsVerifyClient(verify_certs);
316}
317
318static void
319require_incoming_certs_toggled(GtkToggleButton *toggle_button, AccountSecurityTab *self)
320{
321 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
322 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
323
324 gboolean require = gtk_toggle_button_get_active(toggle_button);
325
326 priv->account->setTlsRequireClientCertificate(require);
327}
328
329static void
330ca_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->setTlsCaListCertificate(filename);
338 g_free(filename);
339}
340
341static void
342user_cert_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
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400349 priv->account->setTlsCertificate(filename);
350 g_free(filename);
351}
352
353static void
354private_key_file_set(GtkFileChooser *file_chooser, AccountSecurityTab *self)
355{
356 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
357 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
358
359 gchar *filename = gtk_file_chooser_get_filename(file_chooser);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400360
361 priv->account->setTlsPrivateKey(filename);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400362 g_free(filename);
363}
364
365static void
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400366private_key_password_changed(GtkEntry *entry, AccountSecurityTab *self)
367{
368 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
369 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
370
371 priv->account->setTlsPassword(gtk_entry_get_text(entry));
372}
373
374static void
375check_tlspassword_valid(AccountSecurityTab *self)
376{
377 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
378 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
379
380 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
381 if (priv->user_cert->privateKeyMatch() == Certificate::CheckValues::PASSED) {
382 gtk_label_set_markup(
383 GTK_LABEL(priv->label_password_matches),
384 "<span fgcolor=\"green\">&#x2713;</span>"
385 );
386 } else {
387 gtk_label_set_markup(
388 GTK_LABEL(priv->label_password_matches),
389 "<span fgcolor=\"red\">&#x2717;</span>"
390 );
391 }
392 } else {
393 gtk_label_set_text(GTK_LABEL(priv->label_password_matches), "");
394 }
395}
396
397static void
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400398build_tab_view(AccountSecurityTab *self)
399{
400 g_return_if_fail(IS_ACCOUNT_SECURITY_TAB(self));
401 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(self);
402
403 gboolean not_ring = priv->account->protocol() != Account::Protocol::RING;
404
405 /* SRTP */
406 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp),
407 priv->account->isSrtpEnabled());
408 /* disable options if SRTP is off or if its a RING account */
409 gtk_widget_set_sensitive(priv->checkbutton_use_srtp, not_ring);
410 gtk_widget_set_sensitive(priv->box_key_exchange,
411 priv->account->isSrtpEnabled() && not_ring);
412 gtk_widget_set_sensitive(priv->checkbutton_srtp_fallback,
413 priv->account->isSrtpEnabled() && not_ring);
414 g_signal_connect(priv->checkbutton_use_srtp, "toggled", G_CALLBACK(use_srtp_toggled), self);
415
416 /* encryption key exchange type */
417 priv->key_exchange_selection = gtk_combo_box_set_qmodel(
418 GTK_COMBO_BOX(priv->combobox_key_exchange),
419 (QAbstractItemModel *)priv->account->keyExchangeModel(),
420 priv->account->keyExchangeModel()->selectionModel());
421
422 /* SRTP fallback */
423 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback),
424 priv->account->isSrtpRtpFallback());
425 g_signal_connect(priv->checkbutton_srtp_fallback, "toggled", G_CALLBACK(use_rtp_fallback_toggled), self);
426
427 /* use TLS */
428 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls),
429 priv->account->isTlsEnabled());
430
431 /* disable certain options if TLS is off, or if its a RING account*/
432 gtk_widget_set_sensitive(priv->checkbutton_use_tls, not_ring);
433 gtk_widget_set_sensitive(priv->grid_tls_settings_0,
434 priv->account->isTlsEnabled());
435 gtk_widget_set_sensitive(priv->grid_tls_settings_1,
436 priv->account->isTlsEnabled() && not_ring);
437 gtk_widget_set_sensitive(priv->buttonbox_cipher_list,
438 priv->account->isTlsEnabled() && not_ring);
439 gtk_widget_set_sensitive(priv->treeview_cipher_list,
440 priv->account->isTlsEnabled() && not_ring);
441 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_server,
442 priv->account->isTlsEnabled() && not_ring);
443 gtk_widget_set_sensitive(priv->checkbutton_verify_certs_client,
444 priv->account->isTlsEnabled() && not_ring);
445 gtk_widget_set_sensitive(priv->checkbutton_require_incoming_tls_certs,
446 priv->account->isTlsEnabled() && not_ring);
447 g_signal_connect(priv->checkbutton_use_tls, "toggled", G_CALLBACK(use_tls_toggled), self);
448
449 /* CA certificate */
450 Certificate *ca_cert = priv->account->tlsCaListCertificate();
451 if (ca_cert) {
452 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400453 ca_cert->path().toUtf8().constData());
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400454 }
455 g_signal_connect(priv->filechooserbutton_ca_list, "file-set", G_CALLBACK(ca_cert_file_set), self);
456
457 /* user certificate */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400458 if ( (priv->user_cert = priv->account->tlsCertificate()) ) {
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400459 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400460 priv->user_cert->path().toUtf8().constData()
461 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400462 }
Stepan Salenikovichd890ad72015-05-20 10:17:48 -0400463 g_signal_connect(priv->filechooserbutton_certificate, "file-set", G_CALLBACK(user_cert_file_set), self);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400464
465 /* private key */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400466 if (!priv->account->tlsPrivateKey().isEmpty()) {
467 gtk_file_chooser_set_filename(
468 GTK_FILE_CHOOSER(priv->filechooserbutton_private_key),
469 priv->account->tlsPrivateKey().toUtf8().constData()
470 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400471 }
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400472
Stepan Salenikovichd890ad72015-05-20 10:17:48 -0400473 g_signal_connect(priv->filechooserbutton_private_key, "file-set", G_CALLBACK(private_key_file_set), self);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400474
475 /* password */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400476 check_tlspassword_valid(self);
477 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
478 gtk_entry_set_text(
479 GTK_ENTRY(priv->entry_password),
480 priv->account->tlsPassword().toUtf8().constData()
481 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400482 gtk_widget_set_sensitive(priv->entry_password, TRUE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400483 gtk_widget_set_sensitive(priv->label_private_key_password, TRUE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400484 } else {
485 /* private key not chosen, or password not required, so disactivate the entry */
486 gtk_widget_set_sensitive(priv->entry_password, FALSE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400487 gtk_widget_set_sensitive(priv->label_private_key_password, FALSE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400488 }
489
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400490 g_signal_connect(priv->entry_password, "changed", G_CALLBACK(private_key_password_changed), self);
491
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400492 /* TLS protocol method */
493 priv->tls_method_selection = gtk_combo_box_set_qmodel(GTK_COMBO_BOX(priv->combobox_tls_protocol_method),
494 (QAbstractItemModel *)priv->account->tlsMethodModel(),
495 priv->account->tlsMethodModel()->selectionModel());
496
497 /* outgoing TLS server */
498 gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name),
499 priv->account->tlsServerName().toUtf8().constData());
500 g_signal_connect(priv->entry_tls_server_name, "changed", G_CALLBACK(tls_server_name_changed), self);
501
502
503 /* TLS nego timeout */
504 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout),
505 priv->account->tlsNegotiationTimeoutSec());
506 g_signal_connect(priv->adjustment_tls_timeout, "value-changed", G_CALLBACK(tls_timeout_changed), self);
507
508 /* cipher default or custom */
509 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers),
510 priv->account->cipherModel()->useDefault());
511 /* hide the cipher list if we're using the default ones */
512 gtk_revealer_set_reveal_child(GTK_REVEALER(priv->revealer_cipher_list),
513 !priv->account->cipherModel()->useDefault());
514 g_signal_connect(priv->radiobutton_use_default_ciphers,
515 "toggled", G_CALLBACK(use_default_ciphers_toggled), self);
516
517 /* cipher list */
518 GtkQTreeModel *cipher_model = gtk_q_tree_model_new(
519 (QAbstractItemModel *)priv->account->cipherModel(),
520 2,
521 Qt::CheckStateRole, G_TYPE_BOOLEAN,
522 Qt::DisplayRole, G_TYPE_STRING);
523 gtk_tree_view_set_model(GTK_TREE_VIEW(priv->treeview_cipher_list),
524 GTK_TREE_MODEL(cipher_model));
525 gtk_tree_view_set_headers_visible(GTK_TREE_VIEW(priv->treeview_cipher_list),
526 FALSE);
527
528 GtkCellRenderer *renderer = gtk_cell_renderer_toggle_new();
529 GtkTreeViewColumn *column = gtk_tree_view_column_new_with_attributes(
530 "Enabled", renderer, NULL);
531 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column);
532
533 /* we have to use a custom data function here because Qt::Checked and Qt::Unchecked
534 * are not the same as true/false as there is an intermediate state */
535 gtk_tree_view_column_set_cell_data_func(column,
536 renderer,
537 (GtkTreeCellDataFunc)render_check_state,
538 NULL, NULL);
539
540 g_signal_connect(renderer, "toggled", G_CALLBACK(cipher_enable_toggled), self);
541
542 renderer = gtk_cell_renderer_text_new();
543 column = gtk_tree_view_column_new_with_attributes("Cipher", renderer, "text", 1, NULL);
544 gtk_tree_view_append_column(GTK_TREE_VIEW(priv->treeview_cipher_list), column);
545
546 /* server certs */
547 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server),
548 priv->account->isTlsVerifyServer());
Stepan Salenikovich226df012015-07-08 16:09:39 -0400549 g_signal_connect(priv->checkbutton_verify_certs_server,
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400550 "toggled", G_CALLBACK(verify_certs_server_toggled), self);
551
552 /* client certs */
553 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client),
554 priv->account->isTlsVerifyClient());
555 g_signal_connect(priv->checkbutton_verify_certs_client,
556 "toggled", G_CALLBACK(verify_certs_client_toggled), self);
557
558 /* incoming certs */
559 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs),
560 priv->account->isTlsRequireClientCertificate());
561 g_signal_connect(priv->checkbutton_require_incoming_tls_certs,
562 "toggled", G_CALLBACK(require_incoming_certs_toggled), self);
563
564 /* update account UI if model is updated */
565 priv->account_updated = QObject::connect(
566 priv->account,
567 &Account::changed,
568 [=] () {
569 /* SRTP */
570 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_srtp),
571 priv->account->isSrtpEnabled());
572
573 /* SRTP fallback */
574 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_srtp_fallback),
575 priv->account->isSrtpRtpFallback());
576 /* use TLS */
577 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_use_tls),
578 priv->account->isTlsEnabled());
579
580 /* CA certificate */
581 Certificate *ca_cert = priv->account->tlsCaListCertificate();
582 if (ca_cert) {
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400583 gtk_file_chooser_set_filename(
584 GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list),
585 ca_cert->path().toUtf8().constData()
586 );
587 } else {
588 /* make sure nothing is selected */
589 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_ca_list));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400590 }
591
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400592
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400593 /* user certificate */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400594 QObject::disconnect(priv->cert_changed);
595 if ( (priv->user_cert = priv->account->tlsCertificate()) ) {
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400596 gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate),
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400597 priv->user_cert->path().toUtf8().constData()
598 );
599 } else {
600 /* make sure nothing is selected */
601 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_certificate));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400602 }
603
604 /* private key */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400605 if (!priv->account->tlsPrivateKey().isEmpty()) {
606 gtk_file_chooser_set_filename(
607 GTK_FILE_CHOOSER(priv->filechooserbutton_private_key),
608 priv->account->tlsPrivateKey().toUtf8().constData()
609 );
610 } else {
611 /* make sure nothing is selected */
612 gtk_file_chooser_unselect_all(GTK_FILE_CHOOSER(priv->filechooserbutton_private_key));
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400613 }
614
615 /* password */
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400616 check_tlspassword_valid(self);
617 if (priv->user_cert && priv->user_cert->requirePrivateKeyPassword()) {
618 gtk_entry_set_text(
619 GTK_ENTRY(priv->entry_password),
620 priv->account->tlsPassword().toUtf8().constData()
621 );
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400622 gtk_widget_set_sensitive(priv->entry_password, TRUE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400623 gtk_widget_set_sensitive(priv->label_private_key_password, TRUE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400624 } else {
625 /* private key not chosen, or password not required, so disactivate the entry */
626 gtk_widget_set_sensitive(priv->entry_password, FALSE);
Stepan Salenikovich6242ff12015-08-14 15:20:03 -0400627 gtk_widget_set_sensitive(priv->label_private_key_password, FALSE);
Stepan Salenikovich7a1e71c2015-05-07 11:14:48 -0400628 }
629
630 /* outgoing TLS server */
631 gtk_entry_set_text(GTK_ENTRY(priv->entry_tls_server_name),
632 priv->account->tlsServerName().toUtf8().constData());
633
634 /* TLS nego timeout */
635 gtk_adjustment_set_value(GTK_ADJUSTMENT(priv->adjustment_tls_timeout),
636 priv->account->tlsNegotiationTimeoutSec());
637
638 /* cipher default or custom */
639 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->radiobutton_use_default_ciphers),
640 priv->account->cipherModel()->useDefault());
641
642 /* server certs */
643 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_server),
644 priv->account->isTlsVerifyServer());
645
646 /* client certs */
647 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_verify_certs_client),
648 priv->account->isTlsVerifyClient());
649
650 /* incoming certs */
651 gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(priv->checkbutton_require_incoming_tls_certs),
652 priv->account->isTlsRequireClientCertificate());
653 }
654 );
655}
656
657GtkWidget *
658account_security_tab_new(Account *account)
659{
660 g_return_val_if_fail(account != NULL, NULL);
661
662 gpointer view = g_object_new(ACCOUNT_SECURITY_TAB_TYPE, NULL);
663
664 AccountSecurityTabPrivate *priv = ACCOUNT_SECURITY_TAB_GET_PRIVATE(view);
665 priv->account = account;
666
667 build_tab_view(ACCOUNT_SECURITY_TAB(view));
668
669 return (GtkWidget *)view;
670}