Exemplo n.º 1
0
static struct wpabuf * event_build_message(struct wps_event_ *e)
{
	struct wpabuf *buf;
	char *b;

	buf = wpabuf_alloc(1000 + wpabuf_len(e->data));
	if (buf == NULL)
		return NULL;
	wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path);
	wpabuf_put_str(buf, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n");
	wpabuf_printf(buf, "HOST: %s\r\n", e->addr->domain_and_port);
	wpabuf_put_str(buf, "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n"
		       "NT: upnp:event\r\n"
		       "NTS: upnp:propchange\r\n");
	wpabuf_put_str(buf, "SID: uuid:");
	b = wpabuf_put(buf, 0);
	uuid_bin2str(e->s->uuid, b, 80);
	wpabuf_put(buf, os_strlen(b));
	wpabuf_put_str(buf, "\r\n");
	wpabuf_printf(buf, "SEQ: %u\r\n", e->subscriber_sequence);
	wpabuf_printf(buf, "CONTENT-LENGTH: %d\r\n",
		      (int) wpabuf_len(e->data));
	wpabuf_put_str(buf, "\r\n"); /* terminating empty line */
	wpabuf_put_buf(buf, e->data);
	return buf;
}
Exemplo n.º 2
0
static void wps_er_http_req(void *ctx, struct http_request *req)
{
	struct wps_er *er = ctx;
	struct sockaddr_in *cli = http_request_get_cli_addr(req);
	enum httpread_hdr_type type = http_request_get_type(req);
	struct wpabuf *buf;

	wpa_printf(MSG_DEBUG, "WPS ER: HTTP request: '%s' (type %d) from "
		   "%s:%d",
		   http_request_get_uri(req), type,
		   inet_ntoa(cli->sin_addr), ntohs(cli->sin_port));

	switch (type) {
	case HTTPREAD_HDR_TYPE_NOTIFY:
		wps_er_http_notify(er, req);
		break;
	default:
		wpa_printf(MSG_DEBUG, "WPS ER: Unsupported HTTP request type "
			   "%d", type);
		buf = wpabuf_alloc(200);
		if (buf == NULL) {
			http_request_deinit(req);
			return;
		}
		wpabuf_put_str(buf,
			       "HTTP/1.1 501 Unimplemented\r\n"
			       "Connection: close\r\n");
		http_put_date(buf);
		wpabuf_put_str(buf, "\r\n");
		http_request_send_and_deinit(req, buf);
		break;
	}
}
Exemplo n.º 3
0
/* xml_data_encode -- format data for xml file, escaping special characters.
 *
 * Note that we assume we are using utf8 both as input and as output!
 * In utf8, characters may be classed as follows:
 *     0xxxxxxx(2) -- 1 byte ascii char
 *     11xxxxxx(2) -- 1st byte of multi-byte char w/ unicode value >= 0x80
 *         110xxxxx(2) -- 1st byte of 2 byte sequence (5 payload bits here)
 *         1110xxxx(2) -- 1st byte of 3 byte sequence (4 payload bits here)
 *         11110xxx(2) -- 1st byte of 4 byte sequence (3 payload bits here)
 *      10xxxxxx(2) -- extension byte (6 payload bits per byte)
 *      Some values implied by the above are however illegal because they
 *      do not represent unicode chars or are not the shortest encoding.
 * Actually, we can almost entirely ignore the above and just do
 * text processing same as for ascii text.
 *
 * XML is written with arbitrary unicode characters, except that five
 * characters have special meaning and so must be escaped where they
 * appear in payload data... which we do here.
 */
void xml_data_encode(struct wpabuf *buf, const char *data, int len)
{
	int i;
	for (i = 0; i < len; i++) {
		u8 c = ((u8 *) data)[i];
		if (c == '<') {
			wpabuf_put_str(buf, "&lt;");
			continue;
		}
		if (c == '>') {
			wpabuf_put_str(buf, "&gt;");
			continue;
		}
		if (c == '&') {
			wpabuf_put_str(buf, "&amp;");
			continue;
		}
		if (c == '\'') {
			wpabuf_put_str(buf, "&apos;");
			continue;
		}
		if (c == '"') {
			wpabuf_put_str(buf, "&quot;");
			continue;
		}
		/*
		 * We could try to represent control characters using the
		 * sequence: &#x; where x is replaced by a hex numeral, but not
		 * clear why we would do this.
		 */
		wpabuf_put_u8(buf, c);
	}
}
Exemplo n.º 4
0
static void http_put_empty(struct wpabuf *buf, enum http_reply_code code)
{
	http_put_reply_code(buf, code);
	wpabuf_put_str(buf, http_server_hdr);
	wpabuf_put_str(buf, http_connection_close);
	wpabuf_put_str(buf, "Content-Length: 0\r\n"
		       "\r\n");
}
Exemplo n.º 5
0
/* format_wps_device_xml -- produce content of "file" wps_device.xml
 * (UPNP_WPS_DEVICE_XML_FILE)
 */
static void format_wps_device_xml(struct upnp_wps_device_interface *iface,
				  struct upnp_wps_device_sm *sm,
				  struct wpabuf *buf)
{
	const char *s;
	char uuid_string[80];

	wpabuf_put_str(buf, wps_device_xml_prefix);

	/*
	 * Add required fields with default values if not configured. Add
	 * optional and recommended fields only if configured.
	 */
	s = iface->wps->friendly_name;
	s = ((s && *s) ? s : "WPS Access Point");
	xml_add_tagged_data(buf, "friendlyName", s);

	s = iface->wps->dev.manufacturer;
	s = ((s && *s) ? s : "");
	xml_add_tagged_data(buf, "manufacturer", s);

	if (iface->wps->manufacturer_url)
		xml_add_tagged_data(buf, "manufacturerURL",
				    iface->wps->manufacturer_url);

	if (iface->wps->model_description)
		xml_add_tagged_data(buf, "modelDescription",
				    iface->wps->model_description);

