Example #1
0
int wpas_wps_init(struct wpa_supplicant *wpa_s)
{
	struct wps_context *wps;
	struct wps_registrar_config rcfg;

	wps = os_zalloc(sizeof(*wps));
	if (wps == NULL)
		return -1;

	wps->cred_cb = wpa_supplicant_wps_cred;
	wps->event_cb = wpa_supplicant_wps_event;
	wps->cb_ctx = wpa_s;

	wps->dev.device_name = wpa_s->conf->device_name;
	wps->dev.manufacturer = wpa_s->conf->manufacturer;
	wps->dev.model_name = wpa_s->conf->model_name;
	wps->dev.model_number = wpa_s->conf->model_number;
	wps->dev.serial_number = wpa_s->conf->serial_number;
	if (wpa_s->conf->device_type) {
		char *pos;
		u8 oui[4];
		/* <categ>-<OUI>-<subcateg> */
		wps->dev.categ = atoi(wpa_s->conf->device_type);
		pos = os_strchr(wpa_s->conf->device_type, '-');
		if (pos == NULL) {
			wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
			os_free(wps);
			return -1;
		}
		pos++;
		if (hexstr2bin(pos, oui, 4)) {
			wpa_printf(MSG_ERROR, "WPS: Invalid device_type OUI");
			os_free(wps);
			return -1;
		}
		wps->dev.oui = WPA_GET_BE32(oui);
		pos = os_strchr(pos, '-');
		if (pos == NULL) {
			wpa_printf(MSG_ERROR, "WPS: Invalid device_type");
			os_free(wps);
			return -1;
		}
		pos++;
		wps->dev.sub_categ = atoi(pos);
	}
	wps->dev.os_version = WPA_GET_BE32(wpa_s->conf->os_version);
	wps->dev.rf_bands = WPS_RF_24GHZ | WPS_RF_50GHZ; /* TODO: config */
	os_memcpy(wps->dev.mac_addr, wpa_s->own_addr, ETH_ALEN);
	if (is_nil_uuid(wpa_s->conf->uuid)) {
		uuid_gen_mac_addr(wpa_s->own_addr, wps->uuid);
		wpa_hexdump(MSG_DEBUG, "WPS: UUID based on MAC address",
			    wps->uuid, WPS_UUID_LEN);
	} else
		os_memcpy(wps->uuid, wpa_s->conf->uuid, WPS_UUID_LEN);

	wps->auth_types = WPS_AUTH_WPA2PSK | WPS_AUTH_WPAPSK;
	wps->encr_types = WPS_ENCR_AES | WPS_ENCR_TKIP;

	os_memset(&rcfg, 0, sizeof(rcfg));
	rcfg.new_psk_cb = wpas_wps_new_psk_cb;
	rcfg.pin_needed_cb = wpas_wps_pin_needed_cb;
	rcfg.cb_ctx = wpa_s;

	wps->registrar = wps_registrar_init(wps, &rcfg);
	if (wps->registrar == NULL) {
		wpa_printf(MSG_DEBUG, "Failed to initialize WPS Registrar");
		os_free(wps);
		return -1;
	}

	wpa_s->wps = wps;

	return 0;
}
Example #2
0
static void wps_er_ssdp_rx(int sd, void *eloop_ctx, void *sock_ctx)
{
	struct wps_er *er = eloop_ctx;
	struct sockaddr_in addr; /* client address */
	socklen_t addr_len;
	int nread;
	char buf[MULTICAST_MAX_READ], *pos, *pos2, *start;
	int wfa = 0, byebye = 0;
	int max_age = -1;
	char *location = NULL;
	u8 uuid[WPS_UUID_LEN];

	addr_len = sizeof(addr);
	nread = recvfrom(sd, buf, sizeof(buf) - 1, 0,
			 (struct sockaddr *) &addr, &addr_len);
	if (nread <= 0)
		return;
	buf[nread] = '\0';
	if (er->filter_addr.s_addr &&
	    er->filter_addr.s_addr != addr.sin_addr.s_addr)
		return;

	wpa_printf(MSG_DEBUG, "WPS ER: Received SSDP from %s",
		   inet_ntoa(addr.sin_addr));
	wpa_hexdump_ascii(MSG_MSGDUMP, "WPS ER: Received SSDP contents",
			  (u8 *) buf, nread);

	if (sd == er->multicast_sd) {
		/* Reply to M-SEARCH */
		if (os_strncmp(buf, "HTTP/1.1 200 OK", 15) != 0)
			return; /* unexpected response header */
	} else {
		/* Unsolicited message (likely NOTIFY or M-SEARCH) */
		if (os_strncmp(buf, "NOTIFY ", 7) != 0)
			return; /* only process notifications */
	}

	os_memset(uuid, 0, sizeof(uuid));

	for (start = buf; start && *start; start = pos) {
		pos = os_strchr(start, '\n');
		if (pos) {
			if (pos[-1] == '\r')
				pos[-1] = '\0';
			*pos++ = '\0';
		}
		if (os_strstr(start, "schemas-wifialliance-org:device:"
			      "WFADevice:1"))
			wfa = 1;
		if (os_strstr(start, "schemas-wifialliance-org:service:"
			      "WFAWLANConfig:1"))
			wfa = 1;
		if (os_strncasecmp(start, "LOCATION:", 9) == 0) {
			start += 9;
			while (*start == ' ')
				start++;
			location = start;
		} else if (os_strncasecmp(start, "NTS:", 4) == 0) {
			if (os_strstr(start, "ssdp:byebye"))
				byebye = 1;
		} else if (os_strncasecmp(start, "CACHE-CONTROL:", 14) == 0) {
			start += 9;
			while (*start == ' ')
				start++;
			pos2 = os_strstr(start, "max-age=");
			if (pos2 == NULL)
				continue;
			pos2 += 8;
			max_age = atoi(pos2);
		} else if (os_strncasecmp(start, "USN:", 4) == 0) {
			start += 4;
			pos2 = os_strstr(start, "uuid:");
			if (pos2) {
				pos2 += 5;
				while (*pos2 == ' ')
					pos2++;
				if (uuid_str2bin(pos2, uuid) < 0) {
					wpa_printf(MSG_DEBUG, "WPS ER: "
						   "Invalid UUID in USN: %s",
						   pos2);
					return;
				}
			}
		}
	}

	if (!wfa)
		return; /* Not WPS advertisement/reply */

	if (byebye) {
		wps_er_ap_cache_settings(er, &addr.sin_addr);
		wps_er_ap_remove(er, &addr.sin_addr);
		return;
	}

	if (!location)
		return; /* Unknown location */

	if (max_age < 1)
		return; /* No max-age reported */

	wpa_printf(MSG_DEBUG, "WPS ER: AP discovered: %s "
		   "(packet source: %s  max-age: %d)",
		   location, inet_ntoa(addr.sin_addr), max_age);

	wps_er_ap_add(er, uuid, &addr.sin_addr, location, max_age);
}
Example #3
0
int autoscan_init(struct wpa_supplicant *wpa_s, int req_scan)
{
	const char *name = wpa_s->conf->autoscan;
	const char *params;
	size_t nlen;
	int i;
	const struct autoscan_ops *ops = NULL;

	if (wpa_s->autoscan && wpa_s->autoscan_priv)
		return 0;

	if (name == NULL)
		return 0;

	params = os_strchr(name, ':');
	if (params == NULL) {
		params = "";
		nlen = os_strlen(name);
	} else {
		nlen = params - name;
		params++;
	}

	for (i = 0; autoscan_modules[i]; i++) {
		if (os_strncmp(name, autoscan_modules[i]->name, nlen) == 0) {
			ops = autoscan_modules[i];
			break;
		}
	}

	if (ops == NULL) {
		wpa_printf(MSG_ERROR, "autoscan: Could not find module "
			   "matching the parameter '%s'", name);
		return -1;
	}

	wpa_s->autoscan_params = NULL;

	wpa_s->autoscan_priv = ops->init(wpa_s, params);
	if (wpa_s->autoscan_priv == NULL)
		return -1;
	wpa_s->autoscan = ops;

	wpa_printf(MSG_DEBUG, "autoscan: Initialized module '%s' with "
		   "parameters '%s'", ops->name, params);
	if (!req_scan)
		return 0;

	/*
	 * Cancelling existing scan requests, if any.
	 */
	wpa_supplicant_cancel_sched_scan(wpa_s);
	wpa_supplicant_cancel_scan(wpa_s);

	/*
	 * Firing first scan, which will lead to call autoscan_notify_scan.
	 */
	request_scan(wpa_s);

	return 0;
}
Example #4
0
static int wpa_driver_privsep_set_param(void *priv, const char *param)
{
	struct wpa_driver_privsep_data *drv = priv;
	const char *pos;
	char *own_dir, *priv_dir;
	static unsigned int counter = 0;
	size_t len;
	struct sockaddr_un addr;

	wpa_printf(MSG_DEBUG, "%s: param='%s'", __func__, param);
	if (param == NULL)
		pos = NULL;
	else
		pos = os_strstr(param, "own_dir=");
	if (pos) {
		char *end;
		own_dir = os_strdup(pos + 8);
		if (own_dir == NULL)
			return -1;
		end = os_strchr(own_dir, ' ');
		if (end)
			*end = '\0';
	} else {
		own_dir = os_strdup("/tmp");
		if (own_dir == NULL)
			return -1;
	}

	if (param == NULL)
		pos = NULL;
	else
		pos = os_strstr(param, "priv_dir=");
	if (pos) {
		char *end;
		priv_dir = os_strdup(pos + 9);
		if (priv_dir == NULL) {
			os_free(own_dir);
			return -1;
		}
		end = os_strchr(priv_dir, ' ');
		if (end)
			*end = '\0';
	} else {
		priv_dir = os_strdup("/var/run/wpa_priv");
		if (priv_dir == NULL) {
			os_free(own_dir);
			return -1;
		}
	}

	len = os_strlen(own_dir) + 50;
	drv->own_socket_path = os_malloc(len);
	if (drv->own_socket_path == NULL) {
		os_free(priv_dir);
		os_free(own_dir);
		return -1;
	}
	os_snprintf(drv->own_socket_path, len, "%s/wpa_privsep-%d-%d",
		    own_dir, getpid(), counter++);

	len = os_strlen(own_dir) + 50;
	drv->own_cmd_path = os_malloc(len);
	if (drv->own_cmd_path == NULL) {
		os_free(drv->own_socket_path);
		drv->own_socket_path = NULL;
		os_free(priv_dir);
		os_free(own_dir);
		return -1;
	}
	os_snprintf(drv->own_cmd_path, len, "%s/wpa_privsep-%d-%d",
		    own_dir, getpid(), counter++);

	os_free(own_dir);

	drv->priv_addr.sun_family = AF_UNIX;
	os_snprintf(drv->priv_addr.sun_path, sizeof(drv->priv_addr.sun_path),
		    "%s/%s", priv_dir, drv->ifname);
	os_free(priv_dir);

	drv->priv_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
	if (drv->priv_socket < 0) {
		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
		os_free(drv->own_socket_path);
		drv->own_socket_path = NULL;
		return -1;
	}

	os_memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_UNIX;
	os_strlcpy(addr.sun_path, drv->own_socket_path, sizeof(addr.sun_path));
	if (bind(drv->priv_socket, (struct sockaddr *) &addr, sizeof(addr)) <
	    0) {
		wpa_printf(MSG_ERROR,
			   "privsep-set-params priv-sock: bind(PF_UNIX): %s",
			   strerror(errno));
		close(drv->priv_socket);
		drv->priv_socket = -1;
		unlink(drv->own_socket_path);
		os_free(drv->own_socket_path);
		drv->own_socket_path = NULL;
		return -1;
	}

	eloop_register_read_sock(drv->priv_socket, wpa_driver_privsep_receive,
				 drv, NULL);

	drv->cmd_socket = socket(PF_UNIX, SOCK_DGRAM, 0);
	if (drv->cmd_socket < 0) {
		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
		os_free(drv->own_cmd_path);
		drv->own_cmd_path = NULL;
		return -1;
	}

	os_memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_UNIX;
	os_strlcpy(addr.sun_path, drv->own_cmd_path, sizeof(addr.sun_path));
	if (bind(drv->cmd_socket, (struct sockaddr *) &addr, sizeof(addr)) < 0)
	{
		wpa_printf(MSG_ERROR,
			   "privsep-set-params cmd-sock: bind(PF_UNIX): %s",
			   strerror(errno));
		close(drv->cmd_socket);
		drv->cmd_socket = -1;
		unlink(drv->own_cmd_path);
		os_free(drv->own_cmd_path);
		drv->own_cmd_path = NULL;
		return -1;
	}

	if (wpa_priv_reg_cmd(drv, PRIVSEP_CMD_REGISTER) < 0) {
		wpa_printf(MSG_ERROR, "Failed to register with wpa_priv");
		return -1;
	}

	return 0;
}
Example #5
0
static int wpa_supplicant_global_iface_add(struct wpa_global *global,
					   char *cmd)
{
	struct wpa_interface iface;
	char *pos;

	/*
	 * <ifname>TAB<confname>TAB<driver>TAB<ctrl_interface>TAB<driver_param>
	 * TAB<bridge_ifname>
	 */
	wpa_printf(MSG_DEBUG, "CTRL_IFACE GLOBAL INTERFACE_ADD '%s'", cmd);

	os_memset(&iface, 0, sizeof(iface));

	do {
		iface.ifname = pos = cmd;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.ifname[0] == '\0')
			return -1;
		if (pos == NULL)
			break;

		iface.confname = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.confname[0] == '\0')
			iface.confname = NULL;
		if (pos == NULL)
			break;

		iface.driver = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.driver[0] == '\0')
			iface.driver = NULL;
		if (pos == NULL)
			break;

		iface.ctrl_interface = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.ctrl_interface[0] == '\0')
			iface.ctrl_interface = NULL;
		if (pos == NULL)
			break;

		iface.driver_param = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.driver_param[0] == '\0')
			iface.driver_param = NULL;
		if (pos == NULL)
			break;

		iface.bridge_ifname = pos;
		pos = os_strchr(pos, '\t');
		if (pos)
			*pos++ = '\0';
		if (iface.bridge_ifname[0] == '\0')
			iface.bridge_ifname = NULL;
		if (pos == NULL)
			break;
	} while (0);

	if (wpa_supplicant_get_iface(global, iface.ifname))
		return -1;

	return wpa_supplicant_add_iface(global, &iface) ? 0 : -1;
}
static void clean_past_ated(){
	pid_t pid = getpid();
	pid_t fork_pid;
	int pipefd[2];//0:reading, 1:writing
	pipe(pipefd);
	ate_printf(MSG_INFO,"Pid of ated: %d\n",pid);
	fork_pid = fork();
	if(fork_pid==0){
		char *argv[] = {"ps",NULL/*"-AL"*/,NULL};
		close(pipefd[0]);	//children only DO write data
		dup2(pipefd[1],1);
		dup2(pipefd[1],2);
		execvp("ps", argv);
		exit(0);
	}else{
		/* Wait exec finish */
		char buffer[2048];
		char line[256];
		char ate_pid[16];
		unsigned char exist_ate = 0;
		close(pipefd[1]);
		while(read(pipefd[0],buffer, sizeof(buffer)) != 0){
			char *eol = os_strchr(buffer, '\n');
			char *tmp = buffer;
			while(eol){
				int dif = eol - tmp + 1;
				os_memset(line, '\0', 256);
				os_memcpy(line, tmp, dif);
				if(os_strstr(line, "ated")){
					int distance = 0;
					int dif2 = 0;
					char *l;
				ate_printf(MSG_DEBUG,"Parsing line: %s\n", line);
				repeat_parse:
					l = os_strchr(line+distance,' ');
					if(!l)
						break;
					ate_printf(MSG_DEBUG,"Line: 0x%x, l: 0x%x\n", line, l); 
					dif2 = l - line -distance;
					distance += dif2;
					/* The first char is space */
					if(dif2 == 0){
						distance += 1;
						goto repeat_parse;
					}
					if((dif2) > 16){
					ate_printf(MSG_DEBUG,"String too long for pid, continue to parse, [%s]\n",ate_pid);
						goto repeat_parse;
					}
					os_memset(ate_pid, 0, 16);
					os_memcpy(ate_pid, l - dif2, dif2); //For delete appending space
					ate_printf(MSG_DEBUG,"ate_pid: %s\n",ate_pid);
					exist_ate = 1;
					do{
						int pid_found = 0;
						int ret = -1;
						sscanf(ate_pid,"%d", &pid_found);
						if(pid_found != pid){
							ate_printf(MSG_DEBUG,"!pid_found: %d\n",pid_found);
							ret = kill((pid_t)pid_found, SIGHUP);
							if(ret)
								ate_printf(MSG_ERROR,"kill process %d fail\n",pid_found);
							else
								ate_printf(MSG_INFO, "kill process %d success\n",pid_found);
						}	
					}while(0);
				}
				tmp += dif;
				eol = os_strchr(tmp, '\n');
			}
		}
		close(pipefd[0]);
		waitpid(fork_pid, 0, 0);
		close(pipefd[1]);
	}
}
Example #7
0
static int plmn_id_match(struct wpabuf *anqp, const char *imsi)
{
	const char *sep;
	u8 plmn[3];
	const u8 *pos, *end;
	u8 udhl;

	sep = os_strchr(imsi, '-');
	if (sep == NULL || (sep - imsi != 5 && sep - imsi != 6))
		return 0;

	/* See Annex A of 3GPP TS 24.234 v8.1.0 for description */
	plmn[0] = (imsi[0] - '0') | ((imsi[1] - '0') << 4);
	plmn[1] = imsi[2] - '0';
	if (sep - imsi == 6)
		plmn[1] |= (imsi[5] - '0') << 4;
	else
		plmn[1] |= 0xf0;
	plmn[2] = (imsi[3] - '0') | ((imsi[4] - '0') << 4);

	if (anqp == NULL)
		return 0;
	pos = wpabuf_head_u8(anqp);
	end = pos + wpabuf_len(anqp);
	if (pos + 2 > end)
		return 0;
	if (*pos != 0) {
		wpa_printf(MSG_DEBUG, "Unsupported GUD version 0x%x", *pos);
		return 0;
	}
	pos++;
	udhl = *pos++;
	if (pos + udhl > end) {
		wpa_printf(MSG_DEBUG, "Invalid UDHL");
		return 0;
	}
	end = pos + udhl;

	while (pos + 2 <= end) {
		u8 iei, len;
		const u8 *l_end;
		iei = *pos++;
		len = *pos++ & 0x7f;
		if (pos + len > end)
			break;
		l_end = pos + len;

		if (iei == 0 && len > 0) {
			/* PLMN List */
			u8 num, i;
			num = *pos++;
			for (i = 0; i < num; i++) {
				if (pos + 3 > end)
					break;
				if (os_memcmp(pos, plmn, 3) == 0)
					return 1; /* Found matching PLMN */
			}
		}

		pos = l_end;
	}

	return 0;
}
struct wpa_ctrl * wpa_ctrl_open(const char *ctrl_path)
{
	struct wpa_ctrl *ctrl;
	char buf[128];
	size_t len;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
	struct hostent *h;
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */

