Merge tag 'upstream/0.9.2' into debian
[mech_eap.git] / libeap / wpa_supplicant / ctrl_iface_udp.c
diff --git a/libeap/wpa_supplicant/ctrl_iface_udp.c b/libeap/wpa_supplicant/ctrl_iface_udp.c
deleted file mode 100644 (file)
index 110ca4f..0000000
+++ /dev/null
@@ -1,561 +0,0 @@
-/*
- * WPA Supplicant / UDP socket -based control interface
- * Copyright (c) 2004-2005, Jouni Malinen <j@w1.fi>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- * Alternatively, this software may be distributed under the terms of BSD
- * license.
- *
- * See README and COPYING for more details.
- */
-
-#include "includes.h"
-
-#include "common.h"
-#include "eloop.h"
-#include "config.h"
-#include "eapol_supp/eapol_supp_sm.h"
-#include "wpa_supplicant_i.h"
-#include "ctrl_iface.h"
-#include "common/wpa_ctrl.h"
-
-
-#define COOKIE_LEN 8
-
-/* Per-interface ctrl_iface */
-
-/**
- * struct wpa_ctrl_dst - Internal data structure of control interface monitors
- *
- * This structure is used to store information about registered control
- * interface monitors into struct wpa_supplicant. This data is private to
- * ctrl_iface_udp.c and should not be touched directly from other files.
- */
-struct wpa_ctrl_dst {
-       struct wpa_ctrl_dst *next;
-       struct sockaddr_in addr;
-       socklen_t addrlen;
-       int debug_level;
-       int errors;
-};
-
-
-struct ctrl_iface_priv {
-       struct wpa_supplicant *wpa_s;
-       int sock;
-       struct wpa_ctrl_dst *ctrl_dst;
-       u8 cookie[COOKIE_LEN];
-};
-
-
-static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
-                                          int level, const char *buf,
-                                          size_t len);
-
-
-static int wpa_supplicant_ctrl_iface_attach(struct ctrl_iface_priv *priv,
-                                           struct sockaddr_in *from,
-                                           socklen_t fromlen)
-{
-       struct wpa_ctrl_dst *dst;
-
-       dst = os_zalloc(sizeof(*dst));
-       if (dst == NULL)
-               return -1;
-       os_memcpy(&dst->addr, from, sizeof(struct sockaddr_in));
-       dst->addrlen = fromlen;
-       dst->debug_level = MSG_INFO;
-       dst->next = priv->ctrl_dst;
-       priv->ctrl_dst = dst;
-       wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor attached %s:%d",
-                  inet_ntoa(from->sin_addr), ntohs(from->sin_port));
-       return 0;
-}
-
-
-static int wpa_supplicant_ctrl_iface_detach(struct ctrl_iface_priv *priv,
-                                           struct sockaddr_in *from,
-                                           socklen_t fromlen)
-{
-       struct wpa_ctrl_dst *dst, *prev = NULL;
-
-       dst = priv->ctrl_dst;
-       while (dst) {
-               if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
-                   from->sin_port == dst->addr.sin_port) {
-                       if (prev == NULL)
-                               priv->ctrl_dst = dst->next;
-                       else
-                               prev->next = dst->next;
-                       os_free(dst);
-                       wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor detached "
-                                  "%s:%d", inet_ntoa(from->sin_addr),
-                                  ntohs(from->sin_port));
-                       return 0;
-               }
-               prev = dst;
-               dst = dst->next;
-       }
-       return -1;
-}
-
-
-static int wpa_supplicant_ctrl_iface_level(struct ctrl_iface_priv *priv,
-                                          struct sockaddr_in *from,
-                                          socklen_t fromlen,
-                                          char *level)
-{
-       struct wpa_ctrl_dst *dst;
-
-       wpa_printf(MSG_DEBUG, "CTRL_IFACE LEVEL %s", level);
-
-       dst = priv->ctrl_dst;
-       while (dst) {
-               if (from->sin_addr.s_addr == dst->addr.sin_addr.s_addr &&
-                   from->sin_port == dst->addr.sin_port) {
-                       wpa_printf(MSG_DEBUG, "CTRL_IFACE changed monitor "
-                                  "level %s:%d", inet_ntoa(from->sin_addr),
-                                  ntohs(from->sin_port));
-                       dst->debug_level = atoi(level);
-                       return 0;
-               }
-               dst = dst->next;
-       }
-
-       return -1;
-}
-
-
-static char *
-wpa_supplicant_ctrl_iface_get_cookie(struct ctrl_iface_priv *priv,
-                                    size_t *reply_len)
-{
-       char *reply;
-       reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
-       if (reply == NULL) {
-               *reply_len = 1;
-               return NULL;
-       }
-
-       os_memcpy(reply, "COOKIE=", 7);
-       wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
-                        priv->cookie, COOKIE_LEN);
-
-       *reply_len = 7 + 2 * COOKIE_LEN;
-       return reply;
-}
-
-
-static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,
-                                             void *sock_ctx)
-{
-       struct wpa_supplicant *wpa_s = eloop_ctx;
-       struct ctrl_iface_priv *priv = sock_ctx;
-       char buf[256], *pos;
-       int res;
-       struct sockaddr_in from;
-       socklen_t fromlen = sizeof(from);
-       char *reply = NULL;
-       size_t reply_len = 0;
-       int new_attached = 0;
-       u8 cookie[COOKIE_LEN];
-
-       res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
-                      (struct sockaddr *) &from, &fromlen);
-       if (res < 0) {
-               perror("recvfrom(ctrl_iface)");
-               return;
-       }
-       if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
-               /*
-                * The OS networking stack is expected to drop this kind of
-                * frames since the socket is bound to only localhost address.
-                * Just in case, drop the frame if it is coming from any other
-                * address.
-                */
-               wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
-                          "source %s", inet_ntoa(from.sin_addr));
-               return;
-       }
-       buf[res] = '\0';
-
-       if (os_strcmp(buf, "GET_COOKIE") == 0) {
-               reply = wpa_supplicant_ctrl_iface_get_cookie(priv, &reply_len);
-               goto done;
-       }
-
-       /*
-        * Require that the client includes a prefix with the 'cookie' value
-        * fetched with GET_COOKIE command. This is used to verify that the
-        * client has access to a bidirectional link over UDP in order to
-        * avoid attacks using forged localhost IP address even if the OS does
-        * not block such frames from remote destinations.
-        */
-       if (os_strncmp(buf, "COOKIE=", 7) != 0) {
-               wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
-                          "drop request");
-               return;
-       }
-
-       if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
-               wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
-                          "request - drop request");
-               return;
-       }
-
-       if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
-               wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
-                          "drop request");
-               return;
-       }
-
-       pos = buf + 7 + 2 * COOKIE_LEN;
-       while (*pos == ' ')
-               pos++;
-
-       if (os_strcmp(pos, "ATTACH") == 0) {
-               if (wpa_supplicant_ctrl_iface_attach(priv, &from, fromlen))
-                       reply_len = 1;
-               else {
-                       new_attached = 1;
-                       reply_len = 2;
-               }
-       } else if (os_strcmp(pos, "DETACH") == 0) {
-               if (wpa_supplicant_ctrl_iface_detach(priv, &from, fromlen))
-                       reply_len = 1;
-               else
-                       reply_len = 2;
-       } else if (os_strncmp(pos, "LEVEL ", 6) == 0) {
-               if (wpa_supplicant_ctrl_iface_level(priv, &from, fromlen,
-                                                   pos + 6))
-                       reply_len = 1;
-               else
-                       reply_len = 2;
-       } else {
-               reply = wpa_supplicant_ctrl_iface_process(wpa_s, pos,
-                                                         &reply_len);
-       }
-
- done:
-       if (reply) {
-               sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
-                      fromlen);
-               os_free(reply);
-       } else if (reply_len == 1) {
-               sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
-                      fromlen);
-       } else if (reply_len == 2) {
-               sendto(sock, "OK\n", 3, 0, (struct sockaddr *) &from,
-                      fromlen);
-       }
-
-       if (new_attached)
-               eapol_sm_notify_ctrl_attached(wpa_s->eapol);
-}
-
-
-static void wpa_supplicant_ctrl_iface_msg_cb(void *ctx, int level,
-                                            const char *txt, size_t len)
-{
-       struct wpa_supplicant *wpa_s = ctx;
-       if (wpa_s == NULL || wpa_s->ctrl_iface == NULL)
-               return;
-       wpa_supplicant_ctrl_iface_send(wpa_s->ctrl_iface, level, txt, len);
-}
-
-
-struct ctrl_iface_priv *
-wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s)
-{
-       struct ctrl_iface_priv *priv;
-       struct sockaddr_in addr;
-
-       priv = os_zalloc(sizeof(*priv));
-       if (priv == NULL)
-               return NULL;
-       priv->wpa_s = wpa_s;
-       priv->sock = -1;
-       os_get_random(priv->cookie, COOKIE_LEN);
-
-       if (wpa_s->conf->ctrl_interface == NULL)
-               return priv;
-
-       priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
-       if (priv->sock < 0) {
-               perror("socket(PF_INET)");
-               goto fail;
-       }
-
-       os_memset(&addr, 0, sizeof(addr));
-       addr.sin_family = AF_INET;
-       addr.sin_addr.s_addr = htonl((127 << 24) | 1);
-       addr.sin_port = htons(WPA_CTRL_IFACE_PORT);
-       if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-               perror("bind(AF_INET)");
-               goto fail;
-       }
-
-       eloop_register_read_sock(priv->sock, wpa_supplicant_ctrl_iface_receive,
-                                wpa_s, priv);
-       wpa_msg_register_cb(wpa_supplicant_ctrl_iface_msg_cb);
-
-       return priv;
-
-fail:
-       if (priv->sock >= 0)
-               close(priv->sock);
-       os_free(priv);
-       return NULL;
-}
-
-
-void wpa_supplicant_ctrl_iface_deinit(struct ctrl_iface_priv *priv)
-{
-       struct wpa_ctrl_dst *dst, *prev;
-
-       if (priv->sock > -1) {
-               eloop_unregister_read_sock(priv->sock);
-               if (priv->ctrl_dst) {
-                       /*
-                        * Wait a second before closing the control socket if
-                        * there are any attached monitors in order to allow
-                        * them to receive any pending messages.
-                        */
-                       wpa_printf(MSG_DEBUG, "CTRL_IFACE wait for attached "
-                                  "monitors to receive messages");
-                       os_sleep(1, 0);
-               }
-               close(priv->sock);
-               priv->sock = -1;
-       }
-
-       dst = priv->ctrl_dst;
-       while (dst) {
-               prev = dst;
-               dst = dst->next;
-               os_free(prev);
-       }
-       os_free(priv);
-}
-
-
-static void wpa_supplicant_ctrl_iface_send(struct ctrl_iface_priv *priv,
-                                          int level, const char *buf,
-                                          size_t len)
-{
-       struct wpa_ctrl_dst *dst, *next;
-       char levelstr[10];
-       int idx;
-       char *sbuf;
-       int llen;
-
-       dst = priv->ctrl_dst;
-       if (priv->sock < 0 || dst == NULL)
-               return;
-
-       os_snprintf(levelstr, sizeof(levelstr), "<%d>", level);
-
-       llen = os_strlen(levelstr);
-       sbuf = os_malloc(llen + len);
-       if (sbuf == NULL)
-               return;
-
-       os_memcpy(sbuf, levelstr, llen);
-       os_memcpy(sbuf + llen, buf, len);
-
-       idx = 0;
-       while (dst) {
-               next = dst->next;
-               if (level >= dst->debug_level) {
-                       wpa_printf(MSG_DEBUG, "CTRL_IFACE monitor send %s:%d",
-                                  inet_ntoa(dst->addr.sin_addr),
-                                  ntohs(dst->addr.sin_port));
-                       if (sendto(priv->sock, sbuf, llen + len, 0,
-                                  (struct sockaddr *) &dst->addr,
-                                  sizeof(dst->addr)) < 0) {
-                               perror("sendto(CTRL_IFACE monitor)");
-                               dst->errors++;
-                               if (dst->errors > 10) {
-                                       wpa_supplicant_ctrl_iface_detach(
-                                               priv, &dst->addr,
-                                               dst->addrlen);
-                               }
-                       } else
-                               dst->errors = 0;
-               }
-               idx++;
-               dst = next;
-       }
-       os_free(sbuf);
-}
-
-
-void wpa_supplicant_ctrl_iface_wait(struct ctrl_iface_priv *priv)
-{
-       wpa_printf(MSG_DEBUG, "CTRL_IFACE - %s - wait for monitor",
-                  priv->wpa_s->ifname);
-       eloop_wait_for_read_sock(priv->sock);
-}
-
-
-/* Global ctrl_iface */
-
-struct ctrl_iface_global_priv {
-       int sock;
-       u8 cookie[COOKIE_LEN];
-};
-
-
-static char *
-wpa_supplicant_global_get_cookie(struct ctrl_iface_global_priv *priv,
-                                size_t *reply_len)
-{
-       char *reply;
-       reply = os_malloc(7 + 2 * COOKIE_LEN + 1);
-       if (reply == NULL) {
-               *reply_len = 1;
-               return NULL;
-       }
-
-       os_memcpy(reply, "COOKIE=", 7);
-       wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,
-                        priv->cookie, COOKIE_LEN);
-
-       *reply_len = 7 + 2 * COOKIE_LEN;
-       return reply;
-}
-
-
-static void wpa_supplicant_global_ctrl_iface_receive(int sock, void *eloop_ctx,
-                                                    void *sock_ctx)
-{
-       struct wpa_global *global = eloop_ctx;
-       struct ctrl_iface_global_priv *priv = sock_ctx;
-       char buf[256], *pos;
-       int res;
-       struct sockaddr_in from;
-       socklen_t fromlen = sizeof(from);
-       char *reply;
-       size_t reply_len;
-       u8 cookie[COOKIE_LEN];
-
-       res = recvfrom(sock, buf, sizeof(buf) - 1, 0,
-                      (struct sockaddr *) &from, &fromlen);
-       if (res < 0) {
-               perror("recvfrom(ctrl_iface)");
-               return;
-       }
-       if (from.sin_addr.s_addr != htonl((127 << 24) | 1)) {
-               /*
-                * The OS networking stack is expected to drop this kind of
-                * frames since the socket is bound to only localhost address.
-                * Just in case, drop the frame if it is coming from any other
-                * address.
-                */
-               wpa_printf(MSG_DEBUG, "CTRL: Drop packet from unexpected "
-                          "source %s", inet_ntoa(from.sin_addr));
-               return;
-       }
-       buf[res] = '\0';
-
-       if (os_strcmp(buf, "GET_COOKIE") == 0) {
-               reply = wpa_supplicant_global_get_cookie(priv, &reply_len);
-               goto done;
-       }
-
-       if (os_strncmp(buf, "COOKIE=", 7) != 0) {
-               wpa_printf(MSG_DEBUG, "CTLR: No cookie in the request - "
-                          "drop request");
-               return;
-       }
-
-       if (hexstr2bin(buf + 7, cookie, COOKIE_LEN) < 0) {
-               wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie format in the "
-                          "request - drop request");
-               return;
-       }
-
-       if (os_memcmp(cookie, priv->cookie, COOKIE_LEN) != 0) {
-               wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "
-                          "drop request");
-               return;
-       }
-
-       pos = buf + 7 + 2 * COOKIE_LEN;
-       while (*pos == ' ')
-               pos++;
-
-       reply = wpa_supplicant_global_ctrl_iface_process(global, pos,
-                                                        &reply_len);
-
- done:
-       if (reply) {
-               sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from,
-                      fromlen);
-               os_free(reply);
-       } else if (reply_len) {
-               sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,
-                      fromlen);
-       }
-}
-
-
-struct ctrl_iface_global_priv *
-wpa_supplicant_global_ctrl_iface_init(struct wpa_global *global)
-{
-       struct ctrl_iface_global_priv *priv;
-       struct sockaddr_in addr;
-
-       priv = os_zalloc(sizeof(*priv));
-       if (priv == NULL)
-               return NULL;
-       priv->sock = -1;
-       os_get_random(priv->cookie, COOKIE_LEN);
-
-       if (global->params.ctrl_interface == NULL)
-               return priv;
-
-       wpa_printf(MSG_DEBUG, "Global control interface '%s'",
-                  global->params.ctrl_interface);
-
-       priv->sock = socket(PF_INET, SOCK_DGRAM, 0);
-       if (priv->sock < 0) {
-               perror("socket(PF_INET)");
-               goto fail;
-       }
-
-       os_memset(&addr, 0, sizeof(addr));
-       addr.sin_family = AF_INET;
-       addr.sin_addr.s_addr = htonl((127 << 24) | 1);
-       addr.sin_port = htons(WPA_GLOBAL_CTRL_IFACE_PORT);
-       if (bind(priv->sock, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
-               perror("bind(AF_INET)");
-               goto fail;
-       }
-
-       eloop_register_read_sock(priv->sock,
-                                wpa_supplicant_global_ctrl_iface_receive,
-                                global, priv);
-
-       return priv;
-
-fail:
-       if (priv->sock >= 0)
-               close(priv->sock);
-       os_free(priv);
-       return NULL;
-}
-
-
-void
-wpa_supplicant_global_ctrl_iface_deinit(struct ctrl_iface_global_priv *priv)
-{
-       if (priv->sock >= 0) {
-               eloop_unregister_read_sock(priv->sock);
-               close(priv->sock);
-       }
-       os_free(priv);
-}