	s = iface->wps->dev.model_name;
	s = ((s && *s) ? s : "");
	xml_add_tagged_data(buf, "modelName", s);

	if (iface->wps->dev.model_number)
		xml_add_tagged_data(buf, "modelNumber",
				    iface->wps->dev.model_number);

	if (iface->wps->model_url)
		xml_add_tagged_data(buf, "modelURL", iface->wps->model_url);

	if (iface->wps->dev.serial_number)
		xml_add_tagged_data(buf, "serialNumber",
				    iface->wps->dev.serial_number);

	uuid_bin2str(iface->wps->uuid, uuid_string, sizeof(uuid_string));
	s = uuid_string;
	/* Need "uuid:" prefix, thus we can't use xml_add_tagged_data()
	 * easily...
	 */
	wpabuf_put_str(buf, "<UDN>uuid:");
	xml_data_encode(buf, s, os_strlen(s));
	wpabuf_put_str(buf, "</UDN>\n");

	if (iface->wps->upc)
		xml_add_tagged_data(buf, "UPC", iface->wps->upc);

	wpabuf_put_str(buf, wps_device_xml_postfix);
}
Exemplo n.º 6
0
static void wpabuf_put_property(struct wpabuf *buf, const char *name,
				const char *value)
{
	wpabuf_put_str(buf, "<e:property>");
	wpabuf_printf(buf, "<%s>", name);
	if (value)
		wpabuf_put_str(buf, value);
	wpabuf_printf(buf, "</%s>", name);
	wpabuf_put_str(buf, "</e:property>\n");
}
Exemplo n.º 7
0
static struct wpabuf * wps_er_soap_hdr(const struct wpabuf *msg,
				       const char *name, const char *arg_name,
				       const char *path,
				       const struct sockaddr_in *dst,
				       char **len_ptr, char **body_ptr)
{
	unsigned char *encoded;
	size_t encoded_len;
	struct wpabuf *buf;

	if (msg) {
		encoded = base64_encode(wpabuf_head(msg), wpabuf_len(msg),
					&encoded_len);
		if (encoded == NULL)
			return NULL;
	} else {
		encoded = NULL;
		encoded_len = 0;
	}

	buf = wpabuf_alloc(1000 + encoded_len);
	if (buf == NULL) {
		os_free(encoded);
		return NULL;
	}

	wpabuf_printf(buf,
		      "POST %s HTTP/1.1\r\n"
		      "Host: %s:%d\r\n"
		      "Content-Type: text/xml; charset=\"utf-8\"\r\n"
		      "Content-Length: ",
		      path, inet_ntoa(dst->sin_addr), ntohs(dst->sin_port));

	*len_ptr = wpabuf_put(buf, 0);
	wpabuf_printf(buf,
		      "        \r\n"
		      "SOAPACTION: \"%s#%s\"\r\n"
		      "\r\n",
		      urn_wfawlanconfig, name);

	*body_ptr = wpabuf_put(buf, 0);

	wpabuf_put_str(buf, soap_prefix);
	wpabuf_printf(buf, "<u:%s xmlns:u=\"", name);
	wpabuf_put_str(buf, urn_wfawlanconfig);
	wpabuf_put_str(buf, "\">\n");
	if (encoded) {
		wpabuf_printf(buf, "<%s>%s</%s>\n",
			      arg_name, (char *) encoded, arg_name);
		os_free(encoded);
	}

	return buf;
}
Exemplo n.º 8
0
static void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf,
			       const u8 *home_realm, size_t home_realm_len,
			       int nai_realm, int nai_home_realm)
{
	if (nai_realm && hapd->conf->nai_realm_data) {
		u8 *len;
		unsigned int i, j;
		len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
		wpabuf_put_le16(buf, hapd->conf->nai_realm_count);
		for (i = 0; i < hapd->conf->nai_realm_count; i++) {
			u8 *realm_data_len, *realm_len;
			struct hostapd_nai_realm_data *realm;

			realm = &hapd->conf->nai_realm_data[i];
			realm_data_len = wpabuf_put(buf, 2);
			wpabuf_put_u8(buf, realm->encoding);
			realm_len = wpabuf_put(buf, 1);
			for (j = 0; realm->realm[j]; j++) {
				if (j > 0)
					wpabuf_put_u8(buf, ';');
				wpabuf_put_str(buf, realm->realm[j]);
			}
			*realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1;
			anqp_add_nai_realm_eap(buf, realm);
			gas_anqp_set_element_len(buf, realm_data_len);
		}
		gas_anqp_set_element_len(buf, len);
	} else if (nai_home_realm && hapd->conf->nai_realm_data) {
		hs20_add_nai_home_realm_matches(hapd, buf, home_realm,
						home_realm_len);
	}
}
static void anqp_add_nai_realm_data(struct wpabuf *buf,
				    struct hostapd_nai_realm_data *realm,
				    unsigned int realm_idx)
{
	u8 *realm_data_len;
	unsigned int i;

	wpa_printf(MSG_DEBUG, "realm=%s, len=%d", realm->realm[realm_idx],
		   (int) os_strlen(realm->realm[realm_idx]));
	realm_data_len = wpabuf_put(buf, 2);
	wpabuf_put_u8(buf, realm->encoding);
	wpabuf_put_u8(buf, os_strlen(realm->realm[realm_idx]));
	wpabuf_put_str(buf, realm->realm[realm_idx]);
	if (realm->num_auths) {
		wpabuf_put_u8(buf, 1); /* EAP method count */
		wpabuf_put_u8(buf, 2 + (3 * realm->num_auths));
		wpabuf_put_u8(buf, realm->eap_method);
		wpabuf_put_u8(buf, realm->num_auths);
		for (i = 0; i < realm->num_auths; i++) {
			wpabuf_put_u8(buf, realm->auth_id[i]);
			wpabuf_put_u8(buf, 1);
			wpabuf_put_u8(buf, realm->auth_val[i]);
		}
	} else {
		wpabuf_put_u8(buf, 0); /* EAP method count */
	}
	gas_anqp_set_element_len(buf, realm_data_len);
}
Exemplo n.º 10
0
static void http_req(void *ctx, struct http_request *req)
{
	struct browser_data *data = ctx;
	struct wpabuf *resp;
	const char *url;
	int done = 0;

	url = http_request_get_uri(req);
	wpa_printf(MSG_INFO, "Browser response received: %s", url);

	if (os_strcmp(url, "/") == 0) {
		data->success = 1;
		done = 1;
	} else if (os_strncmp(url, "/osu/", 5) == 0) {
		data->success = atoi(url + 5);
		done = 1;
	}

	resp = wpabuf_alloc(100);
	if (resp == NULL) {
		http_request_deinit(req);
		if (done)
			eloop_terminate();
		return;
	}
	wpabuf_put_str(resp, "User input completed");

	if (done) {
		eloop_cancel_timeout(browser_timeout, NULL, NULL);
		eloop_register_timeout(0, 500000, browser_timeout, &data, NULL);
	}

	http_request_send_and_deinit(req, resp);
}
Exemplo n.º 11
0
void wps_er_send_ssdp_msearch(struct wps_er *er)
{
	struct wpabuf *msg;
	struct sockaddr_in dest;

	msg = wpabuf_alloc(500);
	if (msg == NULL)
		return;

	wpabuf_put_str(msg,
		       "M-SEARCH * HTTP/1.1\r\n"
		       "HOST: 239.255.255.250:1900\r\n"
		       "MAN: \"ssdp:discover\"\r\n"
		       "MX: 3\r\n"
		       "ST: urn:schemas-wifialliance-org:device:WFADevice:1"
		       "\r\n"
		       "\r\n");

	os_memset(&dest, 0, sizeof(dest));
	dest.sin_family = AF_INET;
	dest.sin_addr.s_addr = inet_addr(UPNP_MULTICAST_ADDRESS);
	dest.sin_port = htons(UPNP_MULTICAST_PORT);

	if (sendto(er->multicast_sd, wpabuf_head(msg), wpabuf_len(msg), 0,
		   (struct sockaddr *) &dest, sizeof(dest)) < 0)
		wpa_printf(MSG_DEBUG, "WPS ER: M-SEARCH sendto failed: "
			   "%d (%s)", errno, strerror(errno));

	wpabuf_free(msg);
}
Exemplo n.º 12
0
static void wps_er_http_resp_not_found(struct http_request *req)
{
	struct wpabuf *buf;
	buf = wpabuf_alloc(200);
	if (buf == NULL) {
		http_request_deinit(req);
		return;
	}

	wpabuf_put_str(buf,
		       "HTTP/1.1 404 Not Found\r\n"
		       "Server: unspecified, UPnP/1.0, unspecified\r\n"
		       "Connection: close\r\n");
	http_put_date(buf);
	wpabuf_put_str(buf, "\r\n");
	http_request_send_and_deinit(req, buf);
}
Exemplo n.º 13
0
/**
 * upnp_wps_device_send_event - Queue event messages for subscribers
 * @sm: WPS UPnP state machine from upnp_wps_device_init()
 *
 * This function queues the last WLANEvent to be sent for all currently
 * subscribed UPnP control points. sm->wlanevent must have been set with the
 * encoded data before calling this function.
 */
