~ubuntu-branches/ubuntu/trusty/unity-control-center/trusty

« back to all changes in this revision

Viewing changes to panels/network/net-vpn.c

  • Committer: Package Import Robot
  • Author(s): Robert Ancell
  • Date: 2014-01-08 16:29:18 UTC
  • Revision ID: package-import@ubuntu.com-20140108162918-g29dd08tr913y2qh
Tags: upstream-14.04.0
ImportĀ upstreamĀ versionĀ 14.04.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
 
2
 *
 
3
 * Copyright (C) 2011-2012 Richard Hughes <richard@hughsie.com>
 
4
 *
 
5
 * Licensed under the GNU General Public License Version 2
 
6
 *
 
7
 * This program is free software; you can redistribute it and/or modify
 
8
 * it under the terms of the GNU General Public License as published by
 
9
 * the Free Software Foundation; either version 2 of the License, or
 
10
 * (at your option) any later version.
 
11
 *
 
12
 * This program is distributed in the hope that it will be useful,
 
13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
15
 * GNU General Public License for more details.
 
16
 *
 
17
 * You should have received a copy of the GNU General Public License
 
18
 * along with this program; if not, write to the Free Software
 
19
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 
20
 */
 
21
 
 
22
#include "config.h"
 
23
 
 
24
#include <glib-object.h>
 
25
#include <glib/gi18n.h>
 
26
 
 
27
#include "panel-common.h"
 
28
 
 
29
#include "net-vpn.h"
 
30
#include "nm-client.h"
 
31
#include "nm-remote-connection.h"
 
32
#include "nm-setting-vpn.h"
 
33
 
 
34
#define NET_VPN_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NET_TYPE_VPN, NetVpnPrivate))
 
35
 
 
36
struct _NetVpnPrivate
 
37
{
 
38
        GtkBuilder              *builder;
 
39
        NMConnection            *connection;
 
40
        gchar                   *service_type;
 
41
        gboolean                 valid;
 
42
        gboolean                 updating_device;
 
43
};
 
44
 
 
45
enum {
 
46
        PROP_0,
 
47
        PROP_CONNECTION,
 
48
        PROP_LAST
 
49
};
 
50
 
 
51
G_DEFINE_TYPE (NetVpn, net_vpn, NET_TYPE_OBJECT)
 
52
 
 
53
static void
 
54
connection_vpn_state_changed_cb (NMVPNConnection *connection,
 
55
                                 NMVPNConnectionState state,
 
56
                                 NMVPNConnectionStateReason reason,
 
57
                                 NetVpn *vpn)
 
58
{
 
59
        net_object_emit_changed (NET_OBJECT (vpn));
 
60
}
 
61
 
 
62
static void
 
63
connection_changed_cb (NMConnection *connection,
 
64
                       NetVpn *vpn)
 
65
{
 
66
        net_object_emit_changed (NET_OBJECT (vpn));
 
67
}
 
68
 
 
69
static void
 
70
connection_removed_cb (NMConnection *connection,
 
71
                       NetVpn *vpn)
 
72
{
 
73
        net_object_emit_removed (NET_OBJECT (vpn));
 
74
}
 
75
 
 
76
static char *
 
77
net_vpn_connection_to_type (NMConnection *connection)
 
78
{
 
79
        const gchar *type, *p;
 
80
 
 
81
        type = nm_setting_vpn_get_service_type (nm_connection_get_setting_vpn (connection));
 
82
        /* Go from "org.freedesktop.NetworkManager.vpnc" to "vpnc" for example */
 
83
        p = strrchr (type, '.');
 
84
        return g_strdup (p ? p + 1 : type);
 
85
}
 
86
 
 
87
static void
 
88
net_vpn_set_connection (NetVpn *vpn, NMConnection *connection)
 
