]> git.ipfire.org Git - thirdparty/hostap.git/commitdiff
Increase wpa_supplicant control interface buffer size
authorJouni Malinen <j@w1.fi>
Sat, 2 May 2020 18:58:59 +0000 (21:58 +0300)
committerJouni Malinen <j@w1.fi>
Sun, 3 May 2020 09:16:29 +0000 (12:16 +0300)
Increase the maximum command length from 4 kB to 8 kB mainly to allow
larger certificate blobs to be configured. Use heap memory to avoid
inconveniently large stack requirements. In addition, reject potentially
truncated commands instead of trying to process them.

The maximum length of the request can now be determined with
"GET max_command_len".

Signed-off-by: Jouni Malinen <j@w1.fi>
wpa_supplicant/ctrl_iface.c
wpa_supplicant/ctrl_iface.h
wpa_supplicant/ctrl_iface_named_pipe.c
wpa_supplicant/ctrl_iface_udp.c
wpa_supplicant/ctrl_iface_unix.c

index e0547f16f01f086ea17614a8777088ec96807950..90504948a7251765ac342657351d3dffc1f12ca8 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / Control interface (shared code for all backends)
- * Copyright (c) 2004-2019, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
  *
  * 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",
index d54cc076c4476ecc70b194ef37f2806407659591..510668d49353eff2b83d726ed03f5d3884bfa48e 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / UNIX domain socket -based control interface
- * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
  *
  * This software may be distributed under the terms of the BSD license.
  * See README for more details.
 
 #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 */
 
 /**
index 9c0a47e63936b129d41c8438f690eb9e26c714e4..79ff7871db8d4443db38df1f284ed15e03e50679 100644 (file)
@@ -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;
index 1e92b975276fbd37d58acad221a95fbf24d41be5..1512080d6b3b772e73a7c5fce3e7c7c0754d3c10 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / UDP socket -based control interface
- * Copyright (c) 2004-2016, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
  *
  * 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);
 }
 
 
index 71fe7ed6bef50217f2d3512d3f8049785de948dd..35a38c95f2a8c5ab489ce4fe62fd29ae1fe42720 100644 (file)
@@ -1,6 +1,6 @@
 /*
  * WPA Supplicant / UNIX domain socket -based control interface
- * Copyright (c) 2004-2014, Jouni Malinen <j@w1.fi>
+ * Copyright (c) 2004-2020, Jouni Malinen <j@w1.fi>
  *
  * 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);
 }