static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm)
{
	/* Enqueue event message for all subscribers */
	struct wpabuf *buf; /* holds event message */
	int buf_size = 0;
	struct subscription *s, *tmp;
	/* Actually, utf-8 is the default, but it doesn't hurt to specify it */
	const char *format_head =
		"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
		"<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
	const char *format_tail = "</e:propertyset>\n";

	if (dl_list_empty(&sm->subscriptions)) {
		/* optimize */
		return;
	}

	/* Determine buffer size needed first */
	buf_size += os_strlen(format_head);
	buf_size += 50 + 2 * os_strlen("WLANEvent");
	if (sm->wlanevent)
		buf_size += os_strlen(sm->wlanevent);
	buf_size += os_strlen(format_tail);

	buf = wpabuf_alloc(buf_size);
	if (buf == NULL)
		return;
	wpabuf_put_str(buf, format_head);
	wpabuf_put_property(buf, "WLANEvent", sm->wlanevent);
	wpabuf_put_str(buf, format_tail);

	wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s",
		   (char *) wpabuf_head(buf));

	dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
			      list) {
		if (event_add(s, buf)) {
			wpa_printf(MSG_INFO, "WPS UPnP: Dropping "
				   "subscriber due to event backlog");
			dl_list_del(&s->list);
			subscription_destroy(s);
		}
	}

	wpabuf_free(buf);
}
Exemplo n.º 14
0
static void anqp_add_nai_realm(struct hostapd_data *hapd, struct wpabuf *buf,
			       struct gas_dialog_info *di,
			       struct anqp_query_info *qi, int nai_realm,
			       int nai_home_realm)
{
	/* dynamically set nai_realm_list overrides static configuration */
	if (nai_realm && hapd->conf->hs20_nai_realm_list) {
		wpabuf_put_le16(buf, ANQP_NAI_REALM);
		wpabuf_put_le16(buf, hapd->conf->hs20_nai_realm_list_len);
		wpabuf_put_data(buf, hapd->conf->hs20_nai_realm_list,
				hapd->conf->hs20_nai_realm_list_len);
	} else if (nai_realm && hapd->conf->nai_realm_data) {
		u8 *len;
		unsigned int i, j;
		len = gas_anqp_add_element(buf, ANQP_NAI_REALM);
		wpabuf_put_le16(buf, hapd->conf->nai_realm_count);
		for (i = 0; i < hapd->conf->nai_realm_count; i++) {
			u8 *realm_data_len, *realm_len;
			struct hostapd_nai_realm_data *realm;

			realm = &hapd->conf->nai_realm_data[i];
			realm_data_len = wpabuf_put(buf, 2);
			wpabuf_put_u8(buf, realm->encoding);
			realm_len = wpabuf_put(buf, 1);
			for (j = 0; realm->realm[j]; j++) {
				if (j > 0)
					wpabuf_put_u8(buf, ';');
				wpabuf_put_str(buf, realm->realm[j]);
			}
			*realm_len = (u8 *) wpabuf_put(buf, 0) - realm_len - 1;
			if (realm->num_auths) {
				wpabuf_put_u8(buf, 1); /* EAP method count */
				wpabuf_put_u8(buf, 2 + (3 * realm->num_auths));
				wpabuf_put_u8(buf, realm->eap_method);
				wpabuf_put_u8(buf, realm->num_auths);
				for (j = 0; j < realm->num_auths; j++) {
					wpabuf_put_u8(buf, realm->auth_id[j]);
					wpabuf_put_u8(buf, 1);
					wpabuf_put_u8(buf, realm->auth_val[j]);
				}
			} else {
				wpabuf_put_u8(buf, 0); /* EAP method count */
			}
			gas_anqp_set_element_len(buf, realm_data_len);
		}
		gas_anqp_set_element_len(buf, len);
	} else if (nai_home_realm && hapd->conf->nai_realm_data) {
		process_hs_nai_home_realm(hapd, buf, qi);
	} else if (di) {
		if (nai_realm)
			wpabuf_put_data(buf, di->nai_realm,
					di->nai_realm_len);
		if (nai_home_realm)
			wpabuf_put_data(buf, di->nai_home_realm,
					di->nai_home_realm_len);
	}
}
Exemplo n.º 15
0
static void wps_er_soap_end(struct wpabuf *buf, const char *name,
			    char *len_ptr, char *body_ptr)
{
	char len_buf[10];
	wpabuf_printf(buf, "</u:%s>\n", name);
	wpabuf_put_str(buf, soap_postfix);
	os_snprintf(len_buf, sizeof(len_buf), "%d",
		    (int) ((char *) wpabuf_put(buf, 0) - body_ptr));
	os_memcpy(len_ptr, len_buf, os_strlen(len_buf));
}
Exemplo n.º 16
0
static void anqp_add_icon_binary_file(struct hostapd_data *hapd,
				      struct wpabuf *buf,
				      const u8 *name, size_t name_len)
{
	struct hs20_icon *icon;
	size_t i;
	u8 *len;

	wpa_hexdump_ascii(MSG_DEBUG, "HS 2.0: Requested Icon Filename",
			  name, name_len);
	for (i = 0; i < hapd->conf->hs20_icons_count; i++) {
		icon = &hapd->conf->hs20_icons[i];
		if (name_len == os_strlen(icon->name) &&
		    os_memcmp(name, icon->name, name_len) == 0)
			break;
	}

	if (i < hapd->conf->hs20_icons_count)
		icon = &hapd->conf->hs20_icons[i];
	else
		icon = NULL;

	len = gas_anqp_add_element(buf, ANQP_VENDOR_SPECIFIC);
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_ANQP_OUI_TYPE);
	wpabuf_put_u8(buf, HS20_STYPE_ICON_BINARY_FILE);
	wpabuf_put_u8(buf, 0); /* Reserved */

	if (icon) {
		char *data;
		size_t data_len;

		data = os_readfile(icon->file, &data_len);
		if (data == NULL || data_len > 65535) {
			wpabuf_put_u8(buf, 2); /* Download Status:
						* Unspecified file error */
			wpabuf_put_u8(buf, 0);
			wpabuf_put_le16(buf, 0);
		} else {
			wpabuf_put_u8(buf, 0); /* Download Status: Success */
			wpabuf_put_u8(buf, os_strlen(icon->type));
			wpabuf_put_str(buf, icon->type);
			wpabuf_put_le16(buf, data_len);
			wpabuf_put_data(buf, data, data_len);
		}
		os_free(data);
	} else {
		wpabuf_put_u8(buf, 1); /* Download Status: File not found */
		wpabuf_put_u8(buf, 0);
		wpabuf_put_le16(buf, 0);
	}

	gas_anqp_set_element_len(buf, len);
}
Exemplo n.º 17
0
static void anqp_add_nai_realm_data(struct wpabuf *buf,
				    struct hostapd_nai_realm_data *realm,
				    unsigned int realm_idx)
{
	u8 *realm_data_len;

	wpa_printf(MSG_DEBUG, "realm=%s, len=%d", realm->realm[realm_idx],
		   (int) os_strlen(realm->realm[realm_idx]));
	realm_data_len = wpabuf_put(buf, 2);
	wpabuf_put_u8(buf, realm->encoding);
	wpabuf_put_u8(buf, os_strlen(realm->realm[realm_idx]));
	wpabuf_put_str(buf, realm->realm[realm_idx]);
	anqp_add_nai_realm_eap(buf, realm);
	gas_anqp_set_element_len(buf, realm_data_len);
}
Exemplo n.º 18
0
struct wpabuf * ndef_build_wifi_hc(int begin)
{
	struct wpabuf *hc, *carrier;