	ctrl = os_malloc(sizeof(*ctrl));
	if (ctrl == NULL)
		return NULL;
	os_memset(ctrl, 0, sizeof(*ctrl));

#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
	ctrl->s = socket(PF_INET6, SOCK_DGRAM, 0);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
	ctrl->s = socket(PF_INET, SOCK_DGRAM, 0);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
	if (ctrl->s < 0) {
		perror("socket");
		os_free(ctrl);
		return NULL;
	}

#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
	ctrl->local.sin6_family = AF_INET6;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
	ctrl->local.sin6_addr = in6addr_any;
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
	inet_pton(AF_INET6, "::1", &ctrl->local.sin6_addr);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
	ctrl->local.sin_family = AF_INET;
#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
	ctrl->local.sin_addr.s_addr = INADDR_ANY;
#else /* CONFIG_CTRL_IFACE_UDP_REMOTE */
	ctrl->local.sin_addr.s_addr = htonl((127 << 24) | 1);
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */

	if (bind(ctrl->s, (struct sockaddr *) &ctrl->local,
		 sizeof(ctrl->local)) < 0) {
		close(ctrl->s);
		os_free(ctrl);
		return NULL;
	}

#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
	ctrl->dest.sin6_family = AF_INET6;
	inet_pton(AF_INET6, "::1", &ctrl->dest.sin6_addr);
	ctrl->dest.sin6_port = htons(WPA_CTRL_IFACE_PORT);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
	ctrl->dest.sin_family = AF_INET;
	ctrl->dest.sin_addr.s_addr = htonl((127 << 24) | 1);
	ctrl->dest.sin_port = htons(WPA_CTRL_IFACE_PORT);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */

#ifdef CONFIG_CTRL_IFACE_UDP_REMOTE
	if (ctrl_path) {
		char *port, *name;
		int port_id;
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
		char *scope;
		int scope_id = 0;
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */

		name = os_strdup(ctrl_path);
		if (name == NULL) {
			close(ctrl->s);
			os_free(ctrl);
			return NULL;
		}
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
		port = os_strchr(name, ',');
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
		port = os_strchr(name, ':');
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */

		if (port) {
			port_id = atoi(&port[1]);
			port[0] = '\0';
		} else
			port_id = WPA_CTRL_IFACE_PORT;

#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
		scope = os_strchr(name, '%');
		if (scope) {
			scope_id = if_nametoindex(&scope[1]);
			scope[0] = '\0';
		}
		h = gethostbyname2(name, AF_INET6);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
		h = gethostbyname(name);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
		ctrl->remote_ip = os_strdup(name);
		os_free(name);
		if (h == NULL) {
			perror("gethostbyname");
			close(ctrl->s);
			os_free(ctrl->remote_ip);
			os_free(ctrl);
			return NULL;
		}
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
		ctrl->dest.sin6_scope_id = scope_id;
		ctrl->dest.sin6_port = htons(port_id);
		os_memcpy(&ctrl->dest.sin6_addr, h->h_addr, h->h_length);
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
		ctrl->dest.sin_port = htons(port_id);
		os_memcpy(&ctrl->dest.sin_addr.s_addr, h->h_addr, h->h_length);
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
	} else
		ctrl->remote_ip = os_strdup("localhost");
#endif /* CONFIG_CTRL_IFACE_UDP_REMOTE */

	if (connect(ctrl->s, (struct sockaddr *) &ctrl->dest,
		    sizeof(ctrl->dest)) < 0) {
#ifdef CONFIG_CTRL_IFACE_UDP_IPV6
		char addr[INET6_ADDRSTRLEN];
		wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s",
			   inet_ntop(AF_INET6, &ctrl->dest.sin6_addr, addr,
				     sizeof(ctrl->dest)),
			   ntohs(ctrl->dest.sin6_port),
			   strerror(errno));
#else /* CONFIG_CTRL_IFACE_UDP_IPV6 */
		wpa_printf(MSG_ERROR, "connect(%s:%d) failed: %s",
			   inet_ntoa(ctrl->dest.sin_addr),
			   ntohs(ctrl->dest.sin_port),
			   strerror(errno));
#endif /* CONFIG_CTRL_IFACE_UDP_IPV6 */
		close(ctrl->s);
		os_free(ctrl->remote_ip);
		os_free(ctrl);
		return NULL;
	}

	len = sizeof(buf) - 1;
	if (wpa_ctrl_request(ctrl, "GET_COOKIE", 10, buf, &len, NULL) == 0) {
		buf[len] = '\0';
		ctrl->cookie = os_strdup(buf);
	}

	if (wpa_ctrl_request(ctrl, "IFNAME", 6, buf, &len, NULL) == 0) {
		buf[len] = '\0';
		ctrl->remote_ifname = os_strdup(buf);
	}

	return ctrl;
}
static int wpa_supplicant_ctrl_iface_set_network(
	struct wpa_supplicant *wpa_s, char *cmd)
{
	int id;
	struct wpa_ssid *ssid;
	char *name, *value;

	/* cmd: "<network id> <variable name> <value>" */
	name = os_strchr(cmd, ' ');
	if (name == NULL)
		return -1;
	*name++ = '\0';

	value = os_strchr(name, ' ');
	if (value == NULL)
		return -1;
	*value++ = '\0';

	id = atoi(cmd);
	wpa_printf(MSG_DEBUG, "CTRL_IFACE: SET_NETWORK id=%d name='%s'",
		   id, name);
	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
			      (u8 *) value, os_strlen(value));

	ssid = wpa_config_get_network(wpa_s->conf, id);
	if (ssid == NULL) {
		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find network "
			   "id=%d", id);
		return -1;
	}

#ifdef ANDROID_IBSS_HACK
	if (os_strcmp(name, "ssid") == 0) {
		// check prefix
		if ((value[0] == '"') && (os_strncmp(value+1, ANDROID_IBSS_PREFIX,
			  ANDROID_IBSS_PREFIX_LEN) == 0)) {
			if (wpa_config_set(ssid, "mode", "1", 0) < 0) {
				wpa_printf(MSG_DEBUG, "CTRL_IFACE: failed to set IBSS on '%s'",
					  value);
				return -1;
			}
			value += ANDROID_IBSS_PREFIX_LEN;
			value[0] = '"';
		}
	}
#endif
	if (wpa_config_set(ssid, name, value, 0) < 0) {
		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Failed to set network "
			   "variable '%s'", name);
		return -1;
	} else {
		if (os_strcmp(name, "priority") == 0) {
			wpa_config_update_prio_list(wpa_s->conf);
		}
	}

	if (wpa_s->current_ssid == ssid) {
		/*
		 * Invalidate the EAP session cache if anything in the current
		 * configuration changes.
		 */
		eapol_sm_invalidate_cached_session(wpa_s->eapol);
	}

	if ((os_strcmp(name, "psk") == 0 &&
	     value[0] == '"' && ssid->ssid_len) ||
	    (os_strcmp(name, "ssid") == 0 && ssid->passphrase))
		wpa_config_update_psk(ssid);

	return 0;
}
Example #10
0
struct wpa_config * wpa_config_read(const char *name)
{
	FILE *f;
	char buf[512], *pos;
	int errors = 0, line = 0;
	struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
	struct wpa_cred *cred, *cred_tail = NULL, *cred_head = NULL;
	struct wpa_config *config;
	int id = 0;
	int cred_id = 0;

	config = wpa_config_alloc_empty(NULL, NULL);
	if (config == NULL)
		return NULL;
	wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
	f = fopen(name, "r");
	if (f == NULL) {
		os_free(config);
		return NULL;
	}

	while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {
		if (os_strcmp(pos, "network={") == 0) {
			ssid = wpa_config_read_network(f, &line, id++);
			if (ssid == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: failed to "
					   "parse network block.", line);
				errors++;
				continue;
			}
			if (head == NULL) {
				head = tail = ssid;
			} else {
				tail->next = ssid;
				tail = ssid;
			}
			if (wpa_config_add_prio_network(config, ssid)) {
				wpa_printf(MSG_ERROR, "Line %d: failed to add "
					   "network block to priority list.",
					   line);
				errors++;
				continue;
			}
		} else if (os_strcmp(pos, "cred={") == 0) {
			cred = wpa_config_read_cred(f, &line, cred_id++);
			if (cred == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: failed to "
					   "parse cred block.", line);
				errors++;
				continue;
			}
			if (cred_head == NULL) {
				cred_head = cred_tail = cred;
			} else {
				cred_tail->next = cred;
				cred_tail = cred;
			}
#ifndef CONFIG_NO_CONFIG_BLOBS
		} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
			if (wpa_config_process_blob(config, f, &line, pos + 12)
			    < 0) {
				errors++;
				continue;
			}
