~ubuntu-branches/ubuntu/gutsy/wpasupplicant/gutsy

« back to all changes in this revision

Viewing changes to wpa_supplicant/config_winreg.c

  • Committer: Bazaar Package Importer
  • Author(s): Reinhard Tartler, Alexander Sack
  • Date: 2007-08-26 16:06:57 UTC
  • mfrom: (1.1.9 upstream)
  • Revision ID: james.westby@ubuntu.com-20070826160657-2m8pxoweuxe8f93t
Tags: 0.6.0+0.5.8-0ubuntu1
* New upstream release
* remove patch 11_erroneous_manpage_ref, applied upstream
* remove patch 25_wpas_dbus_unregister_iface_fix, applied upstream

[ Alexander Sack ]
* bumping upstream version to replace development version 0.6.0 with
  this package from stable release branch.
* attempt to fix wierd timeout and high latency issues by going
  back to stable upstream version (0.5.9) (LP: #140763,
  LP: #141233).

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
 
/*
2
 
 * WPA Supplicant / Configuration backend: Windows registry
3
 
 * Copyright (c) 2003-2006, Jouni Malinen <j@w1.fi>
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 version 2 as
7
 
 * published by the Free Software Foundation.
8
 
 *
9
 
 * Alternatively, this software may be distributed under the terms of BSD
10
 
 * license.
11
 
 *
12
 
 * See README and COPYING for more details.
13
 
 *
14
 
 * This file implements a configuration backend for Windows registry.. All the
15
 
 * configuration information is stored in the registry and the format for
16
 
 * network configuration fields is same as described in the sample
17
 
 * configuration file, wpa_supplicant.conf.
18
 
 *
19
 
 * Configuration data is in HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs
20
 
 * key. Each configuration profile has its own key under this. In terms of text
21
 
 * files, each profile would map to a separate text file with possibly multiple
22
 
 * networks. Under each profile, there is a networks key that lists all
23
 
 * networks as a subkey. Each network has set of values in the same way as
24
 
 * network block in the configuration file. In addition, blobs subkey has
25
 
 * possible blobs as values.
26
 
 *
27
 
 * HKEY_LOCAL_MACHINE\SOFTWARE\wpa_supplicant\configs\test\networks\0000
28
 
 *    ssid="example"
29
 
 *    key_mgmt=WPA-PSK
30
 
 */
31
 
 
32
 
#include "includes.h"
33
 
 
34
 
#include "common.h"
35
 
#include "config.h"
36
 
 
37
 
#ifndef WPA_KEY_ROOT
38
 
#define WPA_KEY_ROOT HKEY_LOCAL_MACHINE
39
 
#endif
40
 
#ifndef WPA_KEY_PREFIX
41
 
#define WPA_KEY_PREFIX TEXT("SOFTWARE\\wpa_supplicant")
42
 
#endif
43
 
 
44
 
#ifdef UNICODE
45
 
#define TSTR "%S"
46
 
#else /* UNICODE */
47
 
#define TSTR "%s"
48
 
#endif /* UNICODE */
49
 
 
50
 
 
51
 
static int wpa_config_read_blobs(struct wpa_config *config, HKEY hk)
52
 
{
53
 
        struct wpa_config_blob *blob;
54
 
        int errors = 0;
55
 
        HKEY bhk;
56
 
        LONG ret;
57
 
        DWORD i;
58
 
 
59
 
        ret = RegOpenKeyEx(hk, TEXT("blobs"), 0, KEY_QUERY_VALUE, &bhk);
60
 
        if (ret != ERROR_SUCCESS) {
61
 
                wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config "
62
 
                           "blobs key");
63
 
                return 0; /* assume no blobs */
64
 
        }
65
 
 
66
 
        for (i = 0; ; i++) {
67
 
#define TNAMELEN 255
68
 
                TCHAR name[TNAMELEN];
69
 
                char data[4096];
70
 
                DWORD namelen, datalen, type;
71
 
 
72
 
                namelen = TNAMELEN;
73
 
                datalen = sizeof(data);
74
 
                ret = RegEnumValue(bhk, i, name, &namelen, NULL, &type,
75
 
                                   (LPBYTE) data, &datalen);
76
 
 
77
 
                if (ret == ERROR_NO_MORE_ITEMS)
78
 
                        break;
79
 
 
80
 
                if (ret != ERROR_SUCCESS) {
81
 
                        wpa_printf(MSG_DEBUG, "RegEnumValue failed: 0x%x",
82
 
                                   (unsigned int) ret);
83
 
                        break;
84
 
                }
85
 
 
86
 
                if (namelen >= TNAMELEN)
87
 
                        namelen = TNAMELEN - 1;
88
 
                name[namelen] = TEXT('\0');
89
 
                wpa_unicode2ascii_inplace(name);
90
 
 
91
 
                if (datalen >= sizeof(data))
92
 
                        datalen = sizeof(data) - 1;
93
 
 
94
 
                wpa_printf(MSG_MSGDUMP, "blob %d: field='%s' len %d",
95
 
                           (int) i, name, (int) datalen);
96
 
 
97
 
                blob = os_zalloc(sizeof(*blob));
98
 
                if (blob == NULL) {
99
 
                        errors++;
100
 
                        break;
101
 
                }
102
 
                blob->name = os_strdup((char *) name);
103
 
                blob->data = os_malloc(datalen);
104
 
                if (blob->name == NULL || blob->data == NULL) {
105
 
                        wpa_config_free_blob(blob);
106
 
                        errors++;
107
 
                        break;
108
 
                }
109
 
                os_memcpy(blob->data, data, datalen);
110
 
                blob->len = datalen;
111
 
 
112
 
                wpa_config_set_blob(config, blob);
113
 
        }
114
 
 
115
 
        RegCloseKey(bhk);
116
 
 
117
 
        return errors ? -1 : 0;
118
 
}
119
 
 
120
 
 
121
 