	carrier = wpabuf_alloc(2 + os_strlen(wifi_handover_type));
	if (carrier == NULL)
		return NULL;
	wpabuf_put_u8(carrier, 0x02); /* Carrier Type Format */
	wpabuf_put_u8(carrier, os_strlen(wifi_handover_type));
	wpabuf_put_str(carrier, wifi_handover_type);

	hc = ndef_build_record((begin ? FLAG_MESSAGE_BEGIN : 0) |
			       FLAG_MESSAGE_END | FLAG_TNF_NFC_FORUM, "Hc", 2,
			       "0", 1, carrier);
	wpabuf_free(carrier);

	return hc;
}
Exemplo n.º 19
0
int hs20_send_wnm_notification_t_c(struct hostapd_data *hapd,
				   const u8 *addr, const char *url)
{
	struct wpabuf *buf;
	int ret;
	size_t url_len;

	if (!url) {
		wpa_printf(MSG_INFO, "HS 2.0: No T&C Server URL available");
		return -1;
	}

	url_len = os_strlen(url);
	if (5 + url_len > 255) {
		wpa_printf(MSG_INFO,
			   "HS 2.0: Too long T&C Server URL for WNM-Notification: '%s'",
			   url);
		return -1;
	}

	buf = wpabuf_alloc(4 + 7 + url_len);
	if (!buf)
		return -1;

	wpabuf_put_u8(buf, WLAN_ACTION_WNM);
	wpabuf_put_u8(buf, WNM_NOTIFICATION_REQ);
	wpabuf_put_u8(buf, 1); /* Dialog token */
	wpabuf_put_u8(buf, 1); /* Type - 1 reserved for WFA */

	/* Terms and Conditions Acceptance subelement */
	wpabuf_put_u8(buf, WLAN_EID_VENDOR_SPECIFIC);
	wpabuf_put_u8(buf, 4 + 1 + url_len);
	wpabuf_put_be24(buf, OUI_WFA);
	wpabuf_put_u8(buf, HS20_WNM_T_C_ACCEPTANCE);
	wpabuf_put_u8(buf, url_len);
	wpabuf_put_str(buf, url);

	ret = hostapd_drv_send_action(hapd, hapd->iface->freq, 0, addr,
				      wpabuf_head(buf), wpabuf_len(buf));

	wpabuf_free(buf);

	return ret;
}
Exemplo n.º 20
0
static struct wpabuf * build_fake_wsc_ack(void)
{
	struct wpabuf *msg = wpabuf_alloc(100);
	if (msg == NULL)
		return NULL;
	wpabuf_put_u8(msg, UPNP_WPS_WLANEVENT_TYPE_EAP);
	wpabuf_put_str(msg, "00:00:00:00:00:00");
	if (wps_build_version(msg) ||
	    wps_build_msg_type(msg, WPS_WSC_ACK)) {
		wpabuf_free(msg);
		return NULL;
	}
	/* Enrollee Nonce */
	wpabuf_put_be16(msg, ATTR_ENROLLEE_NONCE);
	wpabuf_put_be16(msg, WPS_NONCE_LEN);
	wpabuf_put(msg, WPS_NONCE_LEN);
	/* Registrar Nonce */
	wpabuf_put_be16(msg, ATTR_REGISTRAR_NONCE);
	wpabuf_put_be16(msg, WPS_NONCE_LEN);
	wpabuf_put(msg, WPS_NONCE_LEN);
	return msg;
}
Exemplo n.º 21
0
static void http_put_reply_code(struct wpabuf *buf, enum http_reply_code code)
{
	wpabuf_put_str(buf, "HTTP/1.1 ");
	switch (code) {
	case HTTP_OK:
		wpabuf_put_str(buf, "200 OK\r\n");
		break;
	case HTTP_BAD_REQUEST:
		wpabuf_put_str(buf, "400 Bad request\r\n");
		break;
	case HTTP_PRECONDITION_FAILED:
		wpabuf_put_str(buf, "412 Precondition failed\r\n");
		break;
	case HTTP_UNIMPLEMENTED:
		wpabuf_put_str(buf, "501 Unimplemented\r\n");
		break;
	case HTTP_INTERNAL_SERVER_ERROR:
	default:
		wpabuf_put_str(buf, "500 Internal server error\r\n");
		break;
	}
}
Exemplo n.º 22
0
static void web_connection_send_reply(struct http_request *req,
				      enum http_reply_code ret,
				      const char *action, int action_len,
				      const struct wpabuf *reply,
				      const char *replyname)
{
	struct wpabuf *buf;
	char *replydata;
	char *put_length_here = NULL;
	char *body_start = NULL;

	if (reply) {
		size_t len;
		replydata = (char *) base64_encode(wpabuf_head(reply),
						   wpabuf_len(reply), &len);
	} else
		replydata = NULL;

	/* Parameters of the response:
	 *      action(action_len) -- action we are responding to
	 *      replyname -- a name we need for the reply
	 *      replydata -- NULL or null-terminated string
	 */
	buf = wpabuf_alloc(1000 + (replydata ? os_strlen(replydata) : 0U) +
			   (action_len > 0 ? action_len * 2 : 0));
	if (buf == NULL) {
		wpa_printf(MSG_INFO, "WPS UPnP: Cannot allocate reply to "
			   "POST");
		os_free(replydata);
		http_request_deinit(req);
		return;
	}

	/*
	 * Assuming we will be successful, put in the output header first.
	 * Note: we do not keep connections alive (and httpread does
	 * not support it)... therefore we must have Connection: close.
	 */
	if (ret == HTTP_OK) {
		wpabuf_put_str(buf,
			       "HTTP/1.1 200 OK\r\n"
			       "Content-Type: text/xml; "
			       "charset=\"utf-8\"\r\n");
	} else {
		wpabuf_printf(buf, "HTTP/1.1 %d Error\r\n", ret);
	}
	wpabuf_put_str(buf, http_connection_close);

	wpabuf_put_str(buf, "Content-Length: ");
	/*
	 * We will paste the length in later, leaving some extra whitespace.
	 * HTTP code is supposed to be tolerant of extra whitespace.
	 */
	put_length_here = wpabuf_put(buf, 0);
	wpabuf_put_str(buf, "        \r\n");

	http_put_date(buf);

	/* terminating empty line */
	wpabuf_put_str(buf, "\r\n");

	body_start = wpabuf_put(buf, 0);

	if (ret == HTTP_OK) {
		wpabuf_put_str(buf, soap_prefix);
		wpabuf_put_str(buf, "<u:");
		wpabuf_put_data(buf, action, action_len);
		wpabuf_put_str(buf, "Response xmlns:u=\"");
		wpabuf_put_str(buf, urn_wfawlanconfig);
		wpabuf_put_str(buf, "\">\n");
		if (replydata && replyname) {
			/* TODO: might possibly need to escape part of reply
			 * data? ...
			 * probably not, unlikely to have ampersand(&) or left
			 * angle bracket (<) in it...
			 */
			wpabuf_printf(buf, "<%s>", replyname);
			wpabuf_put_str(buf, replydata);
			wpabuf_printf(buf, "</%s>\n", replyname);
		}
		wpabuf_put_str(buf, "</u:");
		wpabuf_put_data(buf, action, action_len);
		wpabuf_put_str(buf, "Response>\n");
		wpabuf_put_str(buf, soap_postfix);
	} else {
		/* Error case */
		wpabuf_put_str(buf, soap_prefix);
		wpabuf_put_str(buf, soap_error_prefix);
		wpabuf_printf(buf, "<errorCode>%d</errorCode>\n", ret);
		wpabuf_put_str(buf, soap_error_postfix);
		wpabuf_put_str(buf, soap_postfix);
	}
	os_free(replydata);

	/* Now patch in the content length at the end */
	if (body_start && put_length_here) {
		int body_length = (char *) wpabuf_put(buf, 0) - body_start;
		char len_buf[10];
		os_snprintf(len_buf, sizeof(len_buf), "%d", body_length);
		os_memcpy(put_length_here, len_buf, os_strlen(len_buf));
	}

	http_request_send_and_deinit(req, buf);
}
Exemplo n.º 23
0
/* Given that we have received a header w/ GET, act upon it
 *
 * Format of GET (case-insensitive):
 *
 * First line must be:
 *      GET /<file> HTTP/1.1
 * Since we don't do anything fancy we just ignore other lines.
 *
 * Our response (if no error) which includes only required lines is:
 * HTTP/1.1 200 OK
 * Connection: close
 * Content-Type: text/xml
 * Date: <rfc1123-date>
 *
 * 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_get(struct upnp_wps_device_sm *sm,
				     struct http_request *hreq, char *filename)
{
	struct wpabuf *buf; /* output buffer, allocated */
	char *put_length_here;
	char *body_start;
	enum {
		GET_DEVICE_XML_FILE,
		GET_SCPD_XML_FILE
	} req;
	size_t extra_len = 0;
	int body_length;
	char len_buf[10];
	struct upnp_wps_device_interface *iface;

	iface = dl_list_first(&sm->interfaces,
			      struct upnp_wps_device_interface, list);
	if (iface == NULL) {
		http_request_deinit(hreq);
		return;
	}

	/*
	 * It is not required that filenames be case insensitive but it is
	 * allowed and cannot hurt here.
	 */
	if (os_strcasecmp(filename, UPNP_WPS_DEVICE_XML_FILE) == 0) {
		wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET for device XML");
		req = GET_DEVICE_XML_FILE;
		extra_len = 3000;
		if (iface->wps->friendly_name)
			extra_len += os_strlen(iface->wps->friendly_name);
		if (iface->wps->manufacturer_url)
			extra_len += os_strlen(iface->wps->manufacturer_url);
		if (iface->wps->model_description)
			extra_len += os_strlen(iface->wps->model_description);
		if (iface->wps->model_url)
			extra_len += os_strlen(iface->wps->model_url);
		if (iface->wps->upc)
			extra_len += os_strlen(iface->wps->upc);
	} else if (!os_strcasecmp(filename, UPNP_WPS_SCPD_XML_FILE)) {
		wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET for SCPD XML");
		req = GET_SCPD_XML_FILE;
		extra_len = os_strlen(wps_scpd_xml);
	} else {
		/* File not found */
		wpa_printf(MSG_DEBUG, "WPS UPnP: HTTP GET file not found: %s",
			   filename);
		buf = wpabuf_alloc(200);
		if (buf == NULL) {
			http_request_deinit(hreq);
			return;
		}
		wpabuf_put_str(buf,
			       "HTTP/1.1 404 Not Found\r\n"
			       "Connection: close\r\n");

		http_put_date(buf);

		/* terminating empty line */
		wpabuf_put_str(buf, "\r\n");

		goto send_buf;
	}

	buf = wpabuf_alloc(1000 + extra_len);
	if (buf == NULL) {
		http_request_deinit(hreq);
		return;
	}

	wpabuf_put_str(buf,
		       "HTTP/1.1 200 OK\r\n"
		       "Content-Type: text/xml; charset=\"utf-8\"\r\n");
	wpabuf_put_str(buf, "Server: Unspecified, UPnP/1.0, Unspecified\r\n");
	wpabuf_put_str(buf, "Connection: close\r\n");
	wpabuf_put_str(buf, "Content-Length: ");
	/*
	 * We will paste the length in later, leaving some extra whitespace.
	 * HTTP code is supposed to be tolerant of extra whitespace.
	 */
	put_length_here = wpabuf_put(buf, 0);
	wpabuf_put_str(buf, "        \r\n");

	http_put_date(buf);

	/* terminating empty line */
	wpabuf_put_str(buf, "\r\n");

	body_start = wpabuf_put(buf, 0);

	switch (req) {
	case GET_DEVICE_XML_FILE:
		format_wps_device_xml(iface, sm, buf);
		break;
	case GET_SCPD_XML_FILE:
		wpabuf_put_str(buf, wps_scpd_xml);
		break;
	}

	/* Now patch in the content length at the end */
	body_length = (char *) wpabuf_put(buf, 0) - body_start;
	os_snprintf(len_buf, 10, "%d", body_length);
	os_memcpy(put_length_here, len_buf, os_strlen(len_buf));

