|
26 | 26 |
|
27 | 27 |
|
28 | 28 |
|
| 29 | +struct lws_interceptor_cidr { |
| 30 | + struct lws_interceptor_cidr *next; |
| 31 | + lws_sockaddr46 sa46; |
| 32 | + int len; |
| 33 | +}; |
| 34 | + |
29 | 35 | struct vhd_interceptor { |
30 | 36 | struct lws_context *context; |
31 | 37 | struct lws_vhost *vhost; |
@@ -53,6 +59,7 @@ struct vhd_interceptor { |
53 | 59 | int always_pass; |
54 | 60 |
|
55 | 61 | lws_sorted_usec_list_t sul_stats; |
| 62 | + struct lws_interceptor_cidr *cidr_head; |
56 | 63 | int stats_logging; |
57 | 64 | }; |
58 | 65 |
|
@@ -274,9 +281,28 @@ lws_interceptor_check(struct lws *wsi, const struct lws_protocols *prot) |
274 | 281 |
|
275 | 282 | lws_get_peer_simple(wsi, ip, sizeof(ip)); |
276 | 283 | if (strcmp(sub_claim, ip)) { |
277 | | - lwsl_notice("%s: IP mismatch %s vs %s\n", __func__, sub_claim, ip); |
278 | | - lws_interceptor_inject_header(wsi, vhd, NULL); |
279 | | - return vhd->always_pass ? 0 : 1; |
| 284 | + struct lws_interceptor_cidr *cidr = vhd->cidr_head; |
| 285 | + lws_sockaddr46 sa46; |
| 286 | + int allow = 0; |
| 287 | + |
| 288 | + lws_get_peer_addresses(wsi, lws_get_socket_fd(wsi), |
| 289 | + NULL, 0, ip, sizeof(ip)); |
| 290 | + |
| 291 | + if (!lws_sa46_parse_numeric_address(ip, &sa46)) { |
| 292 | + while (cidr) { |
| 293 | + if (!lws_sa46_on_net(&sa46, &cidr->sa46, cidr->len)) { |
| 294 | + allow = 1; |
| 295 | + break; |
| 296 | + } |
| 297 | + cidr = cidr->next; |
| 298 | + } |
| 299 | + } |
| 300 | + |
| 301 | + if (!allow) { |
| 302 | + lwsl_notice("%s: IP mismatch %s vs %s\n", __func__, sub_claim, ip); |
| 303 | + lws_interceptor_inject_header(wsi, vhd, NULL); |
| 304 | + return vhd->always_pass ? 0 : 1; |
| 305 | + } |
280 | 306 | } |
281 | 307 |
|
282 | 308 | lwsl_notice("%s: valid JWT for %s: exp %lu, now %lu (expires in %lds)\n", |
@@ -519,6 +545,7 @@ lws_callback_interceptor(struct lws *wsi, enum lws_callback_reasons reason, |
519 | 545 | struct vhd_interceptor *vhd = (struct vhd_interceptor *)lws_protocol_vh_priv_get( |
520 | 546 | lws_get_vhost(wsi), lws_get_protocol(wsi)); |
521 | 547 | struct pss_interceptor *pss = (struct pss_interceptor *)user; |
| 548 | + const struct lws_protocol_vhost_options *pvo; |
522 | 549 | const char *cp; |
523 | 550 |
|
524 | 551 | switch (reason) { |
@@ -588,12 +615,41 @@ lws_callback_interceptor(struct lws *wsi, enum lws_callback_reasons reason, |
588 | 615 |
|
589 | 616 | if (!lws_pvo_get_str(in, "always-pass", &cp)) |
590 | 617 | vhd->always_pass = !!atoi(cp); |
| 618 | + |
| 619 | + pvo = lws_pvo_search(in, "cidr-allow"); |
| 620 | + while (pvo) { |
| 621 | + struct lws_interceptor_cidr *cidr = |
| 622 | + malloc(sizeof(*cidr)); |
| 623 | + |
| 624 | + if (!cidr) { |
| 625 | + lwsl_err("%s: OOM\n", __func__); |
| 626 | + return -1; |
| 627 | + } |
| 628 | + |
| 629 | + if (lws_parse_cidr(pvo->value, &cidr->sa46, &cidr->len)) { |
| 630 | + lwsl_err("%s: Bad CIDR %s\n", __func__, |
| 631 | + pvo->value); |
| 632 | + free(cidr); |
| 633 | + return -1; |
| 634 | + } |
| 635 | + |
| 636 | + cidr->next = vhd->cidr_head; |
| 637 | + vhd->cidr_head = cidr; |
| 638 | + |
| 639 | + pvo = lws_pvo_search(pvo->next, "cidr-allow"); |
| 640 | + } |
591 | 641 | break; |
592 | 642 |
|
593 | 643 | case LWS_CALLBACK_PROTOCOL_DESTROY: |
594 | 644 | if (vhd) { |
595 | 645 | lws_sul_cancel(&vhd->sul_stats); |
596 | 646 | lws_jwk_destroy(&vhd->jwk); |
| 647 | + while (vhd->cidr_head) { |
| 648 | + struct lws_interceptor_cidr *cidr = vhd->cidr_head; |
| 649 | + |
| 650 | + vhd->cidr_head = cidr->next; |
| 651 | + free(cidr); |
| 652 | + } |
597 | 653 | } |
598 | 654 | break; |
599 | 655 |
|
|
0 commit comments