~ubuntu-branches/ubuntu/hardy/network-manager-applet/hardy

« back to all changes in this revision

Viewing changes to src/applet-compat.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Mercatante
  • Date: 2007-06-15 12:46:22 UTC
  • Revision ID: james.westby@ubuntu.com-20070615124622-01cyrnf0uxxun4lz
Tags: upstream-0.6.5
ImportĀ upstreamĀ versionĀ 0.6.5

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* NetworkManager -- Network link manager
 
2
 *
 
3
 * Dan Williams <dcbw@redhat.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 2 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 
18
 *
 
19
 * (C) Copyright 2005 Red Hat, Inc.
 
20
 */
 
21
 
 
22
#include <glib.h>
 
23
#include <glib/gi18n.h>
 
24
#include <dbus/dbus.h>
 
25
#include <gconf/gconf-client.h>
 
26
#include <gnome-keyring.h>
 
27
#include <iwlib.h>
 
28
 
 
29
#include "applet.h"
 
30
#include "applet-compat.h"
 
31
#include "gconf-helpers.h"
 
32
#include "nm-utils.h"
 
33
#include "cipher.h"
 
34
#include "cipher-wep-hex.h"
 
35
#include "cipher-wep-ascii.h"
 
36
#include "cipher-wep-passphrase.h"
 
37
 
 
38
 
 
39
/*
 
40
 * Authentication modes
 
41
 */
 
42
typedef enum NMDeviceAuthMethod
 
43
{
 
44
        NM_DEVICE_AUTH_METHOD_UNKNOWN = 0,
 
45
        NM_DEVICE_AUTH_METHOD_NONE,
 
46
        NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM,
 
47
        NM_DEVICE_AUTH_METHOD_SHARED_KEY
 
48
} NMDeviceAuthMethod;
 
49
 
 
50
/*
 
51
 * Encryption key types
 
52
 */
 
53
typedef enum NMEncKeyType
 
54
{
 
55
        NM_ENC_TYPE_UNKNOWN = 0,
 
56
        NM_ENC_TYPE_NONE,
 
57
        NM_ENC_TYPE_HEX_KEY,
 
58
        NM_ENC_TYPE_ASCII_KEY,
 
59
        NM_ENC_TYPE_128_BIT_PASSPHRASE
 
60
        /* FIXME: WPA and 802.1x support */
 
61
} NMEncKeyType;
 
62
 
 
63
#define WEP_PREFIX      "wep_"
 
64
 
 
65
 
 
66
static void
 
67
unset_nm_gconf_key (GConfClient *client,
 
68
                    const char *escaped_network,
 
69
                    const char *key_name)
 
70
{
 
71
        char *  key;
 
72
 
 
73
        g_return_if_fail (client != NULL);
 
74
        g_return_if_fail (escaped_network != NULL);
 
75
        g_return_if_fail (key_name != NULL);
 
76
 
 
77
        key = g_strdup_printf ("%s/%s/%s",
 
78
                            GCONF_PATH_WIRELESS_NETWORKS,
 
79
                            escaped_network,
 
80
                            key_name);
 
81
        gconf_client_unset (client, key, NULL);
 
82
        g_free (key);
 
83
}
 
84
 
 
85
static void
 
86
set_entry_cipher (GConfClient *client,
 
87
                  const char *escaped_network,
 
88
                  int we_cipher)
 
89
{
 
90
        char *key;
 
91
 
 
92
        g_return_if_fail (client != NULL);
 
93
        g_return_if_fail (escaped_network != NULL);
 
94
 
 
95
        key = g_strdup_printf ("%s/%s/we_cipher", GCONF_PATH_WIRELESS_NETWORKS, escaped_network);
 
96
        gconf_client_set_int (client, key, we_cipher, NULL);
 
97
        g_free (key);
 
98
}
 
99
 
 
100
static void
 
101
convert_entry_auth_algorithm (GConfClient *client,
 
102
                              const char *escaped_network)
 