static int wpa_config_read_reg_dword(HKEY hk, const TCHAR *name, int *_val)
122
 
{
123
 
        DWORD val, buflen;
124
 
        LONG ret;
125
 
 
126
 
        buflen = sizeof(val);
127
 
        ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) &val, &buflen);
128
 
        if (ret == ERROR_SUCCESS && buflen == sizeof(val)) {
129
 
                wpa_printf(MSG_DEBUG, TSTR "=%d", name, (int) val);
130
 
                *_val = val;
131
 
                return 0;
132
 
        }
133
 
 
134
 
        return -1;
135
 
}
136
 
 
137
 
 
138
 
static char * wpa_config_read_reg_string(HKEY hk, const TCHAR *name)
139
 
{
140
 
        DWORD buflen;
141
 
        LONG ret;
142
 
        TCHAR *val;
143
 
 
144
 
        buflen = 0;
145
 
        ret = RegQueryValueEx(hk, name, NULL, NULL, NULL, &buflen);
146
 
        if (ret != ERROR_SUCCESS)
147
 
                return NULL;
148
 
        val = os_malloc(buflen);
149
 
        if (val == NULL)
150
 
                return NULL;
151
 
 
152
 
        ret = RegQueryValueEx(hk, name, NULL, NULL, (LPBYTE) val, &buflen);
153
 
        if (ret != ERROR_SUCCESS) {
154
 
                os_free(val);
155
 
                return NULL;
156
 
        }
157
 
 
158
 
        wpa_unicode2ascii_inplace(val);
159
 
        wpa_printf(MSG_DEBUG, TSTR "=%s", name, (char *) val);
160
 
        return (char *) val;
161
 
}
162
 
 
163
 
 
164
 
static int wpa_config_read_global(struct wpa_config *config, HKEY hk)
165
 
{
166
 
        int errors = 0;
167
 
 
168
 
        wpa_config_read_reg_dword(hk, TEXT("ap_scan"), &config->ap_scan);
169
 
        wpa_config_read_reg_dword(hk, TEXT("fast_reauth"),
170
 
                                  &config->fast_reauth);
171
 
        wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"),
172
 
                                  &config->dot11RSNAConfigPMKLifetime);
173
 
        wpa_config_read_reg_dword(hk,
174
 
                                  TEXT("dot11RSNAConfigPMKReauthThreshold"),
175
 
                                  &config->dot11RSNAConfigPMKReauthThreshold);
176
 
        wpa_config_read_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"),
177
 
                                  &config->dot11RSNAConfigSATimeout);
178
 
        wpa_config_read_reg_dword(hk, TEXT("update_config"),
179
 
                                  &config->update_config);
180
 
 
181
 
        if (wpa_config_read_reg_dword(hk, TEXT("eapol_version"),
182
 
                                      &config->eapol_version) == 0) {
183
 
                if (config->eapol_version < 1 ||
184
 
                    config->eapol_version > 2) {
185
 
                        wpa_printf(MSG_ERROR, "Invalid EAPOL version (%d)",
186
 
                                   config->eapol_version);
187
 
                        errors++;
188
 
                }
189
 
        }
190
 
 
191
 
        config->ctrl_interface = wpa_config_read_reg_string(
192
 
                hk, TEXT("ctrl_interface"));
193
 
 
194
 
        return errors ? -1 : 0;
195
 
}
196
 
 
197
 
 
198
 
