ctrl_iface.c

来自「WPA在Linux下实现的原代码 WPA在Linux下实现的原代码」· C语言 代码 · 共 2,029 行 · 第 1/4 页

C
2,029
字号
		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {			ret = snprintf(pos, end - pos, " WPA-EAP");			if (ret < 0 || ret >= end - pos)				return pos - buf;			pos += ret;		}		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK |				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {			ret = snprintf(pos, end - pos, " WPA-PSK");			if (ret < 0 || ret >= end - pos)				return pos - buf;			pos += ret;		}		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {			ret = snprintf(pos, end - pos, " WPA-NONE");			if (ret < 0 || ret >= end - pos)				return pos - buf;			pos += ret;		}		return pos - buf;	}	if (strcmp(field, "proto") == 0) {		if (res < 0) {			ret = snprintf(buf, buflen, "RSN WPA");			if (ret < 0 || (size_t) ret >= buflen)				return -1;			return ret;		}		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA2 |				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2_PSK)) {			ret = snprintf(pos, end - pos, "%sRSN",				       first ? "" : " ");			if (ret < 0 || ret >= end - pos)				return pos - buf;			pos += ret;			first = 0;		}		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |				     WPA_DRIVER_CAPA_KEY_MGMT_WPA_PSK)) {			ret = snprintf(pos, end - pos, "%sWPA",				       first ? "" : " ");			if (ret < 0 || ret >= end - pos)				return pos - buf;			pos += ret;			first = 0;		}		return pos - buf;	}	if (strcmp(field, "auth_alg") == 0) {		if (res < 0) {			ret = snprintf(buf, buflen, "OPEN SHARED LEAP");			if (ret < 0 || (size_t) ret >= buflen)				return -1;			return ret;		}		if (capa.auth & (WPA_DRIVER_AUTH_OPEN)) {			ret = snprintf(pos, end - pos, "%sOPEN",				       first ? "" : " ");			if (ret < 0 || ret >= end - pos)				return pos - buf;			pos += ret;			first = 0;		}		if (capa.auth & (WPA_DRIVER_AUTH_SHARED)) {			ret = snprintf(pos, end - pos, "%sSHARED",				       first ? "" : " ");			if (ret < 0 || ret >= end - pos)				return pos - buf;			pos += ret;			first = 0;		}		if (capa.auth & (WPA_DRIVER_AUTH_LEAP)) {			ret = snprintf(pos, end - pos, "%sLEAP",				       first ? "" : " ");			if (ret < 0 || ret >= end - pos)				return pos - buf;			pos += ret;			first = 0;		}		return pos - buf;	}	wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown GET_CAPABILITY field '%s'",		   field);	return -1;}#ifdef CONFIG_CTRL_IFACE_UDPstatic char *wpa_supplicant_ctrl_iface_get_cookie(struct wpa_supplicant *wpa_s,				     size_t *reply_len){	char *reply;	reply = malloc(7 + 2 * COOKIE_LEN + 1);	if (reply == NULL) {		*reply_len = 1;		return NULL;	}	memcpy(reply, "COOKIE=", 7);	wpa_snprintf_hex(reply + 7, 2 * COOKIE_LEN + 1,			 wpa_s->cookie, COOKIE_LEN);	*reply_len = 7 + 2 * COOKIE_LEN;	return reply;}#endif /* CONFIG_CTRL_IFACE_UDP */static void wpa_supplicant_ctrl_iface_receive(int sock, void *eloop_ctx,					      void *sock_ctx){	struct wpa_supplicant *wpa_s = eloop_ctx;	char _buf[256], *buf = _buf;	int res;	CTRL_IFACE_SOCK from;	socklen_t fromlen = sizeof(from);	char *reply;	const int reply_size = 2048;	int reply_len;	int new_attached = 0, ctrl_rsp = 0;#ifdef CONFIG_CTRL_IFACE_UDP	u8 cookie[COOKIE_LEN];#endif /* CONFIG_CTRL_IFACE_UDP */	res = recvfrom(sock, _buf, sizeof(_buf) - 1, 0,		       (struct sockaddr *) &from, &fromlen);	if (res < 0) {		perror("recvfrom(ctrl_iface)");		return;	}#ifdef CONFIG_CTRL_IFACE_UDP	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;	}#endif /* CONFIG_CTRL_IFACE_UDP */	buf[res] = '\0';#ifdef CONFIG_CTRL_IFACE_UDP	if (strcmp(buf, "GET_COOKIE") == 0) {		reply = wpa_supplicant_ctrl_iface_get_cookie(wpa_s,							     &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 (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 (memcmp(cookie, wpa_s->cookie, COOKIE_LEN) != 0) {		wpa_printf(MSG_DEBUG, "CTLR: Invalid cookie in the request - "			   "drop request");		return;	}	buf += 7 + 2 * COOKIE_LEN;	while (*buf == ' ')		buf++;#endif /* CONFIG_CTRL_IFACE_UDP */	if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0 ||	    strncmp(buf, "SET_NETWORK ", 12) == 0) {		wpa_hexdump_ascii_key(MSG_DEBUG, "RX ctrl_iface",				      (u8 *) _buf, res);	} else {		wpa_hexdump_ascii(MSG_DEBUG, "RX ctrl_iface", (u8 *) _buf,				  res);	}	reply = malloc(reply_size);	if (reply == NULL) {		sendto(sock, "FAIL\n", 5, 0, (struct sockaddr *) &from,		       fromlen);		return;	}	memcpy(reply, "OK\n", 3);	reply_len = 3;	if (strcmp(buf, "PING") == 0) {		memcpy(reply, "PONG\n", 5);		reply_len = 5;	} else if (strcmp(buf, "MIB") == 0) {		reply_len = wpa_sm_get_mib(wpa_s->wpa, reply, reply_size);		if (reply_len >= 0) {			res = eapol_sm_get_mib(wpa_s->eapol, reply + reply_len,					       reply_size - reply_len);			if (res < 0)				reply_len = -1;			else				reply_len += res;		}	} else if (strncmp(buf, "STATUS", 6) == 0) {		reply_len = wpa_supplicant_ctrl_iface_status(			wpa_s, buf + 6, reply, reply_size);	} else if (strcmp(buf, "PMKSA") == 0) {		reply_len = pmksa_cache_list(wpa_s->wpa, reply, reply_size);	} else if (strncmp(buf, "SET ", 4) == 0) {		if (wpa_supplicant_ctrl_iface_set(wpa_s, buf + 4))			reply_len = -1;	} else if (strcmp(buf, "LOGON") == 0) {		eapol_sm_notify_logoff(wpa_s->eapol, FALSE);	} else if (strcmp(buf, "LOGOFF") == 0) {		eapol_sm_notify_logoff(wpa_s->eapol, TRUE);	} else if (strcmp(buf, "REASSOCIATE") == 0) {		wpa_s->disconnected = 0;		wpa_s->reassociate = 1;		wpa_supplicant_req_scan(wpa_s, 0, 0);	} else if (strncmp(buf, "PREAUTH ", 8) == 0) {		if (wpa_supplicant_ctrl_iface_preauth(wpa_s, buf + 8))			reply_len = -1;	} else if (strcmp(buf, "ATTACH") == 0) {		if (wpa_supplicant_ctrl_iface_attach(wpa_s, &from, fromlen))			reply_len = -1;		else			new_attached = 1;	} else if (strcmp(buf, "DETACH") == 0) {		if (wpa_supplicant_ctrl_iface_detach(wpa_s, &from, fromlen))			reply_len = -1;	} else if (strncmp(buf, "LEVEL ", 6) == 0) {		if (wpa_supplicant_ctrl_iface_level(wpa_s, &from, fromlen,						    buf + 6))			reply_len = -1;	} else if (strncmp(buf, WPA_CTRL_RSP, strlen(WPA_CTRL_RSP)) == 0) {		if (wpa_supplicant_ctrl_iface_ctrl_rsp(			    wpa_s, buf + strlen(WPA_CTRL_RSP)))			reply_len = -1;		else			ctrl_rsp = 1;	} else if (strcmp(buf, "RECONFIGURE") == 0) {		if (wpa_supplicant_reload_configuration(wpa_s))			reply_len = -1;	} else if (strcmp(buf, "TERMINATE") == 0) {		eloop_terminate();	} else if (strncmp(buf, "BSSID ", 6) == 0) {		if (wpa_supplicant_ctrl_iface_bssid(wpa_s, buf + 6))			reply_len = -1;	} else if (strcmp(buf, "LIST_NETWORKS") == 0) {		reply_len = wpa_supplicant_ctrl_iface_list_networks(			wpa_s, reply, reply_size);	} else if (strcmp(buf, "DISCONNECT") == 0) {		wpa_s->reassociate = 0;		wpa_s->disconnected = 1;		wpa_supplicant_disassociate(wpa_s, REASON_DEAUTH_LEAVING);	} else if (strcmp(buf, "SCAN") == 0) {		wpa_s->scan_req = 2;		wpa_supplicant_req_scan(wpa_s, 0, 0);	} else if (strcmp(buf, "SCAN_RESULTS") == 0) {		reply_len = wpa_supplicant_ctrl_iface_scan_results(			wpa_s, reply, reply_size);	} else if (strncmp(buf, "SELECT_NETWORK ", 15) == 0) {		if (wpa_supplicant_ctrl_iface_select_network(wpa_s, buf + 15))			reply_len = -1;	} else if (strncmp(buf, "ENABLE_NETWORK ", 15) == 0) {		if (wpa_supplicant_ctrl_iface_enable_network(wpa_s, buf + 15))			reply_len = -1;	} else if (strncmp(buf, "DISABLE_NETWORK ", 16) == 0) {		if (wpa_supplicant_ctrl_iface_disable_network(wpa_s, buf + 16))			reply_len = -1;	} else if (strcmp(buf, "ADD_NETWORK") == 0) {		reply_len = wpa_supplicant_ctrl_iface_add_network(			wpa_s, reply, reply_size);	} else if (strncmp(buf, "REMOVE_NETWORK ", 15) == 0) {		if (wpa_supplicant_ctrl_iface_remove_network(wpa_s, buf + 15))			reply_len = -1;	} else if (strncmp(buf, "SET_NETWORK ", 12) == 0) {		if (wpa_supplicant_ctrl_iface_set_network(wpa_s, buf + 12))			reply_len = -1;	} else if (strncmp(buf, "GET_NETWORK ", 12) == 0) {		reply_len = wpa_supplicant_ctrl_iface_get_network(			wpa_s, buf + 12, reply, reply_size);	} else if (strcmp(buf, "SAVE_CONFIG") == 0) {		if (wpa_supplicant_ctrl_iface_save_config(wpa_s))			reply_len = -1;	} else if (strncmp(buf, "GET_CAPABILITY ", 15) == 0) {		reply_len = wpa_supplicant_ctrl_iface_get_capability(			wpa_s, buf + 15, reply, reply_size);	} else {		memcpy(reply, "UNKNOWN COMMAND\n", 16);		reply_len = 16;	}	if (reply_len < 0) {		memcpy(reply, "FAIL\n", 5);		reply_len = 5;	}#ifdef CONFIG_CTRL_IFACE_UDPdone:#endif /* CONFIG_CTRL_IFACE_UDP */	sendto(sock, reply, reply_len, 0, (struct sockaddr *) &from, fromlen);	free(reply);	if (new_attached)		eapol_sm_notify_ctrl_attached(wpa_s->eapol);	if (ctrl_rsp)		eapol_sm_notify_ctrl_response(wpa_s->eapol);}#ifndef CONFIG_CTRL_IFACE_UDPstatic char * wpa_supplicant_ctrl_iface_path(struct wpa_supplicant *wpa_s){	char *buf;	size_t len;	if (wpa_s->conf->ctrl_interface == NULL)		return NULL;	len = strlen(wpa_s->conf->ctrl_interface) + strlen(wpa_s->ifname) + 2;	buf = malloc(len);	if (buf == NULL)		return NULL;	snprintf(buf, len, "%s/%s",		 wpa_s->conf->ctrl_interface, wpa_s->ifname);#ifdef __CYGWIN__	{		/* Windows/WinPcap uses interface names that are not suitable		 * as a file name - convert invalid chars to underscores */		char *pos = buf;		while (*pos) {			if (*pos == '\\')				*pos = '_';			pos++;		}	}#endif /* __CYGWIN__ */	return buf;}#endif /* CONFIG_CTRL_IFACE_UDP *//** * wpa_supplicant_ctrl_iface_init - Initialize control interface * @wpa_s: Pointer to wpa_supplicant data * Returns: 0 on success, -1 on failure * * Initialize the control interface and start receiving commands from external * programs. */int wpa_supplicant_ctrl_iface_init(struct wpa_supplicant *wpa_s){	CTRL_IFACE_SOCK addr;	int s = -1;#ifndef CONFIG_CTRL_IFACE_UDP	char *fname = NULL;#endif /* CONFIG_CTRL_IFACE_UDP */	wpa_s->ctrl_sock = -1;	if (wpa_s->conf->ctrl_interface == NULL)		return 0;#ifdef CONFIG_CTRL_IFACE_UDP	hostapd_get_rand(wpa_s->cookie, COOKIE_LEN);	s = socket(PF_INET, SOCK_DGRAM, 0);	if (s < 0) {		perror("socket(PF_INET)");		goto fail;	}	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(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		perror("bind(AF_INET)");		goto fail;	}#else /* CONFIG_CTRL_IFACE_UDP */	if (mkdir(wpa_s->conf->ctrl_interface, S_IRWXU | S_IRWXG) < 0) {		if (errno == EEXIST) {			wpa_printf(MSG_DEBUG, "Using existing control "				   "interface directory.");		} else {			perror("mkdir[ctrl_interface]");			goto fail;		}	}	if (wpa_s->conf->ctrl_interface_gid_set &&	    chown(wpa_s->conf->ctrl_interface, 0,		  wpa_s->conf->ctrl_interface_gid) < 0) {		perror("chown[ctrl_interface]");		return -1;	}	if (strlen(wpa_s->conf->ctrl_interface) + 1 + strlen(wpa_s->ifname) >=	    sizeof(addr.sun_path))		goto fail;	s = socket(PF_UNIX, SOCK_DGRAM, 0);	if (s < 0) {		perror("socket(PF_UNIX)");		goto fail;	}	memset(&addr, 0, sizeof(addr));	addr.sun_family = AF_UNIX;	fname = wpa_supplicant_ctrl_iface_path(wpa_s);	if (fname == NULL)		goto fail;	strncpy(addr.sun_path, fname, sizeof(addr.sun_path));	if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {		wpa_printf(MSG_DEBUG, "ctrl_iface bind(PF_UNIX) failed: %s",			   strerror(errno));		if (connect(s, (struct sockaddr *) &addr, sizeof(addr)) < 0) {			wpa_printf(MSG_DEBUG, "ctrl_iface exists, but does not"				   " allow connections - assuming it was left"				   "over from forced program termination");			if (unlink(fname) < 0) {				perror("unlink[ctrl_iface]");				wpa_printf(MSG_ERROR, "Could not unlink "					   "existing ctrl_iface socket '%s'",					   fname);				goto fail;			}			if (bind(s, (struct sockaddr *) &addr, sizeof(addr)) <			    0) {				perror("bind(PF_UNIX)");				goto fail;			}			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "				   "ctrl_iface socket '%s'", fname);		} else {			wpa_printf(MSG_INFO, "ctrl_iface exists and seems to "				   "be in use - cannot override it");			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "				   "not used anymore", fname);			free(fname);			fname = NULL;			goto fail;		}	}	if (wpa_s->conf->ctrl_interface_gid_set &&	    chown(fname, 0, wpa_s->conf->ctrl_interface_gid) < 0) {		perror("chown[ctrl_interface/ifname]");		goto fail;	}	if (chmod(fname, S_IRWXU | S_IRWXG) < 0) {		perror("chmod[ctrl_interface/ifname]");		goto fail;	}	free(fname);#endif /* CONFIG_CTRL_IFACE_UDP */	wpa_s->ctrl_sock = s;	eloop_register_read_sock(s, wpa_supplicant_ctrl_iface_receive, wpa_s,				 NULL);	return 0;fail:	if (s >= 0)		close(s);#ifndef CONFIG_CTRL_IFACE_UDP	if (fname) {		unlink(fname);		free(fname);	}#endif /* CONFIG_CTRL_IFACE_UDP */	return -1;}/**

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?