blob: ff18a9929d945c2c17b8c28b24866abe1e2b27f2 [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;
Sunil Ravi89eba102022-09-13 21:04:37 -070051 char *mud_url;
52 char *extra_conf_req_name;
53 char *extra_conf_req_value;
Hai Shalom899fcc72020-10-19 14:38:18 -070054 enum dpp_netrole netrole;
Hai Shalom4fbc08f2020-05-18 12:37:00 -070055};
56
57/* Remote Controller */
58struct dpp_relay_controller {
59 struct dl_list list;
60 struct dpp_global *global;
61 u8 pkhash[SHA256_MAC_LEN];
62 struct hostapd_ip_addr ipaddr;
Hai Shalom899fcc72020-10-19 14:38:18 -070063 void *msg_ctx;
Hai Shalom4fbc08f2020-05-18 12:37:00 -070064 void *cb_ctx;
65 void (*tx)(void *ctx, const u8 *addr, unsigned int freq, const u8 *msg,
66 size_t len);
67 void (*gas_resp_tx)(void *ctx, const u8 *addr, u8 dialog_token,
68 int prot, struct wpabuf *buf);
69 struct dl_list conn; /* struct dpp_connection */
70};
71
72/* Local Controller */
73struct dpp_controller {
74 struct dpp_global *global;
75 u8 allowed_roles;
76 int qr_mutual;
77 int sock;
78 struct dl_list conn; /* struct dpp_connection */
79 char *configurator_params;
Hai Shalom899fcc72020-10-19 14:38:18 -070080 enum dpp_netrole netrole;
Hai Shaloma20dcd72022-02-04 13:43:00 -080081 struct dpp_bootstrap_info *pkex_bi;
82 char *pkex_code;
83 char *pkex_identifier;
Hai Shalom899fcc72020-10-19 14:38:18 -070084 void *msg_ctx;
85 void *cb_ctx;
86 int (*process_conf_obj)(void *ctx, struct dpp_authentication *auth);
Hai Shaloma20dcd72022-02-04 13:43:00 -080087 bool (*tcp_msg_sent)(void *ctx, struct dpp_authentication *auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -070088};
89
90static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx);
91static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx);
92static void dpp_controller_auth_success(struct dpp_connection *conn,
93 int initiator);
Hai Shalom899fcc72020-10-19 14:38:18 -070094static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx);
Sunil Ravia04bd252022-05-02 22:54:18 -070095#ifdef CONFIG_DPP3
96static void dpp_tcp_build_new_key(void *eloop_ctx, void *timeout_ctx);
97#endif /* CONFIG_DPP3 */
Hai Shalom899fcc72020-10-19 14:38:18 -070098static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx);
Hai Shaloma20dcd72022-02-04 13:43:00 -080099static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700100
101
102static void dpp_connection_free(struct dpp_connection *conn)
103{
104 if (conn->sock >= 0) {
105 wpa_printf(MSG_DEBUG, "DPP: Close Controller socket %d",
106 conn->sock);
107 eloop_unregister_sock(conn->sock, EVENT_TYPE_READ);
108 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
109 close(conn->sock);
110 }
111 eloop_cancel_timeout(dpp_controller_conn_status_result_wait_timeout,
112 conn, NULL);
Hai Shalom899fcc72020-10-19 14:38:18 -0700113 eloop_cancel_timeout(dpp_tcp_build_csr, conn, NULL);
114 eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800115 eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
Sunil Ravia04bd252022-05-02 22:54:18 -0700116#ifdef CONFIG_DPP3
117 eloop_cancel_timeout(dpp_tcp_build_new_key, conn, NULL);
118#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700119 wpabuf_free(conn->msg);
120 wpabuf_free(conn->msg_out);
121 dpp_auth_deinit(conn->auth);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800122 dpp_pkex_free(conn->pkex);
Hai Shalom899fcc72020-10-19 14:38:18 -0700123 os_free(conn->name);
Sunil Ravi89eba102022-09-13 21:04:37 -0700124 os_free(conn->mud_url);
125 os_free(conn->extra_conf_req_name);
126 os_free(conn->extra_conf_req_value);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700127 os_free(conn);
128}
129
130
131static void dpp_connection_remove(struct dpp_connection *conn)
132{
133 dl_list_del(&conn->list);
134 dpp_connection_free(conn);
135}
136
137
138int dpp_relay_add_controller(struct dpp_global *dpp,
139 struct dpp_relay_config *config)
140{
141 struct dpp_relay_controller *ctrl;
Sunil Ravi89eba102022-09-13 21:04:37 -0700142 char txt[100];
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700143
144 if (!dpp)
145 return -1;
146
147 ctrl = os_zalloc(sizeof(*ctrl));
148 if (!ctrl)
149 return -1;
150 dl_list_init(&ctrl->conn);
151 ctrl->global = dpp;
152 os_memcpy(&ctrl->ipaddr, config->ipaddr, sizeof(*config->ipaddr));
153 os_memcpy(ctrl->pkhash, config->pkhash, SHA256_MAC_LEN);
Hai Shalom899fcc72020-10-19 14:38:18 -0700154 ctrl->msg_ctx = config->msg_ctx;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700155 ctrl->cb_ctx = config->cb_ctx;
156 ctrl->tx = config->tx;
157 ctrl->gas_resp_tx = config->gas_resp_tx;
Sunil Ravi89eba102022-09-13 21:04:37 -0700158 wpa_printf(MSG_DEBUG, "DPP: Add Relay connection to Controller %s",
159 hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700160 dl_list_add(&dpp->controllers, &ctrl->list);
161 return 0;
162}
163
164
165static struct dpp_relay_controller *
166dpp_relay_controller_get(struct dpp_global *dpp, const u8 *pkhash)
167{
168 struct dpp_relay_controller *ctrl;
169
170 if (!dpp)
171 return NULL;
172
173 dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
174 list) {
175 if (os_memcmp(pkhash, ctrl->pkhash, SHA256_MAC_LEN) == 0)
176 return ctrl;
177 }
178
179 return NULL;
180}
181
182
Hai Shaloma20dcd72022-02-04 13:43:00 -0800183static struct dpp_relay_controller *
184dpp_relay_controller_get_ctx(struct dpp_global *dpp, void *cb_ctx)
185{
186 struct dpp_relay_controller *ctrl;
187
188 if (!dpp)
189 return NULL;
190
191 dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
192 list) {
193 if (cb_ctx == ctrl->cb_ctx)
194 return ctrl;
195 }
196
197 return NULL;
198}
199
200
Sunil Ravi89eba102022-09-13 21:04:37 -0700201static struct dpp_relay_controller *
202dpp_relay_controller_get_addr(struct dpp_global *dpp,
203 const struct sockaddr_in *addr)
204{
205 struct dpp_relay_controller *ctrl;
206
207 if (!dpp)
208 return NULL;
209
210 dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
211 list) {
212 if (ctrl->ipaddr.af == AF_INET &&
213 addr->sin_addr.s_addr == ctrl->ipaddr.u.v4.s_addr)
214 return ctrl;
215 }
216
217 if (dpp->tmp_controller &&
218 dpp->tmp_controller->ipaddr.af == AF_INET &&
219 addr->sin_addr.s_addr == dpp->tmp_controller->ipaddr.u.v4.s_addr)
220 return dpp->tmp_controller;
221
222 return NULL;
223}
224
225
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700226static void dpp_controller_gas_done(struct dpp_connection *conn)
227{
228 struct dpp_authentication *auth = conn->auth;
Hai Shalom899fcc72020-10-19 14:38:18 -0700229
230 if (auth->waiting_csr) {
231 wpa_printf(MSG_DEBUG, "DPP: Waiting for CSR");
232 conn->on_tcp_tx_complete_gas_done = 0;
233 return;
234 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700235
Sunil Ravia04bd252022-05-02 22:54:18 -0700236#ifdef CONFIG_DPP3
237 if (auth->waiting_new_key) {
238 wpa_printf(MSG_DEBUG, "DPP: Waiting for a new key");
239 conn->on_tcp_tx_complete_gas_done = 0;
240 return;
241 }
242#endif /* CONFIG_DPP3 */
243
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700244 if (auth->peer_version >= 2 &&
245 auth->conf_resp_status == DPP_STATUS_OK) {
246 wpa_printf(MSG_DEBUG, "DPP: Wait for Configuration Result");
247 auth->waiting_conf_result = 1;
248 return;
249 }
250
Sunil Ravi89eba102022-09-13 21:04:37 -0700251 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT "conf_status=%d",
252 auth->conf_resp_status);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700253 dpp_connection_remove(conn);
254}
255
256
257static int dpp_tcp_send(struct dpp_connection *conn)
258{
259 int res;
260
261 if (!conn->msg_out) {
262 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
263 conn->write_eloop = 0;
264 return -1;
265 }
266 res = send(conn->sock,
267 wpabuf_head_u8(conn->msg_out) + conn->msg_out_pos,
268 wpabuf_len(conn->msg_out) - conn->msg_out_pos, 0);
269 if (res < 0) {
270 wpa_printf(MSG_DEBUG, "DPP: Failed to send buffer: %s",
271 strerror(errno));
272 dpp_connection_remove(conn);
273 return -1;
274 }
275
276 conn->msg_out_pos += res;
277 if (wpabuf_len(conn->msg_out) > conn->msg_out_pos) {
278 wpa_printf(MSG_DEBUG,
279 "DPP: %u/%u bytes of message sent to Controller",
280 (unsigned int) conn->msg_out_pos,
281 (unsigned int) wpabuf_len(conn->msg_out));
282 if (!conn->write_eloop &&
283 eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
284 dpp_conn_tx_ready, conn, NULL) == 0)
285 conn->write_eloop = 1;
286 return 1;
287 }
288
289 wpa_printf(MSG_DEBUG, "DPP: Full message sent over TCP");
290 wpabuf_free(conn->msg_out);
291 conn->msg_out = NULL;
292 conn->msg_out_pos = 0;
293 eloop_unregister_sock(conn->sock, EVENT_TYPE_WRITE);
294 conn->write_eloop = 0;
295 if (!conn->read_eloop &&
296 eloop_register_sock(conn->sock, EVENT_TYPE_READ,
297 dpp_controller_rx, conn, NULL) == 0)
298 conn->read_eloop = 1;
299 if (conn->on_tcp_tx_complete_remove) {
Hai Shaloma20dcd72022-02-04 13:43:00 -0800300 if (conn->auth && conn->auth->connect_on_tx_status &&
301 conn->tcp_msg_sent &&
302 conn->tcp_msg_sent(conn->cb_ctx, conn->auth))
303 return 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700304 dpp_connection_remove(conn);
305 } else if (conn->auth && (conn->ctrl || conn->auth->configurator) &&
306 conn->on_tcp_tx_complete_gas_done) {
307 dpp_controller_gas_done(conn);
308 } else if (conn->on_tcp_tx_complete_auth_ok) {
309 conn->on_tcp_tx_complete_auth_ok = 0;
310 dpp_controller_auth_success(conn, 1);
311 }
312
313 return 0;
314}
315
316
317static int dpp_tcp_send_msg(struct dpp_connection *conn,
318 const struct wpabuf *msg)
319{
320 wpabuf_free(conn->msg_out);
321 conn->msg_out_pos = 0;
322 conn->msg_out = wpabuf_alloc(4 + wpabuf_len(msg) - 1);
323 if (!conn->msg_out)
324 return -1;
325 wpabuf_put_be32(conn->msg_out, wpabuf_len(msg) - 1);
326 wpabuf_put_data(conn->msg_out, wpabuf_head_u8(msg) + 1,
327 wpabuf_len(msg) - 1);
328
329 if (dpp_tcp_send(conn) == 1) {
330 if (!conn->write_eloop) {
331 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
332 dpp_conn_tx_ready,
333 conn, NULL) < 0)
334 return -1;
335 conn->write_eloop = 1;
336 }
337 }
338
339 return 0;
340}
341
342
343static void dpp_controller_start_gas_client(struct dpp_connection *conn)
344{
345 struct dpp_authentication *auth = conn->auth;
346 struct wpabuf *buf;
Hai Shalom899fcc72020-10-19 14:38:18 -0700347 const char *dpp_name;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700348
Hai Shalom899fcc72020-10-19 14:38:18 -0700349 dpp_name = conn->name ? conn->name : "Test";
Sunil Ravi89eba102022-09-13 21:04:37 -0700350 buf = dpp_build_conf_req_helper(auth, dpp_name, conn->netrole,
351 conn->mud_url, NULL,
352 conn->extra_conf_req_name,
353 conn->extra_conf_req_value);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700354 if (!buf) {
355 wpa_printf(MSG_DEBUG,
356 "DPP: No configuration request data available");
357 return;
358 }
359
360 dpp_tcp_send_msg(conn, buf);
361 wpabuf_free(buf);
362}
363
364
365static void dpp_controller_auth_success(struct dpp_connection *conn,
366 int initiator)
367{
368 struct dpp_authentication *auth = conn->auth;
369
370 if (!auth)
371 return;
372
373 wpa_printf(MSG_DEBUG, "DPP: Authentication succeeded");
Hai Shalom899fcc72020-10-19 14:38:18 -0700374 wpa_msg(conn->msg_ctx, MSG_INFO,
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700375 DPP_EVENT_AUTH_SUCCESS "init=%d", initiator);
376#ifdef CONFIG_TESTING_OPTIONS
377 if (dpp_test == DPP_TEST_STOP_AT_AUTH_CONF) {
378 wpa_printf(MSG_INFO,
379 "DPP: TESTING - stop at Authentication Confirm");
380 if (auth->configurator) {
381 /* Prevent GAS response */
382 auth->auth_success = 0;
383 }
384 return;
385 }
386#endif /* CONFIG_TESTING_OPTIONS */
387
388 if (!auth->configurator)
389 dpp_controller_start_gas_client(conn);
390}
391
392
393static void dpp_conn_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
394{
395 struct dpp_connection *conn = eloop_ctx;
396
397 wpa_printf(MSG_DEBUG, "DPP: TCP socket %d ready for TX", sock);
398 dpp_tcp_send(conn);
399}
400
401
402static int dpp_ipaddr_to_sockaddr(struct sockaddr *addr, socklen_t *addrlen,
403 const struct hostapd_ip_addr *ipaddr,
404 int port)
405{
406 struct sockaddr_in *dst;
407#ifdef CONFIG_IPV6
408 struct sockaddr_in6 *dst6;
409#endif /* CONFIG_IPV6 */
410
411 switch (ipaddr->af) {
412 case AF_INET:
413 dst = (struct sockaddr_in *) addr;
414 os_memset(dst, 0, sizeof(*dst));
415 dst->sin_family = AF_INET;
416 dst->sin_addr.s_addr = ipaddr->u.v4.s_addr;
417 dst->sin_port = htons(port);
418 *addrlen = sizeof(*dst);
419 break;
420#ifdef CONFIG_IPV6
421 case AF_INET6:
422 dst6 = (struct sockaddr_in6 *) addr;
423 os_memset(dst6, 0, sizeof(*dst6));
424 dst6->sin6_family = AF_INET6;
425 os_memcpy(&dst6->sin6_addr, &ipaddr->u.v6,
426 sizeof(struct in6_addr));
427 dst6->sin6_port = htons(port);
428 *addrlen = sizeof(*dst6);
429 break;
430#endif /* CONFIG_IPV6 */
431 default:
432 return -1;
433 }
434
435 return 0;
436}
437
438
Hai Shaloma20dcd72022-02-04 13:43:00 -0800439static void dpp_relay_conn_timeout(void *eloop_ctx, void *timeout_ctx)
440{
441 struct dpp_connection *conn = eloop_ctx;
442
443 wpa_printf(MSG_DEBUG,
444 "DPP: Timeout while waiting for relayed connection to complete");
445 dpp_connection_remove(conn);
446}
447
448
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700449static struct dpp_connection *
450dpp_relay_new_conn(struct dpp_relay_controller *ctrl, const u8 *src,
451 unsigned int freq)
452{
453 struct dpp_connection *conn;
454 struct sockaddr_storage addr;
455 socklen_t addrlen;
456 char txt[100];
457
458 if (dl_list_len(&ctrl->conn) >= 15) {
459 wpa_printf(MSG_DEBUG,
460 "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one");
461 return NULL;
462 }
463
464 if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &addr, &addrlen,
465 &ctrl->ipaddr, DPP_TCP_PORT) < 0)
466 return NULL;
467
468 conn = os_zalloc(sizeof(*conn));
469 if (!conn)
470 return NULL;
471
472 conn->global = ctrl->global;
473 conn->relay = ctrl;
Hai Shalom899fcc72020-10-19 14:38:18 -0700474 conn->msg_ctx = ctrl->msg_ctx;
475 conn->cb_ctx = ctrl->global->cb_ctx;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700476 os_memcpy(conn->mac_addr, src, ETH_ALEN);
477 conn->freq = freq;
478
479 conn->sock = socket(AF_INET, SOCK_STREAM, 0);
480 if (conn->sock < 0)
481 goto fail;
482 wpa_printf(MSG_DEBUG, "DPP: TCP relay socket %d connection to %s",
483 conn->sock, hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
484
485 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
486 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
487 strerror(errno));
488 goto fail;
489 }
490
491 if (connect(conn->sock, (struct sockaddr *) &addr, addrlen) < 0) {
492 if (errno != EINPROGRESS) {
493 wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
494 strerror(errno));
495 goto fail;
496 }
497
498 /*
499 * Continue connecting in the background; eloop will call us
500 * once the connection is ready (or failed).
501 */
502 }
503
504 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
505 dpp_conn_tx_ready, conn, NULL) < 0)
506 goto fail;
507 conn->write_eloop = 1;
508
Hai Shaloma20dcd72022-02-04 13:43:00 -0800509 eloop_cancel_timeout(dpp_relay_conn_timeout, conn, NULL);
510 eloop_register_timeout(20, 0, dpp_relay_conn_timeout, conn, NULL);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700511
512 dl_list_add(&ctrl->conn, &conn->list);
513 return conn;
514fail:
515 dpp_connection_free(conn);
516 return NULL;
517}
518
519
520static struct wpabuf * dpp_tcp_encaps(const u8 *hdr, const u8 *buf, size_t len)
521{
522 struct wpabuf *msg;
523
524 msg = wpabuf_alloc(4 + 1 + DPP_HDR_LEN + len);
525 if (!msg)
526 return NULL;
527 wpabuf_put_be32(msg, 1 + DPP_HDR_LEN + len);
528 wpabuf_put_u8(msg, WLAN_PA_VENDOR_SPECIFIC);
529 wpabuf_put_data(msg, hdr, DPP_HDR_LEN);
530 wpabuf_put_data(msg, buf, len);
531 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
532 return msg;
533}
534
535
536static int dpp_relay_tx(struct dpp_connection *conn, const u8 *hdr,
537 const u8 *buf, size_t len)
538{
539 u8 type = hdr[DPP_HDR_LEN - 1];
540
541 wpa_printf(MSG_DEBUG,
542 "DPP: Continue already established Relay/Controller connection for this session");
543 wpabuf_free(conn->msg_out);
544 conn->msg_out_pos = 0;
545 conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
546 if (!conn->msg_out) {
547 dpp_connection_remove(conn);
548 return -1;
549 }
550
551 /* TODO: for proto ver 1, need to do remove connection based on GAS Resp
552 * TX status */
553 if (type == DPP_PA_CONFIGURATION_RESULT)
554 conn->on_tcp_tx_complete_remove = 1;
555 dpp_tcp_send(conn);
556 return 0;
557}
558
559
Sunil Ravi89eba102022-09-13 21:04:37 -0700560static struct dpp_connection *
561dpp_relay_match_ctrl(struct dpp_relay_controller *ctrl, const u8 *src,
562 unsigned int freq, u8 type)
563{
564 struct dpp_connection *conn;
565
566 dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
567 if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0)
568 return conn;
569 if ((type == DPP_PA_PKEX_EXCHANGE_RESP ||
570 type == DPP_PA_AUTHENTICATION_RESP) &&
571 conn->freq == 0 &&
572 is_broadcast_ether_addr(conn->mac_addr)) {
573 wpa_printf(MSG_DEBUG,
574 "DPP: Associate this peer to the new Controller initiated connection");
575 os_memcpy(conn->mac_addr, src, ETH_ALEN);
576 conn->freq = freq;
577 return conn;
578 }
579 }
580
581 return NULL;
582}
583
584
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700585int dpp_relay_rx_action(struct dpp_global *dpp, const u8 *src, const u8 *hdr,
586 const u8 *buf, size_t len, unsigned int freq,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800587 const u8 *i_bootstrap, const u8 *r_bootstrap,
588 void *cb_ctx)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700589{
590 struct dpp_relay_controller *ctrl;
591 struct dpp_connection *conn;
592 u8 type = hdr[DPP_HDR_LEN - 1];
593
594 /* Check if there is an already started session for this peer and if so,
595 * continue that session (send this over TCP) and return 0.
596 */
597 if (type != DPP_PA_PEER_DISCOVERY_REQ &&
598 type != DPP_PA_PEER_DISCOVERY_RESP &&
599 type != DPP_PA_PRESENCE_ANNOUNCEMENT &&
600 type != DPP_PA_RECONFIG_ANNOUNCEMENT) {
601 dl_list_for_each(ctrl, &dpp->controllers,
602 struct dpp_relay_controller, list) {
Sunil Ravi89eba102022-09-13 21:04:37 -0700603 conn = dpp_relay_match_ctrl(ctrl, src, freq, type);
604 if (conn)
605 return dpp_relay_tx(conn, hdr, buf, len);
606 }
607
608 if (dpp->tmp_controller) {
609 conn = dpp_relay_match_ctrl(dpp->tmp_controller, src,
610 freq, type);
611 if (conn)
612 return dpp_relay_tx(conn, hdr, buf, len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700613 }
614 }
615
616 if (type == DPP_PA_PRESENCE_ANNOUNCEMENT ||
617 type == DPP_PA_RECONFIG_ANNOUNCEMENT) {
618 /* TODO: Could send this to all configured Controllers. For now,
619 * only the first Controller is supported. */
Hai Shaloma20dcd72022-02-04 13:43:00 -0800620 ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
621 } else if (type == DPP_PA_PKEX_EXCHANGE_REQ) {
622 ctrl = dpp_relay_controller_get_ctx(dpp, cb_ctx);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700623 } else {
624 if (!r_bootstrap)
625 return -1;
626 ctrl = dpp_relay_controller_get(dpp, r_bootstrap);
627 }
628 if (!ctrl)
629 return -1;
630
631 wpa_printf(MSG_DEBUG,
632 "DPP: Authentication Request for a configured Controller");
633 conn = dpp_relay_new_conn(ctrl, src, freq);
634 if (!conn)
635 return -1;
636
637 conn->msg_out = dpp_tcp_encaps(hdr, buf, len);
638 if (!conn->msg_out) {
639 dpp_connection_remove(conn);
640 return -1;
641 }
642 /* Message will be sent in dpp_conn_tx_ready() */
643
644 return 0;
645}
646
647
Sunil Ravi89eba102022-09-13 21:04:37 -0700648static struct dpp_connection *
649dpp_relay_find_conn(struct dpp_relay_controller *ctrl, const u8 *src)
650{
651 struct dpp_connection *conn;
652
653 dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
654 if (os_memcmp(src, conn->mac_addr, ETH_ALEN) == 0)
655 return conn;
656 }
657
658 return NULL;
659}
660
661
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700662int dpp_relay_rx_gas_req(struct dpp_global *dpp, const u8 *src, const u8 *data,
663 size_t data_len)
664{
665 struct dpp_relay_controller *ctrl;
Sunil Ravi89eba102022-09-13 21:04:37 -0700666 struct dpp_connection *conn = NULL;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700667 struct wpabuf *msg;
668
669 /* Check if there is a successfully completed authentication for this
670 * and if so, continue that session (send this over TCP) and return 0.
671 */
672 dl_list_for_each(ctrl, &dpp->controllers,
673 struct dpp_relay_controller, list) {
Sunil Ravi89eba102022-09-13 21:04:37 -0700674 conn = dpp_relay_find_conn(ctrl, src);
675 if (conn)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700676 break;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700677 }
678
Sunil Ravi89eba102022-09-13 21:04:37 -0700679 if (!conn && dpp->tmp_controller)
680 conn = dpp_relay_find_conn(dpp->tmp_controller, src);
681
682 if (!conn)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700683 return -1;
684
685 msg = wpabuf_alloc(4 + 1 + data_len);
686 if (!msg)
687 return -1;
688 wpabuf_put_be32(msg, 1 + data_len);
689 wpabuf_put_u8(msg, WLAN_PA_GAS_INITIAL_REQ);
690 wpabuf_put_data(msg, data, data_len);
691 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
692
693 wpabuf_free(conn->msg_out);
694 conn->msg_out_pos = 0;
695 conn->msg_out = msg;
696 dpp_tcp_send(conn);
697 return 0;
698}
699
700
Sunil Ravi89eba102022-09-13 21:04:37 -0700701bool dpp_relay_controller_available(struct dpp_global *dpp)
702{
703 return dpp && dl_list_len(&dpp->controllers) > 0;
704}
705
706
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700707static void dpp_controller_free(struct dpp_controller *ctrl)
708{
709 struct dpp_connection *conn, *tmp;
710
711 if (!ctrl)
712 return;
713
714 dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
715 list)
716 dpp_connection_remove(conn);
717
718 if (ctrl->sock >= 0) {
719 close(ctrl->sock);
720 eloop_unregister_sock(ctrl->sock, EVENT_TYPE_READ);
721 }
722 os_free(ctrl->configurator_params);
Hai Shaloma20dcd72022-02-04 13:43:00 -0800723 os_free(ctrl->pkex_code);
724 os_free(ctrl->pkex_identifier);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700725 os_free(ctrl);
726}
727
728
729static int dpp_controller_rx_auth_req(struct dpp_connection *conn,
730 const u8 *hdr, const u8 *buf, size_t len)
731{
732 const u8 *r_bootstrap, *i_bootstrap;
733 u16 r_bootstrap_len, i_bootstrap_len;
734 struct dpp_bootstrap_info *own_bi = NULL, *peer_bi = NULL;
735
736 if (!conn->ctrl)
737 return 0;
738
739 wpa_printf(MSG_DEBUG, "DPP: Authentication Request");
740
741 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
742 &r_bootstrap_len);
743 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
744 wpa_printf(MSG_INFO,
745 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
746 return -1;
747 }
748 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
749 r_bootstrap, r_bootstrap_len);
750
751 i_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_I_BOOTSTRAP_KEY_HASH,
752 &i_bootstrap_len);
753 if (!i_bootstrap || i_bootstrap_len != SHA256_MAC_LEN) {
754 wpa_printf(MSG_INFO,
755 "Missing or invalid required Initiator Bootstrapping Key Hash attribute");
756 return -1;
757 }
758 wpa_hexdump(MSG_MSGDUMP, "DPP: Initiator Bootstrapping Key Hash",
759 i_bootstrap, i_bootstrap_len);
760
761 /* Try to find own and peer bootstrapping key matches based on the
762 * received hash values */
763 dpp_bootstrap_find_pair(conn->ctrl->global, i_bootstrap, r_bootstrap,
764 &own_bi, &peer_bi);
765 if (!own_bi) {
766 wpa_printf(MSG_INFO,
767 "No matching own bootstrapping key found - ignore message");
768 return -1;
769 }
770
771 if (conn->auth) {
772 wpa_printf(MSG_INFO,
773 "Already in DPP authentication exchange - ignore new one");
774 return 0;
775 }
776
Hai Shalom899fcc72020-10-19 14:38:18 -0700777 conn->auth = dpp_auth_req_rx(conn->ctrl->global, conn->msg_ctx,
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700778 conn->ctrl->allowed_roles,
779 conn->ctrl->qr_mutual,
780 peer_bi, own_bi, -1, hdr, buf, len);
781 if (!conn->auth) {
782 wpa_printf(MSG_DEBUG, "DPP: No response generated");
783 return -1;
784 }
785
786 if (dpp_set_configurator(conn->auth,
Hai Shaloma20dcd72022-02-04 13:43:00 -0800787 conn->ctrl->configurator_params) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700788 return -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700789
790 return dpp_tcp_send_msg(conn, conn->auth->resp_msg);
791}
792
793
794static int dpp_controller_rx_auth_resp(struct dpp_connection *conn,
795 const u8 *hdr, const u8 *buf, size_t len)
796{
797 struct dpp_authentication *auth = conn->auth;
798 struct wpabuf *msg;
799 int res;
800
801 if (!auth)
802 return -1;
803
804 wpa_printf(MSG_DEBUG, "DPP: Authentication Response");
805
806 msg = dpp_auth_resp_rx(auth, hdr, buf, len);
807 if (!msg) {
808 if (auth->auth_resp_status == DPP_STATUS_RESPONSE_PENDING) {
809 wpa_printf(MSG_DEBUG,
810 "DPP: Start wait for full response");
Hai Shalom899fcc72020-10-19 14:38:18 -0700811 return 0;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700812 }
813 wpa_printf(MSG_DEBUG, "DPP: No confirm generated");
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700814 return -1;
815 }
816
817 conn->on_tcp_tx_complete_auth_ok = 1;
818 res = dpp_tcp_send_msg(conn, msg);
819 wpabuf_free(msg);
820 return res;
821}
822
823
824static int dpp_controller_rx_auth_conf(struct dpp_connection *conn,
825 const u8 *hdr, const u8 *buf, size_t len)
826{
827 struct dpp_authentication *auth = conn->auth;
828
829 wpa_printf(MSG_DEBUG, "DPP: Authentication Confirmation");
830
831 if (!auth) {
832 wpa_printf(MSG_DEBUG,
833 "DPP: No DPP Authentication in progress - drop");
834 return -1;
835 }
836
837 if (dpp_auth_conf_rx(auth, hdr, buf, len) < 0) {
838 wpa_printf(MSG_DEBUG, "DPP: Authentication failed");
839 return -1;
840 }
841
842 dpp_controller_auth_success(conn, 0);
843 return 0;
844}
845
846
847void dpp_controller_conn_status_result_wait_timeout(void *eloop_ctx,
848 void *timeout_ctx)
849{
850 struct dpp_connection *conn = eloop_ctx;
851
852 if (!conn->auth->waiting_conf_result)
853 return;
854
855 wpa_printf(MSG_DEBUG,
856 "DPP: Timeout while waiting for Connection Status Result");
Hai Shalom899fcc72020-10-19 14:38:18 -0700857 wpa_msg(conn->msg_ctx, MSG_INFO,
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700858 DPP_EVENT_CONN_STATUS_RESULT "timeout");
859 dpp_connection_remove(conn);
860}
861
862
863static int dpp_controller_rx_conf_result(struct dpp_connection *conn,
864 const u8 *hdr, const u8 *buf,
865 size_t len)
866{
867 struct dpp_authentication *auth = conn->auth;
868 enum dpp_status_error status;
Hai Shalom899fcc72020-10-19 14:38:18 -0700869 void *msg_ctx = conn->msg_ctx;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700870
871 if (!conn->ctrl && (!auth || !auth->configurator))
872 return 0;
873
874 wpa_printf(MSG_DEBUG, "DPP: Configuration Result");
875
876 if (!auth || !auth->waiting_conf_result) {
877 wpa_printf(MSG_DEBUG,
878 "DPP: No DPP Configuration waiting for result - drop");
879 return -1;
880 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700881
882 status = dpp_conf_result_rx(auth, hdr, buf, len);
883 if (status == DPP_STATUS_OK && auth->send_conn_status) {
Sunil Ravi89eba102022-09-13 21:04:37 -0700884 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
885 "wait_conn_status=1 conf_resp_status=%d",
886 auth->conf_resp_status);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700887 wpa_printf(MSG_DEBUG, "DPP: Wait for Connection Status Result");
Hai Shaloma20dcd72022-02-04 13:43:00 -0800888 auth->waiting_conn_status_result = 1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700889 eloop_cancel_timeout(
890 dpp_controller_conn_status_result_wait_timeout,
891 conn, NULL);
892 eloop_register_timeout(
893 16, 0, dpp_controller_conn_status_result_wait_timeout,
894 conn, NULL);
895 return 0;
896 }
897 if (status == DPP_STATUS_OK)
Sunil Ravi89eba102022-09-13 21:04:37 -0700898 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_SENT
899 "conf_resp_status=%d", auth->conf_resp_status);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700900 else
901 wpa_msg(msg_ctx, MSG_INFO, DPP_EVENT_CONF_FAILED);
902 return -1; /* to remove the completed connection */
903}
904
905
906static int dpp_controller_rx_conn_status_result(struct dpp_connection *conn,
907 const u8 *hdr, const u8 *buf,
908 size_t len)
909{
910 struct dpp_authentication *auth = conn->auth;
911 enum dpp_status_error status;
912 u8 ssid[SSID_MAX_LEN];
913 size_t ssid_len = 0;
914 char *channel_list = NULL;
915
916 if (!conn->ctrl)
917 return 0;
918
919 wpa_printf(MSG_DEBUG, "DPP: Connection Status Result");
920
921 if (!auth || !auth->waiting_conn_status_result) {
922 wpa_printf(MSG_DEBUG,
923 "DPP: No DPP Configuration waiting for connection status result - drop");
924 return -1;
925 }
926
927 status = dpp_conn_status_result_rx(auth, hdr, buf, len,
928 ssid, &ssid_len, &channel_list);
Hai Shalom899fcc72020-10-19 14:38:18 -0700929 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONN_STATUS_RESULT
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700930 "result=%d ssid=%s channel_list=%s",
931 status, wpa_ssid_txt(ssid, ssid_len),
932 channel_list ? channel_list : "N/A");
933 os_free(channel_list);
934 return -1; /* to remove the completed connection */
935}
936
937
938static int dpp_controller_rx_presence_announcement(struct dpp_connection *conn,
939 const u8 *hdr, const u8 *buf,
940 size_t len)
941{
942 const u8 *r_bootstrap;
943 u16 r_bootstrap_len;
944 struct dpp_bootstrap_info *peer_bi;
945 struct dpp_authentication *auth;
946 struct dpp_global *dpp = conn->ctrl->global;
947
948 if (conn->auth) {
949 wpa_printf(MSG_DEBUG,
950 "DPP: Ignore Presence Announcement during ongoing Authentication");
951 return -1;
952 }
953
954 wpa_printf(MSG_DEBUG, "DPP: Presence Announcement");
955
956 r_bootstrap = dpp_get_attr(buf, len, DPP_ATTR_R_BOOTSTRAP_KEY_HASH,
957 &r_bootstrap_len);
958 if (!r_bootstrap || r_bootstrap_len != SHA256_MAC_LEN) {
Hai Shalom899fcc72020-10-19 14:38:18 -0700959 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700960 "Missing or invalid required Responder Bootstrapping Key Hash attribute");
961 return -1;
962 }
963 wpa_hexdump(MSG_MSGDUMP, "DPP: Responder Bootstrapping Key Hash",
964 r_bootstrap, r_bootstrap_len);
965 peer_bi = dpp_bootstrap_find_chirp(dpp, r_bootstrap);
966 if (!peer_bi) {
967 wpa_printf(MSG_DEBUG,
968 "DPP: No matching bootstrapping information found");
969 return -1;
970 }
971
Hai Shalom899fcc72020-10-19 14:38:18 -0700972 auth = dpp_auth_init(dpp, conn->msg_ctx, peer_bi, NULL,
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700973 DPP_CAPAB_CONFIGURATOR, -1, NULL, 0);
974 if (!auth)
975 return -1;
976 if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
977 dpp_auth_deinit(auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700978 return -1;
979 }
980
981 conn->auth = auth;
982 return dpp_tcp_send_msg(conn, conn->auth->req_msg);
983}
984
985
986static int dpp_controller_rx_reconfig_announcement(struct dpp_connection *conn,
987 const u8 *hdr, const u8 *buf,
988 size_t len)
989{
Hai Shalom899fcc72020-10-19 14:38:18 -0700990 const u8 *csign_hash, *fcgroup, *a_nonce, *e_id;
991 u16 csign_hash_len, fcgroup_len, a_nonce_len, e_id_len;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700992 struct dpp_configurator *conf;
993 struct dpp_global *dpp = conn->ctrl->global;
994 struct dpp_authentication *auth;
Hai Shalom899fcc72020-10-19 14:38:18 -0700995 u16 group;
Hai Shalom4fbc08f2020-05-18 12:37:00 -0700996
997 if (conn->auth) {
998 wpa_printf(MSG_DEBUG,
999 "DPP: Ignore Reconfig Announcement during ongoing Authentication");
1000 return -1;
1001 }
1002
1003 wpa_printf(MSG_DEBUG, "DPP: Reconfig Announcement");
1004
1005 csign_hash = dpp_get_attr(buf, len, DPP_ATTR_C_SIGN_KEY_HASH,
1006 &csign_hash_len);
1007 if (!csign_hash || csign_hash_len != SHA256_MAC_LEN) {
Hai Shalom899fcc72020-10-19 14:38:18 -07001008 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001009 "Missing or invalid required Configurator C-sign key Hash attribute");
1010 return -1;
1011 }
1012 wpa_hexdump(MSG_MSGDUMP, "DPP: Configurator C-sign key Hash (kid)",
1013 csign_hash, csign_hash_len);
1014 conf = dpp_configurator_find_kid(dpp, csign_hash);
1015 if (!conf) {
1016 wpa_printf(MSG_DEBUG,
1017 "DPP: No matching Configurator information found");
1018 return -1;
1019 }
1020
Hai Shalom899fcc72020-10-19 14:38:18 -07001021 fcgroup = dpp_get_attr(buf, len, DPP_ATTR_FINITE_CYCLIC_GROUP,
1022 &fcgroup_len);
1023 if (!fcgroup || fcgroup_len != 2) {
1024 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_FAIL
1025 "Missing or invalid required Finite Cyclic Group attribute");
1026 return -1;
1027 }
1028 group = WPA_GET_LE16(fcgroup);
1029 wpa_printf(MSG_DEBUG, "DPP: Enrollee finite cyclic group: %u", group);
1030
1031 a_nonce = dpp_get_attr(buf, len, DPP_ATTR_A_NONCE, &a_nonce_len);
1032 e_id = dpp_get_attr(buf, len, DPP_ATTR_E_PRIME_ID, &e_id_len);
1033
1034 auth = dpp_reconfig_init(dpp, conn->msg_ctx, conf, 0, group,
1035 a_nonce, a_nonce_len, e_id, e_id_len);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001036 if (!auth)
1037 return -1;
1038 if (dpp_set_configurator(auth, conn->ctrl->configurator_params) < 0) {
1039 dpp_auth_deinit(auth);
1040 return -1;
1041 }
1042
1043 conn->auth = auth;
1044 return dpp_tcp_send_msg(conn, auth->reconfig_req_msg);
1045}
1046
1047
1048static int dpp_controller_rx_reconfig_auth_resp(struct dpp_connection *conn,
1049 const u8 *hdr, const u8 *buf,
1050 size_t len)
1051{
1052 struct dpp_authentication *auth = conn->auth;
1053 struct wpabuf *conf;
1054 int res;
1055
1056 wpa_printf(MSG_DEBUG, "DPP: Reconfig Authentication Response");
1057
1058 if (!auth || !auth->reconfig || !auth->configurator) {
1059 wpa_printf(MSG_DEBUG,
1060 "DPP: No DPP Reconfig Authentication in progress - drop");
1061 return -1;
1062 }
1063
1064 conf = dpp_reconfig_auth_resp_rx(auth, hdr, buf, len);
1065 if (!conf)
1066 return -1;
1067
1068 res = dpp_tcp_send_msg(conn, conf);
1069 wpabuf_free(conf);
1070 return res;
1071}
1072
1073
Hai Shaloma20dcd72022-02-04 13:43:00 -08001074static int dpp_controller_rx_pkex_exchange_req(struct dpp_connection *conn,
1075 const u8 *hdr, const u8 *buf,
1076 size_t len)
1077{
1078 struct dpp_controller *ctrl = conn->ctrl;
1079
1080 if (!ctrl)
1081 return 0;
1082
1083 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Request");
1084
1085 /* TODO: Support multiple PKEX codes by iterating over all the enabled
1086 * values here */
1087
1088 if (!ctrl->pkex_code || !ctrl->pkex_bi) {
1089 wpa_printf(MSG_DEBUG,
1090 "DPP: No PKEX code configured - ignore request");
1091 return 0;
1092 }
1093
1094 if (conn->pkex || conn->auth) {
1095 wpa_printf(MSG_DEBUG,
1096 "DPP: Already in PKEX/Authentication session - ignore new PKEX request");
1097 return 0;
1098 }
1099
Sunil Ravia04bd252022-05-02 22:54:18 -07001100 conn->pkex = dpp_pkex_rx_exchange_req(conn->msg_ctx, ctrl->pkex_bi,
Hai Shaloma20dcd72022-02-04 13:43:00 -08001101 NULL, NULL,
1102 ctrl->pkex_identifier,
1103 ctrl->pkex_code,
Sunil Ravi89eba102022-09-13 21:04:37 -07001104 os_strlen(ctrl->pkex_code),
Hai Shaloma20dcd72022-02-04 13:43:00 -08001105 buf, len, true);
1106 if (!conn->pkex) {
1107 wpa_printf(MSG_DEBUG,
1108 "DPP: Failed to process the request");
1109 return -1;
1110 }
1111
1112 return dpp_tcp_send_msg(conn, conn->pkex->exchange_resp);
1113}
1114
1115
1116static int dpp_controller_rx_pkex_exchange_resp(struct dpp_connection *conn,
1117 const u8 *hdr, const u8 *buf,
1118 size_t len)
1119{
1120 struct dpp_pkex *pkex = conn->pkex;
1121 struct wpabuf *msg;
1122 int res;
1123
1124 wpa_printf(MSG_DEBUG, "DPP: PKEX Exchange Response");
1125
1126 if (!pkex || !pkex->initiator || pkex->exchange_done) {
1127 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1128 return 0;
1129 }
1130
1131 msg = dpp_pkex_rx_exchange_resp(pkex, NULL, buf, len);
1132 if (!msg) {
1133 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1134 return -1;
1135 }
1136
1137 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Request");
1138 res = dpp_tcp_send_msg(conn, msg);
1139 wpabuf_free(msg);
1140 return res;
1141}
1142
1143
1144static int dpp_controller_rx_pkex_commit_reveal_req(struct dpp_connection *conn,
1145 const u8 *hdr,
1146 const u8 *buf, size_t len)
1147{
1148 struct dpp_pkex *pkex = conn->pkex;
1149 struct wpabuf *msg;
1150 int res;
1151 struct dpp_bootstrap_info *bi;
1152
1153 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Request");
1154
1155 if (!pkex || pkex->initiator || !pkex->exchange_done) {
1156 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1157 return 0;
1158 }
1159
1160 msg = dpp_pkex_rx_commit_reveal_req(pkex, hdr, buf, len);
1161 if (!msg) {
1162 wpa_printf(MSG_DEBUG, "DPP: Failed to process the request");
1163 return -1;
1164 }
1165
1166 wpa_printf(MSG_DEBUG, "DPP: Send PKEX Commit-Reveal Response");
1167 res = dpp_tcp_send_msg(conn, msg);
1168 wpabuf_free(msg);
1169 if (res < 0)
1170 return res;
1171 bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
1172 if (!bi)
1173 return -1;
1174 conn->pkex = NULL;
1175 return 0;
1176}
1177
1178
1179static int
1180dpp_controller_rx_pkex_commit_reveal_resp(struct dpp_connection *conn,
1181 const u8 *hdr,
1182 const u8 *buf, size_t len)
1183{
1184 struct dpp_pkex *pkex = conn->pkex;
1185 int res;
1186 struct dpp_bootstrap_info *bi;
1187
1188 wpa_printf(MSG_DEBUG, "DPP: PKEX Commit-Reveal Response");
1189
1190 if (!pkex || !pkex->initiator || !pkex->exchange_done) {
1191 wpa_printf(MSG_DEBUG, "DPP: No matching PKEX session");
1192 return 0;
1193 }
1194
1195 res = dpp_pkex_rx_commit_reveal_resp(pkex, hdr, buf, len);
1196 if (res < 0) {
1197 wpa_printf(MSG_DEBUG, "DPP: Failed to process the response");
1198 return res;
1199 }
1200
1201 bi = dpp_pkex_finish(conn->global, pkex, NULL, 0);
1202 if (!bi)
1203 return -1;
1204 conn->pkex = NULL;
1205
1206 if (!conn->pkex_done)
1207 return -1;
1208 return conn->pkex_done(conn->cb_ctx, conn, bi);
1209}
1210
1211
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001212static int dpp_controller_rx_action(struct dpp_connection *conn, const u8 *msg,
1213 size_t len)
1214{
1215 const u8 *pos, *end;
1216 u8 type;
1217
1218 wpa_printf(MSG_DEBUG, "DPP: Received DPP Action frame over TCP");
1219 pos = msg;
1220 end = msg + len;
1221
1222 if (end - pos < DPP_HDR_LEN ||
1223 WPA_GET_BE24(pos) != OUI_WFA ||
1224 pos[3] != DPP_OUI_TYPE) {
1225 wpa_printf(MSG_DEBUG, "DPP: Unrecognized header");
1226 return -1;
1227 }
1228
1229 if (pos[4] != 1) {
1230 wpa_printf(MSG_DEBUG, "DPP: Unsupported Crypto Suite %u",
1231 pos[4]);
1232 return -1;
1233 }
1234 type = pos[5];
1235 wpa_printf(MSG_DEBUG, "DPP: Received message type %u", type);
1236 pos += DPP_HDR_LEN;
1237
1238 wpa_hexdump(MSG_MSGDUMP, "DPP: Received message attributes",
1239 pos, end - pos);
1240 if (dpp_check_attrs(pos, end - pos) < 0)
1241 return -1;
1242
1243 if (conn->relay) {
1244 wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
1245 conn->relay->tx(conn->relay->cb_ctx, conn->mac_addr,
1246 conn->freq, msg, len);
1247 return 0;
1248 }
1249
1250 switch (type) {
1251 case DPP_PA_AUTHENTICATION_REQ:
1252 return dpp_controller_rx_auth_req(conn, msg, pos, end - pos);
1253 case DPP_PA_AUTHENTICATION_RESP:
1254 return dpp_controller_rx_auth_resp(conn, msg, pos, end - pos);
1255 case DPP_PA_AUTHENTICATION_CONF:
1256 return dpp_controller_rx_auth_conf(conn, msg, pos, end - pos);
1257 case DPP_PA_CONFIGURATION_RESULT:
1258 return dpp_controller_rx_conf_result(conn, msg, pos, end - pos);
1259 case DPP_PA_CONNECTION_STATUS_RESULT:
1260 return dpp_controller_rx_conn_status_result(conn, msg, pos,
1261 end - pos);
1262 case DPP_PA_PRESENCE_ANNOUNCEMENT:
1263 return dpp_controller_rx_presence_announcement(conn, msg, pos,
1264 end - pos);
1265 case DPP_PA_RECONFIG_ANNOUNCEMENT:
1266 return dpp_controller_rx_reconfig_announcement(conn, msg, pos,
1267 end - pos);
1268 case DPP_PA_RECONFIG_AUTH_RESP:
1269 return dpp_controller_rx_reconfig_auth_resp(conn, msg, pos,
1270 end - pos);
Hai Shaloma20dcd72022-02-04 13:43:00 -08001271 case DPP_PA_PKEX_V1_EXCHANGE_REQ:
1272 wpa_printf(MSG_DEBUG,
1273 "DPP: Ignore PKEXv1 Exchange Request - not supported over TCP");
1274 return -1;
1275 case DPP_PA_PKEX_EXCHANGE_REQ:
1276 return dpp_controller_rx_pkex_exchange_req(conn, msg, pos,
1277 end - pos);
1278 case DPP_PA_PKEX_EXCHANGE_RESP:
1279 return dpp_controller_rx_pkex_exchange_resp(conn, msg, pos,
1280 end - pos);
1281 case DPP_PA_PKEX_COMMIT_REVEAL_REQ:
1282 return dpp_controller_rx_pkex_commit_reveal_req(conn, msg, pos,
1283 end - pos);
1284 case DPP_PA_PKEX_COMMIT_REVEAL_RESP:
1285 return dpp_controller_rx_pkex_commit_reveal_resp(conn, msg, pos,
1286 end - pos);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001287 default:
1288 /* TODO: missing messages types */
1289 wpa_printf(MSG_DEBUG,
1290 "DPP: Unsupported frame subtype %d", type);
1291 return -1;
1292 }
1293}
1294
1295
Hai Shalom899fcc72020-10-19 14:38:18 -07001296static int dpp_tcp_send_comeback_delay(struct dpp_connection *conn, u8 action)
1297{
1298 struct wpabuf *buf;
1299 size_t len = 18;
1300
1301 if (action == WLAN_PA_GAS_COMEBACK_RESP)
1302 len++;
1303
1304 buf = wpabuf_alloc(4 + len);
1305 if (!buf)
1306 return -1;
1307
1308 wpabuf_put_be32(buf, len);
1309
1310 wpabuf_put_u8(buf, action);
1311 wpabuf_put_u8(buf, conn->gas_dialog_token);
1312 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
1313 if (action == WLAN_PA_GAS_COMEBACK_RESP)
1314 wpabuf_put_u8(buf, 0);
1315 wpabuf_put_le16(buf, 500); /* GAS Comeback Delay */
1316
1317 dpp_write_adv_proto(buf);
1318 wpabuf_put_le16(buf, 0); /* Query Response Length */
1319
1320 /* Send Config Response over TCP */
1321 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf);
1322 wpabuf_free(conn->msg_out);
1323 conn->msg_out_pos = 0;
1324 conn->msg_out = buf;
1325 dpp_tcp_send(conn);
1326 return 0;
1327}
1328
1329
1330static int dpp_tcp_send_gas_resp(struct dpp_connection *conn, u8 action,
1331 struct wpabuf *resp)
1332{
1333 struct wpabuf *buf;
1334 size_t len;
1335
1336 if (!resp)
1337 return -1;
1338
1339 len = 18 + wpabuf_len(resp);
1340 if (action == WLAN_PA_GAS_COMEBACK_RESP)
1341 len++;
1342
1343 buf = wpabuf_alloc(4 + len);
1344 if (!buf) {
1345 wpabuf_free(resp);
1346 return -1;
1347 }
1348
1349 wpabuf_put_be32(buf, len);
1350
1351 wpabuf_put_u8(buf, action);
1352 wpabuf_put_u8(buf, conn->gas_dialog_token);
1353 wpabuf_put_le16(buf, WLAN_STATUS_SUCCESS);
1354 if (action == WLAN_PA_GAS_COMEBACK_RESP)
1355 wpabuf_put_u8(buf, 0);
1356 wpabuf_put_le16(buf, 0); /* GAS Comeback Delay */
1357
1358 dpp_write_adv_proto(buf);
1359 dpp_write_gas_query(buf, resp);
1360 wpabuf_free(resp);
1361
1362 /* Send Config Response over TCP; GAS fragmentation is taken care of by
1363 * the Relay */
1364 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", buf);
1365 wpabuf_free(conn->msg_out);
1366 conn->msg_out_pos = 0;
1367 conn->msg_out = buf;
1368 conn->on_tcp_tx_complete_gas_done = 1;
1369 dpp_tcp_send(conn);
1370 return 0;
1371}
1372
1373
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001374static int dpp_controller_rx_gas_req(struct dpp_connection *conn, const u8 *msg,
1375 size_t len)
1376{
1377 const u8 *pos, *end, *next;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001378 const u8 *adv_proto;
1379 u16 slen;
Hai Shalom899fcc72020-10-19 14:38:18 -07001380 struct wpabuf *resp;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001381 struct dpp_authentication *auth = conn->auth;
1382
1383 if (len < 1 + 2)
1384 return -1;
1385
1386 wpa_printf(MSG_DEBUG,
1387 "DPP: Received DPP Configuration Request over TCP");
1388
1389 if (!auth || (!conn->ctrl && !auth->configurator) ||
1390 (!auth->auth_success && !auth->reconfig_success)) {
1391 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1392 return -1;
1393 }
1394
Sunil Ravi89eba102022-09-13 21:04:37 -07001395 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_REQ_RX);
1396
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001397 pos = msg;
1398 end = msg + len;
1399
Hai Shalom899fcc72020-10-19 14:38:18 -07001400 conn->gas_dialog_token = *pos++;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001401 adv_proto = pos++;
1402 slen = *pos++;
1403 if (*adv_proto != WLAN_EID_ADV_PROTO ||
1404 slen > end - pos || slen < 2)
1405 return -1;
1406
1407 next = pos + slen;
1408 pos++; /* skip QueryRespLenLimit and PAME-BI */
1409
1410 if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
1411 pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
1412 pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
1413 return -1;
1414
1415 pos = next;
1416 /* Query Request */
1417 if (end - pos < 2)
1418 return -1;
1419 slen = WPA_GET_LE16(pos);
1420 pos += 2;
1421 if (slen > end - pos)
1422 return -1;
1423
1424 resp = dpp_conf_req_rx(auth, pos, slen);
Hai Shalom899fcc72020-10-19 14:38:18 -07001425 if (!resp && auth->waiting_cert) {
1426 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
1427 conn->gas_comeback_in_progress = 1;
1428 return dpp_tcp_send_comeback_delay(conn,
1429 WLAN_PA_GAS_INITIAL_RESP);
1430 }
1431
Hai Shaloma20dcd72022-02-04 13:43:00 -08001432 if (!resp && auth->waiting_config && auth->peer_bi) {
1433 char *buf = NULL, *name = "";
1434 char band[200], *b_pos, *b_end;
1435 int i, res, *opclass = auth->e_band_support;
1436 char *mud_url = "N/A";
1437
1438 wpa_printf(MSG_DEBUG, "DPP: Configuration not yet ready");
1439 if (auth->e_name) {
1440 size_t e_len = os_strlen(auth->e_name);
1441
1442 buf = os_malloc(e_len * 4 + 1);
1443 if (buf) {
1444 printf_encode(buf, len * 4 + 1,
1445 (const u8 *) auth->e_name, e_len);
1446 name = buf;
1447 }
1448 }
1449 band[0] = '\0';
1450 b_pos = band;
1451 b_end = band + sizeof(band);
1452 for (i = 0; opclass && opclass[i]; i++) {
1453 res = os_snprintf(b_pos, b_end - b_pos, "%s%d",
1454 b_pos == band ? "" : ",", opclass[i]);
1455 if (os_snprintf_error(b_end - b_pos, res)) {
1456 *b_pos = '\0';
1457 break;
1458 }
1459 b_pos += res;
1460 }
1461 if (auth->e_mud_url) {
1462 size_t e_len = os_strlen(auth->e_mud_url);
1463
1464 if (!has_ctrl_char((const u8 *) auth->e_mud_url, e_len))
1465 mud_url = auth->e_mud_url;
1466 }
1467 wpa_msg(conn->msg_ctx, MSG_INFO, DPP_EVENT_CONF_NEEDED
1468 "peer=%d net_role=%s name=\"%s\" opclass=%s mud_url=%s",
1469 auth->peer_bi->id, dpp_netrole_str(auth->e_netrole),
1470 name, band, mud_url);
1471 os_free(buf);
1472
1473 conn->gas_comeback_in_progress = 1;
1474 return dpp_tcp_send_comeback_delay(conn,
1475 WLAN_PA_GAS_INITIAL_RESP);
1476 }
1477
Hai Shalom899fcc72020-10-19 14:38:18 -07001478 return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_INITIAL_RESP, resp);
1479}
1480
1481
1482static int dpp_controller_rx_gas_comeback_req(struct dpp_connection *conn,
1483 const u8 *msg, size_t len)
1484{
1485 u8 dialog_token;
1486 struct dpp_authentication *auth = conn->auth;
1487 struct wpabuf *resp;
1488
1489 if (len < 1)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001490 return -1;
1491
Hai Shalom899fcc72020-10-19 14:38:18 -07001492 wpa_printf(MSG_DEBUG,
1493 "DPP: Received DPP Configuration Request over TCP (comeback)");
1494
1495 if (!auth || (!conn->ctrl && !auth->configurator) ||
1496 (!auth->auth_success && !auth->reconfig_success) ||
1497 !conn->gas_comeback_in_progress) {
1498 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001499 return -1;
1500 }
1501
Hai Shalom899fcc72020-10-19 14:38:18 -07001502 dialog_token = msg[0];
1503 if (dialog_token != conn->gas_dialog_token) {
1504 wpa_printf(MSG_DEBUG, "DPP: Dialog token mismatch (%u != %u)",
1505 dialog_token, conn->gas_dialog_token);
1506 return -1;
1507 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001508
Hai Shalom899fcc72020-10-19 14:38:18 -07001509 if (!auth->conf_resp_tcp) {
1510 wpa_printf(MSG_DEBUG, "DPP: Certificate not yet ready");
1511 return dpp_tcp_send_comeback_delay(conn,
1512 WLAN_PA_GAS_COMEBACK_RESP);
1513 }
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001514
Hai Shalom899fcc72020-10-19 14:38:18 -07001515 wpa_printf(MSG_DEBUG,
1516 "DPP: Configuration response is ready to be sent out");
1517 resp = auth->conf_resp_tcp;
1518 auth->conf_resp_tcp = NULL;
1519 return dpp_tcp_send_gas_resp(conn, WLAN_PA_GAS_COMEBACK_RESP, resp);
1520}
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001521
Hai Shalom899fcc72020-10-19 14:38:18 -07001522
1523static void dpp_tcp_build_csr(void *eloop_ctx, void *timeout_ctx)
1524{
1525 struct dpp_connection *conn = eloop_ctx;
1526 struct dpp_authentication *auth = conn->auth;
1527
1528 if (!auth || !auth->csrattrs)
1529 return;
1530
1531 wpa_printf(MSG_DEBUG, "DPP: Build CSR");
1532 wpabuf_free(auth->csr);
1533 /* TODO: Additional information needed for CSR based on csrAttrs */
1534 auth->csr = dpp_build_csr(auth, conn->name ? conn->name : "Test");
1535 if (!auth->csr) {
1536 dpp_connection_remove(conn);
1537 return;
1538 }
1539
1540 dpp_controller_start_gas_client(conn);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001541}
1542
1543
Sunil Ravia04bd252022-05-02 22:54:18 -07001544#ifdef CONFIG_DPP3
1545static void dpp_tcp_build_new_key(void *eloop_ctx, void *timeout_ctx)
1546{
1547 struct dpp_connection *conn = eloop_ctx;
1548 struct dpp_authentication *auth = conn->auth;
1549
1550 if (!auth || !auth->waiting_new_key)
1551 return;
1552
1553 wpa_printf(MSG_DEBUG, "DPP: Build config request with a new key");
1554 dpp_controller_start_gas_client(conn);
1555}
1556#endif /* CONFIG_DPP3 */
1557
1558
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001559static int dpp_tcp_rx_gas_resp(struct dpp_connection *conn, struct wpabuf *resp)
1560{
1561 struct dpp_authentication *auth = conn->auth;
1562 int res;
1563 struct wpabuf *msg;
1564 enum dpp_status_error status;
1565
1566 wpa_printf(MSG_DEBUG,
1567 "DPP: Configuration Response for local stack from TCP");
1568
1569 if (auth)
1570 res = dpp_conf_resp_rx(auth, resp);
1571 else
1572 res = -1;
1573 wpabuf_free(resp);
Hai Shalom899fcc72020-10-19 14:38:18 -07001574 if (res == -2) {
1575 wpa_printf(MSG_DEBUG, "DPP: CSR needed");
1576 eloop_register_timeout(0, 0, dpp_tcp_build_csr, conn, NULL);
1577 return 0;
1578 }
Sunil Ravia04bd252022-05-02 22:54:18 -07001579#ifdef CONFIG_DPP3
1580 if (res == -3) {
1581 wpa_printf(MSG_DEBUG, "DPP: New protocol key needed");
1582 eloop_register_timeout(0, 0, dpp_tcp_build_new_key, conn,
1583 NULL);
1584 return 0;
1585 }
1586#endif /* CONFIG_DPP3 */
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001587 if (res < 0) {
1588 wpa_printf(MSG_DEBUG, "DPP: Configuration attempt failed");
1589 return -1;
1590 }
1591
Hai Shalom899fcc72020-10-19 14:38:18 -07001592 if (conn->process_conf_obj)
1593 res = conn->process_conf_obj(conn->cb_ctx, auth);
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001594 else
1595 res = 0;
1596
1597 if (auth->peer_version < 2 || auth->conf_resp_status != DPP_STATUS_OK)
1598 return -1;
1599
1600 wpa_printf(MSG_DEBUG, "DPP: Send DPP Configuration Result");
1601 status = res < 0 ? DPP_STATUS_CONFIG_REJECTED : DPP_STATUS_OK;
1602 msg = dpp_build_conf_result(auth, status);
1603 if (!msg)
1604 return -1;
1605
1606 conn->on_tcp_tx_complete_remove = 1;
1607 res = dpp_tcp_send_msg(conn, msg);
1608 wpabuf_free(msg);
1609
1610 /* This exchange will be terminated in the TX status handler */
1611
1612 return res;
1613}
1614
1615
Hai Shalom899fcc72020-10-19 14:38:18 -07001616static void dpp_tcp_gas_query_comeback(void *eloop_ctx, void *timeout_ctx)
1617{
1618 struct dpp_connection *conn = eloop_ctx;
1619 struct dpp_authentication *auth = conn->auth;
1620 struct wpabuf *msg;
1621
1622 if (!auth)
1623 return;
1624
1625 wpa_printf(MSG_DEBUG, "DPP: Send GAS Comeback Request");
1626 msg = wpabuf_alloc(4 + 2);
1627 if (!msg)
1628 return;
1629 wpabuf_put_be32(msg, 2);
1630 wpabuf_put_u8(msg, WLAN_PA_GAS_COMEBACK_REQ);
1631 wpabuf_put_u8(msg, conn->gas_dialog_token);
1632 wpa_hexdump_buf(MSG_MSGDUMP, "DPP: Outgoing TCP message", msg);
1633
1634 wpabuf_free(conn->msg_out);
1635 conn->msg_out_pos = 0;
1636 conn->msg_out = msg;
1637 dpp_tcp_send(conn);
1638}
1639
1640
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001641static int dpp_rx_gas_resp(struct dpp_connection *conn, const u8 *msg,
Hai Shalom899fcc72020-10-19 14:38:18 -07001642 size_t len, bool comeback)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001643{
1644 struct wpabuf *buf;
1645 u8 dialog_token;
1646 const u8 *pos, *end, *next, *adv_proto;
Hai Shalom899fcc72020-10-19 14:38:18 -07001647 u16 status, slen, comeback_delay;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001648
Hai Shalom60840252021-02-19 19:02:11 -08001649 if (len < (size_t) (5 + 2 + (comeback ? 1 : 0)))
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001650 return -1;
1651
1652 wpa_printf(MSG_DEBUG,
1653 "DPP: Received DPP Configuration Response over TCP");
1654
1655 pos = msg;
1656 end = msg + len;
1657
1658 dialog_token = *pos++;
1659 status = WPA_GET_LE16(pos);
1660 if (status != WLAN_STATUS_SUCCESS) {
1661 wpa_printf(MSG_DEBUG, "DPP: Unexpected Status Code %u", status);
1662 return -1;
1663 }
1664 pos += 2;
Hai Shalom899fcc72020-10-19 14:38:18 -07001665 if (comeback)
1666 pos++; /* ignore Fragment ID */
1667 comeback_delay = WPA_GET_LE16(pos);
1668 pos += 2;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001669
1670 adv_proto = pos++;
1671 slen = *pos++;
1672 if (*adv_proto != WLAN_EID_ADV_PROTO ||
1673 slen > end - pos || slen < 2)
1674 return -1;
1675
1676 next = pos + slen;
1677 pos++; /* skip QueryRespLenLimit and PAME-BI */
1678
1679 if (slen != 8 || *pos != WLAN_EID_VENDOR_SPECIFIC ||
1680 pos[1] != 5 || WPA_GET_BE24(&pos[2]) != OUI_WFA ||
1681 pos[5] != DPP_OUI_TYPE || pos[6] != 0x01)
1682 return -1;
1683
1684 pos = next;
1685 /* Query Response */
1686 if (end - pos < 2)
1687 return -1;
1688 slen = WPA_GET_LE16(pos);
1689 pos += 2;
1690 if (slen > end - pos)
1691 return -1;
1692
Hai Shalom899fcc72020-10-19 14:38:18 -07001693 if (comeback_delay) {
1694 unsigned int secs, usecs;
1695
1696 conn->gas_dialog_token = dialog_token;
1697 secs = (comeback_delay * 1024) / 1000000;
1698 usecs = comeback_delay * 1024 - secs * 1000000;
1699 wpa_printf(MSG_DEBUG, "DPP: Comeback delay: %u",
1700 comeback_delay);
1701 eloop_cancel_timeout(dpp_tcp_gas_query_comeback, conn, NULL);
1702 eloop_register_timeout(secs, usecs, dpp_tcp_gas_query_comeback,
1703 conn, NULL);
1704 return 0;
1705 }
1706
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001707 buf = wpabuf_alloc(slen);
1708 if (!buf)
1709 return -1;
1710 wpabuf_put_data(buf, pos, slen);
1711
1712 if (!conn->relay &&
1713 (!conn->ctrl || (conn->ctrl->allowed_roles & DPP_CAPAB_ENROLLEE)))
1714 return dpp_tcp_rx_gas_resp(conn, buf);
1715
1716 if (!conn->relay) {
1717 wpa_printf(MSG_DEBUG, "DPP: No matching exchange in progress");
1718 wpabuf_free(buf);
1719 return -1;
1720 }
1721 wpa_printf(MSG_DEBUG, "DPP: Relay - send over WLAN");
1722 conn->relay->gas_resp_tx(conn->relay->cb_ctx, conn->mac_addr,
1723 dialog_token, 0, buf);
1724
1725 return 0;
1726}
1727
1728
1729static void dpp_controller_rx(int sd, void *eloop_ctx, void *sock_ctx)
1730{
1731 struct dpp_connection *conn = eloop_ctx;
1732 int res;
1733 const u8 *pos;
1734
1735 wpa_printf(MSG_DEBUG, "DPP: TCP data available for reading (sock %d)",
1736 sd);
1737
1738 if (conn->msg_len_octets < 4) {
1739 u32 msglen;
1740
1741 res = recv(sd, &conn->msg_len[conn->msg_len_octets],
1742 4 - conn->msg_len_octets, 0);
1743 if (res < 0) {
1744 wpa_printf(MSG_DEBUG, "DPP: recv failed: %s",
1745 strerror(errno));
1746 dpp_connection_remove(conn);
1747 return;
1748 }
1749 if (res == 0) {
1750 wpa_printf(MSG_DEBUG,
1751 "DPP: No more data available over TCP");
1752 dpp_connection_remove(conn);
1753 return;
1754 }
1755 wpa_printf(MSG_DEBUG,
1756 "DPP: Received %d/%d octet(s) of message length field",
1757 res, (int) (4 - conn->msg_len_octets));
1758 conn->msg_len_octets += res;
1759
1760 if (conn->msg_len_octets < 4) {
1761 wpa_printf(MSG_DEBUG,
1762 "DPP: Need %d more octets of message length field",
1763 (int) (4 - conn->msg_len_octets));
1764 return;
1765 }
1766
1767 msglen = WPA_GET_BE32(conn->msg_len);
1768 wpa_printf(MSG_DEBUG, "DPP: Message length: %u", msglen);
1769 if (msglen > 65535) {
1770 wpa_printf(MSG_INFO, "DPP: Unexpectedly long message");
1771 dpp_connection_remove(conn);
1772 return;
1773 }
1774
1775 wpabuf_free(conn->msg);
1776 conn->msg = wpabuf_alloc(msglen);
1777 }
1778
1779 if (!conn->msg) {
1780 wpa_printf(MSG_DEBUG,
1781 "DPP: No buffer available for receiving the message");
1782 dpp_connection_remove(conn);
1783 return;
1784 }
1785
1786 wpa_printf(MSG_DEBUG, "DPP: Need %u more octets of message payload",
1787 (unsigned int) wpabuf_tailroom(conn->msg));
1788
1789 res = recv(sd, wpabuf_put(conn->msg, 0), wpabuf_tailroom(conn->msg), 0);
1790 if (res < 0) {
1791 wpa_printf(MSG_DEBUG, "DPP: recv failed: %s", strerror(errno));
1792 dpp_connection_remove(conn);
1793 return;
1794 }
1795 if (res == 0) {
1796 wpa_printf(MSG_DEBUG, "DPP: No more data available over TCP");
1797 dpp_connection_remove(conn);
1798 return;
1799 }
1800 wpa_printf(MSG_DEBUG, "DPP: Received %d octets", res);
1801 wpabuf_put(conn->msg, res);
1802
1803 if (wpabuf_tailroom(conn->msg) > 0) {
1804 wpa_printf(MSG_DEBUG,
1805 "DPP: Need %u more octets of message payload",
1806 (unsigned int) wpabuf_tailroom(conn->msg));
1807 return;
1808 }
1809
1810 conn->msg_len_octets = 0;
1811 wpa_hexdump_buf(MSG_DEBUG, "DPP: Received TCP message", conn->msg);
1812 if (wpabuf_len(conn->msg) < 1) {
1813 dpp_connection_remove(conn);
1814 return;
1815 }
1816
1817 pos = wpabuf_head(conn->msg);
1818 switch (*pos) {
1819 case WLAN_PA_VENDOR_SPECIFIC:
1820 if (dpp_controller_rx_action(conn, pos + 1,
1821 wpabuf_len(conn->msg) - 1) < 0)
1822 dpp_connection_remove(conn);
1823 break;
1824 case WLAN_PA_GAS_INITIAL_REQ:
1825 if (dpp_controller_rx_gas_req(conn, pos + 1,
1826 wpabuf_len(conn->msg) - 1) < 0)
1827 dpp_connection_remove(conn);
1828 break;
1829 case WLAN_PA_GAS_INITIAL_RESP:
Hai Shalom899fcc72020-10-19 14:38:18 -07001830 case WLAN_PA_GAS_COMEBACK_RESP:
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001831 if (dpp_rx_gas_resp(conn, pos + 1,
Hai Shalom899fcc72020-10-19 14:38:18 -07001832 wpabuf_len(conn->msg) - 1,
1833 *pos == WLAN_PA_GAS_COMEBACK_RESP) < 0)
1834 dpp_connection_remove(conn);
1835 break;
1836 case WLAN_PA_GAS_COMEBACK_REQ:
1837 if (dpp_controller_rx_gas_comeback_req(
1838 conn, pos + 1, wpabuf_len(conn->msg) - 1) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001839 dpp_connection_remove(conn);
1840 break;
1841 default:
1842 wpa_printf(MSG_DEBUG, "DPP: Ignore unsupported message type %u",
1843 *pos);
1844 break;
1845 }
1846}
1847
1848
1849static void dpp_controller_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
1850{
1851 struct dpp_controller *ctrl = eloop_ctx;
1852 struct sockaddr_in addr;
1853 socklen_t addr_len = sizeof(addr);
1854 int fd;
1855 struct dpp_connection *conn;
1856
1857 wpa_printf(MSG_DEBUG, "DPP: New TCP connection");
1858
1859 fd = accept(ctrl->sock, (struct sockaddr *) &addr, &addr_len);
1860 if (fd < 0) {
1861 wpa_printf(MSG_DEBUG,
1862 "DPP: Failed to accept new connection: %s",
1863 strerror(errno));
1864 return;
1865 }
1866 wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d",
1867 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
1868
1869 conn = os_zalloc(sizeof(*conn));
1870 if (!conn)
1871 goto fail;
1872
1873 conn->global = ctrl->global;
1874 conn->ctrl = ctrl;
Hai Shalom899fcc72020-10-19 14:38:18 -07001875 conn->msg_ctx = ctrl->msg_ctx;
1876 conn->cb_ctx = ctrl->cb_ctx;
1877 conn->process_conf_obj = ctrl->process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08001878 conn->tcp_msg_sent = ctrl->tcp_msg_sent;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001879 conn->sock = fd;
Hai Shalom899fcc72020-10-19 14:38:18 -07001880 conn->netrole = ctrl->netrole;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001881
1882 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
1883 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
1884 strerror(errno));
1885 goto fail;
1886 }
1887
1888 if (eloop_register_sock(conn->sock, EVENT_TYPE_READ,
1889 dpp_controller_rx, conn, NULL) < 0)
1890 goto fail;
1891 conn->read_eloop = 1;
1892
1893 /* TODO: eloop timeout to expire connections that do not complete in
1894 * reasonable time */
1895 dl_list_add(&ctrl->conn, &conn->list);
1896 return;
1897
1898fail:
1899 close(fd);
1900 os_free(conn);
1901}
1902
1903
Hai Shaloma20dcd72022-02-04 13:43:00 -08001904int dpp_tcp_pkex_init(struct dpp_global *dpp, struct dpp_pkex *pkex,
1905 const struct hostapd_ip_addr *addr, int port,
1906 void *msg_ctx, void *cb_ctx,
1907 int (*pkex_done)(void *ctx, void *conn,
1908 struct dpp_bootstrap_info *bi))
Hai Shalom4fbc08f2020-05-18 12:37:00 -07001909{
1910 struct dpp_connection *conn;
1911 struct sockaddr_storage saddr;
1912 socklen_t addrlen;
1913 const u8 *hdr, *pos, *end;
1914 char txt[100];
1915
1916 wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
1917 hostapd_ip_txt(addr, txt, sizeof(txt)), port);
1918 if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
1919 addr, port) < 0) {
Hai Shaloma20dcd72022-02-04 13:43:00 -08001920 dpp_pkex_free(pkex);
1921 return -1;
1922 }
1923
1924 conn = os_zalloc(sizeof(*conn));
1925 if (!conn) {
1926 dpp_pkex_free(pkex);
1927 return -1;
1928 }
1929
1930 conn->msg_ctx = msg_ctx;
1931 conn->cb_ctx = cb_ctx;
1932 conn->pkex_done = pkex_done;
1933 conn->global = dpp;
1934 conn->pkex = pkex;
1935 conn->sock = socket(AF_INET, SOCK_STREAM, 0);
1936 if (conn->sock < 0)
1937 goto fail;
1938
1939 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
1940 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
1941 strerror(errno));
1942 goto fail;
1943 }
1944
1945 if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
1946 if (errno != EINPROGRESS) {
1947 wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
1948 strerror(errno));
1949 goto fail;
1950 }
1951
1952 /*
1953 * Continue connecting in the background; eloop will call us
1954 * once the connection is ready (or failed).
1955 */
1956 }
1957
1958 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
1959 dpp_conn_tx_ready, conn, NULL) < 0)
1960 goto fail;
1961 conn->write_eloop = 1;
1962
1963 hdr = wpabuf_head(pkex->exchange_req);
1964 end = hdr + wpabuf_len(pkex->exchange_req);
1965 hdr += 2; /* skip Category and Actiom */
1966 pos = hdr + DPP_HDR_LEN;
1967 conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
1968 if (!conn->msg_out)
1969 goto fail;
1970 /* Message will be sent in dpp_conn_tx_ready() */
1971
1972 /* TODO: eloop timeout to clear a connection if it does not complete
1973 * properly */
1974 dl_list_add(&dpp->tcp_init, &conn->list);
1975 return 0;
1976fail:
1977 dpp_connection_free(conn);
1978 return -1;
1979}
1980
1981
1982static int dpp_tcp_auth_start(struct dpp_connection *conn,
1983 struct dpp_authentication *auth)
1984{
1985 const u8 *hdr, *pos, *end;
1986
1987 hdr = wpabuf_head(auth->req_msg);
1988 end = hdr + wpabuf_len(auth->req_msg);
1989 hdr += 2; /* skip Category and Actiom */
1990 pos = hdr + DPP_HDR_LEN;
1991 conn->msg_out = dpp_tcp_encaps(hdr, pos, end - pos);
1992 if (!conn->msg_out)
1993 return -1;
1994 /* Message will be sent in dpp_conn_tx_ready() */
1995 return 0;
1996}
1997
1998
1999int dpp_tcp_init(struct dpp_global *dpp, struct dpp_authentication *auth,
2000 const struct hostapd_ip_addr *addr, int port, const char *name,
Sunil Ravi89eba102022-09-13 21:04:37 -07002001 enum dpp_netrole netrole, const char *mud_url,
2002 const char *extra_conf_req_name,
2003 const char *extra_conf_req_value,
2004 void *msg_ctx, void *cb_ctx,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002005 int (*process_conf_obj)(void *ctx,
2006 struct dpp_authentication *auth),
2007 bool (*tcp_msg_sent)(void *ctx,
2008 struct dpp_authentication *auth))
2009{
2010 struct dpp_connection *conn;
2011 struct sockaddr_storage saddr;
2012 socklen_t addrlen;
2013 char txt[100];
2014
2015 wpa_printf(MSG_DEBUG, "DPP: Initialize TCP connection to %s port %d",
2016 hostapd_ip_txt(addr, txt, sizeof(txt)), port);
2017 if (dpp_ipaddr_to_sockaddr((struct sockaddr *) &saddr, &addrlen,
2018 addr, port) < 0) {
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002019 dpp_auth_deinit(auth);
2020 return -1;
2021 }
2022
2023 conn = os_zalloc(sizeof(*conn));
2024 if (!conn) {
2025 dpp_auth_deinit(auth);
2026 return -1;
2027 }
2028
Hai Shalom899fcc72020-10-19 14:38:18 -07002029 conn->msg_ctx = msg_ctx;
2030 conn->cb_ctx = cb_ctx;
2031 conn->process_conf_obj = process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002032 conn->tcp_msg_sent = tcp_msg_sent;
Hai Shalom899fcc72020-10-19 14:38:18 -07002033 conn->name = os_strdup(name ? name : "Test");
Sunil Ravi89eba102022-09-13 21:04:37 -07002034 if (mud_url)
2035 conn->mud_url = os_strdup(mud_url);
2036 if (extra_conf_req_name)
2037 conn->extra_conf_req_name = os_strdup(extra_conf_req_name);
2038 if (extra_conf_req_value)
2039 conn->extra_conf_req_value = os_strdup(extra_conf_req_value);
Hai Shalom899fcc72020-10-19 14:38:18 -07002040 conn->netrole = netrole;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002041 conn->global = dpp;
2042 conn->auth = auth;
2043 conn->sock = socket(AF_INET, SOCK_STREAM, 0);
2044 if (conn->sock < 0)
2045 goto fail;
2046
2047 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
2048 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
2049 strerror(errno));
2050 goto fail;
2051 }
2052
2053 if (connect(conn->sock, (struct sockaddr *) &saddr, addrlen) < 0) {
2054 if (errno != EINPROGRESS) {
2055 wpa_printf(MSG_DEBUG, "DPP: Failed to connect: %s",
2056 strerror(errno));
2057 goto fail;
2058 }
2059
2060 /*
2061 * Continue connecting in the background; eloop will call us
2062 * once the connection is ready (or failed).
2063 */
2064 }
2065
2066 if (eloop_register_sock(conn->sock, EVENT_TYPE_WRITE,
2067 dpp_conn_tx_ready, conn, NULL) < 0)
2068 goto fail;
2069 conn->write_eloop = 1;
2070
Hai Shaloma20dcd72022-02-04 13:43:00 -08002071 if (dpp_tcp_auth_start(conn, auth) < 0)
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002072 goto fail;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002073
2074 /* TODO: eloop timeout to clear a connection if it does not complete
2075 * properly */
2076 dl_list_add(&dpp->tcp_init, &conn->list);
2077 return 0;
2078fail:
2079 dpp_connection_free(conn);
2080 return -1;
2081}
2082
2083
Hai Shaloma20dcd72022-02-04 13:43:00 -08002084int dpp_tcp_auth(struct dpp_global *dpp, void *_conn,
2085 struct dpp_authentication *auth, const char *name,
Sunil Ravi89eba102022-09-13 21:04:37 -07002086 enum dpp_netrole netrole, const char *mud_url,
2087 const char *extra_conf_req_name,
2088 const char *extra_conf_req_value,
Hai Shaloma20dcd72022-02-04 13:43:00 -08002089 int (*process_conf_obj)(void *ctx,
2090 struct dpp_authentication *auth),
2091 bool (*tcp_msg_sent)(void *ctx,
2092 struct dpp_authentication *auth))
2093{
2094 struct dpp_connection *conn = _conn;
2095
2096 /* Continue with Authentication exchange on an existing TCP connection.
2097 */
2098 conn->process_conf_obj = process_conf_obj;
2099 conn->tcp_msg_sent = tcp_msg_sent;
2100 os_free(conn->name);
2101 conn->name = os_strdup(name ? name : "Test");
Sunil Ravi89eba102022-09-13 21:04:37 -07002102 os_free(conn->mud_url);
2103 conn->mud_url = mud_url ? os_strdup(mud_url) : NULL;
2104 os_free(conn->extra_conf_req_name);
2105 conn->extra_conf_req_name = extra_conf_req_name ?
2106 os_strdup(extra_conf_req_name) : NULL;
2107 conn->extra_conf_req_value = extra_conf_req_value ?
2108 os_strdup(extra_conf_req_value) : NULL;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002109 conn->netrole = netrole;
2110 conn->auth = auth;
2111
2112 if (dpp_tcp_auth_start(conn, auth) < 0)
2113 return -1;
2114
2115 dpp_conn_tx_ready(conn->sock, conn, NULL);
2116 return 0;
2117}
2118
2119
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002120int dpp_controller_start(struct dpp_global *dpp,
2121 struct dpp_controller_config *config)
2122{
2123 struct dpp_controller *ctrl;
2124 int on = 1;
2125 struct sockaddr_in sin;
2126 int port;
2127
2128 if (!dpp || dpp->controller)
2129 return -1;
2130
2131 ctrl = os_zalloc(sizeof(*ctrl));
2132 if (!ctrl)
2133 return -1;
2134 ctrl->global = dpp;
2135 if (config->configurator_params)
2136 ctrl->configurator_params =
2137 os_strdup(config->configurator_params);
2138 dl_list_init(&ctrl->conn);
2139 ctrl->allowed_roles = config->allowed_roles;
Hai Shalom899fcc72020-10-19 14:38:18 -07002140 ctrl->qr_mutual = config->qr_mutual;
2141 ctrl->netrole = config->netrole;
2142 ctrl->msg_ctx = config->msg_ctx;
2143 ctrl->cb_ctx = config->cb_ctx;
2144 ctrl->process_conf_obj = config->process_conf_obj;
Hai Shaloma20dcd72022-02-04 13:43:00 -08002145 ctrl->tcp_msg_sent = config->tcp_msg_sent;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002146
2147 ctrl->sock = socket(AF_INET, SOCK_STREAM, 0);
2148 if (ctrl->sock < 0)
2149 goto fail;
2150
2151 if (setsockopt(ctrl->sock, SOL_SOCKET, SO_REUSEADDR,
2152 &on, sizeof(on)) < 0) {
2153 wpa_printf(MSG_DEBUG,
2154 "DPP: setsockopt(SO_REUSEADDR) failed: %s",
2155 strerror(errno));
2156 /* try to continue anyway */
2157 }
2158
2159 if (fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0) {
2160 wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s",
2161 strerror(errno));
2162 goto fail;
2163 }
2164
2165 /* TODO: IPv6 */
2166 os_memset(&sin, 0, sizeof(sin));
2167 sin.sin_family = AF_INET;
2168 sin.sin_addr.s_addr = INADDR_ANY;
2169 port = config->tcp_port ? config->tcp_port : DPP_TCP_PORT;
2170 sin.sin_port = htons(port);
2171 if (bind(ctrl->sock, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
2172 wpa_printf(MSG_INFO,
2173 "DPP: Failed to bind Controller TCP port: %s",
2174 strerror(errno));
2175 goto fail;
2176 }
2177 if (listen(ctrl->sock, 10 /* max backlog */) < 0 ||
2178 fcntl(ctrl->sock, F_SETFL, O_NONBLOCK) < 0 ||
2179 eloop_register_sock(ctrl->sock, EVENT_TYPE_READ,
2180 dpp_controller_tcp_cb, ctrl, NULL))
2181 goto fail;
2182
2183 dpp->controller = ctrl;
2184 wpa_printf(MSG_DEBUG, "DPP: Controller started on TCP port %d", port);
2185 return 0;
2186fail:
2187 dpp_controller_free(ctrl);
2188 return -1;
2189}
2190
2191
Sunil Ravia04bd252022-05-02 22:54:18 -07002192int dpp_controller_set_params(struct dpp_global *dpp,
2193 const char *configurator_params)
2194{
2195
2196 if (!dpp || !dpp->controller)
2197 return -1;
2198
2199 if (configurator_params) {
2200 char *val = os_strdup(configurator_params);
2201
2202 if (!val)
2203 return -1;
2204 os_free(dpp->controller->configurator_params);
2205 dpp->controller->configurator_params = val;
2206 } else {
2207 os_free(dpp->controller->configurator_params);
2208 dpp->controller->configurator_params = NULL;
2209 }
2210
2211 return 0;
2212}
2213
2214
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002215void dpp_controller_stop(struct dpp_global *dpp)
2216{
2217 if (dpp) {
2218 dpp_controller_free(dpp->controller);
2219 dpp->controller = NULL;
2220 }
2221}
2222
2223
Hai Shaloma20dcd72022-02-04 13:43:00 -08002224void dpp_controller_stop_for_ctx(struct dpp_global *dpp, void *cb_ctx)
2225{
2226 if (dpp && dpp->controller && dpp->controller->cb_ctx == cb_ctx)
2227 dpp_controller_stop(dpp);
2228}
2229
2230
Hai Shalom899fcc72020-10-19 14:38:18 -07002231static bool dpp_tcp_peer_id_match(struct dpp_authentication *auth,
2232 unsigned int id)
2233{
2234 return auth &&
2235 ((auth->peer_bi && auth->peer_bi->id == id) ||
2236 (auth->tmp_peer_bi && auth->tmp_peer_bi->id == id));
2237}
2238
2239
2240static struct dpp_authentication * dpp_tcp_get_auth(struct dpp_global *dpp,
2241 unsigned int id)
2242{
2243 struct dpp_connection *conn;
2244
2245 dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
2246 if (dpp_tcp_peer_id_match(conn->auth, id))
2247 return conn->auth;
2248 }
2249
2250 return NULL;
2251}
2252
2253
2254struct dpp_authentication * dpp_controller_get_auth(struct dpp_global *dpp,
2255 unsigned int id)
2256{
2257 struct dpp_controller *ctrl = dpp->controller;
2258 struct dpp_connection *conn;
2259
2260 if (!ctrl)
2261 return dpp_tcp_get_auth(dpp, id);
2262
2263 dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
2264 if (dpp_tcp_peer_id_match(conn->auth, id))
2265 return conn->auth;
2266 }
2267
2268 return dpp_tcp_get_auth(dpp, id);
2269}
2270
2271
2272void dpp_controller_new_qr_code(struct dpp_global *dpp,
2273 struct dpp_bootstrap_info *bi)
2274{
2275 struct dpp_controller *ctrl = dpp->controller;
2276 struct dpp_connection *conn;
2277
2278 if (!ctrl)
2279 return;
2280
2281 dl_list_for_each(conn, &ctrl->conn, struct dpp_connection, list) {
2282 struct dpp_authentication *auth = conn->auth;
2283
2284 if (!auth->response_pending ||
2285 dpp_notify_new_qr_code(auth, bi) != 1)
2286 continue;
2287 wpa_printf(MSG_DEBUG,
2288 "DPP: Sending out pending authentication response");
2289 dpp_tcp_send_msg(conn, conn->auth->resp_msg);
2290 }
2291}
2292
2293
Hai Shaloma20dcd72022-02-04 13:43:00 -08002294void dpp_controller_pkex_add(struct dpp_global *dpp,
2295 struct dpp_bootstrap_info *bi,
2296 const char *code, const char *identifier)
2297{
2298 struct dpp_controller *ctrl = dpp->controller;
2299
2300 if (!ctrl)
2301 return;
2302
2303 ctrl->pkex_bi = bi;
2304 os_free(ctrl->pkex_code);
2305 ctrl->pkex_code = code ? os_strdup(code) : NULL;
2306 os_free(ctrl->pkex_identifier);
2307 ctrl->pkex_identifier = identifier ? os_strdup(identifier) : NULL;
2308}
2309
2310
Sunil Ravi89eba102022-09-13 21:04:37 -07002311bool dpp_controller_is_own_pkex_req(struct dpp_global *dpp,
2312 const u8 *buf, size_t len)
2313{
2314 struct dpp_connection *conn;
2315 const u8 *attr_key = NULL;
2316 u16 attr_key_len = 0;
2317
2318 dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
2319 if (!conn->pkex || !conn->pkex->enc_key)
2320 continue;
2321
2322 if (!attr_key) {
2323 attr_key = dpp_get_attr(buf, len,
2324 DPP_ATTR_ENCRYPTED_KEY,
2325 &attr_key_len);
2326 if (!attr_key)
2327 return false;
2328 }
2329
2330 if (attr_key_len == wpabuf_len(conn->pkex->enc_key) &&
2331 os_memcmp(attr_key, wpabuf_head(conn->pkex->enc_key),
2332 attr_key_len) == 0)
2333 return true;
2334 }
2335
2336 return false;
2337}
2338
2339
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002340void dpp_tcp_init_flush(struct dpp_global *dpp)
2341{
2342 struct dpp_connection *conn, *tmp;
2343
2344 dl_list_for_each_safe(conn, tmp, &dpp->tcp_init, struct dpp_connection,
2345 list)
2346 dpp_connection_remove(conn);
2347}
2348
2349
2350static void dpp_relay_controller_free(struct dpp_relay_controller *ctrl)
2351{
2352 struct dpp_connection *conn, *tmp;
Sunil Ravi89eba102022-09-13 21:04:37 -07002353 char txt[100];
2354
2355 wpa_printf(MSG_DEBUG, "DPP: Remove Relay connection to Controller %s",
2356 hostapd_ip_txt(&ctrl->ipaddr, txt, sizeof(txt)));
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002357
2358 dl_list_for_each_safe(conn, tmp, &ctrl->conn, struct dpp_connection,
2359 list)
2360 dpp_connection_remove(conn);
2361 os_free(ctrl);
2362}
2363
2364
2365void dpp_relay_flush_controllers(struct dpp_global *dpp)
2366{
2367 struct dpp_relay_controller *ctrl, *tmp;
2368
2369 if (!dpp)
2370 return;
2371
2372 dl_list_for_each_safe(ctrl, tmp, &dpp->controllers,
2373 struct dpp_relay_controller, list) {
2374 dl_list_del(&ctrl->list);
2375 dpp_relay_controller_free(ctrl);
2376 }
Sunil Ravi89eba102022-09-13 21:04:37 -07002377
2378 if (dpp->tmp_controller) {
2379 dpp_relay_controller_free(dpp->tmp_controller);
2380 dpp->tmp_controller = NULL;
2381 }
2382}
2383
2384
2385void dpp_relay_remove_controller(struct dpp_global *dpp,
2386 const struct hostapd_ip_addr *addr)
2387{
2388 struct dpp_relay_controller *ctrl;
2389
2390 if (!dpp)
2391 return;
2392
2393 dl_list_for_each(ctrl, &dpp->controllers, struct dpp_relay_controller,
2394 list) {
2395 if (hostapd_ip_equal(&ctrl->ipaddr, addr)) {
2396 dl_list_del(&ctrl->list);
2397 dpp_relay_controller_free(ctrl);
2398 return;
2399 }
2400 }
2401
2402 if (dpp->tmp_controller &&
2403 hostapd_ip_equal(&dpp->tmp_controller->ipaddr, addr)) {
2404 dpp_relay_controller_free(dpp->tmp_controller);
2405 dpp->tmp_controller = NULL;
2406 }
2407}
2408
2409
2410static void dpp_relay_tcp_cb(int sd, void *eloop_ctx, void *sock_ctx)
2411{
2412 struct dpp_global *dpp = eloop_ctx;
2413 struct sockaddr_in addr;
2414 socklen_t addr_len = sizeof(addr);
2415 int fd;
2416 struct dpp_relay_controller *ctrl;
2417 struct dpp_connection *conn = NULL;
2418
2419 wpa_printf(MSG_DEBUG, "DPP: New TCP connection (Relay)");
2420
2421 fd = accept(dpp->relay_sock, (struct sockaddr *) &addr, &addr_len);
2422 if (fd < 0) {
2423 wpa_printf(MSG_DEBUG,
2424 "DPP: Failed to accept new connection: %s",
2425 strerror(errno));
2426 return;
2427 }
2428 wpa_printf(MSG_DEBUG, "DPP: Connection from %s:%d",
2429 inet_ntoa(addr.sin_addr), ntohs(addr.sin_port));
2430
2431 ctrl = dpp_relay_controller_get_addr(dpp, &addr);
2432 if (!ctrl && dpp->tmp_controller &&
2433 dl_list_len(&dpp->tmp_controller->conn)) {
2434 char txt[100];
2435
2436 wpa_printf(MSG_DEBUG,
2437 "DPP: Remove a temporaty Controller entry for %s",
2438 hostapd_ip_txt(&dpp->tmp_controller->ipaddr,
2439 txt, sizeof(txt)));
2440 dpp_relay_controller_free(dpp->tmp_controller);
2441 dpp->tmp_controller = NULL;
2442 }
2443 if (!ctrl && !dpp->tmp_controller) {
2444 wpa_printf(MSG_DEBUG, "DPP: Add a temporary Controller entry");
2445 ctrl = os_zalloc(sizeof(*ctrl));
2446 if (!ctrl)
2447 goto fail;
2448 dl_list_init(&ctrl->conn);
2449 ctrl->global = dpp;
2450 ctrl->ipaddr.af = AF_INET;
2451 ctrl->ipaddr.u.v4.s_addr = addr.sin_addr.s_addr;
2452 ctrl->msg_ctx = dpp->relay_msg_ctx;
2453 ctrl->cb_ctx = dpp->relay_cb_ctx;
2454 ctrl->tx = dpp->relay_tx;
2455 ctrl->gas_resp_tx = dpp->relay_gas_resp_tx;
2456 dpp->tmp_controller = ctrl;
2457 }
2458 if (!ctrl) {
2459 wpa_printf(MSG_DEBUG,
2460 "DPP: No Controller found for that address");
2461 goto fail;
2462 }
2463
2464 if (dl_list_len(&ctrl->conn) >= 15) {
2465 wpa_printf(MSG_DEBUG,
2466 "DPP: Too many ongoing Relay connections to the Controller - cannot start a new one");
2467 goto fail;
2468 }
2469
2470 conn = os_zalloc(sizeof(*conn));
2471 if (!conn)
2472 goto fail;
2473
2474 conn->global = ctrl->global;
2475 conn->relay = ctrl;
2476 conn->msg_ctx = ctrl->msg_ctx;
2477 conn->cb_ctx = ctrl->global->cb_ctx;
2478 os_memset(conn->mac_addr, 0xff, ETH_ALEN);
2479 conn->sock = fd;
2480
2481 if (fcntl(conn->sock, F_SETFL, O_NONBLOCK) != 0) {
2482 wpa_printf(MSG_DEBUG, "DPP: fnctl(O_NONBLOCK) failed: %s",
2483 strerror(errno));
2484 goto fail;
2485 }
2486
2487 if (eloop_register_sock(conn->sock, EVENT_TYPE_READ,
2488 dpp_controller_rx, conn, NULL) < 0)
2489 goto fail;
2490 conn->read_eloop = 1;
2491
2492 /* TODO: eloop timeout to expire connections that do not complete in
2493 * reasonable time */
2494 dl_list_add(&ctrl->conn, &conn->list);
2495 return;
2496
2497fail:
2498 close(fd);
2499 os_free(conn);
2500}
2501
2502
2503int dpp_relay_listen(struct dpp_global *dpp, int port,
2504 struct dpp_relay_config *config)
2505{
2506 int s;
2507 int on = 1;
2508 struct sockaddr_in sin;
2509
2510 if (dpp->relay_sock >= 0) {
2511 wpa_printf(MSG_INFO, "DPP: %s(%d) - relay port already opened",
2512 __func__, port);
2513 return -1;
2514 }
2515
2516 s = socket(AF_INET, SOCK_STREAM, 0);
2517 if (s < 0) {
2518 wpa_printf(MSG_INFO,
2519 "DPP: socket(SOCK_STREAM) failed: %s",
2520 strerror(errno));
2521 return -1;
2522 }
2523
2524 if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0) {
2525 wpa_printf(MSG_DEBUG,
2526 "DPP: setsockopt(SO_REUSEADDR) failed: %s",
2527 strerror(errno));
2528 /* try to continue anyway */
2529 }
2530
2531 if (fcntl(s, F_SETFL, O_NONBLOCK) < 0) {
2532 wpa_printf(MSG_INFO, "DPP: fnctl(O_NONBLOCK) failed: %s",
2533 strerror(errno));
2534 close(s);
2535 return -1;
2536 }
2537
2538 /* TODO: IPv6 */
2539 os_memset(&sin, 0, sizeof(sin));
2540 sin.sin_family = AF_INET;
2541 sin.sin_addr.s_addr = INADDR_ANY;
2542 sin.sin_port = htons(port);
2543 if (bind(s, (struct sockaddr *) &sin, sizeof(sin)) < 0) {
2544 wpa_printf(MSG_INFO,
2545 "DPP: Failed to bind Relay TCP port: %s",
2546 strerror(errno));
2547 close(s);
2548 return -1;
2549 }
2550 if (listen(s, 10 /* max backlog */) < 0 ||
2551 fcntl(s, F_SETFL, O_NONBLOCK) < 0 ||
2552 eloop_register_sock(s, EVENT_TYPE_READ, dpp_relay_tcp_cb, dpp,
2553 NULL)) {
2554 close(s);
2555 return -1;
2556 }
2557
2558 dpp->relay_sock = s;
2559 dpp->relay_msg_ctx = config->msg_ctx;
2560 dpp->relay_cb_ctx = config->cb_ctx;
2561 dpp->relay_tx = config->tx;
2562 dpp->relay_gas_resp_tx = config->gas_resp_tx;
2563 wpa_printf(MSG_DEBUG, "DPP: Relay started on TCP port %d", port);
2564 return 0;
2565}
2566
2567
2568void dpp_relay_stop_listen(struct dpp_global *dpp)
2569{
2570 if (!dpp || dpp->relay_sock < 0)
2571 return;
2572 eloop_unregister_sock(dpp->relay_sock, EVENT_TYPE_READ);
2573 close(dpp->relay_sock);
2574 dpp->relay_sock = -1;
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002575}
2576
Hai Shaloma20dcd72022-02-04 13:43:00 -08002577
2578bool dpp_tcp_conn_status_requested(struct dpp_global *dpp)
2579{
2580 struct dpp_connection *conn;
2581
Sunil Ravia04bd252022-05-02 22:54:18 -07002582 if (!dpp)
2583 return false;
2584
Hai Shaloma20dcd72022-02-04 13:43:00 -08002585 dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
2586 if (conn->auth && conn->auth->conn_status_requested)
2587 return true;
2588 }
2589
2590 return false;
2591}
2592
2593
2594static void dpp_tcp_send_conn_status_msg(struct dpp_connection *conn,
2595 enum dpp_status_error result,
2596 const u8 *ssid, size_t ssid_len,
2597 const char *channel_list)
2598{
2599 struct dpp_authentication *auth = conn->auth;
2600 int res;
2601 struct wpabuf *msg;
2602
2603 auth->conn_status_requested = 0;
2604
2605 msg = dpp_build_conn_status_result(auth, result, ssid, ssid_len,
2606 channel_list);
2607 if (!msg) {
2608 dpp_connection_remove(conn);
2609 return;
2610 }
2611
2612 res = dpp_tcp_send_msg(conn, msg);
2613 wpabuf_free(msg);
2614
2615 if (res < 0) {
2616 dpp_connection_remove(conn);
2617 return;
2618 }
2619
2620 /* This exchange will be terminated in the TX status handler */
2621 conn->on_tcp_tx_complete_remove = 1;
2622}
2623
2624
2625void dpp_tcp_send_conn_status(struct dpp_global *dpp,
2626 enum dpp_status_error result,
2627 const u8 *ssid, size_t ssid_len,
2628 const char *channel_list)
2629{
2630 struct dpp_connection *conn;
2631
2632 dl_list_for_each(conn, &dpp->tcp_init, struct dpp_connection, list) {
2633 if (conn->auth && conn->auth->conn_status_requested) {
2634 dpp_tcp_send_conn_status_msg(conn, result, ssid,
2635 ssid_len, channel_list);
2636 break;
2637 }
2638 }
2639}
2640
Hai Shalom4fbc08f2020-05-18 12:37:00 -07002641#endif /* CONFIG_DPP2 */