static struct wpa_ssid * wpa_config_read_network(HKEY hk, const TCHAR *netw,
199
 
                                                 int id)
200
 
{
201
 
        HKEY nhk;
202
 
        LONG ret;
203
 
        DWORD i;
204
 
        struct wpa_ssid *ssid;
205
 
        int errors = 0;
206
 
 
207
 
        ret = RegOpenKeyEx(hk, netw, 0, KEY_QUERY_VALUE, &nhk);
208
 
        if (ret != ERROR_SUCCESS) {
209
 
                wpa_printf(MSG_DEBUG, "Could not open wpa_supplicant config "
210
 
                           "network '" TSTR "'", netw);
211
 
                return NULL;
212
 
        }
213
 
 
214
 
        wpa_printf(MSG_MSGDUMP, "Start of a new network '" TSTR "'", netw);
215
 
        ssid = os_zalloc(sizeof(*ssid));
216
 
        if (ssid == NULL) {
217
 
                RegCloseKey(nhk);
218
 
                return NULL;
219
 
        }
220
 
        ssid->id = id;
221
 
 
222
 
        wpa_config_set_network_defaults(ssid);
223
 
 
224
 
        for (i = 0; ; i++) {
225
 
                TCHAR name[255], data[1024];
226
 
                DWORD namelen, datalen, type;
227
 
 
228
 
                namelen = 255;
229
 
                datalen = sizeof(data);
230
 
                ret = RegEnumValue(nhk, i, name, &namelen, NULL, &type,
231
 
                                   (LPBYTE) data, &datalen);
232
 
 
233
 
                if (ret == ERROR_NO_MORE_ITEMS)
234
 
                        break;
235
 
 
236
 
                if (ret != ERROR_SUCCESS) {
237
 
                        wpa_printf(MSG_ERROR, "RegEnumValue failed: 0x%x",
238
 
                                   (unsigned int) ret);
239
 
                        break;
240
 
                }
241
 
 
242
 
                if (namelen >= 255)
243
 
                        namelen = 255 - 1;
244
 
                name[namelen] = TEXT('\0');
245
 
 
246
 
                if (datalen >= 1024)
247
 
                        datalen = 1024 - 1;
248
 
                data[datalen] = TEXT('\0');
249
 
 
250
 
                wpa_unicode2ascii_inplace(name);
251
 
                wpa_unicode2ascii_inplace(data);
252
 
                if (wpa_config_set(ssid, (char *) name, (char *) data, 0) < 0)
253
 
                        errors++;
254
 
        }
255
 
 
256
 
        RegCloseKey(nhk);
257
 
 
258
 
        if (ssid->passphrase) {
259
 
                if (ssid->psk_set) {
260
 
                        wpa_printf(MSG_ERROR, "Both PSK and passphrase "
261
 
                                   "configured for network '" TSTR "'.", netw);
262
 
                        errors++;
263
 
                }
264
 
                wpa_config_update_psk(ssid);
265
 
        }
266
 
 
267
 
        if ((ssid->key_mgmt & (WPA_KEY_MGMT_PSK | WPA_KEY_MGMT_FT_PSK)) &&
268
 
            !ssid->psk_set) {
269
 
                wpa_printf(MSG_ERROR, "WPA-PSK accepted for key management, "
270
 
                           "but no PSK configured for network '" TSTR "'.",
271
 
                           netw);
272
 
                errors++;
273
 
        }
274
 
 
275
 
        if ((ssid->group_cipher & WPA_CIPHER_CCMP) &&
276
 
            !(ssid->pairwise_cipher & WPA_CIPHER_CCMP) &&
277
 
            !(ssid->pairwise_cipher & WPA_CIPHER_NONE)) {
278
 
                /* Group cipher cannot be stronger than the pairwise cipher. */
279
 
                wpa_printf(MSG_DEBUG, "Removed CCMP from group cipher "
280
 
                           "list since it was not allowed for pairwise "
281
 
                           "cipher for network '" TSTR "'.", netw);
282
 
                ssid->group_cipher &= ~WPA_CIPHER_CCMP;
283
 
        }
284
 
 
285
 
        if (errors) {
286
 
                wpa_config_free_ssid(ssid);
287
 
                ssid = NULL;
288
 
        }
289
 
 
290
 
        return ssid;
291
 
}
292
 
 
293
 
 
294
 
static int wpa_config_read_networks(struct wpa_config *config, HKEY hk)
295
 
{
296
 
        HKEY nhk;
297
 
        struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
298
 
        int errors = 0;
299
 
        LONG ret;
300
 
        DWORD i;
301
 
 
302
 
        ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_ENUMERATE_SUB_KEYS,
303
 
                           &nhk);