#endif /* CONFIG_NO_CONFIG_BLOBS */
#ifdef CONFIG_P2P
		} else if (os_strncmp(buf, "wme_ac_", 7) == 0 ||
			   os_strncmp(buf, "wmm_ac_", 7) == 0) {
			pos = os_strchr(buf, '=');
			if (pos == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: invalid line '%s'",
						line, buf);
				errors++;
				continue;
			}
			*pos = '\0';
			pos++;
			if (wpa_config_wmm_ac(config->wmm_ac_params, buf, pos)) {
				wpa_printf(MSG_ERROR, "Line %d: invalid WMM "
					   "ac item", line);
				errors++;
			}
#endif /* CONFIG_P2P */
		} else if (wpa_config_process_global(config, pos, line) < 0) {
			wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
				   "line '%s'.", line, pos);
			errors++;
			continue;
		}
	}

	fclose(f);

	config->ssid = head;
	wpa_config_debug_dump_networks(config);
	config->cred = cred_head;

#ifndef WPA_IGNORE_CONFIG_ERRORS
	if (errors) {
		wpa_config_free(config);
		config = NULL;
		head = NULL;
	}
#endif /* WPA_IGNORE_CONFIG_ERRORS */

	return config;
}
Example #11
0
//=============================================================================
bool ICACHE_FLASH_ATTR
websock_rx_data(TCP_SERV_CONN *ts_conn)
{
//	HTTP_CONN *CurHTTP;
	WEB_SRV_CONN *web_conn = (WEB_SRV_CONN *)ts_conn->linkd;
	if(web_conn == NULL) return false;
	WS_FRSTAT *ws = &web_conn->ws;
	uint16 len;
	uint8 *pstr;

#if DEBUGSOO > 3
	os_printf("ws_rx[%u]%u ", ts_conn->sizei, ts_conn->cntri);
#endif
	if(ts_conn->sizei == 0) return true; // докачивать
	tcpsrv_unrecved_win(ts_conn);
	if((ws->flg & WS_FLG_CLOSE) != 0) {
		// убить буфер ts_conn->pbufi,  конец давно :)
		web_feee_bufi(ts_conn);
		SetSCB(SCB_DISCONNECT);
		return false;
	}
	if(ts_conn->sizei > MAX_RX_BUF_SIZE) {
#if DEBUGSOO > 0
		os_printf("ws:rxbuf_full! ");
#endif
		// убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR
		web_feee_bufi(ts_conn);
		websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG); // WS_CLOSE_UNEXPECTED_ERROR);
		SetSCB(SCB_DISCONNECT);
		return false;
	}
	pstr = ts_conn->pbufi;// + ts_conn->cntri;
	len = ts_conn->sizei;// - ts_conn->cntri;
	while(ts_conn->cntri < ts_conn->sizei || (ws->flg & WS_FLG_FIN) != 0) {
		pstr = ts_conn->pbufi;// + ts_conn->cntri;
		len = ts_conn->sizei;// - ts_conn->cntri;
		if((ws->flg & WS_FLG_FIN) != 0 // обработка
			|| ws->frame_len > ws->cur_len) {
			ws->flg &= ~WS_FLG_FIN;
			len = mMIN(ws->frame_len - ws->cur_len, mMIN(MAX_WS_DATA_BLK_SIZE, len));
			// размаскировать
			if((ws->flg & WS_FLG_MASK) != 0) WebsocketMask(ws, pstr, len);
#if DEBUGSOO > 3
			os_printf("wsfr[%u]blk[%u]at:%u ", ws->frame_len, len, ws->cur_len);
#endif
			switch(ws->status) {
				case sw_frs_binary:
#if DEBUGSOO > 1
					os_printf("ws:bin ");
#endif
					if(ws->frame_len != 0) {
						// пока просто эхо
						uint32 opcode = WS_OPCODE_BINARY;
						if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
						if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
						if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
							return false; // не докачивать, ошибка или закрытие
						}
					}
					ws->cur_len += len;
					ts_conn->cntri += len;
					break;
				case sw_frs_text:
#if DEBUGSOO > 1
					os_printf("ws:txt ");
#if DEBUGSOO > 2
					if(ws->frame_len != 0) {
						uint8 tt = pstr[len];
						pstr[len] = 0;
						os_printf("'%s' ", pstr);
						pstr[len] = tt;
					}
#endif
#endif
					if(ws->frame_len == ws->cur_len + len && ws->frame_len != 0) { // полное соо
						web_conn->msgbufsize = tcp_sndbuf(ts_conn->pcb); // сколько можем выввести сейчас?
						if (web_conn->msgbufsize < MIN_SEND_SIZE) {
#if DEBUGSOO > 0
							os_printf("ws:sndbuf=%u! ", web_conn->msgbufsize);
#endif
							websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
							SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
							return false;
						}
						if(ws->frame_len == (sizeof(txt_wsping)-1) && rom_xstrcmp(pstr, txt_wsping) != 0){
							copy_s4d1(pstr, (void *)txt_wspong, sizeof(txt_wspong) - 1);
							if(websock_tx_frame(ts_conn, WS_OPCODE_TEXT | WS_FRAGMENT_FIN, pstr, sizeof(txt_wspong) - 1) != ERR_OK) {
								return false; // не докачивать, ошибка или закрытие
							}
						}
						else {
							web_conn->msgbuf = (uint8 *) os_malloc(web_conn->msgbufsize);
							if (web_conn->msgbuf == NULL) {
#if DEBUGSOO > 0
								os_printf("ws:mem!\n");
#endif
								websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
								SetSCB(SCB_FCLOSE|SCB_DISCONNECT);
								return false;
							};
							web_conn->msgbuflen = 0;
							uint32 opcode;
							if(CheckSCB(SCB_RETRYCB)) { // повторный callback? да
								if(web_conn->func_web_cb != NULL) web_conn->func_web_cb(ts_conn);
								if(!CheckSCB(SCB_RETRYCB)) {
									ClrSCB(SCB_FCLOSE | SCB_DISCONNECT);
									opcode = WS_OPCODE_CONTINUE | WS_FRAGMENT_FIN;
								}
								else opcode = WS_OPCODE_CONTINUE;
							}
							else {
								pstr[len] = '\0';
								uint8 *vstr = os_strchr(pstr, '=');
								if(vstr != NULL) {
									*vstr++ = '\0';
									web_int_vars(ts_conn, pstr, vstr);
								}
								else {
									web_conn->msgbuf[0] = 0;
									web_int_callback(ts_conn, pstr);
								}
								if(CheckSCB(SCB_RETRYCB)) opcode = WS_OPCODE_TEXT;
								else {
									ClrSCB(SCB_FCLOSE | SCB_DISCONNECT);
									opcode = WS_OPCODE_TEXT | WS_FRAGMENT_FIN;
								}
							}
							if(web_conn->msgbuflen != 0) {
								if(websock_tx_frame(ts_conn, opcode, web_conn->msgbuf, web_conn->msgbuflen) != ERR_OK) {
									os_free(web_conn->msgbuf);
									web_conn->msgbuf = NULL;
									return false; // не докачивать, ошибка или закрытие
								}
							}
							os_free(web_conn->msgbuf);
							web_conn->msgbuf = NULL;
							if(CheckSCB(SCB_RETRYCB)) return false;
						}
					}
/*
					if(0) {
						uint32 opcode = WS_OPCODE_TEXT;
						if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
						if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
						if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
							return false; // не докачивать, ошибка или закрытие
						}
					}
*/
					ws->cur_len += len;
					ts_conn->cntri += len;
					return true; // докачивать
//					break;
//					break;
				case sw_frs_ping:
#if DEBUGSOO > 1
					os_printf("ws:ping ");
#endif
					{
						uint32 opcode = WS_OPCODE_PONG;
						if(ws->cur_len != 0) opcode = WS_OPCODE_CONTINUE;
						if(ws->frame_len == ws->cur_len + len) opcode |= WS_FRAGMENT_FIN;
						if(websock_tx_frame(ts_conn, opcode, pstr, len) != ERR_OK) {
								return false; // не докачивать, ошибка или закрытие
						}
					}
					ws->cur_len += len;
					ts_conn->cntri += len;
					return true; // докачивать
//					break;
				case sw_frs_pong:
#if DEBUGSOO > 1
					os_printf("ws:pong ");
#endif
					ws->cur_len += len;
					ts_conn->cntri += len;
					break;
//					return true;
				case sw_frs_close:
#if DEBUGSOO > 1
				os_printf("ws:close ");
#endif
//				if((ws->flg & WS_FLG_CLOSE) == 0) {
				{
					if(len >= 2) {
					uint32 close_code = (pstr[0]<<8) | pstr[1];
#if DEBUGSOO > 1
						os_printf("code:%d ", close_code);
#endif
						if(close_code == WS_CLOSE_NORMAL)	websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL);
						// else websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0);
					}
					else
					{
						websock_tx_close_err(ts_conn, WS_CLOSE_NORMAL);
						// websock_tx_frame(ts_conn, WS_OPCODE_CLOSE | WS_FRAGMENT_FIN, NULL, 0);
					}
				}
				ts_conn->flag.pcb_time_wait_free = 1;
				SetSCB(SCB_DISCONNECT);
//					ts_conn->cntri = ts_conn->sizei;
/*				ws->cur_len += len;
				ts_conn->cntri += len; */
				return false;
			default:
#if DEBUGSOO > 0
				os_printf("ws:f?! ");
#endif
				websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
				SetSCB(SCB_DISCONNECT);
		//		ts_conn->cntri = ts_conn->sizei;
				return false;
			}
		}
		else
		if(ws->cur_len >= ws->frame_len) { // прием и разбор нового фрейма
			if((ws->flg & WS_FLG_FIN) != 0) { // обработка
#if DEBUGSOO > 3
				os_printf("ws_rx:fin=%u ", ws->cur_len);
#endif
			}
			else {
				uint32 ret = WebsocketHead(ws, pstr, len);
				if(ret >= WS_CLOSE_NORMAL) { // error или close

#if DEBUGSOO > 0
					os_printf("ws:txerr=%u ", ret);
#endif
					websock_tx_close_err(ts_conn, ret);
//					ts_conn->cntri = ts_conn->sizei; // убить буфер ts_conn->pbufi
					return false; // error
				}
				else if(ret == 0) {
#if DEBUGSOO > 3
					os_printf("ws_rx... ");
#endif
					return true; // докачивать
				}
				ts_conn->cntri += ws->head_len; // вычесть заголовок
/*
				switch(ws->status) {
					case sw_frs_binary:
						break;
					case sw_frs_text:
						if(ws->frame_len > MAX_RX_BUF_SIZE) {
							websock_tx_close_err(ts_conn, WS_CLOSE_MESSAGE_TOO_BIG);
							return false;
						}
						break;
				}
*/
			}
		}
#if DEBUGSOO > 3
		os_printf("trim%u-%u ", ts_conn->sizei, ts_conn->sizei - ts_conn->cntri );