103
{
 
104
        char *                  key;
 
105
        int                             int_auth_method;
 
106
        NMDeviceAuthMethod      auth_method = NM_DEVICE_AUTH_METHOD_OPEN_SYSTEM;
 
107
        int                             we_auth_alg = IW_AUTH_ALG_OPEN_SYSTEM;
 
108
 
 
109
        g_return_if_fail (client != NULL);
 
110
        g_return_if_fail (escaped_network != NULL);
 
111
 
 
112
        if (nm_gconf_get_int_helper (client,
 
113
                                                        GCONF_PATH_WIRELESS_NETWORKS,
 
114
                                                        "auth_method",
 
115
                                                        escaped_network,
 
116
                                                        &int_auth_method))
 
117
                auth_method = (NMDeviceAuthMethod) int_auth_method;
 
118
 
 
119
        if (auth_method == NM_DEVICE_AUTH_METHOD_SHARED_KEY)
 
120
                we_auth_alg = IW_AUTH_ALG_SHARED_KEY;
 
121
 
 
122
        key = g_strdup_printf ("%s/%s/%sauth_algorithm",
 
123
                                           GCONF_PATH_WIRELESS_NETWORKS,
 
124
                                           escaped_network,
 
125
                                           WEP_PREFIX);
 
126
        gconf_client_set_int (client, key, we_auth_alg, NULL);
 
127
        g_free (key);
 
128
 
 
129
        /* Remove the old auth_method key */
 
130
        unset_nm_gconf_key (client, escaped_network, "auth_method");
 
131
}
 
132
 
 
133
static char *
 
134
get_key_from_keyring (const char *essid, int *item_id)
 
135
{
 
136
        GnomeKeyringResult      ret;
 
137
        GList *                 found_list = NULL;
 
138
        GnomeKeyringFound *     found;
 
139
        char *                  key;
 
140
 
 
141
        g_return_val_if_fail (essid != NULL, NULL);
 
142
 
 
143
        ret = gnome_keyring_find_itemsv_sync (GNOME_KEYRING_ITEM_GENERIC_SECRET,
 
144
                                        &found_list,
 
145
                                        "essid",
 
146
                                        GNOME_KEYRING_ATTRIBUTE_TYPE_STRING,
 
147
                                        essid,
 
148
                                        NULL);
 
149
        if (ret != GNOME_KEYRING_RESULT_OK)
 
150
                return NULL;
 
151
 
 
152
        found = (GnomeKeyringFound *) found_list->data;
 
153
        key = g_strdup (found->secret);
 
154
        if (item_id)
 
155
                *item_id = found->item_id;
 
156
        gnome_keyring_found_list_free (found_list);
 
157
 
 
158
        return key;
 
159
}
 
160
 
 
161
static void
 
162
set_key_in_keyring (const char *essid,
 
163
                    const char *key)
 
164
{
 
165
        GnomeKeyringAttributeList *     attributes;
 
166
        GnomeKeyringAttribute           attr;
 
167
        GnomeKeyringResult                      ret;
 
168
        const char *                            name;
 
169
        guint32                                 item_id;
 
170
 
 
171
        name = g_strdup_printf (_("Passphrase for wireless network %s"), essid);
 
172
 
 
173
        attributes = gnome_keyring_attribute_list_new ();
 
174
        attr.name = g_strdup ("essid");
 
175
        attr.type = GNOME_KEYRING_ATTRIBUTE_TYPE_STRING;
 
176
        attr.value.string = g_strdup (essid);
 
177
        g_array_append_val (attributes, attr);
 
178
 
 
179
        ret = gnome_keyring_item_create_sync (NULL,
 
180
                                                                   GNOME_KEYRING_ITEM_GENERIC_SECRET,
 
181
                                                                   name,
 
182
                                                                   attributes,
 
183
                                                                   key,
 
184
                                                                   TRUE,
 
185
                                                                   &item_id);
 
186
        if (ret != GNOME_KEYRING_RESULT_OK)
 
187
        {
 
188
                nm_warning ("%s:%d (%s): Error converting encryption key for '%s'.  Ret=%d",
 
189
                        __FILE__, __LINE__, __func__, essid, ret);
 
190
        }
 
191
 
 
192
        gnome_keyring_attribute_list_free (attributes);
 
193
}
 
194
 
 
195
static void
 
196
convert_no_encryption (GConfClient *client,
 
197
                       const char *escaped_network)
 
198
{
 
199
        g_return_if_fail (client != NULL);
 
200
        g_return_if_fail (escaped_network != NULL);
 
201
 
 
202
        set_entry_cipher (client, escaped_network, IW_AUTH_CIPHER_NONE);
 
203
 
 
204
        /* Remove the old auth_method key if it's present */
 
205
        unset_nm_gconf_key (client, escaped_network, "auth_method");
 
206
}
 
207
 
 
208
static void
 