89
{
 
90
        NetVpnPrivate *priv = vpn->priv;
 
91
        /*
 
92
         * vpnc config exmaple:
 
93
         * key=IKE DH Group, value=dh2
 
94
         * key=xauth-password-type, value=ask
 
95
         * key=ipsec-secret-type, value=save
 
96
         * key=IPSec gateway, value=66.187.233.252
 
97
         * key=NAT Traversal Mode, value=natt
 
98
         * key=IPSec ID, value=rh-vpn
 
99
         * key=Xauth username, value=rhughes
 
100
         */
 
101
        priv->connection = g_object_ref (connection);
 
102
        g_signal_connect (priv->connection,
 
103
                          NM_REMOTE_CONNECTION_REMOVED,
 
104
                          G_CALLBACK (connection_removed_cb),
 
105
                          vpn);
 
106
        g_signal_connect (priv->connection,
 
107
                          NM_REMOTE_CONNECTION_UPDATED,
 
108
                          G_CALLBACK (connection_changed_cb),
 
109
                          vpn);
 
110
        if (NM_IS_VPN_CONNECTION (priv->connection)) {
 
111
                g_signal_connect (priv->connection,
 
112
                                  NM_VPN_CONNECTION_VPN_STATE,
 
113
                                  G_CALLBACK (connection_vpn_state_changed_cb),
 
114
                                  vpn);
 
115
        }
 
116
 
 
117
        priv->service_type = net_vpn_connection_to_type (priv->connection);
 
118
}
 
119
 
 
120
static NMVPNConnectionState
 
121
net_vpn_get_state (NetVpn *vpn)
 
122
{
 
123
        NetVpnPrivate *priv = vpn->priv;
 
124
        if (!NM_IS_VPN_CONNECTION (priv->connection))
 
125
                return NM_VPN_CONNECTION_STATE_DISCONNECTED;
 
126
        return nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (priv->connection));
 
127
}
 
128
 
 
129
/* VPN parameters can be found at:
 
130
 * http://git.gnome.org/browse/network-manager-openvpn/tree/src/nm-openvpn-service.h
 
131
 * http://git.gnome.org/browse/network-manager-vpnc/tree/src/nm-vpnc-service.h
 
132
 * http://git.gnome.org/browse/network-manager-pptp/tree/src/nm-pptp-service.h
 
133
 * http://git.gnome.org/browse/network-manager-openconnect/tree/src/nm-openconnect-service.h
 
134
 * http://git.gnome.org/browse/network-manager-openswan/tree/src/nm-openswan-service.h
 
135
 * See also 'properties' directory in these plugins.
 
136
 */
 
137
static const gchar *
 
138
get_vpn_key_gateway (const char *vpn_type)
 
139
{
 
140
        if (g_strcmp0 (vpn_type, "openvpn") == 0)     return "remote";
 
141
        if (g_strcmp0 (vpn_type, "vpnc") == 0)        return "IPSec gateway";
 
142
        if (g_strcmp0 (vpn_type, "pptp") == 0)        return "gateway";
 
143
        if (g_strcmp0 (vpn_type, "openconnect") == 0) return "gateway";
 
144
        if (g_strcmp0 (vpn_type, "openswan") == 0)    return "right";
 
145
        return "";
 
146
}
 
147
 
 
148
static const gchar *
 
149
get_vpn_key_group (const char *vpn_type)
 
150
{
 
151
        if (g_strcmp0 (vpn_type, "openvpn") == 0)     return "";
 
152
        if (g_strcmp0 (vpn_type, "vpnc") == 0)        return "IPSec ID";
 
153
        if (g_strcmp0 (vpn_type, "pptp") == 0)        return "";
 
154
        if (g_strcmp0 (vpn_type, "openconnect") == 0) return "";
 
155
        if (g_strcmp0 (vpn_type, "openswan") == 0)    return "";
 
156
        return "";
 
157
}
 
158
 
 
159
static const gchar *
 
160
get_vpn_key_username (const char *vpn_type)
 
