diff --git a/wpa_supplicant/ctrl_iface.c b/wpa_supplicant/ctrl_iface.c index e0547f16f..90504948a 100644 --- a/wpa_supplicant/ctrl_iface.c +++ b/wpa_supplicant/ctrl_iface.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / Control interface (shared code for all backends) - * Copyright (c) 2004-2019, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -891,6 +891,8 @@ static int wpa_supplicant_ctrl_iface_get(struct wpa_supplicant *wpa_s, if (os_strcmp(cmd, "version") == 0) { res = os_snprintf(buf, buflen, "%s", VERSION_STR); + } else if (os_strcasecmp(cmd, "max_command_len") == 0) { + res = os_snprintf(buf, buflen, "%u", CTRL_IFACE_MAX_LEN); } else if (os_strcasecmp(cmd, "country") == 0) { if (wpa_s->conf->country[0] && wpa_s->conf->country[1]) res = os_snprintf(buf, buflen, "%c%c", diff --git a/wpa_supplicant/ctrl_iface.h b/wpa_supplicant/ctrl_iface.h index d54cc076c..510668d49 100644 --- a/wpa_supplicant/ctrl_iface.h +++ b/wpa_supplicant/ctrl_iface.h @@ -1,6 +1,6 @@ /* * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2005, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -11,6 +11,10 @@ #ifdef CONFIG_CTRL_IFACE +#ifndef CTRL_IFACE_MAX_LEN +#define CTRL_IFACE_MAX_LEN 8192 +#endif /* CTRL_IFACE_MAX_LEN */ + /* Shared functions from ctrl_iface.c; to be called by ctrl_iface backends */ /** diff --git a/wpa_supplicant/ctrl_iface_named_pipe.c b/wpa_supplicant/ctrl_iface_named_pipe.c index 9c0a47e63..79ff7871d 100644 --- a/wpa_supplicant/ctrl_iface_named_pipe.c +++ b/wpa_supplicant/ctrl_iface_named_pipe.c @@ -45,7 +45,7 @@ ConvertStringSecurityDescriptorToSecurityDescriptorA /* Per-interface ctrl_iface */ -#define REQUEST_BUFSIZE 256 +#define REQUEST_BUFSIZE CTRL_IFACE_MAX_LEN #define REPLY_BUFSIZE 4096 struct ctrl_iface_priv; diff --git a/wpa_supplicant/ctrl_iface_udp.c b/wpa_supplicant/ctrl_iface_udp.c index 1e92b9752..1512080d6 100644 --- a/wpa_supplicant/ctrl_iface_udp.c +++ b/wpa_supplicant/ctrl_iface_udp.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / UDP socket -based control interface - * Copyright (c) 2004-2016, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -219,7 +219,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_supplicant *wpa_s = eloop_ctx; struct ctrl_iface_priv *priv = sock_ctx; - char buf[4096], *pos; + char *buf, *pos; int res; #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 struct sockaddr_in6 from; @@ -235,11 +235,15 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, int new_attached = 0; u8 cookie[COOKIE_LEN]; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); return; } @@ -249,6 +253,8 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strcmp(addr, "::1")) { wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", addr); + os_free(buf); + return; } #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { @@ -260,11 +266,17 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, */ wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " "source %s", inet_ntoa(from.sin_addr)); + os_free(buf); return; } #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); + return; + } buf[res] = '\0'; if (os_strcmp(buf, "GET_COOKIE") == 0) { @@ -282,18 +294,21 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strncmp(buf, "COOKIE=", 7) != 0) { wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " "drop request"); + os_free(buf); return; } if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " "request - drop request"); + os_free(buf); return; } if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " "drop request"); + os_free(buf); return; } @@ -339,6 +354,8 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, fromlen); } + os_free(buf); + if (new_attached) eapol_sm_notify_ctrl_attached(wpa_s->eapol); } @@ -600,10 +617,13 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_global *global = eloop_ctx; struct ctrl_iface_global_priv *priv = sock_ctx; - char buf[4096], *pos; + char *buf, *pos; int res; #ifdef CONFIG_CTRL_IFACE_UDP_IPV6 struct sockaddr_in6 from; +#ifndef CONFIG_CTRL_IFACE_UDP_REMOTE + char addr[INET6_ADDRSTRLEN]; +#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ #else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ struct sockaddr_in from; #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ @@ -612,16 +632,28 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, size_t reply_len; u8 cookie[COOKIE_LEN]; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); return; } #ifndef CONFIG_CTRL_IFACE_UDP_REMOTE -#ifndef CONFIG_CTRL_IFACE_UDP_IPV6 +#ifdef CONFIG_CTRL_IFACE_UDP_IPV6 + inet_ntop(AF_INET6, &from.sin6_addr, addr, sizeof(from)); + if (os_strcmp(addr, "::1")) { + wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected source %s", + addr); + os_free(buf); + return; + } +#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */ if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) { /* * The OS networking stack is expected to drop this kind of @@ -631,11 +663,17 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, */ wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected " "source %s", inet_ntoa(from.sin_addr)); + os_free(buf); return; } #endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */ #endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */ + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); + return; + } buf[res] = '\0'; if (os_strcmp(buf, "GET_COOKIE") == 0) { @@ -646,18 +684,21 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, if (os_strncmp(buf, "COOKIE=", 7) != 0) { wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - " "drop request"); + os_free(buf); return; } if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the " "request - drop request"); + os_free(buf); return; } if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) { wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - " "drop request"); + os_free(buf); return; } @@ -694,6 +735,8 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from, fromlen); } + + os_free(buf); } diff --git a/wpa_supplicant/ctrl_iface_unix.c b/wpa_supplicant/ctrl_iface_unix.c index 71fe7ed6b..35a38c95f 100644 --- a/wpa_supplicant/ctrl_iface_unix.c +++ b/wpa_supplicant/ctrl_iface_unix.c @@ -1,6 +1,6 @@ /* * WPA Supplicant / UNIX domain socket -based control interface - * Copyright (c) 2004-2014, Jouni Malinen + * Copyright (c) 2004-2020, Jouni Malinen * * This software may be distributed under the terms of the BSD license. * See README for more details. @@ -131,7 +131,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_supplicant *wpa_s = eloop_ctx; struct ctrl_iface_priv *priv = sock_ctx; - char buf[4096]; + char *buf; int res; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); @@ -139,11 +139,20 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, size_t reply_len = 0; int new_attached = 0; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); + return; + } + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); return; } buf[res] = '\0'; @@ -221,6 +230,7 @@ static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx, } } os_free(reply_buf); + os_free(buf); if (new_attached) eapol_sm_notify_ctrl_attached(wpa_s->eapol); @@ -1046,18 +1056,27 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, { struct wpa_global *global = eloop_ctx; struct ctrl_iface_global_priv *priv = sock_ctx; - char buf[4096]; + char *buf; int res; struct sockaddr_storage from; socklen_t fromlen = sizeof(from); char *reply = NULL, *reply_buf = NULL; size_t reply_len; - res = recvfrom(sock, buf, sizeof(buf) - 1, 0, + buf = os_malloc(CTRL_IFACE_MAX_LEN + 1); + if (!buf) + return; + res = recvfrom(sock, buf, CTRL_IFACE_MAX_LEN, 0, (struct sockaddr *) &from, &fromlen); if (res < 0) { wpa_printf(MSG_ERROR, "recvfrom(ctrl_iface): %s", strerror(errno)); + os_free(buf); + return; + } + if ((size_t) res > CTRL_IFACE_MAX_LEN) { + wpa_printf(MSG_ERROR, "recvform(ctrl_iface): input truncated"); + os_free(buf); return; } buf[res] = '\0'; @@ -1105,6 +1124,7 @@ static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx, } } os_free(reply_buf); + os_free(buf); }