]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
network/ndisc: use the first captive portal in each RA 28328/head
authorYu Watanabe <watanabe.yu+github@gmail.com>
Mon, 10 Jul 2023 04:37:46 +0000 (13:37 +0900)
committerYu Watanabe <watanabe.yu+github@gmail.com>
Thu, 24 Aug 2023 11:01:08 +0000 (20:01 +0900)
To handle malicious RA packets gracefully.

Also prompted by https://github.com/systemd/systemd/pull/28285#issuecomment-1627585140.

src/network/networkd-ndisc.c

index de03abad224e6e2a5d3b4588701d02e2482042c0..ae267ce5ca5131bed1e5b790920286b4ed5dc799 100644 (file)
@@ -900,21 +900,21 @@ static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt)
                 return log_link_warning_errno(link, r, "Failed to get captive portal from RA: %m");
 
         if (len == 0)
-                return 0;
+                return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBADMSG), "Received empty captive portal, ignoring.");
 
         r = make_cstring(uri, len, MAKE_CSTRING_REFUSE_TRAILING_NUL, &captive_portal);
         if (r < 0)
                 return log_link_warning_errno(link, r, "Failed to convert captive portal URI: %m");
 
         if (!in_charset(captive_portal, URI_VALID))
-                return log_link_debug_errno(link, SYNTHETIC_ERRNO(EBADMSG), "Received invalid captive portal, ignoring.");
+                return log_link_warning_errno(link, SYNTHETIC_ERRNO(EBADMSG), "Received invalid captive portal, ignoring.");
 
         exist = set_get(link->ndisc_captive_portals, &(NDiscCaptivePortal) { .captive_portal = captive_portal });
         if (exist) {
                 /* update existing entry */
                 exist->router = router;
                 exist->lifetime_usec = lifetime_usec;
-                return 0;
+                return 1;
         }
 
         if (set_size(link->ndisc_captive_portals) >= NDISC_CAPTIVE_PORTAL_MAX) {
@@ -947,10 +947,11 @@ static int ndisc_router_process_captive_portal(Link *link, sd_ndisc_router *rt)
         TAKE_PTR(new_entry);
 
         link_dirty(link);
-        return 0;
+        return 1;
 }
 
 static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
+        size_t n_captive_portal = 0;
         int r;
 
         assert(link);
@@ -986,7 +987,16 @@ static int ndisc_router_process_options(Link *link, sd_ndisc_router *rt) {
                         r = ndisc_router_process_dnssl(link, rt);
                         break;
                 case SD_NDISC_OPTION_CAPTIVE_PORTAL:
+                        if (n_captive_portal > 0) {
+                                if (n_captive_portal == 1)
+                                        log_link_notice(link, "Received RA with multiple captive portals, only using the first one.");
+
+                                n_captive_portal++;
+                                continue;
+                        }
                         r = ndisc_router_process_captive_portal(link, rt);
+                        if (r > 0)
+                                n_captive_portal++;
                         break;
                 }
                 if (r < 0 && r != -EBADMSG)