1 From 5b78c8f961f25f4dc22d6f2b77ddd06d712cec63 Mon Sep 17 00:00:00 2001
2 From: Jouni Malinen <jouni@codeaurora.org>
3 Date: Wed, 3 Jun 2020 23:17:35 +0300
4 Subject: [PATCH 1/3] WPS UPnP: Do not allow event subscriptions with URLs to
7 The UPnP Device Architecture 2.0 specification errata ("UDA errata
8 16-04-2020.docx") addresses a problem with notifications being allowed
9 to go out to other domains by disallowing such cases. Do such filtering
10 for the notification callback URLs to avoid undesired connections to
11 external networks based on subscriptions that any device in the local
12 network could request when WPS support for external registrars is
13 enabled (the upnp_iface parameter in hostapd configuration).
15 Upstream-Status: Backport
16 CVE: CVE-2020-12695 patch #1
17 Signed-off-by: Jouni Malinen <jouni@codeaurora.org>
18 Signed-off-by: Armin Kuster <akuster@mvista.com>
21 src/wps/wps_er.c | 2 +-
22 src/wps/wps_upnp.c | 38 ++++++++++++++++++++++++++++++++++++--
23 src/wps/wps_upnp_i.h | 3 ++-
24 3 files changed, 39 insertions(+), 4 deletions(-)
26 Index: wpa_supplicant-2.9/src/wps/wps_er.c
27 ===================================================================
28 --- wpa_supplicant-2.9.orig/src/wps/wps_er.c
29 +++ wpa_supplicant-2.9/src/wps/wps_er.c
30 @@ -1298,7 +1298,7 @@ wps_er_init(struct wps_context *wps, con
33 if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text,
35 + NULL, er->mac_addr)) {
36 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
37 "for %s. Does it have IP address?", er->ifname);
38 wps_er_deinit(er, NULL, NULL);
39 Index: wpa_supplicant-2.9/src/wps/wps_upnp.c
40 ===================================================================
41 --- wpa_supplicant-2.9.orig/src/wps/wps_upnp.c
42 +++ wpa_supplicant-2.9/src/wps/wps_upnp.c
43 @@ -303,6 +303,14 @@ static void subscr_addr_free_all(struct
47 +static int local_network_addr(struct upnp_wps_device_sm *sm,
48 + struct sockaddr_in *addr)
50 + return (addr->sin_addr.s_addr & sm->netmask.s_addr) ==
51 + (sm->ip_addr & sm->netmask.s_addr);
55 /* subscr_addr_add_url -- add address(es) for one url to subscription */
56 static void subscr_addr_add_url(struct subscription *s, const char *url,
58 @@ -381,6 +389,7 @@ static void subscr_addr_add_url(struct s
60 for (rp = result; rp; rp = rp->ai_next) {
61 struct subscr_addr *a;
62 + struct sockaddr_in *addr = (struct sockaddr_in *) rp->ai_addr;
64 /* Limit no. of address to avoid denial of service attack */
65 if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) {
66 @@ -389,6 +398,13 @@ static void subscr_addr_add_url(struct s
70 + if (!local_network_addr(s->sm, addr)) {
71 + wpa_printf(MSG_INFO,
72 + "WPS UPnP: Ignore a delivery URL that points to another network %s",
73 + inet_ntoa(addr->sin_addr));
77 a = os_zalloc(sizeof(*a) + alloc_len);
80 @@ -889,11 +905,12 @@ static int eth_get(const char *device, u
81 * @net_if: Selected network interface name
82 * @ip_addr: Buffer for returning IP address in network byte order
83 * @ip_addr_text: Buffer for returning a pointer to allocated IP address text
84 + * @netmask: Buffer for returning netmask or %NULL if not needed
85 * @mac: Buffer for returning MAC address
86 * Returns: 0 on success, -1 on failure
88 int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text,
90 + struct in_addr *netmask, u8 mac[ETH_ALEN])
94 @@ -919,6 +936,19 @@ int get_netif_info(const char *net_if, u
95 in_addr.s_addr = *ip_addr;
96 os_snprintf(*ip_addr_text, 16, "%s", inet_ntoa(in_addr));
99 + os_memset(&req, 0, sizeof(req));
100 + os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name));
101 + if (ioctl(sock, SIOCGIFNETMASK, &req) < 0) {
102 + wpa_printf(MSG_ERROR,
103 + "WPS UPnP: SIOCGIFNETMASK failed: %d (%s)",
104 + errno, strerror(errno));
107 + addr = (struct sockaddr_in *) &req.ifr_netmask;
108 + netmask->s_addr = addr->sin_addr.s_addr;
112 os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name));
113 if (ioctl(sock, SIOCGIFHWADDR, &req) < 0) {
114 @@ -1025,11 +1055,15 @@ static int upnp_wps_device_start(struct
116 /* Determine which IP and mac address we're using */
117 if (get_netif_info(net_if, &sm->ip_addr, &sm->ip_addr_text,
119 + &sm->netmask, sm->mac_addr)) {
120 wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address "
121 "for %s. Does it have IP address?", net_if);
124 + wpa_printf(MSG_DEBUG, "WPS UPnP: Local IP address %s netmask %s hwaddr "
126 + sm->ip_addr_text, inet_ntoa(sm->netmask),
127 + MAC2STR(sm->mac_addr));
129 /* Listen for incoming TCP connections so that others
130 * can fetch our "xml files" from us.
131 Index: wpa_supplicant-2.9/src/wps/wps_upnp_i.h
132 ===================================================================
133 --- wpa_supplicant-2.9.orig/src/wps/wps_upnp_i.h
134 +++ wpa_supplicant-2.9/src/wps/wps_upnp_i.h
135 @@ -128,6 +128,7 @@ struct upnp_wps_device_sm {
136 u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */
137 char *ip_addr_text; /* IP address of network i.f. we use */
138 unsigned ip_addr; /* IP address of network i.f. we use (host order) */
139 + struct in_addr netmask;
140 int multicast_sd; /* send multicast messages over this socket */
141 int ssdp_sd; /* receive discovery UPD packets on socket */
142 int ssdp_sd_registered; /* nonzero if we must unregister */
143 @@ -158,7 +159,7 @@ struct subscription * subscription_find(
144 const u8 uuid[UUID_LEN]);
145 void subscr_addr_delete(struct subscr_addr *a);
146 int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text,
148 + struct in_addr *netmask, u8 mac[ETH_ALEN]);
150 /* wps_upnp_ssdp.c */
151 void msearchreply_state_machine_stop(struct advertisement_state_machine *a);