209
generic_convert_wep_entry (GConfClient *client,
 
210
                           const char *escaped_network,
 
211
                           const char *essid,
 
212
                           IEEE_802_11_Cipher *first_cipher,
 
213
                           IEEE_802_11_Cipher *second_cipher)
 
214
{
 
215
        char *                          key;
 
216
        int                                     key_item_id = -1;
 
217
        int                                     real_we_cipher = IW_AUTH_CIPHER_WEP104;
 
218
        IEEE_802_11_Cipher *    real_cipher = NULL;
 
219
        char *                          hashed_key = NULL;
 
220
 
 
221
        g_return_if_fail (client != NULL);
 
222
        g_return_if_fail (escaped_network != NULL);
 
223
        g_return_if_fail (essid != NULL);
 
224
        g_return_if_fail (first_cipher != NULL);
 
225
 
 
226
        key = get_key_from_keyring (essid, &key_item_id);
 
227
 
 
228
        /* Try to validate key with first cipher */
 
229
        if (ieee_802_11_cipher_validate (first_cipher, essid, key) == 0)
 
230
        {
 
231
                if ((hashed_key = ieee_802_11_cipher_hash (first_cipher, essid, key)))
 
232
                        real_cipher = first_cipher;
 
233
        }
 
234
 
 
235
        if (second_cipher && !hashed_key)
 
236
        {
 
237
                /* Try second cipher then */
 
238
                if (ieee_802_11_cipher_validate (second_cipher, essid, key) == 0)
 
239
                        if ((hashed_key = ieee_802_11_cipher_hash (second_cipher, essid, key)))
 
240
                                real_cipher = second_cipher;
 
241
        }
 
242
 
 
243
        if (real_cipher && hashed_key)
 
244
        {
 
245
                real_we_cipher = ieee_802_11_cipher_get_we_cipher (real_cipher);
 
246
                /* Set the converted key in the keyring */
 
247
                set_key_in_keyring (essid, hashed_key);
 
248
        }
 
249
        else
 
250
        {
 
251
                /* Couldn't convert the key, so remove it from
 
252
                 * the keyring and let the user enter it later.
 
253
                 */
 
254
                nm_warning ("%s:%d (%s): Could not convert old WEP key for network '%s'.",
 
255
                        __FILE__, __LINE__, __func__, essid);
 
256
                gnome_keyring_item_delete_sync (NULL, key_item_id);
 
257
        }
 
258
        g_free (key);
 
259
 
 
260
        /* Set new WE cipher */
 
261
        set_entry_cipher (client, escaped_network, real_we_cipher);
 
262
 
 
263
        /* Set the authentication algorithm */
 
264
        convert_entry_auth_algorithm (client, escaped_network);
 
265
}
 
266
 
 
267
static void
 
268
convert_one_entry (GConfClient *client,
 
269
                   const char *essid)
 
