~ubuntu-branches/ubuntu/saucy/wpasupplicant/saucy

« back to all changes in this revision

Viewing changes to src/wps/wps_registrar.c

  • Committer: Bazaar Package Importer
  • Author(s): Mathieu Trudel-Lapierre
  • Date: 2010-11-22 09:43:43 UTC
  • mfrom: (1.1.16 upstream)
  • Revision ID: james.westby@ubuntu.com-20101122094343-qgsxaojvmswfri77
Tags: 0.7.3-0ubuntu1
* Get wpasupplicant 0.7.3 from Debian's SVN. Leaving 0.7.3-1 as unreleased
  for now.
* Build-Depend on debhelper 8, since the packaging from Debian uses compat 8.

Show diffs side-by-side

added added

removed removed

Lines of Context:
1
1
/*
2
2
 * Wi-Fi Protected Setup - Registrar
3
 
 * Copyright (c) 2008, Jouni Malinen <j@w1.fi>
 
3
 * Copyright (c) 2008-2009, Jouni Malinen <j@w1.fi>
4
4
 *
5
5
 * This program is free software; you can redistribute it and/or modify
6
6
 * it under the terms of the GNU General Public License version 2 as
12
12
 * See README and COPYING for more details.
13
13
 */
14
14
 
15
 
#include "includes.h"
 
15
#include "utils/includes.h"
16
16
 
17
 
#include "common.h"
18
 
#include "sha256.h"
19
 
#include "base64.h"
20
 
#include "ieee802_11_defs.h"
21
 
#include "eloop.h"
 
17
#include "utils/common.h"
 
18
#include "utils/base64.h"
 
19
#include "utils/eloop.h"
 
20
#include "utils/uuid.h"
 
21
#include "utils/list.h"
 
22
#include "crypto/crypto.h"
 
23
#include "crypto/sha256.h"
 
24
#include "common/ieee802_11_defs.h"
22
25
#include "wps_i.h"
23
26
#include "wps_dev_attr.h"
24
27
#include "wps_upnp.h"
 
28
#include "wps_upnp_i.h"
25
29
 
26
30
#define WPS_WORKAROUNDS
27
31
 
28
32
struct wps_uuid_pin {
29
 
        struct wps_uuid_pin *next;
 
33
        struct dl_list list;
30
34
        u8 uuid[WPS_UUID_LEN];
31
35
        int wildcard_uuid;
32
36
        u8 *pin;
45
49
}
46
50
 
47
51
 
48
 
static void wps_free_pins(struct wps_uuid_pin *pins)
 
52
static void wps_remove_pin(struct wps_uuid_pin *pin)
 
53
{
 
54
        dl_list_del(&pin->list);
 
55
        wps_free_pin(pin);
 
56
}
 
57
 
 
58
 
 
59
static void wps_free_pins(struct dl_list *pins)
49
60
{
50
61
        struct wps_uuid_pin *pin, *prev;
51
 
 
52
 
        pin = pins;
53
 
        while (pin) {
54
 
                prev = pin;
55
 
                pin = pin->next;
56
 
                wps_free_pin(prev);
57
 
        }
 
62
        dl_list_for_each_safe(pin, prev, pins, struct wps_uuid_pin, list)
 
63
                wps_remove_pin(pin);
58
64
}
59
65
 
60
66
 
78
84
}
79
85
 
80
86
 
 
87
struct wps_registrar_device {
 
88
        struct wps_registrar_device *next;
 
89
        struct wps_device_data dev;
 
90
        u8 uuid[WPS_UUID_LEN];
 
91
};
 
92
 
 
93
 
81
94
struct wps_registrar {
82
95
        struct wps_context *wps;
83
96
 
86
99
 
87
100
        int (*new_psk_cb)(void *ctx, const u8 *mac_addr, const u8 *psk,
88
101
                          size_t psk_len);
89
 
        int (*set_ie_cb)(void *ctx, const u8 *beacon_ie, size_t beacon_ie_len,
90
 
                         const u8 *probe_resp_ie, size_t probe_resp_ie_len);
 
102
        int (*set_ie_cb)(void *ctx, struct wpabuf *beacon_ie,
 
103
                         struct wpabuf *probe_resp_ie);
91
104
        void (*pin_needed_cb)(void *ctx, const u8 *uuid_e,
92
105
                              const struct wps_device_data *dev);
93
106
        void (*reg_success_cb)(void *ctx, const u8 *mac_addr,
94
107
                               const u8 *uuid_e);
 
108
        void (*set_sel_reg_cb)(void *ctx, int sel_reg, u16 dev_passwd_id,
 
109
                               u16 sel_reg_config_methods);
 
110
        void (*enrollee_seen_cb)(void *ctx, const u8 *addr, const u8 *uuid_e,
 
111
                                 const u8 *pri_dev_type, u16 config_methods,
 
112
                                 u16 dev_password_id, u8 request_type,
 
113
                                 const char *dev_name);
95
114
        void *cb_ctx;
96
115
 
97
 
        struct wps_uuid_pin *pins;
 
116
        struct dl_list pins;
98
117
        struct wps_pbc_session *pbc_sessions;
99
118
 
100
119
        int skip_cred_build;
101
120
        struct wpabuf *extra_cred;
102
121
        int disable_auto_conf;
 
122
        int sel_reg_union;
103
123
        int sel_reg_dev_password_id_override;
104
124
        int sel_reg_config_methods_override;
105
125
        int static_wep_only;
106
126
 
 
127
        struct wps_registrar_device *devices;
 
128
 
107
129
        int force_pbc_overlap;
108
130
};
109
131
 
114
136
                                               void *timeout_ctx);
115
137
 
116
138
 
 
139
static void wps_free_devices(struct wps_registrar_device *dev)
 
140
{
 
141
        struct wps_registrar_device *prev;
 
142
 
 
143
        while (dev) {
 
144
                prev = dev;
 
145
                dev = dev->next;
 
146
                wps_device_data_free(&prev->dev);
 
147
                os_free(prev);
 
148
        }
 
149
}
 
150
 
 
151
 
 
152
static struct wps_registrar_device * wps_device_get(struct wps_registrar *reg,
 
153
                                                    const u8 *addr)
 
154
{
 
155
        struct wps_registrar_device *dev;
 
156
 
 
157
        for (dev = reg->devices; dev; dev = dev->next) {
 
158
                if (os_memcmp(dev->dev.mac_addr, addr, ETH_ALEN) == 0)
 
159
                        return dev;
 
160
        }
 
161
        return NULL;
 
162
}
 