#endif
		if(!web_trim_bufi(ts_conn, &ts_conn->pbufi[ts_conn->cntri], ts_conn->sizei - ts_conn->cntri)) {
#if DEBUGSOO > 0
			os_printf("ws:trim_err! ");
#endif
			// убить буфер ts_conn->pbufi и ответить ошибкой WS_CLOSE_UNEXPECTED_ERROR
			websock_tx_close_err(ts_conn, WS_CLOSE_UNEXPECTED_ERROR);
			SetSCB(SCB_DISCONNECT);
//			ts_conn->cntri = ts_conn->sizei;
			return false;
		};
	}
	return false; // не докачивать, ошибка или закрытие
}
static char * wpa_cli_get_default_ifname(void)
{
	char *ifname = NULL;

#ifdef CONFIG_CTRL_IFACE_UNIX
	struct dirent *dent;
	DIR *dir = opendir(ctrl_iface_dir);
	if (!dir) {
#ifdef ANDROID
		char ifprop[PROPERTY_VALUE_MAX];
		if (property_get("wifi.interface", ifprop, NULL) != 0) {
			ifname = os_strdup(ifprop);
			printf("Using interface '%s'\n", ifname);
			return ifname;
		}
#endif
		return NULL;
	}
	while ((dent = readdir(dir))) {
#ifdef _DIRENT_HAVE_D_TYPE
		/*
		 * Skip the file if it is not a socket. Also accept
		 * DT_UNKNOWN (0) in case the C library or underlying
		 * file system does not support d_type.
		 */
		if (dent->d_type != DT_SOCK && dent->d_type != DT_UNKNOWN)
			continue;
#endif /* _DIRENT_HAVE_D_TYPE */
		if (os_strcmp(dent->d_name, ".") == 0 ||
		    os_strcmp(dent->d_name, "..") == 0)
			continue;
		printf("Selected interface '%s'\n", dent->d_name);
		ifname = os_strdup(dent->d_name);
		break;
	}
	closedir(dir);
#endif /* CONFIG_CTRL_IFACE_UNIX */

#ifdef CONFIG_CTRL_IFACE_NAMED_PIPE
#ifdef ANDROID
	char buf[4096],
#else
	char buf[2048],
#endif 
	*pos;
	size_t len;
	struct wpa_ctrl *ctrl;
	int ret;

	ctrl = wpa_ctrl_open(NULL);
	if (ctrl == NULL)
		return NULL;

	len = sizeof(buf) - 1;
	ret = wpa_ctrl_request(ctrl, "INTERFACES", 10, buf, &len, NULL);
	if (ret >= 0) {
		buf[len] = '\0';
		pos = os_strchr(buf, '\n');
		if (pos)
			*pos = '\0';
		ifname = os_strdup(buf);
	}
	wpa_ctrl_close(ctrl);
#endif /* CONFIG_CTRL_IFACE_NAMED_PIPE */

	return ifname;
}
static void wpa_cli_action_process(const char *msg)
{
	const char *pos;
	char *copy = NULL, *id, *pos2;

	pos = msg;
	if (*pos == '<') {
		/* skip priority */
		pos = os_strchr(pos, '>');
		if (pos)
			pos++;
		else
			pos = msg;
	}

	if (str_match(pos, WPA_EVENT_CONNECTED)) {
		int new_id = -1;
		os_unsetenv("WPA_ID");
		os_unsetenv("WPA_ID_STR");
		os_unsetenv("WPA_CTRL_DIR");

		pos = os_strstr(pos, "[id=");
		if (pos)
			copy = os_strdup(pos + 4);

		if (copy) {
			pos2 = id = copy;
			while (*pos2 && *pos2 != ' ')
				pos2++;
			*pos2++ = '\0';
			new_id = atoi(id);
			os_setenv("WPA_ID", id, 1);
			while (*pos2 && *pos2 != '=')
				pos2++;
			if (*pos2 == '=')
				pos2++;
			id = pos2;
			while (*pos2 && *pos2 != ']')
				pos2++;
			*pos2 = '\0';
			os_setenv("WPA_ID_STR", id, 1);
			os_free(copy);
		}

		os_setenv("WPA_CTRL_DIR", ctrl_iface_dir, 1);

		if (!wpa_cli_connected || new_id != wpa_cli_last_id) {
			wpa_cli_connected = 1;
			wpa_cli_last_id = new_id;
			wpa_cli_exec(action_file, ctrl_ifname, "CONNECTED");
		}
	} else if (str_match(pos, WPA_EVENT_DISCONNECTED)) {
		if (wpa_cli_connected) {
			wpa_cli_connected = 0;
			wpa_cli_exec(action_file, ctrl_ifname, "DISCONNECTED");
		}
	} else if (str_match(pos, WPA_EVENT_TERMINATING)) {
		printf("wpa_supplicant is terminating - stop monitoring\n");
		wpa_cli_quit = 1;
	}
}
struct wps_er *
wps_er_init(struct wps_context *wps, const char *ifname, const char *filter)
{
	struct wps_er *er;
	struct in_addr addr;

	er = os_zalloc(sizeof(*er));
	if (er == NULL)
		return NULL;
	dl_list_init(&er->ap);
	dl_list_init(&er->ap_unsubscribing);
	dl_list_init(&er->ap_settings);

	er->multicast_sd = -1;
	er->ssdp_sd = -1;

	os_strlcpy(er->ifname, ifname, sizeof(er->ifname));
	er->wps = wps;
	if (os_get_random((unsigned char *) &er->event_id,
			  sizeof(er->event_id)) < 0) {
		wps_er_deinit(er, NULL, NULL);
		return NULL;
	}
	/* Limit event_id to < 32 bits to avoid issues with atoi() */
	er->event_id &= 0x0fffffff;

	if (filter && os_strncmp(filter, "ifname=", 7) == 0) {
		const char *pos, *end;
		pos = filter + 7;
		end = os_strchr(pos, ' ');
		if (end) {
			size_t len = end - pos;
			os_strlcpy(er->ifname, pos, len < sizeof(er->ifname) ?
				   len + 1 : sizeof(er->ifname));
			filter = end + 1;
		} else {
			os_strlcpy(er->ifname, pos, sizeof(er->ifname));
			filter = NULL;
		}
		er->forced_ifname = 1;
	}

	if (filter) {
		if (inet_aton(filter, &er->filter_addr) == 0) {
			wpa_printf(MSG_INFO, "WPS UPnP: Invalid filter "
				   "address %s", filter);
			wps_er_deinit(er, NULL, NULL);
			return NULL;
		}
		wpa_printf(MSG_DEBUG, "WPS UPnP: Only accepting connections "
			   "with %s", filter);
	}
	if (get_netif_info(er->ifname, &er->ip_addr, &er->ip_addr_text,
			   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);
		return NULL;
	}

	if (wps_er_ssdp_init(er) < 0) {
		wpa_printf(MSG_INFO, "WPS UPnP: SSDP initialization failed");
		wps_er_deinit(er, NULL, NULL);
		return NULL;
	}

	addr.s_addr = er->ip_addr;
	er->http_srv = http_server_init(&addr, -1, wps_er_http_req, er);
	if (er->http_srv == NULL) {
		wpa_printf(MSG_INFO, "WPS UPnP: HTTP initialization failed");
		wps_er_deinit(er, NULL, NULL);
		return NULL;
	}
	er->http_port = http_server_get_port(er->http_srv);

	wpa_printf(MSG_DEBUG, "WPS ER: Start (ifname=%s ip_addr=%s)",
		   er->ifname, er->ip_addr_text);

	return er;
}
Example #15
0
int main(int argc, char *argv[])
{
	struct hapd_interfaces interfaces;
	int ret = 1;
	size_t i, j;
	int c, debug = 0, daemonize = 0;
	char *pid_file = NULL;
	const char *log_file = NULL;
	const char *entropy_file = NULL;
	char **bss_config = NULL, **tmp_bss;
	size_t num_bss_configs = 0;
#ifdef CONFIG_DEBUG_LINUX_TRACING
	int enable_trace_dbg = 0;
#endif /* CONFIG_DEBUG_LINUX_TRACING */

	if (os_program_init())
		return -1;

	os_memset(&interfaces, 0, sizeof(interfaces));
	interfaces.reload_config = hostapd_reload_config;
	interfaces.config_read_cb = hostapd_config_read;
	interfaces.for_each_interface = hostapd_for_each_interface;
	interfaces.ctrl_iface_init = hostapd_ctrl_iface_init;
	interfaces.ctrl_iface_deinit = hostapd_ctrl_iface_deinit;
	interfaces.driver_init = hostapd_driver_init;
	interfaces.global_iface_path = NULL;
	interfaces.global_iface_name = NULL;
	interfaces.global_ctrl_sock = -1;

	for (;;) {
		c = getopt(argc, argv, "b:Bde:f:hKP:Ttu:vg:G:");
		if (c < 0)
			break;
		switch (c) {
		case 'h':
			usage();
			break;
		case 'd':
			debug++;
			if (wpa_debug_level > 0)
				wpa_debug_level--;
			break;
		case 'B':
			daemonize++;
			break;
		case 'e':
			entropy_file = optarg;
			break;
		case 'f':
			log_file = optarg;
			break;
		case 'K':
			wpa_debug_show_keys++;
			break;
		case 'P':
			os_free(pid_file);
			pid_file = os_rel2abs_path(optarg);
			break;
		case 't':
			wpa_debug_timestamp++;
			break;
#ifdef CONFIG_DEBUG_LINUX_TRACING
		case 'T':
			enable_trace_dbg = 1;
			break;
#endif /* CONFIG_DEBUG_LINUX_TRACING */
		case 'v':
			show_version();
			exit(1);
			break;
		case 'g':
			if (hostapd_get_global_ctrl_iface(&interfaces, optarg))
				return -1;
			break;
		case 'G':
			if (hostapd_get_ctrl_iface_group(&interfaces, optarg))
				return -1;
			break;
		case 'b':
			tmp_bss = os_realloc_array(bss_config,
						   num_bss_configs + 1,
						   sizeof(char *));
			if (tmp_bss == NULL)
				goto out;
			bss_config = tmp_bss;
			bss_config[num_bss_configs++] = optarg;
			break;
#ifdef CONFIG_WPS
		case 'u':
			return gen_uuid(optarg);
#endif /* CONFIG_WPS */
		default:
			usage();
			break;
		}
	}

	if (optind == argc && interfaces.global_iface_path == NULL &&
	    num_bss_configs == 0)
		usage();

	wpa_msg_register_ifname_cb(hostapd_msg_ifname_cb);

	if (log_file)
		wpa_debug_open_file(log_file);
#ifdef CONFIG_DEBUG_LINUX_TRACING
	if (enable_trace_dbg) {
		int tret = wpa_debug_open_linux_tracing();
		if (tret) {
			wpa_printf(MSG_ERROR, "Failed to enable trace logging");
			return -1;
		}
	}
#endif /* CONFIG_DEBUG_LINUX_TRACING */

	interfaces.count = argc - optind;
	if (interfaces.count || num_bss_configs) {
		interfaces.iface = os_calloc(interfaces.count + num_bss_configs,
					     sizeof(struct hostapd_iface *));
		if (interfaces.iface == NULL) {
			wpa_printf(MSG_ERROR, "malloc failed");
			return -1;
		}
	}

	if (hostapd_global_init(&interfaces, entropy_file)) {
		wpa_printf(MSG_ERROR, "Failed to initilize global context");
		return -1;
	}

	/* Allocate and parse configuration for full interface files */
	for (i = 0; i < interfaces.count; i++) {
		interfaces.iface[i] = hostapd_interface_init(&interfaces,
							     argv[optind + i],
							     debug);
		if (!interfaces.iface[i]) {
			wpa_printf(MSG_ERROR, "Failed to initialize interface");
			goto out;
		}
	}

	/* Allocate and parse configuration for per-BSS files */
	for (i = 0; i < num_bss_configs; i++) {
		struct hostapd_iface *iface;
		char *fname;

		wpa_printf(MSG_INFO, "BSS config: %s", bss_config[i]);
		fname = os_strchr(bss_config[i], ':');
		if (fname == NULL) {
			wpa_printf(MSG_ERROR,
				   "Invalid BSS config identifier '%s'",
				   bss_config[i]);
			goto out;
		}
		*fname++ = '\0';
		iface = hostapd_interface_init_bss(&interfaces, bss_config[i],
						   fname, debug);
		if (iface == NULL)
			goto out;
		for (j = 0; j < interfaces.count; j++) {
			if (interfaces.iface[j] == iface)
				break;
		}
		if (j == interfaces.count) {
			struct hostapd_iface **tmp;
			tmp = os_realloc_array(interfaces.iface,
					       interfaces.count + 1,
					       sizeof(struct hostapd_iface *));
			if (tmp == NULL) {
				hostapd_interface_deinit_free(iface);
				goto out;
			}
			interfaces.iface = tmp;
			interfaces.iface[interfaces.count++] = iface;
		}
	}

	/*
	 * Enable configured interfaces. Depending on channel configuration,
	 * this may complete full initialization before returning or use a
	 * callback mechanism to complete setup in case of operations like HT
	 * co-ex scans, ACS, or DFS are needed to determine channel parameters.
	 * In such case, the interface will be enabled from eloop context within
	 * hostapd_global_run().
	 */
	interfaces.terminate_on_error = interfaces.count;
	for (i = 0; i < interfaces.count; i++) {
		if (hostapd_driver_init(interfaces.iface[i]) ||
		    hostapd_setup_interface(interfaces.iface[i]))
			goto out;
	}

	hostapd_global_ctrl_iface_init(&interfaces);

	if (hostapd_global_run(&interfaces, daemonize, pid_file)) {
		wpa_printf(MSG_ERROR, "Failed to start eloop");
		goto out;
	}

	ret = 0;

 out:
	hostapd_global_ctrl_iface_deinit(&interfaces);
	/* Deinitialize all interfaces */
	for (i = 0; i < interfaces.count; i++) {
		if (!interfaces.iface[i])
			continue;
		interfaces.iface[i]->driver_ap_teardown =
			!!(interfaces.iface[i]->drv_flags &
			   WPA_DRIVER_FLAGS_AP_TEARDOWN_SUPPORT);
		hostapd_interface_deinit_free(interfaces.iface[i]);
	}
	os_free(interfaces.iface);

	hostapd_global_deinit(pid_file);
	os_free(pid_file);

	if (log_file)
		wpa_debug_close_file();
	wpa_debug_close_linux_tracing();

	os_free(bss_config);

	os_program_deinit();

	return ret;
}
Example #16
0
static int eap_wsc_new_ap_settings(struct wps_credential *cred,
				   const char *params)
{
	const char *pos, *end;
	size_t len;

	os_memset(cred, 0, sizeof(*cred));

	pos = os_strstr(params, "new_ssid=");
	if (pos == NULL)
		return 0;
	pos += 9;
	end = os_strchr(pos, ' ');
	if (end == NULL)
		len = os_strlen(pos);
	else
		len = end - pos;
	if ((len & 1) || len > 2 * sizeof(cred->ssid) ||
	    hexstr2bin(pos, cred->ssid, len / 2))
		return -1;
	cred->ssid_len = len / 2;

	pos = os_strstr(params, "new_auth=");
	if (pos == NULL)
		return -1;
	if (os_strncmp(pos + 9, "OPEN", 4) == 0)
		cred->auth_type = WPS_AUTH_OPEN;
	else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0)
		cred->auth_type = WPS_AUTH_WPAPSK;
	else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0)
		cred->auth_type = WPS_AUTH_WPA2PSK;
	else
		return -1;

	pos = os_strstr(params, "new_encr=");
	if (pos == NULL)
		return -1;
	if (os_strncmp(pos + 9, "NONE", 4) == 0)
		cred->encr_type = WPS_ENCR_NONE;
	else if (os_strncmp(pos + 9, "WEP", 3) == 0)
		cred->encr_type = WPS_ENCR_WEP;
	else if (os_strncmp(pos + 9, "TKIP", 4) == 0)
		cred->encr_type = WPS_ENCR_TKIP;
	else if (os_strncmp(pos + 9, "CCMP", 4) == 0)
		cred->encr_type = WPS_ENCR_AES;
	else
		return -1;

	pos = os_strstr(params, "new_key=");
	if (pos == NULL)
		return 0;
	pos += 8;
	end = os_strchr(pos, ' ');
	if (end == NULL)
		len = os_strlen(pos);
	else
		len = end - pos;
	if ((len & 1) || len > 2 * sizeof(cred->key) ||
	    hexstr2bin(pos, cred->key, len / 2))
		return -1;
	cred->key_len = len / 2;

	return 1;
}
Example #17
0
static int 
eap_mschapv2_failure_txt(struct eap_sm *sm,
			 struct eap_mschapv2_data *data, char *txt)
{
	char *pos; 
	//char *msg = "";
	int retry = 1;
	struct eap_peer_config *config = eap_get_config(sm);