161
{
 
162
        if (g_strcmp0 (vpn_type, "openvpn") == 0)     return "username";
 
163
        if (g_strcmp0 (vpn_type, "vpnc") == 0)        return "Xauth username";
 
164
        if (g_strcmp0 (vpn_type, "pptp") == 0)        return "user";
 
165
        if (g_strcmp0 (vpn_type, "openconnect") == 0) return "username";
 
166
        if (g_strcmp0 (vpn_type, "openswan") == 0)    return "leftxauthusername";
 
167
        return "";
 
168
}
 
169
 
 
170
static const gchar *
 
171
get_vpn_key_group_password (const char *vpn_type)
 
172
{
 
173
        if (g_strcmp0 (vpn_type, "openvpn") == 0)     return "";
 
174
        if (g_strcmp0 (vpn_type, "vpnc") == 0)        return "Xauth password";
 
175
        if (g_strcmp0 (vpn_type, "pptp") == 0)        return "";
 
176
        if (g_strcmp0 (vpn_type, "openconnect") == 0) return "";
 
177
        if (g_strcmp0 (vpn_type, "openswan") == 0)    return "";
 
178
        return "";
 
179
}
 
180
 
 
181
static const gchar *
 
182
net_vpn_get_gateway (NetVpn *vpn)
 
183
{
 
184
        NetVpnPrivate *priv = vpn->priv;
 
185
        const gchar *key;
 
186
 
 
187
        key = get_vpn_key_gateway (priv->service_type);
 
188
        return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (priv->connection), key);
 
189
}
 
190
 
 
191
static const gchar *
 
192
net_vpn_get_id (NetVpn *vpn)
 
193
{
 
194
        NetVpnPrivate *priv = vpn->priv;
 
195
        const gchar *key;
 
196
 
 
197
        key = get_vpn_key_group (priv->service_type);
 
198
        return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (priv->connection), key);
 
199
}
 
200
 
 
201
static const gchar *
 
202
net_vpn_get_username (NetVpn *vpn)
 
203
{
 
204
        NetVpnPrivate *priv = vpn->priv;
 
205
        const gchar *key;
 
206
 
 
207
        key = get_vpn_key_username (priv->service_type);
 
208
        return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (priv->connection), key);
 
209
}
 
210
 
 
211
static const gchar *
 
212
net_vpn_get_password (NetVpn *vpn)
 
213
{
 
214
        NetVpnPrivate *priv = vpn->priv;
 
215
        const gchar *key;
 
216
 
 
217
        key = get_vpn_key_group_password (priv->service_type);
 
218
        return nm_setting_vpn_get_data_item (nm_connection_get_setting_vpn (priv->connection), key);
 
219
}
 
220
 
 
221
static void
 
222
vpn_proxy_delete (NetObject *object)
 
223
{
 
224
        NetVpn *vpn = NET_VPN (object);
 
225
        nm_remote_connection_delete (NM_REMOTE_CONNECTION (vpn->priv->connection),
 
226
                                     NULL, vpn);
 
227
}
 
228
 
 
229
static GtkWidget *
 
230
vpn_proxy_add_to_notebook (NetObject *object,
 
231
                           GtkNotebook *notebook,
 
232
                           GtkSizeGroup *heading_size_group)
 
233
{
 
234
        GtkWidget *widget;
 
235
        GtkWindow *window;
 
236
        NetVpn *vpn = NET_VPN (object);
 
237
 
 
238
        /* add widgets to size group */
 
239
        widget = GTK_WIDGET (gtk_builder_get_object (vpn->priv->builder,
 
240
                                                     "heading_group_password"));
 
241
        gtk_size_group_add_widget (heading_size_group, widget);
 
242
 
 
243
        /* reparent */
 
244
        window = GTK_WINDOW (gtk_builder_get_object (vpn->priv->builder,
 
245
                                                     "window_tmp"));
 
246
        widget = GTK_WIDGET (gtk_builder_get_object (vpn->priv->builder,
 
247
                                                     "vbox9"));
 
248
        g_object_ref (widget);
 
249
        gtk_container_remove (GTK_CONTAINER (window), widget);
 
250
        gtk_notebook_append_page (notebook, widget, NULL);
 
251
        g_object_unref (widget);
 
252
        return widget;
 
253
}
 