163
 
 
164
 
 
165
static void wps_device_clone_data(struct wps_device_data *dst,
 
166
                                  struct wps_device_data *src)
 
167
{
 
168
        os_memcpy(dst->mac_addr, src->mac_addr, ETH_ALEN);
 
169
        os_memcpy(dst->pri_dev_type, src->pri_dev_type, WPS_DEV_TYPE_LEN);
 
170
 
 
171
#define WPS_STRDUP(n) \
 
172
        os_free(dst->n); \
 
173
        dst->n = src->n ? os_strdup(src->n) : NULL
 
174
 
 
175
        WPS_STRDUP(device_name);
 
176
        WPS_STRDUP(manufacturer);
 
177
        WPS_STRDUP(model_name);
 
178
        WPS_STRDUP(model_number);
 
179
        WPS_STRDUP(serial_number);
 
180
#undef WPS_STRDUP
 
181
}
 
182
 
 
183
 
 
184
int wps_device_store(struct wps_registrar *reg,
 
185
                     struct wps_device_data *dev, const u8 *uuid)
 
186
{
 
187
        struct wps_registrar_device *d;
 
188
 
 
189
        d = wps_device_get(reg, dev->mac_addr);
 
190
        if (d == NULL) {
 
191
                d = os_zalloc(sizeof(*d));
 
192
                if (d == NULL)
 
193
                        return -1;
 
194
                d->next = reg->devices;
 
195
                reg->devices = d;
 
196
        }
 
197
 
 
198
        wps_device_clone_data(&d->dev, dev);
 
199
        os_memcpy(d->uuid, uuid, WPS_UUID_LEN);
 
200
 
 
201
        return 0;
 
202
}
 
203
 
 
204
 
117
205
static void wps_registrar_add_pbc_session(struct wps_registrar *reg,
118
206
                                          const u8 *addr, const u8 *uuid_e)