send_buf:
	http_request_send_and_deinit(hreq, buf);
}
Exemplo n.º 24
0
static void http_put_date(struct wpabuf *buf)
{
	wpabuf_put_str(buf, "Date: ");
	format_date(buf);
	wpabuf_put_str(buf, "\r\n");
}
/* event_send_tx_ready -- actually write event message
 *
 * Prequisite: subscription socket descriptor has become ready to
 * write (because connection to subscriber has been made).
 *
 * It is also possible that we are called because the connect has failed;
 * it is possible to test for this, or we can just go ahead and then
 * the write will fail.
 */
static void event_send_tx_ready(int sock, void *eloop_ctx, void *sock_ctx)
{
	struct wps_event_ *e = sock_ctx;
	struct subscription *s = e->s;
	struct wpabuf *buf;
	char *b;

	assert(e == s->current_event);
	assert(e->sd == sock);

	buf = wpabuf_alloc(1000 + wpabuf_len(e->data));
	if (buf == NULL) {
		event_retry(e, 0);
		goto bad;
	}
	wpabuf_printf(buf, "NOTIFY %s HTTP/1.1\r\n", e->addr->path);
	wpabuf_put_str(buf, "SERVER: Unspecified, UPnP/1.0, Unspecified\r\n");
	wpabuf_printf(buf, "HOST: %s\r\n", e->addr->domain_and_port);
	wpabuf_put_str(buf, "CONTENT-TYPE: text/xml; charset=\"utf-8\"\r\n"
		       "NT: upnp:event\r\n"
		       "NTS: upnp:propchange\r\n");
	wpabuf_put_str(buf, "SID: uuid:");
	b = wpabuf_put(buf, 0);
	uuid_bin2str(s->uuid, b, 80);
	wpabuf_put(buf, os_strlen(b));
	wpabuf_put_str(buf, "\r\n");
	wpabuf_printf(buf, "SEQ: %u\r\n", e->subscriber_sequence);
	wpabuf_printf(buf, "CONTENT-LENGTH: %d\r\n",
		      (int) wpabuf_len(e->data));
	wpabuf_put_str(buf, "\r\n"); /* terminating empty line */
	wpabuf_put_buf(buf, e->data);

	/* Since the message size is pretty small, we should be
	 * able to get the operating system to buffer what we give it
	 * and not have to come back again later to write more...
	 */
#if 0
	/* we could: Turn blocking back on? */
	fcntl(e->sd, F_SETFL, 0);
#endif
	wpa_printf(MSG_DEBUG, "WPS UPnP: Sending event to %s",
		   e->addr->domain_and_port);
	if (send_wpabuf(e->sd, buf) < 0) {
		event_retry(e, 1);
		goto bad;
	}
	wpabuf_free(buf);
	buf = NULL;

	if (e->sd_registered) {
		e->sd_registered = 0;
		eloop_unregister_sock(e->sd, EVENT_TYPE_WRITE);
	}
	/* Set up to read the reply */
	e->hread = httpread_create(e->sd, event_got_response_handler,
				   e /* cookie */,
				   0 /* no data expected */,
				   EVENT_TIMEOUT_SEC);
	if (e->hread == NULL) {
		wpa_printf(MSG_ERROR, "WPS UPnP: httpread_create failed");
		event_retry(e, 0);
		goto bad;
	}
	return;

bad:
	/* Schedule sending more if there is more to send */
	if (s->event_queue)
		event_send_all_later(s->sm);
	wpabuf_free(buf);
}
Exemplo n.º 26
0
static void anqp_add_osu_provider(struct wpabuf *buf,
				  struct hostapd_bss_config *bss,
				  struct hs20_osu_provider *p)
{
	u8 *len, *len2, *count;
	unsigned int i;