	pos = txt;

	if (pos && os_strncmp(pos, "E=", 2) == 0) {
		pos += 2;
		data->prev_error = atoi(pos);
		pos = (char *)os_strchr(pos, ' ');
		if (pos)
			pos++;
	}

	if (pos && os_strncmp(pos, "R=", 2) == 0) {
		pos += 2;
		retry = atoi(pos);
		pos = (char *)os_strchr(pos, ' ');
		if (pos)
			pos++;
	}

	if (pos && os_strncmp(pos, "C=", 2) == 0) {
		int hex_len;
		pos += 2;
		hex_len = (char *)os_strchr(pos, ' ') - (char *)pos;
		if (hex_len == PASSWD_CHANGE_CHAL_LEN * 2) {
			if (hexstr2bin(pos, data->passwd_change_challenge,
				       PASSWD_CHANGE_CHAL_LEN)) {
				wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: invalid failure challenge\n");
			} else {
				data->passwd_change_challenge_valid = 1;
			}
		} else {
			wpa_printf(MSG_ERROR, "EAP-MSCHAPV2: required challenge field "
				  "was not present in failure message\n");
		}
	}

	if (pos && os_strncmp(pos, "V=", 2) == 0) {
		pos += 2;
		data->passwd_change_version = atoi(pos);
		pos = (char *)os_strchr(pos, ' ');
		if (pos)
			pos++;
	}

	if (pos && os_strncmp(pos, "M=", 2) == 0) {
		pos += 2;
		//msg = pos;
	}
	#if 0
	wpa_printf(MSG_WARNING, "EAP-MSCHAPV2: failure message: '%s' (retry %sallowed, error %d)",
		  msg, retry == 1? "" : "not ", data->prev_error);
	#endif
	if (data->prev_error == ERROR_PASSWD_EXPIRED &&
	    data->passwd_change_version == 3 && config) {
		if (config->new_password == NULL) {
			wpa_printf(MSG_DEBUG, "EAP-MSCHAPV2: Password expired - "
				  "password change reqired\n");
			//eap_sm_request_new_password(sm);
		}
	} else if (retry == 1 && config) {
		if (!config->mschapv2_retry)
			//eap_sm_request_identity(sm);
		//eap_sm_request_password(sm);
		config->mschapv2_retry = 1;
	} else if (config) {
		config->mschapv2_retry = 0;
	}

	return retry == 1;
}
Example #18
0
static int test_nist_key_wrap_ad(const char *fname)
{
	FILE *f;
	int ret = 0;
	char buf[15000], *pos, *pos2;
	u8 bin[2000], k[32], p[1024], c[1024 + 8], result[1024 + 8];
	size_t bin_len, k_len = 0, p_len = 0, c_len = 0;
	int ok = 0;
	int fail;

	printf("NIST KW AD tests from %s\n", fname);

	f = fopen(fname, "r");
	if (f == NULL) {
		printf("%s does not exist - cannot validate test vectors\n",
		       fname);
		return 1;
	}

	while (fgets(buf, sizeof(buf), f)) {
		if (buf[0] == '#')
			continue;
		fail = 0;
		pos = os_strchr(buf, '=');
		if (pos == NULL) {
			if (os_strncmp(buf, "FAIL", 4) == 0) {
				fail = 1;
				goto skip_val_parse;
			}
			continue;
		}
		pos2 = pos - 1;
		while (pos2 >= buf && *pos2 == ' ')
			*pos2-- = '\0';
		*pos++ = '\0';
		while (*pos == ' ')
			*pos++ = '\0';
		pos2 = os_strchr(pos, '\r');
		if (!pos2)
			pos2 = os_strchr(pos, '\n');
		if (pos2)
			*pos2 = '\0';
		else
			pos2 = pos + os_strlen(pos);

		if (buf[0] == '[') {
			printf("%s = %s\n", buf, pos);
			continue;
		}

		if (os_strcmp(buf, "COUNT") == 0) {
			printf("Test %s - ", pos);
			continue;
		}

		bin_len = os_strlen(pos);
		if (bin_len > sizeof(bin) * 2) {
			printf("Too long binary data (%s)\n", buf);
			return 1;
		}
		if (bin_len & 0x01) {
			printf("Odd number of hexstring values (%s)\n",
				buf);
			return 1;
		}
		bin_len /= 2;
		if (hexstr2bin(pos, bin, bin_len) < 0) {
			printf("Invalid hex string '%s' (%s)\n", pos, buf);
			return 1;
		}

		if (os_strcmp(buf, "K") == 0) {
			if (bin_len > sizeof(k)) {
				printf("Too long K (%u)\n", (unsigned) bin_len);
				return 1;
			}
			os_memcpy(k, bin, bin_len);
			k_len = bin_len;
			continue;
		}

		if (os_strcmp(buf, "C") == 0) {
			if (bin_len > sizeof(c)) {
				printf("Too long C (%u)\n", (unsigned) bin_len);
				return 1;
			}
			os_memcpy(c, bin, bin_len);
			c_len = bin_len;
			continue;
		}

	skip_val_parse:
		if (!fail) {
			if (os_strcmp(buf, "P") != 0) {
				printf("Unexpected field '%s'\n", buf);
				continue;
			}

			if (bin_len > sizeof(p)) {
				printf("Too long P (%u)\n", (unsigned) bin_len);
				return 1;
			}
			os_memcpy(p, bin, bin_len);
			p_len = bin_len;

			if (p_len % 8 != 0 || c_len % 8 != 0 ||
			    c_len - p_len != 8) {
				printf("invalid parameter length (p_len=%u c_len=%u)\n",
				       (unsigned) p_len, (unsigned) c_len);
				continue;
			}
		}

		if (aes_unwrap(k, k_len, (c_len / 8) - 1, c, result)) {
			if (fail) {
				printf("OK (fail reported)\n");
				ok++;
				continue;
			}
			printf("aes_unwrap() failed\n");
			ret++;
			continue;
		}

		if (fail) {
			printf("FAIL (mismatch not reported)\n");
			ret++;
		} else if (os_memcmp(p, result, p_len) == 0) {
			printf("OK\n");
			ok++;
		} else {
			printf("FAIL\n");
			ret++;
		}
	}

	fclose(f);

	if (ret)
		printf("Test case failed\n");
	else
		printf("%d test vectors OK\n", ok);

	return ret;
}
Example #19
0
/* Given that we have received a header w/ SUBSCRIBE, act upon it
 *
 * Format of SUBSCRIBE (case-insensitive):
 *
 * First line must be:
 *      SUBSCRIBE /wps_event HTTP/1.1
 *
 * Our response (if no error) which includes only required lines is:
 * HTTP/1.1 200 OK
 * Server: xx, UPnP/1.0, xx
 * SID: uuid:xxxxxxxxx
 * Timeout: Second-<n>
 * Content-Length: 0
 * Date: xxxx
 *
 * Header lines must end with \r\n
 * Per RFC 2616, content-length: is not required but connection:close
 * would appear to be required (given that we will be closing it!).
 */
static void web_connection_parse_subscribe(struct upnp_wps_device_sm *sm,
					   struct http_request *req,
					   const char *filename)
{
	struct wpabuf *buf;
	char *b;
	char *hdr = http_request_get_hdr(req);
	char *h;
	char *match;
	int match_len;
	char *end;
	int len;
	int got_nt = 0;
	u8 uuid[UUID_LEN];
	int got_uuid = 0;
	char *callback_urls = NULL;
	struct subscription *s = NULL;
	enum http_reply_code ret = HTTP_INTERNAL_SERVER_ERROR;

	buf = wpabuf_alloc(1000);
	if (buf == NULL) {
		http_request_deinit(req);
		return;
	}

	/* Parse/validate headers */
	h = hdr;
	/* First line: SUBSCRIBE /wps_event HTTP/1.1
	 * has already been parsed.
	 */
	if (os_strcasecmp(filename, UPNP_WPS_DEVICE_EVENT_FILE) != 0) {
		ret = HTTP_PRECONDITION_FAILED;
		goto error;
	}
	wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP SUBSCRIBE for event");
	end = os_strchr(h, '\n');

	for (; end != NULL; h = end + 1) {
		/* Option line by option line */
		h = end + 1;
		end = os_strchr(h, '\n');
		if (end == NULL)
			break; /* no unterminated lines allowed */

		/* NT assures that it is our type of subscription;
		 * not used for a renewl.
		 **/
		match = "NT:";
		match_len = os_strlen(match);
		if (os_strncasecmp(h, match, match_len) == 0) {
			h += match_len;
			while (*h == ' ' || *h == '\t')
				h++;
			match = "upnp:event";
			match_len = os_strlen(match);
			if (os_strncasecmp(h, match, match_len) != 0) {
				ret = HTTP_BAD_REQUEST;
				goto error;
			}
			got_nt = 1;
			continue;
		}
		/* HOST should refer to us */
#if 0
		match = "HOST:";
		match_len = os_strlen(match);
		if (os_strncasecmp(h, match, match_len) == 0) {
			h += match_len;
			while (*h == ' ' || *h == '\t')
				h++;
			.....
		}
#endif
		/* CALLBACK gives one or more URLs for NOTIFYs
		 * to be sent as a result of the subscription.
		 * Each URL is enclosed in angle brackets.
		 */
		match = "CALLBACK:";
		match_len = os_strlen(match);
		if (os_strncasecmp(h, match, match_len) == 0) {
			h += match_len;
			while (*h == ' ' || *h == '\t')
				h++;
			len = end - h;
			os_free(callback_urls);
			callback_urls = os_malloc(len + 1);
			if (callback_urls == NULL) {
				ret = HTTP_INTERNAL_SERVER_ERROR;
				goto error;
			}
			os_memcpy(callback_urls, h, len);
			callback_urls[len] = 0;
			continue;
		}
		/* SID is only for renewal */
		match = "SID:";
		match_len = os_strlen(match);
		if (os_strncasecmp(h, match, match_len) == 0) {
			h += match_len;
			while (*h == ' ' || *h == '\t')
				h++;
			match = "uuid:";
			match_len = os_strlen(match);
			if (os_strncasecmp(h, match, match_len) != 0) {
				ret = HTTP_BAD_REQUEST;
				goto error;
			}
			h += match_len;
			while (*h == ' ' || *h == '\t')
				h++;
			if (uuid_str2bin(h, uuid)) {
				ret = HTTP_BAD_REQUEST;
				goto error;
			}
			got_uuid = 1;
			continue;
		}
		/* TIMEOUT is requested timeout, but apparently we can
		 * just ignore this.
		 */
	}
struct wpa_config * wpa_config_read(const char *name)
{
	FILE *f;
	char buf[256], *pos;
	int errors = 0, line = 0;
	struct wpa_ssid *ssid, *tail = NULL, *head = NULL;
	struct wpa_config *config;
	int id = 0;

	config = wpa_config_alloc_empty(NULL, NULL);
	if (config == NULL)
		return NULL;
	wpa_printf(MSG_DEBUG, "Reading configuration file '%s'", name);
	f = fopen(name, "r");
	if (f == NULL) {
		os_free(config);
		return NULL;
	}

	while (wpa_config_get_line(buf, sizeof(buf), f, &line, &pos)) {
		if (os_strcmp(pos, "network={") == 0) {
			ssid = wpa_config_read_network(f, &line, id++);
			if (ssid == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: failed to "
					   "parse network block.", line);
#ifndef WPA_IGNORE_CONFIG_ERRORS
				errors++;
#endif
				continue;
			}
			if (head == NULL) {
				head = tail = ssid;
			} else {
				tail->next = ssid;
				tail = ssid;
			}
			if (wpa_config_add_prio_network(config, ssid)) {
				wpa_printf(MSG_ERROR, "Line %d: failed to add "
					   "network block to priority list.",
					   line);
				errors++;
				continue;
			}
		} else if (os_strncmp(pos, "blob-base64-", 12) == 0) {
			char *bname = pos + 12, *name_end;
			struct wpa_config_blob *blob;

			name_end = os_strchr(bname, '=');
			if (name_end == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: no blob name "
					   "terminator", line);
				errors++;
				continue;
			}
			*name_end = '\0';

			blob = wpa_config_read_blob(f, &line, bname);
			if (blob == NULL) {
				wpa_printf(MSG_ERROR, "Line %d: failed to read"
					   " blob %s", line, bname);
				errors++;
				continue;
			}
			wpa_config_set_blob(config, blob);
#ifdef CONFIG_CTRL_IFACE
		} else if (os_strncmp(pos, "ctrl_interface=", 15) == 0) {
			os_free(config->ctrl_interface);
			config->ctrl_interface = os_strdup(pos + 15);
			wpa_printf(MSG_DEBUG, "ctrl_interface='%s'",
				   config->ctrl_interface);
		} else if (os_strncmp(pos, "ctrl_interface_group=", 21) == 0) {
			os_free(config->ctrl_interface_group);
			config->ctrl_interface_group = os_strdup(pos + 21);
			wpa_printf(MSG_DEBUG, "ctrl_interface_group='%s' "
				   "(DEPRECATED)",
				   config->ctrl_interface_group);
#endif /* CONFIG_CTRL_IFACE */
		} else if (os_strncmp(pos, "eapol_version=", 14) == 0) {
			config->eapol_version = atoi(pos + 14);
			if (config->eapol_version < 1 ||
			    config->eapol_version > 2) {
				wpa_printf(MSG_ERROR, "Line %d: Invalid EAPOL "
					   "version (%d): '%s'.",
					   line, config->eapol_version, pos);
				errors++;
				continue;
			}
			wpa_printf(MSG_DEBUG, "eapol_version=%d",
				   config->eapol_version);
		} else if (os_strncmp(pos, "ap_scan=", 8) == 0) {
			config->ap_scan = atoi(pos + 8);
			wpa_printf(MSG_DEBUG, "ap_scan=%d", config->ap_scan);
		} else if (os_strncmp(pos, "fast_reauth=", 12) == 0) {
			config->fast_reauth = atoi(pos + 12);
			wpa_printf(MSG_DEBUG, "fast_reauth=%d",
				   config->fast_reauth);
		} else if (os_strncmp(pos, "opensc_engine_path=", 19) == 0) {
			os_free(config->opensc_engine_path);
			config->opensc_engine_path = os_strdup(pos + 19);
			wpa_printf(MSG_DEBUG, "opensc_engine_path='%s'",
				   config->opensc_engine_path);
		} else if (os_strncmp(pos, "pkcs11_engine_path=", 19) == 0) {
			os_free(config->pkcs11_engine_path);
			config->pkcs11_engine_path = os_strdup(pos + 19);
			wpa_printf(MSG_DEBUG, "pkcs11_engine_path='%s'",
				   config->pkcs11_engine_path);
		} else if (os_strncmp(pos, "pkcs11_module_path=", 19) == 0) {
			os_free(config->pkcs11_module_path);
			config->pkcs11_module_path = os_strdup(pos + 19);
			wpa_printf(MSG_DEBUG, "pkcs11_module_path='%s'",
				   config->pkcs11_module_path);
		} else if (os_strncmp(pos, "driver_param=", 13) == 0) {
			os_free(config->driver_param);
			config->driver_param = os_strdup(pos + 13);
			wpa_printf(MSG_DEBUG, "driver_param='%s'",
				   config->driver_param);
		} else if (os_strncmp(pos, "dot11RSNAConfigPMKLifetime=", 27)
			   == 0) {
			config->dot11RSNAConfigPMKLifetime = atoi(pos + 27);
			wpa_printf(MSG_DEBUG, "dot11RSNAConfigPMKLifetime=%d",
				   config->dot11RSNAConfigPMKLifetime);
		} else if (os_strncmp(pos,
				      "dot11RSNAConfigPMKReauthThreshold=", 34)
			   == 0) {
			config->dot11RSNAConfigPMKReauthThreshold =
				atoi(pos + 34);
			wpa_printf(MSG_DEBUG,
				   "dot11RSNAConfigPMKReauthThreshold=%d",
				   config->dot11RSNAConfigPMKReauthThreshold);
		} else if (os_strncmp(pos, "dot11RSNAConfigSATimeout=", 25) ==
			   0) {
			config->dot11RSNAConfigSATimeout = atoi(pos + 25);
			wpa_printf(MSG_DEBUG, "dot11RSNAConfigSATimeout=%d",
				   config->dot11RSNAConfigSATimeout);
		} else if (os_strncmp(pos, "update_config=", 14) == 0) {
			config->update_config = atoi(pos + 14);
			wpa_printf(MSG_DEBUG, "update_config=%d",
				   config->update_config);
		} else if (os_strncmp(pos, "load_dynamic_eap=", 17) == 0) {
			char *so = pos + 17;
			int ret;
			wpa_printf(MSG_DEBUG, "load_dynamic_eap=%s", so);
			ret = eap_peer_method_load(so);
			if (ret == -2) {
				wpa_printf(MSG_DEBUG, "This EAP type was "
					   "already loaded - not reloading.");
			} else if (ret) {
				wpa_printf(MSG_ERROR, "Line %d: Failed to "
					   "load dynamic EAP method '%s'.",
					   line, so);
				errors++;
			}
		} else {
			wpa_printf(MSG_ERROR, "Line %d: Invalid configuration "
				   "line '%s'.", line, pos);
			errors++;
			continue;
		}
	}

	fclose(f);

	config->ssid = head;
	wpa_config_debug_dump_networks(config);