304
 
        if (ret != ERROR_SUCCESS) {
305
 
                wpa_printf(MSG_ERROR, "Could not open wpa_supplicant networks "
306
 
                           "registry key");
307
 
                return -1;
308
 
        }
309
 
 
310
 
        for (i = 0; ; i++) {
311
 
                TCHAR name[255];
312
 
                DWORD namelen;
313
 
 
314
 
                namelen = 255;
315
 
                ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL,
316
 
                                   NULL);
317
 
 
318
 
                if (ret == ERROR_NO_MORE_ITEMS)
319
 
                        break;
320
 
 
321
 
                if (ret != ERROR_SUCCESS) {
322
 
                        wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x",
323
 
                                   (unsigned int) ret);
324
 
                        break;
325
 
                }
326
 
 
327
 
                if (namelen >= 255)
328
 
                        namelen = 255 - 1;
329
 
                name[namelen] = '\0';
330
 
 
331
 
                ssid = wpa_config_read_network(nhk, name, i);
332
 
                if (ssid == NULL) {
333
 
                        wpa_printf(MSG_ERROR, "Failed to parse network "
334
 
                                   "profile '%s'.", name);
335
 
                        errors++;
336
 
                        continue;
337
 
                }
338
 
                if (head == NULL) {
339
 
                        head = tail = ssid;
340
 
                } else {
341
 
                        tail->next = ssid;
342
 
                        tail = ssid;
343
 
                }
344
 
                if (wpa_config_add_prio_network(config, ssid)) {
345
 
                        wpa_printf(MSG_ERROR, "Failed to add network profile "
346
 
                                   "'%s' to priority list.", name);
347
 
                        errors++;
348
 
                        continue;
349
 
                }
350
 
        }
351
 
 
352
 
        RegCloseKey(nhk);
353
 
 
354
 
        config->ssid = head;
355
 
 
356
 
        return errors ? -1 : 0;
357
 
}
358
 
 
359
 
 
360
 
struct wpa_config * wpa_config_read(const char *name)
361
 
{
362
 
        TCHAR buf[256];
363
 
        int errors = 0;
364
 
        struct wpa_config *config;
365
 
        HKEY hk;
366
 
        LONG ret;
367
 
 
368
 
        config = wpa_config_alloc_empty(NULL, NULL);
369
 
        if (config == NULL)
370
 
                return NULL;
371
 
        wpa_printf(MSG_DEBUG, "Reading configuration profile '%s'", name);
372
 
 
373
 
#ifdef UNICODE
374
 
        _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name);
375
 
#else /* UNICODE */
376
 
        os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name);
377
 
#endif /* UNICODE */
378
 
 
379
 
        ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_QUERY_VALUE, &hk);
380
 
        if (ret != ERROR_SUCCESS) {
381
 
                wpa_printf(MSG_ERROR, "Could not open wpa_supplicant "
382
 
                           "configuration registry HKLM\\" TSTR, buf);
383
 
                os_free(config);
384
 
                return NULL;
385
 
        }
386
 
 
387
 
        if (wpa_config_read_global(config, hk))
388
 
                errors++;
389
 
 
390
 
        if (wpa_config_read_networks(config, hk))
391
 
                errors++;
392
 
 
393
 
        if (wpa_config_read_blobs(config, hk))
394
 
                errors++;
395
 
 
396
 
        wpa_config_debug_dump_networks(config);
397
 
 
398
 
        RegCloseKey(hk);
399
 
 
400
 
        if (errors) {
401
 
                wpa_config_free(config);
402
 
                config = NULL;
403
 
        }
404
 
 
405
 
        return config;
406
 
}
407
 
 
408
 
 
409
 
static int wpa_config_write_reg_dword(HKEY hk, const TCHAR *name, int val,
410
 
                                      int def)
411
 
{
412
 
        LONG ret;
413
 
        DWORD _val = val;
414
 
 
415
 
        if (val == def) {
416
 
                RegDeleteValue(hk, name);
417
 
                return 0;
418
 
        }
419
 
 
420
 
        ret = RegSetValueEx(hk, name, 0, REG_DWORD, (LPBYTE) &_val,
421
 
                            sizeof(_val));
422
 
        if (ret != ERROR_SUCCESS) {
423
 
                wpa_printf(MSG_ERROR, "WINREG: Failed to set %s=%d: error %d",
424
 
                           name, val, (int) GetLastError());
425
 
                return -1;
426
 
        }
427
 
 
428
 
        return 0;
429
 
}
430
 
 
431
 
 
432
 
static int wpa_config_write_reg_string(HKEY hk, const char *name,
433
 
                                       const char *val)
434
 