	len = wpabuf_put(buf, 2); /* OSU Provider Length to be filled */

	/* OSU Friendly Name Duples */
	len2 = wpabuf_put(buf, 2);
	for (i = 0; i < p->friendly_name_count; i++) {
		struct hostapd_lang_string *s = &p->friendly_name[i];
		wpabuf_put_u8(buf, 3 + s->name_len);
		wpabuf_put_data(buf, s->lang, 3);
		wpabuf_put_data(buf, s->name, s->name_len);
	}
	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);

	/* OSU Server URI */
	if (p->server_uri) {
		wpabuf_put_u8(buf, os_strlen(p->server_uri));
		wpabuf_put_str(buf, p->server_uri);
	} else
		wpabuf_put_u8(buf, 0);

	/* OSU Method List */
	count = wpabuf_put(buf, 1);
	for (i = 0; p->method_list[i] >= 0; i++)
		wpabuf_put_u8(buf, p->method_list[i]);
	*count = i;

	/* Icons Available */
	len2 = wpabuf_put(buf, 2);
	for (i = 0; i < p->icons_count; i++) {
		size_t j;
		struct hs20_icon *icon = NULL;

		for (j = 0; j < bss->hs20_icons_count && !icon; j++) {
			if (os_strcmp(p->icons[i], bss->hs20_icons[j].name) ==
			    0)
				icon = &bss->hs20_icons[j];
		}
		if (!icon)
			continue; /* icon info not found */

		wpabuf_put_le16(buf, icon->width);
		wpabuf_put_le16(buf, icon->height);
		wpabuf_put_data(buf, icon->language, 3);
		wpabuf_put_u8(buf, os_strlen(icon->type));
		wpabuf_put_str(buf, icon->type);
		wpabuf_put_u8(buf, os_strlen(icon->name));
		wpabuf_put_str(buf, icon->name);
	}
	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);

	/* OSU_NAI */
	if (p->osu_nai) {
		wpabuf_put_u8(buf, os_strlen(p->osu_nai));
		wpabuf_put_str(buf, p->osu_nai);
	} else
		wpabuf_put_u8(buf, 0);

	/* OSU Service Description Duples */
	len2 = wpabuf_put(buf, 2);
	for (i = 0; i < p->service_desc_count; i++) {
		struct hostapd_lang_string *s = &p->service_desc[i];
		wpabuf_put_u8(buf, 3 + s->name_len);
		wpabuf_put_data(buf, s->lang, 3);
		wpabuf_put_data(buf, s->name, s->name_len);
	}
	WPA_PUT_LE16(len2, (u8 *) wpabuf_put(buf, 0) - len2 - 2);

	WPA_PUT_LE16(len, (u8 *) wpabuf_put(buf, 0) - len - 2);
}
Exemplo n.º 27
0
/**
 * upnp_wps_device_send_event - Queue event messages for subscribers
 * @sm: WPS UPnP state machine from upnp_wps_device_init()
 *
 * This function queues the last WLANEvent to be sent for all currently
 * subscribed UPnP control points. sm->wlanevent must have been set with the
 * encoded data before calling this function.
 */