#ifndef WPA_IGNORE_CONFIG_ERRORS
	if (errors) {
		wpa_config_free(config);
		config = NULL;
		head = NULL;
	}
#endif
	return config;
}
Example #21
0
static struct wpa_priv_interface *
wpa_priv_interface_init(const char *dir, const char *params)
{
	struct wpa_priv_interface *iface;
	char *pos;
	size_t len;
	struct sockaddr_un addr;
	int i;

	pos = os_strchr(params, ':');
	if (pos == NULL)
		return NULL;

	iface = os_zalloc(sizeof(*iface));
	if (iface == NULL)
		return NULL;
	iface->fd = -1;

	len = pos - params;
	iface->driver_name = dup_binstr(params, len);
	if (iface->driver_name == NULL) {
		wpa_priv_interface_deinit(iface);
		return NULL;
	}

	for (i = 0; wpa_drivers[i]; i++) {
		if (os_strcmp(iface->driver_name,
			      wpa_drivers[i]->name) == 0) {
			iface->driver = wpa_drivers[i];
			break;
		}
	}
	if (iface->driver == NULL) {
		wpa_printf(MSG_ERROR, "Unsupported driver '%s'",
			   iface->driver_name);
		wpa_priv_interface_deinit(iface);
		return NULL;
	}

	pos++;
	iface->ifname = os_strdup(pos);
	if (iface->ifname == NULL) {
		wpa_priv_interface_deinit(iface);
		return NULL;
	}

	len = os_strlen(dir) + 1 + os_strlen(iface->ifname);
	iface->sock_name = os_malloc(len + 1);
	if (iface->sock_name == NULL) {
		wpa_priv_interface_deinit(iface);
		return NULL;
	}

	os_snprintf(iface->sock_name, len + 1, "%s/%s", dir, iface->ifname);
	if (os_strlen(iface->sock_name) >= sizeof(addr.sun_path)) {
		wpa_priv_interface_deinit(iface);
		return NULL;
	}

	iface->fd = socket(PF_UNIX, SOCK_DGRAM, 0);
	if (iface->fd < 0) {
		wpa_printf(MSG_ERROR, "socket(PF_UNIX): %s", strerror(errno));
		wpa_priv_interface_deinit(iface);
		return NULL;
	}

	os_memset(&addr, 0, sizeof(addr));
	addr.sun_family = AF_UNIX;
	os_strlcpy(addr.sun_path, iface->sock_name, sizeof(addr.sun_path));

	if (bind(iface->fd, (struct sockaddr *) &addr, sizeof(addr)) < 0) {
		wpa_printf(MSG_DEBUG, "bind(PF_UNIX) failed: %s",
			   strerror(errno));
		if (connect(iface->fd, (struct sockaddr *) &addr,
			    sizeof(addr)) < 0) {
			wpa_printf(MSG_DEBUG, "Socket exists, but does not "
				   "allow connections - assuming it was "
				   "leftover from forced program termination");
			if (unlink(iface->sock_name) < 0) {
				wpa_printf(MSG_ERROR,
					   "Could not unlink existing ctrl_iface socket '%s': %s",
					   iface->sock_name, strerror(errno));
				goto fail;
			}
			if (bind(iface->fd, (struct sockaddr *) &addr,
				 sizeof(addr)) < 0) {
				wpa_printf(MSG_ERROR,
					   "wpa-priv-iface-init: bind(PF_UNIX): %s",
					   strerror(errno));
				goto fail;
			}
			wpa_printf(MSG_DEBUG, "Successfully replaced leftover "
				   "socket '%s'", iface->sock_name);
		} else {
			wpa_printf(MSG_INFO, "Socket exists and seems to be "
				   "in use - cannot override it");
			wpa_printf(MSG_INFO, "Delete '%s' manually if it is "
				   "not used anymore", iface->sock_name);
			goto fail;
		}
	}

	if (chmod(iface->sock_name, S_IRWXU | S_IRWXG | S_IRWXO) < 0) {
		wpa_printf(MSG_ERROR, "chmod: %s", strerror(errno));
		goto fail;
	}

	eloop_register_read_sock(iface->fd, wpa_priv_receive, iface, NULL);

	return iface;

fail:
	wpa_priv_interface_deinit(iface);
	return NULL;
}
Example #22
0
static void * eap_wsc_init(struct eap_sm *sm)
{
	struct eap_wsc_data *data;
	const u8 *identity;
	size_t identity_len;
	int registrar;
	struct wps_config cfg;
	const char *pos, *end;
	const char *phase1;
	struct wps_context *wps;
	struct wps_credential new_ap_settings;
	int res;
	int nfc = 0;
	u8 pkhash[WPS_OOB_PUBKEY_HASH_LEN];

	wps = sm->wps;
	if (wps == NULL) {
		wpa_printf(MSG_ERROR, "EAP-WSC: WPS context not available");
		return NULL;
	}

	identity = eap_get_config_identity(sm, &identity_len);

	if (identity && identity_len == WSC_ID_REGISTRAR_LEN &&
	    os_memcmp(identity, WSC_ID_REGISTRAR, WSC_ID_REGISTRAR_LEN) == 0)
		registrar = 1; /* Supplicant is Registrar */
	else if (identity && identity_len == WSC_ID_ENROLLEE_LEN &&
	    os_memcmp(identity, WSC_ID_ENROLLEE, WSC_ID_ENROLLEE_LEN) == 0)
		registrar = 0; /* Supplicant is Enrollee */
	else {
		wpa_hexdump_ascii(MSG_INFO, "EAP-WSC: Unexpected identity",
				  identity, identity_len);
		return NULL;
	}

	data = os_zalloc(sizeof(*data));
	if (data == NULL)
		return NULL;
	data->state = registrar ? MESG : WAIT_START;
	data->registrar = registrar;
	data->wps_ctx = wps;

	os_memset(&cfg, 0, sizeof(cfg));
	cfg.wps = wps;
	cfg.registrar = registrar;

	phase1 = eap_get_config_phase1(sm);
	if (phase1 == NULL) {
		wpa_printf(MSG_INFO, "EAP-WSC: phase1 configuration data not "
			   "set");
		os_free(data);
		return NULL;
	}

	pos = os_strstr(phase1, "pin=");
	if (pos) {
		pos += 4;
		cfg.pin = (const u8 *) pos;
		while (*pos != '\0' && *pos != ' ')
			pos++;
		cfg.pin_len = pos - (const char *) cfg.pin;
		if (cfg.pin_len == 6 &&
		    os_strncmp((const char *) cfg.pin, "nfc-pw", 6) == 0) {
			cfg.pin = NULL;
			cfg.pin_len = 0;
			nfc = 1;
		}
	} else {
		pos = os_strstr(phase1, "pbc=1");
		if (pos)
			cfg.pbc = 1;
	}

	pos = os_strstr(phase1, "dev_pw_id=");
	if (pos) {
		u16 id = atoi(pos + 10);
		if (id == DEV_PW_NFC_CONNECTION_HANDOVER)
			nfc = 1;
		if (cfg.pin || id == DEV_PW_NFC_CONNECTION_HANDOVER)
			cfg.dev_pw_id = id;
	}

	if (cfg.pin == NULL && !cfg.pbc && !nfc) {
		wpa_printf(MSG_INFO, "EAP-WSC: PIN or PBC not set in phase1 "
			   "configuration data");
		os_free(data);
		return NULL;
	}

	pos = os_strstr(phase1, " pkhash=");
	if (pos) {
		size_t len;
		pos += 8;
		end = os_strchr(pos, ' ');
		if (end)
			len = end - pos;
		else
			len = os_strlen(pos);
		if (len != 2 * WPS_OOB_PUBKEY_HASH_LEN ||
		    hexstr2bin(pos, pkhash, WPS_OOB_PUBKEY_HASH_LEN)) {
			wpa_printf(MSG_INFO, "EAP-WSC: Invalid pkhash");
			os_free(data);
			return NULL;
		}
		cfg.peer_pubkey_hash = pkhash;
	}

	res = eap_wsc_new_ap_settings(&new_ap_settings, phase1);
	if (res < 0) {
		os_free(data);
		wpa_printf(MSG_DEBUG, "EAP-WSC: Failed to parse new AP "
			   "settings");
		return NULL;
	}
	if (res == 1) {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Provide new AP settings for "
			   "WPS");
		cfg.new_ap_settings = &new_ap_settings;
	}

	data->wps = wps_init(&cfg);
	if (data->wps == NULL) {
		os_free(data);
		wpa_printf(MSG_DEBUG, "EAP-WSC: wps_init failed");
		return NULL;
	}
	res = eap_get_config_fragment_size(sm);
	if (res > 0)
		data->fragment_size = res;
	else
		data->fragment_size = WSC_FRAGMENT_SIZE;
	wpa_printf(MSG_DEBUG, "EAP-WSC: Fragment size limit %u",
		   (unsigned int) data->fragment_size);

	if (registrar && cfg.pin) {
		wps_registrar_add_pin(data->wps_ctx->registrar, NULL, NULL,
				      cfg.pin, cfg.pin_len, 0);
	}

	/* Use reduced client timeout for WPS to avoid long wait */
	if (sm->ClientTimeout > 30)
		sm->ClientTimeout = 30;

	return data;
}
Example #23
0
static int wpa_supplicant_ctrl_iface_ctrl_rsp(struct wpa_supplicant *wpa_s,
					      char *rsp)
{
#ifdef IEEE8021X_EAPOL
	char *pos, *id_pos;
	int id;
	struct wpa_ssid *ssid;

	pos = os_strchr(rsp, '-');
	if (pos == NULL)
		return -1;
	*pos++ = '\0';
	id_pos = pos;
	pos = os_strchr(pos, ':');
	if (pos == NULL)
		return -1;
	*pos++ = '\0';
	id = atoi(id_pos);
	wpa_printf(MSG_DEBUG, "CTRL_IFACE: field=%s id=%d", rsp, id);
	wpa_hexdump_ascii_key(MSG_DEBUG, "CTRL_IFACE: value",
			      (u8 *) pos, os_strlen(pos));

	ssid = wpa_config_get_network(wpa_s->conf, id);
	if (ssid == NULL) {
		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Could not find SSID id=%d "
			   "to update", id);
		return -1;
	}

	if (os_strcmp(rsp, "IDENTITY") == 0) {
		os_free(ssid->identity);
		ssid->identity = (u8 *) os_strdup(pos);
		ssid->identity_len = os_strlen(pos);
		ssid->pending_req_identity = 0;
		if (ssid == wpa_s->current_ssid)
			wpa_s->reassociate = 1;
	} else if (os_strcmp(rsp, "PASSWORD") == 0) {
		os_free(ssid->password);
		ssid->password = (u8 *) os_strdup(pos);
		ssid->password_len = os_strlen(pos);
		ssid->pending_req_password = 0;
		if (ssid == wpa_s->current_ssid)
			wpa_s->reassociate = 1;
	} else if (os_strcmp(rsp, "NEW_PASSWORD") == 0) {
		os_free(ssid->new_password);
		ssid->new_password = (u8 *) os_strdup(pos);
		ssid->new_password_len = os_strlen(pos);
		ssid->pending_req_new_password = 0;
		if (ssid == wpa_s->current_ssid)
			wpa_s->reassociate = 1;
	} else if (os_strcmp(rsp, "PIN") == 0) {
		os_free(ssid->pin);
		ssid->pin = os_strdup(pos);
		ssid->pending_req_pin = 0;
		if (ssid == wpa_s->current_ssid)
			wpa_s->reassociate = 1;
	} else if (os_strcmp(rsp, "OTP") == 0) {
		os_free(ssid->otp);
		ssid->otp = (u8 *) os_strdup(pos);
		ssid->otp_len = os_strlen(pos);
		os_free(ssid->pending_req_otp);
		ssid->pending_req_otp = NULL;
		ssid->pending_req_otp_len = 0;
	} else if (os_strcmp(rsp, "PASSPHRASE") == 0) {
		os_free(ssid->private_key_passwd);
		ssid->private_key_passwd = (u8 *) os_strdup(pos);
		ssid->pending_req_passphrase = 0;
		if (ssid == wpa_s->current_ssid)
			wpa_s->reassociate = 1;
	} else {
		wpa_printf(MSG_DEBUG, "CTRL_IFACE: Unknown field '%s'", rsp);
		return -1;
	}

	return 0;