{
435
 
        LONG ret;
436
 
        TCHAR *_name, *_val;
437
 
 
438
 
        _name = wpa_strdup_tchar(name);
439
 
        if (_name == NULL)
440
 
                return -1;
441
 
 
442
 
        if (val == NULL) {
443
 
                RegDeleteValue(hk, _name);
444
 
                os_free(_name);
445
 
                return 0;
446
 
        }
447
 
 
448
 
        _val = wpa_strdup_tchar(val);
449
 
        if (_val == NULL) {
450
 
                os_free(_name);
451
 
                return -1;
452
 
        }
453
 
        ret = RegSetValueEx(hk, _name, 0, REG_SZ, (BYTE *) _val,
454
 
                            (os_strlen(val) + 1) * sizeof(TCHAR));
455
 
        if (ret != ERROR_SUCCESS) {
456
 
                wpa_printf(MSG_ERROR, "WINREG: Failed to set %s='%s': "
457
 
                           "error %d", name, val, (int) GetLastError());
458
 
                os_free(_name);
459
 
                os_free(_val);
460
 
                return -1;
461
 
        }
462
 
 
463
 
        os_free(_name);
464
 
        os_free(_val);
465
 
        return 0;
466
 
}
467
 
 
468
 
 
469
 
static int wpa_config_write_global(struct wpa_config *config, HKEY hk)
470
 
{
471
 
#ifdef CONFIG_CTRL_IFACE
472
 
        wpa_config_write_reg_string(hk, "ctrl_interface",
473
 
                                    config->ctrl_interface);
474
 
#endif /* CONFIG_CTRL_IFACE */
475
 
 
476
 
        wpa_config_write_reg_dword(hk, TEXT("eapol_version"),
477
 
                                   config->eapol_version,
478
 
                                   DEFAULT_EAPOL_VERSION);
479
 
        wpa_config_write_reg_dword(hk, TEXT("ap_scan"), config->ap_scan,
480
 
                                   DEFAULT_AP_SCAN);
481
 
        wpa_config_write_reg_dword(hk, TEXT("fast_reauth"),
482
 
                                   config->fast_reauth, DEFAULT_FAST_REAUTH);
483
 
        wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigPMKLifetime"),
484
 
                                   config->dot11RSNAConfigPMKLifetime, 0);
485
 
        wpa_config_write_reg_dword(hk,
486
 
                                   TEXT("dot11RSNAConfigPMKReauthThreshold"),
487
 
                                   config->dot11RSNAConfigPMKReauthThreshold,
488
 
                                   0);
489
 
        wpa_config_write_reg_dword(hk, TEXT("dot11RSNAConfigSATimeout"),
490
 
                                   config->dot11RSNAConfigSATimeout, 0);
491
 
        wpa_config_write_reg_dword(hk, TEXT("update_config"),
492
 
                                   config->update_config,
493
 
                                   0);
494
 
 
495
 
        return 0;
496
 
}
497
 
 
498
 
 
499
 
static int wpa_config_delete_subkeys(HKEY hk, const TCHAR *key)
500
 
{
501
 
        HKEY nhk;
502
 
        int i, errors = 0;
503
 
        LONG ret;
504
 
 
505
 
        ret = RegOpenKeyEx(hk, key, 0, KEY_ENUMERATE_SUB_KEYS | DELETE, &nhk);
506
 
        if (ret != ERROR_SUCCESS) {
507
 
                wpa_printf(MSG_DEBUG, "WINREG: Could not open key '" TSTR
508
 
                           "' for subkey deletion: error 0x%x (%d)", key,
509
 
                           (unsigned int) ret, (int) GetLastError());
510
 
                return 0;
511
 
        }
512
 
 
513
 
        for (i = 0; ; i++) {
514
 
                TCHAR name[255];
515
 
                DWORD namelen;
516
 
 
517
 
                namelen = 255;
518
 
                ret = RegEnumKeyEx(nhk, i, name, &namelen, NULL, NULL, NULL,
519
 
                                   NULL);
520
 
 
521
 
                if (ret == ERROR_NO_MORE_ITEMS)
522
 
                        break;
523
 
 
524
 
                if (ret != ERROR_SUCCESS) {
525
 
                        wpa_printf(MSG_DEBUG, "RegEnumKeyEx failed: 0x%x (%d)",
526
 
                                   (unsigned int) ret, (int) GetLastError());
527
 
                        break;
528
 
                }
529
 
 
530
 
                if (namelen >= 255)
531
 
                        namelen = 255 - 1;
532
 
                name[namelen] = TEXT('\0');
533
 
 
534
 
                ret = RegDeleteKey(nhk, name);
535
 
                if (ret != ERROR_SUCCESS) {
536
 
                        wpa_printf(MSG_DEBUG, "RegDeleteKey failed: 0x%x (%d)",
537
 
                                   (unsigned int) ret, (int) GetLastError());
538
 
                        errors++;
539
 
                }
540
 
        }
541
 
 
542
 
        RegCloseKey(nhk);
543
 
 
544
 
        return errors ? -1 : 0;
545
 
}
546
 
 
547
 
 
548
 