254
 
 
255
static void
 
256
nm_device_refresh_vpn_ui (NetVpn *vpn)
 
257
{
 
258
        GtkWidget *widget;
 
259
        GtkWidget *sw;
 
260
        const gchar *status;
 
261
        NetVpnPrivate *priv = vpn->priv;
 
262
        const GPtrArray *acs;
 
263
        NMActiveConnection *a;
 
264
        gint i;
 
265
        const gchar *path;
 
266
        const gchar *apath;
 
267
        NMVPNConnectionState state;
 
268
        gchar *title;
 
269
        NMClient *client;
 
270
 
 
271
        sw = GTK_WIDGET (gtk_builder_get_object (priv->builder,
 
272
                                                 "device_off_switch"));
 
273
        gtk_widget_set_visible (sw, TRUE);
 
274
 
 
275
        /* update title */
 
276
        widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
 
277
                                                     "label_device"));
 
278
        title = g_strdup_printf (_("%s VPN"), nm_connection_get_id (vpn->priv->connection));
 
279
        net_object_set_title (NET_OBJECT (vpn), title);
 
280
        gtk_label_set_label (GTK_LABEL (widget), title);
 
281
        g_free (title);
 
282
 
 
283
        /* use status */
 
284
        state = net_vpn_get_state (vpn);
 
285
        client = net_object_get_client (NET_OBJECT (vpn));
 
286
        acs = nm_client_get_active_connections (client);
 
287
        if (acs != NULL) {
 
288
                path = nm_connection_get_path (vpn->priv->connection);
 
289
                for (i = 0; i < acs->len; i++) {
 
290
                        a = (NMActiveConnection*)acs->pdata[i];
 
291
 
 
292
                        apath = nm_active_connection_get_connection (a);
 
293
                        if (NM_IS_VPN_CONNECTION (a) && strcmp (apath, path) == 0) {
 
294
                                state = nm_vpn_connection_get_vpn_state (NM_VPN_CONNECTION (a));
 
295
                                break;
 
296
                        }
 
297
                }
 
298
        }
 
299
 
 
300
        widget = GTK_WIDGET (gtk_builder_get_object (priv->builder,
 
301
                                                     "label_status"));
 
302
        status = panel_vpn_state_to_localized_string (state);
 
303
        gtk_label_set_label (GTK_LABEL (widget), status);
 
304
        priv->updating_device = TRUE;
 
305
        gtk_switch_set_active (GTK_SWITCH (sw),
 
306
                               state != NM_VPN_CONNECTION_STATE_FAILED &&
 
307
                               state != NM_VPN_CONNECTION_STATE_DISCONNECTED);
 
308
        priv->updating_device = FALSE;
 
309
 
 
310
        /* service type */
 
311
        panel_set_device_widget_details (vpn->priv->builder,
 
312
                                         "service_type",
 
313
                                         vpn->priv->service_type);
 
314
 
 
315
        /* gateway */
 
316
        panel_set_device_widget_details (vpn->priv->builder,
 
317
                                         "gateway",
 
318
                                         net_vpn_get_gateway (vpn));
 
319
 
 
320
        /* groupname */
 
321
        panel_set_device_widget_details (vpn->priv->builder,
 
322
                                         "group_name",
 
323
                                         net_vpn_get_id (vpn));
 
324
 
 
325
        /* username */
 
326
        panel_set_device_widget_details (vpn->priv->builder,
 
327
                                         "username",
 
328
                                         net_vpn_get_username (vpn));
 
329
 
 
330
        /* password */
 
