Hello community, here is the log from the commit of package hostapd for openSUSE:Factory checked in at 2020-09-29 19:05:02 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/hostapd (Old) and /work/SRC/openSUSE:Factory/.hostapd.new.4249 (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "hostapd" Tue Sep 29 19:05:02 2020 rev:39 rq:838564 version:2.9 Changes: -------- --- /work/SRC/openSUSE:Factory/hostapd/hostapd.changes 2020-04-27 23:35:44.531214527 +0200 +++ /work/SRC/openSUSE:Factory/.hostapd.new.4249/hostapd.changes 2020-09-29 19:05:21.438026817 +0200 @@ -1,0 +2,6 @@ +Tue Sep 29 12:52:10 UTC 2020 - Clemens Famulla-Conrad <cfamullacon...@suse.com> + +- Add CVE-2020-12695.patch -- UPnP SUBSCRIBE misbehavior in hostapd WPS AP + (bsc#1172700) + +------------------------------------------------------------------- New: ---- CVE-2020-12695.patch ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ hostapd.spec ++++++ --- /var/tmp/diff_new_pack.uPUe9W/_old 2020-09-29 19:05:22.054027438 +0200 +++ /var/tmp/diff_new_pack.uPUe9W/_new 2020-09-29 19:05:22.054027438 +0200 @@ -30,6 +30,7 @@ Source3: config Source4: hostapd.service Patch1: CVE-2019-16275.patch +Patch2: CVE-2020-12695.patch BuildRequires: libnl3-devel BuildRequires: openssl-devel BuildRequires: pkgconfig ++++++ CVE-2020-12695.patch ++++++ unchanged: --- a/src/wps/wps_er.c +++ b/src/wps/wps_er.c @@ -1298,7 +1298,7 @@ wps_er_init(struct wps_context *wps, const char *ifname, const char *filter) "with %s", filter); } if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text, - er->mac_addr)) { + NULL, er->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", er->ifname); wps_er_deinit(er, NULL, NULL); unchanged: --- b/src/wps/wps_upnp.c +++ b/src/wps/wps_upnp.c @@ -303,6 +303,14 @@ } +static int local_network_addr(struct upnp_wps_device_sm *sm, + struct sockaddr_in *addr) +{ + return (addr->sin_addr.s_addr & sm->netmask.s_addr) == + (sm->ip_addr & sm->netmask.s_addr); +} + + /* subscr_addr_add_url -- add address(es) for one url to subscription */ static void subscr_addr_add_url(struct subscription *s, const char *url, size_t url_len) @@ -320,9 +328,14 @@ int rerr; size_t host_len, path_len; - /* url MUST begin with http: */ - if (url_len < 7 || os_strncasecmp(url, "http://", 7)) + /* URL MUST begin with HTTP scheme. In addition, limit the length of + * the URL to 700 characters which is around the limit that was + * implicitly enforced for more than 10 years due to a bug in + * generating the event messages. */ + if (url_len < 7 || os_strncasecmp(url, "http://", 7) || url_len > 700) { + wpa_printf(MSG_DEBUG, "WPS UPnP: Reject an unacceptable URL"); goto fail; + } url += 7; url_len -= 7; @@ -381,6 +394,7 @@ for (rp = result; rp; rp = rp->ai_next) { struct subscr_addr *a; + struct sockaddr_in *addr = (struct sockaddr_in *) rp->ai_addr; /* Limit no. of address to avoid denial of service attack */ if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) { @@ -389,6 +403,13 @@ break; } + if (!local_network_addr(s->sm, addr)) { + wpa_printf(MSG_INFO, + "WPS UPnP: Ignore a delivery URL that points to another network %s", + inet_ntoa(addr->sin_addr)); + continue; + } + a = os_zalloc(sizeof(*a) + alloc_len); if (a == NULL) break; @@ -890,11 +911,12 @@ * @net_if: Selected network interface name * @ip_addr: Buffer for returning IP address in network byte order * @ip_addr_text: Buffer for returning a pointer to allocated IP address text + * @netmask: Buffer for returning netmask or %NULL if not needed * @mac: Buffer for returning MAC address * Returns: 0 on success, -1 on failure */ int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, - u8 mac[ETH_ALEN]) + struct in_addr *netmask, u8 mac[ETH_ALEN]) { struct ifreq req; int sock = -1; @@ -920,6 +942,19 @@ in_addr.s_addr = *ip_addr; os_snprintf(*ip_addr_text, 16, "%s", inet_ntoa(in_addr)); + if (netmask) { + os_memset(&req, 0, sizeof(req)); + os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); + if (ioctl(sock, SIOCGIFNETMASK, &req) < 0) { + wpa_printf(MSG_ERROR, + "WPS UPnP: SIOCGIFNETMASK failed: %d (%s)", + errno, strerror(errno)); + goto fail; + } + addr = (struct sockaddr_in *) &req.ifr_netmask; + netmask->s_addr = addr->sin_addr.s_addr; + } + #ifdef __linux__ os_strlcpy(req.ifr_name, net_if, sizeof(req.ifr_name)); if (ioctl(sock, SIOCGIFHWADDR, &req) < 0) { @@ -1026,11 +1061,15 @@ /* Determine which IP and mac address we're using */ if (get_netif_info(net_if, &sm->ip_addr, &sm->ip_addr_text, - sm->mac_addr)) { + &sm->netmask, sm->mac_addr)) { wpa_printf(MSG_INFO, "WPS UPnP: Could not get IP/MAC address " "for %s. Does it have IP address?", net_if); goto fail; } + wpa_printf(MSG_DEBUG, "WPS UPnP: Local IP address %s netmask %s hwaddr " + MACSTR, + sm->ip_addr_text, inet_ntoa(sm->netmask), + MAC2STR(sm->mac_addr)); /* Listen for incoming TCP connections so that others * can fetch our "xml files" from us. unchanged: --- a/src/wps/wps_upnp_i.h +++ b/src/wps/wps_upnp_i.h @@ -128,6 +128,7 @@ struct upnp_wps_device_sm { u8 mac_addr[ETH_ALEN]; /* mac addr of network i.f. we use */ char *ip_addr_text; /* IP address of network i.f. we use */ unsigned ip_addr; /* IP address of network i.f. we use (host order) */ + struct in_addr netmask; int multicast_sd; /* send multicast messages over this socket */ int ssdp_sd; /* receive discovery UPD packets on socket */ int ssdp_sd_registered; /* nonzero if we must unregister */ @@ -158,7 +159,7 @@ struct subscription * subscription_find(struct upnp_wps_device_sm *sm, const u8 uuid[UUID_LEN]); void subscr_addr_delete(struct subscr_addr *a); int get_netif_info(const char *net_if, unsigned *ip_addr, char **ip_addr_text, - u8 mac[ETH_ALEN]); + struct in_addr *netmask, u8 mac[ETH_ALEN]); /* wps_upnp_ssdp.c */ void msearchreply_state_machine_stop(struct advertisement_state_machine *a); diff -u b/src/wps/wps_upnp_event.c b/src/wps/wps_upnp_event.c --- b/src/wps/wps_upnp_event.c +++ b/src/wps/wps_upnp_event.c @@ -147,7 +147,8 @@ struct wpabuf *buf; char *b; - buf = wpabuf_alloc(1000 + wpabuf_len(e->data)); + buf = wpabuf_alloc(1000 + os_strlen(e->addr->path) + + wpabuf_len(e->data)); if (buf == NULL) return NULL; wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path); @@ -293,7 +294,7 @@ buf = event_build_message(e); if (buf == NULL) { - event_retry(e, 0); + event_addr_failure(e); return -1; } @@ -301,7 +302,7 @@ event_http_cb, e); if (e->http_event == NULL) { wpabuf_free(buf); - event_retry(e, 0); + event_addr_failure(e); return -1; }