270
{
 
271
        int                     we_cipher;
 
272
        GConfValue *    addrs_value = NULL;
 
273
        char *          escaped_network;
 
274
        char *          key;
 
275
        int                     int_key_type;
 
276
        NMEncKeyType    key_type = NM_ENC_TYPE_NONE;
 
277
        IEEE_802_11_Cipher * first_cipher = NULL;
 
278
        IEEE_802_11_Cipher * second_cipher = NULL;
 
279
 
 
280
        g_return_if_fail (client != NULL);
 
281
        g_return_if_fail (essid != NULL);
 
282
 
 
283
        if (!(escaped_network = gconf_escape_key (essid, strlen (essid))) || strlen (escaped_network) == 0)
 
284
        {
 
285
                nm_warning ("%s:%d (%s): couldn't unescape network name '%s'.",
 
286
                                __FILE__, __LINE__, __func__, essid);
 
287
                return;
 
288
        }
 
289
 
 
290
        /* Ignore any entry that looks like it doesn't need conversion */
 
291
        if (nm_gconf_get_int_helper (client,
 
292
                                   GCONF_PATH_WIRELESS_NETWORKS,
 
293
                                   "we_cipher",
 
294
                                   escaped_network,
 
295
                                   &we_cipher))
 
296
                goto out;
 
297
 
 
298
        /* Grab the key type off this old entry so we know how to convert it */
 
299
        if (nm_gconf_get_int_helper (client,
 
300
                                   GCONF_PATH_WIRELESS_NETWORKS,
 
301
                                   "key_type",
 
302
                                   escaped_network,
 
303
                                   &int_key_type))
 
304
        {
 
305
                key_type = (NMEncKeyType) int_key_type;
 
306
        }
 
307
 
 
308
        /* Convert the list of stored access point BSSIDs */
 
309
        key = g_strdup_printf ("%s/%s/addresses", GCONF_PATH_WIRELESS_NETWORKS, escaped_network);
 
310
        if ((addrs_value = gconf_client_get (client, key, NULL)))
 
311
        {
 
312
                if ((addrs_value->type == GCONF_VALUE_LIST) && (gconf_value_get_list_type (addrs_value) == GCONF_VALUE_STRING))
 
313
                {
 
314
                        GSList *        list;
 
315
                        char *  conv_key;
 
316
 
 
317
                        list = gconf_client_get_list (client, key, GCONF_VALUE_STRING, NULL);
 
318
                        conv_key = g_strdup_printf ("%s/%s/bssids", GCONF_PATH_WIRELESS_NETWORKS, escaped_network);
 
319
                        gconf_client_set_list (client, conv_key, GCONF_VALUE_STRING, list, NULL);
 
320
                        g_free (conv_key);
 
321
                        g_slist_foreach (list, (GFunc) g_free, NULL);
 
322
                        g_slist_free (list);
 
323
                }
 
324
                gconf_value_free (addrs_value);
 
325
        }
 
326
        gconf_client_unset (client, key, NULL);
 
327
        g_free (key);
 
328
 
 
329
        /* Convert security information, if any */
 
330
        switch (key_type)
 
331
        {
 
332
                case NM_ENC_TYPE_UNKNOWN:
 
333
                case NM_ENC_TYPE_NONE:
 
334
                        convert_no_encryption (client, escaped_network);
 
335
                        break;
 
336
                case NM_ENC_TYPE_HEX_KEY:
 
337
                        first_cipher = cipher_wep128_hex_new ();
 
338
                        second_cipher = cipher_wep64_hex_new ();
 
339
                        break;
 
340
                case NM_ENC_TYPE_ASCII_KEY:
 
341
                        first_cipher = cipher_wep128_ascii_new ();
 
342
                        second_cipher = cipher_wep64_ascii_new ();
 
343
                        break;
 
344
                case NM_ENC_TYPE_128_BIT_PASSPHRASE:
 
345
                        first_cipher = cipher_wep128_passphrase_new ();
 
346
                        second_cipher = cipher_wep64_passphrase_new ();
 
347
                        break;
 
348
                default:
 
349
                        break;
 
350
        }
 
351
 
 
352
        if (first_cipher)
 
353
        {
 
354
                /* Do the actual key conversion */
 
355
                generic_convert_wep_entry (client, escaped_network, essid, first_cipher, second_cipher);
 
356
                ieee_802_11_cipher_unref (first_cipher);
 
357
                if (second_cipher)
 
358
                        ieee_802_11_cipher_unref (second_cipher);
 
359
        }
 
360
        unset_nm_gconf_key (client, escaped_network, "key_type");
 
361
 
 
362
out:
 
363
        g_free (escaped_network);
 
364
 
 
365
        return;
 
366
}
 
367
 
 
368
void
 
369
nma_compat_convert_oldformat_entries (GConfClient *client)
 
370
{
 
371
        GSList *        dir_list = NULL;
 
372
        GSList *        elt;
 
373
 
 
374
        g_return_if_fail (client != NULL);
 
375
 
 
376
        if (!(dir_list = gconf_client_all_dirs (client, GCONF_PATH_WIRELESS_NETWORKS, NULL)))
 
377
                return;
 
378
 
 
379
        for (elt = dir_list; elt; elt = g_slist_next (elt))
 
380
        {
 
381
                char                    key[100];
 
382
                GConfValue *    value;
 
383
                char *          dir = (char *) (elt->data);
 
384
 
 
385
                g_snprintf (&key[0], 99, "%s/essid", dir);
 
386
                if ((value = gconf_client_get (client, key, NULL)))
 
387
                {
 
388
                        if (value->type == GCONF_VALUE_STRING)
 
389
                        {
 
390
                                const char *essid = gconf_value_get_string (value);
 
391
                                convert_one_entry (client, essid);
 
392
                        }
 
393
                        gconf_value_free (value);
 
394
                }
 
395
                g_free (dir);
 
396
        }
 
397
        g_slist_free (dir_list);
 
398
 
 
399
}