331
        panel_set_device_widget_details (vpn->priv->builder,
 
332
                                         "group_password",
 
333
                                         net_vpn_get_password (vpn));
 
334
}
 
335
 
 
336
static void
 
337
vpn_proxy_refresh (NetObject *object)
 
338
{
 
339
        NetVpn *vpn = NET_VPN (object);
 
340
        nm_device_refresh_vpn_ui (vpn);
 
341
}
 
342
 
 
343
static void
 
344
device_off_toggled (GtkSwitch *sw,
 
345
                    GParamSpec *pspec,
 
346
                    NetVpn *vpn)
 
347
{
 
348
        const gchar *path;
 
349
        const GPtrArray *acs;
 
350
        gboolean active;
 
351
        gint i;
 
352
        NMActiveConnection *a;
 
353
        NMClient *client;
 
354
 
 
355
        if (vpn->priv->updating_device)
 
356
                return;
 
357
 
 
358
        active = gtk_switch_get_active (sw);
 
359
        if (active) {
 
360
                client = net_object_get_client (NET_OBJECT (vpn));
 
361
                nm_client_activate_connection (client,
 
362
                                               vpn->priv->connection, NULL, NULL,
 
363
                                               NULL, NULL);
 
364
        } else {
 
365
                path = nm_connection_get_path (vpn->priv->connection);
 
366
                client = net_object_get_client (NET_OBJECT (vpn));
 
367
                acs = nm_client_get_active_connections (client);
 
368
                for (i = 0; i < acs->len; i++) {
 
369
                        a = (NMActiveConnection*)acs->pdata[i];
 
370
                        if (strcmp (nm_active_connection_get_connection (a), path) == 0) {
 
371
                                nm_client_deactivate_connection (client, a);
 
372
                                break;
 
373
                        }
 
374
                }
 
375
        }
 
376
}
 
377
 
 
378
static void
 
379
edit_connection (GtkButton *button, NetVpn *vpn)
 
380
{
 
381
        net_object_edit (NET_OBJECT (vpn));
 
382
}
 
383
 
 
384
static void
 
385
vpn_proxy_edit (NetObject *object)
 
386
{
 
387
        const gchar *uuid;
 
388
        gchar *cmdline;
 
389
        GError *error = NULL;
 
390
        NetVpn *vpn = NET_VPN (object);
 
391
 
 
392
        uuid = nm_connection_get_uuid (vpn->priv->connection);
 
393
        cmdline = g_strdup_printf ("nm-connection-editor --edit %s", uuid);
 
394
        g_debug ("Launching '%s'\n", cmdline);
 
395
        if (!g_spawn_command_line_async (cmdline, &error)) {
 
396
                g_warning ("Failed to launch nm-connection-editor: %s", error->message);
 
397
                g_error_free (error);
 
398
        }
 
399
        g_free (cmdline);
 
400
}
 
401
 
 
402
/**
 
403
 * net_vpn_get_property:
 
404
 **/
 
405
static void
 
406
net_vpn_get_property (GObject *object,
 
407
                      guint prop_id,
 
408
                      GValue *value,
 
409
                      GParamSpec *pspec)
 
410
{
 
411
        NetVpn *vpn = NET_VPN (object);
 
412
        NetVpnPrivate *priv = vpn->priv;
 
413
 
 
414
        switch (prop_id) {
 
415
        case PROP_CONNECTION:
 
416
                g_value_set_object (value, priv->connection);
 
417
                break;
 
418
        default:
 
419
                G_OBJECT_WARN_INVALID_PROPERTY_ID (vpn, prop_id, pspec);
 
420
                break;
 
421
        }
 
422
}
 
423
 
 
424
/**
 
425
 * net_vpn_set_property:
 
426
 **/
 
427
static void
 
428
net_vpn_set_property (GObject *object,
 
429
                      guint prop_id,
 
430
                      const GValue *value,
 
431
                      GParamSpec *pspec)
 