static void write_str(HKEY hk, const char *field, struct wpa_ssid *ssid)
549
 
{
550
 
        char *value = wpa_config_get(ssid, field);
551
 
        if (value == NULL)
552
 
                return;
553
 
        wpa_config_write_reg_string(hk, field, value);
554
 
        os_free(value);
555
 
}
556
 
 
557
 
 
558
 
static void write_int(HKEY hk, const char *field, int value, int def)
559
 
{
560
 
        char val[20];
561
 
        if (value == def)
562
 
                return;
563
 
        os_snprintf(val, sizeof(val), "%d", value);
564
 
        wpa_config_write_reg_string(hk, field, val);
565
 
}
566
 
 
567
 
 
568
 
static void write_bssid(HKEY hk, struct wpa_ssid *ssid)
569
 
{
570
 
        char *value = wpa_config_get(ssid, "bssid");
571
 
        if (value == NULL)
572
 
                return;
573
 
        wpa_config_write_reg_string(hk, "bssid", value);
574
 
        os_free(value);
575
 
}
576
 
 
577
 
 
578
 
static void write_psk(HKEY hk, struct wpa_ssid *ssid)
579
 
{
580
 
        char *value = wpa_config_get(ssid, "psk");
581
 
        if (value == NULL)
582
 
                return;
583
 
        wpa_config_write_reg_string(hk, "psk", value);
584
 
        os_free(value);
585
 
}
586
 
 
587
 
 
588
 
static void write_proto(HKEY hk, struct wpa_ssid *ssid)
589
 
{
590
 
        char *value;
591
 
 
592
 
        if (ssid->proto == DEFAULT_PROTO)
593
 
                return;
594
 
 
595
 
        value = wpa_config_get(ssid, "proto");
596
 
        if (value == NULL)
597
 
                return;
598
 
        if (value[0])
599
 
                wpa_config_write_reg_string(hk, "proto", value);
600
 
        os_free(value);
601
 
}
602
 
 
603
 
 
604
 
static void write_key_mgmt(HKEY hk, struct wpa_ssid *ssid)
605
 
{
606
 
        char *value;
607
 
 
608
 
        if (ssid->key_mgmt == DEFAULT_KEY_MGMT)
609
 
                return;
610
 
 
611
 
        value = wpa_config_get(ssid, "key_mgmt");
612
 
        if (value == NULL)
613
 
                return;
614
 
        if (value[0])
615
 
                wpa_config_write_reg_string(hk, "key_mgmt", value);
616
 
        os_free(value);
617
 
}
618
 
 
619
 
 
620
 
static void write_pairwise(HKEY hk, struct wpa_ssid *ssid)
621
 
{
622
 
        char *value;
623
 
 
624
 
        if (ssid->pairwise_cipher == DEFAULT_PAIRWISE)
625
 
                return;
626
 
 
627
 
        value = wpa_config_get(ssid, "pairwise");
628
 
        if (value == NULL)
629
 
                return;
630
 
        if (value[0])
631
 
                wpa_config_write_reg_string(hk, "pairwise", value);
632
 
        os_free(value);
633
 
}
634
 
 
635
 
 
636
 
static void write_group(HKEY hk, struct wpa_ssid *ssid)
637
 
{
638
 
        char *value;
639
 
 
640
 
        if (ssid->group_cipher == DEFAULT_GROUP)
641
 
                return;
642
 
 
643
 
        value = wpa_config_get(ssid, "group");
644
 
        if (value == NULL)
645
 
                return;
646
 
        if (value[0])
647
 
                wpa_config_write_reg_string(hk, "group", value);
648
 
        os_free(value);
649
 
}
650
 
 
651
 
 
652
 
static void write_auth_alg(HKEY hk, struct wpa_ssid *ssid)
653
 
{
654
 
        char *value;
655
 
 
656
 
        if (ssid->auth_alg == 0)
657
 
                return;
658
 
 
659
 
        value = wpa_config_get(ssid, "auth_alg");
660
 
        if (value == NULL)
661
 
                return;
662
 
        if (value[0])
663
 
                wpa_config_write_reg_string(hk, "auth_alg", value);
664
 
        os_free(value);
665
 
}
666
 
 
667
 
 
668
 
#ifdef IEEE8021X_EAPOL
669
 
static void write_eap(HKEY hk, struct wpa_ssid *ssid)
670
 