static void upnp_wps_device_send_event(struct upnp_wps_device_sm *sm)
{
	/* Enqueue event message for all subscribers */
	struct wpabuf *buf; /* holds event message */
	int buf_size = 0;
	struct subscription *s, *tmp;
	/* Actually, utf-8 is the default, but it doesn't hurt to specify it */
	const char *format_head =
		"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
		"<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
	const char *format_tail = "</e:propertyset>\n";
	struct os_time now;

	if (dl_list_empty(&sm->subscriptions)) {
		/* optimize */
		return;
	}

	if (os_get_time(&now) == 0) {
		if (now.sec != sm->last_event_sec) {
			sm->last_event_sec = now.sec;
			sm->num_events_in_sec = 1;
		} else {
			sm->num_events_in_sec++;
			/*
			 * In theory, this should apply to all WLANEvent
			 * notifications, but EAP messages are of much higher
			 * priority and Probe Request notifications should not
			 * be allowed to drop EAP messages, so only throttle
			 * Probe Request notifications.
			 */
			if (sm->num_events_in_sec > MAX_EVENTS_PER_SEC &&
			    sm->wlanevent_type ==
			    UPNP_WPS_WLANEVENT_TYPE_PROBE) {
				wpa_printf(MSG_DEBUG, "WPS UPnP: Throttle "
					   "event notifications (%u seen "
					   "during one second)",
					   sm->num_events_in_sec);
				return;
			}
		}
	}

	/* Determine buffer size needed first */
	buf_size += os_strlen(format_head);
	buf_size += 50 + 2 * os_strlen("WLANEvent");
	if (sm->wlanevent)
		buf_size += os_strlen(sm->wlanevent);
	buf_size += os_strlen(format_tail);

	buf = wpabuf_alloc(buf_size);
	if (buf == NULL)
		return;
	wpabuf_put_str(buf, format_head);
	wpabuf_put_property(buf, "WLANEvent", sm->wlanevent);
	wpabuf_put_str(buf, format_tail);

	wpa_printf(MSG_MSGDUMP, "WPS UPnP: WLANEvent message:\n%s",
		   (char *) wpabuf_head(buf));

	dl_list_for_each_safe(s, tmp, &sm->subscriptions, struct subscription,
			      list) {
		event_add(s, buf,
			  sm->wlanevent_type == UPNP_WPS_WLANEVENT_TYPE_PROBE);
	}

	wpabuf_free(buf);
}
Exemplo n.º 28
0
/* subscription_first_event -- send format/queue event that is automatically
 * sent on a new subscription.
 */
