~ubuntu-branches/ubuntu/vivid/wpasupplicant/vivid

« back to all changes in this revision

Viewing changes to wpa_supplicant/config_winreg.c

  • Committer: Bazaar Package Importer
  • Author(s): Kel Modderman
  • Date: 2008-03-12 20:03:04 UTC
  • mfrom: (1.1.10 upstream)
  • mto: This revision was merged to the branch mainline in revision 4.
  • Revision ID: james.westby@ubuntu.com-20080312200304-4331y9wj46pdd34z
Tags: 0.6.3-1
* New upstream release.
* Drop patches applied upstream:
  - debian/patches/30_wpa_gui_qt4_eventhistoryui_rework.patch
  - debian/patches/31_wpa_gui_qt4_eventhistory_always_scrollbar.patch
  - debian/patches/32_wpa_gui_qt4_eventhistory_scroll_with_events.patch
  - debian/patches/40_dbus_ssid_data.patch
* Tidy up the clean target of debian/rules. Now that the madwifi headers are
  handled differently we no longer need to do any cleanup.
* Fix formatting error in debian/ifupdown/wpa_action.8 to make lintian
  quieter.
* Add patch to fix formatting errors in manpages build from sgml source. Use
  <emphasis> tags to hightlight keywords instead of surrounding them in
  strong quotes.
  - debian/patches/41_manpage_format_fixes.patch
* wpasupplicant binary package no longer suggests pcscd, guessnet, iproute
  or wireless-tools, nor does it recommend dhcp3-client. These are not
  needed.
* Add debian/patches/10_silence_siocsiwauth_icotl_failure.patch to disable
  ioctl failure messages that occur under normal conditions.
* Cherry pick two upstream git commits concerning the dbus interface:
  - debian/patches/11_avoid_dbus_version_namespace.patch
  - debian/patches/12_fix_potential_use_after_free.patch
* Add debian/patches/42_manpage_explain_available_drivers.patch to explain
  that not all of the driver backends are available in the provided
  wpa_supplicant binary, and that the canonical list of supported driver
  backends can be retrieved from the wpa_supplicant -h (help) output.
  (Closes: #466910)
* Add debian/patches/20_wpa_gui_qt4_disable_link_prl.patch to remove
  link_prl CONFIG compile flag added by qmake-qt4 >= 4.3.4-2 to avoid excess
  linking.

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 INTe(t) write_int(netw, #t, ssid->eap.t, 0)
 
730
#define INT_DEF(t, def) write_int(netw, #t, ssid->t, def)
 
731
#define INT_DEFe(t, def) write_int(netw, #t, ssid->eap.t, def)
 
732
 
 
733
        STR(ssid);
 
734
        INT(scan_ssid);
 
735
        write_bssid(netw, ssid);
 
736
        write_psk(netw, ssid);
 
737
        write_proto(netw, ssid);
 
738
        write_key_mgmt(netw, ssid);
 
739
        write_pairwise(netw, ssid);
 
740
        write_group(netw, ssid);
 
741
        write_auth_alg(netw, ssid);
 
742
#ifdef IEEE8021X_EAPOL
 
743
        write_eap(netw, ssid);
 
744
        STR(identity);
 
745
        STR(anonymous_identity);
 
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
        INTe(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_DEFe(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
}