diff options
author | rpaulo <rpaulo@FreeBSD.org> | 2010-10-29 08:01:21 +0000 |
---|---|---|
committer | rpaulo <rpaulo@FreeBSD.org> | 2010-10-29 08:01:21 +0000 |
commit | 4dc7b761106b26c00b15dfbfd5e4da7a15d85166 (patch) | |
tree | 0b2308ac0b6239b9bd8d56cb4a658ca35f20a06b /src/wps/upnp_xml.c | |
parent | 60c44471bf25f9e84d8701afe1bbcbcc88e18c89 (diff) | |
download | FreeBSD-src-4dc7b761106b26c00b15dfbfd5e4da7a15d85166.zip FreeBSD-src-4dc7b761106b26c00b15dfbfd5e4da7a15d85166.tar.gz |
Import wpa_supplicant / hostapd 0.7.3.
Changes:
2010-09-07 - v0.7.3
* fixed fallback from failed PMKSA caching into full EAP authentication
[Bug 355]
* fixed issue with early D-Bus signals during initialization
* fixed X.509 name handling in internal TLS
* fixed WPS ER to use corrent Enrollee MAC Address in Credential
* fixed scanning routines ot improve AP selection for WPS
* added WPS workaround for open networks
* fixed WPS Diffie-Hellman derivation to use correct public key length
* fixed wpa_supplicant AP mode operations to ignore Supplicant and
scan result events
* improved SME operations with nl80211
* fixed WPS ER event_id handling in some cases
* fixed some issues with bgscan simple to avoid unnecessary scans
* fixed issue with l2_packet_ndis overlapped writes corrupting stack
[Bug 328]
* updated WinPcap to the latest stable version 4.1.2 in Windows
installer
2010-04-18 - v0.7.2
* nl80211: fixed number of issues with roaming
* avoid unnecessary roaming if multiple APs with similar signal
strength are present in scan results
* add TLS client events and server probing to ease design of
automatic detection of EAP parameters
* add option for server certificate matching (SHA256 hash of the
certificate) instead of trusted CA certificate configuration
* bsd: Cleaned up driver wrapper and added various low-level
configuration options
* wpa_gui-qt4: do not show too frequent WPS AP available events as
tray messages
* TNC: fixed issues with fragmentation
* EAP-TNC: add Flags field into fragment acknowledgement (needed to
interoperate with other implementations; may potentially breaks
compatibility with older wpa_supplicant/hostapd versions)
* wpa_cli: added option for using a separate process to receive event
messages to reduce latency in showing these
(CFLAGS += -DCONFIG_WPA_CLI_FORK=y in .config to enable this)
* maximum BSS table size can now be configured (bss_max_count)
* BSSes to be included in the BSS table can be filtered based on
configured SSIDs to save memory (filter_ssids)
* fix number of issues with IEEE 802.11r/FT; this version is not
backwards compatible with old versions
* nl80211: add support for IEEE 802.11r/FT protocol (both over-the-air
and over-the-DS)
* add freq_list network configuration parameter to allow the AP
selection to filter out entries based on the operating channel
* add signal strength change events for bgscan; this allows more
dynamic changes to background scanning interval based on changes in
the signal strength with the current AP; this improves roaming within
ESS quite a bit, e.g., with bgscan="simple:30:-45:300" in the network
configuration block to request background scans less frequently when
signal strength remains good and to automatically trigger background
scans whenever signal strength drops noticeably
(this is currently only available with nl80211)
* add BSSID and reason code (if available) to disconnect event messages
* wpa_gui-qt4: more complete support for translating the GUI with
linguist and add German translation
* fix DH padding with internal crypto code (mainly, for WPS)
* do not trigger initial scan automatically anymore if there are no
enabled networks
2010-01-16 - v0.7.1
* cleaned up driver wrapper API (struct wpa_driver_ops); the new API
is not fully backwards compatible, so out-of-tree driver wrappers
will need modifications
* cleaned up various module interfaces
* merge hostapd and wpa_supplicant developers' documentation into a
single document
* nl80211: use explicit deauthentication to clear cfg80211 state to
avoid issues when roaming between APs
* dbus: major design changes in the new D-Bus API
(fi.w1.wpa_supplicant1)
* nl80211: added support for IBSS networks
* added internal debugging mechanism with backtrace support and memory
allocation/freeing validation, etc. tests (CONFIG_WPA_TRACE=y)
* added WPS ER unsubscription command to more cleanly unregister from
receiving UPnP events when ER is terminated
* cleaned up AP mode operations to avoid need for virtual driver_ops
wrapper
* added BSS table to maintain more complete scan result information
over multiple scans (that may include only partial results)
* wpa_gui-qt4: update Peers dialog information more dynamically while
the dialog is kept open
* fixed PKCS#12 use with OpenSSL 1.0.0
* driver_wext: Added cfg80211-specific optimization to avoid some
unnecessary scans and to speed up association
2009-11-21 - v0.7.0
* increased wpa_cli ping interval to 5 seconds and made this
configurable with a new command line options (-G<seconds>)
* fixed scan buffer processing with WEXT to handle up to 65535
byte result buffer (previously, limited to 32768 bytes)
* allow multiple driver wrappers to be specified on command line
(e.g., -Dnl80211,wext); the first one that is able to initialize the
interface will be used
* added support for multiple SSIDs per scan request to optimize
scan_ssid=1 operations in ap_scan=1 mode (i.e., search for hidden
SSIDs); this requires driver support and can currently be used only
with nl80211
* added support for WPS USBA out-of-band mechanism with USB Flash
Drives (UFD) (CONFIG_WPS_UFD=y)
* driver_ndis: add PAE group address to the multicast address list to
fix wired IEEE 802.1X authentication
* fixed IEEE 802.11r key derivation function to match with the standard
(note: this breaks interoperability with previous version) [Bug 303]
* added better support for drivers that allow separate authentication
and association commands (e.g., mac80211-based Linux drivers with
nl80211; SME in wpa_supplicant); this allows over-the-air FT protocol
to be used (IEEE 802.11r)
* fixed SHA-256 based key derivation function to match with the
standard when using CCMP (for IEEE 802.11r and IEEE 802.11w)
(note: this breaks interoperability with previous version) [Bug 307]
* use shared driver wrapper files with hostapd
* added AP mode functionality (CONFIG_AP=y) with mode=2 in the network
block; this can be used for open and WPA2-Personal networks
(optionally, with WPS); this links in parts of hostapd functionality
into wpa_supplicant
* wpa_gui-qt4: added new Peers dialog to show information about peers
(other devices, including APs and stations, etc. in the neighborhood)
* added support for WPS External Registrar functionality (configure APs
and enroll new devices); can be used with wpa_gui-qt4 Peers dialog
and wpa_cli commands wps_er_start, wps_er_stop, wps_er_pin,
wps_er_pbc, wps_er_learn
(this can also be used with a new 'none' driver wrapper if no
wireless device or IEEE 802.1X on wired is needed)
* driver_nl80211: multiple updates to provide support for new Linux
nl80211/mac80211 functionality
* updated management frame protection to use IEEE Std 802.11w-2009
* fixed number of small WPS issues and added workarounds to
interoperate with common deployed broken implementations
* added support for NFC out-of-band mechanism with WPS
* driver_ndis: fixed wired IEEE 802.1X authentication with PAE group
address frames
* added preliminary support for IEEE 802.11r RIC processing
* added support for specifying subset of enabled frequencies to scan
(scan_freq option in the network configuration block); this can speed
up scanning process considerably if it is known that only a small
subset of channels is actually used in the network (this is currently
supported only with -Dnl80211)
* added a workaround for race condition between receiving the
association event and the following EAPOL-Key
* added background scan and roaming infrastructure to allow
network-specific optimizations to be used to improve roaming within
an ESS (same SSID)
* added new DBus interface (fi.w1.wpa_supplicant1)
Diffstat (limited to 'src/wps/upnp_xml.c')
-rw-r--r-- | src/wps/upnp_xml.c | 252 |
1 files changed, 252 insertions, 0 deletions
diff --git a/src/wps/upnp_xml.c b/src/wps/upnp_xml.c new file mode 100644 index 0000000..b1b1e2b --- /dev/null +++ b/src/wps/upnp_xml.c @@ -0,0 +1,252 @@ +/* + * UPnP XML helper routines + * Copyright (c) 2000-2003 Intel Corporation + * Copyright (c) 2006-2007 Sony Corporation + * Copyright (c) 2008-2009 Atheros Communications + * Copyright (c) 2009, Jouni Malinen <j@w1.fi> + * + * See wps_upnp.c for more details on licensing and code history. + */ + +#include "includes.h" + +#include "common.h" +#include "base64.h" +#include "http.h" +#include "upnp_xml.h" + + +/* + * XML parsing and formatting + * + * XML is a markup language based on unicode; usually (and in our case, + * always!) based on utf-8. utf-8 uses a variable number of bytes per + * character. utf-8 has the advantage that all non-ASCII unicode characters are + * represented by sequences of non-ascii (high bit set) bytes, whereas ASCII + * characters are single ascii bytes, thus we can use typical text processing. + * + * (One other interesting thing about utf-8 is that it is possible to look at + * any random byte and determine if it is the first byte of a character as + * versus a continuation byte). + * + * The base syntax of XML uses a few ASCII punctionation characters; any + * characters that would appear in the payload data are rewritten using + * sequences, e.g., & for ampersand(&) and < for left angle bracket (<). + * Five such escapes total (more can be defined but that does not apply to our + * case). Thus we can safely parse for angle brackets etc. + * + * XML describes tree structures of tagged data, with each element beginning + * with an opening tag <label> and ending with a closing tag </label> with + * matching label. (There is also a self-closing tag <label/> which is supposed + * to be equivalent to <label></label>, i.e., no payload, but we are unlikely + * to see it for our purpose). + * + * Actually the opening tags are a little more complicated because they can + * contain "attributes" after the label (delimited by ascii space or tab chars) + * of the form attribute_label="value" or attribute_label='value'; as it turns + * out we do not have to read any of these attributes, just ignore them. + * + * Labels are any sequence of chars other than space, tab, right angle bracket + * (and ?), but may have an inner structure of <namespace><colon><plain_label>. + * As it turns out, we can ignore the namespaces, in fact we can ignore the + * entire tree hierarchy, because the plain labels we are looking for will be + * unique (not in general, but for this application). We do however have to be + * careful to skip over the namespaces. + * + * In generating XML we have to be more careful, but that is easy because + * everything we do is pretty canned. The only real care to take is to escape + * any special chars in our payload. + */ + +/** + * xml_next_tag - Advance to next tag + * @in: Input + * @out: OUT: start of tag just after '<' + * @out_tagname: OUT: start of name of tag, skipping namespace + * @end: OUT: one after tag + * Returns: 0 on success, 1 on failure + * + * A tag has form: + * <left angle bracket><...><right angle bracket> + * Within the angle brackets, there is an optional leading forward slash (which + * makes the tag an ending tag), then an optional leading label (followed by + * colon) and then the tag name itself. + * + * Note that angle brackets present in the original data must have been encoded + * as < and > so they will not trouble us. + */ +static int xml_next_tag(const char *in, const char **out, + const char **out_tagname, const char **end) +{ + while (*in && *in != '<') + in++; + if (*in != '<') + return 1; + *out = ++in; + if (*in == '/') + in++; + *out_tagname = in; /* maybe */ + while (isalnum(*in) || *in == '-') + in++; + if (*in == ':') + *out_tagname = ++in; + while (*in && *in != '>') + in++; + if (*in != '>') + return 1; + *end = ++in; + return 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, "<"); + continue; + } + if (c == '>') { + wpabuf_put_str(buf, ">"); + continue; + } + if (c == '&') { + wpabuf_put_str(buf, "&"); + continue; + } + if (c == '\'') { + wpabuf_put_str(buf, "'"); + continue; + } + if (c == '"') { + wpabuf_put_str(buf, """); + 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); + } +} + + +/* xml_add_tagged_data -- format tagged data as a new xml line. + * + * tag must not have any special chars. + * data may have special chars, which are escaped. + */ +void xml_add_tagged_data(struct wpabuf *buf, const char *tag, const char *data) +{ + wpabuf_printf(buf, "<%s>", tag); + xml_data_encode(buf, data, os_strlen(data)); + wpabuf_printf(buf, "</%s>\n", tag); +} + + +/* A POST body looks something like (per upnp spec): + * <?xml version="1.0"?> + * <s:Envelope + * xmlns:s="http://schemas.xmlsoap.org/soap/envelope/" + * s:encodingStyle="http://schemas.xmlsoap.org/soap/encoding/"> + * <s:Body> + * <u:actionName xmlns:u="urn:schemas-upnp-org:service:serviceType:v"> + * <argumentName>in arg value</argumentName> + * other in args and their values go here, if any + * </u:actionName> + * </s:Body> + * </s:Envelope> + * + * where : + * s: might be some other namespace name followed by colon + * u: might be some other namespace name followed by colon + * actionName will be replaced according to action requested + * schema following actionName will be WFA scheme instead + * argumentName will be actual argument name + * (in arg value) will be actual argument value + */ +char * xml_get_first_item(const char *doc, const char *item) +{ + const char *match = item; + int match_len = os_strlen(item); + const char *tag, *tagname, *end; + char *value; + + /* + * This is crude: ignore any possible tag name conflicts and go right + * to the first tag of this name. This should be ok for the limited + * domain of UPnP messages. + */ + for (;;) { + if (xml_next_tag(doc, &tag, &tagname, &end)) + return NULL; + doc = end; + if (!os_strncasecmp(tagname, match, match_len) && + *tag != '/' && + (tagname[match_len] == '>' || + !isgraph(tagname[match_len]))) { + break; + } + } + end = doc; + while (*end && *end != '<') + end++; + value = os_zalloc(1 + (end - doc)); + if (value == NULL) + return NULL; + os_memcpy(value, doc, end - doc); + return value; +} + + +struct wpabuf * xml_get_base64_item(const char *data, const char *name, + enum http_reply_code *ret) +{ + char *msg; + struct wpabuf *buf; + unsigned char *decoded; + size_t len; + + msg = xml_get_first_item(data, name); + if (msg == NULL) { + *ret = UPNP_ARG_VALUE_INVALID; + return NULL; + } + + decoded = base64_decode((unsigned char *) msg, os_strlen(msg), &len); + os_free(msg); + if (decoded == NULL) { + *ret = UPNP_OUT_OF_MEMORY; + return NULL; + } + + buf = wpabuf_alloc_ext_data(decoded, len); + if (buf == NULL) { + os_free(decoded); + *ret = UPNP_OUT_OF_MEMORY; + return NULL; + } + return buf; +} |