{
671
 
        char *value;
672
 
 
673
 
        value = wpa_config_get(ssid, "eap");
674
 
        if (value == NULL)
675
 
                return;
676
 
 
677
 
        if (value[0])
678
 
                wpa_config_write_reg_string(hk, "eap", value);
679
 
        os_free(value);
680
 
}
681
 
#endif /* IEEE8021X_EAPOL */
682
 
 
683
 
 
684
 
static void write_wep_key(HKEY hk, int idx, struct wpa_ssid *ssid)
685
 
{
686
 
        char field[20], *value;
687
 
 
688
 
        os_snprintf(field, sizeof(field), "wep_key%d", idx);
689
 
        value = wpa_config_get(ssid, field);
690
 
        if (value) {
691
 
                wpa_config_write_reg_string(hk, field, value);
692
 
                os_free(value);
693
 
        }
694
 
}
695
 
 
696
 
 
697
 
static int wpa_config_write_network(HKEY hk, struct wpa_ssid *ssid, int id)
698
 
{
699
 
        int i, errors = 0;
700
 
        HKEY nhk, netw;
701
 
        LONG ret;
702
 
        TCHAR name[5];
703
 
 
704
 
        ret = RegOpenKeyEx(hk, TEXT("networks"), 0, KEY_CREATE_SUB_KEY, &nhk);
705
 
        if (ret != ERROR_SUCCESS) {
706
 
                wpa_printf(MSG_DEBUG, "WINREG: Could not open networks key "
707
 
                           "for subkey addition: error 0x%x (%d)",
708
 
                           (unsigned int) ret, (int) GetLastError());
709
 
                return 0;
710
 
        }
711
 
 
712
 
#ifdef UNICODE
713
 
        wsprintf(name, L"%04d", id);
714
 
#else /* UNICODE */
715
 
        os_snprintf(name, sizeof(name), "%04d", id);
716
 
#endif /* UNICODE */
717
 
        ret = RegCreateKeyEx(nhk, name, 0, NULL, 0, KEY_WRITE, NULL, &netw,
718
 
                             NULL);
719
 
        RegCloseKey(nhk);
720
 
        if (ret != ERROR_SUCCESS) {
721
 
                wpa_printf(MSG_DEBUG, "WINREG: Could not add network key '%s':"
722
 
                           " error 0x%x (%d)",
723
 
                           name, (unsigned int) ret, (int) GetLastError());
724
 
                return -1;
725
 
        }
726
 
 
727
 
#define STR(t) write_str(netw, #t, ssid)
728
 
#define INT(t) write_int(netw, #t, ssid->t, 0)
729
 
#define INT_DEF(t, def) write_int(netw, #t, ssid->t, def)
730
 
 
731
 
        STR(ssid);
732
 
        INT(scan_ssid);
733
 
        write_bssid(netw, ssid);
734
 
        write_psk(netw, ssid);
735
 
        write_proto(netw, ssid);
736
 
        write_key_mgmt(netw, ssid);
737
 
        write_pairwise(netw, ssid);
738
 
        write_group(netw, ssid);
739
 
        write_auth_alg(netw, ssid);
740
 
#ifdef IEEE8021X_EAPOL
741
 
        write_eap(netw, ssid);
742
 
        STR(identity);
743
 
        STR(anonymous_identity);
744
 
        STR(eappsk);
745
 
        STR(nai);
746
 
        STR(password);
747
 
        STR(ca_cert);
748
 
        STR(ca_path);
749
 
        STR(client_cert);
750
 
        STR(private_key);
751
 
        STR(private_key_passwd);
752
 
        STR(dh_file);
753
 
        STR(subject_match);
754
 
        STR(altsubject_match);
755
 
        STR(ca_cert2);
756
 
        STR(ca_path2);
757
 
        STR(client_cert2);
758
 
        STR(private_key2);
759
 
        STR(private_key2_passwd);
760
 
        STR(dh_file2);
761
 
        STR(subject_match2);
762
 
        STR(altsubject_match2);
763
 
        STR(phase1);
764
 
        STR(phase2);
765
 
        STR(pcsc);
766
 
        STR(pin);
767
 
        STR(engine_id);
768
 
        STR(key_id);
769
 
        INT(engine);
770
 
        INT_DEF(eapol_flags, DEFAULT_EAPOL_FLAGS);
771
 
#endif /* IEEE8021X_EAPOL */
772
 
        for (i = 0; i < 4; i++)
773
 
                write_wep_key(netw, i, ssid);
774
 
        INT(wep_tx_keyidx);
775
 
        INT(priority);
776
 
#ifdef IEEE8021X_EAPOL
777
 
        INT_DEF(eap_workaround, DEFAULT_EAP_WORKAROUND);
778
 
        STR(pac_file);
779
 
        INT_DEF(fragment_size, DEFAULT_FRAGMENT_SIZE);
780
 
#endif /* IEEE8021X_EAPOL */
781
 
        INT(mode);
782
 
        INT(proactive_key_caching);
783
 
        INT(disabled);
784
 
        INT(peerkey);
785
 
#ifdef CONFIG_IEEE80211W
786
 
        INT(ieee80211w);
787
 
#endif /* CONFIG_IEEE80211W */
788
 
        STR(id_str);
789
 
 
790
 
#undef STR
791
 
#undef INT
792
 
#undef INT_DEF
793
 
 
794
 
        RegCloseKey(netw);
795
 
 
796
 
        return errors ? -1 : 0;
797
 
}
798
 
 
799
 
 
800
 