static int subscription_first_event(struct subscription *s)
{
	/*
	 * Actually, utf-8 is the default, but it doesn't hurt to specify it.
	 *
	 * APStatus is apparently a bit set,
	 * 0x1 = configuration change (but is always set?)
	 * 0x10 = ap is locked
	 *
	 * Per UPnP spec, we send out the last value of each variable, even
	 * for WLANEvent, whatever it was.
	 */
	char *wlan_event;
	struct wpabuf *buf;
	int ap_status = 1;      /* TODO: add 0x10 if access point is locked */
	const char *head =
		"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"
		"<e:propertyset xmlns:e=\"urn:schemas-upnp-org:event-1-0\">\n";
	const char *tail = "</e:propertyset>\n";
	char txt[10];
	int ret;

	if (s->sm->wlanevent == NULL) {
		/*
		 * There has been no events before the subscription. However,
		 * UPnP device architecture specification requires all the
		 * evented variables to be included, so generate a dummy event
		 * for this particular case using a WSC_ACK and all-zeros
		 * nonces. The ER (UPnP control point) will ignore this, but at
		 * least it will learn that WLANEvent variable will be used in
		 * event notifications in the future.
		 */
		struct wpabuf *msg;
		wpa_printf(MSG_DEBUG, "WPS UPnP: Use a fake WSC_ACK as the "
			   "initial WLANEvent");
		msg = build_fake_wsc_ack();
		if (msg) {
			s->sm->wlanevent = (char *)
				base64_encode(wpabuf_head(msg),
					      wpabuf_len(msg), NULL);
			wpabuf_free(msg);
		}
	}

	wlan_event = s->sm->wlanevent;
	if (wlan_event == NULL || *wlan_event == '\0') {
		wpa_printf(MSG_DEBUG, "WPS UPnP: WLANEvent not known for "
			   "initial event message");
		wlan_event = "";
	}
	buf = wpabuf_alloc(500 + os_strlen(wlan_event));
	if (buf == NULL)
		return -1;

	wpabuf_put_str(buf, head);
	wpabuf_put_property(buf, "STAStatus", "1");
	os_snprintf(txt, sizeof(txt), "%d", ap_status);
	wpabuf_put_property(buf, "APStatus", txt);
	if (*wlan_event)
		wpabuf_put_property(buf, "WLANEvent", wlan_event);
	wpabuf_put_str(buf, tail);

	ret = event_add(s, buf, 0);
	if (ret) {
		wpabuf_free(buf);
		return ret;
	}
	wpabuf_free(buf);

	return 0;
}