#else /* IEEE8021X_EAPOL */
	wpa_printf(MSG_DEBUG, "CTRL_IFACE: 802.1X not included");
	return -1;
#endif /* IEEE8021X_EAPOL */
}
Example #24
0
static int eap_wsc_new_ap_settings(struct wps_credential *cred,
				   const char *params)
{
	const char *pos, *end;
	size_t len;

	os_memset(cred, 0, sizeof(*cred));

	pos = os_strstr(params, "new_ssid=");
	if (pos == NULL)
		return 0;
	pos += 9;
	end = os_strchr(pos, ' ');
	if (end == NULL)
		len = os_strlen(pos);
	else
		len = end - pos;
	if ((len & 1) || len > 2 * sizeof(cred->ssid) ||
	    hexstr2bin(pos, cred->ssid, len / 2)) {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_ssid");
		return -1;
	}
	cred->ssid_len = len / 2;

	pos = os_strstr(params, "new_auth=");
	if (pos == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_auth");
		return -1;
	}
	if (os_strncmp(pos + 9, "OPEN", 4) == 0)
		cred->auth_type = WPS_AUTH_OPEN;
	else if (os_strncmp(pos + 9, "WPAPSK", 6) == 0)
		cred->auth_type = WPS_AUTH_WPAPSK;
	else if (os_strncmp(pos + 9, "WPA2PSK", 7) == 0)
		cred->auth_type = WPS_AUTH_WPA2PSK;
	else {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_auth");
		return -1;
	}

	pos = os_strstr(params, "new_encr=");
	if (pos == NULL) {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Missing new_encr");
		return -1;
	}
	if (os_strncmp(pos + 9, "NONE", 4) == 0)
		cred->encr_type = WPS_ENCR_NONE;
#ifdef CONFIG_TESTING_OPTIONS
	else if (os_strncmp(pos + 9, "WEP", 3) == 0)
		cred->encr_type = WPS_ENCR_WEP;
#endif /* CONFIG_TESTING_OPTIONS */
	else if (os_strncmp(pos + 9, "TKIP", 4) == 0)
		cred->encr_type = WPS_ENCR_TKIP;
	else if (os_strncmp(pos + 9, "CCMP", 4) == 0)
		cred->encr_type = WPS_ENCR_AES;
	else {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Unknown new_encr");
		return -1;
	}

	pos = os_strstr(params, "new_key=");
	if (pos == NULL)
		return 0;
	pos += 8;
	end = os_strchr(pos, ' ');
	if (end == NULL)
		len = os_strlen(pos);
	else
		len = end - pos;
	if ((len & 1) || len > 2 * sizeof(cred->key) ||
	    hexstr2bin(pos, cred->key, len / 2)) {
		wpa_printf(MSG_DEBUG, "EAP-WSC: Invalid new_key");
		return -1;
	}
	cred->key_len = len / 2;

	return 1;
}
Example #25
0
static int wpa_supplicant_ctrl_iface_get_capability(
	struct wpa_supplicant *wpa_s, const char *_field, char *buf,
	size_t buflen)
{
	struct wpa_driver_capa capa;
	int res, first = 1, ret;
	char *pos, *end, *strict;
	char field[30];

	/* Determine whether or not strict checking was requested */
	os_snprintf(field, sizeof(field), "%s", _field);
	field[sizeof(field) - 1] = '\0';
	strict = os_strchr(field, ' ');
	if (strict != NULL) {
		*strict++ = '\0';
		if (os_strcmp(strict, "strict") != 0)
			return -1;
	}

	wpa_printf(MSG_DEBUG, "CTRL_IFACE: GET_CAPABILITY '%s' %s",
		field, strict ? strict : "");

	if (os_strcmp(field, "eap") == 0) {
		return eap_get_names(buf, buflen);
	}

	res = wpa_drv_get_capa(wpa_s, &capa);

	pos = buf;
	end = pos + buflen;

	if (os_strcmp(field, "pairwise") == 0) {
		if (res < 0) {
			if (strict)
				return 0;
			ret = os_snprintf(buf, buflen, "CCMP TKIP NONE");
			if (ret < 0 || (size_t) ret >= buflen)
				return -1;
			return ret;
		}

		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
			ret = os_snprintf(pos, end - pos, "%sCCMP",
					  first ? "" : " ");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
			first = 0;
		}

		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
			ret = os_snprintf(pos, end - pos, "%sTKIP",
					  first ? "" : " ");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
			first = 0;
		}

		if (capa.key_mgmt & WPA_DRIVER_CAPA_KEY_MGMT_WPA_NONE) {
			ret = os_snprintf(pos, end - pos, "%sNONE",
					  first ? "" : " ");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
			first = 0;
		}

		return pos - buf;
	}

	if (os_strcmp(field, "group") == 0) {
		if (res < 0) {
			if (strict)
				return 0;
			ret = os_snprintf(buf, buflen,
					  "CCMP TKIP WEP104 WEP40");
			if (ret < 0 || (size_t) ret >= buflen)
				return -1;
			return ret;
		}

		if (capa.enc & WPA_DRIVER_CAPA_ENC_CCMP) {
			ret = os_snprintf(pos, end - pos, "%sCCMP",
					  first ? "" : " ");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
			first = 0;
		}

		if (capa.enc & WPA_DRIVER_CAPA_ENC_TKIP) {
			ret = os_snprintf(pos, end - pos, "%sTKIP",
					  first ? "" : " ");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
			first = 0;
		}

		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP104) {
			ret = os_snprintf(pos, end - pos, "%sWEP104",
					  first ? "" : " ");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
			first = 0;
		}

		if (capa.enc & WPA_DRIVER_CAPA_ENC_WEP40) {
			ret = os_snprintf(pos, end - pos, "%sWEP40",
					  first ? "" : " ");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
			first = 0;
		}

		return pos - buf;
	}

	if (os_strcmp(field, "key_mgmt") == 0) {
		if (res < 0) {
			if (strict)
				return 0;
			ret = os_snprintf(buf, buflen, "WPA-PSK WPA-EAP "
					  "IEEE8021X WPA-NONE NONE");
			if (ret < 0 || (size_t) ret >= buflen)
				return -1;
			return ret;
		}

		ret = os_snprintf(pos, end - pos, "NONE IEEE8021X");
		if (ret < 0 || ret >= end - pos)
			return pos - buf;
		pos += ret;

		if (capa.key_mgmt & (WPA_DRIVER_CAPA_KEY_MGMT_WPA |
				     WPA_DRIVER_CAPA_KEY_MGMT_WPA2)) {
			ret = os_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 = os_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 = os_snprintf(pos, end - pos, " WPA-NONE");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
		}

		return pos - buf;
	}

	if (os_strcmp(field, "proto") == 0) {
		if (res < 0) {
			if (strict)
				return 0;
			ret = os_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 = os_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 = os_snprintf(pos, end - pos, "%sWPA",
					  first ? "" : " ");
			if (ret < 0 || ret >= end - pos)
				return pos - buf;
			pos += ret;
			first = 0;
		}

		return pos - buf;
	}

	if (os_strcmp(field, "auth_alg") == 0) {
		if (res < 0) {
			if (strict)
				return 0;
			ret = os_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 = os_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 = os_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 = os_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;
}
Example #26
0
/**
 * eap_peer_select_phase2_methods - Select phase 2 EAP method
 * @config: Pointer to the network configuration
 * @prefix: 'phase2' configuration prefix, e.g., "auth="
 * @types: Buffer for returning allocated list of allowed EAP methods
 * @num_types: Buffer for returning number of allocated EAP methods
 * Returns: 0 on success, -1 on failure
 *
 * This function is used to parse EAP method list and select allowed methods
 * for Phase2 authentication.
 */
int eap_peer_select_phase2_methods(struct eap_peer_config *config,
				   const char *prefix,
				   struct eap_method_type **types,
				   size_t *num_types)
{
	char *start, *pos, *buf;
	struct eap_method_type *methods = NULL, *_methods;
	u32 method;
	size_t num_methods = 0, prefix_len;

	if (config == NULL || config->phase2 == NULL)
		goto get_defaults;

	start = buf = os_strdup(config->phase2);
	if (buf == NULL)
		return -1;

	prefix_len = os_strlen(prefix);

	while (start && *start != '\0') {
		int vendor;
		pos = os_strstr(start, prefix);
		if (pos == NULL)
			break;
		if (start != pos && *(pos - 1) != ' ') {
			start = pos + prefix_len;
			continue;
		}

		start = pos + prefix_len;
		pos = os_strchr(start, ' ');
		if (pos)
			*pos++ = '\0';
		method = eap_get_phase2_type(start, &vendor);
		if (vendor == EAP_VENDOR_IETF && method == EAP_TYPE_NONE) {
			wpa_printf(MSG_ERROR, "TLS: Unsupported Phase2 EAP "
				   "method '%s'", start);
		} else {
			num_methods++;
			_methods = os_realloc_array(methods, num_methods,
						    sizeof(*methods));
			if (_methods == NULL) {
				os_free(methods);
				os_free(buf);
				return -1;
			}
			methods = _methods;
			methods[num_methods - 1].vendor = vendor;
			methods[num_methods - 1].method = method;
		}

		start = pos;
	}

	os_free(buf);

get_defaults:
	if (methods == NULL)
		methods = eap_get_phase2_types(config, &num_methods);

	if (methods == NULL) {
		wpa_printf(MSG_ERROR, "TLS: No Phase2 EAP methods available");
		return -1;
	}
	wpa_hexdump(MSG_DEBUG, "TLS: Phase2 EAP types",
		    (u8 *) methods,
		    num_methods * sizeof(struct eap_method_type));

	*types = methods;
	*num_types = num_methods;

	return 0;
}
/* 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)
{
	int alloc_len;
	char *scratch_mem = NULL;
	char *mem;
	char *domain_and_port;
	char *delim;
	char *path;
	char *domain;
	int port = 80;  /* port to send to (default is port 80) */
	struct addrinfo hints;
	struct addrinfo *result = NULL;
	struct addrinfo *rp;
	int rerr;

	/* url MUST begin with http: */
	if (url_len < 7 || os_strncasecmp(url, "http://", 7))
		goto fail;
	url += 7;
	url_len -= 7;

	/* allocate memory for the extra stuff we need */
	alloc_len = 2 * (url_len + 1);
	scratch_mem = os_zalloc(alloc_len);
	if (scratch_mem == NULL)
		goto fail;
	mem = scratch_mem;
	os_strncpy(mem, url, url_len);
	wpa_printf(MSG_DEBUG, "WPS UPnP: Adding URL '%s'", mem);
	domain_and_port = mem;
	mem += 1 + os_strlen(mem);
	delim = os_strchr(domain_and_port, '/');
	if (delim) {
		*delim++ = 0;   /* null terminate domain and port */
		path = delim;
	} else {
		path = domain_and_port + os_strlen(domain_and_port);
	}
	domain = mem;
	strcpy(domain, domain_and_port);
	delim = os_strchr(domain, ':');
	if (delim) {
		*delim++ = 0;   /* null terminate domain */
		if (isdigit(*delim))
			port = atol(delim);
	}

	/*
	 * getaddrinfo does the right thing with dotted decimal notations, or
	 * will resolve domain names. Resolving domain names will unfortunately
	 * hang the entire program until it is resolved or it times out
	 * internal to getaddrinfo; fortunately we think that the use of actual
	 * domain names (vs. dotted decimal notations) should be uncommon.
	 */
	os_memset(&hints, 0, sizeof(struct addrinfo));
	hints.ai_family = AF_INET;      /* IPv4 */
	hints.ai_socktype = SOCK_STREAM;
#if NO_DOMAIN_NAME_RESOLUTION
	/* Suppress domain name resolutions that would halt
	 * the program for periods of time
	 */
	hints.ai_flags = AI_NUMERICHOST;
#else
	/* Allow domain name resolution. */
	hints.ai_flags = 0;
#endif
	hints.ai_protocol = 0;          /* Any protocol? */
	rerr = getaddrinfo(domain, NULL /* fill in port ourselves */,
			   &hints, &result);
	if (rerr) {
		wpa_printf(MSG_INFO, "WPS UPnP: Resolve error %d (%s) on: %s",
			   rerr, gai_strerror(rerr), domain);
		goto fail;
	}
	for (rp = result; rp; rp = rp->ai_next) {
		struct subscr_addr *a;

		/* Limit no. of address to avoid denial of service attack */
		if (dl_list_len(&s->addr_list) >= MAX_ADDR_PER_SUBSCRIPTION) {
			wpa_printf(MSG_INFO, "WPS UPnP: subscr_addr_add_url: "
				   "Ignoring excessive addresses");
			break;
		}

		a = os_zalloc(sizeof(*a) + alloc_len);
		if (a == NULL)
			continue;
		mem = (void *) (a + 1);
		a->domain_and_port = mem;
		strcpy(mem, domain_and_port);
		mem += 1 + strlen(mem);
		a->path = mem;
		if (path[0] != '/')
			*mem++ = '/';
		strcpy(mem, path);
		mem += 1 + os_strlen(mem);
		os_memcpy(&a->saddr, rp->ai_addr, sizeof(a->saddr));
		a->saddr.sin_port = htons(port);

		dl_list_add(&s->addr_list, &a->list);
	}

fail:
	if (result)
		freeaddrinfo(result);
	os_free(scratch_mem);
}
Example #28
0
int testing_test_fail(void)
{
	const char *func[WPA_TRACE_LEN];
	size_t i, res, len;
	char *pos, *next;
	int match;

	if (!wpa_trace_test_fail_after)
		return 0;

	res = wpa_trace_calling_func(func, WPA_TRACE_LEN);
	i = 0;
	if (i < res && os_strcmp(func[i], __func__) == 0)
		i++;

	pos = wpa_trace_test_fail_func;

	match = 0;
	while (i < res) {
		int allow_skip = 1;
		int maybe = 0;

		if (*pos == '=') {
			allow_skip = 0;
			pos++;
		} else if (*pos == '?') {
			maybe = 1;
			pos++;
		}
		next = os_strchr(pos, ';');
		if (next)
			len = next - pos;
		else
			len = os_strlen(pos);
		if (os_memcmp(pos, func[i], len) != 0) {
			if (maybe && next) {
				pos = next + 1;
				continue;
			}
			if (allow_skip) {
				i++;
				continue;
			}
			return 0;
		}
		if (!next) {
			match = 1;
			break;
		}
		pos = next + 1;
		i++;
	}
	if (!match)
		return 0;

	wpa_trace_test_fail_after--;
	if (wpa_trace_test_fail_after == 0) {
		wpa_printf(MSG_INFO, "TESTING: fail at %s",
			   wpa_trace_test_fail_func);
		for (i = 0; i < res; i++)
			wpa_printf(MSG_INFO, "backtrace[%d] = %s",
				   (int) i, func[i]);
		return 1;
	}

	return 0;
}
Example #29
0
int main(int argc, char *argv[])
{
	struct wpa_supplicant wpa_s;
	int c, ret = 1, wait_for_monitor = 0, save_config = 0;
	char *as_addr = "127.0.0.1";
	int as_port = 1812;
	char *as_secret = "radius";
	char *cli_addr = NULL;
	char *conf = NULL;
	int timeout = 30;
	char *pos;
	struct extra_radius_attr *p = NULL, *p1;

	if (os_program_init())
		return -1;

	hostapd_logger_register_cb(hostapd_logger_cb);

	os_memset(&eapol_test, 0, sizeof(eapol_test));
	eapol_test.connect_info = "CONNECT 11Mbps 802.11b";
	os_memcpy(eapol_test.own_addr, "\x02\x00\x00\x00\x00\x01", ETH_ALEN);

	wpa_debug_level = 0;
	wpa_debug_show_keys = 1;

	for (;;) {
		c = getopt(argc, argv, "a:A:c:C:M:nN:p:r:s:St:W");
		if (c < 0)
			break;
		switch (c) {
		case 'a':
			as_addr = optarg;
			break;
		case 'A':
			cli_addr = optarg;
			break;
		case 'c':
			conf = optarg;
			break;
		case 'C':
			eapol_test.connect_info = optarg;
			break;
		case 'M':
			if (hwaddr_aton(optarg, eapol_test.own_addr)) {
				usage();
				return -1;
			}
			break;
		case 'n':
			eapol_test.no_mppe_keys++;
			break;
		case 'p':
			as_port = atoi(optarg);
			break;
		case 'r':
			eapol_test.eapol_test_num_reauths = atoi(optarg);
			break;
		case 's':
			as_secret = optarg;
			break;
		case 'S':
			save_config++;
			break;
		case 't':
			timeout = atoi(optarg);
			break;
		case 'W':
			wait_for_monitor++;
			break;
		case 'N':
			p1 = os_zalloc(sizeof(p1));
			if (p1 == NULL)
				break;
			if (!p)
				eapol_test.extra_attrs = p1;
			else
				p->next = p1;
			p = p1;

			p->type = atoi(optarg);
			pos = os_strchr(optarg, ':');
			if (pos == NULL) {
				p->syntax = 'n';
				p->data = NULL;
				break;
			}

			pos++;
			if (pos[0] == '\0' || pos[1] != ':') {
				printf("Incorrect format of attribute "
				       "specification\n");
				break;
			}

			p->syntax = pos[0];
			p->data = pos + 2;
			break;
		default:
			usage();
			return -1;
		}
	}

	if (argc > optind && os_strcmp(argv[optind], "scard") == 0) {
		return scard_test();
	}

	if (argc > optind && os_strcmp(argv[optind], "sim") == 0) {
		return scard_get_triplets(argc - optind - 1,
					  &argv[optind + 1]);
	}

	if (conf == NULL) {
		usage();
		printf("Configuration file is required.\n");
		return -1;
	}

	if (eap_register_methods()) {
		wpa_printf(MSG_ERROR, "Failed to register EAP methods");
		return -1;
	}

	if (eloop_init()) {
		wpa_printf(MSG_ERROR, "Failed to initialize event loop");
		return -1;
	}

	os_memset(&wpa_s, 0, sizeof(wpa_s));
	eapol_test.wpa_s = &wpa_s;
	wpa_s.conf = wpa_config_read(conf);
	if (wpa_s.conf == NULL) {
		printf("Failed to parse configuration file '%s'.\n", conf);
		return -1;
	}
	if (wpa_s.conf->ssid == NULL) {
		printf("No networks defined.\n");
		return -1;
	}

	wpa_init_conf(&eapol_test, &wpa_s, as_addr, as_port, as_secret,
		      cli_addr);
	wpa_s.ctrl_iface = wpa_supplicant_ctrl_iface_init(&wpa_s);
	if (wpa_s.ctrl_iface == NULL) {
		printf("Failed to initialize control interface '%s'.\n"
		       "You may have another eapol_test process already "
		       "running or the file was\n"
		       "left by an unclean termination of eapol_test in "
		       "which case you will need\n"
		       "to manually remove this file before starting "
		       "eapol_test again.\n",
		       wpa_s.conf->ctrl_interface);
		return -1;
	}
	if (wpa_supplicant_scard_init(&wpa_s, wpa_s.conf->ssid))
		return -1;

	if (test_eapol(&eapol_test, &wpa_s, wpa_s.conf->ssid))
		return -1;

	if (wait_for_monitor)
		wpa_supplicant_ctrl_iface_wait(wpa_s.ctrl_iface);

	eloop_register_timeout(timeout, 0, eapol_test_timeout, &eapol_test,
			       NULL);
	eloop_register_timeout(0, 0, send_eap_request_identity, &wpa_s, NULL);
	eloop_register_signal_terminate(eapol_test_terminate, &wpa_s);
	eloop_register_signal_reconfig(eapol_test_terminate, &wpa_s);
	eloop_run();

	eloop_cancel_timeout(eapol_test_timeout, &eapol_test, NULL);
	eloop_cancel_timeout(eapol_sm_reauth, &eapol_test, NULL);

	if (eapol_test_compare_pmk(&eapol_test) == 0 ||
	    eapol_test.no_mppe_keys)
		ret = 0;
	if (eapol_test.auth_timed_out)
		ret = -2;
	if (eapol_test.radius_access_reject_received)
		ret = -3;

	if (save_config)
		wpa_config_write(conf, wpa_s.conf);

	test_eapol_clean(&eapol_test, &wpa_s);

	eap_peer_unregister_methods();

	eloop_destroy();

	printf("MPPE keys OK: %d  mismatch: %d\n",
	       eapol_test.num_mppe_ok, eapol_test.num_mppe_mismatch);
	if (eapol_test.num_mppe_mismatch)
		ret = -4;
	if (ret)
		printf("FAILURE\n");
	else
		printf("SUCCESS\n");

	os_program_deinit();

	return ret;
}
static int cavp_rsa_sig_ver(const char *fname)
{
    FILE *f;
    int ret = 0;
    char buf[15000], *pos, *pos2;
    u8 msg[200], n[512], s[512], em[512], e[512];
    size_t msg_len = 0, n_len = 0, s_len = 0, em_len, e_len = 0;
    size_t tmp_len;
    char sha_alg[20];
    int ok = 0;

    printf("CAVP RSA SigVer test vectors from %s\n", fname);

    f = fopen(fname, "r");
    if (f == NULL) {
        printf("%s does not exist - cannot validate CAVP RSA SigVer test vectors\n",
               fname);
        return 0;
    }

    while (fgets(buf, sizeof(buf), f)) {
        pos = os_strchr(buf, '=');
        if (pos == NULL)
            continue;
        pos2 = pos - 1;
        while (pos2 >= buf && *pos2 == ' ')
            *pos2-- = '\0';
        *pos++ = '\0';
        while (*pos == ' ')
            *pos++ = '\0';
        pos2 = os_strchr(pos, '\r');
        if (!pos2)
            pos2 = os_strchr(pos, '\n');
        if (pos2)
            *pos2 = '\0';
        else
            pos2 = pos + os_strlen(pos);

        if (os_strcmp(buf, "SHAAlg") == 0) {
            os_strlcpy(sha_alg, pos, sizeof(sha_alg));
        } else if (os_strcmp(buf, "Msg") == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(msg) * 2) {
                printf("Too long Msg\n");
                return -1;
            }
            msg_len = tmp_len / 2;
            if (hexstr2bin(pos, msg, msg_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strcmp(buf, "n") == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(n) * 2) {
                printf("Too long n\n");
                return -1;
            }
            n_len = tmp_len / 2;
            if (hexstr2bin(pos, n, n_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strcmp(buf, "e") == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(e) * 2) {
                printf("Too long e\n");
                return -1;
            }
            e_len = tmp_len / 2;
            if (hexstr2bin(pos, e, e_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strcmp(buf, "S") == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(s) * 2) {
                printf("Too long S\n");
                return -1;
            }
            s_len = tmp_len / 2;
            if (hexstr2bin(pos, s, s_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strncmp(buf, "EM", 2) == 0) {
            tmp_len = os_strlen(pos);
            if (tmp_len > sizeof(em) * 2)
                return -1;
            em_len = tmp_len / 2;
            if (hexstr2bin(pos, em, em_len) < 0) {
                printf("Invalid hex string '%s'\n", pos);
                ret++;
                break;
            }
        } else if (os_strcmp(buf, "Result") == 0) {
            const u8 *addr[1];
            size_t len[1];
            struct crypto_public_key *pk;
            int res;
            u8 hash[32];
            size_t hash_len;
            const struct asn1_oid *alg;

            addr[0] = msg;
            len[0] = msg_len;
            if (os_strcmp(sha_alg, "SHA1") == 0) {
                if (sha1_vector(1, addr, len, hash) < 0)
                    return -1;
                hash_len = 20;
                alg = &asn1_sha1_oid;
            } else if (os_strcmp(sha_alg, "SHA256") == 0) {
                if (sha256_vector(1, addr, len, hash) < 0)
                    return -1;
                hash_len = 32;
                alg = &asn1_sha256_oid;
            } else {
                continue;
            }

            printf("\nExpected result: %s\n", pos);
            wpa_hexdump(MSG_INFO, "Hash(Msg)", hash, hash_len);

            pk = crypto_public_key_import_parts(n, n_len,
                                                e, e_len);
            if (pk == NULL) {
                printf("Failed to import public key\n");
                ret++;
                continue;
            }

            res = pkcs1_v15_sig_ver(pk, s, s_len, alg,
                                    hash, hash_len);
            crypto_public_key_free(pk);
            if ((*pos == 'F' && !res) || (*pos != 'F' && res)) {
                printf("FAIL\n");
                ret++;
                continue;
            }

            printf("PASS\n");
            ok++;
        }
    }

    fclose(f);

    if (ret)
        printf("Test case failed\n");
    else
        printf("%d test vectors OK\n", ok);

    return ret;
}