static int wpa_config_write_blob(HKEY hk, struct wpa_config_blob *blob)
801
 
{
802
 
        HKEY bhk;
803
 
        LONG ret;
804
 
        TCHAR *name;
805
 
 
806
 
        ret = RegCreateKeyEx(hk, TEXT("blobs"), 0, NULL, 0, KEY_WRITE, NULL,
807
 
                             &bhk, NULL);
808
 
        if (ret != ERROR_SUCCESS) {
809
 
                wpa_printf(MSG_DEBUG, "WINREG: Could not add blobs key: "
810
 
                           "error 0x%x (%d)",
811
 
                           (unsigned int) ret, (int) GetLastError());
812
 
                return -1;
813
 
        }
814
 
 
815
 
        name = wpa_strdup_tchar(blob->name);
816
 
        ret = RegSetValueEx(bhk, name, 0, REG_BINARY, blob->data,
817
 
                            blob->len);
818
 
        if (ret != ERROR_SUCCESS) {
819
 
                wpa_printf(MSG_ERROR, "WINREG: Failed to set blob %s': "
820
 
                           "error 0x%x (%d)", blob->name, (unsigned int) ret,
821
 
                           (int) GetLastError());
822
 
                RegCloseKey(bhk);
823
 
                os_free(name);
824
 
                return -1;
825
 
        }
826
 
        os_free(name);
827
 
 
828
 
        RegCloseKey(bhk);
829
 
 
830
 
        return 0;
831
 
}
832
 
 
833
 
 
834
 
int wpa_config_write(const char *name, struct wpa_config *config)
835
 
{
836
 
        TCHAR buf[256];
837
 
        HKEY hk;
838
 
        LONG ret;
839
 
        int errors = 0;
840
 
        struct wpa_ssid *ssid;
841
 
        struct wpa_config_blob *blob;
842
 
        int id;
843
 
 
844
 
        wpa_printf(MSG_DEBUG, "Writing configuration file '%s'", name);
845
 
 
846
 
#ifdef UNICODE
847
 
        _snwprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%S"), name);
848
 
#else /* UNICODE */
849
 
        os_snprintf(buf, 256, WPA_KEY_PREFIX TEXT("\\configs\\%s"), name);
850
 
#endif /* UNICODE */
851
 
 
852
 
        ret = RegOpenKeyEx(WPA_KEY_ROOT, buf, 0, KEY_SET_VALUE | DELETE, &hk);
853
 
        if (ret != ERROR_SUCCESS) {
854
 
                wpa_printf(MSG_ERROR, "Could not open wpa_supplicant "
855
 
                           "configuration registry %s: error %d", buf,
856
 
                           (int) GetLastError());
857
 
                return -1;
858
 
        }
859
 
 
860
 
        if (wpa_config_write_global(config, hk)) {
861
 
                wpa_printf(MSG_ERROR, "Failed to write global configuration "
862
 
                           "data");
863
 
                errors++;
864
 
        }
865
 
 
866
 
        wpa_config_delete_subkeys(hk, TEXT("networks"));
867
 
        for (ssid = config->ssid, id = 0; ssid; ssid = ssid->next, id++) {
868
 
                if (wpa_config_write_network(hk, ssid, id))
869
 
                        errors++;
870
 
        }
871
 
 
872
 
        RegDeleteKey(hk, TEXT("blobs"));
873
 
        for (blob = config->blobs; blob; blob = blob->next) {
874
 
                if (wpa_config_write_blob(hk, blob))
875
 
                        errors++;
876
 
        }
877
 
 
878
 
        RegCloseKey(hk);
879
 
 
880
 
        wpa_printf(MSG_DEBUG, "Configuration '%s' written %ssuccessfully",
881
 
                   name, errors ? "un" : "");
882
 
        return errors ? -1 : 0;
883
 
}