432
{
 
433
        NetVpn *vpn = NET_VPN (object);
 
434
 
 
435
        switch (prop_id) {
 
436
        case PROP_CONNECTION:
 
437
                net_vpn_set_connection (vpn, g_value_get_object (value));
 
438
                break;
 
439
        default:
 
440
                G_OBJECT_WARN_INVALID_PROPERTY_ID (vpn, prop_id, pspec);
 
441
                break;
 
442
        }
 
443
}
 
444
 
 
445
static void
 
446
net_vpn_constructed (GObject *object)
 
447
{
 
448
        NetVpn *vpn = NET_VPN (object);
 
449
 
 
450
        G_OBJECT_CLASS (net_vpn_parent_class)->constructed (object);
 
451
 
 
452
        nm_device_refresh_vpn_ui (vpn);
 
453
}
 
454
 
 
455
static void
 
456
net_vpn_finalize (GObject *object)
 
457
{
 
458
        NetVpn *vpn = NET_VPN (object);
 
459
        NetVpnPrivate *priv = vpn->priv;
 
460
 
 
461
        g_object_unref (priv->connection);
 
462
        g_free (priv->service_type);
 
463
 
 
464
        G_OBJECT_CLASS (net_vpn_parent_class)->finalize (object);
 
465
}
 
466
 
 
467
static void
 
468
net_vpn_class_init (NetVpnClass *klass)
 
469
{
 
470
        GParamSpec *pspec;
 
471
        GObjectClass *object_class = G_OBJECT_CLASS (klass);
 
472
        NetObjectClass *parent_class = NET_OBJECT_CLASS (klass);
 
473
 
 
474
        object_class->get_property = net_vpn_get_property;
 
475
        object_class->set_property = net_vpn_set_property;
 
476
        object_class->constructed = net_vpn_constructed;
 
477
        object_class->finalize = net_vpn_finalize;
 
478
        parent_class->add_to_notebook = vpn_proxy_add_to_notebook;
 
479
        parent_class->delete = vpn_proxy_delete;
 
480
        parent_class->refresh = vpn_proxy_refresh;
 
481
        parent_class->edit = vpn_proxy_edit;
 
482
 
 
483
        pspec = g_param_spec_object ("connection", NULL, NULL,
 
484
                                     NM_TYPE_CONNECTION,
 
485
                                     G_PARAM_READWRITE | G_PARAM_CONSTRUCT);
 
486
        g_object_class_install_property (object_class, PROP_CONNECTION, pspec);
 
487
 
 
488
        g_type_class_add_private (klass, sizeof (NetVpnPrivate));
 
489
}
 
490
 
 
491
static void
 
492
net_vpn_init (NetVpn *vpn)
 
493
{
 
494
        GError *error = NULL;
 
495
        GtkWidget *widget;
 
496
 
 
497
        vpn->priv = NET_VPN_GET_PRIVATE (vpn);
 
498
 
 
499
        vpn->priv->builder = gtk_builder_new ();
 
500
        gtk_builder_add_from_file (vpn->priv->builder,
 
501
                                   GNOMECC_UI_DIR "/network-vpn.ui",
 
502
                                   &error);
 
503
        if (error != NULL) {
 
504
                g_warning ("Could not load interface file: %s", error->message);
 
505
                g_error_free (error);
 
506
                return;
 
507
        }
 
508
 
 
509
        widget = GTK_WIDGET (gtk_builder_get_object (vpn->priv->builder,
 
510
                                                     "device_off_switch"));
 
511
        g_signal_connect (widget, "notify::active",
 
512
                          G_CALLBACK (device_off_toggled), vpn);
 
513
 
 
514
        widget = GTK_WIDGET (gtk_builder_get_object (vpn->priv->builder,
 
515
                                                     "button_options"));
 
516
        g_signal_connect (widget, "clicked",
 
517
                          G_CALLBACK (edit_connection), vpn);
 
518
}