blob: e88c6de6033bac1c0414c7080b5b4f7ec121754a [file] [log] [blame]
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001/*
2 * DPP over TCP
3 * Copyright (c) 2019-2020, The Linux Foundation
Hai Shaloma20dcd72022-02-04 13:43:00 -08004 * Copyright (c) 2021-2022, Qualcomm Innovation Center, Inc.
Hai Shalom4fbc08f2020-05-18 12:37:00 -07005 *
6 * This software may be distributed under the terms of the BSD license.
7 * See README for more details.
8 */
9
10#include "utils/includes.h"
11#include <fcntl.h>
12
13#include "utils/common.h"
14#include "utils/ip_addr.h"
15#include "utils/eloop.h"
16#include "common/ieee802_11_common.h"
17#include "common/wpa_ctrl.h"
18#include "dpp.h"
19#include "dpp_i.h"
20
21#ifdef CONFIG_DPP2
22
23struct dpp_connection {
24 struct dl_list list;
25 struct dpp_controller *ctrl;
26 struct dpp_relay_controller *relay;
27 struct dpp_global *global;
Hai Shaloma20dcd72022-02-04 13:43:00 -080028 struct dpp_pkex *pkex;
Hai Shalom4fbc08f2020-05-18 12:37:00 -070029 struct dpp_authentication *auth;
Hai Shalom899fcc72020-10-19 14:38:18 -070030 void *msg_ctx;
31 void *cb_ctx;
32 int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
Hai Shaloma20dcd72022-02-04 13:43:00 -080033 int (*pkex_done)(void *ctx, void *conn, struct dpp_bootstrap_info *bi);
34 bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070035 int sock;
36 u8 mac_addr[ETH_ALEN];
37 unsigned int freq;
38 u8 msg_len[4];
39 size_t msg_len_octets;
40 struct wpabuf *msg;
41 struct wpabuf *msg_out;
42 size_t msg_out_pos;
43 unsigned int read_eloop:1;
44 unsigned int write_eloop:1;
45 unsigned int on_tcp_tx_complete_gas_done:1;
46 unsigned int on_tcp_tx_complete_remove:1;
47 unsigned int on_tcp_tx_complete_auth_ok:1;
Hai Shalom899fcc72020-10-19 14:38:18 -070048 unsigned int gas_comeback_in_progress:1;
49 u8 gas_dialog_token;
50 char *name;
51 enum dpp_netrole netrole;
Hai Shalom4fbc08f2020-05-18 12:37:00 -070052};
53
54/* Remote Controller */
55struct dpp_relay_controller {
56 struct dl_list list;
57 struct dpp_global *global;
58 u8 pkhash[SHA256_MAC_LEN];
59 struct hostapd_ip_addr ipaddr;
Hai Shalom899fcc72020-10-19 14:38:18 -070060 void *msg_ctx;
Hai Shalom4fbc08f2020-05-18 12:37:00 -070061 void *cb_ctx;
62 void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg,
63 size_t len);
64 void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token,
65 int prot, struct wpabuf *buf);
66 struct dl_list conn; /* struct dpp_connection */
67};
68
69/* Local Controller */
70struct dpp_controller {
71 struct dpp_global *global;
72 u8 allowed_roles;
73 int qr_mutual;
74 int sock;
75 struct dl_list conn; /* struct dpp_connection */
76 char *configurator_params;
Hai Shalom899fcc72020-10-19 14:38:18 -070077 enum dpp_netrole netrole;
Hai Shaloma20dcd72022-02-04 13:43:00 -080078 struct dpp_bootstrap_info *pkex_bi;
79 char *pkex_code;
80 char *pkex_identifier;
Hai Shalom899fcc72020-10-19 14:38:18 -070081 void *msg_ctx;
82 void *cb_ctx;
83 int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
Hai Shaloma20dcd72022-02-04 13:43:00 -080084 bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070085};
86
87static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
88static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
89static void dpp_controller_auth_success(struct dpp_connection *conn,
90 int initiator);
Hai Shalom899fcc72020-10-19 14:38:18 -070091static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx);
92static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx);
Hai Shaloma20dcd72022-02-04 13:43:00 -080093static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070094
95
96static void dpp_connection_free(struct dpp_connection *conn)
97{
98 if (conn->sock >= 0) {
99 wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d",
100 conn->sock);
101 eloop_unregister_sock(conn->sock, EVENT_TYPE_READ);
102 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
103 close(conn->sock);
104 }
105 eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout,
106 conn, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -0700107 eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL);
108 eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800109 eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700110 wpabuf_free(conn->msg);
111 wpabuf_free(conn->msg_out);
112 dpp_auth_deinit(conn->auth);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800113 dpp_pkex_free(conn->pkex);
Hai Shalom899fcc72020-10-19 14:38:18 -0700114 os_free(conn->name);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700115 os_free(conn);
116}
117
118
119static void dpp_connection_remove(struct dpp_connection *conn)
120{
121 dl_list_del(&conn->list);
122 dpp_connection_free(conn);
123}
124
125
126int dpp_relay_add_controller(struct dpp_global *dpp,
127 struct dpp_relay_config *config)
128{
129 struct dpp_relay_controller *ctrl;
130
131 if (!dpp)
132 return -1;
133
134 ctrl = os_zalloc(sizeof(*ctrl));
135 if (!ctrl)
136 return -1;
137 dl_list_init(&ctrl->conn);
138 ctrl->global = dpp;
139 os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr));
140 os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700141 ctrl->msg_ctx = config->msg_ctx;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700142 ctrl->cb_ctx = config->cb_ctx;
143 ctrl->tx = config->tx;
144 ctrl->gas_resp_tx = config->gas_resp_tx;
145 dl_list_add(&dpp->controllers, &ctrl->list);
146 return 0;
147}
148
149
150static struct dpp_relay_controller *
151dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash)
152{
153 struct dpp_relay_controller *ctrl;
154
155 if (!dpp)
156 return NULL;
157
158 dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
159 list) {
160 if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0)
161 return ctrl;
162 }
163
164 return NULL;
165}
166
167
Hai Shaloma20dcd72022-02-04 13:43:00 -0800168static struct dpp_relay_controller *
169dpp_relay_controller_get_ctx(struct dpp_global *dpp, void *cb_ctx)
170{
171 struct dpp_relay_controller *ctrl;
172
173 if (!dpp)
174 return NULL;
175
176 dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
177 list) {
178 if (cb_ctx == ctrl->cb_ctx)
179 return ctrl;
180 }
181
182 return NULL;
183}
184
185
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700186static void dpp_controller_gas_done(struct dpp_connection *conn)
187{
188 struct dpp_authentication *auth = conn->auth;
Hai Shalom899fcc72020-10-19 14:38:18 -0700189
190 if (auth->waiting_csr) {
191 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
192 conn->on_tcp_tx_complete_gas_done = 0;
193 return;
194 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700195
196 if (auth->peer_version >= 2 &&
197 auth->conf_resp_status == DPP_STATUS_OK) {
198 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
199 auth->waiting_conf_result = 1;
200 return;
201 }
202
Hai Shalom899fcc72020-10-19 14:38:18 -0700203 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700204 dpp_connection_remove(conn);
205}
206
207
208static int dpp_tcp_send(struct dpp_connection *conn)
209{
210 int res;
211
212 if (!conn->msg_out) {
213 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
214 conn->write_eloop = 0;
215 return -1;
216 }
217 res = send(conn->sock,
218 wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos,
219 wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0);
220 if (res < 0) {
221 wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s",
222 strerror(errno));
223 dpp_connection_remove(conn);
224 return -1;
225 }
226
227 conn->msg_out_pos += res;
228 if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) {
229 wpa_printf(MSG_DEBUG,
230 "DPP: %u/%u bytes of message sent to Controller",
231 (unsigned int) conn->msg_out_pos,
232 (unsigned int) wpabuf_len(conn->msg_out));
233 if (!conn->write_eloop &&
234 eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
235 dpp_conn_tx_ready, conn, NULL) == 0)
236 conn->write_eloop = 1;
237 return 1;
238 }
239
240 wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP");
241 wpabuf_free(conn->msg_out);
242 conn->msg_out = NULL;
243 conn->msg_out_pos = 0;
244 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
245 conn->write_eloop = 0;
246 if (!conn->read_eloop &&
247 eloop_register_sock(conn->sock, EVENT_TYPE_READ,
248 dpp_controller_rx, conn, NULL) == 0)
249 conn->read_eloop = 1;
250 if (conn->on_tcp_tx_complete_remove) {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800251 if (conn->auth && conn->auth->connect_on_tx_status &&
252 conn->tcp_msg_sent &&
253 conn->tcp_msg_sent(conn->cb_ctx, conn->auth))
254 return 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700255 dpp_connection_remove(conn);
256 } else if (conn->auth && (conn->ctrl || conn->auth->configurator) &&
257 conn->on_tcp_tx_complete_gas_done) {
258 dpp_controller_gas_done(conn);
259 } else if (conn->on_tcp_tx_complete_auth_ok) {
260 conn->on_tcp_tx_complete_auth_ok = 0;
261 dpp_controller_auth_success(conn, 1);
262 }
263
264 return 0;
265}
266
267
268static int dpp_tcp_send_msg(struct dpp_connection *conn,
269 const struct wpabuf *msg)
270{
271 wpabuf_free(conn->msg_out);
272 conn->msg_out_pos = 0;
273 conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1);
274 if (!conn->msg_out)
275 return -1;
276 wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1);
277 wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1,
278 wpabuf_len(msg) - 1);
279
280 if (dpp_tcp_send(conn) == 1) {
281 if (!conn->write_eloop) {
282 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
283 dpp_conn_tx_ready,
284 conn, NULL) < 0)
285 return -1;
286 conn->write_eloop = 1;
287 }
288 }
289
290 return 0;
291}
292
293
294static void dpp_controller_start_gas_client(struct dpp_connection *conn)
295{
296 struct dpp_authentication *auth = conn->auth;
297 struct wpabuf *buf;
Hai Shalom899fcc72020-10-19 14:38:18 -0700298 const char *dpp_name;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700299
Hai Shalom899fcc72020-10-19 14:38:18 -0700300 dpp_name = conn->name ? conn->name : "Test";
301 buf = dpp_build_conf_req_helper(auth, dpp_name, conn->netrole, NULL,
302 NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700303 if (!buf) {
304 wpa_printf(MSG_DEBUG,
305 "DPP: No configuration request data available");
306 return;
307 }
308
309 dpp_tcp_send_msg(conn, buf);
310 wpabuf_free(buf);
311}
312
313
314static void dpp_controller_auth_success(struct dpp_connection *conn,
315 int initiator)
316{
317 struct dpp_authentication *auth = conn->auth;
318
319 if (!auth)
320 return;
321
322 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Hai Shalom899fcc72020-10-19 14:38:18 -0700323 wpa_msg(conn->msg_ctx, MSG_INFO,
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700324 DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
325#ifdef CONFIG_TESTING_OPTIONS
326 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
327 wpa_printf(MSG_INFO,
328 "DPP: TESTING - stop at Authentication Confirm");
329 if (auth->configurator) {
330 /* Prevent GAS response */
331 auth->auth_success = 0;
332 }
333 return;
334 }
335#endif /* CONFIG_TESTING_OPTIONS */
336
337 if (!auth->configurator)
338 dpp_controller_start_gas_client(conn);
339}
340
341
342static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
343{
344 struct dpp_connection *conn = eloop_ctx;
345
346 wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock);
347 dpp_tcp_send(conn);
348}
349
350
351static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen,
352 const struct hostapd_ip_addr *ipaddr,
353 int port)
354{
355 struct sockaddr_in *dst;
356#ifdef CONFIG_IPV6
357 struct sockaddr_in6 *dst6;
358#endif /* CONFIG_IPV6 */
359
360 switch (ipaddr->af) {
361 case AF_INET:
362 dst = (struct sockaddr_in *) addr;
363 os_memset(dst, 0, sizeof(*dst));
364 dst->sin_family = AF_INET;
365 dst->sin_addr.s_addr = ipaddr->u.v4.s_addr;
366 dst->sin_port = htons(port);
367 *addrlen = sizeof(*dst);
368 break;
369#ifdef CONFIG_IPV6
370 case AF_INET6:
371 dst6 = (struct sockaddr_in6 *) addr;
372 os_memset(dst6, 0, sizeof(*dst6));
373 dst6->sin6_family = AF_INET6;
374 os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6,
375 sizeof(struct in6_addr));
376 dst6->sin6_port = htons(port);
377 *addrlen = sizeof(*dst6);
378 break;
379#endif /* CONFIG_IPV6 */
380 default:
381 return -1;
382 }
383
384 return 0;
385}
386
387
Hai Shaloma20dcd72022-02-04 13:43:00 -0800388static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx)
389{
390 struct dpp_connection *conn = eloop_ctx;
391
392 wpa_printf(MSG_DEBUG,
393 "DPP: Timeout while waiting for relayed connection to complete");
394 dpp_connection_remove(conn);
395}
396
397
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700398static struct dpp_connection *
399dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src,
400 unsigned int freq)
401{
402 struct dpp_connection *conn;
403 struct sockaddr_storage addr;
404 socklen_t addrlen;
405 char txt[100];
406
407 if (dl_list_len(&ctrl->conn) >= 15) {
408 wpa_printf(MSG_DEBUG,
409 "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one");
410 return NULL;
411 }
412
413 if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen,
414 &ctrl->ipaddr, DPP_TCP_PORT) < 0)
415 return NULL;
416
417 conn = os_zalloc(sizeof(*conn));
418 if (!conn)
419 return NULL;
420
421 conn->global = ctrl->global;
422 conn->relay = ctrl;
Hai Shalom899fcc72020-10-19 14:38:18 -0700423 conn->msg_ctx = ctrl->msg_ctx;
424 conn->cb_ctx = ctrl->global->cb_ctx;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700425 os_memcpy(conn->mac_addr, src, ETH_ALEN);
426 conn->freq = freq;
427
428 conn->sock = socket(AF_INET, SOCK_STREAM, 0);
429 if (conn->sock < 0)
430 goto fail;
431 wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s",
432 conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
433
434 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
435 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
436 strerror(errno));
437 goto fail;
438 }
439
440 if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) {
441 if (errno != EINPROGRESS) {
442 wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
443 strerror(errno));
444 goto fail;
445 }
446
447 /*
448 * Continue connecting in the background; eloop will call us
449 * once the connection is ready (or failed).
450 */
451 }
452
453 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
454 dpp_conn_tx_ready, conn, NULL) < 0)
455 goto fail;
456 conn->write_eloop = 1;
457
Hai Shaloma20dcd72022-02-04 13:43:00 -0800458 eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
459 eloop_register_timeout(20, 0, dpp_relay_conn_timeout, conn, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700460
461 dl_list_add(&ctrl->conn, &conn->list);
462 return conn;
463fail:
464 dpp_connection_free(conn);
465 return NULL;
466}
467
468
469static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len)
470{
471 struct wpabuf *msg;
472
473 msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len);
474 if (!msg)
475 return NULL;
476 wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len);
477 wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
478 wpabuf_put_data(msg, hdr, DPP_HDR_LEN);
479 wpabuf_put_data(msg, buf, len);
480 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
481 return msg;
482}
483
484
485static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr,
486 const u8 *buf, size_t len)
487{
488 u8 type = hdr[DPP_HDR_LEN - 1];
489
490 wpa_printf(MSG_DEBUG,
491 "DPP: Continue already established Relay/Controller connection for this session");
492 wpabuf_free(conn->msg_out);
493 conn->msg_out_pos = 0;
494 conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
495 if (!conn->msg_out) {
496 dpp_connection_remove(conn);
497 return -1;
498 }
499
500 /* TODO: for proto ver 1, need to do remove connection based on GAS Resp
501 * TX status */
502 if (type == DPP_PA_CONFIGURATION_RESULT)
503 conn->on_tcp_tx_complete_remove = 1;
504 dpp_tcp_send(conn);
505 return 0;
506}
507
508
509int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
510 const u8 *buf, size_t len, unsigned int freq,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800511 const u8 *i_bootstrap, const u8 *r_bootstrap,
512 void *cb_ctx)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700513{
514 struct dpp_relay_controller *ctrl;
515 struct dpp_connection *conn;
516 u8 type = hdr[DPP_HDR_LEN - 1];
517
518 /* Check if there is an already started session for this peer and if so,
519 * continue that session (send this over TCP) and return 0.
520 */
521 if (type != DPP_PA_PEER_DISCOVERY_REQ &&
522 type != DPP_PA_PEER_DISCOVERY_RESP &&
523 type != DPP_PA_PRESENCE_ANNOUNCEMENT &&
524 type != DPP_PA_RECONFIG_ANNOUNCEMENT) {
525 dl_list_for_each(ctrl, &dpp->controllers,
526 struct dpp_relay_controller, list) {
527 dl_list_for_each(conn, &ctrl->conn,
528 struct dpp_connection, list) {
529 if (os_memcmp(src, conn->mac_addr,
530 ETH_ALEN) == 0)
531 return dpp_relay_tx(conn, hdr, buf, len);
532 }
533 }
534 }
535
536 if (type == DPP_PA_PRESENCE_ANNOUNCEMENT ||
537 type == DPP_PA_RECONFIG_ANNOUNCEMENT) {
538 /* TODO: Could send this to all configured Controllers. For now,
539 * only the first Controller is supported. */
Hai Shaloma20dcd72022-02-04 13:43:00 -0800540 ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
541 } else if (type == DPP_PA_PKEX_EXCHANGE_REQ) {
542 ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700543 } else {
544 if (!r_bootstrap)
545 return -1;
546 ctrl = dpp_relay_controller_get(dpp, r_bootstrap);
547 }
548 if (!ctrl)
549 return -1;
550
551 wpa_printf(MSG_DEBUG,
552 "DPP: Authentication Request for a configured Controller");
553 conn = dpp_relay_new_conn(ctrl, src, freq);
554 if (!conn)
555 return -1;
556
557 conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
558 if (!conn->msg_out) {
559 dpp_connection_remove(conn);
560 return -1;
561 }
562 /* Message will be sent in dpp_conn_tx_ready() */
563
564 return 0;
565}
566
567
568int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
569 size_t data_len)
570{
571 struct dpp_relay_controller *ctrl;
572 struct dpp_connection *conn, *found = NULL;
573 struct wpabuf *msg;
574
575 /* Check if there is a successfully completed authentication for this
576 * and if so, continue that session (send this over TCP) and return 0.
577 */
578 dl_list_for_each(ctrl, &dpp->controllers,
579 struct dpp_relay_controller, list) {
580 if (found)
581 break;
582 dl_list_for_each(conn, &ctrl->conn,
583 struct dpp_connection, list) {
584 if (os_memcmp(src, conn->mac_addr,
585 ETH_ALEN) == 0) {
586 found = conn;
587 break;
588 }
589 }
590 }
591
592 if (!found)
593 return -1;
594
595 msg = wpabuf_alloc(4 + 1 + data_len);
596 if (!msg)
597 return -1;
598 wpabuf_put_be32(msg, 1 + data_len);
599 wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ);
600 wpabuf_put_data(msg, data, data_len);
601 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
602
603 wpabuf_free(conn->msg_out);
604 conn->msg_out_pos = 0;
605 conn->msg_out = msg;
606 dpp_tcp_send(conn);
607 return 0;
608}
609
610
611static void dpp_controller_free(struct dpp_controller *ctrl)
612{
613 struct dpp_connection *conn, *tmp;
614
615 if (!ctrl)
616 return;
617
618 dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
619 list)
620 dpp_connection_remove(conn);
621
622 if (ctrl->sock >= 0) {
623 close(ctrl->sock);
624 eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
625 }
626 os_free(ctrl->configurator_params);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800627 os_free(ctrl->pkex_code);
628 os_free(ctrl->pkex_identifier);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700629 os_free(ctrl);
630}
631
632
633static int dpp_controller_rx_auth_req(struct dpp_connection *conn,
634 const u8 *hdr, const u8 *buf, size_t len)
635{
636 const u8 *r_bootstrap, *i_bootstrap;
637 u16 r_bootstrap_len, i_bootstrap_len;
638 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
639
640 if (!conn->ctrl)
641 return 0;
642
643 wpa_printf(MSG_DEBUG, "DPP: Authentication Request");
644
645 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
646 &r_bootstrap_len);
647 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
648 wpa_printf(MSG_INFO,
649 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
650 return -1;
651 }
652 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
653 r_bootstrap, r_bootstrap_len);
654
655 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
656 &i_bootstrap_len);
657 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
658 wpa_printf(MSG_INFO,
659 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
660 return -1;
661 }
662 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
663 i_bootstrap, i_bootstrap_len);
664
665 /* Try to find own and peer bootstrapping key matches based on the
666 * received hash values */
667 dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap,
668 &own_bi, &peer_bi);
669 if (!own_bi) {
670 wpa_printf(MSG_INFO,
671 "No matching own bootstrapping key found - ignore message");
672 return -1;
673 }
674
675 if (conn->auth) {
676 wpa_printf(MSG_INFO,
677 "Already in DPP authentication exchange - ignore new one");
678 return 0;
679 }
680
Hai Shalom899fcc72020-10-19 14:38:18 -0700681 conn->auth = dpp_auth_req_rx(conn->ctrl->global, conn->msg_ctx,
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700682 conn->ctrl->allowed_roles,
683 conn->ctrl->qr_mutual,
684 peer_bi, own_bi, -1, hdr, buf, len);
685 if (!conn->auth) {
686 wpa_printf(MSG_DEBUG, "DPP: No response generated");
687 return -1;
688 }
689
690 if (dpp_set_configurator(conn->auth,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800691 conn->ctrl->configurator_params) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700692 return -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700693
694 return dpp_tcp_send_msg(conn, conn->auth->resp_msg);
695}
696
697
698static int dpp_controller_rx_auth_resp(struct dpp_connection *conn,
699 const u8 *hdr, const u8 *buf, size_t len)
700{
701 struct dpp_authentication *auth = conn->auth;
702 struct wpabuf *msg;
703 int res;
704
705 if (!auth)
706 return -1;
707
708 wpa_printf(MSG_DEBUG, "DPP: Authentication Response");
709
710 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
711 if (!msg) {
712 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
713 wpa_printf(MSG_DEBUG,
714 "DPP: Start wait for full response");
Hai Shalom899fcc72020-10-19 14:38:18 -0700715 return 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700716 }
717 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700718 return -1;
719 }
720
721 conn->on_tcp_tx_complete_auth_ok = 1;
722 res = dpp_tcp_send_msg(conn, msg);
723 wpabuf_free(msg);
724 return res;
725}
726
727
728static int dpp_controller_rx_auth_conf(struct dpp_connection *conn,
729 const u8 *hdr, const u8 *buf, size_t len)
730{
731 struct dpp_authentication *auth = conn->auth;
732
733 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation");
734
735 if (!auth) {
736 wpa_printf(MSG_DEBUG,
737 "DPP: No DPP Authentication in progress - drop");
738 return -1;
739 }
740
741 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
742 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
743 return -1;
744 }
745
746 dpp_controller_auth_success(conn, 0);
747 return 0;
748}
749
750
751void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
752 void *timeout_ctx)
753{
754 struct dpp_connection *conn = eloop_ctx;
755
756 if (!conn->auth->waiting_conf_result)
757 return;
758
759 wpa_printf(MSG_DEBUG,
760 "DPP: Timeout while waiting for Connection Status Result");
Hai Shalom899fcc72020-10-19 14:38:18 -0700761 wpa_msg(conn->msg_ctx, MSG_INFO,
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700762 DPP_EVENT_CONN_STATUS_RESULT "timeout");
763 dpp_connection_remove(conn);
764}
765
766
767static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
768 const u8 *hdr, const u8 *buf,
769 size_t len)
770{
771 struct dpp_authentication *auth = conn->auth;
772 enum dpp_status_error status;
Hai Shalom899fcc72020-10-19 14:38:18 -0700773 void *msg_ctx = conn->msg_ctx;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700774
775 if (!conn->ctrl && (!auth || !auth->configurator))
776 return 0;
777
778 wpa_printf(MSG_DEBUG, "DPP: Configuration Result");
779
780 if (!auth || !auth->waiting_conf_result) {
781 wpa_printf(MSG_DEBUG,
782 "DPP: No DPP Configuration waiting for result - drop");
783 return -1;
784 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700785
786 status = dpp_conf_result_rx(auth, hdr, buf, len);
787 if (status == DPP_STATUS_OK && auth->send_conn_status) {
788 wpa_msg(msg_ctx, MSG_INFO,
789 DPP_EVENT_CONF_SENT "wait_conn_status=1");
790 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shaloma20dcd72022-02-04 13:43:00 -0800791 auth->waiting_conn_status_result = 1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700792 eloop_cancel_timeout(
793 dpp_controller_conn_status_result_wait_timeout,
794 conn, NULL);
795 eloop_register_timeout(
796 16, 0, dpp_controller_conn_status_result_wait_timeout,
797 conn, NULL);
798 return 0;
799 }
800 if (status == DPP_STATUS_OK)
801 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT);
802 else
803 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
804 return -1; /* to remove the completed connection */
805}
806
807
808static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn,
809 const u8 *hdr, const u8 *buf,
810 size_t len)
811{
812 struct dpp_authentication *auth = conn->auth;
813 enum dpp_status_error status;
814 u8 ssid[SSID_MAX_LEN];
815 size_t ssid_len = 0;
816 char *channel_list = NULL;
817
818 if (!conn->ctrl)
819 return 0;
820
821 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
822
823 if (!auth || !auth->waiting_conn_status_result) {
824 wpa_printf(MSG_DEBUG,
825 "DPP: No DPP Configuration waiting for connection status result - drop");
826 return -1;
827 }
828
829 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
830 ssid, &ssid_len, &channel_list);
Hai Shalom899fcc72020-10-19 14:38:18 -0700831 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700832 "result=%d ssid=%s channel_list=%s",
833 status, wpa_ssid_txt(ssid, ssid_len),
834 channel_list ? channel_list : "N/A");
835 os_free(channel_list);
836 return -1; /* to remove the completed connection */
837}
838
839
840static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn,
841 const u8 *hdr, const u8 *buf,
842 size_t len)
843{
844 const u8 *r_bootstrap;
845 u16 r_bootstrap_len;
846 struct dpp_bootstrap_info *peer_bi;
847 struct dpp_authentication *auth;
848 struct dpp_global *dpp = conn->ctrl->global;
849
850 if (conn->auth) {
851 wpa_printf(MSG_DEBUG,
852 "DPP: Ignore Presence Announcement during ongoing Authentication");
853 return -1;
854 }
855
856 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement");
857
858 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
859 &r_bootstrap_len);
860 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700861 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700862 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
863 return -1;
864 }
865 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
866 r_bootstrap, r_bootstrap_len);
867 peer_bi = dpp_bootstrap_find_chirp(dpp, r_bootstrap);
868 if (!peer_bi) {
869 wpa_printf(MSG_DEBUG,
870 "DPP: No matching bootstrapping information found");
871 return -1;
872 }
873
Hai Shalom899fcc72020-10-19 14:38:18 -0700874 auth = dpp_auth_init(dpp, conn->msg_ctx, peer_bi, NULL,
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700875 DPP_CAPAB_CONFIGURATOR, -1, NULL, 0);
876 if (!auth)
877 return -1;
878 if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
879 dpp_auth_deinit(auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700880 return -1;
881 }
882
883 conn->auth = auth;
884 return dpp_tcp_send_msg(conn, conn->auth->req_msg);
885}
886
887
888static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn,
889 const u8 *hdr, const u8 *buf,
890 size_t len)
891{
Hai Shalom899fcc72020-10-19 14:38:18 -0700892 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
893 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700894 struct dpp_configurator *conf;
895 struct dpp_global *dpp = conn->ctrl->global;
896 struct dpp_authentication *auth;
Hai Shalom899fcc72020-10-19 14:38:18 -0700897 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700898
899 if (conn->auth) {
900 wpa_printf(MSG_DEBUG,
901 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
902 return -1;
903 }
904
905 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement");
906
907 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
908 &csign_hash_len);
909 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700910 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700911 "Missing or invalid required Configurator C-sign key Hash attribute");
912 return -1;
913 }
914 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
915 csign_hash, csign_hash_len);
916 conf = dpp_configurator_find_kid(dpp, csign_hash);
917 if (!conf) {
918 wpa_printf(MSG_DEBUG,
919 "DPP: No matching Configurator information found");
920 return -1;
921 }
922
Hai Shalom899fcc72020-10-19 14:38:18 -0700923 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
924 &fcgroup_len);
925 if (!fcgroup || fcgroup_len != 2) {
926 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
927 "Missing or invalid required Finite Cyclic Group attribute");
928 return -1;
929 }
930 group = WPA_GET_LE16(fcgroup);
931 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
932
933 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
934 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
935
936 auth = dpp_reconfig_init(dpp, conn->msg_ctx, conf, 0, group,
937 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700938 if (!auth)
939 return -1;
940 if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
941 dpp_auth_deinit(auth);
942 return -1;
943 }
944
945 conn->auth = auth;
946 return dpp_tcp_send_msg(conn, auth->reconfig_req_msg);
947}
948
949
950static int dpp_controller_rx_reconfig_auth_resp(struct dpp_connection *conn,
951 const u8 *hdr, const u8 *buf,
952 size_t len)
953{
954 struct dpp_authentication *auth = conn->auth;
955 struct wpabuf *conf;
956 int res;
957
958 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response");
959
960 if (!auth || !auth->reconfig || !auth->configurator) {
961 wpa_printf(MSG_DEBUG,
962 "DPP: No DPP Reconfig Authentication in progress - drop");
963 return -1;
964 }
965
966 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
967 if (!conf)
968 return -1;
969
970 res = dpp_tcp_send_msg(conn, conf);
971 wpabuf_free(conf);
972 return res;
973}
974
975
Hai Shaloma20dcd72022-02-04 13:43:00 -0800976static int dpp_controller_rx_pkex_exchange_req(struct dpp_connection *conn,
977 const u8 *hdr, const u8 *buf,
978 size_t len)
979{
980 struct dpp_controller *ctrl = conn->ctrl;
981
982 if (!ctrl)
983 return 0;
984
985 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request");
986
987 /* TODO: Support multiple PKEX codes by iterating over all the enabled
988 * values here */
989
990 if (!ctrl->pkex_code || !ctrl->pkex_bi) {
991 wpa_printf(MSG_DEBUG,
992 "DPP: No PKEX code configured - ignore request");
993 return 0;
994 }
995
996 if (conn->pkex || conn->auth) {
997 wpa_printf(MSG_DEBUG,
998 "DPP: Already in PKEX/Authentication session - ignore new PKEX request");
999 return 0;
1000 }
1001
1002 conn->pkex = dpp_pkex_rx_exchange_req(conn->ctrl->global, ctrl->pkex_bi,
1003 NULL, NULL,
1004 ctrl->pkex_identifier,
1005 ctrl->pkex_code,
1006 buf, len, true);
1007 if (!conn->pkex) {
1008 wpa_printf(MSG_DEBUG,
1009 "DPP: Failed to process the request");
1010 return -1;
1011 }
1012
1013 return dpp_tcp_send_msg(conn, conn->pkex->exchange_resp);
1014}
1015
1016
1017static int dpp_controller_rx_pkex_exchange_resp(struct dpp_connection *conn,
1018 const u8 *hdr, const u8 *buf,
1019 size_t len)
1020{
1021 struct dpp_pkex *pkex = conn->pkex;
1022 struct wpabuf *msg;
1023 int res;
1024
1025 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response");
1026
1027 if (!pkex || !pkex->initiator || pkex->exchange_done) {
1028 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1029 return 0;
1030 }
1031
1032 msg = dpp_pkex_rx_exchange_resp(pkex, NULL, buf, len);
1033 if (!msg) {
1034 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1035 return -1;
1036 }
1037
1038 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request");
1039 res = dpp_tcp_send_msg(conn, msg);
1040 wpabuf_free(msg);
1041 return res;
1042}
1043
1044
1045static int dpp_controller_rx_pkex_commit_reveal_req(struct dpp_connection *conn,
1046 const u8 *hdr,
1047 const u8 *buf, size_t len)
1048{
1049 struct dpp_pkex *pkex = conn->pkex;
1050 struct wpabuf *msg;
1051 int res;
1052 struct dpp_bootstrap_info *bi;
1053
1054 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request");
1055
1056 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1057 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1058 return 0;
1059 }
1060
1061 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1062 if (!msg) {
1063 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
1064 return -1;
1065 }
1066
1067 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response");
1068 res = dpp_tcp_send_msg(conn, msg);
1069 wpabuf_free(msg);
1070 if (res < 0)
1071 return res;
1072 bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
1073 if (!bi)
1074 return -1;
1075 conn->pkex = NULL;
1076 return 0;
1077}
1078
1079
1080static int
1081dpp_controller_rx_pkex_commit_reveal_resp(struct dpp_connection *conn,
1082 const u8 *hdr,
1083 const u8 *buf, size_t len)
1084{
1085 struct dpp_pkex *pkex = conn->pkex;
1086 int res;
1087 struct dpp_bootstrap_info *bi;
1088
1089 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response");
1090
1091 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1092 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1093 return 0;
1094 }
1095
1096 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1097 if (res < 0) {
1098 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1099 return res;
1100 }
1101
1102 bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
1103 if (!bi)
1104 return -1;
1105 conn->pkex = NULL;
1106
1107 if (!conn->pkex_done)
1108 return -1;
1109 return conn->pkex_done(conn->cb_ctx, conn, bi);
1110}
1111
1112
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001113static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
1114 size_t len)
1115{
1116 const u8 *pos, *end;
1117 u8 type;
1118
1119 wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP");
1120 pos = msg;
1121 end = msg + len;
1122
1123 if (end - pos < DPP_HDR_LEN ||
1124 WPA_GET_BE24(pos) != OUI_WFA ||
1125 pos[3] != DPP_OUI_TYPE) {
1126 wpa_printf(MSG_DEBUG, "DPP: Unrecognized header");
1127 return -1;
1128 }
1129
1130 if (pos[4] != 1) {
1131 wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u",
1132 pos[4]);
1133 return -1;
1134 }
1135 type = pos[5];
1136 wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type);
1137 pos += DPP_HDR_LEN;
1138
1139 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes",
1140 pos, end - pos);
1141 if (dpp_check_attrs(pos, end - pos) < 0)
1142 return -1;
1143
1144 if (conn->relay) {
1145 wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
1146 conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr,
1147 conn->freq, msg, len);
1148 return 0;
1149 }
1150
1151 switch (type) {
1152 case DPP_PA_AUTHENTICATION_REQ:
1153 return dpp_controller_rx_auth_req(conn, msg, pos, end - pos);
1154 case DPP_PA_AUTHENTICATION_RESP:
1155 return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos);
1156 case DPP_PA_AUTHENTICATION_CONF:
1157 return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos);
1158 case DPP_PA_CONFIGURATION_RESULT:
1159 return dpp_controller_rx_conf_result(conn, msg, pos, end - pos);
1160 case DPP_PA_CONNECTION_STATUS_RESULT:
1161 return dpp_controller_rx_conn_status_result(conn, msg, pos,
1162 end - pos);
1163 case DPP_PA_PRESENCE_ANNOUNCEMENT:
1164 return dpp_controller_rx_presence_announcement(conn, msg, pos,
1165 end - pos);
1166 case DPP_PA_RECONFIG_ANNOUNCEMENT:
1167 return dpp_controller_rx_reconfig_announcement(conn, msg, pos,
1168 end - pos);
1169 case DPP_PA_RECONFIG_AUTH_RESP:
1170 return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos,
1171 end - pos);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001172 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
1173 wpa_printf(MSG_DEBUG,
1174 "DPP: Ignore PKEXv1 Exchange Request - not supported over TCP");
1175 return -1;
1176 case DPP_PA_PKEX_EXCHANGE_REQ:
1177 return dpp_controller_rx_pkex_exchange_req(conn, msg, pos,
1178 end - pos);
1179 case DPP_PA_PKEX_EXCHANGE_RESP:
1180 return dpp_controller_rx_pkex_exchange_resp(conn, msg, pos,
1181 end - pos);
1182 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1183 return dpp_controller_rx_pkex_commit_reveal_req(conn, msg, pos,
1184 end - pos);
1185 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1186 return dpp_controller_rx_pkex_commit_reveal_resp(conn, msg, pos,
1187 end - pos);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001188 default:
1189 /* TODO: missing messages types */
1190 wpa_printf(MSG_DEBUG,
1191 "DPP: Unsupported frame subtype %d", type);
1192 return -1;
1193 }
1194}
1195
1196
Hai Shalom899fcc72020-10-19 14:38:18 -07001197static int dpp_tcp_send_comeback_delay(struct dpp_connection *conn, u8 action)
1198{
1199 struct wpabuf *buf;
1200 size_t len = 18;
1201
1202 if (action == WLAN_PA_GAS_COMEBACK_RESP)
1203 len++;
1204
1205 buf = wpabuf_alloc(4 + len);
1206 if (!buf)
1207 return -1;
1208
1209 wpabuf_put_be32(buf, len);
1210
1211 wpabuf_put_u8(buf, action);
1212 wpabuf_put_u8(buf, conn->gas_dialog_token);
1213 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
1214 if (action == WLAN_PA_GAS_COMEBACK_RESP)
1215 wpabuf_put_u8(buf, 0);
1216 wpabuf_put_le16(buf, 500); /* GAS Comeback Delay */
1217
1218 dpp_write_adv_proto(buf);
1219 wpabuf_put_le16(buf, 0); /* Query Response Length */
1220
1221 /* Send Config Response over TCP */
1222 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf);
1223 wpabuf_free(conn->msg_out);
1224 conn->msg_out_pos = 0;
1225 conn->msg_out = buf;
1226 dpp_tcp_send(conn);
1227 return 0;
1228}
1229
1230
1231static int dpp_tcp_send_gas_resp(struct dpp_connection *conn, u8 action,
1232 struct wpabuf *resp)
1233{
1234 struct wpabuf *buf;
1235 size_t len;
1236
1237 if (!resp)
1238 return -1;
1239
1240 len = 18 + wpabuf_len(resp);
1241 if (action == WLAN_PA_GAS_COMEBACK_RESP)
1242 len++;
1243
1244 buf = wpabuf_alloc(4 + len);
1245 if (!buf) {
1246 wpabuf_free(resp);
1247 return -1;
1248 }
1249
1250 wpabuf_put_be32(buf, len);
1251
1252 wpabuf_put_u8(buf, action);
1253 wpabuf_put_u8(buf, conn->gas_dialog_token);
1254 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
1255 if (action == WLAN_PA_GAS_COMEBACK_RESP)
1256 wpabuf_put_u8(buf, 0);
1257 wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */
1258
1259 dpp_write_adv_proto(buf);
1260 dpp_write_gas_query(buf, resp);
1261 wpabuf_free(resp);
1262
1263 /* Send Config Response over TCP; GAS fragmentation is taken care of by
1264 * the Relay */
1265 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf);
1266 wpabuf_free(conn->msg_out);
1267 conn->msg_out_pos = 0;
1268 conn->msg_out = buf;
1269 conn->on_tcp_tx_complete_gas_done = 1;
1270 dpp_tcp_send(conn);
1271 return 0;
1272}
1273
1274
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001275static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg,
1276 size_t len)
1277{
1278 const u8 *pos, *end, *next;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001279 const u8 *adv_proto;
1280 u16 slen;
Hai Shalom899fcc72020-10-19 14:38:18 -07001281 struct wpabuf *resp;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001282 struct dpp_authentication *auth = conn->auth;
1283
1284 if (len < 1 + 2)
1285 return -1;
1286
1287 wpa_printf(MSG_DEBUG,
1288 "DPP: Received DPP Configuration Request over TCP");
1289
1290 if (!auth || (!conn->ctrl && !auth->configurator) ||
1291 (!auth->auth_success && !auth->reconfig_success)) {
1292 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1293 return -1;
1294 }
1295
1296 pos = msg;
1297 end = msg + len;
1298
Hai Shalom899fcc72020-10-19 14:38:18 -07001299 conn->gas_dialog_token = *pos++;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001300 adv_proto = pos++;
1301 slen = *pos++;
1302 if (*adv_proto != WLAN_EID_ADV_PROTO ||
1303 slen > end - pos || slen < 2)
1304 return -1;
1305
1306 next = pos + slen;
1307 pos++; /* skip QueryRespLenLimit and PAME-BI */
1308
1309 if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
1310 pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
1311 pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
1312 return -1;
1313
1314 pos = next;
1315 /* Query Request */
1316 if (end - pos < 2)
1317 return -1;
1318 slen = WPA_GET_LE16(pos);
1319 pos += 2;
1320 if (slen > end - pos)
1321 return -1;
1322
1323 resp = dpp_conf_req_rx(auth, pos, slen);
Hai Shalom899fcc72020-10-19 14:38:18 -07001324 if (!resp && auth->waiting_cert) {
1325 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
1326 conn->gas_comeback_in_progress = 1;
1327 return dpp_tcp_send_comeback_delay(conn,
1328 WLAN_PA_GAS_INITIAL_RESP);
1329 }
1330
Hai Shaloma20dcd72022-02-04 13:43:00 -08001331 if (!resp && auth->waiting_config && auth->peer_bi) {
1332 char *buf = NULL, *name = "";
1333 char band[200], *b_pos, *b_end;
1334 int i, res, *opclass = auth->e_band_support;
1335 char *mud_url = "N/A";
1336
1337 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
1338 if (auth->e_name) {
1339 size_t e_len = os_strlen(auth->e_name);
1340
1341 buf = os_malloc(e_len * 4 + 1);
1342 if (buf) {
1343 printf_encode(buf, len * 4 + 1,
1344 (const u8 *) auth->e_name, e_len);
1345 name = buf;
1346 }
1347 }
1348 band[0] = '\0';
1349 b_pos = band;
1350 b_end = band + sizeof(band);
1351 for (i = 0; opclass && opclass[i]; i++) {
1352 res = os_snprintf(b_pos, b_end - b_pos, "%s%d",
1353 b_pos == band ? "" : ",", opclass[i]);
1354 if (os_snprintf_error(b_end - b_pos, res)) {
1355 *b_pos = '\0';
1356 break;
1357 }
1358 b_pos += res;
1359 }
1360 if (auth->e_mud_url) {
1361 size_t e_len = os_strlen(auth->e_mud_url);
1362
1363 if (!has_ctrl_char((const u8 *) auth->e_mud_url, e_len))
1364 mud_url = auth->e_mud_url;
1365 }
1366 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_NEEDED
1367 "peer=%d net_role=%s name=\"%s\" opclass=%s mud_url=%s",
1368 auth->peer_bi->id, dpp_netrole_str(auth->e_netrole),
1369 name, band, mud_url);
1370 os_free(buf);
1371
1372 conn->gas_comeback_in_progress = 1;
1373 return dpp_tcp_send_comeback_delay(conn,
1374 WLAN_PA_GAS_INITIAL_RESP);
1375 }
1376
Hai Shalom899fcc72020-10-19 14:38:18 -07001377 return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_INITIAL_RESP, resp);
1378}
1379
1380
1381static int dpp_controller_rx_gas_comeback_req(struct dpp_connection *conn,
1382 const u8 *msg, size_t len)
1383{
1384 u8 dialog_token;
1385 struct dpp_authentication *auth = conn->auth;
1386 struct wpabuf *resp;
1387
1388 if (len < 1)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001389 return -1;
1390
Hai Shalom899fcc72020-10-19 14:38:18 -07001391 wpa_printf(MSG_DEBUG,
1392 "DPP: Received DPP Configuration Request over TCP (comeback)");
1393
1394 if (!auth || (!conn->ctrl && !auth->configurator) ||
1395 (!auth->auth_success && !auth->reconfig_success) ||
1396 !conn->gas_comeback_in_progress) {
1397 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001398 return -1;
1399 }
1400
Hai Shalom899fcc72020-10-19 14:38:18 -07001401 dialog_token = msg[0];
1402 if (dialog_token != conn->gas_dialog_token) {
1403 wpa_printf(MSG_DEBUG, "DPP: Dialog token mismatch (%u != %u)",
1404 dialog_token, conn->gas_dialog_token);
1405 return -1;
1406 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001407
Hai Shalom899fcc72020-10-19 14:38:18 -07001408 if (!auth->conf_resp_tcp) {
1409 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
1410 return dpp_tcp_send_comeback_delay(conn,
1411 WLAN_PA_GAS_COMEBACK_RESP);
1412 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001413
Hai Shalom899fcc72020-10-19 14:38:18 -07001414 wpa_printf(MSG_DEBUG,
1415 "DPP: Configuration response is ready to be sent out");
1416 resp = auth->conf_resp_tcp;
1417 auth->conf_resp_tcp = NULL;
1418 return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_COMEBACK_RESP, resp);
1419}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001420
Hai Shalom899fcc72020-10-19 14:38:18 -07001421
1422static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx)
1423{
1424 struct dpp_connection *conn = eloop_ctx;
1425 struct dpp_authentication *auth = conn->auth;
1426
1427 if (!auth || !auth->csrattrs)
1428 return;
1429
1430 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1431 wpabuf_free(auth->csr);
1432 /* TODO: Additional information needed for CSR based on csrAttrs */
1433 auth->csr = dpp_build_csr(auth, conn->name ? conn->name : "Test");
1434 if (!auth->csr) {
1435 dpp_connection_remove(conn);
1436 return;
1437 }
1438
1439 dpp_controller_start_gas_client(conn);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001440}
1441
1442
1443static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
1444{
1445 struct dpp_authentication *auth = conn->auth;
1446 int res;
1447 struct wpabuf *msg;
1448 enum dpp_status_error status;
1449
1450 wpa_printf(MSG_DEBUG,
1451 "DPP: Configuration Response for local stack from TCP");
1452
1453 if (auth)
1454 res = dpp_conf_resp_rx(auth, resp);
1455 else
1456 res = -1;
1457 wpabuf_free(resp);
Hai Shalom899fcc72020-10-19 14:38:18 -07001458 if (res == -2) {
1459 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1460 eloop_register_timeout(0, 0, dpp_tcp_build_csr, conn, NULL);
1461 return 0;
1462 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001463 if (res < 0) {
1464 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1465 return -1;
1466 }
1467
Hai Shalom899fcc72020-10-19 14:38:18 -07001468 if (conn->process_conf_obj)
1469 res = conn->process_conf_obj(conn->cb_ctx, auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001470 else
1471 res = 0;
1472
1473 if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK)
1474 return -1;
1475
1476 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1477 status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK;
1478 msg = dpp_build_conf_result(auth, status);
1479 if (!msg)
1480 return -1;
1481
1482 conn->on_tcp_tx_complete_remove = 1;
1483 res = dpp_tcp_send_msg(conn, msg);
1484 wpabuf_free(msg);
1485
1486 /* This exchange will be terminated in the TX status handler */
1487
1488 return res;
1489}
1490
1491
Hai Shalom899fcc72020-10-19 14:38:18 -07001492static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx)
1493{
1494 struct dpp_connection *conn = eloop_ctx;
1495 struct dpp_authentication *auth = conn->auth;
1496 struct wpabuf *msg;
1497
1498 if (!auth)
1499 return;
1500
1501 wpa_printf(MSG_DEBUG, "DPP: Send GAS Comeback Request");
1502 msg = wpabuf_alloc(4 + 2);
1503 if (!msg)
1504 return;
1505 wpabuf_put_be32(msg, 2);
1506 wpabuf_put_u8(msg, WLAN_PA_GAS_COMEBACK_REQ);
1507 wpabuf_put_u8(msg, conn->gas_dialog_token);
1508 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
1509
1510 wpabuf_free(conn->msg_out);
1511 conn->msg_out_pos = 0;
1512 conn->msg_out = msg;
1513 dpp_tcp_send(conn);
1514}
1515
1516
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001517static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg,
Hai Shalom899fcc72020-10-19 14:38:18 -07001518 size_t len, bool comeback)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001519{
1520 struct wpabuf *buf;
1521 u8 dialog_token;
1522 const u8 *pos, *end, *next, *adv_proto;
Hai Shalom899fcc72020-10-19 14:38:18 -07001523 u16 status, slen, comeback_delay;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001524
Hai Shalom60840252021-02-19 19:02:11 -08001525 if (len < (size_t) (5 + 2 + (comeback ? 1 : 0)))
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001526 return -1;
1527
1528 wpa_printf(MSG_DEBUG,
1529 "DPP: Received DPP Configuration Response over TCP");
1530
1531 pos = msg;
1532 end = msg + len;
1533
1534 dialog_token = *pos++;
1535 status = WPA_GET_LE16(pos);
1536 if (status != WLAN_STATUS_SUCCESS) {
1537 wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status);
1538 return -1;
1539 }
1540 pos += 2;
Hai Shalom899fcc72020-10-19 14:38:18 -07001541 if (comeback)
1542 pos++; /* ignore Fragment ID */
1543 comeback_delay = WPA_GET_LE16(pos);
1544 pos += 2;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001545
1546 adv_proto = pos++;
1547 slen = *pos++;
1548 if (*adv_proto != WLAN_EID_ADV_PROTO ||
1549 slen > end - pos || slen < 2)
1550 return -1;
1551
1552 next = pos + slen;
1553 pos++; /* skip QueryRespLenLimit and PAME-BI */
1554
1555 if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
1556 pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
1557 pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
1558 return -1;
1559
1560 pos = next;
1561 /* Query Response */
1562 if (end - pos < 2)
1563 return -1;
1564 slen = WPA_GET_LE16(pos);
1565 pos += 2;
1566 if (slen > end - pos)
1567 return -1;
1568
Hai Shalom899fcc72020-10-19 14:38:18 -07001569 if (comeback_delay) {
1570 unsigned int secs, usecs;
1571
1572 conn->gas_dialog_token = dialog_token;
1573 secs = (comeback_delay * 1024) / 1000000;
1574 usecs = comeback_delay * 1024 - secs * 1000000;
1575 wpa_printf(MSG_DEBUG, "DPP: Comeback delay: %u",
1576 comeback_delay);
1577 eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
1578 eloop_register_timeout(secs, usecs, dpp_tcp_gas_query_comeback,
1579 conn, NULL);
1580 return 0;
1581 }
1582
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001583 buf = wpabuf_alloc(slen);
1584 if (!buf)
1585 return -1;
1586 wpabuf_put_data(buf, pos, slen);
1587
1588 if (!conn->relay &&
1589 (!conn->ctrl || (conn->ctrl->allowed_roles & DPP_CAPAB_ENROLLEE)))
1590 return dpp_tcp_rx_gas_resp(conn, buf);
1591
1592 if (!conn->relay) {
1593 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1594 wpabuf_free(buf);
1595 return -1;
1596 }
1597 wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
1598 conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr,
1599 dialog_token, 0, buf);
1600
1601 return 0;
1602}
1603
1604
1605static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx)
1606{
1607 struct dpp_connection *conn = eloop_ctx;
1608 int res;
1609 const u8 *pos;
1610
1611 wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)",
1612 sd);
1613
1614 if (conn->msg_len_octets < 4) {
1615 u32 msglen;
1616
1617 res = recv(sd, &conn->msg_len[conn->msg_len_octets],
1618 4 - conn->msg_len_octets, 0);
1619 if (res < 0) {
1620 wpa_printf(MSG_DEBUG, "DPP: recv failed: %s",
1621 strerror(errno));
1622 dpp_connection_remove(conn);
1623 return;
1624 }
1625 if (res == 0) {
1626 wpa_printf(MSG_DEBUG,
1627 "DPP: No more data available over TCP");
1628 dpp_connection_remove(conn);
1629 return;
1630 }
1631 wpa_printf(MSG_DEBUG,
1632 "DPP: Received %d/%d octet(s) of message length field",
1633 res, (int) (4 - conn->msg_len_octets));
1634 conn->msg_len_octets += res;
1635
1636 if (conn->msg_len_octets < 4) {
1637 wpa_printf(MSG_DEBUG,
1638 "DPP: Need %d more octets of message length field",
1639 (int) (4 - conn->msg_len_octets));
1640 return;
1641 }
1642
1643 msglen = WPA_GET_BE32(conn->msg_len);
1644 wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen);
1645 if (msglen > 65535) {
1646 wpa_printf(MSG_INFO, "DPP: Unexpectedly long message");
1647 dpp_connection_remove(conn);
1648 return;
1649 }
1650
1651 wpabuf_free(conn->msg);
1652 conn->msg = wpabuf_alloc(msglen);
1653 }
1654
1655 if (!conn->msg) {
1656 wpa_printf(MSG_DEBUG,
1657 "DPP: No buffer available for receiving the message");
1658 dpp_connection_remove(conn);
1659 return;
1660 }
1661
1662 wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload",
1663 (unsigned int) wpabuf_tailroom(conn->msg));
1664
1665 res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0);
1666 if (res < 0) {
1667 wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno));
1668 dpp_connection_remove(conn);
1669 return;
1670 }
1671 if (res == 0) {
1672 wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP");
1673 dpp_connection_remove(conn);
1674 return;
1675 }
1676 wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res);
1677 wpabuf_put(conn->msg, res);
1678
1679 if (wpabuf_tailroom(conn->msg) > 0) {
1680 wpa_printf(MSG_DEBUG,
1681 "DPP: Need %u more octets of message payload",
1682 (unsigned int) wpabuf_tailroom(conn->msg));
1683 return;
1684 }
1685
1686 conn->msg_len_octets = 0;
1687 wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg);
1688 if (wpabuf_len(conn->msg) < 1) {
1689 dpp_connection_remove(conn);
1690 return;
1691 }
1692
1693 pos = wpabuf_head(conn->msg);
1694 switch (*pos) {
1695 case WLAN_PA_VENDOR_SPECIFIC:
1696 if (dpp_controller_rx_action(conn, pos + 1,
1697 wpabuf_len(conn->msg) - 1) < 0)
1698 dpp_connection_remove(conn);
1699 break;
1700 case WLAN_PA_GAS_INITIAL_REQ:
1701 if (dpp_controller_rx_gas_req(conn, pos + 1,
1702 wpabuf_len(conn->msg) - 1) < 0)
1703 dpp_connection_remove(conn);
1704 break;
1705 case WLAN_PA_GAS_INITIAL_RESP:
Hai Shalom899fcc72020-10-19 14:38:18 -07001706 case WLAN_PA_GAS_COMEBACK_RESP:
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001707 if (dpp_rx_gas_resp(conn, pos + 1,
Hai Shalom899fcc72020-10-19 14:38:18 -07001708 wpabuf_len(conn->msg) - 1,
1709 *pos == WLAN_PA_GAS_COMEBACK_RESP) < 0)
1710 dpp_connection_remove(conn);
1711 break;
1712 case WLAN_PA_GAS_COMEBACK_REQ:
1713 if (dpp_controller_rx_gas_comeback_req(
1714 conn, pos + 1, wpabuf_len(conn->msg) - 1) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001715 dpp_connection_remove(conn);
1716 break;
1717 default:
1718 wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u",
1719 *pos);
1720 break;
1721 }
1722}
1723
1724
1725static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
1726{
1727 struct dpp_controller *ctrl = eloop_ctx;
1728 struct sockaddr_in addr;
1729 socklen_t addr_len = sizeof(addr);
1730 int fd;
1731 struct dpp_connection *conn;
1732
1733 wpa_printf(MSG_DEBUG, "DPP: New TCP connection");
1734
1735 fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len);
1736 if (fd < 0) {
1737 wpa_printf(MSG_DEBUG,
1738 "DPP: Failed to accept new connection: %s",
1739 strerror(errno));
1740 return;
1741 }
1742 wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d",
1743 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
1744
1745 conn = os_zalloc(sizeof(*conn));
1746 if (!conn)
1747 goto fail;
1748
1749 conn->global = ctrl->global;
1750 conn->ctrl = ctrl;
Hai Shalom899fcc72020-10-19 14:38:18 -07001751 conn->msg_ctx = ctrl->msg_ctx;
1752 conn->cb_ctx = ctrl->cb_ctx;
1753 conn->process_conf_obj = ctrl->process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001754 conn->tcp_msg_sent = ctrl->tcp_msg_sent;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001755 conn->sock = fd;
Hai Shalom899fcc72020-10-19 14:38:18 -07001756 conn->netrole = ctrl->netrole;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001757
1758 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
1759 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
1760 strerror(errno));
1761 goto fail;
1762 }
1763
1764 if (eloop_register_sock(conn->sock, EVENT_TYPE_READ,
1765 dpp_controller_rx, conn, NULL) < 0)
1766 goto fail;
1767 conn->read_eloop = 1;
1768
1769 /* TODO: eloop timeout to expire connections that do not complete in
1770 * reasonable time */
1771 dl_list_add(&ctrl->conn, &conn->list);
1772 return;
1773
1774fail:
1775 close(fd);
1776 os_free(conn);
1777}
1778
1779
Hai Shaloma20dcd72022-02-04 13:43:00 -08001780int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex,
1781 const struct hostapd_ip_addr *addr, int port,
1782 void *msg_ctx, void *cb_ctx,
1783 int (*pkex_done)(void *ctx, void *conn,
1784 struct dpp_bootstrap_info *bi))
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001785{
1786 struct dpp_connection *conn;
1787 struct sockaddr_storage saddr;
1788 socklen_t addrlen;
1789 const u8 *hdr, *pos, *end;
1790 char txt[100];
1791
1792 wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
1793 hostapd_ip_txt(addr, txt, sizeof(txt)), port);
1794 if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
1795 addr, port) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001796 dpp_pkex_free(pkex);
1797 return -1;
1798 }
1799
1800 conn = os_zalloc(sizeof(*conn));
1801 if (!conn) {
1802 dpp_pkex_free(pkex);
1803 return -1;
1804 }
1805
1806 conn->msg_ctx = msg_ctx;
1807 conn->cb_ctx = cb_ctx;
1808 conn->pkex_done = pkex_done;
1809 conn->global = dpp;
1810 conn->pkex = pkex;
1811 conn->sock = socket(AF_INET, SOCK_STREAM, 0);
1812 if (conn->sock < 0)
1813 goto fail;
1814
1815 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
1816 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
1817 strerror(errno));
1818 goto fail;
1819 }
1820
1821 if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
1822 if (errno != EINPROGRESS) {
1823 wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
1824 strerror(errno));
1825 goto fail;
1826 }
1827
1828 /*
1829 * Continue connecting in the background; eloop will call us
1830 * once the connection is ready (or failed).
1831 */
1832 }
1833
1834 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
1835 dpp_conn_tx_ready, conn, NULL) < 0)
1836 goto fail;
1837 conn->write_eloop = 1;
1838
1839 hdr = wpabuf_head(pkex->exchange_req);
1840 end = hdr + wpabuf_len(pkex->exchange_req);
1841 hdr += 2; /* skip Category and Actiom */
1842 pos = hdr + DPP_HDR_LEN;
1843 conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
1844 if (!conn->msg_out)
1845 goto fail;
1846 /* Message will be sent in dpp_conn_tx_ready() */
1847
1848 /* TODO: eloop timeout to clear a connection if it does not complete
1849 * properly */
1850 dl_list_add(&dpp->tcp_init, &conn->list);
1851 return 0;
1852fail:
1853 dpp_connection_free(conn);
1854 return -1;
1855}
1856
1857
1858static int dpp_tcp_auth_start(struct dpp_connection *conn,
1859 struct dpp_authentication *auth)
1860{
1861 const u8 *hdr, *pos, *end;
1862
1863 hdr = wpabuf_head(auth->req_msg);
1864 end = hdr + wpabuf_len(auth->req_msg);
1865 hdr += 2; /* skip Category and Actiom */
1866 pos = hdr + DPP_HDR_LEN;
1867 conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
1868 if (!conn->msg_out)
1869 return -1;
1870 /* Message will be sent in dpp_conn_tx_ready() */
1871 return 0;
1872}
1873
1874
1875int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
1876 const struct hostapd_ip_addr *addr, int port, const char *name,
1877 enum dpp_netrole netrole, void *msg_ctx, void *cb_ctx,
1878 int (*process_conf_obj)(void *ctx,
1879 struct dpp_authentication *auth),
1880 bool (*tcp_msg_sent)(void *ctx,
1881 struct dpp_authentication *auth))
1882{
1883 struct dpp_connection *conn;
1884 struct sockaddr_storage saddr;
1885 socklen_t addrlen;
1886 char txt[100];
1887
1888 wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
1889 hostapd_ip_txt(addr, txt, sizeof(txt)), port);
1890 if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
1891 addr, port) < 0) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001892 dpp_auth_deinit(auth);
1893 return -1;
1894 }
1895
1896 conn = os_zalloc(sizeof(*conn));
1897 if (!conn) {
1898 dpp_auth_deinit(auth);
1899 return -1;
1900 }
1901
Hai Shalom899fcc72020-10-19 14:38:18 -07001902 conn->msg_ctx = msg_ctx;
1903 conn->cb_ctx = cb_ctx;
1904 conn->process_conf_obj = process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001905 conn->tcp_msg_sent = tcp_msg_sent;
Hai Shalom899fcc72020-10-19 14:38:18 -07001906 conn->name = os_strdup(name ? name : "Test");
1907 conn->netrole = netrole;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001908 conn->global = dpp;
1909 conn->auth = auth;
1910 conn->sock = socket(AF_INET, SOCK_STREAM, 0);
1911 if (conn->sock < 0)
1912 goto fail;
1913
1914 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
1915 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
1916 strerror(errno));
1917 goto fail;
1918 }
1919
1920 if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
1921 if (errno != EINPROGRESS) {
1922 wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
1923 strerror(errno));
1924 goto fail;
1925 }
1926
1927 /*
1928 * Continue connecting in the background; eloop will call us
1929 * once the connection is ready (or failed).
1930 */
1931 }
1932
1933 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
1934 dpp_conn_tx_ready, conn, NULL) < 0)
1935 goto fail;
1936 conn->write_eloop = 1;
1937
Hai Shaloma20dcd72022-02-04 13:43:00 -08001938 if (dpp_tcp_auth_start(conn, auth) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001939 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001940
1941 /* TODO: eloop timeout to clear a connection if it does not complete
1942 * properly */
1943 dl_list_add(&dpp->tcp_init, &conn->list);
1944 return 0;
1945fail:
1946 dpp_connection_free(conn);
1947 return -1;
1948}
1949
1950
Hai Shaloma20dcd72022-02-04 13:43:00 -08001951int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
1952 struct dpp_authentication *auth, const char *name,
1953 enum dpp_netrole netrole,
1954 int (*process_conf_obj)(void *ctx,
1955 struct dpp_authentication *auth),
1956 bool (*tcp_msg_sent)(void *ctx,
1957 struct dpp_authentication *auth))
1958{
1959 struct dpp_connection *conn = _conn;
1960
1961 /* Continue with Authentication exchange on an existing TCP connection.
1962 */
1963 conn->process_conf_obj = process_conf_obj;
1964 conn->tcp_msg_sent = tcp_msg_sent;
1965 os_free(conn->name);
1966 conn->name = os_strdup(name ? name : "Test");
1967 conn->netrole = netrole;
1968 conn->auth = auth;
1969
1970 if (dpp_tcp_auth_start(conn, auth) < 0)
1971 return -1;
1972
1973 dpp_conn_tx_ready(conn->sock, conn, NULL);
1974 return 0;
1975}
1976
1977
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001978int dpp_controller_start(struct dpp_global *dpp,
1979 struct dpp_controller_config *config)
1980{
1981 struct dpp_controller *ctrl;
1982 int on = 1;
1983 struct sockaddr_in sin;
1984 int port;
1985
1986 if (!dpp || dpp->controller)
1987 return -1;
1988
1989 ctrl = os_zalloc(sizeof(*ctrl));
1990 if (!ctrl)
1991 return -1;
1992 ctrl->global = dpp;
1993 if (config->configurator_params)
1994 ctrl->configurator_params =
1995 os_strdup(config->configurator_params);
1996 dl_list_init(&ctrl->conn);
1997 ctrl->allowed_roles = config->allowed_roles;
Hai Shalom899fcc72020-10-19 14:38:18 -07001998 ctrl->qr_mutual = config->qr_mutual;
1999 ctrl->netrole = config->netrole;
2000 ctrl->msg_ctx = config->msg_ctx;
2001 ctrl->cb_ctx = config->cb_ctx;
2002 ctrl->process_conf_obj = config->process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002003 ctrl->tcp_msg_sent = config->tcp_msg_sent;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002004
2005 ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
2006 if (ctrl->sock < 0)
2007 goto fail;
2008
2009 if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR,
2010 &on, sizeof(on)) < 0) {
2011 wpa_printf(MSG_DEBUG,
2012 "DPP: setsockopt(SO_REUSEADDR) failed: %s",
2013 strerror(errno));
2014 /* try to continue anyway */
2015 }
2016
2017 if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) {
2018 wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s",
2019 strerror(errno));
2020 goto fail;
2021 }
2022
2023 /* TODO: IPv6 */
2024 os_memset(&sin, 0, sizeof(sin));
2025 sin.sin_family = AF_INET;
2026 sin.sin_addr.s_addr = INADDR_ANY;
2027 port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT;
2028 sin.sin_port = htons(port);
2029 if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
2030 wpa_printf(MSG_INFO,
2031 "DPP: Failed to bind Controller TCP port: %s",
2032 strerror(errno));
2033 goto fail;
2034 }
2035 if (listen(ctrl->sock, 10 /* max backlog */) < 0 ||
2036 fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 ||
2037 eloop_register_sock(ctrl->sock, EVENT_TYPE_READ,
2038 dpp_controller_tcp_cb, ctrl, NULL))
2039 goto fail;
2040
2041 dpp->controller = ctrl;
2042 wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port);
2043 return 0;
2044fail:
2045 dpp_controller_free(ctrl);
2046 return -1;
2047}
2048
2049
2050void dpp_controller_stop(struct dpp_global *dpp)
2051{
2052 if (dpp) {
2053 dpp_controller_free(dpp->controller);
2054 dpp->controller = NULL;
2055 }
2056}
2057
2058
Hai Shaloma20dcd72022-02-04 13:43:00 -08002059void dpp_controller_stop_for_ctx(struct dpp_global *dpp, void *cb_ctx)
2060{
2061 if (dpp && dpp->controller && dpp->controller->cb_ctx == cb_ctx)
2062 dpp_controller_stop(dpp);
2063}
2064
2065
Hai Shalom899fcc72020-10-19 14:38:18 -07002066static bool dpp_tcp_peer_id_match(struct dpp_authentication *auth,
2067 unsigned int id)
2068{
2069 return auth &&
2070 ((auth->peer_bi && auth->peer_bi->id == id) ||
2071 (auth->tmp_peer_bi && auth->tmp_peer_bi->id == id));
2072}
2073
2074
2075static struct dpp_authentication * dpp_tcp_get_auth(struct dpp_global *dpp,
2076 unsigned int id)
2077{
2078 struct dpp_connection *conn;
2079
2080 dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
2081 if (dpp_tcp_peer_id_match(conn->auth, id))
2082 return conn->auth;
2083 }
2084
2085 return NULL;
2086}
2087
2088
2089struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp,
2090 unsigned int id)
2091{
2092 struct dpp_controller *ctrl = dpp->controller;
2093 struct dpp_connection *conn;
2094
2095 if (!ctrl)
2096 return dpp_tcp_get_auth(dpp, id);
2097
2098 dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
2099 if (dpp_tcp_peer_id_match(conn->auth, id))
2100 return conn->auth;
2101 }
2102
2103 return dpp_tcp_get_auth(dpp, id);
2104}
2105
2106
2107void dpp_controller_new_qr_code(struct dpp_global *dpp,
2108 struct dpp_bootstrap_info *bi)
2109{
2110 struct dpp_controller *ctrl = dpp->controller;
2111 struct dpp_connection *conn;
2112
2113 if (!ctrl)
2114 return;
2115
2116 dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
2117 struct dpp_authentication *auth = conn->auth;
2118
2119 if (!auth->response_pending ||
2120 dpp_notify_new_qr_code(auth, bi) != 1)
2121 continue;
2122 wpa_printf(MSG_DEBUG,
2123 "DPP: Sending out pending authentication response");
2124 dpp_tcp_send_msg(conn, conn->auth->resp_msg);
2125 }
2126}
2127
2128
Hai Shaloma20dcd72022-02-04 13:43:00 -08002129void dpp_controller_pkex_add(struct dpp_global *dpp,
2130 struct dpp_bootstrap_info *bi,
2131 const char *code, const char *identifier)
2132{
2133 struct dpp_controller *ctrl = dpp->controller;
2134
2135 if (!ctrl)
2136 return;
2137
2138 ctrl->pkex_bi = bi;
2139 os_free(ctrl->pkex_code);
2140 ctrl->pkex_code = code ? os_strdup(code) : NULL;
2141 os_free(ctrl->pkex_identifier);
2142 ctrl->pkex_identifier = identifier ? os_strdup(identifier) : NULL;
2143}
2144
2145
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002146void dpp_tcp_init_flush(struct dpp_global *dpp)
2147{
2148 struct dpp_connection *conn, *tmp;
2149
2150 dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection,
2151 list)
2152 dpp_connection_remove(conn);
2153}
2154
2155
2156static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl)
2157{
2158 struct dpp_connection *conn, *tmp;
2159
2160 dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
2161 list)
2162 dpp_connection_remove(conn);
2163 os_free(ctrl);
2164}
2165
2166
2167void dpp_relay_flush_controllers(struct dpp_global *dpp)
2168{
2169 struct dpp_relay_controller *ctrl, *tmp;
2170
2171 if (!dpp)
2172 return;
2173
2174 dl_list_for_each_safe(ctrl, tmp, &dpp->controllers,
2175 struct dpp_relay_controller, list) {
2176 dl_list_del(&ctrl->list);
2177 dpp_relay_controller_free(ctrl);
2178 }
2179}
2180
Hai Shaloma20dcd72022-02-04 13:43:00 -08002181
2182bool dpp_tcp_conn_status_requested(struct dpp_global *dpp)
2183{
2184 struct dpp_connection *conn;
2185
2186 dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
2187 if (conn->auth && conn->auth->conn_status_requested)
2188 return true;
2189 }
2190
2191 return false;
2192}
2193
2194
2195static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn,
2196 enum dpp_status_error result,
2197 const u8 *ssid, size_t ssid_len,
2198 const char *channel_list)
2199{
2200 struct dpp_authentication *auth = conn->auth;
2201 int res;
2202 struct wpabuf *msg;
2203
2204 auth->conn_status_requested = 0;
2205
2206 msg = dpp_build_conn_status_result(auth, result, ssid, ssid_len,
2207 channel_list);
2208 if (!msg) {
2209 dpp_connection_remove(conn);
2210 return;
2211 }
2212
2213 res = dpp_tcp_send_msg(conn, msg);
2214 wpabuf_free(msg);
2215
2216 if (res < 0) {
2217 dpp_connection_remove(conn);
2218 return;
2219 }
2220
2221 /* This exchange will be terminated in the TX status handler */
2222 conn->on_tcp_tx_complete_remove = 1;
2223}
2224
2225
2226void dpp_tcp_send_conn_status(struct dpp_global *dpp,
2227 enum dpp_status_error result,
2228 const u8 *ssid, size_t ssid_len,
2229 const char *channel_list)
2230{
2231 struct dpp_connection *conn;
2232
2233 dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
2234 if (conn->auth && conn->auth->conn_status_requested) {
2235 dpp_tcp_send_conn_status_msg(conn, result, ssid,
2236 ssid_len, channel_list);
2237 break;
2238 }
2239 }
2240}
2241
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002242#endif /* CONFIG_DPP2 */