119
207
{
264
352
static int wps_build_selected_registrar(struct wps_registrar *reg,
265
353
                                        struct wpabuf *msg)
266
354
{
267
 
        if (!reg->selected_registrar)
 
355
        if (!reg->sel_reg_union)
268
356
                return 0;
269
357
        wpa_printf(MSG_DEBUG, "WPS:  * Selected Registrar");
270
358
        wpabuf_put_be16(msg, ATTR_SELECTED_REGISTRAR);
278
366
                                             struct wpabuf *msg)
279
367
{
280
368
        u16 id = reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT;
281
 
        if (!reg->selected_registrar)
 
369
        if (!reg->sel_reg_union)
282
370
                return 0;
283
371
        if (reg->sel_reg_dev_password_id_override >= 0)
284
372
                id = reg->sel_reg_dev_password_id_override;
294
382
                                            struct wpabuf *msg)
295
383
{
296
384
        u16 methods;
297
 
        if (!reg->selected_registrar)
 
385
        if (!reg->sel_reg_union)
298
386
                return 0;
299
387
        methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
300
388
        if (reg->pbc)
314
402
                                          struct wpabuf *msg)
315
403
{
316
404
        u16 methods;
317
 
        methods = 0;
 
405
        /*
 
406
         * These are the methods that the AP supports as an Enrollee for adding
 
407
         * external Registrars.
 
408
         */
 
409
        methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
318
410
        wpa_printf(MSG_DEBUG, "WPS:  * Config Methods (%x)", methods);
319
411
        wpabuf_put_be16(msg, ATTR_CONFIG_METHODS);
320
412
        wpabuf_put_be16(msg, 2);
334
426
}
335
427
 
336
428
 
337
 
static int wps_build_resp_type(struct wps_registrar *reg, struct wpabuf *msg)
338
 
{
339
 
        u8 resp = reg->wps->ap ? WPS_RESP_AP : WPS_RESP_REGISTRAR;
340
 
        wpa_printf(MSG_DEBUG, "WPS:  * Response Type (%d)", resp);
341
 
        wpabuf_put_be16(msg, ATTR_RESPONSE_TYPE);
342
 
        wpabuf_put_be16(msg, 1);
343
 
        wpabuf_put_u8(msg, resp);
344
 
        return 0;
345
 
}
346
 
 
347
 
 
348
429
/**
349
430
 * wps_registrar_init - Initialize WPS Registrar data
350
431
 * @wps: Pointer to longterm WPS context
365
446
        if (reg == NULL)
366
447
                return NULL;
367
448
 
 
449
        dl_list_init(&reg->pins);
368
450
        reg->wps = wps;
369
451
        reg->new_psk_cb = cfg->new_psk_cb;
370
452
        reg->set_ie_cb = cfg->set_ie_cb;
371
453
        reg->pin_needed_cb = cfg->pin_needed_cb;
372
454
        reg->reg_success_cb = cfg->reg_success_cb;
 
455
        reg->set_sel_reg_cb = cfg->set_sel_reg_cb;
 
456
        reg->enrollee_seen_cb = cfg->enrollee_seen_cb;
373
457
        reg->cb_ctx = cfg->cb_ctx;
374
458
        reg->skip_cred_build = cfg->skip_cred_build;
375
459
        if (cfg->extra_cred) {
404
488
                return;
405
489
        eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
406
490
        eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
407
 
        wps_free_pins(reg->pins);
 
491
        wps_free_pins(&reg->pins);
408
492
        wps_free_pbc_sessions(reg->pbc_sessions);
409
493
        wpabuf_free(reg->extra_cred);
 
494
        wps_free_devices(reg->devices);
410
495
        os_free(reg);
411
496
}
412
497
 
446
531
                p->expiration.sec += timeout;
447
532
        }
448
533
 
449
 
        p->next = reg->pins;
450
 
        reg->pins = p;
 
534
        dl_list_add(&reg->pins, &p->list);
451
535
 
452
536
        wpa_printf(MSG_DEBUG, "WPS: A new PIN configured (timeout=%d)",
453
537
                   timeout);
455
539
        wpa_hexdump_ascii_key(MSG_DEBUG, "WPS: PIN", pin, pin_len);
456
540
        reg->selected_registrar = 1;
457
541
        reg->pbc = 0;
458
 
        wps_set_ie(reg);
 
542
        wps_registrar_selected_registrar_changed(reg);
459
543
        eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
460
544
        eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
461
545
                               wps_registrar_set_selected_timeout,
467
551
 
468
552
static void wps_registrar_expire_pins(struct wps_registrar *reg)
469
553
{
470
 
        struct wps_uuid_pin *pin, *prev, *del;
 
554
        struct wps_uuid_pin *pin, *prev;
471
555
        struct os_time now;
472
556
 
473
557
        os_get_time(&now);
474
 
        prev = NULL;
475
 
        pin = reg->pins;
476
 
        while (pin) {
 
558
        dl_list_for_each_safe(pin, prev, &reg->pins, struct wps_uuid_pin, list)
 
559
        {
477
560
                if ((pin->flags & PIN_EXPIRES) &&
478
561
                    os_time_before(&pin->expiration, &now)) {
479
 
                        if (prev == NULL)
480
 
                                reg->pins = pin->next;
481
 
                        else
482
 
                                prev->next = pin->next;
483
 
                        del = pin;
484
 
                        pin = pin->next;
485
562
                        wpa_hexdump(MSG_DEBUG, "WPS: Expired PIN for UUID",
486
 
                                    del->uuid, WPS_UUID_LEN);
487
 
                        wps_free_pin(del);
488
 
                        continue;
 
563
                                    pin->uuid, WPS_UUID_LEN);
 
564
                        wps_remove_pin(pin);
489
565
                }
490
 
                prev = pin;
491
 
                pin = pin->next;
492
566
        }
493
567
}
494
568
 
503
577
{
504
578
        struct wps_uuid_pin *pin, *prev;
505
579
 
506
 
        prev = NULL;
507
 
        pin = reg->pins;
508
 
        while (pin) {
 
580
        dl_list_for_each_safe(pin, prev, &reg->pins, struct wps_uuid_pin, list)
 
581
        {
509
582
                if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
510
 
                        if (prev == NULL)
511
 
                                reg->pins = pin->next;
512
 
                        else
513
 
                                prev->next = pin->next;
514
583
                        wpa_hexdump(MSG_DEBUG, "WPS: Invalidated PIN for UUID",
515
584
                                    pin->uuid, WPS_UUID_LEN);
516
 
                        wps_free_pin(pin);
 
585
                        wps_remove_pin(pin);
517
586
                        return 0;
518
587
                }
519
 
                prev = pin;
520
 
                pin = pin->next;
521
588
        }
522
589
 
523
590
        return -1;
527
594
static const u8 * wps_registrar_get_pin(struct wps_registrar *reg,
528
595
                                        const u8 *uuid, size_t *pin_len)
529
596
{
530
 
        struct wps_uuid_pin *pin;
 
597
        struct wps_uuid_pin *pin, *found = NULL;
531
598
 
532
599
        wps_registrar_expire_pins(reg);
533
600
 
534
 
        pin = reg->pins;
535
 
        while (pin) {
 
601
        dl_list_for_each(pin, &reg->pins, struct wps_uuid_pin, list) {
536
602
                if (!pin->wildcard_uuid &&
537
 
                    os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0)
 
603
                    os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
 
604
                        found = pin;
538
605
                        break;
539
 
                pin = pin->next;
 
606
                }
540
607
        }
541
608
 
542
 
        if (!pin) {
 
609
        if (!found) {
543
610
                /* Check for wildcard UUIDs since none of the UUID-specific
544
611
                 * PINs matched */
545
 
                pin = reg->pins;
546
 
                while (pin) {
 
612
                dl_list_for_each(pin, &reg->pins, struct wps_uuid_pin, list) {
547
613
                        if (pin->wildcard_uuid == 1) {
548
614
                                wpa_printf(MSG_DEBUG, "WPS: Found a wildcard "
549
615
                                           "PIN. Assigned it for this UUID-E");
550
616
                                pin->wildcard_uuid = 2;
551
617
                                os_memcpy(pin->uuid, uuid, WPS_UUID_LEN);
 
618
                                found = pin;
552
619
                                break;
553
620
                        }
554
 
                        pin = pin->next;
555
621
                }
556
622
        }
557
623
 
558
 
        if (!pin)
 
624
        if (!found)
559
625
                return NULL;
560
626
 
561
627
        /*
562
628
         * Lock the PIN to avoid attacks based on concurrent re-use of the PIN
563
629
         * that could otherwise avoid PIN invalidations.
564
630
         */
565
 
        if (pin->flags & PIN_LOCKED) {
 
631
        if (found->flags & PIN_LOCKED) {
566
632
                wpa_printf(MSG_DEBUG, "WPS: Selected PIN locked - do not "
567
633
                           "allow concurrent re-use");
568
634
                return NULL;
569
635
        }
570
 
        *pin_len = pin->pin_len;
571
 
        pin->flags |= PIN_LOCKED;
572
 
        return pin->pin;
 
636
        *pin_len = found->pin_len;
 
637
        found->flags |= PIN_LOCKED;
 
638
        return found->pin;
573
639
}
574
640
 
575
641
 
587
653
{
588
654
        struct wps_uuid_pin *pin;
589
655
 
590
 
        pin = reg->pins;
591
 
        while (pin) {
 
656
        dl_list_for_each(pin, &reg->pins, struct wps_uuid_pin, list) {
592
657
                if (os_memcmp(pin->uuid, uuid, WPS_UUID_LEN) == 0) {
593
658
                        if (pin->wildcard_uuid == 2) {
594
659
                                wpa_printf(MSG_DEBUG, "WPS: Invalidating used "
598
663
                        pin->flags &= ~PIN_LOCKED;
599
664
                        return 0;
600
665
                }
601
 
                pin = pin->next;
602
666
        }
603
667
 
604
668
        return -1;
609
673
{
610
674
        reg->selected_registrar = 0;
611
675
        reg->pbc = 0;
612
 
        wps_set_ie(reg);
 
676
        wps_registrar_selected_registrar_changed(reg);
613
677
}
614
678
 
615
679
 
644
708
        reg->force_pbc_overlap = 0;
645
709
        reg->selected_registrar = 1;
646
710
        reg->pbc = 1;
647
 
        wps_set_ie(reg);
 
711
        wps_registrar_selected_registrar_changed(reg);
648
712
 
649
713
        eloop_cancel_timeout(wps_registrar_pbc_timeout, reg, NULL);
650
714
        eloop_register_timeout(WPS_PBC_WALK_TIME, 0, wps_registrar_pbc_timeout,
660
724
        wps_registrar_stop_pbc(reg);
661
725
}
662
726
 
 
727
 
663
728
static void wps_registrar_pin_completed(struct wps_registrar *reg)
664
729
{
665
730
        wpa_printf(MSG_DEBUG, "WPS: PIN completed using internal Registrar");
666
731
        eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
667
732
        reg->selected_registrar = 0;
668
 
        wps_set_ie(reg);
 
733
        wps_registrar_selected_registrar_changed(reg);
669
734
}
670
735
 
671
736
 
683
748
                                const struct wpabuf *wps_data)
684
749
{
685
750
        struct wps_parse_attr attr;
686
 
        u16 methods;
687
751
 
688
752
        wpa_hexdump_buf(MSG_MSGDUMP,
689
753
                        "WPS: Probe Request with WPS data received",
703
767
                return;
704
768
        }
705
769
 
706
 
        methods = WPA_GET_BE16(attr.config_methods);
707
 
        if (!(methods & WPS_CONFIG_PUSHBUTTON))
 
770
        if (attr.dev_password_id == NULL) {
 
771
                wpa_printf(MSG_DEBUG, "WPS: No Device Password Id attribute "
 
772
                           "in Probe Request");
 
773
                return;
 
774
        }
 
775
 
 
776
        if (reg->enrollee_seen_cb && attr.uuid_e &&
 
777
            attr.primary_dev_type && attr.request_type) {
 
778
                char *dev_name = NULL;
 
779
                if (attr.dev_name) {
 
780
                        dev_name = os_zalloc(attr.dev_name_len + 1);
 
781
                        if (dev_name) {
 
782
                                os_memcpy(dev_name, attr.dev_name,
 
783
                                          attr.dev_name_len);
 
784
                        }
 
785
                }
 
786
                reg->enrollee_seen_cb(reg->cb_ctx, addr, attr.uuid_e,
 
787
                                      attr.primary_dev_type,
 
788
                                      WPA_GET_BE16(attr.config_methods),
 
789
                                      WPA_GET_BE16(attr.dev_password_id),
 
790
                                      *attr.request_type, dev_name);
 
791
                os_free(dev_name);
 
792
        }
 
793
 
 
794
        if (WPA_GET_BE16(attr.dev_password_id) != DEV_PW_PUSHBUTTON)
708
795
                return; /* Not PBC */
709
796
 
710
797
        wpa_printf(MSG_DEBUG, "WPS: Probe Request for PBC received from "
754
841
}
755
842
 
756
843
 
757
 
static int wps_cb_set_ie(struct wps_registrar *reg,
758
 
                         const struct wpabuf *beacon_ie,
759
 
                         const struct wpabuf *probe_resp_ie)
760
 
{
761
 
        if (reg->set_ie_cb == NULL)
762
 
                return 0;
763
 
 
764
 
        return reg->set_ie_cb(reg->cb_ctx, wpabuf_head(beacon_ie),
765
 
                              wpabuf_len(beacon_ie),
766
 
                              wpabuf_head(probe_resp_ie),
767
 
                              wpabuf_len(probe_resp_ie));
 
844
static int wps_cb_set_ie(struct wps_registrar *reg, struct wpabuf *beacon_ie,
 
845
                         struct wpabuf *probe_resp_ie)
 
846
{
 
847
        return reg->set_ie_cb(reg->cb_ctx, beacon_ie, probe_resp_ie);
 
848
}
 
849
 
 
850
 
 
851
static void wps_cb_set_sel_reg(struct wps_registrar *reg)
 
852
{
 
853
        u16 methods = 0;
 
854
        if (reg->set_sel_reg_cb == NULL)
 
855
                return;
 
856
 
 
857
        if (reg->selected_registrar) {
 
858
                methods = reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
 
859
                if (reg->pbc)
 
860
                        methods |= WPS_CONFIG_PUSHBUTTON;
 
861
        }
 
862
 
 
863
        reg->set_sel_reg_cb(reg->cb_ctx, reg->selected_registrar,
 
864
                            reg->pbc ? DEV_PW_PUSHBUTTON : DEV_PW_DEFAULT,
 
865
                            methods);
768
866
}
769
867
 
770
868
 
804
902
{
805
903
        struct wpabuf *beacon;
806
904
        struct wpabuf *probe;
807
 
        int ret;
 
905
 
 
906
        if (reg->set_ie_cb == NULL)
 
907
                return 0;
808
908
 
809
909
        wpa_printf(MSG_DEBUG, "WPS: Build Beacon and Probe Response IEs");
810
910
 
829
929
            wps_build_selected_registrar(reg, probe) ||
830
930
            wps_build_sel_reg_dev_password_id(reg, probe) ||
831
931
            wps_build_sel_reg_config_methods(reg, probe) ||
832
 
            wps_build_resp_type(reg, probe) ||
 
932
            wps_build_resp_type(probe, reg->wps->ap ? WPS_RESP_AP :
 
933
                                WPS_RESP_REGISTRAR) ||
833
934
            wps_build_uuid_e(probe, reg->wps->uuid) ||
834
935
            wps_build_device_attrs(&reg->wps->dev, probe) ||
835
936
            wps_build_probe_config_methods(reg, probe) ||
870
971
                wpabuf_put_data(probe, ms_wps, sizeof(ms_wps));
871
972
        }
872
973
 
873
 
        ret = wps_cb_set_ie(reg, beacon, probe);
874
 
        wpabuf_free(beacon);
875
 
        wpabuf_free(probe);
876
 
 
877
 
        return ret;
 
974
        return wps_cb_set_ie(reg, beacon, probe);
878
975
}
879
976
 
880
977
 
992
1089
 
993
1090
 
994
1091
static int wps_build_cred_network_idx(struct wpabuf *msg,
995
 
                                      struct wps_credential *cred)
 
1092
                                      const struct wps_credential *cred)
996
1093
{
997
1094
        wpa_printf(MSG_DEBUG, "WPS:  * Network Index");
998
1095
        wpabuf_put_be16(msg, ATTR_NETWORK_INDEX);
1003
1100
 
1004
1101
 
1005
1102
static int wps_build_cred_ssid(struct wpabuf *msg,
1006
 
                               struct wps_credential *cred)
 
1103
                               const struct wps_credential *cred)
1007
1104
{
1008
1105
        wpa_printf(MSG_DEBUG, "WPS:  * SSID");
1009
1106
        wpabuf_put_be16(msg, ATTR_SSID);
1014
1111
 
1015
1112
 
1016
1113
static int wps_build_cred_auth_type(struct wpabuf *msg,
1017
 
                                    struct wps_credential *cred)
 
1114
                                    const struct wps_credential *cred)
1018
1115
{
1019
1116
        wpa_printf(MSG_DEBUG, "WPS:  * Authentication Type (0x%x)",
1020
1117
                   cred->auth_type);
1026
1123
 
1027
1124
 
1028
1125
static int wps_build_cred_encr_type(struct wpabuf *msg,
1029
 
                                    struct wps_credential *cred)
 
1126
                                    const struct wps_credential *cred)
1030
1127
{
1031
1128
        wpa_printf(MSG_DEBUG, "WPS:  * Encryption Type (0x%x)",
1032
1129
                   cred->encr_type);
1038
1135
 
1039
1136
 
1040
1137
static int wps_build_cred_network_key(struct wpabuf *msg,
1041
 
                                      struct wps_credential *cred)
 
1138
                                      const struct wps_credential *cred)
1042
1139
{
1043
 
        wpa_printf(MSG_DEBUG, "WPS:  * Network Key");
 
1140
        wpa_printf(MSG_DEBUG, "WPS:  * Network Key (len=%d)",
 
1141
                   (int) cred->key_len);
1044
1142
        wpabuf_put_be16(msg, ATTR_NETWORK_KEY);
1045
1143
        wpabuf_put_be16(msg, cred->key_len);
1046
1144
        wpabuf_put_data(msg, cred->key, cred->key_len);
1049
1147
 
1050
1148
 
1051
1149
static int wps_build_cred_mac_addr(struct wpabuf *msg,
1052
 
                                   struct wps_credential *cred)
 
1150
                                   const struct wps_credential *cred)
1053
1151
{
1054
1152
        wpa_printf(MSG_DEBUG, "WPS:  * MAC Address (" MACSTR ")",
1055
1153
                   MAC2STR(cred->mac_addr));
1061
1159
 
1062
1160
 
1063
1161
static int wps_build_credential(struct wpabuf *msg,
1064
 
                                struct wps_credential *cred)
 
1162
                                const struct wps_credential *cred)
1065
1163
{
1066
1164
        if (wps_build_cred_network_idx(msg, cred) ||
1067
1165
            wps_build_cred_ssid(msg, cred) ||
1074
1172
}
1075
1173
 
1076
1174
 
1077
 
static int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
 
1175
int wps_build_cred(struct wps_data *wps, struct wpabuf *msg)
1078
1176
{
1079
1177
        struct wpabuf *cred;
1080
1178
 
1082
1180
                goto skip_cred_build;
1083
1181
 
1084
1182
        wpa_printf(MSG_DEBUG, "WPS:  * Credential");
 
1183
        if (wps->use_cred) {
 
1184
                os_memcpy(&wps->cred, wps->use_cred, sizeof(wps->cred));
 
1185
                goto use_provided;
 
1186
        }
1085
1187
        os_memset(&wps->cred, 0, sizeof(wps->cred));
1086
1188
 
1087
1189
        os_memcpy(wps->cred.ssid, wps->wps->ssid, wps->wps->ssid_len);
1149
1251
                                      wps->new_psk, wps->new_psk_len);
1150
1252
                os_memcpy(wps->cred.key, wps->new_psk, wps->new_psk_len);
1151
1253
                wps->cred.key_len = wps->new_psk_len;
 
1254
        } else if (wps->use_psk_key && wps->wps->psk_set) {
 
1255
                char hex[65];
 
1256
                wpa_printf(MSG_DEBUG, "WPS: Use PSK format for Network Key");
 
1257
                wpa_snprintf_hex(hex, sizeof(hex), wps->wps->psk, 32);
 
1258
                os_memcpy(wps->cred.key, hex, 32 * 2);
 
1259
                wps->cred.key_len = 32 * 2;
1152
1260
        } else if (wps->wps->network_key) {
1153
1261
                os_memcpy(wps->cred.key, wps->wps->network_key,
1154
1262
                          wps->wps->network_key_len);
1174
1282
                wps->cred.key_len = wps->new_psk_len * 2;
1175
1283
        }
1176
1284
 
 
1285
use_provided:
1177
1286
        cred = wpabuf_alloc(200);
1178
1287
        if (cred == NULL)
1179
1288
                return -1;
1246
1355
                return NULL;
1247
1356
        }
1248
1357
 
 
1358
        wps->int_reg = 1;
1249
1359
        wps->state = RECV_M3;
1250
1360
        return msg;
1251
1361
}
1379
1489
        if (wps_build_version(msg) ||
1380
1490
            wps_build_msg_type(msg, WPS_M8) ||
1381
1491
            wps_build_enrollee_nonce(wps, msg) ||
1382
 
            (wps->wps->ap && wps_build_cred(wps, plain)) ||
1383
 
            (!wps->wps->ap && wps_build_ap_settings(wps, plain)) ||
 
1492
            ((wps->wps->ap || wps->er) && wps_build_cred(wps, plain)) ||
 
1493
            (!wps->wps->ap && !wps->er && wps_build_ap_settings(wps, plain)) ||
1384
1494
            wps_build_key_wrap_auth(wps, plain) ||
1385
1495
            wps_build_encr_settings(wps, msg, plain) ||
1386
1496
            wps_build_authenticator(wps, msg)) {
1446
1556
        struct wpabuf *msg;
1447
1557
 
1448
1558
#ifdef CONFIG_WPS_UPNP
1449
 
        if (wps->wps->wps_upnp) {
 
1559
        if (!wps->int_reg && wps->wps->wps_upnp) {
1450
1560
                struct upnp_pending_message *p, *prev = NULL;
1451
1561
                if (wps->ext_reg > 1)
1452
1562
                        wps_registrar_free_pending_m2(wps->wps);
1732
1842
                return -1;
1733
1843
        }
1734
1844
 
 
1845
#ifdef CONFIG_WPS_OOB
 
1846
        if (wps->wps->oob_conf.pubkey_hash != NULL) {
 
1847
                const u8 *addr[1];
 
1848
                u8 hash[WPS_HASH_LEN];
 
1849
 
 
1850
                addr[0] = pk;
 
1851
                sha256_vector(1, addr, &pk_len, hash);
 
1852
                if (os_memcmp(hash,
 
1853
                              wpabuf_head(wps->wps->oob_conf.pubkey_hash),
 
1854
                              WPS_OOB_PUBKEY_HASH_LEN) != 0) {
 
1855
                        wpa_printf(MSG_ERROR, "WPS: Public Key hash error");
 
1856
                        return -1;
 
1857
                }
 
1858
        }
 
1859
#endif /* CONFIG_WPS_OOB */
 
1860
 
1735
1861
        wpabuf_free(wps->dh_pubkey_e);
1736
1862
        wps->dh_pubkey_e = wpabuf_alloc_copy(pk, pk_len);
1737
1863
        if (wps->dh_pubkey_e == NULL)
1847
1973
 
1848
1974
        m = WPA_GET_BE16(methods);
1849
1975
 
1850
 
        wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x", m);
 
1976
        wpa_printf(MSG_DEBUG, "WPS: Enrollee Config Methods 0x%x"
 
1977
                   "%s%s%s%s%s%s%s%s%s", m,
 
1978
                   m & WPS_CONFIG_USBA ? " [USBA]" : "",
 
1979
                   m & WPS_CONFIG_ETHERNET ? " [Ethernet]" : "",
 
1980
                   m & WPS_CONFIG_LABEL ? " [Label]" : "",
 
1981
                   m & WPS_CONFIG_DISPLAY ? " [Display]" : "",
 
1982
                   m & WPS_CONFIG_EXT_NFC_TOKEN ? " [Ext NFC Token]" : "",
 
1983
                   m & WPS_CONFIG_INT_NFC_TOKEN ? " [Int NFC Token]" : "",
 
1984
                   m & WPS_CONFIG_NFC_INTERFACE ? " [NFC]" : "",
 
1985
                   m & WPS_CONFIG_PUSHBUTTON ? " [PBC]" : "",
 
1986
                   m & WPS_CONFIG_KEYPAD ? " [Keypad]" : "");
 
1987
 
 
1988
        if (!(m & WPS_CONFIG_DISPLAY) && !wps->use_psk_key) {
 
1989
                /*
 
1990
                 * The Enrollee does not have a display so it is unlikely to be
 
1991
                 * able to show the passphrase to a user and as such, could
 
1992
                 * benefit from receiving PSK to reduce key derivation time.
 
1993
                 */
 
1994
                wpa_printf(MSG_DEBUG, "WPS: Prefer PSK format key due to "
 
1995
                           "Enrollee not supporting display");
 
1996
                wps->use_psk_key = 1;
 
1997
        }
1851
1998
 
1852
1999
        return 0;
1853
2000
}
1928
2075
            wps_process_os_version(&wps->peer_dev, attr->os_version))
1929
2076
                return WPS_FAILURE;
1930
2077
 
1931
 
        if (wps->dev_pw_id != DEV_PW_DEFAULT &&
 
2078
        if (wps->dev_pw_id < 0x10 &&
 
2079
            wps->dev_pw_id != DEV_PW_DEFAULT &&
1932
2080
            wps->dev_pw_id != DEV_PW_USER_SPECIFIED &&
1933
2081
            wps->dev_pw_id != DEV_PW_MACHINE_SPECIFIED &&
1934
2082
            wps->dev_pw_id != DEV_PW_REGISTRAR_SPECIFIED &&
1940
2088
                return WPS_CONTINUE;
1941
2089
        }
1942
2090
 
 
2091
#ifdef CONFIG_WPS_OOB
 
2092
        if (wps->dev_pw_id >= 0x10 &&
 
2093
            wps->dev_pw_id != wps->wps->oob_dev_pw_id) {
 
2094
                wpa_printf(MSG_DEBUG, "WPS: OOB Device Password ID "
 
2095
                           "%d mismatch", wps->dev_pw_id);
 
2096
                wps->state = SEND_M2D;
 
2097
                return WPS_CONTINUE;
 
2098
        }
 
2099
#endif /* CONFIG_WPS_OOB */
 
2100
 
1943
2101
        if (wps->dev_pw_id == DEV_PW_PUSHBUTTON) {
1944
2102
                if (wps->wps->registrar->force_pbc_overlap ||
1945
2103
                    wps_registrar_pbc_overlap(wps->wps->registrar,
1957
2115
                wps->pbc = 1;
1958
2116
        }
1959
2117
 
 
2118
#ifdef WPS_WORKAROUNDS
 
2119
        /*
 
2120
         * It looks like Mac OS X 10.6.3 and 10.6.4 do not like Network Key in
 
2121
         * passphrase format. To avoid interop issues, force PSK format to be
 
2122
         * used.
 
2123
         */
 
2124
        if (!wps->use_psk_key &&
 
2125
            wps->peer_dev.manufacturer &&
 
2126
            os_strncmp(wps->peer_dev.manufacturer, "Apple ", 6) == 0 &&
 
2127
            wps->peer_dev.model_name &&
 
2128
            os_strcmp(wps->peer_dev.model_name, "AirPort") == 0) {
 
2129
                wpa_printf(MSG_DEBUG, "WPS: Workaround - Force Network Key in "
 
2130
                           "PSK format");
 
2131
                wps->use_psk_key = 1;
 
2132
        }
 
2133
#endif /* WPS_WORKAROUNDS */
 
2134
 
1960
2135
        wps->state = SEND_M2;
1961
2136
        return WPS_CONTINUE;
1962
2137
}
2073
2248
}
2074
2249
 
2075
2250
 
 
2251
static void wps_cred_update(struct wps_credential *dst,
 
2252
                            struct wps_credential *src)
 
2253
{
 
2254
        os_memcpy(dst->ssid, src->ssid, sizeof(dst->ssid));
 
2255
        dst->ssid_len = src->ssid_len;
 
2256
        dst->auth_type = src->auth_type;
 
2257
        dst->encr_type = src->encr_type;
 
2258
        dst->key_idx = src->key_idx;
 
2259
        os_memcpy(dst->key, src->key, sizeof(dst->key));
 
2260
        dst->key_len = src->key_len;
 
2261
}
 
2262
 
 
2263
 
2076
2264
static int wps_process_ap_settings_r(struct wps_data *wps,
2077
2265
                                     struct wps_parse_attr *attr)
2078
2266
{
2079
 
        if (wps->wps->ap)
 
2267
        if (wps->wps->ap || wps->er)
2080
2268
                return 0;
2081
2269
 
2082
2270
        /* AP Settings Attributes in M7 when Enrollee is an AP */
2085
2273
 
2086
2274
        wpa_printf(MSG_INFO, "WPS: Received old AP configuration from AP");
2087
2275
 
2088
 
#if 0
2089
 
        /*
2090
 
         * TODO: Provide access to AP settings and allow changes before sending
2091
 
         * out M8. For now, just copy the settings unchanged into M8.
2092
 
         */
2093
 
 
2094
 
        return 0;
2095
 
#else
2096
 
        /*
2097
 
         * For now, use the AP PIN only to receive the current AP settings,
2098
 
         * not to reconfigure the AP.
2099
 
         */
2100
 
        wps_sta_cred_cb(wps);
2101
 
        return 1;
2102
 
#endif
 
2276
        if (wps->new_ap_settings) {
 
2277
                wpa_printf(MSG_INFO, "WPS: Update AP configuration based on "
 
2278
                           "new settings");
 
2279
                wps_cred_update(&wps->cred, wps->new_ap_settings);
 
2280
                return 0;
 
2281
        } else {
 
2282
                /*
 
2283
                 * Use the AP PIN only to receive the current AP settings, not
 
2284
                 * to reconfigure the AP.
 
2285
                 */
 
2286
                if (wps->ap_settings_cb) {
 
2287
                        wps->ap_settings_cb(wps->ap_settings_cb_ctx,
 
2288
                                            &wps->cred);
 
2289
                        return 1;
 
2290
                }
 
2291
                wps_sta_cred_cb(wps);
 
2292
                return 1;
 
2293
        }
2103
2294
}
2104
2295
 
2105
2296
 
2136
2327
        decrypted = wps_decrypt_encr_settings(wps, attr->encr_settings,
2137
2328
                                              attr->encr_settings_len);
2138
2329
        if (decrypted == NULL) {
2139
 
                wpa_printf(MSG_DEBUG, "WPS: Failed to decrypted Encrypted "
 
2330
                wpa_printf(MSG_DEBUG, "WPS: Failed to decrypt Encrypted "
2140
2331
                           "Settings attribute");
2141
2332
                wps->state = SEND_WSC_NACK;
2142
2333
                return WPS_CONTINUE;
2430
2621
        if (wps->wps->wps_upnp && wps->ext_reg) {
2431
2622
                wpa_printf(MSG_DEBUG, "WPS: Negotiation using external "
2432
2623
                           "Registrar completed successfully");
 
2624
                wps_device_store(wps->wps->registrar, &wps->peer_dev,
 
2625
                                 wps->uuid_e);
2433
2626
                return WPS_DONE;
2434
2627
        }
2435
2628
#endif /* CONFIG_WPS_UPNP */
2448
2641
        }
2449
2642
 
2450
2643
        wpa_printf(MSG_DEBUG, "WPS: Negotiation completed successfully");
 
2644
        wps_device_store(wps->wps->registrar, &wps->peer_dev,
 
2645
                         wps->uuid_e);
2451
2646
 
2452
2647
        if (wps->wps->wps_state == WPS_STATE_NOT_CONFIGURED && wps->new_psk &&
2453
2648
            wps->wps->ap && !wps->wps->registrar->disable_auto_conf) {
2475
2670
                wps->new_psk = NULL;
2476
2671
        }
2477
2672
 
2478
 
        if (!wps->wps->ap)
 
2673
        if (!wps->wps->ap && !wps->er)
2479
2674
                wps_sta_cred_cb(wps);
2480
2675
 
2481
2676
        if (wps->new_psk) {
2580
2775
{
2581
2776
        struct wps_registrar *reg = eloop_ctx;
2582
2777
 
2583
 
        wpa_printf(MSG_DEBUG, "WPS: SetSelectedRegistrar timed out - "
2584
 
                   "unselect Registrar");
 
2778
        wpa_printf(MSG_DEBUG, "WPS: Selected Registrar timeout - "
 
2779
                   "unselect internal Registrar");
2585
2780
        reg->selected_registrar = 0;
2586
2781
        reg->pbc = 0;
2587
 
        reg->sel_reg_dev_password_id_override = -1;
2588
 
        reg->sel_reg_config_methods_override = -1;
2589
 
        wps_set_ie(reg);
 
2782
        wps_registrar_selected_registrar_changed(reg);
 
2783
}
 
2784
 
 
2785
 
 
2786
#ifdef CONFIG_WPS_UPNP
 
2787
static void wps_registrar_sel_reg_add(struct wps_registrar *reg,
 
2788
                                      struct subscription *s)
 
2789
{
 
2790
        wpa_printf(MSG_DEBUG, "WPS: External Registrar selected (dev_pw_id=%d "
 
2791
                   "config_methods=0x%x)",
 
2792
                   s->dev_password_id, s->config_methods);
 
2793
        reg->sel_reg_union = 1;
 
2794
        if (reg->sel_reg_dev_password_id_override != DEV_PW_PUSHBUTTON)
 
2795
                reg->sel_reg_dev_password_id_override = s->dev_password_id;
 
2796
        if (reg->sel_reg_config_methods_override == -1)
 
2797
                reg->sel_reg_config_methods_override = 0;
 
2798
        reg->sel_reg_config_methods_override |= s->config_methods;
 
2799
}
 
2800
#endif /* CONFIG_WPS_UPNP */
 
2801
 
 
2802
 
 
2803
static void wps_registrar_sel_reg_union(struct wps_registrar *reg)
 
2804
{
 
2805
#ifdef CONFIG_WPS_UPNP
 
2806
        struct subscription *s;
 
2807
 
 
2808
        if (reg->wps->wps_upnp == NULL)
 
2809
                return;
 
2810
 
 
2811
        dl_list_for_each(s, &reg->wps->wps_upnp->subscriptions,
 
2812
                         struct subscription, list) {
 
2813
                struct subscr_addr *sa;
 
2814
                sa = dl_list_first(&s->addr_list, struct subscr_addr, list);
 
2815
                if (sa) {
 
2816
                        wpa_printf(MSG_DEBUG, "WPS: External Registrar %s:%d",
 
2817
                                   inet_ntoa(sa->saddr.sin_addr),
 
2818
                                   ntohs(sa->saddr.sin_port));
 
2819
                }
 
2820
                if (s->selected_registrar)
 
2821
                        wps_registrar_sel_reg_add(reg, s);
 
2822
                else
 
2823
                        wpa_printf(MSG_DEBUG, "WPS: External Registrar not "
 
2824
                                   "selected");
 
2825
        }
 
2826
#endif /* CONFIG_WPS_UPNP */
2590
2827
}
2591
2828
 
2592
2829
 
2593
2830
/**
2594
 
 * wps_registrar_set_selected_registrar - Notification of SetSelectedRegistrar
 
2831
 * wps_registrar_selected_registrar_changed - SetSelectedRegistrar change
2595
2832
 * @reg: Registrar data from wps_registrar_init()
2596
 
 * @msg: Received message from SetSelectedRegistrar
2597
 
 * Returns: 0 on success, -1 on failure
2598
2833
 *
2599
 
 * This function is called when an AP receives a SetSelectedRegistrar UPnP
2600
 
 * message.
 
2834
 * This function is called when selected registrar state changes, e.g., when an
 
2835
 * AP receives a SetSelectedRegistrar UPnP message.
2601
2836
 */
2602
 
int wps_registrar_set_selected_registrar(struct wps_registrar *reg,
2603
 
                                         const struct wpabuf *msg)
 
2837
void wps_registrar_selected_registrar_changed(struct wps_registrar *reg)
2604
2838
{
2605
 
        struct wps_parse_attr attr;
2606
 
 
2607
 
        wpa_hexdump_buf(MSG_MSGDUMP, "WPS: SetSelectedRegistrar attributes",
2608
 
                        msg);
2609
 
 
2610
 
        if (wps_parse_msg(msg, &attr) < 0)
2611
 
                return -1;
2612
 
        if (!wps_version_supported(attr.version)) {
2613
 
                wpa_printf(MSG_DEBUG, "WPS: Unsupported SetSelectedRegistrar "
2614
 
                           "version 0x%x", attr.version ? *attr.version : 0);
2615
 
                return -1;
2616
 
        }
2617
 
 
2618
 
        if (attr.selected_registrar == NULL ||
2619
 
            *attr.selected_registrar == 0) {
2620
 
                wpa_printf(MSG_DEBUG, "WPS: SetSelectedRegistrar: Disable "
2621
 
                           "Selected Registrar");
2622
 
                eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg,
2623
 
                                     NULL);
2624
 
                wps_registrar_set_selected_timeout(reg, NULL);
2625
 
                return 0;
2626
 
        }
2627
 
 
2628
 
        reg->selected_registrar = 1;
2629
 
        reg->sel_reg_dev_password_id_override = attr.dev_password_id ?
2630
 
                WPA_GET_BE16(attr.dev_password_id) : DEV_PW_DEFAULT;
2631
 
        reg->sel_reg_config_methods_override = attr.sel_reg_config_methods ?
2632
 
                WPA_GET_BE16(attr.sel_reg_config_methods) : -1;
 
2839
        wpa_printf(MSG_DEBUG, "WPS: Selected registrar information changed");
 
2840
 
 
2841
        reg->sel_reg_union = reg->selected_registrar;
 
2842
        reg->sel_reg_dev_password_id_override = -1;
 
2843
        reg->sel_reg_config_methods_override = -1;
 
2844
        if (reg->selected_registrar) {
 
2845
                reg->sel_reg_config_methods_override =
 
2846
                        reg->wps->config_methods & ~WPS_CONFIG_PUSHBUTTON;
 
2847
                if (reg->pbc) {
 
2848
                        reg->sel_reg_dev_password_id_override =
 
2849
                                DEV_PW_PUSHBUTTON;
 
2850
                        reg->sel_reg_config_methods_override |=
 
2851
                                WPS_CONFIG_PUSHBUTTON;
 
2852
                }
 
2853
                wpa_printf(MSG_DEBUG, "WPS: Internal Registrar selected "
 
2854
                           "(pbc=%d)", reg->pbc);
 
2855
        } else
 
2856
                wpa_printf(MSG_DEBUG, "WPS: Internal Registrar not selected");
 
2857
 
 
2858
        wps_registrar_sel_reg_union(reg);
 
2859
 
2633
2860
        wps_set_ie(reg);
2634
 
 
2635
 
        eloop_cancel_timeout(wps_registrar_set_selected_timeout, reg, NULL);
2636
 
        eloop_register_timeout(WPS_PBC_WALK_TIME, 0,
2637
 
                               wps_registrar_set_selected_timeout,
2638
 
                               reg, NULL);
2639
 
        return 0;
 
2861
        wps_cb_set_sel_reg(reg);
 
2862
}
 
2863
 
 
2864
 
 
2865
int wps_registrar_get_info(struct wps_registrar *reg, const u8 *addr,
 
2866
                           char *buf, size_t buflen)
 
2867
{
 
2868
        struct wps_registrar_device *d;
 
2869
        int len = 0, ret;
 
2870
        char uuid[40];
 
2871
        char devtype[WPS_DEV_TYPE_BUFSIZE];
 
2872
 
 
2873
        d = wps_device_get(reg, addr);
 
2874
        if (d == NULL)
 
2875
                return 0;
 
2876
        if (uuid_bin2str(d->uuid, uuid, sizeof(uuid)))
 
2877
                return 0;
 
2878
 
 
2879
        ret = os_snprintf(buf + len, buflen - len,
 
2880
                          "wpsUuid=%s\n"
 
2881
                          "wpsPrimaryDeviceType=%s\n"
 
2882
                          "wpsDeviceName=%s\n"
 
2883
                          "wpsManufacturer=%s\n"
 
2884
                          "wpsModelName=%s\n"
 
2885
                          "wpsModelNumber=%s\n"
 
2886
                          "wpsSerialNumber=%s\n",
 
2887
                          uuid,
 
2888
                          wps_dev_type_bin2str(d->dev.pri_dev_type, devtype,
 
2889
                                               sizeof(devtype)),
 
2890
                          d->dev.device_name ? d->dev.device_name : "",
 
2891
                          d->dev.manufacturer ? d->dev.manufacturer : "",
 
2892
                          d->dev.model_name ? d->dev.model_name : "",
 
2893
                          d->dev.model_number ? d->dev.model_number : "",
 
2894
                          d->dev.serial_number ? d->dev.serial_number : "");
 
2895
        if (ret < 0 || (size_t) ret >= buflen - len)
 
2896
                return len;
 
2897
        len += ret;
 
2898
 
 
2899
        return len;
2640
2900
}